diff options
author | Shauren <shauren.trinity@gmail.com> | 2023-07-24 00:27:25 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2023-07-24 00:27:25 +0200 |
commit | 228c56f3c5e23345cf2b5a391c614e52f61fe7f9 (patch) | |
tree | b08e9b0079045ec551d1bbb041fdfd9e49656004 /src | |
parent | 576ca241ecaea6f357a13f022fb297976aa967ca (diff) |
Scripts/Spells: Modernize spell script internals a bit - this makes Prepare macros unneccessary
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 389 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 232 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 597 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.h | 2505 |
6 files changed, 1994 insertions, 1741 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1239fccfaa1..1bbd97a85ef 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -6044,7 +6044,7 @@ void ObjectMgr::ValidateSpellScripts() if (spellScript) { - spellScript->_Init(&spellScriptLoader->GetName(), spellEntry->Id); + spellScript->_Init(spellScriptLoader->GetName(), spellEntry->Id); spellScript->_Register(); if (!spellScript->_Validate(spellEntry)) @@ -6056,7 +6056,7 @@ void ObjectMgr::ValidateSpellScripts() if (auraScript) { - auraScript->_Init(&spellScriptLoader->GetName(), spellEntry->Id); + auraScript->_Init(spellScriptLoader->GetName(), spellEntry->Id); auraScript->_Register(); if (!auraScript->_Validate(spellEntry)) diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 1dfaa9aeb67..76a51e0795f 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1350,8 +1350,8 @@ void ScriptMgr::FillSpellSummary() UnitAI::FillAISpellInfo(); } -template<typename T, typename F, typename O> -void CreateSpellOrAuraScripts(uint32 spellId, std::vector<T*>& scriptVector, F&& extractor, O* objectInvoker) +template<typename T, typename O> +void CreateSpellOrAuraScripts(uint32 spellId, std::vector<T*>& scriptVector, T*(SpellScriptLoader::*extractor)() const, O* objectInvoker) { SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); for (auto itr = bounds.first; itr != bounds.second; ++itr) @@ -1364,11 +1364,11 @@ void CreateSpellOrAuraScripts(uint32 spellId, std::vector<T*>& scriptVector, F&& if (!tmpscript) continue; - T* script = (*tmpscript.*extractor)(); + T* script = (tmpscript->*extractor)(); if (!script) continue; - script->_Init(&tmpscript->GetName(), spellId); + script->_Init(tmpscript->GetName(), spellId); if (!script->_Load(objectInvoker)) { delete script; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 14cb01ba3fc..03c7eac2081 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -476,9 +476,9 @@ m_lastProcAttemptTime(GameTime::Now() - Seconds(10)), m_lastProcSuccessTime(Game AuraScript* Aura::GetScriptByType(std::type_info const& type) const { - for (AuraScript* loadedScript : m_loadedScripts) - if (typeid(*loadedScript) == type) - return loadedScript; + for (AuraScript* script : m_loadedScripts) + if (typeid(*script) == type) + return script; return nullptr; } @@ -495,10 +495,10 @@ void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 const* baseAmount) Aura::~Aura() { // unload scripts - for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr) + for (AuraScript* script : m_loadedScripts) { - (*itr)->_Unload(); - delete (*itr); + script->_Unload(); + delete script; } for (AuraEffect* effect : _effects) @@ -2008,69 +2008,65 @@ void Aura::_DeleteRemovedApplications() void Aura::LoadScripts() { sScriptMgr->CreateAuraScripts(m_spellInfo->Id, m_loadedScripts, this); - for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr) + for (AuraScript* script : m_loadedScripts) { - TC_LOG_DEBUG("spells", "Aura::LoadScripts: Script `{}` for aura `{}` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id); - (*itr)->Register(); + TC_LOG_DEBUG("spells", "Aura::LoadScripts: Script `{}` for aura `{}` is loaded now", script->GetScriptName(), m_spellInfo->Id); + script->Register(); } } bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target) { bool result = true; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET); - auto hookItrEnd = (*scritr)->DoCheckAreaTarget.end(), hookItr = (*scritr)->DoCheckAreaTarget.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - result &= hookItr->Call(*scritr, target); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AREA_TARGET); + for (AuraScript::CheckAreaTargetHandler const& checkAreaTarget : script->DoCheckAreaTarget) + result &= checkAreaTarget.Call(script, target); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return result; } void Aura::CallScriptDispel(DispelInfo* dispelInfo) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL); - auto hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - hookItr->Call(*scritr, dispelInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL); + for (AuraScript::AuraDispelHandler const& onDispel : script->OnDispel) + onDispel.Call(script, dispelInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL); - auto hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - hookItr->Call(*scritr, dispelInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL); + for (AuraScript::AuraDispelHandler const& afterDispel : script->AfterDispel) + afterDispel.Call(script, dispelInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode) { bool preventDefault = false; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp); - auto effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, mode); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp); + for (AuraScript::EffectApplyHandler const& onEffectApply : script->OnEffectApply) + if (onEffectApply.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()) && onEffectApply.GetMode() & mode) + onEffectApply.Call(script, aurEff, mode); if (!preventDefault) - preventDefault = (*scritr)->_IsDefaultActionPrevented(); + preventDefault = script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return preventDefault; @@ -2079,65 +2075,61 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplicati bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode) { bool preventDefault = false; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp); - auto effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, mode); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp); + for (AuraScript::EffectApplyHandler const& onEffectRemove : script->OnEffectRemove) + if (onEffectRemove.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()) && onEffectRemove.GetMode() & mode) + onEffectRemove.Call(script, aurEff, mode); if (!preventDefault) - preventDefault = (*scritr)->_IsDefaultActionPrevented(); + preventDefault = script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return preventDefault; } void Aura::CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp); - auto effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, mode); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY, aurApp); + for (AuraScript::EffectApplyHandler const& afterEffectApply : script->AfterEffectApply) + if (afterEffectApply.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()) && afterEffectApply.GetMode() & mode) + afterEffectApply.Call(script, aurEff, mode); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptAfterEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp); - auto effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, mode); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE, aurApp); + for (AuraScript::EffectApplyHandler const& afterEffectRemove : script->AfterEffectRemove) + if (afterEffectRemove.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()) && afterEffectRemove.GetMode() & mode) + afterEffectRemove.Call(script, aurEff, mode); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp) { bool preventDefault = false; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp); - auto effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp); + for (AuraScript::EffectPeriodicHandler const& onEffectPeriodic : script->OnEffectPeriodic) + if (onEffectPeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + onEffectPeriodic.Call(script, aurEff); if (!preventDefault) - preventDefault = (*scritr)->_IsDefaultActionPrevented(); + preventDefault = script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return preventDefault; @@ -2145,202 +2137,191 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const* aurEff, AuraApplic void Aura::CallScriptEffectUpdatePeriodicHandlers(AuraEffect* aurEff) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC); - auto effEndItr = (*scritr)->OnEffectUpdatePeriodic.end(), effItr = (*scritr)->OnEffectUpdatePeriodic.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC); + for (AuraScript::EffectUpdatePeriodicHandler const& onEffectUpdatePeriodic : script->OnEffectUpdatePeriodic) + if (onEffectUpdatePeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + onEffectUpdatePeriodic.Call(script, aurEff); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT); - auto effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, amount, canBeRecalculated); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT); + for (AuraScript::EffectCalcAmountHandler const& effectCalcAmount : script->DoEffectCalcAmount) + if (effectCalcAmount.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effectCalcAmount.Call(script, aurEff, amount, canBeRecalculated); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC); - auto effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, isPeriodic, amplitude); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC); + for (AuraScript::EffectCalcPeriodicHandler const& effectCalcPeriodic : script->DoEffectCalcPeriodic) + if (effectCalcPeriodic.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effectCalcPeriodic.Call(script, aurEff, isPeriodic, amplitude); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const* aurEff, SpellModifier*& spellMod) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD); - auto effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, spellMod); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD); + for (AuraScript::EffectCalcSpellModHandler const& effectCalcSpellMod : script->DoEffectCalcSpellMod) + if (effectCalcSpellMod.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effectCalcSpellMod.Call(script, aurEff, spellMod); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectCalcCritChanceHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, Unit const* victim, float& critChance) { - for (AuraScript* loadedScript : m_loadedScripts) + for (AuraScript* script : m_loadedScripts) { - loadedScript->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_CRIT_CHANCE, aurApp); - for (AuraScript::EffectCalcCritChanceHandler const& hook : loadedScript->DoEffectCalcCritChance) - if (hook.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - hook.Call(loadedScript, aurEff, victim, critChance); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_CRIT_CHANCE, aurApp); + for (AuraScript::EffectCalcCritChanceHandler const& effectCalcCritChance : script->DoEffectCalcCritChance) + if (effectCalcCritChance.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effectCalcCritChance.Call(script, aurEff, victim, critChance); - loadedScript->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& defaultPrevented) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp); - auto effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin(); - for (; effItr != effEndItr; ++effItr) - - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp); + for (AuraScript::EffectAbsorbHandler const& onEffectAbsorb : script->OnEffectAbsorb) + if (onEffectAbsorb.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + onEffectAbsorb.Call(script, aurEff, dmgInfo, absorbAmount); if (!defaultPrevented) - defaultPrevented = (*scritr)->_IsDefaultActionPrevented(); + defaultPrevented = script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp); - auto effEndItr = (*scritr)->AfterEffectAbsorb.end(), effItr = (*scritr)->AfterEffectAbsorb.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp); + for (AuraScript::EffectAbsorbHandler const& afterEffectAbsorb : script->AfterEffectAbsorb) + if (afterEffectAbsorb.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + afterEffectAbsorb.Call(script, aurEff, dmgInfo, absorbAmount); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } 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) + for (AuraScript* script : m_loadedScripts) { - (*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); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp); + for (AuraScript::EffectAbsorbHealHandler const& onEffectAbsorbHeal : script->OnEffectAbsorbHeal) + if (onEffectAbsorbHeal.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + onEffectAbsorbHeal.Call(script, aurEff, healInfo, absorbAmount); if (!defaultPrevented) - defaultPrevented = (*scritr)->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + defaultPrevented = script->_IsDefaultActionPrevented(); + + script->_FinishScriptCall(); } } void Aura::CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, HealInfo& healInfo, uint32& absorbAmount) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp); - auto effEndItr = (*scritr)->AfterEffectAbsorbHeal.end(), effItr = (*scritr)->AfterEffectAbsorbHeal.begin(); - for (; effItr != effEndItr; ++effItr) + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB, aurApp); + for (AuraScript::EffectAbsorbHealHandler const& afterEffectAbsorbHeal : script->AfterEffectAbsorbHeal) + if (afterEffectAbsorbHeal.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + afterEffectAbsorbHeal.Call(script, aurEff, healInfo, absorbAmount); - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, healInfo, absorbAmount); - - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } -void Aura::CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount, bool& /*defaultPrevented*/) +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) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp); - auto effEndItr = (*scritr)->OnEffectManaShield.end(), effItr = (*scritr)->OnEffectManaShield.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, aurApp); + for (AuraScript::EffectAbsorbHandler const& onEffectManaShield : script->OnEffectManaShield) + if (onEffectManaShield.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + onEffectManaShield.Call(script, aurEff, dmgInfo, absorbAmount); + + if (!defaultPrevented) + defaultPrevented = script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& absorbAmount) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp); - auto effEndItr = (*scritr)->AfterEffectManaShield.end(), effItr = (*scritr)->AfterEffectManaShield.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, dmgInfo, absorbAmount); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, aurApp); + for (AuraScript::EffectAbsorbHandler const& afterEffectManaShield : script->AfterEffectManaShield) + if (afterEffectManaShield.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + afterEffectManaShield.Call(script, aurEff, dmgInfo, absorbAmount); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo& dmgInfo, uint32& splitAmount) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp); - auto effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, dmgInfo, splitAmount); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp); + for (AuraScript::EffectAbsorbHandler const& effectSplit : script->OnEffectSplit) + if (effectSplit.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + effectSplit.Call(script, aurEff, dmgInfo, splitAmount); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Aura::CallScriptEnterLeaveCombatHandlers(AuraApplication const* aurApp, bool isNowInCombat) { - for (AuraScript* loadedScript : m_loadedScripts) + for (AuraScript* script : m_loadedScripts) { - loadedScript->_PrepareScriptCall(AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT, aurApp); - for (AuraScript::EnterLeaveCombatHandler const& hook : loadedScript->OnEnterLeaveCombat) - hook.Call(loadedScript, isNowInCombat); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT, aurApp); + for (AuraScript::EnterLeaveCombatHandler const& onEnterLeaveCombat : script->OnEnterLeaveCombat) + onEnterLeaveCombat.Call(script, isNowInCombat); - loadedScript->_FinishScriptCall(); + script->_FinishScriptCall(); } } bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) { bool result = true; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp); - auto hookItrEnd = (*scritr)->DoCheckProc.end(), hookItr = (*scritr)->DoCheckProc.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - result &= hookItr->Call(*scritr, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_PROC, aurApp); + for (AuraScript::CheckProcHandler const& checkProc : script->DoCheckProc) + result &= checkProc.Call(script, eventInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return result; @@ -2349,17 +2330,16 @@ bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventI bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) { bool prepare = true; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp); - auto effEndItr = (*scritr)->DoPrepareProc.end(), effItr = (*scritr)->DoPrepareProc.begin(); - for (; effItr != effEndItr; ++effItr) - effItr->Call(*scritr, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_PREPARE_PROC, aurApp); + for (AuraScript::AuraProcHandler const& prepareProc : script->DoPrepareProc) + prepareProc.Call(script, eventInfo); if (prepare) - prepare = !(*scritr)->_IsDefaultActionPrevented(); + prepare = !script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return prepare; @@ -2368,15 +2348,14 @@ bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEven bool Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) { bool handled = false; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp); - auto hookItrEnd = (*scritr)->OnProc.end(), hookItr = (*scritr)->OnProc.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - hookItr->Call(*scritr, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_PROC, aurApp); + for (AuraScript::AuraProcHandler const& onProc : script->OnProc) + onProc.Call(script, eventInfo); - handled |= (*scritr)->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + handled |= script->_IsDefaultActionPrevented(); + script->_FinishScriptCall(); } return handled; @@ -2384,29 +2363,27 @@ bool Aura::CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& void Aura::CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp); - auto hookItrEnd = (*scritr)->AfterProc.end(), hookItr = (*scritr)->AfterProc.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - hookItr->Call(*scritr, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_PROC, aurApp); + for (AuraScript::AuraProcHandler const& afterProc : script->AfterProc) + afterProc.Call(script, eventInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } bool Aura::CallScriptCheckEffectProcHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo) { bool result = true; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC, aurApp); - auto hookItrEnd = (*scritr)->DoCheckEffectProc.end(), hookItr = (*scritr)->DoCheckEffectProc.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - if (hookItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - result &= hookItr->Call(*scritr, aurEff, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC, aurApp); + for (AuraScript::CheckEffectProcHandler const& checkEffectProc : script->DoCheckEffectProc) + if (checkEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + result &= checkEffectProc.Call(script, aurEff, eventInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return result; @@ -2415,33 +2392,31 @@ bool Aura::CallScriptCheckEffectProcHandlers(AuraEffect const* aurEff, AuraAppli bool Aura::CallScriptEffectProcHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo) { bool preventDefault = false; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp); - auto effEndItr = (*scritr)->OnEffectProc.end(), effItr = (*scritr)->OnEffectProc.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PROC, aurApp); + for (AuraScript::EffectProcHandler const& onEffectProc : script->OnEffectProc) + if (onEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + onEffectProc.Call(script, aurEff, eventInfo); if (!preventDefault) - preventDefault = (*scritr)->_IsDefaultActionPrevented(); + preventDefault = script->_IsDefaultActionPrevented(); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return preventDefault; } void Aura::CallScriptAfterEffectProcHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, ProcEventInfo& eventInfo) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (AuraScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp); - auto effEndItr = (*scritr)->AfterEffectProc.end(), effItr = (*scritr)->AfterEffectProc.begin(); - for (; effItr != effEndItr; ++effItr) - if (effItr->IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) - effItr->Call(*scritr, aurEff, eventInfo); + script->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC, aurApp); + for (AuraScript::EffectProcHandler const& afterEffectProc : script->AfterEffectProc) + if (afterEffectProc.IsEffectAffected(m_spellInfo, aurEff->GetEffIndex())) + afterEffectProc.Call(script, aurEff, eventInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1c3d183692a..1cbc3817bdd 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -8484,88 +8484,84 @@ void Spell::FinishTargetProcessing() void Spell::LoadScripts() { sScriptMgr->CreateSpellScripts(m_spellInfo->Id, m_loadedScripts, this); - for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr) + for (SpellScript* script : m_loadedScripts) { - TC_LOG_DEBUG("spells", "Spell::LoadScripts: Script `{}` for spell `{}` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id); - (*itr)->Register(); + TC_LOG_DEBUG("spells", "Spell::LoadScripts: Script `{}` for spell `{}` is loaded now", script->GetScriptName(), m_spellInfo->Id); + script->Register(); } } void Spell::CallScriptOnPrecastHandler() { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_PRECAST); - (*scritr)->OnPrecast(); - (*scritr)->_FinishScriptCall(); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_PRECAST); + script->OnPrecast(); + script->_FinishScriptCall(); } } void Spell::CallScriptBeforeCastHandlers() { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_CAST); - auto hookItrEnd = (*scritr)->BeforeCast.end(), hookItr = (*scritr)->BeforeCast.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_CAST); + for (SpellScript::CastHandler const& beforeCast : script->BeforeCast) + beforeCast.Call(script); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptOnCastHandlers() { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_CAST); - auto hookItrEnd = (*scritr)->OnCast.end(), hookItr = (*scritr)->OnCast.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_CAST); + for (SpellScript::CastHandler const& onCast : script->OnCast) + onCast.Call(script); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptAfterCastHandlers() { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_CAST); - auto hookItrEnd = (*scritr)->AfterCast.end(), hookItr = (*scritr)->AfterCast.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_CAST); + for (SpellScript::CastHandler const& afterCast : script->AfterCast) + afterCast.Call(script); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } SpellCastResult Spell::CallScriptCheckCastHandlers() { SpellCastResult retVal = SPELL_CAST_OK; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CHECK_CAST); - auto hookItrEnd = (*scritr)->OnCheckCast.end(), hookItr = (*scritr)->OnCheckCast.begin(); - for (; hookItr != hookItrEnd; ++hookItr) + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CHECK_CAST); + for (SpellScript::CheckCastHandler const& checkCast : script->OnCheckCast) { - SpellCastResult tempResult = (*hookItr).Call(*scritr); + SpellCastResult tempResult = checkCast.Call(script); if (retVal == SPELL_CAST_OK) retVal = tempResult; } - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return retVal; } int32 Spell::CallScriptCalcCastTimeHandlers(int32 castTime) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CALC_CAST_TIME); - castTime = (*scritr)->CalcCastTime(castTime); - (*scritr)->_FinishScriptCall(); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CALC_CAST_TIME); + castTime = script->CalcCastTime(castTime); + script->_FinishScriptCall(); } return castTime; } @@ -8574,156 +8570,157 @@ bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMo { // execute script effect handler hooks and check if effects was prevented bool preventDefault = false; - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_InitHit(); + script->_InitHit(); - HookList<SpellScript::EffectHandler>::iterator effItr, effEndItr; + Trinity::IteratorPair<HookList<SpellScript::EffectHandler>::iterator> effectHandlers; SpellScriptHookType hookType; switch (mode) { case SPELL_EFFECT_HANDLE_LAUNCH: - effItr = (*scritr)->OnEffectLaunch.begin(); - effEndItr = (*scritr)->OnEffectLaunch.end(); + effectHandlers = Trinity::Containers::MakeIteratorPair(script->OnEffectLaunch.begin(), script->OnEffectLaunch.end()); hookType = SPELL_SCRIPT_HOOK_EFFECT_LAUNCH; break; case SPELL_EFFECT_HANDLE_LAUNCH_TARGET: - effItr = (*scritr)->OnEffectLaunchTarget.begin(); - effEndItr = (*scritr)->OnEffectLaunchTarget.end(); + effectHandlers = Trinity::Containers::MakeIteratorPair(script->OnEffectLaunchTarget.begin(), script->OnEffectLaunchTarget.end()); hookType = SPELL_SCRIPT_HOOK_EFFECT_LAUNCH_TARGET; break; case SPELL_EFFECT_HANDLE_HIT: - effItr = (*scritr)->OnEffectHit.begin(); - effEndItr = (*scritr)->OnEffectHit.end(); + effectHandlers = Trinity::Containers::MakeIteratorPair(script->OnEffectHit.begin(), script->OnEffectHit.end()); hookType = SPELL_SCRIPT_HOOK_EFFECT_HIT; break; case SPELL_EFFECT_HANDLE_HIT_TARGET: - effItr = (*scritr)->OnEffectHitTarget.begin(); - effEndItr = (*scritr)->OnEffectHitTarget.end(); + effectHandlers = Trinity::Containers::MakeIteratorPair(script->OnEffectHitTarget.begin(), script->OnEffectHitTarget.end()); hookType = SPELL_SCRIPT_HOOK_EFFECT_HIT_TARGET; break; default: ABORT(); return false; } - (*scritr)->_PrepareScriptCall(hookType); - for (; effItr != effEndItr; ++effItr) + script->_PrepareScriptCall(hookType); + for (SpellScript::EffectHandler const& effectHandler : effectHandlers) // effect execution can be prevented - if (!(*scritr)->_IsEffectPrevented(effIndex) && (*effItr).IsEffectAffected(m_spellInfo, effIndex)) - (*effItr).Call(*scritr, effIndex); + if (!script->_IsEffectPrevented(effIndex) && effectHandler.IsEffectAffected(m_spellInfo, effIndex)) + effectHandler.Call(script, effIndex); if (!preventDefault) - preventDefault = (*scritr)->_IsDefaultEffectPrevented(effIndex); + preventDefault = script->_IsDefaultEffectPrevented(effIndex); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } return preventDefault; } void Spell::CallScriptSuccessfulDispel(SpellEffIndex effIndex) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL); - auto hookItrEnd = (*scritr)->OnEffectSuccessfulDispel.end(), hookItr = (*scritr)->OnEffectSuccessfulDispel.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - hookItr->Call(*scritr, effIndex); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL); + for (SpellScript::EffectHandler const& onDispel : script->OnEffectSuccessfulDispel) + onDispel.Call(script, effIndex); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptBeforeHitHandlers(SpellMissInfo missInfo) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_InitHit(); - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_HIT); - auto hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr, missInfo); + script->_InitHit(); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_HIT); + for (SpellScript::BeforeHitHandler const& beforeHit : script->BeforeHit) + beforeHit.Call(script, missInfo); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptOnHitHandlers() { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_HIT); - auto hookItrEnd = (*scritr)->OnHit.end(), hookItr = (*scritr)->OnHit.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_HIT); + for (SpellScript::HitHandler const& onHit : script->OnHit) + onHit.Call(script); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptAfterHitHandlers() { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_HIT); - auto hookItrEnd = (*scritr)->AfterHit.end(), hookItr = (*scritr)->AfterHit.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_HIT); + for (SpellScript::HitHandler const& afterHit : script->AfterHit) + afterHit.Call(script); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptCalcCritChanceHandlers(Unit const* victim, float& critChance) { - for (SpellScript* loadedScript : m_loadedScripts) + for (SpellScript* script : m_loadedScripts) { - loadedScript->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CALC_CRIT_CHANCE); - for (SpellScript::OnCalcCritChanceHandler const& hook : loadedScript->OnCalcCritChance) - hook.Call(loadedScript, victim, critChance); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CALC_CRIT_CHANCE); + for (SpellScript::OnCalcCritChanceHandler const& calcCritChance : script->OnCalcCritChance) + calcCritChance.Call(script, victim, critChance); - loadedScript->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT); - auto hookItrEnd = (*scritr)->OnObjectAreaTargetSelect.end(), hookItr = (*scritr)->OnObjectAreaTargetSelect.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget()) - hookItr->Call(*scritr, targets); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT); + for (SpellScript::ObjectAreaTargetSelectHandler const& objectAreaTargetSelect : script->OnObjectAreaTargetSelect) + if (objectAreaTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == objectAreaTargetSelect.GetTarget()) + objectAreaTargetSelect.Call(script, targets); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT); - auto hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget()) - hookItr->Call(*scritr, target); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT); + for (SpellScript::ObjectTargetSelectHandler const& objectTargetSelect : script->OnObjectTargetSelect) + if (objectTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == objectTargetSelect.GetTarget()) + objectTargetSelect.Call(script, target); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } void Spell::CallScriptDestinationTargetSelectHandlers(SpellDestination& target, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + for (SpellScript* script : m_loadedScripts) + { + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT); + for (SpellScript::DestinationTargetSelectHandler const& destinationTargetSelect : script->OnDestinationTargetSelect) + if (destinationTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == destinationTargetSelect.GetTarget()) + destinationTargetSelect.Call(script, target); + + script->_FinishScriptCall(); + } +} + +void Spell::CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) +{ + for (SpellScript* script : m_loadedScripts) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT); - auto hookItrEnd = (*scritr)->OnDestinationTargetSelect.end(), hookItr = (*scritr)->OnDestinationTargetSelect.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - if (hookItr->IsEffectAffected(m_spellInfo, effIndex) && targetType.GetTarget() == hookItr->GetTarget()) - hookItr->Call(*scritr, target); + script->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_RESIST_ABSORB_CALCULATION); + for (SpellScript::OnCalculateResistAbsorbHandler const& calculateResistAbsorb : script->OnCalculateResistAbsorb) + calculateResistAbsorb.Call(script, damageInfo, resistAmount, absorbAmount); - (*scritr)->_FinishScriptCall(); + script->_FinishScriptCall(); } } @@ -8733,18 +8730,16 @@ bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToC if (m_loadedScripts.empty()) return true; - for (auto itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr) + for (SpellScript* script : m_loadedScripts) { - auto targetSelectHookEnd = (*itr)->OnObjectTargetSelect.end(), targetSelectHookItr = (*itr)->OnObjectTargetSelect.begin(); - for (; targetSelectHookItr != targetSelectHookEnd; ++targetSelectHookItr) - if (((*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) || - (!(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck))) + for (SpellScript::ObjectTargetSelectHandler const& objectTargetSelect : script->OnObjectTargetSelect) + if ((objectTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && !objectTargetSelect.IsEffectAffected(m_spellInfo, effIndexToCheck)) || + (!objectTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && objectTargetSelect.IsEffectAffected(m_spellInfo, effIndexToCheck))) return false; - auto areaTargetSelectHookEnd = (*itr)->OnObjectAreaTargetSelect.end(), areaTargetSelectHookItr = (*itr)->OnObjectAreaTargetSelect.begin(); - for (; areaTargetSelectHookItr != areaTargetSelectHookEnd; ++areaTargetSelectHookItr) - if (((*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) || - (!(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck))) + for (SpellScript::ObjectAreaTargetSelectHandler const& objectAreaTargetSelect : script->OnObjectAreaTargetSelect) + if ((objectAreaTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && !objectAreaTargetSelect.IsEffectAffected(m_spellInfo, effIndexToCheck)) || + (!objectAreaTargetSelect.IsEffectAffected(m_spellInfo, effIndex) && objectAreaTargetSelect.IsEffectAffected(m_spellInfo, effIndexToCheck))) return false; } return true; @@ -8890,19 +8885,6 @@ std::string Spell::GetDebugInfo() const return sstr.str(); } -void Spell::CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) -{ - for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) - { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_RESIST_ABSORB_CALCULATION); - auto hookItrEnd = (*scritr)->OnCalculateResistAbsorb.end(), hookItr = (*scritr)->OnCalculateResistAbsorb.begin(); - for (; hookItr != hookItrEnd; ++hookItr) - hookItr->Call(*scritr, damageInfo, resistAmount, absorbAmount); - - (*scritr)->_FinishScriptCall(); - } -} - bool Spell::IsWithinLOS(WorldObject const* source, WorldObject const* target, bool targetAsSourceLocation, VMAP::ModelIgnoreFlags ignoreFlags) const { if (m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT)) diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index f9eb92a1725..50ca1ba5653 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -17,74 +17,74 @@ #include "SpellScript.h" #include "Log.h" -#include "Spell.h" #include "ScriptMgr.h" +#include "Spell.h" #include "SpellAuras.h" #include "SpellMgr.h" +#include "StringConvert.h" #include "Unit.h" -#include <sstream> #include <string> -bool _SpellScript::_Validate(SpellInfo const* entry) +bool SpellScriptBase::_Validate(SpellInfo const* entry) { if (!Validate(entry)) { - TC_LOG_ERROR("scripts", "Spell `{}` did not pass Validate() function of script `{}` - script will be not added to the spell", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` did not pass Validate() function of script `{}` - script will be not added to the spell", entry->Id, m_scriptName); return false; } return true; } -_SpellScript::_SpellScript(): m_currentScriptState(SPELL_SCRIPT_STATE_NONE), m_scriptName(nullptr), m_scriptSpellId(0) +SpellScriptBase::SpellScriptBase(): m_currentScriptState(SPELL_SCRIPT_STATE_NONE), m_scriptSpellId(0) { } -_SpellScript::~_SpellScript() = default; +SpellScriptBase::~SpellScriptBase() = default; -bool _SpellScript::_ValidateSpellInfo(uint32 spellId) +bool SpellScriptBase::ValidateSpellInfoImpl(uint32 spellId) { if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE)) { - TC_LOG_ERROR("scripts.spells", "_SpellScript::ValidateSpellInfo: Spell {} does not exist.", spellId); + TC_LOG_ERROR("scripts.spells", "SpellScriptBase::ValidateSpellInfo: Spell {} does not exist.", spellId); return false; } return true; } -bool _SpellScript::_ValidateSpellEffect(uint32 spellId, SpellEffIndex effectIndex) +bool SpellScriptBase::ValidateSpellEffectImpl(uint32 spellId, SpellEffIndex effectIndex) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE); if (!spellInfo) { - TC_LOG_ERROR("scripts.spells", "_SpellScript::_ValidateSpellEffect: Spell {} does not exist.", spellId); + TC_LOG_ERROR("scripts.spells", "SpellScriptBase::ValidateSpellEffect: Spell {} does not exist.", spellId); return false; } if (spellInfo->GetEffects().size() <= effectIndex) { - TC_LOG_ERROR("scripts.spells", "_SpellScript::_ValidateSpellEffect: Spell {} does not have EFFECT_{}.", spellId, uint32(effectIndex)); + TC_LOG_ERROR("scripts.spells", "SpellScriptBase::ValidateSpellEffect: Spell {} does not have EFFECT_{}.", spellId, uint32(effectIndex)); return false; } return true; } -void _SpellScript::_Register() +void SpellScriptBase::_Register() { m_currentScriptState = SPELL_SCRIPT_STATE_REGISTRATION; Register(); m_currentScriptState = SPELL_SCRIPT_STATE_NONE; } -void _SpellScript::_Unload() +void SpellScriptBase::_Unload() { m_currentScriptState = SPELL_SCRIPT_STATE_UNLOADING; Unload(); m_currentScriptState = SPELL_SCRIPT_STATE_NONE; } -void _SpellScript::_Init(std::string const* scriptname, uint32 spellId) +void SpellScriptBase::_Init(std::string const& scriptname, uint32 spellId) { m_currentScriptState = SPELL_SCRIPT_STATE_NONE; m_scriptName = scriptname; @@ -93,76 +93,70 @@ void _SpellScript::_Init(std::string const* scriptname, uint32 spellId) #ifdef TRINITY_API_USE_DYNAMIC_LINKING // Acquire a strong reference to the binary code // to keep it loaded until all spells are destroyed. - m_moduleReference = sScriptMgr->AcquireModuleReferenceOfScriptName(*scriptname); + m_moduleReference = sScriptMgr->AcquireModuleReferenceOfScriptName(scriptname); #endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING } -std::string const* _SpellScript::_GetScriptName() const +std::string_view SpellScriptBase::GetScriptName() const { return m_scriptName; } -_SpellScript::EffectHook::EffectHook(uint8 _effIndex) +SpellScriptBase::EffectHook::EffectHook(uint8 effIndex) { // effect index must be in range <0;2>, allow use of special effindexes - ASSERT(_effIndex == EFFECT_ALL || _effIndex == EFFECT_FIRST_FOUND || _effIndex < MAX_SPELL_EFFECTS); - effIndex = _effIndex; + ASSERT(effIndex == EFFECT_ALL || effIndex == EFFECT_FIRST_FOUND || effIndex < MAX_SPELL_EFFECTS); + _effIndex = effIndex; } -_SpellScript::EffectHook::EffectHook(EffectHook&& right) noexcept = default; -_SpellScript::EffectHook& _SpellScript::EffectHook::operator=(EffectHook&& right) noexcept = default; -_SpellScript::EffectHook::~EffectHook() = default; +SpellScriptBase::EffectHook::EffectHook(EffectHook&& right) noexcept = default; +SpellScriptBase::EffectHook& SpellScriptBase::EffectHook::operator=(EffectHook&& right) noexcept = default; +SpellScriptBase::EffectHook::~EffectHook() = default; -uint32 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEntry) const +uint32 SpellScriptBase::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellInfo) const { uint32 mask = 0; - if ((effIndex == EFFECT_ALL) || (effIndex == EFFECT_FIRST_FOUND)) + if (_effIndex == EFFECT_ALL || _effIndex == EFFECT_FIRST_FOUND) { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if ((effIndex == EFFECT_FIRST_FOUND) && mask) + if (_effIndex == EFFECT_FIRST_FOUND && mask) return mask; - if (CheckEffect(spellEntry, i)) + if (CheckEffect(spellInfo, i)) mask |= 1 << i; } } else { - if (CheckEffect(spellEntry, effIndex)) - mask |= 1 << effIndex; + if (CheckEffect(spellInfo, _effIndex)) + mask |= 1 << _effIndex; } return mask; } -bool _SpellScript::EffectHook::IsEffectAffected(SpellInfo const* spellEntry, uint8 effIndexToCheck) const +bool SpellScriptBase::EffectHook::IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex) const { - return (GetAffectedEffectsMask(spellEntry) & 1 << effIndexToCheck) != 0; + return (GetAffectedEffectsMask(spellInfo) & 1 << effIndex) != 0; } -std::string _SpellScript::EffectHook::EffIndexToString() const +std::string SpellScriptBase::EffectHook::EffIndexToString() const { - if (effIndex == EFFECT_ALL) + if (_effIndex == EFFECT_ALL) return "EFFECT_ALL"; - if (effIndex == EFFECT_FIRST_FOUND) + if (_effIndex == EFFECT_FIRST_FOUND) return "EFFECT_FIRST_FOUND"; - if (effIndex < MAX_SPELL_EFFECTS) - return Trinity::StringFormat("EFFECT_{}", uint32(effIndex)); + if (_effIndex < MAX_SPELL_EFFECTS) + return Trinity::StringFormat("EFFECT_{}", uint32(_effIndex)); return "Invalid Value"; } -_SpellScript::EffectNameCheck::EffectNameCheck(uint16 _effName) : effName(_effName) +namespace EffectNameCheck { -} - -_SpellScript::EffectNameCheck::EffectNameCheck(EffectNameCheck&& right) noexcept = default; -_SpellScript::EffectNameCheck& _SpellScript::EffectNameCheck::operator=(EffectNameCheck&& right) noexcept = default; -_SpellScript::EffectNameCheck::~EffectNameCheck() = default; - -bool _SpellScript::EffectNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) const +bool Check(SpellInfo const* spellInfo, uint8 effIndex, uint16 effName) { - if (spellEntry->GetEffects().size() <= effIndex) + if (spellInfo->GetEffects().size() <= effIndex) return false; - SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); + SpellEffectInfo const& spellEffectInfo = spellInfo->GetEffect(SpellEffIndex(effIndex)); if (!spellEffectInfo.Effect && !effName) return true; if (!spellEffectInfo.Effect) @@ -170,53 +164,19 @@ bool _SpellScript::EffectNameCheck::Check(SpellInfo const* spellEntry, uint8 eff return (effName == SPELL_EFFECT_ANY) || (spellEffectInfo.Effect == effName); } -std::string _SpellScript::EffectNameCheck::ToString() const +std::string ToString(uint16 effName) { switch (effName) { case SPELL_EFFECT_ANY: return "SPELL_EFFECT_ANY"; default: - char num[10]; - sprintf (num, "%u", effName); - return num; - } -} - -_SpellScript::EffectAuraNameCheck::EffectAuraNameCheck(uint16 _effAurName) : effAurName(_effAurName) -{ -} - -_SpellScript::EffectAuraNameCheck::EffectAuraNameCheck(EffectAuraNameCheck&& right) noexcept = default; -_SpellScript::EffectAuraNameCheck& _SpellScript::EffectAuraNameCheck::operator=(EffectAuraNameCheck&& right) noexcept = default; -_SpellScript::EffectAuraNameCheck::~EffectAuraNameCheck() = default; - -bool _SpellScript::EffectAuraNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) const -{ - if (spellEntry->GetEffects().size() <= effIndex) - return false; - SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); - if (!spellEffectInfo.ApplyAuraName && !effAurName) - return true; - if (!spellEffectInfo.ApplyAuraName) - return false; - return (effAurName == SPELL_AURA_ANY) || (spellEffectInfo.ApplyAuraName == effAurName); -} - -std::string _SpellScript::EffectAuraNameCheck::ToString() const -{ - switch (effAurName) - { - case SPELL_AURA_ANY: - return "SPELL_AURA_ANY"; - default: - char num[10]; - sprintf (num, "%u", effAurName); - return num; + return Trinity::ToString(effName); } } +}; -SpellScript::CastHandler::CastHandler(SpellCastFnType _pCastHandlerScript) : pCastHandlerScript(_pCastHandlerScript) +SpellScript::CastHandler::CastHandler(SpellCastFnType callImpl) : _callImpl(callImpl) { } @@ -224,12 +184,12 @@ SpellScript::CastHandler::CastHandler(CastHandler&& right) noexcept = default; SpellScript::CastHandler& SpellScript::CastHandler::operator=(CastHandler&& right) noexcept = default; SpellScript::CastHandler::~CastHandler() = default; -void SpellScript::CastHandler::Call(SpellScript* spellScript) +void SpellScript::CastHandler::Call(SpellScript* spellScript) const { - (spellScript->*pCastHandlerScript)(); + (spellScript->*_callImpl)(); } -SpellScript::CheckCastHandler::CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript) : _checkCastHandlerScript(checkCastHandlerScript) +SpellScript::CheckCastHandler::CheckCastHandler(SpellCheckCastFnType callImpl) : _callImpl(callImpl) { } @@ -237,27 +197,13 @@ SpellScript::CheckCastHandler::CheckCastHandler(CheckCastHandler&& right) noexce SpellScript::CheckCastHandler& SpellScript::CheckCastHandler::operator=(CheckCastHandler&& right) noexcept = default; SpellScript::CheckCastHandler::~CheckCastHandler() = default; -SpellCastResult SpellScript::CheckCastHandler::Call(SpellScript* spellScript) +SpellCastResult SpellScript::CheckCastHandler::Call(SpellScript* spellScript) const { - return (spellScript->*_checkCastHandlerScript)(); + return (spellScript->*_callImpl)(); } -SpellScript::OnCalculateResistAbsorbHandler::OnCalculateResistAbsorbHandler(SpellOnResistAbsorbCalculateFnType onResistAbsorbCalculateHandlerScript) : - pOnCalculateResistAbsorbHandlerScript(onResistAbsorbCalculateHandlerScript) -{ -} - -SpellScript::OnCalculateResistAbsorbHandler::OnCalculateResistAbsorbHandler(OnCalculateResistAbsorbHandler&& right) noexcept = default; -SpellScript::OnCalculateResistAbsorbHandler& SpellScript::OnCalculateResistAbsorbHandler::operator=(OnCalculateResistAbsorbHandler&& right) noexcept = default; -SpellScript::OnCalculateResistAbsorbHandler::~OnCalculateResistAbsorbHandler() = default; - -void SpellScript::OnCalculateResistAbsorbHandler::Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) -{ - return (spellScript->*pOnCalculateResistAbsorbHandlerScript)(damageInfo, resistAmount, absorbAmount); -} - -SpellScript::EffectHandler::EffectHandler(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) - : _SpellScript::EffectNameCheck(_effName), _SpellScript::EffectHook(_effIndex), pEffectHandlerScript(_pEffectHandlerScript) +SpellScript::EffectHandler::EffectHandler(SpellEffectFnType callImpl, uint8 effIndex, uint16 effName) + : EffectHook(effIndex), _callImpl(callImpl), _effName(effName) { } @@ -267,20 +213,20 @@ SpellScript::EffectHandler::~EffectHandler() = default; std::string SpellScript::EffectHandler::ToString() const { - return "Index: " + EffIndexToString() + " Name: " +_SpellScript::EffectNameCheck::ToString(); + return "Index: " + EffIndexToString() + " Name: " + EffectNameCheck::ToString(_effName); } -bool SpellScript::EffectHandler::CheckEffect(SpellInfo const* spellEntry, uint8 effIndexToCheck) const +bool SpellScript::EffectHandler::CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const { - return _SpellScript::EffectNameCheck::Check(spellEntry, effIndexToCheck); + return EffectNameCheck::Check(spellInfo, effIndex, _effName); } -void SpellScript::EffectHandler::Call(SpellScript* spellScript, SpellEffIndex effIndexToHandle) +void SpellScript::EffectHandler::Call(SpellScript* spellScript, SpellEffIndex effIndex) const { - (spellScript->*pEffectHandlerScript)(effIndexToHandle); + (spellScript->*_callImpl)(effIndex); } -SpellScript::BeforeHitHandler::BeforeHitHandler(SpellBeforeHitFnType pBeforeHitHandlerScript) : _pBeforeHitHandlerScript(pBeforeHitHandlerScript) +SpellScript::BeforeHitHandler::BeforeHitHandler(SpellBeforeHitFnType callImpl) : _callImpl(callImpl) { } @@ -288,26 +234,24 @@ SpellScript::BeforeHitHandler::BeforeHitHandler(BeforeHitHandler&& right) noexce SpellScript::BeforeHitHandler& SpellScript::BeforeHitHandler::operator=(BeforeHitHandler&& right) noexcept = default; SpellScript::BeforeHitHandler::~BeforeHitHandler() = default; -void SpellScript::BeforeHitHandler::Call(SpellScript* spellScript, SpellMissInfo missInfo) +void SpellScript::BeforeHitHandler::Call(SpellScript* spellScript, SpellMissInfo missInfo) const { - (spellScript->*_pBeforeHitHandlerScript)(missInfo); + (spellScript->*_callImpl)(missInfo); } -SpellScript::HitHandler::HitHandler(SpellHitFnType _pHitHandlerScript) : pHitHandlerScript(_pHitHandlerScript) -{ -} +SpellScript::HitHandler::HitHandler(SpellHitFnType callImpl) : _callImpl(callImpl) +{ } SpellScript::HitHandler::HitHandler(HitHandler&& right) noexcept = default; SpellScript::HitHandler& SpellScript::HitHandler::operator=(HitHandler&& right) noexcept = default; SpellScript::HitHandler::~HitHandler() = default; -void SpellScript::HitHandler::Call(SpellScript* spellScript) +void SpellScript::HitHandler::Call(SpellScript* spellScript) const { - (spellScript->*pHitHandlerScript)(); + (spellScript->*_callImpl)(); } -SpellScript::OnCalcCritChanceHandler::OnCalcCritChanceHandler(SpellOnCalcCritChanceFnType onCalcCritChanceHandlerScript) : _onCalcCritChanceHandlerScript( - onCalcCritChanceHandlerScript) +SpellScript::OnCalcCritChanceHandler::OnCalcCritChanceHandler(SpellOnCalcCritChanceFnType callImpl) : _callImpl(callImpl) { } @@ -317,11 +261,11 @@ SpellScript::OnCalcCritChanceHandler::~OnCalcCritChanceHandler() = default; void SpellScript::OnCalcCritChanceHandler::Call(SpellScript* spellScript, Unit const* victim, float& critChance) const { - (spellScript->*_onCalcCritChanceHandlerScript)(victim, critChance); + return (spellScript->*_callImpl)(victim, critChance); } -SpellScript::TargetHook::TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest) - : _SpellScript::EffectHook(_effectIndex), targetType(_targetType), area(_area), dest(_dest) { } +SpellScript::TargetHook::TargetHook(uint8 effectIndex, uint16 targetType, bool area, bool dest) + : EffectHook(effectIndex), _targetType(targetType), _area(area), _dest(dest) { } SpellScript::TargetHook::TargetHook(TargetHook&& right) noexcept = default; SpellScript::TargetHook& SpellScript::TargetHook::operator=(TargetHook&& right) noexcept = default; @@ -329,50 +273,48 @@ SpellScript::TargetHook::~TargetHook() = default; std::string SpellScript::TargetHook::ToString() const { - std::ostringstream oss; - oss << "Index: " << EffIndexToString() << " Target: " << targetType; - return oss.str(); + return Trinity::StringFormat("Index: {} Target: {}", EffIndexToString(), _targetType); } -bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 effIndexToCheck) const +bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const { - if (!targetType) + if (!_targetType) return false; - if (spellEntry->GetEffects().size() <= effIndexToCheck) + if (spellInfo->GetEffects().size() <= effIndex) return false; - SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndexToCheck)); - if (spellEffectInfo.TargetA.GetTarget() != targetType && - spellEffectInfo.TargetB.GetTarget() != targetType) + SpellEffectInfo const& spellEffectInfo = spellInfo->GetEffect(SpellEffIndex(effIndex)); + if (spellEffectInfo.TargetA.GetTarget() != _targetType && + spellEffectInfo.TargetB.GetTarget() != _targetType) return false; - SpellImplicitTargetInfo targetInfo(targetType); + SpellImplicitTargetInfo targetInfo(_targetType); switch (targetInfo.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_CHANNEL: // SINGLE - return !area; + return !_area; case TARGET_SELECT_CATEGORY_NEARBY: // BOTH return true; case TARGET_SELECT_CATEGORY_CONE: // AREA case TARGET_SELECT_CATEGORY_LINE: // AREA - return area; + return _area; case TARGET_SELECT_CATEGORY_AREA: // AREA if (targetInfo.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST) - return area || dest; - return area; + return _area || _dest; + return _area; case TARGET_SELECT_CATEGORY_DEFAULT: switch (targetInfo.GetObjectType()) { case TARGET_OBJECT_TYPE_SRC: // EMPTY return false; case TARGET_OBJECT_TYPE_DEST: // DEST - return dest; + return _dest; default: switch (targetInfo.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: // SINGLE - return !area; + return !_area; case TARGET_REFERENCE_TYPE_TARGET: // BOTH return true; default: @@ -388,8 +330,8 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff return false; } -SpellScript::ObjectAreaTargetSelectHandler::ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) - : TargetHook(_effIndex, _targetType, true, false), pObjectAreaTargetSelectHandlerScript(_pObjectAreaTargetSelectHandlerScript) +SpellScript::ObjectAreaTargetSelectHandler::ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType callImpl, uint8 effIndex, uint16 targetType) + : TargetHook(effIndex, targetType, true, false), _callImpl(callImpl) { } @@ -397,13 +339,13 @@ SpellScript::ObjectAreaTargetSelectHandler::ObjectAreaTargetSelectHandler(Object SpellScript::ObjectAreaTargetSelectHandler& SpellScript::ObjectAreaTargetSelectHandler::operator=(ObjectAreaTargetSelectHandler&& right) noexcept = default; SpellScript::ObjectAreaTargetSelectHandler::~ObjectAreaTargetSelectHandler() = default; -void SpellScript::ObjectAreaTargetSelectHandler::Call(SpellScript* spellScript, std::list<WorldObject*>& targets) +void SpellScript::ObjectAreaTargetSelectHandler::Call(SpellScript* spellScript, std::list<WorldObject*>& targets) const { - (spellScript->*pObjectAreaTargetSelectHandlerScript)(targets); + (spellScript->*_callImpl)(targets); } -SpellScript::ObjectTargetSelectHandler::ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) - : TargetHook(_effIndex, _targetType, false, false), pObjectTargetSelectHandlerScript(_pObjectTargetSelectHandlerScript) +SpellScript::ObjectTargetSelectHandler::ObjectTargetSelectHandler(SpellObjectTargetSelectFnType callImpl, uint8 effIndex, uint16 targetType) + : TargetHook(effIndex, targetType, false, false), _callImpl(callImpl) { } @@ -411,13 +353,13 @@ SpellScript::ObjectTargetSelectHandler::ObjectTargetSelectHandler(ObjectTargetSe SpellScript::ObjectTargetSelectHandler& SpellScript::ObjectTargetSelectHandler::operator=(ObjectTargetSelectHandler&& right) noexcept = default; SpellScript::ObjectTargetSelectHandler::~ObjectTargetSelectHandler() = default; -void SpellScript::ObjectTargetSelectHandler::Call(SpellScript* spellScript, WorldObject*& target) +void SpellScript::ObjectTargetSelectHandler::Call(SpellScript* spellScript, WorldObject*& target) const { - (spellScript->*pObjectTargetSelectHandlerScript)(target); + (spellScript->*_callImpl)(target); } -SpellScript::DestinationTargetSelectHandler::DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) - : TargetHook(_effIndex, _targetType, false, true), DestinationTargetSelectHandlerScript(_DestinationTargetSelectHandlerScript) +SpellScript::DestinationTargetSelectHandler::DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType callImpl, uint8 effIndex, uint16 targetType) + : TargetHook(effIndex, targetType, false, true), _callImpl(callImpl) { } @@ -425,9 +367,22 @@ SpellScript::DestinationTargetSelectHandler::DestinationTargetSelectHandler(Dest SpellScript::DestinationTargetSelectHandler& SpellScript::DestinationTargetSelectHandler::operator=(DestinationTargetSelectHandler&& right) noexcept = default; SpellScript::DestinationTargetSelectHandler::~DestinationTargetSelectHandler() = default; -void SpellScript::DestinationTargetSelectHandler::Call(SpellScript* spellScript, SpellDestination& target) +void SpellScript::DestinationTargetSelectHandler::Call(SpellScript* spellScript, SpellDestination& target) const +{ + (spellScript->*_callImpl)(target); +} + +SpellScript::OnCalculateResistAbsorbHandler::OnCalculateResistAbsorbHandler(SpellOnResistAbsorbCalculateFnType callImpl) : _callImpl(callImpl) +{ +} + +SpellScript::OnCalculateResistAbsorbHandler::OnCalculateResistAbsorbHandler(OnCalculateResistAbsorbHandler&& right) noexcept = default; +SpellScript::OnCalculateResistAbsorbHandler& SpellScript::OnCalculateResistAbsorbHandler::operator=(OnCalculateResistAbsorbHandler&& right) noexcept = default; +SpellScript::OnCalculateResistAbsorbHandler::~OnCalculateResistAbsorbHandler() = default; + +void SpellScript::OnCalculateResistAbsorbHandler::Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) const { - (spellScript->*DestinationTargetSelectHandlerScript)(target); + (spellScript->*_callImpl)(damageInfo, resistAmount, absorbAmount); } SpellScript::SpellScript(): m_spell(nullptr), m_hitPreventEffectMask(0), m_hitPreventDefaultEffectMask(0) @@ -438,39 +393,39 @@ SpellScript::~SpellScript() = default; bool SpellScript::_Validate(SpellInfo const* entry) { - for (auto itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectLaunch` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (EffectHandler& hook : OnEffectLaunch) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectLaunch` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnEffectLaunchTarget.begin(); itr != OnEffectLaunchTarget.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectLaunchTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (EffectHandler& hook : OnEffectLaunchTarget) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectLaunchTarget` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnEffectHit.begin(); itr != OnEffectHit.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectHit` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (EffectHandler& hook : OnEffectHit) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectHit` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnEffectHitTarget.begin(); itr != OnEffectHitTarget.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectHitTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (EffectHandler& hook : OnEffectHitTarget) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectHitTarget` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnEffectSuccessfulDispel.begin(); itr != OnEffectSuccessfulDispel.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectSuccessfulDispel` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (EffectHandler& hook : OnEffectSuccessfulDispel) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectSuccessfulDispel` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnObjectAreaTargetSelect.begin(); itr != OnObjectAreaTargetSelect.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (ObjectAreaTargetSelectHandler& hook : OnObjectAreaTargetSelect) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnObjectTargetSelect.begin(); itr != OnObjectTargetSelect.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnObjectTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (ObjectTargetSelectHandler& hook : OnObjectTargetSelect) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnObjectTargetSelect` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - for (auto itr = OnDestinationTargetSelect.begin(); itr != OnDestinationTargetSelect.end(); ++itr) - if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnDestinationTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString(), m_scriptName->c_str()); + for (DestinationTargetSelectHandler& hook : OnDestinationTargetSelect) + if (!hook.GetAffectedEffectsMask(entry)) + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnDestinationTargetSelect` of SpellScript won't be executed", entry->Id, hook.ToString(), m_scriptName); - return _SpellScript::_Validate(entry); + return SpellScriptBase::_Validate(entry); } bool SpellScript::_Load(Spell* spell) @@ -620,7 +575,7 @@ int64 SpellScript::GetUnitTargetCountForEffect(SpellEffIndex effect) const if (!IsAfterTargetSelectionPhase()) { TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetUnitTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)", - m_scriptName->c_str(), m_scriptSpellId); + m_scriptName, m_scriptSpellId); return 0; } return m_spell->GetUnitTargetCountForEffect(effect); @@ -631,7 +586,7 @@ int64 SpellScript::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const if (!IsAfterTargetSelectionPhase()) { TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetGameObjectTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)", - m_scriptName->c_str(), m_scriptSpellId); + m_scriptName, m_scriptSpellId); return 0; } return m_spell->GetGameObjectTargetCountForEffect(effect); @@ -642,7 +597,7 @@ int64 SpellScript::GetItemTargetCountForEffect(SpellEffIndex effect) const if (!IsAfterTargetSelectionPhase()) { TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetItemTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)", - m_scriptName->c_str(), m_scriptSpellId); + m_scriptName, m_scriptSpellId); return 0; } return m_spell->GetItemTargetCountForEffect(effect); @@ -653,7 +608,7 @@ int64 SpellScript::GetCorpseTargetCountForEffect(SpellEffIndex effect) const if (!IsAfterTargetSelectionPhase()) { TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetCorpseTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)", - m_scriptName->c_str(), m_scriptSpellId); + m_scriptName, m_scriptSpellId); return 0; } return m_spell->GetCorpseTargetCountForEffect(effect); @@ -663,7 +618,7 @@ Unit* SpellScript::GetHitUnit() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitUnit was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitUnit was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } return m_spell->unitTarget; @@ -673,7 +628,7 @@ Creature* SpellScript::GetHitCreature() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitCreature was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitCreature was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } if (m_spell->unitTarget) @@ -685,7 +640,7 @@ Player* SpellScript::GetHitPlayer() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitPlayer was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitPlayer was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } if (m_spell->unitTarget) @@ -697,7 +652,7 @@ Item* SpellScript::GetHitItem() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitItem was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitItem was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } return m_spell->itemTarget; @@ -707,7 +662,7 @@ GameObject* SpellScript::GetHitGObj() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } return m_spell->gameObjTarget; @@ -717,7 +672,7 @@ Corpse* SpellScript::GetHitCorpse() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitCorpse was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitCorpse was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } return m_spell->m_corpseTarget; @@ -727,7 +682,7 @@ WorldLocation* SpellScript::GetHitDest() const { if (!IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitDest was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitDest was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } return m_spell->destTarget; @@ -737,7 +692,7 @@ int32 SpellScript::GetHitDamage() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitDamage was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitDamage was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return 0; } return m_spell->m_damage; @@ -747,7 +702,7 @@ void SpellScript::SetHitDamage(int32 damage) { if (!IsInModifiableHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetHitDamage was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetHitDamage was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } m_spell->m_damage = damage; @@ -757,7 +712,7 @@ int32 SpellScript::GetHitHeal() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitHeal was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitHeal was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return 0; } return m_spell->m_healing; @@ -767,7 +722,7 @@ void SpellScript::SetHitHeal(int32 heal) { if (!IsInModifiableHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetHitHeal was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetHitHeal was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } m_spell->m_healing = heal; @@ -777,7 +732,7 @@ bool SpellScript::IsHitCrit() const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::IsHitCrit was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::IsHitCrit was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return false; } if (Unit* hitUnit = GetHitUnit()) @@ -796,7 +751,7 @@ Aura* SpellScript::GetHitAura(bool dynObjAura /*= false*/) const { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitAura was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetHitAura was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return nullptr; } @@ -814,7 +769,7 @@ void SpellScript::PreventHitAura() { if (!IsInTargetHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::PreventHitAura was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::PreventHitAura was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } if (UnitAura* aura = m_spell->_spellAura) @@ -827,7 +782,7 @@ void SpellScript::PreventHitEffect(SpellEffIndex effIndex) { if (!IsInHitPhase() && !IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::PreventHitEffect was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::PreventHitEffect was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } m_hitPreventEffectMask |= 1 << effIndex; @@ -838,7 +793,7 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex) { if (!IsInHitPhase() && !IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::PreventHitDefaultEffect was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::PreventHitDefaultEffect was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } m_hitPreventDefaultEffectMask |= 1 << effIndex; @@ -846,7 +801,7 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex) SpellEffectInfo const& SpellScript::GetEffectInfo() const { - ASSERT(IsInEffectHook(), "Script: `%s` Spell: `%u`: function SpellScript::GetEffectInfo was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + ASSERT(IsInEffectHook(), "Script: `" STRING_VIEW_FMT "` Spell: `%u`: function SpellScript::GetEffectInfo was called, but function has no effect in current hook!", STRING_VIEW_FMT_ARG(m_scriptName), m_scriptSpellId); return *m_spell->effectInfo; } @@ -855,7 +810,7 @@ int32 SpellScript::GetEffectValue() const { if (!IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetEffectValue was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return 0; } @@ -866,7 +821,7 @@ void SpellScript::SetEffectValue(int32 value) { if (!IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetEffectValue was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } @@ -877,7 +832,7 @@ float SpellScript::GetEffectVariance() const { if (!IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetEffectVariance was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetEffectVariance was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return 0.0f; } @@ -888,7 +843,7 @@ void SpellScript::SetEffectVariance(float variance) { if (!IsInEffectHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetEffectVariance was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetEffectVariance was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId); return; } @@ -920,7 +875,7 @@ void SpellScript::SetCustomCastResultMessage(SpellCustomErrors result) { if (!IsInCheckCastHook()) { - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetCustomCastResultMessage was called while spell not in check cast phase!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::SetCustomCastResultMessage was called while spell not in check cast phase!", m_scriptName, m_scriptSpellId); return; } @@ -932,112 +887,138 @@ Difficulty SpellScript::GetCastDifficulty() const return m_spell->GetCastDifficulty(); } +namespace EffectAuraNameCheck +{ +bool Check(SpellInfo const* spellEntry, uint8 effIndex, uint16 auraType) +{ + if (spellEntry->GetEffects().size() <= effIndex) + return false; + SpellEffectInfo const& spellEffectInfo = spellEntry->GetEffect(SpellEffIndex(effIndex)); + if (!spellEffectInfo.ApplyAuraName && !auraType) + return true; + if (!spellEffectInfo.ApplyAuraName) + return false; + return (auraType == SPELL_AURA_ANY) || (spellEffectInfo.ApplyAuraName == auraType); +} + +std::string ToString(uint16 effAurName) +{ + switch (effAurName) + { + case SPELL_AURA_ANY: + return "SPELL_AURA_ANY"; + default: + return Trinity::ToString(effAurName); + } +} +} + bool AuraScript::_Validate(SpellInfo const* entry) { for (auto itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr) if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && !entry->HasEffect(SPELL_EFFECT_APPLY_AURA)) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = OnDispel.begin(); itr != OnDispel.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `OnDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `OnDispel` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = AfterDispel.begin(); itr != AfterDispel.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `AfterDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `AfterDispel` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectApply` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectApply` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = OnEffectRemove.begin(); itr != OnEffectRemove.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectRemove` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectRemove` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = AfterEffectApply.begin(); itr != AfterEffectApply.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectApply` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectApply` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = AfterEffectRemove.begin(); itr != AfterEffectRemove.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectRemove` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectRemove` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = OnEffectPeriodic.begin(); itr != OnEffectPeriodic.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectPeriodic` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectPeriodic` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = OnEffectUpdatePeriodic.begin(); itr != OnEffectUpdatePeriodic.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectUpdatePeriodic` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectUpdatePeriodic` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = DoEffectCalcAmount.begin(); itr != DoEffectCalcAmount.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcAmount` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcAmount` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = DoEffectCalcPeriodic.begin(); itr != DoEffectCalcPeriodic.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcPeriodic` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcPeriodic` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = DoEffectCalcSpellMod.begin(); itr != DoEffectCalcSpellMod.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcSpellMod` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcSpellMod` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = DoEffectCalcCritChance.begin(); itr != DoEffectCalcCritChance.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcCritChance` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoEffectCalcCritChance` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = OnEffectAbsorb.begin(); itr != OnEffectAbsorb.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectAbsorb` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectAbsorb` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = AfterEffectAbsorb.begin(); itr != AfterEffectAbsorb.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectAbsorb` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectAbsorb` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = OnEffectManaShield.begin(); itr != OnEffectManaShield.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectManaShield` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectManaShield` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = AfterEffectManaShield.begin(); itr != AfterEffectManaShield.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectManaShield` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectManaShield` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = OnEffectSplit.begin(); itr != OnEffectSplit.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = DoCheckEffectProc.begin(); itr != DoCheckEffectProc.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoCheckEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `DoCheckEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = OnProc.begin(); itr != OnProc.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = AfterProc.begin(); itr != AfterProc.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) - TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName); for (auto itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); for (auto itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr) if (!itr->GetAffectedEffectsMask(entry)) - TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName->c_str()); + TC_LOG_ERROR("scripts", "Spell `{}` Effect `{}` of script `{}` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, itr->ToString(), m_scriptName); - return _SpellScript::_Validate(entry); + return SpellScriptBase::_Validate(entry); } -AuraScript::CheckAreaTargetHandler::CheckAreaTargetHandler(AuraCheckAreaTargetFnType _pHandlerScript) : pHandlerScript(_pHandlerScript) +AuraScript::CheckAreaTargetHandler::CheckAreaTargetHandler(AuraCheckAreaTargetFnType callImpl) : _callImpl(callImpl) { } @@ -1045,12 +1026,12 @@ AuraScript::CheckAreaTargetHandler::CheckAreaTargetHandler(CheckAreaTargetHandle AuraScript::CheckAreaTargetHandler& AuraScript::CheckAreaTargetHandler::operator=(CheckAreaTargetHandler&& right) noexcept = default; AuraScript::CheckAreaTargetHandler::~CheckAreaTargetHandler() = default; -bool AuraScript::CheckAreaTargetHandler::Call(AuraScript* auraScript, Unit* _target) +bool AuraScript::CheckAreaTargetHandler::Call(AuraScript* auraScript, Unit* _target) const { - return (auraScript->*pHandlerScript)(_target); + return (auraScript->*_callImpl)(_target); } -AuraScript::AuraDispelHandler::AuraDispelHandler(AuraDispelFnType _pHandlerScript) : pHandlerScript(_pHandlerScript) +AuraScript::AuraDispelHandler::AuraDispelHandler(AuraDispelFnType callImpl) : _callImpl(callImpl) { } @@ -1058,30 +1039,30 @@ AuraScript::AuraDispelHandler::AuraDispelHandler(AuraDispelHandler&& right) noex AuraScript::AuraDispelHandler& AuraScript::AuraDispelHandler::operator=(AuraDispelHandler&& right) noexcept = default; AuraScript::AuraDispelHandler::~AuraDispelHandler() = default; -void AuraScript::AuraDispelHandler::Call(AuraScript* auraScript, DispelInfo* _dispelInfo) +void AuraScript::AuraDispelHandler::Call(AuraScript* auraScript, DispelInfo* dispelInfo) const { - (auraScript->*pHandlerScript)(_dispelInfo); + (auraScript->*_callImpl)(dispelInfo); } -AuraScript::EffectBase::EffectBase(uint8 _effIndex, uint16 _effName) - : _SpellScript::EffectAuraNameCheck(_effName), _SpellScript::EffectHook(_effIndex) { } +AuraScript::EffectBase::EffectBase(uint8 effIndex, uint16 auraType) + : EffectHook(effIndex), _auraType(auraType) { } AuraScript::EffectBase::EffectBase(EffectBase&& right) noexcept = default; AuraScript::EffectBase& AuraScript::EffectBase::operator=(EffectBase&& right) noexcept = default; AuraScript::EffectBase::~EffectBase() = default; -bool AuraScript::EffectBase::CheckEffect(SpellInfo const* spellEntry, uint8 effIndexToCheck) const +bool AuraScript::EffectBase::CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const { - return _SpellScript::EffectAuraNameCheck::Check(spellEntry, effIndexToCheck); + return EffectAuraNameCheck::Check(spellInfo, effIndex, _auraType); } std::string AuraScript::EffectBase::ToString() const { - return "Index: " + EffIndexToString() + " AuraName: " +_SpellScript::EffectAuraNameCheck::ToString(); + return "Index: " + EffIndexToString() + " AuraName: " + EffectAuraNameCheck::ToString(_auraType); } -AuraScript::EffectPeriodicHandler::EffectPeriodicHandler(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) - : AuraScript::EffectBase(_effIndex, _effName), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectPeriodicHandler::EffectPeriodicHandler(AuraEffectPeriodicFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1089,13 +1070,13 @@ AuraScript::EffectPeriodicHandler::EffectPeriodicHandler(EffectPeriodicHandler&& AuraScript::EffectPeriodicHandler& AuraScript::EffectPeriodicHandler::operator=(EffectPeriodicHandler&& right) noexcept = default; AuraScript::EffectPeriodicHandler::~EffectPeriodicHandler() = default; -void AuraScript::EffectPeriodicHandler::Call(AuraScript* auraScript, AuraEffect const* _aurEff) +void AuraScript::EffectPeriodicHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff) const { - (auraScript->*pEffectHandlerScript)(_aurEff); + (auraScript->*_callImpl)(aurEff); } -AuraScript::EffectUpdatePeriodicHandler::EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) - : AuraScript::EffectBase(_effIndex, _effName), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectUpdatePeriodicHandler::EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1103,13 +1084,13 @@ AuraScript::EffectUpdatePeriodicHandler::EffectUpdatePeriodicHandler(EffectUpdat AuraScript::EffectUpdatePeriodicHandler& AuraScript::EffectUpdatePeriodicHandler::operator=(EffectUpdatePeriodicHandler&& right) noexcept = default; AuraScript::EffectUpdatePeriodicHandler::~EffectUpdatePeriodicHandler() = default; -void AuraScript::EffectUpdatePeriodicHandler::Call(AuraScript* auraScript, AuraEffect* aurEff) +void AuraScript::EffectUpdatePeriodicHandler::Call(AuraScript* auraScript, AuraEffect* aurEff) const { - (auraScript->*pEffectHandlerScript)(aurEff); + (auraScript->*_callImpl)(aurEff); } -AuraScript::EffectCalcAmountHandler::EffectCalcAmountHandler(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) - : AuraScript::EffectBase(_effIndex, _effName), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectCalcAmountHandler::EffectCalcAmountHandler(AuraEffectCalcAmountFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1117,13 +1098,13 @@ AuraScript::EffectCalcAmountHandler::EffectCalcAmountHandler(EffectCalcAmountHan AuraScript::EffectCalcAmountHandler& AuraScript::EffectCalcAmountHandler::operator=(EffectCalcAmountHandler&& right) noexcept = default; AuraScript::EffectCalcAmountHandler::~EffectCalcAmountHandler() = default; -void AuraScript::EffectCalcAmountHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) +void AuraScript::EffectCalcAmountHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) const { - (auraScript->*pEffectHandlerScript)(aurEff, amount, canBeRecalculated); + (auraScript->*_callImpl)(aurEff, amount, canBeRecalculated); } -AuraScript::EffectCalcPeriodicHandler::EffectCalcPeriodicHandler(AuraEffectCalcPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) - : AuraScript::EffectBase(_effIndex, _effName), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectCalcPeriodicHandler::EffectCalcPeriodicHandler(AuraEffectCalcPeriodicFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1131,13 +1112,13 @@ AuraScript::EffectCalcPeriodicHandler::EffectCalcPeriodicHandler(EffectCalcPerio AuraScript::EffectCalcPeriodicHandler& AuraScript::EffectCalcPeriodicHandler::operator=(EffectCalcPeriodicHandler&& right) noexcept = default; AuraScript::EffectCalcPeriodicHandler::~EffectCalcPeriodicHandler() = default; -void AuraScript::EffectCalcPeriodicHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer) +void AuraScript::EffectCalcPeriodicHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer) const { - (auraScript->*pEffectHandlerScript)(aurEff, isPeriodic, periodicTimer); + (auraScript->*_callImpl)(aurEff, isPeriodic, periodicTimer); } -AuraScript::EffectCalcSpellModHandler::EffectCalcSpellModHandler(AuraEffectCalcSpellModFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) - : AuraScript::EffectBase(_effIndex, _effName), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectCalcSpellModHandler::EffectCalcSpellModHandler(AuraEffectCalcSpellModFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1145,13 +1126,13 @@ AuraScript::EffectCalcSpellModHandler::EffectCalcSpellModHandler(EffectCalcSpell AuraScript::EffectCalcSpellModHandler& AuraScript::EffectCalcSpellModHandler::operator=(EffectCalcSpellModHandler&& right) noexcept = default; AuraScript::EffectCalcSpellModHandler::~EffectCalcSpellModHandler() = default; -void AuraScript::EffectCalcSpellModHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, SpellModifier*& spellMod) +void AuraScript::EffectCalcSpellModHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, SpellModifier*& spellMod) const { - (auraScript->*pEffectHandlerScript)(aurEff, spellMod); + (auraScript->*_callImpl)(aurEff, spellMod); } -AuraScript::EffectCalcCritChanceHandler::EffectCalcCritChanceHandler(AuraEffectCalcCritChanceFnType effectHandlerScript, uint8 effIndex, uint16 effName) - : AuraScript::EffectBase(effIndex, effName), _effectHandlerScript(effectHandlerScript) +AuraScript::EffectCalcCritChanceHandler::EffectCalcCritChanceHandler(AuraEffectCalcCritChanceFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1161,11 +1142,11 @@ AuraScript::EffectCalcCritChanceHandler::~EffectCalcCritChanceHandler() = defaul void AuraScript::EffectCalcCritChanceHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit const* victim, float& critChance) const { - (auraScript->*_effectHandlerScript)(aurEff, victim, critChance); + (auraScript->*_callImpl)(aurEff, victim, critChance); } -AuraScript::EffectApplyHandler::EffectApplyHandler(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode) - : AuraScript::EffectBase(_effIndex, _effName), pEffectHandlerScript(_pEffectHandlerScript), mode(_mode) +AuraScript::EffectApplyHandler::EffectApplyHandler(AuraEffectApplicationModeFnType callImpl, uint8 effIndex, uint16 auraType, AuraEffectHandleModes mode) + : EffectBase(effIndex, auraType), _callImpl(callImpl), _mode(mode) { } @@ -1173,14 +1154,13 @@ AuraScript::EffectApplyHandler::EffectApplyHandler(EffectApplyHandler&& right) n AuraScript::EffectApplyHandler& AuraScript::EffectApplyHandler::operator=(EffectApplyHandler&& right) noexcept = default; AuraScript::EffectApplyHandler::~EffectApplyHandler() = default; -void AuraScript::EffectApplyHandler::Call(AuraScript* auraScript, AuraEffect const* _aurEff, AuraEffectHandleModes _mode) +void AuraScript::EffectApplyHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, AuraEffectHandleModes mode) const { - if (_mode & mode) - (auraScript->*pEffectHandlerScript)(_aurEff, _mode); + (auraScript->*_callImpl)(aurEff, mode); } -AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overKill) - : AuraScript::EffectBase(_effIndex, overKill ? SPELL_AURA_SCHOOL_ABSORB_OVERKILL : SPELL_AURA_SCHOOL_ABSORB), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(AuraEffectAbsorbFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1188,51 +1168,26 @@ AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(EffectAbsorbHandler&& right AuraScript::EffectAbsorbHandler& AuraScript::EffectAbsorbHandler::operator=(EffectAbsorbHandler&& right) noexcept = default; AuraScript::EffectAbsorbHandler::~EffectAbsorbHandler() = default; -void AuraScript::EffectAbsorbHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) -{ - (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount); -} - -AuraScript::EffectAbsorbHealHandler::EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType _pEffectHandlerScript, uint8 _effIndex) - : AuraScript::EffectBase(_effIndex, SPELL_AURA_SCHOOL_HEAL_ABSORB) -{ - pEffectHandlerScript = _pEffectHandlerScript; -} - -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) -{ -} - -AuraScript::EffectManaShieldHandler::EffectManaShieldHandler(EffectManaShieldHandler&& right) noexcept = default; -AuraScript::EffectManaShieldHandler& AuraScript::EffectManaShieldHandler::operator=(EffectManaShieldHandler&& right) noexcept = default; -AuraScript::EffectManaShieldHandler::~EffectManaShieldHandler() = default; - -void AuraScript::EffectManaShieldHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) +void AuraScript::EffectAbsorbHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) const { - (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount); + (auraScript->*_callImpl)(aurEff, dmgInfo, absorbAmount); } -AuraScript::EffectSplitHandler::EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) - : AuraScript::EffectBase(_effIndex, SPELL_AURA_SPLIT_DAMAGE_PCT), pEffectHandlerScript(_pEffectHandlerScript) +AuraScript::EffectAbsorbHealHandler::EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } -AuraScript::EffectSplitHandler::EffectSplitHandler(EffectSplitHandler&& right) noexcept = default; -AuraScript::EffectSplitHandler& AuraScript::EffectSplitHandler::operator=(EffectSplitHandler&& right) noexcept = default; -AuraScript::EffectSplitHandler::~EffectSplitHandler() = default; +AuraScript::EffectAbsorbHealHandler::EffectAbsorbHealHandler(EffectAbsorbHealHandler&& right) noexcept = default; +AuraScript::EffectAbsorbHealHandler& AuraScript::EffectAbsorbHealHandler::operator=(EffectAbsorbHealHandler&& right) noexcept = default; +AuraScript::EffectAbsorbHealHandler::~EffectAbsorbHealHandler() = default; -void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount) +void AuraScript::EffectAbsorbHealHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount) const { - (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount); + (auraScript->*_callImpl)(aurEff, healInfo, absorbAmount); } -AuraScript::CheckProcHandler::CheckProcHandler(AuraCheckProcFnType handlerScript) : _HandlerScript(handlerScript) +AuraScript::CheckProcHandler::CheckProcHandler(AuraCheckProcFnType callImpl) : _callImpl(callImpl) { } @@ -1240,13 +1195,13 @@ AuraScript::CheckProcHandler::CheckProcHandler(CheckProcHandler&& right) noexcep AuraScript::CheckProcHandler& AuraScript::CheckProcHandler::operator=(CheckProcHandler&& right) noexcept = default; AuraScript::CheckProcHandler::~CheckProcHandler() = default; -bool AuraScript::CheckProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo) +bool AuraScript::CheckProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo) const { - return (auraScript->*_HandlerScript)(eventInfo); + return (auraScript->*_callImpl)(eventInfo); } -AuraScript::CheckEffectProcHandler::CheckEffectProcHandler(AuraCheckEffectProcFnType handlerScript, uint8 effIndex, uint16 effName) - : AuraScript::EffectBase(effIndex, effName), _HandlerScript(handlerScript) +AuraScript::CheckEffectProcHandler::CheckEffectProcHandler(AuraCheckEffectProcFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1254,12 +1209,12 @@ AuraScript::CheckEffectProcHandler::CheckEffectProcHandler(CheckEffectProcHandle AuraScript::CheckEffectProcHandler& AuraScript::CheckEffectProcHandler::operator=(CheckEffectProcHandler&& right) noexcept = default; AuraScript::CheckEffectProcHandler::~CheckEffectProcHandler() = default; -bool AuraScript::CheckEffectProcHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo) +bool AuraScript::CheckEffectProcHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo) const { - return (auraScript->*_HandlerScript)(aurEff, eventInfo); + return (auraScript->*_callImpl)(aurEff, eventInfo); } -AuraScript::AuraProcHandler::AuraProcHandler(AuraProcFnType handlerScript) : _HandlerScript(handlerScript) +AuraScript::AuraProcHandler::AuraProcHandler(AuraProcFnType callImpl) : _callImpl(callImpl) { } @@ -1267,13 +1222,13 @@ AuraScript::AuraProcHandler::AuraProcHandler(AuraProcHandler&& right) noexcept = AuraScript::AuraProcHandler& AuraScript::AuraProcHandler::operator=(AuraProcHandler&& right) noexcept = default; AuraScript::AuraProcHandler::~AuraProcHandler() = default; -void AuraScript::AuraProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo) +void AuraScript::AuraProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo) const { - (auraScript->*_HandlerScript)(eventInfo); + (auraScript->*_callImpl)(eventInfo); } -AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) - : AuraScript::EffectBase(effIndex, effName), _EffectHandlerScript(effectHandlerScript) +AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType callImpl, uint8 effIndex, uint16 auraType) + : EffectBase(effIndex, auraType), _callImpl(callImpl) { } @@ -1281,12 +1236,12 @@ AuraScript::EffectProcHandler::EffectProcHandler(EffectProcHandler&& right) noex AuraScript::EffectProcHandler& AuraScript::EffectProcHandler::operator=(EffectProcHandler&& right) noexcept = default; AuraScript::EffectProcHandler::~EffectProcHandler() = default; -void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, ProcEventInfo& eventInfo) +void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, ProcEventInfo& eventInfo) const { - (auraScript->*_EffectHandlerScript)(aurEff, eventInfo); + (auraScript->*_callImpl)(aurEff, eventInfo); } -AuraScript::EnterLeaveCombatHandler::EnterLeaveCombatHandler(AuraEnterLeaveCombatFnType handlerScript) : _handlerScript(handlerScript) +AuraScript::EnterLeaveCombatHandler::EnterLeaveCombatHandler(AuraEnterLeaveCombatFnType callImpl) : _callImpl(callImpl) { } @@ -1296,10 +1251,10 @@ AuraScript::EnterLeaveCombatHandler::~EnterLeaveCombatHandler() = default; void AuraScript::EnterLeaveCombatHandler::Call(AuraScript* auraScript, bool isNowInCombat) const { - (auraScript->*_handlerScript)(isNowInCombat); + (auraScript->*_callImpl)(isNowInCombat); } -AuraScript::AuraScript(): _SpellScript(), m_aura(nullptr), m_auraApplication(nullptr), m_defaultActionPrevented(false) +AuraScript::AuraScript(): SpellScriptBase(), m_aura(nullptr), m_auraApplication(nullptr), m_defaultActionPrevented(false) { } @@ -1365,7 +1320,7 @@ void AuraScript::PreventDefaultAction() m_defaultActionPrevented = true; break; default: - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}` AuraScript::PreventDefaultAction called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}` AuraScript::PreventDefaultAction called in a hook in which the call won't have effect!", m_scriptName, m_scriptSpellId); break; } } @@ -1568,7 +1523,7 @@ Unit* AuraScript::GetTarget() const case AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT: return m_auraApplication->GetTarget(); default: - TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId); + TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName, m_scriptSpellId); } return nullptr; diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index b560a6c296c..5f7b7367d5e 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -15,8 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __SPELL_SCRIPT_H -#define __SPELL_SCRIPT_H +#ifndef TRINITY_SPELL_SCRIPT_H +#define TRINITY_SPELL_SCRIPT_H #include "ObjectGuid.h" #include "SharedDefines.h" @@ -55,8 +55,8 @@ struct SpellValue; enum Difficulty : uint8; enum class ItemContext : uint8; -#define SPELL_EFFECT_ANY (uint16)-1 -#define SPELL_AURA_ANY (uint16)-1 +#define SPELL_EFFECT_ANY ((uint16)-1) +#define SPELL_AURA_ANY ((uint16)-1) enum SpellScriptState { @@ -65,161 +65,153 @@ enum SpellScriptState SPELL_SCRIPT_STATE_LOADING, SPELL_SCRIPT_STATE_UNLOADING }; -#define SPELL_SCRIPT_STATE_END SPELL_SCRIPT_STATE_UNLOADING + 1 +#define SPELL_SCRIPT_STATE_END (SPELL_SCRIPT_STATE_UNLOADING + 1) -// helper class from which SpellScript and SpellAura derive, use these classes instead -class TC_GAME_API _SpellScript +// helper class from which SpellScript and AuraScript derive, use these classes instead +class TC_GAME_API SpellScriptBase { - // internal use classes & functions - // DO NOT OVERRIDE THESE IN SCRIPTS - protected: - virtual bool _Validate(SpellInfo const* entry); - +// internal use classes & functions +// DO NOT OVERRIDE THESE IN SCRIPTS +public: + SpellScriptBase(); + virtual ~SpellScriptBase(); + + SpellScriptBase(SpellScriptBase const& right) = delete; + SpellScriptBase(SpellScriptBase&& right) = delete; + SpellScriptBase& operator=(SpellScriptBase const& right) = delete; + SpellScriptBase& operator=(SpellScriptBase&& right) = delete; + + void _Register(); + void _Unload(); + void _Init(std::string const& scriptname, uint32 spellId); + std::string_view GetScriptName() const; + +protected: + virtual bool _Validate(SpellInfo const* entry); + + class TC_GAME_API EffectHook + { public: - _SpellScript(); - virtual ~_SpellScript(); - void _Register(); - void _Unload(); - void _Init(std::string const* scriptname, uint32 spellId); - std::string const* _GetScriptName() const; - - _SpellScript(_SpellScript const& right) = delete; - _SpellScript(_SpellScript&& right) = delete; - _SpellScript& operator=(_SpellScript const& right) = delete; - _SpellScript& operator=(_SpellScript&& right) = delete; + explicit EffectHook(uint8 effIndex); + EffectHook(EffectHook const& right) = delete; + EffectHook(EffectHook&& right) noexcept; + EffectHook& operator=(EffectHook const& right) = delete; + EffectHook& operator=(EffectHook&& right) noexcept; + virtual ~EffectHook(); + + uint32 GetAffectedEffectsMask(SpellInfo const* spellInfo) const; + bool IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex) const; + virtual bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const = 0; + std::string EffIndexToString() const; protected: - class TC_GAME_API EffectHook - { - public: - EffectHook(uint8 _effIndex); - EffectHook(EffectHook const& right) = delete; - EffectHook(EffectHook&& right) noexcept; - EffectHook& operator=(EffectHook const& right) = delete; - EffectHook& operator=(EffectHook&& right) noexcept; - virtual ~EffectHook(); - - uint32 GetAffectedEffectsMask(SpellInfo const* spellInfo) const; - bool IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex) const; - virtual bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const = 0; - std::string EffIndexToString() const; - protected: - uint8 effIndex; - }; - - class TC_GAME_API EffectNameCheck - { - public: - EffectNameCheck(uint16 _effName); - EffectNameCheck(EffectNameCheck const& right) = delete; - EffectNameCheck(EffectNameCheck&& right) noexcept; - EffectNameCheck& operator=(EffectNameCheck const& right) = delete; - EffectNameCheck& operator=(EffectNameCheck&& right) noexcept; - virtual ~EffectNameCheck(); - bool Check(SpellInfo const* spellInfo, uint8 effIndex) const; - std::string ToString() const; - private: - uint16 effName; - }; - - class TC_GAME_API EffectAuraNameCheck - { - public: - EffectAuraNameCheck(uint16 _effAurName); - EffectAuraNameCheck(EffectAuraNameCheck const& right) = delete; - EffectAuraNameCheck(EffectAuraNameCheck&& right) noexcept; - EffectAuraNameCheck& operator=(EffectAuraNameCheck const& right) = delete; - EffectAuraNameCheck& operator=(EffectAuraNameCheck&& right) noexcept; - virtual ~EffectAuraNameCheck(); - bool Check(SpellInfo const* spellInfo, uint8 effIndex) const; - std::string ToString() const; - private: - uint16 effAurName; - }; - - uint8 m_currentScriptState; - std::string const* m_scriptName; - uint32 m_scriptSpellId; + uint8 _effIndex; + }; - private: + template<typename> + struct GetScriptClass + { + using type = void; + }; -#ifdef TRINITY_API_USE_DYNAMIC_LINKING + template<typename Return, typename Class, typename... Args> + struct GetScriptClass<Return(Class::*)(Args...)> + { + using type = Class; + }; - // Strong reference to keep the binary code loaded - std::shared_ptr<ModuleReference> m_moduleReference; + template<typename Return, typename Class, typename... Args> + struct GetScriptClass<Return(Class::*)(Args...) const> + { + using type = Class; + }; -#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING + template<typename ScriptFunc> + using GetScriptClass_t = typename GetScriptClass<ScriptFunc>::type; - public: - // - // SpellScript/AuraScript interface base - // these functions are safe to override, see notes below for usage instructions - // - // Function in which handler functions are registered, must be implemented in script - virtual void Register() = 0; - // Function called on server startup, if returns false script won't be used in core - // use for: dbc/template data presence/correctness checks - virtual bool Validate([[maybe_unused]] SpellInfo const* spellInfo) { return true; } - // Function called when script is created, if returns false script will be unloaded afterwards - // use for: initializing local script variables (DO NOT USE CONSTRUCTOR FOR THIS PURPOSE!) - virtual bool Load() { return true; } - // Function called when script is destroyed - // use for: deallocating memory allocated by script - virtual void Unload() { } - // Helpers - static bool ValidateSpellInfo(std::initializer_list<uint32> spellIds) - { - return _ValidateSpellInfo(spellIds.begin(), spellIds.end()); - } + uint8 m_currentScriptState; + std::string_view m_scriptName; + uint32 m_scriptSpellId; - template <class T> - static bool ValidateSpellInfo(T const& spellIds) - { - return _ValidateSpellInfo(std::cbegin(spellIds), std::cend(spellIds)); - } +private: - static bool ValidateSpellEffect(std::initializer_list<std::pair<uint32, SpellEffIndex>> effects) - { - return _ValidateSpellEffects(effects.begin(), effects.end()); - } +#ifdef TRINITY_API_USE_DYNAMIC_LINKING - template <class T> - static bool ValidateSpellEffect(T const& spellEffects) - { - return _ValidateSpellEffects(std::cbegin(spellEffects), std::cend(spellEffects)); - } + // Strong reference to keep the binary code loaded + std::shared_ptr<ModuleReference> m_moduleReference; - private: - template<typename Iterator> - static bool _ValidateSpellInfo(Iterator begin, Iterator end) +#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING + +public: + // + // SpellScript/AuraScript interface base + // these functions are safe to override, see notes below for usage instructions + // + // Function in which handler functions are registered, must be implemented in script + virtual void Register() = 0; + // Function called on server startup, if returns false script won't be used in core + // use for: dbc/template data presence/correctness checks + virtual bool Validate([[maybe_unused]] SpellInfo const* spellInfo) { return true; } + // Function called when script is created, if returns false script will be unloaded afterwards + // use for: initializing local script variables (DO NOT USE CONSTRUCTOR FOR THIS PURPOSE!) + virtual bool Load() { return true; } + // Function called when script is destroyed + // use for: deallocating memory allocated by script + virtual void Unload() { } + // Helpers + static bool ValidateSpellInfo(std::initializer_list<uint32> spellIds) + { + return ValidateSpellInfoImpl(spellIds.begin(), spellIds.end()); + } + + template <class T> + static bool ValidateSpellInfo(T const& spellIds) + { + return ValidateSpellInfoImpl(std::cbegin(spellIds), std::cend(spellIds)); + } + + static bool ValidateSpellEffect(std::initializer_list<std::pair<uint32, SpellEffIndex>> effects) + { + return ValidateSpellEffectsImpl(effects.begin(), effects.end()); + } + + template <class T> + static bool ValidateSpellEffect(T const& spellEffects) + { + return ValidateSpellEffectsImpl(std::cbegin(spellEffects), std::cend(spellEffects)); + } + +private: + template<typename Iterator> + static bool ValidateSpellInfoImpl(Iterator begin, Iterator end) + { + bool allValid = true; + while (begin != end) { - bool allValid = true; - while (begin != end) - { - if (!_ValidateSpellInfo(*begin)) - allValid = false; - - ++begin; - } - return allValid; - } + if (!ValidateSpellInfoImpl(*begin)) + allValid = false; - template<typename Iterator> - static bool _ValidateSpellEffects(Iterator begin, Iterator end) + ++begin; + } + return allValid; + } + + template<typename Iterator> + static bool ValidateSpellEffectsImpl(Iterator begin, Iterator end) + { + bool allValid = true; + while (begin != end) { - bool allValid = true; - while (begin != end) - { - if (!_ValidateSpellEffect(begin->first, begin->second)) - allValid = false; - - ++begin; - } - return allValid; + if (!ValidateSpellEffectImpl(begin->first, begin->second)) + allValid = false; + + ++begin; } + return allValid; + } - static bool _ValidateSpellInfo(uint32 spellId); - static bool _ValidateSpellEffect(uint32 spellId, SpellEffIndex effectIndex); + static bool ValidateSpellInfoImpl(uint32 spellId); + static bool ValidateSpellEffectImpl(uint32 spellId, SpellEffIndex effectIndex); }; // SpellScript interface - enum used for runtime checks of script function calls @@ -249,423 +241,559 @@ enum SpellScriptHookType #define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT_HIT #define HOOK_SPELL_HIT_END SPELL_SCRIPT_HOOK_AFTER_HIT + 1 -class TC_GAME_API SpellScript : public _SpellScript +class TC_GAME_API SpellScript : public SpellScriptBase { // internal use classes & functions // DO NOT OVERRIDE THESE IN SCRIPTS +public: + class TC_GAME_API CastHandler + { public: - #define SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \ - typedef SpellCastResult(CLASSNAME::*SpellCheckCastFnType)(); \ - typedef void(CLASSNAME::*SpellEffectFnType)(SpellEffIndex); \ - typedef void(CLASSNAME::*SpellBeforeHitFnType)(SpellMissInfo missInfo); \ - typedef void(CLASSNAME::*SpellHitFnType)(); \ - typedef void(CLASSNAME::*SpellCastFnType)(); \ - typedef void(CLASSNAME::*SpellOnCalcCritChanceFnType)(Unit const* victim, float& chance); \ - typedef void(CLASSNAME::*SpellOnResistAbsorbCalculateFnType)(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); \ - typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ - typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&); \ - typedef void(CLASSNAME::*SpellDestinationTargetSelectFnType)(SpellDestination&); - - SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript) - - class TC_GAME_API CastHandler - { - public: - CastHandler(SpellCastFnType _pCastHandlerScript); - CastHandler(CastHandler const& right) = delete; - CastHandler(CastHandler&& right) noexcept; - CastHandler& operator=(CastHandler const& right) = delete; - CastHandler& operator=(CastHandler&& right) noexcept; - virtual ~CastHandler(); - void Call(SpellScript* spellScript); - private: - SpellCastFnType pCastHandlerScript; - }; - - class TC_GAME_API CheckCastHandler - { - public: - CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript); - CheckCastHandler(CheckCastHandler const& right) = delete; - CheckCastHandler(CheckCastHandler&& right) noexcept; - CheckCastHandler& operator=(CheckCastHandler const& right) = delete; - CheckCastHandler& operator=(CheckCastHandler&& right) noexcept; - virtual ~CheckCastHandler(); - SpellCastResult Call(SpellScript* spellScript); - private: - SpellCheckCastFnType _checkCastHandlerScript; - }; - - class TC_GAME_API EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook - { - public: - EffectHandler(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); - EffectHandler(EffectHandler const& right) = delete; - EffectHandler(EffectHandler&& right) noexcept; - EffectHandler& operator=(EffectHandler const& right) = delete; - EffectHandler& operator=(EffectHandler&& right) noexcept; - virtual ~EffectHandler(); - std::string ToString() const; - bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override; - void Call(SpellScript* spellScript, SpellEffIndex effIndex); - private: - SpellEffectFnType pEffectHandlerScript; - }; - - class TC_GAME_API HitHandler + using SpellCastFnType = void(SpellScript::*)(); + + template<typename ScriptFunc> + static CastHandler Create(ScriptFunc handler) { - public: - HitHandler(SpellHitFnType _pHitHandlerScript); - HitHandler(HitHandler const& right) = delete; - HitHandler(HitHandler&& right) noexcept; - HitHandler& operator=(HitHandler const& right) = delete; - HitHandler& operator=(HitHandler&& right) noexcept; - virtual ~HitHandler(); - void Call(SpellScript* spellScript); - private: - SpellHitFnType pHitHandlerScript; - }; - - class TC_GAME_API BeforeHitHandler + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellCastFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellCastFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass>, void>, + "CastHandler signature must be \"void HandleCast()\""); + + return { reinterpret_cast<SpellCastFnType>(handler) }; + } + + CastHandler(SpellCastFnType callImpl); + CastHandler(CastHandler const& right) = delete; + CastHandler(CastHandler&& right) noexcept; + CastHandler& operator=(CastHandler const& right) = delete; + CastHandler& operator=(CastHandler&& right) noexcept; + ~CastHandler(); + void Call(SpellScript* spellScript) const; + private: + SpellCastFnType _callImpl; + }; + + class TC_GAME_API CheckCastHandler + { + public: + using SpellCheckCastFnType = SpellCastResult(SpellScript::*)(); + + template<typename ScriptFunc> + static CheckCastHandler Create(ScriptFunc handler) { - public: - BeforeHitHandler(SpellBeforeHitFnType pBeforeHitHandlerScript); - BeforeHitHandler(BeforeHitHandler const& right) = delete; - BeforeHitHandler(BeforeHitHandler&& right) noexcept; - BeforeHitHandler& operator=(BeforeHitHandler const& right) = delete; - BeforeHitHandler& operator=(BeforeHitHandler&& right) noexcept; - virtual ~BeforeHitHandler(); - void Call(SpellScript* spellScript, SpellMissInfo missInfo); - private: - SpellBeforeHitFnType _pBeforeHitHandlerScript; - }; - - class TC_GAME_API OnCalcCritChanceHandler + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellCheckCastFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellCheckCastFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass>, SpellCastResult>, + "CheckCastHandler signature must be \"SpellCastResult CheckCast()\""); + + return { reinterpret_cast<SpellCheckCastFnType>(handler) }; + } + + CheckCastHandler(SpellCheckCastFnType callImpl); + CheckCastHandler(CheckCastHandler const& right) = delete; + CheckCastHandler(CheckCastHandler&& right) noexcept; + CheckCastHandler& operator=(CheckCastHandler const& right) = delete; + CheckCastHandler& operator=(CheckCastHandler&& right) noexcept; + ~CheckCastHandler(); + SpellCastResult Call(SpellScript* spellScript) const; + private: + SpellCheckCastFnType _callImpl; + }; + + class TC_GAME_API EffectHandler : public EffectHook + { + public: + using SpellEffectFnType = void(SpellScript::*)(SpellEffIndex); + + template<typename ScriptFunc> + static EffectHandler Create(ScriptFunc handler, uint8 effIndex, uint16 effName) { - public: - OnCalcCritChanceHandler(SpellOnCalcCritChanceFnType onCalcCritChanceHandlerScript); - OnCalcCritChanceHandler(OnCalcCritChanceHandler const& right) = delete; - OnCalcCritChanceHandler(OnCalcCritChanceHandler&& right) noexcept; - OnCalcCritChanceHandler& operator=(OnCalcCritChanceHandler const& right) = delete; - OnCalcCritChanceHandler& operator=(OnCalcCritChanceHandler&& right) noexcept; - virtual ~OnCalcCritChanceHandler(); - void Call(SpellScript* spellScript, Unit const* victim, float& critChance) const; - private: - SpellOnCalcCritChanceFnType _onCalcCritChanceHandlerScript; - }; - - class TC_GAME_API TargetHook : public _SpellScript::EffectHook + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellEffectFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellEffectFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, SpellEffIndex> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, SpellEffIndex>, void>, + "EffectHandler signature must be \"void HandleEffect(SpellEffIndex effIndex)\""); + + return { reinterpret_cast<SpellEffectFnType>(handler), effIndex, effName }; + } + + EffectHandler(SpellEffectFnType callImpl, uint8 effIndex, uint16 effName); + EffectHandler(EffectHandler const& right) = delete; + EffectHandler(EffectHandler&& right) noexcept; + EffectHandler& operator=(EffectHandler const& right) = delete; + EffectHandler& operator=(EffectHandler&& right) noexcept; + ~EffectHandler(); + std::string ToString() const; + bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override; + void Call(SpellScript* spellScript, SpellEffIndex effIndex) const; + private: + SpellEffectFnType _callImpl; + uint16 _effName; + }; + + class TC_GAME_API BeforeHitHandler + { + public: + using SpellBeforeHitFnType = void(SpellScript::*)(SpellMissInfo missInfo); + + template<typename ScriptFunc> + static BeforeHitHandler Create(ScriptFunc handler) { - public: - TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest); - TargetHook(TargetHook const& right) = delete; - TargetHook(TargetHook&& right) noexcept; - TargetHook& operator=(TargetHook const& right) = delete; - TargetHook& operator=(TargetHook&& right) noexcept; - virtual ~TargetHook(); - bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override; - std::string ToString() const; - uint16 GetTarget() const { return targetType; } - protected: - uint16 targetType; - bool area; - bool dest; - }; - - class TC_GAME_API ObjectAreaTargetSelectHandler : public TargetHook + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellBeforeHitFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellBeforeHitFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, SpellMissInfo> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, SpellMissInfo>, void>, + "BeforeHitHandler signature must be \"void HandleBeforeHit(SpellMissInfo missInfo)\""); + + return { reinterpret_cast<SpellBeforeHitFnType>(handler) }; + } + + BeforeHitHandler(SpellBeforeHitFnType callImpl); + BeforeHitHandler(BeforeHitHandler const& right) = delete; + BeforeHitHandler(BeforeHitHandler&& right) noexcept; + BeforeHitHandler& operator=(BeforeHitHandler const& right) = delete; + BeforeHitHandler& operator=(BeforeHitHandler&& right) noexcept; + ~BeforeHitHandler(); + void Call(SpellScript* spellScript, SpellMissInfo missInfo) const; + private: + SpellBeforeHitFnType _callImpl; + }; + + class TC_GAME_API HitHandler + { + public: + using SpellHitFnType = void(SpellScript::*)(); + + template<typename ScriptFunc> + static HitHandler Create(ScriptFunc handler) { - public: - ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); - ObjectAreaTargetSelectHandler(ObjectAreaTargetSelectHandler const& right) = delete; - ObjectAreaTargetSelectHandler(ObjectAreaTargetSelectHandler&& right) noexcept; - ObjectAreaTargetSelectHandler& operator=(ObjectAreaTargetSelectHandler const& right) = delete; - ObjectAreaTargetSelectHandler& operator=(ObjectAreaTargetSelectHandler&& right) noexcept; - virtual ~ObjectAreaTargetSelectHandler(); - void Call(SpellScript* spellScript, std::list<WorldObject*>& targets); - private: - SpellObjectAreaTargetSelectFnType pObjectAreaTargetSelectHandlerScript; - }; - - class TC_GAME_API ObjectTargetSelectHandler : public TargetHook + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellHitFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellHitFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass>, void>, + "HitHandler signature must be \"void HandleHit()\""); + + return { reinterpret_cast<SpellHitFnType>(handler) }; + } + + HitHandler(SpellHitFnType callImpl); + HitHandler(HitHandler const& right) = delete; + HitHandler(HitHandler&& right) noexcept; + HitHandler& operator=(HitHandler const& right) = delete; + HitHandler& operator=(HitHandler&& right) noexcept; + virtual ~HitHandler(); + void Call(SpellScript* spellScript) const; + private: + SpellHitFnType _callImpl; + }; + + class TC_GAME_API OnCalcCritChanceHandler + { + public: + using SpellOnCalcCritChanceFnType = void(SpellScript::*)(Unit const* victim, float& chance); + + template<typename ScriptFunc> + static OnCalcCritChanceHandler Create(ScriptFunc handler) { - public: - ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); - ObjectTargetSelectHandler(ObjectTargetSelectHandler const& right) = delete; - ObjectTargetSelectHandler(ObjectTargetSelectHandler&& right) noexcept; - ObjectTargetSelectHandler& operator=(ObjectTargetSelectHandler const& right) = delete; - ObjectTargetSelectHandler& operator=(ObjectTargetSelectHandler&& right) noexcept; - virtual ~ObjectTargetSelectHandler(); - void Call(SpellScript* spellScript, WorldObject*& target); - private: - SpellObjectTargetSelectFnType pObjectTargetSelectHandlerScript; - }; - - class TC_GAME_API DestinationTargetSelectHandler : public TargetHook + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellOnCalcCritChanceFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellOnCalcCritChanceFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, Unit const*, float&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, Unit const*, float&>, void>, + "OnCalcCritChanceHandler signature must be \"void CalcCritChance(Unit const* victim, float& critChance)\""); + + return { reinterpret_cast<SpellOnCalcCritChanceFnType>(handler) }; + } + + OnCalcCritChanceHandler(SpellOnCalcCritChanceFnType callImpl); + OnCalcCritChanceHandler(OnCalcCritChanceHandler const& right) = delete; + OnCalcCritChanceHandler(OnCalcCritChanceHandler&& right) noexcept; + OnCalcCritChanceHandler& operator=(OnCalcCritChanceHandler const& right) = delete; + OnCalcCritChanceHandler& operator=(OnCalcCritChanceHandler&& right) noexcept; + virtual ~OnCalcCritChanceHandler(); + void Call(SpellScript* spellScript, Unit const* victim, float& critChance) const; + private: + SpellOnCalcCritChanceFnType _callImpl; + }; + + class TC_GAME_API TargetHook : public EffectHook + { + public: + TargetHook(uint8 effectIndex, uint16 targetType, bool area, bool dest); + TargetHook(TargetHook const& right) = delete; + TargetHook(TargetHook&& right) noexcept; + TargetHook& operator=(TargetHook const& right) = delete; + TargetHook& operator=(TargetHook&& right) noexcept; + virtual ~TargetHook(); + bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override; + std::string ToString() const; + uint16 GetTarget() const { return _targetType; } + protected: + uint16 _targetType; + bool _area; + bool _dest; + }; + + class TC_GAME_API ObjectAreaTargetSelectHandler : public TargetHook + { + public: + using SpellObjectAreaTargetSelectFnType = void(SpellScript::*)(std::list<WorldObject*>&); + + template<typename ScriptFunc> + static ObjectAreaTargetSelectHandler Create(ScriptFunc handler, uint8 effIndex, uint16 targetType) { - public: - DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); - DestinationTargetSelectHandler(DestinationTargetSelectHandler const& right) = delete; - DestinationTargetSelectHandler(DestinationTargetSelectHandler&& right) noexcept; - DestinationTargetSelectHandler& operator=(DestinationTargetSelectHandler const& right) = delete; - DestinationTargetSelectHandler& operator=(DestinationTargetSelectHandler&& right) noexcept; - virtual ~DestinationTargetSelectHandler(); - void Call(SpellScript* spellScript, SpellDestination& target); - private: - SpellDestinationTargetSelectFnType DestinationTargetSelectHandlerScript; - }; - - class TC_GAME_API OnCalculateResistAbsorbHandler + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellObjectAreaTargetSelectFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellObjectAreaTargetSelectFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, std::list<WorldObject*>&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, std::list<WorldObject*>&>, void>, + "ObjectAreaTargetSelectHandler signature must be \"void SetTargets(std::list<WorldObject*>& targets)\""); + + return { reinterpret_cast<SpellObjectAreaTargetSelectFnType>(handler), effIndex, targetType }; + } + + ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType callImpl, uint8 effIndex, uint16 targetType); + ObjectAreaTargetSelectHandler(ObjectAreaTargetSelectHandler const& right) = delete; + ObjectAreaTargetSelectHandler(ObjectAreaTargetSelectHandler&& right) noexcept; + ObjectAreaTargetSelectHandler& operator=(ObjectAreaTargetSelectHandler const& right) = delete; + ObjectAreaTargetSelectHandler& operator=(ObjectAreaTargetSelectHandler&& right) noexcept; + ~ObjectAreaTargetSelectHandler(); + void Call(SpellScript* spellScript, std::list<WorldObject*>& targets) const; + private: + SpellObjectAreaTargetSelectFnType _callImpl; + }; + + class TC_GAME_API ObjectTargetSelectHandler : public TargetHook + { + public: + using SpellObjectTargetSelectFnType = void(SpellScript::*)(WorldObject*&); + + template<typename ScriptFunc> + static ObjectTargetSelectHandler Create(ScriptFunc handler, uint8 effIndex, uint16 targetType) { - public: - OnCalculateResistAbsorbHandler(SpellOnResistAbsorbCalculateFnType _pOnCalculateResistAbsorbHandlerScript); - OnCalculateResistAbsorbHandler(OnCalculateResistAbsorbHandler const& right) = delete; - OnCalculateResistAbsorbHandler(OnCalculateResistAbsorbHandler&& right) noexcept; - OnCalculateResistAbsorbHandler& operator=(OnCalculateResistAbsorbHandler const& right) = delete; - OnCalculateResistAbsorbHandler& operator=(OnCalculateResistAbsorbHandler&& right) noexcept; - virtual ~OnCalculateResistAbsorbHandler(); - void Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); - private: - SpellOnResistAbsorbCalculateFnType pOnCalculateResistAbsorbHandlerScript; - }; - - #define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ - class CastHandlerFunction : public SpellScript::CastHandler { public: explicit CastHandlerFunction(SpellCastFnType _pCastHandlerScript) : SpellScript::CastHandler((SpellScript::SpellCastFnType)_pCastHandlerScript) { } }; \ - class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: explicit CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) { } }; \ - class EffectHandlerFunction : public SpellScript::EffectHandler { public: explicit EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ - class HitHandlerFunction : public SpellScript::HitHandler { public: explicit HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) { } }; \ - class BeforeHitHandlerFunction : public SpellScript::BeforeHitHandler { public: explicit BeforeHitHandlerFunction(SpellBeforeHitFnType pBeforeHitHandlerScript) : SpellScript::BeforeHitHandler((SpellScript::SpellBeforeHitFnType)pBeforeHitHandlerScript) { } }; \ - class OnCalcCritChanceHandlerFunction : public SpellScript::OnCalcCritChanceHandler { public: explicit OnCalcCritChanceHandlerFunction(SpellOnCalcCritChanceFnType onCalcCritChanceHandlerScript) : SpellScript::OnCalcCritChanceHandler((SpellScript::SpellOnCalcCritChanceFnType)onCalcCritChanceHandlerScript) {} }; \ - class OnCalculateResistAbsorbHandlerFunction : public SpellScript::OnCalculateResistAbsorbHandler { public: explicit OnCalculateResistAbsorbHandlerFunction(SpellOnResistAbsorbCalculateFnType _onCalculateResistAbsorbScript) : SpellScript::OnCalculateResistAbsorbHandler((SpellScript::SpellOnResistAbsorbCalculateFnType)_onCalculateResistAbsorbScript) { } }; \ - class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: explicit ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ - class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: explicit ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ - class DestinationTargetSelectHandlerFunction : public SpellScript::DestinationTargetSelectHandler { public: explicit DestinationTargetSelectHandlerFunction(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::DestinationTargetSelectHandler((SpellScript::SpellDestinationTargetSelectFnType)_DestinationTargetSelectHandlerScript, _effIndex, _targetType) { } } - - #define PrepareSpellScript(CLASSNAME) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellObjectTargetSelectFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellObjectTargetSelectFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, WorldObject*&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, WorldObject*&>, void>, + "ObjectTargetSelectHandler signature must be \"void SetTarget(WorldObject*& target)\""); + + return { reinterpret_cast<SpellObjectTargetSelectFnType>(handler), effIndex, targetType }; + } + + ObjectTargetSelectHandler(SpellObjectTargetSelectFnType callImpl, uint8 effIndex, uint16 targetType); + ObjectTargetSelectHandler(ObjectTargetSelectHandler const& right) = delete; + ObjectTargetSelectHandler(ObjectTargetSelectHandler&& right) noexcept; + ObjectTargetSelectHandler& operator=(ObjectTargetSelectHandler const& right) = delete; + ObjectTargetSelectHandler& operator=(ObjectTargetSelectHandler&& right) noexcept; + ~ObjectTargetSelectHandler(); + void Call(SpellScript* spellScript, WorldObject*& target) const; + private: + SpellObjectTargetSelectFnType _callImpl; + }; + + class TC_GAME_API DestinationTargetSelectHandler : public TargetHook + { public: - SpellScript(); - ~SpellScript(); - bool _Validate(SpellInfo const* entry) override; - bool _Load(Spell* spell); - void _InitHit(); - bool _IsEffectPrevented(SpellEffIndex effIndex) const { return (m_hitPreventEffectMask & (1 << effIndex)) != 0; } - bool _IsDefaultEffectPrevented(SpellEffIndex effIndex) const { return (m_hitPreventDefaultEffectMask & (1 << effIndex)) != 0; } - void _PrepareScriptCall(SpellScriptHookType hookType); - void _FinishScriptCall(); - bool IsInCheckCastHook() const; - bool IsAfterTargetSelectionPhase() const; - bool IsInTargetHook() const; - bool IsInModifiableHook() const; - bool IsInHitPhase() const; - bool IsInEffectHook() const; + using SpellDestinationTargetSelectFnType = void(SpellScript::*)(SpellDestination&); + + template<typename ScriptFunc> + static DestinationTargetSelectHandler Create(ScriptFunc handler, uint8 effIndex, uint16 targetType) + { + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellDestinationTargetSelectFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellDestinationTargetSelectFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, SpellDestination&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, SpellDestination&>, void>, + "DestinationTargetSelectHandler signature must be \"void SetTarget(SpellDestination& target)\""); + + return { reinterpret_cast<SpellDestinationTargetSelectFnType>(handler), effIndex, targetType }; + } + + DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType callImpl, uint8 effIndex, uint16 targetType); + DestinationTargetSelectHandler(DestinationTargetSelectHandler const& right) = delete; + DestinationTargetSelectHandler(DestinationTargetSelectHandler&& right) noexcept; + DestinationTargetSelectHandler& operator=(DestinationTargetSelectHandler const& right) = delete; + DestinationTargetSelectHandler& operator=(DestinationTargetSelectHandler&& right) noexcept; + ~DestinationTargetSelectHandler(); + void Call(SpellScript* spellScript, SpellDestination& target) const; private: - Spell* m_spell; - uint32 m_hitPreventEffectMask; - uint32 m_hitPreventDefaultEffectMask; + SpellDestinationTargetSelectFnType _callImpl; + }; + + class TC_GAME_API OnCalculateResistAbsorbHandler + { public: - // - // SpellScript interface - // - // example: void OnPrecast() override { } - virtual void OnPrecast() { } - // - // hooks to which you can attach your functions - // - // example: BeforeCast += SpellCastFn(class::function); - HookList<CastHandler> BeforeCast; - // example: OnCast += SpellCastFn(class::function); - HookList<CastHandler> OnCast; - // example: AfterCast += SpellCastFn(class::function); - HookList<CastHandler> AfterCast; - #define SpellCastFn(F) CastHandlerFunction(&F) - - // example: OnCheckCast += SpellCheckCastFn(); - // where function is SpellCastResult function() - HookList<CheckCastHandler> OnCheckCast; - #define SpellCheckCastFn(F) CheckCastHandlerFunction(&F) - - // example: int32 CalcCastTime(int32 castTime) override { return 1500; } - virtual int32 CalcCastTime(int32 castTime) { return castTime; } - - // example: OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(class::function); - // where function is void function(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) - HookList<OnCalculateResistAbsorbHandler> OnCalculateResistAbsorb; - #define SpellOnResistAbsorbCalculateFn(F) OnCalculateResistAbsorbHandlerFunction(&F) - - // example: OnEffect**** += SpellEffectFn(class::function, EffectIndexSpecifier, EffectNameSpecifier); - // where function is void function(SpellEffIndex effIndex) - HookList<EffectHandler> OnEffectLaunch; - HookList<EffectHandler> OnEffectLaunchTarget; - HookList<EffectHandler> OnEffectHit; - HookList<EffectHandler> OnEffectHitTarget; - HookList<EffectHandler> OnEffectSuccessfulDispel; - #define SpellEffectFn(F, I, N) EffectHandlerFunction(&F, I, N) - - // example: BeforeHit += BeforeSpellHitFn(class::function); - // where function is void function(SpellMissInfo missInfo) - HookList<BeforeHitHandler> BeforeHit; - #define BeforeSpellHitFn(F) BeforeHitHandlerFunction(&F) - - // example: OnHit += SpellHitFn(class::function); - HookList<HitHandler> OnHit; - // example: AfterHit += SpellHitFn(class::function); - HookList<HitHandler> AfterHit; - // where function is: void function() - #define SpellHitFn(F) HitHandlerFunction(&F) - - // example: OnCalcCritChance += SpellOnCalcCritChanceFn(class::function); - // where function is: void function(Unit* victim, float& critChance) - HookList<OnCalcCritChanceHandler> OnCalcCritChance; - #define SpellOnCalcCritChanceFn(F) OnCalcCritChanceHandlerFunction(&F) - - // example: OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); - // where function is void function(std::list<WorldObject*>& targets) - HookList<ObjectAreaTargetSelectHandler> OnObjectAreaTargetSelect; - #define SpellObjectAreaTargetSelectFn(F, I, N) ObjectAreaTargetSelectHandlerFunction(&F, I, N) - - // example: OnObjectTargetSelect += SpellObjectTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); - // where function is void function(WorldObject*& target) - HookList<ObjectTargetSelectHandler> OnObjectTargetSelect; - #define SpellObjectTargetSelectFn(F, I, N) ObjectTargetSelectHandlerFunction(&F, I, N) - - // example: OnDestinationTargetSelect += SpellDestinationTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); - // where function is void function(SpellDestination& target) - HookList<DestinationTargetSelectHandler> OnDestinationTargetSelect; - #define SpellDestinationTargetSelectFn(F, I, N) DestinationTargetSelectHandlerFunction(&F, I, N) - - // hooks are executed in following order, at specified event of spell: - // 1. OnPrecast - executed during spell preparation (before cast bar starts) - // 2. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled - // 3. OnCheckCast - allows to override result of CheckCast function - // 4a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets) - // 4b. OnObjectTargetSelect - executed just before adding selected target to final target list (for single unit targets) - // 4c. OnDestinationTargetSelect - executed just before adding selected target to final target list (for destination targets) - // 5. OnCast - executed just before spell is launched (creates missile) or executed - // 6. AfterCast - executed after spell missile is launched and immediate spell actions are done - // 7. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched - // 8. OnEffectLaunchTarget - executed just before specified effect handler call - when spell missile is launched - called for each target from spell target map - // 9. OnCalcCritChance - executed just after specified effect handler call - when spell missile is launched - called for each target from spell target map - // 10. OnCalculateResistAbsorb - executed when damage resist/absorbs is calculated - before spell hit target - // 11. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest - // 12. BeforeHit - executed just before spell hits a target - called for each target from spell target map - // 13. OnEffectHitTarget - executed just before specified effect handler call - called for each target from spell target map - // 14. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map - // 15. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map - - // this hook is only executed after a successful dispel of any aura - // OnEffectSuccessfulDispel - executed just after effect successfully dispelled aura(s) - - // - // methods allowing interaction with Spell object - // - // methods useable during all spell handling phases - Unit* GetCaster() const; - GameObject* GetGObjCaster() const; - Unit* GetOriginalCaster() const; - SpellInfo const* GetSpellInfo() const; - SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; - SpellValue const* GetSpellValue() const; - - // methods useable after spell is prepared - // accessors to the explicit targets of the spell - // explicit target - target selected by caster (player, game client, or script - DoCast(explicitTarget, ...), required for spell to be cast - // examples: - // -shadowstep - explicit target is the unit you want to go behind of - // -chain heal - explicit target is the unit to be healed first - // -holy nova/arcane explosion - explicit target = NULL because target you are selecting doesn't affect how spell targets are selected - // you can determine if spell requires explicit targets by dbc columns: - // - Targets - mask of explicit target types - // - ImplicitTargetXX set to TARGET_XXX_TARGET_YYY, _TARGET_ here means that explicit target is used by the effect, so spell needs one too - - // returns: WorldLocation which was selected as a spell destination or NULL - WorldLocation const* GetExplTargetDest() const; - - void SetExplTargetDest(WorldLocation& loc); - - // returns: WorldObject which was selected as an explicit spell target or NULL if there's no target - WorldObject* GetExplTargetWorldObject() const; - - // returns: Unit which was selected as an explicit spell target or NULL if there's no target - Unit* GetExplTargetUnit() const; - - // returns: GameObject which was selected as an explicit spell target or NULL if there's no target - GameObject* GetExplTargetGObj() const; - - // returns: Item which was selected as an explicit spell target or NULL if there's no target - Item* GetExplTargetItem() const; - - // methods usable only after spell targets have been fully selected - int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const; - int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const; - int64 GetItemTargetCountForEffect(SpellEffIndex effect) const; - int64 GetCorpseTargetCountForEffect(SpellEffIndex effect) const; - - // methods useable only during spell hit on target, or during spell launch on target: - // returns: target of current effect if it was Unit otherwise NULL - Unit* GetHitUnit() const; - // returns: target of current effect if it was Creature otherwise NULL - Creature* GetHitCreature() const; - // returns: target of current effect if it was Player otherwise NULL - Player* GetHitPlayer() const; - // returns: target of current effect if it was Item otherwise NULL - Item* GetHitItem() const; - // returns: target of current effect if it was GameObject otherwise NULL - GameObject* GetHitGObj() const; - // returns: target of current effect if it was Corpse otherwise nullptr - Corpse* GetHitCorpse() const; - // returns: destination of current effect - WorldLocation* GetHitDest() const; - // setter/getter for for damage done by spell to target of spell hit - // returns damage calculated before hit, and real dmg done after hit - int32 GetHitDamage() const; - void SetHitDamage(int32 damage); - void PreventHitDamage() { SetHitDamage(0); } - // setter/getter for for heal done by spell to target of spell hit - // returns healing calculated before hit, and real dmg done after hit - int32 GetHitHeal() const; - void SetHitHeal(int32 heal); - void PreventHitHeal() { SetHitHeal(0); } - // returns: true if spell critically hits current HitUnit - bool IsHitCrit() const; - Spell* GetSpell() const { return m_spell; } - // returns current spell hit target aura - Aura* GetHitAura(bool dynObjAura = false) const; - // prevents applying aura on current spell hit target - void PreventHitAura(); - - // prevents effect execution on current spell hit target - // including other effect/hit scripts - // will not work on aura/damage/heal - // will not work if effects were already handled - void PreventHitEffect(SpellEffIndex effIndex); - - // prevents default effect execution on current spell hit target - // will not work on aura/damage/heal effects - // will not work if effects were already handled - void PreventHitDefaultEffect(SpellEffIndex effIndex); - - // method available only in EffectHandler method - SpellEffectInfo const& GetEffectInfo() const; - int32 GetEffectValue() const; - void SetEffectValue(int32 value); - float GetEffectVariance() const; - void SetEffectVariance(float variance); - - // returns: cast item if present. - Item* GetCastItem() const; - - // Creates item. Calls Spell::DoCreateItem method. - void CreateItem(uint32 itemId, ItemContext context); - - // Returns SpellInfo from the spell that triggered the current one - SpellInfo const* GetTriggeringSpell() const; - - // finishes spellcast prematurely with selected error message - void FinishCast(SpellCastResult result, int32* param1 = nullptr, int32* param2 = nullptr); - - void SetCustomCastResultMessage(SpellCustomErrors result); - - // returns desired cast difficulty for triggered spells - Difficulty GetCastDifficulty() const; + using SpellOnResistAbsorbCalculateFnType = void(SpellScript::*)(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); + + template<typename ScriptFunc> + static OnCalculateResistAbsorbHandler Create(ScriptFunc handler) + { + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(SpellOnResistAbsorbCalculateFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(SpellOnResistAbsorbCalculateFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, DamageInfo const&, uint32&, int32&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, DamageInfo const&, uint32&, int32&>, void>, + "OnCalculateResistAbsorbHandler signature must be \"void CalcAbsorbResist(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount)\""); + + return { reinterpret_cast<SpellOnResistAbsorbCalculateFnType>(handler) }; + } + + OnCalculateResistAbsorbHandler(SpellOnResistAbsorbCalculateFnType callImpl); + OnCalculateResistAbsorbHandler(OnCalculateResistAbsorbHandler const& right) = delete; + OnCalculateResistAbsorbHandler(OnCalculateResistAbsorbHandler&& right) noexcept; + OnCalculateResistAbsorbHandler& operator=(OnCalculateResistAbsorbHandler const& right) = delete; + OnCalculateResistAbsorbHandler& operator=(OnCalculateResistAbsorbHandler&& right) noexcept; + ~OnCalculateResistAbsorbHandler(); + void Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) const; + private: + SpellOnResistAbsorbCalculateFnType _callImpl; + }; + + // left for custom compatibility only, DO NOT USE + #define PrepareSpellScript(CLASSNAME) using silence_semicolon_warning = void + + SpellScript(); + ~SpellScript(); + bool _Validate(SpellInfo const* entry) override; + bool _Load(Spell* spell); + void _InitHit(); + bool _IsEffectPrevented(SpellEffIndex effIndex) const { return (m_hitPreventEffectMask & (1 << effIndex)) != 0; } + bool _IsDefaultEffectPrevented(SpellEffIndex effIndex) const { return (m_hitPreventDefaultEffectMask & (1 << effIndex)) != 0; } + void _PrepareScriptCall(SpellScriptHookType hookType); + void _FinishScriptCall(); + bool IsInCheckCastHook() const; + bool IsAfterTargetSelectionPhase() const; + bool IsInTargetHook() const; + bool IsInModifiableHook() const; + bool IsInHitPhase() const; + bool IsInEffectHook() const; +private: + Spell* m_spell; + uint32 m_hitPreventEffectMask; + uint32 m_hitPreventDefaultEffectMask; +public: + // + // SpellScript interface + // + // example: void OnPrecast() override { } + virtual void OnPrecast() { } + // + // hooks to which you can attach your functions + // + // example: BeforeCast += SpellCastFn(class::function); + HookList<CastHandler> BeforeCast; + // example: OnCast += SpellCastFn(class::function); + HookList<CastHandler> OnCast; + // example: AfterCast += SpellCastFn(class::function); + HookList<CastHandler> AfterCast; + #define SpellCastFn(F) CastHandler::Create(&F) + + // example: OnCheckCast += SpellCheckCastFn(); + // where function is SpellCastResult function() + HookList<CheckCastHandler> OnCheckCast; + #define SpellCheckCastFn(F) CheckCastHandler::Create(&F) + + // example: int32 CalcCastTime(int32 castTime) override { return 1500; } + virtual int32 CalcCastTime(int32 castTime) { return castTime; } + + // example: OnEffect**** += SpellEffectFn(class::function, EffectIndexSpecifier, EffectNameSpecifier); + // where function is void function(SpellEffIndex effIndex) + HookList<EffectHandler> OnEffectLaunch; + HookList<EffectHandler> OnEffectLaunchTarget; + HookList<EffectHandler> OnEffectHit; + HookList<EffectHandler> OnEffectHitTarget; + HookList<EffectHandler> OnEffectSuccessfulDispel; + #define SpellEffectFn(F, I, N) EffectHandler::Create(&F, I, N) + + // example: BeforeHit += BeforeSpellHitFn(class::function); + // where function is void function(SpellMissInfo missInfo) + HookList<BeforeHitHandler> BeforeHit; + #define BeforeSpellHitFn(F) BeforeHitHandler::Create(&F) + + // example: OnHit += SpellHitFn(class::function); + HookList<HitHandler> OnHit; + // example: AfterHit += SpellHitFn(class::function); + HookList<HitHandler> AfterHit; + // where function is: void function() + #define SpellHitFn(F) HitHandler::Create(&F) + + // example: OnCalcCritChance += SpellOnCalcCritChanceFn(class::function); + // where function is: void function(Unit* victim, float& critChance) + HookList<OnCalcCritChanceHandler> OnCalcCritChance; + #define SpellOnCalcCritChanceFn(F) OnCalcCritChanceHandler::Create(&F) + + // example: OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); + // where function is void function(std::list<WorldObject*>& targets) + HookList<ObjectAreaTargetSelectHandler> OnObjectAreaTargetSelect; + #define SpellObjectAreaTargetSelectFn(F, I, N) ObjectAreaTargetSelectHandler::Create(&F, I, N) + + // example: OnObjectTargetSelect += SpellObjectTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); + // where function is void function(WorldObject*& target) + HookList<ObjectTargetSelectHandler> OnObjectTargetSelect; + #define SpellObjectTargetSelectFn(F, I, N) ObjectTargetSelectHandler::Create(&F, I, N) + + // example: OnDestinationTargetSelect += SpellDestinationTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); + // where function is void function(SpellDestination& target) + HookList<DestinationTargetSelectHandler> OnDestinationTargetSelect; + #define SpellDestinationTargetSelectFn(F, I, N) DestinationTargetSelectHandler::Create(&F, I, N) + + // example: OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(class::function); + // where function is void function(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) + HookList<OnCalculateResistAbsorbHandler> OnCalculateResistAbsorb; + #define SpellOnResistAbsorbCalculateFn(F) OnCalculateResistAbsorbHandler::Create(&F) + + // hooks are executed in following order, at specified event of spell: + // 1. OnPrecast - executed during spell preparation (before cast bar starts) + // 2. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled + // 3. OnCheckCast - allows to override result of CheckCast function + // 4a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets) + // 4b. OnObjectTargetSelect - executed just before adding selected target to final target list (for single unit targets) + // 4c. OnDestinationTargetSelect - executed just before adding selected target to final target list (for destination targets) + // 5. OnCast - executed just before spell is launched (creates missile) or executed + // 6. AfterCast - executed after spell missile is launched and immediate spell actions are done + // 7. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched + // 8. OnEffectLaunchTarget - executed just before specified effect handler call - when spell missile is launched - called for each target from spell target map + // 9. OnCalcCritChance - executed just after specified effect handler call - when spell missile is launched - called for each target from spell target map + // 10. OnCalculateResistAbsorb - executed when damage resist/absorbs is calculated - before spell hit target + // 11. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest + // 12. BeforeHit - executed just before spell hits a target - called for each target from spell target map + // 13. OnEffectHitTarget - executed just before specified effect handler call - called for each target from spell target map + // 14. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map + // 15. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map + + // this hook is only executed after a successful dispel of any aura + // OnEffectSuccessfulDispel - executed just after effect successfully dispelled aura(s) + + // + // methods allowing interaction with Spell object + // + // methods useable during all spell handling phases + Unit* GetCaster() const; + GameObject* GetGObjCaster() const; + Unit* GetOriginalCaster() const; + SpellInfo const* GetSpellInfo() const; + SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; + SpellValue const* GetSpellValue() const; + + // methods useable after spell is prepared + // accessors to the explicit targets of the spell + // explicit target - target selected by caster (player, game client, or script - DoCast(explicitTarget, ...), required for spell to be cast + // examples: + // -shadowstep - explicit target is the unit you want to go behind of + // -chain heal - explicit target is the unit to be healed first + // -holy nova/arcane explosion - explicit target = NULL because target you are selecting doesn't affect how spell targets are selected + // you can determine if spell requires explicit targets by dbc columns: + // - Targets - mask of explicit target types + // - ImplicitTargetXX set to TARGET_XXX_TARGET_YYY, _TARGET_ here means that explicit target is used by the effect, so spell needs one too + + // returns: WorldLocation which was selected as a spell destination or NULL + WorldLocation const* GetExplTargetDest() const; + + void SetExplTargetDest(WorldLocation& loc); + + // returns: WorldObject which was selected as an explicit spell target or NULL if there's no target + WorldObject* GetExplTargetWorldObject() const; + + // returns: Unit which was selected as an explicit spell target or NULL if there's no target + Unit* GetExplTargetUnit() const; + + // returns: GameObject which was selected as an explicit spell target or NULL if there's no target + GameObject* GetExplTargetGObj() const; + + // returns: Item which was selected as an explicit spell target or NULL if there's no target + Item* GetExplTargetItem() const; + + // methods usable only after spell targets have been fully selected + int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const; + int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const; + int64 GetItemTargetCountForEffect(SpellEffIndex effect) const; + int64 GetCorpseTargetCountForEffect(SpellEffIndex effect) const; + + // methods useable only during spell hit on target, or during spell launch on target: + // returns: target of current effect if it was Unit otherwise NULL + Unit* GetHitUnit() const; + // returns: target of current effect if it was Creature otherwise NULL + Creature* GetHitCreature() const; + // returns: target of current effect if it was Player otherwise NULL + Player* GetHitPlayer() const; + // returns: target of current effect if it was Item otherwise NULL + Item* GetHitItem() const; + // returns: target of current effect if it was GameObject otherwise NULL + GameObject* GetHitGObj() const; + // returns: target of current effect if it was Corpse otherwise nullptr + Corpse* GetHitCorpse() const; + // returns: destination of current effect + WorldLocation* GetHitDest() const; + // setter/getter for for damage done by spell to target of spell hit + // returns damage calculated before hit, and real dmg done after hit + int32 GetHitDamage() const; + void SetHitDamage(int32 damage); + void PreventHitDamage() { SetHitDamage(0); } + // setter/getter for for heal done by spell to target of spell hit + // returns healing calculated before hit, and real dmg done after hit + int32 GetHitHeal() const; + void SetHitHeal(int32 heal); + void PreventHitHeal() { SetHitHeal(0); } + // returns: true if spell critically hits current HitUnit + bool IsHitCrit() const; + Spell* GetSpell() const { return m_spell; } + // returns current spell hit target aura + Aura* GetHitAura(bool dynObjAura = false) const; + // prevents applying aura on current spell hit target + void PreventHitAura(); + + // prevents effect execution on current spell hit target + // including other effect/hit scripts + // will not work on aura/damage/heal + // will not work if effects were already handled + void PreventHitEffect(SpellEffIndex effIndex); + + // prevents default effect execution on current spell hit target + // will not work on aura/damage/heal effects + // will not work if effects were already handled + void PreventHitDefaultEffect(SpellEffIndex effIndex); + + // method available only in EffectHandler method + SpellEffectInfo const& GetEffectInfo() const; + int32 GetEffectValue() const; + void SetEffectValue(int32 value); + float GetEffectVariance() const; + void SetEffectVariance(float variance); + + // returns: cast item if present. + Item* GetCastItem() const; + + // Creates item. Calls Spell::DoCreateItem method. + void CreateItem(uint32 itemId, ItemContext context); + + // Returns SpellInfo from the spell that triggered the current one + SpellInfo const* GetTriggeringSpell() const; + + // finishes spellcast prematurely with selected error message + void FinishCast(SpellCastResult result, int32* param1 = nullptr, int32* param2 = nullptr); + + void SetCustomCastResultMessage(SpellCustomErrors result); + + // returns desired cast difficulty for triggered spells + Difficulty GetCastDifficulty() const; }; // AuraScript interface - enum used for runtime checks of script function calls @@ -706,571 +834,784 @@ enum AuraScriptHookType #define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1 #define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START */ -class TC_GAME_API AuraScript : public _SpellScript +class TC_GAME_API AuraScript : public SpellScriptBase { // internal use classes & functions // DO NOT OVERRIDE THESE IN SCRIPTS +public: + class TC_GAME_API CheckAreaTargetHandler + { public: + using AuraCheckAreaTargetFnType = bool(AuraScript::*)(Unit* target); - #define AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \ - typedef bool(CLASSNAME::*AuraCheckAreaTargetFnType)(Unit* target); \ - typedef void(CLASSNAME::*AuraDispelFnType)(DispelInfo* dispelInfo); \ - typedef void(CLASSNAME::*AuraEffectApplicationModeFnType)(AuraEffect const*, AuraEffectHandleModes); \ - typedef void(CLASSNAME::*AuraEffectPeriodicFnType)(AuraEffect const*); \ - typedef void(CLASSNAME::*AuraEffectUpdatePeriodicFnType)(AuraEffect*); \ - typedef void(CLASSNAME::*AuraEffectCalcAmountFnType)(AuraEffect const*, int32 &, bool &); \ - typedef void(CLASSNAME::*AuraEffectCalcPeriodicFnType)(AuraEffect const*, bool &, int32 &); \ - 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&); \ - typedef void(CLASSNAME::*AuraProcFnType)(ProcEventInfo&); \ - typedef void(CLASSNAME::*AuraEffectProcFnType)(AuraEffect*, ProcEventInfo&); \ - typedef void(CLASSNAME::*AuraEnterLeaveCombatFnType)(bool); - - AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript) - - class TC_GAME_API CheckAreaTargetHandler - { - public: - CheckAreaTargetHandler(AuraCheckAreaTargetFnType pHandlerScript); - CheckAreaTargetHandler(CheckAreaTargetHandler const& right) = delete; - CheckAreaTargetHandler(CheckAreaTargetHandler&& right) noexcept; - CheckAreaTargetHandler& operator=(CheckAreaTargetHandler const& right) = delete; - CheckAreaTargetHandler& operator=(CheckAreaTargetHandler&& right) noexcept; - virtual ~CheckAreaTargetHandler(); - bool Call(AuraScript* auraScript, Unit* target); - private: - AuraCheckAreaTargetFnType pHandlerScript; - }; - class TC_GAME_API AuraDispelHandler - { - public: - AuraDispelHandler(AuraDispelFnType pHandlerScript); - AuraDispelHandler(AuraDispelHandler const& right) = delete; - AuraDispelHandler(AuraDispelHandler&& right) noexcept; - AuraDispelHandler& operator=(AuraDispelHandler const& right) = delete; - AuraDispelHandler& operator=(AuraDispelHandler&& right) noexcept; - virtual ~AuraDispelHandler(); - void Call(AuraScript* auraScript, DispelInfo* dispelInfo); - private: - AuraDispelFnType pHandlerScript; - }; - class TC_GAME_API EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook - { - public: - EffectBase(uint8 _effIndex, uint16 _effName); - EffectBase(EffectBase const& right) = delete; - EffectBase(EffectBase&& right) noexcept; - EffectBase& operator=(EffectBase const& right) = delete; - EffectBase& operator=(EffectBase&& right) noexcept; - virtual ~EffectBase(); - std::string ToString() const; - bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override; - }; - class TC_GAME_API EffectPeriodicHandler : public EffectBase + template<typename ScriptFunc> + static CheckAreaTargetHandler Create(ScriptFunc handler) { - public: - EffectPeriodicHandler(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); - EffectPeriodicHandler(EffectPeriodicHandler const& right) = delete; - EffectPeriodicHandler(EffectPeriodicHandler&& right) noexcept; - EffectPeriodicHandler& operator=(EffectPeriodicHandler const& right) = delete; - EffectPeriodicHandler& operator=(EffectPeriodicHandler&& right) noexcept; - virtual ~EffectPeriodicHandler(); - void Call(AuraScript* auraScript, AuraEffect const* _aurEff); - private: - AuraEffectPeriodicFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectUpdatePeriodicHandler : public EffectBase - { - public: - EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); - EffectUpdatePeriodicHandler(EffectUpdatePeriodicHandler const& right) = delete; - EffectUpdatePeriodicHandler(EffectUpdatePeriodicHandler&& right) noexcept; - EffectUpdatePeriodicHandler& operator=(EffectUpdatePeriodicHandler const& right) = delete; - EffectUpdatePeriodicHandler& operator=(EffectUpdatePeriodicHandler&& right) noexcept; - virtual ~EffectUpdatePeriodicHandler(); - void Call(AuraScript* auraScript, AuraEffect* aurEff); - private: - AuraEffectUpdatePeriodicFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectCalcAmountHandler : public EffectBase - { - public: - EffectCalcAmountHandler(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); - EffectCalcAmountHandler(EffectCalcAmountHandler const& right) = delete; - EffectCalcAmountHandler(EffectCalcAmountHandler&& right) noexcept; - EffectCalcAmountHandler& operator=(EffectCalcAmountHandler const& right) = delete; - EffectCalcAmountHandler& operator=(EffectCalcAmountHandler&& right) noexcept; - virtual ~EffectCalcAmountHandler(); - void Call(AuraScript* auraScript, AuraEffect const* aurEff, int32 & amount, bool & canBeRecalculated); - private: - AuraEffectCalcAmountFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectCalcPeriodicHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraCheckAreaTargetFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraCheckAreaTargetFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, Unit*> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, Unit*>, bool>, + "CheckAreaTargetHandler signature must be \"bool CheckTarget(Unit* target)\""); + + return { reinterpret_cast<AuraCheckAreaTargetFnType>(handler) }; + } + + CheckAreaTargetHandler(AuraCheckAreaTargetFnType callImpl); + CheckAreaTargetHandler(CheckAreaTargetHandler const& right) = delete; + CheckAreaTargetHandler(CheckAreaTargetHandler&& right) noexcept; + CheckAreaTargetHandler& operator=(CheckAreaTargetHandler const& right) = delete; + CheckAreaTargetHandler& operator=(CheckAreaTargetHandler&& right) noexcept; + ~CheckAreaTargetHandler(); + bool Call(AuraScript* auraScript, Unit* target) const; + private: + AuraCheckAreaTargetFnType _callImpl; + }; + + class TC_GAME_API AuraDispelHandler + { + public: + using AuraDispelFnType = void(AuraScript::*)(DispelInfo* dispelInfo); + + template<typename ScriptFunc> + static AuraDispelHandler Create(ScriptFunc handler) { - public: - EffectCalcPeriodicHandler(AuraEffectCalcPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); - EffectCalcPeriodicHandler(EffectCalcPeriodicHandler const& right) = delete; - EffectCalcPeriodicHandler(EffectCalcPeriodicHandler&& right) noexcept; - EffectCalcPeriodicHandler& operator=(EffectCalcPeriodicHandler const& right) = delete; - EffectCalcPeriodicHandler& operator=(EffectCalcPeriodicHandler&& right) noexcept; - virtual ~EffectCalcPeriodicHandler(); - void Call(AuraScript* auraScript, AuraEffect const* aurEff, bool & isPeriodic, int32 & periodicTimer); - private: - AuraEffectCalcPeriodicFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectCalcSpellModHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraDispelFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraDispelFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, DispelInfo*> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, DispelInfo*>, void>, + "AuraDispelHandler signature must be \"void HandleDispel(DispelInfo* dispelInfo)\""); + + return { reinterpret_cast<AuraDispelFnType>(handler) }; + } + + AuraDispelHandler(AuraDispelFnType callImpl); + AuraDispelHandler(AuraDispelHandler const& right) = delete; + AuraDispelHandler(AuraDispelHandler&& right) noexcept; + AuraDispelHandler& operator=(AuraDispelHandler const& right) = delete; + AuraDispelHandler& operator=(AuraDispelHandler&& right) noexcept; + ~AuraDispelHandler(); + void Call(AuraScript* auraScript, DispelInfo* dispelInfo) const; + private: + AuraDispelFnType _callImpl; + }; + + class TC_GAME_API EffectBase : public EffectHook + { + public: + EffectBase(uint8 effIndex, uint16 auraType); + EffectBase(EffectBase const& right) = delete; + EffectBase(EffectBase&& right) noexcept; + EffectBase& operator=(EffectBase const& right) = delete; + EffectBase& operator=(EffectBase&& right) noexcept; + virtual ~EffectBase(); + std::string ToString() const; + bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override; + private: + uint16 _auraType; + }; + + class TC_GAME_API EffectPeriodicHandler : public EffectBase + { + public: + using AuraEffectPeriodicFnType = void(AuraScript::*)(AuraEffect const* aurEff); + + template<typename ScriptFunc> + static EffectPeriodicHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - EffectCalcSpellModHandler(AuraEffectCalcSpellModFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); - EffectCalcSpellModHandler(EffectCalcSpellModHandler const& right) = delete; - EffectCalcSpellModHandler(EffectCalcSpellModHandler&& right) noexcept; - EffectCalcSpellModHandler& operator=(EffectCalcSpellModHandler const& right) = delete; - EffectCalcSpellModHandler& operator=(EffectCalcSpellModHandler&& right) noexcept; - virtual ~EffectCalcSpellModHandler(); - void Call(AuraScript* auraScript, AuraEffect const* aurEff, SpellModifier* & spellMod); - private: - AuraEffectCalcSpellModFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectCalcCritChanceHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectPeriodicFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectPeriodicFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*>, void>, + "EffectPeriodicHandler signature must be \"void HandlePeriodic(AuraEffect const* aurEff)\""); + + return { reinterpret_cast<AuraEffectPeriodicFnType>(handler), effIndex, auraType }; + } + + EffectPeriodicHandler(AuraEffectPeriodicFnType callImpl, uint8 effIndex, uint16 auraType); + EffectPeriodicHandler(EffectPeriodicHandler const& right) = delete; + EffectPeriodicHandler(EffectPeriodicHandler&& right) noexcept; + EffectPeriodicHandler& operator=(EffectPeriodicHandler const& right) = delete; + EffectPeriodicHandler& operator=(EffectPeriodicHandler&& right) noexcept; + ~EffectPeriodicHandler(); + void Call(AuraScript* auraScript, AuraEffect const* aurEff) const; + private: + AuraEffectPeriodicFnType _callImpl; + }; + + class TC_GAME_API EffectUpdatePeriodicHandler : public EffectBase + { + public: + using AuraEffectUpdatePeriodicFnType = void(AuraScript::*)(AuraEffect* aurEff); + + template<typename ScriptFunc> + static EffectUpdatePeriodicHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - EffectCalcCritChanceHandler(AuraEffectCalcCritChanceFnType effectHandlerScript, uint8 effIndex, uint16 effName); - EffectCalcCritChanceHandler(EffectCalcCritChanceHandler const& right) = delete; - EffectCalcCritChanceHandler(EffectCalcCritChanceHandler&& right) noexcept; - EffectCalcCritChanceHandler& operator=(EffectCalcCritChanceHandler const& right) = delete; - EffectCalcCritChanceHandler& operator=(EffectCalcCritChanceHandler&& right) noexcept; - virtual ~EffectCalcCritChanceHandler(); - void Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit const* victim, float& critChance) const; - private: - AuraEffectCalcCritChanceFnType _effectHandlerScript; - }; - class TC_GAME_API EffectApplyHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectUpdatePeriodicFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectUpdatePeriodicFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect*> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect*>, void>, + "EffectUpdatePeriodicHandler signature must be \"void HandleUpdatePeriodic(AuraEffect* aurEff)\""); + + return { reinterpret_cast<AuraEffectUpdatePeriodicFnType>(handler), effIndex, auraType }; + } + + EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType callImpl, uint8 effIndex, uint16 auraType); + EffectUpdatePeriodicHandler(EffectUpdatePeriodicHandler const& right) = delete; + EffectUpdatePeriodicHandler(EffectUpdatePeriodicHandler&& right) noexcept; + EffectUpdatePeriodicHandler& operator=(EffectUpdatePeriodicHandler const& right) = delete; + EffectUpdatePeriodicHandler& operator=(EffectUpdatePeriodicHandler&& right) noexcept; + ~EffectUpdatePeriodicHandler(); + void Call(AuraScript* auraScript, AuraEffect* aurEff) const; + private: + AuraEffectUpdatePeriodicFnType _callImpl; + }; + + class TC_GAME_API EffectCalcAmountHandler : public EffectBase + { + public: + using AuraEffectCalcAmountFnType = void(AuraScript::*)(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated); + + template<typename ScriptFunc> + static EffectCalcAmountHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - EffectApplyHandler(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode); - EffectApplyHandler(EffectApplyHandler const& right) = delete; - EffectApplyHandler(EffectApplyHandler&& right) noexcept; - EffectApplyHandler& operator=(EffectApplyHandler const& right) = delete; - EffectApplyHandler& operator=(EffectApplyHandler&& right) noexcept; - virtual ~EffectApplyHandler(); - void Call(AuraScript* auraScript, AuraEffect const* _aurEff, AuraEffectHandleModes _mode); - private: - AuraEffectApplicationModeFnType pEffectHandlerScript; - AuraEffectHandleModes mode; - }; - class TC_GAME_API EffectAbsorbHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectCalcAmountFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectCalcAmountFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*, int32&, bool&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*, int32&, bool&>, void>, + "EffectCalcAmountHandler signature must be \"void CalcAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated)\""); + + return { reinterpret_cast<AuraEffectCalcAmountFnType>(handler), effIndex, auraType }; + } + + EffectCalcAmountHandler(AuraEffectCalcAmountFnType callImpl, uint8 effIndex, uint16 auraType); + EffectCalcAmountHandler(EffectCalcAmountHandler const& right) = delete; + EffectCalcAmountHandler(EffectCalcAmountHandler&& right) noexcept; + EffectCalcAmountHandler& operator=(EffectCalcAmountHandler const& right) = delete; + EffectCalcAmountHandler& operator=(EffectCalcAmountHandler&& right) noexcept; + ~EffectCalcAmountHandler(); + void Call(AuraScript* auraScript, AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) const; + private: + AuraEffectCalcAmountFnType _callImpl; + }; + + class TC_GAME_API EffectCalcPeriodicHandler : public EffectBase + { + public: + using AuraEffectCalcPeriodicFnType = void(AuraScript::*)(AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer); + + template<typename ScriptFunc> + static EffectCalcPeriodicHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex, bool overKill); - EffectAbsorbHandler(EffectAbsorbHandler const& right) = delete; - EffectAbsorbHandler(EffectAbsorbHandler&& right) noexcept; - EffectAbsorbHandler& operator=(EffectAbsorbHandler const& right) = delete; - EffectAbsorbHandler& operator=(EffectAbsorbHandler&& right) noexcept; - virtual ~EffectAbsorbHandler(); - void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount); - private: - AuraEffectAbsorbFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectAbsorbHealHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectCalcPeriodicFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectCalcPeriodicFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*, bool&, int32&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*, bool&, int32&>, void>, + "EffectCalcPeriodicHandler signature must be \"void CalcPeriodic(AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer)\""); + + return { reinterpret_cast<AuraEffectCalcPeriodicFnType>(handler), effIndex, auraType }; + } + + EffectCalcPeriodicHandler(AuraEffectCalcPeriodicFnType callImpl, uint8 effIndex, uint16 auraType); + EffectCalcPeriodicHandler(EffectCalcPeriodicHandler const& right) = delete; + EffectCalcPeriodicHandler(EffectCalcPeriodicHandler&& right) noexcept; + EffectCalcPeriodicHandler& operator=(EffectCalcPeriodicHandler const& right) = delete; + EffectCalcPeriodicHandler& operator=(EffectCalcPeriodicHandler&& right) noexcept; + ~EffectCalcPeriodicHandler(); + void Call(AuraScript* auraScript, AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer) const; + private: + AuraEffectCalcPeriodicFnType _callImpl; + }; + + class TC_GAME_API EffectCalcSpellModHandler : public EffectBase + { + public: + using AuraEffectCalcSpellModFnType = void(AuraScript::*)(AuraEffect const* aurEff, SpellModifier*& spellMod); + + template<typename ScriptFunc> + static EffectCalcSpellModHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - 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 + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectCalcSpellModFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectCalcSpellModFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*, SpellModifier*&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*, SpellModifier*&>, void>, + "EffectCalcSpellModHandler signature must be \"void CalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod)\""); + + return { reinterpret_cast<AuraEffectCalcSpellModFnType>(handler), effIndex, auraType }; + } + + EffectCalcSpellModHandler(AuraEffectCalcSpellModFnType callImpl, uint8 effIndex, uint16 auraType); + EffectCalcSpellModHandler(EffectCalcSpellModHandler const& right) = delete; + EffectCalcSpellModHandler(EffectCalcSpellModHandler&& right) noexcept; + EffectCalcSpellModHandler& operator=(EffectCalcSpellModHandler const& right) = delete; + EffectCalcSpellModHandler& operator=(EffectCalcSpellModHandler&& right) noexcept; + ~EffectCalcSpellModHandler(); + void Call(AuraScript* auraScript, AuraEffect const* aurEff, SpellModifier*& spellMod) const; + private: + AuraEffectCalcSpellModFnType _callImpl; + }; + + class TC_GAME_API EffectCalcCritChanceHandler : public EffectBase + { + public: + using AuraEffectCalcCritChanceFnType = void(AuraScript::*)(AuraEffect const* aurEff, Unit const* victim, float& critChance); + + template<typename ScriptFunc> + static EffectCalcCritChanceHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - EffectManaShieldHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex); - EffectManaShieldHandler(EffectManaShieldHandler const& right) = delete; - EffectManaShieldHandler(EffectManaShieldHandler&& right) noexcept; - EffectManaShieldHandler& operator=(EffectManaShieldHandler const& right) = delete; - EffectManaShieldHandler& operator=(EffectManaShieldHandler&& right) noexcept; - virtual ~EffectManaShieldHandler(); - void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount); - private: - AuraEffectAbsorbFnType pEffectHandlerScript; - }; - class TC_GAME_API EffectSplitHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectCalcCritChanceFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectCalcCritChanceFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*, Unit const*, float&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*, Unit const*, float&>, void>, + "EffectCalcSpellModHandler signature must be \"void CalcCritChance(AuraEffect const* aurEff, Unit const* victim, float& critChance)\""); + + return { reinterpret_cast<AuraEffectCalcCritChanceFnType>(handler), effIndex, auraType }; + } + + EffectCalcCritChanceHandler(AuraEffectCalcCritChanceFnType callImpl, uint8 effIndex, uint16 auraType); + EffectCalcCritChanceHandler(EffectCalcCritChanceHandler const& right) = delete; + EffectCalcCritChanceHandler(EffectCalcCritChanceHandler&& right) noexcept; + EffectCalcCritChanceHandler& operator=(EffectCalcCritChanceHandler const& right) = delete; + EffectCalcCritChanceHandler& operator=(EffectCalcCritChanceHandler&& right) noexcept; + ~EffectCalcCritChanceHandler(); + void Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit const* victim, float& critChance) const; + private: + AuraEffectCalcCritChanceFnType _callImpl; + }; + + class TC_GAME_API EffectApplyHandler : public EffectBase + { + public: + using AuraEffectApplicationModeFnType = void(AuraScript::*)(AuraEffect const* aurEff, AuraEffectHandleModes mode); + + template<typename ScriptFunc> + static EffectApplyHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType, AuraEffectHandleModes mode) { - public: - EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex); - EffectSplitHandler(EffectSplitHandler const& right) = delete; - EffectSplitHandler(EffectSplitHandler&& right) noexcept; - EffectSplitHandler& operator=(EffectSplitHandler const& right) = delete; - EffectSplitHandler& operator=(EffectSplitHandler&& right) noexcept; - virtual ~EffectSplitHandler(); - void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & splitAmount); - private: - AuraEffectSplitFnType pEffectHandlerScript; - }; - class TC_GAME_API CheckProcHandler + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectApplicationModeFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectApplicationModeFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*, AuraEffectHandleModes> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*, AuraEffectHandleModes>, void>, + "EffectApplyHandler signature must be \"void HandleApplyOrRemove(AuraEffect const* aurEff, AuraEffectHandleModes mode)\""); + + return { reinterpret_cast<AuraEffectApplicationModeFnType>(handler), effIndex, auraType, mode }; + } + + EffectApplyHandler(AuraEffectApplicationModeFnType callImpl, uint8 effIndex, uint16 auraType, AuraEffectHandleModes mode); + EffectApplyHandler(EffectApplyHandler const& right) = delete; + EffectApplyHandler(EffectApplyHandler&& right) noexcept; + EffectApplyHandler& operator=(EffectApplyHandler const& right) = delete; + EffectApplyHandler& operator=(EffectApplyHandler&& right) noexcept; + ~EffectApplyHandler(); + AuraEffectHandleModes GetMode() const { return _mode; } + void Call(AuraScript* auraScript, AuraEffect const* aurEff, AuraEffectHandleModes mode) const; + private: + AuraEffectApplicationModeFnType _callImpl; + AuraEffectHandleModes _mode; + }; + + class TC_GAME_API EffectAbsorbHandler : public EffectBase + { + public: + using AuraEffectAbsorbFnType = void(AuraScript::*)(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); + + template<typename ScriptFunc> + static EffectAbsorbHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - CheckProcHandler(AuraCheckProcFnType handlerScript); - CheckProcHandler(CheckProcHandler const& right) = delete; - CheckProcHandler(CheckProcHandler&& right) noexcept; - CheckProcHandler& operator=(CheckProcHandler const& right) = delete; - CheckProcHandler& operator=(CheckProcHandler&& right) noexcept; - virtual ~CheckProcHandler(); - bool Call(AuraScript* auraScript, ProcEventInfo& eventInfo); - private: - AuraCheckProcFnType _HandlerScript; - }; - class TC_GAME_API CheckEffectProcHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectAbsorbFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectAbsorbFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect*, DamageInfo&, uint32&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect*, DamageInfo&, uint32&>, void>, + "EffectAbsorbHandler signature must be \"void HandleAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)\""); + + return { reinterpret_cast<AuraEffectAbsorbFnType>(handler), effIndex, auraType }; + } + + EffectAbsorbHandler(AuraEffectAbsorbFnType callImpl, uint8 effIndex, uint16 auraType); + EffectAbsorbHandler(EffectAbsorbHandler const& right) = delete; + EffectAbsorbHandler(EffectAbsorbHandler&& right) noexcept; + EffectAbsorbHandler& operator=(EffectAbsorbHandler const& right) = delete; + EffectAbsorbHandler& operator=(EffectAbsorbHandler&& right) noexcept; + ~EffectAbsorbHandler(); + void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) const; + private: + AuraEffectAbsorbFnType _callImpl; + }; + + class TC_GAME_API EffectAbsorbHealHandler : public EffectBase + { + public: + using AuraEffectAbsorbHealFnType = void(AuraScript::*)(AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount); + + template<typename ScriptFunc> + static EffectAbsorbHealHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - CheckEffectProcHandler(AuraCheckEffectProcFnType handlerScript, uint8 effIndex, uint16 effName); - CheckEffectProcHandler(CheckEffectProcHandler const& right) = delete; - CheckEffectProcHandler(CheckEffectProcHandler&& right) noexcept; - CheckEffectProcHandler& operator=(CheckEffectProcHandler const& right) = delete; - CheckEffectProcHandler& operator=(CheckEffectProcHandler&& right) noexcept; - virtual ~CheckEffectProcHandler(); - bool Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo); - private: - AuraCheckEffectProcFnType _HandlerScript; - }; - class TC_GAME_API AuraProcHandler + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectAbsorbHealFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectAbsorbHealFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect*, HealInfo&, uint32&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect*, HealInfo&, uint32&>, void>, + "EffectAbsorbHealHandler signature must be \"void HandleAbsorb(AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount)\""); + + return { reinterpret_cast<AuraEffectAbsorbHealFnType>(handler), effIndex, auraType }; + } + + EffectAbsorbHealHandler(AuraEffectAbsorbHealFnType callImpl, uint8 effIndex, uint16 auraType); + EffectAbsorbHealHandler(EffectAbsorbHealHandler const& right) = delete; + EffectAbsorbHealHandler(EffectAbsorbHealHandler&& right) noexcept; + EffectAbsorbHealHandler& operator=(EffectAbsorbHealHandler const& right) = delete; + EffectAbsorbHealHandler& operator=(EffectAbsorbHealHandler&& right) noexcept; + ~EffectAbsorbHealHandler(); + void Call(AuraScript* auraScript, AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount) const; + private: + AuraEffectAbsorbHealFnType _callImpl; + }; + + class TC_GAME_API CheckProcHandler + { + public: + using AuraCheckProcFnType = bool(AuraScript::*)(ProcEventInfo& eventInfo); + + template<typename ScriptFunc> + static CheckProcHandler Create(ScriptFunc handler) { - public: - AuraProcHandler(AuraProcFnType handlerScript); - AuraProcHandler(AuraProcHandler const& right) = delete; - AuraProcHandler(AuraProcHandler&& right) noexcept; - AuraProcHandler& operator=(AuraProcHandler const& right) = delete; - AuraProcHandler& operator=(AuraProcHandler&& right) noexcept; - virtual ~AuraProcHandler(); - void Call(AuraScript* auraScript, ProcEventInfo& eventInfo); - private: - AuraProcFnType _HandlerScript; - }; - class TC_GAME_API EffectProcHandler : public EffectBase + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraCheckProcFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraCheckProcFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, ProcEventInfo&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, ProcEventInfo&>, bool>, + "CheckProcHandler signature must be \"bool CheckProc(ProcEventInfo& eventInfo)\""); + + return { reinterpret_cast<AuraCheckProcFnType>(handler) }; + } + + CheckProcHandler(AuraCheckProcFnType callImpl); + CheckProcHandler(CheckProcHandler const& right) = delete; + CheckProcHandler(CheckProcHandler&& right) noexcept; + CheckProcHandler& operator=(CheckProcHandler const& right) = delete; + CheckProcHandler& operator=(CheckProcHandler&& right) noexcept; + ~CheckProcHandler(); + bool Call(AuraScript* auraScript, ProcEventInfo& eventInfo) const; + private: + AuraCheckProcFnType _callImpl; + }; + + class TC_GAME_API CheckEffectProcHandler : public EffectBase + { + public: + using AuraCheckEffectProcFnType = bool(AuraScript::*)(AuraEffect const* aurEff, ProcEventInfo& eventInfo); + + template<typename ScriptFunc> + static CheckEffectProcHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) { - public: - EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName); - EffectProcHandler(EffectProcHandler const& right) = delete; - EffectProcHandler(EffectProcHandler&& right) noexcept; - EffectProcHandler& operator=(EffectProcHandler const& right) = delete; - EffectProcHandler& operator=(EffectProcHandler&& right) noexcept; - virtual ~EffectProcHandler(); - void Call(AuraScript* auraScript, AuraEffect* aurEff, ProcEventInfo& eventInfo); - private: - AuraEffectProcFnType _EffectHandlerScript; - }; - class TC_GAME_API EnterLeaveCombatHandler + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraCheckEffectProcFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraCheckEffectProcFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect const*, ProcEventInfo&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect const*, ProcEventInfo&>, bool>, + "CheckEffectProcHandler signature must be \"bool CheckProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)\""); + + return { reinterpret_cast<AuraCheckEffectProcFnType>(handler), effIndex, auraType }; + } + + CheckEffectProcHandler(AuraCheckEffectProcFnType callImpl, uint8 effIndex, uint16 auraType); + CheckEffectProcHandler(CheckEffectProcHandler const& right) = delete; + CheckEffectProcHandler(CheckEffectProcHandler&& right) noexcept; + CheckEffectProcHandler& operator=(CheckEffectProcHandler const& right) = delete; + CheckEffectProcHandler& operator=(CheckEffectProcHandler&& right) noexcept; + ~CheckEffectProcHandler(); + bool Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo) const; + private: + AuraCheckEffectProcFnType _callImpl; + }; + + class TC_GAME_API AuraProcHandler + { + public: + using AuraProcFnType = void(AuraScript::*)(ProcEventInfo&); + + template<typename ScriptFunc> + static AuraProcHandler Create(ScriptFunc handler) { - public: - EnterLeaveCombatHandler(AuraEnterLeaveCombatFnType handlerScript); - EnterLeaveCombatHandler(EnterLeaveCombatHandler const& right) = delete; - EnterLeaveCombatHandler(EnterLeaveCombatHandler&& right) noexcept; - EnterLeaveCombatHandler& operator=(EnterLeaveCombatHandler const& right) = delete; - EnterLeaveCombatHandler& operator=(EnterLeaveCombatHandler&& right) noexcept; - virtual ~EnterLeaveCombatHandler(); - void Call(AuraScript* auraScript, bool isNowInCombat) const; - private: - AuraEnterLeaveCombatFnType _handlerScript; - }; - - #define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ - class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: explicit CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) { } }; \ - class AuraDispelFunction : public AuraScript::AuraDispelHandler { public: explicit AuraDispelFunction(AuraDispelFnType _pHandlerScript) : AuraScript::AuraDispelHandler((AuraScript::AuraDispelFnType)_pHandlerScript) { } }; \ - class EffectPeriodicHandlerFunction : public AuraScript::EffectPeriodicHandler { public: explicit EffectPeriodicHandlerFunction(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectPeriodicHandler((AuraScript::AuraEffectPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ - class EffectUpdatePeriodicHandlerFunction : public AuraScript::EffectUpdatePeriodicHandler { public: explicit EffectUpdatePeriodicHandlerFunction(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectUpdatePeriodicHandler((AuraScript::AuraEffectUpdatePeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ - class EffectCalcAmountHandlerFunction : public AuraScript::EffectCalcAmountHandler { public: explicit EffectCalcAmountHandlerFunction(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcAmountHandler((AuraScript::AuraEffectCalcAmountFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ - class EffectCalcPeriodicHandlerFunction : public AuraScript::EffectCalcPeriodicHandler { public: explicit EffectCalcPeriodicHandlerFunction(AuraEffectCalcPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcPeriodicHandler((AuraScript::AuraEffectCalcPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ - class EffectCalcSpellModHandlerFunction : public AuraScript::EffectCalcSpellModHandler { public: explicit EffectCalcSpellModHandlerFunction(AuraEffectCalcSpellModFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcSpellModHandler((AuraScript::AuraEffectCalcSpellModFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ - 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) { } }; \ - class CheckEffectProcHandlerFunction : public AuraScript::CheckEffectProcHandler { public: explicit CheckEffectProcHandlerFunction(AuraCheckEffectProcFnType handlerScript, uint8 effIndex, uint16 effName) : AuraScript::CheckEffectProcHandler((AuraScript::AuraCheckEffectProcFnType)handlerScript, effIndex, effName) { } }; \ - class AuraProcHandlerFunction : public AuraScript::AuraProcHandler { public: explicit AuraProcHandlerFunction(AuraProcFnType handlerScript) : AuraScript::AuraProcHandler((AuraScript::AuraProcFnType)handlerScript) { } }; \ - class EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: explicit EffectProcHandlerFunction(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)effectHandlerScript, effIndex, effName) { } }; \ - class EnterLeaveCombatFunction : public AuraScript::EnterLeaveCombatHandler { public: explicit EnterLeaveCombatFunction(AuraEnterLeaveCombatFnType handlerScript) : AuraScript::EnterLeaveCombatHandler((AuraScript::AuraEnterLeaveCombatFnType)handlerScript) { } } - - #define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraProcFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraProcFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, ProcEventInfo&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, ProcEventInfo&>, void>, + "AuraProcHandler signature must be \"void HandleProc(ProcEventInfo& eventInfo)\""); + + return { reinterpret_cast<AuraProcFnType>(handler) }; + } + AuraProcHandler(AuraProcFnType callImpl); + AuraProcHandler(AuraProcHandler const& right) = delete; + AuraProcHandler(AuraProcHandler&& right) noexcept; + AuraProcHandler& operator=(AuraProcHandler const& right) = delete; + AuraProcHandler& operator=(AuraProcHandler&& right) noexcept; + virtual ~AuraProcHandler(); + void Call(AuraScript* auraScript, ProcEventInfo& eventInfo) const; + private: + AuraProcFnType _callImpl; + }; + + class TC_GAME_API EffectProcHandler : public EffectBase + { public: - AuraScript(); - ~AuraScript(); - bool _Validate(SpellInfo const* entry) override; - bool _Load(Aura* aura); - void _PrepareScriptCall(AuraScriptHookType hookType, AuraApplication const* aurApp = nullptr); - void _FinishScriptCall(); - bool _IsDefaultActionPrevented() const; + using AuraEffectProcFnType = void(AuraScript::*)(AuraEffect*, ProcEventInfo&); + + template<typename ScriptFunc> + static EffectProcHandler Create(ScriptFunc handler, uint8 effIndex, uint16 auraType) + { + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEffectProcFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEffectProcFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, AuraEffect*, ProcEventInfo&> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, AuraEffect*, ProcEventInfo&>, void>, + "EffectProcHandler signature must be \"void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)\""); + + return { reinterpret_cast<AuraEffectProcFnType>(handler), effIndex, auraType }; + } + + EffectProcHandler(AuraEffectProcFnType callImpl, uint8 effIndex, uint16 auraType); + EffectProcHandler(EffectProcHandler const& right) = delete; + EffectProcHandler(EffectProcHandler&& right) noexcept; + EffectProcHandler& operator=(EffectProcHandler const& right) = delete; + EffectProcHandler& operator=(EffectProcHandler&& right) noexcept; + ~EffectProcHandler(); + void Call(AuraScript* auraScript, AuraEffect* aurEff, ProcEventInfo& eventInfo) const; private: - Aura* m_aura; - AuraApplication const* m_auraApplication; - bool m_defaultActionPrevented; + AuraEffectProcFnType _callImpl; + }; + + class TC_GAME_API EnterLeaveCombatHandler + { + public: + using AuraEnterLeaveCombatFnType = void(AuraScript::*)(bool); - class TC_GAME_API ScriptStateStore + template<typename ScriptFunc> + static EnterLeaveCombatHandler Create(ScriptFunc handler) { - public: - AuraApplication const* _auraApplication; - uint8 _currentScriptState; - bool _defaultActionPrevented; - ScriptStateStore(uint8 currentScriptState, AuraApplication const* auraApplication, bool defaultActionPrevented) - : _auraApplication(auraApplication), _currentScriptState(currentScriptState), _defaultActionPrevented(defaultActionPrevented) - { } - }; - typedef std::stack<ScriptStateStore> ScriptStateStack; - ScriptStateStack m_scriptStates; + using ScriptClass = GetScriptClass_t<ScriptFunc>; + + static_assert(sizeof(AuraEnterLeaveCombatFnType) >= sizeof(ScriptFunc)); + static_assert(alignof(AuraEnterLeaveCombatFnType) >= alignof(ScriptFunc)); + static_assert(std::is_invocable_v<ScriptFunc, ScriptClass, bool> + && std::is_same_v<std::invoke_result_t<ScriptFunc, ScriptClass, bool>, void>, + "EnterLeaveCombatHandler signature must be \"void HandleEnterLeaveCombat(bool isNowInCombat)\""); + return { reinterpret_cast<AuraEnterLeaveCombatFnType>(handler) }; + } + + EnterLeaveCombatHandler(AuraEnterLeaveCombatFnType callImpl); + EnterLeaveCombatHandler(EnterLeaveCombatHandler const& right) = delete; + EnterLeaveCombatHandler(EnterLeaveCombatHandler&& right) noexcept; + EnterLeaveCombatHandler& operator=(EnterLeaveCombatHandler const& right) = delete; + EnterLeaveCombatHandler& operator=(EnterLeaveCombatHandler&& right) noexcept; + ~EnterLeaveCombatHandler(); + void Call(AuraScript* auraScript, bool isNowInCombat) const; + private: + AuraEnterLeaveCombatFnType _callImpl; + }; + + // left for custom compatibility only, DO NOT USE + #define PrepareAuraScript(CLASSNAME) using silence_semicolon_warning_2 = void + +public: + AuraScript(); + ~AuraScript(); + bool _Validate(SpellInfo const* entry) override; + bool _Load(Aura* aura); + void _PrepareScriptCall(AuraScriptHookType hookType, AuraApplication const* aurApp = nullptr); + void _FinishScriptCall(); + bool _IsDefaultActionPrevented() const; +private: + Aura* m_aura; + AuraApplication const* m_auraApplication; + bool m_defaultActionPrevented; + + class TC_GAME_API ScriptStateStore + { public: - // - // AuraScript interface - // hooks to which you can attach your functions - // - // executed when area aura checks if it can be applied on target - // example: OnEffectApply += AuraEffectApplyFn(class::function); - // where function is: bool function (Unit* target); - HookList<CheckAreaTargetHandler> DoCheckAreaTarget; - #define AuraCheckAreaTargetFn(F) CheckAreaTargetFunction(&F) - - // executed when aura is dispelled by a unit - // example: OnDispel += AuraDispelFn(class::function); - // where function is: void function (DispelInfo* dispelInfo); - HookList<AuraDispelHandler> OnDispel; - // executed after aura is dispelled by a unit - // example: AfterDispel += AuraDispelFn(class::function); - // where function is: void function (DispelInfo* dispelInfo); - HookList<AuraDispelHandler> AfterDispel; - #define AuraDispelFn(F) AuraDispelFunction(&F) - - // executed when aura effect is applied with specified mode to target - // should be used when when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe - // example: OnEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); - // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); - HookList<EffectApplyHandler> OnEffectApply; - // executed after aura effect is applied with specified mode to target - // example: AfterEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); - // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); - HookList<EffectApplyHandler> AfterEffectApply; - #define AuraEffectApplyFn(F, I, N, M) EffectApplyHandlerFunction(&F, I, N, M) - - // executed after aura effect is removed with specified mode from target - // should be used when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe - // example: OnEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); - // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); - HookList<EffectApplyHandler> OnEffectRemove; - // executed when aura effect is removed with specified mode from target - // example: AfterEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); - // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); - HookList<EffectApplyHandler> AfterEffectRemove; - #define AuraEffectRemoveFn(F, I, N, M) EffectApplyHandlerFunction(&F, I, N, M) - - // executed when periodic aura effect ticks on target - // example: OnEffectPeriodic += AuraEffectPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect const* aurEff); - HookList<EffectPeriodicHandler> OnEffectPeriodic; - #define AuraEffectPeriodicFn(F, I, N) EffectPeriodicHandlerFunction(&F, I, N) - - // executed when periodic aura effect is updated - // example: OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect* aurEff); - HookList<EffectUpdatePeriodicHandler> OnEffectUpdatePeriodic; - #define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandlerFunction(&F, I, N) - - // executed when aura effect calculates amount - // example: DoEffectCalcAmount += AuraEffectCalcAmounFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect* aurEff, int32& amount, bool& canBeRecalculated); - HookList<EffectCalcAmountHandler> DoEffectCalcAmount; - #define AuraEffectCalcAmountFn(F, I, N) EffectCalcAmountHandlerFunction(&F, I, N) - - // executed when aura effect calculates periodic data - // example: DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude); - HookList<EffectCalcPeriodicHandler> DoEffectCalcPeriodic; - #define AuraEffectCalcPeriodicFn(F, I, N) EffectCalcPeriodicHandlerFunction(&F, I, N) - - // executed when aura effect calculates spellmod - // example: DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect const* aurEff, SpellModifier*& spellMod); - HookList<EffectCalcSpellModHandler> DoEffectCalcSpellMod; - #define AuraEffectCalcSpellModFn(F, I, N) EffectCalcSpellModHandlerFunction(&F, I, N) - - // executed when aura effect calculates crit chance for dots and hots - // example: DoEffectCalcCritChance += AuraEffectCalcCritChanceFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect const* aurEff, Unit* victim, float& critChance); - HookList<EffectCalcCritChanceHandler> DoEffectCalcCritChance; - #define AuraEffectCalcCritChanceFn(F, I, N) EffectCalcCritChanceHandlerFunction(&F, I, N) - - // executed when absorb aura effect is going to reduce damage - // example: OnEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier); - // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); - HookList<EffectAbsorbHandler> OnEffectAbsorb; - #define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I) - #define AuraEffectAbsorbOverkillFn(F, I) EffectAbsorbFunction(&F, I, true) - - // 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 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 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); - HookList<EffectManaShieldHandler> OnEffectManaShield; - #define AuraEffectManaShieldFn(F, I) EffectManaShieldFunction(&F, I) - - // executed after mana shield aura effect reduced damage to target - absorbAmount is real amount absorbed by aura - // example: AfterEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier); - // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); - HookList<EffectManaShieldHandler> AfterEffectManaShield; - - // executed when the caster of some spell with split dmg aura gets damaged through it - // example: OnEffectSplit += AuraEffectSplitFn(class::function, EffectIndexSpecifier); - // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount); - HookList<EffectSplitHandler> OnEffectSplit; - #define AuraEffectSplitFn(F, I) EffectSplitFunction(&F, I) - - // executed when aura checks if it can proc - // example: DoCheckProc += AuraCheckProcFn(class::function); - // where function is: bool function (ProcEventInfo& eventInfo); - HookList<CheckProcHandler> DoCheckProc; - #define AuraCheckProcFn(F) CheckProcHandlerFunction(&F) - - // executed when aura effect checks if it can proc the aura - // example: DoCheckEffectProc += AuraCheckEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is bool function (AuraEffect const* aurEff, ProcEventInfo& eventInfo); - HookList<CheckEffectProcHandler> DoCheckEffectProc; - #define AuraCheckEffectProcFn(F, I, N) CheckEffectProcHandlerFunction(&F, I, N) - - // executed before aura procs (possibility to prevent charge drop/cooldown) - // example: DoPrepareProc += AuraProcFn(class::function); - // where function is: void function (ProcEventInfo& eventInfo); - HookList<AuraProcHandler> DoPrepareProc; - // executed when aura procs - // example: OnProc += AuraProcFn(class::function); - // where function is: void function (ProcEventInfo& eventInfo); - HookList<AuraProcHandler> OnProc; - // executed after aura proced - // example: AfterProc += AuraProcFn(class::function); - // where function is: void function (ProcEventInfo& eventInfo); - HookList<AuraProcHandler> AfterProc; - #define AuraProcFn(F) AuraProcHandlerFunction(&F) - - // executed when aura effect procs - // example: OnEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect* aurEff, ProcEventInfo& procInfo); - HookList<EffectProcHandler> OnEffectProc; - // executed after aura effect proced - // example: AfterEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); - // where function is: void function (AuraEffect* aurEff, ProcEventInfo& procInfo); - HookList<EffectProcHandler> AfterEffectProc; - #define AuraEffectProcFn(F, I, N) EffectProcHandlerFunction(&F, I, N) - - // executed when target enters or leaves combat - // example: OnEnterLeaveCombat += AuraEnterLeaveCombatFn(class::function) - // where function is: void function (bool isNowInCombat); - HookList<EnterLeaveCombatHandler> OnEnterLeaveCombat; - #define AuraEnterLeaveCombatFn(F) EnterLeaveCombatFunction(&F) - - // AuraScript interface - hook/effect execution manipulators - - // prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented) - void PreventDefaultAction(); - - // AuraScript interface - functions which are redirecting to Aura class - - // returns proto of the spell - SpellInfo const* GetSpellInfo() const; - SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; - // returns spellid of the spell - uint32 GetId() const; - - // returns guid of object which cast the aura (m_originalCaster of the Spell class) - ObjectGuid GetCasterGUID() const; - // returns unit which cast the aura or NULL if not avalible (caster logged out for example) - Unit* GetCaster() const; - // returns gameobject which cast the aura or NULL if not available - GameObject* GetGObjCaster() const; - // returns object on which aura was cast, target for non-area auras, area aura source for area auras - WorldObject* GetOwner() const; - // returns owner if it's unit or unit derived object, NULL otherwise (only for persistent area auras NULL is returned) - Unit* GetUnitOwner() const; - // returns owner if it's dynobj, NULL otherwise - DynamicObject* GetDynobjOwner() const; - - // removes aura with remove mode (see AuraRemoveMode enum) - void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - // returns aura object of script - Aura* GetAura() const; - - // returns type of the aura, may be dynobj owned aura or unit owned aura - AuraObjectType GetType() const; - - // aura duration manipulation - when duration goes to 0 aura is removed - int32 GetDuration() const; - void SetDuration(int32 duration, bool withMods = false); - // sets duration to maxduration - void RefreshDuration(); - time_t GetApplyTime() const; - int32 GetMaxDuration() const; - void SetMaxDuration(int32 duration); - int32 CalcMaxDuration() const; - // expired - duration just went to 0 - bool IsExpired() const; - // permament - has infinite duration - bool IsPermanent() const; - - // charges manipulation - 0 - not charged aura - uint8 GetCharges() const; - void SetCharges(uint8 charges); - uint8 CalcMaxCharges() const; - bool ModCharges(int8 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - // returns true if last charge dropped - bool DropCharge(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - - // stack amount manipulation - uint8 GetStackAmount() const; - void SetStackAmount(uint8 num); - bool ModStackAmount(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - - // passive - "working in background", not saved, not removed by immunities, not seen by player - bool IsPassive() const; - // death persistent - not removed on death - bool IsDeathPersistent() const; - - // check if aura has effect of given effindex - bool HasEffect(uint8 effIndex) const; - // returns aura effect of given effect index or NULL - AuraEffect* GetEffect(uint8 effIndex) const; - - // check if aura has effect of given aura type - bool HasEffectType(AuraType type) const; - - // AuraScript interface - functions which are redirecting to AuraApplication class - // Do not call these in hooks in which AuraApplication is not avalible, otherwise result will differ from expected (the functions will return NULL) - - // returns currently processed target of an aura - // Return value does not need to be NULL-checked, the only situation this will (always) - // return NULL is when the call happens in an unsupported hook, in other cases, it is always valid - Unit* GetTarget() const; - // returns AuraApplication object of currently processed target - AuraApplication const* GetTargetApplication() const; - - // returns desired cast difficulty for triggered spells - Difficulty GetCastDifficulty() const; + AuraApplication const* _auraApplication; + uint8 _currentScriptState; + bool _defaultActionPrevented; + ScriptStateStore(uint8 currentScriptState, AuraApplication const* auraApplication, bool defaultActionPrevented) + : _auraApplication(auraApplication), _currentScriptState(currentScriptState), _defaultActionPrevented(defaultActionPrevented) + { } + }; + typedef std::stack<ScriptStateStore> ScriptStateStack; + ScriptStateStack m_scriptStates; + +public: + // + // AuraScript interface + // hooks to which you can attach your functions + // + // executed when area aura checks if it can be applied on target + // example: OnEffectApply += AuraEffectApplyFn(class::function); + // where function is: bool function (Unit* target); + HookList<CheckAreaTargetHandler> DoCheckAreaTarget; + #define AuraCheckAreaTargetFn(F) CheckAreaTargetHandler::Create(&F) + + // executed when aura is dispelled by a unit + // example: OnDispel += AuraDispelFn(class::function); + // where function is: void function (DispelInfo* dispelInfo); + HookList<AuraDispelHandler> OnDispel; + // executed after aura is dispelled by a unit + // example: AfterDispel += AuraDispelFn(class::function); + // where function is: void function (DispelInfo* dispelInfo); + HookList<AuraDispelHandler> AfterDispel; + #define AuraDispelFn(F) AuraDispelHandler::Create(&F) + + // executed when aura effect is applied with specified mode to target + // should be used when when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe + // example: OnEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); + // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); + HookList<EffectApplyHandler> OnEffectApply; + // executed after aura effect is applied with specified mode to target + // example: AfterEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); + // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); + HookList<EffectApplyHandler> AfterEffectApply; + #define AuraEffectApplyFn(F, I, N, M) EffectApplyHandler::Create(&F, I, N, M) + + // executed after aura effect is removed with specified mode from target + // should be used when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe + // example: OnEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); + // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); + HookList<EffectApplyHandler> OnEffectRemove; + // executed when aura effect is removed with specified mode from target + // example: AfterEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes); + // where function is: void function (AuraEffect const* aurEff, AuraEffectHandleModes mode); + HookList<EffectApplyHandler> AfterEffectRemove; + #define AuraEffectRemoveFn(F, I, N, M) EffectApplyHandler::Create(&F, I, N, M) + + // executed when periodic aura effect ticks on target + // example: OnEffectPeriodic += AuraEffectPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect const* aurEff); + HookList<EffectPeriodicHandler> OnEffectPeriodic; + #define AuraEffectPeriodicFn(F, I, N) EffectPeriodicHandler::Create(&F, I, N) + + // executed when periodic aura effect is updated + // example: OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect* aurEff); + HookList<EffectUpdatePeriodicHandler> OnEffectUpdatePeriodic; + #define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandler::Create(&F, I, N) + + // executed when aura effect calculates amount + // example: DoEffectCalcAmount += AuraEffectCalcAmounFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect* aurEff, int32& amount, bool& canBeRecalculated); + HookList<EffectCalcAmountHandler> DoEffectCalcAmount; + #define AuraEffectCalcAmountFn(F, I, N) EffectCalcAmountHandler::Create(&F, I, N) + + // executed when aura effect calculates periodic data + // example: DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude); + HookList<EffectCalcPeriodicHandler> DoEffectCalcPeriodic; + #define AuraEffectCalcPeriodicFn(F, I, N) EffectCalcPeriodicHandler::Create(&F, I, N) + + // executed when aura effect calculates spellmod + // example: DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect const* aurEff, SpellModifier*& spellMod); + HookList<EffectCalcSpellModHandler> DoEffectCalcSpellMod; + #define AuraEffectCalcSpellModFn(F, I, N) EffectCalcSpellModHandler::Create(&F, I, N) + + // executed when aura effect calculates crit chance for dots and hots + // example: DoEffectCalcCritChance += AuraEffectCalcCritChanceFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect const* aurEff, Unit* victim, float& critChance); + HookList<EffectCalcCritChanceHandler> DoEffectCalcCritChance; + #define AuraEffectCalcCritChanceFn(F, I, N) EffectCalcCritChanceHandler::Create(&F, I, N) + + // executed when absorb aura effect is going to reduce damage + // example: OnEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier); + // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); + HookList<EffectAbsorbHandler> OnEffectAbsorb; + #define AuraEffectAbsorbFn(F, I) EffectAbsorbHandler::Create(&F, I, SPELL_AURA_SCHOOL_ABSORB) + #define AuraEffectAbsorbOverkillFn(F, I) EffectAbsorbHandler::Create(&F, I, SPELL_AURA_SCHOOL_ABSORB_OVERKILL) + + // 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 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) EffectAbsorbHealHandler::Create(&F, I, SPELL_AURA_SCHOOL_HEAL_ABSORB) + + // 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); + HookList<EffectAbsorbHandler> OnEffectManaShield; + #define AuraEffectManaShieldFn(F, I) EffectAbsorbHandler::Create(&F, I, SPELL_AURA_MANA_SHIELD) + + // executed after mana shield aura effect reduced damage to target - absorbAmount is real amount absorbed by aura + // example: AfterEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier); + // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount); + HookList<EffectAbsorbHandler> AfterEffectManaShield; + + // executed when the caster of some spell with split dmg aura gets damaged through it + // example: OnEffectSplit += AuraEffectSplitFn(class::function, EffectIndexSpecifier); + // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount); + HookList<EffectAbsorbHandler> OnEffectSplit; + #define AuraEffectSplitFn(F, I) EffectAbsorbHandler::Create(&F, I, SPELL_AURA_SPLIT_DAMAGE_PCT) + + // executed when aura checks if it can proc + // example: DoCheckProc += AuraCheckProcFn(class::function); + // where function is: bool function (ProcEventInfo& eventInfo); + HookList<CheckProcHandler> DoCheckProc; + #define AuraCheckProcFn(F) CheckProcHandler::Create(&F) + + // executed when aura effect checks if it can proc the aura + // example: DoCheckEffectProc += AuraCheckEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is bool function (AuraEffect const* aurEff, ProcEventInfo& eventInfo); + HookList<CheckEffectProcHandler> DoCheckEffectProc; + #define AuraCheckEffectProcFn(F, I, N) CheckEffectProcHandler::Create(&F, I, N) + + // executed before aura procs (possibility to prevent charge drop/cooldown) + // example: DoPrepareProc += AuraProcFn(class::function); + // where function is: void function (ProcEventInfo& eventInfo); + HookList<AuraProcHandler> DoPrepareProc; + // executed when aura procs + // example: OnProc += AuraProcFn(class::function); + // where function is: void function (ProcEventInfo& eventInfo); + HookList<AuraProcHandler> OnProc; + // executed after aura proced + // example: AfterProc += AuraProcFn(class::function); + // where function is: void function (ProcEventInfo& eventInfo); + HookList<AuraProcHandler> AfterProc; + #define AuraProcFn(F) AuraProcHandler::Create(&F) + + // executed when aura effect procs + // example: OnEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect* aurEff, ProcEventInfo& procInfo); + HookList<EffectProcHandler> OnEffectProc; + // executed after aura effect proced + // example: AfterEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier); + // where function is: void function (AuraEffect* aurEff, ProcEventInfo& procInfo); + HookList<EffectProcHandler> AfterEffectProc; + #define AuraEffectProcFn(F, I, N) EffectProcHandler::Create(&F, I, N) + + // executed when target enters or leaves combat + // example: OnEnterLeaveCombat += AuraEnterLeaveCombatFn(class::function) + // where function is: void function (bool isNowInCombat); + HookList<EnterLeaveCombatHandler> OnEnterLeaveCombat; + #define AuraEnterLeaveCombatFn(F) EnterLeaveCombatHandler::Create(&F) + + // AuraScript interface - hook/effect execution manipulators + + // prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented) + void PreventDefaultAction(); + + // AuraScript interface - functions which are redirecting to Aura class + + // returns proto of the spell + SpellInfo const* GetSpellInfo() const; + SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const; + // returns spellid of the spell + uint32 GetId() const; + + // returns guid of object which cast the aura (m_originalCaster of the Spell class) + ObjectGuid GetCasterGUID() const; + // returns unit which cast the aura or NULL if not avalible (caster logged out for example) + Unit* GetCaster() const; + // returns gameobject which cast the aura or NULL if not available + GameObject* GetGObjCaster() const; + // returns object on which aura was cast, target for non-area auras, area aura source for area auras + WorldObject* GetOwner() const; + // returns owner if it's unit or unit derived object, NULL otherwise (only for persistent area auras NULL is returned) + Unit* GetUnitOwner() const; + // returns owner if it's dynobj, NULL otherwise + DynamicObject* GetDynobjOwner() const; + + // removes aura with remove mode (see AuraRemoveMode enum) + void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + // returns aura object of script + Aura* GetAura() const; + + // returns type of the aura, may be dynobj owned aura or unit owned aura + AuraObjectType GetType() const; + + // aura duration manipulation - when duration goes to 0 aura is removed + int32 GetDuration() const; + void SetDuration(int32 duration, bool withMods = false); + // sets duration to maxduration + void RefreshDuration(); + time_t GetApplyTime() const; + int32 GetMaxDuration() const; + void SetMaxDuration(int32 duration); + int32 CalcMaxDuration() const; + // expired - duration just went to 0 + bool IsExpired() const; + // permament - has infinite duration + bool IsPermanent() const; + + // charges manipulation - 0 - not charged aura + uint8 GetCharges() const; + void SetCharges(uint8 charges); + uint8 CalcMaxCharges() const; + bool ModCharges(int8 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + // returns true if last charge dropped + bool DropCharge(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + + // stack amount manipulation + uint8 GetStackAmount() const; + void SetStackAmount(uint8 num); + bool ModStackAmount(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + + // passive - "working in background", not saved, not removed by immunities, not seen by player + bool IsPassive() const; + // death persistent - not removed on death + bool IsDeathPersistent() const; + + // check if aura has effect of given effindex + bool HasEffect(uint8 effIndex) const; + // returns aura effect of given effect index or NULL + AuraEffect* GetEffect(uint8 effIndex) const; + + // check if aura has effect of given aura type + bool HasEffectType(AuraType type) const; + + // AuraScript interface - functions which are redirecting to AuraApplication class + // Do not call these in hooks in which AuraApplication is not avalible, otherwise result will differ from expected (the functions will return NULL) + + // returns currently processed target of an aura + // Return value does not need to be NULL-checked, the only situation this will (always) + // return NULL is when the call happens in an unsupported hook, in other cases, it is always valid + Unit* GetTarget() const; + // returns AuraApplication object of currently processed target + AuraApplication const* GetTargetApplication() const; + + // returns desired cast difficulty for triggered spells + Difficulty GetCastDifficulty() const; }; // @@ -1288,4 +1629,4 @@ class TC_GAME_API AuraScript : public _SpellScript // SPELL_EFFECT_XXX - one of values of enum SpellEffects - effect with equal name matches // -#endif // __SPELL_SCRIPT_H +#endif // TRINITY_SPELL_SCRIPT_H |