diff options
author | Seyden <saiifii@live.de> | 2017-07-20 00:15:02 +0200 |
---|---|---|
committer | Treeston <treeston.mmoc@gmail.com> | 2017-07-20 00:15:02 +0200 |
commit | a9174d5eb75b4e0f28542c44b797fcacddc7ab64 (patch) | |
tree | ea5ff3b422d33373d9c28eb3a897635ddf2455a9 | |
parent | a6e46c1c2ef491cd4cce39be47445e9da194e84e (diff) |
Core/Scripts: Implement generic script loaders (and script registry macros) to greatly reduce code duplication (#19526)
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.h | 68 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp | 532 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Naxxramas/naxxramas.h | 1 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_item.cpp | 53 |
4 files changed, 348 insertions, 306 deletions
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 020df6d54ac..eea4d7cc39c 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -205,10 +205,10 @@ class TC_GAME_API SpellScriptLoader : public ScriptObject public: // Should return a fully valid SpellScript pointer. - virtual SpellScript* GetSpellScript() const { return NULL; } + virtual SpellScript* GetSpellScript() const { return nullptr; } // Should return a fully valid AuraScript pointer. - virtual AuraScript* GetAuraScript() const { return NULL; } + virtual AuraScript* GetAuraScript() const { return nullptr; } }; class TC_GAME_API ServerScript : public ScriptObject @@ -1175,6 +1175,70 @@ class TC_GAME_API ScriptMgr std::string _currentContext; }; +template <class S> +class GenericSpellScriptLoader : public SpellScriptLoader +{ + public: + GenericSpellScriptLoader(char const* name) : SpellScriptLoader(name) { } + SpellScript* GetSpellScript() const override { return new S(); } +}; +#define RegisterSpellScript(spell_script) new GenericSpellScriptLoader<spell_script>(#spell_script) + +template <class A> +class GenericAuraScriptLoader : public SpellScriptLoader +{ + public: + GenericAuraScriptLoader(char const* name) : SpellScriptLoader(name) { } + AuraScript* GetAuraScript() const override { return new A(); } +}; +#define RegisterAuraScript(aura_script) new GenericAuraScriptLoader<aura_script>(#aura_script) + +template <class S, class A> +class GenericSpellAndAuraScriptLoader : public SpellScriptLoader +{ + public: + GenericSpellAndAuraScriptLoader(char const* name) : SpellScriptLoader(name) { } + SpellScript* GetSpellScript() const override { return new S(); } + AuraScript* GetAuraScript() const override { return new A(); } +}; +#define RegisterSpellAndAuraScriptPair(spell_script, aura_script) new GenericSpellAndAuraScriptLoader<spell_script, aura_script>(#spell_script) + +template <class AI> +class GenericCreatureScript : public CreatureScript +{ + public: + GenericCreatureScript(char const* name) : CreatureScript(name) { } + CreatureAI* GetAI(Creature* me) const override { return new AI(me); } +}; +#define RegisterCreatureAI(ai_name) new GenericCreatureScript<ai_name>(#ai_name) + +template <class AI, AI*(*AIFactory)(Creature*)> +class FactoryCreatureScript : public CreatureScript +{ + public: + FactoryCreatureScript(char const* name) : CreatureScript(name) { } + CreatureAI* GetAI(Creature* me) const override { return AIFactory(me); } +}; +#define RegisterCreatureAIWithFactory(ai_name, factory_fn) new FactoryCreatureScript<ai_name, &factory_fn>(#ai_name) + +template <class AI> +class GenericGameObjectScript : public GameObjectScript +{ + public: + GenericGameObjectScript(char const* name) : GameObjectScript(name) { } + GameObjectAI* GetAI(GameObject* go) const override { return new AI(go); } +}; +#define RegisterGameObjectAI(ai_name) new GenericGameObjectScript<ai_name>(#ai_name) + +template <class AI> +class GenericAreaTriggerEntityScript : public AreaTriggerEntityScript +{ + public: + GenericAreaTriggerEntityScript(char const* name) : AreaTriggerEntityScript(name) { } + AreaTriggerAI* GetAI(AreaTrigger* at) const override { return new AI(at); } +}; +#define RegisterAreaTriggerAI(ai_name) new GenericAreaTriggerEntityScript<ai_name>(#ai_name) + #define sScriptMgr ScriptMgr::instance() #endif diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index 7bddb692a98..ba52ecb0439 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -160,320 +160,308 @@ enum ThaddiusSpells SPELL_NEGATIVE_CHARGE_AMP = 29660, }; -class boss_thaddius : public CreatureScript +struct boss_thaddius : public BossAI { -public: - boss_thaddius() : CreatureScript("boss_thaddius") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetNaxxramasAI<boss_thaddiusAI>(creature); - } - - struct boss_thaddiusAI : public BossAI - { - public: - boss_thaddiusAI(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningUnlocked(false), ballLightningEnabled(false), shockingEligibility(true) {} + public: + boss_thaddius(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningUnlocked(false), ballLightningEnabled(false), shockingEligibility(true) {} - void InitializeAI() override + void InitializeAI() override + { + if (instance->GetBossState(BOSS_THADDIUS) != DONE) { - if (instance->GetBossState(BOSS_THADDIUS) != DONE) - { - events.SetPhase(PHASE_NOT_ENGAGED); - SetCombatMovement(false); + events.SetPhase(PHASE_NOT_ENGAGED); + SetCombatMovement(false); - // initialize everything properly, and ensure that the coils are loaded by the time we initialize - BeginResetEncounter(true); - } + // initialize everything properly, and ensure that the coils are loaded by the time we initialize + BeginResetEncounter(true); } + } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - void Reset() override { } + void Reset() override { } - void EnterEvadeMode(EvadeReason why) override + void EnterEvadeMode(EvadeReason why) override + { + if (!ballLightningEnabled && why == EVADE_REASON_NO_HOSTILES) { - if (!ballLightningEnabled && why == EVADE_REASON_NO_HOSTILES) - { - ballLightningEnabled = true; - return; // try again - } - if (events.IsInPhase(PHASE_TRANSITION) || (events.IsInPhase(PHASE_THADDIUS) && me->IsAlive())) - BeginResetEncounter(); + ballLightningEnabled = true; + return; // try again } + if (events.IsInPhase(PHASE_TRANSITION) || (events.IsInPhase(PHASE_THADDIUS) && me->IsAlive())) + BeginResetEncounter(); + } - bool CanAIAttack(Unit const* who) const override - { - if (ballLightningEnabled || me->IsWithinMeleeRange(who)) - return BossAI::CanAIAttack(who); - else - return false; - } + bool CanAIAttack(Unit const* who) const override + { + if (ballLightningEnabled || me->IsWithinMeleeRange(who)) + return BossAI::CanAIAttack(who); + else + return false; + } - void JustRespawned() override - { - if (events.IsInPhase(PHASE_RESETTING)) - ResetEncounter(); - } + void JustRespawned() override + { + if (events.IsInPhase(PHASE_RESETTING)) + ResetEncounter(); + } - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - me->setActive(false); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->setActive(false); - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->setActive(false); - Talk(SAY_DEATH); - } + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + me->setActive(false); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->setActive(false); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->setActive(false); + Talk(SAY_DEATH); + } - void DoAction(int32 action) override + void DoAction(int32 action) override + { + switch (action) { - switch (action) - { - case ACTION_RESET_ENCOUNTER_TIMER: - if (events.IsInPhase(PHASE_RESETTING)) - ResetEncounter(); - break; - case ACTION_FEUGEN_RESET: - case ACTION_STALAGG_RESET: - if (!events.IsInPhase(PHASE_NOT_ENGAGED) && !events.IsInPhase(PHASE_RESETTING)) - BeginResetEncounter(); - break; - case ACTION_FEUGEN_AGGRO: - case ACTION_STALAGG_AGGRO: - if (events.IsInPhase(PHASE_RESETTING)) - { - BeginResetEncounter(); - return; - } - if (!events.IsInPhase(PHASE_NOT_ENGAGED)) - return; - events.SetPhase(PHASE_PETS); - - shockingEligibility = true; - - if (!instance->CheckRequiredBosses(BOSS_THADDIUS)) - { - BeginResetEncounter(); - return; - } - instance->SetBossState(BOSS_THADDIUS, IN_PROGRESS); - - me->setActive(true); - DoZoneInCombat(); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->setActive(true); - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->setActive(true); - break; - case ACTION_FEUGEN_DIED: - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_FEUGEN_REVIVING_FX); - feugenAlive = false; - if (stalaggAlive) - events.ScheduleEvent(EVENT_REVIVE_FEUGEN, Seconds(5), 0, PHASE_PETS); - else - Transition(); + case ACTION_RESET_ENCOUNTER_TIMER: + if (events.IsInPhase(PHASE_RESETTING)) + ResetEncounter(); + break; + case ACTION_FEUGEN_RESET: + case ACTION_STALAGG_RESET: + if (!events.IsInPhase(PHASE_NOT_ENGAGED) && !events.IsInPhase(PHASE_RESETTING)) + BeginResetEncounter(); + break; + case ACTION_FEUGEN_AGGRO: + case ACTION_STALAGG_AGGRO: + if (events.IsInPhase(PHASE_RESETTING)) + { + BeginResetEncounter(); + return; + } + if (!events.IsInPhase(PHASE_NOT_ENGAGED)) + return; + events.SetPhase(PHASE_PETS); - break; - case ACTION_STALAGG_DIED: - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_STALAGG_REVIVING_FX); - stalaggAlive = false; - if (feugenAlive) - events.ScheduleEvent(EVENT_REVIVE_STALAGG, Seconds(5), 0, PHASE_PETS); - else - Transition(); + shockingEligibility = true; - break; + if (!instance->CheckRequiredBosses(BOSS_THADDIUS)) + { + BeginResetEncounter(); + return; + } + instance->SetBossState(BOSS_THADDIUS, IN_PROGRESS); + + me->setActive(true); + DoZoneInCombat(); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->setActive(true); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->setActive(true); + break; + case ACTION_FEUGEN_DIED: + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_FEUGEN_REVIVING_FX); + feugenAlive = false; + if (stalaggAlive) + events.ScheduleEvent(EVENT_REVIVE_FEUGEN, Seconds(5), 0, PHASE_PETS); + else + Transition(); + + break; + case ACTION_STALAGG_DIED: + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_STALAGG_REVIVING_FX); + stalaggAlive = false; + if (feugenAlive) + events.ScheduleEvent(EVENT_REVIVE_STALAGG, Seconds(5), 0, PHASE_PETS); + else + Transition(); - case ACTION_POLARITY_CROSSED: - shockingEligibility = false; - break; - default: - break; - } - } + break; - uint32 GetData(uint32 id) const override - { - return (id == DATA_POLARITY_CROSSED && shockingEligibility) ? 1u : 0u; + case ACTION_POLARITY_CROSSED: + shockingEligibility = false; + break; + default: + break; } + } - void Transition() // initiate transition between pet phase and thaddius phase - { - events.SetPhase(PHASE_TRANSITION); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - events.ScheduleEvent(EVENT_TRANSITION_1, Seconds(10), 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_TRANSITION_2, Seconds(12), 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_TRANSITION_3, Seconds(14), 0, PHASE_TRANSITION); - } + uint32 GetData(uint32 id) const override + { + return (id == DATA_POLARITY_CROSSED && shockingEligibility) ? 1u : 0u; + } - void BeginResetEncounter(bool initial = false) - { - if (instance->GetBossState(BOSS_THADDIUS) == DONE) - return; - if (events.IsInPhase(PHASE_RESETTING)) - return; + void Transition() // initiate transition between pet phase and thaddius phase + { + events.SetPhase(PHASE_TRANSITION); - // remove polarity shift debuffs on reset - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POSITIVE_CHARGE_APPLY); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NEGATIVE_CHARGE_APPLY); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->DespawnOrUnsummon(); - me->SetRespawnTime(initial ? 5 : 30); + events.ScheduleEvent(EVENT_TRANSITION_1, Seconds(10), 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_TRANSITION_2, Seconds(12), 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_TRANSITION_3, Seconds(14), 0, PHASE_TRANSITION); + } - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - events.SetPhase(PHASE_RESETTING); - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER); + void BeginResetEncounter(bool initial = false) + { + if (instance->GetBossState(BOSS_THADDIUS) == DONE) + return; + if (events.IsInPhase(PHASE_RESETTING)) + return; + + // remove polarity shift debuffs on reset + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POSITIVE_CHARGE_APPLY); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NEGATIVE_CHARGE_APPLY); + + me->DespawnOrUnsummon(); + me->SetRespawnTime(initial ? 5 : 30); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + events.SetPhase(PHASE_RESETTING); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER); + + me->setActive(false); + } - me->setActive(false); - } + void ResetEncounter() + { + feugenAlive = true; + stalaggAlive = true; - void ResetEncounter() - { - feugenAlive = true; - stalaggAlive = true; + _Reset(); + events.SetPhase(PHASE_NOT_ENGAGED); + me->SetReactState(REACT_PASSIVE); - _Reset(); - events.SetPhase(PHASE_NOT_ENGAGED); - me->SetReactState(REACT_PASSIVE); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_RESET_ENCOUNTER); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_RESET_ENCOUNTER); + } - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_RESET_ENCOUNTER); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_RESET_ENCOUNTER); - } + void UpdateAI(uint32 diff) override + { + if (events.IsInPhase(PHASE_NOT_ENGAGED)) + return; + if (events.IsInPhase(PHASE_THADDIUS) && !UpdateVictim()) + return; - void UpdateAI(uint32 diff) override + events.Update(diff); + while (uint32 eventId = events.ExecuteEvent()) { - if (events.IsInPhase(PHASE_NOT_ENGAGED)) - return; - if (events.IsInPhase(PHASE_THADDIUS) && !UpdateVictim()) - return; - - events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + switch (eventId) { - switch (eventId) - { - case EVENT_REVIVE_FEUGEN: - feugenAlive = true; - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_FEUGEN_REVIVED); - break; - case EVENT_REVIVE_STALAGG: - stalaggAlive = true; - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_STALAGG_REVIVED); - break; - case EVENT_TRANSITION_1: // tesla coils overload - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_TRANSITION); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_TRANSITION); - break; - case EVENT_TRANSITION_2: // tesla coils shock thaddius - me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_TRANSITION_2); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_TRANSITION_2); - break; - case EVENT_TRANSITION_3: // thaddius becomes active - me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); - ballLightningUnlocked = false; - me->RemoveAura(SPELL_THADDIUS_INACTIVE_VISUAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetReactState(REACT_AGGRESSIVE); - - DoZoneInCombat(); - if (Unit* closest = SelectTarget(SELECT_TARGET_NEAREST, 0, 500.0f)) - AttackStart(closest); - else // if there is no nearest target, then there is no target, meaning we should reset - { - BeginResetEncounter(); - return; - } + case EVENT_REVIVE_FEUGEN: + feugenAlive = true; + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_FEUGEN_REVIVED); + break; + case EVENT_REVIVE_STALAGG: + stalaggAlive = true; + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_STALAGG_REVIVED); + break; + case EVENT_TRANSITION_1: // tesla coils overload + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_TRANSITION); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_TRANSITION); + break; + case EVENT_TRANSITION_2: // tesla coils shock thaddius + me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_TRANSITION_2); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_TRANSITION_2); + break; + case EVENT_TRANSITION_3: // thaddius becomes active + me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); + ballLightningUnlocked = false; + me->RemoveAura(SPELL_THADDIUS_INACTIVE_VISUAL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + me->SetReactState(REACT_AGGRESSIVE); + + DoZoneInCombat(); + if (Unit* closest = SelectTarget(SELECT_TARGET_NEAREST, 0, 500.0f)) + AttackStart(closest); + else // if there is no nearest target, then there is no target, meaning we should reset + { + BeginResetEncounter(); + return; + } - if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - feugen->AI()->DoAction(ACTION_TRANSITION_3); - if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - stalagg->AI()->DoAction(ACTION_TRANSITION_3); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_TRANSITION_3); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_TRANSITION_3); - events.SetPhase(PHASE_THADDIUS); + events.SetPhase(PHASE_THADDIUS); - Talk(SAY_AGGRO); + Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_ENABLE_BALL_LIGHTNING, Seconds(5), 0, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_SHIFT, Seconds(10), 0, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_CHAIN, randtime(Seconds(10), Seconds(20)), 0, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_BERSERK, Minutes(6), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_ENABLE_BALL_LIGHTNING, Seconds(5), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_SHIFT, Seconds(10), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_CHAIN, randtime(Seconds(10), Seconds(20)), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_BERSERK, Minutes(6), 0, PHASE_THADDIUS); - break; - case EVENT_ENABLE_BALL_LIGHTNING: - ballLightningUnlocked = true; - break; - case EVENT_SHIFT: - me->CastStop(); // shift overrides all other spells - DoCastAOE(SPELL_POLARITY_SHIFT); - events.ScheduleEvent(EVENT_SHIFT_TALK, Seconds(3), PHASE_THADDIUS); - events.ScheduleEvent(EVENT_SHIFT, Seconds(30), PHASE_THADDIUS); - break; - case EVENT_SHIFT_TALK: - Talk(SAY_ELECT); - Talk(EMOTE_POLARITY_SHIFTED); - break; - case EVENT_CHAIN: - if (me->FindCurrentSpellBySpellId(SPELL_POLARITY_SHIFT)) // delay until shift is over - events.Repeat(Seconds(3)); - else - { - me->CastStop(); - DoCastVictim(SPELL_CHAIN_LIGHTNING); - events.Repeat(randtime(Seconds(10), Seconds(20))); - } - break; - case EVENT_BERSERK: + break; + case EVENT_ENABLE_BALL_LIGHTNING: + ballLightningUnlocked = true; + break; + case EVENT_SHIFT: + me->CastStop(); // shift overrides all other spells + DoCastAOE(SPELL_POLARITY_SHIFT); + events.ScheduleEvent(EVENT_SHIFT_TALK, Seconds(3), PHASE_THADDIUS); + events.ScheduleEvent(EVENT_SHIFT, Seconds(30), PHASE_THADDIUS); + break; + case EVENT_SHIFT_TALK: + Talk(SAY_ELECT); + Talk(EMOTE_POLARITY_SHIFTED); + break; + case EVENT_CHAIN: + if (me->FindCurrentSpellBySpellId(SPELL_POLARITY_SHIFT)) // delay until shift is over + events.Repeat(Seconds(3)); + else + { me->CastStop(); - DoCast(me, SPELL_BERSERK); - break; - default: - break; - } + DoCastVictim(SPELL_CHAIN_LIGHTNING); + events.Repeat(randtime(Seconds(10), Seconds(20))); + } + break; + case EVENT_BERSERK: + me->CastStop(); + DoCast(me, SPELL_BERSERK); + break; + default: + break; } - if (events.IsInPhase(PHASE_THADDIUS) && !me->HasUnitState(UNIT_STATE_CASTING) && me->isAttackReady()) + } + if (events.IsInPhase(PHASE_THADDIUS) && !me->HasUnitState(UNIT_STATE_CASTING) && me->isAttackReady()) + { + if (me->IsWithinMeleeRange(me->GetVictim())) { - if (me->IsWithinMeleeRange(me->GetVictim())) - { - ballLightningEnabled = false; - DoMeleeAttackIfReady(); - } - else if (ballLightningUnlocked) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_BALL_LIGHTNING); + ballLightningEnabled = false; + DoMeleeAttackIfReady(); } + else if (ballLightningUnlocked) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_BALL_LIGHTNING); } + } - private: - bool stalaggAlive; - bool feugenAlive; - bool ballLightningUnlocked; // whether the initial ball lightning grace period has expired and we should proceed to exterminate with extreme prejudice - bool ballLightningEnabled; // switch that is flipped to true if we try to evade due to no eligible targets in melee range - bool shockingEligibility; - }; - + private: + bool stalaggAlive; + bool feugenAlive; + bool ballLightningUnlocked; // whether the initial ball lightning grace period has expired and we should proceed to exterminate with extreme prejudice + bool ballLightningEnabled; // switch that is flipped to true if we try to evade due to no eligible targets in melee range + bool shockingEligibility; }; class npc_stalagg : public CreatureScript @@ -1307,7 +1295,7 @@ class achievement_thaddius_shocking : public AchievementCriteriaScript void AddSC_boss_thaddius() { - new boss_thaddius(); + RegisterNaxxramasCreatureAI(boss_thaddius); new npc_stalagg(); new npc_feugen(); new npc_tesla(); diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 3b6d257f7cf..997d40be2e0 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -223,5 +223,6 @@ inline AI* GetNaxxramasAI(T* obj) { return GetInstanceAI<AI>(obj, NaxxramasScriptName); } +#define RegisterNaxxramasCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetNaxxramasAI) #endif diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 1a721521ae0..1c229714dd5 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -3305,43 +3305,32 @@ enum TeachLanguage SPELL_LEARN_GOBLIN_BINARY = 50246, }; -class spell_item_teach_language : public SpellScriptLoader +class spell_item_teach_language : public SpellScript { - public: - spell_item_teach_language() : SpellScriptLoader("spell_item_teach_language") { } - - class spell_item_teach_language_SpellScript : public SpellScript - { - PrepareSpellScript(spell_item_teach_language_SpellScript); - - bool Load() override - { - return GetCaster()->GetTypeId() == TYPEID_PLAYER; - } + PrepareSpellScript(spell_item_teach_language); - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_LEARN_GNOMISH_BINARY, SPELL_LEARN_GOBLIN_BINARY }); - } + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } - void HandleDummy(SpellEffIndex /* effIndex */) - { - Player* caster = GetCaster()->ToPlayer(); + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_LEARN_GNOMISH_BINARY, SPELL_LEARN_GOBLIN_BINARY }); + } - if (roll_chance_i(34)) - caster->CastSpell(caster, caster->GetTeam() == ALLIANCE ? SPELL_LEARN_GNOMISH_BINARY : SPELL_LEARN_GOBLIN_BINARY, true); - } + void HandleDummy(SpellEffIndex /* effIndex */) + { + Player* caster = GetCaster()->ToPlayer(); - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_item_teach_language_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; + if (roll_chance_i(34)) + caster->CastSpell(caster, caster->GetTeam() == ALLIANCE ? SPELL_LEARN_GNOMISH_BINARY : SPELL_LEARN_GOBLIN_BINARY, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_item_teach_language_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_teach_language::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } }; enum RocketBoots @@ -4608,7 +4597,7 @@ void AddSC_item_spell_scripts() new spell_item_impale_leviroth(); new spell_item_brewfest_mount_transformation(); new spell_item_nitro_boots(); - new spell_item_teach_language(); + RegisterSpellScript(spell_item_teach_language); new spell_item_rocket_boots(); new spell_item_pygmy_oil(); new spell_item_unusual_compass(); |