From 89490e4d7f4abff0eb756fcf07fbf21d7ca6381b Mon Sep 17 00:00:00 2001 From: joschiwald Date: Fri, 11 Jan 2013 01:21:44 +0100 Subject: Core/SpellScripts: implement Spell Proc Hooks and use it in old and new proc system Hooks: - DoCheckProc: executed when aura checks if it can proc - DoPrepareProc: executed before aura procs (possibility to prevent charge drop/cooldown) - OnProc: executed when aura procs - OnEffectProc: executed when aura effect procs - AfterEffectProc: executed after aura effect proced - AfterProc: executed after aura proced and charges removed using PreventDefaultAction() in DoPrepareProc will prevent charge drop and cooldown default execution of a proc can prevented in OnEffectProc with PreventDefaultAction() Now we should be able to convert almost all procs from Unit::ProcDamageAndSpellFor to SpellScripts Notes to old proc system: - if a proc has a cooldown we must check it in spellscript and add it when we handle the proc - behavior with charge drops is possible undefined (use PreventDefaultAction() in OnEffectProc to notify that the script is executed) --- src/server/game/Spells/SpellScript.cpp | 67 +++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'src/server/game/Spells/SpellScript.cpp') diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index c29b08242a0..89ed223545f 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -470,7 +470,7 @@ WorldLocation* SpellScript::GetHitDest() { if (!IsInEffectHook()) { - sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitGObj was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); + sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u`: function SpellScript::GetHitDest was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId); return NULL; } return m_spell->destTarget; @@ -679,6 +679,30 @@ bool AuraScript::_Validate(SpellInfo const* entry) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list::iterator itr = DoCheckProc.begin(); itr != DoCheckProc.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + + for (std::list::iterator itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + + for (std::list::iterator itr = OnProc.begin(); itr != OnProc.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + + for (std::list::iterator itr = AfterProc.begin(); itr != AfterProc.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError(LOG_FILTER_TSCR, "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + + for (std::list::iterator itr = OnEffectProc.begin(); itr != OnEffectProc.end(); ++itr) + if (!(*itr).GetAffectedEffectsMask(entry)) + sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + + for (std::list::iterator itr = AfterEffectProc.begin(); itr != AfterEffectProc.end(); ++itr) + if (!(*itr).GetAffectedEffectsMask(entry)) + sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectProc` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + return _SpellScript::_Validate(entry); } @@ -818,6 +842,37 @@ void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* au (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount); } +AuraScript::CheckProcHandler::CheckProcHandler(AuraCheckProcFnType handlerScript) +{ + _HandlerScript = handlerScript; +} + +bool AuraScript::CheckProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo) +{ + return (auraScript->*_HandlerScript)(eventInfo); +} + +AuraScript::AuraProcHandler::AuraProcHandler(AuraProcFnType handlerScript) +{ + _HandlerScript = handlerScript; +} + +void AuraScript::AuraProcHandler::Call(AuraScript* auraScript, ProcEventInfo& eventInfo) +{ + (auraScript->*_HandlerScript)(eventInfo); +} + +AuraScript::EffectProcHandler::EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) + : AuraScript::EffectBase(effIndex, effName) +{ + _EffectHandlerScript = effectHandlerScript; +} + +void AuraScript::EffectProcHandler::Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo) +{ + (auraScript->*_EffectHandlerScript)(aurEff, eventInfo); +} + bool AuraScript::_Load(Aura* aura) { m_aura = aura; @@ -853,6 +908,8 @@ bool AuraScript::_IsDefaultActionPrevented() case AURA_SCRIPT_HOOK_EFFECT_PERIODIC: case AURA_SCRIPT_HOOK_EFFECT_ABSORB: case AURA_SCRIPT_HOOK_EFFECT_SPLIT: + case AURA_SCRIPT_HOOK_PREPARE_PROC: + case AURA_SCRIPT_HOOK_EFFECT_PROC: return m_defaultActionPrevented; default: ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place"); @@ -869,6 +926,8 @@ void AuraScript::PreventDefaultAction() case AURA_SCRIPT_HOOK_EFFECT_PERIODIC: case AURA_SCRIPT_HOOK_EFFECT_ABSORB: case AURA_SCRIPT_HOOK_EFFECT_SPLIT: + case AURA_SCRIPT_HOOK_PREPARE_PROC: + case AURA_SCRIPT_HOOK_EFFECT_PROC: m_defaultActionPrevented = true; break; default: @@ -1051,6 +1110,12 @@ Unit* AuraScript::GetTarget() const case AURA_SCRIPT_HOOK_EFFECT_MANASHIELD: case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD: case AURA_SCRIPT_HOOK_EFFECT_SPLIT: + case AURA_SCRIPT_HOOK_CHECK_PROC: + case AURA_SCRIPT_HOOK_PREPARE_PROC: + case AURA_SCRIPT_HOOK_PROC: + case AURA_SCRIPT_HOOK_AFTER_PROC: + case AURA_SCRIPT_HOOK_EFFECT_PROC: + case AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC: return m_auraApplication->GetTarget(); default: sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId); -- cgit v1.2.3