// // 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; /// /// The magic effect for bleeding, which will damage the character every second until the effect ends. /// public sealed class BleedingMagicEffect : MagicEffect { private readonly Timer _damageTimer; private readonly float _damage; /// /// Initializes a new instance of the class. /// /// The power up. /// The definition. /// The duration. /// The attacker. /// The owner. /// The bleeding damage. public BleedingMagicEffect(IElement powerUp, MagicEffectDefinition definition, TimeSpan duration, IAttacker attacker, IAttackable owner, float damage) : base(powerUp, definition, duration) { this.Attacker = attacker; this.Owner = owner; this._damage = damage; this._damageTimer = new Timer(1000); 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 || this._damage <= 0) { return; } await this.Owner.ApplyBleedingDamageAsync(this.Attacker, (uint)this._damage).ConfigureAwait(false); } catch (Exception ex) { (this.Owner as ILoggerOwner)?.Logger.LogError(ex, "Error when applying bleeding damage"); } } }