//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.GameLogic;
using System.Timers;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.GameLogic.Attributes;
///
/// The magic effect for poison, which will damage the character in an interval until the effect ends.
///
public sealed class PoisonMagicEffect : MagicEffect
{
private readonly Timer _damageTimer;
///
/// Initializes a new instance of the class.
///
/// The power up.
/// The definition.
/// The duration.
/// The attacker.
/// The owner.
public PoisonMagicEffect(IElement powerUp, MagicEffectDefinition definition, TimeSpan duration, IAttacker attacker, IAttackable owner)
: base(powerUp, definition, duration)
{
this.Attacker = attacker;
this.Owner = owner;
this._damageTimer = new Timer(3000);
this._damageTimer.Elapsed += this.OnDamageTimerElapsed;
this._damageTimer.Start();
}
///
/// Gets the owner of the effect.
///
public IAttackable Owner { get; }
///
/// Gets the attacker which applied the effect.
///
public IAttacker Attacker { get; }
///
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
this._damageTimer.Stop();
this._damageTimer.Dispose();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "Catching all Exceptions.")]
private async void OnDamageTimerElapsed(object? sender, ElapsedEventArgs e)
{
try
{
if (!this.Owner.IsAlive || this.IsDisposed || this.IsDisposing)
{
return;
}
var damage = this.Owner.Attributes[Stats.CurrentHealth] * this.Attacker.Attributes[Stats.PoisonDamageMultiplier];
if (damage <= 0)
{
return;
}
await this.Owner.ApplyPoisonDamageAsync(this.Attacker, (uint)damage).ConfigureAwait(false);
}
catch (Exception ex)
{
(this.Owner as ILoggerOwner)?.Logger.LogError(ex, "Error when applying poison damage");
}
}
}