diff --git a/data/sql/updates/pending_db_world/rev_1620244782542375889.sql b/data/sql/updates/pending_db_world/rev_1620244782542375889.sql
new file mode 100644
index 000000000..a9bd5b999
--- /dev/null
+++ b/data/sql/updates/pending_db_world/rev_1620244782542375889.sql
@@ -0,0 +1,311 @@
+INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1620244782542375889');
+
+-- Added missing aura for Magmadar
+UPDATE `creature_template_addon` SET `auras`='19449' WHERE `entry`=11982;
+
+-- 19411 Lava Bomb (used by Magmadar)
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (19411, 20474) AND `ScriptName`='spell_magmadar_lava_bomb';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(19411, 'spell_magmadar_lava_bomb'),
+(20474, 'spell_magmadar_lava_bomb');
+
+-- Renamed Core Hound script
+update `creature_template` SET `ScriptName`='npc_mc_core_hound' WHERE `entry`=11671;
+
+-- Timers update for NPC "Flamewaker Protector"
+UPDATE `smart_scripts` SET `event_param1`=5000, `event_param2`=5000, `event_param3`=6500, `event_param4`=6500 WHERE `entryorguid`=12119 AND `source_type`=0 AND `id`=0 AND `link`=0;
+UPDATE `smart_scripts` SET `event_param1`=5000, `event_param2`=10000, `event_param3`=7000, `event_param4`=7000 WHERE `entryorguid`=12119 AND `source_type`=0 AND `id`=1 AND `link`=0;
+
+-- Timers update for NPC "Flamewaker"
+UPDATE `smart_scripts` SET `event_param1`=3000, `event_param2`=6000, `event_param3`=10000, `event_param4`=13000 WHERE `entryorguid`=11661 AND `source_type`=0 AND `id`=1 AND `link`=0;
+UPDATE `smart_scripts` SET `event_param1`=3000, `event_param3`=4000, `event_param4`=6000 WHERE `entryorguid`=11661 AND `source_type`=0 AND `id`=0 AND `link`=0;
+UPDATE `smart_scripts` SET `event_param1`=4000, `event_param2`=9000, `event_param3`=5000, `event_param4`=8000 WHERE `entryorguid`=11661 AND `source_type`=0 AND `id`=2 AND `link`=0;
+
+-- Garr texts
+DELETE FROM `creature_text` WHERE `CreatureID`=12057 AND `GroupID`=0 AND `ID`=0;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(12057, 0, 0, '%s forces one of his Firesworn minions to erupt!', 41, 0, 100, 0, 0, 0, 8254, 0, 'Garr EMOTE_MASS_ERRUPTION');
+
+-- Garr
+-- Firesworn
+-- add them immolate and thrash auras
+UPDATE `creature_template_addon` SET `auras`='8876 15733' WHERE `entry`=12099;
+
+-- Conditions for spell "21086 Encouragement"
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=21086;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 3, 21086, 0, 0, 31, 0, 3, 11663, 0, 0, 0, 0, '', 'Encouragement Effects 1 and Effect 2 - can target Flamewaker Healer'),
+(13, 3, 21086, 0, 1, 31, 0, 3, 11664, 0, 0, 0, 0, '', 'Encouragement Effects 1 and Effect 2 - can target Flamewaker Elite');
+
+-- Conditions for spell "21090 Champion"
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=21090;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 7, 21090, 0, 0, 31, 0, 3, 11663, 0, 0, 0, 0, '', 'Champion - can target Flamewaker Healer'),
+(13, 7, 21090, 0, 1, 31, 0, 3, 11664, 0, 0, 0, 0, '', 'Champion - can target Flamewaker Elite');
+
+-- Conditions for spell "21087 Immunity"
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=21087;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 3, 21087, 0, 0, 31, 0, 3, 11663, 0, 0, 0, 0, '', 'Champion - can target Flamewaker Healer');
+
+-- Majordomu summon
+DELETE FROM `creature_summon_groups` WHERE `summonerId`=12018;
+INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`) VALUES
+(12018, 0, 1, 11663, 761.652, -1164.3, -119.533, 3.3919, 8, 10000),
+(12018, 0, 1, 11663, 747.323, -1149.24, -120.06, 3.6629, 8, 10000),
+(12018, 0, 1, 11663, 766.734, -1183.16, -119.292, 2.9889, 8, 10000),
+(12018, 0, 1, 11663, 757.364, -1198.31, -118.652, 2.3095, 8, 10000),
+(12018, 0, 1, 11664, 752.349, -1159.19, -119.261, 3.6032, 8, 10000),
+(12018, 0, 1, 11664, 738.015, -1152.22, -119.512, 4.0792, 8, 10000),
+(12018, 0, 1, 11664, 757.246, -1189.79, -118.633, 2.5333, 8, 10000),
+(12018, 0, 1, 11664, 745.916, -1199.35, -118.119, 1.8932, 8, 10000);
+
+-- Molten Giant
+UPDATE `creature_template_addon` SET `auras`='18943' WHERE `entry`=11658;
+update `creature_addon` set `auras`='18943' where `guid` in (select `guid` from `creature` where `id`=11658);
+UPDATE `smart_scripts` SET `event_param1`='6000', `event_param2`='10000', `event_param3`='7000', `event_param4`='10000' WHERE `entryorguid`=11658 AND `source_type`=0 AND `id`=0 AND `link`=0;
+UPDATE `smart_scripts` SET `event_param1`='6000', `event_param2`='11000', `event_param3`='12000', `event_param4`='16000' WHERE `entryorguid`=11658 AND `source_type`=0 AND `id`=1 AND `link`=0;
+
+-- Firelord
+UPDATE `creature_template_addon` SET `auras`='19396' WHERE `entry`=11668;
+update creature_addon set `auras`='19396' where `guid` in (select `guid` from `creature` where `id`=11668);
+UPDATE `smart_scripts` SET `event_param1`='4000', `event_param3`='2000', `event_param4`='4000' WHERE `entryorguid`=11668 AND `source_type`=0 AND `id`=0 AND `link`=0;
+UPDATE `smart_scripts` SET `event_param2`='15000', `event_param3`='15000', `event_param4`='15000' WHERE `entryorguid`=11668 AND `source_type`=0 AND `id`=1 AND `link`=0;
+
+-- Ancient Core Hound
+UPDATE `creature_template_addon` SET `auras`='18950' WHERE `entry`=11658;
+update creature_addon set `auras`='18950' where `guid` in (select `guid` from `creature` where `id`=11658);
+
+-- Fire Imp
+update `creature_template` set `AIName`='SmartAI' where `entry`=11669;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=11669 AND `source_type`=0 AND `id`=0 AND `link`=0;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(11669, 0, 0, 0, 0, 0, 100, 0, 5000, 15000, 4000, 7000, 0, 11, 20602, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Flame Imp - IC - Cast Fire Nova');
+
+-- spell "Play Dead" aura script (used by core hounds)
+DELETE FROM `spell_script_names` WHERE `spell_id`=19822 AND `ScriptName`='spell_mc_play_dead';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(19822, 'spell_mc_play_dead');
+
+-- Magmadar linked respawn data
+-- set @magmadarGUID := (SELECT `guid` from `creature` WHERE `id` = 11982 AND `map`=409);
+SET @magmadarGUID := 56683;
+DELETE FROM `linked_respawn` WHERE `guid` IN (SELECT `guid` from `creature` WHERE `id` IN (11671, 11673) AND `map`=409);
+INSERT INTO `linked_respawn` (`guid`, `linkedGuid`, `linkType`)
+SELECT `guid`, CONCAT(@magmadarGUID), CONCAT(0) from `creature` WHERE `id` IN (11671, 11673) AND `map`=409;
+
+-- Added "18950 Invisibility and Stealth Detection" to Ancient Core Hounds
+UPDATE `creature_template_addon` SET `auras`='18950' WHERE `entry`=11673;
+
+-- 19695 Inferno (used by Geddon)
+DELETE FROM `spell_script_names` WHERE `spell_id`=19695 AND `ScriptName`='spell_geddon_inferno';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(19695, 'spell_geddon_inferno');
+
+-- Added "Thrash" aura for Core Rager
+UPDATE `creature_template_addon` SET `auras`='12787 20553' WHERE `entry`=11672;
+
+-- Added missing auras for Golemagg
+UPDATE `creature_template_addon` SET `auras`='13879 18943 20556' WHERE `entry`=11988;
+
+-- spell "Attract Rager"(20544) condition
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=20544;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 7, 20544, 0, 0, 31, 0, 3, 11672, 0, 0, 0, 0, '', 'Spell Attract Rager should target only Core Rager');
+
+-- Core Hound formations
+-- GROUP 1
+-- 56638, 56635, 56637, 56634, 56636
+set @leader := 56638;
+DELETE FROM `creature_formations` WHERE `memberGUID` IN (@leader, 56635, 56637, 56634, 56636);
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (@leader, 56635, 56637, 56634, 56636);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(@leader, @leader, 0, 0, 2, 0, 0),
+(@leader, 56635, 0, 0, 3, 0, 0),
+(@leader, 56637, 0, 0, 3, 0, 0),
+(@leader, 56634, 0, 0, 3, 0, 0),
+(@leader, 56636, 0, 0, 3, 0, 0);
+-- GROUP 2
+-- 56629, 56630, 56632, 56633, 56631
+set @leader := 56629;
+DELETE FROM `creature_formations` WHERE `memberGUID` IN (@leader, 56630, 56632, 56633, 56631);
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (@leader, 56630, 56632, 56633, 56631);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(@leader, @leader, 0, 0, 2, 0, 0),
+(@leader, 56630, 0, 0, 3, 0, 0),
+(@leader, 56632, 0, 0, 3, 0, 0),
+(@leader, 56633, 0, 0, 3, 0, 0),
+(@leader, 56631, 0, 0, 3, 0, 0);
+-- GROUP 3
+-- 56639, 56641, 56642, 56643, 56640
+set @leader := 56639;
+DELETE FROM `creature_formations` WHERE `memberGUID` IN (@leader, 56641, 56642, 56643, 56640);
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (@leader, 56641, 56642, 56643, 56640);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(@leader, @leader, 0, 0, 2, 0, 0),
+(@leader, 56641, 0, 0, 3, 0, 0),
+(@leader, 56642, 0, 0, 3, 0, 0),
+(@leader, 56643, 0, 0, 3, 0, 0),
+(@leader, 56640, 0, 0, 3, 0, 0);
+-- GROUP 4
+-- 56651, 56650, 56652, 56653, 56654
+set @leader := 56651;
+DELETE FROM `creature_formations` WHERE `memberGUID` IN (@leader, 56650, 56652, 56653, 56654);
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (@leader, 56650, 56652, 56653, 56654);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(@leader, @leader, 0, 0, 2, 0, 0),
+(@leader, 56650, 0, 0, 3, 0, 0),
+(@leader, 56652, 0, 0, 3, 0, 0),
+(@leader, 56653, 0, 0, 3, 0, 0),
+(@leader, 56654, 0, 0, 3, 0, 0);
+-- GROUP 5
+-- 56648, 56644, 56646, 56649, 56647
+set @leader := 56648;
+DELETE FROM `creature_formations` WHERE `memberGUID` IN (@leader, 56644, 56646, 56649, 56647);
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (@leader, 56644, 56646, 56649, 56647);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(@leader, @leader, 0, 0, 2, 0, 0),
+(@leader, 56644, 0, 0, 3, 0, 0),
+(@leader, 56646, 0, 0, 3, 0, 0),
+(@leader, 56649, 0, 0, 3, 0, 0),
+(@leader, 56647, 0, 0, 3, 0, 0);
+
+-- Lucifron Flamewalkers
+-- These minions has formation data and they always follows Lucifron
+/* ERROR MSG:
+WaypointMovementGenerator::LoadPath: creature Flamewaker Protector (GUID Full: 0xf130002f5700006c Type: Creature Entry: 12119 Low: 108) doesn't have waypoint path id: 566060
+WaypointMovementGenerator::LoadPath: creature Flamewaker Protector (GUID Full: 0xf130002f5700006d Type: Creature Entry: 12119 Low: 109) doesn't have waypoint path id: 566070
+*/
+UPDATE `creature_addon` SET `path_id`='0' WHERE `guid` IN (56606, 56607);
+update `creature` set `MovementType`=0 where `guid` IN (56606, 56607);
+
+-- Garr's Firesworn
+UPDATE `creature_template` SET `ScriptName`='npc_garr_firesworn' WHERE `entry`=12099;
+
+-- Garr's "Separation Anexiety"(23487, server side)
+UPDATE `spell_dbc` SET `EffectAura_1`=226, `EffectAuraPeriod_1`=1000 WHERE `Id`=23487;
+DELETE FROM `spell_script_names` WHERE `spell_id`=23487 AND `ScriptName`='spell_garr_separation_nexiety';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(23487, 'spell_garr_separation_nexiety');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=23487;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 23487, 0, 0, 31, 0, 3, 12099, 0, 0, 0, 0, '', 'Separation Anexiety (effect 0) - should target only Firesworn');
+
+-- Removed script for "Son of Flame"
+update `creature_template` set `ScriptName`='' where `entry`=12143;
+
+-- Garr's linked respawn data
+-- set @garrGUID := (SELECT `guid` from `creature` WHERE `id` = 12101 AND `map`=409);
+SET @garrGUID := 56683;
+DELETE FROM `linked_respawn` WHERE `guid` IN (SELECT `guid` from `creature` WHERE `id` = 12101 AND `map`=409);
+INSERT INTO `linked_respawn` (`guid`, `linkedGuid`, `linkType`)
+SELECT `guid`, CONCAT(@magmadarGUID), CONCAT(0) from `creature` WHERE `id` = 12101 AND `map`=409;
+
+-- "19515 Frenzy (SERVERSIDE)" used by Garr's Firesworn
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=19515;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 19515, 0, 0, 31, 0, 3, 12057, 0, 0, 0, 0, '', 'Frenzy (SERVERSIDE) - should target only Garr');
+
+-- Allow casting while dead
+update `spell_dbc` set `attributes`=`attributes` | 0x00800000 where `id` = 19515;
+
+DELETE FROM `spell_script_names` WHERE `spell_id`=19515 AND `ScriptName`='spell_garr_frenzy';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(19515, 'spell_garr_frenzy');
+
+-- 20482 Firesworn Eruption Trigger (SERVERSIDE)
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=20482;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 3, 20482, 0, 0, 31, 0, 3, 12099, 0, 0, 0, 0, '', 'spell "Firesworn Eruption Trigger" should target only Firesworn');
+
+-- 20482 Firesworn Eruption Trigger (SERVERSIDE)
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=20482 AND `spell_effect`=20483 AND `type`=1;
+INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
+(20482, 20483, 1, 'Firesworn Eruption Trigger - On Hit - Trigger Massive Eruption');
+
+-- Golemagg formation
+set @leader := 56684;
+DELETE FROM `creature_formations` WHERE `memberGUID` IN (@leader, 56685, 56699);
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (@leader, 56685, 56699);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(@leader, @leader, 0, 0, 2, 0, 0),
+(@leader, 56685, 0, 0, 3, 0, 0),
+(@leader, 56699, 0, 0, 3, 0, 0);
+
+-- Condition for "20553 Golemagg's Trust"
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=20553;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 7, 20553, 0, 0, 31, 0, 3, 11672, 0, 0, 0, 0, '', 'Golemagg\'s Trust spell effects should target only Core Ragers');
+
+-- Condition for "20619 Magic Reflection" (Majordomu)
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=20619;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 20619, 0, 0, 31, 0, 3, 0, 0, 0, 0, 0, '', 'Magic Reflection - Should target only creatures'),
+(13, 1, 20619, 0, 0, 34, 1, 0, 1, 0, 0, 0, 0, '', 'Magic Reflection - Should target only friendly creatures');
+
+-- Condition for "21075 Damage Shield" (Majordomou)
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=21075;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 21075, 0, 0, 31, 0, 3, 0, 0, 0, 0, 0, '', 'Damage Shield - Should target only creatures'),
+(13, 1, 21075, 0, 0, 34, 1, 0, 1, 0, 0, 0, 0, '', 'Damage Shield - Should target only friendly creatures');
+
+-- Teleport position for spell "20618 Teleport" (Majordomu)
+DELETE FROM `spell_target_position` WHERE `id`=20618 AND `EffectIndex`=0;
+INSERT INTO `spell_target_position` (`id`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`) VALUES
+(20618, 0, 409, 736.516, -1176.35, -119.006, 0);
+
+-- Teleport position for spell "20534 Teleport" (Majordomu)
+DELETE FROM `spell_target_position` WHERE `id`=20534 AND `EffectIndex`=0;
+INSERT INTO `spell_target_position` (`id`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`) VALUES
+(20534, 0, 409, 736.516, -1176.35, -119.006, 0);
+
+-- 20538 Hate to Zero (SERVERSIDE, majordomu)
+DELETE FROM `spell_script_names` WHERE `spell_id`=20538 AND `ScriptName`='spell_hate_to_zero';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(20538, 'spell_hate_to_zero');
+
+-- Majordomo texts
+UPDATE `creature_template` SET `gossip_menu_id`='4093' WHERE `entry`=12018;
+
+-- Majordomo texts
+DELETE FROM `creature_text` WHERE `CreatureID`=12018;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(12018, 0, 0, 'Reckless mortals! None may challenge the Sons of the Living flame!', 14, 0, 100, 0, 0, 8035, 7612, 0, 'majordomo SAY_AGGRO'),
+(12018, 1, 0, 'The runes of warding have been destroyed! Hunt down the infidels, my brethren!', 14, 0, 100, 0, 0, 8039, 7566, 3, 'majordomo SAY_SPAWN'),
+(12018, 2, 0, 'Ashes to ashes!', 14, 0, 100, 0, 0, 8037, 9425, 0, 'majordomo SAY_SLAY'),
+(12018, 2, 1, 'Burn mortals! Burn for this transgression!', 14, 0, 100, 0, 0, 8036, 0, 0, 'majordomo SAY_SPECIAL'),
+(12018, 3, 0, 'Impossible! Stay your attack, mortals... I submit! I submit!', 14, 0, 100, 0, 0, 8038, 7561, 0, 'majordomo SAY_DEFEAT'),
+(12018, 4, 0, 'Behold Ragnaros - the Firelord! He who was ancient when this world was young! Bow before him, mortals! Bow before your ending!', 14, 0, 100, 0, 0, 8040, 7657, 0, 'majordomo SAY_SUMMON_MAJ'),
+(12018, 5, 0, 'These mortal infidels, my lord! They have invaded your sanctum and seek to steal your secrets!', 14, 0, 100, 0, 0, 8041, 7661, 0, 'majordomo SAY_ARRIVAL2_MAJ'),
+(12018, 6, 0, 'You think you\'ve won already? Perhaps you\'ll need another lesson in pain!', 14, 0, 100, 0, 0, 0, 8545, 0, 'majordomo SAY_LAST_ADD'),
+(12018, 7, 0, 'Brashly, you have come to wrest the secrets of the Living Flame! You will soon regret the recklessness of your quest.', 14, 0, 100, 0, 0, 0, 7567, 0, 'majordomo SAY_DEFEAT_2'),
+(12018, 8, 0, 'I go now to summon the lord whose house this is. Should you seek an audience with him, your paltry lives will surely be forfeit! Nevertheless, seek out his lair, if you dare!', 14, 0, 100, 0, 0, 0, 7568, 0, 'majordomo SAY_DEFEAT_3'),
+(12018, 9, 0, 'Very well, $n', 12, 0, 100, 0, 0, 0, 7649, 0, 'majordomo SAY_RAG_SUM_1'),
+(12018, 10, 0, 'Impudent whelps! You\'\'ve rushed headlong to your own deaths! See now, the master stirs!', 14, 0, 100, 0, 0, 0, 7655, 0, 'majordomo SAY_RAG_SUM_2');
+
+-- Majordomu "21094 Separation Anxiety (SERVERSIDE)"
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=21094;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 21094, 0, 0, 31, 0, 3, 11663, 0, 0, 0, 0, '', 'Separation Anxiety should target Flamewaker Healer'),
+(13, 1, 21094, 0, 1, 31, 0, 3, 11664, 0, 0, 0, 0, '', 'Separation Anxiety should target Flamewaker Elite');
+
+UPDATE `spell_dbc` SET `EffectAura_1`=226, `EffectAuraPeriod_1`=1000 WHERE `Id`=21094;
+DELETE FROM `spell_script_names` WHERE `spell_id`=21094 AND `ScriptName`='spell_majordomo_separation_nexiety';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(21094, 'spell_majordomo_separation_nexiety');
+
+-- Ragnaros texts
+UPDATE `creature_text` SET `Emote`='15' WHERE `CreatureID`=11502 AND `GroupID`=1 AND `ID`=0;
+
+delete from `gameobject` where `guid`=2135424 and `id`=178107;
+INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES
+(2135424, 178107, 409, 1, 1, 838.951, -830.383, -230.206, 0.837757, 0, 0, 0, 1, -604800, 255, 1);
+delete from `gameobject` where `guid`=2135423 and `id`=178108;
+INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES
+(2135423, 178108, 409, 1, 1, 839.279, -831.058, -230.202, -1.37881, 0, 0, 0, 1, -604800, 255, 1);
+
+-- 19774 Summon Ragnaros
+DELETE FROM `spell_script_names` WHERE `spell_id`=19774 AND `ScriptName`='spell_summon_ragnaros';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(19774, 'spell_summon_ragnaros');
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp
index e709a7512..3345a421a 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp
@@ -15,36 +15,31 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Baron_Geddon
-SD%Complete: 100
-SDComment:
-SDCategory: Molten Core
-EndScriptData */
-
-#include "molten_core.h"
-#include "ObjectMgr.h"
-#include "ScriptedCreature.h"
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "molten_core.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
enum Emotes
{
- EMOTE_SERVICE = 0
+ EMOTE_SERVICE = 0
};
enum Spells
{
- SPELL_INFERNO = 19695,
- SPELL_IGNITE_MANA = 19659,
- SPELL_LIVING_BOMB = 20475,
- SPELL_ARMAGEDDON = 20479,
+ SPELL_INFERNO = 19695,
+ SPELL_INFERNO_DUMMY_EFFECT = 19698, // Server side spell which inflicts damage
+ SPELL_IGNITE_MANA = 19659,
+ SPELL_LIVING_BOMB = 20475,
+ SPELL_ARMAGEDDON = 20478,
};
enum Events
{
- EVENT_INFERNO = 1,
- EVENT_IGNITE_MANA = 2,
- EVENT_LIVING_BOMB = 3,
+ EVENT_INFERNO = 1,
+ EVENT_IGNITE_MANA,
+ EVENT_LIVING_BOMB,
};
class boss_baron_geddon : public CreatureScript
@@ -54,62 +49,75 @@ public:
struct boss_baron_geddonAI : public BossAI
{
- boss_baron_geddonAI(Creature* creature) : BossAI(creature, BOSS_BARON_GEDDON)
+ boss_baron_geddonAI(Creature* creature) : BossAI(creature, DATA_GEDDON),
+ armageddonCasted(false)
{
}
- void EnterCombat(Unit* victim) override
+ void Reset() override
{
- BossAI::EnterCombat(victim);
- events.ScheduleEvent(EVENT_INFERNO, 45000);
- events.ScheduleEvent(EVENT_IGNITE_MANA, 30000);
- events.ScheduleEvent(EVENT_LIVING_BOMB, 35000);
+ _Reset();
+ armageddonCasted = false;
}
- void UpdateAI(uint32 diff) override
+ void EnterCombat(Unit* /*attacker*/) override
{
- if (!UpdateVictim())
- return;
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_INFERNO, urand(13000, 15000));
+ events.ScheduleEvent(EVENT_IGNITE_MANA, urand(7000, 19000));
+ events.ScheduleEvent(EVENT_LIVING_BOMB, urand(11000, 16000));
+ }
- events.Update(diff);
-
- // If we are <2% hp cast Armageddon
- if (!HealthAbovePct(2))
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
+ {
+ // If boss is below 2% hp - cast Armageddon
+ if (!armageddonCasted && damage < me->GetHealth() && me->HealthBelowPctDamaged(2, damage))
{
me->InterruptNonMeleeSpells(true);
- DoCast(me, SPELL_ARMAGEDDON);
- Talk(EMOTE_SERVICE);
- return;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
+ if (me->CastSpell(me, SPELL_ARMAGEDDON) == SPELL_CAST_OK)
{
- case EVENT_INFERNO:
- DoCast(me, SPELL_INFERNO);
- events.ScheduleEvent(EVENT_INFERNO, 45000);
- break;
- case EVENT_IGNITE_MANA:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IGNITE_MANA))
- DoCast(target, SPELL_IGNITE_MANA);
- events.ScheduleEvent(EVENT_IGNITE_MANA, 30000);
- break;
- case EVENT_LIVING_BOMB:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_LIVING_BOMB);
- events.ScheduleEvent(EVENT_LIVING_BOMB, 35000);
- break;
- default:
- break;
+ Talk(EMOTE_SERVICE);
+ }
+
+ armageddonCasted = true;
+ }
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_INFERNO:
+ {
+ DoCastSelf(SPELL_INFERNO);
+ events.RepeatEvent(urand(21000, 26000));
+ break;
+ }
+ case EVENT_IGNITE_MANA:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IGNITE_MANA))
+ {
+ DoCast(target, SPELL_IGNITE_MANA);
+ }
+
+ events.RepeatEvent(urand(27000, 32000));
+ break;
+ }
+ case EVENT_LIVING_BOMB:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ {
+ DoCast(target, SPELL_LIVING_BOMB);
+ }
+
+ events.RepeatEvent(urand(11000, 16000));
+ break;
}
}
-
- DoMeleeAttackIfReady();
}
+
+ private:
+ bool armageddonCasted;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -118,7 +126,68 @@ public:
}
};
+// 19695 Inferno
+class spell_geddon_inferno : public SpellScriptLoader
+{
+public:
+ spell_geddon_inferno() : SpellScriptLoader("spell_geddon_inferno") { }
+
+ class spell_geddon_inferno_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_geddon_inferno_AuraScript);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_INFERNO_DUMMY_EFFECT });
+ }
+
+ void PeriodicTick(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+
+ if (Unit* caster = GetUnitOwner())
+ {
+ //The pulses come about 1 second apart and last for 10 seconds. Damage starts at 500 damage per pulse and increases by 500 every other pulse (500, 500, 1000, 1000, 1500, etc.). (Source: Wowwiki)
+ int32 multiplier = 1;
+ switch (aurEff->GetTickNumber())
+ {
+ case 2:
+ case 3:
+ multiplier = 2;
+ break;
+ case 4:
+ case 5:
+ multiplier = 3;
+ break;
+ case 6:
+ case 7:
+ multiplier = 4;
+ break;
+ case 8:
+ multiplier = 5;
+ break;
+ }
+
+ caster->CastCustomSpell(SPELL_INFERNO_DUMMY_EFFECT, SPELLVALUE_BASE_POINT0, 500 * multiplier, caster, TRIGGERED_NONE, nullptr, aurEff);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_geddon_inferno_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_geddon_inferno_AuraScript();
+ }
+};
+
void AddSC_boss_baron_geddon()
{
new boss_baron_geddon();
+
+ // Spells
+ new spell_geddon_inferno();
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_garr.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_garr.cpp
index ca1c95c3c..78490c806 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_garr.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_garr.cpp
@@ -15,83 +15,124 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Garr
-SD%Complete: 50
-SDComment: Adds NYI
-SDCategory: Molten Core
-EndScriptData */
-
-#include "molten_core.h"
-#include "ObjectMgr.h"
-#include "ScriptedCreature.h"
#include "ScriptMgr.h"
+#include "Containers.h"
+#include "ObjectAccessor.h"
+#include "ScriptedCreature.h"
+#include "SpellAuras.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
+#include "molten_core.h"
+
+enum Texts
+{
+ EMOTE_MASS_ERRUPTION = 0,
+};
enum Spells
{
// Garr
- SPELL_ANTIMAGIC_PULSE = 19492,
- SPELL_MAGMA_SHACKLES = 19496,
- SPELL_ENRAGE = 19516,
+ SPELL_ANTIMAGIC_PULSE = 19492, // Dispels magic on nearby enemies, removing 1 beneficial spell
+ SPELL_MAGMA_SHACKLES = 19496, // Reduces the movement speed of nearby enemies by 60%
+ SPELL_SEPARATION_ANXIETY = 23487, // Aura cast on himself by Garr, if adds move out of range, they will cast spell 23492 on themselves (server side)
+ SPELL_FRENZY = 19516, // Increases the caster's attack speed by 9 + scale. Stacks up to 10 times
- // Adds
- SPELL_ERUPTION = 19497,
- SPELL_IMMOLATE = 20294,
+ // Fireworn
+ SPELL_SEPARATION_ANXIETY_MINION = 23492, // Increases damage done by 300% and applied banish immunity
+ SPELL_ERUPTION = 19497, // Deals fire aoe damage and knockbacks nearby enemies
+ SPELL_MASSIVE_ERUPTION = 20483, // Deals fire aoe damage, knockbacks nearby enemies and kills caster
+ SPELL_ERUPTION_TRIGGER = 20482, // Removes banish auras and applied immunity to banish (server side)
+ SPELL_ENRAGE_TRIGGER = 19515, // Server side. Triggers 19516 on hit
};
enum Events
{
- EVENT_ANTIMAGIC_PULSE = 1,
- EVENT_MAGMA_SHACKLES = 2,
+ EVENT_ANTIMAGIC_PULSE = 1,
+ EVENT_MAGMA_SHACKLES,
};
class boss_garr : public CreatureScript
{
public:
- boss_garr() : CreatureScript("boss_garr") { }
+ boss_garr() : CreatureScript("boss_garr") {}
struct boss_garrAI : public BossAI
{
- boss_garrAI(Creature* creature) : BossAI(creature, BOSS_GARR)
+ boss_garrAI(Creature* creature) : BossAI(creature, DATA_GARR),
+ massEruptionTimer(600000) // 10 mins
{
}
- void EnterCombat(Unit* victim) override
+ void Reset() override
{
- BossAI::EnterCombat(victim);
+ _Reset();
+ massEruptionTimer = 600000;
+ }
+
+ void EnterCombat(Unit* /*attacker*/) override
+ {
+ _EnterCombat();
+ DoCastSelf(SPELL_SEPARATION_ANXIETY, true);
events.ScheduleEvent(EVENT_ANTIMAGIC_PULSE, 15000);
events.ScheduleEvent(EVENT_MAGMA_SHACKLES, 10000);
+ massEruptionTimer = 600000; // 10 mins
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
+ {
return;
+ }
+
+ // This should always process
+ if (massEruptionTimer <= diff)
+ {
+ Talk(EMOTE_MASS_ERRUPTION, me);
+ DoCastAOE(SPELL_ERUPTION_TRIGGER, true);
+ massEruptionTimer = 20000;
+ }
+ else
+ {
+ massEruptionTimer -= diff;
+ }
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
return;
+ }
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ANTIMAGIC_PULSE:
- DoCast(me, SPELL_ANTIMAGIC_PULSE);
- events.ScheduleEvent(EVENT_ANTIMAGIC_PULSE, 20000);
+ {
+ DoCastSelf(SPELL_ANTIMAGIC_PULSE);
+ events.RepeatEvent(20000);
break;
+ }
case EVENT_MAGMA_SHACKLES:
- DoCast(me, SPELL_MAGMA_SHACKLES);
- events.ScheduleEvent(EVENT_MAGMA_SHACKLES, 15000);
- break;
- default:
+ {
+ DoCastSelf(SPELL_MAGMA_SHACKLES);
+ events.RepeatEvent(15000);
break;
+ }
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
}
}
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 massEruptionTimer;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -100,60 +141,115 @@ public:
}
};
-class npc_firesworn : public CreatureScript
+class npc_garr_firesworn : public CreatureScript
{
public:
- npc_firesworn() : CreatureScript("npc_firesworn") { }
+ npc_garr_firesworn() : CreatureScript("npc_garr_firesworn") {}
- struct npc_fireswornAI : public ScriptedAI
+ struct npc_garr_fireswornAI : public ScriptedAI
{
- npc_fireswornAI(Creature* creature) : ScriptedAI(creature) { }
+ npc_garr_fireswornAI(Creature* creature) : ScriptedAI(creature) {}
- uint32 immolateTimer;
-
- void Reset() override
+ void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) override
{
- immolateTimer = 4000; //These times are probably wrong
- }
-
- void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
- {
- uint32 const health10pct = me->CountPctFromMaxHealth(10);
- uint32 health = me->GetHealth();
- if (int32(health) - int32(damage) < int32(health10pct))
+ if (damage >= me->GetHealth())
{
- damage = 0;
- DoCastVictim(SPELL_ERUPTION);
- me->DespawnOrUnsummon();
+ // Prevent double damage because Firesworn can kill himself with Massive Erruption
+ if (me != attacker)
+ {
+ DoCastSelf(SPELL_ERUPTION, true);
+ }
+
+ DoCastAOE(SPELL_ENRAGE_TRIGGER);
}
}
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (immolateTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_IMMOLATE);
- immolateTimer = urand(5000, 10000);
- }
- else
- immolateTimer -= diff;
-
- DoMeleeAttackIfReady();
- }
};
CreatureAI* GetAI(Creature* creature) const override
{
- return GetMoltenCoreAI(creature);
+ return GetMoltenCoreAI(creature);
+ }
+};
+
+// 23487 Separation Anxiety (server side)
+class spell_garr_separation_nexiety : public SpellScriptLoader
+{
+public:
+ spell_garr_separation_nexiety() : SpellScriptLoader("spell_garr_separation_nexiety") {}
+
+ class spell_garr_separation_nexiety_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_garr_separation_nexiety_AuraScript);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SEPARATION_ANXIETY_MINION });
+ }
+
+ void HandlePeriodic(AuraEffect const* aurEff)
+ {
+ Unit const* caster = GetCaster();
+ Unit* target = GetTarget();
+ if (caster && target && target->GetDistance(caster) > 40.0f && !target->HasAura(SPELL_SEPARATION_ANXIETY_MINION))
+ {
+ target->CastSpell(target, SPELL_SEPARATION_ANXIETY_MINION, true, nullptr, aurEff);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_garr_separation_nexiety_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ // Should return a fully valid AuraScript pointer.
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_garr_separation_nexiety_AuraScript();
+ }
+};
+
+//19515 Frenzy (SERVERSIDE)
+class spell_garr_frenzy : public SpellScriptLoader
+{
+public:
+ spell_garr_frenzy() : SpellScriptLoader("spell_garr_frenzy") {}
+
+ class spell_garr_frenzy_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_garr_frenzy_SpellScript);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_FRENZY });
+ }
+
+ void HandleHit(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ target->CastSpell(target, SPELL_FRENZY);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_garr_frenzy_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_garr_frenzy_SpellScript();
}
};
void AddSC_boss_garr()
{
new boss_garr();
- new npc_firesworn();
+ new npc_garr_firesworn();
+
+ // Spells
+ new spell_garr_separation_nexiety();
+ new spell_garr_frenzy();
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_gehennas.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_gehennas.cpp
index 072707a5f..4272fdb05 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_gehennas.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_gehennas.cpp
@@ -15,13 +15,6 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Gehennas
-SD%Complete: 90
-SDComment: Adds MC NYI
-SDCategory: Molten Core
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "molten_core.h"
@@ -48,9 +41,7 @@ public:
struct boss_gehennasAI : public BossAI
{
- boss_gehennasAI(Creature* creature) : BossAI(creature, BOSS_GEHENNAS)
- {
- }
+ boss_gehennasAI(Creature* creature) : BossAI(creature, DATA_GEHENNAS) {}
void EnterCombat(Unit* /*attacker*/) override
{
@@ -60,69 +51,47 @@ public:
events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 5000));
}
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
{
- if (!UpdateVictim())
+ switch (eventId)
{
- return;
- }
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- {
- return;
- }
-
- while (uint32 const eventId = events.ExecuteEvent())
- {
- switch (eventId)
+ case EVENT_GEHENNAS_CURSE:
{
- case EVENT_GEHENNAS_CURSE:
+ DoCastVictim(SPELL_GEHENNAS_CURSE);
+ events.RepeatEvent(urand(25000, 30000));
+ break;
+ }
+ case EVENT_RAIN_OF_FIRE:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
- DoCastVictim(SPELL_GEHENNAS_CURSE);
- events.RepeatEvent(urand(25000, 30000));
- break;
+ DoCast(target, SPELL_RAIN_OF_FIRE, true);
}
- case EVENT_RAIN_OF_FIRE:
+ events.RepeatEvent(6000);
+ break;
+ }
+ case EVENT_SHADOW_BOLT:
+ {
+ if (urand(0, 1))
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
{
- DoCast(target, SPELL_RAIN_OF_FIRE);
- }
- events.RepeatEvent(6000);
- break;
- }
- case EVENT_SHADOW_BOLT:
- {
- if (urand(0, 1))
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
- {
- DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
- }
- else
- {
- DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
- }
+ DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
}
else
{
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
}
-
- events.RepeatEvent(5000);
- break;
}
- }
+ else
+ {
+ DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- {
- return;
+ events.RepeatEvent(5000);
+ break;
}
}
-
- DoMeleeAttackIfReady();
}
};
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp
index 2f3e8a671..95bb514b7 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp
@@ -15,40 +15,28 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Golemagg
-SD%Complete: 90
-SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked
-SDCategory: Molten Core
-EndScriptData */
-
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
#include "molten_core.h"
#include "ObjectMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptMgr.h"
+#include "ObjectAccessor.h"
enum Texts
{
- EMOTE_LOWHP = 0,
+ EMOTE_LOWHP = 0,
};
enum Spells
{
// Golemagg
- SPELL_MAGMASPLASH = 13879,
- SPELL_PYROBLAST = 20228,
- SPELL_EARTHQUAKE = 19798,
- SPELL_ENRAGE = 19953,
- SPELL_GOLEMAGG_TRUST = 20553,
+ SPELL_PYROBLAST = 20228,
+ SPELL_EARTHQUAKE = 19798,
+ SPELL_ENRAGE = 19953,
+ SPELL_ATTRACK_RAGER = 20544,
// Core Rager
- SPELL_MANGLE = 19820
-};
-
-enum Events
-{
- EVENT_PYROBLAST = 1,
- EVENT_EARTHQUAKE = 2,
+ SPELL_MANGLE = 19820,
+ SPELL_FULL_HEAL = 17683,
};
class boss_golemagg : public CreatureScript
@@ -58,72 +46,79 @@ public:
struct boss_golemaggAI : public BossAI
{
- boss_golemaggAI(Creature* creature) : BossAI(creature, BOSS_GOLEMAGG_THE_INCINERATOR)
- {
- }
+ boss_golemaggAI(Creature* creature) : BossAI(creature, DATA_GOLEMAGG),
+ earthquakeTimer(0),
+ pyroblastTimer(0),
+ enraged(false)
+ {}
void Reset() override
{
- BossAI::Reset();
- DoCast(me, SPELL_MAGMASPLASH, true);
+ _Reset();
+ earthquakeTimer = 0;
+ pyroblastTimer = urand(3000, 7000);
+ enraged = false;
}
- void EnterCombat(Unit* victim) override
+ void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
- BossAI::EnterCombat(victim);
- events.ScheduleEvent(EVENT_PYROBLAST, 7000);
-
- // The two ragers should join the fight alongside me against my foes.
- std::list ragers;
- me->GetCreaturesWithEntryInRange(ragers, 100, NPC_CORE_RAGER);
- for (Creature* i : ragers)
+ if (!enraged && me->HealthBelowPctDamaged(10, damage))
{
- if (i && i->IsAlive() && !i->IsInCombat())
- {
- i->AI()->AttackStart(victim);
- }
+ DoCastSelf(SPELL_ENRAGE, true);
+ DoCastSelf(SPELL_ATTRACK_RAGER, true);
+ DoCastAOE(SPELL_EARTHQUAKE, true);
+ earthquakeTimer = 5000;
+ enraged = true;
}
}
- void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
- {
- if (!HealthBelowPct(10) || me->HasAura(SPELL_ENRAGE))
- return;
-
- DoCast(me, SPELL_ENRAGE, true);
- events.ScheduleEvent(EVENT_EARTHQUAKE, 3000);
- }
-
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
+ {
return;
+ }
- events.Update(diff);
+ // Should not get impact by cast state (cast should always happen)
+ if (earthquakeTimer)
+ {
+ if (earthquakeTimer <= diff)
+ {
+ DoCastAOE(SPELL_EARTHQUAKE, true);
+ earthquakeTimer = 5000;
+ }
+ else
+ {
+ earthquakeTimer -= diff;
+ }
+ }
if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
{
- switch (eventId)
+ return;
+ }
+
+ if (pyroblastTimer <= diff)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
- case EVENT_PYROBLAST:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_PYROBLAST);
- events.ScheduleEvent(EVENT_PYROBLAST, 7000);
- break;
- case EVENT_EARTHQUAKE:
- DoCastVictim(SPELL_EARTHQUAKE);
- events.ScheduleEvent(EVENT_EARTHQUAKE, 3000);
- break;
- default:
- break;
+ DoCast(target, SPELL_PYROBLAST);
}
+
+ pyroblastTimer = 7000;
+ }
+ else
+ {
+ pyroblastTimer -= diff;
}
DoMeleeAttackIfReady();
}
+
+ private:
+ uint32 earthquakeTimer;
+ uint32 pyroblastTimer;
+ bool enraged;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -139,45 +134,79 @@ public:
struct npc_core_ragerAI : public ScriptedAI
{
- npc_core_ragerAI(Creature* creature) : ScriptedAI(creature)
+ npc_core_ragerAI(Creature* creature) : ScriptedAI(creature),
+ instance(creature->GetInstanceScript()),
+ mangleTimer(7000),
+ rangeCheckTimer(1000)
{
- instance = creature->GetInstanceScript();
}
void Reset() override
{
- mangleTimer = 7 * IN_MILLISECONDS; // These times are probably wrong
+ mangleTimer = 7000; // These times are probably wrong
+ rangeCheckTimer = 1000;
+
+ if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
+ {
+ DoCastSelf(SPELL_CORE_RAGER_QUIET_SUICIDE, true);
+ }
}
- void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
{
- if (HealthAbovePct(50) || !instance)
- return;
-
- if (Creature* pGolemagg = instance->instance->GetCreature(instance->GetGuidData(BOSS_GOLEMAGG_THE_INCINERATOR)))
+ // Just in case if something will go bad, let players to kill this creature
+ if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
{
- if (pGolemagg->IsAlive())
- {
- me->AddAura(SPELL_GOLEMAGG_TRUST, me);
- Talk(EMOTE_LOWHP);
- me->SetFullHealth();
- }
+ return;
+ }
+
+ if (me->HealthBelowPctDamaged(50, damage))
+ {
+ damage = 0;
+ DoCastSelf(SPELL_FULL_HEAL, true);
+ Talk(EMOTE_LOWHP);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
+ {
return;
+ }
+
+ // Should have no impact from unit state
+ if (rangeCheckTimer <= diff)
+ {
+ Creature const* golemagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GEDDON));
+ if (golemagg && me->GetDistance(golemagg) > 100.0f)
+ {
+ instance->DoAction(ACTION_RESET_MAGMADAR_ENCOUNTER);
+ return;
+ }
+
+ rangeCheckTimer = 1000;
+ }
+ else
+ {
+ rangeCheckTimer -= diff;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
+ }
// Mangle
if (mangleTimer <= diff)
{
DoCastVictim(SPELL_MANGLE);
- mangleTimer = 10 * IN_MILLISECONDS;
+ mangleTimer = 10000;
}
else
+ {
mangleTimer -= diff;
+ }
DoMeleeAttackIfReady();
}
@@ -185,6 +214,7 @@ public:
private:
InstanceScript* instance;
uint32 mangleTimer;
+ uint32 rangeCheckTimer;
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_lucifron.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_lucifron.cpp
index e5196a2b6..c8465422c 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_lucifron.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_lucifron.cpp
@@ -15,13 +15,6 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Lucifron
-SD%Complete: 100
-SDComment:
-SDCategory: Molten Core
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "molten_core.h"
@@ -47,9 +40,7 @@ public:
struct boss_lucifronAI : public BossAI
{
- boss_lucifronAI(Creature* creature) : BossAI(creature, BOSS_LUCIFRON)
- {
- }
+ boss_lucifronAI(Creature* creature) : BossAI(creature, DATA_LUCIFRON) {}
void EnterCombat(Unit* /*victim*/) override
{
@@ -59,46 +50,29 @@ public:
events.ScheduleEvent(EVENT_SHADOW_SHOCK, 5000);
}
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
{
- if (!UpdateVictim())
+ switch (eventId)
{
- return;
- }
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- {
- return;
- }
-
- while (uint32 const eventId = events.ExecuteEvent())
- {
- switch (eventId)
+ case EVENT_IMPENDING_DOOM:
{
- case EVENT_IMPENDING_DOOM:
- {
- DoCastVictim(SPELL_IMPENDING_DOOM);
- events.RepeatEvent(20000);
- break;
- }
- case EVENT_LUCIFRON_CURSE:
- {
- DoCastVictim(SPELL_LUCIFRON_CURSE);
- events.RepeatEvent(20000);
- break;
- }
- case EVENT_SHADOW_SHOCK:
- {
- DoCastVictim(SPELL_SHADOW_SHOCK);
- events.RepeatEvent(5000);
- break;
- }
+ DoCastVictim(SPELL_IMPENDING_DOOM);
+ events.RepeatEvent(20000);
+ break;
+ }
+ case EVENT_LUCIFRON_CURSE:
+ {
+ DoCastVictim(SPELL_LUCIFRON_CURSE);
+ events.RepeatEvent(20000);
+ break;
+ }
+ case EVENT_SHADOW_SHOCK:
+ {
+ DoCastVictim(SPELL_SHADOW_SHOCK);
+ events.RepeatEvent(5000);
+ break;
}
}
-
- DoMeleeAttackIfReady();
}
};
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp
index 1234f0652..0e52b99eb 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp
@@ -15,102 +15,98 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Magmadar
-SD%Complete: 75
-SDComment: Conflag on ground nyi
-SDCategory: Molten Core
-EndScriptData */
-
-#include "molten_core.h"
-#include "ObjectMgr.h"
-#include "ScriptedCreature.h"
#include "ScriptMgr.h"
+#include "SpellScript.h"
+#include "ScriptedCreature.h"
+#include "molten_core.h"
enum Texts
{
- EMOTE_FRENZY = 0,
- EMOTE_SMOLDERING = 0,
- EMOTE_IGNITE = 1,
+ EMOTE_FRENZY = 0,
};
enum Spells
{
- SPELL_FRENZY = 19451,
- SPELL_MAGMA_SPIT = 19449,
- SPELL_PANIC = 19408,
- SPELL_LAVA_BOMB = 19428,
- SPELL_SERRATED_BITE = 19771,
+ SPELL_FRENZY = 19451,
+ SPELL_MAGMA_SPIT = 19449,
+ SPELL_PANIC = 19408,
+ SPELL_LAVA_BOMB = 19411, // This calls a dummy server side effect that cast spell 20494 to spawn GO 177704 for 30s
+ SPELL_LAVA_BOMB_EFFECT = 20494, // Spawns trap GO 177704 which triggers 19428
+ SPELL_LAVA_BOMB_RANGED = 20474, // This calls a dummy server side effect that cast spell 20495 to spawn GO 177704 for 60s
+ SPELL_LAVA_BOMB_RANGED_EFFECT = 20495, // Spawns trap GO 177704 which triggers 19428
};
enum Events
{
- EVENT_FRENZY = 1,
- EVENT_PANIC = 2,
- EVENT_LAVA_BOMB = 3,
- EVENT_SERRATED_BITE = 1,
- EVENT_IGNITE = 2,
+ EVENT_FRENZY = 1,
+ EVENT_PANIC,
+ EVENT_LAVA_BOMB,
+ EVENT_LAVA_BOMB_RANGED,
};
+constexpr float MELEE_TARGET_LOOKUP_DIST = 10.0f;
+
class boss_magmadar : public CreatureScript
{
public:
- boss_magmadar() : CreatureScript("boss_magmadar") { }
+ boss_magmadar() : CreatureScript("boss_magmadar") {}
struct boss_magmadarAI : public BossAI
{
- boss_magmadarAI(Creature* creature) : BossAI(creature, BOSS_MAGMADAR)
- {
- }
+ boss_magmadarAI(Creature* creature) : BossAI(creature, DATA_MAGMADAR) {}
- void Reset() override
+ void EnterCombat(Unit* /*victim*/) override
{
- BossAI::Reset();
- DoCast(me, SPELL_MAGMA_SPIT, true);
- }
-
- void EnterCombat(Unit* victim) override
- {
- BossAI::EnterCombat(victim);
- events.ScheduleEvent(EVENT_FRENZY, 30000);
- events.ScheduleEvent(EVENT_PANIC, 20000);
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_FRENZY, 8500);
+ events.ScheduleEvent(EVENT_PANIC, 9500);
events.ScheduleEvent(EVENT_LAVA_BOMB, 12000);
+ events.ScheduleEvent(EVENT_LAVA_BOMB_RANGED, 15000);
}
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
{
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_FRENZY:
{
- case EVENT_FRENZY:
- Talk(EMOTE_FRENZY);
- DoCast(me, SPELL_FRENZY);
- events.ScheduleEvent(EVENT_FRENZY, 15000);
- break;
- case EVENT_PANIC:
- DoCastVictim(SPELL_PANIC);
- events.ScheduleEvent(EVENT_PANIC, 35000);
- break;
- case EVENT_LAVA_BOMB:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LAVA_BOMB))
- DoCast(target, SPELL_LAVA_BOMB);
- events.ScheduleEvent(EVENT_LAVA_BOMB, 12000);
- break;
- default:
- break;
+ Talk(EMOTE_FRENZY);
+ DoCastSelf(SPELL_FRENZY);
+ events.RepeatEvent(urand(15000, 20000));
+ break;
+ }
+ case EVENT_PANIC:
+ {
+ DoCastVictim(SPELL_PANIC);
+ events.RepeatEvent(urand(31000, 38000));
+ break;
+ }
+ case EVENT_LAVA_BOMB:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, MELEE_TARGET_LOOKUP_DIST, true))
+ {
+ DoCast(target, SPELL_LAVA_BOMB);
+ }
+
+ events.RepeatEvent(urand(12000, 15000));
+ break;
+ }
+ case EVENT_LAVA_BOMB_RANGED:
+ {
+ std::list targets;
+ SelectTargetList(targets, [this](Unit* target)
+ {
+ return target && target->IsPlayer() && target->GetDistance(me) > MELEE_TARGET_LOOKUP_DIST && target->GetDistance(me) < 100.0f;
+ }, 1, SELECT_TARGET_RANDOM);
+
+ if (!targets.empty())
+ {
+ DoCast(targets.front() , SPELL_LAVA_BOMB_RANGED);
+ }
+ events.RepeatEvent(urand(12000, 15000));
+ break;
}
}
-
- DoMeleeAttackIfReady();
}
};
@@ -120,142 +116,64 @@ public:
}
};
-// Serrated Bites timer may be wrong
-class npc_magmadar_core_hound : public CreatureScript
+// 19411 Lava Bomb
+// 20474 Lava Bomb
+class spell_magmadar_lava_bomb : public SpellScriptLoader
{
public:
- npc_magmadar_core_hound() : CreatureScript("npc_magmadar_core_hound") { }
+ spell_magmadar_lava_bomb() : SpellScriptLoader("spell_magmadar_lava_bomb") {}
- struct npc_magmadar_core_houndAI : public CreatureAI
+ class spell_magmadar_lava_bomb_SpellScript : public SpellScript
{
- npc_magmadar_core_houndAI(Creature* creature) : CreatureAI(creature)
+ PrepareSpellScript(spell_magmadar_lava_bomb_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
{
+ return ValidateSpellInfo({ SPELL_LAVA_BOMB_EFFECT, SPELL_LAVA_BOMB_RANGED_EFFECT });
}
- EventMap events;
- std::list hounds;
- bool smoldering = false;
- Unit* killer;
-
- void removeFeignDeath()
+ void HandleDummy(SpellEffIndex /*effIndex*/)
{
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
- me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
- me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
- me->ClearUnitState(UNIT_STATE_DIED);
- me->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK);
- me->DisableRotate(false);
- }
-
- void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
- {
- if (me->HealthBelowPctDamaged(0, damage))
+ if (Unit* target = GetHitUnit())
{
- if (!smoldering)
+ uint32 spellId = 0;
+ switch (m_scriptSpellId)
{
- killer = attacker;
- events.ScheduleEvent(EVENT_IGNITE, 10000);
- me->SetHealth(1);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
- me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
- me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
- me->AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
- me->AddUnitState(UNIT_STATE_DIED);
- me->AddUnitState(UNIT_STATE_CANNOT_AUTOATTACK);
- me->DisableRotate(true);
- Talk(EMOTE_SMOLDERING);
- }
- damage = 0;
- smoldering = true;
- }
- }
-
- void Reset() override
- {
- removeFeignDeath();
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- removeFeignDeath();
- }
-
- void EnterCombat(Unit* /*victim*/) override
- {
- events.ScheduleEvent(EVENT_SERRATED_BITE, 10000); // timer may be wrong
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim() && !smoldering)
- return;
-
- events.Update(diff);
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_SERRATED_BITE:
- if (UpdateVictim() && !smoldering)
- {
- DoCast(me->GetVictim(), SPELL_SERRATED_BITE);
- events.ScheduleEvent(EVENT_SERRATED_BITE, 10000); // again, timer may be wrong
- }
+ case SPELL_LAVA_BOMB:
+ {
+ spellId = SPELL_LAVA_BOMB_EFFECT;
break;
- case EVENT_IGNITE:
- smoldering = false;
- me->GetCreaturesWithEntryInRange(hounds, 80, NPC_CORE_HOUND);
- for (Creature* i : hounds)
- {
- if (i && i->IsAlive() && i->IsInCombat() && !i->HasUnitState(UNIT_STATE_DIED))
- {
- Talk(EMOTE_IGNITE);
- me->SetFullHealth();
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
- me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
- me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
- me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
- me->ClearUnitState(UNIT_STATE_DIED);
- me->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK);
- me->DisableRotate(false);
- me->AI()->AttackStart(i->GetVictim());
- return;
- }
- }
- if (me->HasUnitState(UNIT_STATE_DIED))
- {
- if (killer)
- {
- me->Kill(killer, me);
- }
- else
- {
- me->Kill(me, me);
- }
- }
+ }
+ case SPELL_LAVA_BOMB_RANGED:
+ {
+ spellId = SPELL_LAVA_BOMB_RANGED_EFFECT;
break;
+ }
default:
- break;
+ {
+ return;
+ }
}
+ target->CastSpell(target, spellId, true, nullptr, nullptr, GetCaster()->GetGUID());
}
+ }
- DoMeleeAttackIfReady();
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_magmadar_lava_bomb_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
- CreatureAI* GetAI(Creature* creature) const override
+ SpellScript* GetSpellScript() const override
{
- return GetMoltenCoreAI(creature);
+ return new spell_magmadar_lava_bomb_SpellScript();
}
};
void AddSC_boss_magmadar()
{
new boss_magmadar();
- new npc_magmadar_core_hound();
+
+ // Spells
+ new spell_magmadar_lava_bomb();
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp
index 2b6eb4229..b9ab56ed3 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp
@@ -15,192 +15,561 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Majordomo_Executus
-SD%Complete: 30
-SDComment: Correct spawning and Event NYI
-SDCategory: Molten Core
-EndScriptData */
-
-#include "molten_core.h"
-#include "ObjectMgr.h"
-#include "Player.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "molten_core.h"
+#include "Player.h"
+#include "ScriptedGossip.h"
+#include "ObjectAccessor.h"
+#include "SpellScript.h"
enum Texts
{
- SAY_AGGRO = 0,
- SAY_SPAWN = 1,
- SAY_SLAY = 2,
- SAY_SPECIAL = 3,
- SAY_DEFEAT = 4,
+ SAY_AGGRO = 0,
+ SAY_SPAWN = 1,
+ SAY_SLAY = 2,
+ SAY_DEFEAT = 3,
+ SAY_SUMMON_MAJ = 4,
+ SAY_ARRIVAL2_MAJ = 5,
+ SAY_LAST_ADD = 6,
- SAY_SUMMON_MAJ = 5,
- SAY_ARRIVAL2_MAJ = 6
+ SAY_DEFEAT_2 = 7,
+ SAY_DEFEAT_3 = 8,
+
+ // Ragnaros event
+ // Majordomo
+ SAY_RAG_SUM_1 = 9,
+ SAY_RAG_SUM_2 = 10,
+
+ // Ragnaros
+ SAY_ARRIVAL1_RAG = 1,
+ SAY_ARRIVAL3_RAG = 3,
};
enum Spells
{
- SPELL_MAGIC_REFLECTION = 20619,
- SPELL_DAMAGE_REFLECTION = 21075,
- SPELL_BLAST_WAVE = 20229,
- SPELL_AEGIS_OF_RAGNAROS = 20620,
- SPELL_TELEPORT = 20618,
- SPELL_SUMMON_RAGNAROS = 19774,
-};
+ SPELL_MAGIC_REFLECTION = 20619,
+ SPELL_DAMAGE_REFLECTION = 21075,
+ SPELL_BLAST_WAVE = 20229,
+ SPELL_AEGIS_OF_RAGNAROS = 20620,
+ SPELL_TELEPORT_RANDOM = 20618, // Teleport random target
+ SPELL_TELEPORT_TARGET = 20534, // Teleport Victim
+ SPELL_ENCOURAGEMENT = 21086,
+ SPELL_CHAMPION = 21090, // Server side
+ SPELL_IMMUNE_POLY = 21087, // Server side
+ SPELL_HATE_TO_ZERO = 20538, // Threat reset after each teleport. Server side
+ SPELL_SEPARATION_ANXIETY = 21094, // Aura cast on himself by Majordomo Executus, if adds move out of range, they will cast spell 21095 on themselves
+ SPELL_SEPARATION_ANXIETY_MINION = 21095,
-#define GOSSIP_HELLO 4995
+ // Outro & Ragnaros intro
+ SPELL_TELEPORT_SELF = 19484,
+ SPELL_SUMMON_RAGNAROS = 19774,
+ SPELL_ELEMENTAL_FIRE = 19773,
+ SPELL_RAGNA_EMERGE = 20568,
+ SPELL_RAGNAROS_FADE = 21107,
+ SPELL_RAGNAROS_SUBMERGE_EFFECT = 21859, // Applies pacify state and applies all schools immunity
+};
enum Events
{
- EVENT_MAGIC_REFLECTION = 1,
- EVENT_DAMAGE_REFLECTION = 2,
- EVENT_BLAST_WAVE = 3,
- EVENT_TELEPORT = 4,
+ EVENT_MAGIC_REFLECTION = 1,
+ EVENT_DAMAGE_REFLECTION,
+ EVENT_BLAST_WAVE,
+ EVENT_TELEPORT_RANDOM,
+ EVENT_TELEPORT_TARGET,
+ EVENT_AEGIS_OF_RAGNAROS,
- EVENT_OUTRO_1 = 5,
- EVENT_OUTRO_2 = 6,
- EVENT_OUTRO_3 = 7,
+ EVENT_DEFEAT_OUTRO_1 = 1,
+ EVENT_DEFEAT_OUTRO_2,
+ EVENT_DEFEAT_OUTRO_3,
+
+ EVENT_RAGNAROS_SUMMON_1 = 1,
+ EVENT_RAGNAROS_SUMMON_2,
+ EVENT_RAGNAROS_SUMMON_3,
+ EVENT_RAGNAROS_SUMMON_4,
+ EVENT_RAGNAROS_SUMMON_5,
+ EVENT_RAGNAROS_SUMMON_6,
+ EVENT_RAGNAROS_SUMMON_7,
+ EVENT_RAGNAROS_EMERGE,
};
+enum Misc
+{
+ TEXT_ID_SUMMON_1 = 4995,
+ TEXT_ID_SUMMON_2 = 5011,
+ TEXT_ID_SUMMON_3 = 5012,
+
+ GOSSIP_ITEM_SUMMON_1 = 4093,
+ GOSSIP_ITEM_SUMMON_2 = 4109,
+ GOSSIP_ITEM_SUMMON_3 = 4108,
+
+ FACTION_MAJORDOMO_FRIENDLY = 1080,
+ SUMMON_GROUP_ADDS = 1,
+
+ // Points
+ POINT_RAGNAROS_SUMMON = 1,
+
+ // Event phases
+ PHASE_NONE = 1,
+ PHASE_COMBAT = 2,
+ PHASE_DEFEAT_OUTRO = 3,
+ PHASE_RAGNAROS_SUMMONING = 4,
+};
+
+Position const MajordomoRagnaros = { 848.933f, -812.875f, -229.601f, 4.046f };
+Position const MajordomoSummonPos = {759.542f, -1173.43f, -118.974f, 3.3048f };
+Position const MajordomoMoveRagPos = { 830.9636f, -814.7055f, -228.9733f, 0.0f }; // Position used at Ragnaros summoning event
+Position const RagnarosSummonPos = { 838.3082f, -831.4665f, -232.1853f, 2.199115f };
+
class boss_majordomo : public CreatureScript
{
public:
- boss_majordomo() : CreatureScript("boss_majordomo") { }
+ boss_majordomo() : CreatureScript("boss_majordomo") {}
struct boss_majordomoAI : public BossAI
{
- boss_majordomoAI(Creature* creature) : BossAI(creature, BOSS_MAJORDOMO_EXECUTUS)
+ boss_majordomoAI(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_EXECUTUS), spawnInTextTimer(0) {}
+
+ // Disabled events
+ void JustDied(Unit* /*killer*/) override {}
+
+ void JustSummoned(Creature* summon) override
{
+ if (summon->GetEntry() == NPC_RAGNAROS)
+ {
+ summon->CastSpell(summon, SPELL_RAGNAROS_FADE);
+ summon->CastSpell(summon, SPELL_RAGNAROS_SUBMERGE_EFFECT, true);
+ summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NON_ATTACKABLE);
+ summon->SetReactState(REACT_PASSIVE);
+ }
}
- void KilledUnit(Unit* /*victim*/) override
+ void InitializeAI() override
{
- if (urand(0, 99) < 25)
+ BossAI::InitializeAI();
+ if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
+ {
+ events.SetPhase(PHASE_COMBAT);
+
+ std::list p_summons;
+ me->SummonCreatureGroup(SUMMON_GROUP_ADDS, &p_summons);
+ if (!p_summons.empty())
+ {
+ for (TempSummon const* summon : p_summons)
+ {
+ if (summon)
+ {
+ static_minionsGUIDS.insert(summon->GetGUID());
+ }
+ }
+ }
+
+ spawnInTextTimer = 10000;
+ }
+ else
+ {
+ events.SetPhase(PHASE_NONE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
+ }
+ }
+
+ void Reset() override
+ {
+ me->ResetLootMode();
+ events.Reset();
+ aliveMinionsGUIDS.clear();
+
+ if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
+ {
+ events.SetPhase(PHASE_COMBAT);
+ instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, NOT_STARTED);
+ }
+ else
+ {
+ static_minionsGUIDS.clear();
+ summons.DespawnAll();
+ }
+ }
+
+ bool CanAIAttack(Unit const* /*target*/) const override
+ {
+ return instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE;
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (roll_chance_i(25) && victim->IsPlayer())
+ {
Talk(SAY_SLAY);
+ }
}
- void EnterCombat(Unit* who) override
+ void EnterCombat(Unit* /*attacker*/) override
{
- BossAI::EnterCombat(who);
+ if (!events.IsInPhase(PHASE_COMBAT))
+ {
+ return;
+ }
+
+ _EnterCombat();
+ DoCastAOE(SPELL_SEPARATION_ANXIETY);
+ spawnInTextTimer = 0;
Talk(SAY_AGGRO);
- events.ScheduleEvent(EVENT_MAGIC_REFLECTION, 30000);
- events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 15000);
- events.ScheduleEvent(EVENT_BLAST_WAVE, 10000);
- events.ScheduleEvent(EVENT_TELEPORT, 20000);
- // Call every flamewaker around him
- me->CallForHelp(30);
+ DoCastSelf(SPELL_AEGIS_OF_RAGNAROS, true);
+
+ events.ScheduleEvent(EVENT_MAGIC_REFLECTION, 30000, PHASE_COMBAT, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 15000, PHASE_COMBAT, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_BLAST_WAVE, 10000, PHASE_COMBAT, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_TELEPORT_RANDOM, 15000, PHASE_COMBAT, PHASE_COMBAT);
+ events.ScheduleEvent(EVENT_TELEPORT_TARGET, 30000, PHASE_COMBAT, PHASE_COMBAT);
+
+ aliveMinionsGUIDS.clear();
+ aliveMinionsGUIDS = static_minionsGUIDS;
+ }
+
+ void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ {
+ aliveMinionsGUIDS.erase(summon->GetGUID());
+ if (summon->GetEntry() == NPC_FLAMEWAKER_HEALER || summon->GetEntry() == NPC_FLAMEWAKER_ELITE)
+ {
+ uint32 const remainingAdds = std::count_if(aliveMinionsGUIDS.begin(), aliveMinionsGUIDS.end(), [](ObjectGuid const& summonGuid)
+ {
+ return summonGuid.GetEntry() == NPC_FLAMEWAKER_HEALER || summonGuid.GetEntry() == NPC_FLAMEWAKER_ELITE;
+ });
+
+ // Last remaining add
+ if (remainingAdds == 1)
+ {
+ Talk(SAY_LAST_ADD);
+ DoCastAOE(SPELL_CHAMPION);
+ }
+ // 50% of adds
+ else if (remainingAdds == 4)
+ {
+ DoCastAOE(SPELL_IMMUNE_POLY);
+ }
+ else if (!remainingAdds)
+ {
+ if (!static_minionsGUIDS.empty())
+ {
+ for (ObjectGuid const& guid : static_minionsGUIDS)
+ {
+ if (Creature* minion = ObjectAccessor::GetCreature(*me, guid))
+ {
+ minion->DespawnOrUnsummon();
+ }
+ }
+
+ static_minionsGUIDS.clear();
+ }
+
+ instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, DONE);
+ events.CancelEventGroup(PHASE_COMBAT);
+ me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
+ me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
+ EnterEvadeMode();
+ Talk(SAY_DEFEAT);
+ return;
+ }
+ DoCastAOE(SPELL_ENCOURAGEMENT);
+ }
+ }
+
+ void JustReachedHome() override
+ {
+ _JustReachedHome();
+ if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) == DONE)
+ {
+ events.Reset();
+ events.SetPhase(PHASE_DEFEAT_OUTRO);
+ events.ScheduleEvent(EVENT_DEFEAT_OUTRO_1, 7500, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
+ }
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
+ {
+ if (events.IsInPhase(PHASE_COMBAT) && me->GetHealth() <= damage)
+ {
+ damage = 0;
+ }
}
void UpdateAI(uint32 diff) override
{
- if (instance->GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE)
+ if (spawnInTextTimer)
{
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (!me->FindNearestCreature(NPC_FLAMEWAKER_HEALER, 100.0f) && !me->FindNearestCreature(NPC_FLAMEWAKER_ELITE, 100.0f))
+ if (spawnInTextTimer <= diff)
{
- me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me);
- me->SetFaction(FACTION_FRIENDLY);
- EnterEvadeMode();
- Talk(SAY_DEFEAT);
- _JustDied();
- events.ScheduleEvent(EVENT_OUTRO_1, 32000);
- return;
+ spawnInTextTimer = 0;
+ Talk(SAY_SPAWN);
}
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- if (HealthBelowPct(50))
- DoCast(me, SPELL_AEGIS_OF_RAGNAROS, true);
-
- while (uint32 eventId = events.ExecuteEvent())
+ else
{
- switch (eventId)
- {
- case EVENT_MAGIC_REFLECTION:
- DoCast(me, SPELL_MAGIC_REFLECTION);
- events.ScheduleEvent(EVENT_MAGIC_REFLECTION, 30000);
- break;
- case EVENT_DAMAGE_REFLECTION:
- DoCast(me, SPELL_DAMAGE_REFLECTION);
- events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 30000);
- break;
- case EVENT_BLAST_WAVE:
- DoCastVictim(SPELL_BLAST_WAVE);
- events.ScheduleEvent(EVENT_BLAST_WAVE, 10000);
- break;
- case EVENT_TELEPORT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
- DoCast(target, SPELL_TELEPORT);
- events.ScheduleEvent(EVENT_TELEPORT, 20000);
- break;
- default:
- break;
- }
+ spawnInTextTimer -= diff;
}
-
- DoMeleeAttackIfReady();
}
- else
- {
- events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ switch (events.GetPhaseMask())
+ {
+ case (1 << (PHASE_COMBAT - 1)):
{
- switch (eventId)
+ if (!UpdateVictim())
{
- case EVENT_OUTRO_1:
- me->NearTeleportTo(RagnarosTelePos.GetPositionX(), RagnarosTelePos.GetPositionY(), RagnarosTelePos.GetPositionZ(), RagnarosTelePos.GetOrientation());
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- break;
- case EVENT_OUTRO_2:
- instance->instance->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos);
- break;
- case EVENT_OUTRO_3:
- Talk(SAY_ARRIVAL2_MAJ);
- break;
- default:
- break;
+ return;
}
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
+ }
+
+ while (uint32 const eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MAGIC_REFLECTION:
+ {
+ DoCastSelf(SPELL_MAGIC_REFLECTION);
+ events.RepeatEvent(30000);
+ break;
+ }
+ case EVENT_DAMAGE_REFLECTION:
+ {
+ DoCastSelf(SPELL_DAMAGE_REFLECTION);
+ events.RepeatEvent(30000);
+ break;
+ }
+ case EVENT_BLAST_WAVE:
+ {
+ DoCastVictim(SPELL_BLAST_WAVE);
+ events.RepeatEvent(10000);
+ break;
+ }
+ case EVENT_TELEPORT_RANDOM:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
+ {
+ DoCastSelf(SPELL_HATE_TO_ZERO, true);
+ DoCast(target, SPELL_TELEPORT_RANDOM);
+ }
+
+ events.RepeatEvent(15000);
+ break;
+ }
+ case EVENT_TELEPORT_TARGET:
+ {
+ DoCastSelf(SPELL_HATE_TO_ZERO, true);
+ DoCastAOE(SPELL_TELEPORT_TARGET);
+ events.RepeatEvent(30000);
+ break;
+ }
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ break;
}
+ case (1 << (PHASE_DEFEAT_OUTRO - 1)):
+ {
+ events.Update(diff);
+ while (uint32 const eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DEFEAT_OUTRO_1:
+ {
+ Talk(SAY_DEFEAT_2);
+ events.ScheduleEvent(EVENT_DEFEAT_OUTRO_2, 8000, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
+ break;
+ }
+ case EVENT_DEFEAT_OUTRO_2:
+ {
+ Talk(SAY_DEFEAT_3);
+ events.ScheduleEvent(EVENT_DEFEAT_OUTRO_3, 21500, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
+ break;
+ }
+ case EVENT_DEFEAT_OUTRO_3:
+ {
+ DoCastSelf(SPELL_TELEPORT_SELF);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case (1 << (PHASE_RAGNAROS_SUMMONING - 1)):
+ {
+ events.Update(diff);
+ while (uint32 const eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RAGNAROS_SUMMON_1:
+ {
+ if (GameObject* lavaSplash = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_SPLASH)))
+ {
+ lavaSplash->SetRespawnTime(900);
+ lavaSplash->Refresh();
+ }
+ if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
+ {
+ lavaSteam->SetRespawnTime(900);
+ lavaSteam->Refresh();
+ }
+ Talk(SAY_RAG_SUM_2);
+ // Next event will get triggered in MovementInform
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(POINT_RAGNAROS_SUMMON, MajordomoMoveRagPos, true, false);
+ break;
+ }
+ case EVENT_RAGNAROS_SUMMON_2:
+ {
+ if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
+ {
+ me->SetFacingToObject(lavaSteam);
+ }
+
+ Talk(SAY_SUMMON_MAJ);
+ events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_3, 16700, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
+ events.ScheduleEvent(EVENT_RAGNAROS_EMERGE, 15000, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
+ break;
+ }
+ case EVENT_RAGNAROS_SUMMON_3:
+ {
+ if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
+ {
+ ragnaros->AI()->Talk(SAY_ARRIVAL1_RAG);
+ }
+ events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_4, 11700, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
+ break;
+ }
+ case EVENT_RAGNAROS_SUMMON_4:
+ {
+ Talk(SAY_ARRIVAL2_MAJ);
+ events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_5, 8700, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
+ break;
+ }
+ case EVENT_RAGNAROS_SUMMON_5:
+ {
+ if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
+ {
+ ragnaros->AI()->Talk(SAY_ARRIVAL3_RAG);
+ }
+
+ events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_6, 16500, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
+ break;
+ }
+ case EVENT_RAGNAROS_SUMMON_6:
+ {
+ if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
+ {
+ ragnaros->CastSpell(me, SPELL_ELEMENTAL_FIRE, true);
+ ragnaros->AI()->DoAction(ACTION_FINISH_RAGNAROS_INTRO);
+ }
+ break;
+ }
+ // Additional events
+ case EVENT_RAGNAROS_EMERGE:
+ {
+ if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
+ {
+ ragnaros->RemoveAurasDueToSpell(SPELL_RAGNAROS_FADE);
+ ragnaros->CastSpell(ragnaros, SPELL_RAGNA_EMERGE);
+ }
+ }break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type == POINT_MOTION_TYPE && pointId == POINT_RAGNAROS_SUMMON)
+ {
+ DoCastAOE(SPELL_SUMMON_RAGNAROS);
+ events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_2, 11500, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
+ }
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
+ {
+ if (events.IsInPhase(PHASE_DEFEAT_OUTRO) && spellInfo->Id == SPELL_TELEPORT_SELF)
+ {
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->SetHomePosition(MajordomoRagnaros);
+ me->NearTeleportTo(MajordomoRagnaros.GetPositionX(), MajordomoRagnaros.GetPositionY(), MajordomoRagnaros.GetPositionZ(), MajordomoRagnaros.GetOrientation());
+ events.SetPhase(PHASE_NONE);
}
}
void DoAction(int32 action) override
{
- if (action == ACTION_START_RAGNAROS && events.GetNextEventTime(EVENT_OUTRO_2) == 0)
+ if (action == ACTION_START_RAGNAROS_INTRO && !events.IsInPhase(PHASE_RAGNAROS_SUMMONING))
{
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- Talk(SAY_SUMMON_MAJ);
- events.ScheduleEvent(EVENT_OUTRO_2, 8000);
- events.ScheduleEvent(EVENT_OUTRO_3, 24000);
- }
- else if (action == ACTION_START_RAGNAROS_ALT)
- {
- me->SetFaction(FACTION_FRIENDLY);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ events.SetPhase(PHASE_RAGNAROS_SUMMONING);
+ events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_1, 5000, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
}
}
+ private:
+ GuidSet static_minionsGUIDS; // contained data should be changed on encounter completion
+ GuidSet aliveMinionsGUIDS; // used for calculations
+ uint32 spawnInTextTimer;
};
bool OnGossipHello(Player* player, Creature* creature) override
{
- AddGossipItemFor(player, 4093, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, GOSSIP_HELLO, creature->GetGUID());
+ AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ SendGossipMenuFor(player, TEXT_ID_SUMMON_1, creature->GetGUID());
return true;
}
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 /*action*/) override
+ bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
- CloseGossipMenuFor(player);
- creature->AI()->DoAction(ACTION_START_RAGNAROS);
+ ClearGossipMenuFor(player);
+ switch (action)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ {
+ AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ SendGossipMenuFor(player, TEXT_ID_SUMMON_2, creature->GetGUID());
+ break;
+ }
+ case GOSSIP_ACTION_INFO_DEF+1:
+ {
+ AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ SendGossipMenuFor(player, TEXT_ID_SUMMON_2, creature->GetGUID());
+ break;
+ }
+ case GOSSIP_ACTION_INFO_DEF+2:
+ {
+ AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_3, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ SendGossipMenuFor(player, TEXT_ID_SUMMON_3, creature->GetGUID());
+ break;
+ }
+ case GOSSIP_ACTION_INFO_DEF+3:
+ {
+ CloseGossipMenuFor(player);
+ creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ creature->AI()->Talk(SAY_RAG_SUM_1, player);
+ creature->AI()->DoAction(ACTION_START_RAGNAROS_INTRO);
+ break;
+ }
+ default:
+ CloseGossipMenuFor(player);
+ break;
+ }
return true;
}
@@ -210,7 +579,118 @@ public:
}
};
+// 20538 Hate to Zero (SERVERSIDE)
+class spell_hate_to_zero : public SpellScriptLoader
+{
+public:
+ spell_hate_to_zero() : SpellScriptLoader("spell_hate_to_zero") {}
+
+ class spell_hate_to_zero_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_hate_to_zero_SpellScript);
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void HandleHit(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* caster = GetCaster())
+ {
+ if (Creature* creatureCaster = caster->ToCreature())
+ {
+ creatureCaster->getThreatMgr().resetAllAggro();
+ }
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_hate_to_zero_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_hate_to_zero_SpellScript();
+ }
+};
+
+// 21094 Separation Anxiety (server side)
+class spell_majordomo_separation_nexiety : public SpellScriptLoader
+{
+public:
+ spell_majordomo_separation_nexiety() : SpellScriptLoader("spell_majordomo_separation_nexiety") {}
+
+ class spell_majordomo_separation_nexiety_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_majordomo_separation_nexiety_AuraScript);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SEPARATION_ANXIETY_MINION });
+ }
+
+ void HandlePeriodic(AuraEffect const* aurEff)
+ {
+ Unit const* caster = GetCaster();
+ Unit* target = GetTarget();
+ if (caster && target && target->GetDistance(caster) > 40.0f && !target->HasAura(SPELL_SEPARATION_ANXIETY_MINION))
+ {
+ target->CastSpell(target, SPELL_SEPARATION_ANXIETY_MINION, true, nullptr, aurEff);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_majordomo_separation_nexiety_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ // Should return a fully valid AuraScript pointer.
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_majordomo_separation_nexiety_AuraScript();
+ }
+};
+
+// 19774 Summon Ragnaros
+class spell_summon_ragnaros : public SpellScriptLoader
+{
+public:
+ spell_summon_ragnaros() : SpellScriptLoader("spell_summon_ragnaros") {}
+
+ class spell_summon_ragnaros_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_summon_ragnaros_SpellScript);
+
+ void HandleHit()
+ {
+ if (Unit* caster = GetCaster())
+ {
+ caster->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 2 * HOUR * IN_MILLISECONDS);
+ }
+ }
+
+ void Register() override
+ {
+ AfterCast += SpellCastFn(spell_summon_ragnaros_SpellScript::HandleHit);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_summon_ragnaros_SpellScript();
+ }
+};
+
void AddSC_boss_majordomo()
{
new boss_majordomo();
+
+ // Spells
+ new spell_hate_to_zero();
+ new spell_majordomo_separation_nexiety();
+ new spell_summon_ragnaros();
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
index 2e7055318..464b36ae6 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp
@@ -15,289 +15,304 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Ragnaros
-SD%Complete: 95
-SDComment: some spells doesnt work correctly
-SDCategory: Molten Core
-EndScriptData */
-
-#include "molten_core.h"
-#include "ScriptedCreature.h"
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "molten_core.h"
enum Texts
{
- SAY_SUMMON_MAJ = 0,
- SAY_ARRIVAL1_RAG = 1,
- SAY_ARRIVAL2_MAJ = 2,
- SAY_ARRIVAL3_RAG = 3,
- SAY_ARRIVAL5_RAG = 4,
- SAY_REINFORCEMENTS1 = 5,
- SAY_REINFORCEMENTS2 = 6,
- SAY_HAND = 7,
- SAY_WRATH = 8,
- SAY_KILL = 9,
- SAY_MAGMABURST = 10
+ SAY_SUMMON_MAJ = 0,
+ SAY_ARRIVAL1_RAG = 1,
+ SAY_ARRIVAL2_MAJ = 2,
+ SAY_ARRIVAL3_RAG = 3,
+ SAY_ARRIVAL5_RAG = 4,
+ SAY_REINFORCEMENTS1 = 5,
+ SAY_REINFORCEMENTS2 = 6,
+ SAY_HAND = 7,
+ SAY_WRATH = 8,
+ SAY_KILL = 9,
+ SAY_MAGMABURST = 10
};
enum Spells
{
- SPELL_HAND_OF_RAGNAROS = 19780,
- SPELL_WRATH_OF_RAGNAROS = 20566,
- SPELL_LAVA_BURST = 21158,
- SPELL_MAGMA_BLAST = 20565, // Ranged attack
- SPELL_SONS_OF_FLAME_DUMMY = 21108, // Server side effect
- SPELL_RAGSUBMERGE = 21107, // Stealth aura
- SPELL_RAGEMERGE = 20568,
- SPELL_MELT_WEAPON = 21388,
- SPELL_ELEMENTAL_FIRE = 20564,
- SPELL_ERRUPTION = 17731
+ SPELL_HAND_OF_RAGNAROS = 19780,
+ SPELL_WRATH_OF_RAGNAROS = 20566,
+ SPELL_LAVA_BURST = 21158,
+ SPELL_MAGMA_BLAST = 20565, // Ranged attack
+ SPELL_SONS_OF_FLAME_DUMMY = 21108, // Server side effect
+ SPELL_RAGSUBMERGE = 21107, // Stealth aura
+ SPELL_RAGNA_SUBMERGE_VISUAL = 20567, // Visual for submerging into lava
+ SPELL_RAGEMERGE = 20568,
+ SPELL_MELT_WEAPON = 21387,
+ SPELL_ELEMENTAL_FIRE = 20563,
+ SPELL_ERRUPTION = 17731,
+ SPELL_RAGNAROS_SUBMERGE_EFFECT = 21859, // Applies pacify state and applies all schools immunity
};
enum Events
{
EVENT_ERUPTION = 1,
- EVENT_WRATH_OF_RAGNAROS = 2,
- EVENT_HAND_OF_RAGNAROS = 3,
- EVENT_LAVA_BURST = 4,
- EVENT_ELEMENTAL_FIRE = 5,
- EVENT_MAGMA_BLAST = 6,
- EVENT_SUBMERGE = 7,
+ EVENT_WRATH_OF_RAGNAROS,
+ EVENT_HAND_OF_RAGNAROS,
+ EVENT_LAVA_BURST,
+ EVENT_MAGMA_BLAST,
+ EVENT_SUBMERGE,
- EVENT_INTRO_1 = 8,
- EVENT_INTRO_2 = 9,
- EVENT_INTRO_3 = 10,
- EVENT_INTRO_4 = 11,
- EVENT_INTRO_5 = 12
+ EVENT_INTRO_1,
+ EVENT_INTRO_2,
+ EVENT_INTRO_3,
+ EVENT_INTRO_4,
+ EVENT_INTRO_5,
};
+enum Creatures
+{
+ NPC_SON_OF_FLAME = 12143,
+};
+
+enum Misc
+{
+ MAX_SON_OF_FLAME_COUNT = 8,
+};
+
+constexpr float DEATH_ORIENTATION = 4.0f;
+
class boss_ragnaros : public CreatureScript
{
public:
- boss_ragnaros() : CreatureScript("boss_ragnaros") { }
+ boss_ragnaros() : CreatureScript("boss_ragnaros") {}
struct boss_ragnarosAI : public BossAI
{
- boss_ragnarosAI(Creature* creature) : BossAI(creature, BOSS_RAGNAROS)
+ boss_ragnarosAI(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
+ attackableTImer(0),
+ _emergeTimer(90000),
+ _hasYelledMagmaBurst(false),
+ _hasSubmergedOnce(false),
+ _isBanished(false)
{
- _introState = 0;
- me->SetReactState(REACT_PASSIVE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ creature->SetReactState(REACT_PASSIVE);
+ creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
void Reset() override
{
- BossAI::Reset();
+ _Reset();
_emergeTimer = 90000;
_hasYelledMagmaBurst = false;
_hasSubmergedOnce = false;
_isBanished = false;
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
+ DoCastSelf(SPELL_MELT_WEAPON, true);
+ DoCastSelf(SPELL_ELEMENTAL_FIRE, true);
}
- void EnterCombat(Unit* victim) override
+ void DoAction(int32 action) override
{
- BossAI::EnterCombat(victim);
+ if (action == ACTION_FINISH_RAGNAROS_INTRO)
+ {
+ attackableTImer = 10000;
+ }
+ }
+
+ void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
+ {
+ summons.Despawn(summon);
+ }
+
+ void EnterCombat(Unit* /*victim*/) override
+ {
+ _EnterCombat();
events.ScheduleEvent(EVENT_ERUPTION, 15000);
events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30000);
events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 25000);
events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
- events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, 3000);
events.ScheduleEvent(EVENT_MAGMA_BLAST, 2000);
events.ScheduleEvent(EVENT_SUBMERGE, 180000);
}
- void JustDied(Unit* killer) override
+ void JustDied(Unit* /*killer*/) override
{
- BossAI::JustDied(killer);
+ _JustDied();
me->SetFacingTo(DEATH_ORIENTATION);
}
- void KilledUnit(Unit* /*victim*/) override
+ void KilledUnit(Unit* victim) override
{
- if (urand(0, 99) < 25)
+ if (roll_chance_i(25) && victim->GetTypeId() == TYPEID_PLAYER)
+ {
Talk(SAY_KILL);
+ }
}
void AttackStart(Unit* target) override
{
if (target && me->Attack(target, true))
+ {
DoStartNoMovement(target);
+ }
}
void UpdateAI(uint32 diff) override
{
- if (_introState != 2)
+ if (attackableTImer)
{
- if (!_introState)
+ if (attackableTImer <= diff)
{
- me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
- events.ScheduleEvent(EVENT_INTRO_1, 4000);
- events.ScheduleEvent(EVENT_INTRO_2, 23000);
- events.ScheduleEvent(EVENT_INTRO_3, 42000);
- events.ScheduleEvent(EVENT_INTRO_4, 43000);
- events.ScheduleEvent(EVENT_INTRO_5, 53000);
- _introState = 1;
- }
-
- events.Update(diff);
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_INTRO_1:
- Talk(SAY_ARRIVAL1_RAG);
- break;
- case EVENT_INTRO_2:
- Talk(SAY_ARRIVAL3_RAG);
- break;
- case EVENT_INTRO_3:
- me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H);
- break;
- case EVENT_INTRO_4:
- Talk(SAY_ARRIVAL5_RAG);
- if (Creature* executus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MAJORDOMO_EXECUTUS)))
- Unit::Kill(me, executus);
- break;
- case EVENT_INTRO_5:
- me->SetReactState(REACT_AGGRESSIVE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- _introState = 2;
- break;
- default:
- break;
- }
- }
- }
- else
- {
- if (_isBanished && ((_emergeTimer <= diff) || (instance->GetData(DATA_RAGNAROS_ADDS)) > 8))
- {
- //Become unbanished again
+ me->RemoveAurasDueToSpell(SPELL_RAGNAROS_SUBMERGE_EFFECT);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_AGGRESSIVE);
- me->SetFaction(FACTION_MONSTER);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
- me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- AttackStart(target);
- instance->SetData(DATA_RAGNAROS_ADDS, 0);
- _isBanished = false;
+ DoZoneInCombat();
+ attackableTImer = 0;
}
- else if (_isBanished)
+ else
{
- _emergeTimer -= diff;
- return;
+ attackableTImer -= diff;
+ }
+ }
+
+ if (_isBanished && (_emergeTimer <= diff || !summons.HasEntry(NPC_SON_OF_FLAME)))
+ {
+ //Become unbanished again
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetFaction(14);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ {
+ AttackStart(target);
}
- if (!UpdateVictim())
- return;
+ _isBanished = false;
+ }
+ else if (_isBanished)
+ {
+ _emergeTimer -= diff;
+ return;
+ }
- events.Update(diff);
+ if (!UpdateVictim())
+ {
+ return;
+ }
- while (uint32 eventId = events.ExecuteEvent())
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
+ }
+ while (uint32 const eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_ERUPTION:
{
- case EVENT_ERUPTION:
- DoCastVictim(SPELL_ERRUPTION);
- events.ScheduleEvent(EVENT_ERUPTION, urand(20000, 45000));
- break;
- case EVENT_WRATH_OF_RAGNAROS:
- DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
- if (urand(0, 1))
- Talk(SAY_WRATH);
- events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 25000);
- break;
- case EVENT_HAND_OF_RAGNAROS:
- DoCast(me, SPELL_HAND_OF_RAGNAROS);
- if (urand(0, 1))
- Talk(SAY_HAND);
- events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 20000);
- break;
- case EVENT_LAVA_BURST:
- DoCastVictim(SPELL_LAVA_BURST);
- events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
- break;
- case EVENT_ELEMENTAL_FIRE:
- DoCastVictim(SPELL_ELEMENTAL_FIRE);
- events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000));
- break;
- case EVENT_MAGMA_BLAST:
- if (!me->IsWithinMeleeRange(me->GetVictim()))
+ DoCastVictim(SPELL_ERRUPTION);
+ events.RepeatEvent(urand(20000, 45000));
+ break;
+ }
+ case EVENT_WRATH_OF_RAGNAROS:
+ {
+ DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
+ if (urand(0, 1))
+ {
+ Talk(SAY_WRATH);
+ }
+ events.RepeatEvent(25000);
+ break;
+ }
+ case EVENT_HAND_OF_RAGNAROS:
+ {
+ DoCastSelf(SPELL_HAND_OF_RAGNAROS);
+ if (urand(0, 1))
+ {
+ Talk(SAY_HAND);
+ }
+ events.RepeatEvent(20000);
+ break;
+ }
+ case EVENT_LAVA_BURST:
+ {
+ DoCastVictim(SPELL_LAVA_BURST);
+ events.RepeatEvent(10000);
+ break;
+ }
+ case EVENT_MAGMA_BLAST:
+ {
+ Unit* victim = me->GetVictim();
+ if (victim && !me->IsWithinMeleeRange(victim))
+ {
+ DoCast(victim, SPELL_MAGMA_BLAST);
+ if (!_hasYelledMagmaBurst)
{
- DoCastVictim(SPELL_MAGMA_BLAST);
- if (!_hasYelledMagmaBurst)
- {
- Talk(SAY_MAGMABURST);
- _hasYelledMagmaBurst = true;
- }
+ Talk(SAY_MAGMABURST);
+ _hasYelledMagmaBurst = true;
}
- events.ScheduleEvent(EVENT_MAGMA_BLAST, 2500);
- break;
- case EVENT_SUBMERGE:
- {
- if (!_isBanished)
- {
- // TODO: There is a spell to summon him
- me->AttackStop();
- DoResetThreat();
- me->SetReactState(REACT_PASSIVE);
- me->InterruptNonMeleeSpells(false);
- me->SetFaction(FACTION_FRIENDLY);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
- me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
- instance->SetData(DATA_RAGNAROS_ADDS, 0);
-
- if (!_hasSubmergedOnce)
- {
- Talk(SAY_REINFORCEMENTS1);
-
- // summon 8 elementals
- for (uint8 i = 0; i < 8; ++i)
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
- summoned->AI()->AttackStart(target);
-
- _hasSubmergedOnce = true;
- _isBanished = true;
- _emergeTimer = 90000;
- }
- else
- {
- Talk(SAY_REINFORCEMENTS2);
-
- for (uint8 i = 0; i < 8; ++i)
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
- summoned->AI()->AttackStart(target);
-
- _isBanished = true;
- _emergeTimer = 90000;
- }
- }
- events.ScheduleEvent(EVENT_SUBMERGE, 180000);
- break;
- }
- default:
- break;
+ }
+ events.RepeatEvent(2500);
+ break;
+ }
+ case EVENT_SUBMERGE:
+ {
+ if (!_isBanished)
+ {
+ me->InterruptNonMeleeSpells(false);
+ me->AttackStop();
+ DoResetThreat();
+ me->SetReactState(REACT_PASSIVE);
+ me->SetFaction(35);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
+ DoCastSelf(SPELL_RAGNA_SUBMERGE_VISUAL, true);
+ //me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
+ SummonMinions();
+ }
+ events.ScheduleEvent(EVENT_SUBMERGE, 180000);
+ break;
}
}
- DoMeleeAttackIfReady();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
+ }
}
+
+ DoMeleeAttackIfReady();
}
private:
- float const DEATH_ORIENTATION = 4.0f;
+ uint32 attackableTImer; // used after intro
uint32 _emergeTimer;
- uint8 _introState;
bool _hasYelledMagmaBurst;
bool _hasSubmergedOnce;
bool _isBanished;
+
+ void SummonMinions()
+ {
+ Talk(_hasSubmergedOnce ? SAY_REINFORCEMENTS2 : SAY_REINFORCEMENTS1);
+
+ for (uint8 i = 0; i < MAX_SON_OF_FLAME_COUNT; ++i)
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ {
+ if (Creature* summoned = me->SummonCreature(NPC_SON_OF_FLAME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
+ {
+ summoned->AI()->AttackStart(target);
+ }
+ }
+ }
+
+ _isBanished = true;
+ _emergeTimer = 90000;
+ if (!_hasSubmergedOnce)
+ {
+ _hasSubmergedOnce = true;
+ }
+ }
};
CreatureAI* GetAI(Creature* creature) const override
@@ -306,40 +321,7 @@ public:
}
};
-class npc_son_of_flame : public CreatureScript
-{
-public:
- npc_son_of_flame() : CreatureScript("npc_SonOfFlame") { }
-
- struct npc_son_of_flameAI : public ScriptedAI
- {
- npc_son_of_flameAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = me->GetInstanceScript();
- }
-
- void JustDied(Unit* /*killer*/) override { instance->SetData(DATA_RAGNAROS_ADDS, 1); }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
-
- private:
- InstanceScript* instance;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetMoltenCoreAI(creature);
- }
-};
-
void AddSC_boss_ragnaros()
{
new boss_ragnaros();
- new npc_son_of_flame();
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp
index fc5c04eb0..952846c74 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp
@@ -15,29 +15,29 @@
* with this program. If not, see .
*/
-#include "molten_core.h"
-#include "ScriptedCreature.h"
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
#include "SpellScript.h"
+#include "molten_core.h"
+#include "Player.h"
enum Spells
{
- SPELL_ARCANE_EXPLOSION = 19712,
- SPELL_SHAZZRAH_CURSE = 19713,
- SPELL_MAGIC_GROUNDING = 19714,
- SPELL_COUNTERSPELL = 19715,
- SPELL_SHAZZRAH_GATE_DUMMY = 23138, // Teleports to and attacks a random target.
- SPELL_SHAZZRAH_GATE = 23139,
+ SPELL_ARCANE_EXPLOSION = 19712,
+ SPELL_SHAZZRAH_CURSE = 19713,
+ SPELL_MAGIC_GROUNDING = 19714,
+ SPELL_COUNTERSPELL = 19715,
+ SPELL_SHAZZRAH_GATE_DUMMY = 23138, // Teleports to and attacks a random target. About every 45 seconds Shazzrah will blink to random target causing a wipe of the threat list (source: wowwwiki)
+ SPELL_SHAZZRAH_GATE = 23139,
};
enum Events
{
EVENT_ARCANE_EXPLOSION = 1,
- EVENT_ARCANE_EXPLOSION_TRIGGERED = 2,
- EVENT_SHAZZRAH_CURSE = 3,
- EVENT_MAGIC_GROUNDING = 4,
- EVENT_COUNTERSPELL = 5,
- EVENT_SHAZZRAH_GATE = 6,
+ EVENT_SHAZZRAH_CURSE,
+ EVENT_MAGIC_GROUNDING,
+ EVENT_COUNTERSPELL,
+ EVENT_SHAZZRAH_GATE,
};
class boss_shazzrah : public CreatureScript
@@ -47,66 +47,57 @@ public:
struct boss_shazzrahAI : public BossAI
{
- boss_shazzrahAI(Creature* creature) : BossAI(creature, BOSS_SHAZZRAH) { }
+ boss_shazzrahAI(Creature* creature) : BossAI(creature, DATA_SHAZZRAH) {}
- void EnterCombat(Unit* target) override
+ void EnterCombat(Unit* /*target*/) override
{
- BossAI::EnterCombat(target);
- events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 6000);
- events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, 10000);
- events.ScheduleEvent(EVENT_MAGIC_GROUNDING, 24000);
- events.ScheduleEvent(EVENT_COUNTERSPELL, 15000);
- events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 45000);
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(2000, 4000));
+ events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, urand(7000, 11000));
+ events.ScheduleEvent(EVENT_MAGIC_GROUNDING, urand(14000, 19000));
+ events.ScheduleEvent(EVENT_COUNTERSPELL, urand(9000, 10000));
+ events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 30000);
}
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
{
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_ARCANE_EXPLOSION:
{
- case EVENT_ARCANE_EXPLOSION:
- DoCastVictim(SPELL_ARCANE_EXPLOSION);
- events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(4000, 7000));
- break;
- // Triggered subsequent to using "Gate of Shazzrah".
- case EVENT_ARCANE_EXPLOSION_TRIGGERED:
- DoCastVictim(SPELL_ARCANE_EXPLOSION);
- break;
- case EVENT_SHAZZRAH_CURSE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHAZZRAH_CURSE))
- DoCast(target, SPELL_SHAZZRAH_CURSE);
- events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, urand(25000, 30000));
- break;
- case EVENT_MAGIC_GROUNDING:
- DoCast(me, SPELL_MAGIC_GROUNDING);
- events.ScheduleEvent(EVENT_MAGIC_GROUNDING, 35000);
- break;
- case EVENT_COUNTERSPELL:
- DoCastVictim(SPELL_COUNTERSPELL);
- events.ScheduleEvent(EVENT_COUNTERSPELL, urand(16000, 20000));
- break;
- case EVENT_SHAZZRAH_GATE:
- DoResetThreat();
- DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
- events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_TRIGGERED, 2000);
- events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, urand(3000, 6000));
- events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 45000);
- break;
- default:
- break;
+ DoCastVictim(SPELL_ARCANE_EXPLOSION);
+ events.RepeatEvent(urand(4000, 5000));
+ break;
+ }
+ case EVENT_SHAZZRAH_CURSE:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHAZZRAH_CURSE))
+ {
+ DoCast(target, SPELL_SHAZZRAH_CURSE);
+ }
+ events.RepeatEvent(urand(23000, 26000));
+ break;
+ }
+ case EVENT_MAGIC_GROUNDING:
+ {
+ DoCastSelf(SPELL_MAGIC_GROUNDING);
+ events.RepeatEvent(urand(7000, 9000));
+ break;
+ }
+ case EVENT_COUNTERSPELL:
+ {
+ DoCastAOE(SPELL_COUNTERSPELL);
+ events.RepeatEvent(urand(15000, 18000));
+ break;
+ }
+ case EVENT_SHAZZRAH_GATE:
+ {
+ DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
+ events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, urand(3000, 6000));
+ events.RepeatEvent(45000);
+ break;
}
}
-
- DoMeleeAttackIfReady();
}
};
@@ -120,7 +111,7 @@ public:
class spell_shazzrah_gate_dummy : public SpellScriptLoader
{
public:
- spell_shazzrah_gate_dummy() : SpellScriptLoader("spell_shazzrah_gate_dummy") { }
+ spell_shazzrah_gate_dummy() : SpellScriptLoader("spell_shazzrah_gate_dummy") {}
class spell_shazzrah_gate_dummy_SpellScript : public SpellScript
{
@@ -133,21 +124,55 @@ public:
void FilterTargets(std::list& targets)
{
- if (targets.empty())
- return;
+ Unit* caster = GetCaster();
+ if (!targets.empty())
+ {
+ targets.remove_if([caster](WorldObject const* target) -> bool
+ {
+ Player const* plrTarget = target->ToPlayer();
+ // Should not target non player targets
+ if (!plrTarget)
+ {
+ return true;
+ }
- WorldObject* target = Acore::Containers::SelectRandomContainerElement(targets);
- targets.clear();
- targets.push_back(target);
+ // Should skip current victim
+ if (caster->GetVictim() == plrTarget)
+ {
+ return true;
+ }
+
+ // Should not target enemies within melee range
+ if (plrTarget->IsWithinDistInMap(caster, caster->GetMeleeRange(plrTarget)))
+ {
+ return true;
+ }
+
+ return false;
+ });
+ }
+
+ if (!targets.empty())
+ {
+ Acore::Containers::RandomResize(targets, 1);
+ }
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
- if (Unit* target = GetHitUnit())
+ Unit* caster = GetCaster();
+ Unit* target = GetHitUnit();
+
+ if (!caster || !target)
{
- target->CastSpell(GetCaster(), SPELL_SHAZZRAH_GATE, true);
- if (Creature* creature = GetCaster()->ToCreature())
- creature->AI()->AttackStart(target); // Attack the target which caster will teleport to.
+ target->CastSpell(caster, SPELL_SHAZZRAH_GATE, true, nullptr, nullptr, caster->GetGUID());
+ caster->CastSpell(caster, SPELL_ARCANE_EXPLOSION);
+
+ if (Creature* creatureCaster = caster->ToCreature())
+ {
+ creatureCaster->getThreatMgr().resetAllAggro();
+ creatureCaster->AI()->AttackStart(target); // Attack the target which caster will teleport to.
+ }
}
}
@@ -167,5 +192,7 @@ public:
void AddSC_boss_shazzrah()
{
new boss_shazzrah();
+
+ // Spells
new spell_shazzrah_gate_dummy();
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp
index 0b0810ac8..7be891b77 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp
@@ -15,17 +15,9 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Boss_Sulfuron_Harbringer
-SD%Complete: 80
-SDComment: Adds NYI
-SDCategory: Molten Core
-EndScriptData */
-
-#include "molten_core.h"
-#include "ObjectMgr.h"
-#include "ScriptedCreature.h"
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "molten_core.h"
enum Spells
{
@@ -45,84 +37,79 @@ enum Spells
enum Events
{
EVENT_DARK_STRIKE = 1,
- EVENT_DEMORALIZING_SHOUT = 2,
- EVENT_INSPIRE = 3,
- EVENT_KNOCKDOWN = 4,
- EVENT_FLAMESPEAR = 5,
+ EVENT_DEMORALIZING_SHOUT,
+ EVENT_INSPIRE,
+ EVENT_KNOCKDOWN,
+ EVENT_FLAMESPEAR,
- EVENT_HEAL = 6,
- EVENT_SHADOW_WORD_PAIN = 7,
- EVENT_IMMOLATE = 8,
+ EVENT_HEAL,
+ EVENT_SHADOW_WORD_PAIN,
+ EVENT_IMMOLATE,
};
class boss_sulfuron : public CreatureScript
{
public:
- boss_sulfuron() : CreatureScript("boss_sulfuron") { }
+ boss_sulfuron() : CreatureScript("boss_sulfuron") {}
struct boss_sulfuronAI : public BossAI
{
- boss_sulfuronAI(Creature* creature) : BossAI(creature, BOSS_SULFURON_HARBINGER)
- {
- }
+ boss_sulfuronAI(Creature* creature) : BossAI(creature, DATA_SULFURON) {}
- void EnterCombat(Unit* victim) override
+ void EnterCombat(Unit* /*victim*/) override
{
- BossAI::EnterCombat(victim);
- events.ScheduleEvent(EVENT_DARK_STRIKE, 10000);
- events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 15000);
- events.ScheduleEvent(EVENT_INSPIRE, 13000);
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_DARK_STRIKE, urand(4000, 7000));
+ events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, urand(6000, 20000));
+ events.ScheduleEvent(EVENT_INSPIRE, urand(7000, 10000));
events.ScheduleEvent(EVENT_KNOCKDOWN, 6000);
events.ScheduleEvent(EVENT_FLAMESPEAR, 2000);
}
- void UpdateAI(uint32 diff) override
+ void ExecuteEvent(uint32 eventId) override
{
- if (!UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
+ switch (eventId)
{
- switch (eventId)
+ case EVENT_DARK_STRIKE:
{
- case EVENT_DARK_STRIKE:
- DoCast(me, SPELL_DARK_STRIKE);
- events.ScheduleEvent(EVENT_DARK_STRIKE, urand(15000, 18000));
- break;
- case EVENT_DEMORALIZING_SHOUT:
- DoCastVictim(SPELL_DEMORALIZING_SHOUT);
- events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, urand(15000, 20000));
- break;
- case EVENT_INSPIRE:
- {
- std::list healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
- if (!healers.empty())
- DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
+ DoCastSelf(SPELL_DARK_STRIKE);
+ events.RepeatEvent(urand(4000, 7000));
+ break;
+ }
+ case EVENT_DEMORALIZING_SHOUT:
+ {
+ DoCastVictim(SPELL_DEMORALIZING_SHOUT);
+ events.RepeatEvent(urand(12000, 18000));
+ break;
+ }
+ case EVENT_INSPIRE:
+ {
+ std::list healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
+ if (!healers.empty())
+ {
+ DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
+ }
- DoCast(me, SPELL_INSPIRE);
- events.ScheduleEvent(EVENT_INSPIRE, urand(20000, 26000));
- break;
- }
- case EVENT_KNOCKDOWN:
- DoCastVictim(SPELL_KNOCKDOWN);
- events.ScheduleEvent(EVENT_KNOCKDOWN, urand(12000, 15000));
- break;
- case EVENT_FLAMESPEAR:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
- DoCast(target, SPELL_FLAMESPEAR);
- events.ScheduleEvent(EVENT_FLAMESPEAR, urand(12000, 16000));
- break;
- default:
- break;
+ DoCastSelf(SPELL_INSPIRE);
+ events.RepeatEvent(urand(13000, 20000));
+ break;
+ }
+ case EVENT_KNOCKDOWN:
+ {
+ DoCastVictim(SPELL_KNOCKDOWN);
+ events.RepeatEvent(urand(10000, 20000));
+ break;
+ }
+ case EVENT_FLAMESPEAR:
+ {
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ {
+ DoCast(target, SPELL_FLAMESPEAR);
+ }
+ events.RepeatEvent(urand(12000, 16000));
+ break;
}
}
-
- DoMeleeAttackIfReady();
}
};
@@ -135,13 +122,11 @@ public:
class npc_flamewaker_priest : public CreatureScript
{
public:
- npc_flamewaker_priest() : CreatureScript("npc_flamewaker_priest") { }
+ npc_flamewaker_priest() : CreatureScript("npc_flamewaker_priest") {}
struct npc_flamewaker_priestAI : public ScriptedAI
{
- npc_flamewaker_priestAI(Creature* creature) : ScriptedAI(creature)
- {
- }
+ npc_flamewaker_priestAI(Creature* creature) : ScriptedAI(creature) {}
void Reset() override
{
@@ -153,45 +138,63 @@ public:
events.Reset();
}
- void EnterCombat(Unit* victim) override
+ void EnterCombat(Unit* /*victim*/) override
{
- ScriptedAI::EnterCombat(victim);
events.ScheduleEvent(EVENT_HEAL, urand(15000, 30000));
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2000);
- events.ScheduleEvent(EVENT_IMMOLATE, 8000);
+ events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(2000, 4000));
+ events.ScheduleEvent(EVENT_IMMOLATE, urand(3500, 6000));
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
+ {
return;
+ }
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
return;
+ }
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 const eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_HEAL:
+ {
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 1))
+ {
DoCast(target, SPELL_HEAL);
- events.ScheduleEvent(EVENT_HEAL, urand(15000, 20000));
+ }
+ events.RepeatEvent(urand(15000, 20000));
break;
+ }
case EVENT_SHADOW_WORD_PAIN:
+ {
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHADOWWORDPAIN))
+ {
DoCast(target, SPELL_SHADOWWORDPAIN);
- events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(18000, 26000));
+ }
+ events.RepeatEvent(urand(2500, 5000));
break;
+ }
case EVENT_IMMOLATE:
+ {
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IMMOLATE))
+ {
DoCast(target, SPELL_IMMOLATE);
- events.ScheduleEvent(EVENT_IMMOLATE, urand(15000, 25000));
- break;
- default:
+ }
+ events.RepeatEvent(urand(5000, 7000));
break;
+ }
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
}
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp
index a55c949fa..985447286 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp
@@ -15,51 +15,64 @@
* with this program. If not, see .
*/
-/* ScriptData
-SDName: Instance_Molten_Core
-SD%Complete: 0
-SDComment: Place Holder
-SDCategory: Molten Core
-EndScriptData */
-
+#include "ScriptMgr.h"
#include "InstanceScript.h"
-#include "molten_core.h"
#include "ObjectMgr.h"
#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "InstanceScript.h"
#include "TemporarySummon.h"
+#include "molten_core.h"
-Position const SummonPositions[10] =
+MinionData const minionData[] =
{
- {759.542f, -1173.43f, -118.974f, 3.3048f},
- {761.652f, -1164.30f, -119.533f, 3.3919f},
- {747.323f, -1149.24f, -120.060f, 3.6629f},
- {766.734f, -1183.16f, -119.292f, 2.9889f},
- {757.364f, -1198.31f, -118.652f, 2.3095f},
- {752.349f, -1159.19f, -119.261f, 3.6032f},
- {738.015f, -1152.22f, -119.512f, 4.0792f},
- {757.246f, -1189.79f, -118.633f, 2.5333f},
- {745.916f, -1199.35f, -118.119f, 1.8932f},
- {838.510f, -829.840f, -232.000f, 2.00000f},
+ { NPC_FIRESWORN, DATA_GARR },
+ { NPC_FLAMEWALKER, DATA_GEHENNAS },
+ { NPC_FLAMEWALKER_PROTECTOR, DATA_LUCIFRON },
+ { NPC_FLAMEWALKER_PRIEST, DATA_SULFURON },
+ { NPC_FLAMEWALKER_HEALER, DATA_MAJORDOMO_EXECUTUS },
+ { NPC_FLAMEWALKER_ELITE, DATA_MAJORDOMO_EXECUTUS },
+ { 0, 0 } // END
+};
+
+struct MCBossObject
+{
+ uint32 bossId;
+ uint32 runeId;
+ uint32 circleId;
+};
+
+constexpr uint8 MAX_MC_LINKED_BOSS_OBJ = 7;
+MCBossObject const linkedBossObjData[MAX_MC_LINKED_BOSS_OBJ]=
+{
+ { DATA_MAGMADAR, GO_RUNE_KRESS, GO_CIRCLE_MAGMADAR },
+ { DATA_GEHENNAS, GO_RUNE_MOHN, GO_CIRCLE_GEHENNAS },
+ { DATA_GARR, GO_RUNE_BLAZ, GO_CIRCLE_GARR },
+ { DATA_SHAZZRAH, GO_RUNE_MAZJ, GO_CIRCLE_SHAZZRAH },
+ { DATA_GEDDON, GO_RUNE_ZETH, GO_CIRCLE_GEDDON },
+ { DATA_GOLEMAGG, GO_RUNE_THERI, GO_CIRCLE_GOLEMAGG },
+ { DATA_SULFURON, GO_RUNE_KORO, GO_CIRCLE_SULFURON },
};
class instance_molten_core : public InstanceMapScript
{
public:
- instance_molten_core() : InstanceMapScript("instance_molten_core", 409) { }
+ instance_molten_core() : InstanceMapScript(MCScriptName, 409) {}
struct instance_molten_core_InstanceMapScript : public InstanceScript
{
instance_molten_core_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetBossNumber(MAX_ENCOUNTER);
- _deadBossCount = 0;
- _ragnarosAddDeaths = 0;
+ LoadMinionData(minionData);
}
void OnPlayerEnter(Player* /*player*/) override
{
if (CheckMajordomoExecutus())
+ {
SummonMajordomoExecutus();
+ }
}
void OnCreatureCreate(Creature* creature) override
@@ -67,13 +80,61 @@ public:
switch (creature->GetEntry())
{
case NPC_GOLEMAGG_THE_INCINERATOR:
- _golemaggTheIncineratorGUID = creature->GetGUID();
+ {
+ _golemaggGUID = creature->GetGUID();
break;
+ }
+ case NPC_CORE_RAGER:
+ {
+ _golemaggMinionsGUIDS.insert(creature->GetGUID());
+ break;
+ }
case NPC_MAJORDOMO_EXECUTUS:
+ {
_majordomoExecutusGUID = creature->GetGUID();
break;
- default:
+ }
+ case NPC_GARR:
+ {
+ _garrGUID = creature->GetGUID();
break;
+ }
+ case NPC_RAGNAROS:
+ {
+ _ragnarosGUID = creature->GetGUID();
+ break;
+ }
+ case NPC_FIRESWORN:
+ case NPC_FLAMEWALKER:
+ case NPC_FLAMEWALKER_PROTECTOR:
+ case NPC_FLAMEWALKER_PRIEST:
+ case NPC_FLAMEWALKER_HEALER:
+ case NPC_FLAMEWALKER_ELITE:
+ {
+ AddMinion(creature, true);
+ break;
+ }
+ }
+ }
+
+ void OnCreatureRemove(Creature* creature) override
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_FIRESWORN:
+ {
+ AddMinion(creature, false);
+ break;
+ }
+ case NPC_FLAMEWALKER:
+ case NPC_FLAMEWALKER_PROTECTOR:
+ case NPC_FLAMEWALKER_PRIEST:
+ case NPC_FLAMEWALKER_HEALER:
+ case NPC_FLAMEWALKER_ELITE:
+ {
+ AddMinion(creature, false);
+ break;
+ }
}
}
@@ -82,64 +143,92 @@ public:
switch (go->GetEntry())
{
case GO_CACHE_OF_THE_FIRELORD:
+ {
_cacheOfTheFirelordGUID = go->GetGUID();
break;
- case GO_CIRCLE_BARON:
- _circlesGUIDs[5] = go->GetGUID();
- break;
+ }
+ case GO_CIRCLE_GEDDON:
case GO_CIRCLE_GARR:
- _circlesGUIDs[3] = go->GetGUID();
- break;
case GO_CIRCLE_GEHENNAS:
- _circlesGUIDs[2] = go->GetGUID();
- break;
case GO_CIRCLE_GOLEMAGG:
- _circlesGUIDs[7] = go->GetGUID();
- break;
case GO_CIRCLE_MAGMADAR:
- _circlesGUIDs[1] = go->GetGUID();
- break;
case GO_CIRCLE_SHAZZRAH:
- _circlesGUIDs[4] = go->GetGUID();
- break;
case GO_CIRCLE_SULFURON:
- _circlesGUIDs[6] = go->GetGUID();
+ {
+ for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
+ {
+ if (linkedBossObjData[i].circleId != go->GetEntry())
+ {
+ continue;
+ }
+
+ if (GetBossState(linkedBossObjData[i].bossId) == DONE)
+ {
+ go->DespawnOrUnsummon();
+ }
+ else
+ {
+ _circlesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
+ }
+ }
+
break;
- default:
+ }
+ case GO_RUNE_KRESS:
+ case GO_RUNE_MOHN:
+ case GO_RUNE_BLAZ:
+ case GO_RUNE_MAZJ:
+ case GO_RUNE_ZETH:
+ case GO_RUNE_THERI:
+ case GO_RUNE_KORO:
+ {
+ for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
+ {
+ if (linkedBossObjData[i].runeId != go->GetEntry())
+ {
+ continue;
+ }
+
+ if (GetBossState(linkedBossObjData[i].bossId) == DONE)
+ {
+ go->SetGoState(GO_STATE_ACTIVE);
+ }
+ else
+ {
+ _runesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
+ }
+ }
break;
+ }
+ case GO_LAVA_STEAM:
+ {
+ _lavaSteamGUID = go->GetGUID();
+ break;
+ }
+ case GO_LAVA_SPLASH:
+ {
+ _lavaSplashGUID = go->GetGUID();
+ break;
+ }
}
}
- void SetData(uint32 type, uint32 data) override
- {
- if (type == DATA_RAGNAROS_ADDS)
- {
- if (data == 1)
- ++_ragnarosAddDeaths;
- else if (data == 0)
- _ragnarosAddDeaths = 0;
- }
- }
-
- uint32 GetData(uint32 type) const override
+ ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
- case DATA_RAGNAROS_ADDS:
- return _ragnarosAddDeaths;
- }
-
- return 0;
- }
-
- ObjectGuid GetGuidData(uint32 type) const override
- {
- switch (type)
- {
- case BOSS_GOLEMAGG_THE_INCINERATOR:
- return _golemaggTheIncineratorGUID;
- case BOSS_MAJORDOMO_EXECUTUS:
+ case DATA_GOLEMAGG:
+ return _golemaggGUID;
+ case DATA_MAJORDOMO_EXECUTUS:
return _majordomoExecutusGUID;
+ case DATA_GARR:
+ return _garrGUID;
+ case DATA_LAVA_STEAM:
+ return _lavaSteamGUID;
+ case DATA_LAVA_SPLASH:
+ return _lavaSplashGUID;
+ case DATA_RAGNAROS:
+ return _ragnarosGUID;
}
return ObjectGuid::Empty;
@@ -148,54 +237,153 @@ public:
bool SetBossState(uint32 bossId, EncounterState state) override
{
if (!InstanceScript::SetBossState(bossId, state))
+ {
return false;
+ }
- if (state == DONE && bossId < BOSS_MAJORDOMO_EXECUTUS)
- if (CheckMajordomoExecutus())
- SummonMajordomoExecutus();
-
- if (bossId == BOSS_MAJORDOMO_EXECUTUS && state == DONE)
+ if (bossId == DATA_MAJORDOMO_EXECUTUS && state == DONE)
{
DoRespawnGameObject(_cacheOfTheFirelordGUID, 7 * DAY);
}
+ else if (bossId == DATA_GOLEMAGG)
+ {
+ switch (state)
+ {
+ case NOT_STARTED:
+ case FAIL:
+ {
+ if (!_golemaggMinionsGUIDS.empty())
+ {
+ for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
+ {
+ Creature* minion = instance->GetCreature(minionGuid);
+ if (minion && minion->isDead())
+ {
+ minion->Respawn();
+ }
+ }
+ }
+ break;
+ }
+ case IN_PROGRESS:
+ {
+ if (!_golemaggMinionsGUIDS.empty())
+ {
+ for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
+ {
+ if (Creature* minion = instance->GetCreature(minionGuid))
+ {
+ minion->AI()->DoZoneInCombat(nullptr, 150.0f);
+ }
+ }
+ }
+ break;
+ }
+ case DONE:
+ {
+ if (!_golemaggMinionsGUIDS.empty())
+ {
+ for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
+ {
+ if (Creature* minion = instance->GetCreature(minionGuid))
+ {
+ minion->CastSpell(minion, SPELL_CORE_RAGER_QUIET_SUICIDE, true);
+ }
+ }
+ _golemaggMinionsGUIDS.clear();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ // Perform needed checks for Majordomu
+ if (bossId < DATA_MAJORDOMO_EXECUTUS && state == DONE)
+ {
+ if (GameObject* circle = instance->GetGameObject(_circlesGUIDs[bossId]))
+ {
+ circle->DespawnOrUnsummon();
+ _circlesGUIDs[bossId].Clear();
+ }
+
+ if (GameObject* rune = instance->GetGameObject(_runesGUIDs[bossId]))
+ {
+ rune->SetGoState(GO_STATE_ACTIVE);
+ _runesGUIDs[bossId].Clear();
+ }
+
+ if (CheckMajordomoExecutus())
+ {
+ SummonMajordomoExecutus();
+ }
+ }
return true;
}
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_RESET_MAGMADAR_ENCOUNTER)
+ {
+ if (Creature* golemagg = instance->GetCreature(_golemaggGUID))
+ {
+ golemagg->AI()->EnterEvadeMode();
+ }
+
+ if (!_golemaggMinionsGUIDS.empty())
+ {
+ for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
+ {
+ if (Creature* minion = instance->GetCreature(minionGuid))
+ {
+ minion->AI()->EnterEvadeMode();
+ }
+ }
+ }
+ }
+ }
+
void SummonMajordomoExecutus()
{
- if (_majordomoExecutusGUID)
- return;
-
- if (GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE)
+ if (instance->GetCreature(_majordomoExecutusGUID))
{
- instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, SummonPositions[0]);
- instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[1]);
- instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[2]);
- instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[3]);
- instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[4]);
- instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[5]);
- instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[6]);
- instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[7]);
- instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[8]);
+ return;
}
- else if (TempSummon* summon = instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, RagnarosTelePos))
- summon->AI()->DoAction(ACTION_START_RAGNAROS_ALT);
+
+ instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE ? MajordomoSummonPos : MajordomoRagnaros);
}
bool CheckMajordomoExecutus() const
{
- if (GetBossState(BOSS_RAGNAROS) == DONE)
+ if (GetBossState(DATA_RAGNAROS) == DONE)
+ {
return false;
+ }
+
+ for (uint8 i = 0; i < DATA_MAJORDOMO_EXECUTUS; ++i)
+ {
+ if (i == DATA_LUCIFRON)
+ {
+ continue;
+ }
- for (uint8 i = 0; i < BOSS_MAJORDOMO_EXECUTUS; ++i)
if (GetBossState(i) != DONE)
+ {
return false;
+ }
+ }
+
+ // Prevent spawning if Ragnaros is present
+ if (instance->GetCreature(_ragnarosGUID))
+ {
+ return false;
+ }
return true;
}
- std::string GetSaveData() override
+ std::string GetSaveData() override
{
OUT_SAVE_INST_DATA;
@@ -206,7 +394,7 @@ public:
return saveStream.str();
}
- void Load(char const* data) override
+ void Load(char const* data) override
{
if (!data)
{
@@ -228,27 +416,43 @@ public:
uint32 tmpState;
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState > TO_BE_DECIDED)
+ {
tmpState = NOT_STARTED;
+ }
- SetBossState(i, EncounterState(tmpState));
+ SetBossState(i, static_cast(tmpState));
}
if (CheckMajordomoExecutus())
+ {
SummonMajordomoExecutus();
+ }
}
else
+ {
OUT_LOAD_INST_DATA_FAIL;
+ }
OUT_LOAD_INST_DATA_COMPLETE;
}
private:
- ObjectGuid _golemaggTheIncineratorGUID;
+ std::unordered_map _circlesGUIDs;
+ std::unordered_map _runesGUIDs;
+
+ // Golemagg encounter related
+ ObjectGuid _golemaggGUID;
+ GuidSet _golemaggMinionsGUIDS;
+
+ // Ragnaros encounter related
+ ObjectGuid _ragnarosGUID;
+ ObjectGuid _lavaSteamGUID;
+ ObjectGuid _lavaSplashGUID;
+
ObjectGuid _majordomoExecutusGUID;
ObjectGuid _cacheOfTheFirelordGUID;
- uint8 _deadBossCount;
- uint8 _ragnarosAddDeaths;
- std::unordered_map _circlesGUIDs;
+ ObjectGuid _garrGUID;
+ ObjectGuid _magmadarGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.cpp
new file mode 100644
index 000000000..d0b3d7f5c
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.cpp
@@ -0,0 +1,216 @@
+/*
+ * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "molten_core.h"
+
+enum Texts
+{
+ EMOTE_SMOLDERING = 0,
+ EMOTE_IGNITE = 1,
+};
+
+enum Spells
+{
+ // Ancient Core Hound
+ SPELL_SERRATED_BITE = 19771,
+ SPELL_PLAY_DEAD = 19822,
+ SPELL_FULL_HEALTH = 17683,
+ SPELL_FIRE_NOVA_VISUAL = 19823,
+ SPELL_PLAY_DEAD_PACIFY = 19951, // Server side spell
+};
+
+// Serrated Bites timer may be wrong
+class npc_mc_core_hound : public CreatureScript
+{
+public:
+ npc_mc_core_hound() : CreatureScript("npc_mc_core_hound") {}
+
+ struct npc_mc_core_houndAI : public CreatureAI
+ {
+ npc_mc_core_houndAI(Creature* creature) :
+ CreatureAI(creature),
+ instance(creature->GetInstanceScript()),
+ serratedBiteTimer(3000)
+ {
+ }
+
+ void Reset() override
+ {
+ serratedBiteTimer = 3000;
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
+ {
+ // Prevent receiving any extra damage if Hound is playing dead
+ if (me->HasAura(SPELL_PLAY_DEAD))
+ {
+ damage = 0;
+ return;
+ }
+ else if (me->GetHealth() <= damage)
+ {
+ damage = 0;
+ Talk(EMOTE_SMOLDERING);
+ DoCastSelf(SPELL_PLAY_DEAD);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ {
+ return;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_PLAY_DEAD))
+ {
+ return;
+ }
+
+ if (serratedBiteTimer <= diff)
+ {
+ DoCastVictim(SPELL_SERRATED_BITE);
+ serratedBiteTimer = urand(5000, 6000);
+ }
+ else
+ {
+ serratedBiteTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ uint32 serratedBiteTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetMoltenCoreAI(creature);
+ }
+};
+
+// 19822 Play Dead
+class spell_mc_play_dead : public SpellScriptLoader
+{
+public:
+ spell_mc_play_dead() : SpellScriptLoader("spell_mc_play_dead") { }
+
+ class spell_mc_play_dead_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_mc_play_dead_AuraScript);
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Creature* creatureTarget = GetTarget()->ToCreature();
+ if (!creatureTarget)
+ {
+ return;
+ }
+
+ creatureTarget->CastSpell(creatureTarget, SPELL_PLAY_DEAD_PACIFY, true);
+ creatureTarget->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ creatureTarget->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ //creatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
+ creatureTarget->SetReactState(REACT_PASSIVE);
+ creatureTarget->SetControlled(true, UNIT_STATE_ROOT);
+
+ creatureTarget->AttackStop();
+ }
+
+ void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Creature* creatureTarget = GetTarget()->ToCreature();
+ if (!creatureTarget)
+ {
+ return;
+ }
+
+ creatureTarget->RemoveAurasDueToSpell(SPELL_PLAY_DEAD_PACIFY);
+ creatureTarget->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ creatureTarget->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ //creatureTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
+ creatureTarget->SetControlled(false, UNIT_STATE_ROOT);
+ creatureTarget->SetReactState(REACT_AGGRESSIVE);
+
+ if (!creatureTarget->IsInCombat())
+ {
+ return;
+ }
+
+ bool shouldDie = true;
+ std::list hounds;
+ creatureTarget->GetCreaturesWithEntryInRange(hounds, 80.0f, NPC_CORE_HOUND);
+
+ // Perform lambda based check to find if there is any nearby
+ if (!hounds.empty())
+ {
+ // Alive hound been found within 80 yards -> cancel suicide
+ if (std::find_if(hounds.begin(), hounds.end(), [creatureTarget](Creature const* hound)
+ {
+ return creatureTarget != hound && creatureTarget->IsWithinLOSInMap(hound) && hound->IsAlive() && hound->IsInCombat() && !hound->HasAura(SPELL_PLAY_DEAD);
+ }) != hounds.end())
+ {
+ shouldDie = false;
+ }
+ }
+
+ if (!shouldDie)
+ {
+ if (CreatureAI* targetAI = creatureTarget->AI())
+ {
+ targetAI->DoCastSelf(SPELL_FIRE_NOVA_VISUAL, true);
+ targetAI->DoCastSelf(SPELL_FULL_HEALTH, true);
+ targetAI->Talk(EMOTE_IGNITE);
+ }
+ }
+ else
+ {
+ Unit::Kill(creatureTarget, creatureTarget);
+ }
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_mc_play_dead_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_FEIGN_DEATH, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectApplyFn(spell_mc_play_dead_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_FEIGN_DEATH, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_mc_play_dead_AuraScript();
+ }
+};
+
+void AddSC_molten_core()
+{
+ // Creatures
+ new npc_mc_core_hound();
+
+ // Spells
+ new spell_mc_play_dead();
+}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h
index b3bdbf91a..27ed5bdc7 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h
@@ -15,74 +15,107 @@
* with this program. If not, see .
*/
-#include "Player.h"
-
#ifndef DEF_MOLTEN_CORE_H
#define DEF_MOLTEN_CORE_H
-#include "CreatureAIImpl.h"
-
#define MCScriptName "instance_molten_core"
-enum Encounters
+constexpr uint32 MAX_ENCOUNTER = 10;
+
+enum MCData
{
- BOSS_LUCIFRON = 0,
- BOSS_MAGMADAR = 1,
- BOSS_GEHENNAS = 2,
- BOSS_GARR = 3,
- BOSS_SHAZZRAH = 4,
- BOSS_BARON_GEDDON = 5,
- BOSS_SULFURON_HARBINGER = 6,
- BOSS_GOLEMAGG_THE_INCINERATOR = 7,
- BOSS_MAJORDOMO_EXECUTUS = 8,
- BOSS_RAGNAROS = 9,
- MAX_ENCOUNTER,
+ DATA_LUCIFRON = 0,
+ DATA_MAGMADAR = 1,
+ DATA_GEHENNAS = 2,
+ DATA_GARR = 3,
+ DATA_SHAZZRAH = 4,
+ DATA_GEDDON = 5,
+ DATA_SULFURON = 6,
+ DATA_GOLEMAGG = 7,
+ DATA_MAJORDOMO_EXECUTUS = 8,
+ DATA_RAGNAROS = 9,
+
+ // Other data
+ DATA_LAVA_STEAM = 10,
+ DATA_LAVA_SPLASH = 11,
};
-enum Actions
+enum MCActions
{
- ACTION_START_RAGNAROS = 0,
- ACTION_START_RAGNAROS_ALT = 1,
+ ACTION_START_RAGNAROS_INTRO = -1,
+ ACTION_FINISH_RAGNAROS_INTRO = -2,
+ ACTION_RESET_MAGMADAR_ENCOUNTER = -3, // Used when ragers are pulled far away
+ ACTION_PREPARE_MAJORDOMO_RAGNA = -4,
};
-Position const RagnarosTelePos = {829.159f, -815.773f, -228.972f, 5.30500f};
-Position const RagnarosSummonPos = {838.510f, -829.840f, -232.000f, 2.00000f};
-
-enum Creatures
+enum MCCreatures
{
- NPC_LUCIFRON = 12118,
NPC_MAGMADAR = 11982,
- NPC_GEHENNAS = 12259,
- NPC_GARR = 12057,
NPC_SHAZZRAH = 12264,
NPC_BARON_GEDDON = 12056,
- NPC_SULFURON_HARBINGER = 12098,
- NPC_GOLEMAGG_THE_INCINERATOR = 11988,
- NPC_MAJORDOMO_EXECUTUS = 12018,
NPC_RAGNAROS = 11502,
NPC_FLAMEWAKER_HEALER = 11663,
NPC_FLAMEWAKER_ELITE = 11664,
- NPC_CORE_RAGER = 11672,
NPC_CORE_HOUND = 11671,
+
+ // Garr
+ NPC_GARR = 12057,
+ NPC_FIRESWORN = 12099,
+
+ // Gehennas
+ NPC_GEHENNAS = 12259,
+ NPC_FLAMEWALKER = 11661,
+
+ // Golemagg
+ NPC_GOLEMAGG_THE_INCINERATOR = 11988,
+ NPC_CORE_RAGER = 11672,
+
+ // Lucifron
+ NPC_LUCIFRON = 12118,
+ NPC_FLAMEWALKER_PROTECTOR = 12119,
+
+ // Sulfuron
+ NPC_SULFURON_HARBINGER = 12098,
+ NPC_FLAMEWALKER_PRIEST = 11662,
+
+ // Majordomo
+ NPC_MAJORDOMO_EXECUTUS = 12018,
+ NPC_FLAMEWALKER_HEALER = 11663,
+ NPC_FLAMEWALKER_ELITE = 11664,
};
-enum GameObjects
+enum MCGameObjects
{
GO_CACHE_OF_THE_FIRELORD = 179703,
GO_CIRCLE_SULFURON = 178187,
- GO_CIRCLE_BARON = 178188,
+ GO_CIRCLE_GEDDON = 178188,
GO_CIRCLE_SHAZZRAH = 178189,
GO_CIRCLE_GOLEMAGG = 178190,
GO_CIRCLE_GARR = 178191,
GO_CIRCLE_MAGMADAR = 178192,
GO_CIRCLE_GEHENNAS = 178193,
+
+ GO_RUNE_KRESS = 176956, // Magmadar
+ GO_RUNE_MOHN = 176957, // Gehennas
+ GO_RUNE_BLAZ = 176955, // Garr
+ GO_RUNE_MAZJ = 176953, // Shazzrah
+ GO_RUNE_ZETH = 176952, // Geddon
+ GO_RUNE_THERI = 176954, // Golemagg
+ GO_RUNE_KORO = 176951, // Sulfuron
+
+ // Ragnaros event related
+ GO_LAVA_STEAM = 178107,
+ GO_LAVA_SPLASH = 178108,
};
-enum Data
+enum MCSpells
{
- DATA_RAGNAROS_ADDS = 0,
+ SPELL_CORE_RAGER_QUIET_SUICIDE = 3617, // Server side
};
+extern Position const MajordomoRagnaros; // Teleport location to Ragnaros summons area
+extern Position const MajordomoSummonPos; // Majordomo summon position (battle)
+
template
inline AI* GetMoltenCoreAI(T* obj)
{
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 7fb6188df..6c5ca0781 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -74,7 +74,8 @@ void AddSC_boss_selin_fireheart();
void AddSC_boss_vexallus();
void AddSC_boss_priestess_delrissa();
void AddSC_instance_magisters_terrace();
-void AddSC_boss_lucifron(); //Molten core
+void AddSC_molten_core(); //Molten core
+void AddSC_boss_lucifron();
void AddSC_boss_magmadar();
void AddSC_boss_gehennas();
void AddSC_boss_garr();
@@ -210,7 +211,8 @@ void AddEasternKingdomsScripts()
AddSC_boss_vexallus();
AddSC_boss_priestess_delrissa();
AddSC_instance_magisters_terrace();
- AddSC_boss_lucifron(); //Molten core
+ AddSC_molten_core(); // Molten core
+ AddSC_boss_lucifron();
AddSC_boss_magmadar();
AddSC_boss_gehennas();
AddSC_boss_garr();