diff options
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); |