diff options
author | Ivan Beňovic <Ivan.Benovic2@gmail.com> | 2016-07-20 09:08:58 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-07-20 09:08:58 +0200 |
commit | 8ff5b35be1256d03b85438b130dcec7cd4cae6e1 (patch) | |
tree | 38d7460449eb774a0ffddcfb046df9c003ad5bfd | |
parent | dc9e2a53aa27a0cad18b876234e13bba79995323 (diff) |
Core/Spells: Add SpellMissInfo argument to BeforeHit hooks and call them also when the spell doesn't hit. (#17613)
12 files changed, 79 insertions, 32 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 6f5e3d4a1af..5e07d43b4b4 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2338,9 +2338,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } + PrepareScriptHitHandlers(); + CallScriptBeforeHitHandlers(missInfo); + if (spellHitTarget) { SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura); + if (missInfo2 != SPELL_MISS_NONE) { if (missInfo2 != SPELL_MISS_MISS) @@ -2519,9 +2523,6 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (!effectMask) return returnVal; - PrepareScriptHitHandlers(); - CallScriptBeforeHitHandlers(); - if (Player* player = unit->ToPlayer()) { player->StartCriteriaTimer(CRITERIA_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id); @@ -2782,7 +2783,7 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo* target) return; PrepareScriptHitHandlers(); - CallScriptBeforeHitHandlers(); + CallScriptBeforeHitHandlers(SPELL_MISS_NONE); for (SpellEffectInfo const* effect : GetEffects()) if (effect && (effectMask & (1 << effect->EffectIndex))) @@ -2799,7 +2800,7 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo* target) return; PrepareScriptHitHandlers(); - CallScriptBeforeHitHandlers(); + CallScriptBeforeHitHandlers(SPELL_MISS_NONE); for (SpellEffectInfo const* effect : GetEffects()) if (effect && (effectMask & (1 << effect->EffectIndex))) @@ -7190,14 +7191,14 @@ void Spell::CallScriptSuccessfulDispel(SpellEffIndex effIndex) } } -void Spell::CallScriptBeforeHitHandlers() +void Spell::CallScriptBeforeHitHandlers(SpellMissInfo missInfo) { for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) { (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_HIT); - std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin(); + std::list<SpellScript::BeforeHitHandler>::iterator hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin(); for (; hookItr != hookItrEnd; ++hookItr) - (*hookItr).Call(*scritr); + (*hookItr).Call(*scritr, missInfo); (*scritr)->_FinishScriptCall(); } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 888e813f29b..e369ed29242 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -801,7 +801,7 @@ class TC_GAME_API Spell void PrepareScriptHitHandlers(); bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode); void CallScriptSuccessfulDispel(SpellEffIndex effIndex); - void CallScriptBeforeHitHandlers(); + void CallScriptBeforeHitHandlers(SpellMissInfo missInfo); void CallScriptOnHitHandlers(); void CallScriptAfterHitHandlers(); void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index c1eb798760b..a131e005a86 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -206,6 +206,16 @@ void SpellScript::EffectHandler::Call(SpellScript* spellScript, SpellEffIndex ef (spellScript->*pEffectHandlerScript)(effIndexToHandle); } +SpellScript::BeforeHitHandler::BeforeHitHandler(SpellBeforeHitFnType pBeforeHitHandlerScript) +{ + _pBeforeHitHandlerScript = pBeforeHitHandlerScript; +} + +void SpellScript::BeforeHitHandler::Call(SpellScript* spellScript, SpellMissInfo missInfo) +{ + (spellScript->*_pBeforeHitHandlerScript)(missInfo); +} + SpellScript::HitHandler::HitHandler(SpellHitFnType _pHitHandlerScript) { pHitHandlerScript = _pHitHandlerScript; diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 97bbdf14231..bf67a81612a 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -168,6 +168,7 @@ class TC_GAME_API SpellScript : public _SpellScript #define SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \ typedef SpellCastResult(CLASSNAME::*SpellCheckCastFnType)(); \ typedef void(CLASSNAME::*SpellEffectFnType)(SpellEffIndex); \ + typedef void(CLASSNAME::*SpellBeforeHitFnType)(SpellMissInfo missInfo); \ typedef void(CLASSNAME::*SpellHitFnType)(); \ typedef void(CLASSNAME::*SpellCastFnType)(); \ typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ @@ -214,6 +215,15 @@ class TC_GAME_API SpellScript : public _SpellScript SpellHitFnType pHitHandlerScript; }; + class TC_GAME_API BeforeHitHandler + { + public: + BeforeHitHandler(SpellBeforeHitFnType pBeforeHitHandlerScript); + void Call(SpellScript* spellScript, SpellMissInfo missInfo); + private: + SpellBeforeHitFnType _pBeforeHitHandlerScript; + }; + class TC_GAME_API TargetHook : public _SpellScript::EffectHook { public: @@ -259,6 +269,7 @@ class TC_GAME_API SpellScript : public _SpellScript class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) { } }; \ class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) { } }; \ class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) { } }; \ + class BeforeHitHandlerFunction : public SpellScript::BeforeHitHandler { public: BeforeHitHandlerFunction(SpellBeforeHitFnType pBeforeHitHandlerScript) : SpellScript::BeforeHitHandler((SpellScript::SpellBeforeHitFnType)pBeforeHitHandlerScript) { } }; \ class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ class DestinationTargetSelectHandlerFunction : public SpellScript::DestinationTargetSelectHandler { public: DestinationTargetSelectHandlerFunction(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::DestinationTargetSelectHandler((SpellScript::SpellDestinationTargetSelectFnType)_DestinationTargetSelectHandlerScript, _effIndex, _targetType) { } } @@ -307,8 +318,11 @@ class TC_GAME_API SpellScript : public _SpellScript HookList<EffectHandler> OnEffectSuccessfulDispel; #define SpellEffectFn(F, I, N) EffectHandlerFunction(&F, I, N) - // example: BeforeHit += SpellHitFn(class::function); - HookList<HitHandler> BeforeHit; + // example: BeforeHit += BeforeSpellHitFn(class::function); + // where function is void function(SpellMissInfo missInfo) + HookList<BeforeHitHandler> BeforeHit; + #define BeforeSpellHitFn(F) BeforeHitHandlerFunction(&F) + // example: OnHit += SpellHitFn(class::function); HookList<HitHandler> OnHit; // example: AfterHit += SpellHitFn(class::function); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp index 13ba10d3542..0aea30cbead 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -263,8 +263,11 @@ class spell_garfrost_permafrost : public SpellScriptLoader } private: - void PreventHitByLoS() + void PreventHitByLoS(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + if (Unit* target = GetHitUnit()) { Unit* caster = GetCaster(); @@ -305,7 +308,7 @@ class spell_garfrost_permafrost : public SpellScriptLoader void Register() override { - BeforeHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::PreventHitByLoS); + BeforeHit += BeforeSpellHitFn(spell_garfrost_permafrost_SpellScript::PreventHitByLoS); AfterHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::RestoreImmunity); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 4ecffdc8ce7..1e3f97380d9 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -1555,15 +1555,18 @@ class spell_valanar_kinetic_bomb_knockback : public SpellScriptLoader { PrepareSpellScript(spell_valanar_kinetic_bomb_knockback_SpellScript); - void KnockIntoAir() + void KnockIntoAir(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + if (Creature* target = GetHitCreature()) target->AI()->DoAction(ACTION_KINETIC_BOMB_JUMP); } void Register() override { - BeforeHit += SpellHitFn(spell_valanar_kinetic_bomb_knockback_SpellScript::KnockIntoAir); + BeforeHit += BeforeSpellHitFn(spell_valanar_kinetic_bomb_knockback_SpellScript::KnockIntoAir); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index a0ce6700d8d..ec624b7274a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -551,9 +551,9 @@ class spell_blood_queen_vampiric_bite : public SpellScriptLoader return SPELL_CAST_OK; } - void OnCast() + void OnCast(SpellMissInfo missInfo) { - if (GetCaster()->GetTypeId() != TYPEID_PLAYER) + if (GetCaster()->GetTypeId() != TYPEID_PLAYER || missInfo != SPELL_MISS_NONE) return; GetCaster()->RemoveAura(SPELL_FRENZIED_BLOODTHIRST, ObjectGuid::Empty, 0, AURA_REMOVE_BY_ENEMY_SPELL); @@ -585,7 +585,7 @@ class spell_blood_queen_vampiric_bite : public SpellScriptLoader void Register() override { OnCheckCast += SpellCheckCastFn(spell_blood_queen_vampiric_bite_SpellScript::CheckTarget); - BeforeHit += SpellHitFn(spell_blood_queen_vampiric_bite_SpellScript::OnCast); + BeforeHit += BeforeSpellHitFn(spell_blood_queen_vampiric_bite_SpellScript::OnCast); OnEffectHitTarget += SpellEffectFn(spell_blood_queen_vampiric_bite_SpellScript::HandlePresence, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index bf0d24c9e5e..e6314d7987d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -2133,14 +2133,17 @@ class spell_igb_below_zero : public SpellScriptLoader { PrepareSpellScript(spell_igb_below_zero_SpellScript); - void RemovePassengers() + void RemovePassengers(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_EJECT_ALL_PASSENGERS_BELOW_ZERO, TRIGGERED_FULL_MASK); } void Register() override { - BeforeHit += SpellHitFn(spell_igb_below_zero_SpellScript::RemovePassengers); + BeforeHit += BeforeSpellHitFn(spell_igb_below_zero_SpellScript::RemovePassengers); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index c6d199f94a8..039b2f9e96a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -2102,8 +2102,11 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader targets.resize(1); } - void CheckAura() + void CheckAura(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + if (GetHitUnit()->HasAura(GetSpellInfo()->Id)) _hadAura = true; } @@ -2116,7 +2119,7 @@ class spell_the_lich_king_necrotic_plague_jump : public SpellScriptLoader void Register() override { - BeforeHit += SpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::CheckAura); + BeforeHit += BeforeSpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::CheckAura); OnHit += SpellHitFn(spell_the_lich_king_necrotic_plague_SpellScript::AddMissingStack); } @@ -2926,8 +2929,11 @@ class spell_the_lich_king_restore_soul : public SpellScriptLoader } } - void RemoveAura() + void RemoveAura(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + if (Unit* target = GetHitUnit()) target->RemoveAurasDueToSpell(target->GetMap()->IsHeroic() ? SPELL_HARVEST_SOULS_TELEPORT : SPELL_HARVEST_SOUL_TELEPORT); } @@ -2935,7 +2941,7 @@ class spell_the_lich_king_restore_soul : public SpellScriptLoader void Register() override { OnEffectHit += SpellEffectFn(spell_the_lich_king_restore_soul_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); - BeforeHit += SpellHitFn(spell_the_lich_king_restore_soul_SpellScript::RemoveAura); + BeforeHit += BeforeSpellHitFn(spell_the_lich_king_restore_soul_SpellScript::RemoveAura); } InstanceScript* _instance; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 937ccf4d5f3..21ffde07683 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1517,8 +1517,11 @@ class spell_auto_repair : public SpellScriptLoader { PrepareSpellScript(spell_auto_repair_SpellScript); - void CheckCooldownForTarget() + void CheckCooldownForTarget(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + if (GetHitUnit()->HasAuraEffect(SPELL_AUTO_REPAIR, EFFECT_2)) // Check presence of dummy aura indicating cooldown { PreventHitEffect(EFFECT_0); @@ -1559,7 +1562,7 @@ class spell_auto_repair : public SpellScriptLoader void Register() override { OnEffectHitTarget += SpellEffectFn(spell_auto_repair_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - BeforeHit += SpellHitFn(spell_auto_repair_SpellScript::CheckCooldownForTarget); + BeforeHit += BeforeSpellHitFn(spell_auto_repair_SpellScript::CheckCooldownForTarget); } }; diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index ff0be4595cf..01721079648 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -281,8 +281,11 @@ class spell_rog_deadly_poison : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_PLAYER && GetCastItem(); } - void HandleBeforeHit() + void HandleBeforeHit(SpellMissInfo missInfo) { + if (missInfo != SPELL_MISS_NONE) + return; + if (Unit* target = GetHitUnit()) // Deadly Poison if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, flag128(0x10000, 0x80000, 0), GetCaster()->GetGUID())) @@ -345,7 +348,7 @@ class spell_rog_deadly_poison : public SpellScriptLoader void Register() override { - BeforeHit += SpellHitFn(spell_rog_deadly_poison_SpellScript::HandleBeforeHit); + BeforeHit += BeforeSpellHitFn(spell_rog_deadly_poison_SpellScript::HandleBeforeHit); AfterHit += SpellHitFn(spell_rog_deadly_poison_SpellScript::HandleAfterHit); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 6c6eec993ab..937c68e43ec 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -148,10 +148,11 @@ class spell_warl_banish : public SpellScriptLoader } private: - void HandleBanish() + void HandleBanish(SpellMissInfo missInfo) { - /// Casting Banish on a banished target will cancel the effect - /// Check if the target already has Banish, if so, do nothing. + if (missInfo != SPELL_MISS_IMMUNE) + return; + if (Unit* target = GetHitUnit()) { if (target->GetAuraEffect(SPELL_AURA_SCHOOL_IMMUNITY, SPELLFAMILY_WARLOCK, flag128(0, 0x08000000, 0))) @@ -173,7 +174,7 @@ class spell_warl_banish : public SpellScriptLoader void Register() override { - BeforeHit += SpellHitFn(spell_warl_banish_SpellScript::HandleBanish); + BeforeHit += BeforeSpellHitFn(spell_warl_banish_SpellScript::HandleBanish); AfterHit += SpellHitFn(spell_warl_banish_SpellScript::RemoveAura); } |