diff options
-rw-r--r-- | sql/updates/world/2015_02_18_00_world.sql | 4 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp | 243 |
2 files changed, 133 insertions, 114 deletions
diff --git a/sql/updates/world/2015_02_18_00_world.sql b/sql/updates/world/2015_02_18_00_world.sql new file mode 100644 index 00000000000..6a4c12347a3 --- /dev/null +++ b/sql/updates/world/2015_02_18_00_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=52654; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 52654, 0, 0, 31, 0, 3, 28823, 0, 0, 0, 0, '', 'Temper only target Volkhan\'s Anvil'); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index d653ec9e57d..e967f4aa8c5 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -29,7 +29,7 @@ EndScriptData */ #include "Player.h" #include "SpellInfo.h" -enum Enums +enum Texts { SAY_AGGRO = 0, SAY_FORGE = 1, @@ -38,29 +38,50 @@ enum Enums SAY_DEATH = 4, EMOTE_TO_ANVIL = 5, EMOTE_SHATTER = 6, +}; +enum Spells +{ SPELL_HEAT = 52387, SPELL_SHATTERING_STOMP = 52237, - SPELL_TEMPER = 52238, SPELL_TEMPER_DUMMY = 52654, - SPELL_SUMMON_MOLTEN_GOLEM = 52405, + SPELL_FORGE_VISUAL = 52654, // Molten Golem SPELL_BLAST_WAVE = 23113, SPELL_IMMOLATION_STRIKE = 52433, SPELL_SHATTER = 52429, +}; +enum Events +{ + EVENT_PAUSE = 1, + EVENT_SHATTERING_STOMP = 2, + EVENT_SHATTER = 3, + EVENT_FORGE_CAST = 4, + + // Molten Golem + EVENT_BLAST = 5, + EVENT_IMMOLATION = 6 +}; + +enum Npcs +{ NPC_VOLKHAN_ANVIL = 28823, NPC_MOLTEN_GOLEM = 28695, NPC_BRITTLE_GOLEM = 28681, - MAX_GOLEM = 2, - DATA_SHATTER_RESISTANT = 2042 }; +enum Phases +{ + PHASE_INTRO = 1, + PHASE_NORMAL +}; + /*###### ## Boss Volkhan ######*/ @@ -68,68 +89,44 @@ class boss_volkhan : public CreatureScript { public: boss_volkhan() : CreatureScript("boss_volkhan") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_volkhanAI>(creature); - } - - struct boss_volkhanAI : public ScriptedAI + + struct boss_volkhanAI : public BossAI { - boss_volkhanAI(Creature* creature) : ScriptedAI(creature) + boss_volkhanAI(Creature* creature) : BossAI(creature, DATA_VOLKHAN) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() { - m_bIsStriking = false; - m_bHasTemper = false; + m_bIsStriking = false; + m_bHasTemper = false; m_bCanShatterGolem = false; - - m_uiPause_Timer = 3500; - m_uiShatteringStomp_Timer = 0; - m_uiShatter_Timer = 5000; - m_uiDelay_Timer = 1000; - m_uiSummonPhase = 0; - GolemsShattered = 0; + m_uiDelay_Timer = 1000; + m_uiSummonPhase = 0; + GolemsShattered = 0; m_uiHealthAmountModifier = 1; } - InstanceScript* instance; - - GuidList m_lGolemGUIDList; - - bool m_bHasTemper; - bool m_bIsStriking; - bool m_bCanShatterGolem; - - uint8 GolemsShattered; - uint32 m_uiPause_Timer; - uint32 m_uiShatteringStomp_Timer; - uint32 m_uiShatter_Timer; - uint32 m_uiDelay_Timer; - uint32 m_uiSummonPhase; - - uint32 m_uiHealthAmountModifier; - void Reset() override { Initialize(); - + _Reset(); DespawnGolem(); m_lGolemGUIDList.clear(); - - instance->SetBossState(DATA_VOLKHAN, NOT_STARTED); + events.SetPhase(PHASE_INTRO); + events.ScheduleEvent(EVENT_FORGE_CAST, 2 * IN_MILLISECONDS, 0, PHASE_INTRO); } void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - - instance->SetBossState(DATA_VOLKHAN, IN_PROGRESS); + events.SetPhase(PHASE_NORMAL); + events.ScheduleEvent(EVENT_PAUSE, 3.5 * IN_MILLISECONDS, 0, PHASE_NORMAL); + events.ScheduleEvent(EVENT_SHATTERING_STOMP, 0 * IN_MILLISECONDS, 0, PHASE_NORMAL); + events.ScheduleEvent(EVENT_SHATTER, 5 * IN_MILLISECONDS, 0, PHASE_NORMAL); + _EnterCombat(); } void AttackStart(Unit* who) override @@ -150,7 +147,7 @@ public: Talk(SAY_DEATH); DespawnGolem(); - instance->SetBossState(DATA_VOLKHAN, DONE); + _JustDied(); } void KilledUnit(Unit* who) override @@ -224,59 +221,61 @@ public: return 0; } - void UpdateAI(uint32 uiDiff) override + void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + // Return since we have no target and are in CombatPhase + if (events.IsInPhase(PHASE_NORMAL) && !UpdateVictim()) return; - if (m_bIsStriking) - { - if (m_uiPause_Timer <= uiDiff) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) - if (me->GetVictim()) - me->GetMotionMaster()->MoveChase(me->GetVictim()); - - m_bHasTemper = false; - m_bIsStriking = false; - m_uiPause_Timer = 3500; - } - else - m_uiPause_Timer -= uiDiff; + events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) return; - } - // When to start shatter? After 60, 40 or 20% hp? - if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) + while (uint32 eventId = events.ExecuteEvent()) { - if (m_uiShatteringStomp_Timer <= uiDiff) + switch (eventId) { - // Should he stomp even if he has no brittle golem to shatter? - Talk(SAY_STOMP); - - DoCast(me, SPELL_SHATTERING_STOMP); + case EVENT_PAUSE: + if (m_bIsStriking) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) + if (me->GetVictim()) + me->GetMotionMaster()->MoveChase(me->GetVictim()); - Talk(EMOTE_SHATTER); + m_bHasTemper = false; + m_bIsStriking = false; + events.ScheduleEvent(EVENT_PAUSE, 3.5 * IN_MILLISECONDS, 0, PHASE_NORMAL); + } + break; + case EVENT_SHATTERING_STOMP: + if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) + { + // Should he stomp even if he has no brittle golem to shatter? + Talk(SAY_STOMP); - m_uiShatteringStomp_Timer = 30000; - m_bCanShatterGolem = true; - } - else - m_uiShatteringStomp_Timer -= uiDiff; - } + DoCast(me, SPELL_SHATTERING_STOMP); - // Shatter Golems 3 seconds after Shattering Stomp - if (m_bCanShatterGolem) - { - if (m_uiShatter_Timer <= uiDiff) - { - ShatterGolem(); - m_uiShatter_Timer = 3000; - m_bCanShatterGolem = false; + Talk(EMOTE_SHATTER); + events.ScheduleEvent(EVENT_SHATTERING_STOMP, 30 * IN_MILLISECONDS, 0, PHASE_NORMAL); + m_bCanShatterGolem = true; + } + break; + case EVENT_SHATTER: + if (m_bCanShatterGolem) + { + ShatterGolem(); + events.ScheduleEvent(EVENT_SHATTER, 3 * IN_MILLISECONDS, 0, PHASE_NORMAL); + m_bCanShatterGolem = false; + } + break; + case EVENT_FORGE_CAST: + DoCast(me, SPELL_FORGE_VISUAL); + events.ScheduleEvent(EVENT_FORGE_CAST, 15 * IN_MILLISECONDS, 0, PHASE_INTRO); + break; + default: + break; } - else - m_uiShatter_Timer -= uiDiff; } // Health check @@ -302,12 +301,10 @@ public: me->GetMotionMaster()->MoveTargetedHome(); m_uiSummonPhase = 2; // Set Next Phase break; - case 2: // 2 - Check if reached Anvil // This is handled in: void JustReachedHome() override break; - case 3: // 3 - Cast Temper on the Anvil if (Unit* target = GetClosestCreatureWithEntry(me, NPC_VOLKHAN_ANVIL, 1000.0f, true)) @@ -319,10 +316,9 @@ public: m_uiDelay_Timer = 1000; // Delay 2 seconds before next phase can begin m_uiSummonPhase = 4; // Set Next Phase break; - case 4: // 4 - Wait for delay to expire - if (m_uiDelay_Timer <= uiDiff) + if (m_uiDelay_Timer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) { @@ -333,9 +329,8 @@ public: m_uiSummonPhase = 5; } else - m_uiDelay_Timer -= uiDiff; + m_uiDelay_Timer -= diff; break; - case 5: // 5 - Spawn the Golems if (Creature* creatureTarget = GetClosestCreatureWithEntry(me, NPC_VOLKHAN_ANVIL, 1000.0f, true)) @@ -349,13 +344,30 @@ public: DoMeleeAttackIfReady(); } + + private: + GuidList m_lGolemGUIDList; + uint32 m_uiHealthAmountModifier; + uint8 GolemsShattered; + uint32 m_uiDelay_Timer; + uint32 m_uiSummonPhase; + + bool m_bHasTemper; + bool m_bIsStriking; + bool m_bCanShatterGolem; }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_volkhanAI>(creature); + } + }; /*###### ## npc_molten_golem ######*/ + class npc_molten_golem : public CreatureScript { public: @@ -376,18 +388,12 @@ public: void Initialize() { m_bIsFrozen = false; - - m_uiBlast_Timer = 20000; - m_uiDeathDelay_Timer = 0; - m_uiImmolation_Timer = 5000; + events.ScheduleEvent(EVENT_BLAST, 20 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_IMMOLATION, 5 * IN_MILLISECONDS); } bool m_bIsFrozen; - uint32 m_uiBlast_Timer; - uint32 m_uiDeathDelay_Timer; - uint32 m_uiImmolation_Timer; - void Reset() override { Initialize(); @@ -433,30 +439,39 @@ public: me->DespawnOrUnsummon(); } - void UpdateAI(uint32 uiDiff) override + void UpdateAI(uint32 diff) override { // Return since we have no target or if we are frozen if (!UpdateVictim() || m_bIsFrozen) return; - if (m_uiBlast_Timer <= uiDiff) - { - DoCast(me, SPELL_BLAST_WAVE); - m_uiBlast_Timer = 20000; - } - else - m_uiBlast_Timer -= uiDiff; + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (m_uiImmolation_Timer <= uiDiff) + while (uint32 eventId = events.ExecuteEvent()) { - DoCastVictim(SPELL_IMMOLATION_STRIKE); - m_uiImmolation_Timer = 5000; + switch (eventId) + { + case EVENT_BLAST: + DoCast(me, SPELL_BLAST_WAVE); + events.ScheduleEvent(EVENT_BLAST, 20 * IN_MILLISECONDS); + break; + case EVENT_IMMOLATION: + DoCastVictim(SPELL_IMMOLATION_STRIKE); + events.ScheduleEvent(EVENT_BLAST, 5 * IN_MILLISECONDS); + break; + default: + break; + } } - else - m_uiImmolation_Timer -= uiDiff; DoMeleeAttackIfReady(); } + + private: + EventMap events; }; }; |