// // 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"); } } }