aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/2014_08_28_03_world_ulduar.sql106
-rw-r--r--src/server/game/Spells/SpellMgr.cpp10
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp1385
3 files changed, 1501 insertions, 0 deletions
diff --git a/sql/updates/world/2014_08_28_03_world_ulduar.sql b/sql/updates/world/2014_08_28_03_world_ulduar.sql
new file mode 100644
index 00000000000..6405efd18f7
--- /dev/null
+++ b/sql/updates/world/2014_08_28_03_world_ulduar.sql
@@ -0,0 +1,106 @@
+--
+DELETE FROM `vehicle_template_accessory` WHERE `entry` IN (33651, 33432);
+INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`) VALUES
+(33651, 34050, 5, 1, 'VX-001 Rocket Seat 6', 8),
+(33651, 34050, 6, 1, 'VX-001 Rocket Seat 7', 8),
+(33432, 34071, 3, 1, 'MKII MKII turret Seat 1', 8);
+
+DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (33651, 33432);
+INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES
+(33651, 46598, 1, 1),
+(33432, 46598, 1, 1);
+
+UPDATE `creature_template` SET `HoverHeight` = 15, `ScriptName` = 'boss_aerial_command_unit', `InhabitType` = 4, `mechanic_immune_mask` = 646135679 WHERE `entry` = 33670;
+UPDATE `creature_template` SET `HoverHeight` = 15, `InhabitType` = 4, `mechanic_immune_mask` = 646135679 WHERE `entry` = 34109;
+UPDATE `creature_template` SET `unit_flags` = 33554438, `ScriptName` = 'boss_vx_001', `mechanic_immune_mask` = 646135679 WHERE `entry` = 33651;
+UPDATE `creature_template` SET `unit_flags` = 33554438, `mechanic_immune_mask` = 646135679 WHERE `entry` = 34108;
+UPDATE `creature_template` SET `ScriptName` = 'boss_leviathan_mk_ii', `mechanic_immune_mask` = 646135679 WHERE `entry` = 33432;
+UPDATE `creature_template` SET `mechanic_immune_mask` = 646135679 WHERE `entry` = 34106;
+UPDATE `creature_template` SET `InhabitType` = 4, `ScriptName` = 'boss_mimiron' WHERE `entry` = 33350;
+UPDATE `creature_template` SET `unit_flags` = 131078, `ScriptName` = 'npc_mimiron_proximity_mine' WHERE `entry` = 34362;
+UPDATE `creature_template` SET `unit_flags` = 33685510, `faction` = 14, `ScriptName` = 'npc_mimiron_frost_bomb' WHERE `entry` = 34149;
+UPDATE `creature_template` SET `unit_flags` = 33685510 WHERE `entry` IN( 34047, 34110, 34050, 34071);
+UPDATE `creature_template` SET `unit_flags` = 33685510, `ScriptName` = 'npc_magnetic_core' WHERE `entry` = 34068;
+UPDATE `creature_template` SET `unit_flags` = 33554436, `ScriptName` = 'npc_mimiron_flames' WHERE `entry` IN (34363, 34121);
+UPDATE `creature_template` SET `faction` = 14 , `ScriptName` = 'npc_mimiron_emergency_fire_bot' WHERE `entry` = 34147;
+UPDATE `creature_template` SET `faction` = 14 WHERE `entry` IN (34148, 34114, 33855);
+UPDATE `creature_template` SET `ScriptName` = 'npc_mimiron_assault_bot' WHERE `entry` = 34057;
+UPDATE `creature_template` SET `ScriptName` = 'npc_mimiron_computer' WHERE `entry` = 34143;
+UPDATE `creature_template` SET `speed_walk` = 2.5 , `speed_run` = 4.5 , `MovementType` = 2 , `InhabitType` = 7 WHERE `entry` = 33576;
+
+UPDATE `creature_model_info` SET `bounding_radius` = 0.31 , `combat_reach` = 5 WHERE `modelid` = 28979;
+UPDATE `creature_model_info` SET `bounding_radius` = 0.306 , `combat_reach` = 7 WHERE `modelid` = 28841;
+UPDATE `creature_model_info` SET `bounding_radius` = 0.31 , `combat_reach` = 7.7 WHERE `modelid` = 28831;
+
+UPDATE `gameobject_template` SET `flags` = 32, `ScriptName` = 'go_mimiron_hardmode_button' WHERE `entry` = 194739;
+
+UPDATE `creature_addon` SET `path_id` = 1376200 WHERE `guid` = 137620;
+
+UPDATE `creature` SET `position_x` = 2785.423 , `position_y` = 2673.119, `MovementType` = 2 WHERE `guid` = 137620;
+DELETE FROM `creature` WHERE `id` = 34071;
+
+
+DELETE FROM `creature_template_addon` WHERE `entry` IN (34047, 34148, 33836, 34149, 34147, 33670, 34363, 34121, 34109);
+INSERT INTO `creature_template_addon` (`entry`, `bytes1`, `bytes2`, `auras`) VALUES
+(33670, 50331648, 1, ''),
+(34109, 50331648, 1, ''),
+(34363, 0, 1, '64561'),
+(34121, 0, 1, '64561'),
+(34047, 0, 1, '64064'),
+(34148, 0, 1, '64616 64617'),
+(33836, 0, 1, '63767'),
+(34149, 0, 1, '64624'),
+(34147, 0, 1, '64617');
+
+DELETE FROM `creature_text` WHERE `entry` = 34143;
+INSERT INTO `creature_text` (`entry`, `groupid`, `text`, `type`, `probability`, `sound`, `BroadcastTextID`) VALUES
+(34143, 0, 'Self-destruct sequence initiated.', 14, 100, 15413, 34268),
+(34143, 1, 'Self-destruct sequence terminated. Override code A905..', 14, 100, 15414, 34284),
+(34143, 2, 'This area will self-destruct in ten minutes.', 14, 100, 15415, 34283),
+(34143, 3, 'This area will self-destruct in nine minutes.', 14, 100, 15416, 34282),
+(34143, 4, 'This area will self-destruct in eight minutes.', 14, 100, 15417, 34281),
+(34143, 5, 'This area will self-destruct in seven minutes.', 14, 100, 15418, 34280),
+(34143, 6, 'This area will self-destruct in six minutes.', 14, 100, 15419, 34273),
+(34143, 7, 'This area will self-destruct in five minutes.', 14, 100, 15420, 34274),
+(34143, 8, 'This area will self-destruct in four minutes.', 14, 100, 15421, 34275),
+(34143, 9, 'This area will self-destruct in three minutes.', 14, 100, 15422, 34276),
+(34143, 10, 'This area will self-destruct in two minutes.', 14, 100, 15423, 34277),
+(34143, 11, 'This area will self-destruct in one minute.', 14, 100, 15424, 34278),
+(34143, 12, 'Self-destruct sequence finalized. Have a nice day.', 14, 100, 15425, 34279);
+
+DELETE FROM `waypoint_data` WHERE `id` = 1376200;
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+(1376200, 0, 2785.423, 2673.119, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 1, 2823.024, 2649.059, 371.9791, 0, 0, 1, 0, 100, 0),
+(1376200, 2, 2854.097, 2590.826, 371.9791, 0, 0, 1, 0, 100, 0),
+(1376200, 3, 2852.951, 2547.112, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 4, 2822.796, 2489.515, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 5, 2784.964, 2465.247, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 6, 2741.24, 2456.771, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 7, 2701.036, 2464.319, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 8, 2660.476, 2489.578, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 9, 2636.893, 2525.687, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 10, 2631.294, 2547.831, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 11, 2631.437, 2591.752, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 12, 2637.362, 2613.7, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 13, 2650.221, 2636.163, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 14, 2661.572, 2649.715, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 15, 2696.595, 2672.664, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 16, 2711.099, 2677.791, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 17, 2740.676, 2683.12, 372.3605, 0, 0, 1, 0, 100, 0),
+(1376200, 18, 2771.834, 2677.767, 372.3605, 0, 0, 1, 0, 100, 0);
+
+DELETE FROM `disables` WHERE `sourceType` = 4 AND `entry` IN (10544, 10547, 10543, 10546, 10548, 10545, 10450, 10463, 10406, 10405);
+
+DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10406, 10405) AND `type` = 18;
+DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10545,10548,10546,10543,10547,10544, 10450, 10463) AND `type` = 11;
+INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES
+(10544, 11, 0, 0, 'achievement_setup_rocket'),
+(10547, 11, 0, 0, 'achievement_setup_rocket'),
+(10543, 11, 0, 0, 'achievement_setup_mine'),
+(10546, 11, 0, 0, 'achievement_setup_mine'),
+(10548, 11, 0, 0, 'achievement_setup_boom'),
+(10545, 11, 0, 0, 'achievement_setup_boom'),
+(10450, 11, 0, 0, 'achievement_firefighter'),
+(10463, 11, 0, 0, 'achievement_firefighter');
+--
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index bc97744fe32..8e0c8c8bd01 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3350,6 +3350,16 @@ void SpellMgr::LoadSpellInfoCorrections()
// that will be clear if we get more spells with problem like this
spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY;
break;
+ case 63414: // Spinning Up (Mimiron)
+ spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER);
+ spellInfo->ChannelInterruptFlags = 0;
+ break;
+ case 63036: // Rocket Strike (Mimiron)
+ spellInfo->Speed = 0;
+ break;
+ case 64668: // Magnetic Field (Mimiron)
+ spellInfo->Mechanic = MECHANIC_NONE;
+ break;
case 64468: // Empowering Shadows (Yogg-Saron)
case 64486: // Empowering Shadows (Yogg-Saron)
spellInfo->MaxAffectedTargets = 3; // same for both modes?
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 69240866742..f1d44e72684 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -316,6 +316,17 @@ enum Phases
PHASE_AERIAL_ASSEMBLED
};
+enum Waypoints
+{
+ WP_MKII_P1_IDLE = 1,
+ WP_MKII_P4_POS_1,
+ WP_MKII_P4_POS_2,
+ WP_MKII_P4_POS_3,
+ WP_MKII_P4_POS_4,
+ WP_MKII_P4_POS_5,
+ WP_AERIAL_P4_POS
+};
+
uint32 const RepairSpells[4] =
{
SPELL_SEAT_1,
@@ -324,6 +335,1317 @@ uint32 const RepairSpells[4] =
SPELL_SEAT_5
};
+Position const VehicleRelocation[] =
+{
+ { 0.0f, 0.0f, 0.0f},
+ { 2792.070f, 2596.320f, 364.3136f }, // WP_MKII_P1_IDLE
+ { 2765.945f, 2571.095f, 364.0636f }, // WP_MKII_P4_POS_1
+ { 2768.195f, 2573.095f, 364.0636f }, // WP_MKII_P4_POS_2
+ { 2763.820f, 2568.870f, 364.3136f }, // WP_MKII_P4_POS_3
+ { 2761.215f, 2568.875f, 364.0636f }, // WP_MKII_P4_POS_4
+ { 2744.610f, 2569.380f, 364.3136f }, // WP_MKII_P4_POS_5
+ { 2748.513f, 2569.051f, 364.3136f } // WP_AERIAL_P4_POS
+};
+
+Position const VX001SummonPos = { 2744.431f, 2569.385f, 364.3968f, 3.141593f };
+Position const ACUSummonPos = { 2744.650f, 2569.460f, 380.0000f, 0.0f };
+
+static bool IsEncounterFinished(Unit* who)
+{
+ InstanceScript* instance = who->GetInstanceScript();
+
+ Creature* mkii = ObjectAccessor::GetCreature(*who, instance->GetData64(DATA_LEVIATHAN_MK_II));
+ Creature* vx001 = ObjectAccessor::GetCreature(*who, instance->GetData64(DATA_VX_001));
+ Creature* aerial = ObjectAccessor::GetCreature(*who, instance->GetData64(DATA_AERIAL_COMMAND_UNIT));
+ if (!mkii || !vx001 || !aerial)
+ return false;
+
+ if (mkii->getStandState() == UNIT_STAND_STATE_DEAD &&
+ vx001->getStandState() == UNIT_STAND_STATE_DEAD &&
+ aerial->getStandState() == UNIT_STAND_STATE_DEAD)
+ {
+ who->Kill(mkii);
+ who->Kill(vx001);
+ who->Kill(aerial);
+ mkii->DespawnOrUnsummon(120000);
+ vx001->DespawnOrUnsummon(120000);
+ aerial->DespawnOrUnsummon(120000);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*who, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->JustDied(who);
+ return true;
+ }
+ return false;
+}
+
+class boss_mimiron : public CreatureScript
+{
+ public:
+ boss_mimiron() : CreatureScript("boss_mimiron") { }
+
+ struct boss_mimironAI : public BossAI
+ {
+ boss_mimironAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _fireFighter = false;
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_ACTIVATE_VX001:
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_1, 1000);
+ break;
+ case DO_ACTIVATE_AERIAL:
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_1, 5000);
+ break;
+ case DO_ACTIVATE_V0L7R0N_1:
+ Talk(SAY_AERIAL_DEATH);
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_1, VehicleRelocation[WP_MKII_P4_POS_1]);
+ break;
+ case DO_ACTIVATE_V0L7R0N_2:
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_1, 1000);
+ break;
+ case DO_ACTIVATE_HARD_MODE:
+ _fireFighter = true;
+ DoZoneInCombat(me);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ if (!me->GetVehicleBase())
+ return;
+
+ _EnterCombat();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->RemoveAurasDueToSpell(SPELL_WELD);
+ DoCast(me->GetVehicleBase(), SPELL_SEAT_6);
+
+ if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON)))
+ button->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+
+ if (_fireFighter)
+ events.ScheduleEvent(EVENT_SUMMON_FLAMES, 3000);
+ events.ScheduleEvent(EVENT_INTRO_1, 1500);
+ }
+
+ void JustDied(Unit* /*who*/) override
+ {
+ instance->SetBossState(BOSS_MIMIRON, DONE);
+ events.Reset();
+ me->CombatStop(true);
+ me->SetDisableGravity(false);
+ DoCast(me, SPELL_SLEEP_VISUAL_1);
+ DoCastAOE(SPELL_DESPAWN_ASSAULT_BOTS);
+ me->ExitVehicle();
+ // ExitVehicle() offset position is not implemented, so we make up for that with MoveJump()...
+ me->GetMotionMaster()->MoveJump(me->GetPositionX() + (10.f * std::cos(me->GetOrientation())), me->GetPositionY() + (10.f * std::sin(me->GetOrientation())), me->GetPositionZ(), 10.f, 5.f);
+ events.ScheduleEvent(EVENT_OUTTRO_1, 7000);
+ }
+
+ void Reset() override
+ {
+ if (instance->GetBossState(BOSS_MIMIRON) == DONE) // Mimiron will attempt to reset because he is not dead and will be set to friendly before despawning.
+ return;
+
+ _Reset();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_ACTIVE);
+
+ if (_fireFighter)
+ if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER)))
+ computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER);
+
+ if (GameObject* button = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_MIMIRON_BUTTON)))
+ {
+ button->SetGoState(GO_STATE_READY);
+ button->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ }
+
+ _fireFighter = false;
+ DoCast(me, SPELL_WELD);
+
+ if (Unit* mkii = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ DoCast(mkii, SPELL_SEAT_3);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if ((!UpdateVictim() || !CheckInRoom()) && instance->GetBossState(BOSS_MIMIRON) != DONE)
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SUMMON_FLAMES:
+ if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER)))
+ worldtrigger->CastCustomSpell(SPELL_SCRIPT_EFFECT_SUMMON_FLAMES_INITIAL, SPELLVALUE_MAX_TARGETS, 3, NULL, true, NULL, NULL, me->GetGUID());
+ events.RescheduleEvent(EVENT_SUMMON_FLAMES, 28000);
+ break;
+ case EVENT_INTRO_1:
+ Talk(_fireFighter ? SAY_HARDMODE_ON : SAY_MKII_ACTIVATE);
+ events.ScheduleEvent(EVENT_INTRO_2, 5000);
+ break;
+ case EVENT_INTRO_2:
+ if (Unit* mkii = me->GetVehicleBase())
+ {
+ DoCast(mkii, SPELL_SEAT_7);
+ mkii->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM);
+ mkii->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ }
+ events.ScheduleEvent(EVENT_INTRO_3, 2000);
+ break;
+ case EVENT_INTRO_3:
+ if (Creature* mkii = me->GetVehicleCreatureBase())
+ mkii->AI()->DoAction(_fireFighter ? DO_HARDMODE_MKII : DO_START_MKII);
+ break;
+ case EVENT_VX001_ACTIVATION_1:
+ if (Unit* mkii = me->GetVehicleBase())
+ mkii->SetFacingTo(3.686f); // fix magic number
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_2, 1000);
+ break;
+ case EVENT_VX001_ACTIVATION_2:
+ if (Unit* mkii = me->GetVehicleBase())
+ DoCast(mkii, SPELL_SEAT_6);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_3, 1000);
+ break;
+ case EVENT_VX001_ACTIVATION_3:
+ Talk(SAY_MKII_DEATH);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_4, 5000);
+ break;
+ case EVENT_VX001_ACTIVATION_4:
+ instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_READY);
+ if (Unit* worldtrigger = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_MIMIRON_WORLD_TRIGGER)))
+ worldtrigger->CastSpell(worldtrigger, SPELL_ELEVATOR_KNOCKBACK);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_5, 6000);
+ break;
+ case EVENT_VX001_ACTIVATION_5:
+ if (Creature* vx001 = me->SummonCreature(NPC_VX_001, VX001SummonPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000))
+ vx001->CastSpell(vx001, SPELL_FREEZE_ANIM);
+ instance->SetData(DATA_MIMIRON_ELEVATOR, GO_STATE_ACTIVE_ALTERNATIVE);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_6, 19000);
+ break;
+ case EVENT_VX001_ACTIVATION_6:
+ if (Unit* vx001 = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_VX_001)))
+ DoCast(vx001, SPELL_SEAT_1);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_7, 3500);
+ break;
+ case EVENT_VX001_ACTIVATION_7:
+ Talk(SAY_VX001_ACTIVATE);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_8, 4000);
+ break;
+ case EVENT_VX001_ACTIVATION_8:
+ if (Unit* vx001 = me->GetVehicleBase())
+ DoCast(vx001, SPELL_SEAT_2);
+ events.ScheduleEvent(EVENT_VX001_ACTIVATION_9, 3000);
+ break;
+ case EVENT_VX001_ACTIVATION_9:
+ if (Creature* vx001 = me->GetVehicleCreatureBase())
+ vx001->AI()->DoAction(_fireFighter ? DO_HARDMODE_VX001 : DO_START_VX001);
+ break;
+ case EVENT_AERIAL_ACTIVATION_1:
+ if (Unit* mkii = me->GetVehicleBase())
+ DoCast(mkii, SPELL_SEAT_5);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_2, 2500);
+ break;
+ case EVENT_AERIAL_ACTIVATION_2:
+ Talk(SAY_VX001_DEATH);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_3, 5000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_3:
+ me->SummonCreature(NPC_AERIAL_COMMAND_UNIT, ACUSummonPos, TEMPSUMMON_MANUAL_DESPAWN);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_4, 5000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_4:
+ if (Unit* aerial = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)))
+ me->CastSpell(aerial, SPELL_SEAT_1);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_5, 2000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_5:
+ Talk(SAY_AERIAL_ACTIVATE);
+ events.ScheduleEvent(EVENT_AERIAL_ACTIVATION_6, 8000);
+ break;
+ case EVENT_AERIAL_ACTIVATION_6:
+ if (Creature* acu = me->GetVehicleCreatureBase())
+ acu->GetAI()->DoAction(_fireFighter? DO_HARDMODE_AERIAL : DO_START_AERIAL);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_1:
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ mkii->SetFacingTo(float(M_PI));
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_2, 1000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_2:
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ {
+ if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001)))
+ {
+ vx001->RemoveAurasDueToSpell(SPELL_TORSO_DISABLED);
+ vx001->CastSpell(mkii, SPELL_MOUNT_MKII);
+ }
+ }
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_3, 4500);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_3:
+ if (Creature* mkii = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_LEVIATHAN_MK_II)))
+ mkii->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_4, VehicleRelocation[WP_MKII_P4_POS_4]);
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_4, 5000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_4:
+ if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001)))
+ {
+ if (Creature* aerial = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AERIAL_COMMAND_UNIT)))
+ {
+ aerial->GetMotionMaster()->MoveLand(0, (aerial->GetPositionX(), aerial->GetPositionY(), aerial->GetPositionZMinusOffset()));
+ aerial->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
+ aerial->CastSpell(vx001, SPELL_MOUNT_VX_001);
+ aerial->CastSpell(aerial, SPELL_HALF_HEAL);
+ }
+ }
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_5, 4000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_5:
+ Talk(SAY_V07TRON_ACTIVATE);
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_6, 3000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_6:
+ if (Creature* vx001 = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_VX_001)))
+ DoCast(vx001, SPELL_SEAT_2);
+ events.ScheduleEvent(EVENT_VOL7RON_ACTIVATION_7, 5000);
+ break;
+ case EVENT_VOL7RON_ACTIVATION_7:
+ for (uint8 data = DATA_LEVIATHAN_MK_II; data <= DATA_AERIAL_COMMAND_UNIT; ++data)
+ if (Creature* mimironVehicle = ObjectAccessor::GetCreature(*me, instance->GetData64(data)))
+ mimironVehicle->AI()->DoAction(DO_ASSEMBLED_COMBAT);
+ break;
+ case EVENT_OUTTRO_1:
+ me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1);
+ DoCast(me, SPELL_SLEEP_VISUAL_2);
+ me->setFaction(35);
+ events.ScheduleEvent(EVENT_OUTTRO_2, 3000);
+ break;
+ case EVENT_OUTTRO_2:
+ Talk(SAY_V07TRON_DEATH);
+ if (_fireFighter)
+ {
+ if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_COMPUTER)))
+ computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER);
+ me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, 0.f, 0.f, 0.9999619f, 0.008734641f, 604800);
+ }
+ else
+ me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION, GO_CACHE_OF_INNOVATION_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, 0.f, 0.f, 0.9999619f, 0.008734641f, 604800);
+ events.ScheduleEvent(EVENT_OUTTRO_3, 11000);
+ break;
+ case EVENT_OUTTRO_3:
+ DoCast(me, SPELL_TELEPORT_VISUAL);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->DespawnOrUnsummon(1000); // sniffs say 6 sec after, but it doesnt matter.
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ bool _fireFighter;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_mimironAI>(creature);
+ }
+};
+
+class boss_leviathan_mk_ii : public CreatureScript
+{
+ public:
+ boss_leviathan_mk_ii() : CreatureScript("boss_leviathan_mk_ii") { }
+
+ struct boss_leviathan_mk_iiAI : public BossAI
+ {
+ boss_leviathan_mk_iiAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ _fireFighter = false;
+ _setupMine = true;
+ _setupBomb = true;
+ _setupRocket = true;
+ }
+
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth().
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ DoCast(me, SPELL_VEHICLE_DAMAGED, true);
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+
+ if (events.IsInPhase(PHASE_LEVIATHAN_SOLO))
+ {
+ me->CastStop();
+ if (Unit* turret = me->GetVehicleKit()->GetPassenger(3))
+ turret->Kill(turret);
+
+ me->SetSpeed(MOVE_RUN, 1.5f, true);
+ me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, VehicleRelocation[WP_MKII_P1_IDLE]);
+ }
+ else if (events.IsInPhase(PHASE_LEVIATHAN_ASSEMBLED))
+ {
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+
+ if (IsEncounterFinished(who))
+ return;
+
+ me->CastStop();
+ DoCast(me, SPELL_SELF_REPAIR);
+ }
+ events.Reset();
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_HARDMODE_MKII:
+ _fireFighter = true;
+ DoCast(me, SPELL_EMERGENCY_MODE);
+ DoCastAOE(SPELL_EMERGENCY_MODE_TURRET);
+ events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_SOLO);
+ // Missing break intended.
+ case DO_START_MKII:
+ me->SetReactState(REACT_AGGRESSIVE);
+ events.SetPhase(PHASE_LEVIATHAN_SOLO);
+
+ events.ScheduleEvent(EVENT_NAPALM_SHELL, 3000, 0, PHASE_LEVIATHAN_SOLO);
+ events.ScheduleEvent(EVENT_PLASMA_BLAST, 15000, 0, PHASE_LEVIATHAN_SOLO);
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE, 5000);
+ events.ScheduleEvent(EVENT_SHOCK_BLAST, 18000);
+ break;
+ case DO_ASSEMBLED_COMBAT:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ events.SetPhase(PHASE_LEVIATHAN_ASSEMBLED);
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE, 15000);
+ events.ScheduleEvent(EVENT_SHOCK_BLAST, 45000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_SETUP_MINE:
+ return _setupMine;
+ case DATA_SETUP_BOMB:
+ return _setupBomb;
+ case DATA_SETUP_ROCKET:
+ return _setupRocket;
+ case DATA_FIREFIGHTER:
+ return _fireFighter;
+ default:
+ return 0;
+ }
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->Talk(events.IsInPhase(PHASE_LEVIATHAN_SOLO) ? SAY_MKII_SLAY : SAY_V07TRON_SLAY);
+ }
+
+ void MovementInform(uint32 type, uint32 point) override
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (point)
+ {
+ case WP_MKII_P1_IDLE:
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_HALF_HEAL);
+
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_VX001);
+ break;
+ case WP_MKII_P4_POS_1:
+ events.ScheduleEvent(EVENT_MOVE_POINT_2, 1);
+ break;
+ case WP_MKII_P4_POS_2:
+ events.ScheduleEvent(EVENT_MOVE_POINT_3, 1);
+ break;
+ case WP_MKII_P4_POS_3:
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_2);
+ break;
+ case WP_MKII_P4_POS_4:
+ events.ScheduleEvent(EVENT_MOVE_POINT_5, 1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_PASSIVE);
+ _fireFighter = false;
+ _setupMine = true;
+ _setupBomb = true;
+ _setupRocket = true;
+ DoCast(me, SPELL_FREEZE_ANIM);
+ }
+
+ void SetData(uint32 id, uint32 data) override
+ {
+ switch (id)
+ {
+ case DATA_SETUP_MINE:
+ _setupMine = data != 0;
+ break;
+ case DATA_SETUP_BOMB:
+ _setupBomb = data != 0;
+ break;
+ case DATA_SETUP_ROCKET:
+ _setupRocket = data != 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() || !CheckInRoom())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_PROXIMITY_MINE:
+ DoCastAOE(SPELL_PROXIMITY_MINES);
+ events.RescheduleEvent(EVENT_PROXIMITY_MINE, 35000);
+ break;
+ case EVENT_PLASMA_BLAST:
+ DoCastVictim(SPELL_SCRIPT_EFFECT_PLASMA_BLAST);
+ events.RescheduleEvent(EVENT_PLASMA_BLAST, urand(30000, 45000), 0, PHASE_LEVIATHAN_SOLO);
+
+ if (events.GetTimeUntilEvent(EVENT_NAPALM_SHELL) < 9000)
+ events.RescheduleEvent(EVENT_NAPALM_SHELL, 9000, 0, PHASE_LEVIATHAN_SOLO); // The actual spell is cast by the turret, we should not let it interrupt itself.
+ break;
+ case EVENT_SHOCK_BLAST:
+ DoCastAOE(SPELL_SHOCK_BLAST);
+ events.RescheduleEvent(EVENT_SHOCK_BLAST, urand(34000, 36000));
+ break;
+ case EVENT_FLAME_SUPPRESSANT_MK:
+ DoCastAOE(SPELL_FLAME_SUPPRESSANT_MK);
+ events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_MK, 60000, 0, PHASE_LEVIATHAN_SOLO);
+ break;
+ case EVENT_NAPALM_SHELL:
+ DoCastAOE(SPELL_FORCE_CAST_NAPALM_SHELL);
+ events.RescheduleEvent(EVENT_NAPALM_SHELL, urand(6000, 15000), 0, PHASE_LEVIATHAN_SOLO);
+
+ if (events.GetTimeUntilEvent(EVENT_PLASMA_BLAST) < 2000)
+ events.RescheduleEvent(EVENT_PLASMA_BLAST, 2000, 0, PHASE_LEVIATHAN_SOLO); // The actual spell is cast by the turret, we should not let it interrupt itself.
+ break;
+ case EVENT_MOVE_POINT_2:
+ me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_2, VehicleRelocation[WP_MKII_P4_POS_2]);
+ break;
+ case EVENT_MOVE_POINT_3:
+ me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_3, VehicleRelocation[WP_MKII_P4_POS_3]);
+ break;
+ case EVENT_MOVE_POINT_5:
+ me->GetMotionMaster()->MovePoint(WP_MKII_P4_POS_5, VehicleRelocation[WP_MKII_P4_POS_5]);
+ break;
+ default:
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ bool _fireFighter;
+ bool _setupMine;
+ bool _setupBomb;
+ bool _setupRocket;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_leviathan_mk_iiAI>(creature);
+ }
+};
+
+class boss_vx_001 : public CreatureScript
+{
+ public:
+ boss_vx_001() : CreatureScript("boss_vx_001") { }
+
+ struct boss_vx_001AI : public BossAI
+ {
+ boss_vx_001AI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ me->SetDisableGravity(true); // This is the unfold visual state of VX-001, it has to be set on create as it requires an objectupdate if set later.
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SPECIAL_UNARMED); // This is a hack to force the yet to be unfolded visual state.
+ me->SetReactState(REACT_PASSIVE);
+ _fireFighter = false;
+ }
+
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth().
+ me->AttackStop();
+ DoCast(me, SPELL_VEHICLE_DAMAGED, true);
+ me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+
+ if (events.IsInPhase(PHASE_VX001_SOLO))
+ {
+ me->CastStop();
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); // | UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_HALF_HEAL); // has no effect, wat
+ DoCast(me, SPELL_TORSO_DISABLED);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_AERIAL);
+ }
+ else if (events.IsInPhase(PHASE_VX001_ASSEMBLED))
+ {
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ if (IsEncounterFinished(who))
+ return;
+
+ me->CastStop();
+ DoCast(me, SPELL_SELF_REPAIR);
+ }
+ events.Reset();
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_HARDMODE_VX001:
+ _fireFighter = true;
+ DoCast(me, SPELL_EMERGENCY_MODE);
+ events.ScheduleEvent(EVENT_FROST_BOMB, 1000);
+ events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, 6000);
+ // Missing break intended.
+ case DO_START_VX001:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM);
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); // Remove emotestate.
+ //me->SetUInt32Value(UNIT_FIELD_BYTES_1, 33554432); Blizzard handles hover animation like this it seems.
+ DoCast(me, SPELL_HEAT_WAVE_AURA);
+
+ events.SetPhase(PHASE_VX001_SOLO);
+ events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000);
+ events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000));
+ events.ScheduleEvent(EVENT_RAPID_BURST, 500, 0, PHASE_VX001_SOLO);
+ break;
+ case DO_ASSEMBLED_COMBAT:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+
+ events.SetPhase(PHASE_VX001_ASSEMBLED);
+ events.ScheduleEvent(EVENT_ROCKET_STRIKE, 20000);
+ events.ScheduleEvent(EVENT_SPINNING_UP, urand(30000, 35000));
+ events.ScheduleEvent(EVENT_HAND_PULSE, 500, 0, PHASE_VX001_ASSEMBLED);
+ if (_fireFighter)
+ events.ScheduleEvent(EVENT_FROST_BOMB, 1000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode() override
+ {
+ summons.DespawnAll();
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+ if (summon->GetEntry() == NPC_BURST_TARGET)
+ summon->CastSpell(me, SPELL_RAPID_BURST_TARGET_ME);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->Talk(events.IsInPhase(PHASE_VX001_SOLO) ? SAY_VX001_SLAY : SAY_V07TRON_SLAY);
+ }
+
+ void SpellHit(Unit* caster, SpellInfo const* /*spellProto*/) override
+ {
+ if (caster->GetEntry() == NPC_BURST_TARGET && !me->HasUnitState(UNIT_STATE_CASTING))
+ DoCast(caster, SPELL_RAPID_BURST);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ // Handle rotation during SPELL_SPINNING_UP, SPELL_P3WX2_LASER_BARRAGE, SPELL_RAPID_BURST, and SPELL_HAND_PULSE_LEFT/RIGHT
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ if (Creature* channelTarget = ObjectAccessor::GetCreature(*me, me->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT)))
+ me->SetFacingToObject(channelTarget);
+ return;
+ }
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RAPID_BURST:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true))
+ DoCast(target, SPELL_SUMMON_BURST_TARGET);
+ events.RescheduleEvent(EVENT_RAPID_BURST, 3000, 0, PHASE_VX001_SOLO);
+ break;
+ case EVENT_ROCKET_STRIKE:
+ DoCastAOE(events.IsInPhase(PHASE_VX001_SOLO) ? SPELL_ROCKET_STRIKE_LEFT : SPELL_ROCKET_STRIKE_BOTH);
+ events.ScheduleEvent(EVENT_RELOAD, 10000);
+ events.RescheduleEvent(EVENT_ROCKET_STRIKE, urand(20000, 25000));
+ break;
+ case EVENT_RELOAD:
+ for (uint8 seat = 6; seat <= 7; seat++)
+ if (Unit* rocket = me->GetVehicleKit()->GetPassenger(seat))
+ rocket->SetDisplayId(rocket->GetNativeDisplayId());
+ break;
+ case EVENT_HAND_PULSE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true))
+ DoCast(target, urand(0, 1) == 0 ? SPELL_HAND_PULSE_LEFT : SPELL_HAND_PULSE_RIGHT);
+ events.RescheduleEvent(EVENT_HAND_PULSE, urand(1500, 3000), 0, PHASE_VX001_ASSEMBLED);
+ break;
+ case EVENT_FROST_BOMB:
+ DoCastAOE(SPELL_SCRIPT_EFFECT_FROST_BOMB);
+ events.RescheduleEvent(EVENT_FROST_BOMB, 45000);
+ break;
+ case EVENT_SPINNING_UP:
+ DoCastAOE(SPELL_SPINNING_UP);
+ events.DelayEvents(14000);
+ events.RescheduleEvent(EVENT_SPINNING_UP, urand(55000, 65000));
+ break;
+ case EVENT_FLAME_SUPPRESSANT_VX:
+ DoCastAOE(SPELL_FLAME_SUPPRESSANT_VX);
+ events.RescheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, urand(10000, 12000), 0, PHASE_VX001_SOLO);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ bool _fireFighter;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_vx_001AI>(creature);
+ }
+};
+
+class boss_aerial_command_unit : public CreatureScript
+{
+ public:
+ boss_aerial_command_unit() : CreatureScript("boss_aerial_command_unit") { }
+
+ struct boss_aerial_command_unitAI : public BossAI
+ {
+ boss_aerial_command_unitAI(Creature* creature) : BossAI(creature, BOSS_MIMIRON)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ fireFigther = false;
+ }
+
+ void DamageTaken(Unit* who, uint32 &damage) override
+ {
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1; // Let creature fall to 1 hp, but do not let it die or damage itself with SetHealth().
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ DoCast(me, SPELL_VEHICLE_DAMAGED, true);
+ me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
+
+ if (events.IsInPhase(PHASE_AERIAL_SOLO))
+ {
+ me->GetMotionMaster()->Clear(true);
+ me->GetMotionMaster()->MovePoint(WP_AERIAL_P4_POS, VehicleRelocation[WP_AERIAL_P4_POS]);
+ }
+ else if (events.IsInPhase(PHASE_AERIAL_ASSEMBLED))
+ {
+ me->SetStandState(UNIT_STAND_STATE_DEAD);
+
+ if (IsEncounterFinished(who))
+ return;
+
+ me->CastStop();
+ DoCast(me, SPELL_SELF_REPAIR);
+ }
+ events.Reset();
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_HARDMODE_AERIAL:
+ fireFigther = true;
+ DoCast(me, SPELL_EMERGENCY_MODE);
+ events.ScheduleEvent(EVENT_SUMMON_FIRE_BOTS, 1000, 0, PHASE_AERIAL_SOLO);
+ // Missing break intended.
+ case DO_START_AERIAL:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ events.SetPhase(PHASE_AERIAL_SOLO);
+ events.ScheduleEvent(EVENT_SUMMON_JUNK_BOT, 5000, 0, PHASE_AERIAL_SOLO);
+ events.ScheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 9000, 0, PHASE_AERIAL_SOLO);
+ events.ScheduleEvent(EVENT_SUMMON_BOMB_BOT, 9000, 0, PHASE_AERIAL_SOLO);
+ break;
+ case DO_DISABLE_AERIAL:
+ me->CastStop();
+ me->AttackStop();
+ me->SetReactState(REACT_PASSIVE);
+ me->GetMotionMaster()->MoveFall();
+ events.DelayEvents(23000);
+ break;
+ case DO_ENABLE_AERIAL:
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ case DO_ASSEMBLED_COMBAT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ events.SetPhase(PHASE_AERIAL_ASSEMBLED);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode() override
+ {
+ summons.DespawnAll();
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (fireFigther && (summon->GetEntry() == NPC_ASSAULT_BOT || summon->GetEntry() == NPC_JUNK_BOT))
+ summon->CastSpell(summon, SPELL_EMERGENCY_MODE);
+ BossAI::JustSummoned(summon);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->Talk(events.IsInPhase(PHASE_AERIAL_SOLO) ? SAY_AERIAL_SLAY : SAY_V07TRON_SLAY);
+ }
+
+ void MovementInform(uint32 type, uint32 point) override
+ {
+ if (type == POINT_MOTION_TYPE && point == WP_AERIAL_P4_POS)
+ {
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_V0L7R0N_1);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SUMMON_FIRE_BOTS:
+ me->CastCustomSpell(SPELL_SUMMON_FIRE_BOT_TRIGGER, SPELLVALUE_MAX_TARGETS, 3, NULL, true);
+ events.RescheduleEvent(EVENT_SUMMON_FIRE_BOTS, 45000, 0, PHASE_AERIAL_SOLO);
+ break;
+ case EVENT_SUMMON_JUNK_BOT:
+ me->CastCustomSpell(SPELL_SUMMON_JUNK_BOT_TRIGGER, SPELLVALUE_MAX_TARGETS, 1, NULL, true);
+ events.RescheduleEvent(EVENT_SUMMON_JUNK_BOT, urand(11000, 12000), 0, PHASE_AERIAL_SOLO);
+ break;
+ case EVENT_SUMMON_ASSAULT_BOT:
+ me->CastCustomSpell(SPELL_SUMMON_ASSAULT_BOT_TRIGGER, SPELLVALUE_MAX_TARGETS, 1, NULL, true);
+ events.RescheduleEvent(EVENT_SUMMON_ASSAULT_BOT, 30000, 0, PHASE_AERIAL_SOLO);
+ break;
+ case EVENT_SUMMON_BOMB_BOT:
+ DoCast(me, SPELL_SUMMON_BOMB_BOT);
+ events.RescheduleEvent(EVENT_SUMMON_BOMB_BOT, urand(15000, 20000), 0, PHASE_AERIAL_SOLO);
+ break;
+ default:
+ break;
+ }
+ }
+ DoSpellAttackIfReady(events.IsInPhase(PHASE_AERIAL_SOLO) ? SPELL_PLASMA_BALL_P1 : SPELL_PLASMA_BALL_P2);
+ }
+
+ private:
+ bool fireFigther;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<boss_aerial_command_unitAI>(creature);
+ }
+};
+
+class npc_mimiron_assault_bot : public CreatureScript
+{
+ public:
+ npc_mimiron_assault_bot() : CreatureScript("npc_mimiron_assault_bot") { }
+
+ struct npc_mimiron_assault_botAI : public ScriptedAI
+ {
+ npc_mimiron_assault_botAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ events.ScheduleEvent(EVENT_MAGNETIC_FIELD, 14000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_ROOT))
+ {
+ if (Unit* newTarget = SelectTarget(SELECT_TARGET_NEAREST, 0, 30.0f, true))
+ {
+ me->DeleteThreatList();
+ AttackStart(newTarget);
+ }
+ }
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MAGNETIC_FIELD:
+ DoCastVictim(SPELL_MAGNETIC_FIELD);
+ me->ClearUnitState(UNIT_STATE_CASTING);
+ events.RescheduleEvent(EVENT_MAGNETIC_FIELD, 30000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_assault_botAI>(creature);
+ }
+};
+
+class npc_mimiron_emergency_fire_bot : public CreatureScript
+{
+ public:
+ npc_mimiron_emergency_fire_bot() : CreatureScript("npc_mimiron_emergency_fire_bot") { }
+
+ struct npc_mimiron_emergency_fire_botAI : public ScriptedAI
+ {
+ npc_mimiron_emergency_fire_botAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ isWaterSprayReady = true;
+ moveNew = true;
+ }
+
+ uint32 GetData(uint32 id) const override
+ {
+ if (id == DATA_WATERSPRAY)
+ return isWaterSprayReady;
+ if (id == DATA_MOVE_NEW)
+ return moveNew;
+ return 0;
+ }
+
+ void SetData(uint32 id, uint32 data) override
+ {
+ if (id == DATA_WATERSPRAY)
+ isWaterSprayReady = false;
+ else if (id == DATA_MOVE_NEW)
+ moveNew = data ? true : false;
+ }
+
+ void Reset() override
+ {
+ events.ScheduleEvent(EVENT_WATER_SPRAY, 7000);
+ isWaterSprayReady = true;
+ moveNew = true;
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!isWaterSprayReady)
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WATER_SPRAY:
+ isWaterSprayReady = true;
+ events.RescheduleEvent(EVENT_WATER_SPRAY, urand(7000, 9000));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ bool isWaterSprayReady;
+ bool moveNew;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_emergency_fire_botAI>(creature);
+ }
+};
+
+class npc_mimiron_computer : public CreatureScript
+{
+ public:
+ npc_mimiron_computer() : CreatureScript("npc_mimiron_computer") { }
+
+ struct npc_mimiron_computerAI : public ScriptedAI
+ {
+ npc_mimiron_computerAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = me->GetInstanceScript();
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case DO_ACTIVATE_COMPUTER:
+ Talk(SAY_SELF_DESTRUCT_INITIATED);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_10, 3000);
+ break;
+ case DO_DEACTIVATE_COMPUTER:
+ Talk(SAY_SELF_DESTRUCT_TERMINATED);
+ me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_AURA);
+ me->RemoveAurasDueToSpell(SPELL_SELF_DESTRUCTION_VISUAL);
+ events.Reset();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SELF_DESTRUCT_10:
+ Talk(SAY_SELF_DESTRUCT_10);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_HARD_MODE);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_9, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_9:
+ Talk(SAY_SELF_DESTRUCT_9);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_8, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_8:
+ Talk(SAY_SELF_DESTRUCT_8);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_7, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_7:
+ Talk(SAY_SELF_DESTRUCT_7);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_6, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_6:
+ Talk(SAY_SELF_DESTRUCT_6);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_5, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_5:
+ Talk(SAY_SELF_DESTRUCT_5);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_4, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_4:
+ Talk(SAY_SELF_DESTRUCT_4);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_3, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_3:
+ Talk(SAY_SELF_DESTRUCT_3);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_2, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_2:
+ Talk(SAY_SELF_DESTRUCT_2);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_1, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_1:
+ Talk(SAY_SELF_DESTRUCT_1);
+ events.ScheduleEvent(EVENT_SELF_DESTRUCT_FINALIZED, 60000);
+ break;
+ case EVENT_SELF_DESTRUCT_FINALIZED:
+ Talk(SAY_SELF_DESTRUCT_FINALIZED);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_MIMIRON)))
+ mimiron->AI()->DoAction(DO_ACTIVATE_SELF_DESTRUCT);
+ DoCast(me, SPELL_SELF_DESTRUCTION_AURA);
+ DoCast(me, SPELL_SELF_DESTRUCTION_VISUAL);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_computerAI>(creature);
+ }
+};
+
+class npc_mimiron_flames : public CreatureScript
+{
+ public:
+ npc_mimiron_flames() : CreatureScript("npc_mimiron_flames") { }
+
+ struct npc_mimiron_flamesAI : public ScriptedAI
+ {
+ npc_mimiron_flamesAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = me->GetInstanceScript();
+ }
+
+ void Reset() override // Reset is possibly more suitable for this case.
+ {
+ events.ScheduleEvent(EVENT_SPREAD_FLAMES, 4000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (instance->GetBossState(BOSS_MIMIRON) != IN_PROGRESS)
+ me->DespawnOrUnsummon();
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SPREAD_FLAMES:
+ DoCastAOE(SPELL_SUMMON_FLAMES_SPREAD_TRIGGER);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_flamesAI>(creature);
+ }
+};
+
+class npc_mimiron_frost_bomb : public CreatureScript
+{
+ public:
+ npc_mimiron_frost_bomb() : CreatureScript("npc_mimiron_frost_bomb") { }
+
+ struct npc_mimiron_frost_bombAI : public ScriptedAI
+ {
+ npc_mimiron_frost_bombAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void Reset() override
+ {
+ events.ScheduleEvent(EVENT_FROST_BOMB_EXPLOSION, 10000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FROST_BOMB_EXPLOSION:
+ DoCastAOE(SPELL_FROST_BOMB_EXPLOSION);
+ events.ScheduleEvent(EVENT_FROST_BOMB_CLEAR_FIRES, 3000);
+ break;
+ case EVENT_FROST_BOMB_CLEAR_FIRES:
+ DoCastAOE(SPELL_CLEAR_FIRES);
+ me->DespawnOrUnsummon(3000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_frost_bombAI>(creature);
+ }
+};
+
+class npc_mimiron_proximity_mine : public CreatureScript
+{
+ public:
+ npc_mimiron_proximity_mine() : CreatureScript("npc_mimiron_proximity_mine") { }
+
+ struct npc_mimiron_proximity_mineAI : public ScriptedAI
+ {
+ npc_mimiron_proximity_mineAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
+
+ void Reset() override
+ {
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE_ARM, 1500);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_PROXIMITY_MINE_ARM:
+ DoCast(me, SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER);
+ events.ScheduleEvent(EVENT_PROXIMITY_MINE_DETONATION, 33500);
+ break;
+ case EVENT_PROXIMITY_MINE_DETONATION:
+ if (me->HasAura(SPELL_PROXIMITY_MINE_PERIODIC_TRIGGER))
+ DoCastAOE(SPELL_PROXIMITY_MINE_EXPLOSION);
+ me->DespawnOrUnsummon(1000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetUlduarAI<npc_mimiron_proximity_mineAI>(creature);
+ }
+};
+
+class go_mimiron_hardmode_button : public GameObjectScript
+{
+ public:
+ go_mimiron_hardmode_button() : GameObjectScript("go_mimiron_hardmode_button") { }
+
+ bool OnGossipHello(Player* /*player*/, GameObject* go)
+ {
+ InstanceScript* instance = go->GetInstanceScript();
+
+ if (!instance)
+ return false;
+
+ if (Creature* computer = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_COMPUTER)))
+ computer->AI()->DoAction(DO_ACTIVATE_COMPUTER);
+ go->SetGoState(GO_STATE_ACTIVE);
+ go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ return true;
+ }
+};
+
// 63801 Bomb Bot
class spell_mimiron_bomb_bot : public SpellScriptLoader
{
@@ -1426,8 +2748,66 @@ class spell_mimiron_weld : public SpellScriptLoader
}
};
+class achievement_setup_boom : public AchievementCriteriaScript
+{
+ public:
+ achievement_setup_boom() : AchievementCriteriaScript("achievement_setup_boom") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_SETUP_BOMB);
+ }
+};
+
+class achievement_setup_mine : public AchievementCriteriaScript
+{
+ public:
+ achievement_setup_mine() : AchievementCriteriaScript("achievement_setup_mine") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_SETUP_MINE);
+ }
+};
+
+class achievement_setup_rocket : public AchievementCriteriaScript
+{
+ public:
+ achievement_setup_rocket() : AchievementCriteriaScript("achievement_setup_rocket") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_SETUP_ROCKET);
+ }
+};
+
+class achievement_firefighter : public AchievementCriteriaScript
+{
+ public:
+ achievement_firefighter() : AchievementCriteriaScript("achievement_firefighter") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target)
+ {
+ return target && target->GetAI()->GetData(DATA_FIREFIGHTER);
+ }
+};
+
void AddSC_boss_mimiron()
{
+ new boss_aerial_command_unit();
+ new boss_leviathan_mk_ii();
+ new boss_mimiron();
+ new boss_vx_001();
+
+ new npc_mimiron_assault_bot();
+ new npc_mimiron_emergency_fire_bot();
+ new npc_mimiron_computer();
+ new npc_mimiron_flames();
+ new npc_mimiron_frost_bomb();
+ new npc_mimiron_proximity_mine();
+
+ new go_mimiron_hardmode_button();
+
new spell_mimiron_bomb_bot();
new spell_mimiron_clear_fires();
new spell_mimiron_despawn_assault_bots();
@@ -1454,4 +2834,9 @@ void AddSC_boss_mimiron()
new spell_mimiron_summon_junk_bot();
new spell_mimiron_summon_junk_bot_target();
new spell_mimiron_weld();
+
+ new achievement_setup_boom();
+ new achievement_setup_mine();
+ new achievement_setup_rocket();
+ new achievement_firefighter();
}