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.

This commit is contained in:
QAston
2011-05-25 17:13:32 +02:00
parent 6c4d2c8332
commit a1b8fd2054
7 changed files with 89 additions and 11 deletions
+1 -1
View File
@@ -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)
@@ -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)
+30 -4
View File
@@ -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;
@@ -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);
+8
View File
@@ -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());
+11 -1
View File
@@ -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
+21 -5
View File
@@ -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);