diff options
author | Nyr <nyrdeveloper@gmail.com> | 2022-07-25 19:38:42 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-07-28 21:26:48 +0200 |
commit | 44236c70787eae0239fb636e217305dfa043bf71 (patch) | |
tree | f309905195b591feabd5f009d83005fb69b68b26 | |
parent | 51166b2c5e02910728f897ff481ea6ee83a9310c (diff) |
Core/Spells: Implement OnEffectAbsorbHeal and AfterEffectAbsorbHeal hooks
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 64 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.h | 21 |
5 files changed, 98 insertions, 32 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d42751dcbf0..2339aca1d2d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1976,53 +1976,53 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit if (!healInfo.GetHeal()) return; - // Need remove expired auras after - bool existExpired = false; - // absorb without mana cost AuraEffectList const& vHealAbsorb = healInfo.GetTarget()->GetAuraEffectsByType(SPELL_AURA_SCHOOL_HEAL_ABSORB); for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && healInfo.GetHeal() > 0; ++i) { - if (!((*i)->GetMiscValue() & healInfo.GetSpellInfo()->SchoolMask)) + AuraEffect * absorbAurEff = *i; + // Check if aura was removed during iteration - we don't need to work on such auras + AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(healInfo.GetTarget()->GetGUID()); + if (!aurApp) continue; - // Max Amount can be absorbed by this aura - int32 currentAbsorb = (*i)->GetAmount(); + if (!(absorbAurEff->GetMiscValue() & healInfo.GetSchoolMask())) + continue; - // Found empty aura (impossible but..) - if (currentAbsorb <= 0) - { - existExpired = true; + // get amount which can be still absorbed by the aura + int32 currentAbsorb = absorbAurEff->GetAmount(); + // aura with infinite absorb amount - let the scripts handle absorbtion amount, set here to 0 for safety + if (currentAbsorb < 0) + currentAbsorb = 0; + + uint32 tempAbsorb = uint32(currentAbsorb); + + bool defaultPrevented = false; + + absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, healInfo, tempAbsorb, defaultPrevented); + currentAbsorb = tempAbsorb; + + if (defaultPrevented) continue; - } // currentAbsorb - damage can be absorbed by shield - // If need absorb less damage currentAbsorb = std::min<int32>(healInfo.GetHeal(), currentAbsorb); healInfo.AbsorbHeal(currentAbsorb); - // Reduce shield amount - (*i)->ChangeAmount((*i)->GetAmount() - currentAbsorb); - // Need remove it later - if ((*i)->GetAmount() <= 0) - existExpired = true; - } + tempAbsorb = currentAbsorb; + absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, healInfo, tempAbsorb); - // Remove all expired absorb auras - if (existExpired) - { - for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end();) - { - AuraEffect* auraEff = *i; - ++i; - if (auraEff->GetAmount() <= 0) - { - uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount; - auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL); - if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount) - i = vHealAbsorb.begin(); - } + // Reduce shield amount + absorbAurEff->ChangeAmount((*i)->GetAmount() - currentAbsorb); + // Check if our aura is using amount to count damage + 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(AURA_REMOVE_BY_ENEMY_SPELL); } } } diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index da2c0c2b6c9..3ad6cf25935 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2200,6 +2200,23 @@ void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication co } } +void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount, bool& defaultPrevented) +{ + for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp); + auto effEndItr = (*scritr)->OnEffectAbsorbHeal.end(), effItr = (*scritr)->OnEffectAbsorbHeal.begin(); + for (; effItr != effEndItr; ++effItr) + + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, healInfo, absorbAmount); + + if (!defaultPrevented) + defaultPrevented = (*scritr)->_IsDefaultActionPrevented(); + (*scritr)->_FinishScriptCall(); + } +} + void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount) { for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) @@ -2214,6 +2231,21 @@ void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplicati } } +void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount) +{ + for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp); + auto effEndItr = (*scritr)->AfterEffectAbsorbHeal.end(), effItr = (*scritr)->AfterEffectAbsorbHeal.begin(); + for (; effItr != effEndItr; ++effItr) + + if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effItr->Call(*scritr, aurEff, healInfo, absorbAmount); + + (*scritr)->_FinishScriptCall(); + } +} + void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& /*defaultPrevented*/) { for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 3aa899513ba..0ae0110b5d0 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -277,7 +277,9 @@ class TC_GAME_API Aura void CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier*& spellMod); void CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance); void CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool & defaultPrevented); + void CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount, bool& defaultPrevented); void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount); + void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount); void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool & defaultPrevented); void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount); void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 100ea02fbe5..772426ae5ed 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -1164,11 +1164,22 @@ AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(EffectAbsorbHandler&& right AuraScript::EffectAbsorbHandler& AuraScript::EffectAbsorbHandler::operator=(EffectAbsorbHandler&& right) noexcept = default; AuraScript::EffectAbsorbHandler::~EffectAbsorbHandler() = default; +AuraScript::EffectAbsorbHealHandler::EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex) + : AuraScript::EffectBase(_effIndex, SPELL_AURA_SCHOOL_HEAL_ABSORB) +{ + pEffectHandlerScript = _pEffectHandlerScript; +} + void AuraScript::EffectAbsorbHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) { (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount); } +void AuraScript::EffectAbsorbHealHandler::Call(AuraScript * auraScript, AuraEffect * aurEff, HealInfo & healInfo, uint32 & absorbAmount) +{ + (auraScript->*pEffectHandlerScript)(aurEff, healInfo, absorbAmount); +} + AuraScript::EffectManaShieldHandler::EffectManaShieldHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectBase(_effIndex, SPELL_AURA_MANA_SHIELD), pEffectHandlerScript(_pEffectHandlerScript) { diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 7cbb3a5121b..7deec060f01 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -690,6 +690,7 @@ class TC_GAME_API AuraScript : public _SpellScript typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \ typedef void(CLASSNAME::*AuraEffectCalcCritChanceFnType)(AuraEffect const*, Unit const*, float&); \ typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \ + typedef void(CLASSNAME::*AuraEffectAbsorbHealFnType)(AuraEffect*, HealInfo &, uint32 &); \ typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \ typedef bool(CLASSNAME::*AuraCheckProcFnType)(ProcEventInfo&); \ typedef bool(CLASSNAME::*AuraCheckEffectProcFnType)(AuraEffect const*, ProcEventInfo&); \ @@ -842,6 +843,14 @@ class TC_GAME_API AuraScript : public _SpellScript private: AuraEffectAbsorbFnType pEffectHandlerScript; }; + class TC_GAME_API EffectAbsorbHealHandler : public EffectBase + { + public: + EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex); + void Call(AuraScript* auraScript, AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount); + private: + AuraEffectAbsorbHealFnType pEffectHandlerScript; + }; class TC_GAME_API EffectManaShieldHandler : public EffectBase { public: @@ -945,6 +954,7 @@ class TC_GAME_API AuraScript : public _SpellScript class EffectCalcCritChanceHandlerFunction : public AuraScript::EffectCalcCritChanceHandler { public: explicit EffectCalcCritChanceHandlerFunction(AuraEffectCalcCritChanceFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectCalcCritChanceHandler((AuraScript::AuraEffectCalcCritChanceFnType)effectHandlerScript, effIndex, effName) { } }; \ class EffectApplyHandlerFunction : public AuraScript::EffectApplyHandler { public: explicit EffectApplyHandlerFunction(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode) : AuraScript::EffectApplyHandler((AuraScript::AuraEffectApplicationModeFnType)_pEffectHandlerScript, _effIndex, _effName, _mode) { } }; \ class EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: explicit EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overkill = false) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex, overkill) { } }; \ + class EffectAbsorbHealFunction : public AuraScript::EffectAbsorbHealHandler { public: EffectAbsorbHealFunction(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectAbsorbHealHandler((AuraScript::AuraEffectAbsorbHealFnType)_pEffectHandlerScript, _effIndex) { } }; \ class EffectManaShieldFunction : public AuraScript::EffectManaShieldHandler { public: explicit EffectManaShieldFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectManaShieldHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) { } }; \ class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: explicit EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) { } }; \ class CheckProcHandlerFunction : public AuraScript::CheckProcHandler { public: explicit CheckProcHandlerFunction(AuraCheckProcFnType handlerScript) : AuraScript::CheckProcHandler((AuraScript::AuraCheckProcFnType)handlerScript) { } }; \ @@ -1067,11 +1077,22 @@ class TC_GAME_API AuraScript : public _SpellScript #define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I) #define AuraEffectAbsorbOverkillFn(F, I) EffectAbsorbFunction(&F, I, true) + // 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); + HookList<EffectAbsorbHealHandler> OnEffectAbsorbHeal; + #define AuraEffectAbsorbHealFn(F, I) EffectAbsorbHealFunction(&F, I) + // 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, uint32& absorbAmount); HookList<EffectAbsorbHandler> AfterEffectAbsorb; + // 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); + HookList<EffectAbsorbHealHandler> AfterEffectAbsorbHeal; + // executed when mana shield aura effect is going to reduce damage // example: OnEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier); // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); |