aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorccrs <ccrs@users.noreply.github.com>2019-06-25 20:56:43 +0200
committerShauren <shauren.trinity@gmail.com>2021-12-13 00:42:16 +0100
commiteda6e5c316cd034a51130f0a45e784ec0947db4c (patch)
tree9c358a7913652161d436790d50f7267b57c906d7
parentd9b344594ce83f14edac3c272d41506086872723 (diff)
Script/CoS: full instance rewrite (#23388)
(cherry picked from commit ca6228067507f19db230d415a1d088e5c0b5b808)
-rw-r--r--sql/updates/world/master/2021_12_12_01_world_2019_06_25_01_world.sql1730
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp103
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp79
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp317
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp45
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp91
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp2398
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h198
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp920
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/npc_arthas.cpp1669
-rw-r--r--src/server/scripts/Kalimdor/kalimdor_script_loader.cpp92
11 files changed, 5962 insertions, 1680 deletions
diff --git a/sql/updates/world/master/2021_12_12_01_world_2019_06_25_01_world.sql b/sql/updates/world/master/2021_12_12_01_world_2019_06_25_01_world.sql
new file mode 100644
index 00000000000..b1966c4489f
--- /dev/null
+++ b/sql/updates/world/master/2021_12_12_01_world_2019_06_25_01_world.sql
@@ -0,0 +1,1730 @@
+-- Caverns of Time: Stratholme rework
+SET @DAY = 86400;
+SET @CGUID = 111214; -- creature GUIDs (4 creature);
+DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+00 AND @CGUID+03;
+
+-- Move additional Chromie spawns to DB
+INSERT INTO `creature` (`guid`,`id`,`map`,`spawnDifficulties`,`phaseId`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`movementtype`) VALUES
+(@CGUID+00, 27915, 595, '1,2', 0, 1813.298, 1283.578, 142.3258, 3.878161, @DAY, 0, 0);
+
+-- Chromie AI
+UPDATE `creature_template` SET `ScriptName`="npc_chromie_start" WHERE `entry`=26527;
+UPDATE `creature_template` SET `ScriptName`="npc_chromie_middle" WHERE `entry`=27915;
+-- Chromie whispers
+DELETE FROM `creature_text` WHERE `creatureid`=27915 AND `groupid`=1;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`emote`,`comment`) VALUES
+(27915, 1, 0, "Come over here time traveller, we need to talk!", 15, 100, 29167, 0, 70, "Chromie - WHISPER_COME_TALK"),
+(27915, 1, 1, "Quick, over here!", 15, 100, 29169, 0, 70, "Chromie - WHISPER_COME_TALK"),
+(27915, 1, 2, "We meet again, time traveller!", 15, 100, 29168, 0, 70, "Chromie - WHISPER_COME_TALK");
+
+-- Corruptor of Time
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry`=60422;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `Comment`) VALUES
+(13, 1, 60422, 31, 0, 3, 32281, "Corruption of Time - Implicitly target Guardian of Time");
+
+-- Starting inn RP fluff
+DELETE FROM `areatrigger_scripts` WHERE `entry`=5291;
+INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES (5291,"at_stratholme_inn_stairs_cot");
+UPDATE `creature` SET `movementtype`=0,`spawndist`=0 WHERE `id`=30571;
+UPDATE `creature_addon` SET `bytes1`=0 WHERE `guid` IN (SELECT guid FROM `creature` WHERE `id`=30571);
+UPDATE `creature_template` SET `ScriptName`="",`AIName`="SmartAI" WHERE `entry`=30571;
+UPDATE `creature_template` SET `ScriptName`="npc_hearthsinger_forresten_cot",`AIName`="" WHERE `entry`=30551;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 30571 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`action_type`,`action_param1`,`action_param2`,`target_type`,`target_param1`,`target_param2`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(30571, 0, 0, 1, 72, 100, 1, 100, 0, 17, 0, 0, 1, 0, 0, 0, 0, 0, 0, "Michael Belfast - On Action 100 - Set Emote State None (No Repeat)"),
+(30571, 0, 1, 2, 61, 100, 1, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Michael Belfast - On Action 100 - Set Run (false) (No Repeat)"),
+(30571, 0, 2, 0, 61, 100, 1, 0, 0, 69, 42, 0, 8, 0, 0, 1554.371, 587.4865, 99.77525, 1.107272, "Michael Belfast - On Action 100 - Move Position (ID 42) (No Repeat)"),
+(30571, 0, 3, 0, 34, 100, 1, 8, 42, 45, 1, 1, 11, 30551, 100, 0, 0, 0, 0, "Michael Belfast - On Movement Inform (ID 42) - Set Data 1-1 on Hearthsinger Forresten (within 100yd) (No Repeat)");
+DELETE FROM `creature_text` WHERE `creatureid` IN (30551,30552,30553,30561,30571,31017);
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`emote`,`comment`) VALUES
+(30571, 0, 0, "What were you doing in my cellar? There's a food scare going on, and the last thing I need is strangers rummaging around in my goods! Shoo!", 12, 100, 31323, 5, "Michael Belfast - SAY_CELLAR"),
+(30571, 0, 1, "Hey! Stop rooting around in my cellar! Clear out!", 12, 100, 31322, 5, "Michael Belfast - SAY_CELLAR"),
+(30551, 0, 0, "This whole situation seems a bit paranoid, don't you think?", 12, 100, 31324, 1, "Hearthsinger Forresten - LINE_FORREST_1"),
+(30553, 0, 0, "Orders are orders. If the Prince says jump...", 12, 100, 31325, 1, "Footman James - LINE_JAMES_1"),
+(30552, 0, 0, "It's a strange order, you can't deny. Suspicious food? Under that definition, you should arrest Belfast!", 12, 100, 31326, 1, "Fras Siabi - LINE_FRAS_1"),
+(30571, 1, 0, "I HEARD THAT! No more ale for you! Not a drop!", 12, 100, 31327, 22, "Michael Belfast - LINE_BELFAST_1"),
+(31017, 0, 0, "Enough, Michael. Business is hurting enough with this scare as it is. We can use every copper.", 12, 100, 32560, 1, "Mal Corricks - LINE_MAL_1"),
+(30561, 0, 0, "The soldiers are doing important work. The safety of the people is more important, Mal, if you're interested in your customers living to spend another day.", 12, 100, 32571, 1, "Gryan Stoutmantle - LINE_GRYAN_1"),
+(31017, 1, 0, "%s grudgingly nods.", 16, 100, 32569, 273, "Mal Corricks - LINE_MAL_2"),
+(31017, 2, 0, "I can't argue with that.", 12, 100, 32570, 1, "Mal Corricks - LINE_MAL_3"),
+(30553, 1, 0, "Don't worry too much. By the time I went off duty, we hadn't found a scrap of befouled grain here.", 12, 100, 32572, 1, "Footman James - LINE_JAMES_2"),
+(30551, 1, 0, "Thank the Light for that.", 12, 100, 32573, 1, "Hearthsinger Forresten - LINE_FORREST_2"),
+(30552, 1, 0, "%s nods.", 16, 100, 32574, 273, "Fras Siabi - LINE_FRAS_2");
+
+-- Fix a random typo in AI name for Grain Crate Helper
+UPDATE `creature_template` SET `ScriptName`="npc_crate_helper_cot" WHERE `entry`=27827;
+
+-- Arcane Disruption: Require active grain crate within 8yd, and implicitly target the helper for that crate
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (13,17) AND `SourceEntry`=49590;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ErrorType`, `Comment`) VALUES
+(13, 1, 49590, 31, 0, 3, 27827, 0, "Arcane Disruption - Implicitly target Grain Crate Helper"),
+(17, 0, 49590, 30, 0, 190094, 8, 11, "Arcane Disruption - Must be within 8yd of Suspicious Grain Crate"),
+(17, 0, 49590, 29, 0, 27827, 8, 11, "Arcane Disruption - Must be within 8yd of Grain Crate Helper");
+
+-- Arcane Disruption should ignore Line of Sight because the helper NPC is spawned inside the crates
+DELETE FROM `disables` WHERE `sourceType`=0 AND `entry`=49590;
+INSERT INTO `disables` (`sourceType`, `entry`, `flags`) VALUES
+(0, 49590, 64);
+
+-- Make Suspicious Grain Crate and Grain Crate Helper never respawn
+UPDATE `creature` SET `spawntimesecs`=@DAY WHERE `id`=27827;
+UPDATE `gameobject` SET `spawntimesecs`=@DAY WHERE `id`=190094;
+
+-- Grain Crate reaction fluff
+UPDATE `creature` SET `movementtype`=0,`spawndist`=0 WHERE `id` IN (27884,27885,27891,27892,27907);
+-- Event #1:
+UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_jena_anderson" WHERE `entry`=27885;
+UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_martha_goslin" WHERE `entry`=27884;
+UPDATE `creature` SET `position_x`=1635.827,`position_y`=723.0861,`position_z`=113.6452,`orientation`=3.089233 WHERE `id`=27884;
+DELETE FROM `creature_text` WHERE `creatureid` IN (27884,27885);
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`emote`,`BroadcastTextId`,`comment`) VALUES
+(27884,0,"Oh hello, Jena. Of course you can borrow some grain. Help yourself.",12,100,1,27232,"LINE_MARTHA1"),
+(27884,1,"Oh, my.",12,100,1,27235,"LINE_MARTHA2"),
+(27885,0,"Let's see, we had chicken last night.",12,100,0,27219,"LINE_JENA1"),
+(27885,1,"I've got plenty of cured bacon, but he had some for breakfast.",12,100,0,27220,"LINE_JENA2"),
+(27885,2,"I need to make something healthy for him, he's still not recovered from that illness from last week.",12,100,0,27221,"LINE_JENA3"),
+(27885,3,"Strawberries! Oh wait, they're not in season.",12,100,0,27222,"LINE_JENA4"),
+(27885,4,"Ah, I'll make him some fresh bread! I need to get some flour from Martha!",12,100,0,27223,"LINE_JENA5"),
+(27885,5,"Martha, I'm out of flour for bread. You wouldn't happen to have any grain from that recent shipment, would you?",12,100,6,27224,"LINE_JENA6"),
+(27885,6,"Thanks, Martha! I owe you one.",12,100,1,27229,"LINE_JENA7"),
+(27885,7,"Oh, dear.",12,100,0,27230,"LINE_JENA8"),
+(27885,8,"Martha, something's wrong with this grain! Some of the Prince's soldiers were looking for this. I'm going to go look for one.",12,100,5,27231,"LINE_JENA9");
+-- Event #2:
+UPDATE `creature` SET `position_x`=1670.256, `position_y`=872.8734, `position_z`=120.0351, `orientation`=0.418879 WHERE `id`=27907;
+UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_bartleby_battson" WHERE `entry`=27907;
+DELETE FROM `creature_text` WHERE `creatureid`=27907;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`id`,`text`,`type`,`probability`,`emote`,`BroadcastTextId`,`comment`) VALUES
+(27907,0,0,"I'm going to lose my on time bonus because of this!",12,10,0,27255,"LINE_BARTLEBY_IDLE 1"),
+(27907,0,1,"I wasn't even supposed to be here today!",12,10,0,27256,"LINE_BARTLEBY_IDLE 2"),
+(27907,1,0,"Well, guess I should load everything back into the cart.",12,100,0,27257,"LINE_BARTLEBY1"),
+(27907,2,0,"Oh, come on! My cart broke, my horse lost a shoe, and now the cargo goes bad!",12,100,5,27258,"LINE_BARTLEBY2"),
+(27907,3,0,"I guess I'll go find the authorities. If I'm lucky they'll tell me it's the plague and that we're all going to die.",12,100,0,27259,"LINE_BARTLEBY3");
+-- Event #3:
+UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_malcolm_moore" WHERE `entry`=27891;
+UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_stratholme_rp_dummy" WHERE `entry`=27892;
+DELETE FROM `creature_text` WHERE `creatureid` IN (27891,27892);
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`emote`,`BroadcastTextId`,`comment`) VALUES
+(27891,0,"Looks like a storm's coming in, Scruffy...",12,100,0,27236,"LINE_MALCOLM1"),
+(27892,0,"%s begins to growl...",16,100,0,27237,"LINE_SCRUFFY1"),
+(27891,1,"What's wrong, pal?",12,100,1,27238,"LINE_MALCOLM2"),
+(27891,2,"What did you find, boy?",12,100,16,27240,"LINE_MALCOLM3"),
+(27891,3,"This is no good, Scruffy. Stay here and guard the house, I need to go find a soldier.",12,100,0,27241,"LINE_MALCOLM4");
+-- Event #4:
+UPDATE `creature` SET `position_x`=1563.337, `position_y`=671.6413, `position_z`=102.1412, `orientation`=4.2586040 WHERE `id`=27876;
+UPDATE `creature` SET `position_x`=1561.571, `position_y`=670.3199, `position_z`=102.1444, `orientation`=0.5759587 WHERE `id`=27877;
+UPDATE `creature_template` SET `AIName`="", `ScriptName`="npc_sergeant_morigan" WHERE `entry`=27877;
+DELETE FROM `creature_text` WHERE `creatureid` IN (27876,27877);
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`id`,`text`,`type`,`probability`,`emote`,`BroadcastTextId`,`comment`) VALUES
+(27876,0,0,"No, Sergeant.",12,100,274,27198,"LINE_PERELLI_NO #1"),
+(27876,0,1,"No, sir.",12,100,274,27199,"LINE_PERELLI_NO #2"),
+(27876,0,2,"Nope.",12,100,274,27200,"LINE_PERELLI_NO #3"),
+(27876,1,0,"Yes, sir.",12,100,1,27201,"LINE_PERELLI_YES #1"),
+(27876,1,1,"Yes, Sergeant Morigan.",12,100,1,27202,"LINE_PERELLI_YES #2"),
+(27876,1,2,"Absolutely.",12,100,1,27203,"LINE_PERELLI_YES #3"),
+(27876,2,0,"What are you talking about, Sergeant!",12,100,5,27208,"LINE_PERELLI1"),
+(27876,3,0,"You have to believe me, I'm innocent!",12,100,20,27213,"LINE_PERELLI2"),
+(27877,0,0,"Mr. Perelli, have you seen any suspicious activity by men wearing dark robes in the last few weeks?",12,100,6,27190,"LINE_SERGEANT_ASK_NO #1"),
+(27877,0,1,"Mr. Perelli, have you seen any signs of the undead? Any information you can provide would be appreciated by Prince Arthas.",12,100,1,27191,"LINE_SERGEANT_ASK_NO #2"),
+(27877,0,2,"Mr. Perelli, I know you travel around quite a bit hawking your goods. Surely you've heard rumors or information about the Scourge?",12,100,1,27192,"LINE_SERGEANT_ASK_NO #3"),
+(27877,0,3,"Do you plan on leaving the area soon if we have further questions?",12,100,1,27193,"LINE_SERGEANT_ASK_NO #4"),
+(27877,1,0,"Mr. Perelli, have these goods been under your supervision at all times?",12,100,6,27194,"LINE_SERGEANT_ASK_YES #1"),
+(27877,1,1,"You wouldn't happen to have any canned turtle soup from Hillsbrad, would you?",12,100,1,27195,"LINE_SERGEANT_ASK_YES #2"),
+(27877,1,2,"Mr. Perelli, if you happen across any signs of Scourge activity or shady dealings in your travels, let the nearest Lordaeron soldier know.",12,100,1,27197,"LINE_SERGEANT_ASK_YES #3"),
+(27877,2,0,"You don't mind me checking out your merchandise for signs of tampering, do you?",12,100,1,27205,"LINE_SERGEANT_START"),
+(27877,3,0,"Wait, what is this? You've been holding out on me, Perelli!",12,100,0,27206,"LINE_SERGEANT1"),
+(27877,4,0,"I'm confiscating this suspicious grain, Perelli. We were looking for signs of tampered food, and it would be in your best interest to stay put while Prince Arthas checks this out.",12,100,1,27210,"LINE_SERGEANT2"),
+(27877,5,0,"We'll see about that, Perelli. We'll see about that.",12,100,25,27216,"LINE_SERGEANT3");
+-- Event #5:
+UPDATE `creature` SET `position_x`=1588.942, `position_y`=597.9799, `position_z`=99.37262, `orientation`=2.80998 WHERE `id`=27903;
+UPDATE `creature_template` SET `AIName`="", `ScriptName`="npc_roger_owens" WHERE `entry`=27903;
+DELETE FROM `creature_text` WHERE `creatureid`=27903;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`emote`,`BroadcastTextId`,`comment`) VALUES
+(27903,0,"Ok, enough work for now. Time for refreshments and a little conversation in the inn.",12,100,1,27247,"LINE_ROGER1"),
+(27903,1,"Wait, what's that smell?",12,100,1,27248,"LINE_ROGER2"),
+(27903,2,"Can't be me, I took a bath 3 days ago!",12,100,5,27249,"LINE_ROGER3"),
+(27903,3,"Oh, close call. It's just the grain here.",12,100,5,27250,"LINE_ROGER4"),
+(27903,4,"Wait a second. Grain isn't supposed to smell like THAT! I better go find a guard.",12,100,0,27252,"LINE_ROGER5");
+
+-- Arthas AI
+UPDATE `creature_template` SET `ScriptName`="npc_arthas_stratholme",`AIName`="" WHERE `entry`=26499;
+UPDATE `creature_template` SET `unit_flags`=0x8000, `unit_flags2`=0x800 WHERE `entry` IN (26499,31210);
+DELETE FROM `creature` WHERE `id`=26499;
+
+-- Missing Arthas lines
+DELETE FROM `creature_text` WHERE `creatureid`=26499 AND `groupid`>38;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(26499,39,0,"I can't afford to spare you.",12,100,31355,0,"Arthas SAY_AGGRO_ZOMBIE"),
+(26499,40,0,"All officers should check in with me when their squads are ready. We'll enter Stratholme on my order.",12,100,27517,3,"Arthas RP1_LINE_ARTHAS11");
+
+-- Dummy spell scripts
+DELETE FROM `spell_script_names` WHERE `spell_id`=50773;
+INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES (50773,"spell_stratholme_crusader_strike");
+
+-- Arthas/Uther RP data
+UPDATE `creature_template` SET `ScriptName`="npc_stratholme_rp_dummy",`AIName`="" WHERE `entry` IN (26528,26497);
+UPDATE `creature_text` SET `TextRange`=3 WHERE `creatureid` IN (26499,26528,26497,26529,26530,26532,26533,32273);
+UPDATE `creature_text` SET `emote`=396 WHERE
+ (`creatureid` = 26499 AND `groupid` IN (0,3,5)) OR
+ (`creatureid` = 26528 AND `groupid`=3) OR
+ (`creatureid` = 26497 AND `groupid` IN (0,1));
+UPDATE `creature_text` SET `emote`=1 WHERE `creatureid`=26499 AND `groupid`=7;
+UPDATE `creature_text` SET `emote`=5 WHERE
+ (`creatureid` = 26499 AND `groupid` IN (2,4)) OR
+ (`creatureid` = 26528 AND `groupid` IN (1,4));
+UPDATE `creature_text` SET `emote`=6 WHERE `creatureid`=26528 AND `groupid`=2;
+UPDATE `creature_text` SET `emote`=397 WHERE
+ (`creatureid` = 26528 AND `groupid` IN (0,5));
+
+-- Arthas/Mal'ganis RP data
+DELETE FROM `creature_text` WHERE `creatureid` IN (28167,28169);
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`emote`,`comment`) VALUES
+(28167, 0, "Prince Arthas, may the light be praised! Many people in the town have begun to fall seriously ill, can you help us?", 12, 100, 27547, 0, 1, "RP2_LINE_CITIZEN1"),
+(28167, 1, "What? This can't be!", 12, 100, 27549, 0, 274, "RP2_LINE_CITIZEN2"),
+(28169, 0, "Oh, no...", 12, 100, 27552, 0, 0, "RP2_LINE_RESIDENT1");
+UPDATE `creature_text` SET `emote`=1 WHERE
+ (`creatureid` = 26499 AND `groupid` IN (12,14)) OR
+ (`creatureid` = 26533 AND `groupid`=0);
+UPDATE `creature_text` SET `emote`=397 WHERE
+ (`creatureid` = 26499 AND `groupid`=13);
+
+-- Town Hall/Gauntlet RP data
+UPDATE `creature_text` SET `emote`=1 WHERE
+ (`creatureid`=26499 AND `groupid` IN (16,19,22,38)) OR
+ (`creatureid`=28340 AND `groupid`=1);
+UPDATE `creature_text` SET `emote`=5 WHERE
+ (`creatureid`=26499 AND `groupid`=36);
+UPDATE `creature_text` SET `emote`=396 WHERE
+ (`creatureid`=26499 AND `groupid` IN (21,24,25,26,27,31,32,33,34));
+UPDATE `creature_text` SET `emote`=432 WHERE
+ (`creatureid`=26499 AND `groupid` IN (29));
+
+-- Clean up some incorrect spawns in wave area
+DELETE FROM `creature` WHERE `guid` BETWEEN 143949 AND 143952;
+
+-- spawn group data
+DELETE FROM `spawn_group` WHERE `groupId` BETWEEN 52 and 56;
+-- middle chromie
+INSERT INTO `spawn_group` (`groupId`,`spawnType`,`spawnId`) VALUES (52, 0, @CGUID);
+-- crate helpers
+INSERT INTO `spawn_group` SELECT 53 as `groupId`, 0 as `spawnType`, `guid` as `spawnId` FROM `creature` WHERE `id`=27827;
+-- Blanket apply a spawn group to all "live stratholme" mobs that prevents them respawning after the purge begins
+UPDATE `creature_template` SET `ScriptName`="",`AIName`="", `flags_extra`=(`flags_extra`|2) WHERE `entry` IN (28167,31126,31019,28169,31127,31023,31020,31018,31028);
+UPDATE `creature_template` SET `ScriptName`="",`AIName`="SmartAI" WHERE `entry` IN (31057,30570,31027,31021,30994);
+INSERT INTO `spawn_group` SELECT 56 as `groupId`, 0 as `spawnType`, `guid` as `spawnId` FROM `creature` WHERE `id` IN (28167,28169,30570,30994,31018,31019,31020,31021,31023,31027,31028,31057,31126,31127);
+-- Do the same for undead stratholme mobs
+UPDATE `creature_template` SET `ScriptName`="",`AIName`="SmartAI" WHERE `entry` IN (28249,27729,28200,27734,27731,28199,27736,28201);
+INSERT INTO `spawn_group` SELECT 55 as `groupId`, 0 as `spawnType`, `guid` as `spawnId` FROM `creature` WHERE `id` IN (27729,27731,27734,27736,27737,28199,28200,28201,28249);
+-- Gauntlet trash gets its own spawn group...
+UPDATE `spawn_group` sg LEFT JOIN `creature` c on sg.`spawnId`=c.`guid` SET sg.`groupId`=54 WHERE (sg.`groupId`=55) AND (c.`position_x` BETWEEN 2028.0 AND 2372.0) AND (c.`position_y` BETWEEN 1115.0 AND 1355.0);
+
+-- City fluff
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (30570,31027,31021) AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`event_type`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`action_type`,`target_type`,`comment`) VALUES
+(30570,0,0,10,100,7,1,10,1,1,"Emery Neill - Within 1-10 Range Out of Combat LoS - Say Line 0"),
+(31027,0,0,10,100,7,1,10,1,1,"Leeka Turner - Within 1-10 Range Out of Combat LoS - Say Line 0"),
+(31021,0,0,10,100,7,1,10,1,1,"Sophie Aaren - Within 1-10 Range Out of Combat LoS - Say Line 0");
+
+DELETE FROM `creature_text` WHERE `creatureid` IN (30570,31027,31021);
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`emote`,`comment`) VALUES
+(30570,0,0,"The Stone Crow's closed today, sorry. There are too many health concerns, and I'm not about to have Ed under fire for supposedly making people sick.",12,100,31724,1,"Emery Neill TALK_FLUFF 1"),
+(30570,0,1,"I hate to disappoint people, but the Stone Crow's closed. If the kids from the orphanage were evacuated, I don't see why we should be open, either.",12,100,31729,1,"Emery Neill TALK_FLUFF 2"),
+(31027,0,0,"Look, I'll sell you shields today, but no maces. The last thing I want is for some innocent to get brained by one of my weapons.",12,100,31721,1,"Leeka Turner TALK_FLUFF 1"),
+(31027,0,1,"I don't know how much longer I'll be open today with all the commotion outside. If you need something repaired, I'll take a quick look.",12,100,31722,1,"Leeka Turner TALK_FLUFF 2"),
+(31027,0,2,"I hope you're not coming in here fixing for a fight. There are too many angry people on the streets today.",12,100,31720,1,"Leeka Turner TALK_FLUFF 3"),
+(31021,0,0,"What's the commotion outside?",12,100,31730,1,"Sophie Aaren TALK_FLUFF 1"),
+(31021,0,1,"Is something going on? I hear angry voices.",12,100,31731,1,"Sophie Aaren TALK_FLUFF 2"),
+(31021,0,2,"Everything's been so strange lately...",12,100,31732,1,"Sophie Aaren TALK_FLUFF 3");
+
+-- SmartAI fixes for wave creatures
+UPDATE `smart_scripts` SET `event_param3`=3100, `event_param4`=3400 WHERE `entryorguid`=28200 AND `source_type`=0 AND `id` IN (0,1);
+
+-- Lordaeron Crier yells
+DELETE FROM `creature_text` WHERE `creatureid` = 27913;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(27913, 0, "All soldiers of Lordaeron should immediately report to the entrance of Stratholme, and await further orders from Prince Arthas.", 14, 100, 27263, 3, "Lordaeron Crier CALL_TO_GATES"),
+(27913, 1, "Scourge forces have been spotted near the King's Square fountain!", 14, 100, 27642, 3, "Lordaeron Crier KINGS_SQUARE"),
+(27913, 2, "Scourge forces have been spotted near the Market Row Gate!", 14, 100, 27643, 3, "Lordaeron Crier MARKET_ROW"),
+(27913, 3, "Scourge forces have been spotted near the Festival Lane Gate!", 14, 100, 27644, 3, "Lordaeron Crier FESTIVAL_LANE"),
+(27913, 4, "Scourge forces have been spotted near the Elder's Square Gate!", 14, 100, 27645, 3, "Lordaeron Crier ELDERS_SQUARE"),
+(27913, 5, "Scourge forces have been spotted near the Town Hall!", 14, 100, 27646, 3, "Lordaeron Crier TOWN_HALL");
+
+-- Get rid of the colossal mess that is Risen Zombie SmartAI
+UPDATE `creature_template` SET `AIName`="" WHERE `entry` = 27737;
+DELETE FROM `smart_scripts` WHERE -`entryorguid` IN (SELECT `guid` FROM `creature` WHERE `id`=27737 AND `map`=595);
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND -`SourceEntry` IN (SELECT `guid` FROM `creature` WHERE `id`=27737 AND `map`=595);
+
+-- Town Hall infinite spawns
+INSERT INTO `creature` (`guid`,`id`,`map`,`spawnDifficulties`,`phaseId`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`movementtype`) VALUES
+(@CGUID+01, 28340, 595, '1,2', 0, 2398.715, 1207.334, 134.1223, 5.270895, @DAY, 0, 0),
+(@CGUID+02, 28340, 595, '1,2', 0, 2401.265, 1202.789, 134.1039, 1.466077, @DAY, 0, 0),
+(@CGUID+03, 28341, 595, '1,2', 0, 2402.654, 1205.786, 134.1223, 2.897247, @DAY, 0, 0);
+UPDATE `creature_template` SET `unit_flags`=(`unit_flags`|0x100|0x200) WHERE `entry` IN (27742,27743,27744,31202,31203,31206,26532,31215,26533);
+
+-- Town Hall RP event
+DELETE FROM `creature_text` WHERE `creatureid`=28340;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(28340, 0, "Ah, you've finally arrived Prince Arthas. You're here just in the nick of time.", 12, 100, 27811, 3, "Stratholme Citizen (Disguised Infinite) RP3_LINE_CITIZEN1"),
+(28340, 1, "There's no need for you to understand, Arthas. All you need to do is die.", 12, 100, 27815, 3, "Stratholme Citizen (Disguised Infinite) RP3_LINE_CITIZEN2");
+
+-- Difficulty data for trash mobs
+-- DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (52660,52657,52635,52634);
+-- INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
+-- (52660,52660,58817),
+-- (52657,52657,58816),
+-- (52635,52635,58820),
+-- (52634,52634,58813);
+
+-- SAI fixes for Town Hall trash
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (28340,28341) AND `source_type`=0 AND `event_flags`=4;
+UPDATE `smart_scripts` SET `id`=CEIL(`id`/2)+1 WHERE `entryorguid`=28340 AND `source_type`=0 AND `event_flags`=2;
+UPDATE `smart_scripts` SET `id`=CEIL(`id`/2) WHERE `entryorguid`=28341 AND `source_type`=0 AND `event_flags`=2;
+UPDATE `smart_scripts` SET `event_flags`=`event_flags`|4 WHERE `entryorguid` IN (28340,28341) AND `source_type`=0;
+UPDATE `smart_scripts` SET `event_param3`=500, `event_param4`=750 WHERE `entryorguid`=28340 AND `source_type`=0 AND `id`=3;
+DELETE FROM `conditions` WHERE `sourcetypeorreferenceid`=22 AND `sourceentry`=28340 AND `sourceid`=0;
+INSERT INTO `conditions` (`sourcetypeorreferenceid`,`sourcegroup`,`sourceentry`,`sourceid`,`conditiontypeorreference`,`conditiontarget`,`conditionvalue1`,`conditionvalue2`,`comment`) VALUES
+(22,4,28340,0,31,1,3,27743,"Stratholme Citizen - Only execute SAI if entry is 27743 (Infinite Agent)");
+
+-- Chromie #3 data
+DELETE FROM `creature_template_addon` WHERE `entry`=30997;
+INSERT INTO `creature_template_addon` (`entry`,`bytes1`) VALUES
+(30997,50331648);
+DELETE FROM `creature_template_movement` WHERE `creatureid`=30997;
+INSERT INTO `creature_template_movement` (`creatureid`,`ground`,`flight`) VALUES (30997,1,2);
+DELETE FROM `creature_text` WHERE `creatureid`=30997;
+INSERT INTO `creature_text` (`creatureid`,`groupid`,`text`,`type`,`probability`,`BroadcastTextId`,`comment`) VALUES
+(30997,0,"Why, hello again!",12,100,32022,"Chromie #3 RP5_LINE_CHROMIE0");
+
+-- Meathook
+-- DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (52696,52666);
+-- INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
+-- (52696,52696,58823),
+-- (52666,52666,58824);
+
+-- Salramm the Fleshcrafter
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_salramm_steal_flesh';
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(52708,'spell_salramm_steal_flesh');
+-- DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (52480,57725);
+-- INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
+-- (52480,52480,58825),
+-- (57725,57725,58827);
+
+-- Chrono-Lord Epoch
+-- DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (52737,52771);
+-- INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
+-- (52737,52737,58829),
+-- (52771,52771,58830);
+
+-- Mal'ganis
+-- DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (52720,52722,52721);
+-- INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
+-- (52720,52720,58852),
+-- (52722,52722,58850),
+-- (52721,52721,58849);
+
+-- Spline chain data
+DELETE FROM `script_spline_chain_meta` WHERE `entry` IN (26499,26497,26528,28167,26532,27742,27907,27891,27892,27884,27885,27877,27903);
+INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES
+(26499, 1, 0, 3341, 2391),
+(26499, 1, 1, 3167, 2453),
+(26499, 1, 2, 2548, 1218),
+(26499, 1, 3, 2864, 1204),
+(26499, 1, 4, 2870, 0),
+(26497, 1, 0, 4710, 3641),
+(26497, 1, 1, 3684, 2422),
+(26497, 1, 2, 3639, 0),
+(26528, 1, 0, 5743, 4641),
+(26528, 1, 1, 5579, 4844),
+(26528, 1, 2, 4219, 3578),
+(26528, 1, 3, 1549, 0),
+(26499, 2, 0, 4113, 2438),
+(26499, 2, 1, 4586, 3641),
+(26499, 2, 2, 3298, 0),
+(26528, 2, 0, 3930, 0),
+(26497, 2, 0, 2598, 0),
+(26528, 3, 0, 11271, 9703),
+(26528, 3, 1, 6575, 4860),
+(26528, 3, 2, 9893, 8469),
+(26528, 3, 3, 8798, 7171),
+(26528, 3, 4, 9000, 0),
+(26497, 3, 0, 2911, 0),
+(26497, 4, 0, 12325, 11047),
+(26497, 4, 1, 8166, 7296),
+(26497, 4, 2, 8154, 7266),
+(26497, 4, 3, 6745, 6063),
+(26497, 4, 4, 9386, 0),
+(26499, 3, 0, 6366, 4813),
+(26499, 3, 1, 4957, 3671),
+(26499, 3, 2, 3972, 2344),
+(26499, 3, 3, 4644, 0),
+(26499, 4, 0, 2855, 1156),
+(26499, 4, 1, 3214, 2578),
+(26499, 4, 2, 2427, 1203),
+(26499, 4, 3, 2663, 1219),
+(26499, 4, 4, 3016, 2437),
+(26499, 4, 5, 1825, 1204),
+(26499, 4, 6, 3126, 2406),
+(26499, 4, 7, 2751, 1234),
+(26499, 4, 8, 2849, 1219),
+(26499, 4, 9, 4704, 3578),
+(26499, 4, 10, 2073, 1266),
+(26499, 4, 11, 1860, 1218),
+(26499, 4, 12, 1928, 0),
+(26499, 5, 0, 4032, 2266),
+(26499, 5, 1, 4170, 2594),
+(26499, 5, 2, 4925, 3453),
+(26499, 5, 3, 5560, 0),
+(26499, 6, 0, 3285, 0),
+(26499, 7, 0, 2247, 0),
+(28167, 1, 0, 2109, 0),
+(26499, 91, 0, 1862, 812),
+(26499, 91, 1, 1990, 1219),
+(26499, 91, 2, 1831, 0),
+(26499, 92, 0, 2007, 0),
+(26499, 95, 0, 2801, 1203),
+(26499, 95, 1, 3454, 2406),
+(26499, 95, 2, 2278, 1203),
+(26499, 95, 3, 3222, 2453),
+(26499, 95, 4, 2819, 0),
+(26499, 96, 0, 1770, 0),
+(26499, 97, 0, 2572, 1203),
+(26499, 97, 1, 2696, 1203),
+(26499, 97, 2, 2289, 1219),
+(26499, 97, 3, 2102, 1219),
+(26499, 97, 4, 2940, 1219),
+(26499, 97, 5, 3202, 0),
+(26499, 98, 0, 1838, 1219),
+(26499, 98, 1, 1843, 1015),
+(26499, 98, 2, 2029, 1391),
+(26499, 98, 3, 1645, 0),
+(26532, 1, 0, 2677, 0),
+(27742, 1, 0, 2871, 0),
+(27742, 2, 0, 2662, 0),
+(27742, 3, 0, 2454, 0),
+(27742, 4, 0, 2259, 0),
+(27742, 5, 0, 1884, 0),
+(27742, 6, 0, 3268, 0),
+(27742, 7, 0, 2100, 0),
+(27742, 8, 0, 3187, 0),
+(27742, 9, 0, 2649, 0),
+(27742, 10, 0, 888, 0),
+(27742, 11, 0, 871, 0),
+(27742, 12, 0, 844, 0),
+(26499, 101, 0, 3239, 2031),
+(26499, 101, 1, 2072, 1406),
+(26499, 101, 2, 2380, 1219),
+(26499, 101, 3, 1975, 0),
+(26499, 128, 0, 1934, 1157),
+(26499, 128, 1, 1843, 1078),
+(26499, 128, 2, 2542, 1422),
+(26499, 128, 3, 2651, 1203),
+(26499, 128, 4, 4784, 3547),
+(26499, 128, 5, 2204, 1281),
+(26499, 128, 6, 2250, 1250),
+(26499, 128, 7, 3174, 2297),
+(26499, 128, 8, 1604, 0),
+(26499, 1024, 0, 3268, 2422),
+(26499, 1024, 1, 3636, 2422),
+(26499, 1024, 2, 4245, 3640),
+(26499, 1024, 3, 3058, 2469),
+(26499, 1024, 4, 3931, 2390),
+(26499, 1024, 5, 5062, 3656),
+(26499, 1024, 6, 4970, 3844),
+(26499, 1024, 7, 3764, 2375),
+(26499, 1024, 8, 4819, 0),
+(26499, 1025, 0, 4244, 3500),
+(26499, 1025, 1, 4211, 2422),
+(26499, 1025, 2, 5342, 4031),
+(26499, 1025, 3, 5534, 4797),
+(26499, 1025, 4, 4503, 2421),
+(26499, 1025, 5, 5721, 4766),
+(26499, 1025, 6, 4335, 0),
+(26499, 121, 0, 3065, 2282),
+(26499, 121, 1, 1871, 1203),
+(26499, 121, 2, 2231, 1219),
+(26499, 121, 3, 4427, 3828),
+(26499, 121, 4, 3740, 2250),
+(26499, 121, 5, 2766, 0),
+(26499, 124, 0, 3499, 0),
+(26499, 125, 0, 7907, 7266),
+(26499, 125, 1, 8079, 7297),
+(26499, 125, 2, 8198, 0),
+(26499, 127, 0, 7779, 6265),
+(26499, 127, 1, 10397, 9719),
+(26499, 127, 2, 7018, 0),
+(27907, 1, 0, 1260, 0),
+(27907, 2, 0, 2395, 1125),
+(27907, 2, 1, 3378, 2515),
+(27907, 2, 2, 4259, 3516),
+(27907, 2, 3, 3997, 2531),
+(27907, 2, 4, 6453, 4844),
+(27907, 2, 5, 8822, 7281),
+(27907, 2, 6, 5655, 4844),
+(27907, 2, 7, 6149, 4859),
+(27907, 2, 8, 10645, 9688),
+(27907, 2, 9, 4624, 3640),
+(27907, 2, 10, 7230, 6079),
+(27907, 2, 11, 7563, 6062),
+(27907, 2, 12, 6819, 6047),
+(27907, 2, 13, 10112, 8469),
+(27907, 2, 14, 7902, 7281),
+(27907, 2, 15, 4819, 3625),
+(27907, 2, 16, 8246, 7172),
+(27907, 2, 17, 6200, 4750),
+(27907, 2, 18, 2828, 1312),
+(27907, 2, 19, 4017, 2516),
+(27907, 2, 20, 5094, 3500),
+(27907, 2, 21, 5351, 0),
+(27891, 1, 0, 3239, 2625),
+(27891, 1, 1, 2755, 0),
+(27891, 2, 0, 4320, 3235),
+(27891, 2, 1, 3531, 2422),
+(27891, 2, 2, 2835, 0),
+(27891, 3, 0, 1964, 1218),
+(27891, 3, 1, 1879, 1203),
+(27891, 3, 2, 1555, 0),
+(27891, 4, 0, 3004, 1250),
+(27891, 4, 1, 4201, 2438),
+(27891, 4, 2, 4956, 3640),
+(27891, 4, 3, 4015, 2422),
+(27891, 4, 4, 5920, 4844),
+(27891, 4, 5, 5607, 4875),
+(27891, 4, 6, 5841, 4687),
+(27891, 4, 7, 7269, 6250),
+(27891, 4, 8, 6402, 4797),
+(27891, 4, 9, 8083, 7297),
+(27891, 4, 10, 5750, 4750),
+(27891, 4, 11, 3990, 2531),
+(27891, 4, 12, 5397, 3500),
+(27891, 4, 13, 5269, 3750),
+(27891, 4, 14, 6169, 4860),
+(27891, 4, 15, 5497, 4828),
+(27891, 4, 16, 5084, 3625),
+(27891, 4, 17, 5681, 4844),
+(27891, 4, 18, 6803, 6062),
+(27891, 4, 19, 5758, 4844),
+(27891, 4, 20, 4319, 3625),
+(27891, 4, 21, 4710, 3641),
+(27891, 4, 22, 7181, 6062),
+(27891, 4, 23, 8723, 7125),
+(27891, 4, 24, 6300, 5000),
+(27891, 4, 25, 6074, 4828),
+(27891, 4, 26, 6394, 4844),
+(27891, 4, 27, 4809, 3641),
+(27891, 4, 28, 6276, 4750),
+(27891, 4, 29, 6886, 6031),
+(27891, 4, 30, 6358, 4969),
+(27891, 4, 31, 6506, 0),
+(27892, 1, 0, 3242, 2219),
+(27892, 1, 1, 2553, 1234),
+(27892, 1, 2, 3071, 2406),
+(27892, 1, 3, 2449, 1188),
+(27892, 1, 4, 2974, 1234),
+(27892, 1, 5, 3961, 2422),
+(27892, 1, 6, 2884, 1203),
+(27892, 1, 7, 3427, 0),
+(27892, 2, 0, 2022, 0),
+(27884, 1, 0, 2596, 0),
+(27884, 2, 0, 2381, 0),
+(27885, 70, 0, 5363, 3640),
+(27885, 70, 1, 4216, 3500),
+(27885, 70, 2, 5501, 4969),
+(27885, 70, 3, 2752, 1062),
+(27885, 70, 4, 3472, 0),
+(27885, 71, 0, 3757, 0),
+(27885, 72, 0, 3004, 1218),
+(27885, 72, 1, 3927, 2282),
+(27885, 72, 2, 3491, 2562),
+(27885, 72, 3, 3020, 2422),
+(27885, 72, 4, 2334, 1063),
+(27885, 72, 5, 3425, 2562),
+(27885, 72, 6, 3055, 2422),
+(27885, 72, 7, 2369, 1031),
+(27885, 72, 8, 1804, 1375),
+(27885, 72, 9, 1215, 0),
+(27885, 1, 0, 2514, 0),
+(27885, 2, 0, 2443, 0),
+(27885, 3, 0, 2443, 0),
+(27877, 1, 0, 1877, 1359),
+(27877, 1, 1, 2104, 0),
+(27877, 2, 0, 4870, 3641),
+(27877, 2, 1, 5372, 3625),
+(27877, 2, 2, 4919, 3453),
+(27877, 2, 3, 6343, 5016),
+(27877, 2, 4, 7111, 6031),
+(27877, 2, 5, 7063, 6016),
+(27877, 2, 6, 6610, 0),
+(27903, 1, 0, 4337, 3640),
+(27903, 1, 1, 3730, 2407),
+(27903, 1, 2, 3116, 2437),
+(27903, 1, 3, 3533, 0),
+(27903, 2, 0, 1975, 0),
+(27903, 3, 0, 4685, 3625),
+(27903, 3, 1, 4437, 3625),
+(27903, 3, 2, 5367, 3672),
+(27903, 3, 3, 5862, 0);
+
+DELETE FROM `script_spline_chain_waypoints` WHERE `entry` IN (26499,26497,26528,28167,26532,27742,27907,27891,27892,27884,27885,27877,27903);
+INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES
+(26499, 1, 0, 0, 1983.857, 1287.043, 145.5596),
+(26499, 1, 0, 1, 1957.138, 1287.436, 145.6538),
+(26499, 1, 1, 0, 1964.463, 1287.328, 145.6280),
+(26499, 1, 1, 1, 1957.067, 1287.571, 145.8101),
+(26499, 1, 1, 2, 1941.817, 1288.071, 145.8101),
+(26499, 1, 1, 3, 1939.171, 1288.315, 145.4922),
+(26499, 1, 2, 0, 1945.112, 1288.024, 145.7216),
+(26499, 1, 2, 1, 1941.497, 1288.348, 145.7976),
+(26499, 1, 2, 2, 1939.247, 1288.598, 145.5476),
+(26499, 1, 2, 3, 1926.247, 1289.098, 144.5476),
+(26499, 1, 2, 4, 1924.883, 1289.172, 143.8736),
+(26499, 1, 3, 0, 1935.320, 1288.546, 145.0998),
+(26499, 1, 3, 1, 1926.090, 1289.288, 144.4456),
+(26499, 1, 3, 2, 1924.840, 1289.288, 143.9456),
+(26499, 1, 3, 3, 1915.340, 1290.038, 142.1956),
+(26499, 1, 3, 4, 1912.860, 1290.030, 142.2913),
+(26499, 1, 4, 0, 1925.639, 1289.127, 144.0508),
+(26499, 1, 4, 1, 1924.946, 1289.347, 143.9687),
+(26499, 1, 4, 2, 1915.196, 1290.347, 142.2187),
+(26499, 1, 4, 3, 1913.196, 1290.347, 142.7187),
+(26499, 1, 4, 4, 1909.196, 1290.597, 143.2187),
+(26499, 1, 4, 5, 1904.196, 1291.347, 143.7187),
+(26499, 1, 4, 6, 1903.254, 1291.568, 143.3867),
+(26497, 1, 0, 0, 1876.788, 1305.723, 146.2474),
+(26497, 1, 0, 1, 1883.386, 1300.033, 145.7733),
+(26497, 1, 0, 2, 1885.484, 1297.844, 145.2992),
+(26497, 1, 1, 0, 1883.513, 1299.635, 145.5760),
+(26497, 1, 1, 1, 1885.626, 1297.811, 145.3729),
+(26497, 1, 1, 2, 1889.126, 1296.311, 144.8729),
+(26497, 1, 1, 3, 1891.239, 1294.988, 144.1697),
+(26497, 1, 2, 0, 1888.441, 1296.377, 144.6055),
+(26497, 1, 2, 1, 1889.347, 1296.104, 144.6718),
+(26497, 1, 2, 2, 1891.597, 1295.104, 144.4218),
+(26497, 1, 2, 3, 1896.754, 1292.831, 143.7381),
+(26528, 1, 0, 0, 1783.843, 1267.481, 139.7800),
+(26528, 1, 0, 1, 1782.336, 1267.000, 139.7406),
+(26528, 1, 0, 2, 1783.282, 1267.326, 139.7406),
+(26528, 1, 0, 3, 1790.993, 1269.459, 140.2811),
+(26528, 1, 0, 4, 1798.704, 1271.592, 140.9061),
+(26528, 1, 0, 5, 1804.487, 1273.191, 141.4359),
+(26528, 1, 0, 6, 1814.126, 1275.857, 142.0609),
+(26528, 1, 0, 7, 1824.729, 1278.790, 142.6859),
+(26528, 1, 0, 8, 1827.434, 1279.528, 142.9155),
+(26528, 1, 0, 9, 1827.434, 1279.528, 142.9155),
+(26528, 1, 1, 0, 1817.973, 1276.922, 142.2877),
+(26528, 1, 1, 1, 1824.995, 1279.099, 142.9928),
+(26528, 1, 1, 2, 1827.745, 1279.849, 143.2428),
+(26528, 1, 1, 3, 1833.745, 1280.099, 143.7428),
+(26528, 1, 1, 4, 1846.245, 1281.349, 144.2428),
+(26528, 1, 1, 5, 1862.016, 1282.776, 144.1979),
+(26528, 1, 2, 0, 1856.154, 1282.227, 144.1979),
+(26528, 1, 2, 1, 1862.171, 1283.084, 144.4533),
+(26528, 1, 2, 2, 1888.921, 1285.834, 143.9533),
+(26528, 1, 2, 3, 1889.687, 1285.941, 143.7088),
+(26528, 1, 3, 0, 1887.511, 1285.683, 143.7328),
+(26528, 1, 3, 1, 1889.049, 1286.004, 143.7950),
+(26528, 1, 3, 2, 1890.049, 1286.254, 143.7950),
+(26528, 1, 3, 3, 1899.588, 1288.324, 143.3571),
+(26499, 2, 0, 0, 1903.254, 1291.568, 143.3867),
+(26499, 2, 0, 1, 1905.293, 1301.579, 144.5444),
+(26499, 2, 1, 0, 1904.456, 1297.470, 144.0693),
+(26499, 2, 1, 1, 1905.458, 1301.860, 144.8994),
+(26499, 2, 1, 2, 1905.958, 1302.610, 145.6494),
+(26499, 2, 1, 3, 1905.958, 1303.360, 146.6494),
+(26499, 2, 1, 4, 1906.458, 1304.360, 147.1494),
+(26499, 2, 1, 5, 1906.958, 1306.360, 148.1494),
+(26499, 2, 1, 6, 1907.461, 1307.250, 148.2295),
+(26499, 2, 2, 0, 1906.671, 1305.182, 147.4275),
+(26499, 2, 2, 1, 1907.312, 1306.470, 148.3720),
+(26499, 2, 2, 2, 1907.812, 1307.470, 148.6220),
+(26499, 2, 2, 3, 1908.312, 1308.970, 149.1220),
+(26499, 2, 2, 4, 1909.812, 1311.720, 150.1220),
+(26499, 2, 2, 5, 1909.953, 1312.258, 149.8164),
+(26528, 2, 0, 0, 1899.588, 1288.324, 143.3571),
+(26528, 2, 0, 1, 1903.980, 1297.110, 143.5117),
+(26497, 2, 0, 0, 1896.754, 1292.831, 143.7381),
+(26497, 2, 0, 1, 1899.490, 1298.720, 143.8324),
+(26528, 3, 0, 0, 1903.980, 1297.110, 143.5117),
+(26528, 3, 0, 1, 1878.339, 1285.441, 144.0609),
+(26528, 3, 1, 0, 1881.913, 1287.067, 143.9844),
+(26528, 3, 1, 1, 1878.267, 1285.418, 144.3411),
+(26528, 3, 1, 2, 1866.120, 1282.769, 144.1979),
+(26528, 3, 2, 0, 1870.356, 1283.695, 144.1504),
+(26528, 3, 2, 1, 1866.068, 1282.754, 144.3617),
+(26528, 3, 2, 2, 1845.780, 1281.313, 144.0729),
+(26528, 3, 3, 0, 1849.295, 1281.565, 144.0945),
+(26528, 3, 3, 1, 1845.886, 1281.369, 144.2576),
+(26528, 3, 3, 2, 1833.136, 1280.119, 143.5076),
+(26528, 3, 3, 3, 1827.477, 1279.173, 142.9207),
+(26528, 3, 4, 0, 1831.271, 1279.616, 143.2832),
+(26528, 3, 4, 1, 1827.359, 1279.084, 143.2076),
+(26528, 3, 4, 2, 1819.859, 1277.084, 142.4576),
+(26528, 3, 4, 3, 1809.446, 1274.552, 141.6319),
+(26497, 3, 0, 0, 1899.490, 1298.720, 143.8324),
+(26497, 3, 0, 1, 1894.122, 1293.809, 143.8338),
+(26497, 4, 0, 0, 1894.122, 1293.809, 143.8338),
+(26497, 4, 0, 1, 1871.234, 1287.862, 144.6408),
+(26497, 4, 0, 2, 1864.347, 1285.916, 144.4479),
+(26497, 4, 1, 0, 1867.776, 1286.831, 144.4536),
+(26497, 4, 1, 1, 1864.450, 1286.037, 144.5757),
+(26497, 4, 1, 2, 1847.624, 1283.743, 144.1979),
+(26497, 4, 2, 0, 1849.860, 1284.034, 144.2313),
+(26497, 4, 2, 1, 1847.545, 1283.791, 144.4611),
+(26497, 4, 2, 2, 1834.045, 1281.791, 143.7111),
+(26497, 4, 2, 3, 1829.730, 1281.048, 143.1909),
+(26497, 4, 3, 0, 1831.906, 1281.373, 143.3964),
+(26497, 4, 3, 1, 1829.835, 1281.172, 143.3008),
+(26497, 4, 3, 2, 1823.085, 1280.172, 142.8008),
+(26497, 4, 3, 3, 1815.265, 1278.970, 142.2052),
+(26497, 4, 4, 0, 1816.958, 1279.213, 142.2851),
+(26497, 4, 4, 1, 1815.281, 1278.945, 142.2650),
+(26497, 4, 4, 2, 1804.781, 1276.695, 141.7650),
+(26497, 4, 4, 3, 1799.781, 1275.695, 141.5150),
+(26497, 4, 4, 4, 1794.105, 1274.177, 140.7448),
+(26499, 3, 0, 0, 1909.953, 1312.258, 149.8164),
+(26499, 3, 0, 1, 1908.551, 1309.692, 149.4765),
+(26499, 3, 0, 2, 1907.551, 1307.942, 148.7265),
+(26499, 3, 0, 3, 1906.551, 1306.192, 147.7265),
+(26499, 3, 0, 4, 1905.551, 1303.692, 146.7265),
+(26499, 3, 0, 5, 1905.051, 1302.942, 145.9765),
+(26499, 3, 0, 6, 1904.551, 1301.942, 145.2265),
+(26499, 3, 0, 7, 1904.051, 1300.942, 144.2265),
+(26499, 3, 0, 8, 1903.149, 1299.625, 143.6367),
+(26499, 3, 1, 0, 1904.679, 1302.469, 145.4152),
+(26499, 3, 1, 1, 1904.199, 1301.766, 144.8384),
+(26499, 3, 1, 2, 1903.949, 1300.766, 144.3384),
+(26499, 3, 1, 3, 1903.449, 1299.516, 144.0884),
+(26499, 3, 1, 4, 1903.718, 1291.063, 143.2617),
+(26499, 3, 2, 0, 1903.495, 1294.415, 143.4085),
+(26499, 3, 2, 1, 1904.043, 1291.134, 143.5083),
+(26499, 3, 2, 2, 1907.793, 1288.384, 143.0083),
+(26499, 3, 2, 3, 1909.091, 1287.353, 142.6082),
+(26499, 3, 3, 0, 1905.888, 1289.565, 142.9981),
+(26499, 3, 3, 1, 1910.904, 1288.431, 142.5031),
+(26499, 3, 3, 2, 1914.904, 1287.181, 142.0031),
+(26499, 3, 3, 3, 1916.920, 1287.297, 142.0080),
+(26499, 4, 0, 0, 1916.920, 1287.297, 142.0080),
+(26499, 4, 0, 1, 1926.420, 1287.426, 144.2628),
+(26499, 4, 0, 2, 1929.170, 1287.676, 144.5128),
+(26499, 4, 0, 3, 1939.420, 1287.554, 145.5176),
+(26499, 4, 1, 0, 1926.350, 1287.513, 144.1856),
+(26499, 4, 1, 1, 1929.405, 1287.518, 144.9343),
+(26499, 4, 1, 2, 1939.405, 1287.518, 145.6843),
+(26499, 4, 1, 3, 1941.655, 1287.518, 145.9343),
+(26499, 4, 1, 4, 1951.959, 1287.524, 145.6830),
+(26499, 4, 2, 0, 1945.664, 1287.539, 145.7185),
+(26499, 4, 2, 1, 1952.117, 1287.516, 145.9138),
+(26499, 4, 2, 2, 1965.071, 1287.494, 145.6091),
+(26499, 4, 3, 0, 1955.347, 1287.516, 145.6639),
+(26499, 4, 3, 1, 1965.244, 1287.470, 145.8539),
+(26499, 4, 3, 2, 1976.641, 1287.424, 145.5438),
+(26499, 4, 4, 0, 1965.047, 1287.494, 145.6092),
+(26499, 4, 4, 1, 1976.853, 1287.353, 145.7835),
+(26499, 4, 4, 2, 1988.603, 1287.353, 145.5335),
+(26499, 4, 4, 3, 1989.159, 1287.212, 145.4577),
+(26499, 4, 5, 0, 1985.305, 1287.277, 145.4950),
+(26499, 4, 5, 1, 1988.890, 1287.511, 145.7352),
+(26499, 4, 5, 2, 1989.140, 1287.511, 145.7352),
+(26499, 4, 5, 3, 1992.975, 1297.245, 145.4753),
+(26499, 4, 6, 0, 1991.095, 1292.302, 145.4666),
+(26499, 4, 6, 1, 1993.198, 1297.473, 145.7460),
+(26499, 4, 6, 2, 1993.948, 1300.723, 145.7460),
+(26499, 4, 6, 3, 1997.198, 1313.223, 143.7460),
+(26499, 4, 6, 4, 1997.800, 1316.144, 143.0254),
+(26499, 4, 7, 0, 1996.410, 1310.698, 143.7020),
+(26499, 4, 7, 1, 1997.232, 1313.538, 143.3433),
+(26499, 4, 7, 2, 1997.982, 1316.288, 143.3433),
+(26499, 4, 7, 3, 1998.732, 1317.288, 143.3433),
+(26499, 4, 7, 4, 2003.232, 1322.538, 143.3433),
+(26499, 4, 7, 5, 2009.732, 1326.038, 143.3433),
+(26499, 4, 7, 6, 2010.055, 1326.378, 142.9847),
+(26499, 4, 8, 0, 2000.474, 1319.478, 142.9744),
+(26499, 4, 8, 1, 2003.205, 1322.562, 143.2088),
+(26499, 4, 8, 2, 2009.955, 1326.062, 143.2088),
+(26499, 4, 8, 3, 2009.955, 1326.312, 143.2088),
+(26499, 4, 8, 4, 2019.437, 1321.146, 142.9432),
+(26499, 4, 9, 0, 2008.504, 1325.558, 142.9917),
+(26499, 4, 9, 1, 2009.963, 1326.276, 143.2323),
+(26499, 4, 9, 2, 2010.213, 1326.276, 143.2323),
+(26499, 4, 9, 3, 2019.463, 1321.026, 143.2323),
+(26499, 4, 9, 4, 2021.963, 1311.526, 143.2323),
+(26499, 4, 9, 5, 2022.713, 1309.026, 143.2323),
+(26499, 4, 9, 6, 2023.213, 1307.526, 143.7323),
+(26499, 4, 9, 7, 2025.921, 1296.995, 143.4729),
+(26499, 4, 10, 0, 2023.620, 1305.563, 143.4979),
+(26499, 4, 10, 1, 2026.268, 1297.151, 143.5187),
+(26499, 4, 10, 2, 2028.768, 1293.401, 143.5187),
+(26499, 4, 10, 3, 2030.417, 1290.740, 143.5395),
+(26499, 4, 11, 0, 2026.428, 1296.289, 143.4703),
+(26499, 4, 11, 1, 2028.844, 1293.166, 143.6114),
+(26499, 4, 11, 2, 2030.594, 1290.916, 143.6114),
+(26499, 4, 11, 3, 2032.094, 1290.416, 143.8614),
+(26499, 4, 11, 4, 2033.594, 1289.666, 143.6114),
+(26499, 4, 11, 5, 2035.344, 1288.916, 143.6114),
+(26499, 4, 11, 6, 2037.759, 1287.544, 143.2525),
+(26499, 4, 12, 0, 2032.995, 1289.617, 143.4461),
+(26499, 4, 12, 1, 2033.722, 1289.358, 143.6375),
+(26499, 4, 12, 2, 2035.472, 1288.608, 143.3875),
+(26499, 4, 12, 3, 2037.972, 1287.858, 143.3875),
+(26499, 4, 12, 4, 2045.222, 1287.858, 143.1375),
+(26499, 4, 12, 5, 2047.948, 1287.598, 142.8289),
+(26499, 5, 0, 0, 2047.948, 1287.598, 142.8289),
+(26499, 5, 0, 1, 2050.976, 1287.708, 142.7941),
+(26499, 5, 0, 2, 2058.005, 1287.819, 142.2593),
+(26499, 5, 1, 0, 2053.991, 1287.731, 142.4832),
+(26499, 5, 1, 1, 2058.194, 1287.743, 142.4689),
+(26499, 5, 1, 2, 2060.694, 1287.743, 142.2189),
+(26499, 5, 1, 3, 2064.398, 1287.755, 141.9545),
+(26499, 5, 2, 0, 2060.053, 1287.799, 142.1414),
+(26499, 5, 2, 1, 2060.704, 1287.717, 142.1683),
+(26499, 5, 2, 2, 2064.704, 1287.717, 142.1683),
+(26499, 5, 2, 3, 2070.454, 1287.717, 141.9183),
+(26499, 5, 2, 4, 2072.355, 1287.635, 141.6951),
+(26499, 5, 3, 0, 2069.130, 1287.684, 141.8000),
+(26499, 5, 3, 1, 2070.820, 1287.637, 141.9955),
+(26499, 5, 3, 2, 2072.570, 1287.637, 141.7455),
+(26499, 5, 3, 3, 2075.820, 1287.637, 141.7455),
+(26499, 5, 3, 4, 2083.011, 1287.590, 141.1909),
+(26499, 6, 0, 0, 2083.011, 1287.590, 141.1909),
+(26499, 6, 0, 1, 2084.617, 1285.493, 141.1684),
+(26499, 6, 0, 2, 2087.367, 1281.493, 140.9184),
+(26499, 6, 0, 3, 2087.722, 1280.896, 140.6459),
+(26499, 7, 0, 0, 2087.722, 1280.896, 140.6459),
+(26499, 7, 0, 1, 2091.994, 1277.257, 140.4254),
+(28167, 1, 0, 0, 2092.018, 1275.036, 140.8330),
+(28167, 1, 0, 1, 2090.446, 1277.398, 141.0078),
+(28167, 1, 0, 2, 2088.873, 1279.260, 140.6826),
+(26499, 91, 0, 0, 2366.240, 1195.253, 132.0441),
+(26499, 91, 0, 1, 2366.501, 1196.756, 132.5435),
+(26499, 91, 0, 2, 2366.501, 1198.006, 132.5435),
+(26499, 91, 0, 3, 2370.251, 1199.006, 134.2935),
+(26499, 91, 0, 4, 2371.501, 1199.256, 134.7935),
+(26499, 91, 0, 5, 2373.251, 1199.756, 134.7935),
+(26499, 91, 0, 6, 2375.251, 1200.256, 134.2935),
+(26499, 91, 0, 7, 2376.251, 1200.506, 134.2935),
+(26499, 91, 0, 8, 2377.262, 1200.759, 134.0428),
+(26499, 91, 1, 0, 2368.773, 1198.629, 133.4956),
+(26499, 91, 1, 1, 2370.306, 1199.143, 134.2684),
+(26499, 91, 1, 2, 2371.556, 1199.393, 135.0184),
+(26499, 91, 1, 3, 2373.556, 1199.893, 135.0184),
+(26499, 91, 1, 4, 2375.306, 1200.393, 134.2684),
+(26499, 91, 1, 5, 2376.306, 1200.393, 134.2684),
+(26499, 91, 1, 6, 2377.306, 1200.643, 134.2684),
+(26499, 91, 1, 7, 2382.556, 1201.893, 134.2684),
+(26499, 91, 1, 8, 2383.839, 1202.156, 134.0411),
+(26499, 91, 2, 0, 2377.760, 1200.865, 134.0427),
+(26499, 91, 2, 1, 2382.930, 1202.066, 134.2909),
+(26499, 91, 2, 2, 2384.180, 1202.316, 134.2909),
+(26499, 91, 2, 3, 2386.180, 1202.566, 134.2909),
+(26499, 91, 2, 4, 2392.101, 1203.767, 134.0390),
+(26499, 92, 0, 0, 2392.101, 1203.767, 134.0390),
+(26499, 92, 0, 1, 2396.516, 1206.148, 134.0383),
+(26499, 95, 0, 0, 2396.516, 1206.148, 134.0383),
+(26499, 95, 0, 1, 2404.866, 1207.302, 134.2841),
+(26499, 95, 0, 2, 2408.366, 1207.552, 134.0341),
+(26499, 95, 0, 3, 2418.716, 1208.955, 134.0299),
+(26499, 95, 1, 0, 2406.147, 1207.366, 133.9344),
+(26499, 95, 1, 1, 2408.496, 1207.973, 133.9710),
+(26499, 95, 1, 2, 2418.996, 1209.223, 134.2210),
+(26499, 95, 1, 3, 2419.746, 1209.723, 134.2210),
+(26499, 95, 1, 4, 2428.246, 1213.973, 134.2210),
+(26499, 95, 1, 5, 2431.845, 1216.079, 134.0077),
+(26499, 95, 2, 0, 2424.443, 1212.063, 134.0150),
+(26499, 95, 2, 1, 2428.300, 1214.332, 134.2638),
+(26499, 95, 2, 2, 2432.050, 1216.082, 134.2638),
+(26499, 95, 2, 3, 2441.157, 1219.101, 134.0126),
+(26499, 95, 3, 0, 2433.054, 1216.472, 134.0083),
+(26499, 95, 3, 1, 2441.192, 1219.025, 134.4917),
+(26499, 95, 3, 2, 2441.692, 1216.775, 134.4917),
+(26499, 95, 3, 3, 2442.192, 1215.025, 134.2417),
+(26499, 95, 3, 4, 2442.442, 1213.525, 135.9917),
+(26499, 95, 3, 5, 2444.330, 1205.078, 141.9751),
+(26499, 95, 4, 0, 2443.168, 1210.214, 138.0827),
+(26499, 95, 4, 1, 2444.703, 1205.028, 142.3293),
+(26499, 95, 4, 2, 2446.203, 1198.028, 147.5793),
+(26499, 95, 4, 3, 2447.738, 1191.342, 148.0759),
+(26499, 96, 0, 0, 2447.738, 1191.342, 148.0759),
+(26499, 96, 0, 1, 2443.461, 1190.214, 148.0759),
+(26499, 97, 0, 0, 2443.461, 1190.214, 148.0759),
+(26499, 97, 0, 1, 2442.500, 1190.911, 148.3259),
+(26499, 97, 0, 2, 2432.500, 1193.911, 148.3259),
+(26499, 97, 0, 3, 2425.250, 1194.411, 148.3259),
+(26499, 97, 0, 4, 2423.539, 1194.608, 148.0759),
+(26499, 97, 1, 0, 2434.366, 1193.263, 148.0759),
+(26499, 97, 1, 1, 2432.421, 1193.916, 148.3259),
+(26499, 97, 1, 2, 2424.921, 1194.416, 148.3259),
+(26499, 97, 1, 3, 2423.671, 1194.666, 148.3259),
+(26499, 97, 1, 4, 2412.975, 1194.068, 148.0759),
+(26499, 97, 2, 0, 2424.781, 1194.516, 148.0759),
+(26499, 97, 2, 1, 2423.638, 1194.570, 148.3259),
+(26499, 97, 2, 2, 2413.138, 1194.070, 148.3259),
+(26499, 97, 2, 3, 2410.888, 1193.070, 148.3259),
+(26499, 97, 2, 4, 2408.138, 1192.320, 148.3259),
+(26499, 97, 2, 5, 2406.995, 1191.624, 148.0759),
+(26499, 97, 3, 0, 2415.113, 1194.177, 148.0759),
+(26499, 97, 3, 1, 2413.069, 1194.000, 148.3259),
+(26499, 97, 3, 2, 2410.569, 1193.000, 148.3259),
+(26499, 97, 3, 3, 2408.069, 1192.000, 148.3259),
+(26499, 97, 3, 4, 2407.319, 1191.500, 148.3259),
+(26499, 97, 3, 5, 2406.069, 1188.250, 148.3259),
+(26499, 97, 3, 6, 2404.526, 1183.823, 148.0759),
+(26499, 97, 4, 0, 2406.700, 1190.692, 148.0759),
+(26499, 97, 4, 1, 2406.134, 1187.959, 148.3256),
+(26499, 97, 4, 2, 2404.884, 1183.709, 148.3256),
+(26499, 97, 4, 3, 2405.634, 1177.709, 148.3256),
+(26499, 97, 4, 4, 2407.067, 1167.727, 148.0753),
+(26499, 97, 5, 0, 2404.814, 1181.384, 148.0758),
+(26499, 97, 5, 1, 2405.542, 1177.282, 148.3256),
+(26499, 97, 5, 2, 2407.042, 1168.032, 148.3256),
+(26499, 97, 5, 3, 2407.542, 1165.782, 148.3256),
+(26499, 97, 5, 4, 2409.271, 1156.181, 148.0755),
+(26499, 98, 0, 0, 2409.271, 1156.181, 148.0755),
+(26499, 98, 0, 1, 2412.297, 1141.795, 148.0757),
+(26499, 98, 1, 0, 2411.266, 1146.695, 148.0757),
+(26499, 98, 1, 1, 2412.604, 1141.814, 148.3258),
+(26499, 98, 1, 2, 2414.943, 1132.433, 148.0759),
+(26499, 98, 2, 0, 2413.564, 1137.311, 148.0758),
+(26499, 98, 2, 1, 2415.143, 1132.356, 148.3259),
+(26499, 98, 2, 2, 2417.143, 1129.106, 148.3259),
+(26499, 98, 2, 3, 2420.722, 1122.901, 148.0759),
+(26499, 98, 3, 0, 2417.318, 1128.516, 148.0760),
+(26499, 98, 3, 1, 2420.858, 1123.179, 148.3259),
+(26499, 98, 3, 2, 2422.608, 1121.679, 148.3259),
+(26499, 98, 3, 3, 2424.108, 1120.429, 148.3259),
+(26499, 98, 3, 4, 2425.898, 1118.842, 148.0759),
+(26532, 1, 0, 0, 2457.008, 1113.929, 150.0776),
+(26532, 1, 0, 1, 2458.388, 1114.085, 150.0917),
+(26532, 1, 0, 2, 2457.393, 1113.980, 150.0917),
+(26532, 1, 0, 3, 2455.168, 1113.687, 150.0104),
+(26532, 1, 0, 4, 2450.874, 1113.122, 149.0170),
+(26532, 1, 0, 5, 2450.874, 1113.122, 149.0170),
+(27742, 1, 0, 0, 2432.824, 1191.816, 148.1556),
+(27742, 1, 0, 1, 2432.566, 1193.102, 148.1593),
+(27742, 1, 0, 2, 2432.757, 1192.121, 148.1593),
+(27742, 1, 0, 3, 2434.290, 1185.112, 148.0759),
+(27742, 1, 0, 4, 2434.290, 1185.112, 148.0759),
+(27742, 2, 0, 0, 2432.990, 1192.760, 148.1474),
+(27742, 2, 0, 1, 2432.270, 1191.664, 148.1593),
+(27742, 2, 0, 2, 2432.829, 1192.493, 148.1593),
+(27742, 2, 0, 3, 2433.960, 1194.363, 148.0759),
+(27742, 2, 0, 4, 2436.273, 1198.183, 148.0759),
+(27742, 2, 0, 5, 2436.273, 1198.183, 148.0759),
+(27742, 3, 0, 0, 2432.711, 1192.857, 148.1550),
+(27742, 3, 0, 1, 2431.399, 1192.900, 148.1593),
+(27742, 3, 0, 2, 2432.398, 1192.865, 148.1593),
+(27742, 3, 0, 3, 2438.529, 1192.707, 148.0759),
+(27742, 3, 0, 4, 2438.529, 1192.707, 148.0759),
+(27742, 4, 0, 0, 2433.154, 1192.572, 148.1547),
+(27742, 4, 0, 1, 2432.087, 1193.326, 148.1593),
+(27742, 4, 0, 2, 2432.926, 1192.781, 148.1593),
+(27742, 4, 0, 3, 2437.091, 1188.969, 148.0759),
+(27742, 4, 0, 4, 2437.091, 1188.969, 148.0759),
+(27742, 5, 0, 0, 2414.349, 1136.075, 148.1592),
+(27742, 5, 0, 1, 2414.383, 1135.073, 148.1593),
+(27742, 5, 0, 2, 2414.348, 1136.073, 148.1593),
+(27742, 5, 0, 3, 2415.398, 1140.661, 148.0758),
+(27742, 5, 0, 4, 2415.398, 1140.661, 148.0758),
+(27742, 6, 0, 0, 2403.961, 1180.299, 148.1587),
+(27742, 6, 0, 1, 2404.736, 1179.674, 148.1587),
+(27742, 6, 0, 2, 2403.959, 1180.304, 148.1587),
+(27742, 6, 0, 3, 2407.341, 1172.870, 148.0755),
+(27742, 6, 0, 4, 2407.341, 1172.870, 148.0755),
+(27742, 7, 0, 0, 2414.671, 1136.262, 148.1592),
+(27742, 7, 0, 1, 2415.404, 1135.578, 148.1593),
+(27742, 7, 0, 2, 2414.673, 1136.260, 148.1593),
+(27742, 7, 0, 3, 2411.154, 1140.153, 148.0757),
+(27742, 7, 0, 4, 2411.154, 1140.153, 148.0757),
+(27742, 8, 0, 0, 2403.908, 1179.994, 148.1586),
+(27742, 8, 0, 1, 2403.891, 1180.996, 148.1587),
+(27742, 8, 0, 2, 2403.908, 1179.996, 148.1587),
+(27742, 8, 0, 3, 2403.444, 1172.043, 148.0753),
+(27742, 8, 0, 4, 2403.444, 1172.043, 148.0753),
+(27742, 9, 0, 0, 2429.026, 1102.693, 148.1499),
+(27742, 9, 0, 1, 2429.742, 1101.104, 148.1593),
+(27742, 9, 0, 2, 2429.303, 1102.002, 148.1593),
+(27742, 9, 0, 3, 2426.836, 1108.146, 148.0759),
+(27742, 9, 0, 4, 2426.836, 1108.146, 148.0759),
+(27742, 10, 0, 0, 2441.173, 1115.225, 148.1264),
+(27742, 10, 0, 1, 2442.718, 1112.450, 148.1593),
+(27742, 10, 0, 2, 2442.771, 1113.448, 148.1593),
+(27742, 10, 0, 3, 2438.715, 1117.960, 148.0759),
+(27742, 10, 0, 4, 2438.027, 1118.726, 148.0759),
+(27742, 10, 0, 5, 2438.027, 1118.726, 148.0759),
+(27742, 11, 0, 0, 2430.645, 1104.685, 148.1306),
+(27742, 11, 0, 1, 2429.549, 1101.521, 148.1593),
+(27742, 11, 0, 2, 2429.636, 1102.517, 148.1593),
+(27742, 11, 0, 3, 2432.575, 1108.833, 148.0759),
+(27742, 11, 0, 4, 2432.575, 1108.833, 148.0759),
+(27742, 12, 0, 0, 2439.649, 1113.719, 148.1298),
+(27742, 12, 0, 1, 2442.992, 1113.372, 148.1593),
+(27742, 12, 0, 2, 2442.031, 1113.648, 148.1593),
+(27742, 12, 0, 3, 2435.285, 1113.849, 148.0759),
+(27742, 12, 0, 4, 2435.285, 1113.849, 148.0759),
+(26499, 101, 0, 0, 2425.898, 1118.842, 148.0759),
+(26499, 101, 0, 1, 2429.949, 1117.980, 148.5604),
+(26499, 101, 0, 2, 2434.449, 1116.980, 148.5604),
+(26499, 101, 0, 3, 2443.699, 1114.980, 148.5604),
+(26499, 101, 0, 4, 2448.199, 1113.980, 148.5604),
+(26499, 101, 0, 5, 2451.000, 1113.117, 149.0450),
+(26499, 101, 1, 0, 2442.638, 1115.024, 148.0759),
+(26499, 101, 1, 1, 2443.851, 1114.990, 148.5444),
+(26499, 101, 1, 2, 2448.351, 1113.990, 148.5444),
+(26499, 101, 1, 3, 2451.101, 1113.490, 149.2944),
+(26499, 101, 1, 4, 2454.351, 1116.990, 150.2944),
+(26499, 101, 1, 5, 2456.064, 1118.955, 150.0128),
+(26499, 101, 2, 0, 2451.617, 1113.829, 149.2187),
+(26499, 101, 2, 1, 2454.655, 1117.209, 150.1194),
+(26499, 101, 2, 2, 2456.405, 1119.209, 150.1194),
+(26499, 101, 2, 3, 2457.155, 1121.959, 150.1194),
+(26499, 101, 2, 4, 2457.905, 1125.959, 150.1194),
+(26499, 101, 2, 5, 2459.655, 1125.959, 150.1194),
+(26499, 101, 2, 6, 2462.692, 1126.088, 150.0201),
+(26499, 101, 3, 0, 2456.778, 1121.774, 150.0144),
+(26499, 101, 3, 1, 2458.201, 1126.067, 150.2717),
+(26499, 101, 3, 2, 2459.701, 1126.067, 150.2717),
+(26499, 101, 3, 3, 2462.701, 1126.067, 150.2717),
+(26499, 101, 3, 4, 2466.451, 1124.317, 150.2717),
+(26499, 101, 3, 5, 2468.624, 1123.360, 150.0291),
+(26499, 128, 0, 0, 2468.624, 1123.360, 150.0291),
+(26499, 128, 0, 1, 2472.084, 1123.195, 150.2172),
+(26499, 128, 0, 2, 2474.334, 1122.945, 150.2172),
+(26499, 128, 0, 3, 2482.584, 1122.945, 149.9672),
+(26499, 128, 0, 4, 2484.045, 1122.531, 149.9052),
+(26499, 128, 1, 0, 2478.336, 1122.838, 149.9668),
+(26499, 128, 1, 1, 2482.680, 1122.492, 150.1883),
+(26499, 128, 1, 2, 2483.930, 1122.492, 150.1883),
+(26499, 128, 1, 3, 2484.430, 1119.742, 150.1883),
+(26499, 128, 1, 4, 2485.523, 1113.646, 149.9099),
+(26499, 128, 2, 0, 2484.691, 1118.652, 149.9061),
+(26499, 128, 2, 1, 2485.738, 1113.734, 150.1313),
+(26499, 128, 2, 2, 2485.988, 1111.734, 150.1313),
+(26499, 128, 2, 3, 2486.488, 1108.234, 148.3813),
+(26499, 128, 2, 4, 2487.238, 1103.734, 145.6313),
+(26499, 128, 2, 5, 2487.738, 1100.484, 145.3813),
+(26499, 128, 2, 6, 2487.785, 1099.816, 144.8566),
+(26499, 128, 3, 0, 2486.230, 1109.323, 148.7373),
+(26499, 128, 3, 1, 2486.708, 1108.068, 148.1735),
+(26499, 128, 3, 2, 2487.458, 1103.568, 145.6735),
+(26499, 128, 3, 3, 2487.958, 1100.568, 145.1735),
+(26499, 128, 3, 4, 2487.958, 1100.068, 145.1735),
+(26499, 128, 3, 5, 2491.458, 1100.818, 145.1735),
+(26499, 128, 3, 6, 2492.958, 1101.068, 144.9235),
+(26499, 128, 3, 7, 2498.185, 1101.812, 144.6096),
+(26499, 128, 4, 0, 2487.662, 1100.566, 144.8941),
+(26499, 128, 4, 1, 2488.134, 1100.141, 144.9309),
+(26499, 128, 4, 2, 2491.134, 1100.641, 144.9309),
+(26499, 128, 4, 3, 2492.884, 1101.141, 144.6809),
+(26499, 128, 4, 4, 2498.134, 1102.141, 144.6809),
+(26499, 128, 4, 5, 2497.884, 1103.141, 144.6809),
+(26499, 128, 4, 6, 2497.384, 1105.891, 144.1809),
+(26499, 128, 4, 7, 2496.134, 1110.891, 143.9309),
+(26499, 128, 4, 8, 2495.134, 1115.891, 143.9309),
+(26499, 128, 4, 9, 2494.384, 1119.641, 142.4309),
+(26499, 128, 4, 10, 2493.134, 1124.641, 140.4309),
+(26499, 128, 4, 11, 2492.605, 1127.216, 139.9677),
+(26499, 128, 5, 0, 2494.477, 1118.697, 142.5221),
+(26499, 128, 5, 1, 2494.635, 1119.844, 142.2594),
+(26499, 128, 5, 2, 2493.385, 1124.594, 140.5094),
+(26499, 128, 5, 3, 2492.885, 1127.094, 140.2594),
+(26499, 128, 5, 4, 2500.794, 1128.992, 139.9966),
+(26499, 128, 6, 0, 2492.862, 1127.271, 139.9686),
+(26499, 128, 6, 1, 2500.889, 1128.872, 140.2229),
+(26499, 128, 6, 2, 2503.416, 1119.473, 139.9773),
+(26499, 128, 7, 0, 2501.195, 1127.536, 139.9936),
+(26499, 128, 7, 1, 2503.719, 1119.759, 140.0309),
+(26499, 128, 7, 2, 2506.469, 1120.259, 140.0309),
+(26499, 128, 7, 3, 2510.969, 1121.009, 136.7809),
+(26499, 128, 7, 4, 2516.469, 1122.009, 133.0309),
+(26499, 128, 7, 5, 2517.743, 1121.981, 132.0681),
+(26499, 128, 8, 0, 2512.749, 1121.107, 135.3008),
+(26499, 128, 8, 1, 2516.539, 1122.018, 132.9387),
+(26499, 128, 8, 2, 2518.039, 1122.268, 132.4387),
+(26499, 128, 8, 3, 2521.539, 1123.768, 132.4387),
+(26499, 128, 8, 4, 2523.830, 1124.929, 132.0767),
+(26499, 1024, 0, 0, 2534.988, 1126.163, 130.8621),
+(26499, 1024, 0, 1, 2539.021, 1128.049, 130.8222),
+(26499, 1024, 0, 2, 2540.271, 1128.549, 131.0722),
+(26499, 1024, 0, 3, 2540.771, 1128.799, 131.0722),
+(26499, 1024, 0, 4, 2543.521, 1130.299, 130.8222),
+(26499, 1024, 0, 5, 2546.771, 1132.299, 130.3222),
+(26499, 1024, 0, 6, 2549.521, 1134.049, 130.0722),
+(26499, 1024, 0, 7, 2552.771, 1136.049, 129.8222),
+(26499, 1024, 0, 8, 2557.554, 1138.935, 128.7824),
+(26499, 1024, 1, 0, 2551.887, 1135.368, 129.6870),
+(26499, 1024, 1, 1, 2553.038, 1136.289, 129.6371),
+(26499, 1024, 1, 2, 2557.788, 1139.289, 128.8871),
+(26499, 1024, 1, 3, 2561.038, 1147.039, 128.3871),
+(26499, 1024, 1, 4, 2564.288, 1153.789, 127.8871),
+(26499, 1024, 1, 5, 2566.688, 1159.210, 127.0872),
+(26499, 1024, 2, 0, 2562.721, 1150.404, 127.8784),
+(26499, 1024, 2, 1, 2564.198, 1153.856, 127.5824),
+(26499, 1024, 2, 2, 2566.698, 1159.356, 127.3324),
+(26499, 1024, 2, 3, 2565.698, 1169.606, 127.0824),
+(26499, 1024, 2, 4, 2564.448, 1180.356, 126.8324),
+(26499, 1024, 2, 5, 2564.175, 1183.308, 126.2864),
+(26499, 1024, 3, 0, 2564.675, 1178.508, 126.4328),
+(26499, 1024, 3, 1, 2564.468, 1180.668, 126.6039),
+(26499, 1024, 3, 2, 2564.218, 1183.668, 126.3539),
+(26499, 1024, 3, 3, 2562.968, 1197.168, 126.1039),
+(26499, 1024, 3, 4, 2562.718, 1199.418, 126.1039),
+(26499, 1024, 3, 5, 2562.261, 1202.828, 125.7751),
+(26499, 1024, 4, 0, 2562.752, 1197.818, 125.9246),
+(26499, 1024, 4, 1, 2562.524, 1199.785, 126.0767),
+(26499, 1024, 4, 2, 2562.274, 1203.035, 125.8267),
+(26499, 1024, 4, 3, 2560.274, 1207.785, 125.8267),
+(26499, 1024, 4, 4, 2556.774, 1217.035, 126.0767),
+(26499, 1024, 4, 5, 2555.774, 1219.285, 125.8267),
+(26499, 1024, 4, 6, 2552.295, 1227.253, 125.7289),
+(26499, 1024, 5, 0, 2556.829, 1216.141, 125.7983),
+(26499, 1024, 5, 1, 2556.463, 1217.164, 126.0613),
+(26499, 1024, 5, 2, 2555.463, 1219.414, 126.0613),
+(26499, 1024, 5, 3, 2552.213, 1227.414, 126.0613),
+(26499, 1024, 5, 4, 2549.213, 1234.164, 126.0613),
+(26499, 1024, 5, 5, 2543.963, 1246.414, 126.3113),
+(26499, 1024, 5, 6, 2543.463, 1247.414, 126.3113),
+(26499, 1024, 5, 7, 2540.597, 1253.188, 126.3242),
+(26499, 1024, 6, 0, 2545.010, 1243.115, 126.0662),
+(26499, 1024, 6, 1, 2543.567, 1246.399, 126.5910),
+(26499, 1024, 6, 2, 2543.067, 1247.899, 126.5910),
+(26499, 1024, 6, 3, 2540.567, 1253.399, 126.8410),
+(26499, 1024, 6, 4, 2538.817, 1257.399, 126.8410),
+(26499, 1024, 6, 5, 2536.067, 1263.649, 127.0910),
+(26499, 1024, 6, 6, 2535.317, 1265.149, 127.0910),
+(26499, 1024, 6, 7, 2534.567, 1267.149, 127.0910),
+(26499, 1024, 6, 8, 2531.067, 1274.399, 127.5910),
+(26499, 1024, 6, 9, 2528.624, 1279.184, 128.1158),
+(26499, 1024, 7, 0, 2533.040, 1269.595, 127.1209),
+(26499, 1024, 7, 1, 2530.740, 1274.671, 127.9136),
+(26499, 1024, 7, 2, 2528.740, 1279.421, 128.4136),
+(26499, 1024, 7, 3, 2527.490, 1282.671, 128.9136),
+(26499, 1024, 7, 4, 2524.490, 1290.671, 130.4136),
+(26499, 1024, 7, 5, 2523.990, 1292.171, 130.6636),
+(26499, 1024, 7, 6, 2521.939, 1297.247, 130.7063),
+(26499, 1024, 8, 0, 2525.589, 1287.386, 129.5040),
+(26499, 1024, 8, 1, 2524.339, 1290.960, 130.4446),
+(26499, 1024, 8, 2, 2523.839, 1292.460, 130.6946),
+(26499, 1024, 8, 3, 2521.839, 1297.460, 130.9446),
+(26499, 1024, 8, 4, 2521.339, 1299.210, 130.9446),
+(26499, 1024, 8, 5, 2518.839, 1307.210, 130.9446),
+(26499, 1024, 8, 6, 2517.089, 1312.460, 130.4446),
+(26499, 1024, 8, 7, 2514.589, 1319.460, 131.6946),
+(26499, 1024, 8, 8, 2513.089, 1323.535, 131.8852),
+(26499, 1025, 0, 0, 2513.089, 1323.535, 131.8852),
+(26499, 1025, 0, 1, 2511.017, 1328.168, 132.1075),
+(26499, 1025, 0, 2, 2508.267, 1334.418, 132.6075),
+(26499, 1025, 0, 3, 2505.767, 1339.918, 133.1075),
+(26499, 1025, 0, 4, 2502.517, 1347.168, 133.1075),
+(26499, 1025, 0, 5, 2499.267, 1353.918, 132.6075),
+(26499, 1025, 0, 6, 2498.945, 1354.302, 132.3298),
+(26499, 1025, 1, 0, 2500.686, 1350.516, 132.6903),
+(26499, 1025, 1, 1, 2499.187, 1354.250, 132.4188),
+(26499, 1025, 1, 2, 2498.937, 1354.500, 132.4188),
+(26499, 1025, 1, 3, 2495.687, 1361.500, 131.4188),
+(26499, 1025, 1, 4, 2492.187, 1369.500, 130.9188),
+(26499, 1025, 1, 5, 2491.687, 1370.750, 130.9188),
+(26499, 1025, 1, 6, 2486.688, 1380.985, 130.1472),
+(26499, 1025, 2, 0, 2492.489, 1368.358, 130.5943),
+(26499, 1025, 2, 1, 2491.867, 1369.797, 130.6554),
+(26499, 1025, 2, 2, 2491.367, 1370.797, 130.6554),
+(26499, 1025, 2, 3, 2486.617, 1381.297, 130.6554),
+(26499, 1025, 2, 4, 2485.867, 1382.297, 130.4054),
+(26499, 1025, 2, 5, 2485.367, 1383.297, 130.6554),
+(26499, 1025, 2, 6, 2479.617, 1392.547, 130.4054),
+(26499, 1025, 2, 7, 2474.117, 1401.297, 130.6554),
+(26499, 1025, 2, 8, 2473.117, 1402.797, 130.9054),
+(26499, 1025, 2, 9, 2472.617, 1403.547, 130.9054),
+(26499, 1025, 2, 10, 2471.245, 1405.236, 130.7164),
+(26499, 1025, 3, 0, 2478.698, 1393.532, 129.9635),
+(26499, 1025, 3, 1, 2473.843, 1401.439, 130.7012),
+(26499, 1025, 3, 2, 2472.843, 1402.939, 130.9512),
+(26499, 1025, 3, 3, 2472.343, 1403.939, 130.7012),
+(26499, 1025, 3, 4, 2471.343, 1405.439, 130.9512),
+(26499, 1025, 3, 5, 2469.343, 1407.439, 130.9512),
+(26499, 1025, 3, 6, 2467.343, 1409.439, 130.9512),
+(26499, 1025, 3, 7, 2466.593, 1410.189, 130.9512),
+(26499, 1025, 3, 8, 2460.343, 1416.439, 130.7012),
+(26499, 1025, 3, 9, 2459.343, 1417.689, 130.7012),
+(26499, 1025, 3, 10, 2455.843, 1420.939, 130.7012),
+(26499, 1025, 3, 11, 2453.593, 1423.439, 130.7012),
+(26499, 1025, 3, 12, 2449.988, 1426.845, 130.9390),
+(26499, 1025, 4, 0, 2453.816, 1422.953, 130.6408),
+(26499, 1025, 4, 1, 2453.290, 1423.434, 130.9224),
+(26499, 1025, 4, 2, 2450.040, 1426.934, 131.1724),
+(26499, 1025, 4, 3, 2441.790, 1424.934, 130.9224),
+(26499, 1025, 4, 4, 2433.790, 1422.934, 130.9224),
+(26499, 1025, 4, 5, 2429.540, 1421.934, 130.9224),
+(26499, 1025, 4, 6, 2424.290, 1420.934, 130.9224),
+(26499, 1025, 4, 7, 2420.263, 1419.915, 130.7039),
+(26499, 1025, 5, 0, 2434.533, 1421.207, 130.5855),
+(26499, 1025, 5, 1, 2424.042, 1420.156, 131.0255),
+(26499, 1025, 5, 2, 2420.292, 1419.906, 130.7755),
+(26499, 1025, 5, 3, 2414.792, 1418.406, 130.7755),
+(26499, 1025, 5, 4, 2413.292, 1418.156, 130.7755),
+(26499, 1025, 5, 5, 2411.042, 1417.406, 130.7755),
+(26499, 1025, 5, 6, 2409.542, 1417.156, 130.7755),
+(26499, 1025, 5, 7, 2407.292, 1416.656, 130.7755),
+(26499, 1025, 5, 8, 2405.292, 1416.156, 130.7755),
+(26499, 1025, 5, 9, 2404.042, 1415.906, 131.0255),
+(26499, 1025, 5, 10, 2402.042, 1415.406, 131.0255),
+(26499, 1025, 5, 11, 2392.542, 1412.906, 129.5255),
+(26499, 1025, 5, 12, 2390.052, 1412.106, 128.9655),
+(26499, 1025, 6, 0, 2396.684, 1413.820, 130.0156),
+(26499, 1025, 6, 1, 2392.062, 1412.613, 129.3716),
+(26499, 1025, 6, 2, 2390.062, 1412.113, 129.3716),
+(26499, 1025, 6, 3, 2384.812, 1410.613, 128.8716),
+(26499, 1025, 6, 4, 2383.312, 1410.363, 128.6216),
+(26499, 1025, 6, 5, 2377.312, 1408.863, 128.3716),
+(26499, 1025, 6, 6, 2373.562, 1407.863, 128.1216),
+(26499, 1025, 6, 7, 2372.312, 1407.613, 128.1216),
+(26499, 1025, 6, 8, 2367.312, 1406.113, 129.1216),
+(26499, 1025, 6, 9, 2363.440, 1404.906, 128.7275),
+(26499, 121, 0, 0, 2363.440, 1404.906, 128.7275),
+(26499, 121, 0, 1, 2358.990, 1405.489, 128.6729),
+(26499, 121, 0, 2, 2348.990, 1406.239, 128.4229),
+(26499, 121, 0, 3, 2340.740, 1406.989, 128.4229),
+(26499, 121, 0, 4, 2339.039, 1407.072, 128.1182),
+(26499, 121, 1, 0, 2345.191, 1406.526, 128.2732),
+(26499, 121, 1, 1, 2340.630, 1407.124, 128.2652),
+(26499, 121, 1, 2, 2339.130, 1407.374, 128.2652),
+(26499, 121, 1, 3, 2333.380, 1409.624, 128.0152),
+(26499, 121, 1, 4, 2331.068, 1410.722, 127.7572),
+(26499, 121, 2, 0, 2335.882, 1408.518, 127.9085),
+(26499, 121, 2, 1, 2333.191, 1409.975, 127.8890),
+(26499, 121, 2, 2, 2331.191, 1410.975, 127.8890),
+(26499, 121, 2, 3, 2330.441, 1412.725, 127.8890),
+(26499, 121, 2, 4, 2328.191, 1417.225, 127.8890),
+(26499, 121, 2, 5, 2325.941, 1421.225, 128.1390),
+(26499, 121, 2, 6, 2325.501, 1421.931, 127.8694),
+(26499, 121, 3, 0, 2329.097, 1414.691, 127.6474),
+(26499, 121, 3, 1, 2327.793, 1417.433, 127.7593),
+(26499, 121, 3, 2, 2325.793, 1421.683, 128.0093),
+(26499, 121, 3, 3, 2325.543, 1422.183, 128.0093),
+(26499, 121, 3, 4, 2320.793, 1432.433, 128.0093),
+(26499, 121, 3, 5, 2318.043, 1438.433, 128.0093),
+(26499, 121, 3, 6, 2313.990, 1446.675, 127.8712),
+(26499, 121, 4, 0, 2316.703, 1440.844, 127.9002),
+(26499, 121, 4, 1, 2314.089, 1446.997, 127.9399),
+(26499, 121, 4, 2, 2312.339, 1449.997, 127.9399),
+(26499, 121, 4, 3, 2308.589, 1457.747, 127.9399),
+(26499, 121, 4, 4, 2307.589, 1460.247, 127.9399),
+(26499, 121, 4, 5, 2305.589, 1463.997, 127.9399),
+(26499, 121, 4, 6, 2303.476, 1467.651, 127.4796),
+(26499, 121, 5, 0, 2308.176, 1458.273, 127.8228),
+(26499, 121, 5, 1, 2307.366, 1460.375, 127.9764),
+(26499, 121, 5, 2, 2305.366, 1464.375, 127.9764),
+(26499, 121, 5, 3, 2303.616, 1467.875, 127.9764),
+(26499, 121, 5, 4, 2303.366, 1469.125, 127.7264),
+(26499, 121, 5, 5, 2301.055, 1478.977, 128.1299),
+(26499, 124, 0, 0, 2301.055, 1478.977, 128.1299),
+(26499, 124, 0, 1, 2300.165, 1482.206, 128.4268),
+(26499, 124, 0, 2, 2297.415, 1493.456, 128.4268),
+(26499, 124, 0, 3, 2294.415, 1504.456, 128.4268),
+(26499, 124, 0, 4, 2293.774, 1505.934, 128.7237),
+(26499, 125, 0, 0, 2293.774, 1505.934, 128.7237),
+(26499, 125, 0, 1, 2294.480, 1504.757, 128.7930),
+(26499, 125, 0, 2, 2297.480, 1494.007, 128.5430),
+(26499, 125, 0, 3, 2299.687, 1487.080, 128.3622),
+(26499, 125, 1, 0, 2299.220, 1488.567, 128.3622),
+(26499, 125, 1, 1, 2299.924, 1487.100, 128.6501),
+(26499, 125, 1, 2, 2301.424, 1482.600, 128.6501),
+(26499, 125, 1, 3, 2305.924, 1470.350, 127.9001),
+(26499, 125, 1, 4, 2306.127, 1469.633, 127.4379),
+(26499, 125, 2, 0, 2305.861, 1470.353, 127.4057),
+(26499, 125, 2, 1, 2306.282, 1469.703, 127.6345),
+(26499, 125, 2, 2, 2306.782, 1468.453, 127.6345),
+(26499, 125, 2, 3, 2309.282, 1460.953, 127.8845),
+(26499, 125, 2, 4, 2309.782, 1459.953, 127.8845),
+(26499, 125, 2, 5, 2312.532, 1451.703, 128.1345),
+(26499, 125, 2, 6, 2312.702, 1451.052, 127.8632),
+(26499, 127, 0, 0, 2312.702, 1451.052, 127.8632),
+(26499, 127, 0, 1, 2317.856, 1438.543, 128.1186),
+(26499, 127, 0, 2, 2320.011, 1433.034, 127.8741),
+(26499, 127, 1, 0, 2318.402, 1436.999, 127.8968),
+(26499, 127, 1, 1, 2320.325, 1432.932, 128.0935),
+(26499, 127, 1, 2, 2323.075, 1420.182, 128.0935),
+(26499, 127, 1, 3, 2323.325, 1418.432, 127.8435),
+(26499, 127, 1, 4, 2324.075, 1415.432, 127.8435),
+(26499, 127, 1, 5, 2324.748, 1411.865, 127.7902),
+(26499, 127, 2, 0, 2324.370, 1413.555, 127.6901),
+(26499, 127, 2, 1, 2324.838, 1411.816, 128.0130),
+(26499, 127, 2, 2, 2324.088, 1409.566, 128.2630),
+(26499, 127, 2, 3, 2322.588, 1404.066, 128.2630),
+(26499, 127, 2, 4, 2322.588, 1402.816, 128.2630),
+(26499, 127, 2, 5, 2320.807, 1396.578, 128.3358),
+(27907, 1, 0, 0, 1670.256, 872.8734, 120.0351),
+(27907, 1, 0, 1, 1671.586, 872.1134, 120.4314),
+(27907, 1, 0, 2, 1672.917, 871.3535, 120.3277),
+(27907, 2, 0, 0, 1672.917, 871.3535, 120.3277),
+(27907, 2, 0, 1, 1667.076, 870.0946, 119.9527),
+(27907, 2, 1, 0, 1669.969, 870.7180, 120.1384),
+(27907, 2, 1, 1, 1667.148, 870.1765, 120.0045),
+(27907, 2, 1, 2, 1662.828, 866.6351, 119.8706),
+(27907, 2, 2, 0, 1664.689, 868.1503, 119.9065),
+(27907, 2, 2, 1, 1662.898, 866.5289, 120.0467),
+(27907, 2, 2, 2, 1658.108, 859.9075, 119.1869),
+(27907, 2, 3, 0, 1659.009, 861.1918, 119.3174),
+(27907, 2, 3, 1, 1658.206, 859.9042, 119.4396),
+(27907, 2, 3, 2, 1653.903, 852.6165, 119.0619),
+(27907, 2, 4, 0, 1655.873, 856.0323, 119.1204),
+(27907, 2, 4, 1, 1654.021, 852.6975, 119.3411),
+(27907, 2, 4, 2, 1648.169, 841.8626, 119.0619),
+(27907, 2, 5, 0, 1650.059, 845.4074, 119.0619),
+(27907, 2, 5, 1, 1648.144, 841.8294, 119.5816),
+(27907, 2, 5, 2, 1644.644, 832.8294, 119.8316),
+(27907, 2, 5, 3, 1641.229, 825.2514, 120.1012),
+(27907, 2, 6, 0, 1642.712, 828.8032, 119.8451),
+(27907, 2, 6, 1, 1641.215, 825.3640, 120.1445),
+(27907, 2, 6, 2, 1638.217, 815.4248, 119.9439),
+(27907, 2, 7, 0, 1638.808, 817.3542, 119.9748),
+(27907, 2, 7, 1, 1638.145, 815.3091, 120.1469),
+(27907, 2, 7, 2, 1633.981, 802.7640, 119.8189),
+(27907, 2, 8, 0, 1635.010, 805.8387, 119.8493),
+(27907, 2, 8, 1, 1633.980, 802.8589, 119.8655),
+(27907, 2, 8, 2, 1630.980, 791.6089, 119.3655),
+(27907, 2, 8, 3, 1628.730, 783.8589, 119.1155),
+(27907, 2, 8, 4, 1627.451, 780.3792, 118.3817),
+(27907, 2, 9, 0, 1628.106, 782.6379, 118.5758),
+(27907, 2, 9, 1, 1627.364, 780.3354, 118.5013),
+(27907, 2, 9, 2, 1626.114, 774.8354, 118.0013),
+(27907, 2, 9, 3, 1625.122, 771.5330, 117.4269),
+(27907, 2, 10, 0, 1625.746, 773.9089, 117.7027),
+(27907, 2, 10, 1, 1625.181, 771.5463, 117.5337),
+(27907, 2, 10, 2, 1623.431, 765.7963, 117.0337),
+(27907, 2, 10, 3, 1621.931, 760.2963, 116.7837),
+(27907, 2, 10, 4, 1620.617, 756.6836, 115.8646),
+(27907, 2, 11, 0, 1621.453, 759.4308, 116.1794),
+(27907, 2, 11, 1, 1620.671, 756.5874, 116.0332),
+(27907, 2, 11, 2, 1619.671, 752.8374, 115.5332),
+(27907, 2, 11, 3, 1618.921, 749.0874, 115.0332),
+(27907, 2, 11, 4, 1617.421, 742.3374, 114.5332),
+(27907, 2, 11, 5, 1616.889, 741.2440, 113.8870),
+(27907, 2, 12, 0, 1617.759, 744.8360, 114.2508),
+(27907, 2, 12, 1, 1617.185, 742.1613, 114.0811),
+(27907, 2, 12, 2, 1616.935, 741.1613, 114.0811),
+(27907, 2, 12, 3, 1615.685, 736.6613, 113.3311),
+(27907, 2, 12, 4, 1614.935, 732.6613, 113.0811),
+(27907, 2, 12, 5, 1614.185, 729.9113, 112.5811),
+(27907, 2, 12, 6, 1613.611, 728.4866, 111.9114),
+(27907, 2, 13, 0, 1614.082, 730.3239, 112.2263),
+(27907, 2, 13, 1, 1613.991, 729.7391, 112.3380),
+(27907, 2, 13, 2, 1613.491, 728.4891, 112.0880),
+(27907, 2, 13, 3, 1612.741, 725.7391, 111.5880),
+(27907, 2, 13, 4, 1611.741, 722.7391, 110.8380),
+(27907, 2, 13, 5, 1610.491, 718.9891, 110.0880),
+(27907, 2, 13, 6, 1609.491, 715.4891, 109.5880),
+(27907, 2, 13, 7, 1608.241, 711.7391, 109.0880),
+(27907, 2, 13, 8, 1606.400, 706.6543, 107.9497),
+(27907, 2, 14, 0, 1607.669, 710.4952, 108.4556),
+(27907, 2, 14, 1, 1606.452, 706.7616, 108.1364),
+(27907, 2, 14, 2, 1604.952, 702.7616, 107.3864),
+(27907, 2, 14, 3, 1603.702, 698.5116, 106.8864),
+(27907, 2, 14, 4, 1602.202, 694.7616, 106.3864),
+(27907, 2, 14, 5, 1601.236, 692.0279, 105.8172),
+(27907, 2, 15, 0, 1601.766, 693.5259, 105.9085),
+(27907, 2, 15, 1, 1601.327, 692.0245, 105.8733),
+(27907, 2, 15, 2, 1600.077, 687.5245, 105.3733),
+(27907, 2, 15, 3, 1598.388, 682.0231, 104.8380),
+(27907, 2, 16, 0, 1599.201, 684.8760, 105.0273),
+(27907, 2, 16, 1, 1598.270, 681.9597, 105.0760),
+(27907, 2, 16, 2, 1596.020, 675.4597, 104.3260),
+(27907, 2, 16, 3, 1593.770, 669.2097, 103.8260),
+(27907, 2, 16, 4, 1592.339, 665.5434, 103.1246),
+(27907, 2, 17, 0, 1593.179, 667.8270, 103.3361),
+(27907, 2, 17, 1, 1592.436, 665.4673, 103.2942),
+(27907, 2, 17, 2, 1588.686, 658.7173, 102.5442),
+(27907, 2, 17, 3, 1586.192, 654.1075, 101.7524),
+(27907, 2, 18, 0, 1587.781, 657.0647, 102.1362),
+(27907, 2, 18, 1, 1586.085, 654.3907, 101.8541),
+(27907, 2, 18, 2, 1583.389, 651.7168, 101.5720),
+(27907, 2, 19, 0, 1586.359, 654.4169, 101.7926),
+(27907, 2, 19, 1, 1586.304, 654.0751, 101.8038),
+(27907, 2, 19, 2, 1583.304, 652.0751, 101.8038),
+(27907, 2, 19, 3, 1577.749, 653.7333, 101.8150),
+(27907, 2, 20, 0, 1581.581, 652.3631, 101.6499),
+(27907, 2, 20, 1, 1577.755, 654.0015, 101.9234),
+(27907, 2, 20, 2, 1571.428, 659.6400, 102.1970),
+(27907, 2, 21, 0, 1574.082, 657.1602, 102.0366),
+(27907, 2, 21, 1, 1571.396, 659.9266, 102.3597),
+(27907, 2, 21, 2, 1564.711, 666.6931, 102.1827),
+(27891, 1, 0, 0, 1605.242, 805.4160, 122.9956),
+(27891, 1, 0, 1, 1604.245, 806.4799, 123.0291),
+(27891, 1, 0, 2, 1604.988, 805.8108, 123.0291),
+(27891, 1, 0, 3, 1608.775, 799.9248, 122.5304),
+(27891, 1, 0, 4, 1609.356, 799.0145, 122.5348),
+(27891, 1, 0, 5, 1609.356, 799.0145, 122.5348),
+(27891, 1, 1, 0, 1608.523, 800.3172, 122.5636),
+(27891, 1, 1, 1, 1609.076, 799.8616, 122.6980),
+(27891, 1, 1, 2, 1609.576, 799.1116, 122.6980),
+(27891, 1, 1, 3, 1612.576, 796.8616, 122.1980),
+(27891, 1, 1, 4, 1613.629, 795.9061, 121.8324),
+(27891, 2, 0, 0, 1613.629, 795.9061, 121.8324),
+(27891, 2, 0, 1, 1619.153, 798.0073, 121.4171),
+(27891, 2, 0, 2, 1622.903, 799.2573, 120.9171),
+(27891, 2, 0, 3, 1623.677, 799.6086, 120.5017),
+(27891, 2, 1, 0, 1621.165, 798.6823, 120.8382),
+(27891, 2, 1, 1, 1622.956, 799.5746, 120.9384),
+(27891, 2, 1, 2, 1623.706, 799.8246, 120.9384),
+(27891, 2, 1, 3, 1624.456, 802.0746, 120.9384),
+(27891, 2, 1, 4, 1624.456, 803.0746, 120.9384),
+(27891, 2, 1, 5, 1623.956, 804.3246, 121.1884),
+(27891, 2, 1, 6, 1624.747, 804.9668, 121.0387),
+(27891, 2, 2, 0, 1624.479, 802.8323, 120.4636),
+(27891, 2, 2, 1, 1624.002, 804.5530, 121.3668),
+(27891, 2, 2, 2, 1624.752, 805.3030, 121.1168),
+(27891, 2, 2, 3, 1623.752, 805.5530, 121.3668),
+(27891, 2, 2, 4, 1623.526, 808.2736, 121.2700),
+(27891, 3, 0, 0, 1623.526, 808.2736, 121.2700),
+(27891, 3, 0, 1, 1626.520, 807.8563, 120.7418),
+(27891, 3, 0, 2, 1628.014, 806.9391, 120.2136),
+(27891, 3, 1, 0, 1626.385, 807.8394, 120.3929),
+(27891, 3, 1, 1, 1628.291, 807.2866, 120.3352),
+(27891, 3, 1, 2, 1630.197, 808.7338, 120.2776),
+(27891, 3, 2, 0, 1628.905, 807.6716, 120.2397),
+(27891, 3, 2, 1, 1630.320, 809.0569, 120.5691),
+(27891, 3, 2, 2, 1630.235, 810.9423, 120.3985),
+(27891, 4, 0, 0, 1630.235, 810.9423, 120.3985),
+(27891, 4, 0, 1, 1637.624, 809.6946, 119.9439),
+(27891, 4, 1, 0, 1633.221, 810.4380, 120.2148),
+(27891, 4, 1, 1, 1637.633, 810.0463, 120.0794),
+(27891, 4, 1, 2, 1641.046, 814.6545, 119.9439),
+(27891, 4, 2, 0, 1638.513, 810.9830, 119.9439),
+(27891, 4, 2, 1, 1641.174, 815.0283, 120.1939),
+(27891, 4, 2, 2, 1643.836, 822.0737, 119.9439),
+(27891, 4, 3, 0, 1642.674, 818.9854, 119.9439),
+(27891, 4, 3, 1, 1644.072, 822.2241, 120.1545),
+(27891, 4, 3, 2, 1645.969, 828.4629, 119.8652),
+(27891, 4, 4, 0, 1644.710, 824.6933, 119.9116),
+(27891, 4, 4, 1, 1646.290, 828.7598, 120.0492),
+(27891, 4, 4, 2, 1650.040, 837.5098, 119.5492),
+(27891, 4, 4, 3, 1650.369, 838.3262, 119.1869),
+(27891, 4, 5, 0, 1649.444, 836.2549, 119.2863),
+(27891, 4, 5, 1, 1650.179, 837.8422, 119.4052),
+(27891, 4, 5, 2, 1650.679, 838.5922, 119.4052),
+(27891, 4, 5, 3, 1655.414, 848.9295, 119.0240),
+(27891, 4, 6, 0, 1654.576, 847.1667, 119.0511),
+(27891, 4, 6, 1, 1655.585, 849.0662, 119.1610),
+(27891, 4, 6, 2, 1660.595, 860.4657, 119.2708),
+(27891, 4, 7, 0, 1659.596, 858.2399, 119.2232),
+(27891, 4, 7, 1, 1660.843, 860.6360, 119.5880),
+(27891, 4, 7, 2, 1666.843, 872.8860, 120.0880),
+(27891, 4, 7, 3, 1667.591, 874.5321, 119.9527),
+(27891, 4, 8, 0, 1666.319, 871.9752, 119.7821),
+(27891, 4, 8, 1, 1667.038, 873.1796, 119.9924),
+(27891, 4, 8, 2, 1667.788, 874.6796, 120.2424),
+(27891, 4, 8, 3, 1673.258, 886.3840, 119.7027),
+(27891, 4, 9, 0, 1671.561, 882.8347, 119.7776),
+(27891, 4, 9, 1, 1673.602, 886.5914, 119.8583),
+(27891, 4, 9, 2, 1679.643, 901.3481, 119.9391),
+(27891, 4, 10, 0, 1678.839, 899.4649, 119.9093),
+(27891, 4, 10, 1, 1679.969, 901.5616, 120.2496),
+(27891, 4, 10, 2, 1683.098, 913.1584, 120.5898),
+(27891, 4, 11, 0, 1682.465, 910.9940, 120.4706),
+(27891, 4, 11, 1, 1683.396, 913.5186, 120.7802),
+(27891, 4, 11, 2, 1685.327, 920.5432, 120.5898),
+(27891, 4, 12, 0, 1684.195, 916.7935, 120.5898),
+(27891, 4, 12, 1, 1685.654, 920.6906, 120.8133),
+(27891, 4, 12, 2, 1689.612, 929.0876, 120.0367),
+(27891, 4, 13, 0, 1687.636, 925.1472, 120.2918),
+(27891, 4, 13, 1, 1689.939, 929.3484, 120.2842),
+(27891, 4, 13, 2, 1693.242, 937.0495, 119.7766),
+(27891, 4, 14, 0, 1691.542, 933.3212, 119.8984),
+(27891, 4, 14, 1, 1693.478, 937.1957, 119.9730),
+(27891, 4, 14, 2, 1697.413, 947.5701, 120.0476),
+(27891, 4, 15, 0, 1696.199, 944.5081, 119.9687),
+(27891, 4, 15, 1, 1697.549, 947.8503, 120.3882),
+(27891, 4, 15, 2, 1700.049, 954.1003, 120.8882),
+(27891, 4, 15, 3, 1701.398, 957.1926, 120.8076),
+(27891, 4, 16, 0, 1700.771, 955.6768, 120.7328),
+(27891, 4, 16, 1, 1701.678, 957.3701, 121.1093),
+(27891, 4, 16, 2, 1702.178, 962.1201, 121.6093),
+(27891, 4, 16, 3, 1703.085, 968.0635, 121.9858),
+(27891, 4, 17, 0, 1702.531, 964.4929, 121.6341),
+(27891, 4, 17, 1, 1703.102, 968.4348, 122.2155),
+(27891, 4, 17, 2, 1699.173, 977.8768, 122.2970),
+(27891, 4, 18, 0, 1699.959, 975.9057, 122.2345),
+(27891, 4, 18, 1, 1699.201, 978.1485, 122.5168),
+(27891, 4, 18, 2, 1692.942, 991.3913, 122.2992),
+(27891, 4, 19, 0, 1693.720, 989.7047, 122.2989),
+(27891, 4, 19, 1, 1692.886, 991.5643, 122.7157),
+(27891, 4, 19, 2, 1688.386, 1000.314, 122.9657),
+(27891, 4, 19, 3, 1687.053, 1002.424, 123.1325),
+(27891, 4, 20, 0, 1688.126, 1000.414, 122.9252),
+(27891, 4, 20, 1, 1686.979, 1002.745, 123.5141),
+(27891, 4, 20, 2, 1685.729, 1008.245, 124.0141),
+(27891, 4, 20, 3, 1684.832, 1010.575, 124.1030),
+(27891, 4, 21, 0, 1685.289, 1008.901, 123.9621),
+(27891, 4, 21, 1, 1684.719, 1010.909, 124.5019),
+(27891, 4, 21, 2, 1683.969, 1017.409, 125.0019),
+(27891, 4, 21, 3, 1683.149, 1020.417, 125.0417),
+(27891, 4, 22, 0, 1683.598, 1017.778, 124.8063),
+(27891, 4, 22, 1, 1683.211, 1020.651, 125.4366),
+(27891, 4, 22, 2, 1682.461, 1025.651, 125.9366),
+(27891, 4, 22, 3, 1681.325, 1035.525, 126.0669),
+(27891, 4, 23, 0, 1681.661, 1032.742, 125.9537),
+(27891, 4, 23, 1, 1681.260, 1035.870, 126.1730),
+(27891, 4, 23, 2, 1680.360, 1054.498, 125.8924),
+(27891, 4, 24, 0, 1680.544, 1050.879, 125.9257),
+(27891, 4, 24, 1, 1680.535, 1054.749, 125.9715),
+(27891, 4, 24, 2, 1680.526, 1066.620, 126.0174),
+(27891, 4, 25, 0, 1680.476, 1062.975, 125.9798),
+(27891, 4, 25, 1, 1680.652, 1066.777, 126.1676),
+(27891, 4, 25, 2, 1681.828, 1078.079, 126.3554),
+(27891, 4, 26, 0, 1681.482, 1075.029, 126.2654),
+(27891, 4, 26, 1, 1682.196, 1078.414, 126.6603),
+(27891, 4, 26, 2, 1683.446, 1087.914, 127.1603),
+(27891, 4, 26, 3, 1683.910, 1090.798, 127.0551),
+(27891, 4, 27, 0, 1683.277, 1086.956, 126.8661),
+(27891, 4, 27, 1, 1683.617, 1088.229, 127.3948),
+(27891, 4, 27, 2, 1684.117, 1090.979, 127.3948),
+(27891, 4, 27, 3, 1687.117, 1094.729, 127.8948),
+(27891, 4, 27, 4, 1688.957, 1097.002, 128.4234),
+(27891, 4, 28, 0, 1687.148, 1094.779, 127.8260),
+(27891, 4, 28, 1, 1689.088, 1097.265, 128.7533),
+(27891, 4, 28, 2, 1692.588, 1099.265, 129.2533),
+(27891, 4, 28, 3, 1694.088, 1100.265, 129.7533),
+(27891, 4, 28, 4, 1697.338, 1102.265, 130.5033),
+(27891, 4, 28, 5, 1699.528, 1103.752, 130.6805),
+(27891, 4, 29, 0, 1696.527, 1101.835, 130.2339),
+(27891, 4, 29, 1, 1697.750, 1102.589, 130.8327),
+(27891, 4, 29, 2, 1699.750, 1104.089, 131.0827),
+(27891, 4, 29, 3, 1702.500, 1105.589, 132.0827),
+(27891, 4, 29, 4, 1705.500, 1107.339, 132.5827),
+(27891, 4, 29, 5, 1707.250, 1108.339, 133.0827),
+(27891, 4, 29, 6, 1710.000, 1109.839, 133.8327),
+(27891, 4, 29, 7, 1710.973, 1110.343, 133.9314),
+(27891, 4, 30, 0, 1709.266, 1109.362, 133.3899),
+(27891, 4, 30, 1, 1710.148, 1109.964, 133.9583),
+(27891, 4, 30, 2, 1711.148, 1110.714, 134.4583),
+(27891, 4, 30, 3, 1713.148, 1111.464, 134.9583),
+(27891, 4, 30, 4, 1714.898, 1112.214, 135.4583),
+(27891, 4, 30, 5, 1717.398, 1113.464, 135.9583),
+(27891, 4, 30, 6, 1719.148, 1114.214, 136.7083),
+(27891, 4, 30, 7, 1720.898, 1114.964, 137.2083),
+(27891, 4, 30, 8, 1723.031, 1116.066, 137.5268),
+(27891, 4, 31, 0, 1719.710, 1114.490, 136.6331),
+(27891, 4, 31, 1, 1721.044, 1115.318, 137.4891),
+(27891, 4, 31, 2, 1723.294, 1116.318, 137.9891),
+(27891, 4, 31, 3, 1725.794, 1117.818, 138.7391),
+(27891, 4, 31, 4, 1727.294, 1118.568, 138.9891),
+(27891, 4, 31, 5, 1730.044, 1120.068, 139.7391),
+(27891, 4, 31, 6, 1731.544, 1121.068, 140.2391),
+(27891, 4, 31, 7, 1733.379, 1122.147, 140.8451),
+(27892, 1, 0, 0, 1601.366, 805.0612, 123.7103),
+(27892, 1, 0, 1, 1600.004, 806.3074, 123.8376),
+(27892, 1, 0, 2, 1600.781, 805.6780, 123.8376),
+(27892, 1, 0, 3, 1604.224, 802.0498, 123.0886),
+(27892, 1, 0, 4, 1606.311, 799.8455, 122.8354),
+(27892, 1, 0, 5, 1606.311, 799.8455, 122.8354),
+(27892, 1, 1, 0, 1604.806, 801.4352, 123.0180),
+(27892, 1, 1, 1, 1606.652, 799.8110, 122.9106),
+(27892, 1, 1, 2, 1609.497, 797.1868, 122.3031),
+(27892, 1, 2, 0, 1606.937, 799.3236, 122.7309),
+(27892, 1, 2, 1, 1609.646, 797.1644, 122.5922),
+(27892, 1, 2, 2, 1612.855, 794.5053, 121.9534),
+(27892, 1, 3, 0, 1611.604, 795.5046, 122.0837),
+(27892, 1, 3, 1, 1613.088, 794.5215, 122.1889),
+(27892, 1, 3, 2, 1617.072, 793.0383, 121.2942),
+(27892, 1, 4, 0, 1614.179, 794.0447, 121.7464),
+(27892, 1, 4, 1, 1617.402, 793.2491, 121.4646),
+(27892, 1, 4, 2, 1621.126, 794.4536, 120.6827),
+(27892, 1, 5, 0, 1616.998, 793.0639, 121.3057),
+(27892, 1, 5, 1, 1621.170, 794.7802, 120.8156),
+(27892, 1, 5, 2, 1624.841, 798.4964, 120.3256),
+(27892, 1, 6, 0, 1622.230, 795.6549, 120.5766),
+(27892, 1, 6, 1, 1624.831, 798.3754, 120.3729),
+(27892, 1, 6, 2, 1626.933, 801.0958, 120.1692),
+(27892, 1, 7, 0, 1624.277, 797.8823, 120.3798),
+(27892, 1, 7, 1, 1624.999, 798.7412, 120.5467),
+(27892, 1, 7, 2, 1626.999, 801.2412, 120.2967),
+(27892, 1, 7, 3, 1628.722, 805.1000, 120.2136),
+(27892, 2, 0, 0, 1628.722, 805.1000, 120.2136),
+(27892, 2, 0, 1, 1629.004, 810.1380, 120.4927),
+(27884, 1, 0, 0, 1639.946, 725.7776, 113.5619),
+(27884, 1, 0, 1, 1637.886, 725.7106, 113.8119),
+(27884, 1, 0, 2, 1636.136, 725.7106, 113.8119),
+(27884, 1, 0, 3, 1635.827, 723.1434, 113.5619),
+(27884, 2, 0, 0, 1635.827, 723.0861, 113.6452),
+(27884, 2, 0, 1, 1636.886, 725.6819, 113.8536),
+(27884, 2, 0, 2, 1639.946, 725.7776, 113.5619),
+(27885, 70, 0, 0, 1602.132, 743.8040, 114.7303),
+(27885, 70, 0, 1, 1605.358, 744.0162, 114.9277),
+(27885, 70, 0, 2, 1611.608, 744.7662, 114.9277),
+(27885, 70, 0, 3, 1612.858, 744.7662, 114.9277),
+(27885, 70, 0, 4, 1614.108, 744.2662, 114.4277),
+(27885, 70, 0, 5, 1614.583, 743.2285, 114.1251),
+(27885, 70, 1, 0, 1611.180, 744.6971, 114.7383),
+(27885, 70, 1, 1, 1613.148, 744.7632, 114.8577),
+(27885, 70, 1, 2, 1614.398, 744.2632, 114.3577),
+(27885, 70, 1, 3, 1614.648, 743.2632, 114.3577),
+(27885, 70, 1, 4, 1617.615, 737.8293, 113.4772),
+(27885, 70, 2, 0, 1616.893, 739.1165, 113.6317),
+(27885, 70, 2, 1, 1617.805, 737.9444, 113.7083),
+(27885, 70, 2, 2, 1619.805, 734.4444, 112.9583),
+(27885, 70, 2, 3, 1622.555, 729.4444, 112.7083),
+(27885, 70, 2, 4, 1623.717, 727.2723, 112.2850),
+(27885, 70, 3, 0, 1622.905, 728.6694, 112.3143),
+(27885, 70, 3, 1, 1623.866, 727.3546, 112.4240),
+(27885, 70, 3, 2, 1628.827, 726.0397, 112.5336),
+(27885, 70, 4, 0, 1625.025, 726.9567, 112.3486),
+(27885, 70, 4, 1, 1629.196, 726.4058, 112.9477),
+(27885, 70, 4, 2, 1631.196, 726.6558, 112.9477),
+(27885, 70, 4, 3, 1632.196, 726.6558, 113.4477),
+(27885, 70, 4, 4, 1633.366, 726.3549, 113.5467),
+(27885, 71, 0, 0, 1633.366, 726.3549, 113.5467),
+(27885, 71, 0, 1, 1632.387, 726.9871, 113.6156),
+(27885, 71, 0, 2, 1630.887, 727.7371, 113.1156),
+(27885, 71, 0, 3, 1631.387, 727.9871, 113.3656),
+(27885, 71, 0, 4, 1630.887, 727.7371, 113.1156),
+(27885, 71, 0, 5, 1629.887, 728.2371, 113.1156),
+(27885, 71, 0, 6, 1631.387, 729.4871, 113.8656),
+(27885, 71, 0, 7, 1631.637, 730.4871, 113.8656),
+(27885, 71, 0, 8, 1630.407, 730.1193, 113.6845),
+(27885, 72, 0, 0, 1630.407, 730.1193, 113.6845),
+(27885, 72, 0, 1, 1630.917, 730.2725, 113.9209),
+(27885, 72, 0, 2, 1629.667, 728.5225, 112.9209),
+(27885, 72, 0, 3, 1624.917, 727.0225, 112.4209),
+(27885, 72, 0, 4, 1620.917, 725.0225, 111.9209),
+(27885, 72, 0, 5, 1618.417, 722.0225, 111.4209),
+(27885, 72, 0, 6, 1616.167, 718.7725, 110.6709),
+(27885, 72, 0, 7, 1613.928, 715.9256, 109.6573),
+(27885, 72, 1, 0, 1623.199, 726.2747, 112.1131),
+(27885, 72, 1, 1, 1620.688, 725.0859, 112.0865),
+(27885, 72, 1, 2, 1618.188, 721.8359, 111.0865),
+(27885, 72, 1, 3, 1615.938, 718.5859, 110.3365),
+(27885, 72, 1, 4, 1614.188, 715.8359, 109.8365),
+(27885, 72, 1, 5, 1612.938, 713.3359, 109.5865),
+(27885, 72, 1, 6, 1611.188, 708.8359, 109.0865),
+(27885, 72, 1, 7, 1609.688, 705.0859, 108.3365),
+(27885, 72, 1, 8, 1608.688, 702.3359, 107.8365),
+(27885, 72, 1, 9, 1607.678, 700.3972, 107.0600),
+(27885, 72, 2, 0, 1612.112, 711.4092, 108.9662),
+(27885, 72, 2, 1, 1611.035, 708.5569, 108.6749),
+(27885, 72, 2, 2, 1609.535, 704.8069, 108.1749),
+(27885, 72, 2, 3, 1608.285, 702.0569, 107.4249),
+(27885, 72, 2, 4, 1607.785, 700.3069, 107.1749),
+(27885, 72, 2, 5, 1606.535, 696.8069, 106.9249),
+(27885, 72, 2, 6, 1604.285, 691.3069, 106.1749),
+(27885, 72, 2, 7, 1601.958, 685.7047, 105.3837),
+(27885, 72, 3, 0, 1605.050, 693.6397, 106.1223),
+(27885, 72, 3, 1, 1604.178, 691.2042, 105.9571),
+(27885, 72, 3, 2, 1601.928, 685.7042, 105.4571),
+(27885, 72, 3, 3, 1599.928, 680.4542, 104.9571),
+(27885, 72, 3, 4, 1597.928, 674.7042, 104.7071),
+(27885, 72, 3, 5, 1596.307, 671.2687, 103.7920),
+(27885, 72, 4, 0, 1598.042, 675.6906, 104.3130),
+(27885, 72, 4, 1, 1597.688, 674.4025, 104.3032),
+(27885, 72, 4, 2, 1596.188, 671.1525, 104.0532),
+(27885, 72, 4, 3, 1594.188, 665.9025, 103.3032),
+(27885, 72, 4, 4, 1592.188, 661.4025, 103.0532),
+(27885, 72, 4, 5, 1590.834, 658.6144, 102.2933),
+(27885, 72, 5, 0, 1594.380, 666.8188, 103.3112),
+(27885, 72, 5, 1, 1593.886, 665.8480, 103.3166),
+(27885, 72, 5, 2, 1591.886, 661.0980, 102.8166),
+(27885, 72, 5, 3, 1590.886, 658.5980, 102.5666),
+(27885, 72, 5, 4, 1588.636, 653.3480, 102.0666),
+(27885, 72, 5, 5, 1586.136, 647.8480, 101.5666),
+(27885, 72, 5, 6, 1583.393, 641.8773, 100.8220),
+(27885, 72, 6, 0, 1586.642, 649.1833, 101.2471),
+(27885, 72, 6, 1, 1585.855, 647.6183, 101.1272),
+(27885, 72, 6, 2, 1583.355, 641.8683, 100.8772),
+(27885, 72, 6, 3, 1578.605, 629.1183, 100.6272),
+(27885, 72, 6, 4, 1577.569, 626.5533, 100.0073),
+(27885, 72, 7, 0, 1579.374, 631.3001, 100.2685),
+(27885, 72, 7, 1, 1578.524, 628.7549, 100.2654),
+(27885, 72, 7, 2, 1577.524, 626.5049, 100.2654),
+(27885, 72, 7, 3, 1577.024, 625.0049, 100.0154),
+(27885, 72, 7, 4, 1575.274, 620.5049, 100.0154),
+(27885, 72, 7, 5, 1575.024, 619.7549, 100.0154),
+(27885, 72, 7, 6, 1574.774, 619.0049, 100.0154),
+(27885, 72, 7, 7, 1572.675, 613.7097, 99.76225),
+(27885, 72, 8, 0, 1575.843, 622.2479, 99.65166),
+(27885, 72, 8, 1, 1574.988, 620.0990, 99.71298),
+(27885, 72, 8, 2, 1574.738, 619.5990, 99.96298),
+(27885, 72, 8, 3, 1574.488, 618.8490, 99.96298),
+(27885, 72, 8, 4, 1572.738, 613.8490, 99.96298),
+(27885, 72, 8, 5, 1569.633, 609.4501, 99.77429),
+(27885, 72, 9, 0, 1572.403, 613.3293, 99.76333),
+(27885, 72, 9, 1, 1569.547, 609.7275, 100.0184),
+(27885, 72, 9, 2, 1565.190, 611.6257, 99.77345),
+(27885, 1, 0, 0, 1603.050, 747.9994, 114.7605),
+(27885, 1, 0, 1, 1604.049, 750.7614, 114.8151),
+(27885, 1, 0, 2, 1603.475, 749.9422, 114.8151),
+(27885, 1, 0, 3, 1602.821, 746.9496, 114.7310),
+(27885, 1, 0, 4, 1602.132, 743.8040, 114.7303),
+(27885, 1, 0, 5, 1602.132, 743.8040, 114.7303),
+(27885, 2, 0, 0, 1602.132, 743.8040, 114.7303),
+(27885, 2, 0, 1, 1602.813, 747.0300, 114.9824),
+(27885, 2, 0, 2, 1603.493, 749.7560, 114.7345),
+(27885, 3, 0, 0, 1603.493, 749.7560, 114.7345),
+(27885, 3, 0, 1, 1602.813, 747.0300, 114.9824),
+(27885, 3, 0, 2, 1602.132, 743.8040, 114.7303),
+(27877, 1, 0, 0, 1561.571, 670.3199, 102.1444),
+(27877, 1, 0, 1, 1565.856, 668.4106, 102.1827),
+(27877, 1, 1, 0, 1564.340, 669.0860, 102.1692),
+(27877, 1, 1, 1, 1566.094, 668.7725, 102.5262),
+(27877, 1, 1, 2, 1566.594, 668.0225, 102.5262),
+(27877, 1, 1, 3, 1568.348, 669.4590, 102.8832),
+(27877, 2, 0, 0, 1568.348, 669.4590, 102.8832),
+(27877, 2, 0, 1, 1570.132, 667.8282, 102.5401),
+(27877, 2, 0, 2, 1570.132, 666.5782, 102.5401),
+(27877, 2, 0, 3, 1573.416, 658.6976, 102.1970),
+(27877, 2, 1, 0, 1572.105, 661.5780, 102.1970),
+(27877, 2, 1, 1, 1573.661, 658.8035, 102.3220),
+(27877, 2, 1, 2, 1579.911, 652.5535, 101.8220),
+(27877, 2, 1, 3, 1580.717, 651.5290, 101.4470),
+(27877, 2, 2, 0, 1577.634, 654.5538, 101.7866),
+(27877, 2, 2, 1, 1580.112, 652.4617, 101.8577),
+(27877, 2, 2, 2, 1580.862, 651.7117, 101.6077),
+(27877, 2, 2, 3, 1588.590, 650.3696, 101.4288),
+(27877, 2, 3, 0, 1585.335, 650.8489, 101.4363),
+(27877, 2, 3, 1, 1588.816, 650.5333, 101.8634),
+(27877, 2, 3, 2, 1591.066, 656.0333, 102.3634),
+(27877, 2, 3, 3, 1593.566, 661.2833, 102.8634),
+(27877, 2, 3, 4, 1593.797, 661.7178, 102.7905),
+(27877, 2, 4, 0, 1592.303, 658.4574, 102.3747),
+(27877, 2, 4, 1, 1593.883, 661.4075, 103.1464),
+(27877, 2, 4, 2, 1594.133, 661.9075, 103.1464),
+(27877, 2, 4, 3, 1596.383, 667.1575, 103.6464),
+(27877, 2, 4, 4, 1598.633, 671.6575, 104.1464),
+(27877, 2, 4, 5, 1599.962, 674.3575, 104.4181),
+(27877, 2, 5, 0, 1598.789, 671.9459, 104.1030),
+(27877, 2, 5, 1, 1600.133, 674.5853, 104.7467),
+(27877, 2, 5, 2, 1601.883, 678.0853, 105.2467),
+(27877, 2, 5, 3, 1604.383, 683.3353, 105.7467),
+(27877, 2, 5, 4, 1606.477, 687.7247, 105.8904),
+(27877, 2, 6, 0, 1605.371, 685.4503, 105.7326),
+(27877, 2, 6, 1, 1606.650, 687.9642, 106.2105),
+(27877, 2, 6, 2, 1608.900, 693.2142, 106.7105),
+(27877, 2, 6, 3, 1610.900, 697.9642, 107.4605),
+(27877, 2, 6, 4, 1611.928, 700.4782, 107.6884),
+(27903, 1, 0, 0, 1588.942, 597.9799, 99.37262),
+(27903, 1, 0, 1, 1589.883, 608.7765, 99.63657),
+(27903, 1, 1, 0, 1589.730, 607.0264, 99.59379),
+(27903, 1, 1, 1, 1589.919, 609.1281, 99.74018),
+(27903, 1, 1, 2, 1588.607, 616.2296, 99.88657),
+(27903, 1, 2, 0, 1589.159, 613.0059, 99.77844),
+(27903, 1, 2, 1, 1588.610, 616.4816, 100.1237),
+(27903, 1, 2, 2, 1586.060, 619.9573, 99.96897),
+(27903, 1, 3, 0, 1587.032, 618.5356, 99.93755),
+(27903, 1, 3, 1, 1586.021, 620.1125, 100.2397),
+(27903, 1, 3, 2, 1580.011, 623.6895, 100.0418),
+(27903, 2, 0, 0, 1580.011, 623.6895, 100.0418),
+(27903, 2, 0, 1, 1576.298, 620.4587, 99.65415),
+(27903, 3, 0, 0, 1576.298, 620.4587, 99.65415),
+(27903, 3, 0, 1, 1579.411, 622.9457, 99.83286),
+(27903, 3, 0, 2, 1583.411, 622.9457, 100.0829),
+(27903, 3, 0, 3, 1586.523, 620.9327, 100.0116),
+(27903, 3, 1, 0, 1584.299, 622.3154, 100.0116),
+(27903, 3, 1, 1, 1586.711, 620.8452, 100.1366),
+(27903, 3, 1, 2, 1589.123, 612.8749, 99.76157),
+(27903, 3, 2, 0, 1588.503, 614.7979, 99.82124),
+(27903, 3, 2, 1, 1589.286, 612.9751, 99.91640),
+(27903, 3, 2, 2, 1591.070, 601.6522, 99.51157),
+(27903, 3, 3, 0, 1590.331, 605.9120, 99.60647),
+(27903, 3, 3, 1, 1591.018, 601.7597, 99.71784),
+(27903, 3, 3, 2, 1590.768, 600.0097, 99.71784),
+(27903, 3, 3, 3, 1590.768, 598.2597, 99.46784),
+(27903, 3, 3, 4, 1591.268, 596.0097, 99.46784),
+(27903, 3, 3, 5, 1591.268, 595.0097, 99.46784),
+(27903, 3, 3, 6, 1591.268, 594.0097, 99.46784),
+(27903, 3, 3, 7, 1591.268, 593.0097, 99.46784),
+(27903, 3, 3, 8, 1591.705, 591.6074, 99.32922);
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp
index d33eeef1829..a5f3f588c0c 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp
@@ -15,41 +15,39 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Script Data Start
-SDName: Boss epoch
-SDAuthor: Tartalo
-SD%Complete: 80
-SDComment: @todo Intro, consecutive attacks to a random target durin time wrap, adjust timers
-SDCategory:
-Script Data End */
-
-#include "ScriptMgr.h"
#include "culling_of_stratholme.h"
+#include "InstanceScript.h"
+#include "ObjectAccessor.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellInfo.h"
+#include <vector>
enum Spells
{
- SPELL_CURSE_OF_EXERTION = 52772,
- SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec.
- SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec.
- SPELL_WOUNDING_STRIKE = 52771 //Used only on the tank
+ SPELL_CURSE_OF_EXERTION = 52772,
+ SPELL_TIME_WARP = 52766,
+ SPELL_TIME_STOP = 58848,
+ SPELL_TIME_STEP_DUMMY = 52736,
};
+#define SPELL_TIME_STEP_CHARGE DUNGEON_MODE(52737,58829)
+#define SPELL_WOUNDING_STRIKE DUNGEON_MODE(52771,58830)
+
enum Yells
{
- SAY_INTRO = 0,
- SAY_AGGRO = 1,
- SAY_TIME_WARP = 2,
- SAY_SLAY = 3,
- SAY_DEATH = 4
+ SAY_TIME_WARP = 2,
+ SAY_SLAY = 3,
+ SAY_DEATH = 4
};
enum Events
{
- EVENT_CURSE_OF_EXERTION = 1,
+ EVENT_CURSE_OF_EXERTION = 1,
EVENT_TIME_WARP,
EVENT_TIME_STOP,
- EVENT_WOUNDING_STRIKE
+ EVENT_WOUNDING_STRIKE,
+ EVENT_TIME_STEP
};
class boss_epoch : public CreatureScript
@@ -59,17 +57,25 @@ class boss_epoch : public CreatureScript
struct boss_epochAI : public BossAI
{
- boss_epochAI(Creature* creature) : BossAI(creature, DATA_EPOCH) { }
+ boss_epochAI(Creature* creature) : BossAI(creature, DATA_EPOCH), _stepTargetIndex(0) { }
+
+ void InitializeAI() override
+ {
+ if (instance->GetBossState(DATA_EPOCH) == DONE)
+ me->RemoveLootMode(LOOT_MODE_DEFAULT);
+ }
void JustEngagedWith(Unit* /*who*/) override
{
- Talk(SAY_AGGRO);
_JustEngagedWith();
- events.ScheduleEvent(EVENT_CURSE_OF_EXERTION, 9300ms);
- events.ScheduleEvent(EVENT_TIME_WARP, 25300);
- events.ScheduleEvent(EVENT_TIME_STOP, 21300);
- events.ScheduleEvent(EVENT_WOUNDING_STRIKE, 5300ms);
+ _stepTargetIndex = 0;
+ _stepTargets.clear();
+ events.ScheduleEvent(EVENT_WOUNDING_STRIKE, Seconds(4), Seconds(6));
+ events.ScheduleEvent(EVENT_CURSE_OF_EXERTION, Seconds(10), Seconds(17));
+ events.ScheduleEvent(EVENT_TIME_WARP, Seconds(25));
+ if (IsHeroic())
+ events.ScheduleEvent(EVENT_TIME_STOP, Seconds(15));
}
void ExecuteEvent(uint32 eventId) override
@@ -79,26 +85,59 @@ class boss_epoch : public CreatureScript
case EVENT_CURSE_OF_EXERTION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
DoCast(target, SPELL_CURSE_OF_EXERTION);
- events.ScheduleEvent(EVENT_CURSE_OF_EXERTION, 9300ms);
+ events.ScheduleEvent(EVENT_CURSE_OF_EXERTION, 9300);
break;
case EVENT_TIME_WARP:
Talk(SAY_TIME_WARP);
DoCastAOE(SPELL_TIME_WARP);
- events.ScheduleEvent(EVENT_TIME_WARP, 25300);
+ DoCastAOE(SPELL_TIME_STEP_DUMMY);
+ events.Repeat(Seconds(25));
break;
case EVENT_TIME_STOP:
DoCastAOE(SPELL_TIME_STOP);
- events.ScheduleEvent(EVENT_TIME_STOP, 21300);
+ events.Repeat(Seconds(25));
break;
case EVENT_WOUNDING_STRIKE:
DoCastVictim(SPELL_WOUNDING_STRIKE);
- events.ScheduleEvent(EVENT_WOUNDING_STRIKE, 5300ms);
+ events.Repeat(Seconds(12), Seconds(18));
break;
+ case EVENT_TIME_STEP:
+ {
+ // In each step, we charge to a random target that was previously hit by SPELL_TIME_STEP_DUMMY
+ // Once we run out of targets, we charge back to the tank, then stop
+ uint32 nTargets = _stepTargets.size();
+ Unit* target = nullptr;
+ while (nTargets > _stepTargetIndex)
+ {
+ uint32 selected = urand(_stepTargetIndex, nTargets - 1);
+ if (_stepTargetIndex != selected)
+ std::swap(_stepTargets[_stepTargetIndex], _stepTargets[selected]);
+ if ((target = ObjectAccessor::GetUnit(*me, _stepTargets[_stepTargetIndex++])))
+ break;
+ }
+ if (target)
+ events.Repeat(Milliseconds(500));
+ else
+ target = me->GetVictim();
+
+ if (target)
+ DoCast(target, SPELL_TIME_STEP_CHARGE, true);
+ break;
+ }
default:
break;
}
}
+ void SpellHitTarget(Unit* target, SpellInfo const* info) override
+ {
+ if (info->Id == SPELL_TIME_STEP_DUMMY && me->IsHostileTo(target))
+ {
+ _stepTargets.push_back(target->GetGUID());
+ events.RescheduleEvent(EVENT_TIME_STEP, Milliseconds(500));
+ }
+ }
+
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
@@ -110,6 +149,10 @@ class boss_epoch : public CreatureScript
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
+
+ private:
+ uint32 _stepTargetIndex;
+ std::vector<ObjectGuid> _stepTargets;
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp
index a476483a96b..b797b3e9967 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp
@@ -15,31 +15,45 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
#include "culling_of_stratholme.h"
+#include "InstanceScript.h"
+#include "MotionMaster.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellInfo.h"
enum Spells
{
- SPELL_CORRUPTING_BLIGHT = 60588,
- SPELL_VOID_STRIKE = 60590,
- SPELL_CORRUPTION_OF_TIME_CHANNEL = 60422,
- SPELL_CORRUPTION_OF_TIME_TARGET = 60451
+ SPELL_CORRUPTING_BLIGHT = 60588,
+ SPELL_VOID_STRIKE = 60590,
+ SPELL_CORRUPTION_OF_TIME_CHANNEL = 60422,
+ SPELL_CORRUPTION_OF_TIME_TARGET = 60451
};
enum Yells
{
- SAY_AGGRO = 0,
- SAY_DEATH = 1,
- SAY_FAIL = 2
+ SAY_AGGRO = 0,
+ SAY_DEATH = 1,
+ SAY_FAIL = 2
};
enum Events
{
- EVENT_CORRUPTING_BLIGHT = 1,
+ EVENT_CORRUPTING_BLIGHT = 1,
EVENT_VOID_STRIKE
};
+enum Entries
+{
+ NPC_TIME_RIFT = 28409,
+ NPC_GUARDIAN_OF_TIME = 32281
+};
+
+enum Misc
+{
+ MOVEMENT_TIME_RIFT = 1
+};
+
class boss_infinite_corruptor : public CreatureScript
{
public:
@@ -47,17 +61,18 @@ class boss_infinite_corruptor : public CreatureScript
struct boss_infinite_corruptorAI : public BossAI
{
- boss_infinite_corruptorAI(Creature* creature) : BossAI(creature, DATA_INFINITE) { }
+ boss_infinite_corruptorAI(Creature* creature) : BossAI(creature, DATA_INFINITE_CORRUPTOR) { }
void Reset() override
{
_Reset();
+ DoCastAOE(SPELL_CORRUPTION_OF_TIME_CHANNEL); // implicitly targets the Guardian
+ }
- if (Creature* guardian = me->FindNearestCreature(NPC_GUARDIAN_OF_TIME, 100.0f))
- {
- DoCast(nullptr, SPELL_CORRUPTION_OF_TIME_CHANNEL, false);
- guardian->CastSpell(guardian, SPELL_CORRUPTION_OF_TIME_TARGET, false);
- }
+ void SpellHitTarget(Unit* target, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_CORRUPTION_OF_TIME_CHANNEL)
+ target->CastSpell(target, SPELL_CORRUPTION_OF_TIME_TARGET, true);
}
void JustEngagedWith(Unit* /*who*/) override
@@ -100,6 +115,40 @@ class boss_infinite_corruptor : public CreatureScript
break;
}
}
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+ BossAI::EnterEvadeMode(why);
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == POINT_MOTION_TYPE && id == MOVEMENT_TIME_RIFT)
+ {
+ me->DespawnOrUnsummon(Seconds(2));
+ instance->SetBossState(DATA_INFINITE_CORRUPTOR, FAIL);
+ }
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action == -ACTION_CORRUPTOR_LEAVE)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ Talk(SAY_FAIL);
+ if (Creature* rift = me->FindNearestCreature(NPC_TIME_RIFT, 300.0f))
+ {
+ if (me->IsWithinDist2d(rift, 5.0f))
+ MovementInform(POINT_MOTION_TYPE, MOVEMENT_TIME_RIFT);
+ else
+ me->GetMotionMaster()->MovePoint(MOVEMENT_TIME_RIFT, rift->GetPosition()); // @todo offset
+ }
+ else
+ MovementInform(POINT_MOTION_TYPE, MOVEMENT_TIME_RIFT);
+ }
+ }
};
CreatureAI* GetAI(Creature* creature) const override
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp
index f6a95960beb..41f4a865389 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp
@@ -15,238 +15,181 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Script Data Start
-SDName: Boss mal_ganis
-SDAuthor: Tartalo
-SD%Complete: 80
-SDComment: @todo Intro & outro
-SDCategory:
-Script Data End */
-
-#include "ScriptMgr.h"
#include "culling_of_stratholme.h"
#include "InstanceScript.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
+#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellMgr.h"
enum Spells
{
- SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec.
- SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy.
- SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target.
- SPELL_VAMPIRIC_TOUCH = 52723, //Heals the caster for half the damage dealt by a melee attack.
- SPELL_MAL_GANIS_KILL_CREDIT = 58124, // Quest credit
- SPELL_KILL_CREDIT = 58630 // Non-existing spell as encounter credit, created in spell_dbc
+ SPELL_VAMPIRIC_TOUCH = 52723
};
+#define SPELL_CARRION_SWARM DUNGEON_MODE(52720,58852)
+#define SPELL_MIND_BLAST DUNGEON_MODE(52722,58850)
+#define SPELL_SLEEP DUNGEON_MODE(52721,58849)
+
enum Yells
{
- SAY_AGGRO = 2,
- SAY_KILL = 3,
- SAY_SLAY = 4,
- SAY_SLEEP = 5,
- SAY_30HEALTH = 6,
- SAY_15HEALTH = 7,
- SAY_ESCAPE_SPEECH_1 = 8,
- SAY_ESCAPE_SPEECH_2 = 9,
- SAY_OUTRO = 10
+ SAY_KILL = 3,
+ SAY_SLAY = 4,
+ SAY_SLEEP = 5,
+ SAY_30HEALTH = 6,
+ SAY_15HEALTH = 7
};
-enum CombatPhases
+enum Events
{
- COMBAT,
- OUTRO
+ EVENT_CARRION_SWARM = 1,
+ EVENT_MIND_BLAST,
+ EVENT_VAMPIRIC_TOUCH,
+ EVENT_SLEEP
};
class boss_mal_ganis : public CreatureScript
{
-public:
- boss_mal_ganis() : CreatureScript("boss_mal_ganis") { }
+ public:
+ boss_mal_ganis() : CreatureScript("boss_mal_ganis") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetCullingOfStratholmeAI<boss_mal_ganisAI>(creature);
- }
-
- struct boss_mal_ganisAI : public ScriptedAI
- {
- boss_mal_ganisAI(Creature* creature) : ScriptedAI(creature)
+ CreatureAI* GetAI(Creature* creature) const override
{
- Initialize();
- instance = creature->GetInstanceScript();
- uiOutroStep = 0;
- }
+ if (!InstanceHasScript(creature, CoSScriptName))
+ return nullptr;
- void Initialize()
- {
- bYelled = false;
- bYelled2 = false;
- Phase = COMBAT;
- uiCarrionSwarmTimer = 6000;
- uiMindBlastTimer = 11000;
- uiVampiricTouchTimer = urand(10000, 15000);
- uiSleepTimer = urand(15000, 20000);
- uiOutroTimer = 1000;
+ if (creature->GetInstanceScript()->GetData(DATA_INSTANCE_PROGRESS) < MALGANIS_IN_PROGRESS)
+ return new NullCreatureAI(creature);
+ else
+ return new boss_mal_ganisAI(creature);
}
- uint32 uiCarrionSwarmTimer;
- uint32 uiMindBlastTimer;
- uint32 uiVampiricTouchTimer;
- uint32 uiSleepTimer;
-
- uint8 uiOutroStep;
- uint32 uiOutroTimer;
-
- bool bYelled;
- bool bYelled2;
-
- CombatPhases Phase;
-
- InstanceScript* instance;
-
- void Reset() override
+ struct boss_mal_ganisAI : public BossAI
{
- Initialize();
- instance->SetBossState(DATA_MAL_GANIS, NOT_STARTED);
- }
+ boss_mal_ganisAI(Creature* creature) : BossAI(creature, DATA_MAL_GANIS), _defeated(false), _hadYell30(false), _hadYell15(false) { }
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- instance->SetBossState(DATA_MAL_GANIS, IN_PROGRESS);
- }
-
- void DamageTaken(Unit* done_by, uint32 &damage) override
- {
- if (damage >= me->GetHealth() && done_by != me)
- damage = me->GetHealth()-1;
- }
+ void Reset() override
+ {
+ if (!_defeated)
+ instance->SetBossState(DATA_MAL_GANIS, NOT_STARTED);
+ }
- void UpdateAI(uint32 diff) override
- {
- switch (Phase)
+ void DamageTaken(Unit* /*source*/, uint32 &damage) override
{
- case COMBAT:
- //Return since we have no target
- if (!UpdateVictim())
+ if (damage >= me->GetHealth())
+ {
+ damage = me->GetHealth() - 1;
+ if (_defeated)
return;
+ _defeated = true;
- if (!bYelled && HealthBelowPct(30))
- {
- Talk(SAY_30HEALTH);
- bYelled = true;
- }
+ // @todo hack most likely
+ if (InstanceMap* map = instance->instance->ToInstanceMap())
+ map->PermBindAllPlayers();
+ }
+ }
- if (!bYelled2 && HealthBelowPct(15))
- {
- Talk(SAY_15HEALTH);
- bYelled2 = true;
- }
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ _defeated = false;
+ _hadYell30 = false;
+ _hadYell15 = false;
+ events.ScheduleEvent(EVENT_CARRION_SWARM, Seconds(5));
+ events.ScheduleEvent(EVENT_MIND_BLAST, Seconds(6), Seconds(8));
+ events.ScheduleEvent(EVENT_VAMPIRIC_TOUCH, Seconds(4));
+ events.ScheduleEvent(EVENT_SLEEP, Seconds(17), Seconds(21));
+ }
+
+ void JustReachedHome() override
+ {
+ if (!_defeated)
+ me->DespawnOrUnsummon(Seconds(1));
+ }
- if (HealthBelowPct(1))
+ void UpdateAI(uint32 diff) override
+ {
+ if (_defeated)
+ {
+ if (me->IsInCombat())
{
- //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent
- me->AddUnitFlag(UnitFlags(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE));
- uiOutroStep = 1;
- Phase = OUTRO;
- return;
+ EnterEvadeMode();
+ me->SetImmuneToAll(true);
}
+ return;
+ }
- if (Creature* pArthas = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ARTHAS)))
- if (pArthas->isDead())
- {
- EnterEvadeMode();
- me->DisappearAndDie();
- instance->SetBossState(DATA_MAL_GANIS, FAIL);
- }
+ if (!UpdateVictim())
+ return;
- if (uiCarrionSwarmTimer < diff)
- {
- DoCastVictim(SPELL_CARRION_SWARM);
- uiCarrionSwarmTimer = 7000;
- } else uiCarrionSwarmTimer -= diff;
+ if (!_hadYell30 && HealthBelowPct(30))
+ {
+ Talk(SAY_30HEALTH);
+ _hadYell30 = true;
+ }
- if (uiMindBlastTimer < diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_MIND_BLAST);
- uiMindBlastTimer = 6000;
- } else uiMindBlastTimer -= diff;
+ if (!_hadYell15 && HealthBelowPct(15))
+ {
+ Talk(SAY_15HEALTH);
+ _hadYell15 = true;
+ }
- if (uiVampiricTouchTimer < diff)
- {
- DoCast(me, SPELL_VAMPIRIC_TOUCH);
- uiVampiricTouchTimer = 32000;
- } else uiVampiricTouchTimer -= diff;
+ events.Update(diff);
- if (uiSleepTimer < diff)
- {
- Talk(SAY_SLEEP);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_SLEEP);
- uiSleepTimer = urand(15000, 20000);
- } else uiSleepTimer -= diff;
-
- DoMeleeAttackIfReady();
- break;
- case OUTRO:
- if (uiOutroTimer < diff)
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (uiOutroStep)
- {
- case 1:
- Talk(SAY_OUTRO);
- me->GetMotionMaster()->MoveTargetedHome();
- ++uiOutroStep;
- uiOutroTimer = 8000;
- break;
- case 2:
- me->SetTarget(instance->GetGuidData(DATA_ARTHAS));
- me->HandleEmoteCommand(29);
- Talk(SAY_ESCAPE_SPEECH_2);
- ++uiOutroStep;
- uiOutroTimer = 9000;
- break;
- case 3:
- Talk(SAY_OUTRO);
- ++uiOutroStep;
- //uiOutroTimer = 16000;
- break;
- case 4:
- me->HandleEmoteCommand(33);
- ++uiOutroStep;
- uiOutroTimer = 500;
- break;
- case 5:
- me->SetVisible(false);
- me->KillSelf();
- break;
-
- }
- } else uiOutroTimer -= diff;
- break;
- }
- }
+ case EVENT_CARRION_SWARM:
+ DoCastAOE(SPELL_CARRION_SWARM);
+ events.Repeat(Seconds(6));
+ break;
+ case EVENT_MIND_BLAST:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -int32(SPELL_SLEEP)))
+ DoCast(target, SPELL_MIND_BLAST);
+ else
+ DoCastVictim(SPELL_MIND_BLAST);
+ events.Repeat(Seconds(8), Seconds(12));
+ break;
+ case EVENT_VAMPIRIC_TOUCH:
+ DoCastSelf(SPELL_VAMPIRIC_TOUCH);
+ events.Repeat(Seconds(30));
+ break;
+ case EVENT_SLEEP:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f))
+ DoCast(target, SPELL_SLEEP);
+ else
+ DoCastVictim(SPELL_SLEEP);
+ events.Repeat(Seconds(10), Seconds(15));
+ break;
+ default:
+ break;
+ }
- void JustDied(Unit* /*killer*/) override
- {
- instance->SetBossState(DATA_MAL_GANIS, DONE);
- DoCastAOE(SPELL_MAL_GANIS_KILL_CREDIT, true);
- // give achievement credit and LFG rewards to players. criteria use spell 58630 which doesn't exist, but it was created in spell_dbc
- DoCastAOE(SPELL_KILL_CREDIT);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
+ DoMeleeAttackIfReady();
+ }
- Talk(SAY_SLAY);
- }
- };
+ void KilledUnit(Unit* victim) override
+ {
+ if (!_defeated && victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
+ private:
+ bool _defeated;
+ bool _hadYell30;
+ bool _hadYell15;
+ };
};
void AddSC_boss_mal_ganis()
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp
index c5923f54321..2696d0d3fec 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp
@@ -15,28 +15,30 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
#include "culling_of_stratholme.h"
+#include "InstanceScript.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
enum Spells
{
- SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec.
- SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec.
- SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec.
+ SPELL_FRENZY = 58841
};
+#define SPELL_CONSTRICTING_CHAINS DUNGEON_MODE(52696,58823)
+#define SPELL_DISEASE_EXPULSION DUNGEON_MODE(52666,58824)
+
enum Yells
{
- SAY_AGGRO = 0,
- SAY_SLAY = 1,
- SAY_SPAWN = 2,
- SAY_DEATH = 3
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_SPAWN = 2,
+ SAY_DEATH = 3
};
enum Events
{
- EVENT_CHAIN = 1,
+ EVENT_CHAIN = 1,
EVENT_DISEASE,
EVENT_FRENZY
};
@@ -48,18 +50,22 @@ class boss_meathook : public CreatureScript
struct boss_meathookAI : public BossAI
{
- boss_meathookAI(Creature* creature) : BossAI(creature, DATA_MEATHOOK)
+ boss_meathookAI(Creature* creature) : BossAI(creature, DATA_MEATHOOK) { }
+
+ void InitializeAI() override
{
Talk(SAY_SPAWN);
+ if (instance->GetBossState(DATA_MEATHOOK) == DONE)
+ me->RemoveLootMode(LOOT_MODE_DEFAULT);
}
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
_JustEngagedWith();
- events.ScheduleEvent(EVENT_CHAIN, 12s, 17s);
- events.ScheduleEvent(EVENT_DISEASE, 2s, 4s);
- events.ScheduleEvent(EVENT_FRENZY, 21s, 26s);
+ events.ScheduleEvent(EVENT_CHAIN, Seconds(7), Seconds(11));
+ events.ScheduleEvent(EVENT_DISEASE, Seconds(2));
+ events.ScheduleEvent(EVENT_FRENZY, Seconds(13), Seconds(17));
}
void ExecuteEvent(uint32 eventId) override
@@ -67,17 +73,21 @@ class boss_meathook : public CreatureScript
switch (eventId)
{
case EVENT_CHAIN:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, -20.0f, true))
+ DoCast(target, SPELL_CONSTRICTING_CHAINS);
+ else if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true))
DoCast(target, SPELL_CONSTRICTING_CHAINS);
- events.ScheduleEvent(EVENT_CHAIN, 2s, 4s);
+ else
+ DoCastVictim(SPELL_CONSTRICTING_CHAINS);
+ events.Repeat(Seconds(10), Seconds(15));
break;
case EVENT_DISEASE:
DoCastAOE(SPELL_DISEASE_EXPULSION);
- events.ScheduleEvent(EVENT_DISEASE, 1500ms, 4s);
+ events.Repeat(Seconds(3)+Milliseconds(500));
break;
case EVENT_FRENZY:
DoCast(me, SPELL_FRENZY);
- events.ScheduleEvent(EVENT_FRENZY, 21s, 26s);
+ events.Repeat(Seconds(13), Seconds(17));
break;
default:
break;
@@ -88,6 +98,7 @@ class boss_meathook : public CreatureScript
{
Talk(SAY_DEATH);
_JustDied();
+ instance->SetData(DATA_NOTIFY_DEATH, 1);
}
void KilledUnit(Unit* victim) override
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp
index b0c1326c897..b5c5b4a3d4b 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp
@@ -15,34 +15,41 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
#include "culling_of_stratholme.h"
+#include "InstanceScript.h"
#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
enum Spells
{
- SPELL_CURSE_OF_TWISTED_FLESH = 58845,
- SPELL_EXPLODE_GHOUL = 52480,
- SPELL_SHADOW_BOLT = 57725,
- SPELL_STEAL_FLESH = 52708,
- SPELL_SUMMON_GHOULS = 52451
+ SPELL_CURSE_OF_TWISTED_FLESH = 58845,
+ SPELL_STEAL_FLESH = 52708,
+ SPELL_STEAL_FLESH_DEBUFF = 52711,
+ SPELL_STEAL_FLESH_BUFF = 52712,
+ SPELL_SUMMON_GHOULS = 52451
};
+#define SPELL_EXPLODE_GHOUL DUNGEON_MODE(52480,58825)
+#define SPELL_SHADOW_BOLT DUNGEON_MODE(57725,58827)
+
enum Yells
{
- SAY_AGGRO = 0,
- SAY_SPAWN = 1,
- SAY_SLAY = 2,
- SAY_DEATH = 3,
- SAY_EXPLODE_GHOUL = 4,
- SAY_STEAL_FLESH = 5,
- SAY_SUMMON_GHOULS = 6
+ SAY_AGGRO = 0,
+ SAY_SPAWN = 1,
+ SAY_SLAY = 2,
+ SAY_DEATH = 3,
+ SAY_EXPLODE_GHOUL = 4,
+ SAY_STEAL_FLESH = 5,
+ SAY_SUMMON_GHOULS = 6
};
enum Events
{
- EVENT_CURSE_FLESH = 1,
- EVENT_EXPLODE_GHOUL,
+ EVENT_CURSE_FLESH = 1,
+ EVENT_EXPLODE_GHOUL1,
+ EVENT_EXPLODE_GHOUL2,
EVENT_SHADOW_BOLT,
EVENT_STEAL_FLESH,
EVENT_SUMMON_GHOULS
@@ -55,9 +62,13 @@ class boss_salramm : public CreatureScript
struct boss_salrammAI : public BossAI
{
- boss_salrammAI(Creature* creature) : BossAI(creature, DATA_SALRAMM)
+ boss_salrammAI(Creature* creature) : BossAI(creature, DATA_SALRAMM) { }
+
+ void InitializeAI() override
{
Talk(SAY_SPAWN);
+ if (instance->GetBossState(DATA_SALRAMM) == DONE)
+ me->RemoveLootMode(LOOT_MODE_DEFAULT);
}
void JustEngagedWith(Unit* /*who*/) override
@@ -65,10 +76,11 @@ class boss_salramm : public CreatureScript
Talk(SAY_AGGRO);
_JustEngagedWith();
- events.ScheduleEvent(EVENT_CURSE_FLESH, 30s);
- events.ScheduleEvent(EVENT_SUMMON_GHOULS, 19s, 24s);
- events.ScheduleEvent(EVENT_SHADOW_BOLT, 8s, 12s);
- events.ScheduleEvent(EVENT_STEAL_FLESH, 12345); /// @todo: adjust timer
+ events.ScheduleEvent(EVENT_SUMMON_GHOULS, randtime(Seconds(19),Seconds(24)));
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, Seconds(2));
+ events.ScheduleEvent(EVENT_STEAL_FLESH, Seconds(25), Seconds(35));
+ if (IsHeroic())
+ events.ScheduleEvent(EVENT_CURSE_FLESH, Seconds(40));
}
void ExecuteEvent(uint32 eventId) override
@@ -77,28 +89,31 @@ class boss_salramm : public CreatureScript
{
case EVENT_CURSE_FLESH:
DoCastVictim(SPELL_CURSE_OF_TWISTED_FLESH);
- events.ScheduleEvent(EVENT_CURSE_FLESH, 35s);
+ events.Repeat(Seconds(37));
break;
case EVENT_SUMMON_GHOULS:
Talk(SAY_SUMMON_GHOULS);
- DoCast(me, SPELL_SUMMON_GHOULS);
- events.ScheduleEvent(EVENT_SUMMON_GHOULS, 10s);
- events.ScheduleEvent(EVENT_EXPLODE_GHOUL, 6s);
+ DoCastAOE(SPELL_SUMMON_GHOULS);
+ events.ScheduleEvent(EVENT_EXPLODE_GHOUL1, Seconds(20), Seconds(24));
+ events.ScheduleEvent(EVENT_EXPLODE_GHOUL2, Seconds(25), Seconds(29));
break;
case EVENT_SHADOW_BOLT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
DoCast(target, SPELL_SHADOW_BOLT);
- events.ScheduleEvent(EVENT_SHADOW_BOLT, 8s, 12s);
+ events.Repeat(Seconds(3));
break;
case EVENT_STEAL_FLESH:
Talk(SAY_STEAL_FLESH);
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 50.0f, true))
DoCast(target, SPELL_STEAL_FLESH);
- events.ScheduleEvent(EVENT_STEAL_FLESH, 12345);
+ events.Repeat(Seconds(15), Seconds(20));
break;
- case EVENT_EXPLODE_GHOUL:
+ case EVENT_EXPLODE_GHOUL2:
+ events.ScheduleEvent(EVENT_SUMMON_GHOULS, Seconds(4));
+ // intentional missing break
+ case EVENT_EXPLODE_GHOUL1:
Talk(SAY_EXPLODE_GHOUL);
- DoCast(me, SPELL_EXPLODE_GHOUL, true);
+ DoCastAOE(SPELL_EXPLODE_GHOUL, true);
break;
default:
break;
@@ -109,6 +124,7 @@ class boss_salramm : public CreatureScript
{
Talk(SAY_DEATH);
_JustDied();
+ instance->SetData(DATA_NOTIFY_DEATH, 1);
}
void KilledUnit(Unit* victim) override
@@ -124,7 +140,24 @@ class boss_salramm : public CreatureScript
}
};
+class spell_salramm_steal_flesh : public AuraScript
+{
+ PrepareAuraScript(spell_salramm_steal_flesh);
+
+ void HandlePeriodic(AuraEffect const* /*eff*/)
+ {
+ GetCaster()->CastSpell(GetCaster(), SPELL_STEAL_FLESH_BUFF, true);
+ GetCaster()->CastSpell(GetTarget(), SPELL_STEAL_FLESH_DEBUFF, true);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_salramm_steal_flesh::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+};
+
void AddSC_boss_salramm()
{
new boss_salramm();
+ RegisterAuraScript(spell_salramm_steal_flesh);
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
index e7809f8b0e0..7cda95b5661 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp
@@ -15,1262 +15,1464 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ScriptMgr.h"
#include "culling_of_stratholme.h"
+#include "AreaBoundary.h"
+#include "DB2Structure.h"
#include "GameObject.h"
+#include "GameTime.h"
#include "InstanceScript.h"
+#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "PassiveAI.h"
#include "Player.h"
+#include "QuestDef.h"
#include "ScriptedEscortAI.h"
#include "ScriptedGossip.h"
+#include "SmartAI.h"
#include "SpellInfo.h"
+#include "ScriptMgr.h"
+#include "SplineChainMovementGenerator.h"
+#include "StringFormat.h"
#include "TemporarySummon.h"
+#include <unordered_map>
-enum Says
+enum InnEventEntries
{
- //Arthas
- //First Act
- SAY_PHASE101 = 0,
- SAY_PHASE103 = 1,
- SAY_PHASE104 = 2,
- SAY_PHASE106 = 3,
- SAY_PHASE108 = 4,
- SAY_PHASE110 = 5,
- SAY_PHASE112 = 6,
- SAY_PHASE114 = 7,
- SAY_PHASE116 = 8,
- SAY_PHASE118 = 9,
-
- //Second Act - City Streets
- SAY_PHASE201 = 10,
- SAY_PHASE203 = 11,
- SAY_PHASE205 = 12,
- SAY_PHASE208 = 13,
- SAY_PHASE209 = 14,
- SAY_PHASE210 = 15,
-
- //Third Act - Town Hall
- SAY_PHASE301 = 16,
- SAY_PHASE303 = 17,
- SAY_PHASE304 = 18,
- SAY_PHASE306 = 19,
- SAY_PHASE307 = 20,
- SAY_PHASE308 = 21,
- SAY_PHASE309 = 22,
- SAY_PHASE310 = 23,
- SAY_PHASE311 = 24,
- SAY_PHASE312 = 25,
- SAY_PHASE313 = 26,
- SAY_PHASE315 = 27,
-
- //Fourth Act - Fire Corridor
- SAY_PHASE401 = 28,
- SAY_PHASE402 = 29,
- SAY_PHASE403 = 30,
- SAY_PHASE404 = 31,
- SAY_PHASE405 = 32,
- SAY_PHASE406 = 33,
- SAY_PHASE407 = 34,
-
- //Fifth Act - Mal'Ganis Fight
- SAY_PHASE501 = 35,
- SAY_PHASE502 = 36,
- SAY_PHASE503 = 37,
- SAY_PHASE504 = 38,
-
- //Malganis
- SAY_PHASE206 = 0,
- SAY_PHASE207 = 1,
-
- //Epoch
- SAY_PHASE314 = 0,
-
- //Uther
- SAY_PHASE102 = 0,
- SAY_PHASE105 = 1,
- SAY_PHASE107 = 2,
- SAY_PHASE109 = 3,
- SAY_PHASE111 = 4,
- SAY_PHASE115 = 5,
-
- //Jaina
- SAY_PHASE113 = 0,
- SAY_PHASE117 = 1,
-
- //Cityman
- SAY_PHASE202 = 0,
-
- //Crazyman
- SAY_PHASE204 = 0,
-
- //Drakonian
- SAY_PHASE302 = 0,
- SAY_PHASE305 = 1
+ NPC_FORREST = 30551,
+ NPC_BELFAST = 30571,
+ NPC_JAMES = 30553,
+ NPC_FRAS = 30552,
+ NPC_MAL = 31017,
+ NPC_GRYAN = 30561
};
-enum NPCs
+enum InnEventEvents
{
- NPC_INFINITE_ADVERSARY = 27742,
- NPC_INFINITE_HUNTER = 27743,
- NPC_INFINITE_AGENT = 27744,
- NPC_ZOMBIE = 27737,
- NPC_GHOUL = 28249,
- NPC_NECROMANCER = 28200,
- NPC_STALKER = 28199,
- NPC_FIEND = 27734,
- NPC_GOLEM = 28201,
- NPC_EGHOUL = 27729,
- NPC_CONSTRUCT = 27736,
-
- NPC_INVIS_TARGET = 20562,
-
- NPC_KNIGHT_ESCORT = 27745,
- NPC_PRIEST_ESCORT = 27747,
- NPC_CITY_MAN = 28167,
- NPC_CITY_MAN2 = 28169,
- NPC_CITY_MAN3 = 31126,
- NPC_CITY_MAN4 = 31127
+ EVENT_FORREST_1 = 1, // This whole situation seems a bit paranoid, don't you think?
+ EVENT_JAMES_1, // Orders are orders. If the Prince says jump...
+ EVENT_FRAS_1, // It's a strange order, you can't deny. Suspicious food? Under that definition, you should arrest Belfast!
+ EVENT_BELFAST_MOVE = 100,
+ EVENT_BELFAST_1, // I HEARD THAT! No more ale for you! Not a drop!
+ EVENT_MAL_1, // Enough, Michael. Business is hurting enough with this scare as it is. We can use every copper.
+ EVENT_GRYAN_1, // The soldiers are doing important work. The safety of the people is more important, Mal, if you're interested in your customers living to spend another day.
+ EVENT_MAL_2, // Mal Corricks grudgingly nods.
+ EVENT_MAL_3, // I can't argue with that.
+ EVENT_JAMES_2, // Don't worry too much. By the time I went off duty, we hadn't found a scrap of befouled grain here.
+ EVENT_FORREST_2, // Thank the Light for that.
+ EVENT_FRAS_2 // Fras Siabi nods.
};
-enum Spells
+enum InnEventLines
{
- SPELL_FEAR = 39176,
- SPELL_ARTHAS_AURA = 52442,
- SPELL_EXORCISM_N = 52445,
- SPELL_EXORCISM_H = 58822,
- SPELL_HOLY_LIGHT = 52444,
- SPELL_ARCANE_DISRUPTION = 49590
+ LINE_JAMES_1 = 0,
+ LINE_JAMES_2 = 1,
+
+ LINE_FRAS_1 = 0,
+ LINE_FRAS_2 = 1,
+
+ LINE_MAL_1 = 0,
+ LINE_MAL_2 = 1,
+ LINE_MAL_3 = 2,
+
+ LINE_FORREST_1 = 0,
+ LINE_FORREST_2 = 1,
+
+ LINE_BELFAST_0 = 0,
+ LINE_BELFAST_1 = 1,
+ LINE_GRYAN_1 = 0,
};
-enum GossipMenuArthas
+enum InnEventMisc
{
- GOSSIP_MENU_ARTHAS_1 = 100001,
- GOSSIP_MENU_ARTHAS_2 = 100002,
- GOSSIP_MENU_ARTHAS_3 = 100003,
- GOSSIP_MENU_ARTHAS_4 = 100004,
- GOSSIP_MENU_ARTHAS_5 = 100005
+ DATA_REQUEST_FACING = 0,
+ DATA_REACHED_WP = 1
};
-enum EncounterData
+class npc_hearthsinger_forresten_cot : public CreatureScript
{
- ENCOUNTER_WAVES_NUMBER = 8,
- ENCOUNTER_WAVES_MAX_SPAWNS = 5,
- ENCOUNTER_DRACONIAN_NUMBER = 4,
- ENCOUNTER_CHRONO_SPAWNS = 19
+ public:
+ npc_hearthsinger_forresten_cot() : CreatureScript("npc_hearthsinger_forresten_cot") { }
+
+ struct npc_hearthsinger_forresten_cotAI : public NullCreatureAI
+ {
+ npc_hearthsinger_forresten_cotAI(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()), _hadBelfast(false), _hadTalk(false) { }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ uint32 talkerEntry = UINT_MAX, line = 0;
+ switch (eventId)
+ {
+ case EVENT_FORREST_1:
+ talkerEntry = 0, line = LINE_FORREST_1;
+ break;
+ case EVENT_JAMES_1:
+ talkerEntry = NPC_JAMES, line = LINE_JAMES_1;
+ break;
+ case EVENT_FRAS_1:
+ talkerEntry = NPC_FRAS, line = LINE_FRAS_1;
+ break;
+ case EVENT_BELFAST_MOVE:
+ if (Creature* belfast = me->FindNearestCreature(NPC_BELFAST, 80.0f, true))
+ belfast->AI()->DoAction(EVENT_BELFAST_MOVE);
+ return;
+ case EVENT_BELFAST_1:
+ talkerEntry = NPC_BELFAST, line = LINE_BELFAST_1;
+ break;
+ case EVENT_MAL_1:
+ talkerEntry = NPC_MAL, line = LINE_MAL_1;
+ break;
+ case EVENT_GRYAN_1:
+ talkerEntry = NPC_GRYAN, line = LINE_GRYAN_1;
+ break;
+ case EVENT_MAL_2:
+ talkerEntry = NPC_MAL, line = LINE_MAL_2;
+ break;
+ case EVENT_MAL_3:
+ talkerEntry = NPC_MAL, line = LINE_MAL_3;
+ break;
+ case EVENT_JAMES_2:
+ talkerEntry = NPC_JAMES, line = LINE_JAMES_2;
+ break;
+ case EVENT_FORREST_2:
+ talkerEntry = 0, line = LINE_FORREST_2;
+ break;
+ case EVENT_FRAS_2:
+ talkerEntry = NPC_FRAS, line = LINE_FRAS_2;
+ break;
+ default:
+ break;
+ }
+
+ if (talkerEntry != UINT_MAX)
+ {
+ Creature* talker = me;
+ if (talkerEntry)
+ talker = me->FindNearestCreature(talkerEntry, 80.0f, true);
+ if (talker)
+ talker->AI()->Talk(line, ObjectAccessor::GetPlayer(*talker, _triggeringPlayer));
+ }
+ }
+ }
+
+ // Player has hit the Belfast stairs areatrigger, we are taking him over for a moment
+ void SetGUID(ObjectGuid const& guid, int32 /*id*/) override
+ {
+ if (_hadBelfast)
+ return;
+ _hadBelfast = true;
+ if (Creature* belfast = me->FindNearestCreature(NPC_BELFAST, 100.0f, true))
+ {
+ if (Player* invoker = ObjectAccessor::GetPlayer(*belfast, guid))
+ {
+ belfast->StopMoving();
+ belfast->SetFacingToObject(invoker);
+ belfast->AI()->Talk(LINE_BELFAST_0);
+ }
+ }
+ }
+
+ // Belfast SmartAI telling us it's reached the WP
+ void SetData(uint32 /*data*/, uint32 /*value*/) override
+ {
+ _events.ScheduleEvent(EVENT_BELFAST_1, Seconds(0));
+ _events.ScheduleEvent(EVENT_MAL_1, Seconds(6));
+ _events.ScheduleEvent(EVENT_GRYAN_1, Seconds(12));
+ _events.ScheduleEvent(EVENT_MAL_2, Seconds(18));
+ _events.ScheduleEvent(EVENT_MAL_3, Seconds(20));
+ _events.ScheduleEvent(EVENT_JAMES_2, Seconds(26));
+ _events.ScheduleEvent(EVENT_FORREST_2, Seconds(32));
+ _events.ScheduleEvent(EVENT_FRAS_2, Seconds(38));
+ }
+
+ void MoveInLineOfSight(Unit* unit) override
+ {
+ if (!_hadTalk && unit->ToPlayer() && _instance->GetData(DATA_INSTANCE_PROGRESS) <= CRATES_IN_PROGRESS && me->GetDistance2d(unit) <= 10.0f)
+ {
+ _hadTalk = true;
+ _triggeringPlayer = unit->GetGUID();
+ Seconds offset = Seconds(urand(10,30));
+ _events.ScheduleEvent(EVENT_FORREST_1, offset);
+ _events.ScheduleEvent(EVENT_JAMES_1, offset+Seconds(6));
+ _events.ScheduleEvent(EVENT_FRAS_1, offset+Seconds(12));
+ _events.ScheduleEvent(EVENT_BELFAST_MOVE, offset+Seconds(12));
+ }
+ }
+
+
+ private:
+ InstanceScript const* const _instance;
+ EventMap _events;
+ bool _hadBelfast;
+ bool _hadTalk;
+ ObjectGuid _triggeringPlayer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_hearthsinger_forresten_cotAI>(creature);
+ }
};
-// Locations for necromancers and add to spawn
-float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]=
+class at_stratholme_inn_stairs_cot : public AreaTriggerScript
{
- {
- {NPC_ZOMBIE, 2164.698975f, 1255.392944f, 135.040878f, 0.490202f},
- {NPC_ZOMBIE, 2183.501465f, 1263.079102f, 134.859055f, 3.169981f},
- {NPC_GHOUL, 2177.512939f, 1247.313843f, 135.846695f, 1.696574f},
- {NPC_GHOUL, 2171.991943f, 1246.615845f, 135.745026f, 1.696574f},
- {0, 0, 0, 0, 0}
- },
- {
- {NPC_GHOUL, 2254.434326f, 1163.427612f, 138.055038f, 2.077358f},
- {NPC_GHOUL, 2254.703613f, 1158.867798f, 138.212234f, 2.345532f},
- {NPC_GHOUL, 2257.615723f, 1162.310913f, 138.091202f, 2.077358f},
- {NPC_NECROMANCER, 2258.258057f, 1157.250732f, 138.272873f, 2.387766f},
- {0, 0, 0, 0, 0}
- },
- {
- {NPC_STALKER, 2348.120117f, 1202.302490f, 130.491104f, 4.698538f},
- {NPC_GHOUL, 2352.863525f, 1207.819092f, 130.424271f, 4.949865f},
- {NPC_GHOUL, 2343.593750f, 1207.915039f, 130.781311f, 4.321547f},
- {NPC_NECROMANCER, 2348.257324f, 1212.202515f, 130.670135f, 4.450352f},
- {0, 0, 0, 0, 0}
- },
- {
- {NPC_STALKER, 2139.825195f, 1356.277100f, 132.199615f, 5.820131f},
- {NPC_GHOUL, 2137.073486f, 1362.464844f, 132.271637f, 5.820131f},
- {NPC_GHOUL, 2134.075684f, 1354.148071f, 131.885864f, 5.820131f},
- {NPC_NECROMANCER, 2133.302246f, 1358.907837f, 132.037689f, 5.820131f},
- {0, 0, 0, 0, 0}
- },
- {
- {NPC_NECROMANCER, 2264.013428f, 1174.055908f, 138.093094f, 2.860481f},
- {NPC_GHOUL, 2264.207764f, 1170.892700f, 138.034973f, 2.860481f},
- {NPC_GHOUL, 2266.948975f, 1176.898926f, 137.976929f, 2.860481f},
- {NPC_STALKER, 2269.215576f, 1170.109253f, 137.742691f, 2.860481f},
- {NPC_FIEND, 2273.106689f, 1176.101074f, 137.880508f, 2.860481f}
- },
- {
- {NPC_GOLEM, 2349.701660f, 1188.436646f, 130.428864f, 3.908642f},
- {NPC_GHOUL, 2349.909180f, 1194.582642f, 130.417816f, 3.577001f},
- {NPC_EGHOUL, 2354.662598f, 1185.692017f, 130.552032f, 3.577001f},
- {NPC_EGHOUL, 2354.716797f, 1191.614380f, 130.539810f, 3.577001f},
- {0, 0, 0, 0, 0}
- },
- {
- {NPC_CONSTRUCT, 2145.212891f, 1355.288086f, 132.288773f, 6.004838f},
- {NPC_NECROMANCER, 2137.078613f, 1357.612671f, 132.173340f, 6.004838f},
- {NPC_EGHOUL, 2139.402100f, 1352.541626f, 132.127518f, 5.812850f},
- {NPC_EGHOUL, 2142.408447f, 1360.760620f, 132.321564f, 5.812850f},
- {0, 0, 0, 0, 0}
- },
- {
- {NPC_GHOUL, 2172.686279f, 1259.618164f, 134.391754f, 1.865499f},
- {NPC_FIEND, 2177.649170f, 1256.061157f, 135.096512f, 1.849572f},
- {NPC_CONSTRUCT, 2170.782959f, 1253.594849f, 134.973022f, 1.849572f},
- {NPC_NECROMANCER, 2175.595703f, 1249.041992f, 135.603531f, 1.849572f},
- {0, 0, 0, 0, 0}
- }
+ public:
+ at_stratholme_inn_stairs_cot() : AreaTriggerScript("at_stratholme_inn_stairs_cot") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (instance->GetData(DATA_INSTANCE_PROGRESS) <= CRATES_IN_PROGRESS)
+ // Forrest's script will handle Belfast for this, since SmartAI lacks the features to do it (we can't pass a custom target)
+ if (Creature* forrest = player->FindNearestCreature(NPC_FORREST, 200.0f, true))
+ forrest->AI()->SetGUID(player->GetGUID());
+ return true;
+ }
};
-// Locations for rifts to spawn and draconians to go
-float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]=
+enum Chromie1Gossip
{
- {NPC_TIME_RIFT, 2431.790039f, 1190.670044f, 148.076004f, 0.187923f},
- {NPC_INFINITE_ADVERSARY, 2433.857910f, 1185.612061f, 148.075974f, 4.566168f},
- {NPC_INFINITE_ADVERSARY, 2437.577881f, 1188.241089f, 148.075974f, 0.196999f},
- {NPC_INFINITE_AGENT, 2437.165527f, 1192.294922f, 148.075974f, 0.169247f},
- {NPC_INFINITE_HUNTER, 2434.989990f, 1197.679565f, 148.075974f, 0.715971f},
- {NPC_TIME_RIFT, 2403.954834f, 1178.815430f, 148.075943f, 4.966126f},
- {NPC_INFINITE_AGENT, 2403.676758f, 1171.495850f, 148.075607f, 4.902797f},
- {NPC_INFINITE_HUNTER, 2407.691162f, 1172.162720f, 148.075607f, 4.963010f},
- {NPC_TIME_RIFT, 2414.217041f, 1133.446167f, 148.076050f, 1.706972f},
- {NPC_INFINITE_ADVERSARY, 2416.024658f, 1139.456177f, 148.076431f, 1.752129f},
- {NPC_INFINITE_HUNTER, 2410.866699f, 1139.680542f, 148.076431f, 1.752129f},
- {NPC_TIME_RIFT, 2433.081543f, 1099.869751f, 148.076157f, 1.809509f},
- {NPC_INFINITE_ADVERSARY, 2426.947998f, 1107.471680f, 148.076019f, 1.877580f},
- {NPC_INFINITE_HUNTER, 2432.944580f, 1108.896362f, 148.208160f, 2.199241f},
- {NPC_TIME_RIFT, 2444.077637f, 1114.366089f, 148.076157f, 3.049565f},
- {NPC_INFINITE_ADVERSARY, 2438.190674f, 1118.368164f, 148.076172f, 3.139232f},
- {NPC_INFINITE_AGENT, 2435.861328f, 1113.402954f, 148.169327f, 2.390271f},
- {NPC_TIME_RIFT, 2463.131592f, 1115.391724f, 152.473129f, 3.409651f},
- {NPC_EPOCH, 2451.809326f, 1112.901245f, 149.220459f, 3.363617f}
+ // offsets from GOSSIP_ACTION_INFO_DEF
+ GOSSIP_OFFSET_EXPLAIN = 0,
+ GOSSIP_OFFSET_SKIP,
+ GOSSIP_OFFSET_TELEPORT,
+ GOSSIP_OFFSET_EXPLAIN_1,
+ GOSSIP_OFFSET_EXPLAIN_2,
+ GOSSIP_OFFSET_SKIP_1,
+ GOSSIP_OFFSET_OPEN_GM_MENU,
+ GOSSIP_OFFSET_GM_INITIAL,
+
+ GOSSIP_MENU_INITIAL = 9586,
+ GOSSIP_TEXT_INITIAL = 12939,
+ GOSSIP_OPTION_EXPLAIN = 0,
+ GOSSIP_OPTION_SKIP = 2,
+
+ GOSSIP_TEXT_TELEPORT = 13470,
+ GOSSIP_OPTION_TELEPORT = 1,
+
+ GOSSIP_MENU_EXPLAIN_1 = 9594,
+ GOSSIP_TEXT_EXPLAIN_1 = 12949,
+ GOSSIP_OPTION_EXPLAIN_1 = 0,
+
+ GOSSIP_MENU_EXPLAIN_2 = 9595,
+ GOSSIP_TEXT_EXPLAIN_2 = 12950,
+ GOSSIP_OPTION_EXPLAIN_2 = 0,
+
+ GOSSIP_MENU_EXPLAIN_3 = 9596,
+ GOSSIP_TEXT_EXPLAIN_3 = 12952,
+
+ GOSSIP_MENU_SKIP_1 = 11277,
+ GOSSIP_TEXT_SKIP_1 = 15704,
+ GOSSIP_OPTION_SKIP_1 = 0
};
-#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme."
-#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready."
-#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness."
-#define GOSSIP_ITEM_ARTHAS_3 "I'm ready."
-#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!"
-#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire."
+enum Chromie1Misc
+{
+ ITEM_ARCANE_DISRUPTOR = 37888,
+ QUEST_DISPELLING_ILLUSIONS = 13149,
+ SPELL_TELEPORT_PLAYER = 53435,
+ ACHIEVEMENT_NORMAL = 479,
+ ACHIEVEMENT_HEROIC = 500
+};
-class npc_arthas : public CreatureScript
+class npc_chromie_start : public CreatureScript
{
-public:
- npc_arthas() : CreatureScript("npc_arthas") { }
+ public:
+ npc_chromie_start() : CreatureScript("npc_chromie_start") { }
- struct npc_arthasAI : public EscortAI
- {
- npc_arthasAI(Creature* creature) : EscortAI(creature)
+ struct npc_chromie_startAI : public NullCreatureAI
{
- Initialize();
- instance = creature->GetInstanceScript();
- bStepping = false;
- step = 0;
- gossipStep = 0;
- bossEvent = 0;
- WavesCounter = 0;
- }
+ npc_chromie_startAI(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) { }
- void Initialize()
- {
- utherGUID.Clear();
- jainaGUID.Clear();
+ void AdvanceDungeon()
+ {
+ if (_instance->GetData(DATA_INSTANCE_PROGRESS) == JUST_STARTED)
+ _instance->SetData(DATA_CRATES_START, 1);
+ }
- for (uint8 i = 0; i < 2; ++i)
- citymenGUID[i].Clear();
+ void AdvanceDungeonFar()
+ {
+ if (_instance->GetData(DATA_INSTANCE_PROGRESS) <= CRATES_DONE)
+ _instance->SetData(DATA_SKIP_TO_PURGE, 1);
+ }
+
+ bool GossipHello(Player* player) override
+ {
+ if (me->IsQuestGiver())
+ player->PrepareQuestMenu(me->GetGUID());
- for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i)
- waveGUID[i].Clear();
+ if (InstanceScript* instance = me->GetInstanceScript())
+ {
+ if (player->CanBeGameMaster()) // GM instance state override menu
+ AddGossipItemFor(player, GossipOptionIcon::SpiritHealer, "[GM] Access instance control panel", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_OPEN_GM_MENU);
- for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i)
- infiniteDraconianGUID[i].Clear();
+ uint32 state = instance->GetData(DATA_INSTANCE_PROGRESS);
+ if (state < PURGE_STARTING)
+ {
+ AddGossipItemFor(player, GOSSIP_MENU_INITIAL, GOSSIP_OPTION_EXPLAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_EXPLAIN);
+ {
+ bool shouldAddSkipGossip = true;
+ Map::PlayerList const& players = instance->instance->GetPlayers();
+ for (Map::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it)
+ {
+ if (Player* player = it->GetSource())
+ {
+ if (player->IsGameMaster())
+ continue;
+ if (!player->HasAchieved(instance->instance->IsHeroic() ? ACHIEVEMENT_HEROIC : ACHIEVEMENT_NORMAL))
+ {
+ shouldAddSkipGossip = false;
+ break;
+ }
+ }
+ }
+ if (shouldAddSkipGossip)
+ AddGossipItemFor(player, GOSSIP_MENU_INITIAL, GOSSIP_OPTION_SKIP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_SKIP);
+ }
+ SendGossipMenuFor(player, GOSSIP_TEXT_INITIAL, me->GetGUID());
+ }
+ else
+ {
+ AddGossipItemFor(player, GOSSIP_MENU_INITIAL, GOSSIP_OPTION_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_TELEPORT);
+ SendGossipMenuFor(player, GOSSIP_TEXT_TELEPORT, me->GetGUID());
+ }
+ }
+ else // random fallback, this should really never happen
+ SendGossipMenuFor(player, GOSSIP_TEXT_INITIAL, me->GetGUID());
+ return true;
+ }
- stalkerGUID.Clear();
- bossGUID.Clear();
- epochGUID.Clear();
- malganisGUID.Clear();
- infiniteGUID.Clear();
+ bool GossipSelect(Player* player, uint32 /*sender*/, uint32 listId) override
+ {
+ uint32 const action = GetGossipActionFor(player, listId);
+ ClearGossipMenuFor(player);
+ switch (action - GOSSIP_ACTION_INFO_DEF)
+ {
+ case GOSSIP_OFFSET_EXPLAIN:
+ AddGossipItemFor(player, GOSSIP_MENU_EXPLAIN_1, GOSSIP_OPTION_EXPLAIN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_EXPLAIN_1);
+ SendGossipMenuFor(player, GOSSIP_TEXT_EXPLAIN_1, me->GetGUID());
+ break;
+ case GOSSIP_OFFSET_SKIP:
+ AddGossipItemFor(player, GOSSIP_MENU_SKIP_1, GOSSIP_OPTION_SKIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_SKIP_1);
+ SendGossipMenuFor(player, GOSSIP_TEXT_SKIP_1, me->GetGUID());
+ break;
+ case GOSSIP_OFFSET_SKIP_1:
+ AdvanceDungeonFar();
+ // intentional missing break
+ case GOSSIP_OFFSET_TELEPORT:
+ CloseGossipMenuFor(player);
+ me->CastSpell(player, SPELL_TELEPORT_PLAYER);
+ break;
+ case GOSSIP_OFFSET_EXPLAIN_1:
+ AddGossipItemFor(player, GOSSIP_MENU_EXPLAIN_2, GOSSIP_OPTION_EXPLAIN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_EXPLAIN_2);
+ SendGossipMenuFor(player, GOSSIP_TEXT_EXPLAIN_2, me->GetGUID());
+ break;
+ case GOSSIP_OFFSET_EXPLAIN_2:
+ SendGossipMenuFor(player, GOSSIP_TEXT_EXPLAIN_3, me->GetGUID());
+ AdvanceDungeon();
+ if (!player->HasItemCount(ITEM_ARCANE_DISRUPTOR))
+ player->AddItem(ITEM_ARCANE_DISRUPTOR, 1); // @todo figure out spell
+ break;
+ case GOSSIP_OFFSET_OPEN_GM_MENU:
+ AddGossipItemFor(player, GossipOptionIcon::SpiritHealer, "Teleport all players to Arthas", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_GM_INITIAL);
+ for (uint32 state = 1; state <= COMPLETE; state = state << 1)
+ {
+ if (GetStableStateFor(COSProgressStates(state)) == state)
+ AddGossipItemFor(player, GossipOptionIcon::SpiritHealer, Trinity::StringFormat("Set instance progress to 0x%05X", state), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_GM_INITIAL + state);
+ }
+ for (uint32 state = 1; state <= COMPLETE; state = state << 1)
+ {
+ if (GetStableStateFor(COSProgressStates(state)) != state)
+ AddGossipItemFor(player, GossipOptionIcon::SpiritHealer, Trinity::StringFormat("Force state to 0x%05X (UNSTABLE)", state), GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_GM_INITIAL + state);
+ }
+ SendGossipMenuFor(player, GOSSIP_TEXT_SKIP_1, me->GetGUID());
+ break;
+ case GOSSIP_OFFSET_GM_INITIAL:
+ CloseGossipMenuFor(player);
+ if (!player->CanBeGameMaster())
+ break;
+ if (InstanceScript* instance = me->GetInstanceScript())
+ instance->SetGuidData(DATA_GM_RECALL, player->GetGUID());
+ break;
+ default: // handle GM instance state switch
+ CloseGossipMenuFor(player);
+ if (!player->CanBeGameMaster())
+ break;
+ if (InstanceScript* instance = me->GetInstanceScript())
+ instance->SetData(DATA_GM_OVERRIDE, action - GOSSIP_ACTION_INFO_DEF - GOSSIP_OFFSET_GM_INITIAL);
+ break;
+ }
+ return false;
+ }
- phaseTimer = 1000;
- exorcismTimer = 7300;
- wave = 0;
+ void QuestAccept(Player* /*player*/, Quest const* quest) override
+ {
+ if (quest->GetQuestId() == QUEST_DISPELLING_ILLUSIONS)
+ AdvanceDungeon();
+ }
+
+ private:
+ InstanceScript* const _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_chromie_startAI>(creature);
}
+};
- InstanceScript* instance;
+enum Chromie2Gossip
+{
+ // offsets from GOSSIP_ACTION_INFO_DEF
+ GOSSIP_OFFSET_STEP1 = 0,
+ GOSSIP_OFFSET_STEP2,
+ GOSSIP_OFFSET_STEP3,
- bool bStepping;
- uint32 step;
- uint32 phaseTimer;
- uint32 gossipStep;
- uint32 bossEvent;
- uint32 wave;
- uint32 WavesCounter;
+ GOSSIP_MENU_STEP1 = 9610,
+ GOSSIP_TEXT_STEP1 = 12992,
+ GOSSIP_OPTION_STEP1 = 0,
- ObjectGuid utherGUID;
- ObjectGuid jainaGUID;
- ObjectGuid citymenGUID[2];
- ObjectGuid waveGUID[ENCOUNTER_WAVES_MAX_SPAWNS];
- ObjectGuid infiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER];
- ObjectGuid stalkerGUID;
+ GOSSIP_MENU_STEP2 = 9611,
+ GOSSIP_TEXT_STEP2 = 12993,
+ GOSSIP_OPTION_STEP2 = 0,
- ObjectGuid bossGUID;
- ObjectGuid epochGUID;
- ObjectGuid malganisGUID;
- ObjectGuid infiniteGUID;
+ GOSSIP_MENU_STEP3 = 9612,
+ GOSSIP_TEXT_STEP3 = 12994,
+ GOSSIP_OPTION_STEP3 = 0,
- uint32 exorcismTimer;
+ GOSSIP_MENU_STEP4 = 9613,
+ GOSSIP_TEXT_STEP4 = 12995
+};
- void Reset() override
+enum Chromie2Misc
+{
+ WHISPER_CRATES_DONE = 0,
+ WHISPER_COME_TALK = 1
+};
+
+class npc_chromie_middle : public CreatureScript
+{
+ public:
+ npc_chromie_middle() : CreatureScript("npc_chromie_middle") { }
+
+ struct npc_chromie_middleAI : public NullCreatureAI
{
- Initialize();
+ npc_chromie_middleAI(Creature* creature) : NullCreatureAI(creature), Instance(creature->GetInstanceScript()), WhisperDelay(0) { }
+
+ void JustAppeared() override
+ {
+ if (Instance->GetData(DATA_INSTANCE_PROGRESS) == CRATES_DONE)
+ WhisperDelay = 18 * IN_MILLISECONDS;
+ }
- instance->SetBossState(DATA_ARTHAS, NOT_STARTED);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!WhisperDelay)
+ return;
+ if (WhisperDelay > diff)
+ WhisperDelay -= diff;
+ else
+ {
+ if (Instance->GetData(DATA_INSTANCE_PROGRESS) == CRATES_DONE && Whispered.empty())
+ Talk(WHISPER_CRATES_DONE);
+ WhisperDelay = 0;
+ }
+ }
+
+ void MoveInLineOfSight(Unit* unit) override
+ {
+ if (Player* player = unit->ToPlayer())
+ {
+ if (Instance->GetData(DATA_INSTANCE_PROGRESS) == CRATES_DONE && player->GetQuestStatus(QUEST_DISPELLING_ILLUSIONS) == QUEST_STATUS_COMPLETE && me->GetDistance2d(player) < 40.0f)
+ {
+ time_t& whisperedTime = Whispered[player->GetGUID()];
+ time_t now = GameTime::GetGameTime();
+ if (!whisperedTime || (now - whisperedTime) > 15)
+ {
+ Talk(WHISPER_COME_TALK, player);
+ whisperedTime = now;
+ }
+ }
+ }
+ }
+
+ void AdvanceDungeon(Player const* player)
+ {
+ if (Instance->GetData(DATA_INSTANCE_PROGRESS) == CRATES_DONE)
+ Instance->SetGuidData(DATA_UTHER_START, player->GetGUID());
+ }
+
+ bool GossipHello(Player* player) override
+ {
+ if (me->IsQuestGiver())
+ player->PrepareQuestMenu(me->GetGUID());
- bStepping = true;
- step = 0;
- me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- bossEvent = DATA_MEATHOOK;
- gossipStep = 0;
+ if (Instance->GetData(DATA_INSTANCE_PROGRESS) == CRATES_DONE)
+ AddGossipItemFor(player, GOSSIP_MENU_STEP1, GOSSIP_OPTION_STEP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_STEP1);
+ SendGossipMenuFor(player, GOSSIP_TEXT_STEP1, me->GetGUID());
+ return true;
+ }
+
+ bool GossipSelect(Player* player, uint32 /*sender*/, uint32 listId) override
+ {
+ uint32 const action = GetGossipActionFor(player, listId);
+ ClearGossipMenuFor(player);
+ switch (action - GOSSIP_ACTION_INFO_DEF)
+ {
+ case GOSSIP_OFFSET_STEP1:
+ AddGossipItemFor(player, GOSSIP_MENU_STEP2, GOSSIP_OPTION_STEP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_STEP2);
+ SendGossipMenuFor(player, GOSSIP_TEXT_STEP2, me->GetGUID());
+ break;
+ case GOSSIP_OFFSET_STEP2:
+ AddGossipItemFor(player, GOSSIP_MENU_STEP3, GOSSIP_OPTION_STEP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + GOSSIP_OFFSET_STEP3);
+ SendGossipMenuFor(player, GOSSIP_TEXT_STEP3, me->GetGUID());
+ break;
+ case GOSSIP_OFFSET_STEP3:
+ SendGossipMenuFor(player, GOSSIP_TEXT_STEP4, me->GetGUID());
+ AdvanceDungeon(player);
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ InstanceScript* const Instance;
+ uint32 WhisperDelay;
+ std::unordered_map<ObjectGuid, time_t> Whispered;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_chromie_middleAI>(creature);
}
+};
+
+// Generic data for crate fluff events
+enum CrateGenericMisc
+{
+ MOVEID_EVENT1 = 4200,
+ MOVEID_EVENT2,
+ MOVEID_EVENT3,
+ MOVEID_EVENT4,
+ MOVEID_EVENT5,
- void AttackStart(Unit* who) override
+ ACTION_START_FLUFF = 9001
+};
+
+// Crate fluff event #1
+enum CrateEvent1Misc
+{
+ NPC_MARTHA = 27884,
+ NPC_JENA = 27885,
+
+ EVENT_MARTHA_IDLE1 = 1,
+ EVENT_MARTHA_IDLE2,
+ EVENT_JENA_IDLE1,
+ EVENT_JENA_IDLE2,
+ EVENT_JENA_START,
+ EVENT_MARTHA1,
+ EVENT_JENA7,
+ EVENT_JENA_MOVE2,
+ EVENT_JENA8,
+ EVENT_JENA_LEAVE,
+
+ LINE_JENA1 = 0, // Let's see, we had chicken last night.
+ LINE_JENA2 = 1, // I've got plenty of cured bacon, but he had some for breakfast.
+ LINE_JENA3 = 2, // I need to make something healthy for him, he's still not recovered from that illness from last week.
+ LINE_JENA4 = 3, // Strawberries! Oh wait, they're not in season.
+ LINE_JENA5 = 4, // Ah, I'll make him some fresh bread! I need to get some flour from Martha!
+ LINE_JENA6 = 5, // Martha, I'm out of flour for bread. You wouldn't happen to have any grain from that recent shipment, would you?
+ LINE_JENA7 = 6, // Thanks, Martha! I owe you one.
+ LINE_JENA8 = 7, // Oh, dear.
+ LINE_JENA9 = 8, // Martha, something's wrong with this grain! Some of the Prince's soldiers were looking for this. I'm going to go look for one.
+ LINE_MARTHA1= 0, // Oh hello, Jena. Of course you can borrow some grain. Help yourself.
+ LINE_MARTHA2= 1, // Oh, my.
+
+ CHAIN_MARTHA_IDLE1 = 1,
+ CHAIN_MARTHA_IDLE2 = 2,
+ CHAIN_JENA_INITIAL = 1,
+ CHAIN_JENA_IDLE1 = 3,
+ CHAIN_JENA_IDLE2 = 2,
+ CHAIN_JENA_MOVE1 = 70,
+ CHAIN_JENA_MOVE2 = 71,
+ CHAIN_JENA_LEAVE = 72
+};
+
+static float const marthaIdleOrientation1 = 3.159046f;
+static float const marthaIdleOrientation2 = 4.764749f;
+
+struct npc_martha_goslin : public CreatureScript
+{
+ npc_martha_goslin() : CreatureScript("npc_martha_goslin") { }
+
+ struct npc_martha_goslinAI : public NullCreatureAI
+ {
+ npc_martha_goslinAI(Creature* creature) : NullCreatureAI(creature), InterruptTimer(0) { }
+
+ void DoAction(int32 /*action*/) override
{
- if (who && !who->IsImmuneToPC())
- EscortAI::AttackStart(who);
+ InterruptTimer = 12000;
+ SplineChainMovementGenerator::GetResumeInfo(ResumeInfo, me);
+ me->GetMotionMaster()->Clear();
+ me->SetEmoteState(EMOTE_ONESHOT_NONE);
}
- void JustEngagedWith(Unit* /*who*/) override
+ void MovementInform(uint32 type, uint32 id) override
{
- DoCast(me, SPELL_ARTHAS_AURA);
+ if (type == SPLINE_CHAIN_MOTION_TYPE)
+ {
+ switch (id)
+ {
+ case MOVEID_EVENT1:
+ me->SetEmoteState(EMOTE_STATE_USE_STANDING);
+ me->SetFacingTo(marthaIdleOrientation1, true);
+ Events.ScheduleEvent(EVENT_MARTHA_IDLE2, Seconds(9), Seconds(15));
+ break;
+ case MOVEID_EVENT2:
+ me->SetEmoteState(EMOTE_STATE_USE_STANDING);
+ me->SetFacingTo(marthaIdleOrientation2, true);
+ Events.ScheduleEvent(EVENT_MARTHA_IDLE1, Seconds(9), Seconds(15));
+ break;
+ default:
+ break;
+ }
+ }
}
- void JustDied(Unit* /*killer*/) override
+ void UpdateAI(uint32 diff) override
{
- instance->SetBossState(DATA_ARTHAS, FAIL);
+ if (InterruptTimer)
+ {
+ if (InterruptTimer > diff)
+ {
+ InterruptTimer -= diff;
+ return;
+ }
+ diff -= InterruptTimer;
+ InterruptTimer = 0;
+ if (!ResumeInfo.Empty())
+ {
+ me->GetMotionMaster()->ResumeSplineChain(ResumeInfo);
+ ResumeInfo.Clear();
+ }
+
+ if (!diff)
+ return;
+ }
+
+ Events.Update(diff);
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MARTHA_IDLE1:
+ me->SetEmoteState(EMOTE_ONESHOT_NONE);
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_MARTHA_IDLE1, true);
+ break;
+ case EVENT_MARTHA_IDLE2:
+ me->SetEmoteState(EMOTE_ONESHOT_NONE);
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT2, CHAIN_MARTHA_IDLE2, true);
+ break;
+ default:
+ break;
+ }
+ }
}
- void SpawnTimeRift(uint32 timeRiftID, ObjectGuid* guidVector)
+ void JustAppeared() override
{
- me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0], RiftAndSpawnsLocations[timeRiftID][1], RiftAndSpawnsLocations[timeRiftID][2], RiftAndSpawnsLocations[timeRiftID][3], RiftAndSpawnsLocations[timeRiftID][4], TEMPSUMMON_TIMED_DESPAWN, 11000);
+ me->SetEmoteState(EMOTE_STATE_USE_STANDING);
+ Events.RescheduleEvent(EVENT_MARTHA_IDLE2, Seconds(5), Seconds(10));
+ }
+
+ EventMap Events;
+ uint32 InterruptTimer;
+ SplineChainResumeInfo ResumeInfo;
+ };
- for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i)
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_martha_goslinAI>(creature);
+ }
+};
+
+struct npc_jena_anderson : public CreatureScript
+{
+ npc_jena_anderson() : CreatureScript("npc_jena_anderson") { }
+
+ static Creature* Find(Creature* helper)
+ {
+ return helper->FindNearestCreature(NPC_JENA, 45.0f, true);
+ }
+
+ struct npc_jena_andersonAI : public NullCreatureAI
+ {
+ npc_jena_andersonAI(Creature* creature) : NullCreatureAI(creature), Started(false) { }
+
+ void UpdateAI(uint32 diff) override
+ {
+ Events.Update(diff);
+ while (uint32 eventId = Events.ExecuteEvent())
{
- if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break;
- if (Creature* temp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0], RiftAndSpawnsLocations[timeRiftID][1], RiftAndSpawnsLocations[timeRiftID][2], RiftAndSpawnsLocations[timeRiftID][3], RiftAndSpawnsLocations[timeRiftID][4], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
+ switch (eventId)
{
- guidVector[i-timeRiftID-1] = temp->GetGUID();
- temp->SetImmuneToAll(true);
- temp->SetReactState(REACT_PASSIVE);
- temp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1], RiftAndSpawnsLocations[i][2], RiftAndSpawnsLocations[i][3]);
- if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH)
- epochGUID = temp->GetGUID();
+ case EVENT_JENA_IDLE1:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_JENA_IDLE1, true);
+ break;
+ case EVENT_JENA_IDLE2:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT2, CHAIN_JENA_IDLE2, true);
+ break;
+ case EVENT_JENA_START:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT3, CHAIN_JENA_MOVE1, true);
+ break;
+ case EVENT_MARTHA1:
+ if (Creature* martha = me->FindNearestCreature(NPC_MARTHA, 100.0f, true))
+ {
+ martha->AI()->DoAction(0); // interrupt idle movement
+ martha->SetFacingToObject(me, true);
+ martha->AI()->Talk(LINE_MARTHA1, me);
+ }
+ break;
+ case EVENT_JENA7:
+ Talk(LINE_JENA7, me->FindNearestCreature(NPC_MARTHA, 100.0f, true));
+ break;
+ case EVENT_JENA_MOVE2:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT4, CHAIN_JENA_MOVE2, true);
+ break;
+ case EVENT_JENA8:
+ {
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ Creature* martha = me->FindNearestCreature(NPC_MARTHA, 100.0f, true);
+ Talk(LINE_JENA8, martha);
+ Talk(LINE_JENA9, martha);
+ if (martha)
+ me->SetFacingToObject(martha);
+ break;
+ }
+ case EVENT_JENA_LEAVE:
+ if (Creature* martha = me->FindNearestCreature(NPC_MARTHA, 100.0f, true))
+ {
+ martha->AI()->DoAction(0); // interrupt idle movement (again)
+ martha->SetFacingToObject(me, true);
+ martha->AI()->Talk(LINE_MARTHA2, me);
+ }
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT5, CHAIN_JENA_LEAVE, true);
+ break;
+ default:
+ break;
}
}
}
- void SpawnWaveGroup(uint32 waveID, ObjectGuid* guidVector)
+ void MovementInform(uint32 type, uint32 id) override
{
- for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i)
+ if (type == SPLINE_CHAIN_MOTION_TYPE)
{
- if ((uint32)WavesLocations[waveID][i][0] == 0) break;
- if (Creature* temp = me->SummonCreature((uint32)WavesLocations[waveID][i][0], WavesLocations[waveID][i][1], WavesLocations[waveID][i][2], WavesLocations[waveID][i][3], WavesLocations[waveID][i][4], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
+ switch (id)
{
- guidVector[i] = temp->GetGUID();
+ case MOVEID_EVENT1: // IDLE1
+ if (Started)
+ Events.ScheduleEvent(EVENT_JENA_START, Seconds(1), Seconds(3));
+ else
+ Events.ScheduleEvent(EVENT_JENA_IDLE2, Milliseconds(200), Milliseconds(700));
+ break;
+ case MOVEID_EVENT2: // IDLE2
+ Events.ScheduleEvent(EVENT_JENA_IDLE1, Milliseconds(200), Milliseconds(700));
+ break;
+ case MOVEID_EVENT3:
+ if (Creature* martha = me->FindNearestCreature(NPC_MARTHA, 100.0f, true))
+ {
+ me->SetFacingToObject(martha, true);
+ Talk(LINE_JENA6, martha);
+ }
+ Events.ScheduleEvent(EVENT_MARTHA1, Seconds(5) + Milliseconds(500));
+ Events.ScheduleEvent(EVENT_JENA7, Seconds(11));
+ Events.ScheduleEvent(EVENT_JENA_MOVE2, Seconds(16));
+ break;
+ case MOVEID_EVENT4:
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ Events.ScheduleEvent(EVENT_JENA8, Seconds(2));
+ Events.ScheduleEvent(EVENT_JENA_LEAVE, Seconds(8));
+ break;
+ case MOVEID_EVENT5:
+ me->DespawnOrUnsummon(Seconds(1));
+ break;
+ default:
+ break;
}
}
}
- void SetHoldState(bool bOnHold)
+ void DoAction(int32 action) override
{
- SetEscortPaused(bOnHold);
+ if (action == ACTION_START_FLUFF)
+ Started = true;
}
- void JumpToNextStep(uint32 uiTimer)
+ void InitializeAI() override
{
- phaseTimer = uiTimer;
- ++step;
+ if (me->isMoving())
+ return;
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_JENA_INITIAL, true);
}
- void WaypointReached(uint32 waypointId, uint32 /*pathId*/) override
+ EventMap Events;
+ bool Started;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_jena_andersonAI>(creature);
+ }
+};
+
+// Crate fluff event #2
+enum CrateEvent2Misc
+{
+ NPC_BARTLEBY = 27907,
+
+ EVENT_BARTLEBY_IDLE = 1,
+ EVENT_BARTLEBY1,
+ EVENT_BARTLEBY2,
+ EVENT_BARTLEBY2_2,
+ EVENT_BARTLEBY3,
+
+ LINE_BARTLEBY_IDLE = 0,
+ LINE_BARTLEBY1 = 1, // Well, guess I should load everything back into the cart.
+ LINE_BARTLEBY2 = 2, // Oh, come on! My cart broke, my horse lost a shoe, and now the cargo goes bad!
+ LINE_BARTLEBY3 = 3, // I guess I'll go find the authorities. If I'm lucky they'll tell me it's the plague and that we're all going to die.
+
+ CHAIN_BARTLEBY1 = 1,
+ CHAIN_BARTLEBY2 = 2
+};
+
+struct npc_bartleby_battson : public CreatureScript
+{
+ npc_bartleby_battson() : CreatureScript("npc_bartleby_battson") { }
+
+ static Creature* Find(Creature* helper)
+ {
+ return helper->FindNearestCreature(NPC_BARTLEBY, 5.0f, true);
+ }
+
+ struct npc_bartleby_battsonAI : public NullCreatureAI
+ {
+ npc_bartleby_battsonAI(Creature* creature) : NullCreatureAI(creature), Started(false) { }
+
+ void InitializeAI() override
{
- switch (waypointId)
- {
- case 0:
- case 1:
- case 3:
- case 9:
- case 10:
- case 11:
- case 22:
- case 23:
- case 55:
- case 56:
- SetHoldState(true);
- bStepping = true;
- break;
- case 7:
- if (Unit* cityman0 = me->FindNearestCreature(NPC_CITY_MAN, 160.0f))
- citymenGUID[0] = cityman0->GetGUID();
- if (Unit* cityman1 = me->FindNearestCreature(NPC_CITY_MAN2, 160.0f))
- citymenGUID[1] = cityman1->GetGUID();
- break;
- case 8:
- gossipStep = 1;
- me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- SetHoldState(true);
- break;
- case 12:
- SetRun(true);
- Talk(SAY_PHASE210);
- if (Unit* disguised0 = me->SummonCreature(NPC_CITY_MAN3, 2398.14f, 1207.81f, 134.04f, 5.155249f, TEMPSUMMON_DEAD_DESPAWN, 180000))
- {
- infiniteDraconianGUID[0] = disguised0->GetGUID();
- if (Unit* disguised1 = me->SummonCreature(NPC_CITY_MAN4, 2403.22f, 1205.54f, 134.04f, 3.311264f, TEMPSUMMON_DEAD_DESPAWN, 180000))
- {
- infiniteDraconianGUID[1] = disguised1->GetGUID();
+ Events.ScheduleEvent(EVENT_BARTLEBY_IDLE, Minutes(1), Minutes(2));
+ }
- if (Unit* disguised2 = me->SummonCreature(NPC_CITY_MAN, 2400.82f, 1201.69f, 134.01f, 1.534082f, TEMPSUMMON_DEAD_DESPAWN, 180000))
- {
- infiniteDraconianGUID[2] = disguised2->GetGUID();
- disguised0->SetTarget(infiniteDraconianGUID[1]);
- disguised1->SetTarget(infiniteDraconianGUID[0]);
- disguised2->SetTarget(infiniteDraconianGUID[1]);
- }
- }
- }
- break;
- case 20:
- gossipStep = 2;
- me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- SetRun(false);
- SetHoldState(true);
- break;
- case 21:
- Talk(SAY_PHASE301);
- break;
- case 26:
- SetRun(false);
- SpawnTimeRift(0, &infiniteDraconianGUID[0]);
- Talk(SAY_PHASE307);
- SetHoldState(true);
- bStepping = true;
- break;
- case 29:
- SetRun(false);
- SpawnTimeRift(5, &infiniteDraconianGUID[0]);
- SpawnTimeRift(8, &infiniteDraconianGUID[2]);
- Talk(SAY_PHASE309);
- SetHoldState(true);
- bStepping = true;
- break;
- case 31:
- SetRun(false);
- SpawnTimeRift(11, &infiniteDraconianGUID[0]);
- SpawnTimeRift(14, &infiniteDraconianGUID[2]);
- Talk(SAY_PHASE311);
- SetHoldState(true);
- bStepping = true;
- break;
- case 32:
- Talk(SAY_PHASE401);
- break;
- case 34:
- Talk(SAY_PHASE402);
- break;
- case 35:
- Talk(SAY_PHASE403);
- break;
- case 36:
- if (GameObject* gate = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SHKAF_GATE)))
- gate->SetGoState(GO_STATE_ACTIVE);
- break;
- case 45:
- SetRun(true);
- gossipStep = 4;
- me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- SetHoldState(true);
- break;
- case 48:
- SetRun(false);
- Talk(SAY_PHASE405);
- break;
- case 49:
- SetRun(true);
- Talk(SAY_PHASE406);
- break;
- case 50:
- Talk(SAY_PHASE407);
- break;
- case 51:
- gossipStep = 5;
- me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- SetHoldState(true);
- break;
- }
+ void DoAction(int32 action) override
+ {
+ if (Started || action != ACTION_START_FLUFF)
+ return;
+ Started = true;
+ Events.CancelEvent(EVENT_BARTLEBY_IDLE);
+ Events.ScheduleEvent(EVENT_BARTLEBY1, Seconds(15), Seconds(30));
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == SPLINE_CHAIN_MOTION_TYPE)
+ {
+ switch (id)
+ {
+ case MOVEID_EVENT1:
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ Events.ScheduleEvent(EVENT_BARTLEBY2, Seconds(4));
+ Events.ScheduleEvent(EVENT_BARTLEBY2_2, Seconds(6));
+ Events.ScheduleEvent(EVENT_BARTLEBY3, Seconds(12));
+ break;
+ case MOVEID_EVENT2:
+ me->DespawnOrUnsummon(Seconds(1));
+ break;
+ default:
+ break;
+ }
+ }
}
void UpdateAI(uint32 diff) override
{
- EscortAI::UpdateAI(diff);
+ Events.Update(diff);
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BARTLEBY_IDLE:
+ Talk(LINE_BARTLEBY_IDLE);
+ Events.Repeat(Minutes(2), Minutes(4));
+ break;
+ case EVENT_BARTLEBY1:
+ Talk(LINE_BARTLEBY1);
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_BARTLEBY1, true);
+ break;
+ case EVENT_BARTLEBY2:
+ Talk(LINE_BARTLEBY2);
+ break;
+ case EVENT_BARTLEBY2_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
+ break;
+ case EVENT_BARTLEBY3:
+ Talk(LINE_BARTLEBY3);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT2, CHAIN_BARTLEBY2, true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
- if (bStepping)
+ bool Started;
+ EventMap Events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_bartleby_battsonAI>(creature);
+ }
+};
+
+// Crate fluff event #3
+enum CrateEvent3Misc
+{
+ NPC_MALCOLM = 27891,
+ NPC_SCRUFFY = 27892,
+
+ EVENT_SCRUFFY1 = 1,
+ EVENT_MALCOLM2,
+ EVENT_SCRUFFY_MOVE,
+ EVENT_MALCOLM_MOVE,
+ EVENT_MALCOLM_FACE3,
+ EVENT_SCRUFFY_EMOTE,
+ EVENT_MALCOLM3,
+ EVENT_MALCOLM4,
+ EVENT_MALCOLM_MOVE2,
+
+ LINE_MALCOLM1 = 0, // Looks like a storm's coming in, Scruffy...
+ LINE_SCRUFFY1 = 0, // %s begins to growl...
+ LINE_MALCOLM2 = 1, // What's wrong, pal?
+ LINE_MALCOLM3 = 2, // What did you find, boy?
+ LINE_MALCOLM4 = 3, // This is no good, Scruffy. Stay here and guard the house, I need to go find a soldier.
+
+ CHAIN_MALCOLM1 = 1,
+ CHAIN_MALCOLM2 = 2,
+ CHAIN_MALCOLM3 = 3,
+ CHAIN_MALCOLM4 = 4,
+ CHAIN_SCRUFFY1 = 1,
+ CHAIN_SCRUFFY2 = 2
+
+};
+
+static Position const malcolmSpawn = { 1605.2420f, 805.4160f, 122.9956f, 5.284148f };
+static Position const scruffySpawn = { 1601.1030f, 805.3391f, 123.7677f, 5.471561f };
+static float const scruffyFacing2 = 5.734883f;
+static float const malcolmFacing3 = 2.303835f;
+static Position const scruffyPos3 = { 1629.004f, 810.138f, 120.4927f };
+static float const scruffyFacing4 = 5.445427f;
+
+struct npc_malcolm_moore : public CreatureScript
+{
+ npc_malcolm_moore() : CreatureScript("npc_malcolm_moore") { }
+
+ static void Spawn(Map* map)
+ {
+ map->SummonCreature(NPC_MALCOLM, malcolmSpawn);
+ }
+
+ struct npc_malcolm_mooreAI : public NullCreatureAI
+ {
+ npc_malcolm_mooreAI(Creature* creature) : NullCreatureAI(creature) { }
+
+ void InitializeAI() override
+ {
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_MALCOLM1, true);
+ if (Creature* scruffy = me->SummonCreature(NPC_SCRUFFY, scruffySpawn))
+ scruffy->GetMotionMaster()->MoveAlongSplineChain(0, CHAIN_SCRUFFY1, true);
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == SPLINE_CHAIN_MOTION_TYPE)
{
- if (phaseTimer <= diff)
+ switch (id)
{
- switch (step)
- {
- //After reset
- case 0:
+ case MOVEID_EVENT1:
+ Talk(LINE_MALCOLM1);
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT2, CHAIN_MALCOLM2, true);
+ break;
+ case MOVEID_EVENT2:
+ Events.ScheduleEvent(EVENT_SCRUFFY1, Seconds(0));
+ Events.ScheduleEvent(EVENT_MALCOLM2, Seconds(1));
+ Events.ScheduleEvent(EVENT_SCRUFFY_MOVE, Seconds(4));
+ Events.ScheduleEvent(EVENT_MALCOLM_MOVE, Seconds(8));
+ break;
+ case MOVEID_EVENT3:
+ Events.ScheduleEvent(EVENT_MALCOLM_FACE3, Seconds(0));
+ Events.ScheduleEvent(EVENT_MALCOLM3, Seconds(1));
+ Events.ScheduleEvent(EVENT_MALCOLM4, Seconds(6));
+ Events.ScheduleEvent(EVENT_MALCOLM_MOVE2, Seconds(12));
+ break;
+ case MOVEID_EVENT4:
+ me->DespawnOrUnsummon();
+ break;
+ case MOVEID_EVENT5:
+ Events.ScheduleEvent(EVENT_SCRUFFY_EMOTE, Seconds(0));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ Events.Update(diff);
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SCRUFFY1:
+ if (Creature* scruffy = me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true))
{
- Unit* jaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f);
- if (!jaina)
- jaina = me->SummonCreature(NPC_JAINA, 1895.48f, 1292.66f, 143.706f, 0.023475f, TEMPSUMMON_DEAD_DESPAWN, 180000);
- if (jaina)
- jainaGUID = jaina->GetGUID();
- bStepping = false;
- JumpToNextStep(0);
- break;
+ scruffy->SetFacingTo(scruffyFacing2);
+ scruffy->AI()->Talk(LINE_SCRUFFY1);
}
- //After waypoint 0
- case 1:
- me->SetWalk(false);
- if (Unit* uther = me->SummonCreature(NPC_UTHER, 1794.357f, 1272.183f, 140.558f, 1.37f, TEMPSUMMON_DEAD_DESPAWN, 180000))
- {
- utherGUID = uther->GetGUID();
- uther->SetWalk(false);
- uther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f);
- uther->SetTarget(me->GetGUID());
- me->SetTarget(utherGUID);
- }
- JumpToNextStep(17000);
- break;
- case 2:
- Talk(SAY_PHASE101);
- JumpToNextStep(2000);
- break;
- case 3:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- {
- uther->AI()->Talk(SAY_PHASE102);
- }
- JumpToNextStep(8000);
- break;
- case 4:
- SetEscortPaused(false);
- bStepping = false;
- SetRun(false);
- Talk(SAY_PHASE103);
- JumpToNextStep(0);
- break;
- //After waypoint 1
- case 5:
- if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID))
- jaina->SetTarget(me->GetGUID());
- Talk(SAY_PHASE104);
- JumpToNextStep(10000);
- break;
- case 6:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- uther->AI()->Talk(SAY_PHASE105);
- JumpToNextStep(1000);
- break;
- case 7:
- Talk(SAY_PHASE106);
- JumpToNextStep(4000);
- break;
- case 8:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- uther->AI()->Talk(SAY_PHASE107);
- JumpToNextStep(6000);
- break;
- case 9:
- Talk(SAY_PHASE108);
- JumpToNextStep(4000);
- break;
- case 10:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- uther->AI()->Talk(SAY_PHASE109);
- JumpToNextStep(8000);
- break;
- case 11:
- Talk(SAY_PHASE110);
- JumpToNextStep(4000);
- break;
- case 12:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- uther->AI()->Talk(SAY_PHASE111);
- JumpToNextStep(4000);
- break;
- case 13:
- Talk(SAY_PHASE112);
- JumpToNextStep(11000);
- break;
- case 14:
- if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID))
- jaina->AI()->Talk(SAY_PHASE113);
- JumpToNextStep(3000);
- break;
- case 15:
- Talk(SAY_PHASE114);
- JumpToNextStep(9000);
- break;
- case 16:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- uther->AI()->Talk(SAY_PHASE115);
- JumpToNextStep(4000);
- break;
- case 17:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- {
- uther->SetWalk(true);
- uther->GetMotionMaster()->MovePoint(0, 1794.357f, 1272.183f, 140.558f);
- }
- JumpToNextStep(1000);
- break;
- case 18:
- if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID))
- {
- me->SetTarget(jainaGUID);
- jaina->SetWalk(true);
- jaina->GetMotionMaster()->MovePoint(0, 1794.357f, 1272.183f, 140.558f);
- }
- JumpToNextStep(1000);
- break;
- case 19:
- Talk(SAY_PHASE116);
- JumpToNextStep(1000);
- break;
- case 20:
- if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID))
- jaina->AI()->Talk(SAY_PHASE117);
- JumpToNextStep(3000);
- break;
- case 21:
- SetEscortPaused(false);
- bStepping = false;
- me->SetTarget(ObjectGuid::Empty);
- JumpToNextStep(0);
- break;
- //After waypoint 3
- case 22:
- Talk(SAY_PHASE118);
- me->SetTarget(jainaGUID);
- JumpToNextStep(10000);
- break;
- case 23:
- SetEscortPaused(false);
- bStepping = false;
- SetRun(true);
+ break;
+ case EVENT_MALCOLM2:
+ if (Creature* scruffy = me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true))
+ {
+ Talk(LINE_MALCOLM2, scruffy);
+ me->SetFacingToObject(scruffy);
+ }
+ break;
+ case EVENT_SCRUFFY_MOVE:
+ if (Creature* scruffy = me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true))
+ scruffy->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT5, CHAIN_SCRUFFY2, false);
+ break;
+ case EVENT_MALCOLM_MOVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT3, CHAIN_MALCOLM3, true);
+ break;
+ case EVENT_SCRUFFY_EMOTE:
+ if (Creature* scruffy = me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true))
+ scruffy->HandleEmoteCommand(EMOTE_ONESHOT_CREATURE_SPECIAL);
+ break;
+ case EVENT_MALCOLM_FACE3:
+ me->SetFacingTo(malcolmFacing3);
+ break;
+ case EVENT_MALCOLM3:
+ Talk(LINE_MALCOLM3, me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true));
+ break;
+ case EVENT_MALCOLM4:
+ if (Creature* scruffy = me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true))
+ {
+ me->SetFacingToObject(scruffy);
+ Talk(LINE_MALCOLM4, scruffy);
+ }
+ break;
+ case EVENT_MALCOLM_MOVE2:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT4, CHAIN_MALCOLM4, true);
+ if (Creature* scruffy = me->FindNearestCreature(NPC_SCRUFFY, 100.0f, true))
+ scruffy->SetFacingTo(scruffyFacing4);
+ break;
+ default:
+ break;
+ }
+ }
+ }
- if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID))
- jaina->DisappearAndDie();
+ EventMap Events;
+ };
- if (Creature* uther = ObjectAccessor::GetCreature(*me, utherGUID))
- uther->DisappearAndDie();
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_malcolm_mooreAI>(creature);
+ }
+};
- me->SetTarget(ObjectGuid::Empty);
- JumpToNextStep(0);
- break;
- //After Gossip 1 (waypoint 8)
- case 24:
- if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET, 2026.469f, 1287.088f, 143.596f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 14000))
- {
- stalkerGUID = pStalker->GetGUID();
- me->SetTarget(stalkerGUID);
- }
+// Crate fluff event #4
+enum CrateEvent4Misc
+{
+ NPC_SERGEANT = 27877,
+ NPC_PERELLI = 27876,
+
+ EVENT_SERGEANT_IDLE1, // questioning
+ EVENT_SERGEANT_IDLE2, // response
+ EVENT_SERGEANT_CHAIN1,
+ EVENT_SERGEANT1,
+ EVENT_SERGEANT_STAND,
+ EVENT_PERELLI1,
+ EVENT_SERGEANT2,
+ EVENT_PERELLI2,
+ EVENT_SERGEANT3,
+ EVENT_SERGEANT_LEAVE,
+
+ LINE_SERGEANT_ASK_NO = 0,
+ LINE_SERGEANT_ASK_YES = 1,
+ LINE_SERGEANT_START = 2, // You don't mind me checking out your merchandise for signs of tampering, do you?
+ LINE_SERGEANT1 = 3, // Wait, what is this? You've been holding out on me, Perelli!
+ LINE_SERGEANT2 = 4, // I'm confiscating this suspicious grain, Perelli. We were looking for signs of tampered food, and it would be in your best interest to stay put while Prince Arthas checks this out.
+ LINE_SERGEANT3 = 5, // We'll see about that, Perelli. We'll see about that.
+ LINE_PERELLI_NO = 0,
+ LINE_PERELLI_YES = 1,
+ LINE_PERELLI1 = 2, // What are you talking about, Sergeant!
+ LINE_PERELLI2 = 3, // You have to believe me, I'm innocent!
+
+ CHAIN_SERGEANT1 = 1,
+ CHAIN_SERGEANT2 = 2
+};
- instance->DoUpdateWorldState(WORLDSTATE_WAVE_COUNT, 0);
+struct npc_sergeant_morigan : public CreatureScript
+{
+ npc_sergeant_morigan() : CreatureScript("npc_sergeant_morigan") { }
- JumpToNextStep(1000);
- break;
- case 25:
- Talk(SAY_PHASE201);
- JumpToNextStep(12000);
- break;
- case 26:
- SetEscortPaused(false);
- bStepping = false;
- SetRun(false);
- me->SetTarget(ObjectGuid::Empty);
- JumpToNextStep(0);
- break;
- //After waypoint 9
- case 27:
- me->SetTarget(citymenGUID[0]);
- if (Creature* cityman = ObjectAccessor::GetCreature(*me, citymenGUID[0]))
- {
- cityman->SetTarget(me->GetGUID());
- cityman->SetWalk(true);
- cityman->GetMotionMaster()->MovePoint(0, 2088.625f, 1279.191f, 140.743f);
- }
- JumpToNextStep(2000);
- break;
- case 28:
- if (Creature* cityman = ObjectAccessor::GetCreature(*me, citymenGUID[0]))
- cityman->AI()->Talk(SAY_PHASE202);
- JumpToNextStep(4000);
- break;
- case 29:
- SetEscortPaused(false);
- bStepping = false;
- Talk(SAY_PHASE203);
- JumpToNextStep(0);
- break;
- //After waypoint 10
- case 30:
- me->HandleEmoteCommand(37);
- JumpToNextStep(1000);
- break;
- case 31:
- SetEscortPaused(false);
- bStepping = false;
- if (Creature* cityman1 = ObjectAccessor::GetCreature(*me, citymenGUID[1]))
- {
- cityman1->AI()->Talk(SAY_PHASE204);
- cityman1->SetTarget(me->GetGUID());
- if (Creature* cityman0 = ObjectAccessor::GetCreature(*me, citymenGUID[0]))
- cityman0->KillSelf();
- me->SetTarget(citymenGUID[1]);
- }
- JumpToNextStep(0);
- break;
- //After waypoint 11
- case 32:
- me->HandleEmoteCommand(37);
- JumpToNextStep(1000);
- break;
- case 33:
- if (Creature* cityman1 = ObjectAccessor::GetCreature(*me, citymenGUID[1]))
- cityman1->KillSelf();
- JumpToNextStep(1000);
- break;
- case 34:
- if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET, 2081.447f, 1287.770f, 141.3241f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 10000))
- {
- stalkerGUID = pStalker->GetGUID();
- me->SetTarget(stalkerGUID);
- }
- Talk(SAY_PHASE205);
- JumpToNextStep(3000);
- break;
- case 35:
- if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET, 2117.349f, 1288.624f, 136.271f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 60000))
- {
- stalkerGUID = pStalkerM->GetGUID();
- me->SetTarget(stalkerGUID);
- }
- JumpToNextStep(1000);
- break;
- case 36:
- if (Creature* malganis = me->SummonCreature(NPC_MAL_GANIS, 2117.349f, 1288.624f, 136.271f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 60000))
- {
- if (Creature* pStalkerM = ObjectAccessor::GetCreature(*me, stalkerGUID))
- malganis->CastSpell(pStalkerM, 63793, false);
+ static Creature* Find(Creature* helper)
+ {
+ return helper->FindNearestCreature(NPC_SERGEANT, 15.0f, true);
+ }
- malganisGUID = malganis->GetGUID();
- malganis->AI()->Talk(SAY_PHASE206);
- malganis->SetTarget(me->GetGUID());
- malganis->SetReactState(REACT_PASSIVE);
- }
- JumpToNextStep(11000);
- break;
- case 37:
- if (Creature* malganis = ObjectAccessor::GetCreature(*me, malganisGUID))
- {
- Creature* pZombie = GetClosestCreatureWithEntry(malganis, NPC_CITY_MAN, 100.0f);
- if (!pZombie)
- pZombie = GetClosestCreatureWithEntry(malganis, NPC_CITY_MAN2, 100.0f);
- if (pZombie)
- pZombie->UpdateEntry(NPC_ZOMBIE);
- else //There's no one else to transform
- step++;
- }
- else
- step++;
- phaseTimer = 500;
- break;
- case 38:
- if (Creature* malganis = ObjectAccessor::GetCreature(*me, malganisGUID))
- malganis->AI()->Talk(SAY_PHASE207);
- JumpToNextStep(17000);
- break;
- case 39:
- if (Creature* malganis = ObjectAccessor::GetCreature(*me, malganisGUID))
- malganis->SetVisible(false);
- Talk(SAY_PHASE208);
- JumpToNextStep(7000);
- break;
- case 40:
- if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET, 2081.447f, 1287.770f, 141.3241f, 1.37f, TEMPSUMMON_TIMED_DESPAWN, 10000))
- {
- stalkerGUID = pStalker->GetGUID();
- me->SetTarget(stalkerGUID);
- }
- Talk(SAY_PHASE209);
+ struct npc_sergeant_moriganAI : public NullCreatureAI
+ {
+ npc_sergeant_moriganAI(Creature* creature) : NullCreatureAI(creature), Started(false) { }
- bossEvent = DATA_MEATHOOK;
- instance->SetBossState(DATA_ARTHAS, IN_PROGRESS);
+ void InitializeAI() override
+ {
+ Events.RescheduleEvent(EVENT_SERGEANT_IDLE1, Seconds(5), Seconds(15));
+ }
- me->SetReactState(REACT_DEFENSIVE);
- JumpToNextStep(5000);
- break;
- // Summon wave groups - start the Infinite Corruptor timer
- case 41:
- case 43:
- case 45:
- case 47:
- case 51:
- case 53:
- case 55:
- case 57:
- if (!wave && IsHeroic() && instance->GetData(DATA_INFINITE_COUNTER) == NOT_STARTED)
- instance->SetData(DATA_INFINITE_COUNTER, IN_PROGRESS);
-
- if (instance->GetBossState(bossEvent) != DONE)
- {
- SpawnWaveGroup(wave, waveGUID);
- wave++;
- WavesCounter++;
- instance->DoUpdateWorldState(WORLDSTATE_WAVE_COUNT, WavesCounter);
- }
- JumpToNextStep(500);
- break;
- case 42: //Wait group to die
- case 44:
- case 46:
- case 48:
- case 52:
- case 54:
- case 56:
- case 58:
- if (instance->GetBossState(bossEvent) != DONE)
- {
- uint32 mobCounter = 0;
- uint32 deadCounter = 0;
- for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i)
- {
- if (waveGUID[i].IsEmpty())
- break;
- ++mobCounter;
- Unit* temp = ObjectAccessor::GetCreature(*me, waveGUID[i]);
- if (!temp || temp->isDead())
- ++deadCounter;
- }
+ void DoAction(int32 id) override
+ {
+ if (id == ACTION_START_FLUFF)
+ Started = true;
+ }
- if (mobCounter <= deadCounter) //If group is dead
- JumpToNextStep(1000);
- else
- phaseTimer = 1000;
- }
- else
- JumpToNextStep(500);
- break;
- case 49: //Summon Boss
- case 59:
- if (instance->GetBossState(bossEvent) != DONE)
- {
- WavesCounter++;
- instance->DoUpdateWorldState(WORLDSTATE_WAVE_COUNT, WavesCounter);
- uint32 uiBossID = 0;
- if (bossEvent == DATA_MEATHOOK)
- uiBossID = NPC_MEATHOOK;
- else if (bossEvent == DATA_SALRAMM)
- uiBossID = NPC_SALRAMM;
-
- if (Unit* pBoss = me->SummonCreature(uiBossID, 2232.19f, 1331.933f, 126.662f, 3.15f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
- {
- bossGUID = pBoss->GetGUID();
- pBoss->SetWalk(true);
- pBoss->GetMotionMaster()->MovePoint(0, 2194.110f, 1332.00f, 130.00f);
- }
- }
- JumpToNextStep(30000);
- break;
- case 50: //Wait Boss death
- case 60:
- if (instance->GetBossState(bossEvent) == DONE)
- {
- JumpToNextStep(1000);
- if (bossEvent == DATA_MEATHOOK)
- bossEvent = DATA_SALRAMM;
- else if (bossEvent == DATA_SALRAMM)
- {
- SetHoldState(false);
- bStepping = false;
- bossEvent = DATA_EPOCH;
- }
- }
- else if (instance->GetBossState(bossEvent) == FAIL)
- EscortAI::EnterEvadeMode();
- else
- phaseTimer = 10000;
- break;
- //After Gossip 2 (waypoint 22)
- case 61:
- me->SetReactState(REACT_AGGRESSIVE);
- if (Creature* disguised0 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[0]))
- disguised0->SetTarget(me->GetGUID());
- if (Creature* disguised1 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[1]))
- disguised1->SetTarget(me->GetGUID());
- if (Creature* disguised2 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[2]))
- disguised2->SetTarget(me->GetGUID());
- JumpToNextStep(1000);
- break;
- case 62:
- if (Creature* disguised0 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[0]))
- disguised0->AI()->Talk(SAY_PHASE302);
- JumpToNextStep(7000);
- break;
- case 63:
- Talk(SAY_PHASE303);
- SetHoldState(false);
- bStepping = false;
- JumpToNextStep(0);
- break;
- //After waypoint 23
- case 64:
- me->HandleEmoteCommand(54);
- JumpToNextStep(1000);
- break;
- case 65:
- if (Creature* disguised0 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[0]))
- disguised0->HandleEmoteCommand(11);
- JumpToNextStep(1000);
- break;
- case 66:
- Talk(SAY_PHASE304);
- JumpToNextStep(2000);
- break;
- case 67:
- if (Creature* disguised0 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[0]))
- disguised0->AI()->Talk(SAY_PHASE305);
- JumpToNextStep(1000);
- break;
- case 68:
- if (Creature* disguised2 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[2]))
- {
- disguised2->UpdateEntry(NPC_INFINITE_HUNTER);
- //Make them unattackable
- disguised2->SetImmuneToAll(true);
- disguised2->SetReactState(REACT_PASSIVE);
- }
- JumpToNextStep(2000);
- break;
- case 69:
- if (Creature* disguised1 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[1]))
- {
- disguised1->UpdateEntry(NPC_INFINITE_AGENT);
- //Make them unattackable
- disguised1->SetImmuneToAll(true);
- disguised1->SetReactState(REACT_PASSIVE);
- }
- JumpToNextStep(2000);
- break;
- case 70:
- if (Creature* disguised0 = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[0]))
- {
- disguised0->UpdateEntry(NPC_INFINITE_ADVERSARY);
- //Make them unattackable
- disguised0->SetImmuneToAll(true);
- disguised0->SetReactState(REACT_PASSIVE);
- }
- JumpToNextStep(2000);
- break;
- case 71:
- //After waypoint 26, 29, 31
- case 73:
- case 75:
- case 77:
- //Make cratures attackable
- for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i)
- if (Creature* temp = ObjectAccessor::GetCreature(*me, infiniteDraconianGUID[i]))
- {
- temp->SetImmuneToAll(false);
- temp->SetReactState(REACT_AGGRESSIVE);
- }
- JumpToNextStep(5000);
- break;
- case 72:
- case 74:
- case 76:
- if (me->IsInCombat())
- phaseTimer = 1000;
- else
- {
- if (step == 72)
- Talk(SAY_PHASE308);
- if (step == 74)
- Talk(SAY_PHASE308);
- if (step == 76)
- Talk(SAY_PHASE310);
- SetHoldState(false);
- bStepping = false;
- SetRun(true);
- JumpToNextStep(2000);
- }
- break;
- case 78:
- if (me->IsInCombat())
- phaseTimer = 1000;
- else
- {
- Talk(SAY_PHASE312);
- JumpToNextStep(5000);
- }
- break;
- case 79:
- Talk(SAY_PHASE313);
- JumpToNextStep(1000);
- break;
- case 80:
- if (instance->GetBossState(DATA_EPOCH) != DONE)
- {
- SpawnTimeRift(17, &epochGUID);
- if (Creature* epoch = ObjectAccessor::GetCreature(*me, epochGUID))
- epoch->AI()->Talk(SAY_PHASE314);
- me->SetTarget(epochGUID);
- }
- JumpToNextStep(18000);
- break;
- case 81:
- if (instance->GetBossState(DATA_EPOCH) != DONE)
- Talk(SAY_PHASE315);
- JumpToNextStep(6000);
- break;
- case 82:
- if (instance->GetBossState(DATA_EPOCH) != DONE)
- {
- if (Creature* epoch = ObjectAccessor::GetCreature(*me, epochGUID))
- {
- //Make Epoch attackable
- epoch->SetImmuneToAll(false);
- epoch->SetReactState(REACT_AGGRESSIVE);
- }
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == SPLINE_CHAIN_MOTION_TYPE)
+ switch (id)
+ {
+ case MOVEID_EVENT1:
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ Events.ScheduleEvent(EVENT_SERGEANT1, Seconds(1));
+ Events.ScheduleEvent(EVENT_SERGEANT_STAND, Seconds(3));
+ Events.ScheduleEvent(EVENT_PERELLI1, Seconds(7));
+ Events.ScheduleEvent(EVENT_SERGEANT2, Seconds(12));
+ Events.ScheduleEvent(EVENT_PERELLI2, Seconds(20));
+ Events.ScheduleEvent(EVENT_SERGEANT3, Seconds(26));
+ Events.ScheduleEvent(EVENT_SERGEANT_LEAVE, Seconds(31));
+ break;
+ case MOVEID_EVENT2:
+ me->DespawnOrUnsummon(Seconds(1));
+ break;
+ }
+ }
- }
- JumpToNextStep(1000);
- break;
- case 83:
- if (instance->GetBossState(DATA_EPOCH) == DONE)
- {
- gossipStep = 3;
- me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- bStepping = false;
- bossEvent = DATA_MAL_GANIS;
- JumpToNextStep(15000);
- }
- else if (instance->GetBossState(DATA_EPOCH) == FAIL)
- EscortAI::EnterEvadeMode();
- else
- phaseTimer = 10000;
- break;
- //After Gossip 4
- case 84:
- Talk(SAY_PHASE404);
- SetHoldState(false);
- bStepping = false;
- break;
- //After Gossip 5
- case 85:
- Talk(SAY_PHASE501);
- if (Creature* malganis = me->SummonCreature(NPC_MAL_GANIS, 2296.665f, 1502.362f, 128.362f, 4.961f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000))
- {
- malganisGUID = malganis->GetGUID();
- malganis->SetReactState(REACT_PASSIVE);
- }
- if (GameObject* gate = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MAL_GANIS_GATE_1)))
- gate->SetGoState(GO_STATE_ACTIVE);
- SetHoldState(false);
- bStepping = false;
- JumpToNextStep(0);
- break;
- //After waypoint 55
- case 86:
- Talk(SAY_PHASE502);
- JumpToNextStep(6000);
- me->SetTarget(malganisGUID);
- break;
- case 87:
- if (Creature* malganis = ObjectAccessor::GetCreature(*me, malganisGUID))
- {
- malganis->RemoveUnitFlag(UnitFlags(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_UNK_6 | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_UNK_15));
- malganis->SetReactState(REACT_AGGRESSIVE);
- }
- JumpToNextStep(1000);
- break;
- case 88:
- if (instance->GetBossState(DATA_MAL_GANIS) == DONE)
- {
- SetHoldState(false);
- JumpToNextStep(1000);
- }
- else if (instance->GetBossState(DATA_MAL_GANIS) == FAIL)
- EscortAI::EnterEvadeMode();
- else
- phaseTimer = 10000;
- break;
- //After waypoint 56
- case 89:
- SetRun(true);
- me->SetTarget(malganisGUID);
- Talk(SAY_PHASE503);
- JumpToNextStep(7000);
- break;
- case 90:
- instance->SetBossState(DATA_ARTHAS, DONE); //Rewards: Achiev & Chest ;D
- me->SetTarget(instance->GetGuidData(DATA_MAL_GANIS_GATE_2)); //Look behind
- Talk(SAY_PHASE504);
- bStepping = false;
- break;
- }
- } else phaseTimer -= diff;
+ void Perelli(uint32 line, float ori = 0.0f)
+ {
+ if (Creature* perelli = me->FindNearestCreature(NPC_PERELLI, 10.0f, true))
+ {
+ perelli->AI()->Talk(line, me);
+ if (ori)
+ perelli->SetFacingTo(ori);
}
+ }
- //Battling skills
- if (!me->GetVictim())
- return;
-
- if (exorcismTimer < diff)
+ void UpdateAI(uint32 diff) override
+ {
+ Events.Update(diff);
+ while (uint32 eventId = Events.ExecuteEvent())
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_EXORCISM_N);
- exorcismTimer = 7300;
- } else exorcismTimer -= diff;
+ switch (eventId)
+ {
+ case EVENT_SERGEANT_IDLE1:
+ if (Started)
+ {
+ Question = 2;
+ Talk(LINE_SERGEANT_START);
+ }
+ else
+ {
+ Question = urand(0, 1); // 0 is question that's answered with "yes", 1 is question that's answered with "no"
+ Talk(Question ? LINE_SERGEANT_ASK_NO : LINE_SERGEANT_ASK_YES);
+ }
+ Events.ScheduleEvent(EVENT_SERGEANT_IDLE2, Seconds(10));
+ break;
+ case EVENT_SERGEANT_IDLE2:
+ Perelli(Question ? LINE_PERELLI_NO : LINE_PERELLI_YES);
+ if (Question == 2)
+ Events.ScheduleEvent(EVENT_SERGEANT_CHAIN1, Seconds(2));
+ else
+ Events.ScheduleEvent(EVENT_SERGEANT_IDLE1, Seconds(15), Seconds(30));
+ break;
+ case EVENT_SERGEANT_CHAIN1:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_SERGEANT1, true);
+ break;
+ case EVENT_SERGEANT1:
+ Talk(LINE_SERGEANT1);
+ break;
+ case EVENT_SERGEANT_STAND:
+ me->SetFacingTo(2.617994f);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ break;
+ case EVENT_PERELLI1:
+ Perelli(LINE_PERELLI1, 5.916666f);
+ break;
+ case EVENT_SERGEANT2:
+ Talk(LINE_SERGEANT2);
+ break;
+ case EVENT_PERELLI2:
+ Perelli(LINE_PERELLI2);
+ break;
+ case EVENT_SERGEANT3:
+ Talk(LINE_SERGEANT3);
+ break;
+ case EVENT_SERGEANT_LEAVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT2, CHAIN_SERGEANT2, true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ EventMap Events;
+ bool Started;
+ uint8 Question;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_sergeant_moriganAI>(creature);
+ }
+};
+
+// Crate fluff event #5
+enum CrateEvent5Misc
+{
+ NPC_ROGER = 27903,
+
+ EVENT_ROGER_START = 1,
+ EVENT_ROGER_MOVE1,
+ EVENT_ROGER_FACE3,
+ EVENT_ROGER3,
+ EVENT_ROGER_FACE4,
+ EVENT_ROGER4,
+ EVENT_ROGER_MOVE2,
+ EVENT_ROGER5_2,
+ EVENT_ROGER_LEAVE,
+
+ LINE_ROGER1 = 0, // Ok, enough work for now. Time for refreshments and a little conversation in the inn.
+ LINE_ROGER2 = 1, // Wait, what's that smell?
+ LINE_ROGER3 = 2, // Can't be me, I took a bath 3 days ago!
+ LINE_ROGER4 = 3, // Oh, close call. It's just the grain here.
+ LINE_ROGER5 = 4, // Wait a second. Grain isn't supposed to smell like THAT! I better go find a guard.
+
+ CHAIN_ROGER1 = 1,
+ CHAIN_ROGER2 = 2,
+ CHAIN_ROGER3 = 3
+};
- if (HealthBelowPct(40))
- DoCast(me, SPELL_HOLY_LIGHT);
+struct npc_roger_owens : public CreatureScript
+{
+ npc_roger_owens() : CreatureScript("npc_roger_owens") { }
- DoMeleeAttackIfReady();
+ static Creature* Find(Creature* helper)
+ {
+ return helper->FindNearestCreature(NPC_ROGER, 30.0f, true);
+ }
+
+ struct npc_roger_owensAI : public NullCreatureAI
+ {
+ npc_roger_owensAI(Creature* creature) : NullCreatureAI(creature) { }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_START_FLUFF)
+ Events.ScheduleEvent(EVENT_ROGER_START, Seconds(5), Seconds(12));
}
- bool GossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ void MovementInform(uint32 type, uint32 id) override
{
- uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
- ClearGossipMenuFor(player);
- switch (action)
+ if (type == SPLINE_CHAIN_MOTION_TYPE)
{
- case GOSSIP_ACTION_INFO_DEF:
- Start(true, true, player->GetGUID(), nullptr, false, false);
- SetDespawnAtEnd(false);
- bStepping = false;
- step = 1;
- break;
- case GOSSIP_ACTION_INFO_DEF + 1:
- bStepping = true;
- step = 24;
- break;
- case GOSSIP_ACTION_INFO_DEF + 2:
- SetHoldState(false);
- bStepping = false;
- step = 61;
- break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- SetHoldState(false);
- break;
- case GOSSIP_ACTION_INFO_DEF + 4:
- bStepping = true;
- step = 84;
- break;
- case GOSSIP_ACTION_INFO_DEF + 5:
- bStepping = true;
- step = 85;
- break;
+ switch (id)
+ {
+ case MOVEID_EVENT1:
+ Talk(LINE_ROGER2);
+ Events.ScheduleEvent(EVENT_ROGER_FACE3, Seconds(5));
+ Events.ScheduleEvent(EVENT_ROGER3, Seconds(6));
+ Events.ScheduleEvent(EVENT_ROGER_FACE4, Seconds(12));
+ Events.ScheduleEvent(EVENT_ROGER4, Seconds(14));
+ Events.ScheduleEvent(EVENT_ROGER_MOVE2, Seconds(18));
+ break;
+ case MOVEID_EVENT2:
+ me->SetFacingTo(1.134464f, true);
+ Talk(LINE_ROGER5);
+ Events.ScheduleEvent(EVENT_ROGER5_2, Seconds(3));
+ Events.ScheduleEvent(EVENT_ROGER_LEAVE, Seconds(8));
+ break;
+ case MOVEID_EVENT3:
+ me->DespawnOrUnsummon(Seconds(1));
+ break;
+ default:
+ break;
+ }
}
- CloseGossipMenuFor(player);
- SetDespawnAtFar(false);
- me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
- return true;
}
- bool GossipHello(Player* player) override
+ void UpdateAI(uint32 diff) override
{
- if (!bStepping)
+ Events.Update(diff);
+ while (uint32 eventId = Events.ExecuteEvent())
{
- switch (gossipStep)
+ switch (eventId)
{
- case 0: //This one is a workaround since the very beggining of the script is wrong.
- {
- QuestStatus status = player->GetQuestStatus(13149);
- if (status != QUEST_STATUS_COMPLETE && status != QUEST_STATUS_REWARDED)
- return true;
- AddGossipItemFor(player, GossipOptionIcon::None, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
- SendGossipMenuFor(player, 907, me->GetGUID());
+ case EVENT_ROGER_START:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ me->SetFacingTo(1.53589f);
+ Talk(LINE_ROGER1);
+ Events.ScheduleEvent(EVENT_ROGER_MOVE1, Seconds(6));
break;
- }
- case 1:
- AddGossipItemFor(player, GossipOptionIcon::None, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_1, me->GetGUID());
+ case EVENT_ROGER_MOVE1:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT1, CHAIN_ROGER1, true);
+ break;
+ case EVENT_ROGER_FACE3:
+ me->SetFacingTo(6.265732f);
+ break;
+ case EVENT_ROGER3:
+ Talk(LINE_ROGER3);
break;
- case 2:
- AddGossipItemFor(player, GossipOptionIcon::None, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_2, me->GetGUID());
+ case EVENT_ROGER_FACE4:
+ me->SetFacingTo(4.520403f);
break;
- case 3:
- AddGossipItemFor(player, GossipOptionIcon::None, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_3, me->GetGUID());
+ case EVENT_ROGER4:
+ Talk(LINE_ROGER4);
break;
- case 4:
- AddGossipItemFor(player, GossipOptionIcon::None, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_4, me->GetGUID());
+ case EVENT_ROGER_MOVE2:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT2, CHAIN_ROGER2, true);
break;
- case 5:
- AddGossipItemFor(player, GossipOptionIcon::None, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_5, me->GetGUID());
+ case EVENT_ROGER5_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ break;
+ case EVENT_ROGER_LEAVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(MOVEID_EVENT3, CHAIN_ROGER3, true);
break;
default:
- return false;
+ break;
}
}
- return true;
}
+
+ EventMap Events;
};
CreatureAI* GetAI(Creature* creature) const override
{
- return GetCullingOfStratholmeAI<npc_arthasAI>(creature);
+ return GetCullingOfStratholmeAI<npc_roger_owensAI>(creature);
}
};
+enum CrateMisc
+{
+ GO_SUSPICIOUS_CRATE = 190094,
+ GO_CRATE_HIGHLIGHT = 190117,
+ GO_PLAGUED_CRATE = 190095,
+ SPELL_ARCANE_DISRUPTION = 49590,
+ SPELL_CRATES_CREDIT = 58109
+};
+
class npc_crate_helper : public CreatureScript
{
- public:
- npc_crate_helper() : CreatureScript("npc_create_helper_cot") { }
+public:
+ npc_crate_helper() : CreatureScript("npc_crate_helper_cot") { }
+
+ struct npc_crate_helperAI : public NullCreatureAI
+ {
+ npc_crate_helperAI(Creature* creature) : NullCreatureAI(creature), _crateRevealed(false) { }
- struct npc_crate_helperAI : public NullCreatureAI
+ void ReplaceIfCloser(Creature* candidate, Creature*& current, float& currentDist) const
{
- npc_crate_helperAI(Creature* creature) : NullCreatureAI(creature)
- {
- _marked = false;
- }
+ if (!candidate)
+ return;
+ float newDist = me->GetExactDist2dSq(candidate);
+ if (newDist >= currentDist)
+ return;
+ currentDist = newDist;
+ current = candidate;
+ }
- void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (!_crateRevealed && spell->Id == SPELL_ARCANE_DISRUPTION)
{
- if (spell->Id == SPELL_ARCANE_DISRUPTION && !_marked)
+ _crateRevealed = true;
+ if (InstanceScript* instance = me->GetInstanceScript())
{
- _marked = true;
- if (InstanceScript* instance = me->GetInstanceScript())
- instance->SetData(DATA_CRATE_COUNT, instance->GetData(DATA_CRATE_COUNT) + 1);
+ // Update world state
+ instance->SetData(DATA_CRATE_REVEALED, 1);
+
+ // Replace suspicious crate with plagued crate
if (GameObject* crate = me->FindNearestGameObject(GO_SUSPICIOUS_CRATE, 5.0f))
{
- crate->SummonGameObject(GO_PLAGUED_CRATE, *crate, QuaternionData::fromEulerAnglesZYX(crate->GetOrientation(), 0.0f, 0.0f), DAY);
+ crate->SummonGameObject(GO_PLAGUED_CRATE, *crate, crate->GetWorldRotation(), DAY);
crate->Delete();
}
+ if (GameObject* highlight = me->FindNearestGameObject(GO_CRATE_HIGHLIGHT, 5.0f))
+ highlight->Delete();
+
+ // Find nearest fluff event and initiate it
+ Creature* closest = nullptr;
+ float closestDist = INFINITY;
+ ReplaceIfCloser(npc_jena_anderson::Find(me), closest, closestDist);
+ ReplaceIfCloser(npc_bartleby_battson::Find(me), closest, closestDist);
+ ReplaceIfCloser(npc_sergeant_morigan::Find(me), closest, closestDist);
+ ReplaceIfCloser(npc_roger_owens::Find(me), closest, closestDist);
+ if (closest)
+ closest->AI()->DoAction(ACTION_START_FLUFF);
+ else
+ npc_malcolm_moore::Spawn(me->GetMap());
}
}
+ }
- private:
- bool _marked;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+ uint32 GetData(uint32 data) const override
{
- return GetCullingOfStratholmeAI<npc_crate_helperAI>(creature);
+ if (data == DATA_CRATE_REVEALED)
+ return _crateRevealed ? 1 : 0;
+ return 0;
}
+
+ private:
+ bool _crateRevealed;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_crate_helperAI>(creature);
+ }
};
void AddSC_culling_of_stratholme()
{
- new npc_arthas();
+ new npc_hearthsinger_forresten_cot();
+ new at_stratholme_inn_stairs_cot();
+
+ new npc_chromie_start();
+ new npc_chromie_middle();
+
+ new npc_jena_anderson();
+ new npc_martha_goslin();
+ new npc_bartleby_battson();
+ new npc_malcolm_moore();
+ new npc_sergeant_morigan();
+ new npc_roger_owens();
new npc_crate_helper();
}
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h
index a9b9f4a9698..a4ead46b8a4 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h
@@ -15,92 +15,156 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DEF_CULLING_OF_STRATHOLME_H
-#define DEF_CULLING_OF_STRATHOLME_H
+#ifndef CULLING_OF_STRATHOLME_H
+#define CULLING_OF_STRATHOLME_H
#include "CreatureAIImpl.h"
-#define CoSScriptName "instance_culling_of_stratholme"
#define DataHeader "CS"
+#define CoSScriptName "instance_culling_of_stratholme"
-uint32 const EncounterCount = 5;
-
-enum CSDataTypes
-{
- DATA_ARTHAS,
- DATA_MEATHOOK,
- DATA_SALRAMM,
- DATA_EPOCH,
- DATA_MAL_GANIS,
- DATA_INFINITE,
- DATA_CRATE_COUNT,
- DATA_SHKAF_GATE,
- DATA_MAL_GANIS_GATE_1,
- DATA_MAL_GANIS_GATE_2,
- DATA_EXIT_GATE,
- DATA_MAL_GANIS_CHEST,
- DATA_INFINITE_COUNTER
-};
+uint32 constexpr EncounterCount = 5;
-enum CSCreatureIds
-{
- NPC_MEATHOOK = 26529,
- NPC_SALRAMM = 26530,
- NPC_EPOCH = 26532,
- NPC_MAL_GANIS = 26533,
- NPC_INFINITE = 32273,
- NPC_ARTHAS = 26499,
- NPC_JAINA = 26497,
- NPC_UTHER = 26528,
- NPC_CHROMIE = 26527,
- NPC_CHROMIE_2 = 27915,
- NPC_CHROMIE_3 = 30997,
- NPC_GENERIC_BUNNY = 28960,
+/***********************************************************************************************************************\
+|************************* A DEVELOPER'S GUIDE TO FINDING YOUR WAY AROUND THIS INSTANCE SCRIPT *************************|
+|***********************************************************************************************************************|
+* The primary instance logic is split between the instance control script (instance_culling_of_stratholme.cpp) and *
+* Arthas' creature AI (npc_arthas.cpp). The instance script is responsible for global state management and control *
+* of the Scourge Wave event, as well as spawn control (ties into state management) with the help of the templated *
+* CreatureScript wrapper (CanSpawn override as well as Despawn checks on state change) defined in this very header. *
+* Arthas handles all the actual RP timings, pathing, spawns, casts and everything else, really. He also does tons *
+* of state control for himself (positional snapback and gossip/flag management). *
+* Communication between these two scripts (with some auxiliary other scripts throwing stuff in too) is handled *
+* via the SetData/SetGuidData/SetGUID methods on CreatureAI and InstanceScript (as appropriate), as well as *
+* data retrieval using GetData (instance states and the like). *
+* All values specified in this header find use across multiple files (used for communication between them) while *
+* the enums in the files themselves contain action IDs, event IDs, entries and whatnot that only find use in that *
+* particular file. *
+* Generally, any RP sequence will follow the form: *
+* 1. RP sequence is started (creature gossip sends SetGuidData with starting player GUID to InstanceScript) *
+* 2. InstanceScript verifies state consistency and advances the global instance state *
+* 3. InstanceScript passes the player GUID to Arthas AI using SetGUID. The int32 data type serves as action ID. *
+* 4. Arthas AI schedules all necessary events for the sequence and handles it from there using its UpdateAI loop. *
+* 5. At the end of the sequence, Arthas AI notifies the instance script (using SetData). *
+* 6. The instance script advances the global state again. This state change is propagated to Arthas AI (SetData). *
+* 7. Arthas AI is notified of a state change, gets current progress (GetData) and adjusts gossip availability etc. *
+* 8. The cycle repeats. RP sequences (as above) can (and do) also include combat sequences and similar. *
+|***********************************************************************************************************************|
+|*********************************************** KEY METHODS TO LOOK FOR ***********************************************|
+|***********************************************************************************************************************|
+* Arthas AI: (npc_arthas_stratholmeAI in npc_arthas.cpp) *
+* - AdvanceToState: *
+* - handles all the state updating/position consistency logic *
+* - invoked from SetData when the instance script notifies Arthas of a state change *
+* - ScheduleActionOOC: *
+* - queues the specified action to be passed to DoAction after Arthas finishes combat (JustReachedHome) *
+* - typically called during RP sequences just after ensuring Arthas has entered combat with all enemies involved *
+* - MovementInform: *
+* - handles movement notifications not just for Arthas, but also some other creatures that run RP slave AI *
+* - all movement IDs are taken from one single PointIDs enum, which means they are still unique *
+* - EnterCombat: *
+* - stores the current spline chain state so we can resume after (JustReachedHome) *
+|***********************************************************************************************************************|
+* Instance script: (instance_culling_of_stratholme in instance_culling_of_stratholme.cpp) *
+* - GetStableStateFor: *
+* - handles state regression; only certain states should be loaded after a wipe/soft reset *
+* - SetInstanceProgress: *
+* - any changing of the global instance state is done through this method *
+* - handles world state adjustments, spawn control (through AI notification) as well as reset behavior *
+* - SetWorldState/PropagateWorldStateUpdate: *
+* - the instance script stores a std::map of all current world state values for the instance *
+* - SetWorldState adjusts this map, PropagateWorldStateUpdate sends any changed values to all players *
+* - FillInitialWorldStates also draws upon this map to ensure all players have the same states at all times *
+|***********************************************************************************************************************|
+* Spawn control script: (StratholmeCreatureScript<ParentAI> in culling_of_stratholme.h) *
+* - CanSpawn override: *
+* - gets current instance state using GetData, then checks if we should be allowed to respawn (bitmask check) *
+* - StratholmeNPCAIWrapper::CheckDespawn: *
+* - gets current instance state using GetData, then checks if we should despawn ourselves (bitmask check) *
+\***********************************************************************************************************************/
- NPC_TIME_RIFT = 28409,
- NPC_GUARDIAN_OF_TIME = 32281
-};
+struct Position;
-enum CSGameObjectIds
+// Note: These are bitmask values to allow combining, but only a single bit will ever be true in instance script
+enum COSProgressStates : uint32
{
- GO_SHKAF_GATE = 188686,
- GO_MALGANIS_GATE_1 = 187711,
- GO_MALGANIS_GATE_2 = 187723,
- GO_EXIT_GATE = 191788,
- GO_MALGANIS_CHEST_N = 190663,
- GO_MALGANIS_CHEST_H = 193597,
- GO_SUSPICIOUS_CRATE = 190094,
- GO_PLAGUED_CRATE = 190095
-};
+ JUST_STARTED = 0x00001, // dungeon just started, crate count not visible yet; pending chromie interaction
+ CRATES_IN_PROGRESS = 0x00002, // freshly started dungeon, players are revealing scourge crates
+ CRATES_DONE = 0x00004, // all crates revealed, chromie spawns at Stratholme entrance; waiting for player input to begin first RP event
+ UTHER_TALK = 0x00008, // RP event in progress, Uther+Arthas talking
+ PURGE_PENDING = 0x00010, // RP event done, pending player input to start wave event
+ PURGE_STARTING = 0x00020, // Arthas entering Stratholme, RP sequence with Mal'ganis
+ WAVES_IN_PROGRESS = 0x00040, // first section is underway, players are battling waves
+ WAVES_DONE = 0x00080, // wave section completed; Arthas moving to take position in front of Stratholme Town Hall
+ TOWN_HALL_PENDING = 0x00100, // Arthas has reached the Town Hall; pending player input to begin escort section
+ TOWN_HALL = 0x00200, // now escorting Arthas through Stratholme Town Hall
+ TOWN_HALL_COMPLETE = 0x00400, // Town Hall event complete, third boss defeated; pending player input to begin gauntlet transition
+ GAUNTLET_TRANSITION = 0x00800, // Arthas is leading players through the secret passage from Town Hall to the gauntlet
+ GAUNTLET_PENDING = 0x01000, // Pending player input to begin escorting Arthas through the final gauntlet section
+ GAUNTLET_IN_PROGRESS = 0x02000, // Arthas is being escorted through the gauntlet section
+ GAUNTLET_COMPLETE = 0x04000, // Arthas has reached the end of the gauntlet section; player input pending to begin Mal'ganis encounter
+ MALGANIS_IN_PROGRESS = 0x08000, // Arthas has moved into the final square and Mal'ganis encounter begins
+ COMPLETE = 0x10000, // Mal'ganis encounter is completed; dungeon over
-enum CSWorldStatesCoT
-{
- WORLDSTATE_SHOW_CRATES = 3479,
- WORLDSTATE_CRATES_REVEALED = 3480,
- WORLDSTATE_WAVE_COUNT = 3504,
- WORLDSTATE_TIME_GUARDIAN = 3931,
- WORLDSTATE_TIME_GUARDIAN_SHOW = 3932
+ ALL = 0x1FFFF
};
+COSProgressStates GetStableStateFor(COSProgressStates const state); // defined by instance script
+Position const& GetArthasSnapbackFor(COSProgressStates state); // defined by arthas script
-enum CSCrateSpells
+enum COSInstanceData
{
- SPELL_CRATES_CREDIT = 58109
+ DATA_MEATHOOK,
+ DATA_SALRAMM,
+ DATA_EPOCH,
+ DATA_MAL_GANIS,
+ DATA_INFINITE_CORRUPTOR,
+ NUM_BOSS_ENCOUNTERS,
+
+ DATA_INSTANCE_PROGRESS = NUM_BOSS_ENCOUNTERS, // GET only
+ DATA_GM_RECALL, // sent by chromie #1 in response to GM recall command (teleport all to arthas)
+ DATA_GM_OVERRIDE, // sent by chromie #1 in response to GM instance state change commands
+ DATA_ARTHAS_DIED, // failure signal, sent by arthas AI on death - regress instance
+ DATA_CRATES_START, // sent by chromie #1 creature script to initiate crate phase
+ DATA_CRATE_REVEALED, // sent by crate helper AI to trigger re-check of crate status
+ DATA_UTHER_START, // sent by chromie #2 creature script to initiate uther RP sequence
+ DATA_UTHER_FINISHED, // sent by arthas AI to signal transition to pre-purge
+ DATA_SKIP_TO_PURGE, // sent by chromie #1 creature script to skip straight to start of purge
+ DATA_START_PURGE, // sent by arthas creature script to begin pre-purge RP event
+ DATA_START_WAVES, // sent by arthas AI to begin wave event
+ DATA_NOTIFY_DEATH, // sent by wave mob AI to instance script on death
+ DATA_REACH_TOWN_HALL, // sent by arthas AI once he reaches stratholme town hall
+ DATA_START_TOWN_HALL, // sent by arthas creature script to begin town hall sequence
+ DATA_TOWN_HALL_DONE, // sent by arthas AI once Epoch is defeated
+ DATA_TO_GAUNTLET, // sent by arthas creature script to begin gauntlet transition
+ DATA_GAUNTLET_REACHED, // sent by arthas AI once he arrives at the beginning of the gauntlet section
+ DATA_START_GAUNTLET, // sent by arthas creature script to begin gauntlet escort
+ DATA_GAUNTLET_DONE, // sent by arthas AI once he arrives at the end of the gauntlet section
+ DATA_START_MALGANIS, // sent by arthas creature script to begin mal'ganis event
+ DATA_MALGANIS_DONE // sent by arthas AI once mal'ganis outro is over
};
-enum CSTexts
+// these are sent by instance AI to creatures; they are passed as negative values to avoid conflicts with creature script specific actions
+enum COSInstanceActions
{
- SAY_CRATES_COMPLETED = 0,
- // Chromie
- SAY_INFINITE_START = 0, // On Infinite Corruptor event start
- SAY_INFINITE = 1, // On Infinite Corruptor event at 5 minutes
- SAY_INFINITE_FAIL = 2, // On Infinite Corruptor event fail
- // Infinite Corruptor
- SAY_FAIL_EVENT = 2 // On Infinite Corruptor event fail
+ ACTION_PROGRESS_UPDATE = 1,
+ ACTION_CORRUPTOR_LEAVE,
+ ACTION_START_RP_EVENT1, // Arthas/Uther chat in front of town
+ ACTION_START_RP_EVENT2, // Arthas/Mal'ganis chat at entrance
+ ACTION_START_RP_EVENT3, // Town Hall sequence
+ ACTION_START_RP_EVENT4_1, // Bookcase transition sequence
+ ACTION_START_RP_EVENT4_2, // Gauntlet escort phase
+ ACTION_START_RP_EVENT5 // Mal'ganis encounter
};
-enum CSInstanceEvents
+enum COSInstanceEntries
{
- EVENT_INFINITE_TIMER = 1
+ NPC_ARTHAS = 26499,
+ GO_HIDDEN_PASSAGE = 188686,
+ SPAWNGRP_CHROMIE_MID = 52,
+ SPAWNGRP_CRATE_HELPERS = 53,
+ SPAWNGRP_GAUNTLET_TRASH = 54,
+ SPAWNGRP_UNDEAD_TRASH = 55,
+ SPAWNGRP_RESIDENTS = 56
};
template <class AI, class T>
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
index a16cfdf95ea..54223d08184 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp
@@ -20,30 +20,108 @@
#include "CreatureAI.h"
#include "EventMap.h"
#include "GameObject.h"
+#include "GameTime.h"
#include "InstanceScript.h"
#include "Map.h"
#include "MotionMaster.h"
+#include "Log.h"
+#include "Player.h"
#include "ScriptMgr.h"
#include "TemporarySummon.h"
#include "WorldStatePackets.h"
+#include <array>
+#include <sstream>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
-/* Culling of Stratholme encounters:
-0 - Meathook
-1 - Salramm the Fleshcrafter
-2 - Chrono-Lord Epoch
-3 - Mal'Ganis
-4 - Infinite Corruptor (Heroic only)
-*/
+/*
+ * Culling of Stratholme encounters:
+ * 0 - Meathook
+ * 1 - Salramm the Fleshcrafter
+ * 2 - Chrono-Lord Epoch
+ * 3 - Mal'Ganis
+ * 4 - Infinite Corruptor (Heroic only)
+ */
+
+enum COSEvents
+{
+ EVENT_GUARDIAN_TICK = 1,
+ EVENT_RESPAWN_ARTHAS,
+ EVENT_CRIER_CALL_TO_GATES,
+ EVENT_SCOURGE_WAVE,
+ EVENT_CRIER_ANNOUNCE_WAVE
+};
+
+enum COSEntries
+{
+ NPC_GENERIC_BUNNY = 28960,
+ NPC_CRATE_HELPER = 27827,
+ NPC_CHROMIE = 26527, // first chromie - we don't need the other two for anything
+ NPC_INFINITE_CORRUPTOR = 32273,
+ NPC_GUARDIAN_OF_TIME = 32281,
+ NPC_TIME_RIFT = 28409,
+ NPC_LORDAERON_CRIER = 27913,
+ NPC_DEVOURING_GHOUL = 28249,
+ NPC_ENRAGED_GHOUL = 27729,
+ NPC_NECROMANCER = 28200,
+ NPC_CRYPT_FIEND = 27734,
+ NPC_ACOLYTE = 27731,
+ NPC_CRYPT_STALKER = 28199,
+ NPC_ABOMINATION = 27736,
+ NPC_MEATHOOK = 26529,
+ NPC_SALRAMM = 26530,
+
+ GO_MALGANIS_GATE_2 = 187723,
+ GO_EXIT_GATE = 191788,
+
+ SPELL_CRATES_KILL_CREDIT = 58109
+};
+
+enum COSYells
+{
+ CRIER_SAY_CALL_TO_GATES = 0,
+ CRIER_SAY_KINGS_SQUARE = 1,
+ CRIER_SAY_MARKET_ROW = 2,
+ CRIER_SAY_FESTIVAL_LANE = 3,
+ CRIER_SAY_ELDERS_SQUARE = 4,
+ CRIER_SAY_TOWN_HALL = 5,
+
+ CHROMIE_WHISPER_GUARDIAN_1 = 0,
+ CHROMIE_WHISPER_GUARDIAN_2 = 1,
+ CHROMIE_WHISPER_GUARDIAN_3 = 2
+};
+
+enum COSWorldStates
+{
+ WORLDSTATE_SHOW_CRATES = 3479,
+ WORLDSTATE_CRATES_REVEALED = 3480,
+ WORLDSTATE_WAVE_COUNT = 3504,
+ WORLDSTATE_WAVE_MARKER_ES = 3581,
+ WORLDSTATE_WAVE_MARKER_FL = 3582,
+ WORLDSTATE_WAVE_MARKER_KS = 3583,
+ WORLDSTATE_WAVE_MARKER_MR = 3584,
+ WORLDSTATE_WAVE_MARKER_TH = 3585,
+ WORLDSTATE_TIME_GUARDIAN = 3931,
+ WORLDSTATE_TIME_GUARDIAN_SHOW = 3932
+};
-Position const ChromieSummonPos[] =
+enum COSWaveLocations
{
- { 1813.298f, 1283.578f, 142.3258f, 3.878161f },
- { 2273.725f, 1483.684f, 128.7205f, 6.057528f }
+ WAVE_LOC_MIN = CRIER_SAY_KINGS_SQUARE,
+ WAVE_LOC_MAX = CRIER_SAY_TOWN_HALL,
+ WAVE_MARKER_MIN = WORLDSTATE_WAVE_MARKER_ES,
+ WAVE_MARKER_MAX = WORLDSTATE_WAVE_MARKER_TH
};
-Position const InfiniteCorruptorPos = { 2335.47f, 1262.04f, 132.921f, 1.42079f };
-Position const TimeRiftPos = { 2334.626f, 1280.45f, 133.0066f, 1.727876f };
-Position const GuardianOfTimePos = { 2321.489f, 1268.383f, 132.8507f, 0.418879f };
+enum COSMisc
+{
+ NUM_PLAGUE_CRATES = 5,
+ NUM_SCOURGE_WAVES = 10,
+ MAX_SPAWNS_PER_WAVE = 6,
+ WAVE_MEATHOOK = 5,
+ WAVE_SALRAMM = 10
+};
DoorData const doorData[] =
{
@@ -52,295 +130,723 @@ DoorData const doorData[] =
{ 0, 0, DOOR_TYPE_ROOM } // END
};
+COSProgressStates GetStableStateFor(COSProgressStates const state)
+{
+ switch (state)
+ {
+ case JUST_STARTED:
+ default:
+ return JUST_STARTED;
+ case CRATES_IN_PROGRESS:
+ return CRATES_IN_PROGRESS;
+ case CRATES_DONE:
+ return CRATES_DONE;
+ case UTHER_TALK:
+ case PURGE_PENDING:
+ case PURGE_STARTING:
+ case WAVES_IN_PROGRESS:
+ return PURGE_PENDING;
+ case WAVES_DONE:
+ case TOWN_HALL_PENDING:
+ case TOWN_HALL:
+ return TOWN_HALL_PENDING;
+ case TOWN_HALL_COMPLETE:
+ case GAUNTLET_TRANSITION:
+ case GAUNTLET_PENDING:
+ case GAUNTLET_IN_PROGRESS:
+ return GAUNTLET_PENDING;
+ case GAUNTLET_COMPLETE:
+ case MALGANIS_IN_PROGRESS:
+ return GAUNTLET_COMPLETE;
+ case COMPLETE:
+ return COMPLETE;
+ }
+}
+
+static Position const CorruptorPos = { 2331.642f, 1273.273f, 132.9524f, 3.717551f };
+static Position const GuardianPos = { 2321.489f, 1268.383f, 132.8507f, 0.418879f };
+static Position const CorruptorRiftPos = { 2443.626f, 1280.450f, 133.0066f, 1.727876f };
+
+static std::array<std::array<uint32, MAX_SPAWNS_PER_WAVE>, NUM_SCOURGE_WAVES> const HeroicWaves =
+{
+ {
+ { { NPC_DEVOURING_GHOUL, NPC_DEVOURING_GHOUL, NPC_DEVOURING_GHOUL } }, // wave 1
+ { { NPC_DEVOURING_GHOUL, NPC_ENRAGED_GHOUL, NPC_NECROMANCER } }, // wave 2
+ { { NPC_DEVOURING_GHOUL, NPC_ENRAGED_GHOUL, NPC_NECROMANCER, NPC_CRYPT_FIEND } }, // wave 3
+ { { NPC_NECROMANCER, NPC_CRYPT_FIEND, NPC_ACOLYTE, NPC_ACOLYTE, NPC_ACOLYTE, NPC_ACOLYTE } }, // wave 4
+ { { 0 } }, // wave 5, meathook (special)
+ { { NPC_DEVOURING_GHOUL, NPC_NECROMANCER, NPC_CRYPT_FIEND, NPC_CRYPT_STALKER } }, // wave 6
+ { { NPC_DEVOURING_GHOUL, NPC_ENRAGED_GHOUL, NPC_ENRAGED_GHOUL, NPC_ABOMINATION } }, // wave 7
+ { { NPC_DEVOURING_GHOUL, NPC_ENRAGED_GHOUL, NPC_NECROMANCER, NPC_ABOMINATION } }, // wave 8
+ { { NPC_DEVOURING_GHOUL, NPC_NECROMANCER, NPC_CRYPT_FIEND, NPC_ABOMINATION } }, // wave 9
+ { { 0 } } // wave 10, salramm (special)
+ }
+};
+
+struct WaveLocation
+{
+ COSWorldStates const WorldState;
+ std::array<Position, MAX_SPAWNS_PER_WAVE> SpawnPoints;
+};
+
+static const std::array<WaveLocation, WAVE_LOC_MAX - WAVE_LOC_MIN + 1> WaveLocations =
+{
+ {
+ { // King's Square
+ WORLDSTATE_WAVE_MARKER_KS,
+ {
+ {
+ { 2131.474f, 1352.615f, 131.372f, 6.10960f },
+ { 2131.463f, 1357.127f, 131.587f, 5.95173f },
+ { 2129.795f, 1345.093f, 131.194f, 0.17905f },
+ { 2136.235f, 1347.894f, 131.628f, 0.20262f },
+ { 2138.219f, 1356.240f, 132.169f, 5.95173f },
+ { 2140.584f, 1351.624f, 132.142f, 6.08525f }
+ }
+ }
+ },
+ { // Market Row
+ WORLDSTATE_WAVE_MARKER_MR,
+ {
+ {
+ { 2226.364f, 1331.808f, 127.0193f, 3.298672f },
+ { 2229.934f, 1329.146f, 127.057f, 3.24605f },
+ { 2225.028f, 1327.269f, 127.791f, 3.03792f },
+ { 2223.844f, 1335.282f, 127.749f, 3.47774f },
+ { 2222.192f, 1330.859f, 127.526f, 3.18793f },
+ { 2225.865f, 1331.029f, 127.007f, 3.18793f }
+ }
+ }
+ },
+ { // Festival Lane
+ WORLDSTATE_WAVE_MARKER_FL,
+ {
+ {
+ { 2183.596f, 1238.823f, 136.551f, 2.16377f },
+ { 2181.420f, 1237.357f, 136.565f, 2.16377f },
+ { 2178.692f, 1237.446f, 136.694f, 1.99098f },
+ { 2184.980f, 1242.458f, 136.772f, 2.59181f },
+ { 2176.873f, 1240.463f, 136.420f, 2.10094f },
+ { 2181.523f, 1244.298f, 136.338f, 2.38997f }
+ }
+ }
+ },
+ { // Elders' Square
+ WORLDSTATE_WAVE_MARKER_ES,
+ {
+ {
+ { 2267.003f, 1168.055f, 137.821f, 2.79050f },
+ { 2264.392f, 1162.145f, 137.910f, 2.39937f },
+ { 2262.785f, 1166.648f, 138.053f, 2.71353f },
+ { 2265.214f, 1170.771f, 137.972f, 2.80385f },
+ { 2259.745f, 1159.360f, 138.198f, 2.34047f },
+ { 2264.222f, 1171.708f, 138.047f, 2.82742f }
+ }
+ }
+ },
+ { // Town Hall
+ WORLDSTATE_WAVE_MARKER_TH,
+ {
+ {
+ { 2351.656f, 1218.682f, 130.062f, 4.63383f },
+ { 2354.921f, 1218.425f, 130.280f, 4.63383f },
+ { 2347.516f, 1216.976f, 130.491f, 5.02496f },
+ { 2356.508f, 1216.656f, 130.445f, 4.29061f },
+ { 2346.674f, 1216.739f, 130.576f, 5.32341f },
+ { 2351.728f, 1214.561f, 130.255f, 4.61891f }
+ }
+ }
+ }
+ }
+};
+
class instance_culling_of_stratholme : public InstanceMapScript
{
public:
- instance_culling_of_stratholme() : InstanceMapScript(CoSScriptName, 595) { }
+ instance_culling_of_stratholme() : InstanceMapScript("instance_culling_of_stratholme", 595) { }
struct instance_culling_of_stratholme_InstanceMapScript : public InstanceScript
{
- instance_culling_of_stratholme_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
+ instance_culling_of_stratholme_InstanceMapScript(InstanceMap* map) : InstanceScript(map), _currentState(JUST_STARTED), _infiniteGuardianTimeout(0), _waveCount(0), _currentSpawnLoc(0)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
- _crateCount = 0;
- _eventTimer = 0;
- _infiniteCouterState = NOT_STARTED;
+ _currentWorldStates[WORLDSTATE_SHOW_CRATES] = _currentWorldStates[WORLDSTATE_CRATES_REVEALED] = _currentWorldStates[WORLDSTATE_WAVE_COUNT] = _currentWorldStates[WORLDSTATE_TIME_GUARDIAN_SHOW] = _currentWorldStates[WORLDSTATE_TIME_GUARDIAN] = 0;
+ _sentWorldStates = _currentWorldStates;
+ _plagueCrates.reserve(NUM_PLAGUE_CRATES);
}
void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override
{
- packet.Worldstates.emplace_back(WORLDSTATE_SHOW_CRATES, 1);
- packet.Worldstates.emplace_back(WORLDSTATE_CRATES_REVEALED, _crateCount);
- packet.Worldstates.emplace_back(WORLDSTATE_WAVE_COUNT, 0);
- packet.Worldstates.emplace_back(WORLDSTATE_TIME_GUARDIAN, 25);
- packet.Worldstates.emplace_back(WORLDSTATE_TIME_GUARDIAN_SHOW, 0);
+ for (WorldStateMap::const_iterator itr = _sentWorldStates.begin(); itr != _sentWorldStates.end(); ++itr)
+ packet.Worldstates.emplace_back(itr->first, itr->second);
}
- void OnCreatureCreate(Creature* creature) override
+ void WriteSaveDataMore(std::ostringstream& data) override
{
- switch (creature->GetEntry())
+ data << _currentState << ' ' << _infiniteGuardianTimeout;
+ }
+
+ void ReadSaveDataMore(std::istringstream& data) override
+ {
+ // read current instance progress from save data, then regress to the previous stable state
+ uint32 state = JUST_STARTED;
+ time_t infiniteGuardianTime = 0;
+ data >> state;
+ data >> infiniteGuardianTime; // UNIX timestamp
+
+ COSProgressStates loadState = GetStableStateFor(COSProgressStates(state));
+ SetInstanceProgress(loadState, true);
+
+ if (infiniteGuardianTime)
{
- case NPC_CHROMIE:
- _chromieGUID = creature->GetGUID();
+ _infiniteGuardianTimeout = infiniteGuardianTime;
+ events.ScheduleEvent(EVENT_GUARDIAN_TICK, 0s);
+ }
+
+ time_t timediff = (infiniteGuardianTime - GameTime::GetGameTime());
+ if (!infiniteGuardianTime)
+ timediff = -1;
+
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::ReadSaveDataMore: Loaded with state %u and guardian timeout at %zu minutes %zu seconds from now", (uint32)loadState, timediff / MINUTE, timediff % MINUTE);
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ switch (type)
+ {
+ case DATA_GM_OVERRIDE:
+ SetInstanceProgress(COSProgressStates(data), true);
break;
- case NPC_ARTHAS:
- _arthasGUID = creature->GetGUID();
+ case DATA_ARTHAS_DIED:
+ // Respawn everything, then regress to last stable state
+ _arthasGUID = ObjectGuid::Empty;
+ SetInstanceProgress(GetStableStateFor(_currentState), true);
break;
- case NPC_MEATHOOK:
- _meathookGUID = creature->GetGUID();
+ case DATA_CRATES_START:
+ if (_currentState == JUST_STARTED)
+ SetInstanceProgress(CRATES_IN_PROGRESS, false);
break;
- case NPC_SALRAMM:
- _salrammGUID = creature->GetGUID();
+ case DATA_CRATE_REVEALED:
+ if (uint32 missingCrates = MissingPlagueCrates())
+ SetWorldState(WORLDSTATE_CRATES_REVEALED, NUM_PLAGUE_CRATES - missingCrates);
+ else
+ SetInstanceProgress(CRATES_DONE, false);
break;
- case NPC_EPOCH:
- _epochGUID = creature->GetGUID();
+ case DATA_UTHER_FINISHED:
+ if (_currentState == UTHER_TALK)
+ SetInstanceProgress(PURGE_PENDING, false);
break;
- case NPC_MAL_GANIS:
- _malGanisGUID = creature->GetGUID();
+ case DATA_SKIP_TO_PURGE:
+ if (_currentState <= CRATES_DONE)
+ SetInstanceProgress(PURGE_PENDING, false);
break;
- case NPC_INFINITE:
- _infiniteGUID = creature->GetGUID();
- DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 1);
+ case DATA_START_WAVES:
+ if (_currentState == PURGE_STARTING)
+ SetInstanceProgress(WAVES_IN_PROGRESS, false);
break;
- case NPC_GENERIC_BUNNY:
- _genericBunnyGUID = creature->GetGUID();
+ case DATA_REACH_TOWN_HALL:
+ if (_currentState == WAVES_DONE)
+ SetInstanceProgress(TOWN_HALL_PENDING, false);
+ break;
+ case DATA_TOWN_HALL_DONE:
+ if (_currentState == TOWN_HALL)
+ SetInstanceProgress(TOWN_HALL_COMPLETE, false);
+ break;
+ case DATA_GAUNTLET_REACHED:
+ if (_currentState == GAUNTLET_TRANSITION)
+ SetInstanceProgress(GAUNTLET_PENDING, false);
+ break;
+ case DATA_GAUNTLET_DONE:
+ if (_currentState == GAUNTLET_IN_PROGRESS)
+ SetInstanceProgress(GAUNTLET_COMPLETE, false);
+ break;
+ case DATA_MALGANIS_DONE:
+ if (_currentState == MALGANIS_IN_PROGRESS)
+ SetInstanceProgress(COMPLETE, false);
break;
default:
break;
}
}
- void OnGameObjectCreate(GameObject* go) override
+ void OnUnitDeath(Unit* unit) override
{
- switch (go->GetEntry())
+ if (_currentState != WAVES_IN_PROGRESS || _waveSpawns.empty())
+ return;
+
+ // if this is a wave spawn...
+ auto it = _waveSpawns.find(unit->GetGUID());
+ if (it == _waveSpawns.end())
+ return;
+
+ // ... then erase it from our list, then check if there are no more spawns alive...
+ _waveSpawns.erase(it);
+ if (!_waveSpawns.empty())
+ return;
+
+ // ... and if there are none, the wave is done and we progress
+
+ // clear existing world markers
+ for (uint32 marker = WAVE_MARKER_MIN; marker <= WAVE_MARKER_MAX; ++marker)
+ SetWorldState(COSWorldStates(marker), 0, false);
+ PropagateWorldStateUpdate();
+
+ // schedule next wave if applicable
+ if (_waveCount < NUM_SCOURGE_WAVES)
+ events.ScheduleEvent(EVENT_SCOURGE_WAVE, (_waveCount == WAVE_MEATHOOK) ? 20s : 1s);
+ else
+ SetInstanceProgress(WAVES_DONE, false);
+ }
+
+ void SetGuidData(uint32 type, ObjectGuid guid) override
+ {
+ switch (type)
{
- case GO_SHKAF_GATE:
- _shkafGateGUID = go->GetGUID();
+ case DATA_GM_RECALL:
+ {
+ Creature* arthas = instance->GetCreature(_arthasGUID);
+ Position const& target = arthas ? arthas->GetPosition() : GetArthasSnapbackFor(_currentState);
+
+ for (auto itr = instance->GetPlayers().begin(); itr != instance->GetPlayers().end(); ++itr)
+ {
+ if (Player* player = itr->GetSource())
+ if (player->GetGUID() == guid || !player->IsGameMaster())
+ {
+ player->CombatStop(true);
+ const float offsetDist = 10;
+ float myAngle = rand_norm() * 2.0 * M_PI;
+ Position myTarget(target.GetPositionX() + std::sin(myAngle) * offsetDist, target.GetPositionY() + std::sin(myAngle) * offsetDist, target.GetPositionZ(), myAngle + M_PI);
+ player->NearTeleportTo(myTarget);
+ }
+ }
+ break;
+ }
+ case DATA_UTHER_START:
+ if (_currentState == CRATES_DONE)
+ SetInstanceProgress(UTHER_TALK, false);
+ break;
+ case DATA_START_PURGE:
+ InitiateArthasEvent(PURGE_PENDING, PURGE_STARTING, ACTION_START_RP_EVENT2, guid);
break;
- case GO_MALGANIS_GATE_1:
- _malGanisGate1GUID = go->GetGUID();
+ case DATA_START_TOWN_HALL:
+ InitiateArthasEvent(TOWN_HALL_PENDING, TOWN_HALL, ACTION_START_RP_EVENT3, guid);
break;
- case GO_MALGANIS_GATE_2:
- _malGanisGate2GUID = go->GetGUID();
- AddDoor(go, true);
+ case DATA_TO_GAUNTLET:
+ InitiateArthasEvent(TOWN_HALL_COMPLETE, GAUNTLET_TRANSITION, ACTION_START_RP_EVENT4_1, guid);
break;
- case GO_EXIT_GATE:
- _exitGateGUID = go->GetGUID();
- AddDoor(go, true);
+ case DATA_START_GAUNTLET:
+ InitiateArthasEvent(GAUNTLET_PENDING, GAUNTLET_IN_PROGRESS, ACTION_START_RP_EVENT4_2, guid);
break;
- case GO_MALGANIS_CHEST_N:
- case GO_MALGANIS_CHEST_H:
- _malGanisChestGUID = go->GetGUID();
+ case DATA_START_MALGANIS:
+ InitiateArthasEvent(GAUNTLET_COMPLETE, MALGANIS_IN_PROGRESS, ACTION_START_RP_EVENT5, guid);
break;
default:
break;
}
}
- void OnGameObjectRemove(GameObject* go) override
+ uint32 GetData(uint32 type) const override
+ {
+ if (type == DATA_INSTANCE_PROGRESS)
+ return _currentState;
+ return 0;
+ }
+
+ bool SetBossState(uint32 type, EncounterState state) override
{
- switch (go->GetEntry())
+ if (type == DATA_INFINITE_CORRUPTOR && state == DONE)
{
- case GO_MALGANIS_GATE_2:
- case GO_EXIT_GATE:
- AddDoor(go, false);
- break;
- default:
- break;
+ events.CancelEvent(EVENT_GUARDIAN_TICK);
+ SetWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 0, false);
+ SetWorldState(WORLDSTATE_TIME_GUARDIAN, 0);
}
+
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ return true;
}
- void SetData(uint32 type, uint32 data) override
+ void Update(uint32 diff) override
{
- switch (type)
+ events.Update(diff);
+ while (uint32 eventId = events.ExecuteEvent())
{
- case DATA_CRATE_COUNT:
- _crateCount = data;
- if (_crateCount == 5)
- {
- if (Creature* bunny = instance->GetCreature(_genericBunnyGUID))
- bunny->CastSpell(bunny, SPELL_CRATES_CREDIT, true);
+ switch (eventId)
+ {
+ case EVENT_GUARDIAN_TICK: // regular ticks at :00 seconds on the timer, and then at 04:30 remaining for the chromie whisper
+ { // we do the whisper as a guardian tick because i don't want to duplicate the real-time code
+ if (!instance->IsHeroic())
+ return;
+
+ time_t secondsToGuardianDeath = _infiniteGuardianTimeout - GameTime::GetGameTime();
+ if (secondsToGuardianDeath <= 0)
+ {
+ _infiniteGuardianTimeout = 0;
+ SetWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 0, false);
+ SetWorldState(WORLDSTATE_TIME_GUARDIAN, 0);
- // Summon Chromie and global whisper
- if (Creature* chromie = instance->SummonCreature(NPC_CHROMIE_2, ChromieSummonPos[0]))
- if (!instance->GetPlayers().isEmpty())
- chromie->AI()->Talk(SAY_CRATES_COMPLETED);
+ if (Creature* corruptor = instance->GetCreature(_corruptorGUID))
+ {
+ corruptor->AI()->DoAction(-ACTION_CORRUPTOR_LEAVE);
+ if (Creature* guardian = instance->GetCreature(_guardianGUID))
+ Unit::Kill(corruptor, guardian); // @todo is there some spell for this?
+ }
+ SetBossState(DATA_INFINITE_CORRUPTOR, FAIL);
+ }
+ else
+ {
+ time_t minutes = (secondsToGuardianDeath - 1) / MINUTE;
+ time_t seconds = ((secondsToGuardianDeath - 1) % MINUTE) + 1;
+
+ // chromie whispers - we only ever tick at :00 and :30, but give some leeway in case of slow tick rate
+ if (minutes == 24 && seconds >= 45)
+ if (Creature* chromie = instance->GetCreature(_chromieGUID))
+ chromie->AI()->Talk(CHROMIE_WHISPER_GUARDIAN_1);
+ if (minutes == 4 && seconds < 45)
+ if (Creature* chromie = instance->GetCreature(_chromieGUID))
+ chromie->AI()->Talk(CHROMIE_WHISPER_GUARDIAN_2);
+ if (minutes == 0)
+ if (Creature* chromie = instance->GetCreature(_chromieGUID))
+ chromie->AI()->Talk(CHROMIE_WHISPER_GUARDIAN_3);
+
+ // update the timer state
+ SetWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 1, false);
+ SetWorldState(WORLDSTATE_TIME_GUARDIAN, minutes + 1);
+ if (minutes == 4 && seconds > 30)
+ events.Repeat(Seconds(seconds - 30));
+ else
+ events.Repeat(Seconds(seconds));
+ }
+ break;
}
- DoUpdateWorldState(WORLDSTATE_CRATES_REVEALED, _crateCount);
- break;
- case DATA_INFINITE_COUNTER:
- _infiniteCouterState = data;
- if (data == IN_PROGRESS)
+ case EVENT_RESPAWN_ARTHAS:
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::Update: Spawning new Arthas for instance...");
+ instance->SummonCreature(NPC_ARTHAS, GetArthasSnapbackFor(_currentState));
+ events.CancelEvent(EVENT_RESPAWN_ARTHAS); // make sure we don't have two scheduled
+ break;
+ case EVENT_CRIER_CALL_TO_GATES:
+ if (_currentState == CRATES_DONE)
+ if (Creature* crier = instance->GetCreature(_crierGUID))
+ crier->AI()->Talk(CRIER_SAY_CALL_TO_GATES);
+ break;
+ case EVENT_SCOURGE_WAVE:
{
- if (!_infiniteGUID)
+ if (_currentState != WAVES_IN_PROGRESS)
+ break;
+
+ ++_waveCount;
+ SetWorldState(WORLDSTATE_WAVE_COUNT, _waveCount);
+
+ uint8 spawnLoc = urand(WAVE_LOC_MIN, WAVE_LOC_MAX);
+ while (spawnLoc == _currentSpawnLoc) // don't allow repeats
+ spawnLoc = urand(WAVE_LOC_MIN, WAVE_LOC_MAX);
+ WaveLocation const& spawnLocation = WaveLocations[spawnLoc - WAVE_LOC_MIN];
+
+ switch (_waveCount)
{
- _eventTimer = 25;
- instance->SummonCreature(NPC_INFINITE, InfiniteCorruptorPos);
- instance->SummonCreature(NPC_TIME_RIFT, TimeRiftPos);
- instance->SummonCreature(NPC_GUARDIAN_OF_TIME, GuardianOfTimePos);
- events.ScheduleEvent(EVENT_INFINITE_TIMER, 1);
+ case WAVE_MEATHOOK:
+ if (Creature* spawn = instance->SummonCreature(NPC_MEATHOOK, spawnLocation.SpawnPoints[0]))
+ _waveSpawns.insert(spawn->GetGUID());
+ break;
+ case WAVE_SALRAMM:
+ if (Creature* spawn = instance->SummonCreature(NPC_SALRAMM, spawnLocation.SpawnPoints[0]))
+ _waveSpawns.insert(spawn->GetGUID());
+ break;
+ default:
+ if (instance->IsHeroic())
+ {
+ for (uint32 i = 0; i < MAX_SPAWNS_PER_WAVE; ++i)
+ if (uint32 entry = HeroicWaves[_waveCount - 1][i])
+ if (Creature* spawn = instance->SummonCreature(entry, spawnLocation.SpawnPoints[i]))
+ _waveSpawns.insert(spawn->GetGUID());
+ }
+ else
+ {
+ for (uint32 i = 0; i <= 1; ++i)
+ if (Creature* spawn = instance->SummonCreature(NPC_DEVOURING_GHOUL, spawnLocation.SpawnPoints[i]))
+ _waveSpawns.insert(spawn->GetGUID());
+ }
+ break;
}
+
+ for (uint32 marker = WAVE_MARKER_MIN; marker <= WAVE_MARKER_MAX; ++marker)
+ SetWorldState(COSWorldStates(marker), 0, false);
+ SetWorldState(spawnLocation.WorldState, 1);
+
+ events.RescheduleEvent(EVENT_CRIER_ANNOUNCE_WAVE, 2s);
+ _currentSpawnLoc = spawnLoc;
+ break;
}
- break;
- default:
- break;
+ case EVENT_CRIER_ANNOUNCE_WAVE:
+ if (_currentState == WAVES_IN_PROGRESS)
+ if (Creature* crier = instance->GetCreature(_crierGUID))
+ crier->AI()->Talk(_currentSpawnLoc);
+ break;
+ default:
+ break;
+ }
}
}
- bool SetBossState(uint32 type, EncounterState state) override
+ void OnCreatureCreate(Creature* creature) override
{
- if (!InstanceScript::SetBossState(type, state))
- return false;
-
- switch (type)
+ switch (creature->GetEntry())
{
- case DATA_INFINITE:
- if (state == DONE)
- {
- DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 0);
- DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN, 0);
- }
+ case NPC_CHROMIE:
+ _chromieGUID = creature->GetGUID();
+ creature->setActive(true);
break;
- case DATA_MAL_GANIS:
- if (state == DONE)
- {
- if (GameObject* go = instance->GetGameObject(_malGanisChestGUID))
- go->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
- instance->SummonCreature(NPC_CHROMIE_3, ChromieSummonPos[1]);
- }
+ case NPC_INFINITE_CORRUPTOR:
+ _corruptorGUID = creature->GetGUID();
+ creature->setActive(true);
+ break;
+ case NPC_GUARDIAN_OF_TIME:
+ _guardianGUID = creature->GetGUID();
+ creature->setActive(true);
+ break;
+ case NPC_GENERIC_BUNNY:
+ _genericBunnyGUID = creature->GetGUID();
+ creature->setActive(true);
+ break;
+ case NPC_CRATE_HELPER:
+ _plagueCrates.push_back(creature->GetGUID());
+ break;
+ case NPC_ARTHAS:
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::OnCreatureCreate: Arthas spawned at %s", creature->GetPosition().ToString().c_str());
+ _arthasGUID = creature->GetGUID();
+ creature->setActive(true);
+ break;
+ case NPC_LORDAERON_CRIER:
+ _crierGUID = creature->GetGUID();
+ creature->setActive(true);
break;
default:
break;
}
-
- return true;
}
- uint32 GetData(uint32 type) const override
+ void OnGameObjectCreate(GameObject* object) override
{
- switch (type)
+ switch (object->GetEntry())
{
- case DATA_CRATE_COUNT:
- return _crateCount;
- case DATA_INFINITE_COUNTER:
- return _infiniteCouterState;
- default:
+ case GO_HIDDEN_PASSAGE:
+ _passageGUID = object->GetGUID();
+ object->setActive(true);
+ object->SetGoState(_currentState <= GAUNTLET_TRANSITION ? GO_STATE_READY : GO_STATE_ACTIVE);
break;
}
- return 0;
}
- ObjectGuid GetGuidData(uint32 identifier) const override
+ void InitiateArthasEvent(COSProgressStates fromState, COSProgressStates toState, COSInstanceActions startAction, ObjectGuid starterGUID)
+ {
+ if (_currentState != fromState)
+ return;
+ SetInstanceProgress(toState, false);
+ if (Creature* arthas = instance->GetCreature(_arthasGUID))
+ arthas->AI()->SetGUID(starterGUID, -startAction);
+ }
+
+ void SetInstanceProgress(COSProgressStates state, bool force)
{
- switch (identifier)
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::SetInstanceProgress: Instance progress is now 0x%X", (uint32)state);
+ _currentState = state;
+
+ /* Spawn group management */
+ SetSpawnGroupState(SPAWNGRP_CHROMIE_MID, (state >= CRATES_DONE), force);
+ SetSpawnGroupState(SPAWNGRP_CRATE_HELPERS, (state == CRATES_IN_PROGRESS || state == CRATES_DONE), true);
+ SetSpawnGroupState(SPAWNGRP_GAUNTLET_TRASH, (state == WAVES_IN_PROGRESS), force);
+ SetSpawnGroupState(SPAWNGRP_UNDEAD_TRASH, (state >= WAVES_IN_PROGRESS && state < GAUNTLET_COMPLETE), force);
+ SetSpawnGroupState(SPAWNGRP_RESIDENTS, (state < WAVES_IN_PROGRESS), true);
+
+ /* Arthas management */
+ if (state > CRATES_DONE)
+ { // there might be an Arthas instance in the dungeon somewhere
+ // notify him of the change so he can adjust
+ Creature* arthas = instance->GetCreature(_arthasGUID);
+ if (arthas)
+ {
+ if (force)
+ {
+ arthas->DespawnOrUnsummon();
+ arthas = nullptr;
+ }
+ else
+ arthas->AI()->DoAction(-ACTION_PROGRESS_UPDATE);
+ }
+
+ if (!arthas) // if there is currently no arthas, then we need to spawn one
+ events.ScheduleEvent(EVENT_RESPAWN_ARTHAS, 1s);
+ }
+ else if (Creature* arthas = instance->GetCreature(_arthasGUID)) // there shouldn't be any Arthas around
+ arthas->DespawnOrUnsummon();
+
+ /* World state management */
+ // Plague crates
+ if (state == CRATES_IN_PROGRESS)
{
- case DATA_ARTHAS:
- return _arthasGUID;
- case DATA_MEATHOOK:
- return _meathookGUID;
- case DATA_SALRAMM:
- return _salrammGUID;
- case DATA_EPOCH:
- return _epochGUID;
- case DATA_MAL_GANIS:
- return _malGanisGUID;
- case DATA_INFINITE:
- return _infiniteGUID;
- case DATA_SHKAF_GATE:
- return _shkafGateGUID;
- case DATA_MAL_GANIS_GATE_1:
- return _malGanisGate1GUID;
- case DATA_MAL_GANIS_GATE_2:
- return _malGanisGate2GUID;
- case DATA_EXIT_GATE:
- return _exitGateGUID;
- case DATA_MAL_GANIS_CHEST:
- return _malGanisChestGUID;
+ SetWorldState(WORLDSTATE_SHOW_CRATES, 1, false);
+ SetWorldState(WORLDSTATE_CRATES_REVEALED, 0, false);
+ }
+ else if (state == CRATES_DONE)
+ {
+ SetWorldState(WORLDSTATE_SHOW_CRATES, 1, false);
+ SetWorldState(WORLDSTATE_CRATES_REVEALED, NUM_PLAGUE_CRATES, false);
+ }
+ else
+ {
+ SetWorldState(WORLDSTATE_SHOW_CRATES, 0, false);
+ SetWorldState(WORLDSTATE_CRATES_REVEALED, state == JUST_STARTED ? 0 : NUM_PLAGUE_CRATES, false);
+ }
+ // Scourge wave counter
+ if (state == WAVES_DONE)
+ SetWorldState(WORLDSTATE_WAVE_COUNT, NUM_SCOURGE_WAVES, false);
+ else
+ SetWorldState(WORLDSTATE_WAVE_COUNT, 0, false);
+
+ PropagateWorldStateUpdate();
+
+ // Hidden Passage status handling
+ if (GameObject* passage = instance->GetGameObject(_passageGUID))
+ passage->SetGoState(state <= GAUNTLET_TRANSITION ? GO_STATE_READY : GO_STATE_ACTIVE);
+
+ switch (state)
+ {
+ case CRATES_DONE:
+ if (Creature* bunny = instance->GetCreature(_genericBunnyGUID))
+ bunny->CastSpell(nullptr, SPELL_CRATES_KILL_CREDIT, TRIGGERED_FULL_MASK);
+ events.ScheduleEvent(EVENT_CRIER_CALL_TO_GATES, 5s);
+ break;
+ case WAVES_IN_PROGRESS:
+ _waveCount = 0;
+ _currentSpawnLoc = 0;
+ _waveSpawns.clear();
+ events.ScheduleEvent(EVENT_SCOURGE_WAVE, 1s);
+ SpawnInfiniteCorruptor();
+ break;
default:
break;
}
- return ObjectGuid::Empty;
- }
-
- void Update(uint32 diff) override
- {
- events.Update(diff);
- while (uint32 eventId = events.ExecuteEvent())
+ if (force)
{
- switch (eventId)
+ // Forced transitions are regressions (event failures) or GM overrides; respawn all dead creatures, and despawn any temporary summons
+ events.Reset();
+ instance->DeleteRespawnTimes();
+
+ // Reset respawn time on all permanent spawns, despawn all temporary spawns
+ // @todo dynspawn, this won't work
+ std::vector<Creature*> toDespawn;
+ std::unordered_map<ObjectGuid, Creature*> const& objects = instance->GetObjectsStore().GetElements()._elements._element;
+ for (std::unordered_map<ObjectGuid, Creature*>::const_iterator itr = objects.cbegin(); itr != objects.cend(); ++itr)
{
- case EVENT_INFINITE_TIMER:
- DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN, _eventTimer);
+ if (itr->second && (itr->second->isDead() || !itr->second->GetSpawnId() || itr->second->GetOriginalEntry() != itr->second->GetEntry()))
+ {
+ if (itr->second->getDeathState() == DEAD) // despawned, not corpse
+ itr->second->SetRespawnTime(1);
+ else
+ toDespawn.push_back(itr->second);
+ }
+ }
- switch (_eventTimer)
- {
- case 25:
- if (instance->HavePlayers())
- if (Creature* chromie = instance->GetCreature(_chromieGUID))
- chromie->AI()->Talk(SAY_INFINITE_START);
- break;
- case 5:
- if (instance->HavePlayers())
- if (Creature* chromie = instance->GetCreature(_chromieGUID))
- chromie->AI()->Talk(SAY_INFINITE);
- break;
- case 0:
- if (instance->HavePlayers())
- if (Creature* chromie = instance->GetCreature(_chromieGUID))
- chromie->AI()->Talk(SAY_INFINITE_FAIL);
+ for (Creature* creature : toDespawn)
+ {
+ if (creature->GetSpawnId())
+ creature->SetRespawnTime(1);
+ creature->DespawnOrUnsummon(0, 1s);
+ }
- if (Creature* infinite = instance->GetCreature(_infiniteGUID))
- {
- if (Creature* guardian = infinite->FindNearestCreature(NPC_GUARDIAN_OF_TIME, 100.0f))
- Unit::Kill(infinite, guardian);
+ SpawnInfiniteCorruptor();
+ events.RescheduleEvent(EVENT_RESPAWN_ARTHAS, 1s);
+ }
- if (Creature* rift = infinite->FindNearestCreature(NPC_TIME_RIFT, 100.0f))
- {
- infinite->GetMotionMaster()->MovePoint(0, rift->GetPositionX(), rift->GetPositionY(), rift->GetPositionZ());
- rift->DespawnOrUnsummon(3000);
- }
+ SaveToDB();
+ }
- infinite->DespawnOrUnsummon(3000);
- infinite->AI()->Talk(SAY_FAIL_EVENT);
- }
- DoUpdateWorldState(WORLDSTATE_TIME_GUARDIAN_SHOW, 0);
- return;
- default:
- break;
- }
- events.ScheduleEvent(EVENT_INFINITE_TIMER, 1min);
- --_eventTimer;
- break;
- default:
- break;
+ private:
+ typedef std::unordered_map<uint32, uint32> WorldStateMap;
+
+ uint32 MissingPlagueCrates() const
+ {
+ uint32 returnValue = 0;
+ for (ObjectGuid const& crateHelperGUID : _plagueCrates)
+ if (Creature* crateHelper = instance->GetCreature(crateHelperGUID))
+ if (crateHelper->IsAlive() && !crateHelper->AI()->GetData(DATA_CRATE_REVEALED))
+ ++returnValue;
+ return returnValue;
+ }
+
+ void SpawnInfiniteCorruptor()
+ {
+ if (!_infiniteGuardianTimeout && instance->IsHeroic() && (GetBossState(DATA_INFINITE_CORRUPTOR) != DONE && GetBossState(DATA_INFINITE_CORRUPTOR) != FAIL))
+ {
+ instance->SummonCreature(NPC_TIME_RIFT, CorruptorRiftPos);
+ instance->SummonCreature(NPC_GUARDIAN_OF_TIME, GuardianPos);
+ instance->SummonCreature(NPC_INFINITE_CORRUPTOR, CorruptorPos);
+ _infiniteGuardianTimeout = GameTime::GetGameTime() + 25 * MINUTE;
+ events.ScheduleEvent(EVENT_GUARDIAN_TICK, 6s);
+ }
+ }
+
+ void SetWorldState(COSWorldStates state, uint32 value, bool immediate = true)
+ {
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::SetWorldState: %u %u", uint32(state), value);
+ _currentWorldStates[state] = value;
+ if (immediate)
+ PropagateWorldStateUpdate();
+ }
+
+ void PropagateWorldStateUpdate()
+ {
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::PropagateWorldStateUpdate: Propagate world states");
+ for (WorldStateMap::const_iterator it = _currentWorldStates.begin(); it != _currentWorldStates.end(); ++it)
+ {
+ uint32& sent = _sentWorldStates[it->first];
+ if (sent != it->second)
+ {
+ TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::PropagateWorldStateUpdate: Sending world state %u (%u)", it->first, it->second);
+ DoUpdateWorldState(it->first, it->second);
+ sent = it->second;
}
}
}
- private:
+ void SetSpawnGroupState(COSInstanceEntries group, bool state, bool force)
+ {
+ if (state)
+ instance->SpawnGroupSpawn(group, true);
+ else if (force)
+ instance->SpawnGroupDespawn(group, true);
+ else
+ instance->SetSpawnGroupInactive(group);
+ }
+
+ EventMap events;
+ COSProgressStates _currentState;
+ WorldStateMap _sentWorldStates;
+ WorldStateMap _currentWorldStates;
+ time_t _infiniteGuardianTimeout;
+
+ // Generic
ObjectGuid _chromieGUID;
- ObjectGuid _arthasGUID;
- ObjectGuid _meathookGUID;
- ObjectGuid _salrammGUID;
- ObjectGuid _epochGUID;
- ObjectGuid _malGanisGUID;
- ObjectGuid _infiniteGUID;
- ObjectGuid _shkafGateGUID;
- ObjectGuid _malGanisGate1GUID;
- ObjectGuid _malGanisGate2GUID;
- ObjectGuid _exitGateGUID;
- ObjectGuid _malGanisChestGUID;
+ ObjectGuid _corruptorGUID;
+ ObjectGuid _guardianGUID;
ObjectGuid _genericBunnyGUID;
+ std::vector<ObjectGuid> _plagueCrates;
- uint32 _crateCount;
- uint32 _eventTimer;
- uint32 _infiniteCouterState;
+ ObjectGuid _arthasGUID;
+ ObjectGuid _crierGUID;
- EventMap events;
+ // Scourge Waves
+ uint32 _waveCount;
+ uint8 _currentSpawnLoc;
+ std::unordered_set<ObjectGuid> _waveSpawns;
+
+ // Gauntlet
+ ObjectGuid _passageGUID;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/npc_arthas.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/npc_arthas.cpp
new file mode 100644
index 00000000000..77ddd9b8ec4
--- /dev/null
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/npc_arthas.cpp
@@ -0,0 +1,1669 @@
+/*
+ * Copyright (C) 2008-2019 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 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 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 "culling_of_stratholme.h"
+#include "GameObject.h"
+#include "InstanceScript.h"
+#include "Log.h"
+#include "Map.h"
+#include "MotionMaster.h"
+#include "MoveSplineInit.h"
+#include "ObjectAccessor.h"
+#include "PassiveAI.h"
+#include "Player.h"
+#include "Random.h"
+#include "ScriptedCreature.h"
+#include "ScriptedGossip.h"
+#include "ScriptMgr.h"
+#include "ScriptSystem.h"
+#include "SpellScript.h"
+#include "SplineChainMovementGenerator.h"
+#include "TemporarySummon.h"
+#include <array>
+#include <unordered_map>
+#include <vector>
+
+enum Entries
+{
+ NPC_MALGANIS_BUNNY = 20562,
+ NPC_UTHER = 26528,
+ NPC_JAINA = 26497,
+ NPC_CITIZEN = 28167,
+ NPC_RESIDENT = 28169,
+ NPC_FOOTMAN = 27745,
+ NPC_KNIGHT = 27746,
+ NPC_PRIEST = 27747,
+ NPC_SORCERESS = 27752,
+ NPC_RISEN_ZOMBIE = 27737,
+ NPC_CITIZEN_INFINITE = 28340,
+ NPC_RESIDENT_INFINITE = 28341,
+ NPC_TIME_RIFT = 28409,
+ NPC_TIME_RIFT_LARGE = 28439,
+ NPC_INFINITE_ADVERSARY = 27742,
+ NPC_INFINITE_HUNTER = 27743,
+ NPC_INFINITE_AGENT = 27744,
+ NPC_EPOCH = 26532,
+ NPC_MALGANIS = 26533,
+ NPC_CHROMIE_3 = 30997,
+
+ SPELL_HOLY_LIGHT = 52444,
+ SPELL_EXORCISM = 52445,
+ SPELL_DEVOTION_AURA = 52442,
+ SPELL_CRUSADER_STRIKE = 50773,
+ SPELL_SHADOWSTEP_VISUAL = 51908,
+ SPELL_TRANSFORM_VISUAL = 33133,
+ SPELL_MALGANIS_QUEST_CREDIT = 58124,
+ SPELL_MALGANIS_KILL_CREDIT = 58630,
+ SPELL_CHROMIE_3_TRANSFORM = 58986,
+ GO_CHEST_NORMAL = 190663,
+ GO_CHEST_HEROIC = 193597
+};
+
+enum SplineChains
+{
+ // RP1: Arthas/Jaina/Uther, outside Stratholme gates
+ RP1_CHAIN_ARTHAS1 = 1, // Initial movement
+ RP1_CHAIN_UTHER1 = 1, // Initial movement
+ RP1_CHAIN_JAINA1 = 1, // Initial movement
+ RP1_CHAIN_ARTHAS2 = 2, // Arthas moves up the hill to look out over Stratholme
+ RP1_CHAIN_UTHER2 = 2, // Uther follows
+ RP1_CHAIN_JAINA2 = 2, // Jaina follows
+ RP1_CHAIN_UTHER3 = 3, // Uther leaves
+ RP1_CHAIN_JAINA3 = 3, // Jaina turns to leave, but is stopped by Arthas
+ RP1_CHAIN_JAINA4 = 4, // Jaina leaves for real
+ RP1_CHAIN_ARTHAS3 = 3, // Arthas moves down the hill to the bridge
+ RP1_CHAIN_ARTHAS4 = 4, // Arthas moves to the Stratholme entrance
+
+ // RP2: Arthas/Mal'ganis, at Stratholme gates
+ RP2_CHAIN_ARTHAS1 = 5, // Arthas enters Stratholme proper
+ RP2_CHAIN_CITIZEN1 = 1, // A Stratholme citizen greets Arthas
+ RP2_CHAIN_ARTHAS2 = 6, // Arthas advances towards the approaching citizen
+ RP2_CHAIN_ARTHAS3 = 7, // Arthas moves on to a nearby resident
+
+ // RP3: Arthas/Infinites, in Stratholme Town Hall
+ RP3_CHAIN_ARTHAS1 = 91, // Arthas enters Stratholme Town Hall
+ RP3_CHAIN_ARTHAS2 = 92, // Arthas approaches one of the disguised Infinites
+ RP3_CHAIN_ARTHAS3 = 95, // Arthas proceeds up the stairs
+ RP3_CHAIN_ARTHAS3_2 = 96, // Arthas encounters more Infinite resistance
+ RP3_CHAIN_ARTHAS4 = 97, // Arthas presses onward into a hallway
+ RP3_CHAIN_ARTHAS5 = 98, // Arthas advances into the boss room
+ RP3_CHAIN_EPOCH = 1, // Chrono-Lord Epoch advances out of the portal
+
+ // Spawn motions (all on 27742, infinite adversary)
+ RP3_CHAIN_SPAWN1_LOC1 = 4,
+ RP3_CHAIN_SPAWN1_LOC2 = 2,
+ RP3_CHAIN_SPAWN1_LOC3 = 1,
+ RP3_CHAIN_SPAWN1_LOC4 = 3,
+ RP3_CHAIN_SPAWN2_LOC1 = 5,
+ RP3_CHAIN_SPAWN2_LOC2 = 6,
+ RP3_CHAIN_SPAWN2_LOC3 = 7,
+ RP3_CHAIN_SPAWN2_LOC4 = 8,
+ RP3_CHAIN_SPAWN3_LOC1 = 9,
+ RP3_CHAIN_SPAWN3_LOC2 = 10,
+ RP3_CHAIN_SPAWN3_LOC3 = 11,
+ RP3_CHAIN_SPAWN3_LOC4 = 12,
+
+ // RP4: Arthas moving towards Gauntlet
+ RP4_CHAIN_ARTHAS1 = 101, // Arthas moves up to the bookcase
+ RP4_CHAIN_ARTHAS2 = 128, // Arthas advances to the start of the Gauntlet section
+ RP4_CHAIN_GAUNTLET1 = 1024, // Arthas charges to the halfway point of the Gauntlet
+ RP4_CHAIN_GAUNTLET2 = 1025, // Arthas continues to Market Row
+
+ // RP5: Arthas advances on Crusader Square and faces off against Mal'ganis
+ RP5_CHAIN_ARTHAS1 = 121, // Arthas moves into Crusader Square
+ RP5_CHAIN_ARTHAS2 = 124, // After Mal'ganis' defeat, Arthas attempts to chase him down
+ RP5_CHAIN_ARTHAS3 = 125, // Arthas departs...
+ RP5_CHAIN_ARTHAS4 = 127 // ...and then finally despawns
+};
+
+enum PointIDs
+{
+ RP1_POINTID_UTHER1 = 1,
+ RP1_POINTID_ARTHAS2,
+ RP1_POINTID_UTHER2,
+ RP1_POINTID_JAINA2,
+ RP1_POINTID_UTHER3,
+ RP1_POINTID_JAINA4,
+ RP1_POINTID_ARTHAS3,
+ RP1_POINTID_ARTHAS4,
+
+ RP2_POINTID_ARTHAS1,
+ RP2_POINTID_ARTHAS2,
+ RP2_POINTID_ARTHAS3,
+
+ RP3_POINTID_TOWN_HALL,
+ RP3_POINTID_ARTHAS1,
+ RP3_POINTID_ARTHAS2,
+ RP3_POINTID_ARTHAS3,
+ RP3_POINTID_ARTHAS4,
+ RP3_POINTID_ARTHAS5,
+
+ RP4_POINTID_ARTHAS1,
+ RP4_POINTID_ARTHAS2,
+ RP4_POINTID_GAUNTLET1,
+ RP4_POINTID_GAUNTLET2,
+
+ RP5_POINTID_ARTHAS1,
+ RP5_POINTID_ARTHAS3,
+ RP5_POINTID_ARTHAS4
+};
+
+enum Actions
+{
+ ACTION_NONE = 0,
+ RP3_ACTION_AFTER_INITIAL,
+ RP3_ACTION_AFTER_SPAWN1,
+ RP3_ACTION_AFTER_SPAWN2,
+ RP3_ACTION_AFTER_SPAWN3,
+ RP3_ACTION_AFTER_EPOCH,
+ RP5_ACTION_AFTER_MALGANIS
+};
+
+enum Data
+{
+ DATA_RP_DUMMY_MOVED
+};
+
+enum RPEvents
+{
+ RP1_EVENT_START1 = 1,
+ RP1_EVENT_START2,
+ RP1_EVENT_ARTHAS1,
+ RP1_EVENT_UTHER1,
+ RP1_EVENT_ARTHAS2,
+ RP1_EVENT_ARTHAS3,
+ RP1_EVENT_UTHER_FACE,
+ RP1_EVENT_JAINA_FACE,
+ RP1_EVENT_UTHER2,
+ RP1_EVENT_ARTHAS4,
+ RP1_EVENT_UTHER3,
+ RP1_EVENT_ARTHAS_TURN,
+ RP1_EVENT_ARTHAS5,
+ RP1_EVENT_UTHER4,
+ RP1_EVENT_ARTHAS6,
+ RP1_EVENT_UTHER5,
+ RP1_EVENT_ARTHAS7,
+ RP1_EVENT_JAINA1,
+ RP1_EVENT_ARTHAS8,
+ RP1_EVENT_ARTHAS8_2,
+ RP1_EVENT_UTHER6,
+ RP1_EVENT_UTHER_LEAVE,
+ RP1_EVENT_JAINA_LEAVE,
+ RP1_EVENT_ARTHAS9,
+ RP1_EVENT_JAINA2,
+ RP1_EVENT_JAINA_LEAVE2,
+ RP1_EVENT_ARTHAS_LEAVE,
+ RP1_EVENT_ARTHAS10,
+ RP1_EVENT_ARTHAS_LEAVE2,
+ RP1_EVENT_FINISHED,
+
+ RP2_EVENT_ARTHAS_MOVE_1,
+ RP2_EVENT_CITIZEN1,
+ RP2_EVENT_ARTHAS2,
+ RP2_EVENT_ARTHAS_MOVE_2,
+ RP2_EVENT_CITIZEN2,
+ RP2_EVENT_KILL1,
+ RP2_EVENT_ARTHAS_MOVE_3,
+ RP2_EVENT_KILL2,
+ RP2_EVENT_REACT1,
+ RP2_EVENT_REACT2,
+ RP2_EVENT_REACT3,
+ RP2_EVENT_REACT4,
+ RP2_EVENT_REACT5,
+ RP2_EVENT_ARTHAS_MOVE_4,
+ RP2_EVENT_ARTHAS3,
+ RP2_EVENT_MALGANIS1,
+ RP2_EVENT_TROOPS_FACE,
+ RP2_EVENT_ARTHAS_FACE,
+ RP2_EVENT_MALGANIS2,
+ RP2_EVENT_MALGANIS_LEAVE1,
+ RP2_EVENT_MALGANIS_LEAVE2,
+ RP2_EVENT_ARTHAS4,
+ RP2_EVENT_ARTHAS4_2,
+ RP2_EVENT_ARTHAS_MOVE_5,
+ RP2_EVENT_ARTHAS5,
+ RP2_EVENT_ARTHAS5_2,
+ RP2_EVENT_ARTHAS5_3,
+ RP2_EVENT_WAVE_START,
+
+ EVENT_TOWN_HALL_REACHED,
+
+ RP3_EVENT_RESIDENT_FACE,
+ RP3_EVENT_ARTHAS_FACE,
+ RP3_EVENT_CITIZEN1,
+ RP3_EVENT_ARTHAS2,
+ RP3_EVENT_ARTHAS_KILL,
+ RP3_EVENT_INFINITE_LAUGH,
+ RP3_EVENT_ARTHAS3,
+ RP3_EVENT_CITIZEN2,
+ RP3_EVENT_TRANSFORM1,
+ RP3_EVENT_TRANSFORM2,
+ RP3_EVENT_TRANSFORM3,
+ RP3_EVENT_AGGRO,
+ RP3_EVENT_ARTHAS4,
+ RP3_EVENT_ARTHAS_MOVE_1,
+ RP3_EVENT_ARTHAS_MOVE_1_2,
+ RP3_EVENT_SPAWN1,
+ RP3_EVENT_SPAWN1_FACE,
+ RP3_EVENT_SPAWN1_AGGRO,
+ RP3_EVENT_ARTHAS11,
+ RP3_EVENT_ARTHAS_MOVE_2,
+ RP3_EVENT_ARTHAS20,
+ RP3_EVENT_SPAWN2,
+ RP3_EVENT_ARTHAS_FACE2,
+ RP3_EVENT_SPAWN2_FACE,
+ RP3_EVENT_SPAWN2_AGGRO,
+ RP3_EVENT_ARTHAS21,
+ RP3_EVENT_ARTHAS_MOVE_3,
+ RP3_EVENT_SPAWN3,
+ RP3_EVENT_ARTHAS30,
+ RP3_EVENT_SPAWN3_FACE,
+ RP3_EVENT_SPAWN3_AGGRO,
+ RP3_EVENT_EPOCH_SPAWN,
+ RP3_EVENT_ARTHAS31,
+ RP3_EVENT_EPOCH_FACE,
+ RP3_EVENT_EPOCH1,
+ RP3_EVENT_ARTHAS32,
+ RP3_EVENT_ARTHAS32_2,
+ RP3_EVENT_EPOCH_AGGRO,
+
+ RP4_EVENT_ARTHAS2,
+ RP4_EVENT_HIDDEN_PASSAGE,
+ RP4_EVENT_ARTHAS3,
+ RP4_EVENT_GAUNTLET_REACHED,
+
+ RP4_EVENT_ARTHAS_MOVE,
+ RP4_EVENT_ARTHAS11,
+ RP4_EVENT_ARTHAS_FACE,
+ RP4_EVENT_ARTHAS12,
+ RP4_EVENT_GAUNTLET_RESUME,
+ RP4_EVENT_ARTHAS13,
+ RP4_EVENT_GAUNTLET_DONE,
+
+ RP5_EVENT_ARTHAS2,
+ RP5_EVENT_MALGANIS1,
+ RP5_EVENT_MALGANIS_DONE,
+ RP5_EVENT_MALGANIS12,
+ RP5_EVENT_MALGANIS_LEAVE,
+ RP5_EVENT_ARTHAS10,
+ RP5_EVENT_ARTHAS10_2,
+ RP5_EVENT_ARTHAS11,
+ RP5_EVENT_ARTHAS11_2,
+ RP5_EVENT_ARTHAS_LEAVE,
+ RP5_EVENT_ARTHAS_LEAVE2,
+ RP5_EVENT_CHROMIE_SPAWN,
+ RP5_EVENT_CHROMIE_LAND,
+ RP5_EVENT_CHROMIE_TRANSFORM
+};
+
+enum RPEventLines1
+{
+ RP1_LINE_ARTHAS1 = 0, // Glad you could make it, Uther.
+ RP1_LINE_UTHER1 = 0, // Watch your tone with me, boy. You may be the prince, but I'm still your superior as a paladin!
+ RP1_LINE_ARTHAS2 = 1, // As if I could forget. Listen, Uther, there's something about the plague you should know...
+ RP1_LINE_ARTHAS3 = 2, // Oh, no. We're too late. These people have all been infected! They may look fine now, but it's just a matter of time before they turn into the undead!
+ RP1_LINE_UTHER2 = 1, // What?
+ RP1_LINE_ARTHAS4 = 3, // This entire city must be purged.
+ RP1_LINE_UTHER3 = 2, // How can you even consider that? There's got to be some other way.
+ RP1_LINE_ARTHAS5 = 4, // Damn it, Uther! As your future king, I order you to purge this city!
+ RP1_LINE_UTHER4 = 3, // You are not my king yet, boy! Nor would I obey that command even if you were!
+ RP1_LINE_ARTHAS6 = 5, // Then I must consider this an act of treason.
+ RP1_LINE_UTHER5 = 4, // Treason? Have you lost your mind, Arthas?
+ RP1_LINE_ARTHAS7 = 6, // Have I? Lord Uther, by my right of succession and the sovereignty of my crown, I hereby relieve you of your command and suspend your paladins from service.
+ RP1_LINE_JAINA1 = 0, // Arthas! You can't just--
+ RP1_LINE_ARTHAS8 = 7, // It's done! Those of you who have the will to save this land, follow me! The rest of you... get out of my sight!
+ RP1_LINE_UTHER6 = 5, // You've just crossed a terrible threshold, Arthas.
+ RP1_LINE_ARTHAS9 = 8, // Jaina?
+ RP1_LINE_JAINA2 = 1, // I'm sorry, Arthas. I can't watch you do this.
+ RP1_LINE_ARTHAS10 = 9, // Take position here, and I will lead a small force inside Stratholme to begin the culling. We must contain and purge the infected for the sake of all of Lordaeron!
+ RP1_LINE_ARTHAS11 = 40 // All officers should check in with me when their squads are ready. We'll enter Stratholme on my order.
+};
+
+enum RPEventLines2
+{
+ RP2_LINE_ARTHAS1 = 10, // Everyone looks ready. Remember, these people are all infected with the plague and will die soon. We must purge Stratholme to protect the remainder of Lordaeron from the Scourge. Let's go.
+ RP2_LINE_CITIZEN1 = 0, // Prince Arthas, may the light be praised! Many people in the town have begun to fall seriously ill, can you help us?
+ RP2_LINE_ARTHAS2 = 11, // I can only help you with a clean death.
+ RP2_LINE_CITIZEN2 = 1, // What? This can't be!
+ RP2_LINE_RESIDENT1 = 0, // Oh, no...
+ RP2_LINE_ARTHAS3 = 12, // That was just the beginning.
+ RP2_LINE_MALGANIS1 = 0, // Yes, this is the beginning. I've been waiting for you, young prince. I am Mal'Ganis.
+ RP2_LINE_MALGANIS2 = 1, // As you can see, your people are now mine. I will now turn this city household by household, until the flame of life has been snuffed out... forever.
+ RP2_LINE_ARTHAS4 = 13, // I won't allow it, Mal'Ganis! Better that these people die by my hand than serve as your slaves in death!
+ RP2_LINE_ARTHAS5 = 14 // Mal'Ganis will send out some of his Scourge minions to interfere with us. Those of you with the strongest steel and magic shall go forth and destroy them. I will lead the rest of my forces in purging Stratholme of the infected.
+};
+
+enum RPEventLines3
+{
+ RP3_LINE_ARTHAS1 = 16, // Follow me, I know the way through.
+ RP3_LINE_CITIZEN1 = 0, // Ah, you've finally arrived Prince Arthas. You're here just in the nick of time.
+ RP3_LINE_ARTHAS2 = 17, // Yes, I'm glad I could get to you before the plague.
+ RP3_LINE_ARTHAS3 = 18, // What is this sorcery?
+ RP3_LINE_CITIZEN2 = 1, // There's no need for you to understand, Arthas. All you need to do is die.
+ RP3_LINE_ARTHAS4 = 19, // Mal'Ganis appears to have more than Scourge in his arsenal. We should make haste.
+
+ RP3_LINE_ARTHAS10 = 20, // More vile sorcery! Be ready for anything!
+ RP3_LINE_ARTHAS11 = 21, // Let's move on.
+
+ RP3_LINE_ARTHAS20 = 22, // Watch your backs: they have us surrounded in this hall.
+ RP3_LINE_ARTHAS21 = 24, // Mal'ganis is not making this easy.
+
+ RP3_LINE_ARTHAS30 = 25, // They're very persistent.
+ RP3_LINE_ARTHAS31 = 26, // What else can he put in my way?
+ RP3_LINE_EPOCH1 = 0, // Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own.
+ RP3_LINE_ARTHAS32 = 27, // I do what I must for Lordaeron, and neither your words nor your actions will stop me.
+ RP3_LINE_EPOCH2 = 1 // We'll see about that, young prince.
+};
+
+enum RPEventLines4
+{
+ RP4_LINE_ARTHAS1 = 28, // The quickest path to Mal'Ganis lies behind that bookshelf ahead.
+ RP4_LINE_ARTHAS2 = 29, // This will only take a moment.
+ RP4_LINE_ARTHAS3 = 30, // I'm relieved this secret passage still works.
+
+ RP4_LINE_ARTHAS10 = 31, // Let's move through here as quickly as possible. If the undead don't kill us, the fires might.
+ RP4_LINE_ARTHAS11 = 32, // Rest a moment and clear your lungs, but we must move again soon.
+ RP4_LINE_ARTHAS12 = 33, // That's enough; we must move again. Mal'Ganis awaits.
+ RP4_LINE_ARTHAS13 = 34 // At last some good luck. Market Row has not caught fire yet. Mal'Ganis is supposed to be in Crusaders' Square, which is just ahead. Tell me when you're ready to move forward.
+};
+
+enum RPEventLines5
+{
+ RP5_LINE_ARTHAS1 = 35, // Justice will be done.
+ RP5_LINE_ARTHAS2 = 36, // We're going to finish this right now, Mal'Ganis. Just you... and me.
+ RP5_LINE_MALGANIS1 = 2, // This will be a fine test, Prince Arthas.
+ RP5_LINE_MALGANIS12 = 10, // Your journey has just begun, young prince. Gather your forces and meet me in the arctic land of Northrend. It is there that we shall settle the score between us. It is there that your true destiny will unfold.
+ RP5_LINE_ARTHAS10 = 37, // I'll hunt you to the ends of the earth if I have to! Do you hear me? To the ends of the earth!
+ RP5_LINE_ARTHAS11 = 38, // You performed well this day. Anything that Mal'Ganis has left behind is yours. Take it as your reward. I must now begin plans for an expedition to Northrend.
+ RP5_LINE_CHROMIE0 = 0 // Why, hello again!
+};
+
+enum PositionIndices : uint32
+{
+ // Arthas/Uther RP
+ RP1_ARTHAS_INITIAL = 0,
+ RP1_UTHER_SPAWN,
+ RP1_JAINA_SPAWN,
+
+ // Arthas/Mal'ganis RP
+ ARTHAS_PURGE_PENDING_POS,
+ ARTHAS_WAVES_POS,
+ RP2_PRIEST1_POS,
+ RP2_PRIEST2_POS,
+ RP2_FOOT1_POS,
+ RP2_FOOT2_POS,
+ RP2_FOOT3_POS,
+ RP2_FOOT4_POS,
+ RP2_MALGANIS_POS,
+
+ // Town Hall
+ ARTHAS_TOWN_HALL_POS,
+ RP3_SPAWN1_LOC1,
+ RP3_SPAWN1_LOC2,
+ RP3_SPAWN1_LOC3,
+ RP3_SPAWN1_LOC4,
+ RP3_SPAWN1_RIFT,
+ RP3_SPAWN2_LOC1,
+ RP3_SPAWN2_LOC2,
+ RP3_SPAWN2_LOC3,
+ RP3_SPAWN2_LOC4,
+ RP3_SPAWN2_RIFT1,
+ RP3_SPAWN2_RIFT2,
+ RP3_SPAWN3_LOC1,
+ RP3_SPAWN3_LOC2,
+ RP3_SPAWN3_LOC3,
+ RP3_SPAWN3_LOC4,
+ RP3_SPAWN3_RIFT1,
+ RP3_SPAWN3_RIFT2,
+ RP3_EPOCH_SPAWN,
+ RP3_EPOCH_RIFT,
+ ARTHAS_TOWN_HALL_END_POS,
+
+ ARTHAS_GAUNTLET_POS,
+ ARTHAS_GAUNTLET_END_POS,
+
+ RP5_MALGANIS_POS,
+ ARTHAS_FINAL_POS,
+ RP5_CHROMIE_SPAWN,
+
+ // Array element count
+ NUM_POSITIONS,
+};
+
+enum OtherLines
+{
+ LINE_TOWN_HALL_PENDING = 15,
+ LINE_SLAY_ZOMBIE = 39
+};
+
+// @todo sniff
+// All kinds of positions Arthas needs for RP events (there are a lot of these)
+static std::array<Position, NUM_POSITIONS> const ArthasPositions =
+{
+ {
+ { 1983.857f, 1287.043f, 145.5596f, 3.0892330f }, // RP1_ARTHAS_INITIAL
+ { 1783.843f, 1267.481f, 139.7800f, 0.2698664f }, // RP1_UTHER_SPAWN
+ { 1876.788f, 1305.723f, 146.2474f, 6.0737460f }, // RP1_JAINA_SPAWN
+
+ { 2047.948f, 1287.598f, 142.8568f, 3.176499f }, // ARTHAS_PURGE_PENDING_POS
+ { 2091.994f, 1277.257f, 140.4707f, 1.134464f }, // ARTHAS_WAVES_POS // @todo
+ { 2074.624f, 1282.958f, 141.6344f }, // RP2_PRIEST1_POS
+ { 2074.805f, 1292.172f, 141.6728f }, // RP2_PRIEST2_POS
+ { 2077.590f, 1284.609f, 141.5710f }, // RP2_FOOT1_POS
+ { 2078.365f, 1281.254f, 141.5182f }, // RP2_FOOT2_POS
+ { 2077.737f, 1290.441f, 141.5698f }, // RP2_FOOT3_POS
+ { 2078.055f, 1293.624f, 141.5544f }, // RP2_FOOT4_POS
+ { 2113.454f, 1287.986f, 136.3829f, 3.071779f }, // RP2_MALGANIS_POS
+
+ { 2366.240f, 1195.253f, 132.0441f, 3.159046f }, // ARTHAS_TOWN_HALL_POS
+ { 2433.154f, 1192.572f, 148.1547f, 5.542059f }, // RP3_SPAWN1_LOC1
+ { 2432.990f, 1192.760f, 148.1474f, 1.026526f }, // RP3_SPAWN1_LOC2
+ { 2432.824f, 1191.816f, 148.1556f, 4.927707f }, // RP3_SPAWN1_LOC3
+ { 2432.711f, 1192.857f, 148.1550f, 6.257423f }, // RP3_SPAWN1_LOC4
+ { 2433.357f, 1192.168f, 148.1593f, 3.001966f }, // RP3_SPAWN1_RIFT_SPAWN
+ { 2414.349f, 1136.075f, 148.1592f, 1.345922f }, // RP3_SPAWN2_LOC1
+ { 2403.961f, 1180.299f, 148.1587f, 5.139339f }, // RP3_SPAWN2_LOC2
+ { 2414.671f, 1136.262f, 148.1592f, 2.305776f }, // RP3_SPAWN2_LOC3
+ { 2403.908f, 1179.994f, 148.1586f, 4.654133f }, // RP3_SPAWN2_LOC4
+ { 2404.311f, 1178.306f, 148.1585f, 1.605703f }, // RP3_SPAWN2_RIFT1
+ { 2414.041f, 1136.068f, 148.1593f, 2.234021f }, // RP3_SPAWN2_RIFT2
+ { 2429.026f, 1102.693f, 148.1499f, 1.952652f }, // RP3_SPAWN3_LOC1
+ { 2441.173f, 1115.225f, 148.1264f, 2.302970f }, // RP3_SPAWN3_LOC2
+ { 2430.645f, 1104.685f, 148.1306f, 1.135255f }, // RP3_SPAWN3_LOC3
+ { 2439.649f, 1113.719f, 148.1298f, 3.111888f }, // RP3_SPAWN3_LOC4
+ { 2429.296f, 1102.007f, 148.1593f, 6.213372f }, // RP3_SPAWN3_RIFT1
+ { 2440.057f, 1114.226f, 148.1593f, 6.108652f }, // RP3_SPAWN3_RIFT2
+ { 2457.008f, 1113.929f, 150.0776f, 3.272437f }, // RP3_EPOCH_SPAWN
+ { 2456.058f, 1113.838f, 150.0917f, 1.745329f }, // RP3_EPOCH_RIFT
+ { 2425.898f, 1118.842f, 148.0759f, 6.073746f }, // ARTHAS_TOWN_HALL_END_POS
+
+ { 2534.988f, 1126.163f, 130.8621f, 2.844887f }, // ARTHAS_GAUNTLET_POS
+ { 2363.440f, 1404.906f, 128.7869f, 2.775074f }, // ARTHAS_GAUNTLET_END_POS
+
+ { 2296.862f, 1501.015f, 128.4456f, 5.131268f }, // RP5_MALGANIS_POS
+ { 2301.055f, 1478.977f, 128.1299f, 1.758816f }, // ARTHAS_FINAL_POS
+ { 2319.560f, 1506.408f, 152.0474f }, // RP5_CHROMIE_SPAWN
+ }
+};
+
+uint32 const chromiePathSize = 3;
+G3D::Vector3 const ChromieSplinePos[chromiePathSize] =
+{
+ { 2320.632f, 1507.193f, 152.5081f },
+ { 2319.823f, 1506.605f, 152.5081f },
+ { 2306.770f, 1496.780f, 128.3620f }
+};
+
+static float const ArthasSnapbackDistanceThreshold = 5.0f; // how far we can be from where we're supposed at start of phase to be before we snap back
+
+struct SnapbackInfo
+{
+ ReactStates const ReactState;
+ bool const HasGossip;
+ Position const* const SnapbackPosition;
+};
+
+// Positions Arthas should be at when starting a given phase
+static std::unordered_map<uint32, SnapbackInfo> const ArthasSnapbackPositions =
+{
+ { JUST_STARTED, { REACT_PASSIVE, false, &ArthasPositions[RP1_ARTHAS_INITIAL] } },
+ { CRATES_IN_PROGRESS, { REACT_PASSIVE, false, &ArthasPositions[RP1_ARTHAS_INITIAL] } },
+ { CRATES_DONE, { REACT_PASSIVE, false, &ArthasPositions[RP1_ARTHAS_INITIAL] } },
+ { UTHER_TALK, { REACT_PASSIVE, false, &ArthasPositions[RP1_ARTHAS_INITIAL] } },
+ { PURGE_PENDING, { REACT_PASSIVE, true, &ArthasPositions[ARTHAS_PURGE_PENDING_POS] } },
+ { PURGE_STARTING, { REACT_PASSIVE, false, &ArthasPositions[ARTHAS_PURGE_PENDING_POS] } },
+ { WAVES_IN_PROGRESS, { REACT_AGGRESSIVE, false, &ArthasPositions[ARTHAS_WAVES_POS] } },
+ { WAVES_DONE, { REACT_DEFENSIVE, false, &ArthasPositions[ARTHAS_WAVES_POS] } },
+ { TOWN_HALL_PENDING, { REACT_DEFENSIVE, true, &ArthasPositions[ARTHAS_TOWN_HALL_POS] } },
+ { TOWN_HALL, { REACT_DEFENSIVE, false, &ArthasPositions[ARTHAS_TOWN_HALL_POS] } },
+ { TOWN_HALL_COMPLETE, { REACT_PASSIVE, true, &ArthasPositions[ARTHAS_TOWN_HALL_END_POS] } },
+ { GAUNTLET_TRANSITION, { REACT_PASSIVE, false, &ArthasPositions[ARTHAS_TOWN_HALL_END_POS] } },
+ { GAUNTLET_PENDING, { REACT_PASSIVE, true, &ArthasPositions[ARTHAS_GAUNTLET_POS] } },
+ { GAUNTLET_IN_PROGRESS, { REACT_DEFENSIVE, false, &ArthasPositions[ARTHAS_GAUNTLET_POS] } },
+ { GAUNTLET_COMPLETE, { REACT_PASSIVE, true, &ArthasPositions[ARTHAS_GAUNTLET_END_POS] } },
+ { MALGANIS_IN_PROGRESS, { REACT_DEFENSIVE, false, &ArthasPositions[ARTHAS_GAUNTLET_END_POS] } },
+ { COMPLETE, { REACT_PASSIVE, false, &ArthasPositions[ARTHAS_FINAL_POS] } }
+};
+
+class npc_arthas_stratholme : public CreatureScript
+{
+public:
+ npc_arthas_stratholme() : CreatureScript("npc_arthas_stratholme") { }
+
+ struct npc_arthas_stratholmeAI : public ScriptedAI
+ {
+ npc_arthas_stratholmeAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()), _exorcismCooldown(urandms(7, 14)), _progressRP(true), _afterCombat(ACTION_NONE) { }
+
+ inline COSProgressStates GetCurrentProgress()
+ {
+ return COSProgressStates(instance->GetData(DATA_INSTANCE_PROGRESS));
+ }
+
+ void AdvanceToState(COSProgressStates newState)
+ {
+ if (!_progressRP)
+ _progressRP = true;
+
+ auto itr = ArthasSnapbackPositions.find(newState);
+ if (itr != ArthasSnapbackPositions.end())
+ {
+ SnapbackInfo const& target = itr->second;
+
+ // Adjust react state and npc flags based on current state
+ me->SetReactState(target.ReactState);
+ if (target.ReactState == REACT_PASSIVE)
+ me->SetImmuneToAll(true, false);
+ else
+ me->SetImmuneToAll(false);
+
+ // Adjust gossip flag based on whether we have a gossip menu or not
+ if (target.HasGossip)
+ me->AddNpcFlag(UNIT_NPC_FLAG_GOSSIP);
+ else
+ me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
+
+ // Snapback handling - if we're too far from where we're supposed to be, teleport there
+ if (target.SnapbackPosition->GetExactDist(me) > ArthasSnapbackDistanceThreshold)
+ me->NearTeleportTo(*target.SnapbackPosition);
+ }
+
+ switch (newState)
+ {
+ case WAVES_DONE:
+ events.ScheduleEvent(EVENT_TOWN_HALL_REACHED, 3s);
+ break;
+ case UTHER_TALK:
+ if (Creature* uther = me->SummonCreature(NPC_UTHER, ArthasPositions[RP1_UTHER_SPAWN], TEMPSUMMON_MANUAL_DESPAWN))
+ {
+ uther->setActive(true);
+ uther->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_UTHER1, RP1_CHAIN_UTHER1, false);
+ }
+ if (Creature* jaina = me->SummonCreature(NPC_JAINA, ArthasPositions[RP1_JAINA_SPAWN], TEMPSUMMON_MANUAL_DESPAWN))
+ {
+ jaina->setActive(true);
+ jaina->GetMotionMaster()->MoveAlongSplineChain(0, RP1_CHAIN_JAINA1, true);
+ }
+ me->GetMotionMaster()->MoveAlongSplineChain(0, RP1_CHAIN_ARTHAS1, false);
+ break;
+ case TOWN_HALL_PENDING:
+ Talk(LINE_TOWN_HALL_PENDING);
+ break;
+ case COMPLETE:
+ if (events.Empty())
+ {
+ // This must be instance loading into COMPLETE state, spawn chromie
+ events.ScheduleEvent(RP5_EVENT_CHROMIE_SPAWN, 1s);
+ events.ScheduleEvent(RP5_EVENT_CHROMIE_LAND, 12s + 668ms);
+ events.ScheduleEvent(RP5_EVENT_CHROMIE_TRANSFORM, 15s + 491ms);
+ me->SetVisible(false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Will happen immediately (if OOC) or on reached home (if IC)
+ void ScheduleActionOOC(Actions action)
+ {
+ if (_progressRP)
+ DoAction(action);
+ else
+ _afterCombat = action;
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case -ACTION_PROGRESS_UPDATE:
+ AdvanceToState(GetCurrentProgress());
+ break;
+ case RP3_ACTION_AFTER_INITIAL:
+ events.ScheduleEvent(RP3_EVENT_ARTHAS4, 1s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_MOVE_1, 7s);
+ break;
+ case RP3_ACTION_AFTER_SPAWN1:
+ events.ScheduleEvent(RP3_EVENT_ARTHAS11, 1s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_MOVE_2, 3s);
+ break;
+ case RP3_ACTION_AFTER_SPAWN2:
+ events.ScheduleEvent(RP3_EVENT_ARTHAS21, 1s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_MOVE_3, 4s);
+ break;
+ case RP3_ACTION_AFTER_SPAWN3:
+ events.ScheduleEvent(RP3_EVENT_EPOCH_SPAWN, 3s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS31, 4s);
+ events.ScheduleEvent(RP3_EVENT_EPOCH_FACE, 6s);
+ events.ScheduleEvent(RP3_EVENT_EPOCH1, 9s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS32, 22s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS32_2, 27s);
+ events.ScheduleEvent(RP3_EVENT_EPOCH_AGGRO, 30s);
+ break;
+ case RP3_ACTION_AFTER_EPOCH:
+ instance->SetData(DATA_TOWN_HALL_DONE, 1);
+ break;
+ case RP5_ACTION_AFTER_MALGANIS:
+ events.ScheduleEvent(RP5_EVENT_MALGANIS_DONE, 3s);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void SetGUID(ObjectGuid const& guid, int32 type) override
+ {
+ _eventStarterGuid = guid;
+
+ Unit* talkTarget = ObjectAccessor::GetUnit(*me, _eventStarterGuid);
+ switch (type)
+ {
+ case -ACTION_START_RP_EVENT2:
+ Talk(RP2_LINE_ARTHAS1, talkTarget);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS_MOVE_1, Seconds(9));
+ break;
+ case -ACTION_START_RP_EVENT3:
+ Talk(RP3_LINE_ARTHAS1, talkTarget);
+ me->GetMotionMaster()->MoveAlongSplineChain(RP3_POINTID_ARTHAS1, RP3_CHAIN_ARTHAS1, false);
+ break;
+ case -ACTION_START_RP_EVENT4_1:
+ Talk(RP4_LINE_ARTHAS1, talkTarget);
+ me->GetMotionMaster()->MoveAlongSplineChain(RP4_POINTID_ARTHAS1, RP4_CHAIN_ARTHAS1, true);
+ break;
+ case -ACTION_START_RP_EVENT4_2:
+ Talk(RP4_LINE_ARTHAS10, talkTarget);
+ events.ScheduleEvent(RP4_EVENT_ARTHAS_MOVE, Seconds(5));
+ break;
+ case -ACTION_START_RP_EVENT5:
+ Talk(RP5_LINE_ARTHAS1, talkTarget);
+ instance->instance->SummonCreature(NPC_MALGANIS, ArthasPositions[RP5_MALGANIS_POS]);
+ me->GetMotionMaster()->MoveAlongSplineChain(RP5_POINTID_ARTHAS1, RP5_CHAIN_ARTHAS1, false);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (!_progressRP)
+ return;
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
+ switch (id)
+ {
+ case RP1_POINTID_UTHER1:
+ events.ScheduleEvent(RP1_EVENT_START1, 0s);
+ events.ScheduleEvent(RP1_EVENT_START2, 1s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS1, 4s);
+ events.ScheduleEvent(RP1_EVENT_UTHER1, 8s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS2, 15s);
+ break;
+ case RP1_POINTID_UTHER2:
+ events.ScheduleEvent(RP1_EVENT_UTHER_FACE, 0s);
+ break;
+ case RP1_POINTID_JAINA2:
+ events.ScheduleEvent(RP1_EVENT_JAINA_FACE, 0s);
+ break;
+ case RP1_POINTID_ARTHAS2:
+ events.ScheduleEvent(RP1_EVENT_ARTHAS3, 1s);
+ events.ScheduleEvent(RP1_EVENT_UTHER2, 12s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS_TURN, 13s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS4, 14s);
+ events.ScheduleEvent(RP1_EVENT_UTHER3, 18s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS5, 24s);
+ events.ScheduleEvent(RP1_EVENT_UTHER4, 30s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS6, 36s);
+ events.ScheduleEvent(RP1_EVENT_UTHER5, 39s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS7, 44s);
+ events.ScheduleEvent(RP1_EVENT_JAINA1, 57s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS8, 59s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS8_2, 65s);
+ events.ScheduleEvent(RP1_EVENT_UTHER6, 71s);
+ events.ScheduleEvent(RP1_EVENT_UTHER_LEAVE, 74s);
+ events.ScheduleEvent(RP1_EVENT_JAINA_LEAVE, 75s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS9, 76s);
+ events.ScheduleEvent(RP1_EVENT_JAINA2, 78s);
+ events.ScheduleEvent(RP1_EVENT_JAINA_LEAVE2, 82s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS_LEAVE, 88s);
+ break;
+ case RP1_POINTID_UTHER3:
+ if (Creature* uther = me->FindNearestCreature(NPC_UTHER, 500.0f, true))
+ uther->DespawnOrUnsummon();
+ break;
+ case RP1_POINTID_JAINA4:
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 500.0f, true))
+ jaina->DespawnOrUnsummon();
+ break;
+ case RP1_POINTID_ARTHAS3:
+ events.ScheduleEvent(RP1_EVENT_ARTHAS10, 0s);
+ events.ScheduleEvent(RP1_EVENT_ARTHAS_LEAVE2, 12s);
+ break;
+ case RP1_POINTID_ARTHAS4:
+ events.ScheduleEvent(RP1_EVENT_FINISHED, 0s);
+ break;
+ case RP2_POINTID_ARTHAS1:
+ if (Creature* citizen = me->FindNearestCreature(NPC_CITIZEN, 100.0f, true))
+ citizen->SetFacingToObject(me);
+ if (Creature* resident = me->FindNearestCreature(NPC_RESIDENT, 100.0f, true))
+ resident->SetFacingToObject(me);
+ events.ScheduleEvent(RP2_EVENT_CITIZEN1, 2s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS2, 10s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS_MOVE_2, 11s);
+ break;
+ case RP2_POINTID_ARTHAS2:
+ events.ScheduleEvent(RP2_EVENT_CITIZEN2, 0s);
+ events.ScheduleEvent(RP2_EVENT_KILL1, 1s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS_MOVE_3, 3s);
+ break;
+ case RP2_POINTID_ARTHAS3:
+ events.ScheduleEvent(RP2_EVENT_KILL2, 1s);
+ events.ScheduleEvent(RP2_EVENT_REACT1, 2s);
+ events.ScheduleEvent(RP2_EVENT_REACT2, 3s);
+ events.ScheduleEvent(RP2_EVENT_REACT3, 4s);
+ events.ScheduleEvent(RP2_EVENT_REACT4, 6s);
+ events.ScheduleEvent(RP2_EVENT_REACT5, 6s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS_MOVE_4, 4s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS3, 6s);
+ events.ScheduleEvent(RP2_EVENT_MALGANIS1, 10s);
+ events.ScheduleEvent(RP2_EVENT_TROOPS_FACE, 11s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS_FACE, 13s);
+ events.ScheduleEvent(RP2_EVENT_MALGANIS2, 22s);
+ events.ScheduleEvent(RP2_EVENT_MALGANIS_LEAVE1, 34s);
+ events.ScheduleEvent(RP2_EVENT_MALGANIS_LEAVE2, 35s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS4, 35s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS4_2, 39s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS_MOVE_5, 45s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS5, 45s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS5_2, 51s);
+ events.ScheduleEvent(RP2_EVENT_ARTHAS5_3, 57s);
+ events.ScheduleEvent(RP2_EVENT_WAVE_START, 64s);
+ break;
+ case RP3_POINTID_ARTHAS1:
+ {
+ std::list<Creature*> infinites;
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_CITIZEN_INFINITE, 100.0f);
+ for (Creature* infinite : infinites)
+ infinite->SetFacingToObject(me);
+ events.ScheduleEvent(RP3_EVENT_RESIDENT_FACE, 1s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_FACE, 2s);
+ events.ScheduleEvent(RP3_EVENT_CITIZEN1, 3s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS2, 12s);
+ break;
+ }
+ case RP3_POINTID_ARTHAS2:
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_KILL, 1s);
+ events.ScheduleEvent(RP3_EVENT_INFINITE_LAUGH, 2s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS3, 6s);
+ events.ScheduleEvent(RP3_EVENT_CITIZEN2, 8s);
+ events.ScheduleEvent(RP3_EVENT_TRANSFORM1, 10s);
+ events.ScheduleEvent(RP3_EVENT_TRANSFORM2, 12s);
+ events.ScheduleEvent(RP3_EVENT_TRANSFORM3, 14s);
+ events.ScheduleEvent(RP3_EVENT_AGGRO, 15s);
+ break;
+ case RP3_POINTID_ARTHAS3:
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_MOVE_1_2, 1s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN1, 2s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN1_FACE, 5s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN1_AGGRO, 7s);
+ break;
+ case RP3_POINTID_ARTHAS4:
+ events.ScheduleEvent(RP3_EVENT_ARTHAS20, 1s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN2, 2s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS_FACE2, 3s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN2_FACE, 4s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN2_AGGRO, 6s);
+ break;
+ case RP3_POINTID_ARTHAS5:
+ events.ScheduleEvent(RP3_EVENT_SPAWN3, 2s);
+ events.ScheduleEvent(RP3_EVENT_ARTHAS30, 4s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN3_FACE, 5s);
+ events.ScheduleEvent(RP3_EVENT_SPAWN3_AGGRO, 6s);
+ break;
+ case RP4_POINTID_ARTHAS1:
+ events.ScheduleEvent(RP4_EVENT_ARTHAS2, 1s);
+ events.ScheduleEvent(RP4_EVENT_HIDDEN_PASSAGE, 4s); // @todo sniff timer
+ events.ScheduleEvent(RP4_EVENT_ARTHAS3, 5s);
+ break;
+ case RP4_POINTID_ARTHAS2:
+ events.ScheduleEvent(RP4_EVENT_GAUNTLET_REACHED, 1s);
+ break;
+ case RP4_POINTID_GAUNTLET1:
+ events.ScheduleEvent(RP4_EVENT_ARTHAS11, 1s);
+ events.ScheduleEvent(RP4_EVENT_ARTHAS_FACE, 5s);
+ events.ScheduleEvent(RP4_EVENT_ARTHAS12, 21s);
+ events.ScheduleEvent(RP4_EVENT_GAUNTLET_RESUME, 25s);
+ break;
+ case RP4_POINTID_GAUNTLET2:
+ events.ScheduleEvent(RP4_EVENT_ARTHAS13, 1s);
+ events.ScheduleEvent(RP4_EVENT_GAUNTLET_DONE, 7s);
+ break;
+ case RP5_POINTID_ARTHAS1:
+ events.ScheduleEvent(RP5_EVENT_ARTHAS2, 1s);
+ events.ScheduleEvent(RP5_EVENT_MALGANIS1, 6s);
+ break;
+ case RP5_POINTID_ARTHAS3:
+ events.ScheduleEvent(RP5_EVENT_ARTHAS_LEAVE2, 0s);
+ break;
+ case RP5_POINTID_ARTHAS4:
+ me->NearTeleportTo(ArthasPositions[ARTHAS_FINAL_POS]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool CanAIAttack(Unit const* who) const override
+ {
+ if (me->HasReactState(REACT_AGGRESSIVE))
+ {
+ Position const& relativePos = me->IsEngaged() ? me->GetHomePosition() : me->GetPosition();
+ // Don't let us chase too far from home
+ if (relativePos.GetExactDist2d(who) > 30.0f)
+ return false;
+ }
+ return ScriptedAI::CanAIAttack(who);
+ }
+
+ void UpdateAICombat(uint32 diff)
+ {
+ if (me->HasReactState(REACT_PASSIVE))
+ return;
+
+ if (!UpdateVictim())
+ return;
+
+ if (HealthBelowPct(40))
+ DoCastSelf(SPELL_HOLY_LIGHT);
+ if (_exorcismCooldown <= diff)
+ {
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ _exorcismCooldown = 0;
+ else if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ {
+ DoCast(target, SPELL_EXORCISM);
+ _exorcismCooldown = urandms(7, 14);
+ }
+ }
+ else
+ _exorcismCooldown -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (me->IsEngaged())
+ {
+ UpdateAICombat(diff);
+ return;
+ }
+
+ // EventMap is only used for RP handling. RP events are paused while in combat or leashing back to resume pos
+ if (!_progressRP)
+ return;
+
+ events.Update(diff);
+ while (uint32 event = events.ExecuteEvent())
+ {
+ uint32 talkerEntry = UINT_MAX, talkerLine = 0;
+ switch (event)
+ {
+ case RP1_EVENT_START1:
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 100.0f, true))
+ jaina->SetFacingToObject(me);
+ break;
+ case RP1_EVENT_START2:
+ if (Creature* uther = me->FindNearestCreature(NPC_UTHER, 100.0f, true))
+ {
+ uther->SetFacingToObject(me);
+ me->SetFacingToObject(uther);
+ }
+ break;
+ case RP1_EVENT_ARTHAS1:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS1;
+ break;
+ case RP1_EVENT_UTHER1:
+ talkerEntry = NPC_UTHER, talkerLine = RP1_LINE_UTHER1;
+ break;
+ case RP1_EVENT_ARTHAS2:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS2;
+ me->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_ARTHAS2, RP1_CHAIN_ARTHAS2, true);
+ if (Creature* uther = me->FindNearestCreature(NPC_UTHER, 100.0f, true))
+ uther->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_UTHER2, RP1_CHAIN_UTHER2, true);
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 100.0f, true))
+ jaina->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_JAINA2, RP1_CHAIN_JAINA2, true);
+ break;
+ case RP1_EVENT_UTHER_FACE:
+ if (Creature* uther = me->FindNearestCreature(NPC_UTHER, 100.0f, true))
+ uther->SetFacingToObject(me);
+ break;
+ case RP1_EVENT_JAINA_FACE:
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 100.0f, true))
+ jaina->SetFacingToObject(me);
+ break;
+ case RP1_EVENT_ARTHAS3:
+ {
+ me->SetFacingTo(6.248279f); // @todo migrate
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS3;
+ std::list<Creature*> troops;
+ me->GetCreatureListWithEntryInGrid(troops, NPC_FOOTMAN, 100.0f);
+ me->GetCreatureListWithEntryInGrid(troops, NPC_SORCERESS, 100.0f);
+ me->GetCreatureListWithEntryInGrid(troops, NPC_KNIGHT, 100.0f);
+ me->GetCreatureListWithEntryInGrid(troops, NPC_PRIEST, 100.0f);
+ for (Creature* unit : troops)
+ if (unit->IsAlive())
+ unit->SetFacingToObject(me);
+ break;
+ }
+ case RP1_EVENT_UTHER2:
+ talkerEntry = NPC_UTHER, talkerLine = RP1_LINE_UTHER2;
+ break;
+ case RP1_EVENT_ARTHAS4:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS4;
+ break;
+ case RP1_EVENT_UTHER3:
+ talkerEntry = NPC_UTHER, talkerLine = RP1_LINE_UTHER3;
+ break;
+ case RP1_EVENT_ARTHAS_TURN:
+ if (Creature* uther = me->FindNearestCreature(NPC_UTHER, 100.0f, true))
+ me->SetFacingToObject(uther);
+ break;
+ case RP1_EVENT_ARTHAS5:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS5;
+ break;
+ case RP1_EVENT_UTHER4:
+ talkerEntry = NPC_UTHER, talkerLine = RP1_LINE_UTHER4;
+ break;
+ case RP1_EVENT_ARTHAS6:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS6;
+ break;
+ case RP1_EVENT_UTHER5:
+ talkerEntry = NPC_UTHER, talkerLine = RP1_LINE_UTHER5;
+ break;
+ case RP1_EVENT_ARTHAS7:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS7;
+ break;
+ case RP1_EVENT_JAINA1:
+ talkerEntry = NPC_JAINA, talkerLine = RP1_LINE_JAINA1;
+ break;
+ case RP1_EVENT_ARTHAS8:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS8;
+ break;
+ case RP1_EVENT_ARTHAS8_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ break;
+ case RP1_EVENT_UTHER6:
+ talkerEntry = NPC_UTHER, talkerLine = RP1_LINE_UTHER6;
+ break;
+ case RP1_EVENT_UTHER_LEAVE:
+ if (Creature* uther = me->FindNearestCreature(NPC_UTHER, 100.0f, true))
+ uther->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_UTHER3, RP1_CHAIN_UTHER3, true);
+ break;
+ case RP1_EVENT_JAINA_LEAVE:
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 100.0f, true))
+ jaina->GetMotionMaster()->MoveAlongSplineChain(0, RP1_CHAIN_JAINA3, true);
+ break;
+ case RP1_EVENT_ARTHAS9:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS9;
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 100.0f, true))
+ me->SetFacingToObject(jaina);
+ break;
+ case RP1_EVENT_JAINA2:
+ talkerEntry = NPC_JAINA, talkerLine = RP1_LINE_JAINA2;
+ break;
+ case RP1_EVENT_JAINA_LEAVE2:
+ if (Creature* jaina = me->FindNearestCreature(NPC_JAINA, 100.0f, true))
+ jaina->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_JAINA4, RP1_CHAIN_JAINA4, true);
+ break;
+ case RP1_EVENT_ARTHAS_LEAVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_ARTHAS3, RP1_CHAIN_ARTHAS3, true);
+ break;
+ case RP1_EVENT_ARTHAS10:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS10;
+ me->SetFacingTo(3.141593f); // @todo migrate
+ break;
+ case RP1_EVENT_ARTHAS_LEAVE2:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP1_POINTID_ARTHAS4, RP1_CHAIN_ARTHAS4, false);
+ break;
+ case RP1_EVENT_FINISHED:
+ talkerEntry = 0, talkerLine = RP1_LINE_ARTHAS11;
+ me->SetFacingTo(ArthasPositions[ARTHAS_PURGE_PENDING_POS].GetOrientation());
+ instance->SetData(DATA_UTHER_FINISHED, 1);
+ break;
+ case RP2_EVENT_ARTHAS_MOVE_1:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP2_POINTID_ARTHAS1, RP2_CHAIN_ARTHAS1, true);
+ break;
+ case RP2_EVENT_CITIZEN1:
+ if (Creature* citizen = me->FindNearestCreature(NPC_CITIZEN, 100.0f, true))
+ {
+ citizen->GetMotionMaster()->MoveAlongSplineChain(0, RP2_CHAIN_CITIZEN1, true);
+ citizen->AI()->Talk(RP2_LINE_CITIZEN1, ObjectAccessor::GetUnit(*me, _eventStarterGuid));
+ }
+ break;
+ case RP2_EVENT_ARTHAS2:
+ talkerEntry = 0, talkerLine = RP2_LINE_ARTHAS2;
+ break;
+ case RP2_EVENT_ARTHAS_MOVE_2:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP2_POINTID_ARTHAS2, RP2_CHAIN_ARTHAS2, true);
+ break;
+ case RP2_EVENT_CITIZEN2:
+ talkerEntry = NPC_CITIZEN, talkerLine = RP2_LINE_CITIZEN2;
+ break;
+ case RP2_EVENT_KILL1:
+ if (Creature* citizen = me->FindNearestCreature(NPC_CITIZEN, 100.0f, true))
+ DoCast(citizen, SPELL_CRUSADER_STRIKE);
+ if (Creature* resident = me->FindNearestCreature(NPC_RESIDENT, 100.0f, true))
+ {
+ resident->SetEmoteState(EMOTE_STATE_COWER);
+ resident->AI()->Talk(RP2_LINE_RESIDENT1, ObjectAccessor::GetUnit(*me, _eventStarterGuid));
+ }
+ break;
+ case RP2_EVENT_ARTHAS_MOVE_3:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP2_POINTID_ARTHAS3, RP2_CHAIN_ARTHAS3, true);
+ break;
+ case RP2_EVENT_KILL2:
+ if (Creature* resident = me->FindNearestCreature(NPC_RESIDENT, 100.0f, true))
+ DoCast(resident, SPELL_CRUSADER_STRIKE);
+ break;
+ case RP2_EVENT_REACT1:
+ case RP2_EVENT_REACT2:
+ case RP2_EVENT_REACT3:
+ case RP2_EVENT_REACT4:
+ case RP2_EVENT_REACT5:
+ {
+ std::list<Creature*> nearbyVictims;
+ me->GetCreatureListWithEntryInGrid(nearbyVictims, urand(0, 1) ? NPC_CITIZEN : NPC_RESIDENT, 60.0f);
+ if (!nearbyVictims.empty())
+ {
+ std::list<Creature*>::iterator it = nearbyVictims.begin();
+ std::advance(it, urand(0, nearbyVictims.size()-1));
+ Emote emote;
+ switch (urand(0, 3))
+ {
+ case 0:
+ emote = EMOTE_ONESHOT_TALK;
+ break;
+ case 1:
+ emote = EMOTE_ONESHOT_EXCLAMATION;
+ break;
+ case 2:
+ emote = EMOTE_ONESHOT_RUDE;
+ break;
+ case 3:
+ emote = EMOTE_ONESHOT_ROAR;
+ break;
+ default:
+ break;
+ }
+ if ((*it)->IsAlive())
+ (*it)->HandleEmoteCommand(emote);
+ }
+ break;
+ }
+ case RP2_EVENT_ARTHAS_MOVE_4:
+ me->SetFacingTo(2.234021f); // @todo
+ break;
+ case RP2_EVENT_ARTHAS3:
+ talkerEntry = 0, talkerLine = RP2_LINE_ARTHAS3;
+ break;
+ case RP2_EVENT_MALGANIS1:
+ if (Creature* bunny = me->FindNearestCreature(NPC_MALGANIS_BUNNY, 80.0f, true))
+ bunny->CastSpell(bunny, SPELL_SHADOWSTEP_VISUAL);
+
+ if (Creature* malganis = instance->instance->SummonCreature(NPC_MALGANIS, ArthasPositions[RP2_MALGANIS_POS]))
+ {
+ malganis->CastSpell(malganis, SPELL_SHADOWSTEP_VISUAL);
+ malganis->AI()->Talk(RP2_LINE_MALGANIS1);
+ }
+ break;
+ case RP2_EVENT_TROOPS_FACE:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 80.0f, true))
+ {
+ std::list<Creature*> troops;
+ me->GetCreatureListWithEntryInGrid(troops, NPC_FOOTMAN, 50.0f);
+ me->GetCreatureListWithEntryInGrid(troops, NPC_PRIEST, 50.0f);
+ for (Creature* unit : troops)
+ if (unit->IsAlive())
+ unit->SetFacingToObject(malganis);
+ }
+ break;
+ case RP2_EVENT_ARTHAS_FACE:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 80.0f, true))
+ me->SetFacingToObject(malganis);
+ break;
+ case RP2_EVENT_MALGANIS2:
+ talkerEntry = NPC_MALGANIS, talkerLine = RP2_LINE_MALGANIS2;
+ break;
+ case RP2_EVENT_MALGANIS_LEAVE1:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 80.0f, true))
+ malganis->CastSpell(malganis, SPELL_SHADOWSTEP_VISUAL);
+ break;
+ case RP2_EVENT_MALGANIS_LEAVE2:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 80.0f, true))
+ malganis->DespawnOrUnsummon(0);
+ if (Creature* bunny = me->FindNearestCreature(NPC_MALGANIS_BUNNY, 80.0f, true))
+ bunny->CastSpell(bunny, SPELL_SHADOWSTEP_VISUAL);
+ break;
+ case RP2_EVENT_ARTHAS4:
+ talkerEntry = 0, talkerLine = RP2_LINE_ARTHAS4;
+ break;
+ case RP2_EVENT_ARTHAS4_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ break;
+ case RP2_EVENT_ARTHAS5:
+ talkerEntry = 0, talkerLine = RP2_LINE_ARTHAS5;
+ break;
+ case RP2_EVENT_ARTHAS5_2:
+ case RP2_EVENT_ARTHAS5_3:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
+ break;
+ case RP2_EVENT_WAVE_START:
+ instance->SetData(DATA_START_WAVES, 1);
+ break;
+ case EVENT_TOWN_HALL_REACHED:
+ me->DespawnOrUnsummon();
+ instance->SetData(DATA_REACH_TOWN_HALL, 1);
+ break;
+ case RP3_EVENT_RESIDENT_FACE:
+ if (Creature* infinite = me->FindNearestCreature(NPC_RESIDENT_INFINITE, 100.0f, true))
+ infinite->SetFacingToObject(me);
+ break;
+ case RP3_EVENT_ARTHAS_FACE:
+ me->SetFacingTo(0.541052f); // @todo
+ break;
+ case RP3_EVENT_CITIZEN1:
+ talkerEntry = NPC_CITIZEN_INFINITE, talkerLine = RP3_LINE_CITIZEN1;
+ break;
+ case RP3_EVENT_ARTHAS2:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS2;
+ me->GetMotionMaster()->MoveAlongSplineChain(RP3_POINTID_ARTHAS2, RP3_CHAIN_ARTHAS2, true);
+ break;
+ case RP3_EVENT_ARTHAS_KILL:
+ if (Creature* citizen = me->FindNearestCreature(NPC_CITIZEN_INFINITE, 100.0f, true))
+ DoCast(citizen, SPELL_CRUSADER_STRIKE);
+ break;
+ case RP3_EVENT_INFINITE_LAUGH:
+ if (Creature* citizen = me->FindNearestCreature(NPC_CITIZEN_INFINITE, 100.0f, true))
+ citizen->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH);
+ break;
+ case RP3_EVENT_ARTHAS3:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS3;
+ break;
+ case RP3_EVENT_CITIZEN2:
+ talkerEntry = NPC_CITIZEN_INFINITE, talkerLine = RP3_LINE_CITIZEN2;
+ break;
+ case RP3_EVENT_TRANSFORM1:
+ case RP3_EVENT_TRANSFORM3:
+ if (Creature* citizen = me->FindNearestCreature(NPC_CITIZEN_INFINITE, 100.0f, true))
+ {
+ citizen->CastSpell(citizen, SPELL_TRANSFORM_VISUAL);
+ citizen->UpdateEntry(NPC_INFINITE_HUNTER);
+ }
+ break;
+ case RP3_EVENT_TRANSFORM2:
+ if (Creature* resident = me->FindNearestCreature(NPC_RESIDENT_INFINITE, 100.0f, true))
+ {
+ resident->CastSpell(resident, SPELL_TRANSFORM_VISUAL);
+ resident->UpdateEntry(NPC_INFINITE_AGENT);
+ }
+ break;
+ case RP3_EVENT_AGGRO:
+ EngageInfinites();
+ ScheduleActionOOC(RP3_ACTION_AFTER_INITIAL);
+ break;
+ case RP3_EVENT_ARTHAS4:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS4;
+ break;
+ case RP3_EVENT_ARTHAS_MOVE_1:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP3_POINTID_ARTHAS3, RP3_CHAIN_ARTHAS3, false);
+ break;
+ case RP3_EVENT_ARTHAS_MOVE_1_2:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS10;
+ me->GetMotionMaster()->MoveAlongSplineChain(0, RP3_CHAIN_ARTHAS3_2, true);
+ break;
+ case RP3_EVENT_SPAWN1:
+ {
+ uint8 extra = urand(0, 2); // 0 = extra adversary, 1 = extra hunter, 2 = extra agent
+ if (Creature* spawn1 = instance->instance->SummonCreature(NPC_INFINITE_ADVERSARY, ArthasPositions[RP3_SPAWN1_LOC1]))
+ MoveInfiniteOnSpawn(spawn1, RP3_CHAIN_SPAWN1_LOC1);
+ if (Creature* spawn2 = instance->instance->SummonCreature(extra ? NPC_INFINITE_HUNTER : NPC_INFINITE_ADVERSARY, ArthasPositions[RP3_SPAWN1_LOC2]))
+ MoveInfiniteOnSpawn(spawn2, RP3_CHAIN_SPAWN1_LOC2);
+ if (Creature* spawn3 = instance->instance->SummonCreature(extra < 2 ? NPC_INFINITE_HUNTER : NPC_INFINITE_AGENT, ArthasPositions[RP3_SPAWN1_LOC3]))
+ MoveInfiniteOnSpawn(spawn3, RP3_CHAIN_SPAWN1_LOC3);
+ if (Creature* spawn4 = instance->instance->SummonCreature(NPC_INFINITE_AGENT, ArthasPositions[RP3_SPAWN1_LOC4]))
+ MoveInfiniteOnSpawn(spawn4, RP3_CHAIN_SPAWN1_LOC4);
+ if (Creature* rift = instance->instance->SummonCreature(NPC_TIME_RIFT, ArthasPositions[RP3_SPAWN1_RIFT]))
+ rift->DespawnOrUnsummon(Seconds(4));
+ break;
+ }
+ case RP3_EVENT_SPAWN1_FACE:
+ case RP3_EVENT_SPAWN2_FACE:
+ case RP3_EVENT_SPAWN3_FACE:
+ {
+ std::list<Creature*> infinites;
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_INFINITE_ADVERSARY, 100.0f);
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_INFINITE_AGENT, 100.0f);
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_INFINITE_HUNTER, 100.0f);
+ for (Creature* target : infinites)
+ if (target->IsAlive())
+ target->SetFacingToObject(me);
+ break;
+ }
+ case RP3_EVENT_SPAWN1_AGGRO:
+ EngageInfinites();
+ ScheduleActionOOC(RP3_ACTION_AFTER_SPAWN1);
+ break;
+ case RP3_EVENT_ARTHAS11:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS11;
+ break;
+ case RP3_EVENT_ARTHAS_MOVE_2:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP3_POINTID_ARTHAS4, RP3_CHAIN_ARTHAS4, false);
+ break;
+ case RP3_EVENT_ARTHAS20:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS20;
+ break;
+ case RP3_EVENT_SPAWN2:
+ {
+ uint8 extra = urand(0, 2); // 0 = extra adversary, 1 = extra hunter, 2 = extra agent
+ if (Creature* SPAWN2 = instance->instance->SummonCreature(NPC_INFINITE_ADVERSARY, ArthasPositions[RP3_SPAWN2_LOC1]))
+ MoveInfiniteOnSpawn(SPAWN2, RP3_CHAIN_SPAWN2_LOC1);
+ if (Creature* spawn2 = instance->instance->SummonCreature(extra ? NPC_INFINITE_HUNTER : NPC_INFINITE_ADVERSARY, ArthasPositions[RP3_SPAWN2_LOC2]))
+ MoveInfiniteOnSpawn(spawn2, RP3_CHAIN_SPAWN2_LOC2);
+ if (Creature* spawn3 = instance->instance->SummonCreature(extra < 2 ? NPC_INFINITE_HUNTER : NPC_INFINITE_AGENT, ArthasPositions[RP3_SPAWN2_LOC3]))
+ MoveInfiniteOnSpawn(spawn3, RP3_CHAIN_SPAWN2_LOC3);
+ if (Creature* spawn4 = instance->instance->SummonCreature(NPC_INFINITE_AGENT, ArthasPositions[RP3_SPAWN2_LOC4]))
+ MoveInfiniteOnSpawn(spawn4, RP3_CHAIN_SPAWN2_LOC4);
+ if (Creature* rift1 = instance->instance->SummonCreature(NPC_TIME_RIFT, ArthasPositions[RP3_SPAWN2_RIFT1]))
+ rift1->DespawnOrUnsummon(Seconds(5));
+ if (Creature* rift2 = instance->instance->SummonCreature(NPC_TIME_RIFT, ArthasPositions[RP3_SPAWN2_RIFT2]))
+ rift2->DespawnOrUnsummon(Seconds(5));
+ break;
+ }
+ case RP3_EVENT_ARTHAS_FACE2:
+ me->SetFacingTo(1.762783f); // @todo
+ break;
+ case RP3_EVENT_SPAWN2_AGGRO:
+ EngageInfinites();
+ ScheduleActionOOC(RP3_ACTION_AFTER_SPAWN2);
+ break;
+ case RP3_EVENT_ARTHAS21:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS21;
+ break;
+ case RP3_EVENT_ARTHAS_MOVE_3:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP3_POINTID_ARTHAS5, RP3_CHAIN_ARTHAS5, false);
+ break;
+ case RP3_EVENT_SPAWN3:
+ {
+ uint8 extra = urand(0, 2); // 0 = extra adversary, 1 = extra hunter, 2 = extra agent
+ if (Creature* SPAWN3 = instance->instance->SummonCreature(NPC_INFINITE_ADVERSARY, ArthasPositions[RP3_SPAWN3_LOC1]))
+ MoveInfiniteOnSpawn(SPAWN3, RP3_CHAIN_SPAWN3_LOC1);
+ if (Creature* SPAWN3 = instance->instance->SummonCreature(extra ? NPC_INFINITE_HUNTER : NPC_INFINITE_ADVERSARY, ArthasPositions[RP3_SPAWN3_LOC2]))
+ MoveInfiniteOnSpawn(SPAWN3, RP3_CHAIN_SPAWN3_LOC2);
+ if (Creature* spawn3 = instance->instance->SummonCreature(extra < 2 ? NPC_INFINITE_HUNTER : NPC_INFINITE_AGENT, ArthasPositions[RP3_SPAWN3_LOC3]))
+ MoveInfiniteOnSpawn(spawn3, RP3_CHAIN_SPAWN3_LOC3);
+ if (Creature* spawn4 = instance->instance->SummonCreature(NPC_INFINITE_AGENT, ArthasPositions[RP3_SPAWN3_LOC4]))
+ MoveInfiniteOnSpawn(spawn4, RP3_CHAIN_SPAWN3_LOC4);
+ if (Creature* rift1 = instance->instance->SummonCreature(NPC_TIME_RIFT, ArthasPositions[RP3_SPAWN3_RIFT1]))
+ rift1->DespawnOrUnsummon(Seconds(5));
+ if (Creature* rift2 = instance->instance->SummonCreature(NPC_TIME_RIFT, ArthasPositions[RP3_SPAWN3_RIFT2]))
+ rift2->DespawnOrUnsummon(Seconds(5));
+ break;
+ }
+ case RP3_EVENT_ARTHAS30:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS30;
+ break;
+ case RP3_EVENT_SPAWN3_AGGRO:
+ EngageInfinites();
+ ScheduleActionOOC(RP3_ACTION_AFTER_SPAWN3);
+ break;
+ case RP3_EVENT_EPOCH_SPAWN:
+ if (Creature* epoch = instance->instance->SummonCreature(NPC_EPOCH, ArthasPositions[RP3_EPOCH_SPAWN]))
+ epoch->GetMotionMaster()->MoveAlongSplineChain(0, RP3_CHAIN_EPOCH, false);
+ if (Creature* rift = instance->instance->SummonCreature(NPC_TIME_RIFT_LARGE, ArthasPositions[RP3_EPOCH_RIFT]))
+ rift->DespawnOrUnsummon(Seconds(27));
+ break;
+ case RP3_EVENT_ARTHAS31:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS31;
+ me->SetFacingTo(6.073746f); // @todo
+ break;
+ case RP3_EVENT_EPOCH_FACE:
+ if (Creature* epoch = me->FindNearestCreature(NPC_EPOCH, 100.0f, true))
+ epoch->SetFacingToObject(me);
+ break;
+ case RP3_EVENT_EPOCH1:
+ talkerEntry = NPC_EPOCH, talkerLine = RP3_LINE_EPOCH1;
+ break;
+ case RP3_EVENT_ARTHAS32:
+ talkerEntry = 0, talkerLine = RP3_LINE_ARTHAS32;
+ break;
+ case RP3_EVENT_ARTHAS32_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NO_SHEATHE);
+ break;
+ case RP3_EVENT_EPOCH_AGGRO:
+ talkerEntry = NPC_EPOCH, talkerLine = RP3_LINE_EPOCH2;
+ if (Creature* epoch = me->FindNearestCreature(NPC_EPOCH, 100.0f, true))
+ {
+ epoch->SetImmuneToAll(false);
+ me->EngageWithTarget(epoch);
+ epoch->EngageWithTarget(me);
+ }
+ ScheduleActionOOC(RP3_ACTION_AFTER_EPOCH);
+ break;
+ case RP4_EVENT_ARTHAS2:
+ me->SetFacingTo(0.226893f); // @todo
+ talkerEntry = 0, talkerLine = RP4_LINE_ARTHAS2;
+ break;
+ case RP4_EVENT_HIDDEN_PASSAGE:
+ if (GameObject* passage = me->FindNearestGameObject(GO_HIDDEN_PASSAGE, 100.0f))
+ passage->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case RP4_EVENT_ARTHAS3:
+ talkerEntry = 0, talkerLine = RP4_LINE_ARTHAS3;
+ me->GetMotionMaster()->MoveAlongSplineChain(RP4_POINTID_ARTHAS2, RP4_CHAIN_ARTHAS2, false);
+ break;
+ case RP4_EVENT_GAUNTLET_REACHED:
+ me->DespawnOrUnsummon();
+ instance->SetData(DATA_GAUNTLET_REACHED, 1);
+ break;
+ case RP4_EVENT_ARTHAS_MOVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP4_POINTID_GAUNTLET1, RP4_CHAIN_GAUNTLET1, false);
+ break;
+ case RP4_EVENT_ARTHAS11:
+ talkerEntry = 0, talkerLine = RP4_LINE_ARTHAS11;
+ break;
+ case RP4_EVENT_ARTHAS_FACE:
+ me->SetFacingTo(1.780236f); // @todo
+ break;
+ case RP4_EVENT_ARTHAS12:
+ talkerEntry = 0, talkerLine = RP4_LINE_ARTHAS12;
+ break;
+ case RP4_EVENT_GAUNTLET_RESUME:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP4_POINTID_GAUNTLET2, RP4_CHAIN_GAUNTLET2, false);
+ break;
+ case RP4_EVENT_ARTHAS13:
+ talkerEntry = 0, talkerLine = RP4_LINE_ARTHAS13;
+ me->SetFacingTo(ArthasPositions[ARTHAS_GAUNTLET_END_POS].GetOrientation());
+ break;
+ case RP4_EVENT_GAUNTLET_DONE:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_POINT_NO_SHEATHE);
+ instance->SetData(DATA_GAUNTLET_DONE, 1);
+ break;
+ case RP5_EVENT_ARTHAS2:
+ talkerEntry = 0, talkerLine = RP5_LINE_ARTHAS2;
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 100.0f, true))
+ me->SetFacingToObject(malganis);
+ break;
+ case RP5_EVENT_MALGANIS1:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 100.0f, true))
+ {
+ malganis->AI()->Talk(RP5_LINE_MALGANIS1, ObjectAccessor::GetUnit(*malganis, _eventStarterGuid));
+ malganis->SetImmuneToAll(false);
+ me->EngageWithTarget(malganis);
+ malganis->EngageWithTarget(me);
+ }
+ ScheduleActionOOC(RP5_ACTION_AFTER_MALGANIS);
+ break;
+ case RP5_EVENT_MALGANIS_DONE:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 100.0f, true))
+ {
+ malganis->SetFacingToObject(me);
+ malganis->CastSpell(malganis, SPELL_MALGANIS_QUEST_CREDIT, true);
+ malganis->CastSpell(malganis, SPELL_MALGANIS_KILL_CREDIT, true);
+ if (GameObject* chest = malganis->FindNearestGameObject(RAID_MODE(GO_CHEST_NORMAL, GO_CHEST_HEROIC), 100.0f))
+ chest->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ }
+ events.ScheduleEvent(RP5_EVENT_MALGANIS12, 3s);
+ events.ScheduleEvent(RP5_EVENT_MALGANIS_LEAVE, 19s);
+ events.ScheduleEvent(RP5_EVENT_ARTHAS10, 20s);
+ events.ScheduleEvent(RP5_EVENT_ARTHAS10_2, 27s);
+ events.ScheduleEvent(RP5_EVENT_ARTHAS11, 30s);
+ events.ScheduleEvent(RP5_EVENT_ARTHAS11_2, 35s);
+ events.ScheduleEvent(RP5_EVENT_ARTHAS_LEAVE, 45s);
+ events.ScheduleEvent(RP5_EVENT_CHROMIE_SPAWN, 65s);
+ events.ScheduleEvent(RP5_EVENT_CHROMIE_LAND, 76s + 668ms);
+ events.ScheduleEvent(RP5_EVENT_CHROMIE_TRANSFORM, 79s + 491ms);
+ instance->SetBossState(DATA_MAL_GANIS, DONE);
+ instance->SetData(DATA_MALGANIS_DONE, 1);
+ break;
+ case RP5_EVENT_MALGANIS12:
+ talkerEntry = NPC_MALGANIS, talkerLine = RP5_LINE_MALGANIS12;
+ break;
+ case RP5_EVENT_MALGANIS_LEAVE:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 100.0f, true))
+ malganis->CastSpell(malganis, SPELL_SHADOWSTEP_VISUAL);
+ break;
+ case RP5_EVENT_ARTHAS10:
+ if (Creature* malganis = me->FindNearestCreature(NPC_MALGANIS, 100.0f, true))
+ malganis->DespawnOrUnsummon();
+ me->GetMotionMaster()->MoveAlongSplineChain(0, RP5_CHAIN_ARTHAS2, false);
+ talkerEntry = 0, talkerLine = RP5_LINE_ARTHAS10;
+ break;
+ case RP5_EVENT_ARTHAS10_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ break;
+ case RP5_EVENT_ARTHAS11:
+ talkerEntry = 0, talkerLine = RP5_LINE_ARTHAS11;
+ break;
+ case RP5_EVENT_ARTHAS11_2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
+ break;
+ case RP5_EVENT_ARTHAS_LEAVE:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP5_POINTID_ARTHAS3, RP5_CHAIN_ARTHAS3, true);
+ break;
+ case RP5_EVENT_ARTHAS_LEAVE2:
+ me->GetMotionMaster()->MoveAlongSplineChain(RP5_POINTID_ARTHAS4, RP5_CHAIN_ARTHAS4, true);
+ break;
+ case RP5_EVENT_CHROMIE_SPAWN:
+ if (Creature* chromie = instance->instance->SummonCreature(NPC_CHROMIE_3, ArthasPositions[RP5_CHROMIE_SPAWN]))
+ {
+ chromie->RemoveNpcFlag(NPCFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER));
+ Movement::PointsArray path(ChromieSplinePos, ChromieSplinePos + chromiePathSize);
+ Movement::MoveSplineInit init(chromie);
+ init.SetFly();
+ init.SetWalk(true);
+ init.MovebyPath(path, 0);
+ me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE);
+ }
+ break;
+ case RP5_EVENT_CHROMIE_LAND:
+ if (Creature* chromie = me->FindNearestCreature(NPC_CHROMIE_3, 100.0f, true))
+ chromie->SetAnimTier(UNIT_BYTE1_FLAG_NONE, true);
+ break;
+ case RP5_EVENT_CHROMIE_TRANSFORM:
+ if (Creature* chromie = me->FindNearestCreature(NPC_CHROMIE_3, 100.0f, true))
+ {
+ chromie->CastSpell(chromie, SPELL_CHROMIE_3_TRANSFORM);
+ chromie->AI()->Talk(RP5_LINE_CHROMIE0);
+ chromie->AddNpcFlag(NPCFlags(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER));
+ }
+ default:
+ break;
+ }
+
+ if (talkerEntry != UINT_MAX)
+ {
+ Creature* talker;
+ if (talkerEntry)
+ talker = me->FindNearestCreature(talkerEntry, 100.0f, true);
+ else
+ talker = me;
+ if (talker)
+ talker->AI()->Talk(talkerLine, ObjectAccessor::GetUnit(*talker, _eventStarterGuid));
+ }
+ }
+ }
+
+ void EngageInfinites()
+ {
+ std::list<Creature*> infinites;
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_INFINITE_ADVERSARY, 100.0f);
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_INFINITE_AGENT, 100.0f);
+ me->GetCreatureListWithEntryInGrid(infinites, NPC_INFINITE_HUNTER, 100.0f);
+ for (Creature* target : infinites)
+ {
+ target->SetImmuneToAll(false);
+ me->EngageWithTarget(target);
+ target->EngageWithTarget(me);
+ }
+ }
+
+ static void MoveInfiniteOnSpawn(Creature* infinite, SplineChains chainId)
+ {
+ if (std::vector<SplineChainLink> const* chain = sScriptSystemMgr->GetSplineChain(NPC_INFINITE_ADVERSARY, chainId))
+ infinite->GetMotionMaster()->MoveAlongSplineChain(0, *chain, true);
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who && who->GetEntry() == NPC_RISEN_ZOMBIE)
+ Talk(LINE_SLAY_ZOMBIE, who);
+ }
+
+ void JustEngagedWith(Unit* who) override
+ {
+ if (_progressRP)
+ {
+ _progressRP = false;
+ me->SetHomePosition(me->GetPosition());
+
+ SplineChainMovementGenerator::GetResumeInfo(_resumeMovement, me);
+ }
+ ScriptedAI::JustEngagedWith(who);
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ ScriptedAI::EnterEvadeMode(why);
+ }
+
+ void JustReachedHome() override
+ {
+ if (!me->HasAura(SPELL_DEVOTION_AURA))
+ DoCastSelf(SPELL_DEVOTION_AURA);
+
+ _progressRP = true;
+
+ if (!_resumeMovement.Empty()) // WP motion was interrupted, resume
+ {
+ me->GetMotionMaster()->ResumeSplineChain(_resumeMovement);
+ _resumeMovement.Clear();
+ }
+
+ if (_afterCombat)
+ {
+ DoAction(_afterCombat);
+ _afterCombat = ACTION_NONE;
+ }
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ // Instance failure: regress back to last stable state
+ instance->SetData(DATA_ARTHAS_DIED, 1);
+ me->DespawnOrUnsummon(5s);
+ }
+
+ void JustAppeared() override
+ {
+ _progressRP = true;
+ AdvanceToState(GetCurrentProgress());
+ DoCastSelf(SPELL_DEVOTION_AURA);
+ }
+
+ void AdvanceDungeon(Player* cause, COSProgressStates from, COSInstanceData command)
+ {
+ if (instance->GetData(DATA_INSTANCE_PROGRESS) == from)
+ instance->SetGuidData(command, cause->GetGUID());
+ }
+
+ bool GossipSelect(Player* player, uint32 /*sender*/, uint32 /*listId*/) override
+ {
+ AdvanceDungeon(player, PURGE_PENDING, DATA_START_PURGE);
+ AdvanceDungeon(player, TOWN_HALL_PENDING, DATA_START_TOWN_HALL);
+ AdvanceDungeon(player, TOWN_HALL_COMPLETE, DATA_TO_GAUNTLET);
+ AdvanceDungeon(player, GAUNTLET_PENDING, DATA_START_GAUNTLET);
+ AdvanceDungeon(player, GAUNTLET_COMPLETE, DATA_START_MALGANIS);
+ return true;
+ }
+
+ bool GossipHello(Player* /*player*/) override
+ {
+ return false;
+ }
+
+ private:
+ InstanceScript* const instance;
+ EventMap events;
+ ObjectGuid _eventStarterGuid;
+ uint32 _exorcismCooldown; // no EventMap entry for this, it's reserved for RP handling
+
+ bool _progressRP;
+ Actions _afterCombat;
+ SplineChainResumeInfo _resumeMovement;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetCullingOfStratholmeAI<npc_arthas_stratholmeAI>(creature);
+ }
+};
+
+Position const& GetArthasSnapbackFor(COSProgressStates state)
+{
+ auto itr = ArthasSnapbackPositions.find(state);
+ if (itr == ArthasSnapbackPositions.end())
+ itr = ArthasSnapbackPositions.begin();
+ return *(itr->second.SnapbackPosition);
+}
+
+// Arthas' AI is the one controlling everything, all this AI does is report any movementinforms back to Arthas AI
+struct npc_stratholme_rp_dummy : NullCreatureAI
+{
+ npc_stratholme_rp_dummy(Creature* creature) : NullCreatureAI(creature) { }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == POINT_MOTION_TYPE || type == EFFECT_MOTION_TYPE || type == SPLINE_CHAIN_MOTION_TYPE)
+ if (TempSummon* self = me->ToTempSummon())
+ self->GetSummonerCreatureBase()->AI()->MovementInform(type, id);
+ }
+};
+
+class spell_stratholme_crusader_strike : public SpellScript
+{
+ PrepareSpellScript(spell_stratholme_crusader_strike);
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ if (target->GetEntry() == NPC_CITIZEN || target->GetEntry() == NPC_RESIDENT)
+ Unit::Kill(GetCaster(), target);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_stratholme_crusader_strike::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
+
+void AddSC_npc_arthas_stratholme()
+{
+ new npc_arthas_stratholme();
+ RegisterCreatureAI(npc_stratholme_rp_dummy);
+ RegisterSpellScript(spell_stratholme_crusader_strike);
+}
diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
index b407f012790..dbeb903d752 100644
--- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
+++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
@@ -16,12 +16,14 @@
*/
// This is where scripts' loading functions should be declared:
-void AddSC_blackfathom_deeps(); //Blackfathom Depths
+// Blackfathom Depths
+void AddSC_blackfathom_deeps();
void AddSC_boss_gelihast();
void AddSC_boss_kelris();
void AddSC_boss_aku_mai();
void AddSC_instance_blackfathom_deeps();
-void AddSC_hyjal(); //CoT Battle for Mt. Hyjal
+// CoT Battle for Mt. Hyjal
+void AddSC_hyjal();
void AddSC_boss_archimonde();
void AddSC_instance_mount_hyjal();
void AddSC_hyjal_trash();
@@ -29,48 +31,60 @@ void AddSC_boss_rage_winterchill();
void AddSC_boss_anetheron();
void AddSC_boss_kazrogal();
void AddSC_boss_azgalor();
-void AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad
+// CoT Old Hillsbrad
+void AddSC_boss_captain_skarloc();
void AddSC_boss_epoch_hunter();
void AddSC_boss_lieutenant_drake();
void AddSC_instance_old_hillsbrad();
void AddSC_old_hillsbrad();
-void AddSC_boss_aeonus(); //CoT The Black Morass
+// CoT The Black Morass
+void AddSC_boss_aeonus();
void AddSC_boss_chrono_lord_deja();
void AddSC_boss_temporus();
void AddSC_the_black_morass();
void AddSC_instance_the_black_morass();
-void AddSC_boss_epoch(); //CoT Culling Of Stratholme
+// CoT Culling Of Stratholme
+void AddSC_boss_epoch();
+void AddSC_npc_arthas_stratholme();
void AddSC_boss_infinite_corruptor();
void AddSC_boss_salramm();
void AddSC_boss_mal_ganis();
void AddSC_boss_meathook();
void AddSC_culling_of_stratholme();
void AddSC_instance_culling_of_stratholme();
-void AddSC_instance_dire_maul(); //Dire Maul
-void AddSC_instance_ragefire_chasm(); //Ragefire Chasm
-void AddSC_boss_celebras_the_cursed(); //Maraudon
+// Dire Maul
+void AddSC_instance_dire_maul();
+// Ragefire Chasm
+void AddSC_instance_ragefire_chasm();
+// Maraudon
+void AddSC_boss_celebras_the_cursed();
void AddSC_boss_landslide();
void AddSC_boss_noxxion();
void AddSC_boss_ptheradras();
void AddSC_instance_maraudon();
-void AddSC_boss_onyxia(); //Onyxia's Lair
+// Onyxia's Lair
+void AddSC_boss_onyxia();
void AddSC_instance_onyxias_lair();
-void AddSC_boss_tuten_kash(); //Razorfen Downs
+// Razorfen Downs
+void AddSC_boss_tuten_kash();
void AddSC_boss_mordresh_fire_eye();
void AddSC_boss_glutton();
void AddSC_boss_amnennar_the_coldbringer();
void AddSC_razorfen_downs();
void AddSC_instance_razorfen_downs();
-void AddSC_razorfen_kraul(); //Razorfen Kraul
+// Razorfen Kraul
+void AddSC_razorfen_kraul();
void AddSC_instance_razorfen_kraul();
-void AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj
+// Ruins of ahn'qiraj
+void AddSC_boss_kurinnaxx();
void AddSC_boss_rajaxx();
void AddSC_boss_moam();
void AddSC_boss_buru();
void AddSC_boss_ayamiss();
void AddSC_boss_ossirian();
void AddSC_instance_ruins_of_ahnqiraj();
-void AddSC_boss_cthun(); //Temple of ahn'qiraj
+// Temple of ahn'qiraj
+void AddSC_boss_cthun();
void AddSC_boss_viscidus();
void AddSC_boss_fankriss();
void AddSC_boss_huhuran();
@@ -81,9 +95,11 @@ void AddSC_boss_twinemperors();
void AddSC_boss_ouro();
void AddSC_npc_anubisath_sentinel();
void AddSC_instance_temple_of_ahnqiraj();
-void AddSC_wailing_caverns(); //Wailing caverns
+// Wailing caverns
+void AddSC_wailing_caverns();
void AddSC_instance_wailing_caverns();
-void AddSC_boss_zum_rah(); //Zul'Farrak
+// Zul'Farrak
+void AddSC_boss_zum_rah();
void AddSC_zulfarrak();
void AddSC_instance_zulfarrak();
void AddSC_instance_halls_of_origination();
@@ -121,12 +137,14 @@ void AddSC_winterspring();
// void Add${NameOfDirectory}Scripts()
void AddKalimdorScripts()
{
- AddSC_blackfathom_deeps(); //Blackfathom Depths
+ // Blackfathom Depths
+ AddSC_blackfathom_deeps();
AddSC_boss_gelihast();
AddSC_boss_kelris();
AddSC_boss_aku_mai();
AddSC_instance_blackfathom_deeps();
- AddSC_hyjal(); //CoT Battle for Mt. Hyjal
+ // CoT Battle for Mt. Hyjal
+ AddSC_hyjal();
AddSC_boss_archimonde();
AddSC_instance_mount_hyjal();
AddSC_hyjal_trash();
@@ -134,48 +152,60 @@ void AddKalimdorScripts()
AddSC_boss_anetheron();
AddSC_boss_kazrogal();
AddSC_boss_azgalor();
- AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad
+ // CoT Old Hillsbrad
+ AddSC_boss_captain_skarloc();
AddSC_boss_epoch_hunter();
AddSC_boss_lieutenant_drake();
AddSC_instance_old_hillsbrad();
AddSC_old_hillsbrad();
- AddSC_boss_aeonus(); //CoT The Black Morass
+ // CoT The Black Morass
+ AddSC_boss_aeonus();
AddSC_boss_chrono_lord_deja();
AddSC_boss_temporus();
AddSC_the_black_morass();
AddSC_instance_the_black_morass();
- AddSC_boss_epoch(); //CoT Culling Of Stratholme
+ // CoT Culling Of Stratholme
+ AddSC_boss_epoch();
+ AddSC_npc_arthas_stratholme();
AddSC_boss_infinite_corruptor();
AddSC_boss_salramm();
AddSC_boss_mal_ganis();
AddSC_boss_meathook();
AddSC_culling_of_stratholme();
AddSC_instance_culling_of_stratholme();
- AddSC_instance_dire_maul(); //Dire Maul
- AddSC_instance_ragefire_chasm(); //Ragefire Chasm
- AddSC_boss_celebras_the_cursed(); //Maraudon
+ // Dire Maul
+ AddSC_instance_dire_maul();
+ // Ragefire Chasm
+ AddSC_instance_ragefire_chasm();
+ //Maraudon
+ AddSC_boss_celebras_the_cursed();
AddSC_boss_landslide();
AddSC_boss_noxxion();
AddSC_boss_ptheradras();
AddSC_instance_maraudon();
- AddSC_boss_onyxia(); //Onyxia's Lair
+ // Onyxia's Lair
+ AddSC_boss_onyxia();
AddSC_instance_onyxias_lair();
- AddSC_boss_tuten_kash(); //Razorfen Downs
+ // Razorfen Downs
+ AddSC_boss_tuten_kash();
AddSC_boss_mordresh_fire_eye();
AddSC_boss_glutton();
AddSC_boss_amnennar_the_coldbringer();
AddSC_razorfen_downs();
AddSC_instance_razorfen_downs();
- AddSC_razorfen_kraul(); //Razorfen Kraul
+ // Razorfen Kraul
+ AddSC_razorfen_kraul();
AddSC_instance_razorfen_kraul();
- AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj
+ // Ruins of ahn'qiraj
+ AddSC_boss_kurinnaxx();
AddSC_boss_rajaxx();
AddSC_boss_moam();
AddSC_boss_buru();
AddSC_boss_ayamiss();
AddSC_boss_ossirian();
AddSC_instance_ruins_of_ahnqiraj();
- AddSC_boss_cthun(); //Temple of ahn'qiraj
+ // Temple of ahn'qiraj
+ AddSC_boss_cthun();
AddSC_boss_viscidus();
AddSC_boss_fankriss();
AddSC_boss_huhuran();
@@ -186,9 +216,11 @@ void AddKalimdorScripts()
AddSC_boss_ouro();
AddSC_npc_anubisath_sentinel();
AddSC_instance_temple_of_ahnqiraj();
- AddSC_wailing_caverns(); //Wailing caverns
+ // Wailing caverns
+ AddSC_wailing_caverns();
AddSC_instance_wailing_caverns();
- AddSC_boss_zum_rah(); //Zul'Farrak
+ // Zul'Farrak
+ AddSC_boss_zum_rah();
AddSC_zulfarrak();
AddSC_instance_zulfarrak();