diff options
author | Giuseppe Montesanto <montesanto.giuseppe@live.it> | 2012-02-04 13:32:40 +0100 |
---|---|---|
committer | Giuseppe Montesanto <montesanto.giuseppe@live.it> | 2012-02-04 13:32:40 +0100 |
commit | 271feb587f2ef0940e1af3309bb3c679b8ad76d2 (patch) | |
tree | 340b08fc48b884ce5339075d2d68988d15bc42df /src | |
parent | 894c27af520eb550764d4cacd2b43e87fd100597 (diff) |
Add hook on AuraScript called when an aura is dispelled
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 16 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 21 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuras.cpp | 24 | ||||
-rwxr-xr-x | src/server/game/Spells/Auras/SpellAuras.h | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellEffects.cpp | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellScript.cpp | 18 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellScript.h | 23 |
7 files changed, 100 insertions, 6 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 63aa7771063..63a56516e8b 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3492,17 +3492,25 @@ void Unit::RemoveAuraFromStack(uint32 spellId, uint64 casterGUID, AuraRemoveMode } } -void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved/*= 1*/) +void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved/*= 1*/) { for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);) { Aura* aura = iter->second; if (aura->GetCasterGUID() == casterGUID) { + DispelInfo dispelInfo(dispeller, dispellerSpellId, chargesRemoved); + + // Call OnDispel hook on AuraScript + aura->CallScriptDispel(&dispelInfo); + if (aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES) - aura->ModCharges(-chargesRemoved, AURA_REMOVE_BY_ENEMY_SPELL); + aura->ModCharges(-dispelInfo.GetRemovedCharges(), AURA_REMOVE_BY_ENEMY_SPELL); else - aura->ModStackAmount(-chargesRemoved, AURA_REMOVE_BY_ENEMY_SPELL); + aura->ModStackAmount(-dispelInfo.GetRemovedCharges(), AURA_REMOVE_BY_ENEMY_SPELL); + + // Call AfterDispel hook on AuraScript + aura->CallScriptAfterDispel(&dispelInfo); switch (aura->GetSpellInfo()->SpellFamilyName) { @@ -3532,7 +3540,7 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit { // final heal int32 healAmount = aurEff->GetAmount(); - int32 stack = chargesRemoved; + int32 stack = dispelInfo.GetRemovedCharges(); CastCustomSpell(this, 33778, &healAmount, &stack, NULL, true, NULL, NULL, aura->GetCasterGUID()); // mana diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index b64a2e210bc..1808018d865 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -788,6 +788,25 @@ enum MeleeHitOutcome MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL }; +class DispelInfo +{ +private: + Unit* const m_dispeller; + uint32 const m_dispellerSpellId; + uint8 m_chargesRemoved; +public: + explicit DispelInfo(Unit* _dispeller, uint32 _dispellerSpellId, uint8 _chargesRemoved) : + m_dispeller(_dispeller), m_dispellerSpellId(_dispellerSpellId), m_chargesRemoved(_chargesRemoved) {} + + Unit* GetDispeller() { return m_dispeller; } + uint32 GetDispellerSpellId() { return m_dispellerSpellId; } + uint8 GetRemovedCharges() { return m_chargesRemoved; } + void SetRemovedCharges(uint8 amount) + { + m_chargesRemoved = amount; + } +}; + struct CleanDamage { CleanDamage(uint32 mitigated, uint32 absorbed, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) : @@ -1744,7 +1763,7 @@ class Unit : public WorldObject void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void RemoveAuraFromStack(uint32 spellId, uint64 casterGUID = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved = 1); + void RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, uint64 casterGUID, Unit* dispeller, uint8 chargesRemoved = 1); void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit* stealer); void RemoveAurasDueToItemSpell(Item* castItem, uint32 spellId); void RemoveAurasByType(AuraType auraType, uint64 casterGUID = 0, Aura* except = NULL, bool negative = true, bool positive = true); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 5577422919f..8d2309e51f6 100755 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -2075,6 +2075,30 @@ bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target) return true; } +void Aura::CallScriptDispel(DispelInfo* dispelInfo) +{ + for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL); + std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin(); + for (; hookItr != hookItrEnd ; ++hookItr) + (*hookItr).Call(*scritr, dispelInfo); + (*scritr)->_FinishScriptCall(); + } +} + +void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo) +{ + for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL); + std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin(); + for (; hookItr != hookItrEnd ; ++hookItr) + (*hookItr).Call(*scritr, dispelInfo); + (*scritr)->_FinishScriptCall(); + } +} + bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode) { bool preventDefault = false; diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 8c9cde37c15..173819a465c 100755 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -198,6 +198,8 @@ class Aura // AuraScript void LoadScripts(); bool CallScriptCheckAreaTargetHandlers(Unit* target); + void CallScriptDispel(DispelInfo* dispelInfo); + void CallScriptAfterDispel(DispelInfo* dispelInfo); 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); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index eaf5f4e1d31..2699652cfe6 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3317,7 +3317,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex) // Send dispelled spell info dataSuccess << uint32(itr->first->GetId()); // Spell Id dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed - unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), itr->first->GetCasterGUID(), m_caster, itr->second); + unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), m_spellInfo->Id, itr->first->GetCasterGUID(), m_caster, itr->second); } m_caster->SendMessageToSet(&dataSuccess, true); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 8e20fd21fcf..8a58ce3c52a 100755 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -542,6 +542,14 @@ bool AuraScript::_Validate(SpellInfo const* entry) if (!entry->HasAreaAuraEffect()) sLog->outError("TSCR: Spell `%u` of script `%s` does not have area aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError("TSCR: Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + + for (std::list<AuraDispelHandler>::iterator itr = AfterDispel.begin(); itr != AfterDispel.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + sLog->outError("TSCR: Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectApply` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); @@ -607,6 +615,16 @@ bool AuraScript::CheckAreaTargetHandler::Call(AuraScript* auraScript, Unit* _tar return (auraScript->*pHandlerScript)(_target); } +AuraScript::AuraDispelHandler::AuraDispelHandler(AuraDispelFnType _pHandlerScript) +{ + pHandlerScript = _pHandlerScript; +} + +void AuraScript::AuraDispelHandler::Call(AuraScript* auraScript, DispelInfo* _dispelInfo) +{ + (auraScript->*pHandlerScript)(_dispelInfo); +} + AuraScript::EffectBase::EffectBase(uint8 _effIndex, uint16 _effName) : _SpellScript::EffectAuraNameCheck(_effName), _SpellScript::EffectHook(_effIndex) { diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index a1d8e6563b0..945a62674d9 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -385,6 +385,8 @@ enum AuraScriptHookType AURA_SCRIPT_HOOK_EFFECT_MANASHIELD, AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD, AURA_SCRIPT_HOOK_CHECK_AREA_TARGET, + AURA_SCRIPT_HOOK_DISPEL, + AURA_SCRIPT_HOOK_AFTER_DISPEL, /*AURA_SCRIPT_HOOK_APPLY, AURA_SCRIPT_HOOK_REMOVE, */ }; @@ -400,6 +402,7 @@ class AuraScript : public _SpellScript #define AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \ typedef bool(CLASSNAME::*AuraCheckAreaTargetFnType)(Unit* target); \ + typedef void(CLASSNAME::*AuraDispelFnType)(DispelInfo* dispelInfo); \ typedef void(CLASSNAME::*AuraEffectApplicationModeFnType)(AuraEffect const*, AuraEffectHandleModes); \ typedef void(CLASSNAME::*AuraEffectPeriodicFnType)(AuraEffect const*); \ typedef void(CLASSNAME::*AuraEffectUpdatePeriodicFnType)(AuraEffect*); \ @@ -418,6 +421,14 @@ class AuraScript : public _SpellScript private: AuraCheckAreaTargetFnType pHandlerScript; }; + class AuraDispelHandler + { + public: + AuraDispelHandler(AuraDispelFnType pHandlerScript); + void Call(AuraScript* auraScript, DispelInfo* dispelInfo); + private: + AuraDispelFnType pHandlerScript; + }; class EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook { public: @@ -493,6 +504,7 @@ class AuraScript : public _SpellScript #define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \ + class AuraDispelFunction : public AuraScript::AuraDispelHandler { public: AuraDispelFunction(AuraDispelFnType _pHandlerScript) : AuraScript::AuraDispelHandler((AuraScript::AuraDispelFnType)_pHandlerScript) {} }; \ class EffectPeriodicHandlerFunction : public AuraScript::EffectPeriodicHandler { public: EffectPeriodicHandlerFunction(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectPeriodicHandler((AuraScript::AuraEffectPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ class EffectUpdatePeriodicHandlerFunction : public AuraScript::EffectUpdatePeriodicHandler { public: EffectUpdatePeriodicHandlerFunction(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectUpdatePeriodicHandler((AuraScript::AuraEffectUpdatePeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ class EffectCalcAmountHandlerFunction : public AuraScript::EffectCalcAmountHandler { public: EffectCalcAmountHandlerFunction(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcAmountHandler((AuraScript::AuraEffectCalcAmountFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ @@ -540,6 +552,17 @@ class AuraScript : public _SpellScript // where function is: bool function (Unit* target); HookList<CheckAreaTargetHandler> DoCheckAreaTarget; #define AuraCheckAreaTargetFn(F) CheckAreaTargetFunction(&F) + + // executed when aura is dispelled by a unit + // example: OnDispel += AuraDispelFn(class::function); + // where function is: void function (DispelInfo* dispelInfo); + HookList<AuraDispelHandler> OnDispel; + // executed after aura is dispelled by a unit + // example: AfterDispel += AuraDispelFn(class::function); + // where function is: void function (DispelInfo* dispelInfo); + HookList<AuraDispelHandler> AfterDispel; + #define AuraDispelFn(F) AuraDispelFunction(&F) + // 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); |