diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql index dae6a24446..cecff45b36 100644 --- a/sql/base/world_database.sql +++ b/sql/base/world_database.sql @@ -26766,6 +26766,15 @@ INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES ( 69008, 'spell_bronjahm_soulstorm_channel'), ( 68870, 'spell_bronjahm_soulstorm_visual'), -- Pit of Saron +( 68786, 'spell_garfrost_permafrost'), +( 70336, 'spell_garfrost_permafrost'), +( 69012, 'spell_krick_explosive_barrage'), +( 69263, 'spell_ick_explosive_barrage'), +( 44851, 'spell_exploding_orb_hasty_grow'), +( 68987, 'spell_krick_pursuit'), +( 69029, 'spell_krick_pursuit_confusion'), +( 70850, 'spell_krick_pursuit_confusion'), +( 69275, 'spell_tyrannus_mark_of_rimefang'), ( 69172, 'spell_tyrannus_overlord_brand'), -- Icecrown Citadel ( 69057, 'spell_marrowgar_bone_spike_graveyard'), @@ -27949,6 +27958,9 @@ AVG_ROW_LENGTH=0; LOCK TABLES `vehicle_accessory` WRITE; /*!40000 ALTER TABLE `vehicle_accessory` DISABLE KEYS */; INSERT INTO `vehicle_accessory` VALUES +(36476,36477,0,0, 'Krick and Ick'), +(36661,36658,0,0, 'Scourgelord Tyrannus and Rimefang'), +(36891,31260,0,0, 'Ymirjar Skycaller on Drake'), (36678,38309,0,1, 'Professor Putricide - trigger'), (36678,38308,1,1, 'Professor Putricide - trigger'); /*!40000 ALTER TABLE `vehicle_accessory` ENABLE KEYS */; diff --git a/sql/scripts/world_script_texts.sql b/sql/scripts/world_script_texts.sql index 1766dba76e..13f04a9d14 100644 --- a/sql/scripts/world_script_texts.sql +++ b/sql/scripts/world_script_texts.sql @@ -2898,23 +2898,23 @@ INSERT INTO `script_texts` (`npc_entry`,`entry`,`content_default`,`content_loc1` (36658,-1658050,'Your pursuit shall be in vain, adventurers, for the Lich King has placed an army of undead at my command! Behold!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16755,1,0,0,'Tyrannus SAY_AMBUSH_1'), (36658,-1658051,'Persistent whelps! You will not reach the entrance of my lord''s lair! Soldiers, destroy them!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16756,1,0,0,'Tyrannus SAY_AMBUSH_2'), (36658,-1658052,'Rimefang! Trap them within the tunnel! Bury them alive!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16757,1,0,0,'Tyrannus SAY_GAUNTLET_START'), - (36658,-1658053,'Alas, brave, brave adventurers, your meddling has reached its end. Do you hear the clatter of bone and steel coming up the tunnel behind you? That is the sound of your impending demise.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16758,1,0,0,'Tyrannus SAY_INTRO_1'), - (36658,-1658054,'Ha, such an amusing gesture from the rabble. When I have finished with you, my master''s blade will feast upon your souls. Die!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16759,1,0,0,'Tyrannus SAY_INTRO_2'), - (36658,-1658055,'I shall not fail The Lich King! Come and meet your end!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16760,1,0,0,'Tyrannus SAY_AGGRO'), - (36658,-1658056,'Such a shameful display... You are better off dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16761,1,0,0,'Tyrannus SAY_SLAY_1'), - (36658,-1658057,'Perhaps you should have stayed in the mountains!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16762,1,0,0,'Tyrannus SAY_SLAY_2'), - (36658,-1658058,'Impossible! Rimefang... Warn...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16763,1,0,0,'Tyrannus SAY_DEATH'), - (36658,-1658059,'Rimefang, destroy this fool!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16764,1,0,0,'Tyrannus SAY_MARK_RIMEFANG_1'), - (36658,-1658060,'The frostwyrm Rimefang gazes at $N and readies an icy attack!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,3,0,0,'Tyrannus SAY_MARK_RIMEFANG_2'), - (36658,-1658061,'Power... overwhelming!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16765,1,0,0,'Tyrannus SAY_DARK_MIGHT_1'), - (36658,-1658062,'Scourgelord Tyrannus roars and swells with dark might!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,3,0,0,'Tyrannus SAY_DARK_MIGHT_2'), - (37592,-1658063,'Brave champions, we owe you our lives, our freedom... Though it be a tiny gesture in the face of this enormous debt, I pledge that from this day forth, all will know of your deeds, and the blazing path of light you cut through the shadow of this dark citadel.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,0,0,'Gorkun SAY_GORKUN_OUTRO_1'), - (37592,-1658064,'This day will stand as a testament not only to your valor, but to the fact that no foe, not even the Lich King himself, can stand when Alliance and Horde set aside their differences and ---',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,0,0,'Gorkun SAY_GORKUN_OUTRO_2'), - (36993,-1658065,'Heroes, to me!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16614,1,0,0,'Jaina SAY_JAYNA_OUTRO_3'), - (36990,-1658066,'Take cover behind me! Quickly!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17037,1,0,0,'Sylvanas SAY_SYLVANAS_OUTRO_3'), - (36993,-1658067,'The Frost Queen is gone. We must keep moving - our objective is near.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16615,0,0,0,'Jaina SAY_JAYNA_OUTRO_4'), - (36990,-1658068,'I thought he''d never shut up. At last, Sindragosa silenced that long-winded fool. To the Halls of Reflection, champions! Our objective is near... I can sense it.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17036,0,0,0,'Sylvanas SAY_SYLVANAS_OUTRO_4'), - (36993,-1658069,'I... I could not save them... Damn you, Arthas! DAMN YOU!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16616,0,0,0,'Jaina SAY_JAYNA_OUTRO_5'), + (36658,-1658053,'Alas, brave, brave adventurers, your meddling has reached its end. Do you hear the clatter of bone and steel coming up the tunnel behind you? That is the sound of your impending demise.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16758,1,0,0,'Tyrannus SAY_TYRANNUS_INTRO_1'), + (36658,-1658055,'Ha, such an amusing gesture from the rabble. When I have finished with you, my master''s blade will feast upon your souls. Die!', NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16759,1,0,0,'Tyrannus SAY_TYRANNUS_INTRO_3'), + (36658,-1658056,'I shall not fail The Lich King! Come and meet your end!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16760,1, 0,0,'Tyrannus SAY_AGGRO'), + (36658,-1658057,'Such a shameful display... You are better off dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16761,1,0,0,'Tyrannus SAY_SLAY_1'), + (36658,-1658058,'Perhaps you should have stayed in the mountains!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16762,1,0,0,'Tyrannus SAY_SLAY_2'), + (36658,-1658059,'Impossible! Rimefang... Warn...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16763,1,0,0,'Tyrannus SAY_DEATH'), + (36658,-1658060,'Rimefang, destroy this fool!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16764,1,0,0,'Tyrannus SAY_MARK_RIMEFANG_1'), + (36658,-1658061,'The frostwyrm Rimefang gazes at $N and readies an icy attack!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,3, 0,0,'Tyrannus SAY_MARK_RIMEFANG_2'), + (36658,-1658062,'Power... overwhelming!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16765,1,0,0,'Tyrannus SAY_DARK_MIGHT_1'), + (36658,-1658063,'Scourgelord Tyrannus roars and swells with dark might!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,3, 0,0,'Tyrannus SAY_DARK_MIGHT_2'), + (37592,-1658064,'Brave champions, we owe you our lives, our freedom... Though it be a tiny gesture in the face of this enormous debt, I pledge that from this day forth, all will know of your deeds, and the blazing path of light you cut through the shadow of this dark citadel.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1, 0,0,'Gorkun SAY_GORKUN_OUTRO_1'), + (37592,-1658065,'This day will stand as a testament not only to your valor, but to the fact that no foe, not even the Lich King himself, can stand when Alliance and Horde set aside their differences and ---',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1, 0,0,'Gorkun SAY_GORKUN_OUTRO_2'), + (36993,-1658066,'Heroes, to me!', NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16614,1,0,0,'Jaina SAY_JAYNA_OUTRO_3'), + (36990,-1658067,'Take cover behind me! Quickly!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17037,1,0,0,'Sylvanas SAY_SYLVANAS_OUTRO_3'), + (36993,-1658068,'The Frost Queen is gone. We must keep moving - our objective is near.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16615, 0,0,0,'Jaina SAY_JAYNA_OUTRO_4'), + (36990,-1658069,'I thought he''d never shut up. At last, Sindragosa silenced that long-winded fool. To the Halls of Reflection, champions! Our objective is near... I can sense it.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17036, 0,0,0,'Sylvanas SAY_SYLVANAS_OUTRO_4'), + (36993,-1658070,'I... I could not save them... Damn you, Arthas! DAMN YOU!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16616, 0,0,0,'Jaina SAY_JAYNA_OUTRO_5'); -- -1 658 000 ICECROWN CITADEL: FROZEN HALLS: HALLS OF REFLECTION -- INTRO diff --git a/sql/scripts/world_scripts_full.sql b/sql/scripts/world_scripts_full.sql index c6898e326d..6f8bdba2c2 100644 --- a/sql/scripts/world_scripts_full.sql +++ b/sql/scripts/world_scripts_full.sql @@ -9,7 +9,7 @@ UPDATE `gameobject_template` SET `ScriptName`=''; UPDATE `outdoorpvp_template` SET `ScriptName`=''; /* AREA TRIGGERS */ -DELETE FROM `areatrigger_scripts` WHERE `entry` IN (822,5284,5285,5286,5287,4871,4872,4873,5108,5332,5338,5334,5340,5369,5423); +DELETE FROM `areatrigger_scripts` WHERE `entry` IN (822,5284,5285,5286,5287,4871,4872,4873,5108,5332,5338,5334,5340,5369,5423,5633); DELETE FROM `areatrigger_scripts` WHERE `entry` BETWEEN 1726 AND 1740; INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES (822, 'at_map_chamber'), @@ -41,8 +41,8 @@ INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES (1739, 'at_scent_larkorwi'), (1740, 'at_scent_larkorwi'), (5369, 'at_RX_214_repair_o_matic_station'), -(5423, 'at_RX_214_repair_o_matic_station'); - +(5423, 'at_RX_214_repair_o_matic_station'), +(5633, 'at_tyrannus_event_starter'); /* WORLD BOSS */ UPDATE `creature_template` SET `ScriptName`='boss_ysondre' WHERE `entry`=14887; @@ -1071,22 +1071,9 @@ UPDATE `creature_template` SET `Scriptname`='boss_ick' WHERE `entry`=36476; UPDATE `creature_template` SET `Scriptname`='boss_krick' WHERE `entry`=36477; UPDATE `creature_template` SET `Scriptname`='boss_tyrannus' WHERE `entry`=36658; UPDATE `creature_template` SET `Scriptname`='boss_rimefang' WHERE `entry`=36661; -UPDATE `creature_template` SET `Scriptname`='mob_ymirjar_wrathbringer' WHERE `entry`=36840; -UPDATE `creature_template` SET `Scriptname`='mob_ymirjar_skycaller' WHERE `entry`=31260; UPDATE `creature_template` SET `Scriptname`='mob_ymirjar_flamebearer' WHERE `entry`=36893; -UPDATE `creature_template` SET `Scriptname`='mob_ymirjar_deathbringer' WHERE `entry`=36892; UPDATE `creature_template` SET `Scriptname`='mob_wrathbone_laborer' WHERE `entry`=36830; -UPDATE `creature_template` SET `Scriptname`='mob_wrathbone_coldwraith' WHERE `entry`=36842; -UPDATE `creature_template` SET `Scriptname`='mob_wrathbone_sorcerer' WHERE `entry`=37728; -UPDATE `creature_template` SET `Scriptname`='mob_stonespine_gargoyle' WHERE `entry`=36896; -UPDATE `creature_template` SET `Scriptname`='mob_plagueborn_horror' WHERE `entry`=36879; UPDATE `creature_template` SET `Scriptname`='mob_iceborn_protodrake' WHERE `entry`=36891; -UPDATE `creature_template` SET `Scriptname`='mob_hungering_ghoul' WHERE `entry`=37711; -UPDATE `creature_template` SET `Scriptname`='mob_fallen_warrior' WHERE `entry`=38487; -UPDATE `creature_template` SET `Scriptname`='mob_fallen_warrior' WHERE `entry`=36841; -UPDATE `creature_template` SET `Scriptname`='mob_deathwhisper_torturer' WHERE `entry`=37713; -UPDATE `creature_template` SET `Scriptname`='mob_deathwhisper_shadowcaster' WHERE `entry`=37712; -UPDATE `creature_template` SET `Scriptname`='mob_deathwhisper_necrolyte' WHERE `entry`=36788; UPDATE `creature_template` SET `Scriptname`='mob_geist_ambusher' WHERE `entry`=36886; /* RAGEFIRE CHASM */ @@ -1756,7 +1743,7 @@ UPDATE `outdoorpvp_template` SET `ScriptName`='outdoorpvp_si' WHERE `TypeId`=5; UPDATE `outdoorpvp_template` SET `ScriptName`='outdoorpvp_ep' WHERE `TypeId`=6; /* ACHIEVEMENTS */ -DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (3693,6641,6642,6643,6644,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,1234,1239,5605,5606,12778,13036,13035,13037,12977,12967,12986,12982,12780,13012,13011,13013) AND `type` IN (0,11); +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (3693,6641,6642,6643,6644,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,1234,1239,5605,5606,12778,13036,13035,13037,12977,12967,12986,12982,12993,12780,13012,13011,13013) AND `type` IN (0,11); INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`,`ScriptName`) VALUES (3693,11,0,0, 'achievement_storm_glory'), (6641,11,0,0, 'achievement_school_of_hard_knocks'), @@ -1777,6 +1764,7 @@ INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`, (1239,11,0,0, 'achievement_bg_control_all_nodes'), (5605,11,0,0, 'achievement_save_the_day'), (5606,11,0,0, 'achievement_save_the_day'), +(12993,11,0,0, 'achievement_doesnt_go_to_eleven'), (12778,11,0,0, 'achievement_ive_gone_and_made_a_mess'), (13036,11,0,0, 'achievement_ive_gone_and_made_a_mess'), (13035,11,0,0, 'achievement_ive_gone_and_made_a_mess'), diff --git a/sql/updates/10918_world_achievement_criteria_data.sql b/sql/updates/10918_world_achievement_criteria_data.sql new file mode 100644 index 0000000000..a737c83656 --- /dev/null +++ b/sql/updates/10918_world_achievement_criteria_data.sql @@ -0,0 +1,3 @@ +DELETE FROM `achievement_criteria_data` WHERE `criteria_id`=12993 AND `type`=11; +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`,`ScriptName`) VALUES +(12993,11,0,0, 'achievement_doesnt_go_to_eleven'); diff --git a/sql/updates/10918_world_areatrigger_scripts.sql b/sql/updates/10918_world_areatrigger_scripts.sql new file mode 100644 index 0000000000..813db38f4b --- /dev/null +++ b/sql/updates/10918_world_areatrigger_scripts.sql @@ -0,0 +1,3 @@ +DELETE FROM `areatrigger_scripts` where `entry`=5633; +INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES +(5633,'at_tyrannus_event_starter'); diff --git a/sql/updates/10918_world_script_texts.sql b/sql/updates/10918_world_script_texts.sql new file mode 100644 index 0000000000..3eb686443e --- /dev/null +++ b/sql/updates/10918_world_script_texts.sql @@ -0,0 +1,23 @@ +DELETE FROM `script_texts` WHERE `entry` BETWEEN -1658070 AND -1658050; +INSERT INTO `script_texts` (`npc_entry`,`entry`,`content_default`,`content_loc1`,`content_loc2`,`content_loc3`,`content_loc4`,`content_loc5`,`content_loc6`,`content_loc7`,`content_loc8`,`sound`,`type`,`language`,`emote`,`comment`) VALUES +(36658,-1658050,'Your pursuit shall be in vain, adventurers, for the Lich King has placed an army of undead at my command! Behold!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16755,1,0,0,'Tyrannus SAY_AMBUSH_1'), +(36658,-1658051,'Persistent whelps! You will not reach the entrance of my lord\'s lair! Soldiers, destroy them!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16756,1,0,0,'Tyrannus SAY_AMBUSH_2'), +(36658,-1658052,'Rimefang! Trap them within the tunnel! Bury them alive!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16757,1,0,0,'Tyrannus SAY_GAUNTLET_START'), +(36658,-1658053,'Alas, brave, brave adventurers, your meddling has reached its end. Do you hear the clatter of bone and steel coming up the tunnel behind you? That is the sound of your impending demise.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16758,1,0,0,'Tyrannus SAY_TYRANNUS_INTRO_1'), +(37592,-1658054,'Heroes! We will hold off the undead as long as we can, even to our dying breath. Deal with the Scourgelord!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17150,1, 0,0,'Gorkun SAY_GORKUN_INTRO_2'), +(36658,-1658055,'Ha, such an amusing gesture from the rabble. When I have finished with you, my master\'s blade will feast upon your souls. Die!', NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16759,1,0,0,'Tyrannus SAY_TYRANNUS_INTRO_3'), +(36658,-1658056,'I shall not fail The Lich King! Come and meet your end!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16760,1, 0,0,'Tyrannus SAY_AGGRO'), +(36658,-1658057,'Such a shameful display... You are better off dead!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16761,1,0,0,'Tyrannus SAY_SLAY_1'), +(36658,-1658058,'Perhaps you should have stayed in the mountains!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16762,1,0,0,'Tyrannus SAY_SLAY_2'), +(36658,-1658059,'Impossible! Rimefang... Warn...',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16763,1,0,0,'Tyrannus SAY_DEATH'), +(36658,-1658060,'Rimefang, destroy this fool!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16764,1,0,0,'Tyrannus SAY_MARK_RIMEFANG_1'), +(36658,-1658061,'The frostwyrm Rimefang gazes at $N and readies an icy attack!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,3, 0,0,'Tyrannus SAY_MARK_RIMEFANG_2'), +(36658,-1658062,'Power... overwhelming!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16765,1,0,0,'Tyrannus SAY_DARK_MIGHT_1'), +(36658,-1658063,'Scourgelord Tyrannus roars and swells with dark might!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,3, 0,0,'Tyrannus SAY_DARK_MIGHT_2'), +(37592,-1658064,'Brave champions, we owe you our lives, our freedom... Though it be a tiny gesture in the face of this enormous debt, I pledge that from this day forth, all will know of your deeds, and the blazing path of light you cut through the shadow of this dark citadel.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1, 0,0,'Gorkun SAY_GORKUN_OUTRO_1'), +(37592,-1658065,'This day will stand as a testament not only to your valor, but to the fact that no foe, not even the Lich King himself, can stand when Alliance and Horde set aside their differences and ---',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1, 0,0,'Gorkun SAY_GORKUN_OUTRO_2'), +(36993,-1658066,'Heroes, to me!', NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16614,1,0,0,'Jaina SAY_JAYNA_OUTRO_3'), +(36990,-1658067,'Take cover behind me! Quickly!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17037,1,0,0,'Sylvanas SAY_SYLVANAS_OUTRO_3'), +(36993,-1658068,'The Frost Queen is gone. We must keep moving - our objective is near.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16615, 0,0,0,'Jaina SAY_JAYNA_OUTRO_4'), +(36990,-1658069,'I thought he\'d never shut up. At last, Sindragosa silenced that long-winded fool. To the Halls of Reflection, champions! Our objective is near... I can sense it.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,17036, 0,0,0,'Sylvanas SAY_SYLVANAS_OUTRO_4'), +(36993,-1658070,'I... I could not save them... Damn you, Arthas! DAMN YOU!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16616, 0,0,0,'Jaina SAY_JAYNA_OUTRO_5'); diff --git a/sql/updates/10918_world_scriptname.sql b/sql/updates/10918_world_scriptname.sql new file mode 100644 index 0000000000..cca304b3a2 --- /dev/null +++ b/sql/updates/10918_world_scriptname.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `Scriptname`='' WHERE `entry` IN (36840,31260,36892,36842,37728,36896,37713,37712,36788,36879,37711,38487,36841); diff --git a/sql/updates/10918_world_spell_script_names.sql b/sql/updates/10918_world_spell_script_names.sql new file mode 100644 index 0000000000..d086d80dae --- /dev/null +++ b/sql/updates/10918_world_spell_script_names.sql @@ -0,0 +1,17 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN (68786,70336) AND `ScriptName`='spell_garfrost_permafrost'; +DELETE FROM `spell_script_names` WHERE `spell_id`=69012 AND `ScriptName`='spell_krick_explosive_barrage'; +DELETE FROM `spell_script_names` WHERE `spell_id`=69263 AND `ScriptName`='spell_ick_explosive_barrage'; +DELETE FROM `spell_script_names` WHERE `spell_id`=44851 AND `ScriptName`='spell_exploding_orb_hasty_grow'; +DELETE FROM `spell_script_names` WHERE `spell_id`=68987 AND `ScriptName`='spell_krick_pursuit'; +DELETE FROM `spell_script_names` WHERE `spell_id` IN (69029,70850) AND `ScriptName`='spell_krick_pursuit_confusion'; +DELETE FROM `spell_script_names` WHERE `spell_id`=69275 AND `ScriptName`='spell_tyrannus_mark_of_rimefang'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(68786,'spell_garfrost_permafrost'), +(70336,'spell_garfrost_permafrost'), +(69012,'spell_krick_explosive_barrage'), +(69263,'spell_ick_explosive_barrage'), +(44851,'spell_exploding_orb_hasty_grow'), +(68987,'spell_krick_pursuit'), +(69029,'spell_krick_pursuit_confusion'), +(70850,'spell_krick_pursuit_confusion'), +(69275,'spell_tyrannus_mark_of_rimefang'); diff --git a/sql/updates/10918_world_vehicle_accessory.sql b/sql/updates/10918_world_vehicle_accessory.sql new file mode 100644 index 0000000000..c5ae9d376c --- /dev/null +++ b/sql/updates/10918_world_vehicle_accessory.sql @@ -0,0 +1,5 @@ +DELETE FROM `vehicle_accessory` WHERE `entry` IN (36476,36661,36891); +INSERT INTO `vehicle_accessory` (`entry`,`accessory_entry`,`seat_id`,`minion`,`description`) VALUES +(36476,36477,0,0,'Krick and Ick'), +(36661,36658,0,0,'Scourgelord Tyrannus and Rimefang'), +(36891,31260,0,0,'Ymirjar Skycaller on Drake'); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp index 41c3dfe18e..fd31748ae8 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -20,195 +20,314 @@ enum Yells { - SAY_AGGRO = -1658001, - SAY_SLAY_1 = -1658002, - SAY_SLAY_2 = -1658003, - SAY_DEATH = -1658004, - SAY_PHASE2 = -1658005, - SAY_PHASE3 = -1658006, + SAY_AGGRO = -1658001, + SAY_SLAY_1 = -1658002, + SAY_SLAY_2 = -1658003, + SAY_DEATH = -1658004, + SAY_PHASE2 = -1658005, + SAY_PHASE3 = -1658006, - SAY_TYRANNUS_DEATH = -1659007, -}; - -enum eEvents -{ - EVENT_NONE, - EVENT_PERMAFROST, - EVENT_THROW_SARONITE, - EVENT_CHILLINGWAVE, - EVENT_DEEPFREEZE, + SAY_TYRANNUS_DEATH = -1659007, }; enum Spells { - SPELL_PERMAFROST = 70326, - SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura - SPELL_THROW_SARONITE = 68788, - SPELL_THUNDERING_STOMP = 68771, - SPELL_CHILLING_WAVE = 68778, - H_SPELL_CHILLING_WAVE = 70333, - SPELL_DEEP_FREEZE = 70381, - H_SPELL_DEEP_FREEZE = 72930, - SPELL_FORGE_MACE = 68785, - H_SPELL_FORGE_MACE = 70335, - SPELL_FORGE_BLADE = 68774, - H_SPELL_FORGE_BLADE = 70334, + SPELL_PERMAFROST = 70326, + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + SPELL_DEEP_FREEZE = 70381, + SPELL_FORGE_MACE = 68785, + SPELL_FORGE_BLADE = 68774, }; -enum eEnums +#define SPELL_PERMAFROST_HELPER RAID_MODE(68786, 70336) + +enum eEvents { - EQUIP_ID_SWORD = 49345, - EQUIP_ID_MACE = 49344, - ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, + EVENT_THROW_SARONITE = 1, + EVENT_CHILLING_WAVE = 2, + EVENT_DEEP_FREEZE = 3, + EVENT_JUMP = 4, + EVENT_FORGING = 5, + EVENT_RESUME_ATTACK = 6, }; +enum ePhases +{ + PHASE_ONE = 1, + PHASE_TWO = 2, + PHASE_THREE = 3, + + PHASE_ONE_MASK = 1 << PHASE_ONE, + PHASE_TWO_MASK = 1 << PHASE_TWO, + PHASE_THREE_MASK = 1 << PHASE_THREE, +}; + +enum eMiscData +{ + EQUIP_ID_SWORD = 49345, + EQUIP_ID_MACE = 49344, + ACHIEV_DOESNT_GO_TO_ELEVEN = 0, + POINT_FORGE = 0, +}; + +static const Position northForgePos = {722.5643f, -234.1615f, 527.182f, 2.16421f}; +static const Position southForgePos = {639.257f, -210.1198f, 529.015f, 0.523599f}; + class boss_garfrost : public CreatureScript { -public: - boss_garfrost() : CreatureScript("boss_garfrost") { } + public: + boss_garfrost() : CreatureScript("boss_garfrost") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_garfrostAI (pCreature); - } - - struct boss_garfrostAI : public ScriptedAI - { - boss_garfrostAI(Creature *c) : ScriptedAI(c) + struct boss_garfrostAI : public BossAI { - pInstance = c->GetInstanceScript(); - } - - bool phase2; - bool phase3; - bool bAchievement; - - InstanceScript* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - phase2 = false; - phase3 = false; - bAchievement = true; - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_PERMAFROST); - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) - { - if (HealthBelowPct(66) && !phase2) + boss_garfrostAI(Creature *creature) : BossAI(creature, DATA_GARFROST) { - phase2 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_BLADE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); } - if (HealthBelowPct(33) && !phase3) + void InitializeAI() { - phase3 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_MACE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. - events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); + if (!instance || static_cast(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); } - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) + void Reset() { - if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) - DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); + events.Reset(); + events.SetPhase(PHASE_ONE); + SetEquipmentSlots(true); + _permafrostStack = 0; - pInstance->SetData(DATA_GARFROST_EVENT, DONE); - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); + instance->SetBossState(DATA_GARFROST, NOT_STARTED); } - } - void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) + void EnterCombat(Unit* /*who*/) { - if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) - if (pAura->GetStackAmount() > 10) - bAchievement = false; + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_PERMAFROST); + events.ScheduleEvent(EVENT_THROW_SARONITE, 7000); + + instance->SetBossState(DATA_GARFROST, IN_PROGRESS); } - } - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void KilledUnit(Unit* victim) { - switch(eventId) + if (victim->GetTypeId() == TYPEID_PLAYER) + DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (Creature* tyrannus = me->GetCreature(*me, instance->GetData64(DATA_TYRANNUS))) + DoScriptText(SAY_TYRANNUS_DEATH, tyrannus); + + instance->SetBossState(DATA_GARFROST, DONE); + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*uiDamage*/) + { + if (events.GetPhaseMask() & PHASE_ONE_MASK && !HealthAbovePct(66)) { - case EVENT_THROW_SARONITE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_THROW_SARONITE); - events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); - return; - case EVENT_DEEPFREEZE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DEEP_FREEZE); - events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); - return; - case EVENT_CHILLINGWAVE: - DoCastAOE(SPELL_CHILLING_WAVE); - events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); - return; + events.SetPhase(PHASE_TWO); + events.DelayEvents(8000); + DoCast(me, SPELL_THUNDERING_STOMP); + events.ScheduleEvent(EVENT_JUMP, 1500); + return; + } + + if (events.GetPhaseMask() & PHASE_TWO_MASK && !HealthAbovePct(33)) + { + events.SetPhase(PHASE_THREE); + events.DelayEvents(8000); + DoCast(me, SPELL_THUNDERING_STOMP); + events.ScheduleEvent(EVENT_JUMP, 1500); + return; } } - DoMeleeAttackIfReady(); - } - }; + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id != POINT_FORGE) + return; + if (events.GetPhaseMask() & PHASE_TWO_MASK) + DoCast(me, SPELL_FORGE_BLADE); + if (events.GetPhaseMask() & PHASE_THREE_MASK) + DoCast(me, SPELL_FORGE_MACE); + events.ScheduleEvent(EVENT_RESUME_ATTACK, 5000); + } + + void SpellHitTarget(Unit* target, const SpellEntry* spell) + { + if (spell->Id == SPELL_PERMAFROST_HELPER) + { + if (Aura *aura = target->GetAura(SPELL_PERMAFROST_HELPER)) + _permafrostStack = std::max(_permafrostStack, aura->GetStackAmount()); + } + else if (spell->Id == SPELL_FORGE_BLADE) + SetEquipmentSlots(false, EQUIP_ID_SWORD); + else if (spell->Id == SPELL_FORGE_MACE) + SetEquipmentSlots(false, EQUIP_ID_MACE); + } + + uint32 GetData(uint32 type) + { + return _permafrostStack; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_THROW_SARONITE: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_THROW_SARONITE); + events.ScheduleEvent(EVENT_THROW_SARONITE, urand(12500, 20000)); + break; + case EVENT_CHILLING_WAVE: + DoCast(me, SPELL_CHILLING_WAVE); + events.ScheduleEvent(EVENT_CHILLING_WAVE, 40000, 0, PHASE_TWO); + break; + case EVENT_DEEP_FREEZE: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_DEEP_FREEZE); + events.ScheduleEvent(EVENT_DEEP_FREEZE, 35000, 0, PHASE_THREE); + break; + case EVENT_JUMP: + me->AttackStop(); + if (events.GetPhaseMask() & PHASE_TWO_MASK) + me->GetMotionMaster()->MoveJump(northForgePos.GetPositionX(), northForgePos.GetPositionY(), northForgePos.GetPositionZ(), 25.0f, 15.0f); + else if (events.GetPhaseMask() & PHASE_THREE_MASK) + me->GetMotionMaster()->MoveJump(southForgePos.GetPositionX(), southForgePos.GetPositionY(), southForgePos.GetPositionZ(), 25.0f, 15.0f); + break; + case EVENT_RESUME_ATTACK: + if (events.GetPhaseMask() & PHASE_TWO_MASK) + events.ScheduleEvent(EVENT_CHILLING_WAVE, 5000, 0, PHASE_TWO); + else if (events.GetPhaseMask() & PHASE_THREE_MASK) + events.ScheduleEvent(EVENT_DEEP_FREEZE, 10000, 0, PHASE_THREE); + AttackStart(me->getVictim()); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + uint32 _permafrostStack; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_garfrostAI(creature); + } }; +class spell_garfrost_permafrost : public SpellScriptLoader +{ + public: + spell_garfrost_permafrost() : SpellScriptLoader("spell_garfrost_permafrost") { } + + class spell_garfrost_permafrost_SpellScript : public SpellScript + { + PrepareSpellScript(spell_garfrost_permafrost_SpellScript); + + bool Load() + { + prevented = false; + return true; + } + + void PreventHitByLoS() + { + if (Unit* target = GetHitUnit()) + { + Unit* caster = GetCaster(); + //Temporary Line of Sight Check + std::list blockList; + caster->GetGameObjectListWithEntryInGrid(blockList, GO_SARONITE_ROCK, 100.0f); + if (!blockList.empty()) + { + for (std::list::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr) + { + if ((*itr)->isVisibleForInState(target)) + { + if ((*itr)->IsInBetween(caster, target, 4.0f)) + { + prevented = true; + target->ApplySpellImmune(GetSpellInfo()->Id, IMMUNITY_ID, GetSpellInfo()->Id, true); + PreventHitDefaultEffect(EFFECT_0); + PreventHitDefaultEffect(EFFECT_1); + PreventHitDefaultEffect(EFFECT_2); + PreventHitDamage(); + break; + } + } + } + } + } + } + + void RestoreImmunity() + { + if (Unit* target = GetHitUnit()) + { + target->ApplySpellImmune(GetSpellInfo()->Id, IMMUNITY_ID, GetSpellInfo()->Id, false); + if (prevented) + PreventHitAura(); + } + } + + void Register() + { + BeforeHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::PreventHitByLoS); + AfterHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::RestoreImmunity); + } + + bool prevented; + }; + + SpellScript* GetSpellScript() const + { + return new spell_garfrost_permafrost_SpellScript(); + } +}; + +class achievement_doesnt_go_to_eleven : public AchievementCriteriaScript +{ + public: + achievement_doesnt_go_to_eleven() : AchievementCriteriaScript("achievement_doesnt_go_to_eleven") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + if (target) + if (Creature* garfrost = target->ToCreature()) + if (garfrost->AI()->GetData(ACHIEV_DOESNT_GO_TO_ELEVEN) <= 10) + return true; + + return false; + } +}; void AddSC_boss_garfrost() { new boss_garfrost(); + new spell_garfrost_permafrost(); + new achievement_doesnt_go_to_eleven(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index 4b64e27e80..24831c97e9 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -17,22 +17,28 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" - -/* - * SDComment: Spell Explosive barrage is not working. - */ +#include "Vehicle.h" enum Spells { - SPELL_PURSUED = 68987, - SPELL_CONFUSION = 69029, - SPELL_EXPLOSIVE_BARRAGE = 69263, - SPELL_MIGHTY_KICK = 69021, - SPELL_POISON_NOVA = 68989, - H_SPELL_POISON_NOVA = 70434, - SPELL_SHADOW_BOLT = 69028, - SPELL_TOXIC_WASTE = 69024, - H_SPELL_TOXIC_WASTE = 70436, + SPELL_MIGHTY_KICK = 69021, //ick's spell + SPELL_SHADOW_BOLT = 69028, //krick's spell + SPELL_TOXIC_WASTE = 69024, //krick's spell + SPELL_EXPLOSIVE_BARRAGE_KRICK = 69012, //special spell 1 + SPELL_EXPLOSIVE_BARRAGE_ICK = 69263, //special spell 1 + SPELL_POISON_NOVA = 68989, //special spell 2 + SPELL_PURSUIT = 68987, //special spell 3 + + SPELL_EXPLOSIVE_BARRAGE_SUMMON = 69015, + SPELL_EXPLODING_ORB = 69017, //visual on exploding orb + SPELL_AUTO_GROW = 69020, //grow effect on exploding orb + SPELL_HASTY_GROW = 44851, //need to check growing stacks + SPELL_EXPLOSIVE_BARRAGE_DAMAGE = 69019, //damage done by orb while exploding + + SPELL_STRANGULATING = 69413, //krick's selfcast in intro + SPELL_SUICIDE = 7, + SPELL_KRICK_KILL_CREDIT = 71308, + SPELL_NECROMANTIC_POWER = 69753, }; enum Yells @@ -69,423 +75,647 @@ enum Yells enum Events { - EVENT_NONE, - EVENT_PURSUE, - EVENT_MIGHTY_KICK, - EVENT_POISON_NOVA, - EVENT_EXPLOSIVE_BARRAGE, - EVENT_END_EXPLOSIVE_BARRAGE, - - // Krick - EVENT_SHADOW_BOLT, - EVENT_TOXIC_WASTE, + EVENT_MIGHTY_KICK = 1, + EVENT_SHADOW_BOLT = 2, + EVENT_TOXIC_WASTE = 3, + EVENT_SPECIAL = 4, //special spell selection (one of event 5, 6 or 7) + EVENT_PURSUIT = 5, + EVENT_POISON_NOVA = 6, + EVENT_EXPLOSIVE_BARRAGE = 7, // Krick OUTRO - EVENT_OUTRO_1, - EVENT_OUTRO_2, - EVENT_OUTRO_3, - EVENT_OUTRO_4, - EVENT_OUTRO_5, - EVENT_OUTRO_6, - EVENT_OUTRO_7, - EVENT_OUTRO_8, - EVENT_OUTRO_9, - EVENT_OUTRO_10, - EVENT_OUTRO_11, - EVENT_OUTRO_12, - EVENT_OUTRO_END, + EVENT_OUTRO_1 = 8, + EVENT_OUTRO_2 = 9, + EVENT_OUTRO_3 = 10, + EVENT_OUTRO_4 = 11, + EVENT_OUTRO_5 = 12, + EVENT_OUTRO_6 = 13, + EVENT_OUTRO_7 = 14, + EVENT_OUTRO_8 = 15, + EVENT_OUTRO_9 = 16, + EVENT_OUTRO_10 = 17, + EVENT_OUTRO_11 = 18, + EVENT_OUTRO_12 = 19, + EVENT_OUTRO_13 = 20, + EVENT_OUTRO_END = 21, }; enum KrickPhase { - PHASE_COMBAT, - PHASE_OUTRO, + PHASE_COMBAT = 1, + PHASE_OUTRO = 2, }; enum Actions { - ACTION_OUTRO, + ACTION_OUTRO = 1, }; -enum Misc +enum Points { - SEAT_KRICK = 0, - - // events GCD. Shall not be 0. - GCD_1 = 1, + POINT_KRICK_INTRO = 364770, + POINT_KRICK_DEATH = 364771, }; -// Krick is the Gnome. -// Ick is the Mount -// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. +static const Position outroPos[7] = +{ + {828.9342f, 118.6247f, 509.5190f, 0.0000000f}, // Krick's Outro Position + {841.0100f, 196.2450f, 573.9640f, 0.2046099f}, // Scourgelord Tyrannus Outro Position (Tele to...) + {777.2274f, 119.5521f, 510.0363f, 6.0562930f}, // Sylvanas / Jaine Outro Spawn Position (NPC_SYLVANAS_PART1) + {823.3984f, 114.4907f, 509.4899f, 0.0000000f}, // Sylvanas / Jaine Outro Move Position (1) + {835.5887f, 139.4345f, 530.9526f, 0.0000000f}, // Tyrannus Fly down Position (only not blizz one :/) + {828.9342f, 118.6247f, 514.5190f, 0.0000000f}, // Krick's Choke Position + {828.9342f, 118.6247f, 509.4958f, 0.0000000f}, // Kirck's Death Position +}; class boss_ick : public CreatureScript { -public: - boss_ick() : CreatureScript("boss_ick") { } + public: + boss_ick() : CreatureScript("boss_ick") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_ickAI(pCreature); - } - - struct boss_ickAI : public ScriptedAI - { - boss_ickAI(Creature *c) : ScriptedAI(c) + struct boss_ickAI : public BossAI { - pInstance = c->GetInstanceScript(); - } - - InstanceScript* pInstance; - - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); - } - - Creature* GetKrick() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); - - Creature* pKrick = GetKrick(); - if (!pKrick) - pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); - - if (pKrick) - DoScriptText(SAY_KRICK_AGGRO, pKrick); - - events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - } - - void EnterEvadeMode() - { - me->GetMotionMaster()->Clear(); - ScriptedAI::EnterEvadeMode(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (Creature* pKrick = GetKrick()) + boss_ickAI(Creature *creature) : BossAI(creature, DATA_ICK), _vehicle(creature->GetVehicleKit()) { - if (pKrick->AI()) - pKrick->AI()->DoAction(ACTION_OUTRO); + ASSERT(_vehicle); } - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + void InitializeAI() { - EnterEvadeMode(); - return; + if (!instance || static_cast(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); } - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - switch(events.ExecuteEvent()) + void Reset() { - case EVENT_PURSUE: - if (Creature* pKrick = GetKrick()) - DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); + events.Reset(); + instance->SetBossState(DATA_ICK, NOT_STARTED); + } - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Creature* GetKrick() + { + return ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_KRICK)); + } + + void EnterCombat(Unit * /*who*/) + { + _vehicle->InstallAllAccessories(me->GetEntry()); + + if (Creature* krick = GetKrick()) + DoScriptText(SAY_KRICK_AGGRO, krick); + + events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 10000); + events.ScheduleEvent(EVENT_SPECIAL, urand(30000, 35000)); + + instance->SetBossState(DATA_ICK, IN_PROGRESS); + } + + void EnterEvadeMode() + { + me->GetMotionMaster()->Clear(); + ScriptedAI::EnterEvadeMode(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (Creature* krick = GetKrick()) + { + _vehicle->RemoveAllPassengers(); + if (krick->AI()) + krick->AI()->DoAction(ACTION_OUTRO); + } + + instance->SetBossState(DATA_ICK, DONE); + } + + void SetTempThreat(float threat) + { + _tempThreat = threat; + } + + void _ResetThreat(Unit* target) + { + DoModifyThreatPercent(target, -100); + me->AddThreat(target, _tempThreat); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - me->Attack(pTarget,false); - DoScriptText(SAY_ICK_CHASE_1, me, pTarget); - DoCast(pTarget, SPELL_PURSUED); + case EVENT_TOXIC_WASTE: + if (Creature* krick = GetKrick()) + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + krick->CastSpell(target, SPELL_TOXIC_WASTE, false); + events.ScheduleEvent(EVENT_TOXIC_WASTE, urand(7000, 10000)); + break; + case EVENT_SHADOW_BOLT: + if (Creature* krick = GetKrick()) + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1)) + krick->CastSpell(target, SPELL_SHADOW_BOLT, false); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + return; + case EVENT_MIGHTY_KICK: + DoCastVictim(SPELL_MIGHTY_KICK); + events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000); + return; + case EVENT_SPECIAL: + //select one of these three special events + events.ScheduleEvent(RAND(EVENT_EXPLOSIVE_BARRAGE, EVENT_POISON_NOVA, EVENT_PURSUIT), 1000); + events.ScheduleEvent(EVENT_SPECIAL, urand(23000, 28000)); + break; + case EVENT_EXPLOSIVE_BARRAGE: + if (Creature* krick = GetKrick()) + { + DoScriptText(SAY_KRICK_BARRAGE_1, krick); + DoScriptText(SAY_KRICK_BARRAGE_2, krick); + krick->CastSpell(krick, SPELL_EXPLOSIVE_BARRAGE_KRICK, true); + DoCast(me, SPELL_EXPLOSIVE_BARRAGE_ICK); + } + events.DelayEvents(20000); + break; + case EVENT_POISON_NOVA: + if (Creature* krick = GetKrick()) + DoScriptText(SAY_KRICK_POISON_NOVA, krick); + + DoScriptText(SAY_ICK_POISON_NOVA, me); + DoCast(me, SPELL_POISON_NOVA); + break; + case EVENT_PURSUIT: + if (Creature* krick = GetKrick()) + DoScriptText(RAND(SAY_KRICK_CHASE_1, SAY_KRICK_CHASE_2, SAY_KRICK_CHASE_3), krick); + DoCast(me, SPELL_PURSUIT); + break; + default: + break; } + } - DoCast(SPELL_CONFUSION); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - return; - - case EVENT_MIGHTY_KICK: - DoCast(me->getVictim(), SPELL_MIGHTY_KICK); - events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); - return; - - case EVENT_POISON_NOVA: - if (Creature* pKrick = GetKrick()) - DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); - - DoScriptText(SAY_ICK_POISON_NOVA, me); - DoCastAOE(SPELL_POISON_NOVA); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - return; - - case EVENT_TOXIC_WASTE: - DoCast(me->getVictim(), SPELL_TOXIC_WASTE); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - return; - - case EVENT_SHADOW_BOLT: - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - return; - - case EVENT_EXPLOSIVE_BARRAGE: - if (Creature *pKrick = GetKrick()) - { - DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); - DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); - } - - DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); - me->GetMotionMaster()->MoveIdle(); - events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec - events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); - return; - - case EVENT_END_EXPLOSIVE_BARRAGE: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); - break; + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + private: + Vehicle* _vehicle; + float _tempThreat; + }; + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ickAI(creature); + } }; class boss_krick : public CreatureScript { -public: - boss_krick() : CreatureScript("boss_krick") { } + public: + boss_krick() : CreatureScript("boss_krick") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_krickAI(pCreature); - } - - struct boss_krickAI : public ScriptedAI - { - boss_krickAI(Creature *c) : ScriptedAI(c) + struct boss_krickAI : public ScriptedAI { - pInstance = c->GetInstanceScript(); - } - - InstanceScript* pInstance; - EventMap events; - - KrickPhase phase; - uint64 uiNpcOutroDialog; - uint64 uiTyrannus; - - void Reset() - { - uiNpcOutroDialog = 0; - uiTyrannus = 0; - phase = PHASE_COMBAT; - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisible(false); - } - - Creature* GetIck() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - // if killed whatever the reason, it breaks the outro - uiDamage = 0; - } - - void DoAction(const int32 actionId) - { - switch(actionId) + boss_krickAI(Creature* creature) : ScriptedAI(creature), _summons(creature), _instanceScript(creature->GetInstanceScript()) { - case ACTION_OUTRO: - { - Position pos; - if (Creature* pIck = GetIck()) - { - // TODO: tele on Ick then run some distance. - pIck->GetNearPosition(pos, 5.0f, 3.14f); - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); - } - me->SetVisible(true); - - Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); - if (pJainaOrSylvanas) { - Position pos; - me->GetNearPosition(pos, 5.0f, 0); - pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), - pos.GetAngle(me->GetPositionX(), me->GetPositionY())); - } - else { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - else - pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - } - - if (pJainaOrSylvanas) - { - pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); - me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); - uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); - } - - phase = PHASE_OUTRO; - events.Reset(); - events.ScheduleEvent(EVENT_OUTRO_1, 1000); - break; - } } - } - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_OUTRO) + void InitializeAI() { - if (!pInstance) + if (!_instanceScript || static_cast(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); + } + + void Reset() + { + _events.Reset(); + _phase = PHASE_COMBAT; + _outroNpcGUID = 0; + _tyrannusGUID = 0; + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + Creature* GetIck() + { + return ObjectAccessor::GetCreature(*me, _instanceScript->GetData64(DATA_ICK)); + } + + void KilledUnit(Unit* victim) + { + if (victim == me) return; - events.Update(diff); - switch(events.ExecuteEvent()) + DoScriptText(RAND(SAY_KRICK_SLAY_1, SAY_KRICK_SLAY_2), me); + } + + void JustSummoned(Creature* summon) + { + _summons.Summon(summon); + if (summon->GetEntry() == NPC_EXPLODING_ORB) { - case EVENT_OUTRO_1: - { - DoScriptText(SAY_KRICK_OUTRO_1, me); - events.ScheduleEvent(EVENT_OUTRO_2, 14000); - break; - } - case EVENT_OUTRO_2: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_3, 8500); - break; - } - case EVENT_OUTRO_3: - DoScriptText(SAY_KRICK_OUTRO_3, me); - events.ScheduleEvent(EVENT_OUTRO_4, 12000); - break; - case EVENT_OUTRO_4: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_5, 8000); - break; - } - case EVENT_OUTRO_5: - DoScriptText(SAY_KRICK_OUTRO_5, me); - events.ScheduleEvent(EVENT_OUTRO_6, 4000); - break; - case EVENT_OUTRO_6: - // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) - // store uiTyrannus - // Adjust timer so tyrannus has time to come - uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); - events.ScheduleEvent(EVENT_OUTRO_7, 1); - break; - case EVENT_OUTRO_7: - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); - events.ScheduleEvent(EVENT_OUTRO_8, 7000); - break; - case EVENT_OUTRO_8: - DoScriptText(SAY_KRICK_OUTRO_8, me); - // TODO: Tyrannus starts killing Krick. - // there shall be some visual spell effect - events.ScheduleEvent(EVENT_OUTRO_9, 6000); - break; - case EVENT_OUTRO_9: - // tyrannus kills krick - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetHealth(0); + summon->CastSpell(summon, SPELL_EXPLODING_ORB, true); + summon->CastSpell(summon, SPELL_AUTO_GROW, true); + } + } - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); + void DoAction(const int32 actionId) + { + if (actionId == ACTION_OUTRO) + { + Creature* tyrannusPtr = ObjectAccessor::GetCreature(*me, _instanceScript->GetData64(DATA_TYRANNUS_EVENT)); + if (tyrannusPtr) + tyrannusPtr->NearTeleportTo(outroPos[1].GetPositionX(), outroPos[1].GetPositionY(), outroPos[1].GetPositionZ(), outroPos[1].GetOrientation()); + else + tyrannusPtr = me->SummonCreature(NPC_TYRANNUS_EVENTS, outroPos[1], TEMPSUMMON_MANUAL_DESPAWN); - events.ScheduleEvent(EVENT_OUTRO_10, 12000); - break; - case EVENT_OUTRO_10: + tyrannusPtr->SetFlying(true); + me->GetMotionMaster()->MovePoint(POINT_KRICK_INTRO, outroPos[0].GetPositionX(), outroPos[0].GetPositionY(), outroPos[0].GetPositionZ()); + tyrannusPtr->SetFacingToObject(me); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id != POINT_KRICK_INTRO) + return; + + DoScriptText(SAY_KRICK_OUTRO_1, me); + _phase = PHASE_OUTRO; + _events.Reset(); + _events.ScheduleEvent(EVENT_OUTRO_1, 1000); + } + + void UpdateAI(const uint32 diff) + { + if (_phase != PHASE_OUTRO) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); - } + case EVENT_OUTRO_1: + { + if (Creature* temp = me->GetCreature(*me, _instanceScript->GetData64(DATA_JAINA_SYLVANAS_1))) + temp->ForcedDespawn(); - // End of OUTRO. for now... - events.ScheduleEvent(EVENT_OUTRO_END, 8000); - break; - } - case EVENT_OUTRO_END: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - pNpcDialog->DisappearAndDie(); + Creature* jainaOrSylvanas = NULL; + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + jainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, outroPos[2], TEMPSUMMON_MANUAL_DESPAWN); + else + jainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, outroPos[2], TEMPSUMMON_MANUAL_DESPAWN); - me->DisappearAndDie(); - break; + if (jainaOrSylvanas) + { + jainaOrSylvanas->GetMotionMaster()->MovePoint(0, outroPos[3]); + _outroNpcGUID = jainaOrSylvanas->GetGUID(); + } + _events.ScheduleEvent(EVENT_OUTRO_2, 6000); + } + case EVENT_OUTRO_2: + if (Creature* jainaOrSylvanas = me->GetCreature(*me, _outroNpcGUID)) + { + jainaOrSylvanas->SetFacingToObject(me); + me->SetFacingToObject(jainaOrSylvanas); + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_2, jainaOrSylvanas); + else + DoScriptText(SAY_SYLVANAS_OUTRO_2, jainaOrSylvanas); + } + _events.ScheduleEvent(EVENT_OUTRO_3, 5000); + break; + case EVENT_OUTRO_3: + DoScriptText(SAY_KRICK_OUTRO_3, me); + _events.ScheduleEvent(EVENT_OUTRO_4, 18000); + break; + case EVENT_OUTRO_4: + if (Creature* jainaOrSylvanas = me->GetCreature(*me, _outroNpcGUID)) + { + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_4, jainaOrSylvanas); + else + DoScriptText(SAY_SYLVANAS_OUTRO_4, jainaOrSylvanas); + } + _events.ScheduleEvent(EVENT_OUTRO_5, 5000); + break; + case EVENT_OUTRO_5: + DoScriptText(SAY_KRICK_OUTRO_5, me); + _events.ScheduleEvent(EVENT_OUTRO_6, 1000); + break; + case EVENT_OUTRO_6: + if (Creature* tyrannus = me->GetCreature(*me, _instanceScript->GetData64(DATA_TYRANNUS_EVENT))) + { + tyrannus->SetSpeed(MOVE_FLIGHT, 3.5f, true); + tyrannus->GetMotionMaster()->MovePoint(1, outroPos[4]); + _tyrannusGUID = tyrannus->GetGUID(); + } + _events.ScheduleEvent(EVENT_OUTRO_7, 5000); + break; + case EVENT_OUTRO_7: + if (Creature* tyrannus = me->GetCreature(*me, _tyrannusGUID)) + DoScriptText(SAY_TYRANNUS_OUTRO_7, tyrannus); + _events.ScheduleEvent(EVENT_OUTRO_8, 5000); + break; + case EVENT_OUTRO_8: + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->GetMotionMaster()->MovePoint(0, outroPos[5]); + DoCast(me, SPELL_STRANGULATING); + _events.ScheduleEvent(EVENT_OUTRO_9, 2000); + break; + case EVENT_OUTRO_9: + DoScriptText(SAY_KRICK_OUTRO_8, me); + // TODO: Tyrannus starts killing Krick. + // there shall be some visual spell effect + if (Creature* tyrannus = me->GetCreature(*me, _tyrannusGUID)) + tyrannus->CastSpell(me, SPELL_NECROMANTIC_POWER, true); //not sure if it's the right spell :/ + _events.ScheduleEvent(EVENT_OUTRO_10, 1000); + break; + case EVENT_OUTRO_10: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); + me->GetMotionMaster()->MovePoint(0, outroPos[6]); + _events.ScheduleEvent(EVENT_OUTRO_11, 2000); + break; + case EVENT_OUTRO_11: + DoCast(me, SPELL_KRICK_KILL_CREDIT); // don't really know if we need it + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetHealth(0); + _events.ScheduleEvent(EVENT_OUTRO_12, 3000); + break; + case EVENT_OUTRO_12: + if (Creature* tyrannus = me->GetCreature(*me, _tyrannusGUID)) + DoScriptText(SAY_TYRANNUS_OUTRO_9, tyrannus); + _events.ScheduleEvent(EVENT_OUTRO_13, 2000); + break; + case EVENT_OUTRO_13: + if (Creature* jainaOrSylvanas = me->GetCreature(*me, _outroNpcGUID)) + { + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_10, jainaOrSylvanas); + else + DoScriptText(SAY_SYLVANAS_OUTRO_10, jainaOrSylvanas); + } + // End of OUTRO. for now... + _events.ScheduleEvent(EVENT_OUTRO_END, 2000); + break; + case EVENT_OUTRO_END: + //if (Creature* jainaOrSylvanas = me->GetCreature(*me, npcOutroDialogGUID)) + // jainaOrSylvanas->DisappearAndDie(); + + //Todo: jaina walk and tyrannus fly to next step + me->DisappearAndDie(); + break; } } - return; } - } - }; + private: + InstanceScript* _instanceScript; + SummonList _summons; + EventMap _events; + + KrickPhase _phase; + uint64 _outroNpcGUID; + uint64 _tyrannusGUID; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_krickAI(creature); + } }; +class spell_krick_explosive_barrage : public SpellScriptLoader +{ + public: + spell_krick_explosive_barrage() : SpellScriptLoader("spell_krick_explosive_barrage") { } + class spell_krick_explosive_barrage_AuraScript : public AuraScript + { + PrepareAuraScript(spell_krick_explosive_barrage_AuraScript); + + void HandlePeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_UNIT) + { + Map::PlayerList const &players = caster->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player* player = itr->getSource()) + if (player->IsWithinDist(caster, 60.0f)) // don't know correct range + caster->CastSpell(player, SPELL_EXPLOSIVE_BARRAGE_SUMMON, true); + } + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_krick_explosive_barrage_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_krick_explosive_barrage_AuraScript(); + } +}; + +class spell_ick_explosive_barrage : public SpellScriptLoader +{ + public: + spell_ick_explosive_barrage() : SpellScriptLoader("spell_ick_explosive_barrage") { } + + class spell_ick_explosive_barrage_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ick_explosive_barrage_AuraScript); + + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_UNIT) + caster->GetMotionMaster()->MoveIdle(); + } + + void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_UNIT) + { + caster->GetMotionMaster()->Clear(); + caster->GetMotionMaster()->MoveChase(caster->getVictim()); + } + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_ick_explosive_barrage_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_ick_explosive_barrage_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript *GetAuraScript() const + { + return new spell_ick_explosive_barrage_AuraScript(); + } +}; + +class spell_exploding_orb_hasty_grow : public SpellScriptLoader +{ + public: + spell_exploding_orb_hasty_grow() : SpellScriptLoader("spell_exploding_orb_hasty_grow") { } + + class spell_exploding_orb_hasty_grow_AuraScript : public AuraScript + { + PrepareAuraScript(spell_exploding_orb_hasty_grow_AuraScript); + + void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetStackAmount() == 15) + { + GetTarget()->CastSpell(GetTarget(), SPELL_EXPLOSIVE_BARRAGE_DAMAGE, false); + GetTarget()->RemoveAurasDueToSpell(SPELL_HASTY_GROW); + GetTarget()->RemoveAurasDueToSpell(SPELL_AUTO_GROW); + GetTarget()->RemoveAurasDueToSpell(SPELL_EXPLODING_ORB); + if (Creature* creature = GetTarget()->ToCreature()) + creature->ForcedDespawn(1000); + } + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_exploding_orb_hasty_grow_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_SCALE, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_exploding_orb_hasty_grow_AuraScript(); + } +}; + +class spell_krick_pursuit : public SpellScriptLoader +{ + public: + spell_krick_pursuit() : SpellScriptLoader("spell_krick_pursuit") { } + + class spell_krick_pursuit_SpellScript : public SpellScript + { + PrepareSpellScript(spell_krick_pursuit_SpellScript); + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (GetCaster()->GetTypeId() != TYPEID_UNIT) + return; + + Unit* caster = GetCaster(); + CreatureAI* ickAI = caster->ToCreature()->AI(); + if (Unit* target = ickAI->SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true)) + { + DoScriptText(SAY_ICK_CHASE_1, caster, target); + caster->AddAura(GetSpellInfo()->Id, target); + CAST_AI(boss_ick::boss_ickAI, ickAI)->SetTempThreat(caster->getThreatManager().getThreat(target)); + caster->AddThreat(target, float(GetEffectValue())); + target->AddThreat(caster, float(GetEffectValue())); + } + } + + void Register() + { + OnEffect += SpellEffectFn(spell_krick_pursuit_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + class spell_krick_pursuit_AuraScript : public AuraScript + { + PrepareAuraScript(spell_krick_pursuit_AuraScript); + + void HandleExtraEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (Creature* creCaster = caster->ToCreature()) + CAST_AI(boss_ick::boss_ickAI, creCaster->AI())->_ResetThreat(GetTarget()); + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_krick_pursuit_AuraScript::HandleExtraEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_krick_pursuit_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_krick_pursuit_AuraScript(); + } +}; + +class spell_krick_pursuit_confusion : public SpellScriptLoader +{ + public: + spell_krick_pursuit_confusion() : SpellScriptLoader("spell_krick_pursuit_confusion") { } + + class spell_krick_pursuit_confusion_AuraScript : public AuraScript + { + PrepareAuraScript(spell_krick_pursuit_confusion_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + GetTarget()->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + GetTarget()->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_krick_pursuit_confusion_AuraScript::OnApply, EFFECT_2, SPELL_AURA_LINKED, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_krick_pursuit_confusion_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_LINKED, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_krick_pursuit_confusion_AuraScript(); + } +}; void AddSC_boss_ick() { new boss_ick(); new boss_krick(); + new spell_krick_explosive_barrage(); + new spell_ick_explosive_barrage(); + new spell_exploding_orb_hasty_grow(); + new spell_krick_pursuit(); + new spell_krick_pursuit_confusion(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 7c4f93e277..fd2c5dff9d 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -18,266 +18,353 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" -/* - * TODO: - * - Intro/Outro - * - improve script of Rimefang - */ - enum Yells { - SAY_AMBUSH_1 = -1658050, - SAY_AMBUSH_2 = -1658051, - SAY_GAUNTLET_START = -1658052, - SAY_INTRO_1 = -1658053, - SAY_INTRO_2 = -1658054, + SAY_AMBUSH_1 = -1658050, + SAY_AMBUSH_2 = -1658051, + SAY_GAUNTLET_START = -1658052, + SAY_TYRANNUS_INTRO_1 = -1658053, + SAY_GORKUN_INTRO_2 = -1658054, + SAY_TYRANNUS_INTRO_3 = -1658055, - SAY_AGGRO = -1658055, - SAY_SLAY_1 = -1658056, - SAY_SLAY_2 = -1658057, - SAY_DEATH = -1658058, - SAY_MARK_RIMEFANG_1 = -1658059, - SAY_MARK_RIMEFANG_2 = -1658060, - SAY_DARK_MIGHT_1 = -1658061, - SAY_DARK_MIGHT_2 = -1658062, + SAY_AGGRO = -1658056, + SAY_SLAY_1 = -1658057, + SAY_SLAY_2 = -1658058, + SAY_DEATH = -1658059, + SAY_MARK_RIMEFANG_1 = -1658060, + SAY_MARK_RIMEFANG_2 = -1658061, + SAY_DARK_MIGHT_1 = -1658062, + SAY_DARK_MIGHT_2 = -1658063, - SAY_GORKUN_OUTRO_1 = -1658063, - SAY_GORKUN_OUTRO_2 = -1658064, - SAY_JAYNA_OUTRO_3 = -1658065, - SAY_SYLVANAS_OUTRO_3 = -1658066, - SAY_JAYNA_OUTRO_4 = -1658067, - SAY_SYLVANAS_OUTRO_4 = -1658068, - SAY_JAYNA_OUTRO_5 = -1658069, + SAY_GORKUN_OUTRO_1 = -1658064, + SAY_GORKUN_OUTRO_2 = -1658065, + SAY_JAYNA_OUTRO_3 = -1658066, + SAY_SYLVANAS_OUTRO_3 = -1658067, + SAY_JAYNA_OUTRO_4 = -1658068, + SAY_SYLVANAS_OUTRO_4 = -1658069, + SAY_JAYNA_OUTRO_5 = -1658070, }; enum Spells { - SPELL_FORCEFUL_SMASH = 69155, - H_SPELL_FORCEFUL_SMASH = 69627, - SPELL_OVERLORDS_BRAND = 69172, - SPELL_OVERLORD_BRAND_DAMAGE = 69189, - SPELL_OVERLORD_BRAND_HEAL = 69190, - SPELL_DARK_MIGHT = 69167, - H_SPELL_DARK_MIGHT = 69629, - SPELL_HOARFROST = 69246, - SPELL_MARK_OF_RIMEFANG = 69275, - SPELL_ICY_BLAST = 69233, - H_SPELL_ICY_BLAST = 69646, - SPELL_ICY_BLAST_2 = 69238, - H_SPELL_ICY_BLAST_2 = 69628, + SPELL_OVERLORD_BRAND = 69172, + SPELL_OVERLORD_BRAND_HEAL = 69190, + SPELL_OVERLORD_BRAND_DAMAGE = 69189, + SPELL_FORCEFUL_SMASH = 69155, + SPELL_UNHOLY_POWER = 69167, + SPELL_MARK_OF_RIMEFANG = 69275, + SPELL_HOARFROST = 69246, + + SPELL_ICY_BLAST = 69232, + SPELL_ICY_BLAST_AURA = 69238, + + SPELL_EJECT_ALL_PASSENGERS = 50630, + SPELL_FULL_HEAL = 43979, }; enum Events { - EVENT_NONE, - EVENT_FORCEFUL_SMASH, - EVENT_OVERLORDS_BRAND, - EVENT_DARK_MIGHT, + EVENT_OVERLORD_BRAND = 1, + EVENT_FORCEFUL_SMASH = 2, + EVENT_UNHOLY_POWER = 3, + EVENT_MARK_OF_RIMEFANG = 4, // Rimefang - EVENT_MARK_OF_RIMEFANG, - EVENT_HOARFROST, - EVENT_ICY_BLAST, - EVENT_ICY_BLAST_2, + EVENT_MOVE_NEXT = 5, + EVENT_HOARFROST = 6, + EVENT_ICY_BLAST = 7, + + EVENT_INTRO_1 = 8, + EVENT_INTRO_2 = 9, + EVENT_INTRO_3 = 10, + EVENT_COMBAT_START = 11, }; -enum Misc +enum Phases { - SEAT_TYRANNUS = 0 + PHASE_NONE = 0, + PHASE_INTRO = 1, + PHASE_COMBAT = 2, + PHASE_OUTRO = 3, }; +enum Actions +{ + ACTION_START_INTRO = 1, + ACTION_START_RIMEFANG = 2, + ACTION_START_OUTRO = 3, +}; + +#define GUID_HOARFROST 1 + +static const Position rimefangPos[10] = +{ + {1017.299f, 168.9740f, 642.9259f, 0.000000f}, + {1047.868f, 126.4931f, 665.0453f, 0.000000f}, + {1069.828f, 138.3837f, 665.0453f, 0.000000f}, + {1063.042f, 164.5174f, 665.0453f, 0.000000f}, + {1031.158f, 195.1441f, 665.0453f, 0.000000f}, + {1019.087f, 197.8038f, 665.0453f, 0.000000f}, + {967.6233f, 168.9670f, 665.0453f, 0.000000f}, + {969.1198f, 140.4722f, 665.0453f, 0.000000f}, + {986.7153f, 141.6424f, 665.0453f, 0.000000f}, + {1012.601f, 142.4965f, 665.0453f, 0.000000f}, +}; + +static const Position miscPos = {1018.376f, 167.2495f, 628.2811f, 0.000000f}; //tyrannus combat start position + class boss_tyrannus : public CreatureScript { -public: - boss_tyrannus() : CreatureScript("boss_tyrannus") { } + public: + boss_tyrannus() : CreatureScript("boss_tyrannus") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_tyrannusAI(pCreature); - } - - struct boss_tyrannusAI : public ScriptedAI - { - boss_tyrannusAI(Creature *c) : ScriptedAI(c) + struct boss_tyrannusAI : public BossAI { - pInstance = c->GetInstanceScript(); - } - - InstanceScript* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); - } - - Creature* GetRimefang() - { - return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->ExitVehicle(); - - // restore health if any damage done during intro - me->SetFullHealth(); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); - events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) + boss_tyrannusAI(Creature* creature) : BossAI(creature, DATA_TYRANNUS) { - pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); - if (Creature* pRimefang = GetRimefang()) - pRimefang->ForcedDespawn(); } - } - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void InitializeAI() { - switch(eventId) + if (!instance || static_cast(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); + } + + void Reset() + { + events.Reset(); + events.SetPhase(PHASE_NONE); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + instance->SetBossState(DATA_TYRANNUS, NOT_STARTED); + } + + Creature* GetRimefang() + { + return ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_RIMEFANG)); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void AttackStart(Unit* victim) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (victim && me->Attack(victim, true) && !(events.GetPhaseMask() & (1 << PHASE_INTRO))) + me->GetMotionMaster()->MoveChase(victim); + } + + void EnterEvadeMode() + { + instance->SetBossState(DATA_TYRANNUS, FAIL); + if (Creature* rimefang = GetRimefang()) + rimefang->AI()->EnterEvadeMode(); + + me->ForcedDespawn(); + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + instance->SetBossState(DATA_TYRANNUS, DONE); + } + + void DoAction(const int32 actionId) + { + if (actionId == ACTION_START_INTRO) { - case EVENT_FORCEFUL_SMASH: - DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - return; - case EVENT_OVERLORDS_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_OVERLORDS_BRAND); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); - return; - case EVENT_DARK_MIGHT: - DoScriptText(SAY_DARK_MIGHT_1, me); - DoScriptText(SAY_DARK_MIGHT_2, me); - DoCast(me, SPELL_DARK_MIGHT); - events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); - return; + DoScriptText(SAY_TYRANNUS_INTRO_1, me); + events.SetPhase(PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_1, 14000, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_2, 22000, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_3, 34000, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_COMBAT_START, 36000, 0, PHASE_INTRO); + instance->SetBossState(DATA_TYRANNUS, IN_PROGRESS); } } - DoMeleeAttackIfReady(); - } - }; + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() && !(events.GetPhaseMask() & (1 << PHASE_INTRO))) + return; + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_INTRO_1: + //DoScriptText(SAY_GORKUN_INTRO_2, pGorkunOrVictus); + break; + case EVENT_INTRO_2: + DoScriptText(SAY_TYRANNUS_INTRO_3, me); + break; + case EVENT_INTRO_3: + me->ExitVehicle(); + me->GetMotionMaster()->MovePoint(0, miscPos); + break; + case EVENT_COMBAT_START: + if (Creature* rimefang = me->GetCreature(*me, instance->GetData64(DATA_RIMEFANG))) + rimefang->AI()->DoAction(ACTION_START_RIMEFANG); //set rimefang also infight + + events.SetPhase(PHASE_COMBAT); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + DoCast(me, SPELL_FULL_HEAL); + me->SetInCombatWithZone(); + events.ScheduleEvent(EVENT_OVERLORD_BRAND, urand(5000, 7000)); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, urand(14000, 16000)); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, urand(25000, 27000)); + break; + case EVENT_OVERLORD_BRAND: + if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) + DoCast(target, SPELL_OVERLORD_BRAND); + events.ScheduleEvent(EVENT_OVERLORD_BRAND, urand(11000, 12000)); + break; + case EVENT_FORCEFUL_SMASH: + DoCastVictim(SPELL_FORCEFUL_SMASH); + events.ScheduleEvent(EVENT_UNHOLY_POWER, 1000); + break; + case EVENT_UNHOLY_POWER: + DoScriptText(SAY_DARK_MIGHT_1, me); + DoScriptText(SAY_DARK_MIGHT_2, me); + DoCast(me, SPELL_UNHOLY_POWER); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, urand(40000, 48000)); + break; + case EVENT_MARK_OF_RIMEFANG: + DoScriptText(SAY_MARK_RIMEFANG_1, me); + DoScriptText(SAY_MARK_RIMEFANG_2, me); + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_MARK_OF_RIMEFANG); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, urand(24000, 26000)); + break; + } + } + + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_tyrannusAI(creature); + } }; class boss_rimefang : public CreatureScript { -public: - boss_rimefang() : CreatureScript("boss_rimefang") { } + public: + boss_rimefang() : CreatureScript("boss_rimefang") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_rimefangAI(pCreature); - } - - struct boss_rimefangAI : public ScriptedAI - { - boss_rimefangAI(Creature *c) : ScriptedAI(c) + struct boss_rimefangAI : public ScriptedAI { - pInstance = c->GetInstanceScript(); - } - - InstanceScript* pInstance; - EventMap events; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); - events.ScheduleEvent(EVENT_ICY_BLAST, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + boss_rimefangAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) { - switch(eventId) - { - case EVENT_MARK_OF_RIMEFANG: - DoScriptText(SAY_MARK_RIMEFANG_1, me); - DoScriptText(SAY_MARK_RIMEFANG_2, me); + ASSERT(_vehicle); + } - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); - events.ScheduleEvent(EVENT_HOARFROST, 5000); - return; - case EVENT_HOARFROST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HOARFROST); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); - return; - case EVENT_ICY_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ICY_BLAST); - events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); - return; - case EVENT_ICY_BLAST_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); - events.ScheduleEvent(EVENT_ICY_BLAST, 30000); - return; + void Reset() + { + _events.Reset(); + _events.SetPhase(PHASE_NONE); + _currentWaypoint = 0; + _hoarfrostTargetGUID = 0; + me->SetFlying(true); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void JustReachedHome() + { + _vehicle->InstallAllAccessories(me->GetEntry()); + } + + void DoAction(const int32 actionId) + { + if (actionId == ACTION_START_RIMEFANG) + { + _events.SetPhase(PHASE_COMBAT); + me->SetInCombatWithZone(); + _events.ScheduleEvent(EVENT_MOVE_NEXT, 500, 0, PHASE_COMBAT); + _events.ScheduleEvent(EVENT_ICY_BLAST, 15000, 0, PHASE_COMBAT); } } - } - }; + void SetGUID(const uint64& guid, int32 type) + { + if (type == GUID_HOARFROST) + { + _hoarfrostTargetGUID = guid; + _events.ScheduleEvent(EVENT_HOARFROST, 1000); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() && !(_events.GetPhaseMask() & (1 << PHASE_COMBAT))) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_NEXT: + if (_currentWaypoint >= 10 || _currentWaypoint == 0) + _currentWaypoint = 1; + me->GetMotionMaster()->MovePoint(0, rimefangPos[_currentWaypoint]); + ++_currentWaypoint; + _events.ScheduleEvent(EVENT_MOVE_NEXT, 2000, 0, PHASE_COMBAT); + break; + case EVENT_ICY_BLAST: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_ICY_BLAST); + _events.ScheduleEvent(EVENT_ICY_BLAST, 15000, 0, PHASE_COMBAT); + break; + case EVENT_HOARFROST: + if (Unit* target = me->GetUnit(*me, _hoarfrostTargetGUID)) + { + DoCast(target, SPELL_HOARFROST); + _hoarfrostTargetGUID = 0; + } + break; + default: + break; + } + } + } + + private: + Vehicle* _vehicle; + uint64 _hoarfrostTargetGUID; + EventMap _events; + uint8 _currentWaypoint; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_rimefangAI(creature); + } }; class player_overlord_brandAI : public PlayerAI { public: - player_overlord_brandAI(Player* pPlayer) : PlayerAI(pPlayer) + player_overlord_brandAI(Player* player) : PlayerAI(player) { tyrannus = NULL; } @@ -291,7 +378,8 @@ class player_overlord_brandAI : public PlayerAI void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) { - me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->getVictim(), true, NULL, NULL, tyrannus->GetGUID()); + if (tyrannus->getVictim()) + me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->getVictim(), true, NULL, NULL, tyrannus->GetGUID()); } void HealDone(Unit* /*target*/, uint32& addHealth) @@ -299,7 +387,7 @@ class player_overlord_brandAI : public PlayerAI me->CastCustomSpell(SPELL_OVERLORD_BRAND_HEAL, SPELLVALUE_BASE_POINT0, int32(addHealth*5.5f), tyrannus, true, NULL, NULL, tyrannus->GetGUID()); } - void UpdateAI(const uint32 /*diff*/) { } + void UpdateAI(const uint32 diff) { } private: Creature* tyrannus; @@ -352,9 +440,64 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader } }; +class spell_tyrannus_mark_of_rimefang : public SpellScriptLoader +{ + public: + spell_tyrannus_mark_of_rimefang() : SpellScriptLoader("spell_tyrannus_mark_of_rimefang") { } + + class spell_tyrannus_mark_of_rimefang_AuraScript : public AuraScript + { + PrepareAuraScript(spell_tyrannus_mark_of_rimefang_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (!GetCaster() || GetCaster()->GetTypeId() != TYPEID_UNIT) + return; + + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* rimefang = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_RIMEFANG))) + rimefang->AI()->SetGUID(GetTarget()->GetGUID(), GUID_HOARFROST); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_tyrannus_mark_of_rimefang_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_tyrannus_mark_of_rimefang_AuraScript(); + } +}; + +class at_tyrannus_event_starter : public AreaTriggerScript +{ + public: + at_tyrannus_event_starter() : AreaTriggerScript("at_tyrannus_event_starter") { } + + bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) + { + InstanceScript* instance = player->GetInstanceScript(); + if (player->isGameMaster() || !instance) + return false; + + if (instance->GetBossState(DATA_TYRANNUS) != IN_PROGRESS || instance->GetBossState(DATA_TYRANNUS) != DONE) + if (Creature* tyrannus = Unit::GetCreature(*player, instance->GetData64(DATA_TYRANNUS))) + { + tyrannus->AI()->DoAction(ACTION_START_INTRO); + return true; + } + + return false; + } +}; + void AddSC_boss_tyrannus() { new boss_tyrannus(); new boss_rimefang(); new spell_tyrannus_overlord_brand(); + new spell_tyrannus_mark_of_rimefang(); + new at_tyrannus_event_starter(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp index 12b7e1c97c..c26a62d69d 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -18,223 +18,211 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" -#define MAX_ENCOUNTER 3 - -/* Pit of Saron encounters: -0- Forgemaster Garfrost -1- Krick and Ick -2- Scourgelord Tyrannus -*/ - class instance_pit_of_saron : public InstanceMapScript { -public: - instance_pit_of_saron() : InstanceMapScript("instance_pit_of_saron", 658) { } + public: + instance_pit_of_saron() : InstanceMapScript(PoSScriptName, 658) { } - InstanceScript* GetInstanceScript(InstanceMap* pMap) const - { - return new instance_pit_of_saron_InstanceMapScript(pMap); - } - - struct instance_pit_of_saron_InstanceMapScript : public InstanceScript - { - instance_pit_of_saron_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {}; - - uint64 uiKrick; - uint64 uiIck; - uint64 uiGarfrost; - uint64 uiTyrannus; - uint64 uiRimefang; - - uint64 uiJainaOrSylvanas1; - uint64 uiJainaOrSylvanas2; - - uint32 uiTeamInInstance; - uint32 uiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - - uiGarfrost = 0; - uiKrick = 0; - uiIck = 0; - uiTyrannus = 0; - } - - bool IsEncounterInProgress() const + struct instance_pit_of_saron_InstanceScript : public InstanceScript { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* creature) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) + instance_pit_of_saron_InstanceScript(Map* map) : InstanceScript(map) { - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); + SetBossNumber(MAX_ENCOUNTER); + _garfrostGUID = 0; + _krickGUID = 0; + _ickGUID = 0; + _tyrannusGUID = 0; + _rimefangGUID = 0; + _jainaOrSylvanas1GUID = 0; + _jainaOrSylvanas2GUID = 0; + _teamInInstance = 0; } - switch(creature->GetEntry()) + void OnCreatureCreate(Creature* creature, bool /*add*/) { - case CREATURE_KRICK: - uiKrick = creature->GetGUID(); - break; + if (!_teamInInstance) + { + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* player = players.begin()->getSource()) + _teamInInstance = player->GetTeam(); + } - case CREATURE_ICK: - uiIck = creature->GetGUID(); - break; - - case CREATURE_GARFROST: - uiGarfrost = creature->GetGUID(); - break; - - case CREATURE_TYRANNUS: - uiTyrannus = creature->GetGUID(); - break; - - case CREATURE_RIMEFANG: - uiRimefang = creature->GetGUID(); - break; - - case NPC_SYLVANAS_PART1: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); - uiJainaOrSylvanas1 = creature->GetGUID(); - break; - case NPC_SYLVANAS_PART2: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); - uiJainaOrSylvanas2 = creature->GetGUID(); - break; - case NPC_KILARA: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_ELANDRA, ALLIANCE); - break; - case NPC_KORALEN: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_KORLAEN, ALLIANCE); - break; - case NPC_CHAMPION_1_HORDE: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_2_HORDE: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_GARFROST: return uiGarfrost; - case DATA_KRICK: return uiKrick; - case DATA_ICK: return uiIck; - case DATA_TYRANNUS: return uiTyrannus; - case DATA_RIMEFANG: return uiRimefang; - - case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; - case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; + switch (creature->GetEntry()) + { + case NPC_GARFROST: + _garfrostGUID = creature->GetGUID(); + break; + case NPC_KRICK: + _krickGUID = creature->GetGUID(); + break; + case NPC_ICK: + _ickGUID = creature->GetGUID(); + break; + case NPC_TYRANNUS: + _tyrannusGUID = creature->GetGUID(); + break; + case NPC_RIMEFANG: + _rimefangGUID = creature->GetGUID(); + break; + case NPC_TYRANNUS_EVENTS: + _tyrannusEventGUID = creature->GetGUID(); + break; + case NPC_SYLVANAS_PART1: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); + _jainaOrSylvanas1GUID = creature->GetGUID(); + break; + case NPC_SYLVANAS_PART2: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); + _jainaOrSylvanas2GUID = creature->GetGUID(); + break; + case NPC_KILARA: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ELANDRA, ALLIANCE); + break; + case NPC_KORALEN: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_KORLAEN, ALLIANCE); + break; + case NPC_CHAMPION_1_HORDE: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_2_HORDE: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_HORDE_SLAVE_1: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_1, ALLIANCE); + break; + case NPC_HORDE_SLAVE_2: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_2, ALLIANCE); + break; + case NPC_HORDE_SLAVE_3: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_3, ALLIANCE); + break; + case NPC_HORDE_SLAVE_4: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_4, ALLIANCE); + break; + default: + break; + } } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) + uint32 GetData(uint32 type) { - case DATA_GARFROST_EVENT: - uiEncounter[0] = data; - break; - case DATA_TYRANNUS_EVENT: - uiEncounter[1] = data; - break; - case DATA_KRICKANDICK_EVENT: - uiEncounter[2] = data; - break; + switch (type) + { + case DATA_TEAM_IN_INSTANCE: + return _teamInInstance; + default: + break; + } + + return 0; } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) + uint64 GetData64(uint32 type) { - case DATA_GARFROST_EVENT: return uiEncounter[0]; - case DATA_TYRANNUS_EVENT: return uiEncounter[1]; - case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; + switch (type) + { + case DATA_GARFROST: + return _garfrostGUID; + case DATA_KRICK: + return _krickGUID; + case DATA_ICK: + return _ickGUID; + case DATA_TYRANNUS: + return _tyrannusGUID; + case DATA_RIMEFANG: + return _rimefangGUID; + case DATA_TYRANNUS_EVENT: + return _tyrannusEventGUID; + case DATA_JAINA_SYLVANAS_1: + return _jainaOrSylvanas1GUID; + case DATA_JAINA_SYLVANAS_2: + return _jainaOrSylvanas2GUID; + default: + break; + } + + return 0; } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; - - std::ostringstream saveStream; - saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) + std::string GetSaveData() { - OUT_LOAD_INST_DATA_FAIL; - return; + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "P S " << GetBossSaveData(); + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'P' && dataHead2 == 'S') + void Load(const char* in) { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA(in); - } else OUT_LOAD_INST_DATA_FAIL; + char dataHead1, dataHead2; - OUT_LOAD_INST_DATA_COMPLETE; + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'P' && dataHead2 == 'S') + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + private: + uint64 _garfrostGUID; + uint64 _krickGUID; + uint64 _ickGUID; + uint64 _tyrannusGUID; + uint64 _rimefangGUID; + + uint64 _tyrannusEventGUID; + uint64 _jainaOrSylvanas1GUID; + uint64 _jainaOrSylvanas2GUID; + + uint32 _teamInInstance; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const + { + return new instance_pit_of_saron_InstanceScript(map); } - }; - }; - void AddSC_instance_pit_of_saron() { new instance_pit_of_saron(); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp index 777f604283..c5abad82c4 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -18,1134 +18,267 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" -/***************************************SPELLS*************************************/ -// Ymirjar Wrathbringer -#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) +enum eSpells +{ + SPELL_FIREBALL = 69583, //Ymirjar Flamebearer + SPELL_HELLFIRE = 69586, + SPELL_TACTICAL_BLINK = 69584, + SPELL_FROST_BREATH = 69527, //Iceborn Proto-Drake + SPELL_BLINDING_DIRT = 70302, //Wrathbone Laborer + SPELL_PUNCTURE_WOUND = 70278, + SPELL_SHOVELLED = 69572, + SPELL_LEAPING_FACE_MAUL = 69504, // Geist Ambusher +}; -//Ymirjar Skycaller -#define SPELL_FROSTBLADE 70291 -#define SPELL_GLACIAL_STRIKE 70292 - -//Ymirjar Flamebearer -#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) -#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) -#define SPELL_TACTICAL_BLINK 69584 - -//Ymirjar Deathbringer -#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) -#define SPELL_SUMMON_UNDEAD 69516 - -//Wrathbone Laborer -#define SPELL_BLINDING_DIRT 70302 -#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) -#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) - -//Wrathbone Coldwraith -#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) -#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) - -//Stonespine Gargoyle -#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) -#define SPELL_STONEFORM 69575 - -// Plagueborn Horror -#define SPELL_BLIGHT_BOMB 69582 -#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) -#define SPELL_TOXIC_WASTE 70274 - -//Iceborn Proto-Drake -#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) - -//Hungering Ghoul -#define SPELL_DEVOUR_FLESH 70393 - -//Fallen Warrior -#define SPELL_ARCING_SLICE 69579 -#define SPELL_DEMORALIZING_SHOUT 61044 -#define SPELL_SHIELD_BLOCK 69580 - -//Deathwhisper Torturer -#define SPELL_BLACK_BRAND 70392 -#define SPELL_CURSE_OF_AGONY 70391 - -//Deathwhisper Shadowcaster -#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) - -//Deathwhisper Necrolyte -#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) -#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) - -//Wrathbone Sorcerer -#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) - -//Geist Ambusher -#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) - -/****************************************EVENTS************************************/ enum eEvents { - EVENT_NONE, - - // Ymirjar Wrathbringer - EVENT_BLIGHT, - - // Ymirjar Skycaller - EVENT_FROSTBLADE, - EVENT_GLACIAL_STRIKE, - // Ymirjar Flamebearer - EVENT_FIREBALL, - EVENT_HELLFIRE, - EVENT_TACTICAL_BLINK, - - //Ymirjar Deathbringer - EVENT_EMPOWERED_SHADOW_BOLT, - EVENT_SUMMON_UNDEAD, + EVENT_FIREBALL = 1, + EVENT_TACTICAL_BLINK = 2, //Wrathbone Laborer - EVENT_BLINDING_DIRT, - EVENT_PUNCTURE_WOUND, - EVENT_SHOVELLED, - - //Wrathbone Coldwraith - EVENT_FREEZING_CIRCLE, - EVENT_FROSTBOLT, - - //Stonespine Gargoyle - EVENT_GARGOYLE_STRIKE, - EVENT_STONEFORM, - - //Plagueborn Horror - EVENT_BLIGHT_BOMB, - EVENT_PUSTULANT_FLESH, - EVENT_TOXIC_WASTE, - - //Iceborn Proto-Drake - EVENT_FROST_BREATH, - - //Hungering Ghoul - EVENT_DEVOUR_FLESH, - - //Fallen Warrior - EVENT_ARCING_SLICE, - EVENT_DEMORALIZING_SHOUT, - EVENT_SHIELD_BLOCK, - - //Deathwhisper Torturer - EVENT_BLACK_BRAND, - EVENT_CURSE_OF_AGONY, - - //Deathwhisper Shadowcaster - EVENT_SHADOW_BOLT, - - //Deathwhisper Necrolyte - EVENT_CONVERSION_BEAM, - EVENT_SHADOW_BOLT_2, - - EVENT_SHADOW_BOLT_3, - - //Geist Ambusher - EVENT_LEAPING_FACE_MAUL, -}; - -/****************************************AI****************************************/ - -class mob_ymirjar_wrathbringer : public CreatureScript -{ -public: - mob_ymirjar_wrathbringer() : CreatureScript("mob_ymirjar_wrathbringer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_wrathbringerAI(pCreature); - } - - struct mob_ymirjar_wrathbringerAI : public ScriptedAI - { - mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT, 7000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLIGHT); - events.RescheduleEvent(EVENT_BLIGHT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_ymirjar_skycaller : public CreatureScript -{ -public: - mob_ymirjar_skycaller() : CreatureScript("mob_ymirjar_skycaller") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_skyCallerAI(pCreature); - } - - struct mob_ymirjar_skyCallerAI: public ScriptedAI - { - mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROSTBLADE, 1); - events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GLACIAL_STRIKE: - DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); - events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - return; - case EVENT_FROSTBLADE: - DoCast(me, SPELL_FROSTBLADE); - events.CancelEvent(EVENT_FROSTBLADE); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - + EVENT_BLINDING_DIRT = 3, + EVENT_PUNCTURE_WOUND = 4, + EVENT_SHOVELLED = 5, }; class mob_ymirjar_flamebearer : public CreatureScript { -public: - mob_ymirjar_flamebearer() : CreatureScript("mob_ymirjar_flamebearer") { } + public: + mob_ymirjar_flamebearer() : CreatureScript("mob_ymirjar_flamebearer") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_flamebearerAI(pCreature); - } - - struct mob_ymirjar_flamebearerAI: public ScriptedAI - { - mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) + struct mob_ymirjar_flamebearerAI: public ScriptedAI { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 4000); - events.ScheduleEvent(EVENT_HELLFIRE, 8000); - events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_ymirjar_flamebearerAI(Creature* creature) : ScriptedAI(creature) { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - events.RescheduleEvent(EVENT_FIREBALL, 5000); - return; - case EVENT_HELLFIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HELLFIRE); - events.RescheduleEvent(EVENT_HELLFIRE, 10000); - return; - case EVENT_TACTICAL_BLINK: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TACTICAL_BLINK); - events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); - return; - } } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_ymirjar_deathbringer : public CreatureScript -{ -public: - mob_ymirjar_deathbringer() : CreatureScript("mob_ymirjar_deathbringer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_deathbringerAI(pCreature); - } - - struct mob_ymirjar_deathbringerAI: public ScriptedAI - { - mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void Reset() { - switch(eventId) - { - case EVENT_EMPOWERED_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); - events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - return; - } + _events.Reset(); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_wrathbone_laborer : public CreatureScript -{ -public: - mob_wrathbone_laborer() : CreatureScript("mob_wrathbone_laborer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_wrathbone_laborerAI(pCreature); - } - - struct mob_wrathbone_laborerAI: public ScriptedAI - { - mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); - events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - events.ScheduleEvent(EVENT_SHOVELLED, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void EnterCombat(Unit* /*who*/) { - switch(eventId) - { - case EVENT_BLINDING_DIRT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLINDING_DIRT); - events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); - return; - case EVENT_PUNCTURE_WOUND: - DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); - events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - return; - case EVENT_SHOVELLED: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHOVELLED); - events.RescheduleEvent(EVENT_SHOVELLED, 7000); - return; - } + _events.ScheduleEvent(EVENT_FIREBALL, 4000); + _events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_wrathbone_coldwraith : public CreatureScript -{ -public: - mob_wrathbone_coldwraith() : CreatureScript("mob_wrathbone_coldwraith") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_wrathbone_coldwraithAI(pCreature); - } - - struct mob_wrathbone_coldwraithAI: public ScriptedAI - { - mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - events.ScheduleEvent(EVENT_FROSTBOLT, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(const uint32 diff) { - switch(eventId) + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) { - case EVENT_FREEZING_CIRCLE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_CIRCLE); - events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.RescheduleEvent(EVENT_FROSTBOLT, 5000); - return; + switch (eventId) + { + case EVENT_FIREBALL: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_FIREBALL); + _events.RescheduleEvent(EVENT_FIREBALL, 5000); + break; + case EVENT_TACTICAL_BLINK: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_TACTICAL_BLINK); + DoCast(me, SPELL_HELLFIRE); + _events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + private: + EventMap _events; + }; -}; - -class mob_stonespine_gargoyle : public CreatureScript -{ -public: - mob_stonespine_gargoyle() : CreatureScript("mob_stonespine_gargoyle") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_stonespine_gargoyleAI(pCreature); - } - - struct mob_stonespine_gargoyleAI: public ScriptedAI - { - mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) + CreatureAI* GetAI(Creature* creature) const { + return new mob_ymirjar_flamebearerAI(creature); } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GARGOYLE_STRIKE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_GARGOYLE_STRIKE); - events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); - return; - case EVENT_STONEFORM: - if (HealthBelowPct(10)) - DoCast(me, SPELL_STONEFORM); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_plagueborn_horror : public CreatureScript -{ -public: - mob_plagueborn_horror() : CreatureScript("mob_plagueborn_horror") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_plagueborn_horrorAI(pCreature); - } - - struct mob_plagueborn_horrorAI: public ScriptedAI - { - mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); - events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT_BOMB: - if (HealthBelowPct(15)) - DoCast(me, SPELL_BLIGHT_BOMB); - return; - case EVENT_PUSTULANT_FLESH: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PUSTULANT_FLESH); - events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); - return; - case EVENT_TOXIC_WASTE: - DoCast(me, SPELL_TOXIC_WASTE); - events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - }; class mob_iceborn_protodrake : public CreatureScript { -public: - mob_iceborn_protodrake() : CreatureScript("mob_iceborn_protodrake") { } + public: + mob_iceborn_protodrake() : CreatureScript("mob_iceborn_protodrake") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_iceborn_protodrakeAI(pCreature); - } - - struct mob_iceborn_protodrakeAI: public ScriptedAI - { - mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) + struct mob_iceborn_protodrakeAI: public ScriptedAI { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_BREATH, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_iceborn_protodrakeAI(Creature *creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) { - switch(eventId) - { - case EVENT_FROST_BREATH: - DoCast(me->getVictim(), SPELL_FROST_BREATH); - events.RescheduleEvent(EVENT_FROST_BREATH, 10000); - return; - } + ASSERT(_vehicle); } - DoMeleeAttackIfReady(); - } - }; + void Reset() + { + _frostBreathCooldown = 5000; + } + void EnterCombat(Unit* /*who*/) + { + _vehicle->RemoveAllPassengers(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (_frostBreathCooldown < diff) + { + DoCastVictim(SPELL_FROST_BREATH); + _frostBreathCooldown = 10000; + } + else + _frostBreathCooldown -= diff; + + DoMeleeAttackIfReady(); + } + + private: + Vehicle* _vehicle; + uint32 _frostBreathCooldown; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new mob_iceborn_protodrakeAI(creature); + } }; -class mob_hungering_ghoul : public CreatureScript +class mob_wrathbone_laborer : public CreatureScript { -public: - mob_hungering_ghoul() : CreatureScript("mob_hungering_ghoul") { } + public: + mob_wrathbone_laborer() : CreatureScript("mob_wrathbone_laborer") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_hungering_ghoulAI(pCreature); - } - - struct mob_hungering_ghoulAI: public ScriptedAI - { - mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) + struct mob_wrathbone_laborerAI: public ScriptedAI { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_wrathbone_laborerAI(Creature* creature) : ScriptedAI(creature) { - switch(eventId) - { - case EVENT_DEVOUR_FLESH: - DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); - events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); - return; - } } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_fallen_warrior : public CreatureScript -{ -public: - mob_fallen_warrior() : CreatureScript("mob_fallen_warrior") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_fallen_warriorAI(pCreature); - } - - struct mob_fallen_warriorAI: public ScriptedAI - { - mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); - events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void Reset() { - switch(eventId) - { - case EVENT_ARCING_SLICE: - DoCast(me->getVictim(), SPELL_ARCING_SLICE); - events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); - return; - case EVENT_DEMORALIZING_SHOUT: - DoCast(me, SPELL_DEMORALIZING_SHOUT); - events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - return; - case EVENT_SHIELD_BLOCK: - DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); - events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); - return; - } + _events.Reset(); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_deathwhisper_torturer : public CreatureScript -{ -public: - mob_deathwhisper_torturer() : CreatureScript("mob_deathwhisper_torturer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_deathwhisper_torturerAI(pCreature); - } - - struct mob_deathwhisper_torturerAI: public ScriptedAI - { - mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); - events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void EnterCombat(Unit* /*who*/) { - switch(eventId) - { - case EVENT_BLACK_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLACK_BRAND); - events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); - return; - case EVENT_CURSE_OF_AGONY: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CURSE_OF_AGONY); - events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); - return; - } + _events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); + _events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + _events.ScheduleEvent(EVENT_SHOVELLED, 5000); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_deathwhisper_shadowcaster : public CreatureScript -{ -public: - mob_deathwhisper_shadowcaster() : CreatureScript("mob_deathwhisper_shadowcaster") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_deathwhisper_shadowcasterAI(pCreature); - } - - struct mob_deathwhisper_shadowcasterAI: public ScriptedAI - { - mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(const uint32 diff) { - switch(eventId) + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) { - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; + switch(eventId) + { + case EVENT_BLINDING_DIRT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 10.0f, true)) + DoCast(target, SPELL_BLINDING_DIRT); + _events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); + return; + case EVENT_PUNCTURE_WOUND: + DoCastVictim(SPELL_PUNCTURE_WOUND); + _events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + return; + case EVENT_SHOVELLED: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, -5.0f)) + DoCast(target, SPELL_SHOVELLED); + _events.RescheduleEvent(EVENT_SHOVELLED, 7000); + return; + } } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + private: + EventMap _events; + }; -}; - -class mob_deathwhisper_necrolyte : public CreatureScript -{ -public: - mob_deathwhisper_necrolyte() : CreatureScript("mob_deathwhisper_necrolyte") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_deathwhisper_necrolyteAI(pCreature); - } - - struct mob_deathwhisper_necrolyteAI: public ScriptedAI - { - mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) + CreatureAI* GetAI(Creature* creature) const { + return new mob_wrathbone_laborerAI(creature); } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); - events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CONVERSION_BEAM: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CONVERSION_BEAM); - events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); - return; - case EVENT_SHADOW_BOLT_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_2); - events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_wrathbone_sorcerer : public CreatureScript -{ -public: - mob_wrathbone_sorcerer() : CreatureScript("mob_wrathbone_sorcerer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_wrathbone_sorcererAI(pCreature); - } - - struct mob_wrathbone_sorcererAI: public ScriptedAI - { - mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT_3: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_3); - events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } - }; - }; class mob_geist_ambusher : public CreatureScript { -public: - mob_geist_ambusher() : CreatureScript("mob_geist_ambusher") { } + public: + mob_geist_ambusher() : CreatureScript("mob_geist_ambusher") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_geist_ambusherAI(pCreature); - } - - struct mob_geist_ambusherAI: public ScriptedAI - { - mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) + struct mob_geist_ambusherAI: public ScriptedAI { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - //Only here so when I figure out how to make it cast on an NPC i can do that. - events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_geist_ambusherAI(Creature* creature) : ScriptedAI(creature) { - switch(eventId) - { - //Should only be used on NPCs - case EVENT_LEAPING_FACE_MAUL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); - events.CancelEvent(EVENT_LEAPING_FACE_MAUL); - return; - } } - DoMeleeAttackIfReady(); - } - }; + void Reset() + { + _leapingFaceMaulCooldown = 9000; + } + void MoveInLineOfSight(Unit* who) + { + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + if (me->IsWithinDistInMap(who, 30.0f)) + DoCast(who, SPELL_LEAPING_FACE_MAUL); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (_leapingFaceMaulCooldown < diff) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f, true)) + DoCast(target, SPELL_LEAPING_FACE_MAUL); + _leapingFaceMaulCooldown = urand(9000, 14000); + } + else + _leapingFaceMaulCooldown -= diff; + + DoMeleeAttackIfReady(); + } + + private: + uint32 _leapingFaceMaulCooldown; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new mob_geist_ambusherAI(creature); + } }; void AddSC_pit_of_saron() { - new mob_ymirjar_wrathbringer(); - new mob_ymirjar_skycaller(); new mob_ymirjar_flamebearer(); - new mob_ymirjar_deathbringer(); new mob_wrathbone_laborer(); - new mob_wrathbone_coldwraith(); - new mob_stonespine_gargoyle(); - new mob_plagueborn_horror(); new mob_iceborn_protodrake(); - new mob_hungering_ghoul(); - new mob_fallen_warrior(); - new mob_deathwhisper_torturer(); - new mob_deathwhisper_shadowcaster(); - new mob_deathwhisper_necrolyte(); - new mob_wrathbone_sorcerer(); new mob_geist_ambusher(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h index 9368d479cd..d71972d64f 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h @@ -18,34 +18,32 @@ #ifndef DEF_PIT_OF_SARON_H #define DEF_PIT_OF_SARON_H -enum Data +#define PoSScriptName "instance_pit_of_saron" +#define MAX_ENCOUNTER 3 + +enum DataTypes { - DATA_GARFROST_EVENT, - DATA_KRICKANDICK_EVENT, - DATA_TYRANNUS_EVENT, - DATA_TEAM_IN_INSTANCE, + DATA_GARFROST = 0, + DATA_KRICK = 1, + DATA_ICK = 2, + DATA_TYRANNUS = 3, + DATA_RIMEFANG = 4, + + DATA_JAINA_SYLVANAS_1 = 5, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. + DATA_JAINA_SYLVANAS_2 = 6, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. + DATA_TYRANNUS_EVENT = 7, + DATA_TEAM_IN_INSTANCE = 8, }; -enum Data64 +enum CreatureIds { - DATA_GARFROST, - DATA_KRICK, - DATA_ICK, - DATA_TYRANNUS, - DATA_RIMEFANG, - - DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. - DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. -}; - -enum Creatures -{ - CREATURE_GARFROST = 36494, - CREATURE_KRICK = 36477, - CREATURE_ICK = 36476, - CREATURE_TYRANNUS = 36658, - CREATURE_RIMEFANG = 36661, + NPC_GARFROST = 36494, + NPC_KRICK = 36477, + NPC_ICK = 36476, + NPC_TYRANNUS = 36658, + NPC_RIMEFANG = 36661, + NPC_TYRANNUS_EVENTS = 36794, NPC_SYLVANAS_PART1 = 36990, NPC_SYLVANAS_PART2 = 38189, NPC_JAINA_PART1 = 36993, @@ -59,6 +57,25 @@ enum Creatures NPC_CHAMPION_3_HORDE = 37588, NPC_CHAMPION_1_ALLIANCE = 37496, NPC_CHAMPION_2_ALLIANCE = 37497, + + NPC_HORDE_SLAVE_1 = 36770, + NPC_HORDE_SLAVE_2 = 36771, + NPC_HORDE_SLAVE_3 = 36772, + NPC_HORDE_SLAVE_4 = 36773, + NPC_ALLIANCE_SLAVE_1 = 36764, + NPC_ALLIANCE_SLAVE_2 = 36765, + NPC_ALLIANCE_SLAVE_3 = 36766, + NPC_ALLIANCE_SLAVE_4 = 36767, + + NPC_FORGEMASTER_STALKER = 36495, + NPC_EXPLODING_ORB = 36610, + NPC_YMIRJAR_DEATHBRINGER = 36892, + NPC_ICY_BLAST = 36731 +}; + +enum GameObjectIds +{ + GO_SARONITE_ROCK = 196485, }; #endif