Core/Spells: Implement OnEffectAbsorbHeal and AfterEffectAbsorbHeal hooks

Port From (https://github.com/TrinityCore/TrinityCore/commit/44236c70787eae0239fb636e217305dfa043bf71)
This commit is contained in:
hondacrx
2022-07-29 17:42:49 -04:00
parent 9420056307
commit 0affdfbda0
3 changed files with 87 additions and 39 deletions
+33 -37
View File
@@ -3593,57 +3593,53 @@ namespace Game.Entities
if (healInfo.GetHeal() == 0) if (healInfo.GetHeal() == 0)
return; return;
// Need remove expired auras after
bool existExpired = false;
// absorb without mana cost // absorb without mana cost
var vHealAbsorb = healInfo.GetTarget().GetAuraEffectsByType(AuraType.SchoolHealAbsorb); var vHealAbsorb = healInfo.GetTarget().GetAuraEffectsByType(AuraType.SchoolHealAbsorb);
for (var i = 0; i < vHealAbsorb.Count; ++i) for (var i = 0; i < vHealAbsorb.Count && healInfo.GetHeal() > 0; ++i)
{ {
var eff = vHealAbsorb[i]; AuraEffect absorbAurEff = vHealAbsorb[i];
if (healInfo.GetHeal() <= 0) // Check if aura was removed during iteration - we don't need to work on such auras
break; AuraApplication aurApp = absorbAurEff.GetBase().GetApplicationOfTarget(healInfo.GetTarget().GetGUID());
if (aurApp == null)
if (!Convert.ToBoolean(eff.GetMiscValue() & (int)healInfo.GetSpellInfo().SchoolMask))
continue; continue;
// Max Amount can be absorbed by this aura if ((absorbAurEff.GetMiscValue() & (int)healInfo.GetSchoolMask()) == 0)
int currentAbsorb = eff.GetAmount(); continue;
// Found empty aura (impossible but..) // get amount which can be still absorbed by the aura
if (currentAbsorb <= 0) int currentAbsorb = absorbAurEff.GetAmount();
{ // aura with infinite absorb amount - let the scripts handle absorbtion amount, set here to 0 for safety
existExpired = true; if (currentAbsorb < 0)
currentAbsorb = 0;
uint tempAbsorb = (uint)currentAbsorb;
bool defaultPrevented = false;
absorbAurEff.GetBase().CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, healInfo, ref tempAbsorb, ref defaultPrevented);
currentAbsorb = (int)tempAbsorb;
if (defaultPrevented)
continue; continue;
}
// currentAbsorb - damage can be absorbed by shield // currentAbsorb - damage can be absorbed by shield
// If need absorb less damage
currentAbsorb = (int)Math.Min(healInfo.GetHeal(), currentAbsorb); currentAbsorb = (int)Math.Min(healInfo.GetHeal(), currentAbsorb);
healInfo.AbsorbHeal((uint)currentAbsorb); healInfo.AbsorbHeal((uint)currentAbsorb);
// Reduce shield amount tempAbsorb = (uint)currentAbsorb;
eff.ChangeAmount(eff.GetAmount() - currentAbsorb); absorbAurEff.GetBase().CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, healInfo, ref tempAbsorb);
// Need remove it later
if (eff.GetAmount() <= 0)
existExpired = true;
}
// Remove all expired absorb auras // Reduce shield amount
if (existExpired) absorbAurEff.ChangeAmount(absorbAurEff.GetAmount() - currentAbsorb);
{ // Check if our aura is using amount to count damage
for (var i = 0; i < vHealAbsorb.Count;) if (absorbAurEff.GetAmount() >= 0)
{ {
AuraEffect auraEff = vHealAbsorb[i]; // Reduce shield amount
++i; absorbAurEff.ChangeAmount(absorbAurEff.GetAmount() - currentAbsorb);
if (auraEff.GetAmount() <= 0) // Aura cannot absorb anything more - remove it
{ if (absorbAurEff.GetAmount() <= 0)
uint removedAuras = healInfo.GetTarget().m_removedAurasCount; absorbAurEff.GetBase().Remove(AuraRemoveMode.EnemySpell);
auraEff.GetBase().Remove(AuraRemoveMode.EnemySpell);
if (removedAuras + 1 < healInfo.GetTarget().m_removedAurasCount)
i = 0;
}
} }
} }
} }
+26
View File
@@ -1038,6 +1038,7 @@ namespace Game.Scripting
public delegate void AuraEffectCalcSpellModDelegate(AuraEffect aura, ref SpellModifier spellMod); public delegate void AuraEffectCalcSpellModDelegate(AuraEffect aura, ref SpellModifier spellMod);
public delegate void AuraEffectCalcCritChanceFnType(AuraEffect aura, Unit victim, ref float critChance); public delegate void AuraEffectCalcCritChanceFnType(AuraEffect aura, Unit victim, ref float critChance);
public delegate void AuraEffectAbsorbDelegate(AuraEffect aura, DamageInfo damageInfo, ref uint absorbAmount); public delegate void AuraEffectAbsorbDelegate(AuraEffect aura, DamageInfo damageInfo, ref uint absorbAmount);
public delegate void AuraEffectAbsorbHealDelegate(AuraEffect aura, HealInfo healInfo, ref uint absorbAmount);
public delegate void AuraEffectSplitDelegate(AuraEffect aura, DamageInfo damageInfo, uint splitAmount); public delegate void AuraEffectSplitDelegate(AuraEffect aura, DamageInfo damageInfo, uint splitAmount);
public delegate bool AuraCheckProcDelegate(ProcEventInfo info); public delegate bool AuraCheckProcDelegate(ProcEventInfo info);
public delegate bool AuraCheckEffectProcDelegate(AuraEffect aura, ProcEventInfo info); public delegate bool AuraCheckEffectProcDelegate(AuraEffect aura, ProcEventInfo info);
@@ -1202,6 +1203,21 @@ namespace Game.Scripting
AuraEffectAbsorbDelegate pEffectHandlerScript; AuraEffectAbsorbDelegate pEffectHandlerScript;
} }
public class EffectAbsorbHealHandler : EffectBase
{
public EffectAbsorbHealHandler(AuraEffectAbsorbHealDelegate _pEffectHandlerScript, byte _effIndex)
: base(_effIndex, AuraType.SchoolHealAbsorb)
{
pEffectHandlerScript = _pEffectHandlerScript;
}
public void Call(AuraEffect aurEff, HealInfo healInfo, ref uint absorbAmount)
{
pEffectHandlerScript(aurEff, healInfo, ref absorbAmount);
}
AuraEffectAbsorbHealDelegate pEffectHandlerScript;
}
public class EffectManaShieldHandler : EffectBase public class EffectManaShieldHandler : EffectBase
{ {
public EffectManaShieldHandler(AuraEffectAbsorbDelegate _pEffectHandlerScript, byte _effIndex) public EffectManaShieldHandler(AuraEffectAbsorbDelegate _pEffectHandlerScript, byte _effIndex)
@@ -1543,11 +1559,21 @@ namespace Game.Scripting
// where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount); // where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount);
public List<EffectAbsorbHandler> OnEffectAbsorb = new(); public List<EffectAbsorbHandler> 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<EffectAbsorbHealHandler> OnEffectAbsorbHeal = new();
// executed after absorb aura effect reduced damage to target - absorbAmount is real amount absorbed by aura // executed after absorb aura effect reduced damage to target - absorbAmount is real amount absorbed by aura
// example: AfterEffectAbsorb += AuraEffectAbsorbFn(class.function, EffectIndexSpecifier); // example: AfterEffectAbsorb += AuraEffectAbsorbFn(class.function, EffectIndexSpecifier);
// where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount); // where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount);
public List<EffectAbsorbHandler> AfterEffectAbsorb = new(); public List<EffectAbsorbHandler> AfterEffectAbsorb = 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);
public List<EffectAbsorbHealHandler> AfterEffectAbsorbHeal = new();
// executed when mana shield aura effect is going to reduce damage // executed when mana shield aura effect is going to reduce damage
// example: OnEffectManaShield += AuraEffectAbsorbFn(class.function, EffectIndexSpecifier); // example: OnEffectManaShield += AuraEffectAbsorbFn(class.function, EffectIndexSpecifier);
// where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount); // where function is: void function (AuraEffect aurEff, DamageInfo& dmgInfo, uint& absorbAmount);
+28 -2
View File
@@ -287,7 +287,7 @@ namespace Game.Spells
// When sending EstimatedPoints all effects (at least up to the last one that uses GetEstimatedAmount) must have proper value in packet // When sending EstimatedPoints all effects (at least up to the last one that uses GetEstimatedAmount) must have proper value in packet
foreach (AuraEffect effect in GetBase().GetAuraEffects()) foreach (AuraEffect effect in GetBase().GetAuraEffects())
if (effect != null && HasEffect(effect.GetEffIndex())) // Not all of aura's effects have to be applied on every target if (effect != null && HasEffect(effect.GetEffIndex())) // Not all of aura's effects have to be applied on every target
auraData.EstimatedPoints[(int)effect.GetEffIndex()] = effect.GetEstimatedAmount().GetValueOrDefault(effect.GetAmount()); auraData.EstimatedPoints.Add(effect.GetEstimatedAmount().GetValueOrDefault(effect.GetAmount()));
} }
} }
} }
@@ -542,7 +542,6 @@ namespace Game.Spells
if (unit.IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster)) if (unit.IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster))
value &= ~(1u << (int)spellEffectInfo.EffectIndex); value &= ~(1u << (int)spellEffectInfo.EffectIndex);
} }
if (value == 0 || unit.IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(unit)) if (value == 0 || unit.IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(unit))
addUnit = false; addUnit = false;
@@ -2142,6 +2141,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, DamageInfo dmgInfo, ref uint absorbAmount) public void CallScriptEffectAfterAbsorbHandlers(AuraEffect aurEff, AuraApplication aurApp, DamageInfo dmgInfo, ref uint absorbAmount)
{ {
foreach (var auraScript in m_loadedScripts) foreach (var auraScript in m_loadedScripts)
@@ -2156,6 +2169,19 @@ namespace Game.Spells
} }
} }
public void CallScriptEffectAfterAbsorbHandlers(AuraEffect aurEff, AuraApplication aurApp, HealInfo healInfo, ref uint absorbAmount)
{
foreach (var auraScript in m_loadedScripts)
{
auraScript._PrepareScriptCall(AuraScriptHookType.EffectAfterAbsorb, aurApp);
foreach (var eff in auraScript.AfterEffectAbsorbHeal)
if (eff.IsEffectAffected(m_spellInfo, aurEff.GetEffIndex()))
eff.Call(aurEff, healInfo, ref absorbAmount);
auraScript._FinishScriptCall();
}
}
public void CallScriptEffectManaShieldHandlers(AuraEffect aurEff, AuraApplication aurApp, DamageInfo dmgInfo, ref uint absorbAmount, ref bool defaultPrevented) public void CallScriptEffectManaShieldHandlers(AuraEffect aurEff, AuraApplication aurApp, DamageInfo dmgInfo, ref uint absorbAmount, ref bool defaultPrevented)
{ {
foreach (var auraScript in m_loadedScripts) foreach (var auraScript in m_loadedScripts)