diff options
author | QAston <qaston@gmail.com> | 2011-05-25 17:13:32 +0200 |
---|---|---|
committer | QAston <qaston@gmail.com> | 2011-05-25 17:13:32 +0200 |
commit | a1b8fd2054eb705f32dea20fa27ded4624e49f57 (patch) | |
tree | b7be2d4ddfc5cefcaa24fa4163f5e901b58ff19d /src | |
parent | 6c4d2c8332d16bc210d2b75f4b900451eedfc487 (diff) |
Core/AuraScripts: Add AfterEffectRemove and AfterEffectApply hooks, to allow safe triggering of spellcasts or other actions which may call linked events while OnEffectApply and OnEffectRemove are still there for overriding the way effect is handled on target.
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 16 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuras.cpp | 34 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuras.h | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellScript.cpp | 8 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellScript.h | 12 | ||||
-rw-r--r-- | src/server/scripts/Examples/example_spell.cpp | 26 |
7 files changed, 89 insertions, 11 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 84eaaba7531..41312ed19d1 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3578,7 +3578,7 @@ void Unit::RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode) // this kind of call is needed only when aura effect removal handler // or event triggered by it expects to remove // not yet removed effects of an aura - if(aurApp->GetRemoveMode()) + if (aurApp->GetRemoveMode()) { // remove remaining effects of an aura for (uint8 itr = 0 ; itr < MAX_SPELL_EFFECTS; ++itr) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 2e51bb03658..f2441bad080 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -973,10 +973,16 @@ void AuraEffect::HandleEffect(AuraApplication const * aurApp, uint8 mode, bool a || mode == AURA_EFFECT_HANDLE_CHANGE_AMOUNT || mode == AURA_EFFECT_HANDLE_STAT); + // register/unregister effect in lists in case of real AuraEffect apply/remove + // registration/unregistration is done always before real effect handling (some effect handlers code is depending on this) + if (mode & AURA_EFFECT_HANDLE_REAL) + aurApp->GetTarget()->_RegisterAuraEffect(this, apply); + // real aura apply/remove, handle modifier if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) ApplySpellMod(aurApp->GetTarget(), apply); + // call scripts helping/replacing effect handlers bool prevented = false; if (apply) prevented = GetBase()->CallScriptEffectApplyHandlers(const_cast<AuraEffect const *>(this), aurApp, (AuraEffectHandleModes)mode); @@ -988,6 +994,16 @@ void AuraEffect::HandleEffect(AuraApplication const * aurApp, uint8 mode, bool a return; (*this.*AuraEffectHandler [GetAuraType()])(aurApp, mode, apply); + + // check if script events have removed the aura or if default effect prevention was requested + if (apply && aurApp->GetRemoveMode()) + return; + + // call scripts triggering additional events after apply/remove + if (apply) + GetBase()->CallScriptAfterEffectApplyHandlers(const_cast<AuraEffect const *>(this), aurApp, (AuraEffectHandleModes)mode); + else + GetBase()->CallScriptAfterEffectRemoveHandlers(const_cast<AuraEffect const *>(this), aurApp, (AuraEffectHandleModes)mode); } void AuraEffect::HandleEffect(Unit * target, uint8 mode, bool apply) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index f2c87cf3c11..f50452feb80 100755 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -160,16 +160,12 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) { ASSERT(!(m_flags & (1<<effIndex))); m_flags |= 1<<effIndex; - GetTarget()->_RegisterAuraEffect(aurEff, true); aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, true); } else { ASSERT(m_flags & (1<<effIndex)); m_flags &= ~(1<<effIndex); - - // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) - GetTarget()->_RegisterAuraEffect(aurEff, false); aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, false); // Remove all triggered by aura spells vs unlimited duration @@ -1753,6 +1749,36 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplica return preventDefault; } +void Aura::CallScriptAfterEffectApplyHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode) +{ + for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp); + std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->AfterEffectApply.end(), effItr = (*scritr)->AfterEffectApply.begin(); + for(; effItr != effEndItr ; ++effItr) + { + if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex())) + (*effItr).Call(*scritr, aurEff, mode); + } + (*scritr)->_FinishScriptCall(); + } +} + +void Aura::CallScriptAfterEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode) +{ + for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp); + std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->AfterEffectRemove.end(), effItr = (*scritr)->AfterEffectRemove.begin(); + for(; effItr != effEndItr ; ++effItr) + { + if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex())) + (*effItr).Call(*scritr, aurEff, mode); + } + (*scritr)->_FinishScriptCall(); + } +} + bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp) { bool preventDefault = false; diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 29d170b28cd..6c42e94be55 100755 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -171,6 +171,8 @@ class Aura void LoadScripts(); bool CallScriptEffectApplyHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode); bool CallScriptEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode); + void CallScriptAfterEffectApplyHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode); + void CallScriptAfterEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode); bool CallScriptEffectPeriodicHandlers(AuraEffect const * aurEff, AuraApplication const * aurApp); void CallScriptEffectUpdatePeriodicHandlers(AuraEffect * aurEff); void CallScriptEffectCalcAmountHandlers(AuraEffect const * aurEff, int32 & amount, bool & canBeRecalculated); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index b873e4d1669..f1d3989f5f2 100755 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -476,6 +476,14 @@ bool AuraScript::_Validate(SpellEntry const * entry) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list<EffectApplyHandler>::iterator itr = AfterEffectApply.begin(); itr != AfterEffectApply.end(); ++itr) + if (!(*itr).GetAffectedEffectsMask(entry)) + sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + + for (std::list<EffectApplyHandler>::iterator itr = AfterEffectRemove.begin(); itr != AfterEffectRemove.end(); ++itr) + if (!(*itr).GetAffectedEffectsMask(entry)) + sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + for (std::list<EffectPeriodicHandler>::iterator itr = OnEffectPeriodic.begin(); itr != OnEffectPeriodic.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 68b6f987169..ffd462c9507 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -461,15 +461,25 @@ class AuraScript : public _SpellScript // hooks to which you can attach your functions // // 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 when aura effect is removed with specified mode from target + // executed after aura effect is removed with specified mode from 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: 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 diff --git a/src/server/scripts/Examples/example_spell.cpp b/src/server/scripts/Examples/example_spell.cpp index 212ed450ed5..22dc9adea37 100644 --- a/src/server/scripts/Examples/example_spell.cpp +++ b/src/server/scripts/Examples/example_spell.cpp @@ -166,17 +166,31 @@ class spell_ex_66244 : public SpellScriptLoader return false; } - void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + + void HandleOnEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { sLog->outString("Aura Effect is about to be applied on target!"); + // this hook allows you to prevent execution of AuraEffect handler, or to replace it with your own handler + //PreventDefaultAction(); + } + void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + sLog->outString("Aura Effect is about to be removed from target!"); + // this hook allows you to prevent execution of AuraEffect handler, or to replace it with your own handler + //PreventDefaultAction(); + } + + void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + sLog->outString("Aura Effect has just been applied on target!"); Unit* target = GetTarget(); // cast spell on target on aura apply target->CastSpell(target, SPELL_TRIGGERED, true); } - void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + void HandleAfterEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - sLog->outString("Aura Effect is just removed on target!"); + sLog->outString("Aura Effect has just been just removed from target!"); Unit* target = GetTarget(); Unit* caster = GetCaster(); // caster may be not avalible (logged out for example) @@ -243,8 +257,10 @@ class spell_ex_66244 : public SpellScriptLoader // function registering void Register() { - OnEffectApply += AuraEffectApplyFn(spell_ex_66244AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_ex_66244AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectApply += AuraEffectApplyFn(spell_ex_66244AuraScript::HandleOnEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_ex_66244AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectApply += AuraEffectApplyFn(spell_ex_66244AuraScript::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_ex_66244AuraScript::HandleAfterEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); OnEffectPeriodic += AuraEffectPeriodicFn(spell_ex_66244AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_DUMMY); OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_ex_66244AuraScript::HandleEffectPeriodicUpdate, EFFECT_0, SPELL_AURA_DUMMY); DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_ex_66244AuraScript::HandleEffectCalcAmount, EFFECT_0, SPELL_AURA_DUMMY); |