aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp2
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp16
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp34
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.h2
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp8
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h12
-rw-r--r--src/server/scripts/Examples/example_spell.cpp26
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);