diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 035e67661..0eae0ffb4 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -3593,6 +3593,9 @@ namespace Game.Entities if (healInfo.GetHeal() == 0) return; + // Need remove expired auras after + bool existExpired = false; + // absorb without mana cost var vHealAbsorb = healInfo.GetTarget().GetAuraEffectsByType(AuraType.SchoolHealAbsorb); for (var i = 0; i < vHealAbsorb.Count && healInfo.GetHeal() > 0; ++i) @@ -3603,7 +3606,7 @@ namespace Game.Entities if (aurApp == null) continue; - if ((absorbAurEff.GetMiscValue() & (int)healInfo.GetSchoolMask()) == 0) + if ((absorbAurEff.GetMiscValue() & (int)healInfo.GetSpellInfo().GetSchoolMask()) == 0) continue; // get amount which can be still absorbed by the aura @@ -3623,6 +3626,7 @@ namespace Game.Entities continue; // currentAbsorb - damage can be absorbed by shield + // If need absorb less damage currentAbsorb = (int)Math.Min(healInfo.GetHeal(), currentAbsorb); healInfo.AbsorbHeal((uint)currentAbsorb); @@ -3630,16 +3634,31 @@ namespace Game.Entities tempAbsorb = (uint)currentAbsorb; absorbAurEff.GetBase().CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, healInfo, ref tempAbsorb); - // Reduce shield amount - absorbAurEff.ChangeAmount(absorbAurEff.GetAmount() - currentAbsorb); - // Check if our aura is using amount to count damage + // Check if our aura is using amount to count heal if (absorbAurEff.GetAmount() >= 0) { // Reduce shield amount absorbAurEff.ChangeAmount(absorbAurEff.GetAmount() - currentAbsorb); // Aura cannot absorb anything more - remove it if (absorbAurEff.GetAmount() <= 0) - absorbAurEff.GetBase().Remove(AuraRemoveMode.EnemySpell); + existExpired = true; + } + } + + // Remove all expired absorb auras + if (existExpired) + { + for (var i = 0; i < vHealAbsorb.Count;) + { + AuraEffect auraEff = vHealAbsorb[i]; + ++i; + if (auraEff.GetAmount() <= 0) + { + uint removedAuras = healInfo.GetTarget().m_removedAurasCount; + auraEff.GetBase().Remove(AuraRemoveMode.EnemySpell); + if (removedAuras + 1 < healInfo.GetTarget().m_removedAurasCount) + i = 0; + } } } } diff --git a/Source/Game/Scripting/SpellScript.cs b/Source/Game/Scripting/SpellScript.cs index cfeb9b779..41841a0f2 100644 --- a/Source/Game/Scripting/SpellScript.cs +++ b/Source/Game/Scripting/SpellScript.cs @@ -1559,16 +1559,16 @@ namespace Game.Scripting // where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount); public List OnEffectAbsorb = new(); - // executed when absorb aura effect is going to reduce damage - // example: OnEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier); - // where function is: void function (AuraEffect const* aurEff, HealInfo& healInfo, uint32& absorbAmount); - public List OnEffectAbsorbHeal = new(); - // executed after absorb aura effect reduced damage to target - absorbAmount is real amount absorbed by aura // example: AfterEffectAbsorb += AuraEffectAbsorbFn(class.function, EffectIndexSpecifier); // where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount); public List AfterEffectAbsorb = new(); + // executed when absorb aura effect is going to reduce damage + // example: OnEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier); + // where function is: void function (AuraEffect const* aurEff, HealInfo& healInfo, uint32& absorbAmount); + public List OnEffectAbsorbHeal = new(); + // executed after absorb aura effect reduced heal to target - absorbAmount is real amount absorbed by aura // example: AfterEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier); // where function is: void function (AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount); diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index bc68c17a6..86d524d07 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -400,7 +400,17 @@ namespace Game.Spells _effects[spellEffectInfo.EffectIndex] = new AuraEffect(this, spellEffectInfo, baseAmount != null ? baseAmount[spellEffectInfo.EffectIndex] : null, caster); } } - + + public virtual void Dispose() + { + // unload scripts + foreach (var itr in m_loadedScripts.ToList()) + itr._Unload(); + + Cypher.Assert(m_applications.Empty()); + _DeleteRemovedApplications(); + } + public Unit GetCaster() { if (m_owner.GetGUID() == m_casterGuid) @@ -2141,20 +2151,6 @@ namespace Game.Spells } } - public void CallScriptEffectAbsorbHandlers(AuraEffect aurEff, AuraApplication aurApp, HealInfo healInfo, ref uint absorbAmount, ref bool defaultPrevented) - { - foreach (var auraScript in m_loadedScripts) - { - auraScript._PrepareScriptCall(AuraScriptHookType.EffectAbsorb, aurApp); - foreach (var eff in auraScript.OnEffectAbsorbHeal) - if (eff.IsEffectAffected(m_spellInfo, aurEff.GetEffIndex())) - eff.Call(aurEff, healInfo, ref absorbAmount); - - defaultPrevented = auraScript._IsDefaultActionPrevented(); - auraScript._FinishScriptCall(); - } - } - public void CallScriptEffectAfterAbsorbHandlers(AuraEffect aurEff, AuraApplication aurApp, DamageInfo dmgInfo, ref uint absorbAmount) { foreach (var auraScript in m_loadedScripts) @@ -2169,6 +2165,20 @@ namespace Game.Spells } } + public void CallScriptEffectAbsorbHandlers(AuraEffect aurEff, AuraApplication aurApp, HealInfo healInfo, ref uint absorbAmount, ref bool defaultPrevented) + { + foreach (var auraScript in m_loadedScripts) + { + auraScript._PrepareScriptCall(AuraScriptHookType.EffectAbsorb, aurApp); + foreach (var eff in auraScript.OnEffectAbsorbHeal) + if (eff.IsEffectAffected(m_spellInfo, aurEff.GetEffIndex())) + eff.Call(aurEff, healInfo, ref absorbAmount); + + defaultPrevented = auraScript._IsDefaultActionPrevented(); + auraScript._FinishScriptCall(); + } + } + public void CallScriptEffectAfterAbsorbHandlers(AuraEffect aurEff, AuraApplication aurApp, HealInfo healInfo, ref uint absorbAmount) { foreach (var auraScript in m_loadedScripts)