fix(Scripts/MoltenCore): rewrite (#8741)

This commit is contained in:
Andrius Peleckas
2021-11-02 11:59:01 +00:00
committed by GitHub
parent 2f25323456
commit 2da923e761
15 changed files with 2441 additions and 1127 deletions

View File

@@ -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');

View File

@@ -15,36 +15,31 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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();
}

View File

@@ -15,83 +15,124 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<npc_fireswornAI>(creature);
return GetMoltenCoreAI<npc_garr_fireswornAI>(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();
}

View File

@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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();
}
};

View File

@@ -15,40 +15,28 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<Creature*> 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

View File

@@ -15,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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();
}
};

View File

@@ -15,102 +15,98 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<Unit*> 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<Creature*> 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<npc_magmadar_core_houndAI>(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();
}

View File

@@ -15,192 +15,561 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<TempSummon*> 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();
}

View File

@@ -15,289 +15,304 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<npc_son_of_flameAI>(creature);
}
};
void AddSC_boss_ragnaros()
{
new boss_ragnaros();
new npc_son_of_flame();
}

View File

@@ -15,29 +15,29 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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<WorldObject*>& 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();
}

View File

@@ -15,17 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<Creature*> 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<Creature*> 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;
}
}

View File

@@ -15,51 +15,64 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<EncounterState>(tmpState));
}
if (CheckMajordomoExecutus())
{
SummonMajordomoExecutus();
}
}
else
{
OUT_LOAD_INST_DATA_FAIL;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
private:
ObjectGuid _golemaggTheIncineratorGUID;
std::unordered_map<uint32/*bossid*/, ObjectGuid/*circleGUID*/> _circlesGUIDs;
std::unordered_map<uint32/*bossid*/, ObjectGuid/*runeGUID*/> _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<uint8, ObjectGuid> _circlesGUIDs;
ObjectGuid _garrGUID;
ObjectGuid _magmadarGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<npc_mc_core_houndAI>(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<Creature*> 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();
}

View File

@@ -15,74 +15,107 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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 <class AI, class T>
inline AI* GetMoltenCoreAI(T* obj)
{

View File

@@ -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();