From 789c98fccb73a9f77dbf56fe0784e5771b492a5d Mon Sep 17 00:00:00 2001 From: Grimdhex Date: Fri, 17 Oct 2025 13:33:25 +0200 Subject: [PATCH] refactor(Scripts/HallOfLightning): modernize scripts (#23209) --- .../HallsOfLightning/boss_bjarngrim.cpp | 590 ++++++------- .../Ulduar/HallsOfLightning/boss_ionar.cpp | 350 ++++---- .../Ulduar/HallsOfLightning/boss_loken.cpp | 347 ++++---- .../Ulduar/HallsOfLightning/boss_volkhan.cpp | 813 +++++++++--------- .../HallsOfLightning/halls_of_lightning.h | 11 + .../instance_halls_of_lightning.cpp | 58 +- 6 files changed, 1039 insertions(+), 1130 deletions(-) diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index 7f4a5e038..29639ad84 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -106,338 +106,318 @@ enum Yells EMOTE_BERSEKER_STANCE = 8, }; -class boss_bjarngrim : public CreatureScript +struct boss_bjarngrim : public npc_escortAI { -public: - boss_bjarngrim() : CreatureScript("boss_bjarngrim") { } - - CreatureAI* GetAI(Creature* creature) const override + boss_bjarngrim(Creature* creature) : npc_escortAI(creature), summons(creature) { - return GetHallsOfLightningAI(creature); + m_pInstance = creature->GetInstanceScript(); + + // Init waypoints + AddWaypoint(1, 1262.18f, 99.3f, 33.5f, 0); + AddWaypoint(2, 1281.6f, 99.5f, 33.5f, 0); + AddWaypoint(3, 1311.7f, 99.4f, 40.1f, 0); + AddWaypoint(4, 1332.5f, 99.7f, 40.18f, 0); + AddWaypoint(5, 1311.7f, 99.4f, 40.1f, 0); + AddWaypoint(6, 1281.6f, 99.5f, 33.5f, 0); + AddWaypoint(7, 1262.18f, 99.3f, 33.5f, 0); + AddWaypoint(8, 1262, -26.9f, 33.5f, 0); + AddWaypoint(9, 1281.2f, -26.8f, 33.5f, 0); + AddWaypoint(10, 1311.3f, -26.9f, 40.03f, 0); + AddWaypoint(11, 1332, -26.6f, 40.18f, 0); + AddWaypoint(12, 1311.3f, -26.9f, 40.03f, 0); + AddWaypoint(13, 1281.2f, -26.8f, 33.5f, 0); + AddWaypoint(14, 1262, -26.9f, 33.5f, 0); + + Start(true, ObjectGuid::Empty, nullptr, false, true); } - struct boss_bjarngrimAI : public npc_escortAI + void Reset() override { - boss_bjarngrimAI(Creature* creature) : npc_escortAI(creature), summons(creature) + events.Reset(); + summons.DespawnAll(); + + for (uint8 i = 0; i < 2; ++i) + if (Creature* dwarf = me->SummonCreature(NPC_STORMFORGED_LIEUTENANT, me->GetPositionX() + urand(4, 12), me->GetPositionY() + urand(4, 12), me->GetPositionZ())) + { + dwarf->GetMotionMaster()->MoveFollow(me, 3, rand_norm() * 2 * 3.14f); + summons.Summon(dwarf); + } + + me->RemoveAllAuras(); + me->CastSpell(me, SPELL_TEMPORARY_ELECTRICAL_CHARGE, true); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); + + me->CastSpell(me, SPELL_BATTLE_STANCE, true); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + } + + void JustEngagedWith(Unit*) override + { + me->SetInCombatWithZone(); + Talk(SAY_AGGRO); + + RollStance(STANCE_BATTLE); + + events.ScheduleEvent(EVENT_BJARNGRIM_CHANGE_STANCE, 20s, 0); + + // DEFENSIVE STANCE + events.ScheduleEvent(EVENT_BJARNGRIM_REFLECTION, 8s, STANCE_DEFENSIVE); + events.ScheduleEvent(EVENT_BJARNGRIM_KNOCK, 16s, STANCE_DEFENSIVE); + events.ScheduleEvent(EVENT_BJARNGRIM_IRONFORM, 12s, STANCE_DEFENSIVE); + + // BERSERKER STANCE + events.ScheduleEvent(EVENT_BJARNGRIM_INTERCEPT, 23s, STANCE_BERSERKER); + events.ScheduleEvent(EVENT_BJARNGRIM_CLEAVE, 25s, STANCE_BERSERKER); + events.ScheduleEvent(EVENT_BJARNGRIM_WHIRLWIND, 26s, STANCE_BERSERKER); + + // BATTLE STANCE + events.ScheduleEvent(EVENT_BJARNGRIM_PUMMEL, 5s, STANCE_BATTLE); + events.ScheduleEvent(EVENT_BJARNGRIM_MORTAL_STRIKE, 24s, STANCE_BATTLE); + events.ScheduleEvent(EVENT_BJARNGRIM_SLAM, 30s, STANCE_BATTLE); + + if (m_pInstance) { - m_pInstance = creature->GetInstanceScript(); + m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); + m_pInstance->SetData(DATA_BJARNGRIM_ACHIEVEMENT, me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)); + } + } - // Init waypoints - AddWaypoint(1, 1262.18f, 99.3f, 33.5f, 0); - AddWaypoint(2, 1281.6f, 99.5f, 33.5f, 0); - AddWaypoint(3, 1311.7f, 99.4f, 40.1f, 0); - AddWaypoint(4, 1332.5f, 99.7f, 40.18f, 0); - AddWaypoint(5, 1311.7f, 99.4f, 40.1f, 0); - AddWaypoint(6, 1281.6f, 99.5f, 33.5f, 0); - AddWaypoint(7, 1262.18f, 99.3f, 33.5f, 0); - AddWaypoint(8, 1262, -26.9f, 33.5f, 0); - AddWaypoint(9, 1281.2f, -26.8f, 33.5f, 0); - AddWaypoint(10, 1311.3f, -26.9f, 40.03f, 0); - AddWaypoint(11, 1332, -26.6f, 40.18f, 0); - AddWaypoint(12, 1311.3f, -26.9f, 40.03f, 0); - AddWaypoint(13, 1281.2f, -26.8f, 33.5f, 0); - AddWaypoint(14, 1262, -26.9f, 33.5f, 0); + void KilledUnit(Unit* victim) override + { + if (!victim->IsPlayer()) + return; - Start(true, ObjectGuid::Empty, nullptr, false, true); + Talk(SAY_SLAY); + } + + void JustDied(Unit*) override + { + Talk(SAY_DEATH); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, DONE); + } + + void RemoveStanceAura(uint8 stance) + { + switch (stance) + { + case STANCE_DEFENSIVE: + me->RemoveAura(SPELL_DEFENSIVE_STANCE); + me->RemoveAura(SPELL_DEFENSIVE_AURA); + break; + case STANCE_BERSERKER: + me->RemoveAura(SPELL_BERSERKER_STANCE); + me->RemoveAura(SPELL_BERSERKER_AURA); + break; + case STANCE_BATTLE: + me->RemoveAura(SPELL_BATTLE_STANCE); + me->RemoveAura(SPELL_BATTLE_AURA); + break; + } + } + + void RollStance(uint8 stance, uint8 force = 0) + { + if (urand(0, 1)) + stance = (++stance == 4 ? 1 : stance); + else + stance = (--stance == 0 ? 3 : stance); + + if (force) + stance = force; + + switch (stance) + { + case STANCE_DEFENSIVE: + Talk(SAY_DEFENSIVE_STANCE); + + me->CastSpell(me, SPELL_DEFENSIVE_STANCE, true); + me->CastSpell(me, SPELL_DEFENSIVE_AURA, true); + + events.DelayEvents(20s, STANCE_BERSERKER); + events.DelayEvents(20s, STANCE_BATTLE); + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + break; + case STANCE_BERSERKER: + Talk(SAY_BERSERKER_STANCE); + + me->CastSpell(me, SPELL_BERSERKER_STANCE, true); + me->CastSpell(me, SPELL_BERSERKER_AURA, true); + + events.DelayEvents(20s, STANCE_DEFENSIVE); + events.DelayEvents(20s, STANCE_BATTLE); + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + break; + case STANCE_BATTLE: + Talk(SAY_BATTLE_STANCE); + + me->CastSpell(me, SPELL_BATTLE_STANCE, true); + me->CastSpell(me, SPELL_BATTLE_AURA, true); + + events.DelayEvents(20s, STANCE_BERSERKER); + events.DelayEvents(20s, STANCE_DEFENSIVE); + + SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + break; } + m_uiStance = stance; + } + + void WaypointReached(uint32 Point) override + { + if (Point == 1 || Point == 8) + me->CastSpell(me, SPELL_TEMPORARY_ELECTRICAL_CHARGE, true); + else if (Point == 7 || Point == 14) + me->RemoveAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE); + } + + void UpdateEscortAI(uint32 diff) override + { + if (!me->IsInCombat()) + return; + + // Return since we have no target + if (!UpdateVictim()) + { + Reset(); + return; + } + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_BJARNGRIM_CHANGE_STANCE: + // roll new stance + RemoveStanceAura(m_uiStance); + RollStance(m_uiStance); + events.Repeat(20s); + break; + + /////////////////////////////////////////////////////// + ///// DEFENSIVE STANCE + /////////////////////////////////////////////////////// + case EVENT_BJARNGRIM_REFLECTION: + me->CastSpell(me, SPELL_BJARNGRIM_REFLETION, true); + events.Repeat(8s, 9s); + break; + case EVENT_BJARNGRIM_PUMMEL: + me->CastSpell(me->GetVictim(), SPELL_PUMMEL, false); + events.Repeat(10s, 11s); + break; + case EVENT_BJARNGRIM_KNOCK: + me->CastSpell(me, SPELL_KNOCK_AWAY, false); + events.Repeat(20s, 21s); + break; + case EVENT_BJARNGRIM_IRONFORM: + me->CastSpell(me, SPELL_IRONFORM, true); + events.Repeat(18s, 23s); + break; + + /////////////////////////////////////////////////////// + ///// BERSERKER STANCE + /////////////////////////////////////////////////////// + case EVENT_BJARNGRIM_MORTAL_STRIKE: + me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false); + events.Repeat(10s); + break; + case EVENT_BJARNGRIM_WHIRLWIND: + me->CastSpell(me, SPELL_WHIRLWIND, true); + events.Repeat(25s); + break; + + /////////////////////////////////////////////////////// + ///// BATTLE STANCE + /////////////////////////////////////////////////////// + case EVENT_BJARNGRIM_INTERCEPT: + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + me->CastSpell(target, SPELL_INTERCEPT, true); + + events.Repeat(30s); + break; + case EVENT_BJARNGRIM_CLEAVE: + me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false); + events.Repeat(25s); + break; + case EVENT_BJARNGRIM_SLAM: + me->CastSpell(me->GetVictim(), SPELL_SLAM, false); + events.Repeat(10s, 12s); + break; + } + + DoMeleeAttackIfReady(); + } + + private: InstanceScript* m_pInstance; EventMap events; SummonList summons; uint8 m_uiStance; - - void Reset() override - { - events.Reset(); - summons.DespawnAll(); - - for (uint8 i = 0; i < 2; ++i) - if (Creature* dwarf = me->SummonCreature(NPC_STORMFORGED_LIEUTENANT, me->GetPositionX() + urand(4, 12), me->GetPositionY() + urand(4, 12), me->GetPositionZ())) - { - dwarf->GetMotionMaster()->MoveFollow(me, 3, rand_norm() * 2 * 3.14f); - summons.Summon(dwarf); - } - - me->RemoveAllAuras(); - me->CastSpell(me, SPELL_TEMPORARY_ELECTRICAL_CHARGE, true); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); - - me->CastSpell(me, SPELL_BATTLE_STANCE, true); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - } - - void JustEngagedWith(Unit*) override - { - me->SetInCombatWithZone(); - Talk(SAY_AGGRO); - - RollStance(STANCE_BATTLE); - - events.ScheduleEvent(EVENT_BJARNGRIM_CHANGE_STANCE, 20s, 0); - - // DEFENSIVE STANCE - events.ScheduleEvent(EVENT_BJARNGRIM_REFLECTION, 8s, STANCE_DEFENSIVE); - events.ScheduleEvent(EVENT_BJARNGRIM_KNOCK, 16s, STANCE_DEFENSIVE); - events.ScheduleEvent(EVENT_BJARNGRIM_IRONFORM, 12s, STANCE_DEFENSIVE); - - // BERSERKER STANCE - events.ScheduleEvent(EVENT_BJARNGRIM_INTERCEPT, 23s, STANCE_BERSERKER); - events.ScheduleEvent(EVENT_BJARNGRIM_CLEAVE, 25s, STANCE_BERSERKER); - events.ScheduleEvent(EVENT_BJARNGRIM_WHIRLWIND, 26s, STANCE_BERSERKER); - - // BATTLE STANCE - events.ScheduleEvent(EVENT_BJARNGRIM_PUMMEL, 5s, STANCE_BATTLE); - events.ScheduleEvent(EVENT_BJARNGRIM_MORTAL_STRIKE, 24s, STANCE_BATTLE); - events.ScheduleEvent(EVENT_BJARNGRIM_SLAM, 30s, STANCE_BATTLE); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); - m_pInstance->SetData(DATA_BJARNGRIM_ACHIEVEMENT, me->HasAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE)); - } - } - - void KilledUnit(Unit* victim) override - { - if (!victim->IsPlayer()) - return; - - Talk(SAY_SLAY); - } - - void JustDied(Unit*) override - { - Talk(SAY_DEATH); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, DONE); - } - - void RemoveStanceAura(uint8 stance) - { - switch (stance) - { - case STANCE_DEFENSIVE: - me->RemoveAura(SPELL_DEFENSIVE_STANCE); - me->RemoveAura(SPELL_DEFENSIVE_AURA); - break; - case STANCE_BERSERKER: - me->RemoveAura(SPELL_BERSERKER_STANCE); - me->RemoveAura(SPELL_BERSERKER_AURA); - break; - case STANCE_BATTLE: - me->RemoveAura(SPELL_BATTLE_STANCE); - me->RemoveAura(SPELL_BATTLE_AURA); - break; - } - } - - void RollStance(uint8 stance, uint8 force = 0) - { - if (urand(0, 1)) - stance = (++stance == 4 ? 1 : stance); - else - stance = (--stance == 0 ? 3 : stance); - - if (force) - stance = force; - - switch (stance) - { - case STANCE_DEFENSIVE: - Talk(SAY_DEFENSIVE_STANCE); - - me->CastSpell(me, SPELL_DEFENSIVE_STANCE, true); - me->CastSpell(me, SPELL_DEFENSIVE_AURA, true); - - events.DelayEvents(20s, STANCE_BERSERKER); - events.DelayEvents(20s, STANCE_BATTLE); - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - break; - case STANCE_BERSERKER: - Talk(SAY_BERSERKER_STANCE); - - me->CastSpell(me, SPELL_BERSERKER_STANCE, true); - me->CastSpell(me, SPELL_BERSERKER_AURA, true); - - events.DelayEvents(20s, STANCE_DEFENSIVE); - events.DelayEvents(20s, STANCE_BATTLE); - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); - break; - case STANCE_BATTLE: - Talk(SAY_BATTLE_STANCE); - - me->CastSpell(me, SPELL_BATTLE_STANCE, true); - me->CastSpell(me, SPELL_BATTLE_AURA, true); - - events.DelayEvents(20s, STANCE_BERSERKER); - events.DelayEvents(20s, STANCE_DEFENSIVE); - - SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - break; - } - - m_uiStance = stance; - } - - void WaypointReached(uint32 Point) override - { - if (Point == 1 || Point == 8) - me->CastSpell(me, SPELL_TEMPORARY_ELECTRICAL_CHARGE, true); - else if (Point == 7 || Point == 14) - me->RemoveAura(SPELL_TEMPORARY_ELECTRICAL_CHARGE); - } - - void UpdateEscortAI(uint32 diff) override - { - if (!me->IsInCombat()) - return; - - // Return since we have no target - if (!UpdateVictim()) - { - Reset(); - return; - } - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_BJARNGRIM_CHANGE_STANCE: - // roll new stance - RemoveStanceAura(m_uiStance); - RollStance(m_uiStance); - events.Repeat(20s); - break; - - /////////////////////////////////////////////////////// - ///// DEFENSIVE STANCE - /////////////////////////////////////////////////////// - case EVENT_BJARNGRIM_REFLECTION: - me->CastSpell(me, SPELL_BJARNGRIM_REFLETION, true); - events.Repeat(8s, 9s); - break; - case EVENT_BJARNGRIM_PUMMEL: - me->CastSpell(me->GetVictim(), SPELL_PUMMEL, false); - events.Repeat(10s, 11s); - break; - case EVENT_BJARNGRIM_KNOCK: - me->CastSpell(me, SPELL_KNOCK_AWAY, false); - events.Repeat(20s, 21s); - break; - case EVENT_BJARNGRIM_IRONFORM: - me->CastSpell(me, SPELL_IRONFORM, true); - events.Repeat(18s, 23s); - break; - - /////////////////////////////////////////////////////// - ///// BERSERKER STANCE - /////////////////////////////////////////////////////// - case EVENT_BJARNGRIM_MORTAL_STRIKE: - me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false); - events.Repeat(10s); - break; - case EVENT_BJARNGRIM_WHIRLWIND: - me->CastSpell(me, SPELL_WHIRLWIND, true); - events.Repeat(25s); - break; - - /////////////////////////////////////////////////////// - ///// BATTLE STANCE - /////////////////////////////////////////////////////// - case EVENT_BJARNGRIM_INTERCEPT: - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - me->CastSpell(target, SPELL_INTERCEPT, true); - - events.Repeat(30s); - break; - case EVENT_BJARNGRIM_CLEAVE: - me->CastSpell(me->GetVictim(), SPELL_CLEAVE, false); - events.Repeat(25s); - break; - case EVENT_BJARNGRIM_SLAM: - me->CastSpell(me->GetVictim(), SPELL_SLAM, false); - events.Repeat(10s, 12s); - break; - } - - DoMeleeAttackIfReady(); - } - }; }; -class npc_stormforged_lieutenant : public CreatureScript +struct npc_stormforged_lieutenant : public ScriptedAI { -public: - npc_stormforged_lieutenant() : CreatureScript("npc_stormforged_lieutenant") { } + npc_stormforged_lieutenant(Creature* creature) : ScriptedAI(creature) { } - CreatureAI* GetAI(Creature* creature) const override + void Reset() override { - return GetHallsOfLightningAI(creature); + if (me->IsSummon()) + BjarngrimGUID = me->ToTempSummon()->GetSummonerGUID(); + else + BjarngrimGUID.Clear(); } - struct npc_stormforged_lieutenantAI : public ScriptedAI + void JustEngagedWith(Unit*) override { - npc_stormforged_lieutenantAI(Creature* creature) : ScriptedAI(creature) { } + events.ScheduleEvent(EVENT_ARC_WELD, 2s); + events.ScheduleEvent(EVENT_RENEW_STEEL, 10s, 11s); + } + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_ARC_WELD: + me->CastSpell(me->GetVictim(), SPELL_ARC_WELD, true); + events.Repeat(20s); + break; + case EVENT_RENEW_STEEL: + if (Creature* bjarngrim = ObjectAccessor::GetCreature(*me, BjarngrimGUID)) + if (bjarngrim->IsAlive()) + me->CastSpell(bjarngrim, me->GetMap()->IsHeroic() ? SPELL_RENEW_STEEL_H : SPELL_RENEW_STEEL_N, true); + + events.Repeat(10s, 14s); + break; + } + + DoMeleeAttackIfReady(); + } + + private: EventMap events; ObjectGuid BjarngrimGUID; - - void Reset() override - { - if (me->IsSummon()) - BjarngrimGUID = me->ToTempSummon()->GetSummonerGUID(); - else - BjarngrimGUID.Clear(); - } - - void JustEngagedWith(Unit*) override - { - events.ScheduleEvent(EVENT_ARC_WELD, 2s); - events.ScheduleEvent(EVENT_RENEW_STEEL, 10s, 11s); - } - - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_ARC_WELD: - me->CastSpell(me->GetVictim(), SPELL_ARC_WELD, true); - events.Repeat(20s); - break; - case EVENT_RENEW_STEEL: - if (Creature* bjarngrim = ObjectAccessor::GetCreature(*me, BjarngrimGUID)) - if (bjarngrim->IsAlive()) - me->CastSpell(bjarngrim, me->GetMap()->IsHeroic() ? SPELL_RENEW_STEEL_H : SPELL_RENEW_STEEL_N, true); - - events.Repeat(10s, 14s); - break; - } - - DoMeleeAttackIfReady(); - } - }; }; void AddSC_boss_bjarngrim() { - new boss_bjarngrim(); - new npc_stormforged_lieutenant(); + RegisterHallOfLightningCreatureAI(boss_bjarngrim); + RegisterHallOfLightningCreatureAI(npc_stormforged_lieutenant); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index e19997426..f2e3def24 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -68,211 +68,191 @@ enum IonarEvents EVENT_RESTORE = 5, }; -class boss_ionar : public CreatureScript +struct boss_ionar : public BossAI { -public: - boss_ionar() : CreatureScript("boss_ionar") { } - - CreatureAI* GetAI(Creature* creature) const override + boss_ionar(Creature* creature) : BossAI(creature, DATA_IONAR), summons(creature) { - return GetHallsOfLightningAI(creature); + m_pInstance = creature->GetInstanceScript(); } - struct boss_ionarAI : public ScriptedAI + void Reset() override { - boss_ionarAI(Creature* creature) : ScriptedAI(creature), summons(creature) + HealthCheck = 50; + events.Reset(); + summons.DespawnAll(); + + me->SetVisible(true); + + if (m_pInstance) + m_pInstance->SetData(TYPE_IONAR, NOT_STARTED); + } + + void ScheduleEvents(bool spark) + { + events.SetPhase(1); + if (!spark) + events.RescheduleEvent(EVENT_CHECK_HEALTH, 1s, 0, 1); + + events.RescheduleEvent(EVENT_BALL_LIGHTNING, 10s, 0, 1); + events.RescheduleEvent(EVENT_STATIC_OVERLOAD, 5s, 0, 1); + } + + void JustEngagedWith(Unit*) override + { + me->SetInCombatWithZone(); + Talk(SAY_AGGRO); + + if (m_pInstance) + m_pInstance->SetData(TYPE_IONAR, IN_PROGRESS); + + ScheduleEvents(false); + } + + void JustDied(Unit*) override + { + Talk(SAY_DEATH); + + summons.DespawnAll(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_IONAR, DONE); + } + + void KilledUnit(Unit* victim) override + { + if (!victim->IsPlayer()) + return; + + Talk(SAY_SLAY); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_DISPERSE) + Split(); + } + + void Split() + { + Talk(SAY_SPLIT); + + Creature* spark; + for (uint8 i = 0; i < 5; ++i) { - m_pInstance = creature->GetInstanceScript(); + if ((spark = me->SummonCreature(NPC_SPARK_OF_IONAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000))) + { + summons.Summon(spark); + spark->CastSpell(spark, me->GetMap()->IsHeroic() ? SPELL_SPARK_VISUAL_TRIGGER_H : SPELL_SPARK_VISUAL_TRIGGER_N, true); + spark->CastSpell(spark, SPELL_RANDOM_LIGHTNING, true); + spark->SetUnitFlag(UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + spark->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0); + + if (Player* tgt = SelectTargetFromPlayerList(100)) + spark->GetMotionMaster()->MoveFollow(tgt, 0.0f, 0.0f, MOTION_SLOT_CONTROLLED); + } } + me->SetVisible(false); + me->SetControlled(true, UNIT_STATE_STUNNED); + + events.SetPhase(2); + events.ScheduleEvent(EVENT_CALL_SPARKS, 15s, 0, 2); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_BALL_LIGHTNING: + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + me->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_BALL_LIGHTNING_H : SPELL_BALL_LIGHTNING_N, false); + + events.Repeat(10s, 11s); + break; + case EVENT_STATIC_OVERLOAD: + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + me->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_STATIC_OVERLOAD_H : SPELL_STATIC_OVERLOAD_N, false); + + events.Repeat(5s, 6s); + break; + case EVENT_CHECK_HEALTH: + if (HealthBelowPct(HealthCheck)) + me->CastSpell(me, SPELL_DISPERSE, false); + + events.Repeat(1s); + return; + case EVENT_CALL_SPARKS: + { + EntryCheckPredicate pred(NPC_SPARK_OF_IONAR); + summons.DoAction(ACTION_CALLBACK, pred); + events.ScheduleEvent(EVENT_RESTORE, 2s, 0, 2); + return; + } + case EVENT_RESTORE: + EntryCheckPredicate pred(NPC_SPARK_OF_IONAR); + summons.DoAction(ACTION_SPARK_DESPAWN, pred); + + me->SetVisible(true); + me->SetControlled(false, UNIT_STATE_STUNNED); + ScheduleEvents(true); + return; + } + + DoMeleeAttackIfReady(); + } + + private: InstanceScript* m_pInstance; EventMap events; SummonList summons; uint8 HealthCheck; - - void Reset() override - { - HealthCheck = 50; - events.Reset(); - summons.DespawnAll(); - - me->SetVisible(true); - - if (m_pInstance) - m_pInstance->SetData(TYPE_IONAR, NOT_STARTED); - } - - void ScheduleEvents(bool spark) - { - events.SetPhase(1); - if (!spark) - events.RescheduleEvent(EVENT_CHECK_HEALTH, 1s, 0, 1); - - events.RescheduleEvent(EVENT_BALL_LIGHTNING, 10s, 0, 1); - events.RescheduleEvent(EVENT_STATIC_OVERLOAD, 5s, 0, 1); - } - - void JustEngagedWith(Unit*) override - { - me->SetInCombatWithZone(); - Talk(SAY_AGGRO); - - if (m_pInstance) - m_pInstance->SetData(TYPE_IONAR, IN_PROGRESS); - - ScheduleEvents(false); - } - - void JustDied(Unit*) override - { - Talk(SAY_DEATH); - - summons.DespawnAll(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_IONAR, DONE); - } - - void KilledUnit(Unit* victim) override - { - if (!victim->IsPlayer()) - return; - - Talk(SAY_SLAY); - } - - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override - { - if (spell->Id == SPELL_DISPERSE) - Split(); - } - - void Split() - { - Talk(SAY_SPLIT); - - Creature* spark; - for (uint8 i = 0; i < 5; ++i) - { - if ((spark = me->SummonCreature(NPC_SPARK_OF_IONAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 20000))) - { - summons.Summon(spark); - spark->CastSpell(spark, me->GetMap()->IsHeroic() ? SPELL_SPARK_VISUAL_TRIGGER_H : SPELL_SPARK_VISUAL_TRIGGER_N, true); - spark->CastSpell(spark, SPELL_RANDOM_LIGHTNING, true); - spark->SetUnitFlag(UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - spark->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0); - - if (Player* tgt = SelectTargetFromPlayerList(100)) - spark->GetMotionMaster()->MoveFollow(tgt, 0.0f, 0.0f, MOTION_SLOT_CONTROLLED); - } - } - - me->SetVisible(false); - me->SetControlled(true, UNIT_STATE_STUNNED); - - events.SetPhase(2); - events.ScheduleEvent(EVENT_CALL_SPARKS, 15s, 0, 2); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_BALL_LIGHTNING: - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - me->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_BALL_LIGHTNING_H : SPELL_BALL_LIGHTNING_N, false); - - events.Repeat(10s, 11s); - break; - case EVENT_STATIC_OVERLOAD: - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - me->CastSpell(target, me->GetMap()->IsHeroic() ? SPELL_STATIC_OVERLOAD_H : SPELL_STATIC_OVERLOAD_N, false); - - events.Repeat(5s, 6s); - break; - case EVENT_CHECK_HEALTH: - if (HealthBelowPct(HealthCheck)) - me->CastSpell(me, SPELL_DISPERSE, false); - - events.Repeat(1s); - return; - case EVENT_CALL_SPARKS: - { - EntryCheckPredicate pred(NPC_SPARK_OF_IONAR); - summons.DoAction(ACTION_CALLBACK, pred); - events.ScheduleEvent(EVENT_RESTORE, 2s, 0, 2); - return; - } - case EVENT_RESTORE: - EntryCheckPredicate pred(NPC_SPARK_OF_IONAR); - summons.DoAction(ACTION_SPARK_DESPAWN, pred); - - me->SetVisible(true); - me->SetControlled(false, UNIT_STATE_STUNNED); - ScheduleEvents(true); - return; - } - - DoMeleeAttackIfReady(); - } - }; }; -class npc_spark_of_ionar : public CreatureScript +struct npc_spark_of_ionar : public ScriptedAI { -public: - npc_spark_of_ionar() : CreatureScript("npc_spark_of_ionar") { } + npc_spark_of_ionar(Creature* creature) : ScriptedAI(creature) { } - CreatureAI* GetAI(Creature* creature) const override + void MoveInLineOfSight(Unit*) override { } + void UpdateAI(uint32) override { } + void AttackStart(Unit* /*who*/) override { } + + void Reset() override { returning = false; } + + void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override { - return GetHallsOfLightningAI(creature); + damage = 0; } - struct npc_spark_of_ionarAI : public ScriptedAI + void DoAction(int32 param) override { - npc_spark_of_ionarAI(Creature* creature) : ScriptedAI(creature) { } + if (param == ACTION_CALLBACK) + { + me->SetSpeed(MOVE_RUN, 2.5f); + me->GetThreatMgr().ClearAllThreat(); + me->CombatStop(true); + me->GetMotionMaster()->MoveTargetedHome(); + returning = true; + } + else if (param == ACTION_SPARK_DESPAWN) + { + me->GetMotionMaster()->MoveIdle(); + me->RemoveAllAuras(); + me->CastSpell(me, SPELL_SPARK_DESPAWN, true); + me->DespawnOrUnsummon(1s); + } + } + + private: bool returning; - - void MoveInLineOfSight(Unit*) override { } - void UpdateAI(uint32) override { } - void AttackStart(Unit* /*who*/) override { } - - void Reset() override { returning = false; } - - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override - { - damage = 0; - } - - void DoAction(int32 param) override - { - if (param == ACTION_CALLBACK) - { - me->SetSpeed(MOVE_RUN, 2.5f); - me->GetThreatMgr().ClearAllThreat(); - me->CombatStop(true); - me->GetMotionMaster()->MoveTargetedHome(); - returning = true; - } - else if (param == ACTION_SPARK_DESPAWN) - { - me->GetMotionMaster()->MoveIdle(); - - me->RemoveAllAuras(); - me->CastSpell(me, SPELL_SPARK_DESPAWN, true); - me->DespawnOrUnsummon(1s); - } - } - }; }; // 52658, 59795 - Static Overload @@ -302,7 +282,7 @@ class spell_ionar_static_overload : public AuraScript void AddSC_boss_ionar() { - new boss_ionar(); - new npc_spark_of_ionar(); + RegisterHallOfLightningCreatureAI(boss_ionar); + RegisterHallOfLightningCreatureAI(npc_spark_of_ionar); RegisterSpellScript(spell_ionar_static_overload); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index 75c4c06d2..43f9d4d45 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -60,198 +60,187 @@ enum LokenEvents EVENT_AURA_REMOVE = 5 }; -class boss_loken : public CreatureScript +struct boss_loken : public BossAI { -public: - boss_loken() : CreatureScript("boss_loken") { } - - CreatureAI* GetAI(Creature* creature) const override + boss_loken(Creature* creature) : BossAI(creature, DATA_LOKEN) { - return GetHallsOfLightningAI(creature); + m_pInstance = creature->GetInstanceScript(); + if (m_pInstance) + isActive = m_pInstance->GetData(TYPE_LOKEN_INTRO); } - struct boss_lokenAI : public ScriptedAI + void MoveInLineOfSight(Unit*) override { } + + void Reset() override { - boss_lokenAI(Creature* creature) : ScriptedAI(creature) + events.Reset(); + if (m_pInstance) { - m_pInstance = creature->GetInstanceScript(); - if (m_pInstance) - isActive = m_pInstance->GetData(TYPE_LOKEN_INTRO); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); + m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); } + HealthCheck = 75; + IntroTimer = 0; + me->RemoveAllAuras(); + + if (!isActive) + { + me->SetControlled(true, UNIT_STATE_STUNNED); + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + } + else + { + me->SetControlled(false, UNIT_STATE_STUNNED); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + } + } + + void JustEngagedWith(Unit*) override + { + me->SetInCombatWithZone(); + Talk(SAY_AGGRO); + + events.ScheduleEvent(EVENT_ARC_LIGHTNING, 10s); + events.ScheduleEvent(EVENT_SHOCKWAVE, 3s); + events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 15s); + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); + + if (me->GetMap()->IsHeroic()) + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); + } + } + + void JustDied(Unit*) override + { + Talk(SAY_DEATH); + + if (m_pInstance) + m_pInstance->SetData(TYPE_LOKEN, DONE); + } + + void LokenSpeach(bool hp) + { + if (hp) + { + switch (HealthCheck) + { + case 75: + Talk(SAY_75HEALTH); + break; + case 50: + Talk(SAY_50HEALTH); + break; + case 25: + Talk(SAY_25HEALTH); + break; + } + } + else + Talk(SAY_NOVA); + } + + void KilledUnit(Unit* victim) override + { + if (!victim->IsPlayer()) + return; + + Talk(SAY_SLAY); + } + + void UpdateAI(uint32 diff) override + { + if (!isActive) + { + IntroTimer += diff; + if (IntroTimer > 5000 && IntroTimer < 10000) + { + if (SelectTargetFromPlayerList(60)) + { + Talk(SAY_INTRO_1); + IntroTimer = 10000; + } + else + IntroTimer = 0; + } + + if (IntroTimer >= 30000 && IntroTimer < 40000) + { + Talk(SAY_INTRO_2); + IntroTimer = 40000; + } + if (IntroTimer >= 60000) + { + isActive = true; + if (m_pInstance) + m_pInstance->SetData(TYPE_LOKEN_INTRO, 1); + + me->SetControlled(false, UNIT_STATE_STUNNED); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + + if (Player* target = SelectTargetFromPlayerList(80)) + AttackStart(target); + } + + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_CHECK_HEALTH: + if (HealthBelowPct(HealthCheck)) + { + LokenSpeach(true); + HealthCheck -= 25; + } + + events.Repeat(1s); + break; + case EVENT_LIGHTNING_NOVA: + events.Repeat(15s); + me->CastSpell(me, SPELL_LIGHTNING_NOVA_VISUAL, true); + me->CastSpell(me, SPELL_LIGHTNING_NOVA_THUNDERS, true); + + events.DelayEvents(5s); + events.ScheduleEvent(EVENT_AURA_REMOVE, me->GetMap()->IsHeroic() ? 4s : 5s); + + me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_LIGHTNING_NOVA_H : SPELL_LIGHTNING_NOVA_N, false); + break; + case EVENT_SHOCKWAVE: + me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_PULSING_SHOCKWAVE_H : SPELL_PULSING_SHOCKWAVE_N, false); + break; + case EVENT_ARC_LIGHTNING: + if (Unit* target = SelectTargetFromPlayerList(100, SPELL_ARC_LIGHTNING)) + me->CastSpell(target, SPELL_ARC_LIGHTNING, false); + + events.Repeat(12s); + break; + case EVENT_AURA_REMOVE: + me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS); + break; + } + + DoMeleeAttackIfReady(); + } + private: InstanceScript* m_pInstance; EventMap events; bool isActive; uint32 IntroTimer; uint8 HealthCheck; - - void MoveInLineOfSight(Unit*) override { } - - void Reset() override - { - events.Reset(); - if (m_pInstance) - { - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); - m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); - } - - HealthCheck = 75; - IntroTimer = 0; - me->RemoveAllAuras(); - - if (!isActive) - { - me->SetControlled(true, UNIT_STATE_STUNNED); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - } - } - - void JustEngagedWith(Unit*) override - { - me->SetInCombatWithZone(); - Talk(SAY_AGGRO); - - events.ScheduleEvent(EVENT_ARC_LIGHTNING, 10s); - events.ScheduleEvent(EVENT_SHOCKWAVE, 3s); - events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 15s); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); - - if (me->GetMap()->IsHeroic()) - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_TIMELY_DEATH); - } - } - - void JustDied(Unit*) override - { - Talk(SAY_DEATH); - - if (m_pInstance) - m_pInstance->SetData(TYPE_LOKEN, DONE); - } - - void LokenSpeach(bool hp) - { - if (hp) - { - switch (HealthCheck) - { - case 75: - Talk(SAY_75HEALTH); - break; - case 50: - Talk(SAY_50HEALTH); - break; - case 25: - Talk(SAY_25HEALTH); - break; - } - } - else - Talk(SAY_NOVA); - } - - void KilledUnit(Unit* victim) override - { - if (!victim->IsPlayer()) - return; - - Talk(SAY_SLAY); - } - - void UpdateAI(uint32 diff) override - { - if (!isActive) - { - IntroTimer += diff; - if (IntroTimer > 5000 && IntroTimer < 10000) - { - if (SelectTargetFromPlayerList(60)) - { - Talk(SAY_INTRO_1); - IntroTimer = 10000; - } - else - IntroTimer = 0; - } - - if (IntroTimer >= 30000 && IntroTimer < 40000) - { - Talk(SAY_INTRO_2); - IntroTimer = 40000; - } - if (IntroTimer >= 60000) - { - isActive = true; - if (m_pInstance) - m_pInstance->SetData(TYPE_LOKEN_INTRO, 1); - - me->SetControlled(false, UNIT_STATE_STUNNED); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - - if (Player* target = SelectTargetFromPlayerList(80)) - AttackStart(target); - } - - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_CHECK_HEALTH: - if (HealthBelowPct(HealthCheck)) - { - LokenSpeach(true); - HealthCheck -= 25; - } - - events.Repeat(1s); - break; - case EVENT_LIGHTNING_NOVA: - events.Repeat(15s); - me->CastSpell(me, SPELL_LIGHTNING_NOVA_VISUAL, true); - me->CastSpell(me, SPELL_LIGHTNING_NOVA_THUNDERS, true); - - events.DelayEvents(5s); - events.ScheduleEvent(EVENT_AURA_REMOVE, me->GetMap()->IsHeroic() ? 4s : 5s); - - me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_LIGHTNING_NOVA_H : SPELL_LIGHTNING_NOVA_N, false); - break; - case EVENT_SHOCKWAVE: - me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_PULSING_SHOCKWAVE_H : SPELL_PULSING_SHOCKWAVE_N, false); - break; - case EVENT_ARC_LIGHTNING: - if (Unit* target = SelectTargetFromPlayerList(100, SPELL_ARC_LIGHTNING)) - me->CastSpell(target, SPELL_ARC_LIGHTNING, false); - - events.Repeat(12s); - break; - case EVENT_AURA_REMOVE: - me->RemoveAura(SPELL_LIGHTNING_NOVA_THUNDERS); - break; - } - - DoMeleeAttackIfReady(); - } - }; }; class spell_loken_pulsing_shockwave : public SpellScript @@ -276,6 +265,6 @@ class spell_loken_pulsing_shockwave : public SpellScript void AddSC_boss_loken() { - new boss_loken(); + RegisterHallOfLightningCreatureAI(boss_loken); RegisterSpellScript(spell_loken_pulsing_shockwave); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 8d7c3dfdd..41bfd38d1 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -78,23 +78,228 @@ enum Yells EMOTE_SHATTER = 6, }; -class boss_volkhan : public CreatureScript +struct boss_volkhan : public BossAI { -public: - boss_volkhan() : CreatureScript("boss_volkhan") { } - - CreatureAI* GetAI(Creature* creature) const override + boss_volkhan(Creature* creature) : BossAI(creature, DATA_VOLKHAN), summons(creature) { - return GetHallsOfLightningAI(creature); + m_pInstance = creature->GetInstanceScript(); } - struct boss_volkhanAI : public ScriptedAI + void Reset() override { - boss_volkhanAI(Creature* creature) : ScriptedAI(creature), summons(creature) + x = y = z = PointID = ShatteredCount = 0; + HealthCheck = 100; + events.Reset(); + summons.DespawnAll(); + me->SetSpeed(MOVE_RUN, 1.2f, true); + me->SetReactState(REACT_AGGRESSIVE); + + if (m_pInstance) { - m_pInstance = creature->GetInstanceScript(); + m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); + m_pInstance->SetData(DATA_VOLKHAN_ACHIEVEMENT, true); + } + } + + void JustEngagedWith(Unit*) override + { + me->SetInCombatWithZone(); + Talk(SAY_AGGRO); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); + + ScheduleEvents(false); + } + + void JustDied(Unit*) override + { + Talk(SAY_DEATH); + + summons.DespawnAll(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, DONE); + } + + void GetNextPos() + { + if (me->GetPositionY() < -180) + { + if (me->GetPositionX() > 1330) + x = 1355; + else + x = 1308; + + y = -178; + z = 52.5f; + } + else if (me->GetPositionY() < -145) + { + if (me->GetPositionX() > 1330) + x = 1355; + else + x = 1308; + + y = -137; + z = 52.5f; + } + else if (me->GetPositionY() < -130) + { + if (me->GetPositionX() > 1330) + x = 1343; + else + x = 1320; + + y = -123; + z = 56.7f; + } + else + { + PointID = POINT_ANVIL; + x = 1327; + y = -96; + z = 56.7f; + } + } + + void KilledUnit(Unit* victim) override + { + if (!victim->IsPlayer()) + return; + + Talk(SAY_SLAY); + } + + void ScheduleEvents(bool anvil) + { + events.SetPhase(1); + events.RescheduleEvent(EVENT_HEAT, 8s, 0, 1); + events.RescheduleEvent(EVENT_SHATTER, 10s, 0, 1); + events.RescheduleEvent(EVENT_CHECK_HEALTH, anvil ? 1s : 6s, 0, 1); + events.RescheduleEvent(EVENT_POSITION, 4s, 0, 1); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + if (summon->GetEntry() == NPC_MOLTEN_GOLEM) + { + summon->SetFaction(me->GetFaction()); + + if (Unit* target = SelectTarget(SelectTargetMethod::Random)) + summon->AI()->AttackStart(target); + } + } + + void DoAction(int32 param) override + { + if (param == ACTION_DESTROYED) + { + ShatteredCount++; + if (ShatteredCount > 4) + m_pInstance->SetData(DATA_VOLKHAN_ACHIEVEMENT, false); + } + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == POINT_ANVIL) + { + me->SetSpeed(MOVE_RUN, 1.2f, true); + me->SetReactState(REACT_AGGRESSIVE); + me->CastSpell(me, SPELL_TEMPER, false); + PointID = 0; + ScheduleEvents(true); + + // update orientation at server + me->SetOrientation(2.19f); + + // and client + WorldPacket data; + me->BuildHeartBeatMsg(&data); + me->SendMessageToSet(&data, false); + me->SetControlled(true, UNIT_STATE_ROOT); + } + else + events.ScheduleEvent(EVENT_MOVE_TO_ANVIL, 0ms, 0, 2); + } + + void SpellHitTarget(Unit* /*who*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_TEMPER) + { + me->CastSpell(me, SPELL_SUMMON_MOLTEN_GOLEM, true); + me->CastSpell(me, SPELL_SUMMON_MOLTEN_GOLEM, true); + me->GetMotionMaster()->MoveChase(me->GetVictim()); + me->SetControlled(false, UNIT_STATE_ROOT); + } + } + + void GoToAnvil() + { + events.SetPhase(2); + HealthCheck -= 20; + me->SetSpeed(MOVE_RUN, 4.0f, true); + me->SetReactState(REACT_PASSIVE); + + Talk(SAY_FORGE); + + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + + events.ScheduleEvent(EVENT_MOVE_TO_ANVIL, 0ms, 0, 2); + } + + void UpdateAI(uint32 diff) override + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_HEAT: + me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_HEAT_H : SPELL_HEAT_N, true); + events.Repeat(8s); + break; + case EVENT_CHECK_HEALTH: + if (HealthBelowPct(HealthCheck)) + GoToAnvil(); + + events.Repeat(1s); + return; + case EVENT_SHATTER: + { + events.Repeat(10s); + summons.DoAction(ACTION_SHATTER); + break; + } + case EVENT_MOVE_TO_ANVIL: + GetNextPos(); + me->GetMotionMaster()->MovePoint(PointID, x, y, z); + return; + case EVENT_POSITION: + if (me->GetDistance(1331.9f, -106, 56) > 95) + EnterEvadeMode(); + else + events.Repeat(4s); + + return; } + DoMeleeAttackIfReady(); + } + + private: InstanceScript* m_pInstance; EventMap events; SummonList summons; @@ -102,312 +307,86 @@ public: float x, y, z; uint8 PointID; uint8 ShatteredCount; - - void Reset() override - { - x = y = z = PointID = ShatteredCount = 0; - HealthCheck = 100; - events.Reset(); - summons.DespawnAll(); - me->SetSpeed(MOVE_RUN, 1.2f, true); - me->SetReactState(REACT_AGGRESSIVE); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); - m_pInstance->SetData(DATA_VOLKHAN_ACHIEVEMENT, true); - } - } - - void JustEngagedWith(Unit*) override - { - me->SetInCombatWithZone(); - Talk(SAY_AGGRO); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); - - ScheduleEvents(false); - } - - void JustDied(Unit*) override - { - Talk(SAY_DEATH); - - summons.DespawnAll(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, DONE); - } - - void GetNextPos() - { - if (me->GetPositionY() < -180) - { - if (me->GetPositionX() > 1330) - x = 1355; - else - x = 1308; - - y = -178; - z = 52.5f; - } - else if (me->GetPositionY() < -145) - { - if (me->GetPositionX() > 1330) - x = 1355; - else - x = 1308; - - y = -137; - z = 52.5f; - } - else if (me->GetPositionY() < -130) - { - if (me->GetPositionX() > 1330) - x = 1343; - else - x = 1320; - - y = -123; - z = 56.7f; - } - else - { - PointID = POINT_ANVIL; - x = 1327; - y = -96; - z = 56.7f; - } - } - - void KilledUnit(Unit* victim) override - { - if (!victim->IsPlayer()) - return; - - Talk(SAY_SLAY); - } - - void ScheduleEvents(bool anvil) - { - events.SetPhase(1); - events.RescheduleEvent(EVENT_HEAT, 8s, 0, 1); - events.RescheduleEvent(EVENT_SHATTER, 10s, 0, 1); - events.RescheduleEvent(EVENT_CHECK_HEALTH, anvil ? 1s : 6s, 0, 1); - events.RescheduleEvent(EVENT_POSITION, 4s, 0, 1); - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - if (summon->GetEntry() == NPC_MOLTEN_GOLEM) - { - summon->SetFaction(me->GetFaction()); - - if (Unit* target = SelectTarget(SelectTargetMethod::Random)) - summon->AI()->AttackStart(target); - } - } - - void DoAction(int32 param) override - { - if (param == ACTION_DESTROYED) - { - ShatteredCount++; - if (ShatteredCount > 4) - m_pInstance->SetData(DATA_VOLKHAN_ACHIEVEMENT, false); - } - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == POINT_ANVIL) - { - me->SetSpeed(MOVE_RUN, 1.2f, true); - me->SetReactState(REACT_AGGRESSIVE); - me->CastSpell(me, SPELL_TEMPER, false); - PointID = 0; - ScheduleEvents(true); - - // update orientation at server - me->SetOrientation(2.19f); - - // and client - WorldPacket data; - me->BuildHeartBeatMsg(&data); - me->SendMessageToSet(&data, false); - me->SetControlled(true, UNIT_STATE_ROOT); - } - else - events.ScheduleEvent(EVENT_MOVE_TO_ANVIL, 0ms, 0, 2); - } - - void SpellHitTarget(Unit* /*who*/, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_TEMPER) - { - me->CastSpell(me, SPELL_SUMMON_MOLTEN_GOLEM, true); - me->CastSpell(me, SPELL_SUMMON_MOLTEN_GOLEM, true); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - me->SetControlled(false, UNIT_STATE_ROOT); - } - } - - void GoToAnvil() - { - events.SetPhase(2); - HealthCheck -= 20; - me->SetSpeed(MOVE_RUN, 4.0f, true); - me->SetReactState(REACT_PASSIVE); - - Talk(SAY_FORGE); - - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - - events.ScheduleEvent(EVENT_MOVE_TO_ANVIL, 0ms, 0, 2); - } - - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_HEAT: - me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_HEAT_H : SPELL_HEAT_N, true); - events.Repeat(8s); - break; - case EVENT_CHECK_HEALTH: - if (HealthBelowPct(HealthCheck)) - GoToAnvil(); - - events.Repeat(1s); - return; - case EVENT_SHATTER: - { - events.Repeat(10s); - summons.DoAction(ACTION_SHATTER); - break; - } - case EVENT_MOVE_TO_ANVIL: - GetNextPos(); - me->GetMotionMaster()->MovePoint(PointID, x, y, z); - return; - case EVENT_POSITION: - if (me->GetDistance(1331.9f, -106, 56) > 95) - EnterEvadeMode(); - else - events.Repeat(4s); - - return; - } - - DoMeleeAttackIfReady(); - } - }; }; -class npc_molten_golem : public CreatureScript +struct npc_molten_golem : public ScriptedAI { -public: - npc_molten_golem() : CreatureScript("npc_molten_golem") { } - - CreatureAI* GetAI(Creature* creature) const override + npc_molten_golem(Creature* creature) : ScriptedAI(creature) { - return GetHallsOfLightningAI(creature); + m_pInstance = creature->GetInstanceScript(); } - struct npc_molten_golemAI : public ScriptedAI + void Reset() override { - npc_molten_golemAI(Creature* creature) : ScriptedAI(creature) + events.Reset(); + events.ScheduleEvent(EVENT_BLAST, 7s); + events.ScheduleEvent(EVENT_IMMOLATION, 3s); + } + + void DamageTaken(Unit*, uint32& uiDamage, DamageEffectType, SpellSchoolMask) override + { + if (me->GetEntry() == NPC_BRITTLE_GOLEM) { - m_pInstance = creature->GetInstanceScript(); + uiDamage = 0; + return; } - EventMap events; - InstanceScript* m_pInstance; - - void Reset() override + if (uiDamage >= me->GetHealth()) { - events.Reset(); - events.ScheduleEvent(EVENT_BLAST, 7s); - events.ScheduleEvent(EVENT_IMMOLATION, 3s); + me->UpdateEntry(NPC_BRITTLE_GOLEM, 0, false); + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetHealth(me->GetMaxHealth()); + me->RemoveAllAuras(); + me->AttackStop(); + uiDamage = 0; + + if (me->IsNonMeleeSpellCast(false)) + me->InterruptNonMeleeSpells(false); + + me->SetControlled(true, UNIT_STATE_STUNNED); + } + } + + void DoAction(int32 param) override + { + if (me->GetEntry() == NPC_BRITTLE_GOLEM && param == ACTION_SHATTER) + { + if (Creature* volkhan = m_pInstance->GetCreature(DATA_VOLKHAN)) + volkhan->AI()->DoAction(ACTION_DESTROYED); + + me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_SHATTER_H : SPELL_SHATTER_N, true); + me->DespawnOrUnsummon(500ms); + } + } + + void UpdateAI(uint32 diff) override + { + //Return since we have no target or if we are frozen + if (!UpdateVictim() || me->GetEntry() == NPC_BRITTLE_GOLEM) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_BLAST: + me->CastSpell(me, SPELL_BLAST_WAVE, false); + events.Repeat(14s); + break; + case EVENT_IMMOLATION: + me->CastSpell(me->GetVictim(), me->GetMap()->IsHeroic() ? SPELL_IMMOLATION_STRIKE_H : SPELL_IMMOLATION_STRIKE_N, false); + events.Repeat(5s); + break; } - void DamageTaken(Unit*, uint32& uiDamage, DamageEffectType, SpellSchoolMask) override - { - if (me->GetEntry() == NPC_BRITTLE_GOLEM) - { - uiDamage = 0; - return; - } - - if (uiDamage >= me->GetHealth()) - { - me->UpdateEntry(NPC_BRITTLE_GOLEM, 0, false); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); - me->SetHealth(me->GetMaxHealth()); - me->RemoveAllAuras(); - me->AttackStop(); - uiDamage = 0; - - if (me->IsNonMeleeSpellCast(false)) - me->InterruptNonMeleeSpells(false); - - me->SetControlled(true, UNIT_STATE_STUNNED); - } - } - - void DoAction(int32 param) override - { - if (me->GetEntry() == NPC_BRITTLE_GOLEM && param == ACTION_SHATTER) - { - if (Creature* volkhan = ObjectAccessor::GetCreature(*me, m_pInstance->GetGuidData(TYPE_VOLKHAN))) - volkhan->AI()->DoAction(ACTION_DESTROYED); - - me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_SHATTER_H : SPELL_SHATTER_N, true); - me->DespawnOrUnsummon(500ms); - } - } - - void UpdateAI(uint32 diff) override - { - //Return since we have no target or if we are frozen - if (!UpdateVictim() || me->GetEntry() == NPC_BRITTLE_GOLEM) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_BLAST: - me->CastSpell(me, SPELL_BLAST_WAVE, false); - events.Repeat(14s); - break; - case EVENT_IMMOLATION: - me->CastSpell(me->GetVictim(), me->GetMap()->IsHeroic() ? SPELL_IMMOLATION_STRIKE_H : SPELL_IMMOLATION_STRIKE_N, false); - events.Repeat(5s); - break; - } - - DoMeleeAttackIfReady(); - } - }; + DoMeleeAttackIfReady(); + } +private: + EventMap events; + InstanceScript* m_pInstance; }; enum monumentSpells @@ -443,141 +422,127 @@ enum monumentEvents EVENT_UNFREEZE = 20, }; -class npc_hol_monument : public CreatureScript +struct npc_hol_monument : public ScriptedAI { -public: - npc_hol_monument() : CreatureScript("npc_hol_monument") {} - - CreatureAI* GetAI(Creature* creature) const override + npc_hol_monument(Creature* creature) : ScriptedAI(creature) { - return GetHallsOfLightningAI(creature); + _attackGUID.Clear(); + _isActive = urand(0, 1); + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + me->CastSpell(me, SPELL_FREEZE_ANIM, true); } - struct npc_hol_monumentAI : public ScriptedAI + void MoveInLineOfSight(Unit* who) override { - npc_hol_monumentAI(Creature* creature) : ScriptedAI(creature) + if (_attackGUID) + ScriptedAI::MoveInLineOfSight(who); + else if (_isActive && who->IsPlayer()) { - _attackGUID.Clear(); - _isActive = urand(0, 1); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->CastSpell(me, SPELL_FREEZE_ANIM, true); + if ((who->GetPositionX() < me->GetPositionX() || who->GetPositionY() < -220.0f) && me->GetDistance2d(who) < 40) + { + _isActive = false; + _attackGUID = who->GetGUID(); + events.Reset(); + events.RescheduleEvent(EVENT_UNFREEZE, 5s); + } + } + } + + void JustEngagedWith(Unit*) override + { + events.Reset(); + if (me->GetEntry() == 28961) // NPC_TITANIUM_SIEGEBREAKER + { + events.ScheduleEvent(EVENT_PIERCING_HOWL, 10s, 25s); + events.ScheduleEvent(EVENT_PENETRATING_STRIKE, 5s, 10s); + events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 20s, 28s); + events.ScheduleEvent(EVENT_BLADE_TURNING, 12s); + } + else + { + events.ScheduleEvent(EVENT_THROW, 10s, 25s); + events.ScheduleEvent(EVENT_DEADLY_THROW, 15s, 30s); + events.ScheduleEvent(EVENT_DEFLECTION, 15s); + } + } + + void AttackStart(Unit* who) override + { + if (!_attackGUID || !_isActive) + return; + ScriptedAI::AttackStart(who); + } + + void UpdateAI(uint32 diff) override + { + if (!_isActive && !_attackGUID) + return; + + events.Update(diff); + uint32 eventId = events.ExecuteEvent(); + + if (eventId == EVENT_UNFREEZE) + { + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + me->CastSpell(me, SPELL_AWAKEN, true); + me->RemoveAllAuras(); + _isActive = true; + if (Unit* target = ObjectAccessor::GetUnit(*me, _attackGUID)) + AttackStart(target); + return; } + //Return since we have no target or if we are disabled from fight + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (eventId) + { + case EVENT_PIERCING_HOWL: + me->CastSpell(me->GetVictim(), SPELL_PIERCING_HOWL, false); + events.Repeat(10s, 25s); + break; + case EVENT_PENETRATING_STRIKE: + me->CastSpell(me->GetVictim(), SPELL_PENETRATING_STRIKE, false); + events.Repeat(5s, 10s); + break; + case EVENT_FRIGHTENING_SHOUT: + me->CastSpell(me->GetVictim(), SPELL_FRIGHTENING_SHOUT, false); + events.Repeat(20s, 28s); + break; + case EVENT_BLADE_TURNING: + me->CastSpell(me->GetVictim(), me->GetMap()->IsHeroic() ? SPELL_BLADE_TURNING_H : SPELL_BLADE_TURNING_N, false); + events.Repeat(12s); + break; + case EVENT_THROW: + me->CastSpell(SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true, 0), me->GetMap()->IsHeroic() ? SPELL_THROW_H : SPELL_THROW_N, true); + events.Repeat(10s, 25s); + break; + case EVENT_DEADLY_THROW: + me->CastSpell(SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true, 0), me->GetMap()->IsHeroic() ? SPELL_DEADLY_THROW_H : SPELL_DEADLY_THROW_N, true); + events.Repeat(15s, 30s); + break; + case EVENT_DEFLECTION: + me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_DEFLECTION_H : SPELL_DEFLECTION_N, false); + events.Repeat(15s); + break; + } + + DoMeleeAttackIfReady(); + } + + private: EventMap events; bool _isActive; ObjectGuid _attackGUID; - - void Reset() override - { - } - - void MoveInLineOfSight(Unit* who) override - { - if (_attackGUID) - ScriptedAI::MoveInLineOfSight(who); - else if (_isActive && who->IsPlayer()) - { - if ((who->GetPositionX() < me->GetPositionX() || who->GetPositionY() < -220.0f) && me->GetDistance2d(who) < 40) - { - _isActive = false; - _attackGUID = who->GetGUID(); - events.Reset(); - events.RescheduleEvent(EVENT_UNFREEZE, 5s); - } - } - } - - void JustEngagedWith(Unit*) override - { - events.Reset(); - if (me->GetEntry() == 28961) // NPC_TITANIUM_SIEGEBREAKER - { - events.ScheduleEvent(EVENT_PIERCING_HOWL, 10s, 25s); - events.ScheduleEvent(EVENT_PENETRATING_STRIKE, 5s, 10s); - events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 20s, 28s); - events.ScheduleEvent(EVENT_BLADE_TURNING, 12s); - } - else - { - events.ScheduleEvent(EVENT_THROW, 10s, 25s); - events.ScheduleEvent(EVENT_DEADLY_THROW, 15s, 30s); - events.ScheduleEvent(EVENT_DEFLECTION, 15s); - } - } - - void AttackStart(Unit* who) override - { - if (!_attackGUID || !_isActive) - return; - ScriptedAI::AttackStart(who); - } - - void UpdateAI(uint32 diff) override - { - if (!_isActive && !_attackGUID) - return; - - events.Update(diff); - uint32 eventId = events.ExecuteEvent(); - - if (eventId == EVENT_UNFREEZE) - { - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->CastSpell(me, SPELL_AWAKEN, true); - me->RemoveAllAuras(); - _isActive = true; - if (Unit* target = ObjectAccessor::GetUnit(*me, _attackGUID)) - AttackStart(target); - return; - } - - //Return since we have no target or if we are disabled from fight - if (!UpdateVictim()) - return; - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (eventId) - { - case EVENT_PIERCING_HOWL: - me->CastSpell(me->GetVictim(), SPELL_PIERCING_HOWL, false); - events.Repeat(10s, 25s); - break; - case EVENT_PENETRATING_STRIKE: - me->CastSpell(me->GetVictim(), SPELL_PENETRATING_STRIKE, false); - events.Repeat(5s, 10s); - break; - case EVENT_FRIGHTENING_SHOUT: - me->CastSpell(me->GetVictim(), SPELL_FRIGHTENING_SHOUT, false); - events.Repeat(20s, 28s); - break; - case EVENT_BLADE_TURNING: - me->CastSpell(me->GetVictim(), me->GetMap()->IsHeroic() ? SPELL_BLADE_TURNING_H : SPELL_BLADE_TURNING_N, false); - events.Repeat(12s); - break; - case EVENT_THROW: - me->CastSpell(SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true, 0), me->GetMap()->IsHeroic() ? SPELL_THROW_H : SPELL_THROW_N, true); - events.Repeat(10s, 25s); - break; - case EVENT_DEADLY_THROW: - me->CastSpell(SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true, 0), me->GetMap()->IsHeroic() ? SPELL_DEADLY_THROW_H : SPELL_DEADLY_THROW_N, true); - events.Repeat(15s, 30s); - break; - case EVENT_DEFLECTION: - me->CastSpell(me, me->GetMap()->IsHeroic() ? SPELL_DEFLECTION_H : SPELL_DEFLECTION_N, false); - events.Repeat(15s); - break; - } - - DoMeleeAttackIfReady(); - } - }; }; void AddSC_boss_volkhan() { - new boss_volkhan(); - new npc_molten_golem(); - new npc_hol_monument(); + RegisterHallOfLightningCreatureAI(boss_volkhan); + RegisterHallOfLightningCreatureAI(npc_molten_golem); + RegisterHallOfLightningCreatureAI(npc_hol_monument); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h index dac581309..4851d2428 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h @@ -24,6 +24,15 @@ #define HallsOfLightningScriptName "instance_halls_of_lightning" +enum BossIds +{ + DATA_BJARNGRIM = 0, + DATA_IONAR = 1, + DATA_LOKEN = 2, + DATA_VOLKHAN = 3, + MAX_ENCOUNTERS +}; + enum HoLEvents { TYPE_BJARNGRIM = 0, @@ -60,4 +69,6 @@ inline AI* GetHallsOfLightningAI(T* obj) return GetInstanceAI(obj, HallsOfLightningScriptName); } +#define RegisterHallOfLightningCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetHallsOfLightningAI) + #endif diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp index 75954ab04..2caa5c539 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -32,35 +32,19 @@ public: struct instance_halls_of_lightning_InstanceMapScript : public InstanceScript { - instance_halls_of_lightning_InstanceMapScript(Map* pMap) : InstanceScript(pMap) { Initialize(); }; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - ObjectGuid m_uiGeneralBjarngrimGUID; - ObjectGuid m_uiIonarGUID; - ObjectGuid m_uiLokenGUID; - ObjectGuid m_uiVolkhanGUID; - - ObjectGuid m_uiBjarngrimDoorGUID; - ObjectGuid m_uiVolkhanDoorGUID; - ObjectGuid m_uiIonarDoorGUID; - ObjectGuid m_uiLokenDoorGUID; - ObjectGuid m_uiLokenGlobeGUID; - - bool volkhanAchievement; - bool bjarngrimAchievement; - - void Initialize() override + instance_halls_of_lightning_InstanceMapScript(Map* pMap) : InstanceScript(pMap) { SetHeaders(DataHeader); - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - + SetBossNumber(MAX_ENCOUNTERS); volkhanAchievement = false; bjarngrimAchievement = false; - } + }; bool IsEncounterInProgress() const override { + if (InstanceScript::IsEncounterInProgress()) + return true; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) { if (m_auiEncounter[i] == IN_PROGRESS && i != TYPE_LOKEN_INTRO) @@ -195,22 +179,22 @@ public: return m_auiEncounter[uiType]; } - ObjectGuid GetGuidData(uint32 uiData) const override - { - switch (uiData) - { - case TYPE_BJARNGRIM: - return m_uiGeneralBjarngrimGUID; - case TYPE_VOLKHAN: - return m_uiVolkhanGUID; - case TYPE_IONAR: - return m_uiIonarGUID; - case TYPE_LOKEN: - return m_uiLokenGUID; - } + private: + uint32 m_auiEncounter[MAX_ENCOUNTER]; - return ObjectGuid::Empty; - } + ObjectGuid m_uiGeneralBjarngrimGUID; + ObjectGuid m_uiIonarGUID; + ObjectGuid m_uiLokenGUID; + ObjectGuid m_uiVolkhanGUID; + + ObjectGuid m_uiBjarngrimDoorGUID; + ObjectGuid m_uiVolkhanDoorGUID; + ObjectGuid m_uiIonarDoorGUID; + ObjectGuid m_uiLokenDoorGUID; + ObjectGuid m_uiLokenGlobeGUID; + + bool volkhanAchievement; + bool bjarngrimAchievement; }; };