diff options
author | horn <pankrac.ja@seznam.cz> | 2013-03-03 22:19:57 +0100 |
---|---|---|
committer | horn <pankrac.ja@seznam.cz> | 2013-05-14 17:52:37 +0200 |
commit | 0a0698b1d41cca4ae19f84b1c62c97d2964e13a5 (patch) | |
tree | e2744de7b80577a49a9810150211524809d204b0 | |
parent | 8e1601e202708ccd483456f5bfa06957470e2d3c (diff) |
Scripts/Ulduar: Yogg-Saron
Known issues:
- encounter doesn't start immediately after you enter the room, you need to go closer
- players standing outside of the room are not turned Insane after 15 seconds
- encounter resets if the last living player is gripped by Constrictor Tentacle or encased in Hodir's Flash Freeze
- Hodir won't freeze multiple players when they die at the same moment
- Flash Freeze missile (64176) won't hit anybody, probably cast too soon (cosmetic issue)
- there are some unused spells, don't know when or why they should be cast
- some spell animations hit multiple players, but they shouldn't do that
-rw-r--r-- | sql/updates/world/2013_05_14_00_world_instance_ulduar.sql | 473 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptLoader.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 11 | ||||
-rw-r--r-- | src/server/scripts/Northrend/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp | 3227 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp | 55 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 389 | ||||
-rw-r--r-- | src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h | 96 |
10 files changed, 4106 insertions, 153 deletions
diff --git a/sql/updates/world/2013_05_14_00_world_instance_ulduar.sql b/sql/updates/world/2013_05_14_00_world_instance_ulduar.sql new file mode 100644 index 00000000000..1594a8c44a9 --- /dev/null +++ b/sql/updates/world/2013_05_14_00_world_instance_ulduar.sql @@ -0,0 +1,473 @@ +-- NPCs +SET @VOICE_OF_YOGG_SARON := 33280; +SET @YOGG_SARON := 33288; +SET @YOGG_SARON_H := 33955; +SET @SARA := 33134; +SET @SARA_H := 34332; +SET @BRAIN_OF_YOGG_SARON := 33890; +SET @BRAIN_OF_YOGG_SARON_H := 33954; +SET @OMINOUS_CLOUD := 33292; +SET @GUARDIAN_OF_YOGG_SARON := 33136; +SET @GUARDIAN_OF_YOGG_SARON_H := 33968; +SET @CORRUPTOR_TENTACLE := 33985; +SET @CORRUPTOR_TENTACLE_H := 33986; +SET @CONSTRICTOR_TENTACLE := 33983; +SET @CONSTRICTOR_TENTACLE_H := 33984; +SET @CRUSHER_TENTACLE := 33966; +SET @CRUSHER_TENTACLE_H := 33967; +SET @LAUGHING_SKULL := 33990; +SET @DEATH_RAY := 33881; +SET @DEATH_ORB := 33882; +SET @GARONA := 33436; +SET @KING_LLANE := 33437; +SET @SUIT_OF_ARMOR := 33433; +SET @THE_LICH_KING := 33441; +SET @IMMOLATED_CHAMPION := 33442; +SET @TURNED_CHAMPION := 33962; +SET @DEATHSWORN_ZEALOT := 33567; +SET @NELTHARION := 33523; +SET @ALEXSTRASZA := 33536; +SET @YSERA := 33495; +SET @MALYGOS := 33535; +SET @OBSIDIAN_CONSORT := 33720; +SET @AZURE_CONSORT := 33717; +SET @EMERALD_CONSORT := 33719; +SET @RUBY_CONSORT := 33716; +SET @YOGG_SARON_ILLUSIONS := 33552; +SET @TRIGGER := 28332; -- Generic Trigger LAB (Large AOI), maybe to start illusion events? +SET @FREYA_GOSSIP := 33241; +SET @HODIR_GOSSIP := 33213; +SET @THORIM_GOSSIP := 33242; +SET @MIMIRON_GOSSIP := 33244; +SET @FREYA_YS := 33410; +SET @HODIR_YS := 33411; +SET @MIMIRON_YS := 33412; +SET @THORIM_YS := 33413; +SET @IMMORTAL_GUARDIAN := 33988; +SET @IMMORTAL_GUARDIAN_H := 33989; +SET @MARKED_IMMORTAL_GUARDIAN := 36064; +SET @MARKED_IMMORTAL_GUARDIAN_H := 36067; +SET @SANITY_WELL := 33991; +SET @INFLUENCE_TENTACLE := 33943; +SET @INFLUENCE_TENTACLE_H := 33959; +SET @DESCEND_INTO_MADNESS := 34072; + +SET @GUID := 62015; + +-- GameObjects +SET @FLEE_TO_THE_SURFACE := 194625; +SET @DRAGON_SOUL := 194462; +SET @INSTANCE_PORTAL := 194338; +SET @CHAIR := 194360; + +SET @GO_GUID := 17800; + +DELETE FROM `creature_text` WHERE `entry` IN (@SARA,@YOGG_SARON,@VOICE_OF_YOGG_SARON,@GARONA,@KING_LLANE,@THE_LICH_KING,@IMMOLATED_CHAMPION,@NELTHARION,@YSERA,@MALYGOS,@YOGG_SARON_ILLUSIONS,@FREYA_GOSSIP,@HODIR_GOSSIP,@THORIM_GOSSIP,@MIMIRON_GOSSIP,@OMINOUS_CLOUD,@BRAIN_OF_YOGG_SARON); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@SARA,0,0,'Help me! Please get them off me!',14,0,100,0,0,15771,'Sara - SAY_SARA_ULDUAR_SCREAM_1'), +(@SARA,1,0,'What do you want from me? Leave me alone!',14,0,100,0,0,15772,'Sara - SAY_SARA_ULDUAR_SCREAM_2'), +(@SARA,2,0,'The time to strike at the head of the beast will soon be upon us! Focus your anger and hatred on his minions!',14,0,100,457,0,15775,'Sara - SAY_SARA_AGGRO'), +(@SARA,3,0,'Yes! YES! Show them no mercy! Give no pause to your attacks!',14,0,100,0,0,15773,'Sara - SAY_SARA_FERVOR_HIT'), +(@SARA,4,0,'Let hatred and rage guide your blows!',14,0,100,0,0,15774,'SAY_SARA_BLESSING_HIT'), +(@SARA,5,0,'Could they have been saved?',14,0,100,0,0,15779,'Sara - SAY_SARA_KILL'), +(@SARA,5,1,'Powerless to act...',14,0,100,0,0,15778,'Sara - SAY_SARA_KILL'), +(@SARA,6,0,'I am the lucid dream.',14,0,100,457,0,15754,'Sara - SAY_SARA_TRANSFORM_1'), +(@SARA,7,0,'The monster in your nightmares.',14,0,100,457,0,0,'Sara - SAY_SARA_TRANSFORM_2'), +(@SARA,8,0,'The fiend of a thousand faces.',14,0,100,457,0,0,'Sara - SAY_SARA_TRANSFORM_3'), +(@SARA,9,0,'Cower before my true form.',14,0,100,457,0,0,'Sara - SAY_SARA_TRANSFORM_4'), +(@SARA,10,0,'Tremble, mortals, before the coming of the end!',14,0,100,0,0,15777,'Sara - SAY_SARA_DEATH_RAY'), +(@SARA,11,0,'Suffocate upon your own hate!',14,0,100,0,0,15776,'Sara - SAY_SARA_PSYCHOSIS_HIT'), +(@OMINOUS_CLOUD,0,0,'%s begins to boil upon touching $n!',16,0,100,0,0,0,'Ominous Cloud - EMOTE_OMINOUS_CLOUD_PLAYER_TOUCH'), +(@YOGG_SARON,0,0,'BOW DOWN BEFORE THE GOD OF DEATH!',14,0,100,0,0,0,'Yogg-Saron - SAY_YOGG_SARON_SPAWN'), +(@YOGG_SARON,1,0,'MADNESS WILL CONSUME YOU!',14,0,100,0,0,15756,'Yogg-Saron - SAY_YOGG_SARON_MADNESS'), +(@YOGG_SARON,2,0,'Portals open into %s''s mind!',41,0,100,0,0,0,'Yogg-Saron - EMOTE_YOGG_SARON_MADNESS'), +(@YOGG_SARON,3,0,'Look upon the true face of death and know that your end comes soon!',14,0,100,0,0,15755,'Yogg-Saron - SAY_YOGG_SARON_PHASE_3'), +(@YOGG_SARON,4,0,'Eternal suffering awaits!',14,0,100,0,0,15758,'Yogg-Saron - SAY_YOGG_SARON_DEAFENING_ROAR'), +(@YOGG_SARON,5,0,'%s opens his mouth wide!',41,0,100,0,0,0,'Yogg-Saron - EMOTE_YOGG_SARON_DEAFENING_ROAR'), +(@YOGG_SARON,6,0,'Your fate is sealed. The end of days is finally upon you and ALL who inhabit this miserable little seedling. Uulwi ifis halahs gag erh''ongg w''ssh.',14,0,100,0,0,15761,'Yogg-Saron - SAY_YOGG_SARON_DEATH'), +(@YOGG_SARON,7,0,'%s prepares to unleash Empowering Shadows!',41,0,100,0,0,0,'Yogg-Saron - EMOTE_YOGG_SARON_EMPOWERING_SHADOWS'), +(@YOGG_SARON,8,0,'%s goes berserk, extinguishing all life!',41,0,100,0,0,0,'Yogg-Saron - EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE'), +(@VOICE_OF_YOGG_SARON,0,0,'Weak-minded fools!',15,0,100,0,0,15780,'Voice of Yogg-Saron - WHISPER_VOICE_PHASE_1_WIPE'), +(@VOICE_OF_YOGG_SARON,1,0,'Your will is no longer your own...',15,0,100,0,0,15759,'Voice of Yogg-Saron - WHISPER_VOICE_INSANE'), +(@VOICE_OF_YOGG_SARON,1,1,'Destroy them minion, your master commands it!',15,0,100,0,0,15760,'Voice of Yogg-Saron - WHISPER_VOICE_INSANE'), +(@BRAIN_OF_YOGG_SARON,0,0,'The illusion shatters and a path to the central chamber opens!',41,0,100,0,0,0,'Brain of Yogg-Saron - EMOTE_BRAIN_ILLUSION_SHATTERED'), +(@GARONA,0,0,'Bad news sire.',12,0,100,66,0,15538,'Garona'), +(@GARONA,1,0,'The clans are united under Blackhand in this assault. They will stand together until Stormwind has fallen.',12,0,100,274,0,15539,'Garona'), +(@GARONA,2,0,'Gul''dan is bringing up his warlocks by nightfall. Until then, the Blackrock clan will be trying to take the Eastern Wall.',12,0,100,1,0,15540,'Garona'), +(@GARONA,3,0,'The orc leaders agree with your assessment.',12,0,100,0,0,15541,'Garona'), +(@KING_LLANE,0,0,'We will hold until the reinforcements come. As long as men with stout hearts are manning the walls and throne Stormwind will hold.',12,0,100,274,0,15585,'King Llane'), +(@THE_LICH_KING,0,0,'Your resilience is admirable.',12,0,100,0,0,15598,'The Lich King'), +(@THE_LICH_KING,1,0,'I will break you as I broke him.',12,0,100,0,0,15599,'The Lich King'), +(@IMMOLATED_CHAMPION,0,0,'Arrrrrrgh!',14,0,100,0,0,15470,'Immolated Champion'), +(@IMMOLATED_CHAMPION,1,0,'I''m not afraid of you!',12,0,100,0,0,15471,'Immolated Champion'), +(@NELTHARION,0,0,'It is done... All have been given that which must be given. I now seal the Dragon Soul forever...',12,0,100,0,0,15631,'Neltharion'), +(@NELTHARION,1,0,'For it to be as it must, yes.',12,0,100,273,0,15632,'Neltharion'), +(@YSERA,0,0,'That terrible glow... should that be?',12,0,100,0,0,15702,'Ysera'), -- or sound 15784? they are the same +(@MALYGOS,0,0,'It is a weapon like no other. It must be like no other.',12,0,100,1,0,15610,'Malygos'), +(@YOGG_SARON_ILLUSIONS,0,0,'A thousand deaths... or one murder.',12,0,100,0,0,15762,'Yogg-Saron'), -- sound splited! 15763 - "or one murder". +(@YOGG_SARON_ILLUSIONS,1,0,'Your petty quarrels only make me stronger!',12,0,100,0,0,15764,'Yogg-Saron'), +(@YOGG_SARON_ILLUSIONS,2,0,'Yrr n''lyeth... shuul anagg!',12,0,100,0,0,15766,'Yogg-Saron'), +(@YOGG_SARON_ILLUSIONS,3,0,'He will learn... no king rules forever; only death is eternal!',12,0,100,0,0,15767,'Yogg-Saron'), +(@YOGG_SARON_ILLUSIONS,4,0,'His brood learned their lesson before too long. You will soon learn yours!',12,0,100,0,0,15765,'Yogg-Saron'), +(@FREYA_GOSSIP,0,0,'As you wish, $N.',12,0,100,0,0,0,'Freya (Observation Ring) - On Gossip Select'), +(@FREYA_GOSSIP,1,0,'Eonar, your servant calls for your blessing!',14,0,100,0,0,15535,'Freya (Observation Ring) - On Gossip Select'), +(@HODIR_GOSSIP,0,0,'As you wish, $N.',12,0,100,0,0,0,'Hodir (Observation Ring) - On Gossip Select'), +(@HODIR_GOSSIP,1,0,'The veil of winter will protect you, champions!',14,0,100,0,0,15559,'Hodir (Observation Ring) - On Gossip Select'), +(@THORIM_GOSSIP,0,0,'As you wish, $N.',12,0,100,0,0,0,'Thorim (Observation Ring) - On Gossip Select'), +(@THORIM_GOSSIP,1,0,'Golganneth, lend me your strengh! Grant my mortal allies the power of thunder!',14,0,100,0,0,15750,'Thorim (Observation Ring) - On Gossip Select'), +(@MIMIRON_GOSSIP,0,0,'As you wish, $N.',12,0,100,0,0,0,'Mimiron (Observation Ring) - On Gossip Select'), +(@MIMIRON_GOSSIP,1,0,'Combat matrix enhanced. Behold wonderous rapidity!',14,0,100,0,0,15630,'Mimiron (Observation Ring) - On Gossip Select'); + +DELETE FROM `npc_text` WHERE `ID` IN (14332,14333); +INSERT INTO `npc_text` (`ID`,`text0_0`,`text0_1`,`lang0`,`prob0`,`em0_0`,`em0_1`,`em0_2`,`em0_3`,`em0_4`,`em0_5`,`text1_0`,`text1_1`,`lang1`,`prob1`,`em1_0`,`em1_1`,`em1_2`,`em1_3`,`em1_4`,`em1_5`,`text2_0`,`text2_1`,`lang2`,`prob2`,`em2_0`,`em2_1`,`em2_2`,`em2_3`,`em2_4`,`em2_5`,`text3_0`,`text3_1`,`lang3`,`prob3`,`em3_0`,`em3_1`,`em3_2`,`em3_3`,`em3_4`,`em3_5`,`text4_0`,`text4_1`,`lang4`,`prob4`,`em4_0`,`em4_1`,`em4_2`,`em4_3`,`em4_4`,`em4_5`,`text5_0`,`text5_1`,`lang5`,`prob5`,`em5_0`,`em5_1`,`em5_2`,`em5_3`,`em5_4`,`em5_5`,`text6_0`,`text6_1`,`lang6`,`prob6`,`em6_0`,`em6_1`,`em6_2`,`em6_3`,`em6_4`,`em6_5`,`text7_0`,`text7_1`,`lang7`,`prob7`,`em7_0`,`em7_1`,`em7_2`,`em7_3`,`em7_4`,`em7_5`,`WDBVerified`) VALUES +(14332,'Mortals, I am indebted to you for freeing me from the terrible corruption that besets this place. Though I have not yet recovered fully, I can help you battle Yogg-Saron.$B$BI can grant you and your friends the Resilience of Nature, increasing your damage and increasing healing taken from spells and effects. In addition, I can conjure Sanity Wells that will allow you to recover your Sanity when your grip on reality falters.','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,1), +(14333,'Mortals, I am indebted to you for freeing me from the terrible corruption that besets this place. Though I have not yet recovered fully, I can help you battle Yogg-Saron.$B$BI can grant you and your friends the Fury of the Storm, increasing your damage and maximum health. Should you be faced with evil so malevolent that it cannot be destroyed, I can channel all my power into a final Titanic Storm that will destroy even Immortals.','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,1); + +DELETE FROM `gossip_menu` WHERE `entry` IN (10324,10333,10335,10336,10337); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(10324,14332), +(10333,14325), +(10335,14326), +(10337,14333), +(10336,14334); + +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (10324,10333,10335,10336,10337); +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(10324,0,0,'Lend us your aid, keeper. Together we will defeat Yogg-Saron.',1,1,10333,0,0,0,''), +(10333,0,0,'Yes.',1,1,0,0,0,0,''), -- not sure if this menu_id is shared for all keepers +(10335,0,0,'Lend us your aid, keeper. Together we will defeat Yogg-Saron.',1,1,10333,0,0,0,''), +(10337,0,0,'Lend us your aid, keeper. Together we will defeat Yogg-Saron.',1,1,10333,0,0,0,''), +(10336,0,0,'Lend us your aid, keeper. Together we will defeat Yogg-Saron.',1,1,10333,0,0,0,''); + +DELETE FROM `gameobject` WHERE `id` IN (@FLEE_TO_THE_SURFACE,@DRAGON_SOUL,@INSTANCE_PORTAL+0,@INSTANCE_PORTAL+1,@CHAIR+0,@CHAIR+1,@CHAIR+2,@CHAIR+3,@CHAIR+4,@CHAIR+5); +DELETE FROM `gameobject` WHERE `guid` BETWEEN @GO_GUID+0 AND @GO_GUID+11; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@GO_GUID+0,@FLEE_TO_THE_SURFACE,603,3,1,1999.761,-57.29888,243.5464,0,0,0,0,1,604800,0,0), +(@GO_GUID+1,@FLEE_TO_THE_SURFACE,603,3,1,1943.855,-25.59109,243.7952,0,0,0,0,1,604800,0,0), +(@GO_GUID+2,@FLEE_TO_THE_SURFACE,603,3,1,2000.26,5.519748,243.1853,0,0,0,0,1,604800,0,0), +(@GO_GUID+3,@DRAGON_SOUL,603,3,1,2104.028,-25.21278,242.6467,0,0,0,0,1,604800,0,0), +(@GO_GUID+4,@INSTANCE_PORTAL+0,603,2,1,2178.255,-24.15329,248.345,3.141593,0,0,-1,0,604800,0,0), +(@GO_GUID+5,@INSTANCE_PORTAL+1,603,1,1,2178.255,-24.15329,248.345,3.141593,0,0,-1,0,604800,0,0), +(@GO_GUID+6,@CHAIR+0,603,3,1,1954.696,91.8725,239.6242,5.989951,0,0,-0.1460924,0.9892709,604800,0,0), +(@GO_GUID+7,@CHAIR+1,603,3,1,1961.835,65.23161,239.6471,3.686116,0,0,-0.9631653,0.2689101,604800,0,0), +(@GO_GUID+8,@CHAIR+2,603,3,1,1886.634,72.21145,239.6242,1.713894,0,0,0.755847,0.6547483,604800,0,0), +(@GO_GUID+9,@CHAIR+3,603,3,1,1944.326,106.1581,239.6471,3.686116,0,0,-0.9631653,0.2689101,604800,0,0), +(@GO_GUID+10,@CHAIR+4,603,3,1,1899.228,45.58289,239.6471,1.417184,0,0,0.6507654,0.7592788,604800,0,0), +(@GO_GUID+11,@CHAIR+5,603,3,1,1923.472,28.16412,239.6471,2.289849,0,0,0.9106789,0.413115,604800,0,0); + +DELETE FROM `creature` WHERE `id` IN (@VOICE_OF_YOGG_SARON,@SARA,@BRAIN_OF_YOGG_SARON,@OMINOUS_CLOUD,@LAUGHING_SKULL,@THE_LICH_KING,@IMMOLATED_CHAMPION,@DEATHSWORN_ZEALOT,@GARONA,@KING_LLANE,@SUIT_OF_ARMOR,@NELTHARION,@MALYGOS,@ALEXSTRASZA,@YSERA,@OBSIDIAN_CONSORT,@AZURE_CONSORT,@EMERALD_CONSORT,@RUBY_CONSORT,@YOGG_SARON_ILLUSIONS,@TRIGGER,@SANITY_WELL); +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+7; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`) VALUES +(@GUID+0,@VOICE_OF_YOGG_SARON,603,3,1,0,0,1980.137,-25.74376,326.4671,0,604800,0,0,0,0,0,0,0,0), +(@GUID+1,@SARA,603,3,1,0,0,1980.43,-25.7708,329.3963,3.124139,604800,0,0,0,0,0,0,0,0), +(@GUID+2,@BRAIN_OF_YOGG_SARON,603,3,1,0,0,1981.622,-25.89063,261.6898,0.1047198,604800,0,0,0,0,0,0,0,0), +(@GUID+3,@SANITY_WELL,603,3,1,0,0,1899.941,0.330621,332.2957,0,604800,0,0,0,0,0,0,0,0), +(@GUID+4,@SANITY_WELL,603,3,1,0,0,1900.478,-51.23861,332.1303,0,604800,0,0,0,0,0,0,0,0), +(@GUID+5,@SANITY_WELL,603,3,1,0,0,1987.125,-91.27024,330.1858,0,604800,0,0,0,0,0,0,0,0), +(@GUID+6,@SANITY_WELL,603,3,1,0,0,1975.885,40.02165,331.0996,0,604800,0,0,0,0,0,0,0,0), +(@GUID+7,@SANITY_WELL,603,3,1,0,0,2042.559,-40.3667,329.2744,0,604800,0,0,0,0,0,0,0,0); +-- (@GUID+8,@TRIGGER,603,3,1,0,0,,604800,0,0,0,0,0,0,0,0), -- spawn was not found in sniffs (Icecrown vision) +-- (@GUID+9,@TRIGGER,603,3,1,0,0,1928.978,67.9108,242.4596,0,604800,0,0,0,0,0,0,0,0), +-- (@GUID+10,@TRIGGER,603,3,1,0,0,2113.323,-28.4375,242.8768,0,604800,0,0,0,0,0,0,0,0); + +DELETE FROM `creature_summon_groups` WHERE `summonerId` IN (@VOICE_OF_YOGG_SARON,@BRAIN_OF_YOGG_SARON); +INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES +(@VOICE_OF_YOGG_SARON,0,0,@OMINOUS_CLOUD,1993.538,-17.93403,324.9728,0,6,0), +(@VOICE_OF_YOGG_SARON,0,0,@OMINOUS_CLOUD,1968.158,-42.65644,324.9676,0,6,0), +(@VOICE_OF_YOGG_SARON,0,0,@OMINOUS_CLOUD,1952.901,-27.36388,325.6934,0,6,0), +(@VOICE_OF_YOGG_SARON,0,0,@OMINOUS_CLOUD,1991.673,-65.39913,328.3430,0,6,0), +(@VOICE_OF_YOGG_SARON,0,0,@OMINOUS_CLOUD,2018.573,4.088733,328.8741,0,6,0), +(@VOICE_OF_YOGG_SARON,0,0,@OMINOUS_CLOUD,2034.443,-25.29962,329.0554,0,6,0), +(@VOICE_OF_YOGG_SARON,0,1,@DESCEND_INTO_MADNESS,1964.596,-42.70562,325.0845,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,1,@DESCEND_INTO_MADNESS,1986.936,-46.21083,324.9798,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,1,@DESCEND_INTO_MADNESS,1989.495,-6.69694,325.0786,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,1,@DESCEND_INTO_MADNESS,1965.521,-8.089301,324.9476,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,2,@DESCEND_INTO_MADNESS,2000.841,-25.40006,325.192,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,2,@DESCEND_INTO_MADNESS,1960.216,-26.14138,325.0096,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,2,@DESCEND_INTO_MADNESS,1976.303,-47.82541,325.1116,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,2,@DESCEND_INTO_MADNESS,1997.688,-37.46083,325.039,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,2,@DESCEND_INTO_MADNESS,1998.07,-13.35666,325.1668,0,3,60000), +(@VOICE_OF_YOGG_SARON,0,2,@DESCEND_INTO_MADNESS,1976.992,-3.959093,325.1694,0,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@NELTHARION,2117.713,-25.27073,242.73,3.141593,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@MALYGOS,2107.963,-37.29351,242.73,2.024582,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@ALEXSTRASZA,2092.347,-25.26042,242.7301,6.265732,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@YSERA,2109.765,-14.37967,242.73,4.206244,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@OBSIDIAN_CONSORT,2146.88,-17.03125,239.8058,3.351032,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@OBSIDIAN_CONSORT,2146.24,-34.40451,239.8058,3.01942,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@AZURE_CONSORT,2113.33,-65.71007,239.8058,1.780236,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@AZURE_CONSORT,2139.83,-50.28646,239.8058,2.460914,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@EMERALD_CONSORT,2116.931,11.375,239.8058,4.415683,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@EMERALD_CONSORT,2136.641,-1.996528,239.8058,3.839724,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@RUBY_CONSORT,2069.479,-5.699653,239.8058,5.427974,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@RUBY_CONSORT,2069.298,-43.53168,239.8006,0.4712389,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@YOGG_SARON_ILLUSIONS,2109.695,-25.09549,222.3250,0,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2134.533,18.86881,239.8042,1.850049,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2063.156,27.95839,244.2707,5.288348,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2070.133,-73.0108,242.5237,1.308997,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2135.219,-41.44271,239.8027,5.846853,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2088.254,5.053657,239.8672,0.9948376,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2119.228,1.421441,239.8039,0,3,60000), +(@BRAIN_OF_YOGG_SARON,0,0,@LAUGHING_SKULL,2102.441,-75.04541,239.8635,1.658063,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@THE_LICH_KING,1908.557,-152.4427,240.0719,4.328416,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@IMMOLATED_CHAMPION,1903.599,-160.3576,240.1064,1.082104,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@TURNED_CHAMPION,1919.113,-160.9657,240.0659,2.700784,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1917.559,-135.7448,240.0730,4.188790,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1919.125,-140.9566,240.0730,3.979351,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1948.469,-136.2951,240.0707,3.438299,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1956.444,-138.4028,240.1078,3.368485,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1952.965,-130.5295,240.1347,3.804818,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1902.132,-111.3594,240.0698,4.852015,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1905.326,-104.7865,240.0523,4.764749,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1897.345,-106.6076,240.1444,4.939282,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@DEATHSWORN_ZEALOT,1912.129,-136.9340,240.0730,4.188790,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@YOGG_SARON_ILLUSIONS,1906.226,-155.8941,223.4727,0,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1863.897,-100.9364,240.073,5.235988,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1948.668,-152.4481,240.073,1.919862,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1932.213,-93.62798,240.073,4.852015,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1964.457,-149.5943,240.073,3.385939,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1992.463,-131.2119,240.073,3.455752,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1901.194,-90.4624,240.073,0.1396263,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1923.746,-164.5339,240.073,3.455752,3,60000), +(@BRAIN_OF_YOGG_SARON,0,1,@LAUGHING_SKULL,1905.937,-133.1651,240.073,5.77704,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@GARONA,1931.064,60.5659,241.5013,2.084251,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@KING_LLANE,1928.349,66.05186,242.4596,5.113815,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1956.503,72.19462,239.7495,3.281219,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1951.04,49.88875,239.7495,2.495821,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1931.14,38.46949,239.7495,1.710423,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1908.993,44.26659,239.7495,0.9250245,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1897.344,64.31419,239.7495,0.1396263,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1903.393,86.60285,239.7495,5.61996,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1923.342,98.01228,239.7495,4.834562,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@SUIT_OF_ARMOR,1945.442,92.17952,239.7495,4.049164,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@YOGG_SARON_ILLUSIONS,1929.160,67.75694,221.7322,0,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@LAUGHING_SKULL,1941.561,109.4812,239.7496,3.316126,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@LAUGHING_SKULL,1922.55,54.68001,241.1263,0.1919862,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@LAUGHING_SKULL,1893.146,44.24343,239.7496,0,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@LAUGHING_SKULL,1926.526,43.26215,239.7496,0.9948376,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@LAUGHING_SKULL,1904.3,73.70443,239.7496,4.276057,3,60000), +(@BRAIN_OF_YOGG_SARON,0,2,@LAUGHING_SKULL,1955.173,85.26153,239.7496,4.049164,3,60000); + +-- ScriptNames +UPDATE `creature_template` SET `ScriptName`='boss_voice_of_yogg_saron' WHERE `entry`=@VOICE_OF_YOGG_SARON; +UPDATE `creature_template` SET `ScriptName`='boss_yogg_saron' WHERE `entry`=@YOGG_SARON; +UPDATE `creature_template` SET `ScriptName`='boss_sara' WHERE `entry`=@SARA; +UPDATE `creature_template` SET `ScriptName`='boss_brain_of_yogg_saron' WHERE `entry`=@BRAIN_OF_YOGG_SARON; +UPDATE `creature_template` SET `ScriptName`='npc_ominous_cloud' WHERE `entry`=@OMINOUS_CLOUD; +UPDATE `creature_template` SET `ScriptName`='npc_guardian_of_yogg_saron' WHERE `entry`=@GUARDIAN_OF_YOGG_SARON; +UPDATE `creature_template` SET `ScriptName`='npc_immortal_guardian' WHERE `entry` IN (@IMMORTAL_GUARDIAN,@MARKED_IMMORTAL_GUARDIAN); +UPDATE `creature_template` SET `ScriptName`='npc_corruptor_tentacle' WHERE `entry`=@CORRUPTOR_TENTACLE; +UPDATE `creature_template` SET `ScriptName`='npc_constrictor_tentacle' WHERE `entry`=@CONSTRICTOR_TENTACLE; +UPDATE `creature_template` SET `ScriptName`='npc_crusher_tentacle' WHERE `entry`=@CRUSHER_TENTACLE; -- should have UNIT_FLAG_PACIFIED? but it breaks tentacle's AI +UPDATE `creature_template` SET `ScriptName`='npc_descend_into_madness' WHERE `entry`=@DESCEND_INTO_MADNESS; +UPDATE `creature_template` SET `ScriptName`='npc_influence_tentacle' WHERE `entry` IN (@SUIT_OF_ARMOR,@DEATHSWORN_ZEALOT,@RUBY_CONSORT,@EMERALD_CONSORT,@OBSIDIAN_CONSORT,@AZURE_CONSORT,@INFLUENCE_TENTACLE); +UPDATE `creature_template` SET `ScriptName`='npc_observation_ring_keeper' WHERE `entry` IN (@FREYA_GOSSIP,@HODIR_GOSSIP,@THORIM_GOSSIP,@MIMIRON_GOSSIP); +UPDATE `creature_template` SET `ScriptName`='npc_yogg_saron_keeper' WHERE `entry` IN (@FREYA_YS,@HODIR_YS,@THORIM_YS,@MIMIRON_YS); +UPDATE `creature_template` SET `ScriptName`='npc_laughing_skull' WHERE `entry`=@LAUGHING_SKULL; +UPDATE `creature_template` SET `ScriptName`='npc_yogg_saron_illusions' WHERE `entry`=@YOGG_SARON_ILLUSIONS; +UPDATE `creature_template` SET `ScriptName`='npc_garona' WHERE `entry`=@GARONA; +UPDATE `creature_template` SET `ScriptName`='npc_turned_champion' WHERE `entry`=@TURNED_CHAMPION; + +-- Difficulty entries +UPDATE `creature_template` SET `difficulty_entry_1`=@BRAIN_OF_YOGG_SARON_H WHERE `entry`=@BRAIN_OF_YOGG_SARON; +UPDATE `creature_template` SET `difficulty_entry_1`=@GUARDIAN_OF_YOGG_SARON_H WHERE `entry`=@GUARDIAN_OF_YOGG_SARON; +UPDATE `creature_template` SET `difficulty_entry_1`=@CORRUPTOR_TENTACLE_H WHERE `entry`=@CORRUPTOR_TENTACLE; +UPDATE `creature_template` SET `difficulty_entry_1`=@CONSTRICTOR_TENTACLE_H WHERE `entry`=@CONSTRICTOR_TENTACLE; +UPDATE `creature_template` SET `difficulty_entry_1`=@CRUSHER_TENTACLE_H WHERE `entry`=@CRUSHER_TENTACLE; +UPDATE `creature_template` SET `difficulty_entry_1`=@IMMORTAL_GUARDIAN_H WHERE `entry`=@IMMORTAL_GUARDIAN; +UPDATE `creature_template` SET `difficulty_entry_1`=@MARKED_IMMORTAL_GUARDIAN_H WHERE `entry`=@MARKED_IMMORTAL_GUARDIAN; +UPDATE `creature_template` SET `difficulty_entry_1`=@INFLUENCE_TENTACLE_H WHERE `entry`=@INFLUENCE_TENTACLE; + +-- creature_template updates +UPDATE `creature_template` SET `gossip_menu_id`=10324,`npcflag`=1 WHERE `entry`=@FREYA_GOSSIP; +UPDATE `creature_template` SET `gossip_menu_id`=10335,`npcflag`=1 WHERE `entry`=@HODIR_GOSSIP; +UPDATE `creature_template` SET `gossip_menu_id`=10337,`npcflag`=1 WHERE `entry`=@THORIM_GOSSIP; +UPDATE `creature_template` SET `gossip_menu_id`=10336,`npcflag`=1 WHERE `entry`=@MIMIRON_GOSSIP; +UPDATE `creature_template` SET `minlevel`=81,`maxlevel`=81,`unit_flags`=33554432 WHERE `entry`=@SANITY_WELL; +UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14,`minlevel`=80,`maxlevel`=80,`unit_flags`=33554432 WHERE `entry` IN (@VOICE_OF_YOGG_SARON,@DEATH_ORB); +UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14,`minlevel`=81,`maxlevel`=81,`unit_flags`=33554432 WHERE `entry` IN (@LAUGHING_SKULL,@DEATH_RAY); +UPDATE `creature_template` SET `faction_A`=16,`faction_H`=16,`minlevel`=82,`maxlevel`=82 WHERE `entry` IN (@CRUSHER_TENTACLE,@CRUSHER_TENTACLE_H); +UPDATE `creature_template` SET `exp`=2,`faction_A`=16,`faction_H`=16,`minlevel`=82,`maxlevel`=82 WHERE `entry` IN (@GUARDIAN_OF_YOGG_SARON,@GUARDIAN_OF_YOGG_SARON_H); +UPDATE `creature_template` SET `faction_A`=190,`faction_H`=190,`minlevel`=82,`maxlevel`=82 WHERE `entry` IN (@SUIT_OF_ARMOR,@DEATHSWORN_ZEALOT,@RUBY_CONSORT,@EMERALD_CONSORT,@OBSIDIAN_CONSORT,@AZURE_CONSORT,@INFLUENCE_TENTACLE,@INFLUENCE_TENTACLE_H); +UPDATE `creature_template` SET `faction_A`=16,`faction_H`=16 WHERE `entry` IN (@YOGG_SARON,@YOGG_SARON_H,@BRAIN_OF_YOGG_SARON,@BRAIN_OF_YOGG_SARON_H,@IMMORTAL_GUARDIAN,@IMMORTAL_GUARDIAN_H,@CONSTRICTOR_TENTACLE,@CONSTRICTOR_TENTACLE_H,@CORRUPTOR_TENTACLE,@CORRUPTOR_TENTACLE_H); +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (@SARA,@SARA_H,@BRAIN_OF_YOGG_SARON,@BRAIN_OF_YOGG_SARON_H,@VOICE_OF_YOGG_SARON,@DEATH_ORB); +UPDATE `creature_template` SET `minlevel`=60,`maxlevel`=60,`unit_flags`=33554688,`InhabitType`=4 WHERE `entry`=@YOGG_SARON_ILLUSIONS; +UPDATE `creature_template` SET `npcflag`=16777216 WHERE `entry`=@DESCEND_INTO_MADNESS; + +-- Creature immunities +UPDATE `creature_template` SET `mechanic_immune_mask`=617299839 WHERE `entry` IN (@YOGG_SARON,@YOGG_SARON_H,@BRAIN_OF_YOGG_SARON,@BRAIN_OF_YOGG_SARON_H); +UPDATE `creature_template` SET `mechanic_immune_mask`=13312063 WHERE `entry` IN (@CRUSHER_TENTACLE,@CRUSHER_TENTACLE_H,@CONSTRICTOR_TENTACLE,@CONSTRICTOR_TENTACLE_H,@CORRUPTOR_TENTACLE,@CORRUPTOR_TENTACLE_H,@SUIT_OF_ARMOR,@DEATHSWORN_ZEALOT,@RUBY_CONSORT,@EMERALD_CONSORT,@OBSIDIAN_CONSORT,@AZURE_CONSORT,@INFLUENCE_TENTACLE,@INFLUENCE_TENTACLE_H); + +UPDATE `creature_model_info` SET `bounding_radius`=0.31,`combat_reach`=33 WHERE `modelid`=28951; + +DELETE FROM `creature_template_addon` WHERE `entry` IN (@OMINOUS_CLOUD,@VOICE_OF_YOGG_SARON,@BRAIN_OF_YOGG_SARON,@BRAIN_OF_YOGG_SARON_H,@SARA,@SARA_H,@DEATH_ORB,@DEATHSWORN_ZEALOT); +INSERT INTO `creature_template_addon`(`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(@OMINOUS_CLOUD,0,0,0,0,0,'63029'), +(@VOICE_OF_YOGG_SARON,0,0,50331648,0,0,''), +(@BRAIN_OF_YOGG_SARON,0,0,33554432,0,0,''), +(@BRAIN_OF_YOGG_SARON_H,0,0,33554432,0,0,''), +(@SARA,0,0,50331648,0,0,''), +(@SARA_H,0,0,50331648,0,0,''), +(@DEATH_ORB,0,0,50331648,0,0,''), +(@DEATHSWORN_ZEALOT,0,0,8,0,0,''); + +DELETE FROM `spell_dbc` WHERE `Id`=63029; +INSERT INTO `spell_dbc` (`Id`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`AttributesEx6`,`AttributesEx7`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectMiscValueB1`,`EffectMiscValueB2`,`EffectMiscValueB3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`EffectSpellClassMaskA1`,`EffectSpellClassMaskA2`,`EffectSpellClassMaskA3`,`EffectSpellClassMaskB1`,`EffectSpellClassMaskB2`,`EffectSpellClassMaskB3`,`EffectSpellClassMaskC1`,`EffectSpellClassMaskC2`,`EffectSpellClassMaskC3`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`SpellFamilyFlags3`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`DmgMultiplier3`,`AreaGroupId`,`SchoolMask`,`Comment`) VALUES +(63029,0,0,0x00000100,0x10000000,0,0,0,0,0,0,0,0,0,1,0,0,101,0,0,70,70,21,1,0,-1,0,0,6,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,23,0,0,1000,0,0,0,0,0,0,0,0,0,0,0,63030,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'Ominous Cloud - SPELL_BOIL_OMINOUSLY_PERIODIC'); + +DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (63795,62714,64468,64159,64125); +INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`,`spellid2`,`spellid3`) VALUES +(63795,63795,65301,0,0), +(62714,62714,65209,0,0), +(64468,64468,64486,0,0), +(64159,64159,64160,0,0), +(64125,64125,64126,0,0); + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (62650,62670,62671,62702,63030,63050,63120,63305,63802,63830,63881,63984,64125,64174,64465,64466,64467,64132,64131,64161,63744,63745,63747,65206,64172,64059,64069,65238,63882,63993,64010,64013,64012,64148,64164,64168,64184,63795,63803,65301,64555); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(62650,'spell_yogg_saron_keeper_aura'), +(62670,'spell_yogg_saron_keeper_aura'), +(62671,'spell_yogg_saron_keeper_aura'), +(62702,'spell_yogg_saron_keeper_aura'), +(63030,'spell_yogg_saron_boil_ominously'), +(63050,'spell_yogg_saron_sanity'), +(63120,'spell_yogg_saron_insane'), +(63305,'spell_yogg_saron_grim_reprisal'), +(63802,'spell_yogg_saron_brain_link'), +(63803,'spell_yogg_saron_brain_link_damage'), +(63795,'spell_yogg_saron_psychosis'), +(65301,'spell_yogg_saron_psychosis'), +(63830,'spell_yogg_saron_malady_of_the_mind'), +(63881,'spell_yogg_saron_malady_of_the_mind'), +(63984,'spell_yogg_saron_hate_to_zero'), +(64125,'spell_yogg_saron_squeeze'), +(64174,'spell_yogg_saron_hodirs_protective_gaze'), +(64465,'spell_yogg_saron_shadow_beacon'), +(64466,'spell_yogg_saron_empowering_shadows_range_check'), +(64467,'spell_yogg_saron_empowering_shadows_missile'), +(64132,'spell_yogg_saron_constrictor_tentacle'), +(64131,'spell_yogg_saron_lunge'), +(64161,'spell_yogg_saron_empowered'), +(63744,'spell_yogg_saron_target_selectors'), +(63745,'spell_yogg_saron_target_selectors'), +(63747,'spell_yogg_saron_target_selectors'), +(65206,'spell_yogg_saron_target_selectors'), +(64172,'spell_yogg_saron_titanic_storm'), +(64059,'spell_yogg_saron_induce_madness'), +(64069,'spell_yogg_saron_match_health'), +(65238,'spell_yogg_saron_shattered_illusion'), +(63882,'spell_yogg_saron_death_ray_warning_visual'), +(63993,'spell_yogg_saron_cancel_illusion_room_aura'), +(64010,'spell_yogg_saron_nondescript'), +(64013,'spell_yogg_saron_nondescript'), +(64012,'spell_yogg_saron_revealed_tentacle'), +(64148,'spell_yogg_saron_diminsh_power'), +(64164,'spell_yogg_saron_lunatic_gaze'), +(64168,'spell_yogg_saron_lunatic_gaze'), +(64184,'spell_yogg_saron_in_the_maws_of_the_old_god'), +(64555,'spell_yogg_saron_insane_periodic'); + +DELETE FROM `spell_target_position` WHERE `id` IN (63989,63997,63998,63992); +INSERT INTO `spell_target_position` (`id`,`target_map`,`target_position_x`,`target_position_y`,`target_position_z`,`target_orientation`) VALUES +(63989,603,1954.14,21.522,239.718,2.09439), +(63997,603,2043.12,-25.6981,239.721,0), +(63998,603,1949.13,-80.6744,239.99,4.18879), +(63992,603,1970.61,-25.5988,324.55,3.10346); + +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=@DESCEND_INTO_MADNESS; +INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`,`user_type`) VALUES +(@DESCEND_INTO_MADNESS,63989,2,0), +(@DESCEND_INTO_MADNESS,63997,2,0), +(@DESCEND_INTO_MADNESS,63998,2,0); + +DELETE FROM `disables` WHERE `SourceType`=4 AND `entry` IN (10187,10189,10293,10294,10388,10409,10410,10412,10414,10415,10416,10417); + +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10185,10187,10189,10296,10321,10322,10323,10324,10325,10326,10388,10409,10410,10412,10414,10415,10416,10417); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`,`ScriptName`) VALUES +(10185,18,0,0,''), +(10185,12,0,0,''), +(10187,1,@SARA,0,''), +(10187,7,65157,0,''), +(10187,12,0,0,''), +(10189,1,@SARA,0,''), +(10189,7,65157,0,''), +(10189,12,1,0,''), +(10296,18,0,0,''), +(10296,12,1,0,''), +(10321,18,0,0,''), +(10321,12,1,0,''), +(10322,18,0,0,''), +(10322,12,1,0,''), +(10323,18,0,0,''), +(10323,12,1,0,''), +(10324,18,0,0,''), +(10324,12,0,0,''), +(10325,18,0,0,''), +(10325,12,0,0,''), +(10326,18,0,0,''), +(10326,12,0,0,''), +(10388,18,0,0,''), +(10388,12,0,0,''), +(10409,18,0,0,''), +(10409,12,0,0,''), +(10410,18,0,0,''), +(10410,12,0,0,''), +(10412,18,0,0,''), +(10412,12,0,0,''), +(10414,18,0,0,''), +(10414,12,1,0,''), +(10415,18,0,0,''), +(10415,12,1,0,''), +(10416,18,0,0,''), +(10416,12,1,0,''), +(10417,18,0,0,''), +(10417,12,1,0,''); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (62714,65209,62978,63037,63882,63884,63886,64059,64063,64069,64172,64173,64184,65238,63744,63745,63747,64465,64466,64555,65719,65206); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry`=64184; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=18 AND `SourceGroup`=@DESCEND_INTO_MADNESS; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(18,@DESCEND_INTO_MADNESS,63997,0,0,13,0,38,0,0,0,0,0,'','Required instance data for spellclick'), +(18,@DESCEND_INTO_MADNESS,63998,0,0,13,0,38,1,0,0,0,0,'','Required instance data for spellclick'), +(18,@DESCEND_INTO_MADNESS,63989,0,0,13,0,38,2,0,0,0,0,'','Required instance data for spellclick'), +(13,2,62714,0,0,31,0,3,@GUARDIAN_OF_YOGG_SARON,0,0,0,0,'','Shadow Nova'), +(13,2,65209,0,0,31,0,3,@GUARDIAN_OF_YOGG_SARON,0,0,0,0,'','Shadow Nova'), +(13,1,62978,0,0,31,0,3,@OMINOUS_CLOUD,0,0,0,0,'','Summon Guardian'), +(13,1,63037,0,0,31,0,3,@IMMOLATED_CHAMPION,0,0,0,0,'','Deathgrasp'), +(13,1,63744,0,0,31,0,3,@GUARDIAN_OF_YOGG_SARON,0,0,0,0,'','Sara''s Anger'), +(13,1,63745,0,0,31,0,4,0,0,0,0,0,'','Sara''s Blessing'), +(13,1,63747,0,0,31,0,4,0,0,0,0,0,'','Sara''s Fervor'), +(13,1,63882,0,0,31,0,3,@DEATH_ORB,0,0,0,0,'','Death Ray Warning Visual'), +(13,1,63884,0,0,1,0,63120,0,0,1,0,0,'','Death Ray damage'), +(13,1,63884,0,0,1,0,63830,1,0,1,0,0,'','Death Ray damage'), +(13,1,63884,0,0,1,0,63881,1,0,1,0,0,'','Death Ray damage'), +(13,1,63886,0,0,31,0,3,@DEATH_ORB,0,0,0,0,'','Death Ray Damage Visual'), +(13,1,64059,0,0,31,0,4,0,0,0,0,0,'','Induce Madness'), +(13,1,64059,0,0,1,0,63988,0,0,0,0,0,'','Induce Madness'), +(13,1,64063,0,0,31,0,3,@KING_LLANE,0,0,0,0,'','Assassinate'), +(13,1,64069,0,0,31,0,3,@YOGG_SARON,0,0,0,0,'','Match Health'), +(13,1,64172,0,0,31,0,3,@IMMORTAL_GUARDIAN,0,0,0,0,'','Titanic Storm'), +(13,1,64172,0,0,1,0,64162,0,0,0,0,0,'','Titanic Storm'), +(13,1,64172,0,1,31,0,3,@MARKED_IMMORTAL_GUARDIAN,0,0,0,0,'','Titanic Storm'), +(13,1,64172,0,1,1,0,64162,0,0,0,0,0,'','Titanic Storm'), +(13,1,64173,0,0,31,0,3,@SARA,0,0,0,0,'','Shattered Illusion'), +(13,1,64173,0,1,31,0,3,@YOGG_SARON,0,0,0,0,'','Shattered Illusion'), +(13,1,64173,0,2,31,0,3,@CRUSHER_TENTACLE,0,0,0,0,'','Shattered Illusion'), +(13,1,64173,0,3,31,0,3,@CONSTRICTOR_TENTACLE,0,0,0,0,'','Shattered Illusion'), +(13,1,64173,0,4,31,0,3,@CORRUPTOR_TENTACLE,0,0,0,0,'','Shattered Illusion'), +(13,1,64184,0,0,31,0,3,@YOGG_SARON,0,0,0,0,'','In the Maws of the Old God'), +(13,1,65238,0,0,31,0,3,@SARA,0,0,0,0,'','Shattered Illusion remove'), +(13,1,65238,0,1,31,0,3,@YOGG_SARON,0,0,0,0,'','Shattered Illusion remove'), +(13,1,65238,0,2,31,0,3,@CRUSHER_TENTACLE,0,0,0,0,'','Shattered Illusion remove'), +(13,1,65238,0,3,31,0,3,@CONSTRICTOR_TENTACLE,0,0,0,0,'','Shattered Illusion remove'), +(13,1,65238,0,4,31,0,3,@CORRUPTOR_TENTACLE,0,0,0,0,'','Shattered Illusion remove'), +(13,1,64465,0,0,31,0,3,@IMMORTAL_GUARDIAN,0,0,0,0,'','Shadow Beacon'), +(13,1,64465,0,0,1,0,64497,0,0,1,0,0,'','Shadow Beacon'), +(13,1,64466,0,0,31,0,3,@YOGG_SARON,0,0,0,0,'','Empowering Shadows'), +(13,1,64555,0,0,1,0,63050,0,0,1,0,0,'','Insane Periodic'), +(13,1,65719,0,0,31,0,3,@SARA,0,0,0,0,'','Shadow Nova'), +(13,1,65206,0,0,31,0,3,@CORRUPTOR_TENTACLE,0,0,0,0,'','Destabilization Matrix'), +(13,1,65206,0,1,31,0,3,@CRUSHER_TENTACLE,0,0,0,0,'','Destabilization Matrix'); + +-- Loot +UPDATE `creature_loot_template` SET `lootmode`=32-`lootmode` WHERE `entry` IN (@YOGG_SARON,@YOGG_SARON_H); +UPDATE `creature_loot_template` SET `ChanceOrQuestChance`=-100,`lootmode`=32 WHERE `entry`=@YOGG_SARON_H AND `item`=45897; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f8add7e8691..3872f9154b9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -7773,6 +7773,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg Aura* charge = GetAura(50241); if (charge && charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL)) RemoveAurasDueToSpell(50240); + break; } } break; diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index edabc7b4284..5f5024729ca 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -445,6 +445,7 @@ void AddSC_ulduar_teleporter(); void AddSC_boss_mimiron(); void AddSC_boss_hodir(); void AddSC_boss_freya(); +void AddSC_boss_yogg_saron(); void AddSC_boss_algalon_the_observer(); void AddSC_instance_ulduar(); void AddSC_boss_keleseth(); //Utgarde Keep @@ -1184,6 +1185,7 @@ void AddNorthrendScripts() AddSC_boss_mimiron(); AddSC_boss_hodir(); AddSC_boss_freya(); + AddSC_boss_yogg_saron(); AddSC_boss_algalon_the_observer(); AddSC_instance_ulduar(); AddSC_boss_keleseth(); //Utgarde Keep diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8f887cebe38..dfec24f3996 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2633,7 +2633,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA { // for delayed spells ignore negative spells (after duel end) for friendly targets /// @todo this cause soul transfer bugged - if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->IsPositive()) + // 63881 - Malady of the Mind jump spell (Yogg-Saron) + if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->IsPositive() && m_spellInfo->Id != 63881) return SPELL_MISS_EVADE; // assisting case, healing and resurrection diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 66f7121adf3..026c61d4965 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -84,6 +84,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, // ToC Icehowl Arctic Breath else if (spellproto->SpellVisual[0] == 14153) return DIMINISHING_NONE; + // Black Plague + else if (spellproto->Id == 64155) + return DIMINISHING_NONE; break; } // Event spells @@ -3327,6 +3330,14 @@ void SpellMgr::LoadDbcDataCorrections() // that will be clear if we get more spells with problem like this spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY; break; + case 61791: // Ride Vehicle (Yogg-Saron) + // TODO: remove this when basepoints of all Ride Vehicle auras are calculated correctly + spellInfo->EffectBasePoints[0] = 1; + break; + case 64468: // Empowering Shadows (Yogg-Saron) + case 64486: // Empowering Shadows (Yogg-Saron) + spellInfo->MaxAffectedTargets = 3; // same for both modes? + break; case 62301: // Cosmic Smash (Algalon the Observer) spellInfo->MaxAffectedTargets = 1; break; diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index 1da1e4ab178..674c35836a2 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -26,7 +26,7 @@ set(scripts_STAT_SRCS Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp Northrend/Ulduar/Ulduar/instance_ulduar.cpp Northrend/Ulduar/Ulduar/boss_auriaya.cpp - Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp + Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp Northrend/Ulduar/Ulduar/boss_hodir.cpp Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp new file mode 100644 index 00000000000..57f50e7ad39 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -0,0 +1,3227 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "PassiveAI.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "MoveSplineInit.h" +#include "CreatureTextMgr.h" +#include "ulduar.h" + +enum Yells +{ + // Sara + SAY_SARA_ULDUAR_SCREAM_1 = 0, // screams randomly in a whole instance, unused on retail + SAY_SARA_ULDUAR_SCREAM_2 = 1, // screams randomly in a whole instance, unused on retail + SAY_SARA_AGGRO = 2, + SAY_SARA_FERVOR_HIT = 3, + SAY_SARA_BLESSING_HIT = 4, + SAY_SARA_KILL = 5, + SAY_SARA_TRANSFORM_1 = 6, + SAY_SARA_TRANSFORM_2 = 7, + SAY_SARA_TRANSFORM_3 = 8, + SAY_SARA_TRANSFORM_4 = 9, + SAY_SARA_DEATH_RAY = 10, + SAY_SARA_PSYCHOSIS_HIT = 11, + + // Yogg-Saron + SAY_YOGG_SARON_SPAWN = 0, + SAY_YOGG_SARON_MADNESS = 1, + EMOTE_YOGG_SARON_MADNESS = 2, + SAY_YOGG_SARON_PHASE_3 = 3, + SAY_YOGG_SARON_DEAFENING_ROAR = 4, + EMOTE_YOGG_SARON_DEAFENING_ROAR = 5, + SAY_YOGG_SARON_DEATH = 6, + EMOTE_YOGG_SARON_EMPOWERING_SHADOWS = 7, + EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE = 8, + + // Voice of Yogg-Saron + WHISPER_VOICE_PHASE_1_WIPE = 0, + WHISPER_VOICE_INSANE = 1, + + // Brain of Yogg-Saron + EMOTE_BRAIN_ILLUSION_SHATTERED = 0, + + // Ominous Cloud + EMOTE_OMINOUS_CLOUD_PLAYER_TOUCH = 0, + + // Keepers + SAY_KEEPER_CHOSEN_1 = 0, + SAY_KEEPER_CHOSEN_2 = 1, + + // Yogg-Saron illusions + SAY_STORMWIND_ROLEPLAY_4 = 0, + SAY_STORMWIND_ROLEPLAY_7 = 1, + SAY_ICECROWN_ROLEPLAY_5 = 2, + SAY_ICECROWN_ROLEPLAY_6 = 3, + SAY_CHAMBER_ROLEPLAY_5 = 4, + + // Neltharion + SAY_CHAMBER_ROLEPLAY_1 = 0, + SAY_CHAMBER_ROLEPLAY_3 = 1, + + // Ysera + SAY_CHAMBER_ROLEPLAY_2 = 0, + + // Malygos + SAY_CHAMBER_ROLEPLAY_4 = 0, + + // Immolated Champion + SAY_ICECROWN_ROLEPLAY_1 = 0, + SAY_ICECROWN_ROLEPLAY_3 = 1, + + // The Lich King + SAY_ICECROWN_ROLEPLAY_2 = 0, + SAY_ICECROWN_ROLEPLAY_4 = 1, + + // Garona + SAY_STORMWIND_ROLEPLAY_1 = 0, + SAY_STORMWIND_ROLEPLAY_2 = 1, + SAY_STORMWIND_ROLEPLAY_3 = 2, + SAY_STORMWIND_ROLEPLAY_6 = 3, + + // King Llane + SAY_STORMWIND_ROLEPLAY_5 = 0, +}; + +enum Spells +{ + // Voice of Yogg-Saron + SPELL_SUMMON_GUARDIAN_2 = 62978, + SPELL_SANITY_PERIODIC = 63786, + SPELL_SANITY = 63050, + SPELL_INSANE_PERIODIC = 64554, + SPELL_INSANE = 63120, + //SPELL_CLEAR_INSANE = 63122, // when it should be casted? + SPELL_CONSTRICTOR_TENTACLE = 64132, + SPELL_CRUSHER_TENTACLE_SUMMON = 64139, + SPELL_CORRUPTOR_TENTACLE_SUMMON = 64143, + SPELL_IMMORTAL_GUARDIAN = 64158, + + // Sara + SPELL_SARAS_FERVOR = 63138, + SPELL_SARAS_FERVOR_TARGET_SELECTOR = 63747, + SPELL_SARAS_BLESSING = 63134, + SPELL_SARAS_BLESSING_TARGET_SELECTOR = 63745, + SPELL_SARAS_ANGER = 63147, + SPELL_SARAS_ANGER_TARGET_SELECTOR = 63744, + SPELL_FULL_HEAL = 43978, + SPELL_PHASE_2_TRANSFORM = 65157, + SPELL_SHADOWY_BARRIER_SARA = 64775, + SPELL_RIDE_YOGG_SARON_VEHICLE = 61791, + SPELL_PSYCHOSIS = 63795, + SPELL_MALADY_OF_THE_MIND = 63830, + SPELL_BRAIN_LINK = 63802, + SPELL_BRAIN_LINK_DAMAGE = 63803, // red beam + SPELL_BRAIN_LINK_NO_DAMAGE = 63804, // yellow beam + SPELL_DEATH_RAY = 63891, + + // Ominous Cloud + SPELL_OMINOUS_CLOUD_VISUAL = 63084, + SPELL_SUMMON_GUARDIAN_1 = 63031, + + // Guardian of Yogg-Saron + SPELL_DARK_VOLLEY = 63038, + SPELL_SHADOW_NOVA = 62714, + SPELL_SHADOW_NOVA_2 = 65719, + + // Yogg-Saron + SPELL_EXTINGUISH_ALL_LIFE = 64166, + SPELL_SHADOWY_BARRIER_YOGG = 63894, + SPELL_KNOCK_AWAY = 64022, + SPELL_PHASE_3_TRANSFORM = 63895, + SPELL_DEAFENING_ROAR = 64189, + SPELL_LUNATIC_GAZE = 64163, + SPELL_LUNATIC_GAZE_DAMAGE = 64164, + SPELL_SHADOW_BEACON = 64465, + + // Brain of Yogg-Saron + SPELL_MATCH_HEALTH = 64066, + SPELL_MATCH_HEALTH_2 = 64069, + SPELL_INDUCE_MADNESS = 64059, + SPELL_BRAIN_HURT_VISUAL = 64361, + SPELL_SHATTERED_ILLUSION = 64173, + SPELL_SHATTERED_ILLUSION_REMOVE = 65238, + + // Tentacles + SPELL_ERUPT = 64144, + SPELL_TENTACLE_VOID_ZONE = 64017, // used by Corruptor Tentacle and Crusher Tentacle only + + // Crusher Tentacle + SPELL_DIMINISH_POWER = 64145, + SPELL_DIMINSH_POWER = 64148, + SPELL_FOCUSED_ANGER = 57688, + SPELL_CRUSH = 64146, + //SPELL_CRUSH_2 = 65201, // triggered by SPELL_CRUSH, basepoints of SPELL_MALADY_OF_THE_MIND + + // Constrictor Tentacle + SPELL_TENTACLE_VOID_ZONE_2 = 64384, + SPELL_LUNGE = 64131, + + // Corruptor Tentacle + SPELL_APATHY = 64156, + SPELL_BLACK_PLAGUE = 64153, + SPELL_CURSE_OF_DOOM = 64157, + SPELL_DRAINING_POISON = 64152, + + // Immortal Guardian + SPELL_EMPOWERING_SHADOWS = 64468, + SPELL_EMPOWERED = 64161, + SPELL_EMPOWERED_BUFF = 65294, + SPELL_WEAKENED = 64162, + SPELL_DRAIN_LIFE = 64159, + SPELL_RECENTLY_SPAWNED = 64497, + SPELL_SIMPLE_TELEPORT = 64195, + + // Keepers at Observation Ring + SPELL_TELEPORT = 62940, + + // Keepers + SPELL_SIMPLE_TELEPORT_KEEPERS = 12980, + SPELL_KEEPER_ACTIVE = 62647, + + // Mimiron + SPELL_SPEED_OF_INVENTION = 62671, + SPELL_DESTABILIZATION_MATRIX = 65206, + + // Freya + SPELL_RESILIENCE_OF_NATURE = 62670, + SPELL_SANITY_WELL_SUMMON = 64170, + + // Sanity Well + SPELL_SANITY_WELL_VISUAL = 63288, + SPELL_SANITY_WELL = 64169, + + // Thorim + SPELL_FURY_OF_THE_STORM = 62702, + SPELL_TITANIC_STORM = 64171, + + // Hodir + SPELL_FORTITUDE_OF_FROST = 62650, + SPELL_HODIRS_PROTECTIVE_GAZE = 64174, + SPELL_FLASH_FREEZE_VISUAL = 64176, + + // Death Orb + SPELL_DEATH_RAY_ORIGIN_VISUAL = 63893, + + // Death Ray + SPELL_DEATH_RAY_WARNING_VISUAL = 63882, + SPELL_DEATH_RAY_PERIODIC = 63883, + SPELL_DEATH_RAY_DAMAGE_VISUAL = 63886, + + // Laughing Skull + SPELL_LUNATIC_GAZE_SKULL = 64167, + + // Descend Into Madness + SPELL_TELEPORT_PORTAL_VISUAL = 64416, + + // Illusions + SPELL_GRIM_REPRISAL = 63305, + SPELL_GRIM_REPRISAL_DAMAGE = 64039, + + // Suit of Armor + SPELL_NONDESCRIPT_1 = 64013, + + // Dragon Consorts & Deathsworn Zealot + SPELL_NONDESCRIPT_2 = 64010, + + // Garona + SPELL_ASSASSINATE = 64063, + + // King Llane + SPELL_PERMANENT_FEIGN_DEATH = 29266, + + // The Lich King + SPELL_DEATHGRASP = 63037, + + // Turned Champion + SPELL_VERTEX_COLOR_BLACK = 39662, + + // Player self cast spells + SPELL_MALADY_OF_THE_MIND_JUMP = 63881, + SPELL_ILLUSION_ROOM = 63988, + SPELL_HATE_TO_ZERO = 63984, + SPELL_TELEPORT_BACK_TO_MAIN_ROOM = 63992, + SPELL_INSANE_VISUAL = 64464, + SPELL_CONSTRICTOR_TENTACLE_SUMMON = 64133, + SPELL_SQUEEZE = 64125, + SPELL_FLASH_FREEZE = 64175, + SPELL_LOW_SANITY_SCREEN_EFFECT = 63752, + + SPELL_IN_THE_MAWS_OF_THE_OLD_GOD = 64184, +}; + +enum Phases +{ + PHASE_ONE = 1, + PHASE_TRANSFORM = 2, + PHASE_TWO = 3, + PHASE_THREE = 4, +}; + +enum Events +{ + // Voice of Yogg-Saron + EVENT_LOCK_DOOR = 1, + EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON = 2, + EVENT_SUMMON_CORRUPTOR_TENTACLE = 3, + EVENT_SUMMON_CONSTRICTOR_TENTACLE = 4, + EVENT_SUMMON_CRUSHER_TENTACLE = 5, + EVENT_ILLUSION = 6, + EVENT_SUMMON_IMMORTAL_GUARDIAN = 7, + EVENT_EXTINGUISH_ALL_LIFE = 8, // handled by Voice, timer starts at the beginning of the fight (Yogg-Saron is not spawned at this moment) + + // Sara + EVENT_SARAS_FERVOR = 9, + EVENT_SARAS_BLESSING = 10, + EVENT_SARAS_ANGER = 11, + EVENT_TRANSFORM_1 = 12, + EVENT_TRANSFORM_2 = 13, + EVENT_TRANSFORM_3 = 14, + EVENT_TRANSFORM_4 = 15, + EVENT_PSYCHOSIS = 16, + EVENT_MALADY_OF_THE_MIND = 17, + EVENT_BRAIN_LINK = 18, + EVENT_DEATH_RAY = 19, + + // Tentacles + EVENT_DIMINISH_POWER = 20, + EVENT_CAST_RANDOM_SPELL = 21, + + // Yogg-Saron + EVENT_YELL_BOW_DOWN = 22, + EVENT_SHADOW_BEACON = 23, + EVENT_LUNATIC_GAZE = 24, + EVENT_DEAFENING_ROAR = 25, // only on 25-man with 0-3 keepers active (Hard Mode) + + // Guardian of Yogg-Saron + EVENT_DARK_VOLLEY = 26, + + // Immortal Guardian + EVENT_DRAIN_LIFE = 27, + + // Keepers + EVENT_DESTABILIZATION_MATRIX = 28, + EVENT_HODIRS_PROTECTIVE_GAZE = 29, + + // Chamber Illusion + EVENT_CHAMBER_ROLEPLAY_1 = 30, + EVENT_CHAMBER_ROLEPLAY_2 = 31, + EVENT_CHAMBER_ROLEPLAY_3 = 32, + EVENT_CHAMBER_ROLEPLAY_4 = 33, + EVENT_CHAMBER_ROLEPLAY_5 = 34, + + // Icecrown Illusion + EVENT_ICECROWN_ROLEPLAY_1 = 35, + EVENT_ICECROWN_ROLEPLAY_2 = 36, + EVENT_ICECROWN_ROLEPLAY_3 = 37, + EVENT_ICECROWN_ROLEPLAY_4 = 38, + EVENT_ICECROWN_ROLEPLAY_5 = 39, + EVENT_ICECROWN_ROLEPLAY_6 = 40, + + // Stormwind Illusion + EVENT_STORMWIND_ROLEPLAY_1 = 41, + EVENT_STORMWIND_ROLEPLAY_2 = 42, + EVENT_STORMWIND_ROLEPLAY_3 = 43, + EVENT_STORMWIND_ROLEPLAY_4 = 44, + EVENT_STORMWIND_ROLEPLAY_5 = 45, + EVENT_STORMWIND_ROLEPLAY_6 = 46, + EVENT_STORMWIND_ROLEPLAY_7 = 47, +}; + +enum EventGroups +{ + EVENT_GROUP_SUMMON_TENTACLES = 1, +}; + +enum Actions +{ + ACTION_PHASE_TRANSFORM = 0, + ACTION_PHASE_TWO = 1, + ACTION_PHASE_THREE = 2, + ACTION_INDUCE_MADNESS = 3, + ACTION_SANITY_WELLS = 4, + ACTION_FLASH_FREEZE = 5, + ACTION_TENTACLE_KILLED = 6, + ACTION_START_ROLEPLAY = 8, + ACTION_TOGGLE_SHATTERED_ILLUSION = 9, +}; + +enum CreatureGroups +{ + CREATURE_GROUP_CLOUDS = 0, + CREATURE_GROUP_PORTALS_10 = 1, + CREATURE_GROUP_PORTALS_25 = 2, +}; + +Position const YoggSaronSpawnPos = {1980.43f, -25.7708f, 324.9724f, 3.141593f}; +Position const ObservationRingKeepersPos[4] = +{ + {1945.682f, 33.34201f, 411.4408f, 5.270895f}, // Freya + {1945.761f, -81.52171f, 411.4407f, 1.029744f}, // Hodir + {2028.822f, -65.73573f, 411.4426f, 2.460914f}, // Thorim + {2028.766f, 17.42014f, 411.4446f, 3.857178f}, // Mimiron +}; +Position const YSKeepersPos[4] = +{ + {2036.873f, 25.42513f, 338.4984f, 3.909538f}, // Freya + {1939.045f, -90.87457f, 338.5426f, 0.994837f}, // Hodir + {1939.148f, 42.49035f, 338.5427f, 5.235988f}, // Thorim + {2036.658f, -73.58822f, 338.4985f, 2.460914f}, // Mimiron +}; +Position const IllusionsMiscPos[2] = +{ + {1928.793f, 65.03109f, 242.3763f, 0.0f}, // Garona end position + {1912.324f, -155.7967f, 239.9896f, 0.0f}, // Saurfang end position +}; + +enum MiscData +{ + ACHIEV_TIMED_START_EVENT = 21001, + SOUND_LUNATIC_GAZE = 15757, +}; + +class StartAttackEvent : public BasicEvent +{ + public: + StartAttackEvent(Creature* summoner, Creature* owner) + : _summoner(summoner), _owner(owner) + { + } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) + { + _owner->SetReactState(REACT_AGGRESSIVE); + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f)) + _owner->AI()->AttackStart(target); + return true; + } + + private: + Creature* _summoner; + Creature* _owner; +}; + +class boss_voice_of_yogg_saron : public CreatureScript +{ + public: + boss_voice_of_yogg_saron() : CreatureScript("boss_voice_of_yogg_saron") { } + + struct boss_voice_of_yogg_saronAI : public BossAI + { + boss_voice_of_yogg_saronAI(Creature* creature) : BossAI(creature, BOSS_YOGG_SARON) + { + SetCombatMovement(false); + } + + void MoveInLineOfSight(Unit* who) + { + // TODO: MoveInLineOfSight doesn't work for such a big distance + if (who->GetTypeId() == TYPEID_PLAYER && me->GetDistance2d(who) < 99.0f && !me->isInCombat()) + me->SetInCombatWithZone(); + } + + void EnterEvadeMode() + { + BossAI::EnterEvadeMode(); + + for (uint8 i = DATA_SARA; i <= DATA_MIMIRON_YS; ++i) + if (Creature* creature = ObjectAccessor::GetCreature(*me, instance->GetData64(i))) + creature->AI()->EnterEvadeMode(); + + // not sure, spoken by Sara (sound), regarding to wowwiki Voice whispers it + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player *player = itr->getSource()) + { + if (events.IsInPhase(PHASE_ONE)) + Talk(WHISPER_VOICE_PHASE_1_WIPE, player->GetGUID()); + + player->RemoveAurasDueToSpell(SPELL_SANITY); + player->RemoveAurasDueToSpell(SPELL_INSANE); + } + } + + void Reset() + { + _Reset(); + events.SetPhase(PHASE_ONE); + + instance->SetData(DATA_DRIVE_ME_CRAZY, uint32(true)); + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + + _guardiansCount = 0; + _guardianTimer = 20000; + _illusionShattered = false; + + bool clockwise = false; + std::list<TempSummon*> clouds; + me->SummonCreatureGroup(CREATURE_GROUP_CLOUDS, &clouds); + clouds.sort(Trinity::ObjectDistanceOrderPred(me, true)); + for (std::list<TempSummon*>::const_iterator itr = clouds.begin(); itr != clouds.end(); ++itr) + { + (*itr)->AI()->DoAction(int32(clockwise)); + clockwise = !clockwise; + } + } + + void EnterCombat(Unit* /*who*/) + { + if (Creature* sara = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SARA))) + sara->SetInCombatWith(me); + + for (uint8 i = DATA_FREYA_YS; i <= DATA_MIMIRON_YS; ++i) + if (Creature* keeper = ObjectAccessor::GetCreature(*me, instance->GetData64(i))) + keeper->SetInCombatWith(me); + + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + + me->CastCustomSpell(SPELL_SUMMON_GUARDIAN_2, SPELLVALUE_MAX_TARGETS, 1); + DoCast(me, SPELL_SANITY_PERIODIC); + + events.ScheduleEvent(EVENT_LOCK_DOOR, 15000); + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON, _guardianTimer, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_EXTINGUISH_ALL_LIFE, 900000); // 15 minutes + } + + void JustDied(Unit* killer) + { + // don't despawn Yogg-Saron's corpse, remove him from SummonList! + if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_YOGG_SARON))) + summons.Despawn(yogg); + + BossAI::JustDied(killer); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + // don't summon tentacles when illusion is shattered, delay them + if (_illusionShattered) + events.DelayEvents(diff, EVENT_GROUP_SUMMON_TENTACLES); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_LOCK_DOOR: + DoCast(me, SPELL_INSANE_PERIODIC); + instance->SetBossState(BOSS_YOGG_SARON, IN_PROGRESS); + break; + case EVENT_EXTINGUISH_ALL_LIFE: + if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_YOGG_SARON))) + { + yogg->AI()->Talk(EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE, me->GetGUID()); + yogg->CastSpell((Unit*)NULL, SPELL_EXTINGUISH_ALL_LIFE, true); + } + events.ScheduleEvent(EVENT_EXTINGUISH_ALL_LIFE, 10000); // cast it again after a short while, players can survive + break; + case EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON: + me->CastCustomSpell(SPELL_SUMMON_GUARDIAN_2, SPELLVALUE_MAX_TARGETS, 1); + ++_guardiansCount; + if (_guardiansCount <= 6 && _guardiansCount % 3 == 0) + _guardianTimer -= 5000; + events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON, _guardianTimer, 0, PHASE_ONE); + break; + case EVENT_SUMMON_CORRUPTOR_TENTACLE: + DoCastAOE(SPELL_CORRUPTOR_TENTACLE_SUMMON); + events.ScheduleEvent(EVENT_SUMMON_CORRUPTOR_TENTACLE, 30000, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); + break; + case EVENT_SUMMON_CONSTRICTOR_TENTACLE: + me->CastCustomSpell(SPELL_CONSTRICTOR_TENTACLE, SPELLVALUE_MAX_TARGETS, 1); + events.ScheduleEvent(EVENT_SUMMON_CONSTRICTOR_TENTACLE, 25000, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); + break; + case EVENT_SUMMON_CRUSHER_TENTACLE: + DoCastAOE(SPELL_CRUSHER_TENTACLE_SUMMON); + events.ScheduleEvent(EVENT_SUMMON_CRUSHER_TENTACLE, 60000, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); + break; + case EVENT_ILLUSION: + { + if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_YOGG_SARON))) + { + yogg->AI()->Talk(EMOTE_YOGG_SARON_MADNESS); + yogg->AI()->Talk(SAY_YOGG_SARON_MADNESS); + } + + me->SummonCreatureGroup(CREATURE_GROUP_PORTALS_10); + if (me->GetMap()->Is25ManRaid()) + me->SummonCreatureGroup(CREATURE_GROUP_PORTALS_25); + + uint8 illusion = urand(CHAMBER_ILLUSION, STORMWIND_ILLUSION); + instance->SetData(DATA_ILLUSION, illusion); + + if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRAIN_OF_YOGG_SARON))) + brain->AI()->DoAction(ACTION_INDUCE_MADNESS); + events.ScheduleEvent(EVENT_ILLUSION, 80000, 0, PHASE_TWO); // wowwiki says 80 secs, wowhead says something about 90 secs + break; + } + case EVENT_SUMMON_IMMORTAL_GUARDIAN: + DoCastAOE(SPELL_IMMORTAL_GUARDIAN); + events.ScheduleEvent(EVENT_SUMMON_IMMORTAL_GUARDIAN, 15000, 0, PHASE_THREE); + break; + default: + break; + } + } + } + + void DoAction(int32 action) + { + switch (action) + { + case ACTION_PHASE_TRANSFORM: + events.SetPhase(PHASE_TRANSFORM); + summons.DespawnEntry(NPC_OMINOUS_CLOUD); + break; + case ACTION_PHASE_TWO: + events.SetPhase(PHASE_TWO); + me->SummonCreature(NPC_YOGG_SARON, YoggSaronSpawnPos); + if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRAIN_OF_YOGG_SARON))) + brain->SetInCombatWithZone(); + events.ScheduleEvent(EVENT_SUMMON_CORRUPTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); + events.ScheduleEvent(EVENT_SUMMON_CONSTRICTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); + events.ScheduleEvent(EVENT_SUMMON_CRUSHER_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO); + events.ScheduleEvent(EVENT_ILLUSION, 60000, 0, PHASE_TWO); + break; + case ACTION_TOGGLE_SHATTERED_ILLUSION: + _illusionShattered = !_illusionShattered; + break; + case ACTION_PHASE_THREE: + events.SetPhase(PHASE_THREE); + events.ScheduleEvent(EVENT_SUMMON_IMMORTAL_GUARDIAN, 1000, 0, PHASE_THREE); + break; + default: + break; + } + } + + void JustSummoned(Creature* summon) + { + switch (summon->GetEntry()) + { + case NPC_GUARDIAN_OF_YOGG_SARON: + summon->m_Events.AddEvent(new StartAttackEvent(me, summon), summon->m_Events.CalculateTime(1000)); + break; + case NPC_YOGG_SARON: + summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); + break; + case NPC_CONSTRICTOR_TENTACLE: + summon->CastSpell(summon, SPELL_LUNGE, true); + break; + case NPC_CRUSHER_TENTACLE: + case NPC_CORRUPTOR_TENTACLE: + summon->SetReactState(REACT_PASSIVE); + summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); + summon->m_Events.AddEvent(new StartAttackEvent(me, summon), summon->m_Events.CalculateTime(5000)); + break; + case NPC_DESCEND_INTO_MADNESS: + summon->CastSpell(summon, SPELL_TELEPORT_PORTAL_VISUAL, true); + break; + case NPC_IMMORTAL_GUARDIAN: + summon->CastSpell(summon, SPELL_SIMPLE_TELEPORT, true); + break; + } + + BossAI::JustSummoned(summon); + } + + private: + uint8 _guardiansCount; + uint32 _guardianTimer; + bool _illusionShattered; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_voice_of_yogg_saronAI>(creature); + } +}; + +class boss_sara : public CreatureScript +{ + public: + boss_sara() : CreatureScript("boss_sara") { } + + struct boss_saraAI : public ScriptedAI + { + boss_saraAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + uint64 GetLinkedPlayerGUID(uint64 guid) const + { + std::map<uint64, uint64>::const_iterator itr = _linkData.find(guid); + if (itr != _linkData.end()) + return itr->second; + + return 0; + } + + void SetLinkBetween(uint64 player1, uint64 player2) + { + _linkData[player1] = player2; + _linkData[player2] = player1; + } + + // called once for each target on aura remove + void RemoveLinkFrom(uint64 player1) + { + _linkData.erase(player1); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (_events.IsInPhase(PHASE_ONE) && damage >= me->GetHealth()) + { + damage = 0; + + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_PHASE_TRANSFORM); + + Talk(SAY_SARA_TRANSFORM_1); + _events.SetPhase(PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_1, 4700, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_2, 9500, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_3, 14300, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_4, 14500, 0, PHASE_TRANSFORM); + } + } + + void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) + { + if (!roll_chance_i(30) || _events.IsInPhase(PHASE_TRANSFORM)) + return; + + switch (spell->Id) + { + case SPELL_SARAS_FERVOR: + Talk(SAY_SARA_FERVOR_HIT); + break; + case SPELL_SARAS_BLESSING: + Talk(SAY_SARA_BLESSING_HIT); + break; + case SPELL_PSYCHOSIS: + Talk(SAY_SARA_PSYCHOSIS_HIT); + break; + default: + break; + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER && !me->IsInEvadeMode()) + Talk(SAY_SARA_KILL); + } + + void EnterCombat(Unit* /*who*/) + { + Talk(SAY_SARA_AGGRO); + _events.ScheduleEvent(EVENT_SARAS_FERVOR, 5000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SARAS_BLESSING, urand(10000, 30000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SARAS_ANGER, urand(15000, 25000), 0, PHASE_ONE); + } + + void Reset() + { + me->RemoveAllAuras(); + me->SetReactState(REACT_PASSIVE); + me->setFaction(35); + _events.Reset(); + _events.SetPhase(PHASE_ONE); + } + + void UpdateAI(uint32 diff) + { + if (!me->isInCombat()) + return; + + if (me->HasAura(SPELL_SHATTERED_ILLUSION)) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SARAS_FERVOR: + me->CastCustomSpell(SPELL_SARAS_FERVOR_TARGET_SELECTOR, SPELLVALUE_MAX_TARGETS, 1); + _events.ScheduleEvent(EVENT_SARAS_FERVOR, 6000, 0, PHASE_ONE); + break; + case EVENT_SARAS_ANGER: + me->CastCustomSpell(SPELL_SARAS_ANGER_TARGET_SELECTOR, SPELLVALUE_MAX_TARGETS, 1); + _events.ScheduleEvent(EVENT_SARAS_ANGER, urand(6000, 8000), 0, PHASE_ONE); + break; + case EVENT_SARAS_BLESSING: + me->CastCustomSpell(SPELL_SARAS_BLESSING_TARGET_SELECTOR, SPELLVALUE_MAX_TARGETS, 1); + _events.ScheduleEvent(EVENT_SARAS_BLESSING, urand(6000, 30000), 0, PHASE_ONE); + break; + case EVENT_TRANSFORM_1: + Talk(SAY_SARA_TRANSFORM_2); + break; + case EVENT_TRANSFORM_2: + Talk(SAY_SARA_TRANSFORM_3); + break; + case EVENT_TRANSFORM_3: + Talk(SAY_SARA_TRANSFORM_4); + DoCast(me, SPELL_FULL_HEAL); + me->setFaction(16); + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_PHASE_TWO); + if (Creature* mimiron = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MIMIRON_YS))) + mimiron->AI()->DoAction(ACTION_PHASE_TWO); + break; + case EVENT_TRANSFORM_4: + DoCast(me, SPELL_PHASE_2_TRANSFORM); + if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetData64(BOSS_YOGG_SARON))) + DoCast(yogg, SPELL_RIDE_YOGG_SARON_VEHICLE); + DoCast(me, SPELL_SHADOWY_BARRIER_SARA); + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_DEATH_RAY, 20000, 0, PHASE_TWO); // almost never casted at scheduled time, why? + _events.ScheduleEvent(EVENT_MALADY_OF_THE_MIND, 18000, 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_PSYCHOSIS, 1, 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_BRAIN_LINK, 23000, 0, PHASE_TWO); + break; + case EVENT_DEATH_RAY: + DoCast(me, SPELL_DEATH_RAY); + _events.ScheduleEvent(EVENT_DEATH_RAY, 21000, 0, PHASE_TWO); + break; + case EVENT_MALADY_OF_THE_MIND: + me->CastCustomSpell(SPELL_MALADY_OF_THE_MIND, SPELLVALUE_MAX_TARGETS, 1); + _events.ScheduleEvent(EVENT_MALADY_OF_THE_MIND, urand(18000, 25000), 0, PHASE_TWO); + break; + case EVENT_PSYCHOSIS: + me->CastCustomSpell(SPELL_PSYCHOSIS, SPELLVALUE_MAX_TARGETS, 1); + _events.ScheduleEvent(EVENT_PSYCHOSIS, 4000, 0, PHASE_TWO); + break; + case EVENT_BRAIN_LINK: + me->CastCustomSpell(SPELL_BRAIN_LINK, SPELLVALUE_MAX_TARGETS, 2); + _events.ScheduleEvent(EVENT_BRAIN_LINK, urand(23000, 26000), 0, PHASE_TWO); + break; + default: + break; + } + } + } + + void JustSummoned(Creature* summon) + { + summon->SetReactState(REACT_PASSIVE); + + switch (summon->GetEntry()) + { + case NPC_DEATH_ORB: + Talk(SAY_SARA_DEATH_RAY); + summon->CastSpell(summon, SPELL_DEATH_RAY_ORIGIN_VISUAL); + for (uint8 i = 0; i < 4; ++i) + { + Position pos; + float radius = frand(25.0f, 50.0f); + float angle = frand(0.0f, 2.0f * M_PI); + pos.m_positionX = YoggSaronSpawnPos.GetPositionX() + radius * cosf(angle); + pos.m_positionY = YoggSaronSpawnPos.GetPositionY() + radius * sinf(angle); + pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), YoggSaronSpawnPos.GetPositionZ() + 5.0f); + me->SummonCreature(NPC_DEATH_RAY, pos, TEMPSUMMON_TIMED_DESPAWN, 20000); + } + break; + case NPC_DEATH_RAY: + summon->CastSpell(summon, SPELL_DEATH_RAY_WARNING_VISUAL); + break; + } + + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->JustSummoned(summon); + } + + void DoAction(int32 action) + { + switch (action) + { + case ACTION_PHASE_THREE: // Sara does nothing in phase 3 + _events.SetPhase(PHASE_THREE); + break; + default: + break; + } + } + + private: + EventMap _events; + InstanceScript* _instance; + std::map<uint64, uint64> _linkData; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_saraAI>(creature); + } +}; + +class boss_yogg_saron : public CreatureScript +{ + public: + boss_yogg_saron() : CreatureScript("boss_yogg_saron") { } + + struct boss_yogg_saronAI : public PassiveAI + { + boss_yogg_saronAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } + + void Reset() + { + _events.Reset(); + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_YELL_BOW_DOWN, 3000, 0, PHASE_TWO); + DoCast(me, SPELL_SHADOWY_BARRIER_YOGG); + DoCast(me, SPELL_KNOCK_AWAY); + + me->ResetLootMode(); + switch (_instance->GetData(DATA_KEEPERS_COUNT)) + { + case 0: + me->AddLootMode(LOOT_MODE_HARD_MODE_4); + case 1: + me->AddLootMode(LOOT_MODE_HARD_MODE_3); + case 2: + me->AddLootMode(LOOT_MODE_HARD_MODE_2); + case 3: + me->AddLootMode(LOOT_MODE_HARD_MODE_1); + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_IN_THE_MAWS_OF_THE_OLD_GOD) + me->AddLootMode(32); + } + + void JustDied(Unit* /*killer*/) + { + Talk(SAY_YOGG_SARON_DEATH); + + if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + me->Kill(creature); + + for (uint8 i = DATA_SARA; i <= DATA_BRAIN_OF_YOGG_SARON; ++i) + if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetData64(i))) + creature->DisappearAndDie(); + + for (uint8 i = DATA_FREYA_YS; i <= DATA_MIMIRON_YS; ++i) + if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetData64(i))) + creature->AI()->EnterEvadeMode(); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player *player = itr->getSource()) + { + player->RemoveAurasDueToSpell(SPELL_SANITY); + player->RemoveAurasDueToSpell(SPELL_INSANE); + } + } + + void UpdateAI(uint32 diff) + { + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_YELL_BOW_DOWN: + Talk(SAY_YOGG_SARON_SPAWN); + break; + case EVENT_SHADOW_BEACON: + DoCastAOE(SPELL_SHADOW_BEACON); + Talk(EMOTE_YOGG_SARON_EMPOWERING_SHADOWS); + _events.ScheduleEvent(EVENT_SHADOW_BEACON, 45000, 0, PHASE_THREE); + break; + case EVENT_LUNATIC_GAZE: + DoCast(me, SPELL_LUNATIC_GAZE); + sCreatureTextMgr->SendSound(me, SOUND_LUNATIC_GAZE, CHAT_MSG_MONSTER_YELL, 0, TEXT_RANGE_NORMAL, TEAM_OTHER, false); + _events.ScheduleEvent(EVENT_LUNATIC_GAZE, 12000, 0, PHASE_THREE); + break; + case EVENT_DEAFENING_ROAR: + DoCastAOE(SPELL_DEAFENING_ROAR); + Talk(SAY_YOGG_SARON_DEAFENING_ROAR); + Talk(EMOTE_YOGG_SARON_DEAFENING_ROAR); + _events.ScheduleEvent(EVENT_DEAFENING_ROAR, urand(20000, 25000), 0, PHASE_THREE); // timer guessed + break; + default: + break; + } + } + } + + void DoAction(int32 action) + { + switch (action) + { + case ACTION_PHASE_THREE: + _events.SetPhase(PHASE_THREE); + _events.ScheduleEvent(EVENT_SHADOW_BEACON, 45000, 0, PHASE_THREE); + _events.ScheduleEvent(EVENT_LUNATIC_GAZE, 12000, 0, PHASE_THREE); + if (me->GetMap()->Is25ManRaid() && _instance->GetData(DATA_KEEPERS_COUNT) < 4) + _events.ScheduleEvent(EVENT_DEAFENING_ROAR, urand(20000, 25000), 0, PHASE_THREE); // timer guessed + Talk(SAY_YOGG_SARON_PHASE_3); + DoCast(me, SPELL_PHASE_3_TRANSFORM); + me->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER_YOGG); + break; + default: + break; + } + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_yogg_saronAI>(creature); + } +}; + +class boss_brain_of_yogg_saron : public CreatureScript +{ + public: + boss_brain_of_yogg_saron() : CreatureScript("boss_brain_of_yogg_saron") { } + + struct boss_brain_of_yogg_saronAI : public PassiveAI + { + boss_brain_of_yogg_saronAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()), _summons(creature) { } + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_MATCH_HEALTH); + _summons.DespawnAll(); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (me->HealthBelowPctDamaged(30, damage) && !me->HasAura(SPELL_BRAIN_HURT_VISUAL)) + { + me->RemoveAllAuras(); + me->InterruptNonMeleeSpells(true); + DoCastAOE(SPELL_SHATTERED_ILLUSION_REMOVE, true); + DoCast(me, SPELL_MATCH_HEALTH_2, true); // it doesn't seem to hit Yogg-Saron here + DoCast(me, SPELL_BRAIN_HURT_VISUAL, true); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_PHASE_THREE); + if (Creature* sara = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_SARA))) + sara->AI()->DoAction(ACTION_PHASE_THREE); + if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetData64(BOSS_YOGG_SARON))) + yogg->AI()->DoAction(ACTION_PHASE_THREE); + + for (uint8 i = DATA_THORIM_YS; i <= DATA_MIMIRON_YS; ++i) + if (Creature* keeper = ObjectAccessor::GetCreature(*me, _instance->GetData64(i))) + keeper->AI()->DoAction(ACTION_PHASE_THREE); + } + } + + void UpdateAI(uint32 /*diff*/) { } + + void DoAction(int32 action) + { + switch (action) + { + case ACTION_INDUCE_MADNESS: + { + _tentaclesKilled = 0; + + me->SummonCreatureGroup(_instance->GetData(DATA_ILLUSION)); + + // make sure doors won't be opened + for (uint32 i = GO_BRAIN_ROOM_DOOR_1; i <= GO_BRAIN_ROOM_DOOR_3; ++i) + _instance->HandleGameObject(_instance->GetData64(i), false); + + DoCastAOE(SPELL_INDUCE_MADNESS); + break; + } + case ACTION_TENTACLE_KILLED: + { + uint8 illusion = _instance->GetData(DATA_ILLUSION); + if (++_tentaclesKilled >= (illusion == ICECROWN_ILLUSION ? 9 : 8)) + { + sCreatureTextMgr->SendChat(me, EMOTE_BRAIN_ILLUSION_SHATTERED, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_AREA); + _summons.DespawnAll(); + DoCastAOE(SPELL_SHATTERED_ILLUSION, true); + _instance->HandleGameObject(_instance->GetData64(GO_BRAIN_ROOM_DOOR_1 + illusion), true); + + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION); + } + break; + } + default: + break; + } + } + + void JustSummoned(Creature* summon) + { + _summons.Summon(summon); + } + + private: + InstanceScript* _instance; + SummonList _summons; + uint8 _tentaclesKilled; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<boss_brain_of_yogg_saronAI>(creature); + } +}; + +class npc_ominous_cloud : public CreatureScript +{ + public: + npc_ominous_cloud() : CreatureScript("npc_ominous_cloud") { } + + struct npc_ominous_cloudAI : public PassiveAI + { + npc_ominous_cloudAI(Creature* creature) : PassiveAI(creature) { } + + void Reset() + { + DoCast(me, SPELL_OMINOUS_CLOUD_VISUAL); + } + + void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise) + { + float step = clockwise ? -M_PI / 8.0f : M_PI / 8.0f; + float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY()); + + for (uint8 i = 0; i < 16; angle += step, ++i) + { + G3D::Vector3 point; + point.x = centerPos.GetPositionX() + radius * cosf(angle); + point.y = centerPos.GetPositionY() + radius * sinf(angle); + point.z = me->GetMap()->GetHeight(me->GetPhaseMask(), point.x, point.y, z + 5.0f); + path.push_back(point); + } + } + + void UpdateAI(uint32 /*diff*/) { } + + void DoAction(int32 action) + { + Movement::MoveSplineInit init(me); + FillCirclePath(YoggSaronSpawnPos, me->GetDistance2d(YoggSaronSpawnPos.GetPositionX(), YoggSaronSpawnPos.GetPositionY()), me->GetPositionZ(), init.Path(), action); + init.SetWalk(true); + init.SetCyclic(); + init.Launch(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_ominous_cloudAI>(creature); + } +}; + +class npc_guardian_of_yogg_saron : public CreatureScript +{ + public: + npc_guardian_of_yogg_saron() : CreatureScript("npc_guardian_of_yogg_saron") { } + + struct npc_guardian_of_yogg_saronAI : public ScriptedAI + { + npc_guardian_of_yogg_saronAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void JustDied(Unit* /*killer*/) + { + DoCastAOE(SPELL_SHADOW_NOVA); + DoCastAOE(SPELL_SHADOW_NOVA_2); + } + + void Reset() + { + _events.ScheduleEvent(EVENT_DARK_VOLLEY, urand(10000, 15000)); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DARK_VOLLEY: + DoCastAOE(SPELL_DARK_VOLLEY); + _events.ScheduleEvent(EVENT_DARK_VOLLEY, urand(10000, 15000)); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + void IsSummonedBy(Unit* summoner) + { + if (summoner->GetEntry() != NPC_OMINOUS_CLOUD) + return; + + // Guardian can be summoned both by Voice of Yogg-Saron and by Ominous Cloud + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->JustSummoned(me); + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_guardian_of_yogg_saronAI>(creature); + } +}; + +class npc_corruptor_tentacle : public CreatureScript +{ + public: + npc_corruptor_tentacle() : CreatureScript("npc_corruptor_tentacle") { } + + struct npc_corruptor_tentacleAI : public ScriptedAI + { + npc_corruptor_tentacleAI(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + } + + void Reset() + { + DoCast(me, SPELL_TENTACLE_VOID_ZONE); + DoCastAOE(SPELL_ERUPT); + _events.ScheduleEvent(EVENT_CAST_RANDOM_SPELL, 1); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->HasAura(SPELL_SHATTERED_ILLUSION)) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CAST_RANDOM_SPELL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, RAND(SPELL_BLACK_PLAGUE, SPELL_CURSE_OF_DOOM, SPELL_APATHY, SPELL_DRAINING_POISON)); + _events.ScheduleEvent(EVENT_CAST_RANDOM_SPELL, 3000); + break; + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_corruptor_tentacleAI>(creature); + } +}; + +class npc_constrictor_tentacle : public CreatureScript +{ + public: + npc_constrictor_tentacle() : CreatureScript("npc_constrictor_tentacle") { } + + struct npc_constrictor_tentacleAI : public ScriptedAI + { + npc_constrictor_tentacleAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + { + SetCombatMovement(false); + } + + void Reset() + { + DoCast(me, SPELL_TENTACLE_VOID_ZONE_2); + DoCastAOE(SPELL_ERUPT); + } + + void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) + { + if (!apply) + passenger->RemoveAurasDueToSpell(SPELL_SQUEEZE); + } + + void UpdateAI(uint32 /*diff*/) + { + UpdateVictim(); + } + + void IsSummonedBy(Unit* summoner) + { + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->JustSummoned(me); + } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_constrictor_tentacleAI>(creature); + } +}; + +class npc_crusher_tentacle : public CreatureScript +{ + public: + npc_crusher_tentacle() : CreatureScript("npc_crusher_tentacle") { } + + struct npc_crusher_tentacleAI : public ScriptedAI + { + npc_crusher_tentacleAI(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + } + + void Reset() + { + DoCast(me, SPELL_CRUSH); + DoCast(me, SPELL_TENTACLE_VOID_ZONE); + DoCast(me, SPELL_DIMINSH_POWER); + DoCast(me, SPELL_FOCUSED_ANGER); + DoCastAOE(SPELL_ERUPT); + + _events.ScheduleEvent(EVENT_DIMINISH_POWER, urand(6000, 8000)); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->HasAura(SPELL_SHATTERED_ILLUSION) || me->HasUnitState(UNIT_STATE_CASTING)) + return; + + // update timers when the Diminish Power is not being channeled so the next one + // is not cast immediately after interrupt + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DIMINISH_POWER: + DoCast(SPELL_DIMINISH_POWER); + _events.ScheduleEvent(EVENT_DIMINISH_POWER, urand(20000, 30000)); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_crusher_tentacleAI>(creature); + } +}; + +class npc_influence_tentacle : public CreatureScript +{ + public: + npc_influence_tentacle() : CreatureScript("npc_influence_tentacle") { } + + struct npc_influence_tentacleAI : public PassiveAI + { + npc_influence_tentacleAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } + + void Reset() + { + DoCast(me, me->GetEntry() == NPC_SUIT_OF_ARMOR ? SPELL_NONDESCRIPT_1 : SPELL_NONDESCRIPT_2); + } + + void JustDied(Unit* /*killer*/) + { + if (Creature* brain = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_BRAIN_OF_YOGG_SARON))) + brain->AI()->DoAction(ACTION_TENTACLE_KILLED); + } + + void UpdateAI(uint32 diff) { } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_influence_tentacleAI>(creature); + } +}; + +typedef boss_sara::boss_saraAI SaraAI; + +class npc_descend_into_madness : public CreatureScript +{ + public: + npc_descend_into_madness() : CreatureScript("npc_descend_into_madness") { } + + struct npc_descend_into_madnessAI : public PassiveAI + { + npc_descend_into_madnessAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } + + void OnSpellClick(Unit* clicker) + { + clicker->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + me->DespawnOrUnsummon(); + } + + void UpdateAI(uint32 /*diff*/) { } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_descend_into_madnessAI>(creature); + } +}; + +class npc_immortal_guardian : public CreatureScript +{ + public: + npc_immortal_guardian() : CreatureScript("npc_immortal_guardian") { } + + struct npc_immortal_guardianAI : public ScriptedAI + { + npc_immortal_guardianAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() + { + DoCast(me, SPELL_EMPOWERED); + DoCast(me, SPELL_RECENTLY_SPAWNED); + _events.ScheduleEvent(EVENT_DRAIN_LIFE, urand(3000, 13000)); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) + { + if (me->HealthBelowPctDamaged(1, damage)) + damage = me->GetHealth() - me->CountPctFromMaxHealth(1); // or set immune to damage? should be done here or in SPELL_WEAKENED spell script? + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DRAIN_LIFE: + DoCast(SPELL_DRAIN_LIFE); + _events.ScheduleEvent(EVENT_DRAIN_LIFE, urand(20000, 30000)); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_immortal_guardianAI>(creature); + } +}; + +class npc_observation_ring_keeper : public CreatureScript +{ + public: + npc_observation_ring_keeper() : CreatureScript("npc_observation_ring_keeper") { } + + struct npc_observation_ring_keeperAI : public ScriptedAI + { + npc_observation_ring_keeperAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() + { + DoCast(SPELL_SIMPLE_TELEPORT_KEEPERS); // not visible here + DoCast(SPELL_KEEPER_ACTIVE); + } + + void sGossipSelect(Player* player, uint32 sender, uint32 /*action*/) + { + if (sender != 10333) + return; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->DespawnOrUnsummon(2000); + DoCast(SPELL_TELEPORT); + Talk(SAY_KEEPER_CHOSEN_1, player->GetGUID()); + Talk(SAY_KEEPER_CHOSEN_2, player->GetGUID()); + + switch (me->GetEntry()) + { + case NPC_FREYA_OBSERVATION_RING: + me->SummonCreature(NPC_FREYA_YS, YSKeepersPos[0]); + break; + case NPC_HODIR_OBSERVATION_RING: + me->SummonCreature(NPC_HODIR_YS, YSKeepersPos[1]); + break; + case NPC_THORIM_OBSERVATION_RING: + me->SummonCreature(NPC_THORIM_YS, YSKeepersPos[2]); + break; + case NPC_MIMIRON_OBSERVATION_RING: + me->SummonCreature(NPC_MIMIRON_YS, YSKeepersPos[3]); + break; + } + } + + void UpdateAI(uint32 diff) { } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_observation_ring_keeperAI>(creature); + } +}; + +class npc_yogg_saron_keeper : public CreatureScript +{ + public: + npc_yogg_saron_keeper() : CreatureScript("npc_yogg_saron_keeper") { } + + struct npc_yogg_saron_keeperAI : public ScriptedAI + { + npc_yogg_saron_keeperAI(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* /*summoner*/) + { + DoCast(SPELL_SIMPLE_TELEPORT_KEEPERS); + } + + void Reset() + { + _events.Reset(); + _events.SetPhase(PHASE_ONE); + me->SetReactState(REACT_PASSIVE); + me->RemoveAllAuras(); + + DoCast(SPELL_KEEPER_ACTIVE); // can we skip removing this aura somehow? + + if (me->GetEntry() == NPC_FREYA_YS) + { + std::list<Creature*> wells; + GetCreatureListWithEntryInGrid(wells, me, NPC_SANITY_WELL, 200.0f); + for (std::list<Creature*>::const_iterator itr = wells.begin(); itr != wells.end(); ++itr) + { + (*itr)->RemoveAurasDueToSpell(SPELL_SANITY_WELL); + (*itr)->RemoveAurasDueToSpell(SPELL_SANITY_WELL_VISUAL); + } + } + } + + void EnterCombat(Unit* /*who*/) + { + switch (me->GetEntry()) + { + case NPC_FREYA_YS: + DoCast(SPELL_RESILIENCE_OF_NATURE); + DoCast(SPELL_SANITY_WELL_SUMMON); + break; + case NPC_HODIR_YS: + DoCast(SPELL_FORTITUDE_OF_FROST); + DoCast(SPELL_HODIRS_PROTECTIVE_GAZE); + break; + case NPC_THORIM_YS: + DoCast(SPELL_FURY_OF_THE_STORM); + break; + case NPC_MIMIRON_YS: + DoCast(SPELL_SPEED_OF_INVENTION); + break; + } + } + + void UpdateAI(uint32 diff) + { + if (!me->isInCombat()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_DESTABILIZATION_MATRIX: + me->CastCustomSpell(SPELL_DESTABILIZATION_MATRIX, SPELLVALUE_MAX_TARGETS, 1); + _events.ScheduleEvent(EVENT_DESTABILIZATION_MATRIX, urand(15000, 25000), 0, PHASE_TWO); + break; + case EVENT_HODIRS_PROTECTIVE_GAZE: + DoCast(SPELL_HODIRS_PROTECTIVE_GAZE); + break; + } + } + } + + void DoAction(int32 action) + { + switch (action) + { + // setting the phases is only for Thorim and Mimiron + case ACTION_PHASE_TWO: + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_DESTABILIZATION_MATRIX, urand(5000, 15000), 0, PHASE_TWO); + break; + case ACTION_PHASE_THREE: + _events.SetPhase(PHASE_THREE); + if (me->GetEntry() == NPC_THORIM_YS) + DoCast(SPELL_TITANIC_STORM); + break; + case ACTION_SANITY_WELLS: + { + std::list<Creature*> wells; + GetCreatureListWithEntryInGrid(wells, me, NPC_SANITY_WELL, 200.0f); + for (std::list<Creature*>::const_iterator itr = wells.begin(); itr != wells.end(); ++itr) + { + (*itr)->CastSpell(*itr, SPELL_SANITY_WELL); + (*itr)->CastSpell(*itr, SPELL_SANITY_WELL_VISUAL); + } + break; + } + case ACTION_FLASH_FREEZE: + DoCast(SPELL_FLASH_FREEZE_VISUAL); + _events.ScheduleEvent(EVENT_HODIRS_PROTECTIVE_GAZE, urand(25000, 30000)); + break; + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_yogg_saron_keeperAI>(creature); + } +}; + +class npc_yogg_saron_illusions : public CreatureScript +{ + public: + npc_yogg_saron_illusions() : CreatureScript("npc_yogg_saron_illusions") { } + + struct npc_yogg_saron_illusionsAI : public ScriptedAI + { + npc_yogg_saron_illusionsAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void IsSummonedBy(Unit* /*summoner*/) + { + switch (_instance->GetData(DATA_ILLUSION)) + { + case CHAMBER_ILLUSION: + // i think the first Talk should be delayed as in this moment + // players are too far away to be able to see it + if (Creature* neltharion = me->FindNearestCreature(NPC_NELTHARION, 50.0f)) + neltharion->AI()->Talk(SAY_CHAMBER_ROLEPLAY_1); + + _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_1, 16000); + _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_2, 22000); + _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_3, 28000); + _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_4, 36000); + break; + case ICECROWN_ILLUSION: + // same here + _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_1, 1000); + _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_2, 7500); + _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_3, 19500); + _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_4, 25500); + _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_5, 33000); + _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_6, 41300); + break; + case STORMWIND_ILLUSION: + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_4, 33800); // "A thousand deaths..." + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_5, 38850); + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_7, 58750); + // TODO: use "or one murder." sound and split the text in DB + break; + } + } + + void UpdateAI(uint32 diff) + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CHAMBER_ROLEPLAY_1: + if (Creature* ysera = me->FindNearestCreature(NPC_YSERA, 50.0f)) + ysera->AI()->Talk(SAY_CHAMBER_ROLEPLAY_2); + break; + case EVENT_CHAMBER_ROLEPLAY_2: + if (Creature* neltharion = me->FindNearestCreature(NPC_NELTHARION, 50.0f)) + neltharion->AI()->Talk(SAY_CHAMBER_ROLEPLAY_3); + break; + case EVENT_CHAMBER_ROLEPLAY_3: + if (Creature* malygos = me->FindNearestCreature(NPC_MALYGOS, 50.0f)) + malygos->AI()->Talk(SAY_CHAMBER_ROLEPLAY_4); + break; + case EVENT_CHAMBER_ROLEPLAY_4: + Talk(SAY_CHAMBER_ROLEPLAY_5); + break; + case EVENT_ICECROWN_ROLEPLAY_1: + if (Creature* bolvar = me->FindNearestCreature(NPC_IMMOLATED_CHAMPION, 50.0f)) + { + bolvar->AI()->Talk(SAY_ICECROWN_ROLEPLAY_1); + + if (Creature* lichKing = me->FindNearestCreature(NPC_THE_LICH_KING, 50.0f)) + lichKing->CastSpell(bolvar, SPELL_DEATHGRASP); + } + break; + case EVENT_ICECROWN_ROLEPLAY_2: + if (Creature* lichKing = me->FindNearestCreature(NPC_THE_LICH_KING, 50.0f)) + lichKing->AI()->Talk(SAY_ICECROWN_ROLEPLAY_2); + break; + case EVENT_ICECROWN_ROLEPLAY_3: + if (Creature* bolvar = me->FindNearestCreature(NPC_IMMOLATED_CHAMPION, 50.0f)) + bolvar->AI()->Talk(SAY_ICECROWN_ROLEPLAY_3); + if (Creature* saurfang = me->FindNearestCreature(NPC_TURNED_CHAMPION, 50.0f)) + saurfang->AI()->DoAction(ACTION_START_ROLEPLAY); + break; + case EVENT_ICECROWN_ROLEPLAY_4: + if (Creature* lichKing = me->FindNearestCreature(NPC_THE_LICH_KING, 50.0f)) + lichKing->AI()->Talk(SAY_ICECROWN_ROLEPLAY_4); + break; + case EVENT_ICECROWN_ROLEPLAY_5: + Talk(SAY_ICECROWN_ROLEPLAY_5); + break; + case EVENT_ICECROWN_ROLEPLAY_6: + Talk(SAY_ICECROWN_ROLEPLAY_6); + break; + case EVENT_STORMWIND_ROLEPLAY_4: + Talk(SAY_STORMWIND_ROLEPLAY_4); + break; + case EVENT_STORMWIND_ROLEPLAY_5: + if (Creature* llane = me->FindNearestCreature(NPC_KING_LLANE, 50.0f)) + llane->AI()->Talk(SAY_STORMWIND_ROLEPLAY_5); + break; + case EVENT_STORMWIND_ROLEPLAY_7: + Talk(SAY_STORMWIND_ROLEPLAY_7); + break; + default: + break; + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_yogg_saron_illusionsAI>(creature); + } +}; + +class npc_garona : public CreatureScript +{ + public: + npc_garona() : CreatureScript("npc_garona") { } + + struct npc_garonaAI : public ScriptedAI + { + npc_garonaAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() + { + _events.Reset(); + + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(0, IllusionsMiscPos[0]); + + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_1, 9250); + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_2, 16700); + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_3, 24150); + _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_6, 52700); + } + + void UpdateAI(uint32 diff) + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_STORMWIND_ROLEPLAY_1: + Talk(SAY_STORMWIND_ROLEPLAY_1); + break; + case EVENT_STORMWIND_ROLEPLAY_2: + Talk(SAY_STORMWIND_ROLEPLAY_2); + break; + case EVENT_STORMWIND_ROLEPLAY_3: + Talk(SAY_STORMWIND_ROLEPLAY_3); + break; + case EVENT_STORMWIND_ROLEPLAY_6: + Talk(SAY_STORMWIND_ROLEPLAY_6); + if (Creature* llane = me->FindNearestCreature(NPC_KING_LLANE, 50.0f)) + { + DoCast(SPELL_ASSASSINATE); + llane->CastSpell(llane, SPELL_PERMANENT_FEIGN_DEATH); + } + break; + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_garonaAI>(creature); + } +}; + +class npc_turned_champion : public CreatureScript +{ + public: + npc_turned_champion() : CreatureScript("npc_turned_champion") { } + + struct npc_turned_championAI : public ScriptedAI + { + npc_turned_championAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() + { + DoCast(SPELL_VERTEX_COLOR_BLACK); + } + + void MovementInform(uint32 type, uint32 pointId) + { + if (type != POINT_MOTION_TYPE || pointId != 0) + return; + + me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE); + } + + void DoAction(int32 action) + { + if (action != ACTION_START_ROLEPLAY) + return; + + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(0, IllusionsMiscPos[1]); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_turned_championAI>(creature); + } +}; + +class npc_laughing_skull : public CreatureScript +{ + public: + npc_laughing_skull() : CreatureScript("npc_laughing_skull") { } + + struct npc_laughing_skullAI : public ScriptedAI + { + npc_laughing_skullAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_LUNATIC_GAZE_SKULL); + } + + // don't evade, otherwise the Lunatic Gaze aura is removed + void UpdateAI(uint32 diff) { } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetUlduarAI<npc_laughing_skullAI>(creature); + } +}; + +class spell_yogg_saron_target_selectors : public SpellScriptLoader // 63744, 63745, 63747, 65206 +{ + public: + spell_yogg_saron_target_selectors() : SpellScriptLoader("spell_yogg_saron_target_selectors") { } + + class spell_yogg_saron_target_selectors_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_target_selectors_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, uint32(GetEffectValue())); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_target_selectors_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_target_selectors_SpellScript(); + } +}; + +class SanityReduction : public SpellScript +{ + public: + SanityReduction() : SpellScript() { } + SanityReduction(uint8 stacks) : SpellScript(), _stacks(stacks) { } + + void RemoveSanity(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (Aura* sanity = target->GetAura(SPELL_SANITY)) + sanity->ModStackAmount(-int32(_stacks), AURA_REMOVE_BY_ENEMY_SPELL); + } + + protected: + uint8 _stacks; +}; + +class HighSanityTargetSelector +{ + public: + HighSanityTargetSelector() { } + + bool operator()(WorldObject* object) + { + if (Unit* unit = object->ToUnit()) + if (Aura* sanity = unit->GetAura(SPELL_SANITY)) + return sanity->GetStackAmount() <= 40; + return true; + } +}; + +class spell_yogg_saron_psychosis : public SpellScriptLoader // 63795, 65301 +{ + public: + spell_yogg_saron_psychosis() : SpellScriptLoader("spell_yogg_saron_psychosis") { } + + class spell_yogg_saron_psychosis_SpellScript : public SanityReduction + { + PrepareSpellScript(spell_yogg_saron_psychosis_SpellScript); + + bool Load() + { + _stacks = GetSpellInfo()->Id == SPELL_PSYCHOSIS ? 9 : 12; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(HighSanityTargetSelector()); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ILLUSION_ROOM)); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_psychosis_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_psychosis_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_psychosis_SpellScript::RemoveSanity, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_psychosis_SpellScript(); + } +}; + +class spell_yogg_saron_malady_of_the_mind : public SpellScriptLoader // 63830, 63881 +{ + public: + spell_yogg_saron_malady_of_the_mind() : SpellScriptLoader("spell_yogg_saron_malady_of_the_mind") { } + + class spell_yogg_saron_malady_of_the_mind_SpellScript : public SanityReduction + { + public: + spell_yogg_saron_malady_of_the_mind_SpellScript() : SanityReduction(3) { } + + PrepareSpellScript(spell_yogg_saron_malady_of_the_mind_SpellScript); + + bool Load() + { + _applyHandlers = GetSpellInfo()->Id == SPELL_MALADY_OF_THE_MIND; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(HighSanityTargetSelector()); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ILLUSION_ROOM)); + } + + void Register() + { + if (_applyHandlers) + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + } + + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::RemoveSanity, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + + bool _applyHandlers; + }; + + class spell_yogg_saron_malady_of_the_mind_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_malady_of_the_mind_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MALADY_OF_THE_MIND_JUMP)) + return false; + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + switch (GetTargetApplication()->GetRemoveMode()) + { + case AURA_REMOVE_BY_ENEMY_SPELL: + case AURA_REMOVE_BY_EXPIRE: + case AURA_REMOVE_BY_DEATH: + break; + default: + return; + } + + GetTarget()->CastSpell(GetTarget(), SPELL_MALADY_OF_THE_MIND_JUMP); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_malady_of_the_mind_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_MOD_FEAR, AURA_EFFECT_HANDLE_REAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_malady_of_the_mind_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_malady_of_the_mind_AuraScript(); + } +}; + +class spell_yogg_saron_brain_link : public SpellScriptLoader // 63802 +{ + public: + spell_yogg_saron_brain_link() : SpellScriptLoader("spell_yogg_saron_brain_link") { } + + class spell_yogg_saron_brain_link_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_brain_link_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ILLUSION_ROOM)); + + if (targets.size() != 2) + { + targets.clear(); + return; + } + + if (SaraAI* ai = CAST_AI(SaraAI, GetCaster()->GetAI())) + ai->SetLinkBetween(targets.front()->GetGUID(), targets.back()->GetGUID()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_brain_link_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + class spell_yogg_saron_brain_link_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_brain_link_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_BRAIN_LINK_DAMAGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_BRAIN_LINK_NO_DAMAGE)) + return false; + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + if (!caster) + return; + + if (SaraAI* ai = CAST_AI(SaraAI, caster->GetAI())) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + ai->RemoveLinkFrom(GetTarget()->GetGUID()); + else + { + if (Player* player = ObjectAccessor::GetPlayer(*GetTarget(), ai->GetLinkedPlayerGUID(GetTarget()->GetGUID()))) + { + ai->RemoveLinkFrom(GetTarget()->GetGUID()); + player->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + } + } + } + } + + void DummyTick(AuraEffect const* aurEff) + { + Unit* caster = GetCaster(); + if (!caster) + return; + + SaraAI* ai = CAST_AI(SaraAI, caster->GetAI()); + if (!ai) + return; + + Player* linked = ObjectAccessor::GetPlayer(*GetTarget(), ai->GetLinkedPlayerGUID(GetTarget()->GetGUID())); + if (!linked) + return; + + GetTarget()->CastSpell(linked, (GetTarget()->GetDistance(linked) > (float)aurEff->GetAmount()) ? SPELL_BRAIN_LINK_DAMAGE : SPELL_BRAIN_LINK_NO_DAMAGE, true); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_brain_link_AuraScript::DummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_brain_link_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_brain_link_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_brain_link_AuraScript(); + } +}; + +class spell_yogg_saron_brain_link_damage : public SpellScriptLoader // 63803 +{ + public: + spell_yogg_saron_brain_link_damage() : SpellScriptLoader("spell_yogg_saron_brain_link_damage") { } + + class spell_yogg_saron_brain_link_damage_SpellScript : public SanityReduction + { + public: + spell_yogg_saron_brain_link_damage_SpellScript() : SanityReduction(2) { } + + PrepareSpellScript(spell_yogg_saron_brain_link_damage_SpellScript); + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_brain_link_damage_SpellScript::RemoveSanity, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_brain_link_damage_SpellScript(); + } +}; + +class spell_yogg_saron_boil_ominously : public SpellScriptLoader // 63030 +{ + public: + spell_yogg_saron_boil_ominously() : SpellScriptLoader("spell_yogg_saron_boil_ominously") { } + + class spell_yogg_saron_boil_ominously_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_boil_ominously_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_GUARDIAN_1)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (!target->HasAura(SPELL_FLASH_FREEZE) && !GetCaster()->HasAura(SPELL_SUMMON_GUARDIAN_1) && !GetCaster()->HasAura(SPELL_SUMMON_GUARDIAN_2)) + { + if (Creature* caster = GetCaster()->ToCreature()) + caster->AI()->Talk(EMOTE_OMINOUS_CLOUD_PLAYER_TOUCH, target->GetGUID()); + + GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_GUARDIAN_1, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_boil_ominously_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_boil_ominously_SpellScript(); + } +}; + +class spell_yogg_saron_shadow_beacon : public SpellScriptLoader // 64465 +{ + public: + spell_yogg_saron_shadow_beacon() : SpellScriptLoader("spell_yogg_saron_shadow_beacon") { } + + class spell_yogg_saron_shadow_beacon_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_shadow_beacon_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + target->SetEntry(NPC_MARKED_IMMORTAL_GUARDIAN); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + target->SetEntry(NPC_IMMORTAL_GUARDIAN); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_shadow_beacon_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_shadow_beacon_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_shadow_beacon_AuraScript(); + } +}; + +class spell_yogg_saron_empowering_shadows_range_check : public SpellScriptLoader // 64466 +{ + public: + spell_yogg_saron_empowering_shadows_range_check() : SpellScriptLoader("spell_yogg_saron_empowering_shadows_range_check") { } + + class spell_yogg_saron_empowering_shadows_range_check_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_empowering_shadows_range_check_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->CastSpell(GetCaster(), uint32(GetEffectValue()), true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_empowering_shadows_range_check_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_empowering_shadows_range_check_SpellScript(); + } +}; + +class spell_yogg_saron_empowering_shadows_missile : public SpellScriptLoader // 64467 +{ + public: + spell_yogg_saron_empowering_shadows_missile() : SpellScriptLoader("spell_yogg_saron_empowering_shadows_missile") { } + + class spell_yogg_saron_empowering_shadows_missile_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_empowering_shadows_missile_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_EMPOWERING_SHADOWS)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->CastSpell((Unit*)NULL, SPELL_EMPOWERING_SHADOWS, true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_empowering_shadows_missile_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_empowering_shadows_missile_SpellScript(); + } +}; + +// it works, but is it scripted correctly? why is it aura with 2500ms duration? +class spell_yogg_saron_constrictor_tentacle : public SpellScriptLoader // 64132 +{ + public: + spell_yogg_saron_constrictor_tentacle() : SpellScriptLoader("spell_yogg_saron_constrictor_tentacle") { } + + class spell_yogg_saron_constrictor_tentacle_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_constrictor_tentacle_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_CONSTRICTOR_TENTACLE_SUMMON)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_CONSTRICTOR_TENTACLE_SUMMON); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_constrictor_tentacle_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_constrictor_tentacle_AuraScript(); + } +}; + +class spell_yogg_saron_lunge : public SpellScriptLoader // 64131 +{ + public: + spell_yogg_saron_lunge() : SpellScriptLoader("spell_yogg_saron_lunge") { } + + class spell_yogg_saron_lunge_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_lunge_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SQUEEZE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->CastSpell(target, SPELL_SQUEEZE, true); + target->CastSpell(GetCaster(), uint32(GetEffectValue()), true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_lunge_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_lunge_SpellScript(); + } +}; + +class spell_yogg_saron_squeeze : public SpellScriptLoader // 64125 +{ + public: + spell_yogg_saron_squeeze() : SpellScriptLoader("spell_yogg_saron_squeeze") { } + + class spell_yogg_saron_squeeze_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_squeeze_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* vehicle = GetTarget()->GetVehicleBase()) + if (vehicle->isAlive()) + vehicle->Kill(vehicle); // should tentacle die or just release its target? + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_squeeze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_squeeze_AuraScript(); + } +}; + +class spell_yogg_saron_diminsh_power : public SpellScriptLoader // 64148 +{ + public: + spell_yogg_saron_diminsh_power() : SpellScriptLoader("spell_yogg_saron_diminsh_power") { } + + class spell_yogg_saron_diminsh_power_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_diminsh_power_AuraScript); + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + if (Spell* spell = GetTarget()->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + if (spell->getState() == SPELL_STATE_CASTING) + GetTarget()->InterruptSpell(CURRENT_CHANNELED_SPELL); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_yogg_saron_diminsh_power_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_diminsh_power_AuraScript(); + } +}; + +// not sure about SPELL_WEAKENED part, where should it be handled? +class spell_yogg_saron_empowered : public SpellScriptLoader // 64161 +{ + public: + spell_yogg_saron_empowered() : SpellScriptLoader("spell_yogg_saron_empowered") { } + + class spell_yogg_saron_empowered_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_empowered_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_EMPOWERED_BUFF)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WEAKENED)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastCustomSpell(SPELL_EMPOWERED_BUFF, SPELLVALUE_AURA_STACK, 9, GetTarget(), TRIGGERED_FULL_MASK); + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + Unit* target = GetTarget(); + float stack = ceil((target->GetHealthPct() / 10) - 1); + target->RemoveAurasDueToSpell(SPELL_EMPOWERED_BUFF); + + if (stack) + { + target->RemoveAurasDueToSpell(SPELL_WEAKENED); + target->CastCustomSpell(SPELL_EMPOWERED_BUFF, SPELLVALUE_AURA_STACK, stack, target, TRIGGERED_FULL_MASK); + } + else if (!target->HealthAbovePct(1) && !target->HasAura(SPELL_WEAKENED)) + target->CastSpell(target, SPELL_WEAKENED, true); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_empowered_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_empowered_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_empowered_AuraScript(); + } +}; + +class spell_yogg_saron_match_health : public SpellScriptLoader // 64069 +{ + public: + spell_yogg_saron_match_health() : SpellScriptLoader("spell_yogg_saron_match_health") { } + + class spell_yogg_saron_match_health_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_match_health_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->SetHealth(target->CountPctFromMaxHealth((int32)GetCaster()->GetHealthPct())); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_match_health_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_match_health_SpellScript(); + } +}; + +class spell_yogg_saron_shattered_illusion : public SpellScriptLoader // 65238 +{ + public: + spell_yogg_saron_shattered_illusion() : SpellScriptLoader("spell_yogg_saron_shattered_illusion") { } + + class spell_yogg_saron_shattered_illusion_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_shattered_illusion_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->RemoveAurasDueToSpell(uint32(GetEffectValue())); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_shattered_illusion_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_shattered_illusion_SpellScript(); + } +}; + +class spell_yogg_saron_death_ray_warning_visual : public SpellScriptLoader // 63882 +{ + public: + spell_yogg_saron_death_ray_warning_visual() : SpellScriptLoader("spell_yogg_saron_death_ray_warning_visual") { } + + class spell_yogg_saron_death_ray_warning_visual_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_death_ray_warning_visual_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_RAY_PERIODIC)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_RAY_DAMAGE_VISUAL)) + return false; + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + caster->CastSpell(caster, SPELL_DEATH_RAY_PERIODIC, true); + caster->CastSpell((Unit*)NULL, SPELL_DEATH_RAY_DAMAGE_VISUAL, true); + // TODO: set better movement + caster->GetMotionMaster()->MoveConfused(); + } + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_death_ray_warning_visual_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_death_ray_warning_visual_AuraScript(); + } +}; + +class spell_yogg_saron_cancel_illusion_room_aura : public SpellScriptLoader // 63993 +{ + public: + spell_yogg_saron_cancel_illusion_room_aura() : SpellScriptLoader("spell_yogg_saron_cancel_illusion_room_aura") { } + + class spell_yogg_saron_cancel_illusion_room_aura_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_cancel_illusion_room_aura_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_TELEPORT_BACK_TO_MAIN_ROOM)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->CastSpell(target, SPELL_TELEPORT_BACK_TO_MAIN_ROOM); + target->RemoveAurasDueToSpell(uint32(GetEffectValue())); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_cancel_illusion_room_aura_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_cancel_illusion_room_aura_SpellScript(); + } +}; + +class spell_yogg_saron_nondescript : public SpellScriptLoader // 64010, 64013 +{ + public: + spell_yogg_saron_nondescript() : SpellScriptLoader("spell_yogg_saron_nondescript") { } + + class spell_yogg_saron_nondescript_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_nondescript_AuraScript); + + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), uint32(aurEff->GetAmount()), true); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_nondescript_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_nondescript_AuraScript(); + } +}; + +class spell_yogg_saron_revealed_tentacle : public SpellScriptLoader // 64012 +{ + public: + spell_yogg_saron_revealed_tentacle() : SpellScriptLoader("spell_yogg_saron_revealed_tentacle") { } + + class spell_yogg_saron_revealed_tentacle_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_revealed_tentacle_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_TENTACLE_VOID_ZONE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_GRIM_REPRISAL)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Creature* caster = GetCaster()->ToCreature()) + { + caster->CastSpell(caster, SPELL_TENTACLE_VOID_ZONE, true); + caster->CastSpell(caster, SPELL_GRIM_REPRISAL, true); + caster->UpdateEntry(NPC_INFLUENCE_TENTACLE, 0, caster->GetCreatureData()); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_revealed_tentacle_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_revealed_tentacle_SpellScript(); + } +}; + +class spell_yogg_saron_grim_reprisal : public SpellScriptLoader // 63305 +{ + public: + spell_yogg_saron_grim_reprisal() : SpellScriptLoader("spell_yogg_saron_grim_reprisal") { } + + class spell_yogg_saron_grim_reprisal_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_grim_reprisal_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_GRIM_REPRISAL_DAMAGE)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + int32 damage = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), 60); + GetTarget()->CastCustomSpell(SPELL_GRIM_REPRISAL_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetDamageInfo()->GetAttacker(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_yogg_saron_grim_reprisal_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_grim_reprisal_AuraScript(); + } +}; + +class spell_yogg_saron_induce_madness : public SpellScriptLoader // 64059 +{ + public: + spell_yogg_saron_induce_madness() : SpellScriptLoader("spell_yogg_saron_induce_madness") { } + + class spell_yogg_saron_induce_madness_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_induce_madness_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_TELEPORT_BACK_TO_MAIN_ROOM)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHATTERED_ILLUSION_REMOVE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->CastSpell(target, SPELL_TELEPORT_BACK_TO_MAIN_ROOM); + target->RemoveAurasDueToSpell(SPELL_SANITY, 0, 0, AURA_REMOVE_BY_ENEMY_SPELL); + target->RemoveAurasDueToSpell(uint32(GetEffectValue())); + } + } + + void ClearShatteredIllusion() + { + GetCaster()->CastSpell((Unit*)NULL, SPELL_SHATTERED_ILLUSION_REMOVE); + + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* voice = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_induce_madness_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + AfterCast += SpellCastFn(spell_yogg_saron_induce_madness_SpellScript::ClearShatteredIllusion); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_induce_madness_SpellScript(); + } +}; + +class spell_yogg_saron_sanity : public SpellScriptLoader // 63050 +{ + public: + spell_yogg_saron_sanity() : SpellScriptLoader("spell_yogg_saron_sanity") { } + + class spell_yogg_saron_sanity_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_sanity_SpellScript); + + // don't target players outside of room or handle it in SPELL_INSANE_PERIODIC? + + void ModSanityStacks() + { + GetSpell()->SetSpellValue(SPELLVALUE_AURA_STACK, 100); + } + + void Register() + { + BeforeCast += SpellCastFn(spell_yogg_saron_sanity_SpellScript::ModSanityStacks); + } + }; + + class spell_yogg_saron_sanity_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_sanity_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_LOW_SANITY_SCREEN_EFFECT)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_INSANE)) + return false; + return true; + } + + void DummyTick(AuraEffect const* aurEff) + { + if (GetTarget()->HasAura(SPELL_SANITY_WELL)) + ModStackAmount(20); + + if (GetStackAmount() <= 40 && !GetTarget()->HasAura(SPELL_LOW_SANITY_SCREEN_EFFECT)) + GetTarget()->CastSpell(GetTarget(), SPELL_LOW_SANITY_SCREEN_EFFECT, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + if (InstanceScript* instance = GetTarget()->GetInstanceScript()) + instance->SetData(DATA_DRIVE_ME_CRAZY, uint32(false)); + + GetTarget()->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + + if (Unit* caster = GetCaster()) + caster->CastSpell(GetTarget(), SPELL_INSANE, true); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_sanity_AuraScript::DummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_sanity_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_sanity_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_sanity_AuraScript(); + } +}; + +class spell_yogg_saron_insane : public SpellScriptLoader // 63120 +{ + public: + spell_yogg_saron_insane() : SpellScriptLoader("spell_yogg_saron_insane") { } + + class spell_yogg_saron_insane_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_insane_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_INSANE_VISUAL)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (Creature* yogg = caster->ToCreature()) + yogg->AI()->Talk(WHISPER_VOICE_INSANE, GetTarget()->GetGUID()); + + GetTarget()->CastSpell(GetTarget(), SPELL_INSANE_VISUAL, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTarget()->isAlive()) + GetTarget()->Kill(GetTarget()); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_insane_AuraScript::OnApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_insane_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_insane_AuraScript(); + } +}; + +class spell_yogg_saron_insane_periodic : public SpellScriptLoader // 64555 +{ + public: + spell_yogg_saron_insane_periodic() : SpellScriptLoader("spell_yogg_saron_insane_periodic") { } + + class spell_yogg_saron_insane_periodic_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_insane_periodic_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, uint32(GetEffectValue()), true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_insane_periodic_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_insane_periodic_SpellScript(); + } +}; + +class LunaticGazeTargetSelector +{ + public: + LunaticGazeTargetSelector(Unit* caster) : _caster(caster) { } + + bool operator()(WorldObject* object) + { + return !object->HasInArc(static_cast<float>(M_PI), _caster); + } + + private: + Unit* _caster; +}; + +class spell_yogg_saron_lunatic_gaze : public SpellScriptLoader // 64164, 64168 +{ + public: + spell_yogg_saron_lunatic_gaze() : SpellScriptLoader("spell_yogg_saron_lunatic_gaze") { } + + class spell_yogg_saron_lunatic_gaze_SpellScript : public SanityReduction + { + PrepareSpellScript(spell_yogg_saron_lunatic_gaze_SpellScript); + + bool Load() + { + _stacks = GetSpellInfo()->Id == SPELL_LUNATIC_GAZE_DAMAGE ? 4 : 2; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(LunaticGazeTargetSelector(GetCaster())); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_lunatic_gaze_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_lunatic_gaze_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_lunatic_gaze_SpellScript::RemoveSanity, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_lunatic_gaze_SpellScript(); + } +}; + +class spell_yogg_saron_keeper_aura : public SpellScriptLoader // 62650, 62670, 62671, 62702 +{ + public: + spell_yogg_saron_keeper_aura() : SpellScriptLoader("spell_yogg_saron_keeper_aura") { } + + class spell_yogg_saron_keeper_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_keeper_aura_AuraScript); + + bool CanApply(Unit* target) + { + if (target->GetTypeId() != TYPEID_PLAYER && target != GetCaster()) + return false; + return true; + } + + void Register() + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_yogg_saron_keeper_aura_AuraScript::CanApply); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_keeper_aura_AuraScript(); + } +}; + +class spell_yogg_saron_hate_to_zero : public SpellScriptLoader // 63984 +{ + public: + spell_yogg_saron_hate_to_zero() : SpellScriptLoader("spell_yogg_saron_hate_to_zero") { } + + class spell_yogg_saron_hate_to_zero_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_hate_to_zero_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (target->CanHaveThreatList()) + target->getThreatManager().modifyThreatPercent(GetCaster(), -100); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_hate_to_zero_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_hate_to_zero_SpellScript(); + } +}; + +class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader // 64184 +{ + public: + spell_yogg_saron_in_the_maws_of_the_old_god() : SpellScriptLoader("spell_yogg_saron_in_the_maws_of_the_old_god") { } + + class spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript); + + SpellCastResult CheckRequirement() + { + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* yogg = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(BOSS_YOGG_SARON))) + if (yogg->FindCurrentSpellBySpellId(SPELL_DEAFENING_ROAR)) + if (GetCaster()->GetDistance(yogg) > 20.0f) + return SPELL_FAILED_OUT_OF_RANGE; + else + return SPELL_CAST_OK; + + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript::CheckRequirement); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript(); + } +}; + +class spell_yogg_saron_titanic_storm : public SpellScriptLoader // 64172 +{ + public: + spell_yogg_saron_titanic_storm() : SpellScriptLoader("spell_yogg_saron_titanic_storm") { } + + class spell_yogg_saron_titanic_storm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_yogg_saron_titanic_storm_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + GetCaster()->Kill(target); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_titanic_storm_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_yogg_saron_titanic_storm_SpellScript(); + } +}; + +class spell_yogg_saron_hodirs_protective_gaze : public SpellScriptLoader // 64174 +{ + public: + spell_yogg_saron_hodirs_protective_gaze() : SpellScriptLoader("spell_yogg_saron_hodirs_protective_gaze") { } + + class spell_yogg_saron_hodirs_protective_gaze_AuraScript : public AuraScript + { + PrepareAuraScript(spell_yogg_saron_hodirs_protective_gaze_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_FLASH_FREEZE)) + return false; + return true; + } + + bool CanApply(Unit* target) + { + if (target->GetTypeId() != TYPEID_PLAYER && target != GetCaster()) + return false; + return true; + } + + void OnAbsorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount) + { + if (dmgInfo.GetDamage() >= GetTarget()->GetHealth()) + { + absorbAmount = dmgInfo.GetDamage(); + // or absorbAmount = dmgInfo.GetDamage() - GetTarget()->GetHealth() + 1 + GetTarget()->CastSpell(GetTarget(), SPELL_FLASH_FREEZE, true); + } + else + PreventDefaultAction(); + } + + void Register() + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_yogg_saron_hodirs_protective_gaze_AuraScript::CanApply); + OnEffectAbsorb += AuraEffectAbsorbFn(spell_yogg_saron_hodirs_protective_gaze_AuraScript::OnAbsorb, EFFECT_0); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_yogg_saron_hodirs_protective_gaze_AuraScript(); + } +}; + +void AddSC_boss_yogg_saron() +{ + new boss_voice_of_yogg_saron(); + new boss_sara(); + new boss_yogg_saron(); + new boss_brain_of_yogg_saron(); + new npc_ominous_cloud(); + new npc_guardian_of_yogg_saron(); + new npc_corruptor_tentacle(); + new npc_constrictor_tentacle(); + new npc_crusher_tentacle(); + new npc_influence_tentacle(); + new npc_descend_into_madness(); + new npc_immortal_guardian(); + new npc_observation_ring_keeper(); + new npc_yogg_saron_keeper(); + new npc_yogg_saron_illusions(); + new npc_garona(); + new npc_turned_champion(); + new npc_laughing_skull(); + new spell_yogg_saron_target_selectors(); + new spell_yogg_saron_psychosis(); + new spell_yogg_saron_malady_of_the_mind(); + new spell_yogg_saron_brain_link(); + new spell_yogg_saron_brain_link_damage(); + new spell_yogg_saron_boil_ominously(); + new spell_yogg_saron_shadow_beacon(); + new spell_yogg_saron_empowering_shadows_range_check(); + new spell_yogg_saron_empowering_shadows_missile(); + new spell_yogg_saron_constrictor_tentacle(); + new spell_yogg_saron_lunge(); + new spell_yogg_saron_squeeze(); + new spell_yogg_saron_diminsh_power(); + new spell_yogg_saron_empowered(); + new spell_yogg_saron_match_health(); + new spell_yogg_saron_shattered_illusion(); + new spell_yogg_saron_death_ray_warning_visual(); + new spell_yogg_saron_cancel_illusion_room_aura(); + new spell_yogg_saron_nondescript(); + new spell_yogg_saron_revealed_tentacle(); + new spell_yogg_saron_grim_reprisal(); + new spell_yogg_saron_induce_madness(); + new spell_yogg_saron_sanity(); + new spell_yogg_saron_insane(); + new spell_yogg_saron_insane_periodic(); + new spell_yogg_saron_lunatic_gaze(); + new spell_yogg_saron_keeper_aura(); + new spell_yogg_saron_hate_to_zero(); + new spell_yogg_saron_in_the_maws_of_the_old_god(); + new spell_yogg_saron_titanic_storm(); + new spell_yogg_saron_hodirs_protective_gaze(); +} diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp deleted file mode 100644 index 4bcb1b9e584..00000000000 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ScriptMgr.h" -#include "ulduar.h" - -enum Sara -{ - // text - YELL_SARA_PREFIGHT = 0, - YELL_COMBAT_PHASE_1 = 1, - YELL_COMBAT_PHASE_2 = 2, - YELL_SLAY = 3, - - // Phase 1 spells - SPELL_SARAS_ANGER_1 = 63147, // Target Entry 33136 - SPELL_SARAS_ANGER_2 = 63744, // Target Entry 33136 - SPELL_SARAS_FEVOR_1 = 63138, // Target Player - SPELL_SARAS_FEVOR_2 = 63747, // Target Player - SPELL_SARAS_BLESSING_1 = 63134, // Target Player - SPELL_SARAS_BLESSING_2 = 63745, // Target Self - - // Phase 2 spells - SPELL_PHYCHOSIS = 63795, // Target Self - SPELL_MALADY_OF_THE_MIND = 63830, // Target Self - SPELL_DEATH_RAY = 63891, // Target Self - SPELL_BRAIN_LINK = 63802, // Target Self -}; - -enum YoggSaron_Yells -{ -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 21001, -}; -//not in scriptloader yet just to remove warning boss_yoggsaron.obj : warning LNK4221: no public symbols found; archive member will be inaccessible -void AddSC_boss_yoggsaron() -{ -} diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 125f66497bf..421d0ecf3c9 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -24,14 +24,15 @@ static DoorData const doorData[] = { - {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, - {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, + {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, + {GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S }, + {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, + {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, }; MinionData const minionData[] = @@ -56,7 +57,6 @@ class instance_ulduar : public InstanceMapScript uint64 IgnisGUID; uint64 RazorscaleGUID; uint64 RazorscaleController; - uint64 RazorHarpoonGUIDs[4]; uint64 ExpeditionCommanderGUID; uint64 XT002GUID; uint64 XTToyPileGUIDs[4]; @@ -67,14 +67,18 @@ class instance_ulduar : public InstanceMapScript uint64 HodirGUID; uint64 ThorimGUID; uint64 FreyaGUID; - uint64 KeeperGUIDs[3]; + uint64 ElderGUIDs[3]; uint64 VezaxGUID; uint64 YoggSaronGUID; + uint64 VoiceOfYoggSaronGUID; + uint64 SaraGUID; + uint64 BrainOfYoggSaronGUID; uint64 AlgalonGUID; - uint64 LeviathanGateGUID; - uint64 VezaxDoorGUID; + uint64 BrannBronzebeardAlgGUID; // GameObjects + uint64 LeviathanGateGUID; + uint64 RazorHarpoonGUIDs[4]; uint64 KologarnChestGUID; uint64 KologarnBridgeGUID; uint64 KologarnDoorGUID; @@ -84,11 +88,13 @@ class instance_ulduar : public InstanceMapScript uint64 HodirDoorGUID; uint64 HodirIceDoorGUID; uint64 ArchivumDoorGUID; + uint64 VezaxDoorGUID; + uint64 BrainRoomDoorGUIDs[3]; + uint64 KeeperGUIDs[4]; uint64 AlgalonSigilDoorGUID[3]; uint64 AlgalonFloorGUID[2]; uint64 AlgalonUniverseGUID; uint64 AlgalonTrapdoorGUID; - uint64 BrannBronzebeardAlgGUID; uint64 GiftOfTheObserverGUID; // Miscellaneous @@ -96,8 +102,11 @@ class instance_ulduar : public InstanceMapScript uint32 HodirRareCacheData; uint32 ColossusData; uint8 elderCount; + uint8 illusion; + uint8 keepersCount; bool conSpeedAtory; bool Unbroken; + bool IsDriveMeCrazyEligible; std::set<uint64> mRubbleSpawns; @@ -119,6 +128,9 @@ class instance_ulduar : public InstanceMapScript FreyaGUID = 0; VezaxGUID = 0; YoggSaronGUID = 0; + VoiceOfYoggSaronGUID = 0; + SaraGUID = 0; + BrainOfYoggSaronGUID = 0; AlgalonGUID = 0; KologarnChestGUID = 0; KologarnBridgeGUID = 0; @@ -141,6 +153,8 @@ class instance_ulduar : public InstanceMapScript HodirRareCacheData = 0; ColossusData = 0; elderCount = 0; + illusion = 0; + keepersCount = 0; conSpeedAtory = false; Unbroken = true; _algalonSummoned = false; @@ -151,7 +165,11 @@ class instance_ulduar : public InstanceMapScript memset(XTToyPileGUIDs, 0, sizeof(XTToyPileGUIDs)); memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs)); memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs)); + memset(ElderGUIDs, 0, sizeof(ElderGUIDs)); + memset(BrainRoomDoorGUIDs, 0, sizeof(BrainRoomDoorGUIDs)); memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs)); + memset(_summonObservationRingKeeper, false, sizeof(_summonObservationRingKeeper)); + memset(_summonYSKeeper, false, sizeof(_summonYSKeeper)); } void FillInitialWorldStates(WorldPacket& packet) @@ -174,6 +192,38 @@ class instance_ulduar : public InstanceMapScript else algalon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); } + + // Keepers at Observation Ring + if (GetBossState(BOSS_FREYA) == DONE && _summonObservationRingKeeper[0] && !KeeperGUIDs[0]) + { + _summonObservationRingKeeper[0] = false; + instance->SummonCreature(NPC_FREYA_OBSERVATION_RING, ObservationRingKeepersPos[0]); + } + if (GetBossState(BOSS_HODIR) == DONE && _summonObservationRingKeeper[1] && !KeeperGUIDs[1]) + { + _summonObservationRingKeeper[1] = false; + instance->SummonCreature(NPC_HODIR_OBSERVATION_RING, ObservationRingKeepersPos[1]); + } + if (GetBossState(BOSS_THORIM) == DONE && _summonObservationRingKeeper[2] && !KeeperGUIDs[2]) + { + _summonObservationRingKeeper[2] = false; + instance->SummonCreature(NPC_THORIM_OBSERVATION_RING, ObservationRingKeepersPos[2]); + } + if (GetBossState(BOSS_MIMIRON) == DONE && _summonObservationRingKeeper[3] && !KeeperGUIDs[3]) + { + _summonObservationRingKeeper[3] = false; + instance->SummonCreature(NPC_MIMIRON_OBSERVATION_RING, ObservationRingKeepersPos[3]); + } + + // Keepers in Yogg-Saron's room + if (_summonYSKeeper[0]) + instance->SummonCreature(NPC_FREYA_YS, YSKeepersPos[0]); + if (_summonYSKeeper[1]) + instance->SummonCreature(NPC_HODIR_YS, YSKeepersPos[1]); + if (_summonYSKeeper[2]) + instance->SummonCreature(NPC_THORIM_YS, YSKeepersPos[2]); + if (_summonYSKeeper[3]) + instance->SummonCreature(NPC_MIMIRON_YS, YSKeepersPos[3]); } void OnCreatureCreate(Creature* creature) @@ -194,6 +244,8 @@ class instance_ulduar : public InstanceMapScript case NPC_IGNIS: IgnisGUID = creature->GetGUID(); break; + + // Razorscale case NPC_RAZORSCALE: RazorscaleGUID = creature->GetGUID(); break; @@ -203,6 +255,8 @@ class instance_ulduar : public InstanceMapScript case NPC_EXPEDITION_COMMANDER: ExpeditionCommanderGUID = creature->GetGUID(); break; + + // XT-002 Deconstructor case NPC_XT002: XT002GUID = creature->GetGUID(); break; @@ -229,24 +283,6 @@ class instance_ulduar : public InstanceMapScript AddMinion(creature, true); break; - // Freya's Keeper - case NPC_IRONBRANCH: - KeeperGUIDs[0] = creature->GetGUID(); - if (GetBossState(BOSS_FREYA) == DONE) - creature->DespawnOrUnsummon(); - break; - case NPC_BRIGHTLEAF: - KeeperGUIDs[1] = creature->GetGUID(); - if (GetBossState(BOSS_FREYA) == DONE) - creature->DespawnOrUnsummon(); - break; - case NPC_STONEBARK: - KeeperGUIDs[2] = creature->GetGUID(); - if (GetBossState(BOSS_FREYA) == DONE) - creature->DespawnOrUnsummon(); - break; - - // Kologarn case NPC_KOLOGARN: KologarnGUID = creature->GetGUID(); break; @@ -256,25 +292,11 @@ class instance_ulduar : public InstanceMapScript case NPC_MIMIRON: MimironGUID = creature->GetGUID(); break; + + // Hodir case NPC_HODIR: HodirGUID = creature->GetGUID(); break; - case NPC_THORIM: - ThorimGUID = creature->GetGUID(); - break; - case NPC_FREYA: - FreyaGUID = creature->GetGUID(); - break; - case NPC_VEZAX: - VezaxGUID = creature->GetGUID(); - break; - case NPC_YOGGSARON: - YoggSaronGUID = creature->GetGUID(); - break; - case NPC_ALGALON: - AlgalonGUID = creature->GetGUID(); - break; - // Hodir's Helper NPCs case NPC_EIVI_NIGHTFEATHER: if (TeamInInstance == HORDE) creature->UpdateEntry(NPC_TOR_GREYCLOUD, HORDE); @@ -307,6 +329,80 @@ class instance_ulduar : public InstanceMapScript if (TeamInInstance == HORDE) creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA, HORDE); break; + + case NPC_THORIM: + ThorimGUID = creature->GetGUID(); + break; + + // Freya + case NPC_FREYA: + FreyaGUID = creature->GetGUID(); + break; + case NPC_IRONBRANCH: + ElderGUIDs[0] = creature->GetGUID(); + if (GetBossState(BOSS_FREYA) == DONE) + creature->DespawnOrUnsummon(); + break; + case NPC_BRIGHTLEAF: + ElderGUIDs[1] = creature->GetGUID(); + if (GetBossState(BOSS_FREYA) == DONE) + creature->DespawnOrUnsummon(); + break; + case NPC_STONEBARK: + ElderGUIDs[2] = creature->GetGUID(); + if (GetBossState(BOSS_FREYA) == DONE) + creature->DespawnOrUnsummon(); + break; + + case NPC_VEZAX: + VezaxGUID = creature->GetGUID(); + break; + + // Yogg-Saron + case NPC_YOGG_SARON: + YoggSaronGUID = creature->GetGUID(); + break; + case NPC_VOICE_OF_YOGG_SARON: + VoiceOfYoggSaronGUID = creature->GetGUID(); + break; + case NPC_BRAIN_OF_YOGG_SARON: + BrainOfYoggSaronGUID = creature->GetGUID(); + break; + case NPC_SARA: + SaraGUID = creature->GetGUID(); + break; + case NPC_FREYA_YS: + KeeperGUIDs[0] = creature->GetGUID(); + _summonYSKeeper[0] = false; + SaveToDB(); + ++keepersCount; + break; + case NPC_HODIR_YS: + KeeperGUIDs[1] = creature->GetGUID(); + _summonYSKeeper[1] = false; + SaveToDB(); + ++keepersCount; + break; + case NPC_THORIM_YS: + KeeperGUIDs[2] = creature->GetGUID(); + _summonYSKeeper[2] = false; + SaveToDB(); + ++keepersCount; + break; + case NPC_MIMIRON_YS: + KeeperGUIDs[3] = creature->GetGUID(); + _summonYSKeeper[3] = false; + SaveToDB(); + ++keepersCount; + break; + case NPC_SANITY_WELL: + creature->SetReactState(REACT_PASSIVE); + break; + + // Algalon + case NPC_ALGALON: + AlgalonGUID = creature->GetGUID(); + break; case NPC_BRANN_BRONZBEARD_ALG: BrannBronzebeardAlgGUID = creature->GetGUID(); break; @@ -418,6 +514,18 @@ class instance_ulduar : public InstanceMapScript if (GetBossState(BOSS_ASSEMBLY_OF_IRON) != DONE) HandleGameObject(ArchivumDoorGUID, false); break; + case GO_YOGG_SARON_DOOR: + AddDoor(gameObject, true); + break; + case GO_BRAIN_ROOM_DOOR_1: + BrainRoomDoorGUIDs[0] = gameObject->GetGUID(); + break; + case GO_BRAIN_ROOM_DOOR_2: + BrainRoomDoorGUIDs[1] = gameObject->GetGUID(); + break; + case GO_BRAIN_ROOM_DOOR_3: + BrainRoomDoorGUIDs[2] = gameObject->GetGUID(); + break; case GO_CELESTIAL_PLANETARIUM_ACCESS_10: case GO_CELESTIAL_PLANETARIUM_ACCESS_25: if (_algalonSummoned) @@ -509,27 +617,36 @@ class instance_ulduar : public InstanceMapScript { // Flame Leviathan's Tower Event triggers Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID); - if (FlameLeviathan && FlameLeviathan->isAlive()) // No leviathan, no event triggering ;) + + switch (eventId) { - switch (eventId) - { - case EVENT_TOWER_OF_STORM_DESTROYED: + case EVENT_TOWER_OF_STORM_DESTROYED: + if (FlameLeviathan && FlameLeviathan->isAlive()) FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_STORM_DESTROYED); - break; - case EVENT_TOWER_OF_FROST_DESTROYED: + break; + case EVENT_TOWER_OF_FROST_DESTROYED: + if (FlameLeviathan && FlameLeviathan->isAlive()) FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FROST_DESTROYED); - break; - case EVENT_TOWER_OF_FLAMES_DESTROYED: + break; + case EVENT_TOWER_OF_FLAMES_DESTROYED: + if (FlameLeviathan && FlameLeviathan->isAlive()) FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FLAMES_DESTROYED); - break; - case EVENT_TOWER_OF_LIFE_DESTROYED: + break; + case EVENT_TOWER_OF_LIFE_DESTROYED: + if (FlameLeviathan && FlameLeviathan->isAlive()) FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED); - break; - } + break; + case EVENT_ACTIVATE_SANITY_WELL: + if (Creature* freya = instance->GetCreature(KeeperGUIDs[0])) + freya->AI()->DoAction(4/*ACTION_SANITY_WELLS*/); + break; + case EVENT_HODIRS_PROTECTIVE_GAZE_PROC: + if (Creature* hodir = instance->GetCreature(KeeperGUIDs[1])) + hodir->AI()->DoAction(5/*ACTION_FLASH_FREEZE*/); + break; } } - bool SetBossState(uint32 type, EncounterState state) { if (!InstanceScript::SetBossState(type, state)) @@ -542,8 +659,14 @@ class instance_ulduar : public InstanceMapScript case BOSS_RAZORSCALE: case BOSS_XT002: case BOSS_AURIAYA: + break; case BOSS_MIMIRON: + if (state == DONE) + instance->SummonCreature(NPC_MIMIRON_OBSERVATION_RING, ObservationRingKeepersPos[3]); + break; case BOSS_FREYA: + if (state == DONE) + instance->SummonCreature(NPC_FREYA_OBSERVATION_RING, ObservationRingKeepersPos[0]); break; case BOSS_ASSEMBLY_OF_IRON: if (state == DONE) @@ -553,7 +676,7 @@ class instance_ulduar : public InstanceMapScript if (state == DONE) HandleGameObject(VezaxDoorGUID, true); break; - case BOSS_YOGGSARON: + case BOSS_YOGG_SARON: break; case BOSS_KOLOGARN: if (state == DONE) @@ -576,12 +699,18 @@ class instance_ulduar : public InstanceMapScript HodirChest->SetRespawnTime(HodirChest->GetRespawnDelay()); HandleGameObject(HodirDoorGUID, true); HandleGameObject(HodirIceDoorGUID, true); + + instance->SummonCreature(NPC_HODIR_OBSERVATION_RING, ObservationRingKeepersPos[1]); } break; case BOSS_THORIM: if (state == DONE) + { if (GameObject* gameObject = instance->GetGameObject(ThorimChestGUID)) gameObject->SetRespawnTime(gameObject->GetRespawnDelay()); + + instance->SummonCreature(NPC_THORIM_OBSERVATION_RING, ObservationRingKeepersPos[2]); + } break; case BOSS_ALGALON: if (state == DONE) @@ -661,6 +790,12 @@ class instance_ulduar : public InstanceMapScript case DATA_UNBROKEN: Unbroken = bool(data); break; + case DATA_ILLUSION: + illusion = data; + break; + case DATA_DRIVE_ME_CRAZY: + IsDriveMeCrazyEligible = data ? true : false; + break; case EVENT_DESPAWN_ALGALON: DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1); DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, 60); @@ -688,10 +823,24 @@ class instance_ulduar : public InstanceMapScript return LeviathanGUID; case BOSS_IGNIS: return IgnisGUID; + + // Razorscale case BOSS_RAZORSCALE: return RazorscaleGUID; case DATA_RAZORSCALE_CONTROL: return RazorscaleController; + case DATA_EXPEDITION_COMMANDER: + return ExpeditionCommanderGUID; + case GO_RAZOR_HARPOON_1: + return RazorHarpoonGUIDs[0]; + case GO_RAZOR_HARPOON_2: + return RazorHarpoonGUIDs[1]; + case GO_RAZOR_HARPOON_3: + return RazorHarpoonGUIDs[2]; + case GO_RAZOR_HARPOON_4: + return RazorHarpoonGUIDs[3]; + + // XT-002 Deconstructor case BOSS_XT002: return XT002GUID; case DATA_TOY_PILE_0: @@ -699,6 +848,15 @@ class instance_ulduar : public InstanceMapScript case DATA_TOY_PILE_2: case DATA_TOY_PILE_3: return XTToyPileGUIDs[data - DATA_TOY_PILE_0]; + + // Assembly of Iron + case DATA_STEELBREAKER: + return AssemblyGUIDs[0]; + case DATA_MOLGEIM: + return AssemblyGUIDs[1]; + case DATA_BRUNDIR: + return AssemblyGUIDs[2]; + case BOSS_KOLOGARN: return KologarnGUID; case BOSS_AURIAYA: @@ -709,42 +867,47 @@ class instance_ulduar : public InstanceMapScript return HodirGUID; case BOSS_THORIM: return ThorimGUID; + + // Freya case BOSS_FREYA: return FreyaGUID; + case BOSS_BRIGHTLEAF: + return ElderGUIDs[0]; + case BOSS_IRONBRANCH: + return ElderGUIDs[1]; + case BOSS_STONEBARK: + return ElderGUIDs[2]; + case BOSS_VEZAX: return VezaxGUID; - case BOSS_YOGGSARON: - return YoggSaronGUID; - case BOSS_ALGALON: - return AlgalonGUID; - // Razorscale expedition commander - case DATA_EXPEDITION_COMMANDER: - return ExpeditionCommanderGUID; - case GO_RAZOR_HARPOON_1: - return RazorHarpoonGUIDs[0]; - case GO_RAZOR_HARPOON_2: - return RazorHarpoonGUIDs[1]; - case GO_RAZOR_HARPOON_3: - return RazorHarpoonGUIDs[2]; - case GO_RAZOR_HARPOON_4: - return RazorHarpoonGUIDs[3]; - - // Assembly of Iron - case DATA_STEELBREAKER: - return AssemblyGUIDs[0]; - case DATA_MOLGEIM: - return AssemblyGUIDs[1]; - case DATA_BRUNDIR: - return AssemblyGUIDs[2]; - - // Freya's Keepers - case BOSS_BRIGHTLEAF: + // Yogg-Saron + case BOSS_YOGG_SARON: + return YoggSaronGUID; + case DATA_VOICE_OF_YOGG_SARON: + return VoiceOfYoggSaronGUID; + case DATA_BRAIN_OF_YOGG_SARON: + return BrainOfYoggSaronGUID; + case DATA_SARA: + return SaraGUID; + case GO_BRAIN_ROOM_DOOR_1: + return BrainRoomDoorGUIDs[0]; + case GO_BRAIN_ROOM_DOOR_2: + return BrainRoomDoorGUIDs[1]; + case GO_BRAIN_ROOM_DOOR_3: + return BrainRoomDoorGUIDs[2]; + case DATA_FREYA_YS: return KeeperGUIDs[0]; - case BOSS_IRONBRANCH: + case DATA_HODIR_YS: return KeeperGUIDs[1]; - case BOSS_STONEBARK: + case DATA_THORIM_YS: return KeeperGUIDs[2]; + case DATA_MIMIRON_YS: + return KeeperGUIDs[3]; + + // Algalon + case BOSS_ALGALON: + return AlgalonGUID; case DATA_SIGILDOOR_01: return AlgalonSigilDoorGUID[0]; case DATA_SIGILDOOR_02: @@ -776,6 +939,10 @@ class instance_ulduar : public InstanceMapScript return HodirRareCacheData; case DATA_UNBROKEN: return uint32(Unbroken); + case DATA_ILLUSION: + return illusion; + case DATA_KEEPERS_COUNT: + return keepersCount; default: break; } @@ -789,6 +956,30 @@ class instance_ulduar : public InstanceMapScript { case CRITERIA_HERALD_OF_TITANS: return _maxArmorItemLevel <= MAX_HERALD_ARMOR_ITEMLEVEL && _maxWeaponItemLevel <= MAX_HERALD_WEAPON_ITEMLEVEL; + case CRITERIA_WAITS_DREAMING_STORMWIND_25: + case CRITERIA_WAITS_DREAMING_STORMWIND_10: + return illusion == STORMWIND_ILLUSION; + case CRITERIA_WAITS_DREAMING_CHAMBER_25: + case CRITERIA_WAITS_DREAMING_CHAMBER_10: + return illusion == CHAMBER_ILLUSION; + case CRITERIA_WAITS_DREAMING_ICECROWN_25: + case CRITERIA_WAITS_DREAMING_ICECROWN_10: + return illusion == ICECROWN_ILLUSION; + case CRITERIA_DRIVE_ME_CRAZY_10: + case CRITERIA_DRIVE_ME_CRAZY_25: + return IsDriveMeCrazyEligible; + case CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_10: + case CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_25: + return keepersCount <= 3; + case CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_10: + case CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_25: + return keepersCount <= 2; + case CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_10: + case CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_25: + return keepersCount <= 1; + case CRITERIA_ALONE_IN_THE_DARKNESS_10: + case CRITERIA_ALONE_IN_THE_DARKNESS_25: + return keepersCount == 0; } return false; @@ -801,6 +992,9 @@ class instance_ulduar : public InstanceMapScript std::ostringstream saveStream; saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS) << ' ' << _algalonTimer << ' ' << (_algalonSummoned ? 1 : 0); + for (uint8 i = 0; i < 4; ++i) + saveStream << ' ' << (KeeperGUIDs[i] ? 1 : 0); + OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); } @@ -851,6 +1045,21 @@ class instance_ulduar : public InstanceMapScript DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, _algalonTimer); } } + + for (uint8 i = 0; i < 4; ++i) + { + loadStream >> tempState; + _summonYSKeeper[i] = tempState != 0; + } + + if (GetBossState(BOSS_FREYA) == DONE && !_summonYSKeeper[0]) + _summonObservationRingKeeper[0] = true; + if (GetBossState(BOSS_HODIR) == DONE && !_summonYSKeeper[1]) + _summonObservationRingKeeper[1] = true; + if (GetBossState(BOSS_THORIM) == DONE && !_summonYSKeeper[2]) + _summonObservationRingKeeper[2] = true; + if (GetBossState(BOSS_MIMIRON) == DONE && !_summonYSKeeper[3]) + _summonObservationRingKeeper[3] = true; } OUT_LOAD_INST_DATA_COMPLETE; @@ -889,6 +1098,8 @@ class instance_ulduar : public InstanceMapScript uint32 _algalonTimer; bool _summonAlgalon; bool _algalonSummoned; + bool _summonObservationRingKeeper[4]; + bool _summonYSKeeper[4]; uint32 _maxArmorItemLevel; uint32 _maxWeaponItemLevel; }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 08fd95d0e26..86c0c4888ed 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -21,6 +21,8 @@ #include "ObjectMgr.h" #define UlduarScriptName "instance_ulduar" +extern Position const ObservationRingKeepersPos[4]; +extern Position const YSKeepersPos[4]; extern Position const AlgalonLandPos; enum UlduarBosses @@ -42,7 +44,7 @@ enum UlduarBosses BOSS_IRONBRANCH = 12, BOSS_STONEBARK = 13, BOSS_VEZAX = 14, - BOSS_YOGGSARON = 15, + BOSS_YOGG_SARON = 15, BOSS_ALGALON = 16, }; @@ -74,7 +76,7 @@ enum UlduarNPCs NPC_THORIM = 32865, NPC_FREYA = 32906, NPC_VEZAX = 33271, - NPC_YOGGSARON = 33288, + NPC_YOGG_SARON = 33288, NPC_ALGALON = 32871, // Mimiron @@ -115,6 +117,39 @@ enum UlduarNPCs NPC_NATURES_BLADE = 33527, NPC_GUARDIAN_OF_LIFE = 33528, + // Yogg-Saron + NPC_SARA = 33134, + NPC_GUARDIAN_OF_YOGG_SARON = 33136, + NPC_HODIR_OBSERVATION_RING = 33213, + NPC_FREYA_OBSERVATION_RING = 33241, + NPC_THORIM_OBSERVATION_RING = 33242, + NPC_MIMIRON_OBSERVATION_RING = 33244, + NPC_VOICE_OF_YOGG_SARON = 33280, + NPC_OMINOUS_CLOUD = 33292, + NPC_FREYA_YS = 33410, + NPC_HODIR_YS = 33411, + NPC_MIMIRON_YS = 33412, + NPC_THORIM_YS = 33413, + NPC_SUIT_OF_ARMOR = 33433, + NPC_KING_LLANE = 33437, + NPC_THE_LICH_KING = 33441, + NPC_IMMOLATED_CHAMPION = 33442, + NPC_YSERA = 33495, + NPC_NELTHARION = 33523, + NPC_MALYGOS = 33535, + NPC_DEATH_RAY = 33881, + NPC_DEATH_ORB = 33882, + NPC_BRAIN_OF_YOGG_SARON = 33890, + NPC_INFLUENCE_TENTACLE = 33943, + NPC_TURNED_CHAMPION = 33962, + NPC_CRUSHER_TENTACLE = 33966, + NPC_CONSTRICTOR_TENTACLE = 33983, + NPC_CORRUPTOR_TENTACLE = 33985, + NPC_IMMORTAL_GUARDIAN = 33988, + NPC_SANITY_WELL = 33991, + NPC_DESCEND_INTO_MADNESS = 34072, + NPC_MARKED_IMMORTAL_GUARDIAN = 36064, + // Algalon the Observer NPC_BRANN_BRONZBEARD_ALG = 34064, NPC_AZEROTH = 34246, @@ -155,6 +190,12 @@ enum UlduarGameObjects GO_HODIR_ICE_DOOR = 194441, GO_ARCHIVUM_DOOR = 194556, + // Yogg-Saron + GO_YOGG_SARON_DOOR = 194773, + GO_BRAIN_ROOM_DOOR_1 = 194635, + GO_BRAIN_ROOM_DOOR_2 = 194636, + GO_BRAIN_ROOM_DOOR_3 = 194637, + // Algalon the Observer GO_CELESTIAL_PLANETARIUM_ACCESS_10 = 194628, GO_CELESTIAL_PLANETARIUM_ACCESS_25 = 194752, @@ -169,12 +210,18 @@ enum UlduarGameObjects GO_GIFT_OF_THE_OBSERVER_25 = 194822, }; -enum LeviathanData +enum EventIds { EVENT_TOWER_OF_STORM_DESTROYED = 21031, EVENT_TOWER_OF_FROST_DESTROYED = 21032, EVENT_TOWER_OF_FLAMES_DESTROYED = 21033, EVENT_TOWER_OF_LIFE_DESTROYED = 21030, + EVENT_ACTIVATE_SANITY_WELL = 21432, + EVENT_HODIRS_PROTECTIVE_GAZE_PROC = 21437, +}; + +enum LeviathanActions +{ ACTION_TOWER_OF_STORM_DESTROYED = 1, ACTION_TOWER_OF_FROST_DESTROYED = 2, ACTION_TOWER_OF_FLAMES_DESTROYED = 3, @@ -184,14 +231,30 @@ enum LeviathanData enum UlduarAchievementCriteriaIds { - CRITERIA_CON_SPEED_ATORY = 21597, - CRITERIA_DISARMED = 21687, - CRITERIA_HERALD_OF_TITANS = 10678, + CRITERIA_CON_SPEED_ATORY = 21597, + CRITERIA_DISARMED = 21687, + CRITERIA_WAITS_DREAMING_STORMWIND_25 = 10321, + CRITERIA_WAITS_DREAMING_CHAMBER_25 = 10322, + CRITERIA_WAITS_DREAMING_ICECROWN_25 = 10323, + CRITERIA_WAITS_DREAMING_STORMWIND_10 = 10324, + CRITERIA_WAITS_DREAMING_CHAMBER_10 = 10325, + CRITERIA_WAITS_DREAMING_ICECROWN_10 = 10326, + CRITERIA_DRIVE_ME_CRAZY_10 = 10185, + CRITERIA_DRIVE_ME_CRAZY_25 = 10296, + CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_10 = 10410, + CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_25 = 10414, + CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_10 = 10388, + CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_25 = 10415, + CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_10 = 10409, + CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_25 = 10416, + CRITERIA_ALONE_IN_THE_DARKNESS_10 = 10412, + CRITERIA_ALONE_IN_THE_DARKNESS_25 = 10417, + CRITERIA_HERALD_OF_TITANS = 10678, }; enum UlduarData { - // Collosus (Leviathan) + // Colossus (Leviathan) DATA_COLOSSUS = 20, // Razorscale @@ -212,6 +275,18 @@ enum UlduarData // Hodir DATA_HODIR_RARE_CACHE, + // Yogg-Saron + DATA_VOICE_OF_YOGG_SARON, + DATA_SARA, + DATA_BRAIN_OF_YOGG_SARON, + DATA_FREYA_YS, + DATA_HODIR_YS, + DATA_THORIM_YS, + DATA_MIMIRON_YS, + DATA_ILLUSION, + DATA_DRIVE_ME_CRAZY, + DATA_KEEPERS_COUNT, + // Algalon the Observer DATA_ALGALON_SUMMON_STATE, DATA_SIGILDOOR_01, @@ -245,6 +320,13 @@ enum UlduarEvents ACTION_INIT_ALGALON = 6, }; +enum YoggSaronIllusions +{ + CHAMBER_ILLUSION = 0, + ICECROWN_ILLUSION = 1, + STORMWIND_ILLUSION = 2, +}; + template<class AI> CreatureAI* GetUlduarAI(Creature* creature) { |