121 lines
4.2 KiB
C#
121 lines
4.2 KiB
C#
// <copyright file="DevilSquareContext.cs" company="MUnique">
|
|
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
|
// </copyright>
|
|
|
|
namespace MUnique.OpenMU.GameLogic.MiniGames;
|
|
|
|
using System.Collections.Concurrent;
|
|
using System.Threading;
|
|
using Nito.Disposables.Internals;
|
|
|
|
/// <summary>
|
|
/// The context of a devil square game.
|
|
/// </summary>
|
|
public sealed class DevilSquareContext : MiniGameContext
|
|
{
|
|
private readonly ConcurrentDictionary<string, PlayerGameState> _gameStates = new();
|
|
|
|
private IReadOnlyCollection<(string Name, int Score, int BonusMoney, int BonusExp)>? _highScoreTable;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="DevilSquareContext"/> class.
|
|
/// </summary>
|
|
/// <param name="key">The key of this context.</param>
|
|
/// <param name="definition">The definition of the mini game.</param>
|
|
/// <param name="gameContext">The game context, to which this game belongs.</param>
|
|
/// <param name="mapInitializer">The map initializer, which is used when the event starts.</param>
|
|
public DevilSquareContext(MiniGameMapKey key, MiniGameDefinition definition, IGameContext gameContext, IMapInitializer mapInitializer)
|
|
: base(key, definition, gameContext, mapInitializer)
|
|
{
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void OnMonsterDied(object? sender, DeathInformation e)
|
|
{
|
|
base.OnMonsterDied(sender, e);
|
|
|
|
if (this._gameStates.TryGetValue(e.KillerName, out var state))
|
|
{
|
|
state.AddScore(this.Definition.GameLevel);
|
|
|
|
// todo add money? -> in the original servers, in DS drops no money!
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override async ValueTask OnGameStartAsync(ICollection<Player> players)
|
|
{
|
|
foreach (var player in players)
|
|
{
|
|
this._gameStates.TryAdd(player.Name, new PlayerGameState(player));
|
|
}
|
|
|
|
await base.OnGameStartAsync(players).ConfigureAwait(false);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override async ValueTask GameEndedAsync(ICollection<Player> finishers)
|
|
{
|
|
var sortedFinishers = finishers
|
|
.Select(f => this._gameStates[f.Name])
|
|
.WhereNotNull()
|
|
.OrderBy(state => state.Score)
|
|
.ToList();
|
|
|
|
var scoreList = new List<(string Name, int Score, int BonusMoney, int BonusExp)>();
|
|
int rank = 0;
|
|
foreach (var state in sortedFinishers)
|
|
{
|
|
rank++;
|
|
state.Rank = rank;
|
|
var (bonusScore, givenMoney) = await this.GiveRewardsAndGetBonusScoreAsync(state.Player, rank).ConfigureAwait(false);
|
|
state.AddScore(bonusScore);
|
|
scoreList.Add((
|
|
state.Player.Name,
|
|
state.Score,
|
|
givenMoney,
|
|
this.Definition.Rewards.FirstOrDefault(r => r.RewardType == MiniGameRewardType.Experience && (r.Rank is null || r.Rank == rank))?.RewardAmount ?? 0));
|
|
}
|
|
|
|
this._highScoreTable = scoreList.AsReadOnly();
|
|
|
|
await this.SaveRankingAsync(sortedFinishers.Select(state => (state.Rank, state.Player.SelectedCharacter!, state.Score))).ConfigureAwait(false);
|
|
await base.GameEndedAsync(finishers).ConfigureAwait(false);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override async ValueTask ShowScoreAsync(Player player)
|
|
{
|
|
if (this._highScoreTable is { } table
|
|
&& this._gameStates.TryGetValue(player.Name, out var state))
|
|
{
|
|
await player.InvokeViewPlugInAsync<IMiniGameScoreTableViewPlugin>(p => p.ShowScoreTableAsync((byte)state.Rank, table)).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
private sealed class PlayerGameState
|
|
{
|
|
private int _score;
|
|
|
|
public PlayerGameState(Player player)
|
|
{
|
|
if (player.SelectedCharacter?.CharacterClass is null)
|
|
{
|
|
throw new InvalidOperationException($"The player '{player}' is in the wrong state");
|
|
}
|
|
|
|
this.Player = player;
|
|
}
|
|
|
|
public Player Player { get; }
|
|
|
|
public int Score => this._score;
|
|
|
|
public int Rank { get; set; }
|
|
|
|
public void AddScore(int value)
|
|
{
|
|
Interlocked.Add(ref this._score, value);
|
|
}
|
|
}
|
|
} |