diff --git a/VC100/100ScriptDev2.vcxproj b/VC100/100ScriptDev2.vcxproj index 839c203026..9b050e59a4 100644 --- a/VC100/100ScriptDev2.vcxproj +++ b/VC100/100ScriptDev2.vcxproj @@ -107,6 +107,7 @@ true true true + /Zm200 mangosd.lib;ACEd.lib;framework.lib;%(AdditionalDependencies) @@ -138,6 +139,7 @@ true true true + -Zm124 %(AdditionalOptions) mangosd.lib;ACEd.lib;framework.lib;%(AdditionalDependencies) @@ -153,7 +155,7 @@ - /MP -Zm110 %(AdditionalOptions) + /MP %(AdditionalOptions) ..\..\..\..\dep\include\;..\..\..\shared\;..\..\..\framework\;..\..\..\game\;..\include\;..\base\;..\..\..\..\dep\ACE_wrappers\;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;SCRIPT;_SECURE_SCL=0;%(PreprocessorDefinitions) false @@ -428,6 +430,7 @@ + @@ -444,7 +447,7 @@ - + @@ -611,6 +614,7 @@ + @@ -704,7 +708,7 @@ - + @@ -717,14 +721,15 @@ - + + - + diff --git a/VC100/100ScriptDev2.vcxproj.filters b/VC100/100ScriptDev2.vcxproj.filters index 96bfb01412..d1883a0f23 100644 --- a/VC100/100ScriptDev2.vcxproj.filters +++ b/VC100/100ScriptDev2.vcxproj.filters @@ -459,7 +459,6 @@ scripts\eastern_kingdoms\blackwing_lair -<<<<<<< HEAD scripts\eastern_kingdoms @@ -468,10 +467,9 @@ scripts\eastern_kingdoms -======= + scripts\eastern_kingdoms\deadmines ->>>>>>> ffcf70dd7e44e8566120c51dcf32915a37396e99 scripts\eastern_kingdoms\deadmines @@ -1000,13 +998,14 @@ scripts\kalimdor\razorfen_downs + scripts\kalimdor\razorfen_downs scripts\kalimdor\razorfen_kraul - + scripts\kalimdor\razorfen_kraul @@ -1507,6 +1506,9 @@ scripts\northrend\ulduar\ulduar + + scripts\northrend\ulduar\ulduar + scripts\northrend\utgarde_keep\utgarde_keep @@ -1786,7 +1788,7 @@ scripts\outland\tempest_keep\botanica - + scripts\outland\tempest_keep\the_eye @@ -1825,7 +1827,7 @@ scripts\world - + scripts\world @@ -1862,6 +1864,16 @@ system + + + scripts\world + + + include + + + scripts\kalimdor + @@ -2111,6 +2123,9 @@ + + include + diff --git a/addition/mangos_training_dummy.sql b/addition/mangos_training_dummy.sql new file mode 100644 index 0000000000..e3b074b8cf --- /dev/null +++ b/addition/mangos_training_dummy.sql @@ -0,0 +1 @@ +update creature_template set AiName = '', Scriptname = 'npc_training_dummy' where entry in (17578, 24792, 32543, 32546, 32542, 32545, 30527, 31143, 31144, 31146, 32541, 32666, 32667); \ No newline at end of file diff --git a/addition/r01_ebon_hold_mangos.sql b/addition/r01_ebon_hold_mangos.sql new file mode 100644 index 0000000000..75346f479e --- /dev/null +++ b/addition/r01_ebon_hold_mangos.sql @@ -0,0 +1,81 @@ +-- Into the Realm of Shadows +UPDATE `creature_template` SET `ScriptName`='npc_salanar_the_horseman',ainame="" WHERE `entry`='28653'; +UPDATE `creature_template` SET `ScriptName`='mob_dark_rider_of_acherus',ainame="" WHERE `entry`='28768'; + +-- The Gift That Keeps On Giving +UPDATE `creature_template` SET `ScriptName`='mob_scarlet_miner',ainame="" WHERE `entry`='28822'; + +-- How To Win Friends And Influence Enemies +UPDATE `creature_template` SET `ScriptName`='npc_crusade_persuaded',ainame="" WHERE `entry` IN (28939,28940,28610); + +-- An End To All Things... +UPDATE creature_template SET InhabitType = 3 WHERE entry = 28670; + +-- Ambush At The Overlook +DELETE FROM `creature` WHERE `id` = 28957; +INSERT INTO `creature` (`id`, `map`, `phaseMask`, `spawnMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `DeathState`, `MovementType`) VALUES +(28957, 609, 4, 1, 0, 0, 1416.466, -6017.807, 116.357, 1, 360, 0, 0, 1, 0, 0, 1); +UPDATE `creature_template` SET `ScriptName`='mob_scarlet_courier_controller',flags_extra=130,ainame="" WHERE `entry`='28957'; +UPDATE `creature_template` SET `ScriptName`='mob_scarlet_courier',ainame="" WHERE `entry`='29076'; + +-- Bloody Breakout +UPDATE `creature_template` SET `ScriptName`='mob_high_inquisitor_valroth',minmana=6489,maxmana=6489,unit_flags=32768,ainame="" WHERE `entry`='29001'; +UPDATE `creature_template` SET `AIName`='EventAI',minmana=1020,maxmana=1058,unit_flags=32768 WHERE (`entry`='29007'); +DELETE FROM creature_ai_scripts WHERE id BETWEEN 90030 AND 90033; +INSERT INTO `creature_ai_scripts` VALUES ('90030', '29007', '0', '0', '100', '1', '1000', '4000', '1000', '4000', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Smite'); +INSERT INTO `creature_ai_scripts` VALUES ('90031', '29007', '0', '0', '100', '1', '1000', '10000', '20000', '21000', '11', '34809', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Holy Fury'); +INSERT INTO `creature_ai_scripts` VALUES ('90032', '29007', '0', '0', '100', '1', '1000', '5000', '1000', '5000', '11', '19725', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte - Turn Undead'); +INSERT INTO `creature_ai_scripts` VALUES ('90033', '29007', '4', '0', '100', '0', '0', '0', '0', '0', '11', '15498', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Crimson Acolyte aggro'); + +-- The Light of Dawn (to do) +UPDATE `creature_template` SET `ScriptName`='npc_highlord_darion_mograine',ainame="" WHERE `entry`='29173'; +UPDATE `creature_template` SET `ScriptName`='npc_the_lich_king_tirion_dawn',ainame="" WHERE `entry` in (29183,29175); +UPDATE creature_template SET AIName='EventAI',unit_flags=0,type_flags=8 WHERE entry IN (29199,29204,29200,29174,29182,29186,29190,29219,29206,29176,29178,29179,29180,29177,29181); +DELETE FROM `spell_script_target` WHERE `entry` in (53658, 53679, 53701, 53705, 53706, 53677, 53685); +-- insert into spell_script_target values (53658, 1, 29173); +insert into spell_script_target values (53679, 1, 29183); +insert into spell_script_target values (53701, 1, 29175); +insert into spell_script_target values (53705, 1, 29183); +insert into spell_script_target values (53706, 1, 29183); +insert into spell_script_target values (53677, 1, 29227); +insert into spell_script_target values (53685, 1, 29175); + +DELETE FROM `gameobject` WHERE `id` IN (191330); +INSERT INTO `gameobject` (`id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES +('191330','609','1','128','2283.896','-5287.914','83.066','1','0.0','0.0','0.0','1.0','180','0','1'); + +DELETE FROM creature_ai_scripts WHERE id BETWEEN 90051 AND 90084; +INSERT INTO `creature_ai_scripts` VALUES ('90051', '29199', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '52374', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Koltira Deathweaver - SPELL_BLOOD_STRIKE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90052', '29199', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '49576', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Koltira Deathweaver - SPELL_DEATH_GRIP'); +INSERT INTO `creature_ai_scripts` VALUES ('90053', '29199', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '52372', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Koltira Deathweaver - SPELL_ICY_TOUCH2'); +INSERT INTO `creature_ai_scripts` VALUES ('90054', '29199', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '50668', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Koltira Deathweaver - SPELL_PLAGUE_STRIKE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90055', '29204', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '52374', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Orbaz Bloodbane - SPELL_BLOOD_STRIKE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90056', '29204', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '49576', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Orbaz Bloodbane - SPELL_DEATH_GRIP'); +INSERT INTO `creature_ai_scripts` VALUES ('90057', '29204', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '52372', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Orbaz Bloodbane - SPELL_ICY_TOUCH2'); +INSERT INTO `creature_ai_scripts` VALUES ('90058', '29204', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '50668', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Orbaz Bloodbane - SPELL_PLAGUE_STRIKE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90059', '29200', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '52374', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Thassarian - SPELL_BLOOD_STRIKE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90060', '29200', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '49576', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Thassarian - SPELL_DEATH_GRIP'); +INSERT INTO `creature_ai_scripts` VALUES ('90061', '29200', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '52372', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Thassarian - SPELL_ICY_TOUCH2'); +INSERT INTO `creature_ai_scripts` VALUES ('90062', '29200', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '50668', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Thassarian - SPELL_PLAGUE_STRIKE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90063', '29174', '14', '0', '100', '3', '10000', '20', '5000', '10000', '11', '29427', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', 'Defender of the Light - SPELL_HOLY_LIGHT1'); +INSERT INTO `creature_ai_scripts` VALUES ('90064', '29174', '4', '0', '100', '0', '0', '0', '0', '0', '11', '53625', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', 'Defender of the Light aggro'); +INSERT INTO `creature_ai_scripts` VALUES ('90065', '29174', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '53625', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Defender of the Light - SPELL_HEROIC_LEAP'); +INSERT INTO `creature_ai_scripts` VALUES ('90066', '29174', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '53643', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Defender of the Light - SPELL_HOLY_STRIKE'); +INSERT INTO `creature_ai_scripts` VALUES ('90067', '29174', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '53638', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Defender of the Light - SPELL_HOLY_WRATH'); +INSERT INTO `creature_ai_scripts` VALUES ('90068', '29174', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '53629', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Defender of the Light - SPELL_UPPERCUT'); +INSERT INTO `creature_ai_scripts` VALUES ('90069', '29182', '14', '0', '100', '3', '10000', '20', '5000', '10000', '11', '33642', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', 'Rimblat Earthshatter - SPELL_CHAIN_HEAL'); +INSERT INTO `creature_ai_scripts` VALUES ('90070', '29182', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53630', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Rimblat Earthshatter - SPELL_THUNDER'); +INSERT INTO `creature_ai_scripts` VALUES ('90071', '29186', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53633', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Rampaging Abomination - SPELL_CLEAVE1'); +INSERT INTO `creature_ai_scripts` VALUES ('90072', '29186', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '50335', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Rampaging Abomination - SPELL_SCOURGE_HOOK'); +INSERT INTO `creature_ai_scripts` VALUES ('90073', '29190', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53634', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Flesh Behemoth - SPELL_SCOURGE_HOOK'); +INSERT INTO `creature_ai_scripts` VALUES ('90074', '29190', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '36706', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Flesh Behemoth - SPELL_THUNDERCLAP'); +INSERT INTO `creature_ai_scripts` VALUES ('90075', '29190', '0', '0', '100', '3', '5000', '10000', '5000', '10000', '11', '53627', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Flesh Behemoth - SPELL_THUNDERCLAP'); +INSERT INTO `creature_ai_scripts` VALUES ('90076', '29219', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53632', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Volatile Ghoul - SPELL_GHOULPLOSION'); +INSERT INTO `creature_ai_scripts` VALUES ('90077', '29206', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53631', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Warrior of the Frozen Wastes - SPELL_CLEAVE'); +INSERT INTO `creature_ai_scripts` VALUES ('90078', '29176', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53631', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Korfax - SPELL_CLEAVE'); +INSERT INTO `creature_ai_scripts` VALUES ('90079', '29176', '0', '0', '100', '3', '10000', '20000', '10000', '10000', '11', '53625', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Korfax - SPELL_CLEAVE'); +INSERT INTO `creature_ai_scripts` VALUES ('90080', '29177', '14', '0', '100', '3', '10000', '20', '5000', '10000', '11', '37979', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', 'Commander Eligor Dawnbringer - SPELL_HOLY_LIGHT2'); +INSERT INTO `creature_ai_scripts` VALUES ('90081', '29181', '14', '0', '100', '3', '10000', '20', '5000', '10000', '11', '20664', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', 'Rayne - SPELL_REJUVENATION'); +INSERT INTO `creature_ai_scripts` VALUES ('90082', '29181', '14', '0', '100', '3', '10000', '20', '5000', '10000', '11', '25817', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', 'Rayne - SPELL_TRANQUILITY'); +INSERT INTO `creature_ai_scripts` VALUES ('90083', '29181', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '20678', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Rayne - SPELL_STARFALL'); +INSERT INTO `creature_ai_scripts` VALUES ('90084', '29181', '0', '0', '100', '3', '10000', '20000', '10000', '20000', '11', '21807', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'Rayne - SPELL_WRATH'); diff --git a/addition/r01_ebon_hold_scriptdev2.sql b/addition/r01_ebon_hold_scriptdev2.sql new file mode 100644 index 0000000000..ea485b5057 --- /dev/null +++ b/addition/r01_ebon_hold_scriptdev2.sql @@ -0,0 +1,142 @@ +-- -1 609 000 EBON HOLD +DELETE FROM script_texts WHERE entry BETWEEN -1609127 AND -1609101; +INSERT INTO `script_texts` (`entry`,`content_default`,`sound`,`type`,`language`,`emote`,`comment`) VALUES +-- How To Win Friends And Influence Enemies + (-1609101, 'I\'ll tear the secrets from your soul! Tell me about the "Crimson Dawn" and your life may be spared!',0,0,0,0,'player SAY_PERSUADE1'), + (-1609102, 'Tell me what you know about "Crimson Dawn" or the beatings will continue!',0,0,0,0,'player SAY_PERSUADE2'), + (-1609103, 'I\'m through being courteous with your kind, human! What is the "Crimson Dawn?"',0,0,0,0,'player SAY_PERSUADE3'), + (-1609104, 'Is your life worth so little? Just tell me what I need to know about "Crimson Dawn" and I\'ll end your suffering quickly.',0,0,0,0,'player SAY_PERSUADE4'), + (-1609105, 'I can keep this up for a very long time, Scarlet dog! Tell me about the "Crimson Dawn!"',0,0,0,0,'player SAY_PERSUADE5'), + (-1609106, 'What is the "Crimson Dawn?"',0,0,0,0,'player SAY_PERSUADE6'), + (-1609107, '"Crimson Dawn!" What is it! Speak!',0,0,0,0,'player SAY_PERSUADE7'), + (-1609108, 'You\'ll be hanging in the gallows shortly, Scourge fiend!',0,0,0,0,'crusader SAY_CRUSADER1'), + (-1609109, 'You\'ll have to kill me, monster! I will tell you NOTHING!',0,0,0,0,'crusader SAY_CRUSADER2'), + (-1609110, 'You hit like a girl. Honestly. Is that the best you can do?',0,0,0,0,'crusader SAY_CRUSADER3'), + (-1609111, 'ARGH! You burned my last good tabard!',0,0,0,0,'crusader SAY_CRUSADER4'), + (-1609112, 'Argh... The pain... The pain is almost as unbearable as the lashings I received in grammar school when I was but a child.',0,0,0,0,'crusader SAY_CRUSADER5'), + (-1609113, 'I used to work for Grand Inquisitor Isillien! Your idea of pain is a normal mid-afternoon for me!',0,0,0,0,'crusader SAY_CRUSADER6'), + (-1609114, 'I\'ll tell you everything! STOP! PLEASE!',0,0,0,20,'break crusader SAY_PERSUADED1'), + (-1609115, 'We... We have only been told that the "Crimson Dawn" is an awakening. You see, the Light speaks to the High General. It is the Light...',0,0,0,20,'break crusader SAY_PERSUADED2'), + (-1609116, 'The Light that guides us. The movement was set in motion before you came... We... We do as we are told. It is what must be done.',0,0,0,20,'break crusader SAY_PERSUADED3'), + (-1609117, 'I know very little else... The High General chooses who may go and who must stay behind. There\'s nothing else... You must believe me!',0,0,0,20,'break crusader SAY_PERSUADED4'), + (-1609118, 'LIES! The pain you are about to endure will be talked about for years to come!',0,0,0,0,'break crusader SAY_PERSUADED5'), + (-1609119, 'NO! PLEASE! There is one more thing that I forgot to mention... A courier comes soon... From Hearthglen. It...',0,0,0,20,'break crusader SAY_PERSUADED6'), +-- Ambush At The Overlook + (-1609120, 'Hrm, what a strange tree. I must investigate.',0,0,0,0,'Scarlet Courier SAY_TREE1'), + (-1609121, 'What''s this!? This isn''t a tree at all! Guards! Guards!',0,0,0,0,'Scarlet Courier SAY_TREE2'), -- Bloody Breakout + (-1609122, 'The Crusade will purge your kind from this world!',0,1,0,0,'High Inquisitor Valroth start'), + (-1609123, 'It seems that I\'ll need to deal with you myself. The High Inquisitor comes for you, Scourge!',0,1,0,0,'High Inquisitor Valroth aggro'), + (-1609124, 'You have come seeking deliverance? I have come to deliver!',0,0,0,0,'High Inquisitor Valroth yell'), + (-1609125, 'LIGHT PURGE YOU!',0,0,0,0,'High Inquisitor Valroth yell'), + (-1609126, 'Coward!',0,0,0,0,'High Inquisitor Valroth yell'), + (-1609127, 'High Inquisitor Valroth\'s remains fall to the ground.',0,2,0,0,'High Inquisitor Valroth death'); + +DELETE FROM script_texts WHERE entry BETWEEN -1609286 AND -1609201; +INSERT INTO `script_texts` (`entry`,`content_default`,`sound`,`type`,`language`,`emote`,`comment`) VALUES +-- The Light of Dawn +-- pre text + (-1609201, 'Soldiers of the Scourge, stand ready! You will soon be able to unleash your fury upon the Argent Dawn!',14677,1,0,0,'Highlord Darion Mograine'), + (-1609202, 'The sky weeps at the devastation of sister earth! Soon, tears of blood will rain down upon us!',14678,1,0,0,'Highlord Darion Mograine'), + (-1609203, 'Death knights of Acherus, the death march begins!',14681,1,0,0,'Highlord Darion Mograine'), +-- intro + (-1609204, 'Soldiers of the Scourge, death knights of Acherus, minions of the darkness: hear the call of the Highlord!',14679,1,0,22,'Highlord Darion Mograine'), + (-1609205, 'RISE!',14680,1,0,15,'Highlord Darion Mograine'), + (-1609206, 'The skies turn red with the blood of the fallen! The Lich King watches over us, minions! Onward! Leave only ashes and misery in your destructive wake!',14682,1,0,25,'Highlord Darion Mograine'), +-- During the fight + (-1609207, 'Scourge armies approach!',0,1,0,0,'Korfax, Champion of the Light'), + (-1609208, 'Stand fast, brothers and sisters! The Light will prevail!',14487,1,0,0,'Lord Maxwell Tyrosus'), + (-1609209, 'Kneel before the Highlord!',14683,0,0,0,'Highlord Darion Mograine'), + (-1609210, 'You stand no chance!',14684,0,0,0,'Highlord Darion Mograine'), + (-1609211, 'The Scourge will destroy this place!',14685,0,0,0,'Highlord Darion Mograine'), + (-1609212, 'Your life is forfeit.',14686,0,0,0,'Highlord Darion Mograine'), + (-1609213, 'Life is meaningless without suffering.',14687,0,0,0,'Highlord Darion Mograine'), + (-1609214, 'How much longer will your forces hold out?',14688,0,0,0,'Highlord Darion Mograine'), + (-1609215, 'The Argent Dawn is finished!"',14689,0,0,0,'Highlord Darion Mograine'), + (-1609216, 'Spare no one!',14690,0,0,0,'Highlord Darion Mograine'), + (-1609217, 'What is this?! My... I cannot strike...',14691,0,0,0,'Highlord Darion Mograine'), + (-1609218, 'Obey me, blade!',14692,1,0,0,'Highlord Darion Mograine'), + (-1609219, 'You will do as I command! I am in control here!',14693,0,0,0,'Highlord Darion Mograine'), + (-1609220, 'I can not... the blade fights me.',14694,0,0,0,'Highlord Darion Mograine'), + (-1609221, 'What is happening to me?',14695,0,0,0,'Highlord Darion Mograine'), + (-1609222, 'Power...wanes...',14696,0,0,0,'Highlord Darion Mograine'), + (-1609223, 'Ashbringer defies me...',14697,0,0,0,'Highlord Darion Mograine'), + (-1609224, 'Minions, come to my aid!',14698,0,0,0,'Highlord Darion Mograine'), +-- After the fight + (-1609225, 'You cannot win, Darion!',14584,1,0,0,'Highlord Tirion Fordring'), + (-1609226, 'Bring them before the chapel!',14585,1,0,0,'Highlord Tirion Fordring'), + (-1609227, 'Stand down, death knights. We have lost... The Light... This place... No hope...',14699,0,0,68,'Highlord Darion Mograine'), + (-1609228, 'Have you learned nothing, boy? You have become all that your father fought against! Like that coward, Arthas, you allowed yourself to be consumed by the darkness...the hate... Feeding upon the misery of those you tortured and killed!',14586,0,0,378,'Highlord Tirion Fordring'), + (-1609229, 'Your master knows what lies beneath the chapel. It is why he dares not show his face! He\'s sent you and your death knights to meet their doom, Darion.',14587,0,0,25,'Highlord Tirion Fordring'), + (-1609230, 'What you are feeling right now is the anguish of a thousand lost souls! Souls that you and your master brought here! The Light will tear you apart, Darion!',14588,0,0,1,'Highlord Tirion Fordring'), + (-1609231, 'Save your breath, old man. It might be the last you ever draw.',14700,0,0,25,'Highlord Darion Mograine'), + (-1609232, 'My son! My dear, beautiful boy!',14493,0,0,0,'Highlord Alexandros Mograine'), + (-1609233, 'Father!',14701,0,0,5,'Highlord Darion Mograine'), + (-1609234, 'Argh...what...is...',14702,0,0,68,'Highlord Darion Mograine'), + (-1609235, 'Father, you have returned!',14703,0,0,0,'Darion Mograine'), + (-1609236, 'You have been gone a long time, father. I thought...',14704,0,0,0,'Darion Mograine'), + (-1609237, 'Nothing could have kept me away from here, Darion. Not from my home and family.',14494,0,0,1,'Highlord Alexandros Mograine'), + (-1609238, 'Father, I wish to join you in the war against the undead. I want to fight! I can sit idle no longer!',14705,0,0,6,'Darion Mograine'), + (-1609239, 'Darion Mograine, you are barely of age to hold a sword, let alone battle the undead hordes of Lordaeron! I couldn\'t bear losing you. Even the thought...',14495,0,0,1,'Highlord Alexandros Mograine'), + (-1609240, 'If I die, father, I would rather it be on my feet, standing in defiance against the undead legions! If I die, father, I die with you!',14706,0,0,6,'Darion Mograine'), + (-1609241, 'My son, there will come a day when you will command the Ashbringer and, with it, mete justice across this land. I have no doubt that when that day finally comes, you will bring pride to our people and that Lordaeron will be a better place because of you. But, my son, that day is not today.',14496,0,0,1,'Highlord Alexandros Mograine'), + (-1609242, 'Do not forget...',14497,0,0,6,'Highlord Alexandros Mograine'), + (-1609243, 'Touching...',14803,1,0,0,'The Lich King'), + (-1609244, 'You have\'ve betrayed me! You betrayed us all you monster! Face the might of Mograine!',14707,1,0,0,'Highlord Darion Mograine'), + (-1609245, 'He\'s mine now...',14805,0,0,0,'The Lich King'), + (-1609246, 'Pathetic...',14804,0,0,0,'The Lich King'), + (-1609247, 'You\'re a damned monster, Arthas!',14589,0,0,25,'Highlord Tirion Fordring'), + (-1609248, 'You were right, Fordring. I did send them in to die. Their lives are meaningless, but yours...',14806,0,0,1,'The Lich King'), + (-1609249, 'How simple it was to draw the great Tirion Fordring out of hiding. You\'ve left yourself exposed, paladin. Nothing will save you...',14807,0,0,1,'The Lich King'), + (-1609250, 'ATTACK!!!',14488,1,0,0,'Lord Maxwell Tyrosus'), + (-1609251, 'APOCALYPSE!',14808,1,0,0,'The Lich King'), + (-1609252, 'That day is not today...',14708,0,0,0,'Highlord Darion Mograine'), + (-1609253, 'Tirion!',14709,1,0,0,'Highlord Darion Mograine'), + (-1609254, 'ARTHAS!!!!',14591,1,0,0,'Highlord Tirion Fordring'), + (-1609255, 'What is this?',14809,1,0,0,'The Lich King'), + (-1609256, 'Your end.',14592,1,0,0,'Highlord Tirion Fordring'), + (-1609257, 'Impossible...',14810,1,0,0,'The Lich King'), + (-1609258, 'This... isn\'t... over...',14811,1,0,25,'The Lich King'), + (-1609259, 'When next we meet it won\'t be on holy ground, paladin.',14812,1,0,1,'The Lich King'), + (-1609260, 'Rise, Darion, and listen...',14593,0,0,0,'Highlord Tirion Fordring'), + (-1609261, 'We have all been witness to a terrible tragedy. The blood of good men has been shed upon this soil! Honorable knights, slain defending their lives - our lives!',14594,0,0,0,'Highlord Tirion Fordring'), + (-1609262, 'And while such things can never be forgotten, we must remain vigilant in our cause!',14595,0,0,0,'Highlord Tirion Fordring'), + (-1609263, 'The Lich King must answer for what he has done and must not be allowed to cause further destruction to our world.',14596,0,0,0,'Highlord Tirion Fordring'), + (-1609264, 'I make a promise to you now, brothers and sisters: The Lich King will be defeated! On this day, I call for a union.',14597,0,0,0,'Highlord Tirion Fordring'), + (-1609265, 'The Argent Dawn and the Order of the Silver Hand will come together as one! We will succeed where so many before us have failed!',14598,0,0,0,'Highlord Tirion Fordring'), + (-1609266, 'We will take the fight to Arthas and tear down the walls of Icecrown!',14599,0,0,15,'Highlord Tirion Fordring'), + (-1609267, 'The Argent Crusade comes for you, Arthas!',14600,1,0,15,'Highlord Tirion Fordring'), + (-1609268, 'So too do the Knights of the Ebon Blade... While our kind has no place in your world, we will fight to bring an end to the Lich King. This I vow!',14710,0,0,1,'Highlord Darion Mograine'), +-- Emotes + (-1609269, 'Thousands of Scourge rise up at the Highlord\'s command.',0,2,0,0,''), + (-1609270, 'The army marches towards Light\'s Hope Chapel.',0,2,0,0,''), + (-1609271, 'After over a hundred Defenders of the Light fall, Highlord Tirion Fordring arrives.',0,2,0,0,''), + (-1609272, 'flee',0,2,0,0,'Orbaz'), + (-1609273, 'kneels in defeat before Tirion Fordring.',0,2,0,0,'Highlord Darion Mograine'), + (-1609274, 'arrives.',0,2,0,0,'Highlord Alexandros Mograine'), + (-1609275, 'becomes a shade of his past, and walks up to his father.',0,2,0,0,'Highlord Darion Mograine'), + (-1609276, 'hugs his father.',0,2,0,0,'Darion Mograine'), + (-1609277, 'disappears, and the Lich King appears.',0,2,0,0,'Alexandros'), + (-1609278, 'becomes himself again...and is now angry.',0,2,0,0,'Highlord Darion Mograine'), + (-1609279, 'casts a spell on Tirion.',0,2,0,0,'The Lich King'), + (-1609280, 'gasps for air.',0,2,0,0,'Highlord Tirion Fordring'), + (-1609281, 'casts a powerful spell, killing the Defenders and knocking back the others.',0,2,0,0,'The Lich King'), + (-1609282, 'throws the Corrupted Ashbringer to Tirion, who catches it. Tirion becomes awash with Light, and the Ashbringer is cleansed.',0,2,0,0,'Highlord Darion Mograine'), + (-1609283, 'collapses.',0,2,0,0,'Highlord Darion Mograine'), + (-1609284, 'charges towards the Lich King, Ashbringer in hand and strikes the Lich King.',0,2,0,0,'Highlord Tirion Fordring'), + (-1609285, 'disappears. Tirion walks over to where Darion lay',0,2,0,0,'The Lich King'), + (-1609286, 'Light washes over the chapel X the Light of Dawn is uncovered.',0,2,0,0,''); + + +DELETE FROM script_waypoint WHERE entry=29173; +INSERT INTO script_waypoint VALUES + (29173, 0, 2431.639, -5137.05, 83.843, 0, 'intro'), + (29173, 1, 2319.242, -5266.486, 82.825, 0, 'summon & on hold'), + (29173, 2, 2318.775, -5266.832, 82.783, 0, 'cast light of dawn'), + (29173, 3, 2280.812, -5284.091, 82.608, 0, 'move to here and start'), + (29173, 4, 2280.727, -5286.839, 82.930, 0, 'move forward to talk'), + (29173, 5, 2280.812, -5284.091, 82.608, 0, 'when baba pop'), + (29173, 6, 2281.461, -5263.014, 81.164, 0, 'charge to lich king'), + (29173, 7, 2257.479, -5296.702, 82.165, 0, 'being kicked by Lich King'), + (29173, 8, 2261.237, -5294.983, 82.167, 0, 'throw'), + (29173, 9, 2259.34, -5294.379, 82.167, 0, 'event end'); + diff --git a/addition/r02_quests_mangos.sql b/addition/r02_quests_mangos.sql new file mode 100644 index 0000000000..54a20dc40f --- /dev/null +++ b/addition/r02_quests_mangos.sql @@ -0,0 +1,50 @@ +-- Fix for quest The valiant's Challenge [AT] + +UPDATE creature_template SET gossip_menu_id = 33518 WHERE entry = 33518; + +UPDATE creature_template SET mindmg = 3500, maxdmg = 4500, AIName = 'EventAI', faction_A =14, faction_H =14 WHERE entry = 33707; + +DELETE from gossip_menu where entry=33518; +INSERT into gossip_menu (entry, text_id) VALUES +(33518, 1); + +DELETE FROM gossip_menu_option WHERE menu_id = 33518; +INSERT INTO gossip_menu_option VALUES +(33518, 0, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13725, 0, 0, 0, 0, 0, 0, 0), +(33518, 1, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13699, 0, 0, 0, 0, 0, 0, 0), +(33518, 2, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13713, 0, 0, 0, 0, 0, 0, 0), +(33518, 3, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13723, 0, 0, 0, 0, 0, 0, 0), +(33518, 4, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13724, 0, 0, 0, 0, 0, 0, 0), +(33518, 5, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13726, 0, 0, 0, 0, 0, 0, 0), +(33518, 6, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13727, 0, 0, 0, 0, 0, 0, 0), +(33518, 7, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13728, 0, 0, 0, 0, 0, 0, 0), +(33518, 8, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13729, 0, 0, 0, 0, 0, 0, 0), +(33518, 9, 0, 'I am ready to fight!', 1, 1, 0, 0, 33518, 0, 0, NULL, 9, 13731, 0, 0, 0, 0, 0, 0, 0); + +DELETE FROM gossip_scripts WHERE id = 50102; +INSERT INTO gossip_scripts VALUES +(33518, 1, 10, 33707, 120000, 0, 0, 0, 0, 0, 0, 0, 8540.62, 1113.35, 556.78, 0.37, 'Summon Argent champion'); + +DELETE FROM creature_template_addon WHERE entry = 33707; +INSERT INTO creature_template_addon (entry, mount) VALUES +(33707, 28918); + +DELETE FROM creature_ai_scripts WHERE creature_id = 33707; +INSERT INTO creature_ai_scripts VALUES +(3370701, 33707, 4, 0, 100, 1, 0, 1, 1, 5, 11, 63010, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Argent champion - Cast Charge on Aggro'), +(3370702, 33707, 6, 0, 100, 0, 0, 0, 0, 0, 33, 33708, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Argent champion - Kill credit'); + +-- Fix for quest Bury those cockroaches! + +UPDATE creature_template SET ScriptName='npc_seaforium_depth_charge' WHERE entry=25401; + +-- Fix for quest Mistery of the infinite + +UPDATE creature_template SET +ScriptName='npc_hourglass' +WHERE entry=27840; + + +DELETE from creature_ai_scripts WHERE id=2790002; +INSERT into creature_ai_scripts VALUES +(2790002,27900,6,0,100,0,0,0,0,0,15,12470,6,0,0,0,0,0,0,0,0,0,'Infinite Timerender - Quest Credit after death'); \ No newline at end of file diff --git a/addition/r03_battle_standard_mangos.sql b/addition/r03_battle_standard_mangos.sql new file mode 100644 index 0000000000..30e9385fb1 --- /dev/null +++ b/addition/r03_battle_standard_mangos.sql @@ -0,0 +1 @@ +UPDATE `creature_template` SET `ScriptName` = 'npc_battle_standard' WHERE `entry` IN (14465, 14466); \ No newline at end of file diff --git a/base/BSW_ai.cpp b/base/BSW_ai.cpp index 7a623d5660..8f597ab3ff 100644 --- a/base/BSW_ai.cpp +++ b/base/BSW_ai.cpp @@ -808,7 +808,7 @@ Unit* BSWScriptedAI::_doSelect(uint32 SpellID, bool spellsearchtype, float range _list.push_back((Unit*)player); } - debug_log("BSW: search random player with criteria = %u, found %u players.",SpellID,_list.size()); + debug_log("BSW: search random player with criteria = %u, found %u players.",SpellID,(unsigned int)(_list.size())); if (_list.empty()) return NULL; else return _list[urand(0,_list.size() - 1)]; @@ -866,4 +866,4 @@ bool BSWScriptedAI::_isDifficultyInMask(uint8 mask) return ((uint8)currentDifficulty & mask); }; -#endif \ No newline at end of file +#endif diff --git a/base/escort_ai.cpp b/base/escort_ai.cpp index 101317f879..f72712dc56 100644 --- a/base/escort_ai.cpp +++ b/base/escort_ai.cpp @@ -50,7 +50,7 @@ void npc_escortAI::GetAIInformation(ChatHandler& reader) oss << "\nNext Waypoint Id = " << CurrentWP->uiId << " Position: " << CurrentWP->fX << " " << CurrentWP->fY << " " << CurrentWP->fZ; } - reader.PSendSysMessage(oss.str().c_str()); + reader.PSendSysMessage("%s",oss.str().c_str()); } bool npc_escortAI::IsVisible(Unit* pWho) const @@ -532,7 +532,7 @@ void npc_escortAI::Start(bool bRun, const Player* pPlayer, const Quest* pQuest, //disable npcflags m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); - debug_log("SD2: EscortAI started with %u waypoints. Run = %d, PlayerGuid = %u", WaypointList.size(), m_bIsRunning, m_playerGuid.GetCounter()); + debug_log("SD2: EscortAI started with %u waypoints. Run = %d, PlayerGuid = %u", (unsigned int)WaypointList.size(), m_bIsRunning, m_playerGuid.GetCounter()); CurrentWP = WaypointList.begin(); diff --git a/include/sc_instance.cpp b/include/sc_instance.cpp index 2928388e0b..157c9ccea2 100644 --- a/include/sc_instance.cpp +++ b/include/sc_instance.cpp @@ -31,14 +31,21 @@ void ScriptedInstance::DoUseDoorOrButton(ObjectGuid guid, uint32 uiWithRestoreTi } /// Function that uses a door or button that is stored in m_mGoEntryGuidStore -void ScriptedInstance::DoUseDoorOrButton(uint32 uiEntry, uint32 uiWithRestoreTime /*= 0*/, bool bUseAlternativeState /*= false*/) +void ScriptedInstance::DoUseDoorOrButton(uint64 uiEntry, uint32 uiWithRestoreTime /*= 0*/, bool bUseAlternativeState /*= false*/) { + // FIXME REMOVE when no more GO-Guids are stored as uint64 + if (uiEntry > (uint64(HIGHGUID_GAMEOBJECT) << 48)) + { + DoUseDoorOrButton(ObjectGuid(uiEntry), uiWithRestoreTime, bUseAlternativeState); + return; + } + EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry); if (find != m_mGoEntryGuidStore.end()) DoUseDoorOrButton(find->second, uiWithRestoreTime, bUseAlternativeState); else // Output log, possible reason is not added GO to storage, or not yet loaded - debug_log("SD2: Script call DoUseDoorOrButton(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); + debug_log("SD2: Script call DoUseDoorOrButton(by Entry), but no gameobject of entry "UI64FMTD" was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); } /** @@ -68,14 +75,21 @@ void ScriptedInstance::DoRespawnGameObject(ObjectGuid guid, uint32 uiTimeToDespa } /// Function that respawns a despawned GO that is stored in m_mGoEntryGuidStore -void ScriptedInstance::DoRespawnGameObject(uint32 uiEntry, uint32 uiTimeToDespawn) +void ScriptedInstance::DoRespawnGameObject(uint64 uiEntry, uint32 uiTimeToDespawn) { + // FIXME REMOVE when no more GO-Guids are stored as uint64 + if (uiEntry > (uint64(HIGHGUID_GAMEOBJECT) << 48)) + { + DoRespawnGameObject(ObjectGuid(uiEntry), uiTimeToDespawn); + return; + } + EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry); if (find != m_mGoEntryGuidStore.end()) DoRespawnGameObject(find->second, uiTimeToDespawn); else // Output log, possible reason is not added GO to storage, or not yet loaded; - debug_log("SD2: Script call DoRespawnGameObject(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); + debug_log("SD2: Script call DoRespawnGameObject(by Entry), but no gameobject of entry "UI64FMTD" was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId()); } /** diff --git a/include/sc_instance.h b/include/sc_instance.h index 384987b353..75da035afc 100644 --- a/include/sc_instance.h +++ b/include/sc_instance.h @@ -35,11 +35,13 @@ class MANGOS_DLL_DECL ScriptedInstance : public InstanceData // Change active state of doors or buttons void DoUseDoorOrButton(ObjectGuid guid, uint32 uiWithRestoreTime = 0, bool bUseAlternativeState = false); - void DoUseDoorOrButton(uint32 uiEntry, uint32 uiWithRestoreTime = 0, bool bUseAlternativeState = false); + // FIXME revert back to uint32 uiEntry when no more GO-Guids are stored as uint64 + void DoUseDoorOrButton(uint64 uiEntry, uint32 uiWithRestoreTime = 0, bool bUseAlternativeState = false); // Respawns a GO having negative spawntimesecs in gameobject-table void DoRespawnGameObject(ObjectGuid guid, uint32 uiTimeToDespawn = MINUTE); - void DoRespawnGameObject(uint32 uiEntry, uint32 uiTimeToDespawn = MINUTE); + // FIXME revert back to uint32 uiEntry when no more GO-Guids are stored as uint64 + void DoRespawnGameObject(uint64 uiEntry, uint32 uiTimeToDespawn = MINUTE); // Sends world state update to all players in instance void DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData); diff --git a/scripts/battlegrounds/battleground.cpp b/scripts/battlegrounds/battleground.cpp index 722a0d1319..1ac05a3807 100644 --- a/scripts/battlegrounds/battleground.cpp +++ b/scripts/battlegrounds/battleground.cpp @@ -37,8 +37,6 @@ EndScriptData */ enum { - SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel - SPELL_SPIRIT_HEAL = 22012, // Spirit Heal SPELL_SPIRIT_HEAL_MANA = 44535, // in battlegrounds player get this no-mana-cost-buff @@ -57,7 +55,7 @@ struct MANGOS_DLL_DECL npc_spirit_guideAI : public ScriptedAI { // auto cast the whole time this spell if (!m_creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - { + { m_creature->CastSpell(m_creature, SPELL_SPIRIT_HEAL, true); m_creature->CastSpell(m_creature, SPELL_SPIRIT_HEAL_CHANNEL, false); } @@ -103,13 +101,63 @@ CreatureAI* GetAI_npc_spirit_guide(Creature* pCreature) return new npc_spirit_guideAI(pCreature); } -void AddSC_battleground() +struct MANGOS_DLL_DECL npc_battleground_vehicleAI : public ScriptedAI +{ + npc_battleground_vehicleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + Reset(); + } + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + } + + void EnterCombat(Unit *pEnemy) + { + if (!m_creature->isCharmed()) + m_creature->CombatStop(); + } + + void Aggro(Unit* who) + { + // Theorically, we should never be here... + if (!m_creature->isCharmed()) + m_creature->CombatStop(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->isCharmed()) + if (m_creature->isInCombat()) // And theorically, this should never happen... but it happens + m_creature->CombatStop(); + } + + void HealBy(Unit* pHealer, uint32 uiAmountHealed) + { + // Some spells like chain heals can heal vehicles, this prevents it: + m_creature->DealDamage(m_creature, uiAmountHealed, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } +}; + +CreatureAI* GetAI_npc_battleground_vehicle(Creature* pCreature) { - Script* pNewScript; + return new npc_battleground_vehicleAI(pCreature); +} - pNewScript = new Script; - pNewScript->Name = "npc_spirit_guide"; - pNewScript->GetAI = &GetAI_npc_spirit_guide; - pNewScript->pGossipHello = &GossipHello_npc_spirit_guide; - pNewScript->RegisterSelf(); +void AddSC_battleground() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_spirit_guide"; + newscript->GetAI = &GetAI_npc_spirit_guide; + newscript->pGossipHello = &GossipHello_npc_spirit_guide; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_battleground_vehicle"; + newscript->GetAI = &GetAI_npc_battleground_vehicle; + newscript->RegisterSelf(); } diff --git a/scripts/custom/alterac_valley.cpp b/scripts/custom/alterac_valley.cpp new file mode 100644 index 0000000000..cf1e5c3069 --- /dev/null +++ b/scripts/custom/alterac_valley.cpp @@ -0,0 +1,477 @@ +#include "precompiled.h" + +/*###### +## nnpc_vanndar_stormpike +######*/ +#define SAY_AGGRO_A "Soldiers of Stormpike, your General is under attack! I require aid! Come! Come! Slay these mangy Frostwolf dogs." +#define SAY_KILL_1_A "Take no prisoners! Drive these heathens from our lands!" +#define SAY_KILL_2_A "We, the Alliance, will prevail!" +#define SAY_KILL_3_A "The Stormpike clan bows to no one, especially the horde!" +#define SAY_KILL_4_A "Is that the best you can do?" +#define SAY_KILL_5_A "Your attacks are weak! Go practice on some rabbits and come back when you're stronger." +#define SAY_EVADE_1_A "You'll never get me out of me bunker, heathens!" +#define SAY_EVADE_2_A "Why don't ya try again without yer cheap tactics, pansies! Or are you too chicken?" + +enum +{ + SPELL_AVATAR = 19135, + SPELL_THUNDERCLAP = 15588, + SPELL_STORMBOLT = 20685 +}; + +struct MANGOS_DLL_DECL npc_vanndar_stormpikeAI : public ScriptedAI +{ + npc_vanndar_stormpikeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiEvadeCheckCooldown; + uint32 m_uiAvatar_Timer; + uint32 m_uiStormBolt_Timer; + uint32 m_uiThunderClap_Timer; + + void Reset() + { + m_uiEvadeCheckCooldown = 2500; + m_uiAvatar_Timer = 2000+rand()%17000; + m_uiThunderClap_Timer = 4000+rand()%12000; + m_uiStormBolt_Timer = 6000+rand()%20000; + } + + void Aggro(Unit *pWho) + { + if (pWho) + m_creature->MonsterYell(SAY_AGGRO_A, LANG_UNIVERSAL, pWho); + + m_creature->CallForHelp(20.0f); + } + + void JustReachedHome() + { + + } + + void JustDied(Unit* pKiller) + { + } + + void KilledUnit(Unit* victim) + { + switch(rand()%5) + { + case 0: m_creature->MonsterYell(SAY_KILL_1_A, LANG_UNIVERSAL, 0); break; + case 1: m_creature->MonsterYell(SAY_KILL_2_A, LANG_UNIVERSAL, 0); break; + case 2: m_creature->MonsterYell(SAY_KILL_3_A, LANG_UNIVERSAL, 0); break; + case 3: m_creature->MonsterYell(SAY_KILL_4_A, LANG_UNIVERSAL, 0); break; + case 4: m_creature->MonsterYell(SAY_KILL_5_A, LANG_UNIVERSAL, 0); break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiAvatar_Timer < uiDiff) + { + DoCast(m_creature, SPELL_AVATAR); + m_uiAvatar_Timer = 2000+rand()%17000; + } + else m_uiAvatar_Timer -= uiDiff; + + if (m_uiThunderClap_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_THUNDERCLAP); + + m_uiThunderClap_Timer = 4000+rand()%12000; + m_creature->CallForHelp(40.0f); + } + else m_uiThunderClap_Timer -= uiDiff; + + if (m_uiStormBolt_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(m_creature->getVictim(),SPELL_STORMBOLT); + m_uiStormBolt_Timer = 6000+rand()%20000; + } + else m_uiStormBolt_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); + } + + bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) + { + if (m_uiEvadeCheckCooldown < uiDiff) + m_uiEvadeCheckCooldown = 2500; + else + { + m_uiEvadeCheckCooldown -= uiDiff; + return false; + } + + if (m_creature->IsInEvadeMode() || !m_creature->getVictim()) + return false; + + float fX,fY,fZ; + m_creature->GetRespawnCoord(fX,fY,fZ); + + if (m_creature->GetDistance2d(fX, fY) < 40.0f) + return false; + + if (m_creature->getVictim()) + { + switch(rand()%2) + { + case 0: m_creature->MonsterYell(SAY_EVADE_1_A,LANG_UNIVERSAL,m_creature->getVictim()); + break; + case 1: m_creature->MonsterYell(SAY_EVADE_2_A,LANG_UNIVERSAL,m_creature->getVictim()); + break; + } + m_creature->DealDamage(m_creature->getVictim(), m_creature->getVictim()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + EnterEvadeMode(); + return true; + } +}; + +CreatureAI* GetAI_npc_vanndar_stormpike(Creature* pCreature) +{ + return new npc_vanndar_stormpikeAI(pCreature); +} + + +/*###### +## npc_drekthar +######*/ +#define SAY_AGGRO_H "Stormpike filth! In my keep?! Slay them all!" +#define SAY_KILL_1_H "Your attacks are slowed by the cold, I think!" +#define SAY_KILL_2_H "Today, you will meet your ancestors!" +#define SAY_KILL_3_H "If you will not leave Alterac Valley on your own, then the Frostwolves will force you out!" +#define SAY_KILL_4_H "You cannot defeat the Frostwolf clan!" +#define SAY_KILL_5_H "Your attacks are weak! Go practice on some rabbits and come back when you're stronger." +#define SAY_EVADE_1_H "You seek to draw the General of the Frostwolf legion out from his fortress? PREPOSTEROUS!" +#define SAY_EVADE_2_H "You are no match for the strength of the Horde!" + +enum +{ + SPELL_FRENZY = 8269, + SPELL_KNOCKDOWN = 19128, + SPELL_WHIRLWIND = 13736 +}; + +struct MANGOS_DLL_DECL npc_drektharAI : public ScriptedAI +{ + npc_drektharAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiEvadeCheckCooldown; + uint32 m_uiFrenzy_Timer; + uint32 m_uiKnockback_Timer; + uint32 m_uiWhirlwind_Timer; + + void Reset() + { + m_uiEvadeCheckCooldown = 2500; + m_uiFrenzy_Timer = urand(2000, 19000); + m_uiKnockback_Timer = urand(4000, 15000); + m_uiWhirlwind_Timer = urand(6000, 20000); + } + + void Aggro(Unit *pWho) + { + if (pWho) + m_creature->MonsterYell(SAY_AGGRO_H, LANG_UNIVERSAL, pWho); + + m_creature->CallForHelp(20.0f); + } + + void KilledUnit(Unit* victim) + { + switch(urand(0,5)) + { + case 0: m_creature->MonsterYell(SAY_KILL_1_H, LANG_UNIVERSAL, 0); break; + case 1: m_creature->MonsterYell(SAY_KILL_2_H, LANG_UNIVERSAL, 0); break; + case 2: m_creature->MonsterYell(SAY_KILL_3_H, LANG_UNIVERSAL, 0); break; + case 3: m_creature->MonsterYell(SAY_KILL_4_H, LANG_UNIVERSAL, 0); break; + case 4: m_creature->MonsterYell(SAY_KILL_5_H, LANG_UNIVERSAL, 0); break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiFrenzy_Timer < uiDiff) + { + DoCast(m_creature, SPELL_FRENZY); + m_uiFrenzy_Timer = urand(2000, 18000); + } + else + m_uiFrenzy_Timer -= uiDiff; + + if (m_uiKnockback_Timer < uiDiff) + { + if (m_creature->getVictim()) + DoCast(m_creature->getVictim(), SPELL_KNOCKDOWN); + + m_uiKnockback_Timer = urand(4000, 15000); + m_creature->CallForHelp(40.0f); + } + else + m_uiKnockback_Timer -= uiDiff; + + if (m_uiWhirlwind_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(m_creature->getVictim(), SPELL_WHIRLWIND); + + m_uiWhirlwind_Timer = urand(5000, 25000); + } + else + m_uiWhirlwind_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); + } + + bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) + { + if (m_uiEvadeCheckCooldown < uiDiff) + m_uiEvadeCheckCooldown = 2500; + else + { + m_uiEvadeCheckCooldown -= uiDiff; + return false; + } + + if (m_creature->IsInEvadeMode() || !m_creature->getVictim()) + return false; + + float fX,fY,fZ; + m_creature->GetRespawnCoord(fX,fY,fZ); + + if (m_creature->GetDistance2d(fX, fY) < 40.0f) + return false; + + if (m_creature->getVictim()) + { + switch(urand(0,1)) + { + case 0: m_creature->MonsterYell(SAY_EVADE_1_H,LANG_UNIVERSAL,m_creature->getVictim()); + break; + case 1: m_creature->MonsterYell(SAY_EVADE_2_H,LANG_UNIVERSAL,m_creature->getVictim()); + break; + } + + m_creature->DealDamage(m_creature->getVictim(), m_creature->getVictim()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + EnterEvadeMode(); + return true; + } +}; + +CreatureAI* GetAI_npc_drekthar(Creature* pCreature) +{ + return new npc_drektharAI(pCreature); +} + +/*###### +## nnpc_marshall +######*/ +enum +{ + SPELL_CHARGE = 22911, + SPELL_CLEAVE = 40504, + SPELL_DEMORALIZINGSHOUT = 23511 +}; + +struct MANGOS_DLL_DECL npc_marshallAI : public ScriptedAI +{ + npc_marshallAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_uiMyAura = GetAuraByEntry(); + Reset(); + } + + uint32 m_uiEvadeCheckCooldown; + uint32 m_uiCharge_Timer; + uint32 m_uiCleave_Timer; + uint32 m_uiWhirlwind_Timer; + uint32 m_uiDemoralizingShout_Timer; + uint32 m_uiMyAura; + uint32 m_uiMyAuraTimer; + + void Reset() + { + m_uiEvadeCheckCooldown = 2500; + m_uiCharge_Timer = 1000; + m_uiCleave_Timer = urand(3000, 15000); + m_uiWhirlwind_Timer = urand(5000, 20000); + m_uiDemoralizingShout_Timer = urand(15000, 20000); + m_uiMyAuraTimer = 2000; + } + + void Aggro(Unit* pWho) + { + m_creature->CallForHelp(20.0f); + } + + void JustDied(Unit* pKiller) + { + if (m_uiMyAura) + m_creature->RemoveAurasDueToSpell(m_uiMyAura); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiMyAuraTimer < uiDiff) + { + if (m_uiMyAura && !m_creature->HasAura(m_uiMyAura)) + m_creature->CastSpell(m_creature, m_uiMyAura, true); + + m_uiMyAuraTimer = 2000; + } + else + m_uiMyAuraTimer -= uiDiff; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiCleave_Timer < uiDiff) + { + if (m_creature->getVictim()) + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + + m_uiCleave_Timer = urand(3000, 15000); + } + else + m_uiCleave_Timer -= uiDiff; + + if (m_uiCharge_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(target, SPELL_CHARGE); + + m_uiCharge_Timer = urand(1000, 15000); + } + else + m_uiCharge_Timer -= uiDiff; + + if (m_uiWhirlwind_Timer < uiDiff) + { + DoCast(m_creature,SPELL_WHIRLWIND, true); + m_uiWhirlwind_Timer = urand(5000, 20000); + } + else + m_uiWhirlwind_Timer -= uiDiff; + + if (m_uiDemoralizingShout_Timer < uiDiff) + { + if (m_creature->getVictim()) + DoCast(m_creature->getVictim(), SPELL_DEMORALIZINGSHOUT); + + m_uiDemoralizingShout_Timer = urand(15000, 20000); + m_creature->CallForHelp(40.0f); + } + else + m_uiDemoralizingShout_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); + } + + bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) + { + if (m_uiEvadeCheckCooldown < uiDiff) + m_uiEvadeCheckCooldown = 2500; + else + { + m_uiEvadeCheckCooldown -= uiDiff; + return false; + } + + if (m_creature->IsInEvadeMode() || !m_creature->getVictim()) + return false; + + float fX,fY,fZ; + m_creature->GetRespawnCoord(fX,fY,fZ); + + if (m_creature->GetDistance2d(fX, fY) < 40.0f) + return false; + + if (m_creature->getVictim()) + m_creature->DealDamage(m_creature->getVictim(), m_creature->getVictim()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); +/* + if (Creature *pBoss = GetClosestCreatureWithEntry(m_creature, m_creature->getFaction() == 730 ? 11948 : 11946, 40.0f)) + { + if (pBoss->isAlive() && pBoss->isInCombat() && pBoss->getVictim()) + pBoss->AI()->EnterEvadeMode(); + } +*/ + EnterEvadeMode(); + return true; + } + + uint32 GetAuraByEntry() + { + switch (m_creature->GetEntry()) + { + case 14762: // Dun Baldar North Marshal + return 45828; + case 14763: // Dun Baldar South Marshal + return 45829; + case 14772: // East Frostwolf Warmaster + return 45826; + case 14773: // Iceblood Warmaster + return 45822; + case 14764: // Icewing Marshal + return 45831; + case 14765: // Stonehearth Marshal + return 45830; + case 14776: // Tower Point Warmaster + return 45823; + case 14777: // West Frostwolf Warmaster + return 45824; + default: + error_log("SD2: Alterac Valley entry %u non prevista per questo script", m_creature->GetEntry()); + return 0; + } + + } + +}; + +CreatureAI* GetAI_npc_marshall(Creature* pCreature) +{ + return new npc_marshallAI(pCreature); +} + +void AddSC_alterac_valley() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_vanndar_stormpike"; + newscript->GetAI = &GetAI_npc_vanndar_stormpike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_drekthar"; + newscript->GetAI = &GetAI_npc_drekthar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_marshall"; + newscript->GetAI = &GetAI_npc_marshall; + newscript->RegisterSelf(); +} diff --git a/scripts/custom/small_pet_handler.cpp b/scripts/custom/small_pet_handler.cpp new file mode 100644 index 0000000000..e2e8b9a33e --- /dev/null +++ b/scripts/custom/small_pet_handler.cpp @@ -0,0 +1,357 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Small Pet Handler +SDAuthor: ckegg +SD%Complete: 0% +SDComment: +SDCategory: Pet behavior +EndScriptData */ + +#include "precompiled.h" + +enum +{ + NPC_PANDA = 11325, + SPELL_PANDA_SLEEP = 19231, + SPELL_PANDA_ROAR = 40664, + + NPC_DIABLO = 11326, + SPELL_DIABLO_FLAME = 18874, + //SPELL_DIABLO = 18873, + + NPC_ZERGLING = 11327, + SPELL_ZERGLING = 19227, + //SPELL_ZERGLING = 19226, + + NPC_WILLY = 23231, + SPELL_WILLY_SLEEP = 40663, + //SPELL_WILLY = 40619, + //SPELL_WILLY = 40638, + + NPC_DRAGON_KITE = 25110, + SPELL_DRAGON_KITE_LIGHTNING = 45197, + + NPC_BATTLE_BOT = 34587, + SPELL_BATTLE_BOT_MELEE = 65694, + + NPC_MURKY = 15186, + NPC_LURKY = 15358, + SPELL_MURKY_DANCE = 25165, + + NPC_EGBERT = 23258, + SPELL_EGBERT_HAPPYNESS = 40669, + + //NPC_KIRIN = , + SPELL_KIRIN_ARCANE = 61479, + + NPC_MULGORE = 33219, + SPELL_MULGORE_HAPPYNESS = 62585, + + NPC_PENGU = 32595, + NPC_CHILLY = 31128, + SPELL_PENGU_SOUND = 61635, + + NPC_STINKER = 23274, + SPELL_STINKER_BROKEN_HEART = 62004, + + NPC_SCORCHLING = 25706, + SPELL_SCORCHLING_BLAST = 45889, + + NPC_SPRING_RABBIT = 32791, + SPELL_SPRING_RABBIT_IN_LOVE = 61728, + SPELL_SPRING_RABBIT_JUMP = 61724, + + NPC_STRAND_CRAWLERT = 33226, + SPELL_STRAND_CRAWLERT_BUBBLE = 62587, + + NPC_TELDRASSIL_SPROUTLING = 33188, + SPELL_SPROUTLING_SLEEP = 62499, + SPELL_SPROUTLING_DANCE = 62504, + + NPC_TIRISFAL_BATLING = 33197, + NPC_VAMPIRIC_BATLING = 28513, + SPELL_TIRISFAL_BATLING_SOUND = 62545, + + NPC_TYRAEL = 29089, + SPELL_TYRAEL_DANCE = 54398, + + NPC_TRAIN_WRECKER = 33404, + SPELL_TRAIN_WRECKER_BLOW = 62943, + + NPC_BLIZZARD_BEAR = 32841, + SPELL_BLIZZARD_BEAR_SIT = 61853, + + NPC_MOJO = 24480, + SPELL_FEELING_FROGGY = 43906, + SPELL_FROG_LOVE = 62537, + EMOTE_KISS = -1799979, +}; + +struct MANGOS_DLL_DECL npc_small_pet_handlerAI : public ScriptedAI +{ + npc_small_pet_handlerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + bool m_bIsIdle; + bool m_bIsInAction; + uint32 m_uiCheckTimer; + uint32 m_uiActionTimer; + ObjectGuid m_uiPlayerGUID; + + void Reset() + { + m_bIsIdle = false; + m_bIsInAction = false; + m_uiCheckTimer = 5000; + m_uiActionTimer = urand(10000, 30000); + m_uiPlayerGUID.Clear(); + + if (Unit* pOwner = m_creature->GetCharmerOrOwner()) + { + m_creature->GetMotionMaster()->MoveFollow(pOwner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + m_uiPlayerGUID = pOwner->GetObjectGuid(); + } + } + + void AttackStart(Unit* who) + { + return; + } + + void ReceiveEmote(Player* pPlayer, uint32 uiEmote) + { + if (!pPlayer) + return; + + switch (m_creature->GetEntry()) + { + case NPC_MOJO: + { + if (uiEmote == TEXTEMOTE_KISS) + { + DoScriptText(EMOTE_KISS, m_creature, pPlayer); + pPlayer->CastSpell(pPlayer, SPELL_FEELING_FROGGY, true); + DoCast(m_creature, SPELL_FROG_LOVE, true); + } + break; + } + default: break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + // Check if pet is moving + if (m_uiCheckTimer < uiDiff) + { + if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID)) + { + // Change speed if owner is mounted + if (pPlayer->IsMounted()) + m_creature->SetSpeedRate(MOVE_RUN, 2.0f, true); + else + m_creature->SetSpeedRate(MOVE_RUN, 1.0f, true); + + // Check if owner is stopped + if (pPlayer->isMoving() && m_bIsIdle) + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + //m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); + m_bIsIdle = false; + m_uiActionTimer = urand(10000, 30000); + } + else if (m_creature->IsWithinDistInMap(pPlayer, 1.5f) && !m_bIsIdle) + { + m_bIsIdle = true; + } + } + m_uiCheckTimer = 5000; + } + else + m_uiCheckTimer -= uiDiff; + + // Return if pet is moving + if (!m_bIsIdle) + { + m_bIsInAction = false; + return; + } + + // Do pet's action + if (m_uiActionTimer < uiDiff) + { + // Do action + if (!m_bIsInAction) + { + m_uiActionTimer = urand(30000, 60000); // Prevent stopping action too early + m_bIsInAction = true; + PetAction(m_creature->GetEntry()); + } + // Stop action + else + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); + m_uiActionTimer = urand(10000, 30000); + m_bIsInAction = false; + } + } + else + m_uiActionTimer -= uiDiff; + } + + void PetAction(uint32 uiPetGUID) + { + if (!uiPetGUID) + return; + + switch(uiPetGUID) + { + case NPC_PANDA: + { + DoCast(m_creature, urand(0, 1) ? SPELL_PANDA_SLEEP : SPELL_PANDA_ROAR); + break; + } + case NPC_DIABLO: + { + DoCast(m_creature, SPELL_DIABLO_FLAME); + break; + } + case NPC_ZERGLING: + { + DoCast(m_creature, SPELL_ZERGLING); + break; + } + case NPC_WILLY: + { + DoCast(m_creature, SPELL_WILLY_SLEEP); + break; + } + case NPC_DRAGON_KITE: + { + if (Unit* pOwner = m_creature->GetCharmerOrOwner()) + DoCast(pOwner, SPELL_DRAGON_KITE_LIGHTNING); + break; + } + case NPC_BATTLE_BOT: + { + if (Creature* pBattleBot = GetClosestCreatureWithEntry(m_creature, NPC_BATTLE_BOT, 3.0f)) + { + m_creature->GetMotionMaster()->MovePoint(0, pBattleBot->GetPositionX()+rand()%5, pBattleBot->GetPositionY()+rand()%5, pBattleBot->GetPositionZ()); + DoCast(m_creature, SPELL_BATTLE_BOT_MELEE); + pBattleBot->CastSpell(pBattleBot, SPELL_BATTLE_BOT_MELEE, false); + m_uiActionTimer = 3000; // make bot repeats the action + m_bIsInAction = false; + } + break; + } + case NPC_MURKY: + case NPC_LURKY: + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_DANCE); + DoCast(m_creature, SPELL_MURKY_DANCE); + break; + } + case NPC_EGBERT: + { + DoCast(m_creature, SPELL_EGBERT_HAPPYNESS); + break; + } + case NPC_MULGORE: + { + DoCast(m_creature, SPELL_MULGORE_HAPPYNESS); + break; + } + case NPC_PENGU: + case NPC_CHILLY: + { + DoCast(m_creature, SPELL_PENGU_SOUND); + m_uiActionTimer = urand(5000, 10000); // repeat + m_bIsInAction = false; + break; + } + case NPC_STINKER: + { + DoCast(m_creature, SPELL_STINKER_BROKEN_HEART); + break; + } + case NPC_SCORCHLING: + { + DoCast(m_creature, SPELL_SCORCHLING_BLAST); + break; + } + case NPC_SPRING_RABBIT: + { + DoCast(m_creature, urand(0, 1) ? SPELL_SPRING_RABBIT_IN_LOVE : SPELL_SPRING_RABBIT_JUMP); + break; + } + case NPC_STRAND_CRAWLERT: + { + DoCast(m_creature, SPELL_STRAND_CRAWLERT_BUBBLE); + break; + } + case NPC_TELDRASSIL_SPROUTLING: + { + DoCast(m_creature, urand(0, 1) ? SPELL_SPROUTLING_SLEEP : SPELL_SPROUTLING_DANCE); + break; + } + case NPC_TIRISFAL_BATLING: + case NPC_VAMPIRIC_BATLING: + { + DoCast(m_creature, SPELL_TIRISFAL_BATLING_SOUND); + break; + } + case NPC_TYRAEL: + { + DoCast(m_creature, SPELL_TYRAEL_DANCE); + break; + } + case NPC_TRAIN_WRECKER: + { + DoCast(m_creature, SPELL_TRAIN_WRECKER_BLOW); + break; + } + case NPC_BLIZZARD_BEAR: + { + DoCast(m_creature, SPELL_BLIZZARD_BEAR_SIT); + break; + } + default: break; + } + } +}; + +CreatureAI* GetAI_npc_small_pet_handler(Creature* pCreature) +{ + return new npc_small_pet_handlerAI(pCreature); +} + +void AddSC_npc_small_pet_handler() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_small_pet_handler"; + newscript->GetAI = &GetAI_npc_small_pet_handler; + newscript->RegisterSelf(); +} diff --git a/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp index 8a3fc73546..2624b6f9b8 100644 --- a/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp +++ b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp @@ -441,7 +441,7 @@ bool EffectDummyCreature_spell_banner_of_provocation(Unit* pCaster, uint32 uiSpe { instance_blackrock_depths* pInstance = (instance_blackrock_depths*)pCreatureTarget->GetInstanceData(); if (pInstance && pInstance->GetData(TYPE_RING_OF_LAW) != DONE && pInstance->GetData(TYPE_RING_OF_LAW) != SPECIAL) - pInstance->SetData(TYPE_RING_OF_LAW, pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS ? SPECIAL : DATA_BANNER_BEFORE_EVENT); + pInstance->SetData(TYPE_RING_OF_LAW, pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS ? uint32(SPECIAL) : uint32(DATA_BANNER_BEFORE_EVENT)); return true; } diff --git a/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h index 8f19b8bb6e..9a136f58b1 100644 --- a/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h +++ b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h @@ -55,6 +55,8 @@ enum GO_ARENA_SPOILS = 181074, GO_SECRET_DOOR = 174553, + GO_MINIONSUMMONER = 188508, + SPELL_STONED = 10255, // Aura of Warbringer Constructs in Relict Vault }; diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp index c7aaf79fb3..84529ce99f 100644 --- a/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp +++ b/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp @@ -16,13 +16,517 @@ /* ScriptData SDName: boss_coren_direbrew -SD%Complete: 0 -SDComment: Placeholder +SD%Complete: 40 +SDComment: Placeholder, Epona SDCategory: Blackrock Depths EndScriptData */ #include "precompiled.h" +#include "blackrock_depths.h" +#include "escort_ai.h" +enum +{ + SAY_PAY = -1799998, + SAY_AGGRO = -1799997, + + SAY_IDLE1 = -1799996, + SAY_IDLE2 = -1799995, + SAY_IDLE3 = -1799994, + SAY_IDLE4 = -1799993, + + SAY_ANTAGONIST1_1 = -1799992, + SAY_ANTAGONIST1_2 = -1799991, + SAY_ANTAGONIST1_3 = -1799990, + SAY_ANTAGONIST2_1 = -1799989, + SAY_ANTAGONIST2_2 = -1799988, + SAY_ANTAGONIST2_3 = -1799987, + SAY_ANTAGONIST4 = -1799986, + + // Coren + SPELL_DISARM = 47310, + + // Ilsa + ITEM_BREWMAIDEN_BREW = 36748, + SPELL_BREWMAIDEN_BREW = 47371, + SPELL_STUN = 35856, + + // Ursula + SPELL_BARRELED = 47442, + + MOB_ANTAGONIST = 23795, + MOB_ILSA = 26764, + MOB_URSULA = 26822, + MOB_MINION = 26776 +}; + +float Coord[6][3] = +{ + {902.65f, -131.26f, -49.74f}, // Antagonist1 + {902.85f, -134.45f, -49.74f}, // Antagonist2 + {904.72f, -137.24f, -49.75f}, // Antagonist3 + {905.53f, -128.06f, -49.74f}, // Coren noncombat event movement point1 id 1 + {909.47f, -137.38f, -49.74f}, // Coren noncombat event movement point2 id 2 + {898.79f, -140.91f, -49.75f} // Ursula and Ilsa spawn point +}; + +/*##### +# Coren +#####*/ +struct MANGOS_DLL_DECL boss_coren_direbrewAI : public ScriptedAI +{ + boss_coren_direbrewAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bEventStarted; + bool m_bAntagonistAttacked; + bool m_bIlsaSpawned; + bool m_bUrsulaSpawned; + + // Adds GUIDs + ObjectGuid m_Antagonist1Guid; + ObjectGuid m_Antagonist2Guid; + ObjectGuid m_Antagonist3Guid; + ObjectGuid m_UrsulaGuid; + ObjectGuid m_IlsaGuid; + + Player* m_pInsulter; + + uint32 m_uiAggroYellTimer; + uint32 m_uiWalkTimer; + uint32 m_uiSpeachTimer; + uint32 m_uiMinionTimer; + uint32 m_uiDisarmTimer; + + uint8 m_uiSpeach; + uint8 m_uiWalk; + uint8 m_uiMinionSummoningPhase; + + void Reset() + { + DespawnAdds(); + // Coren cannot be attacked before reaching the final position + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + m_creature->setFaction(35); + + m_bEventStarted = false; + m_bAntagonistAttacked = false; + m_bIlsaSpawned = false; + m_bUrsulaSpawned = false; + + m_pInsulter = NULL; + + m_uiDisarmTimer = 12000; + m_uiAggroYellTimer = 10000; + m_uiWalkTimer = 0; + m_uiSpeachTimer = 0; + m_uiSpeach = 0; + m_uiWalk = 0; + m_uiMinionSummoningPhase = 0; + + m_uiMinionTimer = 10000; + } + + void SaySay(ObjectGuid guid, int32 text) + { + Creature* pPointer = m_creature->GetMap()->GetCreature(guid); + if (pPointer && pPointer->isAlive()) + DoScriptText(text, pPointer, NULL); + } + + void Despawn(ObjectGuid guid) + { + if (Creature* pPointer = m_creature->GetMap()->GetCreature(guid)) + pPointer->ForcedDespawn(); + } + + void Assault(ObjectGuid guid, uint32 faction, Unit* pTarget) + { + Creature* pPointer = m_creature->GetMap()->GetCreature(guid); + if (pTarget && pPointer) + { + pPointer->setFaction(faction); + pPointer->AI()->AttackStart(pTarget); + } + } + + + void DespawnAdds() + { + Despawn(m_UrsulaGuid); + Despawn(m_IlsaGuid); + Despawn(m_Antagonist1Guid); + Despawn(m_Antagonist2Guid); + Despawn(m_Antagonist3Guid); + if (m_pInstance) + if (GameObject* pMinionSummoner = m_pInstance->GetSingleGameObjectFromStorage(GO_MINIONSUMMONER)) + pMinionSummoner->SetGoState(GO_STATE_READY); + } + + void JustDied(Unit* pKiller) + { + DespawnAdds(); + + Map::PlayerList const &PlayerList = m_creature->GetMap()->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->GetQuestStatus(113021) == QUEST_STATUS_INCOMPLETE) + pPlayer->KilledMonsterCredit(428569); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->isInCombat() || !m_creature->SelectHostileTarget() || !m_creature->getVictim()) + { + // After insulting coren a small noncombat event begins + if (m_bEventStarted) + { + // Coren Walking in fornt of Antagonists + if (m_uiWalkTimer < uiDiff) + { + m_creature->SetSpeedRate(MOVE_WALK, 1.0f); + switch(m_uiWalk) + { + case 0: + m_creature->GetMotionMaster()->MovePoint(1, Coord[3][0], Coord[3][1], Coord[3][2]); + m_uiWalk = 1; + break; + case 1: + m_creature->GetMotionMaster()->MovePoint(2, Coord[4][0], Coord[4][1], Coord[4][2]); + m_uiWalk = 0; + break; + } + m_uiWalkTimer = 6000; + } + else m_uiWalkTimer -= uiDiff; + + // Coren Yell and Antagonists response + if (m_uiSpeachTimer < uiDiff) + { + switch(m_uiSpeach) + { + case 0: + DoScriptText(SAY_IDLE1, m_creature); + m_uiSpeach = 1; + m_uiSpeachTimer = 2000; + break; + case 1: + SaySay(m_Antagonist1Guid, SAY_ANTAGONIST1_1); + SaySay(m_Antagonist2Guid, SAY_ANTAGONIST1_2); + SaySay(m_Antagonist3Guid, SAY_ANTAGONIST1_3); + m_uiSpeach = 2; + m_uiSpeachTimer = 4000; + break; + case 2: + DoScriptText(SAY_IDLE2, m_creature); + m_uiSpeach = 3; + m_uiSpeachTimer = 2000; + break; + case 3: + SaySay(m_Antagonist1Guid, SAY_ANTAGONIST2_2); + SaySay(m_Antagonist2Guid, SAY_ANTAGONIST2_3); + SaySay(m_Antagonist3Guid, SAY_ANTAGONIST2_1); + m_uiSpeach = 4; + m_uiSpeachTimer = 4000; + break; + case 4: + DoScriptText(SAY_IDLE3, m_creature); + m_uiSpeach = 5; + m_uiSpeachTimer = 2000; + break; + case 5: + SaySay(m_Antagonist1Guid, SAY_ANTAGONIST1_1); + SaySay(m_Antagonist2Guid, SAY_ANTAGONIST1_2); + SaySay(m_Antagonist3Guid, SAY_ANTAGONIST1_3); + m_uiSpeach = 6; + m_uiSpeachTimer = 4000; + break; + case 6: + DoScriptText(SAY_IDLE4, m_creature); + m_uiSpeach = 7; + m_uiSpeachTimer = 2000; + break; + case 7: + SaySay(m_Antagonist1Guid, SAY_ANTAGONIST4); + SaySay(m_Antagonist2Guid, SAY_ANTAGONIST4); + SaySay(m_Antagonist3Guid, SAY_ANTAGONIST4); + DoScriptText(SAY_PAY, m_creature); + m_creature->setFaction(16); + m_creature->SetInCombatWithZone(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AttackStart(m_pInsulter); + break; + } + } + else m_uiSpeachTimer -= uiDiff; + } + } + else + { + + //Force Antagonist to assist Coren in combat + if (!m_bAntagonistAttacked && m_creature->getVictim()) + { + Assault(m_Antagonist1Guid, m_creature->getFaction(), m_creature->getVictim()); + Assault(m_Antagonist2Guid, m_creature->getFaction(), m_creature->getVictim()); + Assault(m_Antagonist3Guid, m_creature->getFaction(), m_creature->getVictim()); + m_bAntagonistAttacked = true; + } + + if (!m_bIlsaSpawned && m_creature->GetHealthPercent() <= 66.0f) + { + Creature* pIlsa = m_creature->SummonCreature(MOB_ILSA, Coord[5][0], Coord[5][1], Coord[5][2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + if (pIlsa && m_creature->getVictim()) // i know if(victim) was checked at the top but once got crash with multithreaded mangos + { + pIlsa->AI()->AttackStart(m_creature->getVictim()); + m_IlsaGuid = pIlsa->GetObjectGuid(); + m_bIlsaSpawned = true; + } + } + + if (!m_bUrsulaSpawned && m_creature->GetHealthPercent() <= 33.0f) + { + Creature* pUrsula = m_creature->SummonCreature(MOB_URSULA, Coord[5][0], Coord[5][1], Coord[5][2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + if (pUrsula && m_creature->getVictim())// i know if(victim) was checked at the top but once got crash with multithreaded mangos + { + pUrsula->AI()->AttackStart(m_creature->getVictim()); + m_UrsulaGuid = pUrsula->GetObjectGuid(); + m_bUrsulaSpawned = true; + } + } + + if (m_uiMinionTimer < uiDiff) + { + if (m_pInstance) + { + if (GameObject* pMinionSummoner = m_pInstance->GetSingleGameObjectFromStorage(GO_MINIONSUMMONER)) + { + switch(m_uiMinionSummoningPhase) + { + case 0: + pMinionSummoner->SetGoState(GO_STATE_ACTIVE); + if (m_creature->getVictim()) + if (Creature* pMinion = m_creature->SummonCreature(MOB_MINION, pMinionSummoner->GetPositionX(), pMinionSummoner->GetPositionY(), pMinionSummoner->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000)) + { + pMinion->setFaction(m_creature->getFaction()); + pMinion->AI()->AttackStart(m_creature->getVictim()); + } + m_uiMinionTimer = 3000; + m_uiMinionSummoningPhase = 1; + break; + case 1: + pMinionSummoner->SetGoState(GO_STATE_READY); + m_uiMinionTimer = 20000; + m_uiMinionSummoningPhase = 0; + break; + } + } + } + else m_uiMinionTimer = 20000; + } + else m_uiMinionTimer -= uiDiff; + + if (m_uiAggroYellTimer < uiDiff) + { + DoScriptText(SAY_AGGRO, m_creature); + m_uiAggroYellTimer = 45000 + (rand()%45000); + } + else m_uiAggroYellTimer -= uiDiff; + + if (m_uiDisarmTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_DISARM); + m_uiDisarmTimer = 12000; + } + else m_uiDisarmTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + } +}; +CreatureAI* GetAI_boss_coren_direbrew(Creature* pCreature) +{ + return new boss_coren_direbrewAI(pCreature); +} + +bool GossipSelect_boss_coren_direbrew(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + + if (pPlayer) + { + if (boss_coren_direbrewAI* pCorenAI = dynamic_cast(pCreature->AI())) + { + if( pCorenAI->m_creature == pCreature) + { + Creature* temp; + temp = pCreature->SummonCreature(MOB_ANTAGONIST, Coord[0][0], Coord[0][1], Coord[0][2], 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (temp != NULL) + { + pCorenAI->m_Antagonist1Guid = temp->GetObjectGuid(); + temp = NULL; + } + temp = pCreature->SummonCreature(MOB_ANTAGONIST, Coord[1][0], Coord[1][1], Coord[1][2], 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (temp != NULL) + { + pCorenAI->m_Antagonist2Guid = temp->GetObjectGuid(); + temp = NULL; + } + temp = pCreature->SummonCreature(MOB_ANTAGONIST, Coord[2][0], Coord[2][1], Coord[2][2], 0, TEMPSUMMON_DEAD_DESPAWN, 0); + if (temp != NULL) + { + pCorenAI->m_Antagonist3Guid = temp->GetObjectGuid(); + temp = NULL; + } + pCorenAI->m_bEventStarted = true; + pCorenAI->m_pInsulter = pPlayer; + } + } + } + return true; +} + +/*##### +# Ilsa +#####*/ +struct MANGOS_DLL_DECL mob_ilsaAI : public ScriptedAI +{ + mob_ilsaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiLaunchTimer; + uint32 m_uiCheckTimer; + + bool m_bCheck; + + Player* m_pBrewed; + + void Reset () + { + m_uiLaunchTimer = 10000; + + m_bCheck = false; + + m_pBrewed = NULL; + } + + void UpdateAI (const uint32 uiDiff) + { + if (m_uiLaunchTimer < uiDiff) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + if (m_pBrewed = m_creature->GetMap()->GetPlayer(pTarget->GetObjectGuid())) + { + ItemPosCountVec dest; + uint8 msg = m_pBrewed->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_BREWMAIDEN_BREW, 1, NULL); + if (msg == EQUIP_ERR_OK) + { + m_pBrewed->StoreNewItem(dest, ITEM_BREWMAIDEN_BREW, 1, true); + m_bCheck = true; + m_uiCheckTimer = 6000; + } + } + } + } + m_uiLaunchTimer = urand(8000, 10000); + } + else m_uiLaunchTimer -= uiDiff; + + if (m_bCheck) + { + if (m_uiCheckTimer < uiDiff) + { + m_bCheck = false; + if (m_pBrewed->HasItemCount(ITEM_BREWMAIDEN_BREW, 1)) + m_pBrewed->CastSpell(m_pBrewed, SPELL_STUN, false); + m_pBrewed = NULL; + } + else m_uiCheckTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_ilsa(Creature* pCreature) +{ + return new mob_ilsaAI(pCreature); +} + +/*##### +# Ursula +#####*/ +struct MANGOS_DLL_DECL mob_ursulaAI : public ScriptedAI +{ + mob_ursulaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiBarrelTimer; + + void Reset () + { + m_uiBarrelTimer = 10000; + } + + void UpdateAI (const uint32 uiDiff) + { + if (m_uiBarrelTimer < uiDiff) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->CastSpell(pTarget, SPELL_BARRELED, false); + } + m_uiBarrelTimer = urand(8000, 10000); + } + else m_uiBarrelTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_mob_ursula(Creature* pCreature) +{ + return new mob_ursulaAI(pCreature); +} void AddSC_boss_coren_direbrew() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_coren_direbrew"; + newscript->GetAI = &GetAI_boss_coren_direbrew; + newscript->pGossipSelect = &GossipSelect_boss_coren_direbrew; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ilsa"; + newscript->GetAI = &GetAI_mob_ilsa; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ursula"; + newscript->GetAI = &GetAI_mob_ursula; + newscript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h b/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h index 248e54bdf4..83c93ee26b 100644 --- a/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h +++ b/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h @@ -53,10 +53,11 @@ class MANGOS_DLL_DECL instance_blackrock_spire : public ScriptedInstance void OnObjectCreate(GameObject* pGo); void OnCreatureCreate(Creature* pCreature); + void OnCreatureDeath(Creature* pCreature); void SetData(uint32 uiType, uint32 uiData); - void SetData64(uint32 uiType, uint64 uiData); uint32 GetData(uint32 uiType); + void SetDataGuid(uint32 uiType, ObjectGuid uiData); const char* Save() { return m_strInstData.c_str(); } void Load(const char* chrIn); diff --git a/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp b/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp index cef7661efc..99ff0f32b7 100644 --- a/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp +++ b/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp @@ -110,6 +110,17 @@ void instance_blackrock_spire::OnCreatureCreate(Creature* pCreature) } } +void instance_blackrock_spire::OnCreatureDeath(Creature* pCreature) +{ + switch(pCreature->GetEntry()) + { + case NPC_BLACKHAND_SUMMONER: + case NPC_BLACKHAND_VETERAN: + SetDataGuid(TYPE_ROOM_EVENT, pCreature->GetObjectGuid()); + break; + } +} + void instance_blackrock_spire::SetData(uint32 uiType, uint32 uiData) { switch(uiType) @@ -161,7 +172,7 @@ void instance_blackrock_spire::SetData(uint32 uiType, uint32 uiData) } } -void instance_blackrock_spire::SetData64(uint32 uiType, uint64 uiData) +void instance_blackrock_spire::SetDataGuid(uint32 uiType, ObjectGuid uiData) { if (uiType == TYPE_ROOM_EVENT && GetData(TYPE_ROOM_EVENT) == IN_PROGRESS) { @@ -170,7 +181,7 @@ void instance_blackrock_spire::SetData64(uint32 uiType, uint64 uiData) { if (m_aRoomRuneGuid[i]) // This check is used, to ensure which runes still need processing { - m_alRoomEventMobGUIDSorted[i].remove(ObjectGuid(uiData)); + m_alRoomEventMobGUIDSorted[i].remove(uiData); if (m_alRoomEventMobGUIDSorted[i].empty()) { DoUseDoorOrButton(m_aRoomRuneGuid[i]); diff --git a/scripts/eastern_kingdoms/dun_morogh.cpp b/scripts/eastern_kingdoms/dun_morogh.cpp index af98644462..1b40890c5c 100644 --- a/scripts/eastern_kingdoms/dun_morogh.cpp +++ b/scripts/eastern_kingdoms/dun_morogh.cpp @@ -23,6 +23,9 @@ EndScriptData */ /* ContentData npc_narm_faulk +npc_neill_ramstein Brewfest event +npc_flynn_firebrew Brewfest event +npc_pol_amberstill Brewfest event EndContentData */ #include "precompiled.h" @@ -80,12 +83,180 @@ CreatureAI* GetAI_npc_narm_faulk(Creature* pCreature) return new npc_narm_faulkAI(pCreature); } +/*##### +# Neill Ramstein +#####*/ + +enum +{ + QUEST_BACK_AGAIN_A = 11122, + QUEST_BARK_FOR_BARLEY = 11293, + QUEST_BARK_FOR_THUNDER = 11294, + QUEST_NOW_RAM_RACING_A = 11318, + + SPELL_RENTAL_RAM = 43883, + SPELL_RAM_FATIGUE = 43052, + SPELL_SPEED_RAM_GALLOP = 42994, + SPELL_SPEED_RAM_CANTER = 42993, + SPELL_SPEED_RAM_TROT = 42992, + SPELL_SPEED_RAM_NORMAL = 43310, + SPELL_SPEED_RAM_EXHAUSED = 43332, + SPELL_RENTAL_RAM_DND = 42146 +}; + +bool QuestAccept_npc_neill_ramstein(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + switch (pQuest->GetQuestId()) + { + case QUEST_BACK_AGAIN_A: + case QUEST_BARK_FOR_BARLEY: + case QUEST_BARK_FOR_THUNDER: + case QUEST_NOW_RAM_RACING_A: + pPlayer->CastSpell(pPlayer, SPELL_RENTAL_RAM, false); + break; + } + return true; +} + +bool QuestRewarded_npc_neill_ramstein(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pPlayer->HasAura(SPELL_RENTAL_RAM)) + { + pPlayer->RemoveAurasDueToSpell(SPELL_RENTAL_RAM); + pPlayer->RemoveAurasDueToSpell(SPELL_RAM_FATIGUE); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_GALLOP); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_CANTER); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_TROT); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_NORMAL); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_EXHAUSED); + pPlayer->RemoveAurasDueToSpell(SPELL_RENTAL_RAM_DND); + } + return true; +} + +/*##### +# Flynn Firebrew +#####*/ +enum +{ + ITEM_PORTABLE_KEG = 33797 +}; + +struct MANGOS_DLL_DECL npc_flynn_firebrew : public ScriptedAI +{ + npc_flynn_firebrew (Creature* pCreature) : ScriptedAI (pCreature) + { + m_pMap = pCreature->GetMap(); + Reset(); + } + + Map* m_pMap; + + void Reset () {} + + void MoveInLineOfSight (Unit* pWho) + { + // player should be near the npc + if (m_creature->GetDistance(pWho) > 10.0f) + return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + Player* pPlayer = m_pMap->GetPlayer(pWho->GetObjectGuid()); + if (!pPlayer) + return; + if (pPlayer->GetQuestStatus(QUEST_BACK_AGAIN_A) == QUEST_STATUS_INCOMPLETE) + { + // player can only have 1 keg + if (pPlayer->HasItemCount(ITEM_PORTABLE_KEG, 1)) + return; + + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_PORTABLE_KEG, 1, NULL); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, ITEM_PORTABLE_KEG, 1, true); + pPlayer->GetItemByEntry(ITEM_PORTABLE_KEG)->SendCreateUpdateToPlayer(pPlayer); + } + } + } +}; + +CreatureAI* GetAI_npc_flynn_firebrew(Creature* pCreature) +{ + return new npc_flynn_firebrew(pCreature); +} + +/*##### +# Pol Amberstill +#####*/ +enum +{ + NPC_CREDIT_CREATURE = 24337, +}; + +struct MANGOS_DLL_DECL npc_pol_amberstill : public ScriptedAI +{ + npc_pol_amberstill (Creature* pCreature) : ScriptedAI (pCreature) + { + m_pMap = pCreature->GetMap(); + Reset(); + } + + Map* m_pMap; + + void Reset () {} + + void MoveInLineOfSight (Unit* pWho) + { + // player should be near the npc + if (m_creature->GetDistance(pWho) > 10.0f) + return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + Player* pPlayer = m_pMap->GetPlayer(pWho->GetObjectGuid()); + if (!pPlayer) + return; + if (pPlayer->GetQuestStatus(QUEST_BACK_AGAIN_A) == QUEST_STATUS_INCOMPLETE) + { + // player can only have 1 keg + if (pPlayer->HasItemCount(ITEM_PORTABLE_KEG, 1)) + { + pPlayer->DestroyItemCount(ITEM_PORTABLE_KEG, 1, true); + pPlayer->KilledMonsterCredit(NPC_CREDIT_CREATURE); + } + } + } +}; + +CreatureAI* GetAI_npc_pol_amberstill(Creature* pCreature) +{ + return new npc_pol_amberstill(pCreature); +} + void AddSC_dun_morogh() { - Script* pNewScript; + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_narm_faulk"; + newscript->GetAI = &GetAI_npc_narm_faulk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_neill_ramstein"; + newscript->pQuestAcceptNPC = &QuestAccept_npc_neill_ramstein; + newscript->pQuestRewardedNPC = &QuestRewarded_npc_neill_ramstein; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_flynn_firebrew"; + newscript->GetAI = &GetAI_npc_flynn_firebrew; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "npc_narm_faulk"; - pNewScript->GetAI = &GetAI_npc_narm_faulk; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_pol_amberstill"; + newscript->GetAI = &GetAI_npc_pol_amberstill; + newscript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/eastern_plaguelands.cpp b/scripts/eastern_kingdoms/eastern_plaguelands.cpp index ebc83e32d5..07ee5b5c06 100644 --- a/scripts/eastern_kingdoms/eastern_plaguelands.cpp +++ b/scripts/eastern_kingdoms/eastern_plaguelands.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Eastern_Plaguelands SD%Complete: 100 -SDComment: Quest support: 5211, 5742. Special vendor Augustus the Touched +SDComment: Quest support: 5211, 5742, 7622. Special vendor Augustus the Touched SDCategory: Eastern Plaguelands EndScriptData */ @@ -26,6 +26,8 @@ mobs_ghoul_flayer npc_augustus_the_touched npc_darrowshire_spirit npc_tirion_fordring +npc_infected_peasant +npc_eris_havenfire EndContentData */ #include "precompiled.h" @@ -147,6 +149,484 @@ bool GossipSelect_npc_tirion_fordring(Player* pPlayer, Creature* pCreature, uint return true; } +/*###### +## npc_infected_peasant +######*/ + +enum +{ + SPELL_DEATHS_DOOR = 23127, // Green (weak) + SPELL_SEETHING_PLAGUE = 23072, // Purple (strong) + + NPC_INJURED_PEASANT = 14484, + NPC_PLAGUED_PEASANT = 14485, + + SPELL_ENTER_THE_LIGHT_DND = 23107 +}; + +struct MANGOS_DLL_DECL npc_infected_peasantAI : public ScriptedAI +{ + npc_infected_peasantAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + uint32 m_uiDiseaseTimer; + + void Reset() {m_uiDiseaseTimer = 0;} + + void AttackStart(Unit* pVictim) {return;} + + // I still don't know from where I got these values + void UpdateAI(const uint32 uiDiff) + { + // Holding this aura means that this NPC is saved + if (m_creature->HasAura(SPELL_ENTER_THE_LIGHT_DND, EFFECT_INDEX_0)) + return; + + // And again... Messy, untidy, bullshit code ...for eyes :D + if (m_uiDiseaseTimer <= uiDiff) + { + uint16 uiChance = urand(1,100); + + if (uiChance <= 10 && m_creature->GetEntry() == NPC_INJURED_PEASANT) + m_creature->CastSpell(m_creature, SPELL_DEATHS_DOOR, false); + else if (uiChance <= 25) + { + if (m_creature->GetEntry() == NPC_PLAGUED_PEASANT) + m_creature->CastSpell(m_creature, SPELL_SEETHING_PLAGUE, false); + else + m_creature->CastSpell(m_creature, SPELL_DEATHS_DOOR, false); + } + else if (uiChance <= 40 && m_creature->GetEntry() == NPC_PLAGUED_PEASANT) + m_creature->CastSpell(m_creature, SPELL_DEATHS_DOOR, false); + + m_uiDiseaseTimer = urand(8000,10000); + } + else + m_uiDiseaseTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_infected_peasant(Creature* pCreature) +{ + return new npc_infected_peasantAI(pCreature); +} + +/*###### +## npc_eris_havenfire +######*/ + +// Get the right spawns for both aArcherSpawn and aPeasantSpawn +static const float aArcherSpawn[8][3] = +{ + {3327.42f, -3021.11f, 170.579f}, + {3335.4f, -3054.3f, 173.636f}, + {3314.3f, -3017.5f, 162.094f}, + {3351.3f, -3079.08f, 178.678f}, + {3358.93f, -3076.1f, 174.875f}, + {3371.58f, -3069.24f, 175.201f}, + {3377.78f, -3041.79f, 173.068f}, + {3369.46f, -3023.11f, 171.831f} +}; + +static const float aPeasantSpawn[15][3] = +{ + {3352.44f, -3048.32f, 164.833f}, + {3355.26f, -3052.93f, 165.72f}, + {3358.12f, -3050.71f, 165.307f}, + {3360.07f, -3052.31f, 165.3f}, + {3361.64f, -3055.29f, 165.295f}, + {3361.4f, -3052.17f, 165.261f}, + {3363.13f, -3056.21f, 165.285f}, + {3363.99f, -3054.49f, 165.342f}, + {3366.84f, -3053.95f, 165.541f}, + {3367.61f, -3056.84f, 165.88f}, + {3364.9f, -3052.68f, 165.321f}, + {3363.3f, -3051.2f, 165.266f}, + {3367.61f, -3051.14f, 165.517f}, + {3363.54f, -3049.64f, 165.238f}, + {3360.66f, -3049.14f, 165.261f} +}; + +static const uint32 aPeasantSpawnYell[] = {-1000696, -1000697, -1000698}; +static const uint32 aPeasantRandomSay[] = {-1000699, -1000700, -1000701}; // TODO +static const uint32 aPeasantSaveSay[] = {-1000702, -1000703, -1000704, -1000705}; + +enum +{ + QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW = 7622, + + NPC_SCOURGE_ARCHER = 14489, + NPC_SCOURGE_FOOTSOLDIER = 14486, + + SPELL_BLESSING_OF_NORDRASSIL = 23108 +}; + +// Never show this code to your friends. It's Super-Duper!! +struct MANGOS_DLL_DECL npc_eris_havenfireAI : public ScriptedAI +{ + npc_eris_havenfireAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsQuestInProgress = false; + Reset(); + } + + bool m_bIsQuestInProgress; + uint32 m_uiMainTimer; + uint8 m_uiPhase, m_uiCurrentWave, m_uiKillCounter, m_uiSaveCounter, m_uiTotalSaved, m_uiTotalKilled; + ObjectGuid m_playerGuid; + GUIDList m_lSummonedGUIDList; + + void Reset() + { + // No need to continue while 'WE ARE IN'!! + if (m_bIsQuestInProgress) + return; + + m_bIsQuestInProgress = false; + m_uiMainTimer = 5000; + m_uiPhase = 1; + m_uiCurrentWave = 0; + m_uiKillCounter = 0; + m_uiSaveCounter = 0; + m_uiTotalSaved = 0; + m_uiTotalKilled = 0; + m_playerGuid.Clear(); + + if (!m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + + // Despawn when something is spawned + if (!m_lSummonedGUIDList.empty()) + { + for (GUIDList::const_iterator itr = m_lSummonedGUIDList.begin(); itr != m_lSummonedGUIDList.end(); ++itr) + if (Creature* pSummoned = m_creature->GetMap()->GetCreature(*itr)) + pSummoned->ForcedDespawn(); + } + m_lSummonedGUIDList.clear(); + } + + void PhaseEnded(bool bFailed, bool bWave) + { + Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid); + + // Continue only when we have starting player + if (!pPlayer) + return; + + // Failed + if (bFailed && !bWave) + { + DoScriptText(urand(0, 1) ? -1000706 : -1000707, m_creature); + if (pPlayer->GetQuestStatus(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW); + + m_bIsQuestInProgress = false; + Reset(); + return; + } + + // Wave completed + if (!bFailed && bWave) + { + DoScriptText(-1000709, m_creature); + m_creature->CastSpell(pPlayer, SPELL_BLESSING_OF_NORDRASSIL, false); + // m_uiSaveCounter and m_uiKillCounter are only temporar values + m_uiSaveCounter = 0; + m_uiKillCounter = 0; + return; + } + + // Whole event completed + if (!bFailed && !bWave) + { + DoScriptText(-1000708, m_creature); + if (pPlayer->GetQuestStatus(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW); + + m_bIsQuestInProgress = false; + Reset(); + return; // Formal return? + } + } + + void DoNextWave(bool bInit) + { + if (bInit) + { + for(uint8 i = 0; i < 9; ++i) + { + if (Creature* pTemp = m_creature->SummonCreature(NPC_SCOURGE_ARCHER, aArcherSpawn[i][0], aArcherSpawn[i][1], aArcherSpawn[i][2], 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) + { + m_lSummonedGUIDList.push_back(pTemp->GetObjectGuid()); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + return; + } + + ++m_uiCurrentWave; + + uint8 uiShorter = 10 + m_uiCurrentWave; + uint8 uiRandomPeasant = urand(0, uiShorter); + + for(uint8 i = 0; i < uiShorter; ++i) + { + // As I'm reading through the code now, I see that there is a 1:7 chance to spawn a NPC_PLAGUED_PEASANT instead NPC_INJURED_PEASANT. + // The chance increases by each phase with 1 (Phase 1 - 1:7, Phase 2 - 2:7, etc...) + if (Creature* pTemp = m_creature->SummonCreature(urand(0, 7 - m_uiCurrentWave) ? NPC_INJURED_PEASANT : NPC_PLAGUED_PEASANT, aPeasantSpawn[i][0], aPeasantSpawn[i][1], aPeasantSpawn[i][2], 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + float fX, fY, fZ; + if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid)) + pTemp->setFaction(pPlayer->getFaction()); + pTemp->GetRandomPoint(3332.767f, -2979.002f, 160.97f, 5.0f, fX, fY, fZ); + pTemp->GetMotionMaster()->MovePoint(1, fX, fY, fZ); + if (i == uiRandomPeasant) + DoScriptText(aPeasantSpawnYell[urand(0,2)], pTemp); + } + } + } + + void SummonedMovementInform(Creature* pSummoned, uint32 /*uiMotionType*/, uint32 uiPointId) + { + if (uiPointId == 1) + { + if (m_uiSaveCounter >= 10 + m_uiCurrentWave) // When saved peasants exceed maximum peasants, something went wrong ^^ + debug_log("SD2: npc_eris_havenfire: Current wave %u was not reset properly in void WaveFinished().", m_uiCurrentWave); + + ++m_uiSaveCounter; + ++m_uiTotalSaved; + + // When counted, force despawn. I don't know exactly when they should disappear + pSummoned->GetMotionMaster()->Clear(false); + + if (pSummoned->HasAura(SPELL_DEATHS_DOOR, EFFECT_INDEX_0)) + pSummoned->RemoveAurasDueToSpell(SPELL_DEATHS_DOOR); + + if (pSummoned->HasAura(SPELL_SEETHING_PLAGUE, EFFECT_INDEX_0)) + pSummoned->RemoveAurasDueToSpell(SPELL_SEETHING_PLAGUE); + + uint8 uiRandomPeasant = urand(1,10); + if (uiRandomPeasant == 5) + DoScriptText(aPeasantSaveSay[urand(0,3)], pSummoned); + + pSummoned->CastSpell(pSummoned, SPELL_ENTER_THE_LIGHT_DND, false); + pSummoned->ForcedDespawn(4000); + } + } + + void SummonedCreatureJustDied(Creature* pSummoned) + { + /* We do not want to count staying peasants. + * It means that they are saved. Saved peasants are ForcedDespawn(), + * which triggers SummonedCreatureJustDied. + */ + if (pSummoned->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE && + (pSummoned->GetEntry() == NPC_INJURED_PEASANT || pSummoned->GetEntry() == NPC_PLAGUED_PEASANT)) + { + ++m_uiKillCounter; + ++m_uiTotalKilled; + } + pSummoned->RemoveCorpse(); + } + + void DoSummonFootsoldier() + { + Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid); + + for(uint8 i = 0; i < 6 + 1; ++i) + { + float fX, fY, fZ; + + if (pPlayer) + { + pPlayer->GetRandomPoint(pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 15.0f, fX, fY, fZ); + + if (Creature* pTemp = m_creature->SummonCreature(NPC_SCOURGE_FOOTSOLDIER, fX, fY, fZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + m_lSummonedGUIDList.push_back(pTemp->GetObjectGuid()); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + // Nothing is needed to update when the event is not in progress + if (!m_bIsQuestInProgress) + return; + + if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid)) + { + pPlayer->DeleteThreatList(); + if (pPlayer->GetQuestStatus(QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW) != QUEST_STATUS_INCOMPLETE || pPlayer->isDead()) + { + m_bIsQuestInProgress = false; + Reset(); + return; + } + } + + if (m_uiPhase) + { + // Reaching 15 dead peasants means fail for us + if (m_uiTotalKilled >= 15) + { + PhaseEnded(true, false); + return; + } + // Do next step + else if (m_uiKillCounter + m_uiSaveCounter == 10 + m_uiCurrentWave) + { + // When we saved 50 peasants + if (m_uiTotalSaved >= 50) + PhaseEnded(false, false); + // When the wave completed, but still we are not done + else + PhaseEnded(false, true); + + return; + } + + // No more phases or no wave + if (m_uiPhase >= 15 || !m_uiCurrentWave) + return; + + // Force Archers to attack peasants + if (!m_lSummonedGUIDList.empty()) + { + for (GUIDList::const_iterator itr = m_lSummonedGUIDList.begin(); itr != m_lSummonedGUIDList.end(); ++itr) + { + if (Creature* pArcher = m_creature->GetMap()->GetCreature(*itr)) + { + // Archer is not an 'archer' + if (pArcher->GetEntry() != NPC_SCOURGE_ARCHER) + continue; + + if (pArcher->getVictim()) + if (((pArcher->getVictim()->GetEntry() == NPC_PLAGUED_PEASANT || pArcher->getVictim()->GetEntry() == NPC_INJURED_PEASANT)) && + !pArcher->getVictim()->HasAura(SPELL_ENTER_THE_LIGHT_DND, EFFECT_INDEX_0)) + continue; + + float fRange = 59.9f; // Range above 60 yd is not valid, because ACID recognizes it as out of range + + /* Make the chance of being a victim equal for each peasant. + * I mean that now NPC_INJURED_PEASANT has now a bigger chance to be a target, + * because it is checked in the first place. On the second is NPC_PLAGUED_PEASANT. + * So this is needed to be solved. + */ + + Creature* pPeasant = GetClosestCreatureWithEntry(pArcher, NPC_INJURED_PEASANT, fRange); + if (!pPeasant) + pPeasant = GetClosestCreatureWithEntry(pArcher, NPC_PLAGUED_PEASANT, fRange); + + if (pPeasant && !pPeasant->HasAura(SPELL_ENTER_THE_LIGHT_DND, EFFECT_INDEX_0)) + pArcher->AI()->AttackStart(pPeasant); + else if (pArcher->getVictim()) + pArcher->AI()->EnterEvadeMode(); + } + } + } + + + if (m_uiMainTimer < uiDiff) + { + switch(m_uiPhase) + { + case 1: // Spawn Archers + DoNextWave(true); + m_uiMainTimer = 2000; + break; + case 2: // Wave 1 + DoNextWave(false); + m_uiMainTimer = 60000; + break; + case 3: // Wave 2 + DoNextWave(false); + m_uiMainTimer = 20000; + break; + case 4: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 5: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 6: // Wave 3 + Summon Scourge Footsoldiers + DoNextWave(false); + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 7: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 8: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 9: // Wave 4 + Summon Scourge Footsoldiers + DoNextWave(false); + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 10: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 11: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 12: // Wave 5 + Summon Scourge Footsoldiers + DoNextWave(false); + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 13: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 20000; + break; + case 14: // Summon Scourge Footsoldiers + DoSummonFootsoldier(); + m_uiMainTimer = 0; + break; + } + + /* Just a note: + * Phase is NOT Wave. Phase means a part of this event in this script. + * Wave means a wave of peasants. We have maximum of 5 waves. You never can be clear enough :P + */ + ++m_uiPhase; + } + else + m_uiMainTimer -= uiDiff; + } + else // Impossible to have m_bIsQuestInProgress and !m_uiPhase + debug_log("SD2: npc_eris_havenfire: No phase detected!"); + + } +}; + +bool QuestAccept_npc_eris_havenfire(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pQuest->GetQuestId() == QUEST_THE_BALANCE_OF_LIGHT_AND_SHADOW) + { + // Everybody loves dynamic casts <3 + if (npc_eris_havenfireAI* pEris = dynamic_cast(pCreature->AI())) + { + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + pEris->m_bIsQuestInProgress = true; + pEris->m_uiCurrentWave = 1; + pEris->m_playerGuid = pPlayer->GetObjectGuid(); + } + } + + return true; +} + +CreatureAI* GetAI_npc_eris_havenfire(Creature* pCreature) +{ + return new npc_eris_havenfireAI(pCreature); +} + void AddSC_eastern_plaguelands() { Script* pNewScript; @@ -173,4 +653,16 @@ void AddSC_eastern_plaguelands() pNewScript->pGossipHello = &GossipHello_npc_tirion_fordring; pNewScript->pGossipSelect = &GossipSelect_npc_tirion_fordring; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_infected_peasant"; + pNewScript->GetAI = &GetAI_npc_infected_peasant; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_eris_havenfire"; + pNewScript->GetAI = &GetAI_npc_eris_havenfire; + pNewScript->pQuestAcceptNPC = &QuestAccept_npc_eris_havenfire; + pNewScript->RegisterSelf(); + } diff --git a/scripts/eastern_kingdoms/eversong_woods.cpp b/scripts/eastern_kingdoms/eversong_woods.cpp index 548c365df1..ceea663e33 100644 --- a/scripts/eastern_kingdoms/eversong_woods.cpp +++ b/scripts/eastern_kingdoms/eversong_woods.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Eversong_Woods SD%Complete: 100 -SDComment: Quest support: 8483, 8488, 8490, 9686 +SDComment: Quest support: 8346, 8483, 8488, 8490, 9686 SDCategory: Eversong Woods EndScriptData */ @@ -27,6 +27,7 @@ go_harbinger_second_trial npc_prospector_anvilward npc_apprentice_mirveda npc_infused_crystal +npc_mana_wyrm EndContentData */ #include "precompiled.h" @@ -536,6 +537,44 @@ CreatureAI* GetAI_npc_infused_crystalAI(Creature* pCreature) return new npc_infused_crystalAI (pCreature); } +/*###### +## npc_mana_wyrm +######*/ + +enum +{ + ARCANE_TORRENT_MANA = 28730, + ARCANE_TORRENT_ENERGY = 25046, + ARCANE_TORRENT_RUNIC = 50613, + NPC_CREDIT_THIRST_UNENDING = 15468 +}; + +struct MANGOS_DLL_DECL npc_mana_wyrmAI : public ScriptedAI +{ + npc_mana_wyrmAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + void Reset() {} + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if ( pCaster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && ( (pSpell->Id == ARCANE_TORRENT_MANA) || (pSpell->Id == ARCANE_TORRENT_ENERGY) || (pSpell->Id == ARCANE_TORRENT_RUNIC) ) ) + { + if(((Player*)pCaster)->GetQuestStatus(8346) == QUEST_STATUS_INCOMPLETE) + { + ((Player*)pCaster)->KilledMonsterCredit(NPC_CREDIT_THIRST_UNENDING); + } + } + } +}; + +CreatureAI* GetAI_npc_mana_wyrm(Creature* pCreature) +{ + return new npc_mana_wyrmAI(pCreature); +} + void AddSC_eversong_woods() { Script* pNewScript; @@ -568,4 +607,9 @@ void AddSC_eversong_woods() pNewScript->Name = "npc_infused_crystal"; pNewScript->GetAI = &GetAI_npc_infused_crystalAI; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_mana_wyrm"; + pNewScript->GetAI = &GetAI_npc_mana_wyrm; + pNewScript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp b/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp index 6cd022c52d..c48ead7776 100644 --- a/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp +++ b/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp @@ -116,7 +116,7 @@ struct MANGOS_DLL_DECL boss_midnightAI : public ScriptedAI { m_uiPhase = 2; - if (Creature* pAttumen = m_creature->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000)) + if (Creature* pAttumen = m_creature->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000)) { m_attumenGuid = pAttumen->GetObjectGuid(); pAttumen->AI()->AttackStart(m_creature->getVictim()); diff --git a/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp b/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp index 8b1de57f80..6cd98dfe65 100644 --- a/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp +++ b/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp @@ -255,7 +255,10 @@ struct MANGOS_DLL_DECL boss_moroesAI : public ScriptedAI m_creature->setFaction(35); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCastSpellIfCan(m_creature, SPELL_VANISH); + //Momentarily workarounded because this cast make boss go crazy... -> DoCastSpellIfCan(m_creature, SPELL_VANISH); + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->RemoveAllAuras(); + //end m_bInVanish = true; m_uiVanish_Timer = 30000; m_uiWait_Timer = 5000; @@ -275,6 +278,9 @@ struct MANGOS_DLL_DECL boss_moroesAI : public ScriptedAI m_creature->setFaction(16); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //workaround + m_creature->SetVisibility(VISIBILITY_ON); + //end m_creature->AI()->AttackStart(m_creature->getVictim()); m_bInVanish = false; } diff --git a/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp b/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp index 25ceaaeffe..f76b3e40e4 100644 --- a/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp +++ b/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp @@ -17,9 +17,8 @@ /* ScriptData SDName: Ebon_Hold -SD%Complete: 95% ---- still a few minor bugs here and there -SDComment: Quest support: 12641, 12701, 12848, 12733, 12739(and 12742 to 12750), 12720, 12727, 12698. Special Npc (npc_valkyr_battle_maiden) -ToDo: +SD%Complete: 85 +SDComment: Quest support: 12848, 12733, 12739(and 12742 to 12750), 12727, 12698. SDCategory: Ebon Hold EndScriptData */ @@ -29,27 +28,13 @@ npc_death_knight_initiate npc_unworthy_initiate_anchor npc_unworthy_initiate go_acherus_soul_prison -npc_koltira_deathweaver -Mob scarlet miner -npc_scarlet_miner -mob_scarlet_ghoul -Gothik -npc_eye_of_acherus -npc_mine_cart -scourge_gryphon -npc_valkyr_battle_maiden -npc_crusade_persuaded +npc_scarlet_ghoul EndContentData */ #include "precompiled.h" #include "escort_ai.h" #include "ObjectMgr.h" #include "TemporarySummon.h" -#include "WorldPacket.h" -#include "Vehicle.h" -// not inuse yet but will be -//#define LESS_LAG // if you do not have a good server and do not want it to be laggy as hell -- uncomment this if you do - /*###### ## npc_a_special_surprise @@ -231,6 +216,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12742, QUEST_STATUS_COMPLETE); return; } break; @@ -259,6 +245,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12748, QUEST_STATUS_COMPLETE); return; } break; @@ -287,6 +274,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12744, QUEST_STATUS_COMPLETE); return; } break; @@ -315,6 +303,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12743, QUEST_STATUS_COMPLETE); return; } break; @@ -343,6 +332,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12750, QUEST_STATUS_COMPLETE); return; } break; @@ -371,6 +361,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12739, QUEST_STATUS_COMPLETE); return; } break; @@ -399,6 +390,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12745, QUEST_STATUS_COMPLETE); return; } break; @@ -427,6 +419,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12749, QUEST_STATUS_COMPLETE); return; } break; @@ -455,6 +448,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12747, QUEST_STATUS_COMPLETE); return; } break; @@ -483,6 +477,7 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI DoScriptText(EMOTE_DIES, m_creature); m_creature->SetDeathState(JUST_DIED); m_creature->SetHealth(0); + pPlayer->SetQuestStatus(12746, QUEST_STATUS_COMPLETE); return; } break; @@ -498,6 +493,36 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI else m_uiExecuteSpeech_Timer -= uiDiff; } + else if (m_playerGuid.IsEmpty()) + { + Map *map = m_creature->GetMap(); + + if (!map) + return; + + Map::PlayerList const& pPlayers = map->GetPlayers(); + + if (pPlayers.isEmpty()) + return; + + for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) + { + Player *pPlayer = itr->getSource(); + if (!pPlayer) + break; + + if (MeetQuestCondition(pPlayer)) + { + float distance = m_creature->GetDistance(pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ()); + if (distance <= 10.0f) + if (MeetQuestCondition(pPlayer)) + { + m_playerGuid = pPlayer->GetObjectGuid(); + break; + } + } + } + } } }; @@ -527,11 +552,6 @@ enum SPELL_DUEL_VICTORY = 52994, SPELL_DUEL_FLAG = 52991, - SPELL_BLOOD_STRIKE_DUEL = 52374, - SPELL_DEATH_COIL_DUEL = 52375, - SPELL_ICY_TOUCH_DUEL = 52372, - SPELL_PLAGUE_STRIKE_DUEL = 52373, - QUEST_DEATH_CHALLENGE = 12733, FACTION_HOSTILE = 2068 }; @@ -550,10 +570,6 @@ struct MANGOS_DLL_DECL npc_death_knight_initiateAI : public ScriptedAI ObjectGuid m_duelerGuid; uint32 m_uiDuelTimer; bool m_bIsDuelInProgress; - uint32 m_uiBloodStrike_Timer; - uint32 m_uiDeathCoil_Timer; - uint32 m_uiIcyTouch_Timer; - uint32 m_uiPlagueStrike_Timer; void Reset() { @@ -565,10 +581,6 @@ struct MANGOS_DLL_DECL npc_death_knight_initiateAI : public ScriptedAI m_duelerGuid.Clear(); m_uiDuelTimer = 5000; m_bIsDuelInProgress = false; - m_uiBloodStrike_Timer = 4000; - m_uiDeathCoil_Timer = 6000; - m_uiIcyTouch_Timer = 2000; - m_uiPlagueStrike_Timer = 5000; } void AttackedBy(Unit* pAttacker) @@ -624,37 +636,7 @@ struct MANGOS_DLL_DECL npc_death_knight_initiateAI : public ScriptedAI return; } - if (m_uiBloodStrike_Timer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLOOD_STRIKE_DUEL); - m_uiBloodStrike_Timer = 9000; - } - else - m_uiBloodStrike_Timer -= uiDiff; - - if (m_uiDeathCoil_Timer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_DEATH_COIL_DUEL); - m_uiDeathCoil_Timer = 8000; - } - else - m_uiDeathCoil_Timer -= uiDiff; - - if (m_uiIcyTouch_Timer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_ICY_TOUCH_DUEL); - m_uiIcyTouch_Timer = 8000; - } - else - m_uiIcyTouch_Timer -= uiDiff; - - if (m_uiPlagueStrike_Timer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_PLAGUE_STRIKE_DUEL); - m_uiPlagueStrike_Timer = 8000; - } - else - m_uiPlagueStrike_Timer -= uiDiff; + // TODO: spells DoMeleeAttackIfReady(); } @@ -719,13 +701,14 @@ enum eKoltira SPELL_KOLTIRA_TRANSFORM = 52899, SPELL_ANTI_MAGIC_ZONE = 52894, - QUEST_BLOODY_BREAKOUT = 12727, + QUEST_BREAKOUT = 12727, NPC_CRIMSON_ACOLYTE = 29007, NPC_HIGH_INQUISITOR_VALROTH = 29001, NPC_KOLTIRA_ALT = 28447, - NPC_KOLTIRA = 28912, + //not sure about this id + //NPC_DEATH_KNIGHT_MOUNT = 29201, MODEL_DEATH_KNIGHT_MOUNT = 25278 }; @@ -743,7 +726,6 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI { m_uiWave = 0; m_uiWave_Timer = 3000; - m_creature->UpdateEntry(NPC_KOLTIRA); // needs to go back to regular entry at reset m_valrothGuid.Clear(); } } @@ -760,13 +742,14 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI break; case 2: m_creature->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(m_creature, SPELL_KOLTIRA_TRANSFORM); // spell to show graphic changes + //m_creature->UpdateEntry(NPC_KOLTIRA_ALT); //unclear if we must update or not + DoCastSpellIfCan(m_creature, SPELL_KOLTIRA_TRANSFORM); break; case 3: - SetEscortPaused(true); // needs to pause wp movement + SetEscortPaused(true); m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); DoScriptText(SAY_BREAKOUT2, m_creature); - m_creature->UpdateEntry(NPC_KOLTIRA_ALT); // actual change // used to update to npc w antimagic zone template aura read sql for more notes + DoCastSpellIfCan(m_creature, SPELL_ANTI_MAGIC_ZONE); // cast again that makes bubble up break; case 4: SetRun(true); @@ -799,41 +782,40 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI { if (HasEscortState(STATE_ESCORT_PAUSED)) { - if(m_uiWave < 4 && !m_creature->HasAura(SPELL_ANTI_MAGIC_ZONE)) - DoCast(m_creature, SPELL_ANTI_MAGIC_ZONE, true); + if (m_uiWave <= 4) + { + // Renew Anti Magic Zone ASAP + if (!m_creature->HasAura(SPELL_ANTI_MAGIC_ZONE)) + m_creature->CastSpell(m_creature, SPELL_ANTI_MAGIC_ZONE, true); + } if (m_uiWave_Timer < uiDiff) { switch(m_uiWave) { case 0: - SetCombatMovement(false); // needed or he moves and doesnt stay in place DoScriptText(SAY_BREAKOUT3, m_creature); SummonAcolyte(3); m_uiWave_Timer = 20000; break; case 1: - SetCombatMovement(false); // needed or he moves and doesnt stay in place DoScriptText(SAY_BREAKOUT4, m_creature); SummonAcolyte(3); m_uiWave_Timer = 20000; break; case 2: - SetCombatMovement(false); // needed or he moves and doesnt stay in place DoScriptText(SAY_BREAKOUT5, m_creature); SummonAcolyte(4); m_uiWave_Timer = 20000; break; case 3: - SetCombatMovement(false); // needed or he moves and doesnt stay in place DoScriptText(SAY_BREAKOUT6, m_creature); m_creature->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329f, -6045.818f, 127.583f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); m_uiWave_Timer = 1000; break; - // missing script text 7 = SAY_BREAKOUT7 case 4: { - Creature* pTemp = m_creature->GetMap()->GetCreature(m_valrothGuid); // var to get valroth 's guid + Creature* pTemp = m_creature->GetMap()->GetCreature(m_valrothGuid); if (!pTemp || !pTemp->isAlive()) { @@ -849,13 +831,12 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI } case 5: DoScriptText(SAY_BREAKOUT9, m_creature); - SetCombatMovement(true); // OK,OK deathweaver do your thing - m_creature->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); // this will remove the aura before he takes off + m_creature->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); m_uiWave_Timer = 2500; break; case 6: DoScriptText(SAY_BREAKOUT10, m_creature); - SetEscortPaused(false); // moving on wp is ok now + SetEscortPaused(false); break; } @@ -879,7 +860,7 @@ CreatureAI* GetAI_npc_koltira_deathweaver(Creature* pCreature) bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, const Quest* pQuest) { - if (pQuest->GetQuestId() == QUEST_BLOODY_BREAKOUT) + if (pQuest->GetQuestId() == QUEST_BREAKOUT) { pCreature->SetStandState(UNIT_STAND_STATE_STAND); @@ -890,7 +871,7 @@ bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, c } /*###### -## npc_unworthy_initiate_anchor +## ######*/ enum @@ -947,6 +928,10 @@ DisplayToSpell m_aDisplayToSpell[] = {25373, 51551} // belf M }; +/*###### +## npc_unworthy_initiate_anchor +######*/ + struct MANGOS_DLL_DECL npc_unworthy_initiate_anchorAI : public ScriptedAI { npc_unworthy_initiate_anchorAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } @@ -1028,6 +1013,7 @@ struct MANGOS_DLL_DECL npc_unworthy_initiateAI : public ScriptedAI if (m_creature->getFaction() != m_uiNormFaction) m_creature->setFaction(m_uiNormFaction); + m_myAnchorGuid.Clear(); m_uiAnchorCheckTimer = 5000; m_uiPhase = PHASE_INACTIVE_OR_COMBAT; m_uiPhaseTimer = 7500; @@ -1040,12 +1026,6 @@ struct MANGOS_DLL_DECL npc_unworthy_initiateAI : public ScriptedAI void JustReachedHome() { SetAnchor(); - - if (Creature* pAnchor = GetAnchor()) - { - if (npc_unworthy_initiate_anchorAI* pAnchorAI = dynamic_cast(pAnchor->AI())) - pAnchorAI->ResetPrison(); - } } void JustRespawned() @@ -1302,62 +1282,6 @@ CreatureAI* GetAI_npc_eye_of_acherus(Creature* pCreature) return new npc_eye_of_acherusAI(pCreature); } -/*###### -## Mob scarlet miner -######*/ -enum scarletminer -{ - QUEST_GIFT_THAT_KEEPS_GIVING = 12698, - SPELL_GIFT_OF_THE_HARVESTER_MISSILE = 52481, - SPELL_SUMMOM_GHOUL = 52490, - SPELL_SUMMON_GHOST = 52505, -}; - -struct MANGOS_DLL_DECL mob_scarlet_minerAI : public ScriptedAI -{ - mob_scarlet_minerAI(Creature *pCreature) : ScriptedAI(pCreature) - { - // NEEDS CORRECTED/OR SUPPORT IN CORE SO HACK CAN BE REMOVED - // hack spell 52481 - // 35% chance to summon ghoul - SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_GIFT_OF_THE_HARVESTER_MISSILE); - if (TempSpell && TempSpell->EffectImplicitTargetB[0] != 16) - { - TempSpell->EffectImplicitTargetB[0] = 16; - TempSpell->EffectImplicitTargetB[1] = 87; - TempSpell->EffectImplicitTargetB[2] = 16; - } - } - - void Reset() {} - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (pCaster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && pSpell->Id == SPELL_GIFT_OF_THE_HARVESTER_MISSILE) - { - if(((Player*)pCaster)->GetQuestStatus(QUEST_GIFT_THAT_KEEPS_GIVING) == QUEST_STATUS_INCOMPLETE) - { - if (rand()%100 < 35) //35% chance to summon ghoul - { - pCaster->CastSpell(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),SPELL_SUMMOM_GHOUL, true); - } - else - { - pCaster->CastSpell(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),SPELL_SUMMON_GHOST, true); - } - - m_creature->SetDeathState(JUST_DIED); - m_creature->RemoveCorpse(); - } - } - } -}; - -CreatureAI* GetAI_mob_scarlet_miner(Creature* pCreature) -{ - return new mob_scarlet_minerAI (pCreature); -}; - /*###### ## mob_scarlet_ghoul ######*/ @@ -1387,8 +1311,8 @@ struct MANGOS_DLL_DECL mob_scarlet_ghoulAI : public ScriptedAI { m_bIsSpawned = false; fDist = (float)urand(1, 5); - m_creatorGuid = m_creature->GetCreatorGuid(); - if (Player* pOwner = m_creature->GetMap()->GetPlayer(m_creatorGuid) ) + m_uiCreatorGuid = m_creature->GetCreatorGuid(); + if (Player* pOwner = m_creature->GetMap()->GetPlayer(m_uiCreatorGuid) ) fAngle = m_creature->GetAngle(pOwner); Reset(); @@ -1397,9 +1321,9 @@ struct MANGOS_DLL_DECL mob_scarlet_ghoulAI : public ScriptedAI Unit* pTarget; - ObjectGuid m_creatorGuid; - ObjectGuid m_targetGUID; - ObjectGuid m_harvesterGUID; + ObjectGuid m_uiCreatorGuid; + ObjectGuid m_uiTargetGUID; + ObjectGuid m_uiHarvesterGUID; uint32 m_uiWaitForThrowTimer; @@ -1414,20 +1338,19 @@ struct MANGOS_DLL_DECL mob_scarlet_ghoulAI : public ScriptedAI m_uiWaitForThrowTimer = 3000; m_bWaitForThrow = false; pTarget = NULL; - //m_creatorGuid.Clear(); - m_targetGUID.Clear(); - m_harvesterGUID.Clear(); + m_uiTargetGUID.Clear(); + m_uiHarvesterGUID.Clear(); } void MoveInLineOfSight(Unit *pWho) { if (!m_bWaitForThrow && pWho->GetEntry() == ENTRY_GOTHIK && m_creature->GetDistance(pWho) < 15.0f) { - m_harvesterGUID = pWho->GetObjectGuid(); + m_uiHarvesterGUID = pWho->GetObjectGuid(); - if (Player* pOwner = m_creature->GetMap()->GetPlayer(m_creatorGuid) ) + if (Player* pOwner = m_creature->GetMap()->GetPlayer(m_uiCreatorGuid) ) { - pOwner->KilledMonsterCredit(m_creature->GetEntry(), m_creature->GetObjectGuid() ); + pOwner->KilledMonsterCredit(m_creature->GetEntry()); // this will execute if m_creature survived Harvester's wrath float x, y, z, o; o = float(urand(53, 57))/10.0f; @@ -1452,7 +1375,7 @@ struct MANGOS_DLL_DECL mob_scarlet_ghoulAI : public ScriptedAI { if (m_uiWaitForThrowTimer <= uiDiff) { - if (Creature* pGothik = m_creature->GetMap()->GetCreature(m_harvesterGUID) ) + if (Creature* pGothik = m_creature->GetMap()->GetCreature(m_uiHarvesterGUID) ) { if (pGothik->AI()->DoCastSpellIfCan(m_creature, roll_chance_i(50) ? 52519 : 52521) == CAST_OK) DoScriptText(SAY_SCARLET_GOTHIK1 - urand(0, 4), pGothik); @@ -1467,7 +1390,7 @@ struct MANGOS_DLL_DECL mob_scarlet_ghoulAI : public ScriptedAI return; } - Player* pOwner = m_creature->GetMap()->GetPlayer(m_creatorGuid); + Player* pOwner = m_creature->GetMap()->GetPlayer(m_uiCreatorGuid); if (!pOwner || !pOwner->IsInWorld()) { m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); @@ -1819,6 +1742,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI uiTargetcheck = 10000; ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetVisibility(VISIBILITY_ON); m_creature->Mount(25279); UpdateWorldState(m_creature->GetMap(), WORLD_STATE_REMAINS, 0); @@ -2608,7 +2532,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI pTemp->SetWalk(false); pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x, LightofDawnLoc[2].y, LightofDawnLoc[2].z); if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) - pTemp->GetMap()->CreatureRelocation(pTemp, LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z, 0.0f); // workarounds, he should kick back by Tirion, but here we relocate him + pTemp->GetMap()->CreatureRelocation(pTemp, LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z, 0.0f); // workarounds, he should kick back by Tirion, but here we relocate him } JumpToNextStep(1500); break; @@ -3087,7 +3011,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature) { if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu( pCreature->GetObjectGuid() ); + pPlayer->PrepareQuestMenu( pCreature->GetObjectGuid()); if (pPlayer->GetQuestStatus(12801) == QUEST_STATUS_INCOMPLETE) pPlayer->ADD_GOSSIP_ITEM( 0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); @@ -3126,7 +3050,7 @@ struct MANGOS_DLL_DECL npc_the_lich_king_tirion_dawnAI : public ScriptedAI ## npc orbaz, koltira, tassarian ######*/ struct MANGOS_DLL_DECL npc_minibosses_dawn_of_lightAI : public ScriptedAI -{ +{ npc_minibosses_dawn_of_lightAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } uint32 uiIcyTouchTimer; @@ -3266,93 +3190,6 @@ struct MANGOS_DLL_DECL mob_acherus_ghoulAI : public ScriptedAI } }; -/*###### -## npc_valkyr_battle_maiden -######*/ - -enum -{ - SPELL_REVIVE = 51918, -}; - -#define REVIVE_WHISPER "It is not yet your time, champion. Rise! Rise and fight once more!" - -struct MANGOS_DLL_DECL npc_valkyr_battle_maidenAI : ScriptedAI -{ - npc_valkyr_battle_maidenAI(Creature* pCreature) : ScriptedAI(pCreature) - { - Reset(); - } - - float x, y, z; - - uint32 m_uiPhase; - uint32 m_uiPhaseTimer; - ObjectGuid m_summonerGuid; - - void Reset() - { - m_summonerGuid.Clear(); - - if (m_summonerGuid = (dynamic_cast(m_creature))->GetSummonerGuid()) - if(Unit* pUnit = m_creature->GetMap()->GetUnit(m_summonerGuid)) - if(pUnit->GetTypeId() != TYPEID_PLAYER) - m_summonerGuid.Clear(); - - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - m_creature->SetVisibility(VISIBILITY_OFF); - m_creature->SetLevitate(true); - m_uiPhase = 0; - m_uiPhaseTimer = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - Player* pPlayer = NULL; - if (!(pPlayer = (Player*)m_creature->GetMap()->GetUnit(m_summonerGuid))) - m_uiPhase = 3; - - if (m_uiPhaseTimer <= uiDiff) - { - switch (m_uiPhase) - { - case 0: - pPlayer->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius()); - m_creature->GetMotionMaster()->MovementExpired(); - m_creature->GetMap()->CreatureRelocation(m_creature, x-2.0f , y-1.5f, z+2.5f, 0); - m_creature->SetFacingToObject(pPlayer); - m_creature->SetVisibility(VISIBILITY_ON); - m_uiPhase++; - break; - case 1: - m_creature->SetGuidValue(UNIT_FIELD_TARGET, pPlayer->GetObjectGuid()); - m_uiPhase++; - break; - case 2: - DoCast(pPlayer, SPELL_REVIVE, true); - m_creature->MonsterWhisper(REVIVE_WHISPER, pPlayer); - // cause 51918 has cast time of 2 seconds - m_uiPhaseTimer = 3000; - m_uiPhase++; - break; - case 3: - m_creature->ForcedDespawn(); - default: - break; - } - } - else - m_uiPhaseTimer -= uiDiff; - } -}; - - -CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature) -{ - return new npc_valkyr_battle_maidenAI(pCreature); -}; - /*###### ## mob_warrior_of_the_frozen_wastes (53631) ######*/ @@ -3446,11 +3283,10 @@ struct MANGOS_DLL_DECL npc_mine_carAI : public ScriptedAI Reset(); } - ObjectGuid m_scarletMinerGuid; + ObjectGuid m_uiScarletMinerGuid; void Reset() { - m_scarletMinerGuid.Clear(); } void MoveInLineOfSight(Unit* /*pUnit*/) @@ -3470,12 +3306,12 @@ struct MANGOS_DLL_DECL npc_mine_carAI : public ScriptedAI void SetScarletMinerGuid(const ObjectGuid &guid) { - m_scarletMinerGuid = guid; + m_uiScarletMinerGuid = guid; } void FollowMiner() { - if(Creature* pMiner = m_creature->GetMap()->GetCreature(m_scarletMinerGuid)) + if(Creature* pMiner = m_creature->GetMap()->GetCreature(m_uiScarletMinerGuid)) { // buggy sometimes... m_creature->SetSpeedRate(MOVE_WALK, 1.5f, true); @@ -3488,31 +3324,24 @@ struct MANGOS_DLL_DECL npc_mine_carAI : public ScriptedAI void ExitMineCar() { - if (Creature* pMiner = m_creature->GetMap()->GetCreature(m_scarletMinerGuid)) + if(Creature* pMiner = m_creature->GetMap()->GetCreature(m_uiScarletMinerGuid)) pMiner->ForcedDespawn(); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 /*uiDiff*/) { - if (m_creature->GetVehicleKit()->HasEmptySeat(0)) - { - m_creature->ForcedDespawn(); - } } }; -/*###### -## npc_scarlet_miner -######*/ - enum { - SPELL_CAR_DRAG = 52465, - SPELL_CAR_CHECK = 54173 + SPELL_CAR_DRAG = 52465, + SPELL_CAR_CHECK = 54173 }; -#define SAY_SCARLET_MINER1 "Where'd this come from? I better get this down to the ships before the foreman sees it!" -#define SAY_SCARLET_MINER2 "Now I can have a rest!" +/*###### +## npc_scarlet_miner +######*/ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI { @@ -3524,10 +3353,10 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI uint32 m_uiMonoTimer; uint32 m_uiMonoPhase; - - ObjectGuid m_mineCarGuid; - ObjectGuid m_playerGuid; - + + ObjectGuid m_uiMineCarGuid; + ObjectGuid m_uiPlayerGuid; + bool m_bReachedShip; uint32 m_uiShipDelay; @@ -3536,8 +3365,8 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI m_uiMonoTimer = 0; m_uiMonoPhase = 0; - m_mineCarGuid.Clear(); - m_playerGuid.Clear(); + m_uiMineCarGuid.Clear(); + m_uiPlayerGuid.Clear(); m_bReachedShip = false; m_uiShipDelay = 3000; @@ -3545,10 +3374,12 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI void StartCarEvent(Player *pPlayer) { + pPlayer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (pPlayer->GetVehicle()) { - m_mineCarGuid = pPlayer->GetVehicle()->GetBase()->GetObjectGuid(); - m_playerGuid = pPlayer->GetObjectGuid(); + m_uiMineCarGuid = pPlayer->GetVehicle()->GetBase()->GetObjectGuid(); + m_uiPlayerGuid = pPlayer->GetObjectGuid(); Start(false, pPlayer); } } @@ -3558,9 +3389,10 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI switch(uiWp) { case 0: - if (Unit* pMineCar = m_creature->GetMap()->GetCreature(m_mineCarGuid)) + if (Unit *pMineCar = m_creature->GetMap()->GetCreature(m_uiMineCarGuid)) m_creature->SetInFront(pMineCar); - + + // say something SetRun(true); m_uiMonoTimer = 4000; m_uiMonoPhase = 1; @@ -3581,9 +3413,7 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI { if (m_uiMonoPhase == 1) { - m_creature->MonsterSay(SAY_SCARLET_MINER1,LANG_UNIVERSAL, NULL); - - if (Creature *pMineCar = m_creature->GetMap()->GetCreature(m_mineCarGuid)) + if (Creature *pMineCar = m_creature->GetMap()->GetCreature(m_uiMineCarGuid)) DoCast(pMineCar, SPELL_CAR_DRAG); m_uiMonoTimer = 800; @@ -3591,7 +3421,7 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI } else { - if (Creature *pMineCar = m_creature->GetMap()->GetCreature(m_mineCarGuid)) + if (Creature *pMineCar = m_creature->GetMap()->GetCreature(m_uiMineCarGuid)) { if(npc_mine_carAI* pMineCarAI = dynamic_cast(pMineCar->AI())) { @@ -3609,22 +3439,25 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI { if (m_uiShipDelay <= uiDiff) { - if (Creature *pMineCar = m_creature->GetMap()->GetCreature(m_mineCarGuid)) + if (Creature *pMineCar = m_creature->GetMap()->GetCreature(m_uiMineCarGuid)) { m_creature->SetInFront(pMineCar); - m_creature->MonsterSay(SAY_SCARLET_MINER2,LANG_UNIVERSAL, NULL); + pMineCar->Relocate(pMineCar->GetPositionX(), pMineCar->GetPositionY(), pMineCar->GetPositionZ() + 1); pMineCar->GetMotionMaster()->MovementExpired(); pMineCar->StopMoving(); pMineCar->RemoveAurasDueToSpell(SPELL_CAR_DRAG); - if (Player *pPlayer = m_creature->GetMap()->GetPlayer(ObjectGuid(m_playerGuid))) + if (Player *pPlayer = m_creature->GetMap()->GetPlayer(ObjectGuid(m_uiPlayerGuid))) { + pPlayer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (pPlayer->GetVehicle()) pPlayer->ExitVehicle(); } - if (npc_mine_carAI* pMineCarAI = dynamic_cast(pMineCar->AI())) + // Say something + + if(npc_mine_carAI* pMineCarAI = dynamic_cast(pMineCar->AI())) { pMineCarAI->ExitMineCar(); } @@ -3639,36 +3472,29 @@ struct MANGOS_DLL_DECL npc_scarlet_minerAI : public npc_escortAI } }; -/*###### -## go_inconspicous_mine_car -######*/ - enum { - QUEST_MASSACRE_AT_LIGHTS_POINT = 12701, + QUEST_MASSACRE_AT_LIGHTS_POINT = 12701, - ENTRY_SCARLET_MINER = 28841, - ENTRY_MINE_CAR = 28817, + ENTRY_SCARLET_MINER = 28841, + ENTRY_MINE_CAR = 28817, - SPELL_MINE_CAR_SUMM = 52463 + SPELL_MINE_CAR_SUMM = 52463 }; -bool GOUse_go_inconspicous_mine_car(Player* pPlayer, GameObject* /*pGo*/) +bool GOUse_inconspicous_mine_car(Player *pPlayer, GameObject* /*pGo*/) { if (pPlayer->GetQuestStatus(QUEST_MASSACRE_AT_LIGHTS_POINT) == QUEST_STATUS_INCOMPLETE) { - if (pPlayer->GetVehicle()) - return false; - - if (Creature* pMiner = pPlayer->SummonCreature(ENTRY_SCARLET_MINER, 2383.869f, -5900.312f, 107.996f, pPlayer->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN, 1)) + if (Creature *pMiner = pPlayer->SummonCreature(ENTRY_SCARLET_MINER, 2383.869629f, -5900.312500f, 107.996086f, pPlayer->GetOrientation(),TEMPSUMMON_DEAD_DESPAWN, 1)) { pPlayer->CastSpell(pPlayer, SPELL_MINE_CAR_SUMM, true); - if (Creature* pMineCar = (Creature*)pPlayer->GetVehicle()->GetBase()) + if (Creature *pMineCar = (Creature*)pPlayer->GetVehicle()->GetBase()) { if (npc_mine_carAI* pMineCarAI = dynamic_cast(pMineCar->AI())) { pMineCarAI->SetScarletMinerGuid(pMiner->GetObjectGuid()); - if (npc_scarlet_minerAI* pMinerAI = dynamic_cast(pMiner->AI())) + if(npc_scarlet_minerAI* pMinerAI = dynamic_cast(pMiner->AI())) { pMinerAI->StartCarEvent(pPlayer); } @@ -3700,12 +3526,27 @@ struct MANGOS_DLL_DECL npc_scourge_gryphonAI : public npc_escortAI { } + void MoveInLineOfSight(Unit* /*pUnit*/) + { + return; + } + + void EnterCombat(Unit* /*pUnit*/) + { + return; + } + + void AttackStart(Unit* /*pUnit*/) + { + return; + } + void SpellHit(Unit* pUnit, const SpellEntry* pSpell) { if (pUnit && pUnit->GetTypeId() == TYPEID_PLAYER) { if (pSpell->Id == RIDE_VEHICLE_HARDCODED) - { + { FlyToDeathsBreach((Player*)pUnit); } } @@ -3715,7 +3556,7 @@ struct MANGOS_DLL_DECL npc_scourge_gryphonAI : public npc_escortAI { pPlayer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - // Need to be set here. If flag is applied earlier, the Spell Immune Mask + // Need to be set here. If flag is applied earlier, the Spell Immune Mask // makes the vehicle mount spell (ID - 46598 Ride Vehicle Hardcoded) disfunctional m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetLevitate(true); @@ -3727,14 +3568,17 @@ struct MANGOS_DLL_DECL npc_scourge_gryphonAI : public npc_escortAI { switch(uiWp) { - case 0: + case 1: SetRun(); break; case 4: + if (m_creature->GetVehicle()) + m_creature->GetVehicle()->RemoveAllPassengers(); + if (Player* pPlayer = GetPlayerForEscort()) pPlayer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->ForcedDespawn(); // should be enough to remove players just take the vehicle away 8) + m_creature->ForcedDespawn(); return; default: break; @@ -3748,184 +3592,87 @@ struct MANGOS_DLL_DECL npc_scourge_gryphonAI : public npc_escortAI }; /*###### -## quest How To Win Friends And Influence Enemies && replaces EventAI for these npcs overall +## npc_valkyr_battle_maiden ######*/ -enum win_friends -{ - QUEST_HOW_TO_WIN_FRIENDS = 12720, - - NPC_PREACHER = 28939, - SPELL_HOLY_FURY_OOC = 34809, - SPELL_HOLY_SMITE = 15498, - - NPC_MARKSMEN = 28610, - SPELL_RAPTOR_STRIKE = 32915, - - SAY_PERSUADE1 = -1609101, - SAY_PERSUADE2 = -1609102, - SAY_PERSUADE3 = -1609103, - SAY_PERSUADE4 = -1609104, - SAY_PERSUADE5 = -1609105, - SAY_PERSUADE6 = -1609106, - SAY_PERSUADE7 = -1609107, - SAY_CRUSADER1 = -1609108, - SAY_CRUSADER2 = -1609109, - SAY_CRUSADER3 = -1609110, - SAY_CRUSADER4 = -1609111, - SAY_CRUSADER5 = -1609112, - SAY_CRUSADER6 = -1609113, - SAY_PERSUADED1 = -1609114, - SAY_PERSUADED2 = -1609115, - SAY_PERSUADED3 = -1609116, - SAY_PERSUADED4 = -1609117, - SAY_PERSUADED5 = -1609118, - SAY_PERSUADED6 = -1609119, - SPELL_PERSUASIVE_STRIKE = 52781 +enum +{ + SPELL_REVIVE = 51918, }; -struct MANGOS_DLL_DECL npc_crusade_persuadedAI : public ScriptedAI +#define REVIVE_WHISPER "It is not yet your time, champion. Rise! Rise and fight once more!" + +struct MANGOS_DLL_DECL npc_valkyr_battle_maidenAI : ScriptedAI { - npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature) + npc_valkyr_battle_maidenAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } - ObjectGuid m_playerGUID; - uint32 m_uiSpeech_timer; - uint32 m_uiSpeech_counter; - uint32 m_uiCrusade_faction; + float x, y, z; - uint32 m_uiHOLYFURYTimer; - uint32 m_uiHOLYSMITETimer; - uint32 m_uiRATORSTRIKETimer; + uint32 m_uiPhase; + uint32 m_uiPhaseTimer; + ObjectGuid m_uiSummonerGuid; void Reset() { - m_uiSpeech_timer = 0; - m_uiSpeech_counter = 0; - m_uiCrusade_faction = 0; - m_playerGUID.Clear(); + m_uiSummonerGuid.Clear(); - m_uiHOLYFURYTimer = 60000; - m_uiHOLYSMITETimer = 5500; + if (m_uiSummonerGuid = (dynamic_cast(m_creature))->GetSummonerGuid()) + if(Unit* pUnit = m_creature->GetMap()->GetUnit(m_uiSummonerGuid)) + if(pUnit->GetTypeId() != TYPEID_PLAYER) + m_uiSummonerGuid.Clear(); - m_uiRATORSTRIKETimer = 4500; - } + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && spell->Id == SPELL_PERSUASIVE_STRIKE && m_uiSpeech_counter == 0) - { - if(((Player*)caster)->GetQuestStatus(QUEST_HOW_TO_WIN_FRIENDS) == QUEST_STATUS_INCOMPLETE) - { - if (rand()%100 > 90) // chance - { - m_playerGUID = ((Player*)caster)->GetObjectGuid(); - m_uiCrusade_faction = m_creature->getFaction(); - m_uiSpeech_timer = 1000; - m_uiSpeech_counter = 1; - m_creature->setFaction(35); - } - else if (m_uiSpeech_counter == 0) - { - switch(rand()%6) - { - case 0: DoScriptText(SAY_PERSUADE1, caster);break; - case 1: DoScriptText(SAY_PERSUADE2, caster);break; - case 2: DoScriptText(SAY_PERSUADE3, caster);break; - case 3: DoScriptText(SAY_PERSUADE4, caster);break; - case 4: DoScriptText(SAY_PERSUADE5, caster);break; - case 5: DoScriptText(SAY_PERSUADE6, caster);break; - case 6: DoScriptText(SAY_PERSUADE7, caster);break; - } - switch(rand()%5) - { - case 0: DoScriptText(SAY_CRUSADER1, m_creature);break; - case 1: DoScriptText(SAY_CRUSADER2, m_creature);break; - case 2: DoScriptText(SAY_CRUSADER3, m_creature);break; - case 3: DoScriptText(SAY_CRUSADER4, m_creature);break; - case 4: DoScriptText(SAY_CRUSADER5, m_creature);break; - case 5: DoScriptText(SAY_CRUSADER6, m_creature);break; - } - } - } - } + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->SetLevitate(true); + m_uiPhase = 0; + m_uiPhaseTimer = 0; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { - if (m_uiSpeech_counter >= 1 && m_uiSpeech_counter <= 6) + Player* pPlayer = NULL; + if (!(pPlayer = (Player*)m_creature->GetMap()->GetUnit(m_uiSummonerGuid))) + m_uiPhase = 3; + + if (m_uiPhaseTimer <= uiDiff) { - if (m_uiSpeech_timer < diff) + switch (m_uiPhase) { - m_creature->CombatStop(true); - m_creature->StopMoving(); - if (Unit* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGUID)) - { - switch(m_uiSpeech_counter) - { - case 1: DoScriptText(SAY_PERSUADED1, m_creature); m_uiSpeech_timer = 8000; m_uiSpeech_counter++; break; - case 2: DoScriptText(SAY_PERSUADED2, m_creature); m_uiSpeech_timer = 8000; m_uiSpeech_counter++; break; - case 3: DoScriptText(SAY_PERSUADED3, m_creature); m_uiSpeech_timer = 8000; m_uiSpeech_counter++; break; - case 4: DoScriptText(SAY_PERSUADED4, m_creature); m_uiSpeech_timer = 8000; m_uiSpeech_counter++; break; - case 5: DoScriptText(SAY_PERSUADED5, pPlayer); m_uiSpeech_timer = 8000; m_uiSpeech_counter++; break; - case 6: - DoScriptText(SAY_PERSUADED6, m_creature); - m_creature->setFaction(m_uiCrusade_faction); - m_uiSpeech_timer = 0; - m_uiCrusade_faction = 0; - m_uiSpeech_counter++; - AttackStart(pPlayer); - if(((Player*)pPlayer)->GetQuestStatus(QUEST_HOW_TO_WIN_FRIENDS) == QUEST_STATUS_INCOMPLETE) - ((Player*)pPlayer)->AreaExploredOrEventHappens(QUEST_HOW_TO_WIN_FRIENDS); - break; - } - } + case 0: + pPlayer->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius()); + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMap()->CreatureRelocation(m_creature, x-2.0f , y-1.5f, z+2.5f, 0); + m_creature->SetFacingToObject(pPlayer); + m_creature->SetVisibility(VISIBILITY_ON); + m_uiPhase++; + break; + case 1: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pPlayer->GetObjectGuid().GetRawValue()); + m_uiPhase++; + break; + case 2: + DoCast(pPlayer, SPELL_REVIVE, true); + m_creature->MonsterWhisper(REVIVE_WHISPER, pPlayer); + // cause 51918 has cast time of 2 seconds + m_uiPhaseTimer = 3000; + m_uiPhase++; + break; + case 3: + m_creature->ForcedDespawn(); + default: + break; } - else - m_uiSpeech_timer -= diff; } else - { - if (m_creature->GetEntry() == NPC_PREACHER) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiHOLYSMITETimer < diff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_HOLY_SMITE); - m_uiHOLYSMITETimer = 5500 + rand()%1400; - }else m_uiHOLYSMITETimer -= diff; - - if (m_uiHOLYFURYTimer < diff) - { - DoCastSpellIfCan(m_creature, SPELL_HOLY_FURY_OOC); - m_uiHOLYFURYTimer = 1000 + rand()%90000; - }else m_uiHOLYFURYTimer -= diff; - - DoMeleeAttackIfReady(); - } - else - { - if (m_creature->GetEntry() == NPC_MARKSMEN) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiRATORSTRIKETimer < diff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_RAPTOR_STRIKE); - m_uiRATORSTRIKETimer = 4500 + rand()%1400; - }else m_uiRATORSTRIKETimer -= diff; - DoMeleeAttackIfReady(); - } - } - } + m_uiPhaseTimer -= uiDiff; } }; + //Scarlet courier enum ScarletCourierEnum { @@ -3937,7 +3684,7 @@ enum ScarletCourierEnum struct MANGOS_DLL_DECL mob_scarlet_courierAI : ScriptedAI { - mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) + mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) { Reset(); } @@ -3978,7 +3725,7 @@ struct MANGOS_DLL_DECL mob_scarlet_courierAI : ScriptedAI { case 1: m_creature->SetWalk(true); - if (GameObject* tree = GetClosestGameObjectWithEntry(m_creature,GO_INCONSPICUOUS_TREE, 40.0f)) + if (GameObject* tree = m_creature->GetClosestGameObjectWithEntry(m_creature,GO_INCONSPICUOUS_TREE, 40.0f)) { DoScriptText(SAY_TREE1, m_creature); float x, y, z; @@ -3987,7 +3734,7 @@ struct MANGOS_DLL_DECL mob_scarlet_courierAI : ScriptedAI } break; case 2: - if (GameObject* tree = GetClosestGameObjectWithEntry(m_creature,GO_INCONSPICUOUS_TREE, 40.0f)) + if (GameObject* tree = m_creature->GetClosestGameObjectWithEntry(m_creature,GO_INCONSPICUOUS_TREE, 40.0f)) if (Unit *unit = tree->GetOwner()) AttackStart(unit); break; @@ -4006,39 +3753,151 @@ struct MANGOS_DLL_DECL mob_scarlet_courierAI : ScriptedAI } }; -CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) +/*###### +## quest How To Win Friends And Influence Enemies +######*/ +enum win_friends { - return new mob_scarlet_courierAI(pCreature); + SAY_PERSUADE1 = -1609101, + SAY_PERSUADE2 = -1609102, + SAY_PERSUADE3 = -1609103, + SAY_PERSUADE4 = -1609104, + SAY_PERSUADE5 = -1609105, + SAY_PERSUADE6 = -1609106, + SAY_PERSUADE7 = -1609107, + SAY_CRUSADER1 = -1609108, + SAY_CRUSADER2 = -1609109, + SAY_CRUSADER3 = -1609110, + SAY_CRUSADER4 = -1609111, + SAY_CRUSADER5 = -1609112, + SAY_CRUSADER6 = -1609113, + SAY_PERSUADED1 = -1609114, + SAY_PERSUADED2 = -1609115, + SAY_PERSUADED3 = -1609116, + SAY_PERSUADED4 = -1609117, + SAY_PERSUADED5 = -1609118, + SAY_PERSUADED6 = -1609119, + SPELL_PERSUASIVE_STRIKE = 52781 }; -CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature) +struct MANGOS_DLL_DECL npc_crusade_persuadedAI : public ScriptedAI { - return new npc_crusade_persuadedAI(pCreature); + npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 uiSpeech_timer; + uint32 uiSpeech_counter; + uint32 uiCrusade_faction; + ObjectGuid uiPlayerGUID; + + void Reset() + { + uiSpeech_timer = 0; + uiSpeech_counter = 0; + uiCrusade_faction = 0; + uiPlayerGUID.Clear(); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (caster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && spell->Id == SPELL_PERSUASIVE_STRIKE && uiSpeech_counter == 0) + { + if(((Player*)caster)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE) + { + if (rand()%100 > 90) // chance + { + uiPlayerGUID = ((Player*)caster)->GetObjectGuid(); + uiCrusade_faction = m_creature->getFaction(); + uiSpeech_timer = 1000; + uiSpeech_counter = 1; + m_creature->setFaction(35); + } + else if (uiSpeech_counter == 0) + { + switch(rand()%6) + { + case 0: DoScriptText(SAY_PERSUADE1, caster);break; + case 1: DoScriptText(SAY_PERSUADE2, caster);break; + case 2: DoScriptText(SAY_PERSUADE3, caster);break; + case 3: DoScriptText(SAY_PERSUADE4, caster);break; + case 4: DoScriptText(SAY_PERSUADE5, caster);break; + case 5: DoScriptText(SAY_PERSUADE6, caster);break; + case 6: DoScriptText(SAY_PERSUADE7, caster);break; + } + switch(rand()%5) + { + case 0: DoScriptText(SAY_CRUSADER1, m_creature);break; + case 1: DoScriptText(SAY_CRUSADER2, m_creature);break; + case 2: DoScriptText(SAY_CRUSADER3, m_creature);break; + case 3: DoScriptText(SAY_CRUSADER4, m_creature);break; + case 4: DoScriptText(SAY_CRUSADER5, m_creature);break; + case 5: DoScriptText(SAY_CRUSADER6, m_creature);break; + } + } + } + } + } + + void UpdateAI(const uint32 diff) + { + if (uiSpeech_counter >= 1 && uiSpeech_counter <= 6) + if (uiSpeech_timer < diff) + { + m_creature->CombatStop(true); + m_creature->StopMoving(); + Unit* pPlayer = (Player*)m_creature->GetMap()->GetUnit(uiPlayerGUID); + + switch(uiSpeech_counter) + { + case 1: DoScriptText(SAY_PERSUADED1, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break; + case 2: DoScriptText(SAY_PERSUADED2, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break; + case 3: DoScriptText(SAY_PERSUADED3, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break; + case 4: DoScriptText(SAY_PERSUADED4, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break; + case 5: DoScriptText(SAY_PERSUADED5, pPlayer); uiSpeech_timer = 8000; uiSpeech_counter++; break; + case 6: + DoScriptText(SAY_PERSUADED6, m_creature); + m_creature->setFaction(uiCrusade_faction); + //m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiSpeech_timer = 0; + uiCrusade_faction = 0; + uiSpeech_counter++; + AttackStart(pPlayer); + if(((Player*)pPlayer)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE) + ((Player*)pPlayer)->AreaExploredOrEventHappens(12720); + break; + } + }else uiSpeech_timer -= diff; + else + DoMeleeAttackIfReady(); + } }; CreatureAI* GetAI_npc_highlord_darion_mograine(Creature* pCreature) -{ +{ return new npc_highlord_darion_mograineAI(pCreature); -}; +} CreatureAI* GetAI_npc_the_lich_king_tirion_dawn(Creature* pCreature) { - return new npc_the_lich_king_tirion_dawnAI(pCreature); + return new npc_the_lich_king_tirion_dawnAI(pCreature); }; CreatureAI* GetAI_npc_minibosses_dawn_of_light(Creature* pCreature) -{ +{ return new npc_minibosses_dawn_of_lightAI (pCreature); -}; +} CreatureAI* GetAI_mob_warrior_of_the_frozen_wastes(Creature* pCreature) { - return new mob_warrior_of_the_frozen_wastesAI(pCreature); -}; + return new mob_warrior_of_the_frozen_wastesAI(pCreature); +} CreatureAI* GetAI_mob_acherus_ghoul(Creature* pCreature) { - return new mob_acherus_ghoulAI(pCreature); + return new mob_acherus_ghoulAI(pCreature); }; CreatureAI* GetAI_npc_mine_car(Creature* pCreature) @@ -4056,6 +3915,21 @@ CreatureAI* GetAI_npc_scourge_gryphon(Creature* pCreature) return new npc_scourge_gryphonAI(pCreature); }; +CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature) +{ + return new npc_valkyr_battle_maidenAI(pCreature); +}; + +CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) +{ + return new mob_scarlet_courierAI(pCreature); +}; + +CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature) +{ + return new npc_crusade_persuadedAI (pCreature); +}; + void AddSC_ebon_hold() { Script* pNewScript; @@ -4098,11 +3972,6 @@ void AddSC_ebon_hold() pNewScript->GetAI = &GetAI_npc_eye_of_acherus; pNewScript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "mob_scarlet_miner"; - pNewScript->GetAI = &GetAI_mob_scarlet_miner; - pNewScript->RegisterSelf(); - pNewScript = new Script; pNewScript->Name = "mob_scarlet_ghoul"; pNewScript->GetAI = &GetAI_mob_scarlet_ghoul; @@ -4111,7 +3980,7 @@ void AddSC_ebon_hold() pNewScript = new Script; pNewScript->Name = "npc_highlord_darion_mograine"; pNewScript->GetAI = &GetAI_npc_highlord_darion_mograine; - pNewScript->pGossipHello = &GossipHello_npc_highlord_darion_mograine; + pNewScript->pGossipHello = &GossipHello_npc_highlord_darion_mograine; pNewScript->pGossipSelect = &GossipSelect_npc_highlord_darion_mograine; pNewScript->RegisterSelf(); @@ -4130,6 +3999,11 @@ void AddSC_ebon_hold() pNewScript->GetAI = &GetAI_mob_acherus_ghoul; pNewScript->RegisterSelf(); + pNewScript = new Script; + pNewScript->Name = "mob_warrior_of_the_frozen_wastes"; + pNewScript->GetAI = &GetAI_mob_warrior_of_the_frozen_wastes; + pNewScript->RegisterSelf(); + pNewScript = new Script; pNewScript->Name = "npc_mine_car"; pNewScript->GetAI = &GetAI_npc_mine_car; @@ -4142,7 +4016,7 @@ void AddSC_ebon_hold() pNewScript = new Script; pNewScript->Name = "go_inconspicous_mine_car"; - pNewScript->pGOUse = &GOUse_go_inconspicous_mine_car; + pNewScript->pGOUse = &GOUse_inconspicous_mine_car; pNewScript->RegisterSelf(); pNewScript = new Script; @@ -4150,23 +4024,18 @@ void AddSC_ebon_hold() pNewScript->GetAI = &GetAI_npc_scourge_gryphon; pNewScript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "mob_warrior_of_the_frozen_wastes"; - pNewScript->GetAI = &GetAI_mob_warrior_of_the_frozen_wastes; - pNewScript->RegisterSelf(); - pNewScript = new Script; pNewScript->Name= "npc_valkyr_battle_maiden"; pNewScript->GetAI = &GetAI_npc_valkyr_battle_maiden; pNewScript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "npc_crusade_persuaded"; - pNewScript->GetAI = &GetAI_npc_crusade_persuaded; - pNewScript->RegisterSelf(); - pNewScript = new Script; pNewScript->Name= "mob_scarlet_courier"; pNewScript->GetAI = &GetAI_mob_scarlet_courier; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_crusade_persuaded"; + pNewScript->GetAI = &GetAI_npc_crusade_persuaded; + pNewScript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp index 53280faf66..b3efca9e4a 100644 --- a/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp +++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp @@ -16,22 +16,17 @@ /* ScriptData SDName: boss_headless_horseman -SD%Complete: 80 -SDComment: - -TODO: -// only get one chance per summon to win if u wipe or lose aggro he despawns -// fix phase change when body heals to full -// his little flight entrace needs to have spawn creature movement in DB or script -// could use a little tweaking - +SD%Complete: 95% +SDComment: by Enturion's Staff SDCategory: Scarlet Monastery EndScriptData */ +#include "precompiled.h" + #include "precompiled.h" #include "scarlet_monastery.h" -enum Texts +enum { SAY_ENTRANCE = -1189022, SAY_REJOINED = -1189023, @@ -47,489 +42,1065 @@ enum Texts SAY_PLAYER1 = -1189031, SAY_PLAYER2 = -1189032, SAY_PLAYER3 = -1189033, - SAY_PLAYER4 = -1189034 + SAY_PLAYER4 = -1189034, + + //Spells + SPELL_CLEAVE = 42587, + SPELL_CONFLAGRATION = 42380, //Phase 2, can't find real spell(Dim Fire?) + SPELL_SUMMON_PUMPKIN = 42394, //summon 4 pumpkin or 52236, Phase 3(requres summon_spells.patch - TARGET_EFFECT_SELECT not implemened in core) + + SPELL_WHIRLWIND = 43116, //or ?41194 + SPELL_CLEAVE_PROC = 42587, //procs after "killing" body(at each end of phase or when he really dies?) + SPELL_IMMUNE = 42556, + SPELL_BODY_REGEN = 42403, //regenerates 4% of total hp per 1sec;not used, because this, body regen and whirlwind non stackable with each other + SPELL_BODY_CONFUSE = 43105, //confused movement + + SPELL_FLYING_HEAD = 42399, //visual flying head + SPELL_HEAD = 42413, //visual buff, "head" + SPELL_HEAD_IS_DEAD = 42428, //at killing head, Phase 3 + SPELL_HEAD_INVIS = 44312, //not used + + SPELL_PUMPKIN_AURA = 42280, + SPELL_PUMPKIN_AURA_GREEN = 42294, + SPELL_PUMPKIN_DEATH = 42291, + SPELL_SQUASH_SOUL = 42514, //pumpkin debuff + SPELL_SPROUTING = 42281, //process bar + heal + SPELL_SPROUT_BODY = 42285, //transforms itself into fiend + + //Effects + SPELL_RHYME_BIG = 42909, //summoning rhyme + SPELL_RHYME_SMALL = 42910, + SPELL_HEAD_SPEAKS = 43129, + SPELL_HEAD_LANDS = 42400, + SPELL_BODY_FLAME = 42074, + SPELL_ON_KILL_PROC = 43877, //procs after killing players? + SPELL_ENRAGE_VISUAL = 42438, // he uses this spell? + SPELL_WISP_BLUE = 42821, + SPELL_WISP_FLIGHT_PORT = 42818, + SPELL_SMOKE = 42355, + SPELL_DEATH = 42566, + SPELL_LAUGH1 = 43881, + SPELL_LAUGH2 = 43894, + SPELL_LAUGH3 = 43885, + SPELL_CREATE_TREATS = 42754 }; -enum HorsemanSpells +struct Locations { - //spells - SPELL_HORSEMAN_CLEAVE = 42587, - SPELL_CONFLAGRATION = 42380, - SPELL_SUMMON_PUMPKIN = 42394, //Jack o laterned //summons 4 pumpkins missiles or 52236 - - SPELL_WHIRLWIND = 43116, //or ?41194 // After losing its head, the body will AoE whirlwind for ~2k/sec. - SPELL_CLEAVE_PROC = 42587, //procs after "killing" body(at each end of phase or when he really dies?) - SPELL_IMMUNE = 42556, - SPELL_BODY_REGEN = 42403, //regen 4% of total hp per 1sec;not used, because this, body regen and whirlwind non stackable with each other - SPELL_BODY_CONFUSE = 43105, //confused movement - - SPELL_SEND_HEAD = 42399, //visual flying head - SPELL_HEAD = 42413, //visual buff, "head" - SPELL_HEAD_IS_DEAD = 42428, //at killing head, Phase 3 - SPELL_HEAD_INVIS = 44312, //not used - SPELL_SUMMON_WISP_HEAD = 42823, //summonig whispering head - - SPELL_PUMPKIN_AURA = 42280, - SPELL_PUMPKIN_AURA_GREEN = 42294, - SPELL_PUMPKIN_DEATH = 42291, - SPELL_SQUASH_SOUL = 42514, //pumpkin debuff - SPELL_SPROUTING = 42281, - SPELL_SPROUT_BODY = 42285, + float x, y, z; +}; - //Effects - SPELL_RHYME_BIG = 42909, //summoning rhyme - SPELL_RHYME_SMALL = 42910, - SPELL_HEAD_SPEAKS = 43129, - SPELL_HEAD_LANDS = 42400, - SPELL_BODY_FLAME = 42074, - SPELL_ON_KILL_PROC = 43877, //procs after killing players? - SPELL_ENRAGE_VISUAL = 42438, // he uses this spell? - SPELL_WISP = 43034, - -// laughs - SPELL_LAUGH0 = 43881, - SPELL_LAUGH1 = 43885, - SPELL_LAUGH2 = 43894, +static Locations FlightPoint[]= +{ + {1751.00f,1347.00f,19.00f}, + {1765.00f,1347.00f,19.00f}, + {1784.00f,1346.80f,25.40f}, + {1803.30f,1347.60f,33.00f}, + {1824.00f,1350.00f,42.60f}, + {1838.80f,1353.20f,49.80f}, + {1852.00f,1357.60f,55.70f}, + {1861.30f,1364.00f,59.40f}, + {1866.30f,1374.80f,61.70f}, + {1864.00f,1387.30f,63.20f}, + {1854.80f,1399.40f,64.10f}, + {1844.00f,1406.90f,64.10f}, + {1824.30f,1411.40f,63.30f}, + {1801.00f,1412.30f,60.40f}, + {1782.00f,1410.10f,55.50f}, + {1770.50f,1405.20f,50.30f}, + {1765.20f,1400.70f,46.60f}, + {1761.40f,1393.40f,41.70f}, + {1759.10f,1386.70f,36.60f}, + {1757.80f,1378.20f,29.00f}, + {1758.00f,1367.00f,19.51f}, + {1784.00f,1346.80f,25.40f}, + {1797.00f,1341.70f,18.89f} }; -enum Phazes +static Locations Spawn[]= { - PHASE_ZERO = 0, // summon the npc head ( invis at first til phase 2 - PHASE_ONE = 1, // just summoned once aggro starts off with cleave and summons head buff at aggro - PHASE_TWO = 2, // head and body split - PHASE_THREE = 3, // head and body rejoin start conflartion - PHASE_FOUR = 4, // head and body split again - PHASE_FIVE = 5, // head and body rejoin he cast conf and summons pumkin .. if body damaged enough repeat phase 4 + {1776.27f,1348.74f,19.20f}, //spawn point for pumpkin shrine mob + {1765.28f,1347.46f,17.55f} //spawn point for smoke }; -uint8 m_uiPhase; // golbal phase counter +struct Summon +{ + const char* text; +}; -/*###### -## boss_headless_horseman -######*/ -struct MANGOS_DLL_DECL boss_headless_horsemanAI : public ScriptedAI +static Summon Text[]= { - boss_headless_horsemanAI(Creature* pCreature) : ScriptedAI(pCreature) + {"Horseman rise..."}, + {"Your time is nigh..."}, + {"You felt death once..."}, + {"Now, know demise!"} +}; +/*##### +# Wisp Invis +#####*/ +struct MANGOS_DLL_DECL mob_wisp_invisAI : public ScriptedAI +{ + mob_wisp_invisAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + m_uiCreaturetype = m_uiDelay = m_uiSpell = m_uiSpell2 = 0; + //that's hack but there are no info about range of this spells in dbc + SpellEntry *pWisp = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_WISP_BLUE); + if (pWisp) + pWisp->rangeIndex = 6; //100 yards + SpellEntry *pPort = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_WISP_FLIGHT_PORT); + if (pPort) + pPort->rangeIndex = 6; + Reset(); - m_uiPhase = PHASE_ZERO; - pEntered = false; } - - ScriptedInstance* m_pInstance; - bool pEntered; + uint32 m_uiCreaturetype; + uint32 m_uiDelay; + uint32 m_uiSpell; + uint32 m_uiSpell2; - uint32 m_uiCleave_Timer; - uint32 m_uiConflageration_Timer; - uint32 m_uiPumpkinSprout_Timer; + void Reset() + { + } - ObjectGuid HeadGUID; + void EnterCombat(Unit *pWho) + { + } - void Reset() + void SetType(uint32 _type) { - m_uiCleave_Timer = 5000; - m_uiConflageration_Timer = 5000; - m_uiPumpkinSprout_Timer = 5000; + switch(m_uiCreaturetype = _type) + { + case 1: + m_uiSpell = SPELL_PUMPKIN_AURA_GREEN; + break; + case 2: + m_uiDelay = 15000; + m_uiSpell = SPELL_BODY_FLAME; + m_uiSpell2 = SPELL_DEATH; + break; + case 3: + m_uiDelay = 15000; + m_uiSpell = SPELL_SMOKE; + break; + case 4: + m_uiDelay = 7000; + m_uiSpell2 = SPELL_WISP_BLUE; + break; + } + if (m_uiSpell) + DoCast(m_creature, m_uiSpell); + } + + void SpellHit(Unit* pCaster, const SpellEntry *pSpell) + { + if (pSpell->Id == SPELL_WISP_FLIGHT_PORT && m_uiCreaturetype == 4) + DoSpawnCreature(NPC_SIR_THOMAS, 1, 1, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 240000); } - void Aggro(Unit* pWho) + void MoveInLineOfSight(Unit *pWho) { - if (!pWho) + if (!pWho || m_uiCreaturetype != 1 || !pWho->isTargetableForAttack()) return; - if (pEntered) - m_creature->SetInCombatWithZone(); + if (m_creature->IsWithinDist(pWho, 0.1f, false) && !pWho->HasAura(SPELL_SQUASH_SOUL)) + DoCast(pWho, SPELL_SQUASH_SOUL); } - void Laugh() + void UpdateAI(const uint32 uiDiff) { - switch(urand(0,2)) + if (m_uiDelay) { - case 0: DoCast(m_creature,SPELL_LAUGH0,true); break; - case 1: DoCast(m_creature,SPELL_LAUGH1,true); break; - case 2: DoCast(m_creature,SPELL_LAUGH2,true); break; + if (m_uiDelay <= uiDiff) + { + m_creature->RemoveAurasDueToSpell(SPELL_SMOKE); + if (m_uiSpell2) + DoCastSpellIfCan(m_creature, m_uiSpell2); + m_uiDelay = 0; + } + else + m_uiDelay -= uiDiff; } } +}; + +/*##### +# Horseman's Head +#####*/ +struct MANGOS_DLL_DECL mob_headAI : public ScriptedAI +{ + mob_headAI(Creature *pCreature) : ScriptedAI(pCreature) + { + Reset(); + } - void KilledUnit(Unit* pVictim) + ObjectGuid m_uiBodyguid; + + uint32 m_uiPhase; + uint32 m_uiLaugh; + uint32 m_uiWait; + + bool m_bWithBody; + bool m_bDie; + + void Reset() { - DoScriptText(SAY_SLAY, m_creature); + m_uiPhase = 0; + m_uiBodyguid.Clear(); + m_bDie = false; + m_bWithBody = true; + m_uiWait = 1000; + m_uiLaugh = urand(15000, 30000); } - void JustDied(Unit* pKiller) + void EnterCombat(Unit *pWho) { - DoScriptText(SAY_DEATH, m_creature); } - void RemoveRegenAuras() + void SaySound(int32 uiTextEntry, Unit *pTarget = 0) { - if (m_creature->HasAura(SPELL_BODY_REGEN)) - m_creature->RemoveAurasDueToSpell(SPELL_BODY_REGEN); - if (m_creature->HasAura(SPELL_IMMUNE)) - m_creature->RemoveAurasDueToSpell(SPELL_IMMUNE); - if (m_creature->HasAura(SPELL_BODY_CONFUSE)) - m_creature->RemoveAurasDueToSpell(SPELL_BODY_CONFUSE); - if (m_creature->HasAura(SPELL_WHIRLWIND)) - m_creature->RemoveAurasDueToSpell(SPELL_WHIRLWIND); + DoScriptText(uiTextEntry, m_creature, pTarget); + //DoCast(m_creature,SPELL_HEAD_SPEAKS,true); + Creature *pSpeaker = DoSpawnCreature(NPC_HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 1000); + if (pSpeaker) + pSpeaker->CastSpell(pSpeaker, SPELL_HEAD_SPEAKS, false); + + m_uiLaugh += 3000; } - void ApplyRegenAuras() + void Disappear(); + + void DamageTaken(Unit* pDoneBy,uint32 &uiDamage) { - if (!m_creature->HasAura(SPELL_BODY_REGEN)) - DoCast(m_creature,SPELL_BODY_REGEN,true); - if (!m_creature->HasAura(SPELL_IMMUNE)) - DoCast(m_creature,SPELL_IMMUNE,true); - if (!m_creature->HasAura(SPELL_BODY_CONFUSE)) - DoCast(m_creature,SPELL_BODY_CONFUSE,true); - if (!m_creature->HasAura(SPELL_WHIRLWIND)) - DoCast(m_creature,SPELL_WHIRLWIND,true); + if (m_bWithBody) + return; + + switch(m_uiPhase) + { + case 1: + if (((m_creature->GetHealth() - uiDamage)*100)/m_creature->GetMaxHealth() < 67) + { + m_creature->SetHealth(m_creature->GetMaxHealth()*67/100); + uiDamage = 0; + Disappear(); + } + break; + case 2: + if (((m_creature->GetHealth() - uiDamage)*100)/m_creature->GetMaxHealth() < 34) + { + m_creature->SetHealth(m_creature->GetMaxHealth()*34/100); + uiDamage = 0; + Disappear(); + } + break; + case 3: + if (uiDamage >= m_creature->GetHealth()) + { + Disappear(); + m_bDie = true; + m_bWithBody = true; + m_uiWait = 300; + uiDamage = 0; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->StopMoving(); + //m_creature->GetMotionMaster()->MoveIdle(); + DoCast(m_creature, SPELL_HEAD_IS_DEAD); + } + break; + } } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + void SpellHit(Unit *pCaster, const SpellEntry* pSpell) { - if (!pSpell) + if (!m_bWithBody) return; - if (pSpell->Id == SPELL_SEND_HEAD) + if (pSpell->Id == SPELL_FLYING_HEAD) { - DoScriptText(SAY_REJOINED,m_creature); - //m_creature->CastSpell(m_creature,SPELL_HEAD,false); + if (m_uiPhase < 3) + ++m_uiPhase; + else + m_uiPhase = 3; + + m_bWithBody = false; + + if (!m_uiBodyguid) + m_uiBodyguid = pCaster->GetObjectGuid(); + + m_creature->RemoveAllAuras(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_HEAD_LANDS, true); + DoCast(m_creature, SPELL_HEAD, false); + SaySound(SAY_LOST_HEAD); + m_creature->GetMotionMaster()->Clear(false); + if (pCaster->getVictim()) + m_creature->GetMotionMaster()->MoveFleeing(pCaster->getVictim()); } } void UpdateAI(const uint32 uiDiff) { - if (!pEntered) // should also be in phase zero + if (!m_bWithBody) + { + if (m_uiWait < uiDiff) + { + m_uiWait = 5000; + if (!m_creature->getVictim()) + return; + + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveFleeing(m_creature->getVictim()); + } + else + m_uiWait -= uiDiff; + + if (m_uiLaugh < uiDiff) + { + m_uiLaugh = urand(15000, 30000); + //DoCast(m_creature,SPELL_HEAD_SPEAKS,true); //this pSpell remove buff "head" + Creature *speaker = DoSpawnCreature(NPC_HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 1000); + if (speaker) + speaker->CastSpell(speaker, SPELL_HEAD_SPEAKS, false); + + DoScriptText(EMOTE_LAUGH, m_creature); + } + else + m_uiLaugh -= uiDiff; + } + else + { + if (m_bDie) + { + if (m_uiWait < uiDiff) + { + m_bDie = false; + if (Creature *pBody = m_creature->GetMap()->GetCreature(m_uiBodyguid)) + { + pBody->RemoveAurasDueToSpell(SPELL_IMMUNE); + pBody->DealDamage(pBody, pBody->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + else + m_uiWait -= uiDiff; + } + } + } +}; + +/*##### +# Headless Horseman +#####*/ +struct MANGOS_DLL_DECL boss_headless_horsemanAI : public ScriptedAI +{ + boss_headless_horsemanAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SpellEntry *pConfl = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_CONFLAGRATION); + + if(pConfl) { - float x,y,z; - m_creature->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius(), 15.0f, 0.0f); - if (Creature* pTemp = m_creature->SummonCreature(NPC_HEAD, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0)) - HeadGUID = pTemp->GetObjectGuid(); + pConfl->EffectApplyAuraName[0] = SPELL_AURA_PERIODIC_DAMAGE_PERCENT; + pConfl->EffectBasePoints[0] = 10; + //confl->EffectBaseDice[0] = 10; + pConfl->DmgMultiplier[0] = 1; + } - pEntered = true; - m_uiPhase = PHASE_ONE; + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *m_pInstance; + + ObjectGuid m_uiHeadGuid; + ObjectGuid m_uiPlayerGuid; + + uint32 m_uiPhase; + uint32 m_uiId; + uint32 m_uiCount; + uint32 m_uiSayTimer; + + uint32 m_uiConflagrateTimer; + uint32 m_uiSummonaddsTimer; + uint32 m_uiCleaveTimer; + uint32 m_uiRegenTimer; + uint32 m_uiWhirlwindTimer; + uint32 m_uiLaughTimer; + uint32 m_uiBurnTimer; + + bool m_bWithhead; + bool m_bReturned; + bool m_bIsFlying; + bool m_bWpReached; + bool m_bBurned; + + void Reset() + { + m_uiPhase = 0; + m_uiConflagrateTimer = 3000; + m_uiSummonaddsTimer = 3000; + m_uiLaughTimer = urand(16000,20000); + m_uiCleaveTimer = 2000; + m_uiRegenTimer = 1000; + m_uiBurnTimer = 6000; + m_uiCount = 0; + m_uiSayTimer = 3000; + m_uiPlayerGuid.Clear(); + + m_bWithhead = true; + m_bReturned = true; + m_bBurned = false; + m_bIsFlying = false; + m_bWpReached = false; + + m_creature->SetVisibility(VISIBILITY_OFF); + DoCast(m_creature, SPELL_HEAD); + + if (m_uiHeadGuid) + { + if (Creature* Head = m_creature->GetMap()->GetCreature(m_uiHeadGuid)) + Head->ForcedDespawn(); + + m_uiHeadGuid.Clear(); } - Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_HEAD); + if (m_pInstance && m_pInstance->GetData(DATA_HORSEMAN_EVENT) == NOT_STARTED) + Intro(); + } - if (!m_pInstance) - return; + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(DATA_HORSEMAN_EVENT, FAIL); - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + m_creature->AddObjectToRemoveList(); + } + + void Intro() + { + if (m_pInstance) + m_pInstance->SetData(DATA_HORSEMAN_EVENT, IN_PROGRESS); + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //m_creature->AddMonsterMoveFlag(MONSTER_MOVE_LEVITATING); + //m_creature->AddMonsterMoveFlag(MONSTER_MOVE_TELEPORT2); + m_creature->SetSpeedRate(MOVE_WALK,5.0f,true); + m_bWpReached = false; + m_uiCount = 0; + m_uiSayTimer = 3000; + m_uiId = 0; + m_uiPhase = 0; + } + + void MovementInform(uint32 type, uint32 i) + { + if (type != POINT_MOTION_TYPE || !m_bIsFlying || i != m_uiId) return; - - switch (m_uiPhase) - { - case PHASE_ONE: - { - // he gets his head - if (!m_creature->HasAura(SPELL_HEAD)) - DoCast(m_creature,SPELL_HEAD,false); - if (((m_creature->GetHealth()*100) / (m_creature->GetMaxHealth())) <= 1) - m_uiPhase = PHASE_TWO; + m_bWpReached = true; - if (m_uiCleave_Timer <= uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(),SPELL_CLEAVE_PROC,false); - m_uiCleave_Timer = 5000; - }else m_uiCleave_Timer -= uiDiff; - DoMeleeAttackIfReady(); + switch (m_uiId) + { + case 0: + if (Creature *smoke = m_creature->SummonCreature(NPC_HELPER, Spawn[1].x, Spawn[1].y, Spawn[1].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) + ((mob_wisp_invisAI*)smoke->AI())->SetType(3); + DoCast(m_creature,SPELL_RHYME_BIG); + break; + case 1: + { + m_creature->SetVisibility(VISIBILITY_ON); break; } - case PHASE_TWO: + case 6: + if (m_pInstance) + m_pInstance->SetData(DATA_PUMPKIN_SHRINE, 0); //hide gameobject + break; + case 19: + //m_creature->RemoveMonsterMoveFlag(MONSTER_MOVE_LEVITATING); + //m_creature->RemoveMonsterMoveFlag(MONSTER_MOVE_TELEPORT2); + //m_creature->SetMonsterMoveFlags(MONSTER_MOVE_WALK); + break; + case 22: { - if (m_creature->HasAura(SPELL_HEAD)) + m_uiPhase = 1; + m_bIsFlying = false; + m_bWpReached = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_ENTRANCE, m_creature); + + if (Player *pWho = m_creature->GetMap()->GetPlayer(m_uiPlayerGuid)) { - m_creature->RemoveAurasDueToSpell(SPELL_HEAD); -// visual of head flying off body ( really head flying at target which in this case needs to be the head npc ) - DoCast(pHead,SPELL_SEND_HEAD,true); + m_creature->DeleteThreatList(); + m_creature->SetInCombatWithZone(); + m_creature->AddThreat(pWho, 100.0f); + DoStartMovement(pWho); } + break; + } + } + ++m_uiId; + } - ApplyRegenAuras(); + void MoveInLineOfSight(Unit* pWho) + { + if (!m_bWithhead || m_uiPhase == 0) + return; - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (pHead->AI()) - pHead->AI()->AttackStart(pTarget); + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; - if ((pHead->GetHealth()*100) / (pHead->GetMaxHealth()) <= 66) /*|| (m_creature->GetHealth()*100) / (m_creature->GetMaxHealth()) <= 100)*/ + if (m_creature->IsWithinDistInMap(pWho, 66) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(pWho); + } + else if (m_creature->GetMap()->IsDungeon()) { - RemoveRegenAuras(); - m_uiPhase = PHASE_THREE; + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); } + } + } + } - break; + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() == TYPEID_PLAYER) + { + if (m_bWithhead) + DoScriptText(SAY_SLAY, m_creature); + //maybe possible when player dies from conflagration + else if (Creature *pHead = m_creature->GetMap()->GetCreature(m_uiHeadGuid)) + ((mob_headAI*)pHead->AI())->SaySound(SAY_PLAYER1); + } + } + + void JustDied(Unit* pKiller) + { + m_creature->StopMoving(); + //m_creature->GetMotionMaster()->MoveIdle(); + DoScriptText(SAY_DEATH, m_creature); + + Map::PlayerList const& players = m_pInstance->instance->GetPlayers(); + + if (!players.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->CastSpell(pPlayer, SPELL_CREATE_TREATS, true); } - case PHASE_THREE: + } + + if (Creature *pFlame = DoSpawnCreature(NPC_HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + pFlame->CastSpell(pFlame, SPELL_BODY_FLAME, false); + + if (Creature *pWisp = DoSpawnCreature(NPC_WISP_INVIS, 1, 1, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 240000)) + { + ((mob_wisp_invisAI*)pWisp->AI())->SetType(4); + } + + if (m_pInstance) + m_pInstance->SetData(DATA_HORSEMAN_EVENT, DONE); + } + + void SpellHitTarget(Unit* pUnit, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_CONFLAGRATION) + if (pUnit->HasAura(SPELL_CONFLAGRATION, EFFECT_INDEX_0)) + DoScriptText(SAY_CONFLAGRATION, m_creature); + } + + void SpellHit(Unit *pCaster, const SpellEntry* pSpell) + { + if (m_bWithhead) + return; + + if (pSpell->Id == SPELL_FLYING_HEAD) + { + if (m_uiPhase < 3) + ++m_uiPhase; + else + m_uiPhase = 3; + m_bWithhead = true; + m_creature->RemoveAllAuras(); + m_creature->SetName("Headless Horseman"); + m_creature->SetHealth(m_creature->GetMaxHealth()); + DoScriptText(SAY_REJOINED, m_creature); + DoCast(m_creature, SPELL_HEAD); + pCaster->GetMotionMaster()->Clear(false); + pCaster->GetMotionMaster()->MoveFollow(m_creature, 6, urand(0, 5)); + //DoResetThreat();//not sure if need + ThreatList const& tList = m_creature->getThreatManager().getThreatList(); + for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr) { -// give him his head back ( the head will target and cast spell send head at the body will look like head flying back on to body - if (!m_creature->HasAura(SPELL_HEAD)) - DoCast(m_creature,SPELL_HEAD,false); + Unit* pUnit = m_creature->GetMap()->GetCreature((*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive() && pUnit != pCaster) + m_creature->AddThreat(pUnit, pCaster->getThreatManager().getThreat(pUnit)); + } + } + } - if (((m_creature->GetHealth()*100) / (m_creature->GetMaxHealth())) <= 1) - m_uiPhase = PHASE_FOUR; + void DamageTaken(Unit *pDoneBy, uint32 &uiDamage) + { + if (!m_bWithhead) + { + uiDamage = 0; + return; + } + + if (m_creature->GetHealth() <= uiDamage + m_creature->GetMaxHealth()/100) + { + m_bWithhead = false; + m_bReturned = false; + uiDamage = 0; + m_creature->SetHealth(m_creature->GetMaxHealth()/100); - if (m_uiConflageration_Timer <= uiDiff) + m_creature->RemoveAllAuras(); + m_creature->SetDisplayId(22352); + m_creature->SetNativeDisplayId(22352); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (!m_uiHeadGuid) + { + if (Unit* pSummon = DoSpawnCreature(NPC_HEAD, rand()%6, rand()%6, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + m_uiHeadGuid = pSummon->GetObjectGuid(); + } + + Creature* pHead = (Creature*) m_creature->GetMap()->GetCreature(m_uiHeadGuid); + if (pHead && pHead->isAlive()) + { + //((mob_headAI*)Head->AI())->m_uiPhase = m_uiPhase; + pHead->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pHead->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + //pHead->CastSpell(Head,SPELL_HEAD_INVIS,false); + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_IMMUNE, true); + DoCast(m_creature, SPELL_BODY_REGEN, true); + m_creature->CastSpell(pHead, SPELL_FLYING_HEAD, true); + DoCast(m_creature, SPELL_BODY_CONFUSE, false); //test + + pHead->SetVisibility(VISIBILITY_ON); + //done_by->ProcDamageAndSpell(m_creature,PROC_FLAG_KILL,PROC_FLAG_KILLED,PROC_EX_NONE,0); + + m_uiWhirlwindTimer = urand(4000, 5000); + m_uiRegenTimer = 0; + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiPhase == 0) + { + if (!m_bIsFlying) + { + if (m_uiSayTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_uiSayTimer = 3000; + + if (m_uiCount < 3) { - DoScriptText(SAY_CONFLAGRATION,m_creature); - pTarget->CastSpell(pTarget,SPELL_CONFLAGRATION,false); + if (Player* pWho = m_creature->GetMap()->GetPlayer(m_uiPlayerGuid)) + pWho->Say(Text[m_uiCount].text, LANG_UNIVERSAL); + + ++m_uiCount; } - m_uiConflageration_Timer = 15000; - }else m_uiConflageration_Timer -= uiDiff; + else + { + DoCast(m_creature,SPELL_RHYME_BIG); + if (Player* pWho = m_creature->GetMap()->GetPlayer(m_uiPlayerGuid)) + pWho->Yell(Text[m_uiCount].text, LANG_UNIVERSAL); - DoMeleeAttackIfReady(); - break; + //HandleEmoteCommand(ANIM_EMOTE_SHOUT); + + m_bWpReached = true; + m_bIsFlying = true; + m_uiCount = 0; + } + } + else + m_uiSayTimer -= uiDiff; } - case PHASE_FOUR: + else { - if (m_creature->HasAura(SPELL_HEAD)) + if (m_bWpReached) { - m_creature->RemoveAurasDueToSpell(SPELL_HEAD); -// visual of head flying off body ( really head flying at target which in this case needs to be the head npc ) - DoCast(pHead,SPELL_SEND_HEAD,true); + m_bWpReached = false; + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MovePoint(m_uiId, FlightPoint[m_uiId].x, FlightPoint[m_uiId].y, FlightPoint[m_uiId].z); } + } + } // m_uiPhase 0 + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - ApplyRegenAuras(); + if (m_bWithhead) + { + switch(m_uiPhase) + { + case 1: + if (m_bBurned) + break; + + if (m_uiBurnTimer < uiDiff) + { + if (Creature *pFlame = m_creature->SummonCreature(NPC_HELPER, Spawn[0].x, Spawn[0].y, Spawn[0].z, 0, TEMPSUMMON_TIMED_DESPAWN, 17000)) + ((mob_wisp_invisAI*)pFlame->AI())->SetType(2); - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (pHead->AI()) - pHead->AI()->AttackStart(pTarget); + m_bBurned = true; + } + else + m_uiBurnTimer -= uiDiff; - if ((pHead->GetHealth()*100) / (pHead->GetMaxHealth()) <= 33) /*|| (m_creature->GetHealth()*100) / (m_creature->GetMaxHealth()) <= 100)*/ + break; + case 2: + if (m_uiConflagrateTimer < uiDiff) + { + Unit* pTarget = NULL; + Unit* pTemp = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1); + + if (pTemp) + { + if (pTemp->GetTypeId() != TYPEID_PLAYER) + pTarget = pTemp->GetCharmerOrOwnerPlayerOrPlayerItself(); + else + pTarget = pTemp; + } + else + pTarget = m_creature->getVictim(); + + if (pTarget) + m_creature->CastSpell(pTarget, SPELL_CONFLAGRATION, false); + + m_uiConflagrateTimer = urand(5000, 8000); + } + else + m_uiConflagrateTimer -= uiDiff; + break; + case 3: + if (m_uiSummonaddsTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_SUMMON_PUMPKIN); + DoScriptText(SAY_SPROUTING_PUMPKINS, m_creature); + m_uiSummonaddsTimer = urand(5000, 10000); + } + else + m_uiSummonaddsTimer -= uiDiff; + break; + } //switch + + if (m_uiLaughTimer < uiDiff) + { + m_uiLaughTimer = urand(11000, 22000); +/* + if (Creature *speaker = DoSpawnCreature(HELPER,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN,1000)) + speaker->CastSpell(speaker,SPELL_HEAD_SPEAKS,false); +*/ + switch (urand(1,3)) { - RemoveRegenAuras(); - m_uiPhase = PHASE_FIVE; + case 1: + DoCast(m_creature, SPELL_LAUGH1, true); + break; + case 2: + DoCast(m_creature, SPELL_LAUGH2, true); + break; + case 3: + DoCast(m_creature, SPELL_LAUGH3, true); + break; } - break; + DoScriptText(EMOTE_LAUGH, m_creature); } - case PHASE_FIVE: - { - - if (!m_creature->HasAura(SPELL_HEAD)) - DoCast(m_creature,SPELL_HEAD,false); + else + m_uiLaughTimer -= uiDiff; - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (pHead->AI()) - pHead->AI()->AttackStart(pTarget); - - if (m_uiPumpkinSprout_Timer <= uiDiff) + if (m_creature->getVictim()) + { + if (m_uiCleaveTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoScriptText(SAY_SPROUTING_PUMPKINS,m_creature); - m_creature->CastSpell(pTarget,SPELL_SUMMON_PUMPKIN,false); - } - m_uiPumpkinSprout_Timer = 30000; - }else m_uiPumpkinSprout_Timer -= uiDiff; + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + m_uiCleaveTimer = urand(2000, 6000); //1 cleave per 2.0-6.0sec + } + else + m_uiCleaveTimer -= uiDiff; - if (m_uiConflageration_Timer <= uiDiff) + DoMeleeAttackIfReady(); + } + } + else + { + if (m_uiRegenTimer < uiDiff) + { + m_uiRegenTimer = 1000; //"body calls head" + if (!m_bReturned) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (m_creature->GetHealth() < m_creature->GetMaxHealth()) + m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth()*0.04f);// regen rate + else { - DoScriptText(SAY_CONFLAGRATION,m_creature); - pTarget->CastSpell(pTarget,SPELL_CONFLAGRATION,false); + Creature* pHead = m_creature->GetMap()->GetCreature(m_uiHeadGuid); + if (pHead && pHead->isAlive()) + { + ((mob_headAI*)pHead->AI())->Disappear(); + ((mob_headAI*)pHead->AI())->m_uiPhase = m_uiPhase; + } + m_creature->RemoveAurasDueToSpell(SPELL_BODY_CONFUSE); + m_bReturned = true; + return; } - m_uiConflageration_Timer = 15000; - }else m_uiConflageration_Timer -= uiDiff; + } + } + else + m_uiRegenTimer -= uiDiff; - if (((m_creature->GetHealth()*100) / (m_creature->GetMaxHealth())) <= 1) + if (m_uiWhirlwindTimer < uiDiff) + { + m_uiWhirlwindTimer = urand(4000, 5000); + if (urand(0,2)) // 2 su 3 whirl { - m_uiPhase = PHASE_FOUR; - DoCast(pHead,SPELL_SEND_HEAD,true); + m_creature->RemoveAurasDueToSpell(SPELL_BODY_CONFUSE); + DoCast(m_creature, SPELL_WHIRLWIND, true); + } + else + { + m_creature->RemoveAurasDueToSpell(SPELL_WHIRLWIND); + DoCast(m_creature, SPELL_BODY_CONFUSE); } - - DoMeleeAttackIfReady(); - break; - //default: break; } + else + m_uiWhirlwindTimer -= uiDiff; } } }; -CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature) +void mob_headAI::Disappear() { - return new boss_headless_horsemanAI(pCreature); -} - -/*###### -## npc_horsemans_head -######*/ + if (m_bWithBody) + return; -struct MANGOS_DLL_DECL npc_horsemans_headAI : public ScriptedAI + if (m_uiBodyguid) + { + Creature *pBody = m_creature->GetMap()->GetCreature(m_uiBodyguid); + if (pBody && pBody->isAlive()) + { + m_bWithBody = true; + pBody->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pBody->RemoveAurasDueToSpell(SPELL_IMMUNE);//hack, SpellHit doesn't calls if body has immune aura + pBody->SetDisplayId(22351); + pBody->SetNativeDisplayId(22351); + DoCast(pBody, SPELL_FLYING_HEAD); + + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetVisibility(VISIBILITY_OFF); + ((boss_headless_horsemanAI*)pBody->AI())->m_bReturned = true; + } + } +} +/*##### +# Pulsing Pumpkin +#####*/ +struct MANGOS_DLL_DECL mob_pulsing_pumpkinAI : public ScriptedAI { - npc_horsemans_headAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_pulsing_pumpkinAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); Reset(); } - ScriptedInstance* m_pInstance; + + bool m_bSprouted; + ObjectGuid m_uiDebuffGuid; void Reset() { - if (!m_creature->HasAura(SPELL_HEAD_INVIS)) - m_creature->CastSpell(m_creature,SPELL_HEAD_INVIS,false); - if (m_creature->HasAura(SPELL_HEAD)) - m_creature->RemoveAurasDueToSpell(SPELL_HEAD); + float x, y, z; + m_creature->GetPosition(x, y, z); //this visual aura some under ground + m_creature->Relocate(x, y, z + 0.35f); + Despawn(); + if (Creature *pDebuff = DoSpawnCreature(NPC_HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 14500)) + { + pDebuff->SetDisplayId(m_creature->GetDisplayId()); + pDebuff->CastSpell(pDebuff, SPELL_PUMPKIN_AURA_GREEN ,false); + pDebuff->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + ((mob_wisp_invisAI*)pDebuff->AI())->SetType(1); + m_uiDebuffGuid = pDebuff->GetObjectGuid(); + } + + m_bSprouted = false; + DoCast(m_creature, SPELL_PUMPKIN_AURA, true); + DoCast(m_creature, SPELL_SPROUTING); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } - void Aggro(Unit* pWho) + void Aggro(Unit *pWho){} + + void SpellHit(Unit *pCaster, const SpellEntry *pSpell) { - if (!pWho) + if (pSpell->Id == SPELL_SPROUTING) + { + m_bSprouted = true; + m_creature->RemoveAllAuras(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + DoCast(m_creature, SPELL_SPROUT_BODY, true); + m_creature->UpdateEntry(NPC_PUMPKIN_FIEND); + DoStartMovement(m_creature->getVictim()); + } + } + + void Despawn() + { + if (!m_uiDebuffGuid) return; - DoCast(m_creature,SPELL_HEAD,false); - //m_creature->SetInCombatWithZone(); + if(Creature *pDebuff = m_creature->GetMap()->GetCreature(m_uiDebuffGuid)) + pDebuff->SetVisibility(VISIBILITY_OFF); + + m_uiDebuffGuid.Clear(); } - void JustDied(Unit* pKiller) + void JustDied(Unit *killer) { + if(!m_bSprouted) + Despawn(); } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + void MoveInLineOfSight(Unit *pWho) { - if (!pSpell) + if (!pWho || !pWho->isTargetableForAttack() || !m_creature->IsHostileTo(pWho) || m_creature->getVictim()) return; - if (pSpell->Id == SPELL_SEND_HEAD) - { - m_creature->CastSpell(m_creature,SPELL_HEAD,true); - DoScriptText(SAY_LOST_HEAD,m_creature); - } + m_creature->AddThreat(pWho, 0.0f); - if (m_creature->HasAura(SPELL_HEAD_INVIS)) - m_creature->RemoveAurasDueToSpell(SPELL_HEAD_INVIS); + if(m_bSprouted) + DoStartMovement(pWho); } void UpdateAI(const uint32 uiDiff) { - if (!m_pInstance) - return; - - Creature* pHorseman = m_pInstance->GetSingleCreatureFromStorage(NPC_HEADLESS_HORSEMAN); - - switch (m_uiPhase) + if (m_bSprouted) { - case 0: - case 1: - case 3: - case 5: - if (m_creature->HasAura(SPELL_HEAD)) - { - DoCast(pHorseman,SPELL_SEND_HEAD,true); - m_creature->RemoveAurasDueToSpell(SPELL_HEAD); - } - if (!m_creature->HasAura(SPELL_HEAD_INVIS)) - m_creature->CastSpell(m_creature,SPELL_HEAD_INVIS,true); - break; - case 2: - case 4: - if (m_creature->HasAura(SPELL_HEAD_INVIS)) - m_creature->RemoveAurasDueToSpell(SPELL_HEAD_INVIS); - + if (m_creature->SelectHostileTarget() || m_creature->getVictim()) DoMeleeAttackIfReady(); - break; } + else if (!m_creature->HasAura(SPELL_PUMPKIN_AURA, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_PUMPKIN_AURA, true); } +}; +/*##### +# Loosely Turned Soil +#####*/ +enum HorsemanQuests +{ + QUEST_CALL_HORSEMAN_0 = 11392, + QUEST_CALL_HORSEMAN_1 = 11404, + QUEST_CALL_HORSEMAN_2 = 11405 }; -CreatureAI* GetAI_npc_horsemans_head(Creature* pCreature) +bool GOHello_go_loosely_turned_soil(Player* pPlayer, GameObject* pSoil) { - return new npc_horsemans_headAI(pCreature); -} + ScriptedInstance* m_pInstance = (ScriptedInstance*)pSoil->GetInstanceData(); -/*###### -## mob_pulsing_pumpkin -######*/ + if (!m_pInstance) + return true; -struct MANGOS_DLL_DECL mob_pulsing_pumpkinAI : public ScriptedAI -{ - mob_pulsing_pumpkinAI(Creature* pCreature) : ScriptedAI(pCreature) + if (pSoil->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) { - // on creature create - m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); - Reset(); - DoCast(m_creature,SPELL_PUMPKIN_AURA_GREEN,true); - DoCast(m_creature,SPELL_PUMPKIN_AURA,true); - DoCast(m_creature,SPELL_SPROUTING,false); - - bSquashed = false; - bTransformed = false; + pPlayer->PrepareQuestMenu(pSoil->GetObjectGuid()); + pPlayer->SendPreparedQuest(pSoil->GetObjectGuid()); } + else + return true; + + if ((pPlayer->GetQuestStatus(QUEST_CALL_HORSEMAN_0) != QUEST_STATUS_COMPLETE) && !pPlayer->GetQuestRewardStatus(QUEST_CALL_HORSEMAN_0)) + pPlayer->AreaExploredOrEventHappens(QUEST_CALL_HORSEMAN_0); + else if ((pPlayer->GetQuestStatus(QUEST_CALL_HORSEMAN_1) != QUEST_STATUS_COMPLETE) && !pPlayer->GetQuestRewardStatus(QUEST_CALL_HORSEMAN_1)) + pPlayer->AreaExploredOrEventHappens(QUEST_CALL_HORSEMAN_1); + else if ((pPlayer->GetQuestStatus(QUEST_CALL_HORSEMAN_2) != QUEST_STATUS_COMPLETE) && !pPlayer->GetQuestRewardStatus(QUEST_CALL_HORSEMAN_2)) + pPlayer->AreaExploredOrEventHappens(QUEST_CALL_HORSEMAN_2); + m_pInstance->SetData(DATA_HORSEMAN_EVENT, NOT_STARTED); + return true; +} - ScriptedInstance* m_pInstance; - - bool bSquashed; - bool bTransformed; +bool GOChooseReward_go_loosely_turned_soil(Player* pPlayer, GameObject* pSoil, const Quest* pQuest) +{ + ScriptedInstance* m_pInstance = (ScriptedInstance*)pSoil->GetInstanceData(); - void Reset() {} + if (!m_pInstance) + return true; - void UpdateAI(const uint32 uiDiff) + if (m_pInstance->GetData(DATA_HORSEMAN_EVENT) == NOT_STARTED) { - if (!m_pInstance) - return; + outstring_log("SD2: Headless Horseman summoned by: %s", pPlayer->GetName()); - Creature* pHorseman = m_pInstance->GetSingleCreatureFromStorage(NPC_HEADLESS_HORSEMAN); - - // Apply squash after landing - if (!bSquashed && m_creature->HasAura(SPELL_PUMPKIN_AURA)) + if (Creature* horseman = pSoil->SummonCreature(NPC_HH_MOUNTED, FlightPoint[0].x, FlightPoint[0].y, FlightPoint[0].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000)) { - Map::PlayerList const& lPlayers = m_pInstance->instance->GetPlayers(); - if (!lPlayers.isEmpty()) - { - for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - if (m_creature->GetDistance(pPlayer) <= INTERACTION_DISTANCE) - DoCast(pPlayer,SPELL_SQUASH_SOUL,true); - } - } - bSquashed = true; - } - - if (!bTransformed && m_creature->HasAura(SPELL_SPROUT_BODY)) - { - m_creature->UpdateEntry(NPC_PUMPKIN_FIEND); - if (Unit* pTarget = pHorseman->getVictim()) - AttackStart(pTarget); - bTransformed = true; + ((boss_headless_horsemanAI*)horseman->AI())->m_uiPlayerGuid = pPlayer->GetObjectGuid(); } + } + return true; +} - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; +CreatureAI* GetAI_mob_head(Creature* pCreature) +{ + return new mob_headAI (pCreature); +} - DoMeleeAttackIfReady(); - } -}; +CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature) +{ + return new boss_headless_horsemanAI (pCreature); +} CreatureAI* GetAI_mob_pulsing_pumpkin(Creature* pCreature) { - return new mob_pulsing_pumpkinAI(pCreature); + return new mob_pulsing_pumpkinAI (pCreature); } +CreatureAI* GetAI_mob_wisp_invis(Creature* pCreature) +{ + return new mob_wisp_invisAI (pCreature); +} + + void AddSC_boss_headless_horseman() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_headless_horseman"; - pNewScript->GetAI = GetAI_boss_headless_horseman; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_horsemans_head"; - pNewScript->GetAI = GetAI_npc_horsemans_head; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_pulsing_pumpkin"; - pNewScript->GetAI = GetAI_mob_pulsing_pumpkin; - pNewScript->RegisterSelf(); + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_headless_horseman"; + NewScript->GetAI = GetAI_boss_headless_horseman; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_head"; + NewScript->GetAI = &GetAI_mob_head; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_pulsing_pumpkin"; + NewScript->GetAI = &GetAI_mob_pulsing_pumpkin; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_wisp_invis"; + NewScript->GetAI = &GetAI_mob_wisp_invis; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "go_loosely_turned_soil"; + NewScript->pGossipHelloGO = &GOHello_go_loosely_turned_soil; + NewScript->pQuestRewardedGO = &GOChooseReward_go_loosely_turned_soil; + NewScript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp b/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp index bf3ac9a240..810a21be49 100644 --- a/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp +++ b/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp @@ -39,12 +39,13 @@ void instance_scarlet_monastery::OnCreatureCreate(Creature* pCreature) { switch(pCreature->GetEntry()) { - case NPC_HEAD: - case NPC_PUMPKIN_FIEND: - case NPC_HEADLESS_HORSEMAN: case NPC_MOGRAINE: case NPC_WHITEMANE: case NPC_VORREL: + case NPC_SIR_THOMAS: + case NPC_HH_MOUNTED: + case NPC_HH_UNHORSED: + case NPC_HEAD: m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); break; } @@ -52,8 +53,13 @@ void instance_scarlet_monastery::OnCreatureCreate(Creature* pCreature) void instance_scarlet_monastery::OnObjectCreate(GameObject* pGo) { - if (pGo->GetEntry() == GO_WHITEMANE_DOOR) - m_mGoEntryGuidStore[GO_WHITEMANE_DOOR] = pGo->GetObjectGuid(); + switch (pGo->GetEntry()) + { + case GO_WHITEMANE_DOOR: + case GO_PUMPKIN_SHRINE: + m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); + break; + } } void instance_scarlet_monastery::SetData(uint32 uiType, uint32 uiData) @@ -63,25 +69,45 @@ void instance_scarlet_monastery::SetData(uint32 uiType, uint32 uiData) case TYPE_MOGRAINE_AND_WHITE_EVENT: if (uiData == IN_PROGRESS) DoUseDoorOrButton(GO_WHITEMANE_DOOR); - if (uiData == FAIL) + else if (uiData == FAIL) DoUseDoorOrButton(GO_WHITEMANE_DOOR); - m_auiEncounter[0] = uiData; - break; - case TYPE_HALLOWSEND_EVENT: - m_auiEncounter[1] = uiData; - break; + m_auiEncounter[0] = uiData; + break; + case DATA_PUMPKIN_SHRINE: + HandleGameObject(m_mGoEntryGuidStore[GO_PUMPKIN_SHRINE], false); + break; + case DATA_HORSEMAN_EVENT: + m_auiEncounter[1] = uiData; + if (uiData == DONE) + HandleGameObject(m_mGoEntryGuidStore[GO_PUMPKIN_SHRINE], true); + break; } } -uint32 instance_scarlet_monastery::GetData(uint32 uiData) +void instance_scarlet_monastery::HandleGameObject(ObjectGuid uiGuid, bool bOpen) { - switch(uiData) + GameObject* pGo = instance->GetGameObject(uiGuid); + + if(pGo) + { + pGo->SetGoState(bOpen ? GO_STATE_ACTIVE : GO_STATE_READY); + if (!bOpen) + pGo->SetRespawnTime(0); + } + else + debug_log("TSCR: InstanceData: HandleGameObject failed"); +} + +uint32 instance_scarlet_monastery::GetData(uint32 uiType) +{ + switch(uiType) { case TYPE_MOGRAINE_AND_WHITE_EVENT: return m_auiEncounter[0]; - case TYPE_HALLOWSEND_EVENT: + case DATA_HORSEMAN_EVENT: return m_auiEncounter[1]; } + return 0; } diff --git a/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h b/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h index 1bba7553cf..3b326fb647 100644 --- a/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h +++ b/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h @@ -20,20 +20,31 @@ enum { - MAX_ENCOUNTER = 2, + MAX_ENCOUNTER = 1, TYPE_MOGRAINE_AND_WHITE_EVENT = 1, - TYPE_HALLOWSEND_EVENT = 6, - NPC_MOGRAINE = 3976, - NPC_WHITEMANE = 3977, - NPC_VORREL = 3981, + DATA_MOGRAINE = 2, + DATA_WHITEMANE = 3, + DATA_DOOR_WHITEMANE = 4, + DATA_VORREL = 5, + DATA_HORSEMAN_EVENT = 6, + DATA_PUMPKIN_SHRINE = 7, + NPC_HH_MOUNTED = 23682, + NPC_HH_UNHORSED = 23800, NPC_HEAD = 23775, + NPC_PULSING_PUMPKIN = 23694, NPC_PUMPKIN_FIEND = 23545, - NPC_HEADLESS_HORSEMAN = 23682, + NPC_HELPER = 23686, + NPC_WISP_INVIS = 24034, + NPC_SIR_THOMAS = 23904, + NPC_MOGRAINE = 3976, + NPC_WHITEMANE = 3977, + NPC_VORREL = 3981, GO_WHITEMANE_DOOR = 104600, + GO_PUMPKIN_SHRINE = 186267, }; class MANGOS_DLL_DECL instance_scarlet_monastery : public ScriptedInstance @@ -45,9 +56,10 @@ class MANGOS_DLL_DECL instance_scarlet_monastery : public ScriptedInstance void OnCreatureCreate(Creature* pCreature); void OnObjectCreate(GameObject* pGo); + void HandleGameObject(ObjectGuid uiGuid, bool bOpen); void SetData(uint32 uiType, uint32 uiData); - uint32 GetData(uint32 uiData); + uint32 GetData(uint32 uiType); private: uint32 m_auiEncounter[MAX_ENCOUNTER]; diff --git a/scripts/eastern_kingdoms/stormwind_city.cpp b/scripts/eastern_kingdoms/stormwind_city.cpp index 0570561cae..ea05dde3d7 100644 --- a/scripts/eastern_kingdoms/stormwind_city.cpp +++ b/scripts/eastern_kingdoms/stormwind_city.cpp @@ -240,9 +240,34 @@ bool GossipSelect_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature, } /*###### -## King Varian +## npc_thargold_ironwing ######*/ +#define GOSSIP_ITEM_THAR "Ich mchte durch den Hafen von Sturmwind fliegen." + +bool GossipHello_npc_thargold_ironwing(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THAR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(13454, pCreature->GetObjectGuid()); + + return true; +} + +bool GossipSelect_npc_thargold_ironwing(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->GetSession()->SendDoFlight(1149, 1041); + } + return true; +} + +/*###### + ## King Varian + ######*/ + enum { SPELL_HEROIC_LEAP = 59688, @@ -322,6 +347,12 @@ void AddSC_stormwind_city() pNewScript->pGossipHello = &GossipHello_npc_lady_katrana_prestor; pNewScript->pGossipSelect = &GossipSelect_npc_lady_katrana_prestor; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_thargold_ironwing"; + pNewScript->pGossipHello = &GossipHello_npc_thargold_ironwing; + pNewScript->pGossipSelect = &GossipSelect_npc_thargold_ironwing; + pNewScript->RegisterSelf(); pNewScript = new Script; pNewScript->Name = "boss_king_varian_wrynn"; diff --git a/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp b/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp index 2b2bd131de..b760c49c32 100644 --- a/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp +++ b/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp @@ -172,10 +172,7 @@ struct MANGOS_DLL_DECL boss_kalecgosAI : public ScriptedAI { if (m_pInstance) { - pTarget->CastSpell(pTarget, SPELL_TELEPORT_SPECTRAL_REALM, true); - pTarget->CastSpell(pTarget, SPELL_SPECTRAL_REALM_FORCE_FACTION, true); - pTarget->CastSpell(pTarget, SPELL_SPECTRAL_REALM, true); - + pTarget->CastSpell(pTarget, SPELL_SPECTRAL_REALM_GO, true); m_pInstance->SetGuid(DATA_PLAYER_SPECTRAL_REALM, pTarget->GetObjectGuid()); } } @@ -344,7 +341,7 @@ struct MANGOS_DLL_DECL boss_kalecgosAI : public ScriptedAI if (m_uiSpectralBlastTimer < uiDiff) { m_bHasSpectralTarget = false; - DoCastSpellIfCan(m_creature, SPELL_SPECTRAL_BLAST_DUMMY); + m_creature->CastSpell(m_creature, SPELL_SPECTRAL_BLAST_DUMMY, false); m_uiSpectralBlastTimer = 30000; } else @@ -571,10 +568,7 @@ bool GOUse_go_spectral_rift(Player* pPlayer, GameObject* pGo) return true; // Make them able to see Sathrovarr (he's invisible for some reason). Also, when this buff wears off, they get teleported back to Normal Realm (this is handled by Instance Script) - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_SPECTRAL_REALM, true); - pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_REALM_FORCE_FACTION, true); - pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_REALM, true); - + pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_REALM_GO, true); pInstance->SetGuid(DATA_PLAYER_SPECTRAL_REALM, pPlayer->GetObjectGuid()); } diff --git a/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp b/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp index 55b65f9dbc..1bcf87ae87 100644 --- a/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp +++ b/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp @@ -1,5 +1,5 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 - * Copyright (C) 2011 - 2012 MangosR2 +/* Copyright (C) 2006 - 2011 ScriptDev2 + * Copyright (C) 2011 MangosR2_ScriptDev2 * 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 @@ -27,124 +27,129 @@ EndScriptData */ enum UsedSpells { - // spells - - //Kilajden Spells - // generic - SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?) - SPELL_REBIRTH = 44200, // Emerge from the Sunwell - SPELL_DESTROY_DRAKES = 46707, - - // phase 1 - SPELL_SOULFLAY = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight. - SPELL_SOUL_FLAY_SLOW = 47106, - SPELL_LEGION_LIGHTING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5fk mana burn - SPELL_FIREBLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK - SPELL_FIREBLOOM_EFF = 45642, // 100% Damage - - // phase 2 - SPELL_SINISTER_REFLECTION = 45892, - //SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies//dont work - SPELL_COPY_WEAPON = 41055, // } - SPELL_COPY_WEAPON2 = 41054, // } - SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation - SPELL_COPY_OFFHAND_WEAPON = 45205, // } - SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs) - SPELL_SHADOW_SPIKE_MISSLE = 46589, - SPELL_SHADOWSPIKE_EXP = 45885, // 100% damage -> target self cast long range - SPELL_SHADOWSPIKE_DEV = 60851, // aoe 6k dmg - SPELL_SHADOWSPIKE_VIS = 33125, // visual effect - - //SPELL_FLAMEDART = 45737, // Bombards the raid with flames every 3(?) seconds - SPELL_FLAMEDART = 45740, - SPELL_DARKNESS_EXPLOSION = 45657, - SPELL_DARKNESS_OF_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50,000 damage to the raid - - // phase 3 - SPELL_ARMAGEDDON_TRIGG = 45921, - SPELL_ARMAGEDDON_VISUAL = 45909, - //SPELL_ARMAGEDDON_EFFECT = 24207, // MIGHT BE CORRECT VISUAL - SPELL_ARMAGEDDON_DMG = 45915, - SPELL_ARMAGEDDON_HELLFIRE = 45911, - SPELL_ARMAGEDDON_SPARK = 45914, - -/* Armageddon spells wrong visual - SPELL_ARMAGEDDON_TRIGGER = 45909, // Meteor spell trigger missile should cast Creature on himself - SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands - SPELL_ARMAGEDDON_VISUAL2 = 45914, // Does the light visual to indicate where the meteor missle lands - SPELL_ARMAGEDDON_VISUAL3 = 24207, // This shouldn't correct but same as seen on the movie - SPELL_ARMAGEDDON_SUMMON_TRIGGER = 45921, // Summons the triggers that cast the spells on himself need random target select - SPELL_ARMAGEDDON_DAMAGE = 45915, // This does the area damage -*/ - - // phase 4 - // Same spells with lower timers - - //Hand of the Deceiver Spells - SPELL_FELLFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!) - SPELL_SHADOWBOLT_VOLLEY = 45770, //~30 yard range Shadow Bolt Volley for ~2k(?) damage - SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry! - SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat - //SPELL_IMPFUSION = 45779, // 100% - SPELL_SUMMON_FELFIRE_FIEND = 46464, - - // Felfire fiend - SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target. - - // Anveena - SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble - SPELL_ANVEENA_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this) - SPELL_SUNWELL_IGNITION = 46822, - SPELL_SACRIFICE_OF_ANVEENA = 46474, // This is cast on Kil'Jaeden when Anveena sacrifices herself into the Sunwell - SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue - SPELL_CALL_ENTROPIUS = 46818, - - //Orb Spells - SPELL_SHADOW_ORB_BOLT_TRIGG = 45679, - //SPELL_ORB_BOLT_DEV = 45680, - //SPELL_ORB_BOLT = 53086, - //SPELL_SHADOW_BOLT = 45680, //45679 would be correct but triggers to often //TODO fix console error - - //Reflections Spells TODO - SPELL_PRIEST = 47077, // HOLY_SMITE - SPELL_PRIEST2 = 47079, // RENEW - - SPELL_PALADIN = 38921, // HOLY_SHOCK - SPELL_PALADIN2 = 37369, // HAMMER_OF_JUSTICE - - SPELL_WARLOCK = 46190, // CURSE_OF_AGONY - SPELL_WARLOCK2 = 47076, // SHADOW_BOLT - - SPELL_MAGE = 47074, // FIREBALL - - SPELL_ROGUE = 45897, // HEMORRHAGE - - SPELL_WARRIOR = 17207, // WHIRLWIND - - SPELL_DRUID = 47072, // MOONFIRE - - SPELL_SHAMAN = 47071, // EARTH_SHOCK - - SPELL_HUNTER = 48098, // MULTI_SHOT - SPELL_HUNTER2 = 16496, // SHOOT - SPELL_HUNTER3 = 40652, // WING_CLIP - - // USED BY BLUE ORB - SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid. - SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated - //SPELL_REVITALIZE = 45027, // 100% - //SPELL_SHIELD_OF_BLUE = 45848, // 100% - //AURA_BLUESHIELD = 44867, // :D - //SPELL_HASTE = 45856, // NOT WORKING + /*** Spells used during the encounter ***/ + /* Hand of the Deceiver's spells and cosmetics */ + SPELL_SHADOW_BOLT_VOLLEY = 45770, // ~30 yard range Shadow Bolt Volley for ~2k(?) damage + SPELL_SHADOW_INFUSION = 45772, // They gain this at 20% - Immunity to Stun/Silence and makes them look angry! + SPELL_FELFIRE_PORTAL = 46875, // Creates a portal that spawns Felfire Fiends (LIVE FOR THE SWARM!1 FOR THE OVERMIND!) + SPELL_SHADOW_CHANNELING = 46757, // Channeling animation out of combat + SPELL_SUMMON_FELFIRE_FIEND = 46464, + + /* Volatile Felfire Fiend's spells */ + SPELL_FELFIRE_FISSION = 45779, // Felfire Fiends explode when they die or get close to target. + + /* Kil'Jaeden's spells and cosmetics */ + SPELL_TRANS = 23188, // Surprisingly, this seems to be the right spell.. (Where is it used?) + SPELL_REBIRTH = 44200, // Emerge from the Sunwell + SPELL_SOUL_FLAY_DAMAGE = 45442, // 9k Shadow damage over 3 seconds. Spammed throughout all the fight. + SPELL_SOUL_FLAY_MOVEMENT = 47106, // -50% Movement component of the above. Players cast it on selves unless this spell is fixed. + SPELL_LEGION_LIGHTNING = 45664, // Chain Lightning, 4 targets, ~3k Shadow damage, 1.5k mana burn + SPELL_FIRE_BLOOM = 45641, // Places a debuff on 5 raid members, which causes them to deal 2k Fire damage to nearby allies and selves. MIGHT NOT WORK + SPELL_SINISTER_REFLECTION = 45785, // Summon shadow copies of 5 raid members that fight against KJ's enemies + SPELL_COPY_WEAPON = 41055, // } + SPELL_COPY_WEAPON2 = 41054, // } + SPELL_COPY_OFFHAND = 45206, // }- Spells used in Sinister Reflection creation + SPELL_COPY_OFFHAND_WEAPON = 45205, // } + SPELL_SINISTER_REFLECTION_CLASS = 45893, + SPELL_SINISTER_REFLECTION_CLONE = 45785, // Cause the target to become a clone of the caster. + SPELL_SINISTER_REFLECTION_SUMMON = 45891, + SPELL_SHADOW_SPIKE = 46680, // Bombard random raid members with Shadow Spikes (Very similar to Void Reaver orbs) + SPELL_SHADOW_SPIKE_VISUAL = 46589, + SPELL_SHADOW_SPIKE_EFFECT = 45885, // Inflicts 5100 to 6900% Shadow damage to an enemy and leaves it wounded, reducing the effectiveness of any healing by 50% for 10 sec. + SPELL_FLAME_DART = 45740, // Bombards the raid with flames every 3(?) seconds + SPELL_DARKNESS_OF_A_THOUSAND_SOULS = 46605, // Begins a 8-second channeling, after which he will deal 50'000 damage to the raid + SPELL_DARKNESS_OF_A_THOUSAND_SOULS_EFFECT = 45657, // Deals 47500 to 52500 Shadow damage to all enemies within reach. + SPELL_ARMAGEDDON = 45909, // Meteor spell + SPELL_ARMAGEDDON_VISUAL = 45911, // Does the hellfire visual to indicate where the meteor missle lands + SPELL_SACRIFICE_OF_ANVEENA = 46474, // Anveena sacrifices herself, causing Kil'jaeden to take 25% increased Holy damage. + + /* Anveena's spells and cosmetics (Or, generally, everything that has "Anveena" in name) */ + SPELL_ANVEENA_PRISON = 46367, // She hovers locked within a bubble + SPELL_ANVEENA_ENERGY_DRAIN = 46410, // Sunwell energy glow animation (Control mob uses this) + + /* Shield Orb spells */ + SPELL_SHADOW_BOLT = 45680, // constantly shooting Shadow Bolts at the raid (up to 3 bolts within 1 second) + SPELL_SHADOW_ORB_BOLT_TRIGG = 45679, + + /* Orb of the Blue Dragonflight */ + SPELL_BLINK = 45862, + SPELL_BREATH_REVITALIZE = 45860, + SPELL_BREATH_HASTE = 45856, + SPELL_SHIELD_OF_THE_BLUE = 45848, + + /*** Other Spells (used by players, etc) ***/ + SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT = 45839, // Possess the blue dragon from the orb to help the raid. + SPELL_POWER_OF_THE_BLUE_FLIGHT = 45833, // Empowers a humanoid with the essence of the Blue Flight. + SPELL_SUMMON_BLUE_DRAKE = 45836, // Summon (25653) + SPELL_ENTROPIUS_BODY = 46819, // Visual for Entropius at the Epilogue + SPELL_RING_OF_BLUE_FLAME = 45825, // Blue Flame Ring on actived orb + + //Orbs of DragonFligth + SPELL_REVITALIZE = 45027, // 100% + SPELL_SHIELD_OF_BLUE = 45848, // 100% + AURA_BLUESHIELD = 26013, // :D + AURA_NODRAGON = 44032, // workaround to dont summon more than 1 dragon per minute + SPELL_HASTE = 45856, // NOT WORKING +}; + +enum Text +{ + /*** Speech and sounds***/ + // These are used throughout Sunwell and Magisters(?). Players can hear this while running through the instances. + SAY_KJ_OFFCOMBAT1 = -1580056, + SAY_KJ_OFFCOMBAT2 = -1580057, + SAY_KJ_OFFCOMBAT3 = -1580058, + SAY_KJ_OFFCOMBAT4 = -1580059, + SAY_KJ_OFFCOMBAT5 = -1580060, + + // Encounter speech and sounds + SAY_KJ_EMERGE = -1580061, + SAY_KJ_SLAY1 = -1580062, + SAY_KJ_SLAY2 = -1580063, + SAY_KJ_REFLECTION1 = -1580064, + SAY_KJ_REFLECTION2 = -1580065, + SAY_KJ_DARKNESS1 = -1580066, + SAY_KJ_DARKNESS2 = -1580067, + SAY_KJ_DARKNESS3 = -1580068, + SAY_KJ_CANNOT_WIN = -1580070, + SAY_KJ_DENINE = -1580069, + SAY_KJ_LOST_POWER = -1580071, + + /*** Kalecgos - Anveena speech at the beginning of Phase 5; Anveena's sacrifice ***/ + SAY_KALECGOS_INTRO = -1580072, + SAY_KALECGOS_AWAKEN = -1580073, + SAY_ANVEENA_IMPRISONED = -1580074, + SAY_KALECGOS_LETGO = -1580075, + SAY_ANVEENA_LOST = -1580076, + SAY_KALECGOS_FOCUS = -1580077, + SAY_ANVEENA_KALEC = -1580078, + SAY_KALECGOS_FATE = -1580079, + SAY_ANVEENA_GOODBYE = -1580080, + SAY_KALECGOS_GOODBYE = -1580081, + SAY_KALECGOS_ENCOURAGE = -1580082, + SAY_KALECGOS_ORB1 = -1580083, + SAY_KALECGOS_ORB2 = -1580084, + SAY_KALECGOS_ORB3 = -1580085, + SAY_KALECGOS_ORB4 = -1580086, + + /*** Outro Sounds***/ + SAY_VELEN_01 = 12515, + SAY_VELEN_02 = 12516, + SAY_VELEN_03 = 12517, + SAY_VELEN_04 = 12518, + SAY_VELEN_05 = 12519, + SAY_VELEN_06 = 12520, + SAY_VELEN_07 = 12521, + SAY_VELEN_08 = 12522, + SAY_VELEN_09 = 12523, + SAY_LIADRIN_01 = 12526, + SAY_LIADRIN_02 = 12525, + SAY_LIADRIN_03 = 12524, }; enum Npcs_Go { - //NPC_ANVEENA = 26046, // Embodiment of the Sunwell - //NPC_KALECGOS = 25319, // Helps the raid throughout the fight NPC_BLUE_DRAGON = 25653, // controlled by players - NPC_VELEN = 26246, // outro - NPC_LIADRIN = 26247, // outro NPC_VELEN_PORTAL = 24925, NPC_CORE_ENTROPIUS = 26262, // Used in the ending cinematic? @@ -153,95 +158,38 @@ enum Npcs_Go NPC_FELFIRE_PORTAL = 25603, NPC_SHIELD_ORB = 25502, NPC_SINISTER = 25708, // Sinister Reflection - NPC_ARMAGEDON = 25735, + NPC_ARMAGEDDON = 25735, NPC_FELFIRE_FIEND = 25598, NPC_SHADOWSPIKE = 30598, // objects NPC_BLUE_ORB_TARGET = 25640, - ORB_BLUE_DRAGONFLIGHT = 188415, -}; - -enum Texts -{ -/*** Speech and sounds***/ - // These are used throughout Sunwell and Magisters(?). Players can hear this while running through the instances. - SAY_OFFCOMBAT1 = -1580064, - SAY_OFFCOMBAT2 = -1580065, - SAY_OFFCOMBAT3 = -1580066, - SAY_OFFCOMBAT4 = -1580067, - SAY_OFFCOMBAT5 = -1580068, + GO_ORB_OF_THE_BLUE_DRAGONFLIGHT = 188415, - // Encounter speech and sounds - SAY_EMERGE = -1580069, - SAY_SLAY1 = -1580070, - SAY_SLAY2 = -1580071, - SAY_REFLECTION1 = -1580072, - SAY_REFLECTION2 = -1580073, - SAY_DARKNESS1 = -1580074, - SAY_DARKNESS2 = -1580075, - SAY_DARKNESS3 = -1580076, - SAY_PHASE_FOUR = -1580077, - SAY_PHASE_THREE = -1580078, - SAY_PHASE_FIVE = -1580079, - - // Kalecgos - Anveena speech - SAY_KALECGOS_INTRO = -1580080, - // phase 2 - SAY_KALECGOS_AWAKEN = -1580081, - SAY_ANVEENA_IMPRISONED = -1580082, - // phase 3 - SAY_KALECGOS_LETGO = -1580083, - SAY_ANVEENA_LOST = -1580084, - // phase 4 - SAY_KALECGOS_FOCUS = -1580085, - SAY_ANVEENA_KALEC = -1580086, - SAY_KALECGOS_FATE = -1580087, - SAY_ANVEENA_GOODBYE = -1580088, - SAY_KALECGOS_GOODBYE = -1580089, - SAY_KALECGOS_ENCOURAGE = -1580090, - - // orbs - SAY_KALECGOS_ORB1 = -1580091, - SAY_KALECGOS_ORB2 = -1580092, - SAY_KALECGOS_ORB3 = -1580093, - SAY_KALECGOS_ORB4 = -1580094, - - /*** Outro Sounds***/ - SAY_OUTRO_01_VELEN = -1580095, - SAY_OUTRO_02_VELEN = -1580096, - SAY_OUTRO_03_VELEN = -1580097, - SAY_OUTRO_04_VELEN = -1580098, - SAY_OUTRO_05_LIADRIN = -1580099, - SAY_OUTRO_06_VELEN = -1580100, - SAY_OUTRO_07_LIADRIN = -1580101, - SAY_OUTRO_08_VELEN = -1580102, - SAY_OUTRO_09_VELEN = -1580103, - SAY_OUTRO_10_LIADRIN = -1580104, - SAY_OUTRO_11_VELEN = -1580105, - SAY_OUTRO_12_VELEN = -1580106, - SAY_OUTRO_13_VELEN = -1580107, + // misc + MAX_DECEIVERS = 3, }; -enum Phazes +enum Phase { - PHASE_IDLE = 0, // phase which kil jaedan is yelling awhile players goes thur instance - PHASE_ONE = 1, // kil starts his attack spells - PHASE_TWO = 2, - PHASE_THREE = 3, - PHASE_FOUR = 4, - PHASE_OUTRO = 5, + PHASE_IDLE = 0, + PHASE_DECEIVERS = 1, // Fight with the 3 Deceivers + PHASE_NORMAL = 2, // Kil'Jaeden emerges from the sunwell + PHASE_DARKNESS = 3, // At 85%, he gains few abilities; Kalecgos joins the fight + PHASE_ARMAGEDDON = 4, // At 55%, he gains even more abilities + PHASE_SACRIFICE = 5, // At 25%, Anveena sacrifices herself into the Sunwell; at this point he becomes enraged and has *significally* shorter cooldowns. + PHASE_OUTRO = 6, }; uint8 m_uiDecieverDead; /*###### -## boss_kiljaeden +## mob_kalecgos ######*/ -struct MANGOS_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI +struct MANGOS_DLL_DECL mob_kalecgosAI : public ScriptedAI { - boss_kiljaedenAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + mob_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) { m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); Reset(); @@ -249,80 +197,656 @@ struct MANGOS_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI ScriptedInstance* m_pInstance; - //timers,bools,ect\\ + uint32 m_uiOrbsEmpowered; + uint32 m_uiEmpowerTimer; + ObjectGuid m_auiOrb[4]; -// All Phases - uint32 m_uiSoulFlayTimer; - uint32 m_uiLegionLightingTimer; + void Reset() + { + m_uiOrbsEmpowered = 0; + m_uiEmpowerTimer = 0; -//phase holder - uint8 m_uiPhase; + for(uint8 i = 0; i < 4; ++i) + m_auiOrb[i].Clear(); -// Phase Idle - uint32 m_uiOrdersTimer; - // decievers this phase + FindOrbs(); + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetLevitate(true); + } + + void UpdateAI(const uint32 uiDiff) + { + // Empower a orb + if (m_uiEmpowerTimer) + { + if(m_uiEmpowerTimer < uiDiff) + { + switch(m_uiOrbsEmpowered) + { + case 0: DoScriptText(SAY_KALECGOS_ORB1, m_creature);break; + case 1: DoScriptText(SAY_KALECGOS_ORB2, m_creature);break; + case 2: DoScriptText(SAY_KALECGOS_ORB3, m_creature);break; + case 3: DoScriptText(SAY_KALECGOS_ORB4, m_creature);break; + } + + EmpowerOrb(m_uiOrbsEmpowered); + m_uiOrbsEmpowered++; + + if (m_uiOrbsEmpowered == 3) + m_uiEmpowerTimer = 20000; + else + m_uiEmpowerTimer = 0; -// Phase One - uint32 m_uiShieldOrbTimer; - uint32 m_uiMaxShieldOrbs; -// Phase Two + } + else m_uiEmpowerTimer -= uiDiff; + } + } + + void EmpowerOrb(uint32 uiActiveOrb) + { + if (uiActiveOrb < 4) + { + GameObject* pOrb = m_creature->GetMap()->GetGameObject(m_auiOrb[uiActiveOrb]); + + if(!pOrb) + return; + + // workaround effect + if (Unit* pSummon = m_creature->SummonCreature(NPC_SINISTER, pOrb->GetPositionX(), pOrb->GetPositionY(), pOrb->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 300000)) + { + pSummon->SetDisplayId(11686); + pSummon->setFaction(35); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pSummon->CastSpell(pSummon, SPELL_RING_OF_BLUE_FLAME, true); + } + + //m_creature->CastSpell(orb, SPELL_RING_OF_BLUE_FLAME, true); + pOrb->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + } + } + + void FindOrbs() + { + std::list orbList; + GetGameObjectListWithEntryInGrid(orbList, m_creature, GO_ORB_OF_THE_BLUE_DRAGONFLIGHT, 200.0f); + + if(orbList.empty()) + return; + + uint8 i = 0; + for(std::list::iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + { + m_auiOrb[i] = (*itr)->GetObjectGuid(); + (*itr)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + i++; + } + } + +}; + +CreatureAI* GetAI_mob_kalecgos(Creature *_Creature) +{ + return new mob_kalecgosAI (_Creature); +} + +/*###### +## mob_kiljaeden_controller +######*/ + +struct MANGOS_DLL_DECL mob_kiljaeden_controllerAI : public Scripted_NoMovementAI +{ + mob_kiljaeden_controllerAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + + // hack spell 45885 + SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_SHADOW_SPIKE_EFFECT); + if (pTempSpell && pTempSpell->EffectImplicitTargetB[0] != 16) + { + pTempSpell->EffectImplicitTargetA[0] = 53; + pTempSpell->EffectImplicitTargetA[1] = 0; + pTempSpell->EffectImplicitTargetB[0] = 16; + pTempSpell->EffectImplicitTargetB[1] = 0; + } + pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_SHIELD_OF_THE_BLUE); + if (pTempSpell && pTempSpell->EffectImplicitTargetB[0] != 22) + { + pTempSpell->EffectImplicitTargetB[0] = 22; + } + } + + ScriptedInstance* m_pInstance; + std::list m_uiHandDeceivers; + + bool m_bIsOutroEnd; + bool m_bIsProphetSpawned; + bool m_bIsOnce; + + ObjectGuid m_auiOrb[4]; + + uint32 m_uiOrbsEmpowered; + uint32 m_uiEmpowerTimer; + uint32 m_uiEventTimer; + uint32 m_uiAnveenaSpeechTimer; + uint32 m_uiAnveenaSpeechCounter; + uint32 m_uiProphetsTimer; + uint32 m_uiProphetsCount; + uint32 m_uiOrdersTimer; -//Phase Three void Reset() { -// Special Timers and Stuff Reset - m_uiPhase = PHASE_IDLE; - m_uiDecieverDead = 0; + m_bIsOnce = true; + m_bIsProphetSpawned = true; + m_bIsOutroEnd = false; + m_uiEventTimer = 1000; + m_uiOrdersTimer = 30000; + m_uiAnveenaSpeechTimer = 0; + m_uiAnveenaSpeechCounter = 0; + m_uiProphetsCount = 10; + m_uiOrbsEmpowered = 0; + m_uiEmpowerTimer = 0; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + std::list orbList; + GetGameObjectListWithEntryInGrid(orbList, m_creature, GO_ORB_OF_THE_BLUE_DRAGONFLIGHT, 50.0f); + + if(!orbList.empty()) + { + uint8 i = 0; + for(std::list::iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + { + m_auiOrb[i] = (*itr)->GetObjectGuid(); + (*itr)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + i++; + } + } -// All Phases - m_uiSoulFlayTimer = 5000; - m_uiLegionLightingTimer = 10000; + if (m_pInstance) + { + m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_IDLE); + m_pInstance->SetData(TYPE_KILJAEDEN, NOT_STARTED); -// Phase Idle - m_uiOrdersTimer = 10000; + if (Creature* pKalecgos = m_pInstance->GetSingleCreatureFromStorage(NPC_KALECGOS)) + { + if(mob_kalecgosAI* pKalecgosAI = dynamic_cast(pKalecgos->AI())) + pKalecgosAI->Reset(); + } + } + } -// Phase One - m_uiShieldOrbTimer = 25000; - m_uiMaxShieldOrbs = 1; + void EmpowerOrb(uint32 uiActiveOrb) + { + if (uiActiveOrb < 4) + { + GameObject* pOrb = m_creature->GetMap()->GetGameObject(m_auiOrb[uiActiveOrb]); -// Phase Two + if(!pOrb) + return; -// Kil Jaed resets - m_creature->SetVisibility(VISIBILITY_OFF); - m_creature->setFaction(35); + // workaround effect + if (Unit* pSummon = m_creature->SummonCreature(NPC_SINISTER, pOrb->GetPositionX(), pOrb->GetPositionY(), pOrb->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 300000)) + { + pSummon->SetDisplayId(11686); + pSummon->setFaction(35); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pSummon->CastSpell(pSummon, SPELL_RING_OF_BLUE_FLAME, true); + } - if (!m_creature->HasAura(SPELL_SUNWELL_RADIANCE_AURA, EFFECT_INDEX_0)) - m_creature->CastSpell(m_creature, SPELL_SUNWELL_RADIANCE_AURA, true); + //m_creature->CastSpell(orb, SPELL_RING_OF_BLUE_FLAME, true); + pOrb->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + } + } - // if (m_creature->HasAura(SPELL_SACRIFICE_OF_ANVEENA, EFFECT_INDEX_0)) - // m_creature->RemoveAurasDueToSpell(SPELL_SACRIFICE_OF_ANVEENA,0); + void UpdateAI(const uint32 uiDiff) + { + if (m_uiEventTimer < uiDiff) + { + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_IDLE) + { + // for reset in case of crash during the encounter + std::list lDeceiver; + GetCreatureListWithEntryInGrid(lDeceiver, m_creature, NPC_DECIVER, 50.0f); + + if (!lDeceiver.empty()) + { + for(std::list::iterator itr = lDeceiver.begin(); itr != lDeceiver.end(); ++itr) + { + if ((*itr) && !(*itr)->isAlive()) + (*itr)->Respawn(); + } + } + } + + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_DECEIVERS) + { + + if (m_uiOrdersTimer < uiDiff) + { + switch (rand()%5) + { + case 0: + DoScriptText(SAY_KJ_OFFCOMBAT1, m_creature); + break; + case 1: + DoScriptText(SAY_KJ_OFFCOMBAT2, m_creature); + break; + case 2: + DoScriptText(SAY_KJ_OFFCOMBAT3, m_creature); + break; + case 3: + DoScriptText(SAY_KJ_OFFCOMBAT4, m_creature); + break; + case 4: + DoScriptText(SAY_KJ_OFFCOMBAT5, m_creature); + break; + } + m_uiOrdersTimer = 30000; + } + else m_uiOrdersTimer -= uiDiff; + + // if all dead, KILJAEDEN + if (m_uiDecieverDead >= MAX_DECEIVERS) + { + m_creature->RemoveAurasDueToSpell(SPELL_ANVEENA_ENERGY_DRAIN); + m_uiAnveenaSpeechTimer = 25000; // first speech after 25 secs + + if(Creature* pKiljaeden = DoSpawnCreature(NPC_KILJAEDEN, 0, 0,0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS)) + { + pKiljaeden->CastSpell(pKiljaeden, SPELL_REBIRTH, false); + DoScriptText(SAY_KJ_EMERGE, pKiljaeden); + pKiljaeden->SetInCombatWithZone(); + } + } + } + + // Anveena and Kil'jaeden spawn check + if (m_pInstance) + { + Creature* pKiljaeden; + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) >= PHASE_NORMAL) + pKiljaeden = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN); + else + pKiljaeden = NULL; + + Creature* pAnveena = m_pInstance->GetSingleCreatureFromStorage(NPC_ANVEENA); + Creature* pKalecgos = m_pInstance->GetSingleCreatureFromStorage(NPC_KALECGOS); + + if (m_pInstance->GetData(TYPE_KILJAEDEN) == IN_PROGRESS) + { + if(m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) < PHASE_SACRIFICE) + { + m_uiAnveenaSpeechCounter = 0; + m_uiAnveenaSpeechTimer = 5000; + } + else if(m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) < PHASE_ARMAGEDDON) + { + m_uiAnveenaSpeechCounter = 0; + m_uiAnveenaSpeechTimer = 5000; + } + else if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) < PHASE_DARKNESS) + { + m_uiAnveenaSpeechCounter = 0; + m_uiAnveenaSpeechTimer = 5000; + } + } + + if (m_pInstance->GetData(TYPE_KILJAEDEN) == DONE && m_bIsOutroEnd) + { + m_creature->ForcedDespawn(); + return; + } + + // Empower a orb + if (m_uiEmpowerTimer && pKalecgos) + { + if(m_uiEmpowerTimer < uiDiff) + { + switch(m_uiOrbsEmpowered) + { + case 0: + DoScriptText(SAY_KALECGOS_ORB1, pKalecgos); + break; + case 1: + DoScriptText(SAY_KALECGOS_ORB2, pKalecgos); + break; + case 2: + DoScriptText(SAY_KALECGOS_ORB3, pKalecgos); + break; + case 3: + DoScriptText(SAY_KALECGOS_ORB4, pKalecgos); + break; + } + + EmpowerOrb(m_uiOrbsEmpowered); + m_uiOrbsEmpowered++; + + if (m_uiOrbsEmpowered == 3) + m_uiEmpowerTimer = 20000; + else + m_uiEmpowerTimer = 0; + + } + else m_uiEmpowerTimer -= uiDiff; + } + + // Phase 2 speech + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_NORMAL && m_uiAnveenaSpeechTimer) + { + if (m_uiAnveenaSpeechTimer < uiDiff) + { + if (pKalecgos && pKalecgos->isAlive()) + DoScriptText(SAY_KALECGOS_INTRO, pKalecgos); + m_uiAnveenaSpeechTimer = 0; + } + else + m_uiAnveenaSpeechTimer -= uiDiff; + } + + // Phase 3 speech + else if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_DARKNESS && m_uiAnveenaSpeechTimer) + { + if(m_uiAnveenaSpeechTimer < uiDiff) + { + switch(m_uiAnveenaSpeechCounter) + { + case 0: + if (pKalecgos) + DoScriptText(SAY_KALECGOS_AWAKEN, pKalecgos); + m_uiAnveenaSpeechTimer = 5000; + break; + case 1: + if (pAnveena) + DoScriptText(SAY_ANVEENA_IMPRISONED, pAnveena); + m_uiAnveenaSpeechTimer = 5000; + break; + case 2: + if (pKiljaeden) + DoScriptText(SAY_KJ_DENINE, pKiljaeden); + m_uiAnveenaSpeechTimer = 0; + break; + } + + m_uiAnveenaSpeechCounter++; + } + else + m_uiAnveenaSpeechTimer -= uiDiff; + } + // Phase 4 speech + else if ( m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_ARMAGEDDON && m_uiAnveenaSpeechTimer) + { + if (m_uiAnveenaSpeechTimer < uiDiff) + { + switch(m_uiAnveenaSpeechCounter) + { + case 0: + if (pKalecgos) + DoScriptText(SAY_KALECGOS_LETGO, pKalecgos); + m_uiAnveenaSpeechTimer = 7000; + break; + case 1: + if (pAnveena) + DoScriptText(SAY_ANVEENA_LOST, pAnveena); + m_uiAnveenaSpeechTimer = 5000; + break; + case 2: + if (pKiljaeden) + DoScriptText(SAY_KJ_CANNOT_WIN, pKiljaeden); + m_uiAnveenaSpeechTimer = 0; + break; + } + + m_uiAnveenaSpeechCounter++; + } + else + m_uiAnveenaSpeechTimer -= uiDiff; + } + // Phase 5 speech + else if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_SACRIFICE && m_uiAnveenaSpeechTimer) + { + if (m_uiAnveenaSpeechTimer < uiDiff) + { + switch(m_uiAnveenaSpeechCounter) + { + case 0: + if (pKalecgos) + DoScriptText(SAY_KALECGOS_FOCUS, pKalecgos); + m_uiAnveenaSpeechTimer = 10000; + break; + case 1: + if (pAnveena) + DoScriptText(SAY_ANVEENA_KALEC, pAnveena); + m_uiAnveenaSpeechTimer = 3000; + break; + case 2: + if (pKalecgos) + DoScriptText(SAY_KALECGOS_FATE, pKalecgos); + m_uiAnveenaSpeechTimer = 7000; + break; + case 3: + if (pAnveena) + DoScriptText(SAY_ANVEENA_GOODBYE, pAnveena); + m_uiAnveenaSpeechTimer = 6000; + break; + case 4: + if (pKiljaeden && pKiljaeden->isAlive() && pAnveena && pAnveena->isAlive()) + { + pAnveena->CastSpell(pKiljaeden, SPELL_SACRIFICE_OF_ANVEENA, true); + + pAnveena->ForcedDespawn(); + DoScriptText(SAY_KJ_LOST_POWER, pKiljaeden); + } + m_uiAnveenaSpeechTimer = 13000; + break; + case 5: + if (pKalecgos) + DoScriptText(SAY_KALECGOS_GOODBYE, pKalecgos); + m_uiAnveenaSpeechTimer = 14000; + break; + case 6: + if (pKalecgos) + DoScriptText(SAY_KALECGOS_ENCOURAGE, pKalecgos); + m_uiAnveenaSpeechTimer = 0; + break; + } + m_uiAnveenaSpeechCounter++; + } + else + m_uiAnveenaSpeechTimer -= uiDiff; + } + } + } + else + m_uiEventTimer -=uiDiff; + + // OUTRO + if (m_pInstance && m_pInstance->GetData(TYPE_KILJAEDEN) == DONE && m_bIsOnce) + { + m_bIsProphetSpawned = false; + m_uiProphetsCount = 0; + m_uiProphetsTimer = 20000; + m_bIsOnce = false; + } + + if (!m_bIsProphetSpawned) + { + if (Creature* pVelen = m_creature->SummonCreature(NPC_VELEN, m_creature->GetPositionX()+15, m_creature->GetPositionY()+15, m_creature->GetPositionZ(), 3.874f, TEMPSUMMON_TIMED_DESPAWN, 360000)) + { + pVelen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pVelen->setFaction(35); + } + + if (Creature* pLiadrin = m_creature->SummonCreature(NPC_LIADRIN, m_creature->GetPositionX()+20, m_creature->GetPositionY()+17, m_creature->GetPositionZ(), 3.874f, TEMPSUMMON_TIMED_DESPAWN, 360000)) + { + pLiadrin->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pLiadrin->setFaction(35); + } + + m_bIsProphetSpawned = true; + } + + if (!m_bIsOnce) + { + if ((m_uiProphetsTimer < uiDiff) && !m_bIsOutroEnd) + { + switch(m_uiProphetsCount) + { + case 0: + DoPlaySoundToSet(m_creature, SAY_VELEN_01); + m_uiProphetsTimer = 25000; + break; + case 1: + DoPlaySoundToSet(m_creature, SAY_VELEN_02); + m_uiProphetsTimer = 15000; + break; + case 2: + DoPlaySoundToSet(m_creature, SAY_VELEN_03); + m_uiProphetsTimer = 10000; + break; + case 3: + DoPlaySoundToSet(m_creature, SAY_VELEN_04); + m_uiProphetsTimer = 26000; + break; + case 9: + DoPlaySoundToSet(m_creature, SAY_LIADRIN_01); + m_uiProphetsTimer = 20000; + break; + case 5: + DoPlaySoundToSet(m_creature, SAY_VELEN_05); + m_uiProphetsTimer = 16000; + break; + case 6: + DoPlaySoundToSet(m_creature, SAY_LIADRIN_02); + m_uiProphetsTimer = 3000; + break; + case 7: + DoPlaySoundToSet(m_creature, SAY_VELEN_06); + m_uiProphetsTimer = 17000; + break; + case 8: + DoPlaySoundToSet(m_creature, SAY_VELEN_07); + m_uiProphetsTimer = 16000; + break; + case 4: + DoPlaySoundToSet(m_creature, SAY_LIADRIN_03); + m_uiProphetsTimer = 11000; + break; + case 10: + DoPlaySoundToSet(m_creature, SAY_VELEN_08); + m_uiProphetsTimer = 7000; + break; + case 11: + DoPlaySoundToSet(m_creature, SAY_VELEN_09); + m_bIsOutroEnd = true; + m_creature->setFaction(35); + break; + } + ++m_uiProphetsCount; + } + else + m_uiProphetsTimer -= uiDiff; + } + } + + void FindHandDeceivers() + { + std::list DeceiverList; + GetCreatureListWithEntryInGrid(DeceiverList, m_creature, NPC_DECIVER, 50.0f); + + if (!DeceiverList.empty()) + { + m_uiHandDeceivers.clear(); + for(std::list::iterator itr = DeceiverList.begin(); itr != DeceiverList.end(); ++itr) + m_uiHandDeceivers.push_back((*itr)->GetObjectGuid()); + } + } +}; + +CreatureAI* GetAI_mob_kiljaeden_controller(Creature *pCreature) +{ + return new mob_kiljaeden_controllerAI(pCreature); +} + +/*###### +## boss_kiljaeden +######*/ + +struct MANGOS_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI +{ + boss_kiljaedenAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + /* General */ + ScriptedInstance* m_pInstance; + uint32 m_uiCancelShieldTimer; + + /* Phase 2+ spells */ + uint32 m_uiSoulFlayTimer; + uint32 m_uiLegionLightningTimer; + uint32 m_uiFireBloomTimer; + uint32 m_uiSummonShieldOrbTimer; + + /* Phase 3+ spells */ + uint32 m_uiFlameDartTimer; + uint32 m_uiDarknessTimer; + uint32 m_uiDarknessBombTimer; + uint32 m_uiShadowSpikeTimer; + uint32 m_uiShadowSpikeCount; + + /* Phase 4+ spells */ + uint32 m_uiArmageddonTimer; + + void Reset() + { + // Special Timers and Stuff Reset + m_uiSoulFlayTimer = 15000; + m_uiLegionLightningTimer = 30000; + m_uiFireBloomTimer = 30000; + m_uiSummonShieldOrbTimer = 45000; + + m_uiFlameDartTimer = 3000; + m_uiDarknessTimer = 60000; + m_uiDarknessBombTimer = 0; + m_uiShadowSpikeTimer = 5000; + m_uiShadowSpikeCount = 30000; + + m_uiArmageddonTimer = 10000; + m_uiCancelShieldTimer = 3000000; } void Aggro(Unit* pWho) { - m_creature->SetInCombatWithZone(); - DoCast(m_creature, SPELL_REBIRTH); - DoScriptText(SAY_EMERGE, m_creature); - m_uiPhase = PHASE_ONE; + DoScriptText(SAY_KJ_EMERGE, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_NORMAL); } void JustReachedHome() { + m_uiDecieverDead = 0; + if (m_pInstance) + { m_pInstance->SetData(TYPE_KILJAEDEN, NOT_STARTED); m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_IDLE); - if (Creature* pAnveena = m_pInstance->GetSingleCreatureFromStorage(NPC_ANVEENA)) - { - if (!pAnveena->isAlive()) - pAnveena->Respawn(); - } + if (Creature* pAnveena = m_pInstance->GetSingleCreatureFromStorage(NPC_ANVEENA)) + { + if (!pAnveena->isAlive()) + pAnveena->Respawn(); + } - if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN_CONTROLLER)) - { - if (pController->isAlive()) - pController->AI()->EnterEvadeMode(); + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN_CONTROLLER)) + { + if (pController->isAlive()) + pController->AI()->EnterEvadeMode(); + } } std::list lDecievers; @@ -335,14 +859,63 @@ struct MANGOS_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI (*iter)->Respawn(); } } + + m_creature->ForcedDespawn(); + } + + void CastSinisterReflection() + { +// for (uint8 i = 0; i < 4; ++i) // disadvantage is it may be duplicated target +// DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), SPELL_SINISTER_REFLECTION); + // workaround + for (uint8 i = 0; i < 4; ++i) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + if (Creature* pSummon = pPlayer->SummonCreature(NPC_SINISTER, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pSummon->SetDisplayId(pPlayer->GetDisplayId()); + pSummon->setFaction(m_creature->getFaction()); + pSummon->SetMaxHealth(100000); + pSummon->SetHealth(100000); + + pSummon->setPowerType(pPlayer->getPowerType()); + pSummon->SetMaxPower(pPlayer->getPowerType(),pPlayer->GetMaxPower(pPlayer->getPowerType())); + pSummon->SetPower(pPlayer->getPowerType(),pPlayer->GetMaxPower(pPlayer->getPowerType())); + + // pSummon->CastSpell(pPlayer, SPELL_SINISTER_REFLECTION_CLASS, true); + // pSummon->CastSpell(pPlayer, SPELL_SINISTER_REFLECTION_CLONE, true); + pSummon->CastSpell(pPlayer, SPELL_COPY_WEAPON, true); + pSummon->CastSpell(pPlayer, SPELL_COPY_WEAPON2, true); + pSummon->CastSpell(pPlayer, SPELL_COPY_OFFHAND, true); + pSummon->CastSpell(pPlayer, SPELL_COPY_OFFHAND_WEAPON, true); + pSummon->AI()->AttackStart(pPlayer); + } + } + } + } + + switch(urand(0,1)) + { + case 0: DoScriptText(SAY_KJ_REFLECTION1, m_creature);break; + case 1: DoScriptText(SAY_KJ_REFLECTION2, m_creature);break; + } + } + + void DamageDeal(Unit* pDoneTo, uint32& uiDamage) + { + if(pDoneTo->HasAura(AURA_BLUESHIELD)) + uiDamage = uiDamage * 0.05; } void KilledUnit(Unit* pVictim) { switch (rand()%2) { - case 0: DoScriptText(SAY_SLAY1, m_creature); break; - case 1: DoScriptText(SAY_SLAY2, m_creature); break; + case 0: DoScriptText(SAY_KJ_SLAY1, m_creature); break; + case 1: DoScriptText(SAY_KJ_SLAY2, m_creature); break; } } @@ -357,62 +930,301 @@ struct MANGOS_DLL_DECL boss_kiljaedenAI : public Scripted_NoMovementAI void UpdateAI(const uint32 uiDiff) { -// Phase_Idle - if (m_uiPhase == PHASE_IDLE) + if (!m_pInstance || !m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiCancelShieldTimer < uiDiff) { - if (m_uiOrdersTimer < uiDiff) + std::list t_list = m_creature->getThreatManager().getThreatList(); + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { - switch (rand()%5) + Player* pPlayer = m_creature->GetMap()->GetPlayer((*itr)->getUnitGuid()); + if (pPlayer && pPlayer->HasAura(AURA_BLUESHIELD)) { - case 0: DoScriptText(SAY_OFFCOMBAT1, m_creature); break; - case 1: DoScriptText(SAY_OFFCOMBAT2, m_creature); break; - case 2: DoScriptText(SAY_OFFCOMBAT3, m_creature); break; - case 3: DoScriptText(SAY_OFFCOMBAT4, m_creature); break; - case 4: DoScriptText(SAY_OFFCOMBAT5, m_creature); break; - } - m_uiOrdersTimer = 30000; + if(pPlayer->HasAura(AURA_BLUESHIELD)) + pPlayer->RemoveAurasDueToSpell(AURA_BLUESHIELD); + } } - else m_uiOrdersTimer -= uiDiff; - // break; // might be needed went know till play testing + m_uiCancelShieldTimer = 3000000; } + else + m_uiCancelShieldTimer -= uiDiff; - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - // Legion Lighting all phases - if (m_uiLegionLightingTimer < uiDiff) + // ***************************************** + // ********* Check for Blue Aura *********** + // ***************************************** + if(Unit* pDragon = GetClosestCreatureWithEntry(m_creature, NPC_BLUE_DRAGON, 80.0f)) { - DoCast(m_creature->getVictim(), SPELL_LEGION_LIGHTING); - m_uiLegionLightingTimer = 11000; - }else m_uiLegionLightingTimer -= uiDiff; + if(pDragon && pDragon->HasAura(SPELL_SHIELD_OF_BLUE)) + { + std::list t_list = m_creature->getThreatManager().getThreatList(); + for(std::list::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Player *pPlayer = m_creature->GetMap()->GetPlayer((*itr)->getUnitGuid()); + if (pPlayer && pPlayer->IsWithinDistInMap(pDragon, 15.0f)) + { + pPlayer->RemoveAurasDueToSpell(AURA_BLUESHIELD); + pPlayer->CastSpell(pPlayer, AURA_BLUESHIELD, true); + } + } + } + } - // soul flay all phases + // ***************************************** + // *********** Phase 2 spells ************** + // ***************************************** + + // Soul Flay : 9k damage over 3 seconds on highest aggro if (m_uiSoulFlayTimer < uiDiff) { - DoCast(m_creature->getVictim(), SPELL_SOULFLAY); - m_uiSoulFlayTimer = 7000; - }else m_uiSoulFlayTimer -= uiDiff; + DoCast(m_creature->getVictim(), SPELL_SOUL_FLAY_DAMAGE); + m_creature->getVictim()->CastSpell(m_creature->getVictim(), SPELL_SOUL_FLAY_MOVEMENT, true); + m_uiSoulFlayTimer = 3500; + } + else + m_uiSoulFlayTimer -= uiDiff; + + // Legion Lightning : Lightning on random target, jumps to 3 additional players, burns 1500 mana and deals 3k damage + if (m_uiLegionLightningTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), SPELL_LEGION_LIGHTNING); + m_uiLegionLightningTimer = (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_SACRIFICE) ? 18000 : 30000; // 18 seconds in PHASE_SACRIFICE + } + else + m_uiLegionLightningTimer -= uiDiff; + + // Fire Bloom : Places a debuff on 5 random targets; targets and all nearby allies suffer ~1.7k fire damage every 2 seconds + if (m_uiFireBloomTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FIRE_BLOOM); + m_uiFireBloomTimer = (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_SACRIFICE) ? 25000 : 40000; // 25 seconds in PHASE_SACRIFICE + } + else + m_uiFireBloomTimer -= uiDiff; + + // Summon Shield Orb : Spawns a Shield Orb add and constantly shooting Shadow Bolts at the raid + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) != PHASE_SACRIFICE) + { + if (m_uiSummonShieldOrbTimer < uiDiff) + { + // northeast of Kil'jaeden + for(uint8 i = 1; i < m_pInstance->GetData(TYPE_KILJAEDEN_PHASE); ++i) + { + if (Creature* pOrb = m_creature->SummonCreature(NPC_SHIELD_ORB, 1709.000f, 615.000f, 40.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pOrb->AI()->AttackStart(pTarget); + } + m_uiSummonShieldOrbTimer = (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_SACRIFICE) ? 30000 : 60000; // 30 seconds in PHASE_SACRIFICE + } + else + m_uiSummonShieldOrbTimer -= uiDiff; + } + + // ***************************************** + // *********** Phase 3 spells ************** + // ***************************************** + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_NORMAL && (m_creature->GetHealthPercent() < 85.0f)) + { + m_creature->InterruptNonMeleeSpells(true); + + // Sinister Reflection + CastSinisterReflection(); + + // Shadow Spike + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_SPIKE); + + m_uiSoulFlayTimer = 30000; // Don't let other spells + m_uiLegionLightningTimer += 30000; // interrupt Shadow Spikes + m_uiFireBloomTimer += 30000; + m_uiSummonShieldOrbTimer += 30000; + m_uiFlameDartTimer += 30000; + //m_uiDarknessTimer += 30000; + m_uiShadowSpikeCount = 30000; // shadow spike visual timer + + // Active orb after 35 seconds + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN_CONTROLLER)) + { + if(mob_kiljaeden_controllerAI* pControllerAI = dynamic_cast(pController->AI())) + pControllerAI->m_uiEmpowerTimer = 35000; + } -// Phase_One - if (m_uiPhase == PHASE_ONE) + m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_DARKNESS); + } + else if(m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) <= PHASE_NORMAL) + return; + + // Shadow Spike Effect Count + if (m_uiShadowSpikeCount) { - if (m_uiShieldOrbTimer < uiDiff) // needs a trigger like a bool that keeps it from casting at everytime the bool would reset every phase or something not sure yet 8) + if (m_uiShadowSpikeTimer < uiDiff) { - for(uint8 i = 0; i < m_uiMaxShieldOrbs; ++i) + // workaround + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - float angle = (float) rand()*360/RAND_MAX + 1; - float homeX = m_creature->GetPositionX() + 20*cos(angle*(M_PI/180)); - float homeY = m_creature->GetPositionY() + 20*sin(angle*(M_PI/180)); - m_creature->SummonCreature(NPC_SHIELD_ORB, homeX, homeY, m_creature->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + m_creature->CastSpell(pTarget, SPELL_SHADOW_SPIKE_VISUAL, true); + // visual effect to ground (because missile is glitched) + if(Creature *pSpikeAlert = m_creature->SummonCreature(NPC_SINISTER, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()+1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 4000)) + { + pSpikeAlert->SetDisplayId(15882); + pSpikeAlert->SetName("Shadow Spike"); + pSpikeAlert->setFaction(35); + pSpikeAlert->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } } - m_uiShieldOrbTimer = 50000; + + m_uiShadowSpikeTimer = 5000; + m_uiShadowSpikeCount -= m_uiShadowSpikeTimer; } - else m_uiShieldOrbTimer -= uiDiff; + else + m_uiShadowSpikeTimer -= uiDiff; + } - //if (m_creature->GetHealthPercent() < 85.0f) - //m_uiPhase = PHASE_TWO; + // Flame Dart Explosion + if(m_uiFlameDartTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FLAME_DART); + + m_uiFlameDartTimer = 3000; } + else + m_uiFlameDartTimer -= uiDiff; + + // Darkness of a Thousand Souls : Begins to channel for 8 seconds, then deals 50'000 damage to all raid members. + if (m_uiDarknessTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + //DoCast(m_creature, SPELL_DARKNESS_OF_A_THOUSAND_SOULS); + m_creature->CastSpell(m_creature, SPELL_DARKNESS_OF_A_THOUSAND_SOULS, true); + + m_uiSummonShieldOrbTimer += 9000; // Don't let other spells + m_uiFireBloomTimer += 9000; // interrupt Darkness of a Thousand Souls + m_uiLegionLightningTimer += 9000; + m_uiFlameDartTimer += 9000; + + if(m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) >= PHASE_ARMAGEDDON) + m_uiArmageddonTimer += 9000; // Armageddon on the other hand, can be casted now, if Anveena has already sacrificed + + m_uiSoulFlayTimer = 9000; + m_uiDarknessBombTimer = 8000; // Darkness of a Thousand Souls effect timer + + switch(rand()%3) + { + case 0: DoScriptText(SAY_KJ_DARKNESS1, m_creature);break; + case 1: DoScriptText(SAY_KJ_DARKNESS2, m_creature);break; + case 2: DoScriptText(SAY_KJ_DARKNESS3, m_creature);break; + } + + m_uiDarknessTimer = (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_SACRIFICE) ? 30000 + rand()%10000 : 40000 + rand()%30000; + } + else + m_uiDarknessTimer -= uiDiff; + + // Darkness of a Thousand Souls Effect + if (m_uiDarknessBombTimer) + { + if(m_uiDarknessBombTimer < uiDiff) + { + DoCast(m_creature, SPELL_DARKNESS_OF_A_THOUSAND_SOULS_EFFECT); + m_uiDarknessBombTimer = 0; + } + else + m_uiDarknessBombTimer -= uiDiff; + } + + // ***************************************** + // *********** Phase 4 spells ************** + // ***************************************** + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_DARKNESS && (m_creature->GetHealthPercent() < 55.0f)) + { + m_creature->InterruptNonMeleeSpells(true); + + // Sinister Reflection + CastSinisterReflection(); + + // Shadow Spike + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_SPIKE); + + m_uiSoulFlayTimer = 30000; // Don't let other spells + m_uiLegionLightningTimer += 30000; // interrupt Shadow Spikes + m_uiFireBloomTimer += 30000; + m_uiSummonShieldOrbTimer += 30000; + m_uiFlameDartTimer += 30000; + m_uiDarknessTimer += 30000; + m_uiArmageddonTimer += 30000; + m_uiShadowSpikeCount = 30000; // shadow spike visual timer + + // Active orb after 35 seconds + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN_CONTROLLER)) + { + if(mob_kiljaeden_controllerAI* pControllerAI = dynamic_cast(pController->AI())) + pControllerAI->m_uiEmpowerTimer = 35000; + } + + m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_ARMAGEDDON); + } + else if(m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) <= PHASE_DARKNESS) + return; + + // Armageddon + if (m_uiArmageddonTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + float fX, fY, fZ; + pTarget->GetPosition(fX, fY, fZ); + if(Creature* pArmageddon = m_creature->SummonCreature(NPC_ARMAGEDDON, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 5000)) + { + pArmageddon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(pArmageddon, SPELL_ARMAGEDDON, true); + pArmageddon->CastSpell(pArmageddon, SPELL_ARMAGEDDON_VISUAL, true); + } + } + m_uiArmageddonTimer = 4000; // No, I'm not kidding + } + else + m_uiArmageddonTimer -= uiDiff; + + + // ***************************************** + // *********** Phase 5 spells ************** + // ***************************************** + if (m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) == PHASE_ARMAGEDDON && (m_creature->GetHealthPercent() < 25.0f)) + { + m_creature->InterruptNonMeleeSpells(true); + + // Sinister Reflection + CastSinisterReflection(); + + // Shadow Spike + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_SPIKE); + + m_uiSoulFlayTimer = 30000; // Don't let other spells + m_uiLegionLightningTimer += 30000; // interrupt Shadow Spikes + m_uiFireBloomTimer += 30000; + m_uiSummonShieldOrbTimer += 30000; + m_uiFlameDartTimer += 30000; + m_uiDarknessTimer += 30000; + m_uiArmageddonTimer += 30000; + m_uiShadowSpikeCount = 30000; // shadow spike visual timer + + // Active orb after 35 seconds + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN_CONTROLLER)) + { + if(mob_kiljaeden_controllerAI* pControllerAI = dynamic_cast(pController->AI())) + pControllerAI->m_uiEmpowerTimer = 35000; + } + m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_SACRIFICE); + } + else if(m_pInstance->GetData(TYPE_KILJAEDEN_PHASE) <= PHASE_ARMAGEDDON) + return; } }; @@ -430,7 +1242,7 @@ struct MANGOS_DLL_DECL mob_deceiverAI : public ScriptedAI { mob_deceiverAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } @@ -453,8 +1265,10 @@ struct MANGOS_DLL_DECL mob_deceiverAI : public ScriptedAI m_uiDecieverDead = 0; if (m_pInstance) + { m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_IDLE); m_pInstance->SetData(TYPE_KILJAEDEN, NOT_STARTED); + } } void Aggro(Unit* pWho) @@ -462,13 +1276,19 @@ struct MANGOS_DLL_DECL mob_deceiverAI : public ScriptedAI if (m_pInstance) { m_pInstance->SetData(TYPE_KILJAEDEN, IN_PROGRESS); - m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_ONE); + m_pInstance->SetData(TYPE_KILJAEDEN_PHASE, PHASE_DECEIVERS); + + if (Creature* pAnveena = m_pInstance->GetSingleCreatureFromStorage(NPC_ANVEENA)) + { + pAnveena->GetMap()->CreatureRelocation(pAnveena, 1698.45f, 628.03f, 70.1989f, 0.0f); + pAnveena->GetMotionMaster()->MovePoint(1, 1698.45f, 628.03f, 70.1989f); + } } m_creature->CastStop(); - std::list lDecievers; GetCreatureListWithEntryInGrid(lDecievers, m_creature, NPC_DECIVER, 40.0f); + if (!lDecievers.empty()) { for(std::list::iterator iter = lDecievers.begin(); iter != lDecievers.end(); ++iter) @@ -481,17 +1301,7 @@ struct MANGOS_DLL_DECL mob_deceiverAI : public ScriptedAI void JustDied(Unit* pKiller) { - if (++m_uiDecieverDead == 3) - { - if (m_pInstance) - { - if (Unit* pKilJaeden = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN)) - { - pKilJaeden->setFaction(14); - pKilJaeden->SetVisibility(VISIBILITY_ON); - } - } - } + ++m_uiDecieverDead; if (Creature* pPortal = m_creature->GetMap()->GetCreature(m_uiPortalGUID)) pPortal->ForcedDespawn(); @@ -541,7 +1351,7 @@ struct MANGOS_DLL_DECL mob_deceiverAI : public ScriptedAI if (m_uiShadowBoltTimer < uiDiff) { m_creature->InterruptNonMeleeSpells(true); - DoCast(m_creature, SPELL_SHADOWBOLT_VOLLEY); + DoCast(m_creature, SPELL_SHADOW_BOLT_VOLLEY); m_uiShadowBoltTimer = urand(6000, 10000); } else m_uiShadowBoltTimer -= uiDiff; @@ -714,32 +1524,250 @@ CreatureAI* GetAI_mob_felfire_fiend(Creature* pCreature) return new mob_felfire_fiendAI(pCreature); } +/*###### +## mob_sinister_reflection +######*/ +struct MANGOS_DLL_DECL mob_sinister_reflectionAI : public ScriptedAI +{ + mob_sinister_reflectionAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_uiPlayerClass = 0; + } + + uint32 m_uiPlayerAbilityTimer; + uint32 m_uiPlayerClass; + + void Reset() + { + m_uiPlayerAbilityTimer = urand(3500, 6000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!m_uiPlayerClass) + { + m_uiPlayerClass = m_creature->getVictim()->getClass(); + + if (m_uiPlayerClass == CLASS_PRIEST && m_creature->getVictim()->HasSpell(15473)) + m_uiPlayerClass = 10; + } + + if (m_uiPlayerAbilityTimer < diff) + { + UseAbility(); + m_uiPlayerAbilityTimer = urand(3500, 6000); + } + else + m_uiPlayerAbilityTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void UseAbility() + { + if (!m_uiPlayerClass) + return; + + uint32 random = urand(0,1); + uint32 uiSpell = 0; + Unit* pTarget = NULL; + + switch (m_uiPlayerClass) + { + case CLASS_WARRIOR: + uiSpell = 15576; + pTarget = m_creature; + break; + case CLASS_PALADIN: + random ? uiSpell = 38921 : uiSpell = 37369; + pTarget = m_creature->getVictim(); + break; + case CLASS_HUNTER: + random ? uiSpell = 48098 : uiSpell = 16496; + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + break; + case CLASS_ROGUE: + uiSpell = 45897; + pTarget = m_creature->getVictim(); + break; + case CLASS_PRIEST: + uiSpell = 47079; + pTarget = DoSelectLowestHpFriendly(50, 0); + if (pTarget->GetEntry() != m_creature->GetEntry()) // solo altri Sinister Reflection + pTarget = m_creature; + break; + case 10: + uiSpell = 47077; + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + break; + case CLASS_SHAMAN: + uiSpell = 47077; + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + break; + case CLASS_MAGE: + uiSpell = 47074; + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + break; + case CLASS_WARLOCK: + random ? uiSpell = 46190 : uiSpell = 47076; + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + break; + case CLASS_DRUID: + uiSpell = 47072; + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + break; + } + + if (pTarget) + DoCastSpellIfCan(pTarget, uiSpell); + } +}; + + +CreatureAI* GetAI_mob_sinister_reflection(Creature *_Creature) +{ + return new mob_sinister_reflectionAI (_Creature); +} + +//Dragon Gossip Menu +//This function is called when the player opens the gossip menubool + +#define GOSSIP_ITEM_1 "cast on me Shield of the Blue Dragon Flight ! Quikly !" +#define GOSSIP_ITEM_2 "cast on me Dragon Breath: Revitalize !" +#define GOSSIP_ITEM_3 "cast on me Dragon Breath: Haste! (NON FUNZIONA)" +#define GOSSIP_ITEM_4 "cast on me Blink !" +#define GOSSIP_ITEM_5 "Fight with our Enemy !" + +bool GossipHello_dragon(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_dragon(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance*)pPlayer->GetInstanceData(); + + if (!m_pInstance) + return false; + + if (uiSender == GOSSIP_SENDER_MAIN) + { + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + if (Creature* pKJ = m_pInstance->GetSingleCreatureFromStorage(NPC_KILJAEDEN)) + { + if (boss_kiljaedenAI* pKJAI = dynamic_cast(pKJ->AI())) + pKJAI->m_uiCancelShieldTimer = 5500; + } + + pCreature->CastSpell(pPlayer, SPELL_SHIELD_OF_BLUE, false); + pPlayer->CastSpell(pPlayer, SPELL_SHIELD_OF_BLUE, false); + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + case GOSSIP_ACTION_INFO_DEF+2: + pCreature->CastSpell(pPlayer, SPELL_REVITALIZE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CastSpell(pPlayer, SPELL_HASTE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->TeleportTo(pPlayer->GetMapId(), pPlayer->GetPositionX()+10, pPlayer->GetPositionY()+10, pPlayer->GetPositionZ(), pPlayer->GetOrientation()); + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + } + } + + return true; +} + +bool GOUse_orb_of_the_blue_flight(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance*)pPlayer->GetInstanceData(); + + if (m_pInstance && m_pInstance->GetData(TYPE_KILJAEDEN) == IN_PROGRESS) + { + if(Creature* pDragon = pPlayer->SummonCreature(NPC_BLUE_DRAGON, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ()+1, 0, TEMPSUMMON_CORPSE_DESPAWN, 20000)) + { + pDragon->SetSpeedRate(MOVE_FLIGHT, 1.0f); + pDragon->SetSpeedRate(MOVE_WALK, 1.0f); + pDragon->SetSpeedRate(MOVE_RUN, 1.0f); + pDragon->GetMotionMaster()->MoveFollow(pPlayer, 0.0f, 0.0f); + pDragon->DealDamage(pDragon, pDragon->GetHealth()/100, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + pPlayer->CastSpell(pPlayer, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, true); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + } + + return true; +} + void AddSC_boss_kiljaeden() { Script *pNewScript; pNewScript = new Script; - pNewScript->Name="boss_kiljaeden"; + pNewScript->Name = "mob_kiljaeden_controller"; + pNewScript->GetAI = &GetAI_mob_kiljaeden_controller; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "boss_kiljaeden"; pNewScript->GetAI = &GetAI_boss_kiljaeden; pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name="mob_deceiver"; + pNewScript->Name = "mob_kalecgos"; + pNewScript->GetAI = &GetAI_mob_kalecgos; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "mob_hand_of_the_deceiver"; pNewScript->GetAI = &GetAI_mob_deceiver; pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name="mob_shield_orb"; + pNewScript->Name = "mob_shield_orb"; pNewScript->GetAI = &GetAI_mob_shield_orb; pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name="mob_felfire_portal"; + pNewScript->Name = "mob_felfire_portal"; pNewScript->GetAI = &GetAI_mob_felfire_portal; pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name="mob_felfire_fiend"; + pNewScript->Name = "mob_felfire_fiend"; pNewScript->GetAI = &GetAI_mob_felfire_fiend; pNewScript->RegisterSelf(); -} + + pNewScript = new Script; + pNewScript->Name = "mob_sinister_reflection"; + pNewScript->GetAI = &GetAI_mob_sinister_reflection; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "dragon"; + pNewScript->pGossipHello = &GossipHello_dragon; + pNewScript->pGossipSelect = &GossipSelect_dragon; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "go_orb_of_the_blue_flight"; + pNewScript->pGOUse = &GOUse_orb_of_the_blue_flight; + pNewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp b/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp index 0fbd69a501..631f908a99 100644 --- a/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp +++ b/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp @@ -43,6 +43,8 @@ instance_sunwell_plateau::instance_sunwell_plateau(Map* pMap) : ScriptedInstance void instance_sunwell_plateau::Initialize() { memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiKiljaedenPhase = 0; } bool instance_sunwell_plateau::IsEncounterInProgress() const @@ -63,7 +65,7 @@ void instance_sunwell_plateau::OnCreatureCreate(Creature* pCreature) case NPC_KALECGOS_DRAGON: case NPC_KALECGOS_HUMAN: case NPC_SATHROVARR: - case NPC_MADRIGOSA: + case NPC_MADRIGOSA: case NPC_BRUTALLUS: case NPC_FELMYST: case NPC_ALYTHESS: @@ -74,6 +76,8 @@ void instance_sunwell_plateau::OnCreatureCreate(Creature* pCreature) case NPC_KILJAEDEN_CONTROLLER: case NPC_ANVEENA: case NPC_KALECGOS: + case NPC_LIADRIN: + case NPC_VELEN: m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); break; } @@ -167,6 +171,9 @@ void instance_sunwell_plateau::SetData(uint32 uiType, uint32 uiData) case DATA_SET_SPECTRAL_CHECK: m_uiSpectralRealmTimer = uiData; break; + case TYPE_KILJAEDEN_PHASE: + m_uiKiljaedenPhase = uiData; + break; } if (uiData == DONE) @@ -184,7 +191,7 @@ void instance_sunwell_plateau::SetData(uint32 uiType, uint32 uiData) } } -void instance_sunwell_plateau::SetData64(uint32 uiType, uint64 uiData) +void instance_sunwell_plateau::SetGuid(uint32 uiType, ObjectGuid uiData) { if (uiType == DATA_PLAYER_SPECTRAL_REALM) m_lSpectralRealmList.push_back(ObjectGuid(uiData)); @@ -192,10 +199,20 @@ void instance_sunwell_plateau::SetData64(uint32 uiType, uint64 uiData) uint32 instance_sunwell_plateau::GetData(uint32 uiType) { - if (uiType < MAX_ENCOUNTER) - return m_auiEncounter[uiType]; - - return 0; + switch (uiType) + { + case TYPE_KALECGOS: + case TYPE_BRUTALLUS: + case TYPE_FELMYST: + case TYPE_EREDAR_TWINS: + case TYPE_MURU: + case TYPE_KILJAEDEN: + return m_auiEncounter[uiType]; + case TYPE_KILJAEDEN_PHASE: + return m_uiKiljaedenPhase; + default: + return 0; + } } void instance_sunwell_plateau::DoEjectSpectralRealmPlayers() @@ -212,8 +229,7 @@ void instance_sunwell_plateau::DoEjectSpectralRealmPlayers() if (pPlayer && !pPlayer->HasAura(SPELL_SPECTRAL_REALM)) { m_lSpectralRealmList.remove(pPlayer->GetObjectGuid()); - pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_EXHAUSTION, true); - pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_NORMAL_REALM, true); + pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_REALM_RETURN, true); } } } diff --git a/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h b/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h index 3297fc2c45..c7ebc332ce 100644 --- a/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h +++ b/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h @@ -35,7 +35,9 @@ enum NPC_KILJAEDEN_CONTROLLER = 25608, // kiljaeden event controller NPC_ANVEENA = 26046, // related to kiljaeden event NPC_KALECGOS = 25319, // related to kiljaeden event - NPC_MADRIGOSA = 25160, // Alive and flying one + NPC_LIADRIN = 26247, // related to kiljaeden event + NPC_VELEN = 26246, // related to kiljaeden event + NPC_MADRIGOSA = 25160, // Alive and flying one GO_FORCEFIELD = 188421, // kalecgos door + collisions GO_BOSS_COLLISION_1 = 188523, @@ -53,6 +55,8 @@ enum AREATRIGGER_TWINS = 4937, // spells related to kalecgos event + SPELL_SPECTRAL_REALM_GO = 44811, + SPELL_SPECTRAL_REALM_RETURN = 44845, SPELL_SPECTRAL_REALM = 46021, SPELL_TELEPORT_NORMAL_REALM = 46020, SPELL_SPECTRAL_EXHAUSTION = 44867, @@ -75,7 +79,7 @@ class MANGOS_DLL_DECL instance_sunwell_plateau : public ScriptedInstance void OnCreatureCreate(Creature* pCreature); void SetData(uint32 uiType, uint32 uiData); - void SetData64(uint32 uiType, uint64 uiData); + void SetGuid(uint32 uiType, ObjectGuid uiData); uint32 GetData(uint32 uiType); void Update(uint32 uiDiff); @@ -90,6 +94,7 @@ class MANGOS_DLL_DECL instance_sunwell_plateau : public ScriptedInstance std::string m_strInstData; // Misc + uint32 m_uiKiljaedenPhase; uint32 m_uiSpectralRealmTimer; GUIDList m_lSpectralRealmList; }; diff --git a/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp b/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp index a7a39fc9a8..617e1e40b8 100644 --- a/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp +++ b/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp @@ -135,6 +135,27 @@ void instance_uldaman::SetData(uint32 uiType, uint32 uiData) } } +void instance_uldaman::SetGuid(uint32 uiData, ObjectGuid uiGuid) +{ + switch(uiData) + + { + case DATA_EVENT_STARTER: + m_playerGuid = uiGuid; + break; + } +} + +ObjectGuid instance_uldaman::GetGuid(uint32 uiData) +{ + switch(uiData) + { + case DATA_EVENT_STARTER: + return m_playerGuid; + } + return ObjectGuid(); +} + void instance_uldaman::Load(const char* chrIn) { if (!chrIn) @@ -157,16 +178,6 @@ void instance_uldaman::Load(const char* chrIn) OUT_LOAD_INST_DATA_COMPLETE; } -void instance_uldaman::SetData64(uint32 uiData, uint64 uiGuid) -{ - switch(uiData) - { - case DATA_EVENT_STARTER: - m_playerGuid = ObjectGuid(uiGuid); - break; - } -} - uint32 instance_uldaman::GetData(uint32 uiType) { switch(uiType) @@ -177,16 +188,6 @@ uint32 instance_uldaman::GetData(uint32 uiType) return 0; } -uint64 instance_uldaman::GetData64(uint32 uiData) -{ - switch(uiData) - { - case DATA_EVENT_STARTER: - return m_playerGuid.GetRawValue(); - } - return 0; -} - void instance_uldaman::StartEvent(uint32 uiEventId, Player* pPlayer) { m_playerGuid = pPlayer->GetObjectGuid(); diff --git a/scripts/eastern_kingdoms/uldaman/uldaman.h b/scripts/eastern_kingdoms/uldaman/uldaman.h index c7977851b1..1f78c0e73d 100644 --- a/scripts/eastern_kingdoms/uldaman/uldaman.h +++ b/scripts/eastern_kingdoms/uldaman/uldaman.h @@ -47,9 +47,9 @@ class MANGOS_DLL_DECL instance_uldaman : public ScriptedInstance void Update(uint32 uiDiff); void SetData(uint32 uiType, uint32 uiData); - void SetData64(uint32 uiData, uint64 uiGuid); uint32 GetData(uint32 uiType); - uint64 GetData64(uint32 uiData); + void SetGuid(uint32 uiData, ObjectGuid uiGuid); + ObjectGuid GetGuid(uint32 uiData); void StartEvent(uint32 uiEventId, Player* pPlayer); diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp index b873ba0457..f576eedc38 100644 --- a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp @@ -704,7 +704,7 @@ struct MANGOS_DLL_DECL npc_arthasAI : public npc_escortAI break; case 5: m_pInstance->SetData(TYPE_PHASE, 4); - if (Creature* pMeathook = m_creature->SummonCreature(NPC_MEATHOOK,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000)) + if (Creature* pMeathook = m_creature->SummonCreature(NPC_MEATHOOK, 2224.0225f, 1332.0918f, 127.328f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000)) { DoScriptText(SAY_MEATHOOK_SPAWN, pMeathook); } diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp index 125a68ce6a..96cf5f87a9 100644 --- a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp @@ -1007,13 +1007,13 @@ struct MANGOS_DLL_DECL npc_time_riftCSAI : public ScriptedAI switch(Step) { case 1: - if (Creature* pArthas = m_pInstance->GetSingleCreatureFromStorage(NPC_ARTHAS)) + if (Creature* pArthas = m_pInstance->GetSingleCreatureFromStorage(NPC_ARTHAS)) { - Drakonian01 = m_creature->SummonCreature(NPC_INFINITE_ADVERSARY,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + Drakonian01 = m_creature->SummonCreature(NPC_INFINITE_ADVERSARY,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); Drakonian01->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); - Drakonian02 = m_creature->SummonCreature(NPC_INFINITE_HUNTER,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + Drakonian02 = m_creature->SummonCreature(NPC_INFINITE_HUNTER,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); Drakonian02->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); - Drakonian03 = m_creature->SummonCreature(NPC_INFINITE_AGENT,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + Drakonian03 = m_creature->SummonCreature(NPC_INFINITE_AGENT,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000); Drakonian03->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); } m_uiStepTimer = 3000; diff --git a/scripts/kalimdor/darkshore.cpp b/scripts/kalimdor/darkshore.cpp index ca6a33d095..8ca01285a8 100644 --- a/scripts/kalimdor/darkshore.cpp +++ b/scripts/kalimdor/darkshore.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Darkshore SD%Complete: 100 -SDComment: Quest support: 731, 2078, 5321 +SDComment: Quest support: 731, 2078, 2118, 5321 SDCategory: Darkshore EndScriptData */ @@ -25,6 +25,8 @@ EndScriptData */ npc_kerlonian npc_prospector_remtravel npc_threshwackonator +npc_captured_rabid_thistle_bear +npc_rabid_thistle_bear EndContentData */ #include "precompiled.h" @@ -380,6 +382,101 @@ bool GossipSelect_npc_threshwackonator(Player* pPlayer, Creature* pCreature, uin return true; } +/*##### +# npc_captured_rabid_thistle_bear +#####*/ + +enum +{ + QUEST_PLAGUED_LANDS = 2118, + NPC_THANARIUM_TREETENDER = 3701, + NPC_CAPTURED_RABID_THISTLE_BEAR = 11836, + OBJECT_BEARTRAP = 111148 +}; + +struct MANGOS_DLL_DECL npc_captured_rabid_thistle_bearAI : public FollowerAI +{ + npc_captured_rabid_thistle_bearAI(Creature* pCreature) : FollowerAI(pCreature) + { + Reset(); + } + + void Reset() + { + } + + void MoveInLineOfSight(Unit* pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_THANARIUM_TREETENDER) + { + if (m_creature->IsWithinDistInMap(pWho, 5.0f)) + { + DoAtEnd(); + } + } + } + + void DoAtEnd() + { + if (Player* pHolder = GetLeaderForFollower()) + { + pHolder->KilledMonsterCredit(NPC_CAPTURED_RABID_THISTLE_BEAR); + SetFollowComplete(); + } + } +}; + +CreatureAI* GetAI_npc_captured_rabid_thistle_bear(Creature* pCreature) +{ + return new npc_captured_rabid_thistle_bearAI(pCreature); +} + +/*##### +# npc_rabid_thistle_bear +#####*/ + +struct MANGOS_DLL_DECL npc_rabid_thistle_bearAI : public ScriptedAI +{ + npc_rabid_thistle_bearAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + void Reset() + { + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (GameObject* pGoTemp = GetClosestGameObjectWithEntry(m_creature, OBJECT_BEARTRAP, 3.0f)) + { + if (m_creature->getVictim()->GetTypeId() == TYPEID_PLAYER) + { + Creature *pCapturedBear = m_creature->SummonCreature(NPC_CAPTURED_RABID_THISTLE_BEAR, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetAngle(m_creature->getVictim()), TEMPSUMMON_CORPSE_DESPAWN, 24000); + + if (npc_captured_rabid_thistle_bearAI* pCapturedBearAI = dynamic_cast(pCapturedBear->AI())) + { + pCapturedBearAI->StartFollow((Player*)m_creature->getVictim(), FACTION_ESCORT_N_FRIEND_PASSIVE, 0); + pCapturedBear->SetSpeedRate(MOVE_WALK, 2.0f); + m_creature->ForcedDespawn(); + } + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_rabid_thistle_bear(Creature* pCreature) +{ + return new npc_rabid_thistle_bearAI(pCreature); +} + void AddSC_darkshore() { Script* pNewScript; @@ -402,4 +499,14 @@ void AddSC_darkshore() pNewScript->pGossipHello = &GossipHello_npc_threshwackonator; pNewScript->pGossipSelect = &GossipSelect_npc_threshwackonator; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_captured_rabid_thistle_bear"; + pNewScript->GetAI = &GetAI_npc_captured_rabid_thistle_bear; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_rabid_thistle_bear"; + pNewScript->GetAI = &GetAI_npc_rabid_thistle_bear; + pNewScript->RegisterSelf(); } diff --git a/scripts/kalimdor/durotar.cpp b/scripts/kalimdor/durotar.cpp new file mode 100644 index 0000000000..69e5fccff7 --- /dev/null +++ b/scripts/kalimdor/durotar.cpp @@ -0,0 +1,187 @@ +/* ScriptData +SDName: Durotar +SD%Complete: +SDComment: Support for quest 11409 +SDCategory: Durotar +EndScriptData */ + +/* ContentData +npc_ram_master_ray Brewfest event +npc_bok_ropcertain Brewfest event +npc_driz_tumblequick Brewfest event +EndContentData */ + +#include "precompiled.h" + +/*##### +# Ram Master Ray +#####*/ + +enum +{ + QUEST_BARK_FOR_DROHN = 11407, + QUEST_BARK_FOR_TCHALI = 11408, + QUEST_NOW_RAM_RACING_H = 11409, + QUEST_BACK_AGAIN_H = 11412, + + SPELL_RENTAL_RAM = 43883, + SPELL_RAM_FATIGUE = 43052, + SPELL_SPEED_RAM_GALLOP = 42994, + SPELL_SPEED_RAM_CANTER = 42993, + SPELL_SPEED_RAM_TROT = 42992, + SPELL_SPEED_RAM_NORMAL = 43310, + SPELL_SPEED_RAM_EXHAUSED = 43332, + SPELL_RENTAL_RAM_DND = 42146 +}; + +bool QuestAccept_npc_ram_master_ray(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + switch(pQuest->GetQuestId()) + { + case QUEST_BARK_FOR_DROHN: + case QUEST_BARK_FOR_TCHALI: + case QUEST_NOW_RAM_RACING_H: + case QUEST_BACK_AGAIN_H: + pPlayer->CastSpell(pPlayer, SPELL_RENTAL_RAM, false); + + break; + } + return true; +} + +bool QuestRewarded_npc_ram_master_ray(Player* pPlayer, Creature* pCreature, const Quest* pQuest) +{ + if (pPlayer->HasAura(SPELL_RENTAL_RAM)) + { + pPlayer->RemoveAurasDueToSpell(SPELL_RENTAL_RAM); + pPlayer->RemoveAurasDueToSpell(SPELL_RAM_FATIGUE); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_GALLOP); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_CANTER); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_TROT); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_NORMAL); + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_EXHAUSED); + pPlayer->RemoveAurasDueToSpell(SPELL_RENTAL_RAM_DND); + } + return true; +} + +/*##### +# Bok Dropcertain +#####*/ +enum +{ + ITEM_PORTABLE_KEG = 33797 +}; + +struct MANGOS_DLL_DECL npc_bok_dropcertain : public ScriptedAI +{ + npc_bok_dropcertain (Creature* pCreature) : ScriptedAI (pCreature) + { + m_pMap = pCreature->GetMap(); + Reset(); + } + + Map* m_pMap; + + void Reset () {} + + void MoveInLineOfSight (Unit* pWho) + { + // player should be near the npc + if (m_creature->GetDistance(pWho) > 10.0f) + return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + Player* pPlayer = m_pMap->GetPlayer(pWho->GetObjectGuid()); + if (!pPlayer) + return; + if (pPlayer->GetQuestStatus(QUEST_BACK_AGAIN_H) == QUEST_STATUS_INCOMPLETE) + { + // player can only have 1 keg + if (pPlayer->HasItemCount(ITEM_PORTABLE_KEG, 1)) + return; + + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_PORTABLE_KEG, 1, NULL); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, ITEM_PORTABLE_KEG, 1, true); + pPlayer->GetItemByEntry(ITEM_PORTABLE_KEG)->SendCreateUpdateToPlayer(pPlayer); + } + } + } +}; + +CreatureAI* GetAI_npc_bok_dropcertain(Creature* pCreature) +{ + return new npc_bok_dropcertain(pCreature); +} + +/*##### +# Driz Tumberquick +#####*/ +enum +{ + NPC_CREDIT_CREATURE = 24337, +}; + +struct MANGOS_DLL_DECL npc_driz_tumblequick : public ScriptedAI +{ + npc_driz_tumblequick (Creature* pCreature) : ScriptedAI (pCreature) + { + m_pMap = pCreature->GetMap(); + Reset(); + } + + Map* m_pMap; + + void Reset () {} + + void MoveInLineOfSight (Unit* pWho) + { + // player should be near the npc + if (m_creature->GetDistance(pWho) > 10.0f) + return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + Player* pPlayer = m_pMap->GetPlayer(pWho->GetObjectGuid()); + if (!pPlayer) + return; + if (pPlayer->GetQuestStatus(QUEST_BACK_AGAIN_H) == QUEST_STATUS_INCOMPLETE) + { + // player can only have 1 keg + if (pPlayer->HasItemCount(ITEM_PORTABLE_KEG, 1)) + { + pPlayer->DestroyItemCount(ITEM_PORTABLE_KEG, 1, true); + pPlayer->KilledMonsterCredit(NPC_CREDIT_CREATURE); + } + } + } +}; + +CreatureAI* GetAI_npc_driz_tumblequick(Creature* pCreature) +{ + return new npc_driz_tumblequick(pCreature); +} +void AddSC_durotar() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_ram_master_ray"; + newscript->pQuestAcceptNPC = &QuestAccept_npc_ram_master_ray; + newscript->pQuestRewardedNPC = &QuestRewarded_npc_ram_master_ray; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bok_dropcertain"; + newscript->GetAI = &GetAI_npc_bok_dropcertain; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_driz_tumblequick"; + newscript->GetAI = &GetAI_npc_driz_tumblequick; + newscript->RegisterSelf(); +} diff --git a/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp b/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp index a7341340ed..7ffae41770 100644 --- a/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp +++ b/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp @@ -63,9 +63,9 @@ enum //SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays SPELL_BELLOWINGROAR = 18431, - SPELL_HEATED_GROUND = 22191, // TODO + SPELL_HEATED_GROUND = 22191, // seem to works, but need a visual effect - SPELL_SUMMONWHELP = 17646, // TODO this spell is only a summon spell, but would need a spell to activate the eggs + SPELL_SUMMONWHELP = 17646, SPELL_SUMMON_LAIR_GUARD = 68968, MAX_WHELPS_PER_PACK = 40, @@ -177,8 +177,8 @@ struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI void JustReachedHome() { // in case evade in phase 2, see comments for hack where phase 2 is set - m_creature->SetLevitate(false); - m_creature->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + m_creature->SetHover(false); if (m_pInstance) m_pInstance->SetData(TYPE_ONYXIA, FAIL); @@ -269,14 +269,28 @@ struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI switch (m_uiPhase) { - case PHASE_END: // Here is room for additional summoned whelps and Erruption + case PHASE_END: if (m_uiBellowingRoarTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_BELLOWINGROAR) == CAST_OK) + { + // seem to trigger correctly the Eruption spell, but without any visual effect + DoCast(m_creature, SPELL_HEATED_GROUND); m_uiBellowingRoarTimer = 30000; + } } else m_uiBellowingRoarTimer -= uiDiff; + + if (m_uiWhelpTimer < uiDiff) // sometimes spawn an additional whelp + { + uint8 uiSpawnLoc = urand (0,1); + m_creature->SummonCreature(NPC_ONYXIA_WHELP, afSpawnLocations[uiSpawnLoc][0], afSpawnLocations[uiSpawnLoc][1], afSpawnLocations[uiSpawnLoc][2], 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, MINUTE*IN_MILLISECONDS); + m_uiWhelpTimer = urand(40000, 45000); + } + else + m_uiWhelpTimer -=uiDiff; + // no break, phase 3 will use same abilities as in 1 case PHASE_START: { @@ -321,9 +335,10 @@ struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI DoScriptText(SAY_PHASE_2_TRANS, m_creature); - // sort of a hack, it is unclear how this really work but the values appear to be valid - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); - m_creature->SetLevitate(true); + // flying method borrowed from Sapphiron + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + DoCastSpellIfCan(m_creature, 11010); + m_creature->SetHover(true); if (m_pPointData) m_creature->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); @@ -344,9 +359,14 @@ struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI m_uiPhase = PHASE_END; DoScriptText(SAY_PHASE_3_TRANS, m_creature); - // undo flying - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); - m_creature->SetLevitate(false); + // flying method borrowed from Sapphiron + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + m_creature->SetHover(false); + + m_uiWhelpTimer = urand(40000, 45000); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ONYXIA, DATA_LAND); SetCombatMovement(true); m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); diff --git a/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp b/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp index 6772476b59..dbdfdcf438 100644 --- a/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp +++ b/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp @@ -25,7 +25,8 @@ EndScriptData */ #include "onyxias_lair.h" instance_onyxias_lair::instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap), - m_uiAchievWhelpsCount(0) + m_uiAchievWhelpsCount(0), + m_bPlayerToasted(0) { Initialize(); } @@ -61,14 +62,20 @@ void instance_onyxias_lair::SetData(uint32 uiType, uint32 uiData) return; m_uiEncounter = uiData; - if (uiData == IN_PROGRESS) + switch (uiData) { - DoStartTimedAchievement(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEV_START_ONYXIA_ID); - m_uiAchievWhelpsCount = 0; + case IN_PROGRESS: + DoStartTimedAchievement(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEV_START_ONYXIA_ID); + m_uiAchievWhelpsCount = 0; + m_bPlayerToasted = false; + break; + case DATA_LIFTOFF: + m_tPhaseTwoStart = time(NULL); + break; + case DATA_PLAYER_TOASTED: + m_bPlayerToasted = true; + break; } - if (uiData == DATA_LIFTOFF) - m_tPhaseTwoStart = time(NULL); - // Currently no reason to save anything } @@ -81,7 +88,7 @@ bool instance_onyxias_lair::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Pl return m_uiAchievWhelpsCount >= ACHIEV_CRIT_REQ_MANY_WHELPS; case ACHIEV_CRIT_NO_BREATH_N: case ACHIEV_CRIT_NO_BREATH_H: - return m_uiEncounter != DATA_PLAYER_TOASTED; + return !m_bPlayerToasted; default: return false; } diff --git a/scripts/kalimdor/onyxias_lair/onyxias_lair.h b/scripts/kalimdor/onyxias_lair/onyxias_lair.h index 4ecbd7c914..3ead7c86b4 100644 --- a/scripts/kalimdor/onyxias_lair/onyxias_lair.h +++ b/scripts/kalimdor/onyxias_lair/onyxias_lair.h @@ -12,6 +12,7 @@ enum // Special data fields for Onyxia DATA_LIFTOFF = 4, DATA_PLAYER_TOASTED = 5, + DATA_LAND = 6, NPC_ONYXIA_WHELP = 11262, NPC_ONYXIA_TRIGGER = 12758, @@ -45,6 +46,7 @@ class MANGOS_DLL_DECL instance_onyxias_lair : public ScriptedInstance bool CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/); protected: + bool m_bPlayerToasted; uint32 m_uiEncounter; uint32 m_uiAchievWhelpsCount; diff --git a/scripts/northrend/azjol-nerub/ahnkahet/boss_taldaram.cpp b/scripts/northrend/azjol-nerub/ahnkahet/boss_taldaram.cpp index 3e9ad4e62a..6255a72fc4 100644 --- a/scripts/northrend/azjol-nerub/ahnkahet/boss_taldaram.cpp +++ b/scripts/northrend/azjol-nerub/ahnkahet/boss_taldaram.cpp @@ -17,8 +17,8 @@ /* ScriptData SDName: Boss_Taldaram -SD%Complete: 80% -SDAuthor: Tassadar +SD%Complete: 90% +SDAuthor: based on rsa's(tassadar), updated&fixed by orangevirus(kelthuzad) SDComment: Timers, maybe wrong orb behavior SDCategory: Ahn'kahet EndScriptData */ @@ -83,26 +83,41 @@ struct MANGOS_DLL_DECL boss_taldaramAI : public ScriptedAI instance_ahnkahet* m_pInstance; bool m_bIsRegularMode; - uint8 m_uiVanishPhase; - uint32 m_uiDamageTaken; - Unit* m_uEmbraceTarget; - uint32 m_uiBloodthirst_Timer; - uint32 m_uiSummonOrb_Timer; - uint32 m_uiVanish_Timer; - uint32 m_uiVanishPhase_Timer; - uint32 m_uiEmbrace_Timer; + bool isInVanish; + bool isInVampyrMode; + + uint32 summonFlameOrbTimer; + bool orbSummoned; + uint32 orbstartTimer; + uint32 vanishTimer; + uint32 bloodthirstTimer; + uint32 embraceOfTheVampyrTimer; + uint32 embraceOfTheVampyrInterruptDamage; + uint32 embraceOfTheVampyrInterruptMaxDamage; + uint32 embraceOfTheVampyrFinishedTimer; + uint32 healtVanish; + + Creature* pFlameOrb; + Creature* pFlameOrb2; + Creature* pFlameOrb3; void Reset() { - m_creature->SetRespawnDelay(DAY); - m_uiBloodthirst_Timer = 4000; - m_uiSummonOrb_Timer = 13000; - m_uiVanish_Timer = 17000; - m_uiVanishPhase_Timer = 0; - m_uiEmbrace_Timer = 0; - m_uiVanishPhase = 0; - m_uiDamageTaken = 0; + summonFlameOrbTimer = 12000; + vanishTimer = 14000; + bloodthirstTimer = 10000; + embraceOfTheVampyrFinishedTimer = 20000; + embraceOfTheVampyrInterruptMaxDamage = m_bIsRegularMode ? 20000 : 40000; + orbstartTimer = 500; + orbSummoned = false; + isInVanish = false; + isInVampyrMode = false; + pFlameOrb = NULL; + pFlameOrb2 = NULL; + pFlameOrb3 = NULL; + healtVanish=0; + if (m_pInstance) m_pInstance->SetData(TYPE_TALDARAM, NOT_STARTED); } @@ -111,7 +126,7 @@ struct MANGOS_DLL_DECL boss_taldaramAI : public ScriptedAI { DoScriptText(SAY_AGGRO, m_creature); m_creature->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL); - m_creature->SetLevitate(false); + if (m_pInstance) m_pInstance->SetData(TYPE_TALDARAM, IN_PROGRESS); } @@ -134,107 +149,113 @@ struct MANGOS_DLL_DECL boss_taldaramAI : public ScriptedAI m_pInstance->SetData(TYPE_TALDARAM, DONE); } - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if(m_creature->IsNonMeleeSpellCasted(false)) + // hack to prevent the orb damaging taldaram + if(pDoneBy->GetEntry() == NPC_FLAME_ORB) + uiDamage = 0; + + if (isInVampyrMode) { - m_uiDamageTaken += uiDamage; - uint32 m_uiMinDamage = m_bIsRegularMode ? 20000 : 40000; - if(m_uiDamageTaken >= m_uiMinDamage) + embraceOfTheVampyrInterruptDamage += uiDamage; + + if (embraceOfTheVampyrInterruptDamage > embraceOfTheVampyrInterruptMaxDamage) { - m_uiVanishPhase = 0; - m_creature->InterruptNonMeleeSpells(false); + m_creature->InterruptNonMeleeSpells(false); + isInVampyrMode = false; + embraceOfTheVampyrInterruptDamage = 0; } } } - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (!m_pInstance) return; - if(m_uiVanishPhase != 0) + void MoveInLineOfSight(Unit* pWho) + { + if (m_pInstance) { - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if(m_uiVanishPhase_Timer <= uiDiff) + if (pWho->IsWithinDist(m_creature, 10.0f, true)) { - m_creature->InterruptNonMeleeSpells(false); - m_uiVanishPhase = 0; - }else m_uiVanishPhase_Timer -= uiDiff; + if (m_creature->isAlive()) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + } + AttackStart(pWho); + } + } + } + } - if(m_uiVanishPhase != 1) - return; + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - // Embrace of the Vampyr - if(m_uiEmbrace_Timer <= uiDiff) + if (!isInVanish && !isInVampyrMode) + // Summon Flame Orb + if(summonFlameOrbTimer <= uiDiff) { - switch(urand(0, 1)) + for(int i = 0; i < 3; ++i) { - case 0: DoScriptText(SAY_FEED_1, m_creature); break; - case 1: DoScriptText(SAY_FEED_2, m_creature); break; + m_creature->SummonCreature(NPC_FLAME_ORB, m_creature->GetPositionX(), m_creature->GetPositionY(), FLAME_ORB_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if(m_bIsRegularMode) + break; } - m_creature->SetVisibility(VISIBILITY_ON); - if(m_uEmbraceTarget && m_uEmbraceTarget->isAlive()) - DoCast(m_uEmbraceTarget, m_bIsRegularMode ? SPELL_EMBRACE_OF_THE_VAMPYR : SPELL_EMBRACE_OF_THE_VAMPYR_H); - m_uiDamageTaken = 0; - m_uiVanishPhase = 2; - }else m_uiEmbrace_Timer -= uiDiff; - return; - } + DoCast(m_creature, SPELL_CONJURE_FLAME_ORB); + vanishTimer += 10000; + summonFlameOrbTimer = 16000 + rand()%10000; + }else summonFlameOrbTimer -= uiDiff; - // Bloodthirst - if(m_uiBloodthirst_Timer <= uiDiff) - { - DoCast(m_creature->getVictim(), SPELL_BLOODTHIRST); - m_uiBloodthirst_Timer = 8000 + rand()%6000; - }else m_uiBloodthirst_Timer -= uiDiff; - // Summon Flame Orb - if(m_uiSummonOrb_Timer <= uiDiff) - { - for(int i = 0; i <= 3; ++i) + if (!isInVampyrMode) + if(vanishTimer < uiDiff) { - m_creature->SummonCreature(NPC_FLAME_ORB, m_creature->GetPositionX(), m_creature->GetPositionY(), FLAME_ORB_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if(m_bIsRegularMode) - break; - } - DoCast(m_creature, SPELL_CONJURE_FLAME_ORB); - m_uiSummonOrb_Timer = 16000 + rand()%10000; - m_uiVanish_Timer = 16000; - }else m_uiSummonOrb_Timer -= uiDiff; - - // Vanish - if(m_uiVanish_Timer <= uiDiff) + healtVanish=m_creature->GetHealth(); + m_creature->CastSpell(m_creature,SPELL_VANISH,true); + isInVanish = true; + embraceOfTheVampyrTimer = 2400; + vanishTimer = 200000; + }else vanishTimer -= uiDiff; + + if (isInVanish) { - switch(urand(0, 1)) + if (embraceOfTheVampyrTimer < uiDiff) { - case 0: DoScriptText(SAY_VANISH_1, m_creature); break; - case 1: DoScriptText(SAY_VANISH_2, m_creature); break; - } + Player* pPlayer; - //DoCast(m_creature, SPELL_VANISH); We dont want to drop aggro - m_uiVanishPhase = 1; - bool stop = false; - while(!stop) - { - m_uEmbraceTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); - if(m_uEmbraceTarget && m_uEmbraceTarget->isAlive() && m_uEmbraceTarget->GetTypeId() == TYPEID_PLAYER) - stop = true; - else - continue; - - m_creature->GetMotionMaster()->MoveChase(m_uEmbraceTarget); - break; - } + // get player enemy + do + { + pPlayer = (Player*) m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + } + while (!pPlayer); + + m_creature->NearTeleportTo(pPlayer->GetPositionX() + 3.0f, pPlayer->GetPositionY() + 3.0f, pPlayer->GetPositionZ(), pPlayer->GetOrientation()); + m_creature->RemoveAurasDueToSpell(SPELL_VANISH); + m_creature->SetHealth(healtVanish); + DoCastSpellIfCan(pPlayer, m_bIsRegularMode ? SPELL_EMBRACE_OF_THE_VAMPYR : SPELL_EMBRACE_OF_THE_VAMPYR_H); + isInVampyrMode = true; + summonFlameOrbTimer += 20000; + isInVanish = false; + vanishTimer = 25000; + }else embraceOfTheVampyrTimer -= uiDiff; + } - m_creature->SetVisibility(VISIBILITY_OFF); - m_uiVanish_Timer = 10000 + rand()%10000; - m_uiEmbrace_Timer = 3500; - m_uiVanishPhase_Timer = 22500; - return; - }else m_uiVanish_Timer -= uiDiff; + // set VampyrMode false when Spell not stopped by damage + if(isInVampyrMode) + if(embraceOfTheVampyrFinishedTimer < uiDiff) + { + isInVampyrMode = false; + embraceOfTheVampyrFinishedTimer = 20000; + } else embraceOfTheVampyrFinishedTimer -= uiDiff; + + if(!isInVampyrMode && !isInVanish) + if (bloodthirstTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_BLOODTHIRST); + bloodthirstTimer = m_bIsRegularMode ? 15000 : 8000; + }else bloodthirstTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -272,6 +293,8 @@ struct MANGOS_DLL_DECL mob_flame_orbAI : public ScriptedAI m_uiCast_Timer = 3000; direction = -1; m_bIsFlying = false; + m_creature->SetDisplayId(10045); //hack to set model invisible + m_creature->SetLevitate(true); DoCast(m_creature, SPELL_FLAME_ORB_VISUAL); DoCast(m_creature, SPELL_FLAME_ORB_SPAWN_EFFECT); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -297,7 +320,7 @@ struct MANGOS_DLL_DECL mob_flame_orbAI : public ScriptedAI return; DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_ORB : SPELL_FLAME_ORB_H); - direction = rand()%4; + direction = urand(0,3); switch(direction) { case 0: // Up @@ -315,10 +338,8 @@ struct MANGOS_DLL_DECL mob_flame_orbAI : public ScriptedAI default: m_creature->GetMotionMaster()->MovePoint(0, FLAME_ORB_UP_X, FLAME_ORB_UP_Y, FLAME_ORB_Z); break; - } m_bIsFlying = true; - m_creature->SetLevitate(true); }else m_uiCast_Timer -= uiDiff; } }; diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp index df28ca180d..9f22f954cc 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2006 - 2011 ScriptDev2 - * This program is free software; you can redistribute it and/or modify +* 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. @@ -26,8 +26,8 @@ EndScriptData */ enum { + // Spells SPELL_BERSERK = 47008, - // Yells // Eadric SPELL_VENGEANCE = 66889, @@ -54,37 +54,38 @@ enum SPELL_OLD_WOUNDS_H = 67679, }; -// Eadric The Pure struct MANGOS_DLL_DECL boss_eadricAI : public ScriptedAI { boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Vengeance_Timer; - uint32 Radiance_Timer; - uint32 Hammer_Timer; - uint32 Hammer_Dmg_Timer; - uint32 m_uiBerserk_Timer; - ObjectGuid HammerTarget; + uint32 m_uiVengeanceTimer; + uint32 m_uiRadianceTimer; + uint32 m_uiHammerTimer; + uint32 m_uiHammerDamagTimer; + uint32 m_uiBerserkTimer; + ObjectGuid m_pHammerTargetGuid; void Reset() { m_creature->SetRespawnDelay(DAY); - Vengeance_Timer = 1000; - Radiance_Timer = m_bIsRegularMode ? 15000 : 8000; - Hammer_Timer = m_bIsRegularMode ? 40000 : 10000; - Hammer_Dmg_Timer = m_bIsRegularMode ? 45000 : 20000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - HammerTarget.Clear(); m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_uiVengeanceTimer = 1*IN_MILLISECONDS; + m_uiRadianceTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 8*IN_MILLISECONDS; + m_uiHammerTimer = m_bIsRegularMode ? 40*IN_MILLISECONDS : 10*IN_MILLISECONDS; + m_uiHammerDamagTimer = m_bIsRegularMode ? 45*IN_MILLISECONDS : 20*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; + m_pHammerTargetGuid.Clear(); } void Aggro(Unit* pWho) @@ -104,56 +105,55 @@ struct MANGOS_DLL_DECL boss_eadricAI : public ScriptedAI m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, DONE); } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Vengeance_Timer < diff) + if (m_uiVengeanceTimer < uiDiff) { DoCast(m_creature, SPELL_VENGEANCE); - Vengeance_Timer = m_bIsRegularMode ? 12000 : 8000; + m_uiVengeanceTimer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 8*IN_MILLISECONDS; } else - Vengeance_Timer -= diff; + m_uiVengeanceTimer -= uiDiff; - if (Radiance_Timer < diff) + if (m_uiRadianceTimer < uiDiff) { DoCast(m_creature, m_bIsRegularMode ? SPELL_RADIANCE : SPELL_RADIANCE_H); - Radiance_Timer = m_bIsRegularMode ? 20000 : 12000; + m_uiRadianceTimer = m_bIsRegularMode ? 20*IN_MILLISECONDS : 12*IN_MILLISECONDS; } else - Radiance_Timer -= diff; + m_uiRadianceTimer -= uiDiff; - if (Hammer_Timer < diff) + if (m_uiHammerTimer < uiDiff) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - DoCast(target, SPELL_HAMMER_OF_JUSTICE); - HammerTarget = target->GetObjectGuid(); + DoCast(pTarget, SPELL_HAMMER_OF_JUSTICE); + m_pHammerTargetGuid = pTarget->GetObjectGuid(); } - Hammer_Timer = m_bIsRegularMode ? 40000 : 15000; + m_uiHammerTimer = m_bIsRegularMode ? 40*IN_MILLISECONDS : 15*IN_MILLISECONDS; } else - Hammer_Timer -= diff; + m_uiHammerTimer -= uiDiff; - if (Hammer_Dmg_Timer < diff) + if (m_uiHammerDamagTimer < uiDiff) { - if (Unit* pHammerTarget = m_creature->GetMap()->GetUnit(HammerTarget)) + if (Unit* pHammerTarget = m_creature->GetMap()->GetUnit(m_pHammerTargetGuid)) DoCast(pHammerTarget, SPELL_HAMMER); - - Hammer_Dmg_Timer = m_bIsRegularMode ? 50000 : 15000; + m_uiHammerDamagTimer = m_bIsRegularMode ? 50*IN_MILLISECONDS : 15*IN_MILLISECONDS; } else - Hammer_Dmg_Timer -= diff; + m_uiHammerDamagTimer -= uiDiff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -164,50 +164,51 @@ CreatureAI* GetAI_boss_eadric(Creature* pCreature) return new boss_eadricAI(pCreature); } -// Argent Confessor Paletress struct MANGOS_DLL_DECL boss_paletressAI : public ScriptedAI { boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Smite_Timer; - uint32 Holy_Fire_Timer; - uint32 Renew_Timer; - uint32 Shield_Delay; - uint32 Shield_Check; - uint32 m_uiBerserk_Timer; - bool summoned; - bool shielded; + bool m_bIsSummoned; + bool m_bIsShielded; + uint32 m_uiSmiteTimer; + uint32 m_uiHolyFireTimer; + uint32 m_uiRenewTimer; + uint32 m_uiShieldDelay; + uint32 m_uiShieldCheck; + uint32 m_uiBerserkTimer; void Reset() { m_creature->SetRespawnDelay(DAY); m_creature->RemoveAurasDueToSpell(SPELL_SHIELD); - Smite_Timer = 5000; - Holy_Fire_Timer = m_bIsRegularMode ? 10000 : 8000; - Renew_Timer = m_bIsRegularMode ? 7000 : 5000; - Shield_Delay = 0; - Shield_Check = 1000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - summoned = false; - shielded = false; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_bIsSummoned = false; + m_bIsShielded = false; + m_uiSmiteTimer = 5*IN_MILLISECONDS; + m_uiHolyFireTimer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 8*IN_MILLISECONDS; + m_uiRenewTimer = m_bIsRegularMode ? 7*IN_MILLISECONDS : 5*IN_MILLISECONDS; + m_uiShieldDelay = 0; + m_uiShieldCheck = 1*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } - void JustSummoned(Creature* _summoned) + void JustSummoned(Creature* pSummoned) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) - _summoned->AddThreat(target); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + pSummoned->AddThreat(pTarget); - summoned = true; + m_bIsSummoned = true; } void Aggro(Unit* pWho) @@ -227,57 +228,58 @@ struct MANGOS_DLL_DECL boss_paletressAI : public ScriptedAI m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, DONE); } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Smite_Timer < diff) + if (m_uiSmiteTimer < uiDiff) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) DoCast(target, m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); - - Smite_Timer = 2000; + m_uiSmiteTimer = 2*IN_MILLISECONDS; } else - Smite_Timer -= diff; + m_uiSmiteTimer -= uiDiff; - if (Holy_Fire_Timer < diff) + if (m_uiHolyFireTimer < uiDiff) { m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) DoCast(target, m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); - - Holy_Fire_Timer = m_bIsRegularMode ? 10000 : 7000; + m_uiHolyFireTimer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 7*IN_MILLISECONDS; } else - Holy_Fire_Timer -= diff; + m_uiHolyFireTimer -= uiDiff; - if (Renew_Timer < diff) + if (m_uiRenewTimer < uiDiff) { m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); m_creature->CastStop(m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); switch(urand(0, 1)) { case 0: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_MEMORY)) + { + uint32 uiMemoryId = m_pInstance->GetData(DATA_MEMORY); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiMemoryId)) { if (pTemp->isAlive()) DoCast(pTemp, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); else DoCast(m_creature, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); } - break; + break; + } case 1: DoCast(m_creature, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); break; } - Renew_Timer = 25000; + m_uiRenewTimer = 25*IN_MILLISECONDS; } else - Renew_Timer -= diff; + m_uiRenewTimer -= uiDiff; - if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 35 ) && !summoned) + if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 35 ) && !m_bIsSummoned ) { m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); m_creature->CastStop(m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); @@ -300,102 +302,103 @@ struct MANGOS_DLL_DECL boss_paletressAI : public ScriptedAI m_creature->SummonCreature(MEMORY_ECK, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); break; case 5: - m_creature->SummonCreature(MEMORY_ENTROPIUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_ENTROPIUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 6: - m_creature->SummonCreature(MEMORY_GRUUL, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_GRUUL, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 7: - m_creature->SummonCreature(MEMORY_HAKKAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_HAKKAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 8: - m_creature->SummonCreature(MEMORY_HEIGAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_HEIGAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 9: - m_creature->SummonCreature(MEMORY_HEROD, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_HEROD, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 10: - m_creature->SummonCreature(MEMORY_HOGGER, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_HOGGER, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 11: - m_creature->SummonCreature(MEMORY_IGNIS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_IGNIS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 12: - m_creature->SummonCreature(MEMORY_ILLIDAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_ILLIDAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 13: - m_creature->SummonCreature(MEMORY_INGVAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_INGVAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 14: - m_creature->SummonCreature(MEMORY_KALITHRESH, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_KALITHRESH, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 15: - m_creature->SummonCreature(MEMORY_LUCIFRON, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_LUCIFRON, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 16: - m_creature->SummonCreature(MEMORY_MALCHEZAAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_MALCHEZAAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 17: - m_creature->SummonCreature(MEMORY_MUTANUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_MUTANUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 18: - m_creature->SummonCreature(MEMORY_ONYXIA, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_ONYXIA, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 19: - m_creature->SummonCreature(MEMORY_THUNDERAAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_THUNDERAAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 20: - m_creature->SummonCreature(MEMORY_VANCLEEF, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_VANCLEEF, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 21: - m_creature->SummonCreature(MEMORY_VASHJ, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_VASHJ, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 22: - m_creature->SummonCreature(MEMORY_VEKNILASH, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_VEKNILASH, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 23: - m_creature->SummonCreature(MEMORY_VEZAX, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_VEZAX, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; case 24: - m_creature->SummonCreature(MEMORY_ARCHIMONDE, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - break; + m_creature->SummonCreature(MEMORY_ARCHIMONDE, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; } - Shield_Delay = 1000; + m_uiShieldDelay = 1*IN_MILLISECONDS; } - if (Shield_Delay < diff && !shielded && summoned) + + if (m_uiShieldDelay < uiDiff && !m_bIsShielded && m_bIsSummoned) { m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); m_creature->CastStop(m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); DoCast(m_creature, SPELL_SHIELD); - shielded = true; - Shield_Check = m_bIsRegularMode ? 3000 : 5000; + m_bIsShielded = true; + m_uiShieldCheck = m_bIsRegularMode ? 3*IN_MILLISECONDS : 5*IN_MILLISECONDS; } else - Shield_Delay -= diff; + m_uiShieldDelay -= uiDiff; - if (Shield_Check < diff && shielded) + if (m_uiShieldCheck < uiDiff && m_bIsShielded) { - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_MEMORY)) + uint32 uiMemoryId = m_pInstance->GetData(DATA_MEMORY); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiMemoryId)) { if (!pTemp->isAlive()) { m_creature->RemoveAurasDueToSpell(SPELL_SHIELD); - shielded = false; + m_bIsShielded = false; } - else - Shield_Check = 1000; } + m_uiShieldCheck = 1*IN_MILLISECONDS; } else - Shield_Check -= diff; + m_uiShieldCheck -= uiDiff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -406,28 +409,29 @@ CreatureAI* GetAI_boss_paletress(Creature* pCreature) return new boss_paletressAI(pCreature); } -// Summoned Memory struct MANGOS_DLL_DECL mob_toc5_memoryAI : public ScriptedAI { mob_toc5_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Old_Wounds_Timer; - uint32 Shadows_Timer; - uint32 Fear_Timer; + uint32 m_uiOldWoundsTimer; + uint32 m_uiShadowsTimer; + uint32 m_uiFearTimer; void Reset() { - Old_Wounds_Timer = 5000; - Shadows_Timer = 8000; - Fear_Timer = 13000; + m_creature->setFaction(14); + + m_uiOldWoundsTimer = 5*IN_MILLISECONDS; + m_uiShadowsTimer = 8*IN_MILLISECONDS; + m_uiFearTimer = 13*IN_MILLISECONDS; } void JustDied(Unit* pKiller) @@ -436,39 +440,37 @@ struct MANGOS_DLL_DECL mob_toc5_memoryAI : public ScriptedAI return; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Old_Wounds_Timer < diff) + if (m_uiOldWoundsTimer < uiDiff) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) - DoCast(target, m_bIsRegularMode ? SPELL_OLD_WOUNDS : SPELL_OLD_WOUNDS_H); - - Old_Wounds_Timer = 10000; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_OLD_WOUNDS : SPELL_OLD_WOUNDS_H); + m_uiOldWoundsTimer = 10*IN_MILLISECONDS; } else - Old_Wounds_Timer -= diff; + m_uiOldWoundsTimer -= uiDiff; - if (Fear_Timer < diff) + if (m_uiFearTimer < uiDiff) { DoCast(m_creature, m_bIsRegularMode ? SPELL_FEAR : SPELL_FEAR_H); - Fear_Timer = 40000; + m_uiFearTimer = 40*IN_MILLISECONDS; } else - Fear_Timer -= diff; + m_uiFearTimer -= uiDiff; - if (Shadows_Timer < diff) + if (m_uiShadowsTimer < uiDiff) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) - DoCast(target, m_bIsRegularMode ? SPELL_SHADOWS : SPELL_SHADOWS_H); - - Shadows_Timer = 10000; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_SHADOWS : SPELL_SHADOWS_H); + m_uiShadowsTimer = 10*IN_MILLISECONDS; } else - Shadows_Timer -= diff; - + m_uiShadowsTimer -= uiDiff; + DoMeleeAttackIfReady(); } }; diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp index 4e08a07582..a6ab88e6e2 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2006 - 2011 ScriptDev2 - * This program is free software; you can redistribute it and/or modify +* 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. @@ -26,8 +26,8 @@ EndScriptData */ enum { + // Spells SPELL_BERSERK = 47008, - // Yells // Undead SPELL_PLAGUE_STRIKE = 67724, @@ -43,7 +43,6 @@ enum SPELL_DEATH = 67808, SPELL_DEATH_H = 67875, SPELL_MARK = 67823, - // Risen ghoul SPELL_CLAW = 67879, SPELL_EXPLODE = 67729, @@ -51,60 +50,56 @@ enum SPELL_LEAP = 67749, SPELL_LEAP_H = 67880, - // Sword ID + // Others EQUIP_SWORD = 40343 }; -// Risen Ghoul struct MANGOS_DLL_DECL mob_toc5_risen_ghoulAI : public ScriptedAI { mob_toc5_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Attack; + uint32 m_uiAttackTimer; void Reset() { - Attack = 2500; + m_uiAttackTimer = 2.5*IN_MILLISECONDS; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Attack < diff) + if (m_uiAttackTimer < uiDiff) { - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_BLACK_KNIGHT)) - { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BLACK_KNIGHT)) if (pTemp->isAlive()) if ((pTemp->GetHealth()*100 / pTemp->GetMaxHealth()) < 25) DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLODE : SPELL_EXPLODE_H); - } if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 4)) { DoCast(m_creature->getVictim(), SPELL_CLAW); - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) - m_creature->AI()->AttackStart(target); - - Attack = 2500; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + m_creature->AI()->AttackStart(pTarget); + m_uiAttackTimer = 2.5*IN_MILLISECONDS; } else if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 30)) { DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_LEAP : SPELL_LEAP_H); - Attack = 2500; + m_uiAttackTimer = 2.5*IN_MILLISECONDS; } } else - Attack -= diff; + m_uiAttackTimer -= uiDiff; if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLODE : SPELL_EXPLODE_H); @@ -118,52 +113,50 @@ CreatureAI* GetAI_mob_toc5_risen_ghoul(Creature* pCreature) return new mob_toc5_risen_ghoulAI(pCreature); } -// The Black Knight struct MANGOS_DLL_DECL boss_black_knightAI : public ScriptedAI { boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Plague_Strike_Timer; + bool m_bGhoul; + uint8 m_uiPhase; + uint32 m_uiPlagueStrikeTimer; uint32 Icy_Touch_Timer; - uint32 Obliterate_Timer; - uint32 Choke_Timer; - uint32 Death_Timer; - uint32 Mark_Timer; + uint32 m_uiObliterateTimer; + uint32 m_uiChokeTimer; + uint32 m_uiDeathTimer; + uint32 m_uiMarkTimer; uint32 Phase_Delay; - uint32 Summon_Ghoul; + uint32 m_uiSummonGhoulTimer; uint32 m_uiBerserk_Timer; - bool phase1; - bool phase2; - bool phase3; - bool ghoul; void Reset() { m_creature->SetRespawnDelay(DAY); m_creature->SetDisplayId(29837); SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - Plague_Strike_Timer = m_bIsRegularMode ? 5000 : 4000; - Icy_Touch_Timer = m_bIsRegularMode ? 10000 : 7000; - Obliterate_Timer = m_bIsRegularMode ? 16000 : 10000; - Choke_Timer = 15000; - Summon_Ghoul = 4000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - phase1 = true; - phase2 = false; - phase3 = false; - ghoul = false; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_bGhoul = false; + m_uiPhase = 1; + m_uiPlagueStrikeTimer = m_bIsRegularMode ? 5*IN_MILLISECONDS : 4*IN_MILLISECONDS; + Icy_Touch_Timer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 7*IN_MILLISECONDS; + m_uiObliterateTimer = m_bIsRegularMode ? 16*IN_MILLISECONDS : 10*IN_MILLISECONDS; + m_uiChokeTimer = 15*IN_MILLISECONDS; + m_uiSummonGhoulTimer = 4*IN_MILLISECONDS; + m_uiBerserk_Timer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } + void Aggro(Unit* pWho) { if (!m_pInstance) @@ -175,52 +168,36 @@ struct MANGOS_DLL_DECL boss_black_knightAI : public ScriptedAI void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if ((uiDamage > m_creature->GetHealth() || m_creature->GetHealth()/m_creature->GetHealth() <= 0.1 ) && !phase3) + if ((uiDamage > m_creature->GetHealth() || m_creature->GetHealth()/m_creature->GetHealth() <= 0.1 ) && m_uiPhase != 3) { uiDamage = 0; - if (phase2) + if (m_uiPhase == 2) StartPhase3(); - - if (phase1) + else if (m_uiPhase == 1) StartPhase2(); } } + void JustDied(Unit* pKiller) { if (!m_pInstance) return; - if (phase3 && !phase1 && !phase2) - { + if (m_uiPhase == 3) m_pInstance->SetData(TYPE_BLACK_KNIGHT, DONE); - } -/* if (phase2 && !phase1 && !phase3) - if (!m_creature->isAlive()) - { - m_creature->Respawn(); - StartPhase3(); - } - if (phase1 && !phase2 && !phase3) - if (!m_creature->isAlive()) - { - m_creature->Respawn(); - StartPhase2(); - }*/ } void StartPhase2() { m_creature->SetHealth(m_creature->GetMaxHealth()); m_creature->SetDisplayId(27550); - phase1 = false; - phase2 = true; - phase3 = false; DoCast(m_creature, SPELL_ARMY); - Plague_Strike_Timer = m_bIsRegularMode ? 14000 : 8000; - Icy_Touch_Timer = m_bIsRegularMode ? 12000 : 7000; - Obliterate_Timer = m_bIsRegularMode ? 18000 : 10000; + m_uiPhase = 2; + m_uiPlagueStrikeTimer = m_bIsRegularMode ? 14*IN_MILLISECONDS : 8*IN_MILLISECONDS; + Icy_Touch_Timer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 7*IN_MILLISECONDS; + m_uiObliterateTimer = m_bIsRegularMode ? 18*IN_MILLISECONDS : 10*IN_MILLISECONDS; } void StartPhase3() @@ -228,87 +205,91 @@ struct MANGOS_DLL_DECL boss_black_knightAI : public ScriptedAI m_creature->SetHealth(m_creature->GetMaxHealth()); m_creature->SetDisplayId(14560); SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - phase1 = false; - phase2 = false; - phase3 = true; - Death_Timer = m_bIsRegularMode ? 5000 : 3000; - Mark_Timer = m_bIsRegularMode ? 9000 : 7000; + m_uiPhase = 3; + m_uiDeathTimer = m_bIsRegularMode ? 5*IN_MILLISECONDS : 3*IN_MILLISECONDS; + m_uiMarkTimer = m_bIsRegularMode ? 9*IN_MILLISECONDS : 7*IN_MILLISECONDS; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Plague_Strike_Timer < diff && !phase3) + if (m_uiPhase != 3) { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_PLAGUE_STRIKE : SPELL_PLAGUE_STRIKE_H); - Plague_Strike_Timer = m_bIsRegularMode ? 10500 : 7000; - } - else - Plague_Strike_Timer -= diff; - - if (Icy_Touch_Timer < diff && !phase3) - { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ICY_TOUCH : SPELL_ICY_TOUCH_H); - Icy_Touch_Timer = m_bIsRegularMode ? 10000 : 8000; - } - else - Icy_Touch_Timer -= diff; - - if (Obliterate_Timer < diff && !phase3) - { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_OBLITERATE : SPELL_OBLITERATE_H); - Obliterate_Timer = m_bIsRegularMode ? 11000 : 8000; - } - else - Obliterate_Timer -= diff; + if (m_uiPhase == 1) + { + if (m_uiChokeTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_CHOKE); + m_uiChokeTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; + } + else + m_uiChokeTimer -= uiDiff; + + if (m_uiSummonGhoulTimer < uiDiff && !m_bGhoul) + { + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == NPC_JAEREN) + m_creature->SummonCreature(NPC_RISEN_JAEREN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + else + m_creature->SummonCreature(NPC_RISEN_ARELAS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + m_bGhoul = true; + } + else + m_uiSummonGhoulTimer -= uiDiff; + } - if (Choke_Timer < diff && phase1) - { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) - DoCast(m_creature->getVictim(), SPELL_CHOKE); - Choke_Timer = m_bIsRegularMode ? 15000 : 10000; - } - else - Choke_Timer -= diff; + if (m_uiPlagueStrikeTimer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_PLAGUE_STRIKE : SPELL_PLAGUE_STRIKE_H); + m_uiPlagueStrikeTimer = m_bIsRegularMode ? 10.5*IN_MILLISECONDS : 7*IN_MILLISECONDS; + } + else + m_uiPlagueStrikeTimer -= uiDiff; - if (Summon_Ghoul < diff && phase1 && !ghoul) - { - if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == m_pInstance->GetData(DATA_JAEREN)) - m_creature->SummonCreature(NPC_RISEN_JAEREN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (Icy_Touch_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ICY_TOUCH : SPELL_ICY_TOUCH_H); + Icy_Touch_Timer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 8*IN_MILLISECONDS; + } else - m_creature->SummonCreature(NPC_RISEN_ARELAS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + Icy_Touch_Timer -= uiDiff; - ghoul = true; + if (m_uiObliterateTimer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_OBLITERATE : SPELL_OBLITERATE_H); + m_uiObliterateTimer = m_bIsRegularMode ? 11*IN_MILLISECONDS : 8*IN_MILLISECONDS; + } + else + m_uiObliterateTimer -= uiDiff; } else - Summon_Ghoul -= diff; - - if (Mark_Timer < diff && phase3) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) - DoCast(target, SPELL_MARK); - Mark_Timer = m_bIsRegularMode ? 15000 : 10000; - } - else - Mark_Timer -= diff; + if (m_uiMarkTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_MARK); + m_uiMarkTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; + } + else + m_uiMarkTimer -= uiDiff; - if (Death_Timer < diff && phase3) - { - DoCast(m_creature, m_bIsRegularMode ? SPELL_DEATH : SPELL_DEATH_H); - Death_Timer = 3500; + if (m_uiDeathTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_DEATH : SPELL_DEATH_H); + m_uiDeathTimer = 3.5*IN_MILLISECONDS; + } + else + m_uiDeathTimer -= uiDiff; } - else - Death_Timer -= diff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserk_Timer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserk_Timer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserk_Timer -= uiDiff; DoMeleeAttackIfReady(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp index e1c25b0e3c..a48d70aab6 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -26,93 +26,98 @@ EndScriptData */ enum { - // Common - SPELL_BERSERK = 47008, - // Yells + // Spells + SPELL_BERSERK = 47008, + // Warrior - SPELL_MORTAL_STRIKE = 68783, - SPELL_MORTAL_STRIKE_H = 68784, - SPELL_BLADESTORM = 63784, - SPELL_INTERCEPT = 67540, - SPELL_ROLLING_THROW = 47115, //need core support for spell 67546, using 47115 instead + SPELL_MORTAL_STRIKE = 68783, + SPELL_MORTAL_STRIKE_H = 68784, + SPELL_BLADESTORM = 63784, + SPELL_INTERCEPT = 67540, + SPELL_ROLLING_THROW = 47115, //need core support for spell 67546, using 47115 instead // Mage - SPELL_FIREBALL = 66042, - SPELL_FIREBALL_H = 68310, - SPELL_BLAST_WAVE = 66044, - SPELL_BLAST_WAVE_H = 68312, - SPELL_HASTE = 66045, - SPELL_POLYMORPH = 66043, - SPELL_POLYMORPH_H = 68311, + SPELL_FIREBALL = 66042, + SPELL_FIREBALL_H = 68310, + SPELL_BLAST_WAVE = 66044, + SPELL_BLAST_WAVE_H = 68312, + SPELL_HASTE = 66045, + SPELL_POLYMORPH = 66043, + SPELL_POLYMORPH_H = 68311, // Shaman - SPELL_CHAIN_LIGHTNING = 67529, - SPELL_CHAIN_LIGHTNING_H = 68319, - SPELL_EARTH_SHIELD = 67530, - SPELL_HEALING_WAVE = 67528, - SPELL_HEALING_WAVE_H = 68318, - SPELL_HEX_OF_MENDING = 67534, + SPELL_CHAIN_LIGHTNING = 67529, + SPELL_CHAIN_LIGHTNING_H = 68319, + SPELL_EARTH_SHIELD = 67530, + SPELL_HEALING_WAVE = 67528, + SPELL_HEALING_WAVE_H = 68318, + SPELL_HEX_OF_MENDING = 67534, // Hunter - SPELL_DISENGAGE = 68340, - SPELL_LIGHTNING_ARROWS = 66083, - SPELL_MULTI_SHOT = 66081, - SPELL_SHOOT = 66079, + SPELL_DISENGAGE = 68340, + SPELL_LIGHTNING_ARROWS = 66083, + SPELL_MULTI_SHOT = 66081, + SPELL_SHOOT = 66079, // Rogue - SPELL_EVISCERATE = 67709, - SPELL_EVISCERATE_H = 68317, - SPELL_FAN_OF_KNIVES = 67706, - SPELL_POISON_BOTTLE = 67701 + SPELL_EVISCERATE = 67709, + SPELL_EVISCERATE_H = 68317, + SPELL_FAN_OF_KNIVES = 67706, + SPELL_POISON_BOTTLE = 67701 }; -// Warrior struct MANGOS_DLL_DECL mob_toc5_warriorAI : public ScriptedAI { mob_toc5_warriorAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Mortal_Strike_Timer; - uint32 Bladestorm_Timer; - uint32 Rolling_Throw_Timer; - uint32 Intercept_Cooldown; - uint32 intercept_check; - uint32 m_uiBerserk_Timer; + uint32 m_uiMortalStrikeTimer; + uint32 m_uiBladestormTimer; + uint32 m_uiRollingThrowTimer; + uint32 m_uiInterceptCooldown; + uint32 m_uiInterceptTimer; + uint32 m_uiBerserkTimer; void Reset() { m_creature->SetRespawnDelay(DAY); - Mortal_Strike_Timer = m_bIsRegularMode ? 9000 : 6000; - Bladestorm_Timer = m_bIsRegularMode ? 30000 : 20000; - Rolling_Throw_Timer = m_bIsRegularMode ? 45000 : 30000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - Intercept_Cooldown = 0; - intercept_check = 1000; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_uiMortalStrikeTimer = m_bIsRegularMode ? 9*IN_MILLISECONDS : 6*IN_MILLISECONDS; + m_uiBladestormTimer = m_bIsRegularMode ? 30*IN_MILLISECONDS : 20*IN_MILLISECONDS; + m_uiRollingThrowTimer = m_bIsRegularMode ? 45*IN_MILLISECONDS : 30*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; + m_uiInterceptCooldown = 0; + m_uiInterceptTimer = 1*IN_MILLISECONDS; } + void Aggro(Unit* pWho) { if (!m_pInstance) return; - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); -// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); } void JustDied(Unit* pKiller) @@ -126,67 +131,71 @@ struct MANGOS_DLL_DECL mob_toc5_warriorAI : public ScriptedAI if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Mortal_Strike_Timer < diff) + if (m_uiMortalStrikeTimer < uiDiff) { DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_MORTAL_STRIKE : SPELL_MORTAL_STRIKE_H); - Mortal_Strike_Timer = m_bIsRegularMode ? 6000 : 4000; + m_uiMortalStrikeTimer = m_bIsRegularMode ? 6*IN_MILLISECONDS : 4*IN_MILLISECONDS; } else - Mortal_Strike_Timer -= diff; + m_uiMortalStrikeTimer -= uiDiff; - if (Rolling_Throw_Timer < diff) + if (m_uiRollingThrowTimer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_ROLLING_THROW); - Rolling_Throw_Timer = m_bIsRegularMode ? 30000 : 15000; + m_uiRollingThrowTimer = m_bIsRegularMode ? 30*IN_MILLISECONDS : 15*IN_MILLISECONDS; } else - Rolling_Throw_Timer -= diff; + m_uiRollingThrowTimer -= uiDiff; - if (Bladestorm_Timer < diff) + if (m_uiBladestormTimer < uiDiff) { DoCast(m_creature, SPELL_BLADESTORM); - Bladestorm_Timer = m_bIsRegularMode ? 60000 : 20000; + m_uiBladestormTimer = m_bIsRegularMode ? 1*MINUTE*IN_MILLISECONDS : 20*IN_MILLISECONDS; } else - Bladestorm_Timer -= diff; + m_uiBladestormTimer -= uiDiff; - if (intercept_check < diff) + if (m_uiInterceptTimer < uiDiff) { - if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25) && Intercept_Cooldown < diff) + if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25) && m_uiInterceptCooldown < uiDiff) { DoCast(m_creature->getVictim(), SPELL_INTERCEPT); - Intercept_Cooldown = m_bIsRegularMode ? 15000 : 10000; + m_uiInterceptCooldown = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; } - intercept_check = 1000; + m_uiInterceptTimer = 1*IN_MILLISECONDS; } - else + else { - intercept_check -= diff; - Intercept_Cooldown -= diff; + m_uiInterceptTimer -= uiDiff; + m_uiInterceptCooldown -= uiDiff; } - if (m_uiBerserk_Timer < diff) + + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -197,35 +206,36 @@ CreatureAI* GetAI_mob_toc5_warrior(Creature* pCreature) return new mob_toc5_warriorAI(pCreature); } -// Mage struct MANGOS_DLL_DECL mob_toc5_mageAI : public ScriptedAI { mob_toc5_mageAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Fireball_Timer; - uint32 Blast_Wave_Timer; - uint32 Haste_Timer; - uint32 Polymorph_Timer; - uint32 m_uiBerserk_Timer; + uint32 m_uiFireballTimer; + uint32 m_uiBlastWaveTimer; + uint32 m_uiHasteTimer; + uint32 m_uiPolymorphTimer; + uint32 m_uiBerserkTimer; void Reset() { m_creature->SetRespawnDelay(DAY); - Fireball_Timer = 0; - Blast_Wave_Timer = m_bIsRegularMode ? 20000 : 12000; - Haste_Timer = m_bIsRegularMode ? 12000 : 9000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - Polymorph_Timer = m_bIsRegularMode ? 12000 : 10000; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_uiFireballTimer = 0; + m_uiBlastWaveTimer = m_bIsRegularMode ? 20*IN_MILLISECONDS : 12*IN_MILLISECONDS; + m_uiHasteTimer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 9*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; + m_uiPolymorphTimer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 10*IN_MILLISECONDS; } void Aggro(Unit* pWho) @@ -233,19 +243,22 @@ struct MANGOS_DLL_DECL mob_toc5_mageAI : public ScriptedAI if (!m_pInstance) return; - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); -// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); } void JustDied(Unit* pKiller) @@ -259,63 +272,64 @@ struct MANGOS_DLL_DECL mob_toc5_mageAI : public ScriptedAI if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Fireball_Timer < diff) + if (m_uiFireballTimer < uiDiff) { DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H); - Fireball_Timer = m_bIsRegularMode ? 5000 : 3000; + m_uiFireballTimer = m_bIsRegularMode ? 5*IN_MILLISECONDS : 3*IN_MILLISECONDS; } else - Fireball_Timer -= diff; + m_uiFireballTimer -= uiDiff; - if (Blast_Wave_Timer < diff) + if (m_uiBlastWaveTimer < uiDiff) { DoCast(m_creature, m_bIsRegularMode ? SPELL_BLAST_WAVE : SPELL_BLAST_WAVE_H); - Blast_Wave_Timer = m_bIsRegularMode ? 20000 : 12000; + m_uiBlastWaveTimer = m_bIsRegularMode ? 20*IN_MILLISECONDS : 12*IN_MILLISECONDS; } else - Blast_Wave_Timer -= diff; + m_uiBlastWaveTimer -= uiDiff; - if (Haste_Timer < diff) + if (m_uiHasteTimer < uiDiff) { DoCast(m_creature, SPELL_HASTE); - Haste_Timer = m_bIsRegularMode ? 10000 : 8000; + m_uiHasteTimer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 8*IN_MILLISECONDS; } else - Haste_Timer -= diff; + m_uiHasteTimer -= uiDiff; - if (Polymorph_Timer < diff) + if (m_uiPolymorphTimer < uiDiff) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) - DoCast(target, m_bIsRegularMode ? SPELL_POLYMORPH : SPELL_POLYMORPH_H); - - Polymorph_Timer = m_bIsRegularMode ? 20000 : 15000; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_POLYMORPH : SPELL_POLYMORPH_H); + m_uiPolymorphTimer = m_bIsRegularMode ? 20*IN_MILLISECONDS : 15*IN_MILLISECONDS; } else - Polymorph_Timer -= diff; + m_uiPolymorphTimer -= uiDiff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } - else - m_uiBerserk_Timer -= diff; + else m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -326,39 +340,42 @@ CreatureAI* GetAI_mob_toc5_mage(Creature* pCreature) return new mob_toc5_mageAI(pCreature); } -// Shaman struct MANGOS_DLL_DECL mob_toc5_shamanAI : public ScriptedAI { mob_toc5_shamanAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Chain_Lightning_Timer; - uint32 Earth_Shield_Timer; - uint32 Healing_Wave_Timer; - uint32 Hex_Timer; - - float mob1_health; - float mob2_health; - float mob3_health; - uint32 m_uiBerserk_Timer; + uint32 m_uiChainLightningTimer; + uint32 m_uiEarthShieldTimer; + uint32 m_uiHealingWaveTimer; + uint32 m_uiHexTimer; + uint32 m_uiBerserkTimer; + float m_fHealthFirstChampion; + float m_fHealthSecondChampion; + float m_fHealthThirdChampion; void Reset() { m_creature->SetRespawnDelay(DAY); - Chain_Lightning_Timer = m_bIsRegularMode ? 2000 : 1000; - Earth_Shield_Timer = m_bIsRegularMode ? 10000 : 5000; - Healing_Wave_Timer = m_bIsRegularMode ? 20000 : 12000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - Hex_Timer = m_bIsRegularMode ? 15000 : 10000; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_uiChainLightningTimer = m_bIsRegularMode ? 2*IN_MILLISECONDS : 1*IN_MILLISECONDS; + m_uiEarthShieldTimer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 5*IN_MILLISECONDS; + m_uiHealingWaveTimer = m_bIsRegularMode ? 20*IN_MILLISECONDS : 12*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; + m_uiHexTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; + m_fHealthFirstChampion = 0; + m_fHealthSecondChampion = 0; + m_fHealthThirdChampion = 0; } void Aggro(Unit* pWho) @@ -366,19 +383,22 @@ struct MANGOS_DLL_DECL mob_toc5_shamanAI : public ScriptedAI if (!m_pInstance) return; - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); -// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); } void JustDied(Unit* pKiller) @@ -392,122 +412,130 @@ struct MANGOS_DLL_DECL mob_toc5_shamanAI : public ScriptedAI if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Chain_Lightning_Timer < diff) + if (m_uiChainLightningTimer < uiDiff) { DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H); - Chain_Lightning_Timer = m_bIsRegularMode ? 12000 : 8000; + m_uiChainLightningTimer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 8*IN_MILLISECONDS; } else - Chain_Lightning_Timer -= diff; + m_uiChainLightningTimer -= uiDiff; - if (Hex_Timer < diff) + if (m_uiHexTimer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_HEX_OF_MENDING); - Hex_Timer = m_bIsRegularMode ? 30000 : 20000; + m_uiHexTimer = m_bIsRegularMode ? 30*IN_MILLISECONDS : 20*IN_MILLISECONDS; } else - Hex_Timer -= diff; + m_uiHexTimer -= uiDiff; - if (Healing_Wave_Timer < diff) + if (m_uiHealingWaveTimer < uiDiff) { - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) - { + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) - mob1_health = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); + m_fHealthFirstChampion = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); else - mob1_health = 100; - } - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) - { + m_fHealthFirstChampion = 100; + + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) - mob2_health = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); + m_fHealthSecondChampion = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); else - mob2_health = 100; - } - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) - { + m_fHealthSecondChampion = 100; + + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) - mob3_health = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); + m_fHealthThirdChampion = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); else - mob3_health = 100; - } - if (mob1_health < mob2_health && mob1_health < mob3_health && mob1_health < 70) - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) - DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); + m_fHealthThirdChampion = 100; - if (mob1_health > mob2_health && mob2_health < mob3_health && mob2_health < 70) - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + if (m_fHealthFirstChampion < m_fHealthSecondChampion && m_fHealthFirstChampion < m_fHealthThirdChampion && m_fHealthFirstChampion < 70) + { + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); - - if (mob3_health < mob2_health && mob1_health > mob3_health && mob3_health < 70) - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + } + if (m_fHealthFirstChampion > m_fHealthSecondChampion && m_fHealthSecondChampion < m_fHealthThirdChampion && m_fHealthSecondChampion < 70) + { + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); + } + if (m_fHealthThirdChampion < m_fHealthSecondChampion && m_fHealthFirstChampion > m_fHealthThirdChampion && m_fHealthThirdChampion < 70) + { + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) + DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); + } - Healing_Wave_Timer = m_bIsRegularMode ? 8000 : 6000; + m_uiHealingWaveTimer = m_bIsRegularMode ? 8*IN_MILLISECONDS : 6*IN_MILLISECONDS; } else - Healing_Wave_Timer -= diff; + m_uiHealingWaveTimer -= uiDiff; - if (Earth_Shield_Timer < diff) + if (m_uiEarthShieldTimer < uiDiff) { + uint32 uiOtherId; switch(urand(0, 2)) { case 0: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) - { + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) DoCast(pTemp, SPELL_EARTH_SHIELD); else DoCast(m_creature, SPELL_EARTH_SHIELD); - } break; case 1: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) - { + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) DoCast(pTemp, SPELL_EARTH_SHIELD); else DoCast(m_creature, SPELL_EARTH_SHIELD); - } break; case 2: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) - { + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) DoCast(pTemp, SPELL_EARTH_SHIELD); else DoCast(m_creature, SPELL_EARTH_SHIELD); - } break; } - Earth_Shield_Timer = m_bIsRegularMode ? 35000 : 25000; + m_uiEarthShieldTimer = m_bIsRegularMode ? 35*IN_MILLISECONDS : 25*IN_MILLISECONDS; } else - Earth_Shield_Timer -= diff; + m_uiEarthShieldTimer -= uiDiff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -518,39 +546,40 @@ CreatureAI* GetAI_mob_toc5_shaman(Creature* pCreature) return new mob_toc5_shamanAI(pCreature); } -// Hunter struct MANGOS_DLL_DECL mob_toc5_hunterAI : public ScriptedAI { mob_toc5_hunterAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Shoot_Timer; - uint32 Lightning_Arrows_Timer; - uint32 Multi_Shot_Timer; - uint32 Disengage_Cooldown; - uint32 enemy_check; - uint32 disengage_check; - uint32 m_uiBerserk_Timer; + uint32 m_uiShootTimer; + uint32 m_uiLightningArrowsTimer; + uint32 m_uiMultiShotTimer; + uint32 m_uiDisengageCooldownTimer; + uint32 m_uiEnemyCheckTimer; + uint32 m_uiDisengageCheckTimer; + uint32 m_uiBerserkTimer; void Reset() { m_creature->SetRespawnDelay(DAY); - Shoot_Timer = 0; - Lightning_Arrows_Timer = m_bIsRegularMode ? 18000 : 10000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - Multi_Shot_Timer = m_bIsRegularMode ? 15000 : 8000; - Disengage_Cooldown = 0; - enemy_check = 1000; - disengage_check; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_uiShootTimer = 0; + m_uiLightningArrowsTimer = m_bIsRegularMode ? 18*IN_MILLISECONDS : 10*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; + m_uiMultiShotTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 8*IN_MILLISECONDS; + m_uiDisengageCooldownTimer = 0; + m_uiEnemyCheckTimer = 1*IN_MILLISECONDS; + m_uiDisengageCheckTimer = 0; } void Aggro(Unit* pWho) @@ -558,19 +587,22 @@ struct MANGOS_DLL_DECL mob_toc5_hunterAI : public ScriptedAI if (!m_pInstance) return; - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); -// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); } void JustDied(Unit* pKiller) @@ -584,85 +616,89 @@ struct MANGOS_DLL_DECL mob_toc5_hunterAI : public ScriptedAI if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (enemy_check < diff) + if (m_uiEnemyCheckTimer < uiDiff) { if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 30)) { - m_creature->SetSpeedRate(MOVE_RUN, 0.0001f); + m_creature->SetSpeedRate(MOVE_RUN, 0.0001); } else { - m_creature->SetSpeedRate(MOVE_RUN, 1.2f); + m_creature->SetSpeedRate(MOVE_RUN, 1.2); } - enemy_check = 100; + m_uiEnemyCheckTimer = 0.1*IN_MILLISECONDS; } else - enemy_check -= diff; + m_uiEnemyCheckTimer -= uiDiff; - if (Disengage_Cooldown>0) - Disengage_Cooldown -= diff; + if (m_uiDisengageCooldownTimer > 0) + m_uiDisengageCooldownTimer -= uiDiff; - if (Shoot_Timer < diff) + if (m_uiShootTimer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_SHOOT); - Shoot_Timer = m_bIsRegularMode ? 5000 : 3000; + m_uiShootTimer = m_bIsRegularMode ? 5*IN_MILLISECONDS : 3*IN_MILLISECONDS; } else - Shoot_Timer -= diff; + m_uiShootTimer -= uiDiff; - if (Multi_Shot_Timer < diff) + if (m_uiMultiShotTimer < uiDiff) { m_creature->CastStop(SPELL_SHOOT); DoCast(m_creature->getVictim(), SPELL_MULTI_SHOT); - Multi_Shot_Timer = m_bIsRegularMode ? 10000 : 5000; + m_uiMultiShotTimer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 5*IN_MILLISECONDS; } else - Multi_Shot_Timer -= diff; + m_uiMultiShotTimer -= uiDiff; - if (Lightning_Arrows_Timer < diff) + if (m_uiLightningArrowsTimer < uiDiff) { m_creature->CastStop(SPELL_SHOOT); DoCast(m_creature, SPELL_LIGHTNING_ARROWS); - Lightning_Arrows_Timer = m_bIsRegularMode ? 15000 : 8000; + m_uiLightningArrowsTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 8*IN_MILLISECONDS; } else - Lightning_Arrows_Timer -= diff; + m_uiLightningArrowsTimer -= uiDiff; - if (disengage_check < diff) + if (m_uiDisengageCheckTimer < uiDiff) { - if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 5) && Disengage_Cooldown == 0) + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 5) && m_uiDisengageCooldownTimer == 0) { DoCast(m_creature, SPELL_DISENGAGE); - Disengage_Cooldown = m_bIsRegularMode ? 15000 : 10000; + m_uiDisengageCooldownTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; } - disengage_check = 1000; + m_uiDisengageCheckTimer = 1*IN_MILLISECONDS; } else - disengage_check -= diff; + m_uiDisengageCheckTimer -= uiDiff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserkTimer -= uiDiff; + DoMeleeAttackIfReady(); } @@ -673,33 +709,34 @@ CreatureAI* GetAI_mob_toc5_hunter(Creature* pCreature) return new mob_toc5_hunterAI(pCreature); } -// Rogue struct MANGOS_DLL_DECL mob_toc5_rogueAI : public ScriptedAI { mob_toc5_rogueAI(Creature* pCreature) : ScriptedAI(pCreature) { - Reset(); m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 Eviscerate_Timer; - uint32 FoK_Timer; - uint32 Poison_Timer; - uint32 m_uiBerserk_Timer; + uint32 m_uiEviscerateTimer; + uint32 m_uiFanOfKnivesTimer; + uint32 m_uiPoisonTimer; + uint32 m_uiBerserkTimer; void Reset() { m_creature->SetRespawnDelay(DAY); - Eviscerate_Timer = m_bIsRegularMode ? 20000 : 10000; - FoK_Timer = m_bIsRegularMode ? 15000 : 10000; - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; - Poison_Timer = m_bIsRegularMode ? 12000 : 5000; m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); m_creature->SetWalk(true); + m_creature->setFaction(14); + + m_uiEviscerateTimer = m_bIsRegularMode ? 20*IN_MILLISECONDS : 10*IN_MILLISECONDS; + m_uiFanOfKnivesTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; + m_uiPoisonTimer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 5*IN_MILLISECONDS; } void Aggro(Unit* pWho) @@ -707,19 +744,22 @@ struct MANGOS_DLL_DECL mob_toc5_rogueAI : public ScriptedAI if (!m_pInstance) return; - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); -// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); } void JustDied(Unit* pKiller) @@ -733,55 +773,57 @@ struct MANGOS_DLL_DECL mob_toc5_rogueAI : public ScriptedAI if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + uint32 uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uiOtherId = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiOtherId)) pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Eviscerate_Timer < diff) + if (m_uiEviscerateTimer < uiDiff) { DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_EVISCERATE : SPELL_EVISCERATE_H); - Eviscerate_Timer = m_bIsRegularMode ? 15000 : 10000; + m_uiEviscerateTimer = m_bIsRegularMode ? 15*IN_MILLISECONDS : 10*IN_MILLISECONDS; } else - Eviscerate_Timer -= diff; + m_uiEviscerateTimer -= uiDiff; - if (FoK_Timer < diff) + if (m_uiFanOfKnivesTimer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_FAN_OF_KNIVES); - FoK_Timer = m_bIsRegularMode ? 12000 : 7000; + m_uiFanOfKnivesTimer = m_bIsRegularMode ? 12*IN_MILLISECONDS : 7*IN_MILLISECONDS; } else - FoK_Timer -= diff; + m_uiFanOfKnivesTimer -= uiDiff; - if (Poison_Timer < diff) + if (m_uiPoisonTimer < uiDiff) { if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) DoCast(m_creature, SPELL_POISON_BOTTLE); - - Poison_Timer = m_bIsRegularMode ? 10000 : 5000; + m_uiPoisonTimer = m_bIsRegularMode ? 10*IN_MILLISECONDS : 5*IN_MILLISECONDS; } else - Poison_Timer -= diff; + m_uiPoisonTimer -= uiDiff; - if (m_uiBerserk_Timer < diff) + if (m_uiBerserkTimer < uiDiff) { DoCast(m_creature, SPELL_BERSERK); - m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + m_uiBerserkTimer = m_bIsRegularMode ? 5*MINUTE*IN_MILLISECONDS : 3*MINUTE*IN_MILLISECONDS; } else - m_uiBerserk_Timer -= diff; + m_uiBerserkTimer -= uiDiff; DoMeleeAttackIfReady(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp index fc55a60375..950847e5c7 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -27,10 +27,10 @@ EndScriptData */ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance { - instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) + instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) { - m_bIsRegularMode = pMap->IsRegularDifficulty(); - Initialize(); + m_bRegular = pMap->IsRegularDifficulty(); + Initialize(); } uint32 m_auiEncounter[MAX_ENCOUNTER+1]; @@ -41,54 +41,53 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance uint32 m_uiChampionId2; uint32 m_uiChampionId3; uint32 m_uiChampionsCount; - uint32 m_uiArgentChallengerID; - uint32 m_uiBlackKnightMinionID; - uint32 m_uiAnnouncerID; - bool m_bIsRegularMode; + uint32 m_uiArgentChallengerId; + uint32 m_uiMemoryId; + uint32 m_uiAnnouncerId; + bool m_bRegular; void Initialize() { - m_uiBlackKnightMinionID = 0; m_uiChampionId1 = 0; m_uiChampionId2 = 0; m_uiChampionId3 = 0; m_uiChampionsCount = 3; - m_uiArgentChallengerID = 0; + m_uiArgentChallengerId = 0; + m_uiMemoryId = 0; + m_uiAnnouncerId = 0; for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) m_auiEncounter[i] = NOT_STARTED; } + + enum PhaseControl + { + HORDE_CONTROL_PHASE_SHIFT_1 = 55773, + HORDE_CONTROL_PHASE_SHIFT_2 = 60028, + ALLIANCE_CONTROL_PHASE_SHIFT_1 = 55774, + ALLIANCE_CONTROL_PHASE_SHIFT_2 = 60027, + }; void OnPlayerEnter(Player *pPlayer) { - - enum PhaseControl - { - HORDE_CONTROL_PHASE_SHIFT_1 = 55773, - HORDE_CONTROL_PHASE_SHIFT_2 = 60028, - ALLIANCE_CONTROL_PHASE_SHIFT_1 = 55774, - ALLIANCE_CONTROL_PHASE_SHIFT_2 = 60027, - }; - - if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) - return; + // ENTURION errore di compilazione su windows, mettiamo return perch da noi il bool 0 + //if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) return; + return; switch (pPlayer->GetTeam()) { case ALLIANCE: - if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(HORDE_CONTROL_PHASE_SHIFT_1)) - pPlayer->RemoveAurasDueToSpell(HORDE_CONTROL_PHASE_SHIFT_1); - - pPlayer->CastSpell(pPlayer, HORDE_CONTROL_PHASE_SHIFT_2, false); - break; + if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(HORDE_CONTROL_PHASE_SHIFT_1)) + pPlayer->RemoveAurasDueToSpell(HORDE_CONTROL_PHASE_SHIFT_1); + pPlayer->CastSpell(pPlayer, HORDE_CONTROL_PHASE_SHIFT_2, false); + break; case HORDE: - if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(ALLIANCE_CONTROL_PHASE_SHIFT_1)) - pPlayer->RemoveAurasDueToSpell(ALLIANCE_CONTROL_PHASE_SHIFT_1); - - pPlayer->CastSpell(pPlayer, ALLIANCE_CONTROL_PHASE_SHIFT_2, false); - break; - } - } + if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(ALLIANCE_CONTROL_PHASE_SHIFT_1)) + pPlayer->RemoveAurasDueToSpell(ALLIANCE_CONTROL_PHASE_SHIFT_1); + pPlayer->CastSpell(pPlayer, ALLIANCE_CONTROL_PHASE_SHIFT_2, false); + break; + }; + }; void OnCreatureCreate(Creature* pCreature) { @@ -100,37 +99,33 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance case NPC_COLOSOS: case NPC_JAELYNE: case NPC_LANA: + break; + // Champions of the Horde case NPC_MOKRA: case NPC_ERESSEA: case NPC_RUNOK: case NPC_ZULTORE: case NPC_VISCERI: - { - if (m_uiChampionId1 == 0) - m_uiChampionId1 = pCreature->GetEntry(); - else if (m_uiChampionId2 == 0) - m_uiChampionId2 = pCreature->GetEntry(); - else if (m_uiChampionId3 == 0) - m_uiChampionId3 = pCreature->GetEntry(); - else - return; break; - } + // Argent Challenge case NPC_EADRIC: case NPC_PALETRESS: - m_uiArgentChallengerID = pCreature->GetEntry(); - break; - // Coliseum Announcers - case NPC_JAEREN: - case NPC_ARELAS: - m_uiAnnouncerID = pCreature->GetEntry(); + m_uiArgentChallengerId = pCreature->GetEntry(); break; + // Black Knight case NPC_BLACK_KNIGHT: case NPC_RISEN_JAEREN: case NPC_RISEN_ARELAS: + break; + + // Coliseum Announcers + case NPC_JAEREN: + case NPC_ARELAS: + break; + // memories case MEMORY_ALGALON: case MEMORY_ARCHIMONDE: @@ -157,9 +152,8 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance case MEMORY_VASHJ: case MEMORY_VEKNILASH: case MEMORY_VEZAX: + m_uiMemoryId = pCreature->GetEntry(); break; - default: - return; } m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); } @@ -174,11 +168,9 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance case GO_CHAMPIONS_LOOT_H: case GO_EADRIC_LOOT_H: case GO_PALETRESS_LOOT_H: - m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); break; - default: - return; } + m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); } void SetData(uint32 uiType, uint32 uiData) @@ -186,7 +178,7 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance switch(uiType) { case DATA_TOC5_ANNOUNCER: - m_uiAnnouncerID = uiData; + m_uiAnnouncerId = uiData; break; case DATA_CHAMPIONID_1: m_uiChampionId1 = uiData; @@ -201,48 +193,44 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance m_uiChampionsCount = uiData; break; case DATA_ARGENT_CHALLENGER: - m_uiArgentChallengerID = uiData; - break; - case DATA_BLACK_KNIGHT_MINION: - m_uiBlackKnightMinionID = uiData; + m_uiArgentChallengerId = uiData; break; case TYPE_GRAND_CHAMPIONS: m_auiEncounter[0] = uiData; if (uiData == DONE) { - if (GameObject* pChest = GetSingleGameObjectFromStorage(m_bIsRegularMode ? GO_CHAMPIONS_LOOT : GO_CHAMPIONS_LOOT_H)) + if (GameObject* pChest = GetSingleGameObjectFromStorage(m_bRegular ? GO_CHAMPIONS_LOOT : GO_CHAMPIONS_LOOT_H)) if (pChest && !pChest->isSpawned()) pChest->SetRespawnTime(DAY); } if (uiData == FAIL) { - m_auiEncounter[0] = NOT_STARTED; + m_auiEncounter[0] = NOT_STARTED; } break; case TYPE_ARGENT_CHALLENGE: m_auiEncounter[1] = uiData; if (uiData == DONE) { - if (m_uiArgentChallengerID == NPC_EADRIC) - if (GameObject* pChest = GetSingleGameObjectFromStorage(m_bIsRegularMode ? GO_EADRIC_LOOT : GO_EADRIC_LOOT_H)) + if (m_uiArgentChallengerId == NPC_EADRIC) + if (GameObject* pChest = GetSingleGameObjectFromStorage(m_bRegular ? GO_EADRIC_LOOT : GO_EADRIC_LOOT_H)) if (pChest && !pChest->isSpawned()) pChest->SetRespawnTime(DAY); - - if (m_uiArgentChallengerID == NPC_PALETRESS) - if (GameObject* pChest = GetSingleGameObjectFromStorage(m_bIsRegularMode ? GO_PALETRESS_LOOT : GO_PALETRESS_LOOT_H)) + if (m_uiArgentChallengerId == NPC_PALETRESS) + if (GameObject* pChest = GetSingleGameObjectFromStorage(m_bRegular ? GO_PALETRESS_LOOT : GO_PALETRESS_LOOT_H)) if (pChest && !pChest->isSpawned()) pChest->SetRespawnTime(DAY); } if (uiData == FAIL) { - m_auiEncounter[1] = NOT_STARTED; + m_auiEncounter[1] = NOT_STARTED; } break; case TYPE_BLACK_KNIGHT: m_auiEncounter[2] = uiData; if (uiData == FAIL) { - m_auiEncounter[2] = NOT_STARTED; + m_auiEncounter[2] = NOT_STARTED; } break; } @@ -267,6 +255,10 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance { switch(uiType) { + case DATA_TOC5_ANNOUNCER: + return m_uiAnnouncerId; + case DATA_MEMORY: + return m_uiMemoryId; case DATA_CHAMPIONID_1: return m_uiChampionId1; case DATA_CHAMPIONID_2: @@ -276,11 +268,7 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance case DATA_CHAMPIONS_COUNT: return m_uiChampionsCount; case DATA_ARGENT_CHALLENGER: - return m_uiArgentChallengerID; - case DATA_BLACK_KNIGHT_MINION: - return m_uiBlackKnightMinionID; - case DATA_TOC5_ANNOUNCER: - return m_uiAnnouncerID; + return m_uiArgentChallengerId; case TYPE_GRAND_CHAMPIONS: return m_auiEncounter[0]; case TYPE_ARGENT_CHALLENGE: @@ -288,7 +276,6 @@ struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance case TYPE_BLACK_KNIGHT: return m_auiEncounter[2]; } - return 0; } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp index 13e33c1bec..2033e621cd 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -28,7 +28,7 @@ EndContentData */ #include "precompiled.h" #include "trial_of_the_champion.h" -#define GOSSIP_START_EVENT "Im ready for the next challenge." +#define GOSSIP_START_EVENT "We are ready to fight." /*###### ## npc_toc5_announcer @@ -43,10 +43,10 @@ struct _Messages static _Messages _GossipMessage[]= { - {GOSSIP_START_EVENT,GOSSIP_ACTION_INFO_DEF+1,false,TYPE_GRAND_CHAMPIONS}, - {GOSSIP_START_EVENT,GOSSIP_ACTION_INFO_DEF+2,false,TYPE_ARGENT_CHALLENGE}, - {GOSSIP_START_EVENT,GOSSIP_ACTION_INFO_DEF+3,false,TYPE_BLACK_KNIGHT}, - {GOSSIP_START_EVENT,GOSSIP_ACTION_INFO_DEF+4,true,TYPE_BLACK_KNIGHT}, +{"Are you ready to challenge the Grand Champions of yuor opposite Faction?",GOSSIP_ACTION_INFO_DEF+1,false,TYPE_GRAND_CHAMPIONS}, // +{"Are you ready to challenge the Argent Champion?",GOSSIP_ACTION_INFO_DEF+2,false,TYPE_ARGENT_CHALLENGE}, // +{"I've heard that the Black Knight is still alive and that he wants to fight with you. Do you think this is even possible?",GOSSIP_ACTION_INFO_DEF+3,false,TYPE_BLACK_KNIGHT}, // +{"The Fight is over, Champions, you can go to rest now. I'll go to take a nap soon.",GOSSIP_ACTION_INFO_DEF+4,true,TYPE_BLACK_KNIGHT}, // }; struct MANGOS_DLL_DECL npc_toc5_announcerAI : public ScriptedAI @@ -65,11 +65,9 @@ struct MANGOS_DLL_DECL npc_toc5_announcerAI : public ScriptedAI void UpdateAI(const uint32 diff) { - if (!m_pInstance) - return; + if (!m_pInstance) return; - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; } }; @@ -80,13 +78,13 @@ CreatureAI* GetAI_npc_toc5_announcer(Creature* pCreature) bool GossipHello_npc_toc5_announcer(Player* pPlayer, Creature* pCreature) { + ScriptedInstance* m_pInstance; m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - if (!m_pInstance) - return false; + if (!m_pInstance) return false; - if (pPlayer->IsInCombat()) + if(pPlayer->IsInCombat()) return true; for(uint8 i = 0; i < MAX_ENCOUNTER+1; i++) @@ -96,9 +94,11 @@ bool GossipHello_npc_toc5_announcer(Player* pPlayer, Creature* pCreature) pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _GossipMessage[i].name, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); break; } + if (_GossipMessage[i].state && m_pInstance->GetData(_GossipMessage[i].encounter) == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _GossipMessage[i].name, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _GossipMessage[i].name, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); } + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); return true; @@ -106,125 +106,144 @@ bool GossipHello_npc_toc5_announcer(Player* pPlayer, Creature* pCreature) bool GossipSelect_npc_toc5_announcer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { - if (!pPlayer || !pCreature) - return true; - - ScriptedInstance* m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pPlayer->CLOSE_GOSSIP_MENU(); switch(uiAction) { case GOSSIP_ACTION_INFO_DEF+1: { - if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) != 0) + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == 0) { m_pInstance->SetData(DATA_TOC5_ANNOUNCER, pCreature->GetEntry()); - if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == DATA_ARELAS) + + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == NPC_ARELAS) { - m_pInstance->SetData(DATA_BLACK_KNIGHT_MINION, 35564); switch(urand(0, 4)) { - case 0: m_pInstance->SetData(DATA_CHAMPIONID_1, 35572); break; - case 1: m_pInstance->SetData(DATA_CHAMPIONID_1, 35569); break; - case 2: m_pInstance->SetData(DATA_CHAMPIONID_1, 35571); break; - case 3: m_pInstance->SetData(DATA_CHAMPIONID_1, 35570); break; - case 4: m_pInstance->SetData(DATA_CHAMPIONID_1, 35617); break; + case 0: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_MOKRA); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_ERESSEA); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_RUNOK); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_ZULTORE); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_VISCERI); break; } - do { + + do + { switch(urand(0, 4)) { - case 0: m_pInstance->SetData(DATA_CHAMPIONID_2, 35572); break; - case 1: m_pInstance->SetData(DATA_CHAMPIONID_2, 35569); break; - case 2: m_pInstance->SetData(DATA_CHAMPIONID_2, 35571); break; - case 3: m_pInstance->SetData(DATA_CHAMPIONID_2, 35570); break; - case 4: m_pInstance->SetData(DATA_CHAMPIONID_2, 35617); break; - } - } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_2)); - do{ + case 0: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_MOKRA); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_ERESSEA); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_RUNOK); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_ZULTORE); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_VISCERI); break; + } + } + while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_2)); + + do + { switch(urand(0, 4)) { - case 0: m_pInstance->SetData(DATA_CHAMPIONID_3, 35572); break; - case 1: m_pInstance->SetData(DATA_CHAMPIONID_3, 35569); break; - case 2: m_pInstance->SetData(DATA_CHAMPIONID_3, 35571); break; - case 3: m_pInstance->SetData(DATA_CHAMPIONID_3, 35570); break; - case 4: m_pInstance->SetData(DATA_CHAMPIONID_3, 35617); break; - } - } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_3) || m_pInstance->GetData(DATA_CHAMPIONID_2) == m_pInstance->GetData(DATA_CHAMPIONID_3)); + case 0: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_MOKRA); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_ERESSEA); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_RUNOK); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_ZULTORE); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_VISCERI); break; + } + } + while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_3) || m_pInstance->GetData(DATA_CHAMPIONID_2) == m_pInstance->GetData(DATA_CHAMPIONID_3)); } - if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == DATA_JAEREN) + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == NPC_JAEREN) { - m_pInstance->SetData(DATA_BLACK_KNIGHT_MINION, 123); - switch(urand(0, 4)) { - case 0: m_pInstance->SetData(DATA_CHAMPIONID_1, 34705); break; - case 1: m_pInstance->SetData(DATA_CHAMPIONID_1, 34702); break; - case 2: m_pInstance->SetData(DATA_CHAMPIONID_1, 34701); break; - case 3: m_pInstance->SetData(DATA_CHAMPIONID_1, 34657); break; - case 4: m_pInstance->SetData(DATA_CHAMPIONID_1, 34703); break; + case 0: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_JACOB); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_AMBROSE); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_COLOSOS); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_JAELYNE); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_1, NPC_LANA); break; } - do{ + + do + { switch(urand(0, 4)) { - case 0: m_pInstance->SetData(DATA_CHAMPIONID_2, 34705); break; - case 1: m_pInstance->SetData(DATA_CHAMPIONID_2, 34702); break; - case 2: m_pInstance->SetData(DATA_CHAMPIONID_2, 34701); break; - case 3: m_pInstance->SetData(DATA_CHAMPIONID_2, 34657); break; - case 4: m_pInstance->SetData(DATA_CHAMPIONID_2, 34703); break; + case 0: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_JACOB); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_AMBROSE); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_COLOSOS); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_JAELYNE); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_2, NPC_LANA); break; } - } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_2)); - do{ + } + while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_2)); + + do + { switch(urand(0, 4)) { - case 0: m_pInstance->SetData(DATA_CHAMPIONID_3, 34705); break; - case 1: m_pInstance->SetData(DATA_CHAMPIONID_3, 34702); break; - case 2: m_pInstance->SetData(DATA_CHAMPIONID_3, 34701); break; - case 3: m_pInstance->SetData(DATA_CHAMPIONID_3, 34657); break; - case 4: m_pInstance->SetData(DATA_CHAMPIONID_3, 34703); break; + case 0: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_JACOB); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_AMBROSE); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_COLOSOS); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_JAELYNE); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_3, NPC_LANA); break; } - } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_3) || m_pInstance->GetData(DATA_CHAMPIONID_2) == m_pInstance->GetData(DATA_CHAMPIONID_3)); + } + while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_3) || m_pInstance->GetData(DATA_CHAMPIONID_2) == m_pInstance->GetData(DATA_CHAMPIONID_3)); + } switch(urand(0, 1)) { - case 0: m_pInstance->SetData(DATA_ARGENT_CHALLENGER, 35119); break; - case 1: m_pInstance->SetData(DATA_ARGENT_CHALLENGER, 34928); break; + case 0: m_pInstance->SetData(DATA_ARGENT_CHALLENGER, NPC_EADRIC); break; + case 1: m_pInstance->SetData(DATA_ARGENT_CHALLENGER, NPC_PALETRESS); break; } } if (m_pInstance->GetData(TYPE_GRAND_CHAMPIONS) == NOT_STARTED || m_pInstance->GetData(TYPE_GRAND_CHAMPIONS) == IN_PROGRESS) { m_pInstance->SetData(DATA_CHAMPIONS_COUNT, 3); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_1)) + + uint32 uiChampion1Id = m_pInstance->GetData(DATA_CHAMPIONID_1); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiChampion1Id)) pTemp->Respawn(); else - pCreature->SummonCreature(m_pInstance->GetData(DATA_CHAMPIONID_1), 738.665771f, 661.031433f, 412.394623f, 4.698702f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pCreature->SummonCreature(uiChampion1Id, 738.665771f, 661.031433f, 412.394623f, 4.698702f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_2)) + uint32 uiChampion2Id = m_pInstance->GetData(DATA_CHAMPIONID_2); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiChampion2Id)) pTemp->Respawn(); else - pCreature->SummonCreature(m_pInstance->GetData(DATA_CHAMPIONID_2), 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pCreature->SummonCreature(uiChampion2Id, 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_CHAMPION_3)) + uint32 uiChampion3Id = m_pInstance->GetData(DATA_CHAMPIONID_3); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiChampion3Id)) pTemp->Respawn(); else - pCreature->SummonCreature(m_pInstance->GetData(DATA_CHAMPIONID_3), 754.360779f, 660.816162f, 412.395996f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pCreature->SummonCreature(uiChampion3Id, 754.360779f, 660.816162f, 412.395996f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); } + break; } + case GOSSIP_ACTION_INFO_DEF+2: { if ((m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) == NOT_STARTED || m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) == IN_PROGRESS) && m_pInstance->GetData(TYPE_GRAND_CHAMPIONS) == DONE) { - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(DATA_ARGENT_CHALLENGER)) + uint32 uiChallenger = m_pInstance->GetData(DATA_ARGENT_CHALLENGER); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiChallenger)) pTemp->Respawn(); else - pCreature->SummonCreature(m_pInstance->GetData(DATA_ARGENT_CHALLENGER), 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pCreature->SummonCreature(uiChallenger, 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, IN_PROGRESS); } + break; } + case GOSSIP_ACTION_INFO_DEF+3: { if ((m_pInstance->GetData(TYPE_BLACK_KNIGHT) == NOT_STARTED || m_pInstance->GetData(TYPE_BLACK_KNIGHT) == IN_PROGRESS) && m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) == DONE) @@ -233,15 +252,19 @@ bool GossipSelect_npc_toc5_announcer(Player* pPlayer, Creature* pCreature, uint3 pCreature->DealDamage(pCreature, pCreature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); m_pInstance->SetData(TYPE_BLACK_KNIGHT, IN_PROGRESS); } + break; } + case GOSSIP_ACTION_INFO_DEF+4: { if (m_pInstance->GetData(TYPE_BLACK_KNIGHT) == DONE) { pCreature->DealDamage(pCreature, pCreature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } + break; } } + return true; } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp index a98ca0dbfd..08492dc780 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -21,197 +21,204 @@ SDComment: by /dev/rsa SDCategory: EndScriptData */ +// Anubarak - underground phase partially not worked, timers need correct +// Burrower - underground phase not implemented, buff not worked. +// Leecheng Swarm spell not worked - awaiting core support +// Anubarak spike aura worked only after 9750 + #include "precompiled.h" #include "trial_of_the_crusader.h" -enum Yells +enum Summons { - SAY_INTRO = -1713554, - SAY_AGGRO = -1713555, - SAY_SUBMERGE = -1713556, - SAY_LOW_HEALTH = -1713560, - SAY_SLAY_1 = -1713562, - SAY_SLAY_2 = -1713563, - SAY_DEATH = -1713564, - - EMOTE_SUBMERGE = -1713557, - EMOTE_PURSUING = -1713558, - EMOTE_OUT_OF_THE_GROUND = -1713559, - EMOTE_LEECHING_SWARM = -1713561, + MAX_ORBS = 6, + NPC_FROST_SPHERE = 34606, + NPC_BURROWER = 34607, + NPC_SCARAB = 34605, + NPC_SPIKE = 34660, }; -enum Summons +enum BossSpells { - NPC_FROST_SPHERE = 34606, - NPC_PERMAFROST = 33184, - NPC_NERUBIAN_BURROW_1 = 34862, - NPC_NERUBIAN_BURROW_2 = 34863, - NPC_NERUBIAN_BURROW_3 = 34864, - NPC_NERUBIAN_BURROW_4 = 34865, - NPC_BURROWER = 34607, - NPC_SCARAB = 34605, - NPC_SPIKE = 34660, - NPC_SPIKE_TRIGGER = 5672, + SPELL_COLD = 66013, + SPELL_MARK = 67574, + SPELL_LEECHING_SWARM = 66118, + SPELL_LEECHING_HEAL = 66125, + SPELL_LEECHING_DAMAGE = 66240, + SPELL_SPIKE_CALL = 66169, + SPELL_POUND = 66012, + SPELL_SHOUT = 67730, + SPELL_SUBMERGE_0 = 53421, + SPELL_SUBMERGE_1 = 67322, + SPELL_SUMMON_BEATLES = 66339, + SPELL_BERSERK = 26662, + + // Scarabs' Spell + SPELL_DETERMINATION = 66092, + SPELL_ACID_MANDIBLE = 67861, + + //Burrowers' Spells + SPELL_SPIDER_FRENZY = 66129, + SPELL_SHADOW_STRIKE = 66134, + SPELL_EXPOSE_WEAKNESS = 67847, + + // Spikes' Spell + SPELL_PURSUING_SPIKES_0 = 65920, + SPELL_PURSUING_SPIKES_1 = 65922, + SPELL_PURSUING_SPIKES_2 = 65923, + + + SUMMON_SCARAB = NPC_SCARAB, + SUMMON_BORROWER = NPC_BURROWER, + + // Permafrost + SPELL_PERMAFROST_N10 = 66193, + SPELL_PERMAFROST_N25 = 67855, + SPELL_PERMAFROST_H10 = 67856, + SPELL_PERMAFROST_H25 = 67857, + SPELL_PERMAFROST_VISUAL = 65882, }; -enum BossSpells +static Locations OrbLoc[]= { - SPELL_FROST_VISUAL = 67539, - SPELL_PERMAFROST = 66193, - SPELL_PERMAFROST_SPAWN = 65882, - SPELL_COLD = 66013, - SPELL_MARK = 67574, - SPELL_LEECHING_SWARM = 66118, - SPELL_LEECHING_HEAL = 66125, - SPELL_LEECHING_DAMAGE = 66240, - SPELL_IMPALE_10 = 65919, - SPELL_IMPALE_25 = 67859, - SPELL_IMPALE_GROUND = 65921, - SPELL_PURSUING_SPIKE_LOW = 65920, - SPELL_PURSUING_SPIKE_MED = 65922, - SPELL_PURSUING_SPIKE_HIGH = 65923, - SPELL_PURSUING_SPIKE_COLD = 66181, - SPELL_POUND = 66012, - SPELL_SHOUT = 67730, - SPELL_SUBMERGE_ANUB = 53421, - SPELL_EMERGE_ANUB = 65982, - SPELL_SUBMERGE_BURROWER = 53421, // Temporal (Original: 67322) - SPELL_EMERGE_BURROWER = 65982, - SPELL_SUMMON_BEATLES = 66339, - SPELL_DETERMINATION = 66092, - SPELL_ACID_MANDIBLE = 65775, - SPELL_SPIDER_FRENZY = 66129, - SPELL_EXPOSE_WEAKNESS = 67847, - SPELL_SUMMON_SCARAB = 66340, - SPELL_SHADOW_STRIKE = 66134, - SPELL_ACHIEV_TRAITOR_KING_10 = 68186, - SPELL_ACHIEV_TRAITOR_KING_25 = 68515, - SPELL_BERSERK = 26662, + {686.162720f, 137.699341f, 142.140900f}, + {716.846436f, 101.386314f, 142.120087f}, + {755.520447f, 99.565300f, 142.126083f}, + {801.836440f, 132.908325f, 142.162261f}, + {763.514221f, 172.092712f, 142.120148f}, + {714.347595f, 168.373795f, 142.207657f} }; +bool HasPermafrostAura(Unit* pWho) +{ + if(pWho->HasAura(SPELL_PERMAFROST_N25) + || pWho->HasAura(SPELL_PERMAFROST_H10) + || pWho->HasAura(SPELL_PERMAFROST_H25) + || pWho->HasAura(SPELL_PERMAFROST_N10)) + return true; + + return false; +} + +void RemovePermafrostAura(Unit* pWho) +{ + pWho->RemoveAurasDueToSpell(SPELL_PERMAFROST_N25); + pWho->RemoveAurasDueToSpell(SPELL_PERMAFROST_H10); + pWho->RemoveAurasDueToSpell(SPELL_PERMAFROST_H25); + pWho->RemoveAurasDueToSpell(SPELL_PERMAFROST_N10); +} + +/*##### +# Anub'Arak +#####*/ struct MANGOS_DLL_DECL boss_anubarak_trialAI : public BSWScriptedAI -{ +{ boss_anubarak_trialAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); - + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - bool intro; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiEventStep; - uint32 m_uiNextEventTimer; - - uint32 m_uiPoundTimer; - uint32 m_uiColdTimer; - uint32 m_uiSummonBurrowerTimer; - uint32 m_uiSubmergeAnubTimer; - uint32 m_uiNerubianBurrowTimer; - uint32 m_uiSubmergePhaseTimer; - uint32 m_uiFrostSphereOneTimer; - uint32 m_uiFrostSphereTwoTimer; - uint32 m_uiSummonScarabTimer; - uint32 m_uiPursuingTimer; + Creature* m_pSpike; uint32 m_uiBerserkTimer; + uint32 m_uiBurrowTimer; + uint32 m_uiBurrowerSummonTimer; + uint32 m_uiSpikeCallTimer; + uint8 m_uiStage; + bool m_bSpikeCalled; + bool m_bIntro; - Unit* pTarget; - - void Reset() + void Reset() { - if (!m_pInstance) - return; - - intro = true; - pTarget = NULL; - - m_uiEventStep = 0; - m_uiNextEventTimer = 0; - - m_uiPoundTimer = 20000; - m_uiColdTimer = 30000; - m_uiSummonBurrowerTimer = 10000; - m_uiSubmergeAnubTimer = 80000; - m_uiNerubianBurrowTimer = 0; - m_uiSubmergePhaseTimer = 88000; - m_uiFrostSphereOneTimer = urand(5000, 10000); - m_uiFrostSphereTwoTimer = 2000; - m_uiSummonScarabTimer = 2000; - m_uiPursuingTimer = 1000; - m_uiBerserkTimer = 570000; + if(!m_pInstance) + return; + m_uiSpikeCallTimer = 3000; + m_bSpikeCalled = false; + m_uiBerserkTimer = 600000; + m_uiBurrowTimer = 90000; + m_uiBurrowerSummonTimer = 15000; + m_uiStage = 0; + m_bIntro = true; + m_pSpike = NULL; m_creature->SetRespawnDelay(DAY); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } - void NextStep(uint32 uiTime = 1000) - { - ++m_uiEventStep; - m_uiNextEventTimer = uiTime; - } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(SAY_SLAY_1 - urand(0, 1),m_creature,pVictim); + DoScriptText(-1713563,m_creature); } - void MoveInLineOfSight(Unit* pWho) + + void MoveInLineOfSight(Unit* pWho) { - if (!intro) + if (!m_bIntro) return; - DoScriptText(SAY_INTRO, m_creature); - intro = false; - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_1)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_2)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_3)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_4)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); + DoScriptText(-1713554, m_creature); + m_bIntro = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } void JustReachedHome() { if (m_pInstance) m_pInstance->SetData(TYPE_ANUBARAK, FAIL); +// m_creature->ForcedDespawn(); + } + + void SummonOrbs() + { + for (uint8 i = 0; i <= MAX_ORBS; i++) + m_creature->SummonCreature(NPC_FROST_SPHERE, OrbLoc[i].x, OrbLoc[i].y, OrbLoc[i].z, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 15000); + } + + void SummonBurrower() + { + float fOffset; + + switch (currentDifficulty) + { + case RAID_DIFFICULTY_25MAN_HEROIC: + fOffset = urand(0, 17); + DoSpawnCreature(NPC_BURROWER, (20 * cos(fOffset)), (20 * sin(fOffset)), 0.0f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + fOffset = urand(0, 17); + DoSpawnCreature(NPC_BURROWER, (20 * cos(fOffset)), (20 * sin(fOffset)), 0.0f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + case RAID_DIFFICULTY_10MAN_HEROIC: + case RAID_DIFFICULTY_25MAN_NORMAL: + fOffset = urand(0, 17); + DoSpawnCreature(NPC_BURROWER, (20 * cos(fOffset)), (20 * sin(fOffset)), 0.0f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + case RAID_DIFFICULTY_10MAN_NORMAL: + fOffset = urand(0, 17); + DoSpawnCreature(NPC_BURROWER, (20 * cos(fOffset)), (20 * sin(fOffset)), 0.0f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + break; + } } void JustDied(Unit* pKiller) { - if (!m_pInstance) + if (!m_pInstance) return; - - DoScriptText(SAY_DEATH, m_creature); + DoScriptText(-1713564, m_creature); m_pInstance->SetData(TYPE_ANUBARAK, DONE); - m_pInstance->SetData(TYPE_EVENT, 6000); } void Aggro(Unit* pWho) { - if (!intro) - DoScriptText(SAY_AGGRO, m_creature); + SummonOrbs(); + + if (!m_bIntro) + DoScriptText(-1713555, m_creature); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetInCombatWithZone(); m_pInstance->SetData(TYPE_ANUBARAK, IN_PROGRESS); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } void UpdateAI(const uint32 uiDiff) @@ -219,264 +226,116 @@ struct MANGOS_DLL_DECL boss_anubarak_trialAI : public BSWScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiNextEventTimer <= uiDiff) - { - switch (m_uiEventStep) - { - case 0: - if (m_uiFrostSphereOneTimer <= uiDiff) - { - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[29].x + urand(5, 15), SpawnLoc[29].y - urand(10, 20), SpawnLoc[29].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[30].x + urand(5, 15), SpawnLoc[30].y - urand(10, 20), SpawnLoc[30].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[31].x + urand(5, 15), SpawnLoc[31].y - urand(10, 20), SpawnLoc[31].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[32].x + urand(5, 15), SpawnLoc[32].y - urand(10, 20), SpawnLoc[32].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[49].x + urand(5, 15), SpawnLoc[49].y - urand(10, 20), SpawnLoc[49].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[50].x + urand(5, 15), SpawnLoc[50].y - urand(10, 20), SpawnLoc[50].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[51].x + urand(5, 15), SpawnLoc[51].y - urand(10, 20), SpawnLoc[51].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[52].x + urand(5, 15), SpawnLoc[52].y - urand(10, 20), SpawnLoc[52].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - m_uiFrostSphereOneTimer = 40000; - } - else - m_uiFrostSphereOneTimer -= uiDiff; - - if (m_uiPoundTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_POUND) == CAST_OK) - m_uiPoundTimer = 20000; - } - else - m_uiPoundTimer -= uiDiff; - - if (m_uiColdTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_COLD) == CAST_OK) - m_uiColdTimer = 25000; - } - else - m_uiColdTimer -= uiDiff; + switch(m_uiStage) + { + case 0: + timedCast(SPELL_POUND, uiDiff); + timedCast(SPELL_COLD, uiDiff); - if (m_uiSummonBurrowerTimer <= uiDiff) + if (m_uiBurrowTimer < uiDiff) + { + m_uiBurrowTimer = 60000; + m_uiStage = 1; + } + else m_uiBurrowTimer -= uiDiff; + + break; + case 1: + doCast(SPELL_SUBMERGE_0); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_uiStage = 2; + DoScriptText(-1713557, m_creature); + break; + case 2: + if (!m_bSpikeCalled) + { + if (m_uiSpikeCallTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - float x, y, z; - m_creature->GetPosition(x, y, z); - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - - if (m_bIs25Man || m_bIsHeroic) - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - - if (m_bIs25Man && m_bIsHeroic) +// doCast(SPELL_SPIKE_CALL); +// This summon not supported in database. Temporary override. + if(m_pSpike = DoSpawnCreature(NPC_SPIKE, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000)) { - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - } - m_uiSummonBurrowerTimer = 45000; - } - else - m_uiSummonBurrowerTimer -= uiDiff; - - if (m_uiSubmergeAnubTimer <= uiDiff) - { - m_creature->CastSpell(m_creature, SPELL_SUBMERGE_ANUB, false); - m_uiSubmergeAnubTimer = 80000; - NextStep(); - } - else - m_uiSubmergeAnubTimer -= uiDiff; - - break; - case 1: - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(SAY_SUBMERGE, m_creature); - DoScriptText(EMOTE_SUBMERGE, m_creature); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_1)) - pNerubianBurrow->SetVisibility(VISIBILITY_ON); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_2)) - pNerubianBurrow->SetVisibility(VISIBILITY_ON); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_3)) - pNerubianBurrow->SetVisibility(VISIBILITY_ON); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_4)) - pNerubianBurrow->SetVisibility(VISIBILITY_ON); - - NextStep(2000); - break; - case 2: - if (m_uiPursuingTimer <= uiDiff) - { - float x, y, z; - m_creature->GetPosition(x, y, z); - - m_creature->SummonCreature(NPC_SPIKE, x, y, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - m_uiPursuingTimer = 90000; - } - else - m_uiPursuingTimer -= uiDiff; - - if (m_uiFrostSphereTwoTimer <= uiDiff) - { - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[29].x + urand(5, 15), SpawnLoc[29].y - urand(10, 20), SpawnLoc[29].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[30].x + urand(5, 15), SpawnLoc[30].y - urand(10, 20), SpawnLoc[30].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 40000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[31].x + urand(5, 15), SpawnLoc[31].y - urand(10, 20), SpawnLoc[31].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[32].x + urand(5, 15), SpawnLoc[32].y - urand(10, 20), SpawnLoc[32].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 40000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[49].x + urand(5, 15), SpawnLoc[49].y - urand(10, 20), SpawnLoc[49].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[50].x + urand(5, 15), SpawnLoc[50].y - urand(10, 20), SpawnLoc[50].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[51].x + urand(5, 15), SpawnLoc[51].y - urand(10, 20), SpawnLoc[51].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - if (Creature *pFrostSphere = m_creature->SummonCreature(NPC_FROST_SPHERE, SpawnLoc[52].x + urand(5, 15), SpawnLoc[52].y - urand(10, 20), SpawnLoc[52].z + 10.0f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - pFrostSphere->CastSpell(m_creature, SPELL_FROST_VISUAL, false); - - m_uiFrostSphereTwoTimer = 30000; + m_pSpike->SetInCombatWith(pTarget); + m_pSpike->AddThreat(pTarget, 100000.0f); + DoScriptText(-1713558, m_creature, pTarget); + doCast(SPELL_MARK, pTarget); + m_pSpike->GetMotionMaster()->MoveChase(pTarget); + m_bSpikeCalled = true; + m_uiSpikeCallTimer = 3000; + } } - else - m_uiFrostSphereTwoTimer -= uiDiff; - - if (m_uiSummonScarabTimer <= uiDiff) - { - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_1)) - pNerubianBurrow->CastSpell(pNerubianBurrow, SPELL_SUMMON_SCARAB, false); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_2)) - pNerubianBurrow->CastSpell(pNerubianBurrow, SPELL_SUMMON_SCARAB, false); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_3)) - pNerubianBurrow->CastSpell(pNerubianBurrow, SPELL_SUMMON_SCARAB, false); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_4)) - pNerubianBurrow->CastSpell(pNerubianBurrow, SPELL_SUMMON_SCARAB, false); + } + else m_uiSpikeCallTimer -= uiDiff; + } + if (timedQuery(SPELL_SUMMON_BEATLES, uiDiff)) + { + doCast(SPELL_SUMMON_BEATLES); + doCast(SUMMON_SCARAB); + DoScriptText(-1713560, m_creature); + } - m_uiSummonScarabTimer = 8000; - } - else - m_uiSummonScarabTimer -= uiDiff; + if (m_uiBurrowTimer < uiDiff) + { + m_uiBurrowTimer = 90000; + m_uiStage = 3; + m_bSpikeCalled = false; + } + else m_uiBurrowTimer -= uiDiff; - if (m_uiSubmergePhaseTimer <= uiDiff) - { - m_uiSubmergePhaseTimer = 90000; - NextStep(); - } - else - m_uiSubmergePhaseTimer -= uiDiff; - - break; - case 3: - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->RemoveAurasDueToSpell(SPELL_SUBMERGE_ANUB); - m_creature->CastSpell(m_creature, SPELL_EMERGE_ANUB, false); - DoScriptText(EMOTE_OUT_OF_THE_GROUND,m_creature); - - if (Creature *pSpike = m_pInstance->GetSingleCreatureFromStorage(NPC_SPIKE)) - pSpike->ForcedDespawn(); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_1)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_2)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_3)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - if (Creature *pNerubianBurrow = m_pInstance->GetSingleCreatureFromStorage(NPC_NERUBIAN_BURROW_4)) - pNerubianBurrow->SetVisibility(VISIBILITY_OFF); - - m_uiEventStep = 0; - break; - case 4: - m_creature->CastSpell(m_creature, SPELL_LEECHING_SWARM, false); - DoScriptText(SAY_LOW_HEALTH, m_creature); - DoScriptText(EMOTE_LEECHING_SWARM, m_creature); - m_uiEventStep = 5; - NextStep(3000); - break; - case 5: - if (m_uiPoundTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_POUND) == CAST_OK) - m_uiPoundTimer = 20000; - } - else - m_uiPoundTimer -= uiDiff; - - if (m_uiColdTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_COLD) == CAST_OK) - m_uiColdTimer = 25000; - } - else - m_uiColdTimer -= uiDiff; + break; + case 3: + m_uiStage = 0; + DoScriptText(-1713559, m_creature); - if (m_bIsHeroic) - { - if (m_uiSummonBurrowerTimer <= uiDiff) - { - float x, y, z; - m_creature->GetPosition(x, y, z); - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - - if (m_bIs25Man || m_bIsHeroic) - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - - if (m_bIs25Man && m_bIsHeroic) - { - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - m_creature->SummonCreature(NPC_BURROWER, x + 3.0f, y + 3.0f, z, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000); - } - m_uiSummonBurrowerTimer = 45000; - } - else - m_uiSummonBurrowerTimer -= uiDiff; - } - break; + if (m_pSpike) + { + m_pSpike->ForcedDespawn(); + m_pSpike = NULL; } - if (m_uiBerserkTimer <= uiDiff) + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + doRemove(SPELL_SUBMERGE_0, m_creature); + break; + case 4: + doCast(SPELL_LEECHING_SWARM); + DoScriptText(-1713561, m_creature); + m_uiStage = 5; + break; + case 5: + timedCast(SPELL_POUND, uiDiff); + timedCast(SPELL_COLD, uiDiff); + break; + } + + if (m_uiBurrowerSummonTimer < uiDiff) + { + if (currentDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) + SummonBurrower(); + else + { + if (m_uiStage != 5) { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) - m_uiBerserkTimer = 570000; + SummonBurrower(); } - else - m_uiBerserkTimer -= uiDiff; + } + DoScriptText(-1713556, m_creature); + m_uiBurrowerSummonTimer = 65000; + } + else m_uiBurrowerSummonTimer -= uiDiff; - if (m_creature->GetHealthPercent() < 30.0f && m_uiEventStep == 0) - m_uiEventStep = 4; + if (m_uiBerserkTimer < uiDiff) + { + m_uiBerserkTimer = 600000; + doCast(SPELL_BERSERK); + } + else m_uiBerserkTimer -= uiDiff; - } - else - m_uiNextEventTimer -= uiDiff; + if (m_creature->GetHealthPercent() < 30.0f && m_uiStage == 0) + m_uiStage = 4; DoMeleeAttackIfReady(); } @@ -487,76 +346,53 @@ CreatureAI* GetAI_boss_anubarak_trial(Creature* pCreature) return new boss_anubarak_trialAI(pCreature); } +/*##### +# Swarm Scarab +#####*/ struct MANGOS_DLL_DECL mob_swarm_scarabAI : public BSWScriptedAI { mob_swarm_scarabAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); - + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiAcidMandibleTimer; - uint32 m_uiDeterminationTimer; void Reset() { m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(DAY); - - m_uiAcidMandibleTimer = 2000; - m_uiDeterminationTimer = urand(10000, 20000); } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; } void JustDied(Unit* Killer) { - m_creature->CastSpell(m_creature, m_bIs25Man ? SPELL_ACHIEV_TRAITOR_KING_25 : SPELL_ACHIEV_TRAITOR_KING_10, false); - m_creature->ForcedDespawn(5000); } void Aggro(Unit *who) { - if (!m_pInstance) + if (!m_pInstance) return; } void UpdateAI(const uint32 uiDiff) { - if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) m_creature->ForcedDespawn(); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiDeterminationTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_DETERMINATION) == CAST_OK) - m_uiDeterminationTimer = 30000; - } - else - m_uiDeterminationTimer -= uiDiff; + timedCast(SPELL_DETERMINATION, uiDiff); - if (m_uiAcidMandibleTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ACID_MANDIBLE) == CAST_OK) - m_uiAcidMandibleTimer = 2000; - } - else - m_uiAcidMandibleTimer -= uiDiff; + timedCast(SPELL_ACID_MANDIBLE, uiDiff); DoMeleeAttackIfReady(); } @@ -567,57 +403,47 @@ CreatureAI* GetAI_mob_swarm_scarab(Creature* pCreature) return new mob_swarm_scarabAI(pCreature); }; +/*##### +# Nerubian Borrower +#####*/ struct MANGOS_DLL_DECL mob_nerubian_borrowerAI : public BSWScriptedAI { mob_nerubian_borrowerAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsSubmerged; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiExposeWeaknessTimer; - uint32 m_uiSpiderFrenzyTimer; - uint32 m_uiShadowStrikeTimer; - uint32 m_uiSubmergeBurrowerTimer; + uint32 m_uiStrikeTimer; + uint32 m_uiRangeCheckTimer; + uint8 m_uiAllies; + bool m_bSubmerged; void Reset() { m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(DAY); - m_bIsSubmerged = false; - - m_uiExposeWeaknessTimer = 8000; - m_uiSpiderFrenzyTimer = 0; - m_uiShadowStrikeTimer = 5000; - m_uiSubmergeBurrowerTimer = 5000; + m_bSubmerged = false; + m_uiStrikeTimer = 35000; + m_uiRangeCheckTimer = 1000; + m_uiAllies = 0; } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; } void JustDied(Unit* Killer) { - m_creature->ForcedDespawn(5000); - - if (Creature* pNerubianBurrower = GetClosestCreatureWithEntry(m_creature, NPC_BURROWER, 50.0f)) - pNerubianBurrower->RemoveAurasDueToSpell(SPELL_SPIDER_FRENZY); } void Aggro(Unit *who) { - if (!m_pInstance) + if (!m_pInstance) return; } @@ -629,67 +455,67 @@ struct MANGOS_DLL_DECL mob_nerubian_borrowerAI : public BSWScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiExposeWeaknessTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_EXPOSE_WEAKNESS) == CAST_OK) - m_uiExposeWeaknessTimer = 8000; - } - else - m_uiExposeWeaknessTimer -= uiDiff; - - if (m_uiSpiderFrenzyTimer <= uiDiff) + if (m_uiRangeCheckTimer < uiDiff) { - if (Creature* pNerubianBurrower = GetClosestCreatureWithEntry(m_creature, NPC_BURROWER, 50.0f)) + std::list pBurrowers; + GetCreatureListWithEntryInGrid(pBurrowers, m_creature, NPC_BURROWER, 12.0f); + uint8 uiAllies = 0; + if(!pBurrowers.empty()) { - m_creature->_AddAura(SPELL_SPIDER_FRENZY); - pNerubianBurrower->_AddAura(SPELL_SPIDER_FRENZY); + for (std::list::iterator iter = pBurrowers.begin(); iter != pBurrowers.end(); ++iter) + { + if ((*iter)->GetObjectGuid() != m_creature->GetObjectGuid()) + uiAllies++; + } } - m_uiSpiderFrenzyTimer = 1000; - } - else - m_uiSpiderFrenzyTimer -= uiDiff; - - if (m_bIsHeroic) - { - if (m_uiShadowStrikeTimer <= uiDiff) + if (uiAllies) { - m_creature->CastSpell(m_creature->getVictim(), SPELL_SHADOW_STRIKE, false); - m_uiShadowStrikeTimer = 30000; + if (m_uiAllies != uiAllies) + { + DoCast(m_creature, SPELL_SPIDER_FRENZY); + + if (SpellAuraHolderPtr pFrenzy = m_creature->GetSpellAuraHolder(SPELL_SPIDER_FRENZY)) + { + if (pFrenzy->GetStackAmount() < uiAllies) + pFrenzy->SetStackAmount(uiAllies); + } + + m_uiAllies = uiAllies; + } } - else - m_uiShadowStrikeTimer -= uiDiff; + + m_uiRangeCheckTimer = 1000; } + else m_uiRangeCheckTimer -= uiDiff; - if (m_creature->GetHealthPercent() < 20.0f && !m_bIsSubmerged && !hasAura(SPELL_PERMAFROST, m_creature)) + timedCast(SPELL_EXPOSE_WEAKNESS, uiDiff); + + if (!m_bSubmerged && m_creature->GetHealthPercent() < 20.0f && timedQuery(SPELL_SUBMERGE_1, uiDiff)) { - m_creature->CastSpell(m_creature, SPELL_SUBMERGE_BURROWER, false); - m_creature->RemoveAllAuras(); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(EMOTE_SUBMERGE, m_creature); - m_bIsSubmerged = true; + doCast(SPELL_SUBMERGE_1); + m_bSubmerged = true; + DoScriptText(-1713557, m_creature); } - if (m_bIsSubmerged) + if (m_bSubmerged && m_creature->GetHealthPercent() > 50.0f) { - if (m_uiSubmergeBurrowerTimer <= uiDiff) - { - m_creature->SetHealth(m_creature->GetMaxHealth()); - m_uiSubmergeBurrowerTimer = 5000; - } - else - m_uiSubmergeBurrowerTimer -= uiDiff; - } + doRemove(SPELL_SUBMERGE_1, m_creature); + m_bSubmerged = false; + DoScriptText(-1713559, m_creature); + } - if (m_creature->GetHealthPercent() > 50.0f && m_bIsSubmerged) + // only hero ability and only if not-submerged + if (!m_bSubmerged && (currentDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC)) { - m_creature->CastSpell(m_creature, SPELL_EMERGE_BURROWER, false); - m_creature->RemoveAurasDueToSpell(SPELL_SUBMERGE_BURROWER); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoScriptText(EMOTE_OUT_OF_THE_GROUND, m_creature); - m_bIsSubmerged = false; + if (m_uiStrikeTimer < uiDiff) + { + m_uiStrikeTimer = 35000; + Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_SHADOW_STRIKE); + } + else m_uiStrikeTimer -= uiDiff; } DoMeleeAttackIfReady(); @@ -701,9 +527,12 @@ CreatureAI* GetAI_mob_nerubian_borrower(Creature* pCreature) return new mob_nerubian_borrowerAI(pCreature); }; -struct MANGOS_DLL_DECL mob_frost_sphereAI : public BSWScriptedAI +/*##### +# Forst Sphere +#####*/ +struct MANGOS_DLL_DECL mob_frost_sphereAI : public ScriptedAI { - mob_frost_sphereAI(Creature* pCreature) : BSWScriptedAI(pCreature) + mob_frost_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); @@ -714,36 +543,37 @@ struct MANGOS_DLL_DECL mob_frost_sphereAI : public BSWScriptedAI void Reset() { m_creature->SetRespawnDelay(DAY); - m_creature->SetLevitate(true); - SetCombatMovement(false); + m_creature->SetSpeedRate(MOVE_RUN, 0.1f); + m_creature->SetWalk(true); m_creature->GetMotionMaster()->MoveRandom(); } - void Aggro(Unit *who) + void Aggro(Unit* pWho) { - if (!m_pInstance) - return; + return; + } - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + void AttackStart(Unit* pWho) + { + return; + } - m_creature->SetVisibility(VISIBILITY_OFF); - m_creature->CastSpell(m_creature, SPELL_PERMAFROST_SPAWN, false); - float x, y, z; - m_creature->GetPosition(x, y, z); - if (Creature *pPermafrost = m_creature->SummonCreature(NPC_PERMAFROST, x, y, z - 9.8f, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage >= m_creature->GetHealth()) { - pPermafrost->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pPermafrost->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pPermafrost->CastSpell(pPermafrost, SPELL_PERMAFROST, false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetHealth(m_creature->GetMaxHealth()); + DoCast(m_creature, SPELL_PERMAFROST_VISUAL); + DoCast(m_creature, SPELL_PERMAFROST_N10, true); } } void UpdateAI(const uint32 uiDiff) { - if (!m_pInstance || m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) - m_creature->ForcedDespawn(); + if (!m_pInstance || m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + m_creature->ForcedDespawn(); } }; @@ -752,143 +582,141 @@ CreatureAI* GetAI_mob_frost_sphere(Creature* pCreature) return new mob_frost_sphereAI(pCreature); }; -struct MANGOS_DLL_DECL mob_anubarak_spikeAI : public BSWScriptedAI +/*##### +# Spike +#####*/ +struct MANGOS_DLL_DECL mob_anubarak_spikeAI : public ScriptedAI { - mob_anubarak_spikeAI(Creature* pCreature) : BSWScriptedAI(pCreature) + mob_anubarak_spikeAI(Creature* pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + m_uiDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } + Difficulty m_uiDifficulty; ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - - bool m_bIncreaseSpeed; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiEventStep; - uint32 m_uiNextEventTimer; - - uint32 m_uiImpaleTimer; - uint32 m_uiIncreaseSpeedTimer; - uint32 m_uiSpikeCallTimer; - uint32 m_uiPermafrostTimer; + uint32 m_uiCheckTimer; + uint32 m_uiAuraTimer; + uint32 m_uiChangeTimer; + bool m_bSpeed; + bool m_bChange; void Reset() { + m_uiChangeTimer = 5000; + m_uiCheckTimer = 500; + m_uiAuraTimer = 7000; m_creature->SetRespawnDelay(DAY); - m_creature->SetVisibility(VISIBILITY_OFF); - m_creature->SetInCombatWithZone(); - m_creature->setFaction(14); - m_creature->SetSpeedRate(MOVE_RUN, 0.0f); + m_creature->SetSpeedRate(MOVE_RUN, 1.5f); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - m_uiEventStep = 0; - m_uiNextEventTimer = 8000; - - m_uiImpaleTimer = 5000; - m_uiIncreaseSpeedTimer = 5000; - m_uiSpikeCallTimer = 4500; - m_uiPermafrostTimer = 5000; + m_bSpeed = false; + m_bChange = false; } - void NextStep(uint32 uiTime = 1000) + void Aggro(Unit *pWho) { - ++m_uiEventStep; - m_uiIncreaseSpeedTimer = uiTime; + if (!m_pInstance) + return; + + DoCast(m_creature, SPELL_PURSUING_SPIKES_0); } - void Aggro(Unit *who) + void ChangeTarget() { - if (!m_pInstance) - return; + Unit* pVictim = m_creature->getVictim(); + Unit* pTemp = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + + if (pVictim) + { + pVictim->RemoveAurasDueToSpell(SPELL_MARK); + m_creature->AddThreat(pVictim, -100000.0f); + } + + m_creature->AddThreat(pTemp, 100000.0f); + DoScriptText(-1713558, m_creature, pTemp); + m_creature->CastSpell(pTemp, SPELL_MARK, false); + m_creature->GetMotionMaster()->MoveChase(pTemp); } void UpdateAI(const uint32 uiDiff) { - if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) m_creature->ForcedDespawn(); - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiIncreaseSpeedTimer <= uiDiff) - { - switch (m_uiEventStep) - { - case 0: - m_creature->SetSpeedRate(MOVE_RUN, 0.75f); - m_creature->CastSpell(m_creature, SPELL_PURSUING_SPIKE_LOW, false); - NextStep(7000); - break; - case 1: - m_creature->SetSpeedRate(MOVE_RUN, 1.0f); - m_creature->CastSpell(m_creature, SPELL_PURSUING_SPIKE_MED, false); - NextStep(7000); - break; - case 2: - m_creature->SetSpeedRate(MOVE_RUN, 1.5f); - m_creature->CastSpell(m_creature, SPELL_PURSUING_SPIKE_HIGH, false); - NextStep(7000); - break; - } - } - else - m_uiIncreaseSpeedTimer -= uiDiff; - - if (m_uiSpikeCallTimer <= uiDiff) + if (m_bChange) { - m_creature->SetVisibility(VISIBILITY_ON); - - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (m_uiChangeTimer < uiDiff) { - DoScriptText(EMOTE_PURSUING, m_creature, pTarget); - m_creature->AddThreat(pTarget, 100000.0f); - m_creature->CastSpell(pTarget, SPELL_MARK, false); - m_creature->CastSpell(m_creature, SPELL_IMPALE_GROUND, false); + ChangeTarget(); + m_creature->RemoveAurasDueToSpell(SPELL_PURSUING_SPIKES_0); + m_creature->RemoveAurasDueToSpell(SPELL_PURSUING_SPIKES_1); + m_creature->RemoveAurasDueToSpell(SPELL_PURSUING_SPIKES_2); + DoCast(m_creature, SPELL_PURSUING_SPIKES_0); + m_uiChangeTimer = 5000; + m_bChange = false; + m_bSpeed = false; } - m_uiSpikeCallTimer = 90000; + else m_uiChangeTimer -= uiDiff; + + return; } - else - m_uiSpikeCallTimer -= uiDiff; - if (m_uiImpaleTimer <= uiDiff) + if (m_uiAuraTimer < uiDiff) { - if (m_creature->IsWithinDist(m_creature->getVictim(), 4.0f)) + if (!m_bSpeed) { - m_creature->CastSpell(m_creature->getVictim(), m_bIs25Man? SPELL_IMPALE_25 : SPELL_IMPALE_10, false); - m_creature->ForcedDespawn(100); - - float x, y, z; - m_creature->GetPosition(x, y, z); - m_creature->SummonCreature(NPC_SPIKE, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + DoCast(m_creature, SPELL_PURSUING_SPIKES_1); + m_bSpeed = true; } + else + DoCast(m_creature, SPELL_PURSUING_SPIKES_2); - m_uiImpaleTimer = 500; + m_uiAuraTimer = 7000; } - else - m_uiImpaleTimer -= uiDiff; + else m_uiAuraTimer -= uiDiff; - if (m_uiPermafrostTimer <= uiDiff) + if (m_uiCheckTimer < uiDiff) { - if (m_creature->HasAura(SPELL_PERMAFROST) || GetClosestCreatureWithEntry(m_creature, NPC_PERMAFROST, 5.0f)) + if (m_creature->getVictim() && m_creature->getVictim()->IsWithinDist(m_creature, 1.0)) + { + m_bChange = true; + return; + } + + std::list lOrbs; + GetCreatureListWithEntryInGrid(lOrbs, m_creature, NPC_FROST_SPHERE, 10.0f); + if (!lOrbs.empty()) { - m_creature->RemoveAllAuras(); - m_creature->ForcedDespawn(); + float fDist = 999.99f; + Creature* pNearest = NULL; + + // get nearest dead Frost Sphere + for (std::list::iterator iter = lOrbs.begin(); iter != lOrbs.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + { + if ((*iter)->GetDistance(m_creature) <= fDist) + { + pNearest = (*iter); + fDist = pNearest->GetDistance(m_creature); + } + } + } - float x, y, z; - m_creature->GetPosition(x, y, z); - m_creature->SummonCreature(NPC_SPIKE, x + urand(5.0f, 10.0f), y + urand(5.0f, 10.0f), z, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + if (pNearest) + { + if(m_uiDifficulty <= RAID_DIFFICULTY_25MAN_NORMAL) + pNearest->Respawn(); + + RemovePermafrostAura(m_creature); + ChangeTarget(); + } } - m_uiPermafrostTimer = 250; + m_uiCheckTimer = 500; } - else - m_uiPermafrostTimer -= uiDiff; + else m_uiCheckTimer -= uiDiff; } }; @@ -899,30 +727,31 @@ CreatureAI* GetAI_mob_anubarak_spike(Creature* pCreature) void AddSC_boss_anubarak_trial() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_anubarak_trial"; - pNewScript->GetAI = &GetAI_boss_anubarak_trial; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_swarm_scarab"; - pNewScript->GetAI = &GetAI_mob_swarm_scarab; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_nerubian_borrower"; - pNewScript->GetAI = &GetAI_mob_nerubian_borrower; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_anubarak_spike"; - pNewScript->GetAI = &GetAI_mob_anubarak_spike; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_frost_sphere"; - pNewScript->GetAI = &GetAI_mob_frost_sphere; - pNewScript->RegisterSelf(); + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_anubarak_trial"; + newscript->GetAI = &GetAI_boss_anubarak_trial; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_swarm_scarab"; + newscript->GetAI = &GetAI_mob_swarm_scarab; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nerubian_borrower"; + newscript->GetAI = &GetAI_mob_nerubian_borrower; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_anubarak_spike"; + newscript->GetAI = &GetAI_mob_anubarak_spike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_sphere"; + newscript->GetAI = &GetAI_mob_frost_sphere; + newscript->RegisterSelf(); + } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp index cfe5a931fd..02806c5c94 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -24,278 +24,43 @@ EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" -#define AI_MELEE 0 -#define AI_RANGED 1 -#define AI_HEALER 2 +enum AiType +{ + AI_MELEE = 0, + AI_RANGED = 1, + AI_HEALER = 2 +}; #define SPELL_ANTI_AOE 68595 #define SPELL_PVP_TRINKET 65547 -enum Spells -{ - /******************************************************************** - HEALERS - ********************************************************************/ - - //Druid Restoration - SPELL_LIFEBLOOM = 66093, - SPELL_NOURISH = 66066, - SPELL_REGROWTH = 66067, - SPELL_REJUVENATION = 66065, - SPELL_TRANQUILITY = 66086, - SPELL_BARKSKIN = 65860, //1 min cd - SPELL_THORNS = 66068, - SPELL_NATURE_GRASP = 66071, //1 min cd, self buff - SPELL_ROOTS = 66070, - - //Shaman Restoraion - SPELL_HEALING_WAVE = 66055, - SPELL_RIPTIDE = 66053, - SPELL_SPIRIT_CLEANSE = 66056, //friendly only - SPELL_HEX = 66054, - SPELL_EARTH_SHIELD = 66063, - SPELL_EARTH_SHOCK = 65973, - - //Paladyn Holy - SPELL_HAND_OF_FREEDOM = 68757, //25 sec cd - SPELL_BUBBLE = 66010, //5 min cd - SPELL_CLEANSE = 66116, - SPELL_FLASH_OF_LIGHT = 66113, - SPELL_HOLY_LIGHT = 66112, - SPELL_HOLY_SHOCK = 66114, - SPELL_FLASH_HEAL = 66113, - SPELL_HAND_OF_PROTECTION = 66009, - SPELL_HAMMER_OF_JUSTICE = 66613, - SPELL_FORBEARANCE = 25771, - - //Priest Discipline - SPELL_RENEW = 66177, - SPELL_SHIELD = 66099, - SPELL_FLASH_HEAL_P = 66104, - SPELL_DISPEL = 65546, - SPELL_PSYCHIC_SCREAM = 65543, - SPELL_MANA_BURN = 66100, - SPELL_PEANANCE = 68030, - SPELL_WEAKEN_SOUL = 6788, - - /******************************************************************** - RANGED - ********************************************************************/ - - //Priest Shadow - SPELL_SILENCE = 65542, - SPELL_VAMPIRIC_TOUCH = 65490, - SPELL_SW_PAIN = 65541, - SPELL_MIND_FLAY = 65488, - SPELL_MIND_BLAST = 65492, - SPELL_HORROR = 65545, - SPELL_DISPERSION = 65544, - SPELL_SHADOWFORM = 16592, - - //Warlock - SPELL_HELLFIRE = 65816, - SPELL_CORRUPTION = 65810, - SPELL_CURSE_OF_AGONY = 65814, - SPELL_CURSE_OF_EXHAUSTION = 65815, - SPELL_FEAR = 65809, //8s - SPELL_SEARING_PAIN = 65819, - SPELL_SHADOW_BOLT = 65821, - SPELL_UNSTABLE = 65812, - SPELL_SUMMON_FEL = 67514, - - //Mage - SPELL_BARRAGE = 65799, //3s - SPELL_BLAST = 65791, - SPELL_EXPLOSION = 65800, - SPELL_BLINK = 65793, //15s - SPELL_CS = 65790, //24s - SPELL_FROST_NOVA = 65792, //25s - SPELL_FROSTBOLT = 65807, - SPELL_ICE_BLOCK = 65802, //5min - SPELL_POLY = 65801, //15s - - //Hunter - SPELL_AIMED_SHOT = 65883, - SPELL_DETERENCE = 65871, //90s - SPELL_DISENGAGE = 65869, //30s - SPELL_EXPLOSIVE_SHOT = 65866, - SPELL_FROST_TRAP = 65880, //30s - SPELL_SHOOT = 65868, //1.7s - SPELL_STEADY_SHOT = 65867, //3s - SPELL_WING_CLIP = 66207, //6s - SPELL_WYVERN_STING = 65877, //60s - SPELL_CALL_PET = 67777, - - //Druid Balance - SPELL_CYCLONE = 65859, //6s - SPELL_ROOTS_B = 65857, //10s - SPELL_FEARIE = 65863, - SPELL_FORCED_OF_NATURE = 65861, //180s - SPELL_SWARM = 65855, - SPELL_MOONFIRE = 65856, //5s - SPELL_STARFIRE = 65854, - SPELL_WRATH = 65862, - //Barskin - - /******************************************************************** - MELEE - ********************************************************************/ - - //Warrior Arms - SPELL_BLADESTORM = 65947, - SPELL_INTIMIDATING_SHOUT = 65930, - SPELL_MORTAL_STRIKE = 65926, - SPELL_CHARGE = 68764, - SPELL_DISARM = 65935, - SPELL_OVERPOWER = 65924, - SPELL_SUNDER_ARMOR = 65936, - SPELL_SHATTERING_THROW = 65940, - SPELL_RETALIATION = 65932, - - //Death Knight - SPELL_CHAINS = 66020, //8sec - SPELL_DEATH_COLI = 66019, //5sec - SPELL_DEATH_GRIP = 66017, //35sec - SPELL_FROST_STRIKE = 66047, //6sec - SPELL_ICEBOUND = 66023, //1min - SPELL_ICE_TOUCH = 66021, //8sec - SPELL_STRANGULATE = 66018, //2min - - //Rogue - SPELL_FAN_OF_KNIVES = 65955, //2sec - SPELL_BLIND = 65960, //2min - SPELL_CLOAK = 65961, //90sec - SPELL_BLADE_FLURRY = 65956, //2min - SPELL_SHADOWSTEP = 66178, //30sec - SPELL_HEMORRHAGE = 65954, - SPELL_EVISCERATE = 65957, - SPELL_WOUND_POISON = 65962, - - //Shaman En - SPELL_LAVA_LASH = 65974, - SPELL_STORMSTRIKE = 65970, - SPELL_WINDFURY = 65976, - SPELL_MALESTROM = 65986, - //Heroism - //Earth Shock - - SPELL_TOTEM_WIND = 39586, - SPELL_TOTEM_GROUND = 65989, - SPELL_TOTEM_HEAL = 71984, - SPELL_TOTEM_TREMOR = 65992, - SPELL_TOTEM_STR = 65991, - SPELL_TOTEM_SEARING = 39588, - - //Paladyn Retri - SPELL_AVENGING_WRATH = 66011, //3min cd - SPELL_STRIKE = 66003, //6sec cd - SPELL_STORM = 66006, //10sec cd - SPELL_JUDGEMENT_COMAND = 66005, //8sec cd - SPELL_REPENTANCE = 66008, //60sec cd - SPELL_SEAL_COMAND = 66004, //no cd - //SPELL_Divine_Shield = 66010, //5min cd - //SPELL_Hand_of_Protection = 66009, //5min cd - //SPELL_HAMMER_OF_JUSTICE = 66007, //40sec cd - - //Felhunter - SPELL_DEVOUR_MAGIC = 67518, - SPELL_SPELL_LOCK = 67519, - - //Cat - SPELL_CLAW = 67793, - - //Other - //SPELL_TRINKET = 65547, //5min cd - SPELL_HEROISM = 65983, - SPELL_BLOODLUST = 65980, - AURA_EXHAUSTION = 57723, - AURA_SATED = 57724, - SPELL_DIVINE_SHIELD = 63148, - SPELL_BLOCK = 45438, - - //NPC - NPC_FELHUNTER = 35465, - NPC_CAT = 35610, -}; - +/*##### +# Faction's Champions's shared AI +#####*/ struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI { boss_faction_championsAI(Creature* pCreature, uint32 aitype) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroicMode = (m_uiMapDifficulty == RAID_DIFFICULTY_10MAN_HEROIC || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); - mAIType = aitype; + currentDifficulty = pCreature->GetMap()->GetDifficulty(); + m_uiAIType = aitype; Init(); } ScriptedInstance* m_pInstance; - bool m_bIsHeroicMode; - Difficulty m_uiMapDifficulty; - uint32 mAIType; - uint32 UpdateTimer; - uint32 m_uiChangeTargetTimer; - uint32 m_uiInsygniaTimer; + uint32 m_uiAIType; + uint32 m_uiThreatTimer; + uint32 m_uiCCTimer; void Init() { - UpdateTimer = 5000; - m_uiChangeTargetTimer = 6000; - resetTimers(); - m_uiInsygniaTimer = urand(30*IN_MILLISECONDS, 60*IN_MILLISECONDS); + m_uiCCTimer = rand()%10000; + m_uiThreatTimer = 5000; + m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(DAY); } - void Reset() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_CRUSADERS, NOT_STARTED); - } - - void JustDied(Unit *killer) - { - if (m_pInstance) - m_pInstance->SetData(TYPE_CRUSADERS_COUNT, 0); - } - - void Aggro(Unit *who) - { - if (!m_pInstance) - return; - - m_pInstance->SetData(TYPE_CRUSADERS, IN_PROGRESS); - m_creature->CastSpell(m_creature, SPELL_ANTI_AOE, true); - if (who->GetTypeId() != TYPEID_PLAYER) - if (Unit* player = doSelectRandomPlayerAtRange(80.0f)) - m_creature->AddThreat(player, 100.0f); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (m_creature->Attack(pWho, true)) - { - m_creature->AddThreat(pWho); - m_creature->SetInCombatWith(pWho); - - if (mAIType == AI_MELEE) - m_creature->GetMotionMaster()->MoveChase(pWho); - else - DoStartMovement(pWho, 20.0f); - - if (mAIType == AI_HEALER) - m_creature->GetMotionMaster()->MoveChase(pWho); - - if (mAIType == AI_RANGED) - m_creature->GetMotionMaster()->MoveChase(pWho); - - SetCombatMovement(true); - } - } - void JustReachedHome() { if (m_pInstance) @@ -306,8 +71,8 @@ struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI float CalculateThreat(float distance, float armor, uint32 health) { - float dist_mod = (mAIType == AI_MELEE) ? 15.0f/(15.0f + distance) : 1.0f; - float armor_mod = (mAIType == AI_MELEE) ? armor / 16635.0f : 0.0f; + float dist_mod = (m_uiAIType == AI_MELEE) ? 15.0f/(15.0f + distance) : 1.0f; + float armor_mod = (m_uiAIType == AI_MELEE) ? armor / 16635.0f : 0.0f; float eh = (health+1) * (1.0f + armor_mod); return dist_mod * 30000.0f / eh; } @@ -317,12 +82,12 @@ struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI ThreatList const& tList = m_creature->getThreatManager().getThreatList(); ThreatList::const_iterator itr; bool empty = true; - for (itr = tList.begin(); itr!=tList.end(); ++itr) + for(itr = tList.begin(); itr!=tList.end(); ++itr) { Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); if (pUnit && m_creature->getThreatManager().getThreat(pUnit)) { - if (pUnit->GetTypeId()==TYPEID_PLAYER) + if(pUnit->GetTypeId()==TYPEID_PLAYER) { float threat = CalculateThreat(m_creature->GetDistance2d(pUnit), (float)pUnit->GetArmor(), pUnit->GetHealth()); m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); @@ -335,8 +100,10 @@ struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI void UpdatePower() { - if (m_creature->getPowerType() == POWER_MANA) + if(m_creature->getPowerType() == POWER_MANA) m_creature->ModifyPower(POWER_MANA, m_creature->GetMaxPower(POWER_MANA) / 3); + //else if(m_creature->getPowerType() == POWER_ENERGY) + // m_creature->ModifyPower(POWER_ENERGY, 100); } void RemoveCC() @@ -349,96 +116,109 @@ struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI //DoCast(m_creature, SPELL_PVP_TRINKET); } - //add - Unit* SelectEnemyTargetWithinMana() + void JustDied(Unit *killer) + { + if(m_pInstance) m_pInstance->SetData(TYPE_CRUSADERS_COUNT, 0); + } + + void Aggro(Unit *who) + { + if(!m_pInstance) + return; + m_pInstance->SetData(TYPE_CRUSADERS, IN_PROGRESS); + DoCast(m_creature, SPELL_ANTI_AOE, true); + + if(who->GetTypeId() != TYPEID_PLAYER) + if (Unit* player = doSelectRandomPlayerAtRange(80.0f)) + m_creature->AddThreat(player, 100.0f); + } + + void Reset() + { + if(m_pInstance) + m_pInstance->SetData(TYPE_CRUSADERS, NOT_STARTED); + } + + Creature* SelectRandomFriendlyMissingBuff(uint32 spell) + { + std::list lst = DoFindFriendlyMissingBuff(40.0f, spell); + std::list::const_iterator itr = lst.begin(); + if(lst.empty()) + return NULL; + advance(itr, rand()%lst.size()); + return (*itr); + } + + Unit* SelectEnemyCaster(bool casting) { ThreatList const& tList = m_creature->getThreatManager().getThreatList(); ThreatList::const_iterator iter; - for (iter = tList.begin(); iter!=tList.end(); ++iter) + for(iter = tList.begin(); iter!=tList.end(); ++iter) { Unit *target; - if (target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) - if (target->getPowerType() == POWER_MANA) + if(target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) + if(target->getPowerType() == POWER_MANA) return target; } return NULL; } - Unit* KillPlayer() + uint32 EnemiesInRange(float distance) { ThreatList const& tList = m_creature->getThreatManager().getThreatList(); ThreatList::const_iterator iter; - for (iter = tList.begin(); iter!=tList.end(); ++iter) + uint32 count = 0; + for(iter = tList.begin(); iter!=tList.end(); ++iter) { Unit *target; - if (target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) - if (target->GetHealthPercent() < 30.0f) - return target; + if(target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) + if(m_creature->GetDistance2d(target) < distance) + ++count; } - return NULL; + return count; } - Unit* SelectTargetWithinDist() + void AttackStart(Unit* pWho) { - ThreatList const& m_threatlist = m_creature->getThreatManager().getThreatList(); - - if (m_threatlist.empty()) - return NULL; + if (!pWho) + return; - GUIDList distPositive; - for (ThreatList::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + if (m_creature->Attack(pWho, true)) { - if (Unit* pTemp = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid())) - { - //player within 10 yards - if ((pTemp->GetTypeId() == TYPEID_PLAYER && !m_creature->IsWithinDist(pTemp, 1.0f) && m_creature->IsWithinDist(pTemp, 10.0f))) - distPositive.push_back(pTemp->GetObjectGuid()); - } - } + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); - if (!distPositive.empty()) - { - GUIDList::iterator m_uiPlayerGUID = distPositive.begin(); - advance(m_uiPlayerGUID, (rand()%distPositive.size())); + if(m_uiAIType==AI_MELEE) + DoStartMovement(pWho); + else + DoStartMovement(pWho, 20.0f); - if (Player* pTemp = m_creature->GetMap()->GetPlayer(*m_uiPlayerGUID)) - return pTemp; + SetCombatMovement(true); } - return NULL; } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (m_pInstance && m_pInstance->GetData(TYPE_CRUSADERS) != IN_PROGRESS) - m_creature->ForcedDespawn(); - - if (m_uiChangeTargetTimer < uiDiff) + if(m_uiThreatTimer < diff) { + UpdatePower(); UpdateThreat(); - m_uiChangeTargetTimer = 6000; + m_uiThreatTimer = 4000; } else - m_uiChangeTargetTimer -= uiDiff; + m_uiThreatTimer -= diff; - if (UpdateTimer < uiDiff) + if(m_uiCCTimer < diff) { - UpdatePower(); - UpdateTimer = 2000; + RemoveCC(); + m_uiCCTimer = 8000+rand()%2000; } else - UpdateTimer -= uiDiff; - - if (m_bIsHeroicMode) - { - if (m_uiInsygniaTimer < uiDiff) - { - RemoveCC(); - m_uiInsygniaTimer = 5*MINUTE*IN_MILLISECONDS; - } - else - m_uiInsygniaTimer -= uiDiff; - } + m_uiCCTimer -= diff; + if(m_uiAIType == AI_MELEE) + DoMeleeAttackIfReady(); } }; @@ -446,1226 +226,585 @@ struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI HEALERS ********************************************************************/ -/************** -** Druid Resto -***************/ +enum DruidHealSpells +{ + SPELL_LIFEBLOOM = 66093, + SPELL_NOURISH = 66066, + SPELL_REGROWTH = 66067, + SPELL_REJUVENATION = 66065, + SPELL_TRANQUILITY = 66086, + SPELL_BARKSKIN = 65860, //1 min cd + SPELL_THORNS = 66068, + SPELL_NATURE_GRASP = 66071 //1 min cd, self buff +}; + struct MANGOS_DLL_DECL mob_toc_druidAI : public boss_faction_championsAI { mob_toc_druidAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); + m_uiTranquillityTimer = 600000; + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiBarskinTimer; - uint32 m_uiNatureGraspTimer; - uint32 m_uiTranquilityTimer; - uint32 m_uiThornsTimer; - uint32 m_uiLifebloomTimer; - uint32 m_uiRejuvenationTimer; - uint32 m_uiCastHealTimer; - - void Reset() - { - m_uiBarskinTimer = 0; - m_uiNatureGraspTimer = urand(20*IN_MILLISECONDS, 80*IN_MILLISECONDS); - m_uiTranquilityTimer = 35*IN_MILLISECONDS; - m_uiThornsTimer = urand(25*IN_MILLISECONDS, 90*IN_MILLISECONDS); - m_uiLifebloomTimer = urand(2*IN_MILLISECONDS, 8*IN_MILLISECONDS); - m_uiRejuvenationTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiCastHealTimer = urand(3*IN_MILLISECONDS, 5*IN_MILLISECONDS); - + uint32 m_uiTranquillityTimer; + void Init() + { SetEquipmentSlots(false, 51799, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - } + boss_faction_championsAI::Init(); + } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiBarskinTimer < uiDiff) + timedCast(SPELL_NATURE_GRASP, diff); + + if(timedQuery(SPELL_BARKSKIN, diff)) + if(m_creature->GetHealthPercent() < 50.0f) + doCast(SPELL_BARKSKIN); + + if(timedQuery(SPELL_LIFEBLOOM, diff)) { - if (m_creature->GetHealthPercent() < 60.0f) + switch(urand(0,4)) { - m_creature->CastSpell(m_creature, SPELL_BARKSKIN, true); - m_uiBarskinTimer = 1*MINUTE*IN_MILLISECONDS; + case 0: + doCast(SPELL_LIFEBLOOM); + break; + case 1: + doCast(SPELL_NOURISH); + break; + case 2: + doCast(SPELL_REGROWTH); + break; + case 3: + doCast(SPELL_REJUVENATION); + break; + case 4: + if(Creature* target = SelectRandomFriendlyMissingBuff(SPELL_THORNS)) + doCast(SPELL_THORNS, target); + break; } } - else - m_uiBarskinTimer -= uiDiff; - if (m_uiNatureGraspTimer <= uiDiff) + if (m_uiTranquillityTimer < diff) { - DoCastSpellIfCan(m_creature, SPELL_NATURE_GRASP); - m_uiNatureGraspTimer = 1*MINUTE*IN_MILLISECONDS; + if (currentDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) + DoCast(m_creature, SPELL_TRANQUILITY); + m_uiTranquillityTimer = 600000; } else - m_uiNatureGraspTimer -= uiDiff; + m_uiTranquillityTimer -= diff; - if (m_uiThornsTimer < uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_THORNS); - m_uiThornsTimer = urand(25*IN_MILLISECONDS, 90*IN_MILLISECONDS); - } - else - m_uiThornsTimer -= uiDiff; + boss_faction_championsAI::UpdateAI(diff); + } +}; - if (m_uiTranquilityTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_TRANQUILITY) == CAST_OK) - { - m_uiTranquilityTimer = 10*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiTranquilityTimer -= uiDiff; +enum ShamanHealSpell +{ + SPELL_HEALING_WAVE = 66055, + SPELL_RIPTIDE = 66053, + SPELL_SPIRIT_CLEANSE = 66056, //friendly only + SPELL_HEROISM = 65983, + SPELL_BLOODLUST = 65980, + SPELL_HEX = 66054, + SPELL_EARTH_SHIELD = 66063, + SPELL_EARTH_SHOCK = 65973 +}; - if (m_uiLifebloomTimer < uiDiff) - { - if (Unit *target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_LIFEBLOOM); - m_uiLifebloomTimer = urand(5*IN_MILLISECONDS, 8*IN_MILLISECONDS); - } - } - else - m_uiLifebloomTimer -= uiDiff; +struct MANGOS_DLL_DECL mob_toc_shamanAI : public boss_faction_championsAI +{ + mob_toc_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) + { + Init(); + } - if (m_uiRejuvenationTimer < uiDiff) - { - if (Unit *target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_REJUVENATION); - m_uiRejuvenationTimer = urand(8*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - } - else - m_uiRejuvenationTimer -= uiDiff; + void Init() + { + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_HEROISM, diff); - if (m_uiCastHealTimer < uiDiff) + timedCast(SPELL_HEX, diff); + + if(timedQuery(SPELL_HEALING_WAVE, diff)) { - if (Unit *target = DoSelectLowestHpFriendly(40.0f)) + switch(urand(0,5)) { - switch(urand(0, 1)) - { - case 0: - DoCastSpellIfCan(target, SPELL_NOURISH); - m_uiCastHealTimer = 1500; - break; - case 1: - DoCastSpellIfCan(target, SPELL_REGROWTH); - m_uiCastHealTimer = urand(2500, 15000); - break; - } + case 0: case 1: + doCast(SPELL_HEALING_WAVE); + break; + case 2: + doCast(SPELL_RIPTIDE); + break; + case 3: + doCast(SPELL_EARTH_SHOCK); + break; + case 4: + doCast(SPELL_SPIRIT_CLEANSE); + break; + case 5: + if(Unit *target = SelectRandomFriendlyMissingBuff(SPELL_EARTH_SHIELD)) + doCast(target, SPELL_EARTH_SHIELD); + break; } - m_uiCastHealTimer = urand(8*IN_MILLISECONDS, 18*IN_MILLISECONDS); } - else - m_uiCastHealTimer -= uiDiff; - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/**************** -** Shaman Resto -*****************/ -struct MANGOS_DLL_DECL mob_toc_shamanAI : public boss_faction_championsAI +enum PaladinHealSpell +{ + SPELL_HAND_OF_FREEDOM = 68757, //25 sec cd + SPELL_BUBBLE = 66010, //5 min cd + SPELL_CLEANSE = 66116, + SPELL_FLASH_OF_LIGHT = 66113, + SPELL_HOLY_LIGHT = 66112, + SPELL_HOLY_SHOCK = 66114, + SPELL_HAND_OF_PROTECTION = 66009, + SPELL_HAMMER_OF_JUSTICE = 66613 +}; + +struct MANGOS_DLL_DECL mob_toc_paladinAI : public boss_faction_championsAI { - mob_toc_shamanAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) + mob_toc_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; + void Init() + { + SetEquipmentSlots(false, 50771, 47079, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); + } - uint32 m_uiHeroismOrBloodlustTimer; - uint32 m_uiHexTimer; - uint32 m_uiEartShockTimer; - uint32 m_uiHealingWaveTimer; - uint32 m_uiRiptideTimer; - uint32 m_uiEarthShieldTimer; + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - void Reset() + //cast bubble at 20% hp + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_BUBBLE, diff); + + if(Unit *target = DoSelectLowestHpFriendly(40.0f)) + if(target->GetHealthPercent() < 15.0f) + timedCast(SPELL_HAND_OF_PROTECTION, diff); + + timedCast(SPELL_HOLY_SHOCK, diff); + + if(Unit *target = SelectRandomFriendlyMissingBuff(SPELL_HAND_OF_FREEDOM)) + timedCast(SPELL_HAND_OF_FREEDOM, diff, target); + + timedCast(SPELL_HAMMER_OF_JUSTICE, diff); + + if(timedQuery(SPELL_FLASH_OF_LIGHT, diff)) + { + switch(urand(0,4)) + { + case 0: case 1: + doCast(SPELL_FLASH_OF_LIGHT); + break; + case 2: case 3: + doCast(SPELL_HOLY_LIGHT); + break; + case 4: + doCast(SPELL_CLEANSE); + break; + } + } + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +enum PriestHealSpell +{ + SPELL_RENEW = 66177, + SPELL_SHIELD = 66099, + SPELL_FLASH_HEAL = 66104, + SPELL_DISPEL = 65546, + SPELL_PSYCHIC_SCREAM = 65543, + SPELL_MANA_BURN = 66100 +}; + +struct MANGOS_DLL_DECL mob_toc_priestAI : public boss_faction_championsAI +{ + mob_toc_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) { - m_uiEarthShieldTimer = 0; - m_uiHexTimer = urand(10*IN_MILLISECONDS, 40*IN_MILLISECONDS); - m_uiEartShockTimer = urand(5*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiHealingWaveTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiRiptideTimer = urand(2*IN_MILLISECONDS, 8*IN_MILLISECONDS); - m_uiHeroismOrBloodlustTimer = 30*IN_MILLISECONDS; + Init(); + } + void Init() + { SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - } + boss_faction_championsAI::Init(); + } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiHeroismOrBloodlustTimer <= uiDiff) + if(EnemiesInRange(10.0f) > 2) + timedCast(SPELL_PSYCHIC_SCREAM, diff); + + if(timedQuery(SPELL_RENEW, diff)) { - if (m_creature->getFaction()) //Am i alliance? + switch(urand(0,5)) { - if (!m_creature->HasAura(AURA_EXHAUSTION)) - { - DoCastSpellIfCan(m_creature, SPELL_HEROISM); + case 0: + doCast(SPELL_RENEW); + break; + case 1: + doCast(SPELL_SHIELD); + break; + case 2: + case 3: + doCast(SPELL_FLASH_HEAL); + break; + case 4: + if(Unit *target = urand(0,1) ? m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0) : DoSelectLowestHpFriendly(40.0f)) + doCast(target, SPELL_DISPEL); + break; + case 5: + doCast(SPELL_MANA_BURN); + break; + } + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_1)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + boss_faction_championsAI::UpdateAI(diff); + } +}; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_3)) - pChampion->_AddAura(SPELL_HEROISM, 40000); +/******************************************************************** + RANGED +********************************************************************/ - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_4)) - pChampion->_AddAura(SPELL_HEROISM, 40000); +enum PriestDpsSpell +{ + SPELL_SILENCE = 65542, + SPELL_VAMPIRIC_TOUCH = 65490, + SPELL_SW_PAIN = 65541, + SPELL_MIND_FLAY = 65488, + SPELL_MIND_BLAST = 65492, + SPELL_HORROR = 65545, + SPELL_DISPERSION = 65544, + SPELL_SHADOWFORM = 16592 +}; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_5)) - pChampion->_AddAura(SPELL_HEROISM, 40000); +struct MANGOS_DLL_DECL mob_toc_shadow_priestAI : public boss_faction_championsAI +{ + mob_toc_shadow_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) + { + Init(); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_6)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + void Init() + { + SetEquipmentSlots(false, 50040, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_7)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + void Aggro(Unit *who) + { + boss_faction_championsAI::Aggro(who); + doCast(SPELL_SHADOWFORM); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_8)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_9)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + if(EnemiesInRange(10.0f) > 2) + timedCast(SPELL_PSYCHIC_SCREAM, diff); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_10)) - pChampion->_AddAura(SPELL_HEROISM, 40000); - - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_11)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_DISPERSION, diff); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_12)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + if(Unit *target = SelectEnemyCaster(false)) + timedCast(SPELL_SILENCE, diff, target); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_13)) - pChampion->_AddAura(SPELL_HEROISM, 40000); + timedCast(SPELL_MIND_BLAST, diff); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_1_14)) - pChampion->_AddAura(SPELL_HEROISM, 40000); - } - } - else + if(timedQuery(SPELL_MIND_FLAY, diff)) + { + switch(urand(0,4)) { - if (!m_creature->HasAura(AURA_SATED)) - { - DoCastSpellIfCan(m_creature, SPELL_BLOODLUST); + case 0: case 1: + doCast(SPELL_MIND_FLAY); + break; + case 2: + doCast(SPELL_VAMPIRIC_TOUCH); + break; + case 3: + doCast(SPELL_SW_PAIN); + break; + case 4: + doCast(SPELL_DISPEL); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } +}; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_1)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); +enum WarlockSpell +{ + SPELL_HELLFIRE = 65816, + SPELL_CORRUPTION = 65810, + SPELL_CURSE_OF_AGONY = 65814, + SPELL_CURSE_OF_EXHAUSTION = 65815, + SPELL_FEAR = 65809, //8s + SPELL_SEARING_PAIN = 65819, + SPELL_SHADOW_BOLT = 65821, + SPELL_UNSTABLE_AFFLICTION = 65812 //15s +}; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_3)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); +struct MANGOS_DLL_DECL mob_toc_warlockAI : public boss_faction_championsAI +{ + mob_toc_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) + { + Init(); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_4)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + void Init() + { + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_5)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_6)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + timedCast(SPELL_FEAR, diff); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_7)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + if(EnemiesInRange(10.0f) > 2) + timedCast(SPELL_HELLFIRE, diff); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_8)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + timedCast(SPELL_UNSTABLE_AFFLICTION, diff); - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_9)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + if(timedQuery(SPELL_SHADOW_BOLT, diff)) + { + switch(urand(0,5)) + { + case 0: + doCast(SPELL_SEARING_PAIN); + break; + case 1: case 2: + doCast(SPELL_SHADOW_BOLT); + break; + case 3: + doCast(SPELL_CORRUPTION); + break; + case 4: + doCast(SPELL_CURSE_OF_AGONY); + break; + case 5: + doCast(SPELL_CURSE_OF_EXHAUSTION); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } +}; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_10)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); - - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_11)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); +enum MageSpell +{ + SPELL_ARCANE_BARRAGE = 65799, //3s + SPELL_ARCANE_BLAST = 65791, + SPELL_ARCANE_EXPLOSION = 65800, + SPELL_BLINK = 65793, //15s + SPELL_COUNTERSPELL = 65790, //24s + SPELL_FROST_NOVA = 65792, //25s + SPELL_FROSTBOLT = 65807, + SPELL_ICE_BLOCK = 65802, //5min + SPELL_POLYMORPH = 65801 //15s +}; - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_12)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); +struct MANGOS_DLL_DECL mob_toc_mageAI : public boss_faction_championsAI +{ + mob_toc_mageAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) + { + Init(); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_13)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); + void Init() + { + SetEquipmentSlots(false, 47524, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); + } - if (Creature* pChampion = m_pInstance->GetSingleCreatureFromStorage(NPC_CRUSADER_2_14)) - pChampion->_AddAura(SPELL_BLOODLUST, 40000); - } - } - m_uiHeroismOrBloodlustTimer = 10*MINUTE*IN_MILLISECONDS; - } - else - m_uiHeroismOrBloodlustTimer -= uiDiff; + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - if (m_uiHexTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_HEX); - m_uiHexTimer = 45*IN_MILLISECONDS; - } - } - else - m_uiHexTimer -= uiDiff; + if(Unit *target = SelectEnemyCaster(false)) + timedCast(SPELL_COUNTERSPELL, diff, target); - if (m_uiEartShockTimer < uiDiff) + if(m_creature->GetHealthPercent() < 50.0f && EnemiesInRange(10.0f) > 3) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_EARTH_SHOCK); - m_uiEartShockTimer = urand(5*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } + timedCast(SPELL_FROST_NOVA, diff); + timedCast(SPELL_BLINK, diff); } - else - m_uiEartShockTimer -= uiDiff; - if (m_uiHealingWaveTimer < uiDiff) - { - if (Unit *target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_HEALING_WAVE); - m_uiHealingWaveTimer = urand(7*IN_MILLISECONDS, 12*IN_MILLISECONDS); - } - } - else - m_uiHealingWaveTimer -= uiDiff; + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_ICE_BLOCK, diff); - if (m_uiRiptideTimer < uiDiff) - { - if (Unit *target = DoSelectLowestHpFriendly(40.0f)) - { - switch(urand(0, 1)) - { - case 0: - m_creature->CastSpell(target, SPELL_RIPTIDE, false); - break; - case 1: - m_creature->CastSpell(target, SPELL_SPIRIT_CLEANSE , false); - break; - } - } - m_uiRiptideTimer = urand(6*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiRiptideTimer -= uiDiff; + timedCast(SPELL_POLYMORPH, diff); - if (m_uiEarthShieldTimer < uiDiff) + if(timedQuery(SPELL_ARCANE_BARRAGE, diff)) { - if (Unit *target = DoSelectLowestHpFriendly(40.0f)) + switch(urand(0,2)) { - DoCastSpellIfCan(target, SPELL_EARTH_SHIELD); - m_uiEarthShieldTimer = urand(10*IN_MILLISECONDS, 18*IN_MILLISECONDS); + case 0: + doCast(SPELL_ARCANE_BARRAGE); + break; + case 1: + doCast(SPELL_ARCANE_BLAST); + break; + case 2: + doCast(SPELL_FROSTBOLT); + break; } } - else - m_uiEarthShieldTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/*************** -** Paladin Holy -****************/ -struct MANGOS_DLL_DECL mob_toc_paladinAI : public boss_faction_championsAI + +enum HunterSpell { - mob_toc_paladinAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) - { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - bool m_bAttack; - - uint32 m_uiBubbleTimer; - uint32 m_uiHandOfProtectionTimer; - uint32 m_uiHolyShockTimer; - uint32 m_uiHandOfFreedomTimer; - uint32 m_uiHammerOfJusticeTimer; - uint32 m_uiHolyLightTimer; - uint32 m_uiFlashHealTimer; - - void Reset() - { - m_uiBubbleTimer = 0; - m_uiHandOfProtectionTimer = 0; - m_uiHolyShockTimer = urand(6*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiHandOfFreedomTimer = urand(25*IN_MILLISECONDS, 40*IN_MILLISECONDS); - m_uiHammerOfJusticeTimer = urand(5*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiHolyLightTimer = urand(8*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiFlashHealTimer = urand(2*IN_MILLISECONDS, 10*IN_MILLISECONDS); - - SetEquipmentSlots(false, 50771, 47079, EQUIP_NO_CHANGE); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiBubbleTimer <= uiDiff) - { - if (m_creature->GetHealthPercent() <= 25.0f) - { - DoCastSpellIfCan(m_creature, SPELL_BUBBLE); - m_uiBubbleTimer = 5*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiBubbleTimer -= uiDiff; - - if (m_uiHammerOfJusticeTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMMER_OF_JUSTICE); - m_uiHammerOfJusticeTimer = 40*IN_MILLISECONDS; - } - else - m_uiHammerOfJusticeTimer -= uiDiff; - - if (m_uiHandOfProtectionTimer <= uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - if (target->GetHealthPercent() <= 20.0f) - { - DoCastSpellIfCan(target, SPELL_HAND_OF_PROTECTION); - m_uiHandOfProtectionTimer = 5*MINUTE*IN_MILLISECONDS; - } - } - } - else - m_uiHandOfProtectionTimer -= uiDiff; - - if (m_uiHandOfFreedomTimer <= uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_HAND_OF_FREEDOM); - m_uiHandOfFreedomTimer = 25*IN_MILLISECONDS; - } - } - else - m_uiHandOfFreedomTimer -= uiDiff; - - if (m_uiHolyLightTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_HOLY_LIGHT); - m_uiHolyLightTimer = urand(9*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - } - else - m_uiHolyLightTimer -= uiDiff; - - if (m_uiFlashHealTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_FLASH_HEAL); - m_uiFlashHealTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - } - } - else - m_uiFlashHealTimer -= uiDiff; - - if (m_uiHolyShockTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_HOLY_SHOCK); - m_uiHolyShockTimer = urand(6*IN_MILLISECONDS, 16*IN_MILLISECONDS); - } - } - else - m_uiHolyShockTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); - } + SPELL_AIMED_SHOT = 65883, + SPELL_DETERRENCE = 65871, //90s + SPELL_DISENGAGE = 65869, //30s + SPELL_EXPLOSIVE_SHOT = 65866, + SPELL_FROST_TRAP = 65880, //30s + SPELL_SHOOT = 65868, //1.7s + SPELL_STEADY_SHOT = 65867, //3s + SPELL_WING_CLIP = 66207, //6s + SPELL_WYVERN_STING = 65877 //60s }; -/************** -** Priest Disc -***************/ -struct MANGOS_DLL_DECL mob_toc_priestAI : public boss_faction_championsAI -{ - mob_toc_priestAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) - { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiPeananceTimer; - uint32 m_uiRenewTimer; - uint32 m_uiShieldTimer; - uint32 m_uiFlashHealTimer; - uint32 m_uiPsychicScreamTimer; - //uint32 m_uiManaBurnTimer; - - void Reset() - { - m_uiPsychicScreamTimer = urand(8*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiPeananceTimer = urand(3*IN_MILLISECONDS, 12*IN_MILLISECONDS); - m_uiRenewTimer = urand(2*IN_MILLISECONDS, 16*IN_MILLISECONDS); - m_uiShieldTimer = 0; - m_uiFlashHealTimer = urand(6*IN_MILLISECONDS, 10*IN_MILLISECONDS); - //m_uiManaBurnTimer = urand(6*IN_MILLISECONDS, 16*IN_MILLISECONDS); - - SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiPeananceTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - if (DoCastSpellIfCan(target, SPELL_PEANANCE) == CAST_OK) - { - m_uiPeananceTimer = urand(6*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - } - } - else - m_uiPeananceTimer -= uiDiff; - - if (m_uiRenewTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_RENEW); - m_uiRenewTimer = urand(10*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - } - else - m_uiRenewTimer -= uiDiff; - - if (m_uiShieldTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_SHIELD); - m_uiShieldTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - } - else - m_uiShieldTimer -= uiDiff; - - if (m_uiFlashHealTimer < uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - DoCastSpellIfCan(target, SPELL_FLASH_HEAL_P); - m_uiFlashHealTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - } - } - else - m_uiFlashHealTimer -= uiDiff; - - if (m_uiPsychicScreamTimer < uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_DISPEL, true); - DoCastSpellIfCan(m_creature->getVictim(), SPELL_PSYCHIC_SCREAM); - m_uiPsychicScreamTimer = 30*IN_MILLISECONDS; - } - else - m_uiPsychicScreamTimer -= uiDiff; - - /*if(m_uiManaBurnTimer < uiDiff) - { - if (Unit* pTarget = SelectEnemyTargetWithinMana()) - { - DoCastSpellIfCan(pTarget, SPELL_MANA_BURN); - m_uiManaBurnTimer = urand(6000, 15000); - } - }else m_uiManaBurnTimer -= uiDiff;*/ - - boss_faction_championsAI::UpdateAI(uiDiff); - } -}; - -/**************************************************** - Ranged -*****************************************************/ - -/********************* -** Priest Shadow -**********************/ -struct MANGOS_DLL_DECL mob_toc_shadow_priestAI : public boss_faction_championsAI +struct MANGOS_DLL_DECL mob_toc_hunterAI : public boss_faction_championsAI { - mob_toc_shadow_priestAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) + mob_toc_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiDispersionTimer; - uint32 m_uiBlastTimer; - uint32 m_uiSilenceTimer; - uint32 m_uiHorrorTimer; - uint32 m_uiFearTimer; - uint32 m_uiDispelTimer; - uint32 m_uiTouchTimer; - uint32 m_uiMindFlayTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() + void Init() { - m_uiDispersionTimer = 0; - m_uiBlastTimer = urand(1*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiHorrorTimer = urand(3*IN_MILLISECONDS, 30*IN_MILLISECONDS); - m_uiFearTimer = urand(4*IN_MILLISECONDS, 19*IN_MILLISECONDS); - m_uiDispelTimer = urand(8*IN_MILLISECONDS, 11*IN_MILLISECONDS); - m_uiTouchTimer = urand(6*IN_MILLISECONDS, 18*IN_MILLISECONDS); - m_uiMindFlayTimer = urand(7*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiSilenceTimer = urand(9*IN_MILLISECONDS, 25*IN_MILLISECONDS); - m_uiKillPlayerTimer = 0; - - SetEquipmentSlots(false, 50040, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + SetEquipmentSlots(false, 47156, EQUIP_NO_CHANGE, 48711); + boss_faction_championsAI::Init(); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_MIND_BLAST, false); - m_creature->CastSpell(target, SPELL_MIND_FLAY, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; + if(EnemiesInRange(10.0f) > 3) + timedCast(SPELL_DISENGAGE, diff); - if (m_uiDispersionTimer < uiDiff) - { - if (m_creature->GetHealthPercent() <= 20.0f) - { - m_creature->CastSpell(m_creature, SPELL_DISPERSION, true); - m_uiDispersionTimer = 90*IN_MILLISECONDS; - } - } - else - m_uiDispersionTimer -= uiDiff; + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_DETERRENCE, diff); - if (m_uiHorrorTimer < uiDiff) - { - if (Unit *target = SelectTargetWithinDist()) - { - DoCastSpellIfCan(target, SPELL_HORROR); - m_uiHorrorTimer = 2*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiHorrorTimer -= uiDiff; + timedCast(SPELL_WYVERN_STING, diff); - if (m_uiFearTimer < uiDiff) - { - if (Unit *target = SelectTargetWithinDist()) - { - DoCastSpellIfCan(m_creature, SPELL_PSYCHIC_SCREAM); - m_uiFearTimer = urand(20*IN_MILLISECONDS, 35*IN_MILLISECONDS); - } - } - else - m_uiFearTimer -= uiDiff; + timedCast(SPELL_FROST_TRAP, diff ); - if (m_uiDispelTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_DISPEL); - m_uiDispelTimer = urand(2*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - else - m_uiDispelTimer -= uiDiff; - - if (m_uiTouchTimer < uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_SW_PAIN, true); - m_creature->CastSpell(m_creature->getVictim(), SPELL_VAMPIRIC_TOUCH, false); - m_uiTouchTimer = urand(5*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - else - m_uiTouchTimer -= uiDiff; - - if (m_uiBlastTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_BLAST); - m_uiBlastTimer = urand(8*IN_MILLISECONDS, 16*IN_MILLISECONDS); - } - else - m_uiBlastTimer -= uiDiff; - - if (m_uiMindFlayTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_FLAY); - m_uiMindFlayTimer = urand(9*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiMindFlayTimer -= uiDiff; + if(m_creature->GetDistance2d(m_creature->getVictim()) < 5.0f) + timedCast(SPELL_WING_CLIP, diff); - if (m_uiSilenceTimer < uiDiff) + if(timedQuery(SPELL_SHOOT, diff)) { - if (Unit *target = SelectEnemyTargetWithinMana()) + switch(urand(0,3)) { - DoCastSpellIfCan(target, SPELL_SILENCE); - m_uiSilenceTimer = 45*IN_MILLISECONDS; + case 0: case 1: + doCast(SPELL_SHOOT); + break; + case 2: + doCast(SPELL_EXPLOSIVE_SHOT); + break; + case 3: + doCast(SPELL_AIMED_SHOT); + break; } } - else - m_uiSilenceTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; - -/************ -** Warlock -*************/ -struct MANGOS_DLL_DECL mob_toc_warlockAI : public boss_faction_championsAI +enum DruipDpsSpell { - mob_toc_warlockAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) - { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiHelfireTimer; - uint32 m_uiFearTimer; - uint32 m_uiUnstableTimer; - uint32 m_uiSearingPainTimer; - uint32 m_uiCoruptionTimer; - uint32 m_uiExhaustTimer; - uint32 m_uiAgonyTimer; - uint32 m_uiShadowBoltTimer; - uint32 m_uiSummonTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() - { - m_uiHelfireTimer = urand(30*IN_MILLISECONDS, 48*IN_MILLISECONDS); - m_uiFearTimer = urand(15*IN_MILLISECONDS, 22*IN_MILLISECONDS); - m_uiUnstableTimer = urand(9*IN_MILLISECONDS, 18*IN_MILLISECONDS); - m_uiSearingPainTimer = urand(5*IN_MILLISECONDS, 9*IN_MILLISECONDS); - m_uiCoruptionTimer = urand(2*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiExhaustTimer = urand(1*IN_MILLISECONDS, 13*IN_MILLISECONDS); - m_uiAgonyTimer = urand(3*IN_MILLISECONDS, 12*IN_MILLISECONDS); - m_uiShadowBoltTimer = urand(6*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiSummonTimer = 0; - m_uiKillPlayerTimer = 0; - - SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - } - - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_FEAR, false); - m_creature->CastSpell(target, SPELL_SHADOW_BOLT, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - if (m_uiHelfireTimer < uiDiff) - { - if (Unit *target = SelectTargetWithinDist()) - { - DoCastSpellIfCan(m_creature, SPELL_HELLFIRE); - m_uiHelfireTimer = 45*IN_MILLISECONDS; - } - } - else - m_uiHelfireTimer -= uiDiff; - - if (m_uiCoruptionTimer < uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_UNSTABLE, false); - m_creature->CastSpell(m_creature->getVictim(), SPELL_CURSE_OF_AGONY, true); - m_creature->CastSpell(m_creature->getVictim(), SPELL_CURSE_OF_EXHAUSTION, true); - m_creature->CastSpell(m_creature->getVictim(), SPELL_CORRUPTION, true); - m_uiCoruptionTimer = urand(8*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiCoruptionTimer -= uiDiff; - - if (m_uiSearingPainTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_SEARING_PAIN); - m_uiSearingPainTimer = urand(6*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - else - m_uiSearingPainTimer -= uiDiff; - - if (m_uiFearTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_FEAR); - m_uiFearTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - else - m_uiFearTimer -= uiDiff; - - if (m_uiShadowBoltTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOW_BOLT); - m_uiShadowBoltTimer = urand(4*IN_MILLISECONDS, 10*IN_MILLISECONDS); - } - else - m_uiShadowBoltTimer -= uiDiff; - - if (m_uiSummonTimer < uiDiff) - { - m_creature->SummonCreature(NPC_FELHUNTER, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0); - m_uiSummonTimer = 10*MINUTE*IN_MILLISECONDS; - } - else - m_uiSummonTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); - } + SPELL_CYCLONE = 65859, //6s + SPELL_ENTANGLING_ROOTS = 65857, //10s + SPELL_FAERIE_FIRE = 65863, + SPELL_FORCE_OF_NATURE = 65861, //180s + SPELL_INSECT_SWARM = 65855, + SPELL_MOONFIRE = 65856, //5s + SPELL_STARFIRE = 65854, + SPELL_WRATH = 65862 }; -/******** -** Mage -*********/ -struct MANGOS_DLL_DECL mob_toc_mageAI : public boss_faction_championsAI -{ - mob_toc_mageAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) - { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiBarrageTimer; - uint32 m_uiBlastTimer; - uint32 m_uiExplosionTimer; - uint32 m_uiCounterSpellTimer; - uint32 m_uiNovaTimer; - uint32 m_uiBlinkTimer; - uint32 m_uiPolymorphTimer; - uint32 m_uiIceBlockTimer; - uint32 m_uiFrostboltTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() - { - m_uiBarrageTimer = urand(2*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiBlastTimer = urand(8*IN_MILLISECONDS, 19*IN_MILLISECONDS); - m_uiExplosionTimer = urand(10*IN_MILLISECONDS, 18*IN_MILLISECONDS); - m_uiCounterSpellTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - m_uiBlinkTimer = urand(7*IN_MILLISECONDS, 12*IN_MILLISECONDS); - m_uiIceBlockTimer = 0; - m_uiPolymorphTimer = urand(2*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiFrostboltTimer = urand(1*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiKillPlayerTimer = 0; - - SetEquipmentSlots(false, 47524, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_CS, false); - m_creature->CastSpell(target, SPELL_BARRAGE, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - if (m_uiBarrageTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_BARRAGE); - m_uiBarrageTimer = urand(4*IN_MILLISECONDS, 10*IN_MILLISECONDS); - } - else - m_uiBarrageTimer -= uiDiff; - - if (m_uiBlastTimer < uiDiff) - { - for (uint32 i = 1; i < 3; ++i) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_BLAST); - m_uiBlastTimer = urand(4*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - } - } - else - m_uiBlastTimer -= uiDiff; - - if (m_uiExplosionTimer < uiDiff) - { - if (m_creature->IsWithinDist(m_creature->getVictim(), 10.0f)) - { - DoCastSpellIfCan(m_creature, SPELL_EXPLOSION); - m_uiExplosionTimer = urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - } - else - m_uiExplosionTimer -= uiDiff; - - if (m_uiBlinkTimer < uiDiff) - { - if (m_creature->IsWithinDist(m_creature->getVictim(), 5.0f)) - { - m_creature->CastSpell(m_creature, SPELL_FROST_NOVA, true); - m_creature->CastSpell(m_creature, SPELL_BLINK, true); - m_uiBlinkTimer = urand(25*IN_MILLISECONDS, 35*IN_MILLISECONDS); - } - } - else - m_uiBlinkTimer -= uiDiff; - - if (m_uiCounterSpellTimer < uiDiff) - { - if (Unit* pTarget = SelectEnemyTargetWithinMana()) - { - DoCastSpellIfCan(pTarget, SPELL_CS); - m_uiCounterSpellTimer = 24*IN_MILLISECONDS; - } - } - else - m_uiCounterSpellTimer -= uiDiff; - - if (m_uiFrostboltTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROSTBOLT); - m_uiFrostboltTimer = urand(3*IN_MILLISECONDS, 8*IN_MILLISECONDS); - } - else - m_uiFrostboltTimer -= uiDiff; - - if (m_uiIceBlockTimer < uiDiff) - { - if (m_creature->GetHealthPercent() <= 20.0f) - { - m_creature->CastSpell(m_creature, SPELL_ICE_BLOCK, true); - m_uiIceBlockTimer = 3*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiIceBlockTimer -= uiDiff; - - if (m_uiPolymorphTimer <= uiDiff) - { - if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_POLY); - m_uiPolymorphTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - } - else - m_uiPolymorphTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); - } -}; - -/********** -** Hunter -***********/ -struct MANGOS_DLL_DECL mob_toc_hunterAI : public boss_faction_championsAI -{ - mob_toc_hunterAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) - { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiAimedShotTimer; - uint32 m_uiDeterenceTimer; - uint32 m_uiLeapTimer; - uint32 m_uiExplosivShotTimer; - uint32 m_uiFrostTrapTimer; - uint32 m_uiSteadyShotTimer; - uint32 m_uiWingClipTimer; - uint32 m_uiWyvernStingTimer; - uint32 m_uiSummonTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() - { - m_uiAimedShotTimer = urand(2*IN_MILLISECONDS, 5*IN_MILLISECONDS); - m_uiDeterenceTimer = 0; - m_uiLeapTimer = urand(25*IN_MILLISECONDS, 45*IN_MILLISECONDS); - m_uiExplosivShotTimer = urand(4*IN_MILLISECONDS, 6*IN_MILLISECONDS); - m_uiFrostTrapTimer = urand(15*IN_MILLISECONDS, 8*IN_MILLISECONDS); - m_uiSteadyShotTimer = urand(6*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiWingClipTimer = urand(10*IN_MILLISECONDS, 20*IN_MILLISECONDS); - m_uiWyvernStingTimer = urand(25*IN_MILLISECONDS, 35*IN_MILLISECONDS); - m_uiSummonTimer = 0; - m_uiKillPlayerTimer = 0; - - SetEquipmentSlots(false, 47156, EQUIP_NO_CHANGE, 48711); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_EXPLOSIVE_SHOT, false); - m_creature->CastSpell(target, SPELL_AIMED_SHOT, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS;; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - if (m_uiAimedShotTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_AIMED_SHOT); - m_uiAimedShotTimer = urand(7*IN_MILLISECONDS, 10*IN_MILLISECONDS); - } - } - else - m_uiAimedShotTimer -= uiDiff; - - if (m_uiDeterenceTimer < uiDiff) - { - if (m_creature->GetHealthPercent() <= 20.0f) - { - m_creature->CastSpell(m_creature, SPELL_DETERENCE, true); - m_uiDeterenceTimer = 90*IN_MILLISECONDS; - } - } - else - m_uiDeterenceTimer -= uiDiff; - - if (m_uiLeapTimer < uiDiff) - { - if (m_creature->IsWithinDist(m_creature->getVictim(), 5.0f)) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_WING_CLIP, true); - m_creature->CastSpell(m_creature, SPELL_DISENGAGE, true); - m_uiLeapTimer = urand(35*IN_MILLISECONDS, 45*IN_MILLISECONDS); - } - } - else - m_uiLeapTimer -= uiDiff; - - if (m_uiExplosivShotTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_EXPLOSIVE_SHOT); - m_uiExplosivShotTimer = urand(4*IN_MILLISECONDS, 8*IN_MILLISECONDS); - } - else - m_uiExplosivShotTimer -= uiDiff; - - if (m_uiSteadyShotTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STEADY_SHOT); - m_uiSteadyShotTimer = urand(3*IN_MILLISECONDS, 12*IN_MILLISECONDS); - } - else - m_uiSteadyShotTimer -= uiDiff; - - if (m_uiFrostTrapTimer < uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_FROST_TRAP); - m_uiFrostTrapTimer = 1*MINUTE*IN_MILLISECONDS; - } - else - m_uiFrostTrapTimer -= uiDiff; - - if (m_uiWyvernStingTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_WYVERN_STING); - m_uiWyvernStingTimer = 2*MINUTE*IN_MILLISECONDS; - } - else - m_uiWyvernStingTimer -= uiDiff; - - if (m_uiSummonTimer < uiDiff) - { - m_creature->SummonCreature(NPC_CAT, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0); - m_uiSummonTimer = 10*MINUTE*IN_MILLISECONDS; - } - else - m_uiSummonTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); - } -}; - - - -/***************** -** Druid Balance -******************/ struct MANGOS_DLL_DECL mob_toc_boomkinAI : public boss_faction_championsAI { - mob_toc_boomkinAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) + mob_toc_boomkinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiCycloneTimer; - uint32 m_uiFearieFeralTimer; - uint32 m_uiForcedTimer; - uint32 m_uiSpellTimer; - uint32 m_uiMonfireTimer; - uint32 m_uiStarfireTimer; - uint32 m_uiWrathTimer; - uint32 m_uiRootsTimer; - uint32 m_uiBarkskinTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() - { - m_uiCycloneTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - m_uiFearieFeralTimer = 0; - m_uiForcedTimer = urand(35*IN_MILLISECONDS, 45*IN_MILLISECONDS); - m_uiSpellTimer = urand(6*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiStarfireTimer = urand(8*IN_MILLISECONDS, 19*IN_MILLISECONDS); - m_uiWrathTimer = urand(3*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiBarkskinTimer = 0; - m_uiRootsTimer = urand(10*IN_MILLISECONDS, 18*IN_MILLISECONDS); - m_uiKillPlayerTimer = 0; - + void Init() + { SetEquipmentSlots(false, 50966, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - } + boss_faction_championsAI::Init(); + } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_WRATH, false); - m_creature->CastSpell(target, SPELL_MOONFIRE, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; + if(m_creature->GetHealthPercent() < 50.0f) + timedCast(SPELL_BARKSKIN, diff); - if (m_uiBarkskinTimer < uiDiff) - { - if (m_creature->GetHealthPercent() <= 50.0f) - { - m_creature->CastSpell(m_creature, SPELL_BARKSKIN, true); - m_uiBarkskinTimer = 1*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiBarkskinTimer -= uiDiff; + timedCast(SPELL_CYCLONE, diff); - if (m_uiCycloneTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - { - DoCastSpellIfCan(pTarget, SPELL_CYCLONE); - m_uiCycloneTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - } - else - m_uiCycloneTimer -= uiDiff; + timedCast(SPELL_ENTANGLING_ROOTS, diff); - if (m_uiFearieFeralTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_FEARIE); - m_uiFearieFeralTimer = urand(25*IN_MILLISECONDS, 60*IN_MILLISECONDS); - } - else - m_uiFearieFeralTimer -= uiDiff; + timedCast(SPELL_FAERIE_FIRE, diff); - if (m_uiForcedTimer < uiDiff) + if(timedQuery(SPELL_MOONFIRE, diff)) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_FORCED_OF_NATURE); - m_uiForcedTimer = 90*IN_MILLISECONDS; - } - else - m_uiForcedTimer -= uiDiff; - - if (m_uiSpellTimer < uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_MOONFIRE, true); - m_creature->CastSpell(m_creature->getVictim(), SPELL_SWARM, true); - m_uiSpellTimer = urand(10*IN_MILLISECONDS, 20*IN_MILLISECONDS); - } - else - m_uiSpellTimer -= uiDiff; - - if (m_uiStarfireTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STARFIRE); - m_uiStarfireTimer = urand(8*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - else - m_uiStarfireTimer -= uiDiff; - - if (m_uiWrathTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_WRATH); - m_uiWrathTimer = urand(4*IN_MILLISECONDS, 8*IN_MILLISECONDS); - } - else - m_uiWrathTimer -= uiDiff; - - if (m_uiRootsTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_ROOTS_B); - m_uiRootsTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); + switch(urand(0,6)) + { + case 0: case 1: + doCast(SPELL_MOONFIRE); + break; + case 2: + doCast(SPELL_INSECT_SWARM); + break; + case 3: + doCast(SPELL_STARFIRE); + break; + case 4: case 5: case 6: + doCast(SPELL_WRATH); + break; + } } - else - m_uiRootsTimer -= uiDiff; - - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; @@ -1673,848 +812,306 @@ struct MANGOS_DLL_DECL mob_toc_boomkinAI : public boss_faction_championsAI MELEE ********************************************************************/ -/*********** -** Warrior -************/ +enum WarriorSpell +{ + SPELL_BLADESTORM = 65947, + SPELL_INTIMIDATING_SHOUT = 65930, + SPELL_MORTAL_STRIKE = 65926, + SPELL_CHARGE = 68764, + SPELL_DISARM = 65935, + SPELL_OVERPOWER = 65924, + SPELL_SUNDER_ARMOR = 65936, + SPELL_SHATTERING_THROW = 65940, + SPELL_RETALIATION = 65932 +}; + struct MANGOS_DLL_DECL mob_toc_warriorAI : public boss_faction_championsAI { - mob_toc_warriorAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) + mob_toc_warriorAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiBladestormTimer; - uint32 m_uiIntimidatingShoutTimer; - uint32 m_uiMortalStrikeTimer; - uint32 m_uiSunderArmorTimer; - uint32 m_uiChargeTimer; - uint32 m_uiRetaliationTimer; - uint32 m_uiOverpowerTimer; - uint32 m_uiShatteringThrowTimer; - uint32 m_uiDisarmTimer; - uint32 m_uiRemoveBubleTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() + void Init() { - m_uiBladestormTimer = urand(35*IN_MILLISECONDS, 45*IN_MILLISECONDS); - m_uiChargeTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - m_uiIntimidatingShoutTimer = urand(25*IN_MILLISECONDS, 35*IN_MILLISECONDS); - m_uiMortalStrikeTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiSunderArmorTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - m_uiRetaliationTimer = urand(45*IN_MILLISECONDS, 55*IN_MILLISECONDS); - m_uiOverpowerTimer = urand(8*IN_MILLISECONDS, 8*IN_MILLISECONDS); - m_uiShatteringThrowTimer = urand(50*IN_MILLISECONDS, 55*IN_MILLISECONDS); - m_uiDisarmTimer = urand(15*IN_MILLISECONDS, 35*IN_MILLISECONDS); - m_uiRemoveBubleTimer = 0; - m_uiKillPlayerTimer = 0; - SetEquipmentSlots(false, 47427, 46964, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); } - // Its not good idea - Unit* SelectPlayerWithDivineShield() + void UpdateAI(const uint32 diff) { - ThreatList const& tList = m_creature->getThreatManager().getThreatList(); - ThreatList::const_iterator iter; - for (iter = tList.begin(); iter!=tList.end(); ++iter) - { - Unit *target; - if (target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) - if (target->HasAura(SPELL_DIVINE_SHIELD)) - return target; - } - return NULL; - } - - // Its not good idea - Unit* SelectPlayerWithIceBlock() - { - ThreatList const& tList = m_creature->getThreatManager().getThreatList(); - ThreatList::const_iterator iter; - for (iter = tList.begin(); iter!=tList.end(); ++iter) - { - Unit *target; - if (target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) - if (target->HasAura(SPELL_ICE_BLOCK)) - return target; - } - return NULL; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_INTIMIDATING_SHOUT, false); - m_creature->CastSpell(target, SPELL_BLADESTORM, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - // Its bad solution but work - if (m_uiRemoveBubleTimer < uiDiff) - { - if (Unit *target = SelectPlayerWithDivineShield()) - { - DoCastSpellIfCan(target, SPELL_SHATTERING_THROW); + timedCast(SPELL_BLADESTORM, diff); - if (target->HasAura(SPELL_SHATTERING_THROW)) - { - target->RemoveAurasDueToSpell(SPELL_DIVINE_SHIELD); - } - } - if (Unit *target = SelectPlayerWithIceBlock()) - { - DoCastSpellIfCan(target, SPELL_SHATTERING_THROW); - - if (target->HasAura(SPELL_SHATTERING_THROW)) - { - target->RemoveAurasDueToSpell(SPELL_ICE_BLOCK); - } - } - m_uiRemoveBubleTimer = 10*IN_MILLISECONDS; - } - else - m_uiRemoveBubleTimer -= uiDiff; - - if (m_uiBladestormTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_BLADESTORM); - m_uiBladestormTimer = 90*IN_MILLISECONDS; - } - else - m_uiBladestormTimer -= uiDiff; - - if (m_uiChargeTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_CHARGE); - m_uiChargeTimer = urand(15*IN_MILLISECONDS, 20*IN_MILLISECONDS); - } - } - else - m_uiChargeTimer -= uiDiff; - - if (m_uiIntimidatingShoutTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_INTIMIDATING_SHOUT); - m_uiIntimidatingShoutTimer = 2*MINUTE*IN_MILLISECONDS; - } - else - m_uiIntimidatingShoutTimer -= uiDiff; - - if (m_uiMortalStrikeTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_STRIKE); - m_uiMortalStrikeTimer = urand(10*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiMortalStrikeTimer -= uiDiff; + timedCast(SPELL_INTIMIDATING_SHOUT, diff); - if (m_uiSunderArmorTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUNDER_ARMOR); - m_uiSunderArmorTimer = urand(10*IN_MILLISECONDS, 14*IN_MILLISECONDS); - } - else - m_uiSunderArmorTimer -= uiDiff; + timedCast(SPELL_MORTAL_STRIKE, diff); - if (m_uiRetaliationTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_RETALIATION); - m_uiRetaliationTimer = 5*MINUTE*IN_MILLISECONDS; - } - else - m_uiRetaliationTimer -= uiDiff; + timedCast(SPELL_SUNDER_ARMOR, diff); - if (m_uiOverpowerTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_OVERPOWER); - m_uiOverpowerTimer = urand(8*IN_MILLISECONDS, 12*IN_MILLISECONDS); - } - else - m_uiOverpowerTimer -= uiDiff; + timedCast(SPELL_CHARGE, diff); - if (m_uiDisarmTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_DISARM); - m_uiDisarmTimer = 40*IN_MILLISECONDS; - } - else - m_uiDisarmTimer -= uiDiff; + timedCast(SPELL_RETALIATION, diff); - if (m_uiShatteringThrowTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_SHATTERING_THROW); - m_uiShatteringThrowTimer = 5*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiShatteringThrowTimer -= uiDiff; + timedCast(SPELL_OVERPOWER, diff); + + timedCast(SPELL_SHATTERING_THROW, diff); - DoMeleeAttackIfReady(); + timedCast(SPELL_DISARM, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/******* -** DK -********/ -struct MANGOS_DLL_DECL mob_toc_dkAI : public boss_faction_championsAI +enum DeathKSpell +{ + SPELL_CHAINS_OF_ICE = 66020, //8sec + SPELL_DEATH_COIL = 66019, //5sec + SPELL_DEATH_GRIP = 66017, //35sec + SPELL_FROST_STRIKE = 66047, //6sec + SPELL_ICEBOUND_FORTITUDE = 66023, //1min + SPELL_ICY_TOUCH = 66021, //8sec + SPELL_STRANGULATE = 66018 //2min +}; + +struct MANGOS_DLL_DECL mob_toc_dkAI : public boss_faction_championsAI { - mob_toc_dkAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) + mob_toc_dkAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiIceboundFortitudeTimer; - uint32 m_uiChainsOfIceTimer; - uint32 m_uiDeathCoilTimer; - uint32 m_uiSilenceTimer; - uint32 m_uiFrostStrikeTimer; - uint32 m_uiIcyTouchTimer; - uint32 m_uiDeathGripTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() + void Init() { - m_uiChainsOfIceTimer = urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiDeathCoilTimer = urand(8*IN_MILLISECONDS, 12*IN_MILLISECONDS); - m_uiSilenceTimer = urand(25*IN_MILLISECONDS, 40*IN_MILLISECONDS); - m_uiFrostStrikeTimer = urand(7*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiIcyTouchTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiDeathGripTimer = urand(15*IN_MILLISECONDS, 20*IN_MILLISECONDS); - m_uiIceboundFortitudeTimer = 0; - m_uiKillPlayerTimer = 0; - SetEquipmentSlots(false, 47518, 51021, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_CHAINS, false); - m_creature->CastSpell(target, SPELL_DEATH_COLI, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - if (m_uiIceboundFortitudeTimer < uiDiff) - { - if (m_creature->GetHealthPercent() < 50.0f) - { - m_creature->CastSpell(m_creature, SPELL_ICEBOUND, true); - m_uiIceboundFortitudeTimer = 2*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiIceboundFortitudeTimer -= uiDiff; - - if (m_uiChainsOfIceTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_CHAINS); - m_uiChainsOfIceTimer = urand(15*IN_MILLISECONDS, 20*IN_MILLISECONDS); - } - } - else - m_uiChainsOfIceTimer -= uiDiff; + if(m_creature->GetHealthPercent() < 50.0f) + timedCast(SPELL_ICEBOUND_FORTITUDE, diff); - if (m_uiDeathCoilTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_DEATH_COLI); - m_uiDeathCoilTimer = urand(8*IN_MILLISECONDS, 14*IN_MILLISECONDS); - } - else - m_uiDeathCoilTimer -= uiDiff; + timedCast(SPELL_CHAINS_OF_ICE, diff); - if (m_uiSilenceTimer < uiDiff) - { - if (Unit *target = SelectEnemyTargetWithinMana()) - { - DoCastSpellIfCan(target, SPELL_STRANGULATE); - m_uiSilenceTimer = 2*IN_MILLISECONDS; - } - } - else - m_uiSilenceTimer -= uiDiff; + timedCast(SPELL_DEATH_COIL, diff); - if (m_uiFrostStrikeTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROST_STRIKE); - m_uiFrostStrikeTimer = urand(8*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiFrostStrikeTimer -= uiDiff; + if(Unit *target = SelectEnemyCaster(false)) + timedCast(SPELL_STRANGULATE, diff, target); - if (m_uiIcyTouchTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_ICE_TOUCH); - m_uiIcyTouchTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - else - m_uiIcyTouchTimer -= uiDiff; + timedCast(SPELL_FROST_STRIKE, diff); - if (m_uiDeathGripTimer <= uiDiff) - { - if (m_creature->IsInRange(m_creature->getVictim(), 10.0f, 30.0f)) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_DEATH_GRIP); - m_creature->getVictim()->NearTeleportTo(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0.0f); - m_uiDeathGripTimer = 35*IN_MILLISECONDS; - } - } - else - m_uiDeathGripTimer -= uiDiff; + timedCast(SPELL_ICY_TOUCH, diff); - DoMeleeAttackIfReady(); + if(m_creature->IsInRange(m_creature->getVictim(), 10.0f, 30.0f, false)) + timedCast(SPELL_DEATH_GRIP, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/********* -** Rogue -**********/ -struct MANGOS_DLL_DECL mob_toc_rogueAI : public boss_faction_championsAI +enum RogueSpell +{ + SPELL_FAN_OF_KNIVES = 65955, //2sec + SPELL_BLIND = 65960, //2min + SPELL_CLOAK = 65961, //90sec + SPELL_BLADE_FLURRY = 65956, //2min + SPELL_SHADOWSTEP = 66178, //30sec + SPELL_HEMORRHAGE = 65954, + SPELL_EVISCERATE = 65957 +}; + +struct MANGOS_DLL_DECL mob_toc_rogueAI : public boss_faction_championsAI { - mob_toc_rogueAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) + mob_toc_rogueAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiFanOfKnivesTimer; - uint32 m_uiHemorrhageTimer; - uint32 m_uiEviscerateTimer; - uint32 m_uiShadowstepTimer; - uint32 m_uiBlindTimer; - uint32 m_uiCloakTimer; - uint32 m_uiBladeFlurryTimer; - uint32 m_uiKillPlayerTimer; - uint32 m_uiWoundPoisonTimer; - - void Reset() + void Init() { - m_uiFanOfKnivesTimer = urand(8*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiHemorrhageTimer = 0; - m_uiEviscerateTimer = urand(15*IN_MILLISECONDS, 20*IN_MILLISECONDS); - m_uiShadowstepTimer = urand(10*IN_MILLISECONDS, 80*IN_MILLISECONDS); - m_uiBlindTimer = urand(7*IN_MILLISECONDS, 8*IN_MILLISECONDS); - m_uiCloakTimer = 0; - m_uiBladeFlurryTimer = urand(12*IN_MILLISECONDS, 120*IN_MILLISECONDS); - m_uiWoundPoisonTimer = urand(2*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiKillPlayerTimer = 0; - SetEquipmentSlots(false, 47422, 49982, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_SHADOWSTEP, false); - m_creature->CastSpell(target, SPELL_EVISCERATE, true); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - //Its not blizzlike but work. - if (m_uiWoundPoisonTimer < uiDiff) - { - if (m_creature->IsWithinDist(m_creature->getVictim(), 3.0f)) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_WOUND_POISON); - m_uiWoundPoisonTimer = urand(10*IN_MILLISECONDS, 16*IN_MILLISECONDS); - } - } - else - m_uiWoundPoisonTimer -= uiDiff; - - if (m_uiFanOfKnivesTimer <= uiDiff) - { - if (Unit *target = SelectTargetWithinDist()) - { - DoCastSpellIfCan(target, SPELL_FAN_OF_KNIVES); - m_uiFanOfKnivesTimer = urand(16*IN_MILLISECONDS, 20*IN_MILLISECONDS); - } - } - else - m_uiFanOfKnivesTimer -= uiDiff; - - if (m_uiHemorrhageTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEMORRHAGE); - m_uiHemorrhageTimer = urand(8*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - else - m_uiHemorrhageTimer -= uiDiff; + if(EnemiesInRange(15.0f) > 2) + timedCast(SPELL_FAN_OF_KNIVES, diff); - if (m_uiEviscerateTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_EVISCERATE); - m_uiEviscerateTimer = urand(20*IN_MILLISECONDS, 35*IN_MILLISECONDS); - } - else - m_uiEviscerateTimer -= uiDiff; + timedCast(SPELL_HEMORRHAGE, diff); - if (m_uiShadowstepTimer <= uiDiff) - { - if (m_creature->IsInRange(m_creature->getVictim(), 10.0f, 40.0f)) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOWSTEP); - m_uiShadowstepTimer = 40*IN_MILLISECONDS; - } - } - else - m_uiShadowstepTimer -= uiDiff; + timedCast(SPELL_EVISCERATE, diff); - if (m_uiBlindTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - { - if(Unit *target = SelectTargetWithinDist()) - { - DoCastSpellIfCan(target, SPELL_BLIND); - m_uiBlindTimer = 2*MINUTE*IN_MILLISECONDS; - } - } - } - else - m_uiBlindTimer -= uiDiff; + if(m_creature->IsInRange(m_creature->getVictim(), 10.0f, 40.0f)) + timedCast(SPELL_SHADOWSTEP, diff); - if (m_uiCloakTimer <= uiDiff) - { - if (m_creature->GetHealthPercent() < 50.0f) - { - DoCastSpellIfCan(m_creature, SPELL_CLOAK); - m_uiCloakTimer = 90*IN_MILLISECONDS; - } - } - else - m_uiCloakTimer -= uiDiff; + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + if(m_creature->IsInRange(target, 0.0f, 15.0f, false)) + timedCast(SPELL_BLIND, diff, target); - if (m_uiBladeFlurryTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_BLADE_FLURRY); - m_uiBladeFlurryTimer = 2*MINUTE*IN_MILLISECONDS; - } - else - m_uiBladeFlurryTimer -= uiDiff; + if(m_creature->GetHealthPercent() < 50.0f) + timedCast(SPELL_CLOAK, diff); - DoMeleeAttackIfReady(); + timedCast(SPELL_BLADE_FLURRY, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/************* -** Shaman En -**************/ -struct MANGOS_DLL_DECL mob_toc_enh_shamanAI : public boss_faction_championsAI +enum ShamanDpsSpell { - mob_toc_enh_shamanAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) - { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); - } - ScriptedInstance* m_pInstance; - - uint32 m_uiHeroismOrBloodlustTimer; - uint32 m_uiEarthShockTimer; - uint32 m_uiStormstrikeTimer; - uint32 m_uiLavaLashTimer; - uint32 m_uiTotemTimer; - uint32 m_uiSummonTotemTimer; - uint32 m_uiWindFuryTimer; - uint32 m_uiKillPlayerTimer; + SPELL_LAVA_LASH = 65974, + SPELL_STORMSTRIKE = 65970 +}; - void Reset() +struct MANGOS_DLL_DECL mob_toc_enh_shamanAI : public boss_faction_championsAI +{ + mob_toc_enh_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_uiHeroismOrBloodlustTimer = urand(25*IN_MILLISECONDS, 60*IN_MILLISECONDS); - m_uiEarthShockTimer = urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiStormstrikeTimer = urand(9*IN_MILLISECONDS, 20*IN_MILLISECONDS); - m_uiLavaLashTimer = urand(5*IN_MILLISECONDS, 8*IN_MILLISECONDS); - m_uiWindFuryTimer = urand(5000, 15000); - m_uiKillPlayerTimer = 0; - m_uiSummonTotemTimer = 0; - - SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE); + Init(); } - void Totems() + void Init() { - switch(urand(0, 1)) - { - case 0: - m_creature->CastSpell(m_creature, SPELL_TOTEM_GROUND, false); - break; - case 1: - m_creature->CastSpell(m_creature, SPELL_TOTEM_TREMOR, false); - break; - } + SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE); + boss_faction_championsAI::Init(); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_STORMSTRIKE, false); - m_creature->CastSpell(target, SPELL_LAVA_LASH, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - if (m_uiHeroismOrBloodlustTimer <= uiDiff) - { - if (m_creature->getFaction()) //Am i alliance? - { - if (!m_creature->HasAura(AURA_EXHAUSTION)) - DoCastSpellIfCan(m_creature, SPELL_HEROISM); - } - else - { - if (!m_creature->HasAura(AURA_SATED)) - DoCastSpellIfCan(m_creature, SPELL_BLOODLUST); - } - m_uiHeroismOrBloodlustTimer = 10*MINUTE*IN_MILLISECONDS; - } - else - m_uiHeroismOrBloodlustTimer -= uiDiff; - - if (m_uiEarthShockTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_EARTH_SHOCK); - m_uiEarthShockTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - else - m_uiEarthShockTimer -= uiDiff; - - if (m_uiStormstrikeTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STORMSTRIKE); - m_uiStormstrikeTimer = urand(14*IN_MILLISECONDS, 30*IN_MILLISECONDS); - } - else - m_uiStormstrikeTimer -= uiDiff; - - if (m_uiLavaLashTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_LAVA_LASH); - m_uiLavaLashTimer = urand(12*IN_MILLISECONDS, 16*IN_MILLISECONDS); - } - else - m_uiLavaLashTimer -= uiDiff; - - //Its not blizzlike but work. - if (m_uiWindFuryTimer < uiDiff) - { - if (m_creature->IsWithinDist(m_creature->getVictim(), 3.0f)) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_WINDFURY); - m_uiWindFuryTimer = urand(15*IN_MILLISECONDS, 25*IN_MILLISECONDS); - } - } - else - m_uiWindFuryTimer -= uiDiff; - - if (m_uiTotemTimer < uiDiff) - { - Totems(); - m_uiTotemTimer = urand(1*IN_MILLISECONDS, 3*IN_MILLISECONDS); - } - else - m_uiTotemTimer -= uiDiff; + timedCast(SPELL_HEROISM, diff); - if (m_uiSummonTotemTimer < uiDiff) - { - m_creature->CastSpell(m_creature, SPELL_TOTEM_SEARING, true); - m_creature->CastSpell(m_creature, SPELL_TOTEM_HEAL, true); - m_creature->CastSpell(m_creature, SPELL_TOTEM_STR, true); - m_creature->CastSpell(m_creature, SPELL_TOTEM_WIND, true); + timedCast(SPELL_EARTH_SHOCK, diff); - m_uiSummonTotemTimer = urand(18*IN_MILLISECONDS, 30*IN_MILLISECONDS); - } - else - m_uiSummonTotemTimer -= uiDiff; + timedCast(SPELL_STORMSTRIKE, diff); - DoMeleeAttackIfReady(); + timedCast(SPELL_LAVA_LASH, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/**************** -** Paladyn Retri -*****************/ -struct MANGOS_DLL_DECL mob_toc_retro_paladinAI : public boss_faction_championsAI +enum PaladinDpsSpell +{ + SPELL_AVENGING_WRATH = 66011, //3min cd + SPELL_CRUSADER_STRIKE = 66003, //6sec cd + SPELL_DIVINE_SHIELD = 66010, //5min cd + SPELL_DIVINE_STORM = 66006, //10sec cd + SPELL_JUDJEMENT_OF_COMMAND = 66005, //8sec cd + SPELL_REPENTANCE = 66008, //60sec cd + SPELL_SEAL_OF_COMMAND = 66004, //no cd +}; + +struct MANGOS_DLL_DECL mob_toc_retro_paladinAI : public boss_faction_championsAI { - mob_toc_retro_paladinAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) + mob_toc_retro_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); + Init(); } - ScriptedInstance* m_pInstance; - - uint32 m_uiRepeteanceTimer; - uint32 m_uiCrusaderStrikeTimer; - uint32 m_uiAvengingWrathTimer; - uint32 m_uiDivineShieldTimer; - uint32 m_uiDivineStormTimer; - uint32 m_uiJudgementOfCommandTimer; - uint32 m_uiHammerOfJusticeTimer; - uint32 m_uiHandOfProtectionTimer; - uint32 m_uiKillPlayerTimer; - - void Reset() + void Init() { - m_uiRepeteanceTimer = 30*IN_MILLISECONDS; - m_uiCrusaderStrikeTimer = urand(6*IN_MILLISECONDS, 18*IN_MILLISECONDS); - m_uiAvengingWrathTimer = urand(35*IN_MILLISECONDS, 40*IN_MILLISECONDS); - m_uiDivineShieldTimer = urand(0*IN_MILLISECONDS, 360*IN_MILLISECONDS); - m_uiDivineStormTimer = urand(9*IN_MILLISECONDS, 10*IN_MILLISECONDS); - m_uiJudgementOfCommandTimer = urand(8*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiHammerOfJusticeTimer = urand(5*IN_MILLISECONDS, 15*IN_MILLISECONDS); - m_uiHandOfProtectionTimer = 0; - m_uiKillPlayerTimer = 0; - SetEquipmentSlots(false, 47519, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); - DoCastSpellIfCan(m_creature, SPELL_SEAL_COMAND); + boss_faction_championsAI::Init(); } - void UpdateAI(const uint32 uiDiff) + void Aggro(Unit *who) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiKillPlayerTimer < uiDiff) - { - if (Unit *target = KillPlayer()) - { - m_creature->CastSpell(target, SPELL_STRIKE, false); - m_creature->CastSpell(target, SPELL_STORM, false); - m_uiKillPlayerTimer = 10*IN_MILLISECONDS; - } - } - else - m_uiKillPlayerTimer -= uiDiff; - - if (m_uiRepeteanceTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - DoCastSpellIfCan(pTarget, SPELL_REPENTANCE); - m_uiRepeteanceTimer = 1*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiRepeteanceTimer -= uiDiff; - - if (m_uiHammerOfJusticeTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMMER_OF_JUSTICE); - m_uiHammerOfJusticeTimer = 35*IN_MILLISECONDS; - } - else - m_uiHammerOfJusticeTimer -= uiDiff; + boss_faction_championsAI::Aggro(who); + doCast(SPELL_SEAL_OF_COMMAND); + } - if (m_uiHandOfProtectionTimer <= uiDiff) - { - if (Unit* target = DoSelectLowestHpFriendly(40.0f)) - { - if (target->GetHealthPercent() <= 20.0f) - { - DoCastSpellIfCan(target, SPELL_HAND_OF_PROTECTION); - m_uiHandOfProtectionTimer = 5*MINUTE*IN_MILLISECONDS; - } - } - } - else - m_uiHandOfProtectionTimer -= uiDiff; + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - if (m_uiCrusaderStrikeTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STRIKE); - m_uiCrusaderStrikeTimer = urand(6*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiCrusaderStrikeTimer -= uiDiff; + timedCast(SPELL_REPENTANCE, diff); - if (m_uiAvengingWrathTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_AVENGING_WRATH); - m_uiAvengingWrathTimer = 2*MINUTE*IN_MILLISECONDS; - } - else - m_uiAvengingWrathTimer -= uiDiff; + timedCast(SPELL_CRUSADER_STRIKE, diff); - if (m_uiDivineShieldTimer <= uiDiff) - { - if (m_creature->GetHealthPercent() < 50.0f) - { - DoCastSpellIfCan(m_creature, SPELL_DIVINE_SHIELD); - m_uiDivineShieldTimer = 5*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiDivineShieldTimer -= uiDiff; + timedCast(SPELL_AVENGING_WRATH, diff); - if (m_uiDivineStormTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STORM); - m_uiDivineStormTimer = urand(10*IN_MILLISECONDS, 18*IN_MILLISECONDS); - } - else - m_uiDivineStormTimer -= uiDiff; + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_DIVINE_SHIELD, diff); - if (m_uiJudgementOfCommandTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_JUDGEMENT_COMAND); - m_uiJudgementOfCommandTimer = urand(8*IN_MILLISECONDS, 15*IN_MILLISECONDS); - } - else - m_uiJudgementOfCommandTimer -= uiDiff; + timedCast(SPELL_DIVINE_STORM, diff); - DoMeleeAttackIfReady(); + timedCast(SPELL_JUDJEMENT_OF_COMMAND, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/**************** -** Felhunter -*****************/ -struct MANGOS_DLL_DECL mob_toc_pet_warlockAI : public boss_faction_championsAI +enum TocPetSpell +{ + SPELL_WPET0 = 67518, + SPELL_WPET1 = 67519, + SPELL_HPET0 = 67793 +}; + +struct MANGOS_DLL_DECL mob_toc_pet_warlockAI : public boss_faction_championsAI { - mob_toc_pet_warlockAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) + mob_toc_pet_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); + Init(); } - uint32 m_uiDevourMagicTimer; - uint32 m_uiSpellLockTimer; - - void Reset() + void Aggro(Unit *who) { - m_uiDevourMagicTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS); - m_uiSpellLockTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS); + boss_faction_championsAI::Aggro(who); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (m_pInstance && m_pInstance->GetData(TYPE_CRUSADERS) != IN_PROGRESS) - m_creature->ForcedDespawn(); - - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiDevourMagicTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_DEVOUR_MAGIC); - m_uiDevourMagicTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS); - } - else - m_uiDevourMagicTimer -= uiDiff; - - if (m_uiSpellLockTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_SPELL_LOCK); - m_uiSpellLockTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS); - } - else - m_uiSpellLockTimer -= uiDiff; + timedCast(SPELL_WPET0, diff); - DoMeleeAttackIfReady(); + timedCast(SPELL_WPET1, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; -/******** -** Cat -*********/ -struct MANGOS_DLL_DECL mob_toc_pet_hunterAI : public boss_faction_championsAI +struct MANGOS_DLL_DECL mob_toc_pet_hunterAI : public boss_faction_championsAI { - mob_toc_pet_hunterAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) + mob_toc_pet_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) { - m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - Reset(); + Init(); } - uint32 m_uiClawTimer; - - void Reset() + void Aggro(Unit *who) { - m_uiClawTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); + boss_faction_championsAI::Aggro(who); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (m_pInstance && m_pInstance->GetData(TYPE_CRUSADERS) != IN_PROGRESS) - m_creature->ForcedDespawn(); - - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiClawTimer <= uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLAW); - m_uiClawTimer = urand(5*IN_MILLISECONDS, 10*IN_MILLISECONDS); - } - else - m_uiClawTimer -= uiDiff; - - DoMeleeAttackIfReady(); + timedCast(SPELL_HPET0, diff); - boss_faction_championsAI::UpdateAI(uiDiff); + boss_faction_championsAI::UpdateAI(diff); } }; + +/*========================================================*/ CreatureAI* GetAI_mob_toc_druid(Creature *pCreature) { return new mob_toc_druidAI (pCreature); diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp index dceffff69b..d78fe84630 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -25,119 +25,91 @@ EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" - -enum Yells -{ - SAY_AGGRO = -1713517, - SAY_DEATH = -1713525, - SAY_SLAY_1 = -1713567, - SAY_SLAY_2 = -1713568, - SAY_INFERNAL_VOLCANO = -1713520, - SAY_NETHER_PORTAL = -1713519, - SAY_SUMMON_MISTRESS = -1713521, - SAY_SUMMON_INFERNAL = -1713524, - SAY_INCINERATE_FLESH = -1713523, - SAY_ENRAGE = -1713750, - - EMOTE_INCINERATE_FLESH = -1713522, -}; - enum Equipment { - EQUIP_MAIN = 47266, - EQUIP_DONE = EQUIP_NO_CHANGE, + EQUIP_MAIN = 47266, + EQUIP_OFFHAND = 46996, + EQUIP_RANGED = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, }; enum Summons { - NPC_LEGION_FLAME = 34784, - NPC_INFERNAL_VOLCANO = 34813, - NPC_FEL_INFERNAL = 34815, - NPC_NETHER_PORTAL = 34825, - NPC_MISTRESS = 34826, + NPC_LEGION_FLAME = 34784, + NPC_INFERNAL_VOLCANO = 34813, + NPC_FEL_INFERNAL = 34815, + NPC_NETHER_PORTAL = 34825, + NPC_MISTRESS = 34826, }; enum BossSpells { - SPELL_NETHER_POWER = 67108, - SPELL_SUMMON_VOLCAN_N = 66258, - SPELL_SUMMON_VOLCAN_H = 67902, - SPELL_SUMMON_INFERNAL_PERIODIC = 66252, - SPELL_FEL_FIREBALL = 66532, - SPELL_FEL_LIGHTING = 66528, - SPELL_INCINERATE_FLESH = 66237, - SPELL_BURNING_INFERNO = 66242, - SPELL_SUMMON_NETHER_PORTAL_N = 66269, - SPELL_SUMMON_NETHER_PORTAL_H = 67899, - SPELL_SUMMON_MISTRESS_PERIODIC = 67103, - SPELL_LEGION_FLAME = 66197, - SPELL_LEGION_FLAME_AURA = 66201, - SPELL_SHIVAN_SLASH = 67098, - SPELL_SPINNING_STRIKE = 66283, // Need core support - SPELL_MISTRESS_KISS = 67906, - SPELL_FEL_INFERNO = 67047, - SPELL_FEL_STREAK = 66494, - SPELL_WILFRED_PORTAL = 68424, - SPELL_ENRAGE = 26662, + SPELL_JARAXXUS_TOUCH = 66209, + SPELL_CURSE_OF_NETHER = 66211, + SPELL_NETHER_POWER = 67108, + SPELL_INFERNAL = 66258, + SPELL_INFERNAL_ERUPTION = 66255, + SPELL_FEL_FIREBALL = 66532, + SPELL_FEL_LIGHTING = 66528, + SPELL_INCINERATE_FLESH = 66237, + SPELL_BURNING_INFERNO = 66242, + SPELL_NETHER_PORTAL = 66264, + SPELL_LEGION_FLAME_0 = 66877, + SPELL_LEGION_FLAME_1 = 66197, + SPELL_SHIVAN_SLASH = 67098, + SPELL_SPINNING_STRIKE = 66316, + SPELL_FEL_INFERNO = 67047, + SPELL_FEL_STREAK = 66494, + SPELL_MISTRESS_KISS = 67078, + SPELL_BERSERK = 26662 }; /*###### -## boss_jaraxxus +## Lord Jaraxxus ######*/ -struct MANGOS_DLL_DECL boss_jaraxxusAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_jaraxxusAI : public BSWScriptedAI { - boss_jaraxxusAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_jaraxxusAI(Creature* pCreature) : BSWScriptedAI(pCreature) { - m_pInstance = (instance_trial_of_the_crusader*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } - instance_trial_of_the_crusader* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiNetherPowerTimer; - uint32 m_uiFelFireballTimer; - uint32 m_uiFelLightingTimer; - uint32 m_uiIncinerateFleshTimer; - uint32 m_uiLegionFlameTimer; - uint32 m_uiInfernalEruptionTimer; - uint32 m_uiNetherPortalTimer; - uint32 m_uiEnrageTimer; - uint32 m_uiCheckTimer; - - std::list mistressEntryList; + ScriptedInstance* m_pInstance; + uint32 m_uiPowerTimer; + uint32 m_uiSummonTimer; + uint32 m_uiFizzlebangSecurityKillTimer; + uint8 m_uiStackReply; + bool m_bVolcanoOrPortal; + bool m_bPowerCheck; - void Reset() + void Reset() { - if (!m_pInstance) + if(!m_pInstance) return; - m_pInstance->SetData(TYPE_JARAXXUS, NOT_STARTED); +// SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + m_bVolcanoOrPortal = urand(0,1); + m_uiPowerTimer = 27000; + m_uiSummonTimer = 60000; + // this to avoid Fizzlebang to be saved by players + m_uiFizzlebangSecurityKillTimer = 7000; + m_bPowerCheck = false; + + if (currentDifficulty == RAID_DIFFICULTY_10MAN_NORMAL || currentDifficulty == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiStackReply = 4; + else + m_uiStackReply = 9; - m_uiNetherPowerTimer = 0; - m_uiFelFireballTimer = 15000; - m_uiFelLightingTimer = 12000; - m_uiIncinerateFleshTimer = 20000; - m_uiLegionFlameTimer = 30000; - m_uiInfernalEruptionTimer = 80000; - m_uiNetherPortalTimer = 20000; - m_uiEnrageTimer = 600000; - m_uiCheckTimer = 1000; - + DoScriptText(-1713517,m_creature); m_creature->SetRespawnDelay(DAY); - - mistressEntryList.clear(); } void JustReachedHome() { - if (!m_pInstance) + if (!m_pInstance) return; m_pInstance->SetData(TYPE_JARAXXUS, FAIL); @@ -146,49 +118,40 @@ struct MANGOS_DLL_DECL boss_jaraxxusAI : public ScriptedAI void JustDied(Unit* pKiller) { - if (!m_pInstance) + if (!m_pInstance) return; - DoScriptText(SAY_DEATH, m_creature); + DoScriptText(-1713525, m_creature); m_pInstance->SetData(TYPE_JARAXXUS, DONE); - m_pInstance->SetData(TYPE_EVENT,1999); - m_pInstance->SetData(TYPE_STAGE,0); + m_pInstance->SetData(TYPE_EVENT, 2000); + m_pInstance->SetData(TYPE_STAGE, 0); } void Aggro(Unit* pWho) { - if (!m_pInstance) + if (!m_pInstance) return; - DoScriptText(SAY_AGGRO, m_creature); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetInCombatWithZone(); m_pInstance->SetData(TYPE_JARAXXUS, IN_PROGRESS); + DoScriptText(-1713514, m_creature); + doCast(SPELL_NETHER_POWER); } - void KilledUnit(Unit* pVictim) + //hacky workaround for interrupt Fel Fireball (need core fix) + void SpellHit(Unit* who, const SpellEntry* spell) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + // don't self interrupt + if (!who->IsControlledByPlayer()) return; - DoScriptText(SAY_SLAY_1 - urand(0, 1),m_creature,pVictim); - } - - void CheckAchiev() - { - mistressEntryList.clear(); - GetCreatureListWithEntryInGrid(mistressEntryList, m_creature, NPC_MISTRESS, 250.0f); - - if (mistressEntryList.empty()) + if (spell->EffectMechanic[0] == MECHANIC_INTERRUPT || spell->EffectMechanic[1] == MECHANIC_INTERRUPT || spell->EffectMechanic[2] == MECHANIC_INTERRUPT) { - m_pInstance->SetSpecialAchievementCriteria(TYPE_SIXTY_PAIN_SPIKE, false); - return; + m_creature->InterruptNonMeleeSpells(false, SPELL_FEL_FIREBALL); + m_creature->InterruptNonMeleeSpells(false, 66963); // 25 man + m_creature->InterruptNonMeleeSpells(false, 66964); // 10 man hero + m_creature->InterruptNonMeleeSpells(false, 66965); // 25 man hero } - - if (mistressEntryList.size()-1 >= 2) - m_pInstance->SetSpecialAchievementCriteria(TYPE_SIXTY_PAIN_SPIKE, true); - else - m_pInstance->SetSpecialAchievementCriteria(TYPE_SIXTY_PAIN_SPIKE, false); } void UpdateAI(const uint32 uiDiff) @@ -196,98 +159,82 @@ struct MANGOS_DLL_DECL boss_jaraxxusAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiCheckTimer < uiDiff) + if (!m_bPowerCheck) { - CheckAchiev(); - m_uiCheckTimer = 500; - } - else - m_uiCheckTimer -= uiDiff; - - if (m_uiEnrageTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_ENRAGE) == CAST_OK) + if (Creature* pFizzle = m_pInstance->GetSingleCreatureFromStorage(NPC_FIZZLEBANG)) { - m_uiEnrageTimer = 600000; - DoScriptText(SAY_ENRAGE, m_creature); - } - } - else - m_uiEnrageTimer -= uiDiff; + if (!pFizzle->isAlive()) + { + //little workaround to give initial stack amount of Nether Power + doCast(SPELL_NETHER_POWER); + m_uiStackReply--; + if (m_uiStackReply <= 0) + m_bPowerCheck = true; + } + else if (pFizzle->isAlive()) // don't cast if Fizzlebang is alive + { + DoMeleeAttackIfReady(); - if (m_uiNetherPowerTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_NETHER_POWER) == CAST_OK) - m_uiNetherPowerTimer = 30000; + //kill Fizzlebang if is elapsed too much time + if (m_uiFizzlebangSecurityKillTimer < uiDiff) + m_creature->DealDamage(pFizzle, pFizzle->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiFizzlebangSecurityKillTimer -= uiDiff; + return; + } + } } - else - m_uiNetherPowerTimer -= uiDiff; - if (m_uiFelFireballTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (DoCastSpellIfCan(pTarget, SPELL_FEL_FIREBALL) == CAST_OK) - m_uiFelFireballTimer = 12000; - } - else - m_uiFelFireballTimer -= uiDiff; + timedCast(SPELL_FEL_FIREBALL, uiDiff); - if (m_uiFelLightingTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (DoCastSpellIfCan(pTarget, SPELL_FEL_LIGHTING) == CAST_OK) - m_uiFelLightingTimer = 25000; - } - else - m_uiFelLightingTimer -= uiDiff; + timedCast(SPELL_FEL_LIGHTING, uiDiff); - if (m_uiIncinerateFleshTimer <= uiDiff) + if (timedQuery(SPELL_INCINERATE_FLESH, uiDiff)) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { - if (DoCastSpellIfCan(pTarget, SPELL_INCINERATE_FLESH) == CAST_OK) - { - DoScriptText(SAY_INCINERATE_FLESH, m_creature); - DoScriptText(EMOTE_INCINERATE_FLESH, m_creature, pTarget); - m_uiIncinerateFleshTimer = 22000; - } - } + DoScriptText(-1713522, m_creature, pTarget); + doCast(SPELL_INCINERATE_FLESH, pTarget); + } } - else - m_uiIncinerateFleshTimer -= uiDiff; - if (m_uiLegionFlameTimer <= uiDiff) + if (timedQuery(SPELL_LEGION_FLAME_1, uiDiff)) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - m_creature->CastSpell(pTarget, SPELL_LEGION_FLAME, false); - - m_uiLegionFlameTimer = 30000; + DoScriptText(-1713518, m_creature); + doCast(SPELL_LEGION_FLAME_1); } - else - m_uiLegionFlameTimer -= uiDiff; - if (m_uiInfernalEruptionTimer <= uiDiff) + if (m_uiSummonTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsHeroic ? SPELL_SUMMON_VOLCAN_H : SPELL_SUMMON_VOLCAN_N) == CAST_OK) + float fPosX, fPosY, fPosZ; + fPosZ = m_creature->GetPositionZ(); + double dOffset = urand(0, 17); + int i = urand(0, 19); + fPosX = SpawnLoc[1].x + 20 * cos(dOffset + i*18); + fPosY = SpawnLoc[1].y + 20 * sin(dOffset + i*18); + + if (m_bVolcanoOrPortal) + { + DoScriptText(-1713520, m_creature); + m_creature->SummonCreature(NPC_INFERNAL_VOLCANO, fPosX, fPosY, fPosZ, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); + m_bVolcanoOrPortal = false; + } + else { - m_uiInfernalEruptionTimer = 120000; - DoScriptText(SAY_INFERNAL_VOLCANO, m_creature); - DoScriptText(SAY_SUMMON_INFERNAL, m_creature); + DoScriptText(-1713519, m_creature); + m_creature->SummonCreature(NPC_NETHER_PORTAL, fPosX, fPosY, fPosZ, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); + m_bVolcanoOrPortal = true; } + m_uiSummonTimer = 60000; } - else - m_uiInfernalEruptionTimer -= uiDiff; + else m_uiSummonTimer -= uiDiff; - if (m_uiNetherPortalTimer <= uiDiff) + if (m_uiPowerTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsHeroic ? SPELL_SUMMON_NETHER_PORTAL_H : SPELL_SUMMON_NETHER_PORTAL_N) == CAST_OK) - { - DoScriptText(SAY_NETHER_PORTAL, m_creature); - m_uiNetherPortalTimer = 120000; - } + doCast(SPELL_NETHER_POWER); + m_uiPowerTimer = 27000; } else - m_uiNetherPortalTimer -= uiDiff; + m_uiPowerTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -298,36 +245,58 @@ CreatureAI* GetAI_boss_jaraxxus(Creature* pCreature) return new boss_jaraxxusAI(pCreature); } -struct MANGOS_DLL_DECL mob_legion_flameAI : public ScriptedAI +/*##### +# Legion Flame +#####*/ +struct MANGOS_DLL_DECL mob_legion_flameAI : public BSWScriptedAI { - mob_legion_flameAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_legion_flameAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; + uint32 m_uiRangeCheckTimer; void Reset() { m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - m_creature->_AddAura(SPELL_LEGION_FLAME_AURA); - m_creature->ForcedDespawn(60000); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetInCombatWithZone(); + m_creature->SetDisplayId(27625); m_creature->SetRespawnDelay(DAY); + m_uiRangeCheckTimer = 1000; } - void UpdateAI(const uint32 uiDiff) + void KilledUnit(Unit* pVictim) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer){} + + void Aggro(Unit *who) + { + if (!m_pInstance) + return; + } + void UpdateAI(const uint32 uiDiff) + { if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) - { - m_creature->RemoveAllAuras(); m_creature->ForcedDespawn(); + + if (m_uiRangeCheckTimer < uiDiff) + { + doCast(m_creature,SPELL_LEGION_FLAME_0); + m_uiRangeCheckTimer = 1000; } + else m_uiRangeCheckTimer -= uiDiff; + } }; @@ -336,59 +305,88 @@ CreatureAI* GetAI_mob_legion_flame(Creature* pCreature) return new mob_legion_flameAI(pCreature); } -struct MANGOS_DLL_DECL mob_infernal_volcanoAI : public ScriptedAI +/*##### +# Infernal Vulcano +#####*/ +struct MANGOS_DLL_DECL mob_infernal_volcanoAI : public BSWScriptedAI { - mob_infernal_volcanoAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_infernal_volcanoAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiSummonInfernalTimer; + uint32 m_uiCount; + uint32 m_uiTimer; void Reset() { - m_creature->SetInCombatWithZone(); - SetCombatMovement(false); - - m_uiSummonInfernalTimer = 12000; - - if (!m_bIsHeroic) + m_uiTimer = 5000; + m_creature->SetRespawnDelay(DAY); + m_uiCount = 0; + if (currentDifficulty <= RAID_DIFFICULTY_25MAN_NORMAL) + { m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } - DoCastSpellIfCan(m_creature, SPELL_SUMMON_INFERNAL_PERIODIC); + void AttackStart(Unit *who) + { + return; } - void JustDied(Unit* Killer) + void KilledUnit(Unit* pVictim) { - m_creature->ForcedDespawn(); + if (pVictim->GetTypeId() != TYPEID_PLAYER) + return; } - void AttackStart(Unit *pWho) + void JustDied(Unit* Killer){} + + void Aggro(Unit *who) { - return; + if (!m_pInstance) + return; } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) m_creature->ForcedDespawn(); - if (m_uiSummonInfernalTimer <= uiDiff) + if (currentDifficulty <= RAID_DIFFICULTY_25MAN_NORMAL) { - DoCastSpellIfCan(m_creature, SPELL_SUMMON_INFERNAL_PERIODIC); - m_uiSummonInfernalTimer = 9000; + if (m_uiCount >= 3) + { + m_creature->ForcedDespawn(); + } } - else - m_uiSummonInfernalTimer -= uiDiff; + + if (m_uiTimer < diff) + { + doCast(SPELL_INFERNAL_ERUPTION); + DoScriptText(-1713524, m_creature); + m_uiCount++; + m_uiTimer = 5000; + } + else m_uiTimer -= diff; + + if (m_uiCount >= 3) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + } }; @@ -397,42 +395,37 @@ CreatureAI* GetAI_mob_infernal_volcano(Creature* pCreature) return new mob_infernal_volcanoAI(pCreature); } -struct MANGOS_DLL_DECL mob_fel_infernalAI : public ScriptedAI +/*##### +# Fel Infernal +#####*/ +struct MANGOS_DLL_DECL mob_fel_infernalAI : public BSWScriptedAI { - mob_fel_infernalAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_fel_infernalAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - uint32 m_uiFelInfernoTimer; - uint32 m_uiFelStreakTimer; - void Reset() { - m_uiFelInfernoTimer = 10000, - m_uiFelStreakTimer = 20000, - m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(DAY); } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; } - void JustDied(Unit* Killer) - { - m_creature->ForcedDespawn(5000); - } + void JustDied(Unit* Killer){} void Aggro(Unit *who) { - if (!m_pInstance) + if (!m_pInstance) return; } @@ -444,25 +437,9 @@ struct MANGOS_DLL_DECL mob_fel_infernalAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiFelInfernoTimer <= uiDiff) - { - if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - m_creature->CastSpell(pTarget, SPELL_FEL_INFERNO, false); + timedCast(SPELL_FEL_INFERNO, uiDiff); - m_uiFelInfernoTimer = 25000; - } - else - m_uiFelInfernoTimer -= uiDiff; - - if (m_uiFelStreakTimer <= uiDiff) - { - if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - m_creature->CastSpell(pTarget, SPELL_FEL_STREAK, false); - - m_uiFelStreakTimer = 25000; - } - else - m_uiFelStreakTimer -= uiDiff; + timedCast(SPELL_FEL_STREAK, uiDiff); DoMeleeAttackIfReady(); } @@ -473,55 +450,91 @@ CreatureAI* GetAI_mob_fel_infernal(Creature* pCreature) return new mob_fel_infernalAI(pCreature); } -struct MANGOS_DLL_DECL mob_nether_portalAI : public ScriptedAI +/*##### +# Nether Portal +#####*/ + +struct MANGOS_DLL_DECL mob_nether_portalAI : public BSWScriptedAI { - mob_nether_portalAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_nether_portalAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiSummonMistressTimer; + uint32 m_uiTimer; + bool m_bHasSummoned; void Reset() { - m_creature->SetInCombatWithZone(); + m_uiTimer = 15000; + m_bHasSummoned = false; m_creature->SetRespawnDelay(DAY); - SetCombatMovement(false); - - m_uiSummonMistressTimer = 18000; - - if (!m_bIsHeroic) + m_creature->SetDisplayId(29074); + if (currentDifficulty <= RAID_DIFFICULTY_25MAN_NORMAL) + { m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } - DoCastSpellIfCan(m_creature, SPELL_SUMMON_MISTRESS_PERIODIC, CAST_TRIGGERED); } - void AttackStart(Unit *pWho) + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) + return; + } + + void AttackStart(Unit *who) { return; } - void UpdateAI(const uint32 uiDiff) + void JustDied(Unit* Killer){} + + void Aggro(Unit *who) { - if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + if (!m_pInstance) + return; + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS ) m_creature->ForcedDespawn(); - if (m_uiSummonMistressTimer <= uiDiff) + if (currentDifficulty <= RAID_DIFFICULTY_25MAN_NORMAL) { - DoCastSpellIfCan(m_creature, SPELL_SUMMON_MISTRESS_PERIODIC, CAST_TRIGGERED); - m_uiSummonMistressTimer = 9000; + if (m_bHasSummoned) + { + m_creature->ForcedDespawn(); + } } - else - m_uiSummonMistressTimer -= uiDiff; + + if (m_uiTimer < diff) + { + m_creature->SummonCreature(NPC_MISTRESS, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); + DoScriptText(-1713521, m_creature); + m_bHasSummoned = true; + m_uiTimer = 15000; + } + else m_uiTimer -= diff; + + if (m_bHasSummoned) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + } }; @@ -530,57 +543,43 @@ CreatureAI* GetAI_mob_nether_portal(Creature* pCreature) return new mob_nether_portalAI(pCreature); } -struct MANGOS_DLL_DECL mob_mistress_of_painAI : public ScriptedAI +/*##### +# Misterss of Pain +#####*/ +struct MANGOS_DLL_DECL mob_mistress_of_painAI : public BSWScriptedAI { - mob_mistress_of_painAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_mistress_of_painAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - - uint32 m_uiShivanSlashTimer; - uint32 m_uiSpinningStrikeTimer; - uint32 m_uiMistressKissTimer; void Reset() { m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(DAY); - - m_uiShivanSlashTimer = 10000; - m_uiSpinningStrikeTimer = 5000; - m_uiMistressKissTimer = 8000; } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; } - void JustDied(Unit* Killer) - { - m_creature->ForcedDespawn(); - } + void JustDied(Unit* Killer){} void Aggro(Unit *who) { - if (!m_pInstance) - return; + if (!m_pInstance) return; + DoScriptText(-1713523,m_creature, who); } - void UpdateAI(const uint32 uiDiff) { - if (!m_pInstance) + if (!m_pInstance) return; if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) @@ -589,34 +588,12 @@ struct MANGOS_DLL_DECL mob_mistress_of_painAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiShivanSlashTimer <= uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_SHIVAN_SLASH, false); - m_uiShivanSlashTimer = 10000; - } - else - m_uiShivanSlashTimer -= uiDiff; - - if (m_uiSpinningStrikeTimer <= uiDiff) - { - m_creature->CastSpell(m_creature->getVictim(), SPELL_SPINNING_STRIKE, false); - m_uiSpinningStrikeTimer = 10000; - } - else - m_uiSpinningStrikeTimer -= uiDiff; + timedCast(SPELL_SHIVAN_SLASH, uiDiff); - if (m_bIsHeroic) - { - if (m_uiMistressKissTimer <= uiDiff) - { - if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - m_creature->CastSpell(pTarget, SPELL_MISTRESS_KISS, false); + timedCast(SPELL_SPINNING_STRIKE, uiDiff); - m_uiMistressKissTimer = 10000; - } - else - m_uiMistressKissTimer -= uiDiff; - } + if (currentDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) + timedCast(SPELL_MISTRESS_KISS, uiDiff); DoMeleeAttackIfReady(); } @@ -629,35 +606,35 @@ CreatureAI* GetAI_mob_mistress_of_pain(Creature* pCreature) void AddSC_boss_jaraxxus() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_jaraxxus"; - pNewScript->GetAI = &GetAI_boss_jaraxxus; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_legion_flame"; - pNewScript->GetAI = &GetAI_mob_legion_flame; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_infernal_volcano"; - pNewScript->GetAI = &GetAI_mob_infernal_volcano; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_fel_infernal"; - pNewScript->GetAI = &GetAI_mob_fel_infernal; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_nether_portal"; - pNewScript->GetAI = &GetAI_mob_nether_portal; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_mistress_of_pain"; - pNewScript->GetAI = &GetAI_mob_mistress_of_pain; - pNewScript->RegisterSelf(); + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_jaraxxus"; + newscript->GetAI = &GetAI_boss_jaraxxus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_legion_flame"; + newscript->GetAI = &GetAI_mob_legion_flame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_infernal_volcano"; + newscript->GetAI = &GetAI_mob_infernal_volcano; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_infernal"; + newscript->GetAI = &GetAI_mob_fel_infernal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nether_portal"; + newscript->GetAI = &GetAI_mob_nether_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_mistress_of_pain"; + newscript->GetAI = &GetAI_mob_mistress_of_pain; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp index 0d0f9a9dd8..ee64cb6b71 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -24,209 +24,109 @@ SDComment: by /dev/rsa SDCategory: EndScriptData */ -// Snobols have to jump into players. Need core support -// Some spells have wrong target, invalid. +// not implemented: +// snobolds link +// snakes underground cast (not support in core) #include "precompiled.h" #include "trial_of_the_crusader.h" -enum Emotes -{ - EMOTE_SUMMON_SNOBOLD = -1713601, - EMOTE_ENRAGE = -1713504, - EMOTE_TRAMPLE = -1713506, - EMOTE_STAGGERED = -1713507, - EMOTE_CRASH = -1713508, -}; enum Equipment { - EQUIP_MAIN = 47505, - EQUIP_DONE = EQUIP_NO_CHANGE, + EQUIP_MAIN = 50760, + EQUIP_OFFHAND = 48040, + EQUIP_RANGED = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, }; enum Summons { - NPC_SNOBOLD_VASSAL = 34800, - NPC_SLIME_POOL = 35176, - NPC_FIRE_BOMB = 34854, + NPC_SNOBOLD_VASSAL = 34800, + NPC_SLIME_POOL = 35176, + NPC_FIRE_BOMB = 34854, }; enum BossSpells { - // Gormok - SPELL_IMPALE = 66331, - SPELL_STAGGERING_STOMP = 67648, - SPELL_RISING_ANGER = 66636, - SPELL_SNOBOLLED = 66406, - SPELL_BATTER = 66408, - SPELL_FIRE_BOMB = 66313, - SPELL_FIRE_BOMB_DOT = 66318, - SPELL_HEAD_CRACK = 66407, - - // Acidmaw & Dreadscale - SPELL_EMERGE = 66947, - SPELL_SUBMERGE = 66948, - SPELL_ENRAGE = 68335, - SPELL_ACID_SPIT = 66880, - SPELL_PARALYTIC_SPRAY = 66901, - SPELL_PARALYTIC_TOXIN = 66823, - SPELL_ACID_SPEW = 66819, - SPELL_PARALYTIC_BITE = 66824, - SPELL_SWEEP = 66794, - SPELL_FIRE_SPIT = 66796, - SPELL_MOLTEN_SPEW = 66821, - SPELL_BURNING_BITE = 66879, - SPELL_BURNING_SPRAY = 66902, - SPELL_BURNING_BILE = 66869, - SPELL_AUTO_GROW = 62559, - SPELL_SLIME_POOL = 66883, - SPELL_SLIME_POOL_AURA = 66882, - SPELL_SLIME_POOL_VISUAL = 63084, - SPELL_CHECK_ACHIEV = 68523, - - // Icehowl - SPELL_FEROCIOUS_BUTT = 66770, - SPELL_MASSIVE_CRASH = 66683, - SPELL_WHIRL = 67345, - SPELL_ARCTIC_BREATH = 66689, - SPELL_TRAMPLE = 66734, - SPELL_ADRENALINE = 68667, - SPELL_FROTHING_RAGE = 66759, - SPELL_STAGGERED_DAZE = 66758, -}; - -enum Models -{ - MODEL_ACIDMAW_STATIONARY = 29815, - MODEL_ACIDMAW_MOBILE = 29816, - MODEL_DREADSCALE_STATIONARY = 26935, - MODEL_DREADSCALE_MOBILE = 24564, -}; - -enum Phases -{ - // Snakes - PHASE_EMERGED = 0, - PHASE_SUBMERGED = 1, - - // Icehowl - PHASE_NORMAL = 0, - PHASE_MOVING = 1, - PHASE_TRAMPLE = 2, -}; - -enum Points -{ - POINT_CENTER = 0, - POINT_TARGET = 1, +SPELL_IMPALE = 66331, +SPELL_STAGGERING_STOMP = 67648, +SPELL_RISING_ANGER = 66636, +SUMMON_SNOBOLD = NPC_SNOBOLD_VASSAL, +SPELL_ACID_SPIT = 66880, +SPELL_PARALYTIC_SPRAY = 66901, +SPELL_ACID_SPEW = 66819, +SPELL_PARALYTIC_BITE = 66824, +SPELL_SWEEP_0 = 66794, +SPELL_SLIME_POOL = 66883, +SPELL_FIRE_SPIT = 66796, +SPELL_MOLTEN_SPEW = 66821, +SPELL_BURNING_BITE = 66879, +SPELL_BURNING_SPRAY = 66902, +SPELL_SWEEP_1 = 67646, +SPELL_FEROCIOUS_BUTT = 66770, +SPELL_MASSIVE_CRASH = 66683, +SPELL_WHIRL = 67345, +SPELL_ARCTIC_BREATH = 66689, +SPELL_TRAMPLE = 66734, +SPELL_ADRENALINE = 68667, +SPELL_SNOBOLLED = 66406, +SPELL_BATTER = 66408, +SPELL_FIRE_BOMB = 66313, +SPELL_FIRE_BOMB_1 = 66317, +SPELL_FIRE_BOMB_DOT = 66318, +SPELL_HEAD_CRACK = 66407, +SPELL_SUBMERGE_0 = 53421, +SPELL_ENRAGE = 68335, +SPELL_FROTHING_RAGE = 66759, +SPELL_STAGGERED_DAZE = 66758, +SPELL_SLIME_POOL_DMG = 66881, +SPELL_SLIME_POOL_AURA = 66882, +SPELL_SLIME_POOL_VISUAL = 63084, }; - -struct MANGOS_DLL_DECL boss_gormokAI : public ScriptedAI +/*##### +# Gormok the Impaler +#####*/ +struct MANGOS_DLL_DECL boss_gormokAI : public BSWScriptedAI { - boss_gormokAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_gormokAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - Unit* pFocus; - - bool m_bIsHeroic; - bool m_bIs25Man; - - uint8 SnoboldsCount; - - uint32 m_uiImpaleTimer; - uint32 m_uiStaggeringStompTimer; - uint32 m_uiSummonSnoboldTimer; + uint16 m_uiSnowboldHealtPercent; - std::list mobsGUIDList; - - void Reset() + void Reset() { - if (!m_pInstance) - return; - - SetEquipmentSlots(false, EQUIP_MAIN, -1, -1); + if(!m_pInstance) return; + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); m_creature->SetRespawnDelay(7*DAY); m_creature->SetInCombatWithZone(); - - SnoboldsCount = m_bIs25Man? 5 : 4; - - pFocus = NULL; - - m_uiImpaleTimer = urand(15000, 30000); - m_uiStaggeringStompTimer = urand(20000, 25000); - m_uiSummonSnoboldTimer = urand(20000, 30000); - - mobsGUIDList.clear(); - } - - void SummonAdds() - { - if (!m_pInstance) - return; - - for (uint32 i = 0; i < SnoboldsCount; i++) - { - Unit *pTemp = m_creature->SummonCreature(NPC_SNOBOLD_VASSAL, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0); - pTemp->EnterVehicle(m_creature->GetVehicleKit(), i); - mobsGUIDList.push_back(pTemp->GetObjectGuid()); - } - } - - void ThrowAdd(Unit *pTarget) - { - if (!m_pInstance || mobsGUIDList.empty()) - return; - - for(std::list::iterator itr = mobsGUIDList.begin(); itr != mobsGUIDList.end(); ++itr) - { - if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) - { - if (pTemp->isAlive()) - { - pTemp->ExitVehicle(); - pTemp->SetInCombatWithZone(); - pTemp->AddThreat(pTarget, 10000.0f); - pTemp->AI()->AttackStart(pTarget); - mobsGUIDList.remove(pTemp->GetObjectGuid()); - break; - } - } - } + m_uiSnowboldHealtPercent = 80; } void JustDied(Unit* pKiller) { - if (!m_pInstance) + if (!m_pInstance) return; - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_DONE); + m_pInstance->SetData(TYPE_GORMOK, DONE); } void JustReachedHome() { - if (!m_pInstance) + if (!m_pInstance) return; - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); - + m_pInstance->SetData(TYPE_GORMOK, FAIL); m_creature->ForcedDespawn(); } void Aggro(Unit* pWho) { - if (!m_pInstance) - return; - - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_IN_PROGRESS); - SummonAdds(); + m_pInstance->SetData(TYPE_GORMOK, IN_PROGRESS); } void UpdateAI(const uint32 uiDiff) @@ -234,33 +134,16 @@ struct MANGOS_DLL_DECL boss_gormokAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiImpaleTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_IMPALE) == CAST_OK) - m_uiImpaleTimer = 10000; - } - else - m_uiImpaleTimer -= uiDiff; + timedCast(SPELL_IMPALE, uiDiff); - if (m_uiStaggeringStompTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_STAGGERING_STOMP) == CAST_OK) - m_uiStaggeringStompTimer = 20000; - } - else - m_uiStaggeringStompTimer -= uiDiff; + timedCast(SPELL_STAGGERING_STOMP, uiDiff); - if (m_uiSummonSnoboldTimer <= uiDiff && SnoboldsCount > 0) + if (m_creature->GetHealthPercent() < m_uiSnowboldHealtPercent) { - DoScriptText(EMOTE_SUMMON_SNOBOLD, m_creature); - ThrowAdd(pFocus = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)); - pFocus->_AddAura(SPELL_SNOBOLLED); - m_creature->_AddAura(SPELL_RISING_ANGER); - --SnoboldsCount; - m_uiSummonSnoboldTimer = 20000; + doCast(SUMMON_SNOBOLD); + DoScriptText(-1713601,m_creature); + m_uiSnowboldHealtPercent -= 20; } - else - m_uiSummonSnoboldTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -271,44 +154,45 @@ CreatureAI* GetAI_boss_gormok(Creature* pCreature) return new boss_gormokAI(pCreature); } -struct MANGOS_DLL_DECL mob_snobold_vassalAI : public ScriptedAI +/*##### +# Snowbold Vassal +#####*/ +struct MANGOS_DLL_DECL mob_snobold_vassalAI : public BSWScriptedAI { - mob_snobold_vassalAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_snobold_vassalAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - Unit *pFocus; - - uint32 m_uiBatterTimer; - uint32 m_uiFireBombTimer; - uint32 m_uiHeadCrackTimer; + Unit* m_pBoss; + Unit* m_pDefaultTarget; void Reset() { - pFocus = NULL; - - m_uiBatterTimer = 10000; - m_uiFireBombTimer = urand(10000, 20000); - m_uiHeadCrackTimer = urand(10000, 30000); - + m_pBoss = NULL; + m_pDefaultTarget = NULL; m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(DAY); + m_pBoss = m_pInstance->GetSingleCreatureFromStorage(NPC_GORMOK); + if (m_pBoss) + doCast(SPELL_RISING_ANGER,m_pBoss); } - void Aggro(Unit *pWho) + void Aggro(Unit *who) { - if (!m_pInstance) + if (!m_pInstance) return; - pFocus = pWho; + m_pDefaultTarget = who; + doCast(SPELL_SNOBOLLED, m_pDefaultTarget); } void JustReachedHome() { - if (!m_pInstance) + if (!m_pInstance) return; m_creature->ForcedDespawn(); @@ -316,50 +200,29 @@ struct MANGOS_DLL_DECL mob_snobold_vassalAI : public ScriptedAI void JustDied(Unit* pKiller) { - if (pFocus && pFocus->isAlive()) - pFocus->RemoveAurasDueToSpell(SPELL_SNOBOLLED); - - m_creature->ForcedDespawn(5000); + if (m_pDefaultTarget && m_pDefaultTarget->isAlive()) + doRemove(SPELL_SNOBOLLED, m_pDefaultTarget); +// if (pBoss && pBoss->isAlive()) doRemove(SPELL_RISING_ANGER,pBoss); +// This string - not offlike, in off this buff not removed! especially for small servers. } void UpdateAI(const uint32 uiDiff) { + if (m_pInstance->GetData(TYPE_BEASTS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) - m_creature->ForcedDespawn(); + timedCast(SPELL_BATTER, uiDiff); - if (m_uiBatterTimer <= uiDiff) + if (timedCast(SPELL_FIRE_BOMB, uiDiff, m_creature->getVictim()) == CAST_OK) { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_BATTER) == CAST_OK) - m_uiBatterTimer = 15000; + doCast(SPELL_FIRE_BOMB_1, m_creature->getVictim()); + doCast(SPELL_FIRE_BOMB_DOT, m_creature->getVictim()); } - else - m_uiBatterTimer -= uiDiff; - if (m_uiFireBombTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIRE_BOMB) == CAST_OK) - { - float x, y, z; - m_creature->GetPosition(x, y, z); - - if (Creature *pBomb = m_creature->SummonCreature(NPC_FIRE_BOMB, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) - pBomb->CastSpell(pBomb, SPELL_FIRE_BOMB_DOT, true); - } - m_uiFireBombTimer = urand(10000, 20000); - } - else - m_uiFireBombTimer -= uiDiff; - - if (m_uiHeadCrackTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEAD_CRACK) == CAST_OK) - m_uiHeadCrackTimer = urand(10000, 30000); - } - else - m_uiHeadCrackTimer -= uiDiff; + timedCast(SPELL_HEAD_CRACK, uiDiff); DoMeleeAttackIfReady(); } @@ -370,113 +233,51 @@ CreatureAI* GetAI_mob_snobold_vassal(Creature* pCreature) return new mob_snobold_vassalAI(pCreature); } -struct MANGOS_DLL_DECL mob_fire_bombAI : public ScriptedAI +/*##### +# Acidmaw +#####*/ +struct MANGOS_DLL_DECL boss_acidmawAI : public BSWScriptedAI { - mob_fire_bombAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_acidmawAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; + uint8 m_uiStage; + bool m_bIsSubmerged; + bool m_bEnraged; + bool m_bFirstAppear; + uint32 m_uiAppearTimer; + uint32 m_uiSpewTimer; - void Reset() - { - m_creature->SetInCombatWithZone(); - SetCombatMovement(false); - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) - m_creature->ForcedDespawn(); - } -}; - -CreatureAI* GetAI_mob_fire_bomb(Creature* pCreature) -{ - return new mob_fire_bombAI(pCreature); -} - -struct MANGOS_DLL_DECL boss_acidmawAI : public ScriptedAI -{ - boss_acidmawAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_trial_of_the_crusader*)pCreature->GetInstanceData(); - Reset(); - } - - instance_trial_of_the_crusader* m_pInstance; - - uint32 m_uiPhase; - uint32 m_uiPhaseTimer; - uint32 m_uiAcidSpewTimer; - uint32 m_uiParalyticBiteTimer; - uint32 m_uiAcidSpitTimer; - uint32 m_uiParalyticSprayTimer; - uint32 m_uiSweepTimer; - uint32 m_uiSlimePoolTimer; - uint32 m_uiAchievTimer; - - bool m_bIsEnraged; - bool m_bAchievFailed; void Reset() { - m_uiPhaseTimer = 65000; - m_uiAcidSpewTimer = urand(10000, 20000); - m_uiParalyticBiteTimer = 15000; - m_uiAcidSpitTimer = 0; - m_uiParalyticSprayTimer = 15000; - m_uiSweepTimer = 20000; - m_uiSlimePoolTimer = 10000; - - m_uiPhase = PHASE_SUBMERGED; - - m_uiAchievTimer = 10000; - - m_bIsEnraged = false; - m_bAchievFailed = false; - + m_uiStage = 1; + m_bEnraged = false; + m_bIsSubmerged = false; + m_bFirstAppear = true; + m_uiAppearTimer = 0; + m_uiSpewTimer = 30000; m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(7*DAY); - m_creature->SetDisplayId(MODEL_ACIDMAW_STATIONARY); - m_creature->SetSpeedRate(MOVE_WALK, 0); - m_creature->SetSpeedRate(MOVE_RUN, 0); + m_pInstance->SetData(TYPE_SNAKES, ACIDMAW_SUBMERGED); } void JustDied(Unit* pKiller) { if (!m_pInstance) return; - - if (Creature* pDreadscale = m_pInstance->GetSingleCreatureFromStorage(NPC_DREADSCALE)) - { - if (!pDreadscale->isAlive()) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_DONE); - else - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_SPECIAL); - } - - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !m_bAchievFailed) - CheckAchiev(); - } - - void CheckAchiev() - { - Map* pMap = m_creature->GetMap(); - Map::PlayerList const& pPlayers = pMap->GetPlayers(); - if (!pPlayers.isEmpty()) + + if (Creature* pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_DREADSCALE)) { - for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) - { - Unit *pTarget = itr->getSource(); - if (pTarget) - m_creature->CastSpell(pTarget, SPELL_CHECK_ACHIEV, true); - } + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_SNAKES, DONE); + else + m_pInstance->SetData(TYPE_SNAKES, SPECIAL); } } @@ -485,129 +286,151 @@ struct MANGOS_DLL_DECL boss_acidmawAI : public ScriptedAI if (!m_pInstance) return; - if (m_pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); - + if (m_pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS && m_pInstance->GetData(TYPE_BEASTS) != FAIL) + m_pInstance->SetData(TYPE_SNAKES, FAIL); + m_creature->ForcedDespawn(); } + void Aggro(Unit* pWho) + { + m_pInstance->SetData(TYPE_SNAKES, IN_PROGRESS); + } + void UpdateAI(const uint32 uiDiff) { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - switch (m_uiPhase) + switch (m_uiStage) { - case PHASE_EMERGED: - if (m_uiAcidSpewTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ACID_SPEW) == CAST_OK) - m_uiAcidSpewTimer = urand(15000, 30000); - } - else - m_uiAcidSpewTimer -= uiDiff; - - if (m_uiParalyticBiteTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_PARALYTIC_BITE) == CAST_OK) - m_uiParalyticBiteTimer = urand(15000, 30000); - } - else - m_uiParalyticBiteTimer -= uiDiff; - - if (m_uiSlimePoolTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_SLIME_POOL) == CAST_OK) - m_uiSlimePoolTimer = 12000; - } - else - m_uiSlimePoolTimer -= uiDiff; - - if (m_uiPhaseTimer <= uiDiff) - { - m_creature->SetDisplayId(MODEL_ACIDMAW_STATIONARY); - m_creature->SetSpeedRate(MOVE_WALK, 0); - m_creature->SetSpeedRate(MOVE_RUN, 0); - DoCastSpellIfCan(m_creature, SPELL_EMERGE); - m_uiPhase = PHASE_SUBMERGED; - m_uiPhaseTimer = 65000; - } - else - m_uiPhaseTimer -= uiDiff; + case 0: + if (m_bIsSubmerged) + { + if (m_uiAppearTimer < uiDiff) + { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + m_bIsSubmerged = false; + } + else + { + m_uiAppearTimer -= uiDiff; + return; + } + } - break; - case PHASE_SUBMERGED: - if (m_uiAcidSpitTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, SPELL_ACID_SPIT) == CAST_OK) - m_uiAcidSpitTimer = 1200; - } - } - else - m_uiAcidSpitTimer -= uiDiff; - - if (m_uiParalyticSprayTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if(DoCastSpellIfCan(pTarget, SPELL_PARALYTIC_SPRAY, CAST_INTERRUPT_PREVIOUS) == CAST_OK) - m_uiParalyticSprayTimer = 20000; - } - } - else - m_uiParalyticSprayTimer -= uiDiff; - - if (m_uiSweepTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_SWEEP, CAST_INTERRUPT_PREVIOUS) == CAST_OK) - { - m_uiSweepTimer = 20000; - m_uiAcidSpitTimer = 3000; - } - } - else - m_uiSweepTimer -= uiDiff; - - if (m_uiPhaseTimer <= uiDiff) - { - m_uiPhase = PHASE_EMERGED; - m_creature->RemoveAurasDueToSpell(SPELL_EMERGE); - m_creature->SetDisplayId(MODEL_ACIDMAW_MOBILE); - m_creature->SetSpeedRate(MOVE_WALK, 1); - m_creature->SetSpeedRate(MOVE_RUN, 1); - SetCombatMovement(true); - DoResetThreat(); - m_uiPhaseTimer = 65000; - } - else - m_uiPhaseTimer -= uiDiff; - - break; - } + if ( m_uiSpewTimer < uiDiff) + { + doCast(SPELL_ACID_SPEW); + m_uiSpewTimer = 30000; + } + else m_uiSpewTimer -= uiDiff; - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !m_bIsEnraged) - { - m_creature->RemoveAurasDueToSpell(SPELL_SUBMERGE); - m_creature->SetDisplayId(MODEL_ACIDMAW_MOBILE); - m_creature->SetSpeedRate(MOVE_WALK, 1); - m_creature->SetSpeedRate(MOVE_RUN, 1); - DoCastSpellIfCan(m_creature, SPELL_ENRAGE, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_EMERGE); + timedCast(SPELL_PARALYTIC_BITE, uiDiff); + + if (timedQuery(SPELL_SLIME_POOL, uiDiff)) + m_creature->SummonCreature(NPC_SLIME_POOL, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + + if (m_pInstance->GetData(TYPE_SNAKES) == ACIDMAW_SUBMERGED) + m_uiStage = 1; + + break; + case 1: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SUBMERGE_0); + m_uiStage = 2; + DoScriptText(-1713557,m_creature); + if (!m_bFirstAppear) + { + if (Creature* pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_DREADSCALE)) + { + float fSisx, fSisy, fSisz; + float fBrox, fBroy, fBroz; + pSister->GetPosition(fSisx, fSisy, fSisz); + m_creature->GetPosition(fBrox, fBroy, fBroz); + m_creature->SetPosition(fSisx, fSisy, fSisz, 0, true); + pSister->SetPosition(fBrox, fBroy, fBroz, 0, true); + } + } + else + { + m_creature->SetPosition(546.347839f, 162.338888f, 395.14f, 0, true); + m_bFirstAppear = false; + } + m_uiAppearTimer = 2000; + m_bIsSubmerged = true; + m_pInstance->SetData(TYPE_SNAKES, ACIDMAW_SUBMERGED); + break; + case 2: + if (m_bIsSubmerged) + { + if (m_uiAppearTimer < uiDiff) + { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_bIsSubmerged = false; + } + else + { + m_uiAppearTimer -= uiDiff; + return; + } + } + + timedCast(SPELL_ACID_SPIT, uiDiff); - DoScriptText(EMOTE_ENRAGE, m_creature); + timedCast(SPELL_PARALYTIC_SPRAY, uiDiff); - m_bIsEnraged = true; - m_uiPhase = PHASE_EMERGED; + timedCast(SPELL_SWEEP_0, uiDiff); + + if ((timedQuery(SPELL_SUBMERGE_0, uiDiff) && m_pInstance->GetData(TYPE_SNAKES) == ACIDMAW_SUBMERGED) || m_pInstance->GetData(TYPE_SNAKES) == DREADSCALE_SUBMERGED) + m_uiStage = 3; + break; + case 3: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SUBMERGE_0); + DoScriptText(-1713557,m_creature); + m_pInstance->SetData(TYPE_SNAKES, DREADSCALE_SUBMERGED); + if (Creature* pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_DREADSCALE)) + { + float fSisx, fSisy, fSisz; + float fBrox, fBroy, fBroz; + pSister->GetPosition(fSisx, fSisy, fSisz); + m_creature->GetPosition(fBrox, fBroy, fBroz); + m_creature->SetPosition(fSisx, fSisy, fSisz, 0, true); + pSister->SetPosition(fBrox, fBroy, fBroz, 0, true); + } + m_uiSpewTimer += 1000; + m_uiAppearTimer = 2000; + m_bIsSubmerged = true; + m_uiStage = 0; + m_pInstance->SetData(TYPE_SNAKES, DREADSCALE_SUBMERGED); + break; } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) + if (m_pInstance->GetData(TYPE_SNAKES) == SPECIAL && !m_bEnraged) { - ++m_uiAchievTimer; - if (m_uiAchievTimer < uiDiff) - m_bAchievFailed = true; - } + DoScriptText(-1713559,m_creature); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + doCast(SPELL_ENRAGE); + doRemove(SPELL_SUBMERGE_0); + m_bEnraged = true; + SetCombatMovement(true); + m_bIsSubmerged = false; + m_uiStage = 0; + DoScriptText(-1713504,m_creature); + } DoMeleeAttackIfReady(); } @@ -618,211 +441,167 @@ CreatureAI* GetAI_boss_acidmaw(Creature* pCreature) return new boss_acidmawAI(pCreature); } -struct MANGOS_DLL_DECL boss_dreadscaleAI : public ScriptedAI +/*##### +# Dreadscale +#####*/ +struct MANGOS_DLL_DECL boss_dreadscaleAI : public BSWScriptedAI { - boss_dreadscaleAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_dreadscaleAI(Creature* pCreature) : BSWScriptedAI(pCreature) { - m_pInstance = (instance_trial_of_the_crusader*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } - instance_trial_of_the_crusader* m_pInstance; - - uint32 m_uiPhase; - uint32 m_uiPhaseTimer; - uint32 m_uiBurningBiteTimer; - uint32 m_uiMoltenSpewTimer; - uint32 m_uiFireSpitTimer; - uint32 m_uiBurningSprayTimer; - uint32 m_uiSweepTimer; - uint32 m_uiSlimePoolTimer; - uint32 m_uiAchievTimer; - - bool m_bIsEnraged; - bool m_bAchievFailed; + ScriptedInstance* m_pInstance; + uint8 m_uiStage; + bool m_bEnraged; + bool m_bIsSubmerged; + uint32 m_uiAppearTimer; + uint32 m_uiSpewTimer; void Reset() { - m_uiPhaseTimer = 65000; - m_uiBurningBiteTimer = urand(10000, 20000); - m_uiMoltenSpewTimer = urand(15000, 30000); - m_uiFireSpitTimer = 1000; - m_uiBurningSprayTimer = 15000; - m_uiSweepTimer = 20000; - m_uiSlimePoolTimer = 10000; - m_uiAchievTimer = 10000; - - m_uiPhase = PHASE_EMERGED; - - m_bIsEnraged = false; - m_bAchievFailed = false; - + m_uiStage = 0; + m_bEnraged = false; + m_bIsSubmerged = false; + m_uiAppearTimer = 0; + m_uiSpewTimer = 30000; m_creature->SetInCombatWithZone(); m_creature->SetRespawnDelay(7*DAY); - m_creature->SetDisplayId(MODEL_DREADSCALE_MOBILE); - m_creature->SetSpeedRate(MOVE_WALK, 1); - m_creature->SetSpeedRate(MOVE_RUN, 1); } void JustDied(Unit* pKiller) { if (!m_pInstance) return; - - if (Creature *pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_ACIDMAW)) - { + + if (Creature* pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_ACIDMAW)) if (!pSister->isAlive()) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_DONE); - else - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_SPECIAL); - } - - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !m_bAchievFailed) - CheckAchiev(); - } - - void CheckAchiev() - { - Map* pMap = m_creature->GetMap(); - Map::PlayerList const& pPlayers = pMap->GetPlayers(); - if (!pPlayers.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) - { - Unit *pTarget = itr->getSource(); - if (pTarget) - m_creature->CastSpell(pTarget, SPELL_CHECK_ACHIEV, true); - } - } + m_pInstance->SetData(TYPE_SNAKES, DONE); + else + m_pInstance->SetData(TYPE_SNAKES, SPECIAL); } void JustReachedHome() { if (!m_pInstance) return; - - if (m_pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); - + + if (m_pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS && m_pInstance->GetData(TYPE_BEASTS) != FAIL) + m_pInstance->SetData(TYPE_SNAKES, FAIL); + m_creature->ForcedDespawn(); } + void Aggro(Unit* pWho) + { + m_pInstance->SetData(TYPE_SNAKES, IN_PROGRESS); + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - switch (m_uiPhase) + switch (m_uiStage) { - case PHASE_EMERGED: - if (m_uiBurningBiteTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_BURNING_BITE) == CAST_OK) - m_uiBurningBiteTimer = urand(15000, 30000); - } - else - m_uiBurningBiteTimer -= uiDiff; - - if (m_uiMoltenSpewTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MOLTEN_SPEW) == CAST_OK) - m_uiMoltenSpewTimer = urand(15000, 30000); - } - else - m_uiMoltenSpewTimer -= uiDiff; - - if (m_uiSlimePoolTimer <= uiDiff) - { - if(DoCastSpellIfCan(m_creature->getVictim(), SPELL_SLIME_POOL) == CAST_OK) - m_uiSlimePoolTimer = 12000; - } - else - m_uiSlimePoolTimer -= uiDiff; - - if (m_uiPhaseTimer <= uiDiff) - { - m_uiPhase = PHASE_SUBMERGED; - DoCastSpellIfCan(m_creature, SPELL_EMERGE); - m_creature->SetDisplayId(MODEL_DREADSCALE_STATIONARY); - m_creature->SetSpeedRate(MOVE_WALK, 0); - m_creature->SetSpeedRate(MOVE_RUN, 0); - m_uiPhaseTimer = 65000; - } - else - m_uiPhaseTimer -= uiDiff; + case 0: + if (m_bIsSubmerged) + { + if (m_uiAppearTimer < uiDiff) + { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + m_bIsSubmerged = false; + } + else + { + m_uiAppearTimer -= uiDiff; + return; + } + } + timedCast(SPELL_BURNING_BITE, uiDiff); - break; - case PHASE_SUBMERGED: - if (m_uiFireSpitTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, SPELL_FIRE_SPIT) == CAST_OK) - m_uiFireSpitTimer = 1200; - } - } - else - m_uiFireSpitTimer -= uiDiff; - - if (m_uiBurningSprayTimer <= uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, SPELL_BURNING_SPRAY, CAST_INTERRUPT_PREVIOUS) == CAST_OK) - m_uiBurningSprayTimer = 20000; - } - } - else - m_uiBurningSprayTimer -= uiDiff; - - if (m_uiSweepTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_SWEEP, CAST_INTERRUPT_PREVIOUS) == CAST_OK) - { - m_uiSweepTimer = 20000; - m_uiFireSpitTimer = 3000; - } - } - else - m_uiSweepTimer -= uiDiff; - - if (m_uiPhaseTimer <= uiDiff) - { - m_uiPhase = PHASE_EMERGED; - m_creature->SetDisplayId(MODEL_DREADSCALE_MOBILE); - m_creature->SetSpeedRate(MOVE_WALK, 1); - m_creature->SetSpeedRate(MOVE_RUN, 1); - SetCombatMovement(true); - m_creature->RemoveAurasDueToSpell(SPELL_EMERGE); - DoResetThreat(); - m_uiPhaseTimer = 65000; - } - else - m_uiPhaseTimer -= uiDiff; + if ( m_uiSpewTimer < uiDiff) + { + doCast(SPELL_MOLTEN_SPEW); + m_uiSpewTimer = 30000; + } + else m_uiSpewTimer -= uiDiff; + if (timedQuery(SPELL_SLIME_POOL, uiDiff)) + m_creature->SummonCreature(NPC_SLIME_POOL, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000); - break; - } + if (m_pInstance->GetData(TYPE_SNAKES) == DREADSCALE_SUBMERGED) + m_uiStage = 1; - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !m_bIsEnraged) - { - m_creature->RemoveAurasDueToSpell(SPELL_SUBMERGE); - m_creature->SetDisplayId(MODEL_DREADSCALE_MOBILE); - m_creature->SetSpeedRate(MOVE_WALK, 1); - m_creature->SetSpeedRate(MOVE_RUN, 1); - DoCastSpellIfCan(m_creature, SPELL_EMERGE, CAST_TRIGGERED); + break; + case 1: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SUBMERGE_0); + m_uiStage = 2; + m_uiAppearTimer = 2000; + m_bIsSubmerged = true; + DoScriptText(-1713557,m_creature); + m_pInstance->SetData(TYPE_SNAKES, DREADSCALE_SUBMERGED); + break; + case 2: + if (m_bIsSubmerged) + { + if (m_uiAppearTimer < uiDiff) + { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_bIsSubmerged = false; + } + else + { + m_uiAppearTimer -= uiDiff; + return; + } + } + timedCast(SPELL_FIRE_SPIT, uiDiff); - DoScriptText(EMOTE_ENRAGE, m_creature); - DoCastSpellIfCan(m_creature, SPELL_ENRAGE, CAST_TRIGGERED); + timedCast(SPELL_BURNING_SPRAY, uiDiff); - m_bIsEnraged = true; + timedCast(SPELL_SWEEP_0, uiDiff); + + if ((timedQuery(SPELL_SUBMERGE_0, uiDiff) && m_pInstance->GetData(TYPE_SNAKES) == DREADSCALE_SUBMERGED) || m_pInstance->GetData(TYPE_SNAKES) == ACIDMAW_SUBMERGED) + m_uiStage = 3; + break; + case 3: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SUBMERGE_0); + DoScriptText(-1713559,m_creature); + m_pInstance->SetData(TYPE_SNAKES, ACIDMAW_SUBMERGED); + m_uiAppearTimer = 2000; + m_uiSpewTimer += 1000; + m_bIsSubmerged = true; + m_uiStage = 0; + break; } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) + if (m_pInstance->GetData(TYPE_SNAKES) == SPECIAL && !m_bEnraged) { - ++m_uiAchievTimer; - if (m_uiAchievTimer < uiDiff) - m_bAchievFailed = true; - } + DoScriptText(-1713559,m_creature); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + doCast(SPELL_ENRAGE); + doRemove(SPELL_SUBMERGE_0); + m_bEnraged = true; + SetCombatMovement(true); + m_bIsSubmerged = false; + m_uiStage = 0; + DoScriptText(-1713504,m_creature); + } DoMeleeAttackIfReady(); } @@ -833,58 +612,67 @@ CreatureAI* GetAI_boss_dreadscale(Creature* pCreature) return new boss_dreadscaleAI(pCreature); } -struct MANGOS_DLL_DECL mob_slime_poolAI : public ScriptedAI +/*##### +# Slime Pool +#####*/ +struct MANGOS_DLL_DECL mob_slime_poolAI : public Scripted_NoMovementAI { - mob_slime_poolAI(Creature *pCreature) : ScriptedAI(pCreature) + mob_slime_poolAI(Creature *pCreature) : Scripted_NoMovementAI(pCreature) { m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); Reset(); } ScriptedInstance *m_pInstance; - - uint32 m_uiIncreaseSizeTimer; - + uint32 m_uiDespawnTimer; + uint32 m_uiSizeTimer; float m_fSize; - bool m_bIsCloudCasted; + bool m_bCloudCasted; void Reset() { - if (!m_pInstance) + if(!m_pInstance) return; - - m_uiIncreaseSizeTimer = 0; - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetInCombatWithZone(); - DoCastSpellIfCan(m_creature, SPELL_SLIME_POOL_AURA, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_AUTO_GROW, CAST_TRIGGERED); - SetCombatMovement(false); - + m_uiDespawnTimer = 30000; + m_bCloudCasted = false; m_fSize = m_creature->GetFloatValue(OBJECT_FIELD_SCALE_X); - m_bIsCloudCasted = false; + m_uiSizeTimer = 500; } - void AttackStart(Unit *who) + void AttackStart(Unit *pWho) { return; } void UpdateAI(const uint32 uiDiff) { - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_DONE) + if (m_pInstance->GetData(TYPE_BEASTS) != IN_PROGRESS) m_creature->ForcedDespawn(); - if (!m_bIsCloudCasted) + if (!m_bCloudCasted) { - m_creature->CastSpell(m_creature, SPELL_SLIME_POOL_VISUAL, false); - m_bIsCloudCasted = true; + DoCast(m_creature, SPELL_SLIME_POOL_VISUAL); + DoCast(m_creature, SPELL_SLIME_POOL_AURA); + m_bCloudCasted = true; } - if (m_fSize >= 6.0f) - m_creature->ForcedDespawn(); + if (m_uiSizeTimer < uiDiff) + { + m_fSize = m_fSize*1.035; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); + m_uiSizeTimer = 500; + } + else m_uiSizeTimer -= uiDiff; + + if (m_uiDespawnTimer <= uiDiff) + { + m_creature->ForcedDespawn(); + } + else + m_uiDespawnTimer -= uiDiff; } }; @@ -894,146 +682,78 @@ CreatureAI* GetAI_mob_slime_pool(Creature* pCreature) return new mob_slime_poolAI(pCreature); } -struct MANGOS_DLL_DECL boss_icehowlAI : public ScriptedAI +/*##### +# Icehowl +#####*/ +struct MANGOS_DLL_DECL boss_icehowlAI : public BSWScriptedAI { - boss_icehowlAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_icehowlAI(Creature* pCreature) : BSWScriptedAI(pCreature) { - m_pInstance = ((instance_trial_of_the_crusader*)pCreature->GetInstanceData()); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } - instance_trial_of_the_crusader* m_pInstance; - - uint32 m_uiFerociousButtTimer; - uint32 m_uiArcticBreathTimer; - uint32 m_uiWhirlTimer; - uint32 m_uiMassiveCrashTimer; - uint32 m_uiWaitTimer; - uint32 m_uiPhaseTimer; - uint32 m_uiPhase; - uint32 m_uiCheckTimer; - + ScriptedInstance* m_pInstance; + bool m_bMovementStarted; + bool m_bTrampleCasted; + uint8 m_uiStage; float fPosX, fPosY, fPosZ; - Unit *pFocus; - bool m_bAchievFailed; - - std::list vassalsEntryList; + Unit* m_pTarget; + Unit* m_pOldTarget; - void Reset() + void Reset() { - if (!m_pInstance) + if(!m_pInstance) return; - - m_uiFerociousButtTimer = 15000; - m_uiArcticBreathTimer = 25000; - m_uiWhirlTimer = 20000; - m_uiMassiveCrashTimer = 30000; - m_uiPhase = PHASE_NORMAL; - m_uiCheckTimer = 0; // if not vassals at encounter start only check once. - m_creature->SetRespawnDelay(7*DAY); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetSpeedRate(MOVE_WALK, 3.0f); - m_creature->SetSpeedRate(MOVE_RUN, 3.0f); - - m_bAchievFailed = false; - - pFocus = NULL; - - vassalsEntryList.clear(); + m_bMovementStarted = false; + m_uiStage = 0; } - void MovementInform(uint32 uiMovementType, uint32 uiData) + void JustDied(Unit* pKiller) { - if (uiMovementType != POINT_MOTION_TYPE) + if (!m_pInstance) return; - if (uiData == POINT_CENTER) - { - if (m_uiPhase == PHASE_MOVING) - { - if (DoCastSpellIfCan(m_creature, SPELL_MASSIVE_CRASH) == CAST_OK) - { - pFocus = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); - DoScriptText(EMOTE_TRAMPLE, m_creature, pFocus); - m_creature->SetSpeedRate(MOVE_WALK, 6.0f); - m_creature->SetSpeedRate(MOVE_RUN, 6.0f); - m_uiWaitTimer = 5000; - m_uiPhaseTimer = 8000; - m_uiPhase = PHASE_TRAMPLE; - } - } - } - else if (uiData == POINT_TARGET) - { - if (m_uiPhase == PHASE_MOVING) - { - if (pFocus && pFocus->isAlive() && m_creature->IsWithinDistInMap(pFocus, 10.0f)) // I think that it should be any player not only focused. - { - DoCastSpellIfCan(m_creature, SPELL_TRAMPLE, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_FROTHING_RAGE, CAST_TRIGGERED); - } - else - { - DoCastSpellIfCan(m_creature, SPELL_STAGGERED_DAZE, CAST_TRIGGERED); - DoScriptText(EMOTE_STAGGERED, m_creature); - } - - if (m_creature->getVictim()) - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetSpeedRate(MOVE_WALK, 3.0f); - m_creature->SetSpeedRate(MOVE_RUN, 3.0f); - SetCombatMovement(true); - m_uiPhase = PHASE_NORMAL; - pFocus = NULL; - } - } + m_pInstance->SetData(TYPE_ICEHOWL, DONE); } - void CheckAchiev() + void MovementInform(uint32 type, uint32 id) { - vassalsEntryList.clear(); - GetCreatureListWithEntryInGrid(vassalsEntryList, m_creature, NPC_SNOBOLD_VASSAL, 250.0f); + if(!m_pInstance) + return; - if (vassalsEntryList.empty()) - { - m_pInstance->SetSpecialAchievementCriteria(TYPE_UPPER_BACK_PAIN, false); - m_bAchievFailed = true; + if(type != POINT_MOTION_TYPE) return; - } - if (vassalsEntryList.size()-1 >= 2) - m_pInstance->SetSpecialAchievementCriteria(TYPE_UPPER_BACK_PAIN, true); + if(id != 1 && m_bMovementStarted) + { + m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ); + } else { - m_pInstance->SetSpecialAchievementCriteria(TYPE_UPPER_BACK_PAIN, false); - m_bAchievFailed = true; + m_creature->GetMotionMaster()->MovementExpired(); + m_bMovementStarted = false; + SetCombatMovement(true); + if (m_pOldTarget && m_pOldTarget->isAlive()) + m_creature->GetMotionMaster()->MoveChase(m_pOldTarget); } } - void JustDied(Unit* pKiller) - { - if (!m_pInstance) - return; - - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_DONE); - } - void JustReachedHome() { - if (!m_pInstance) + if (!m_pInstance) return; - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); - + m_pInstance->SetData(TYPE_ICEHOWL, FAIL); m_creature->ForcedDespawn(); } void Aggro(Unit* pWho) { m_creature->SetInCombatWithZone(); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_IN_PROGRESS); + m_pInstance->SetData(TYPE_ICEHOWL, IN_PROGRESS); } void UpdateAI(const uint32 uiDiff) @@ -1041,93 +761,136 @@ struct MANGOS_DLL_DECL boss_icehowlAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (!m_bAchievFailed) + switch (m_uiStage) { - if (m_uiCheckTimer < uiDiff) + case 0: + timedCast(SPELL_FEROCIOUS_BUTT, uiDiff); + + timedCast(SPELL_ARCTIC_BREATH, uiDiff); + + timedCast(SPELL_WHIRL, uiDiff); + + if (timedQuery(SPELL_MASSIVE_CRASH, uiDiff)) { - CheckAchiev(); - m_uiCheckTimer = 500; + m_creature->SetPosition(SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 0); + m_pOldTarget = m_creature->getVictim(); + m_uiStage = 1; + break; } - else - m_uiCheckTimer -= uiDiff; - } - switch (m_uiPhase) - { - case PHASE_NORMAL: - if (m_uiFerociousButtTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FEROCIOUS_BUTT) == CAST_OK) - m_uiFerociousButtTimer = urand(15000, 30000); - } - else - m_uiFerociousButtTimer -= uiDiff; - - if (m_uiArcticBreathTimer <= uiDiff) - { - if (Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - if (DoCastSpellIfCan(pTarget, SPELL_ARCTIC_BREATH) == CAST_OK) - m_uiArcticBreathTimer = urand(25000, 40000); - } - else - m_uiArcticBreathTimer -= uiDiff; - - if (m_uiWhirlTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_WHIRL) == CAST_OK) - m_uiWhirlTimer = urand(20000, 30000); - } - else - m_uiWhirlTimer -= uiDiff; - - if (m_uiMassiveCrashTimer <= uiDiff) - { - m_creature->AttackStop(); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - SetCombatMovement(false); - m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MovePoint(POINT_CENTER, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - m_uiPhase = PHASE_MOVING; - m_uiMassiveCrashTimer = 40000; - } - else - m_uiMassiveCrashTimer -= uiDiff; - - DoMeleeAttackIfReady(); + timedCast(SPELL_FROTHING_RAGE, uiDiff); - break; - case PHASE_TRAMPLE: - if (m_creature->IsNonMeleeSpellCasted(true)) - return; + DoMeleeAttackIfReady(); - if (m_uiWaitTimer < uiDiff) + break; + case 1: + if (doCast(SPELL_MASSIVE_CRASH) == CAST_OK) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + m_uiStage = 2; + } + break; + case 2: + if (m_pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + { + m_bTrampleCasted = false; + m_uiStage = 3; + resetTimer(SPELL_TRAMPLE); + DoScriptText(-1713506,m_creature,m_pTarget); + m_creature->GetMotionMaster()->MoveIdle(); + } + break; + case 3: + if (timedQuery(SPELL_TRAMPLE,uiDiff)) + { + if (m_pTarget && m_pTarget->isAlive() && (m_pTarget->IsWithinDistInMap(m_creature, 200.0f))) { - if (pFocus && pFocus->isAlive()) + m_pTarget->GetPosition(fPosX, fPosY, fPosZ); + float fTarX, fTarY; + fTarX =fPosX - SpawnLoc[1].x; + fTarY =fPosY - SpawnLoc[1].y; + //this to avoid boss going in texture and despawn + if (fTarX > 0) + fTarX = SpawnLoc[1].x - fTarX +8.0f; + else + fTarX = SpawnLoc[1].x - fTarX -8.0f; + + if (fTarY > 0) + fTarY = SpawnLoc[1].y - fTarY +8.0f; + else + fTarY = SpawnLoc[1].y - fTarY -8.0f; + + m_creature->SetPosition(fTarX, fTarY, fPosZ, 0); + m_bTrampleCasted = false; + m_bMovementStarted = true; + m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ); + DoScriptText(-1713508,m_creature); + m_uiStage = 4; + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { - pFocus->GetPosition(fPosX, fPosY, fPosZ); - m_creature->SetFacingToObject(pFocus); - m_uiWaitTimer = 10000; // For count only once + Unit* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + + if (pPlayer->isAlive()) + { + pPlayer->RemoveAurasDueToSpell(SPELL_MASSIVE_CRASH); + pPlayer->CastSpell(pPlayer, SPELL_ADRENALINE, true); + } } } else - m_uiWaitTimer -= uiDiff; - - if (m_uiPhaseTimer <= uiDiff) { - if (pFocus && pFocus->isAlive()) + m_bTrampleCasted = true; + m_uiStage = 5; + } + } + break; + case 4: + if (m_bMovementStarted) + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 5.0f)) { - m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MovePoint(POINT_TARGET, fPosX, fPosY, fPosZ); - DoScriptText(EMOTE_CRASH, m_creature); - m_uiPhase = PHASE_MOVING; + doCast(SPELL_TRAMPLE, pPlayer); + m_bTrampleCasted = true; + m_bMovementStarted = false; } } - else - m_uiPhaseTimer -= uiDiff; - break; - case PHASE_MOVING: - break; + } + else + m_uiStage = 5; + + if (m_bTrampleCasted) + m_uiStage = 5; + + break; + case 5: + if (!m_bTrampleCasted) + { + doCast(SPELL_STAGGERED_DAZE); + DoScriptText(-1713507,m_creature); + } + m_bMovementStarted = false; + m_creature->GetMotionMaster()->MovementExpired(); + if (m_pOldTarget && m_pOldTarget->isAlive()) + m_creature->GetMotionMaster()->MoveChase(m_pOldTarget); + SetCombatMovement(true); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiStage = 0; + break; } + } }; @@ -1138,40 +901,36 @@ CreatureAI* GetAI_boss_icehowl(Creature* pCreature) void AddSC_northrend_beasts() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_gormok"; - pNewScript->GetAI = &GetAI_boss_gormok; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_acidmaw"; - pNewScript->GetAI = &GetAI_boss_acidmaw; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_dreadscale"; - pNewScript->GetAI = &GetAI_boss_dreadscale; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_icehowl"; - pNewScript->GetAI = &GetAI_boss_icehowl; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_snobold_vassal"; - pNewScript->GetAI = &GetAI_mob_snobold_vassal; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_fire_bomb"; - pNewScript->GetAI = &GetAI_mob_fire_bomb; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_slime_pool"; - pNewScript->GetAI = &GetAI_mob_slime_pool; - pNewScript->RegisterSelf(); + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_gormok"; + newscript->GetAI = &GetAI_boss_gormok; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_acidmaw"; + newscript->GetAI = &GetAI_boss_acidmaw; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_dreadscale"; + newscript->GetAI = &GetAI_boss_dreadscale; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_icehowl"; + newscript->GetAI = &GetAI_boss_icehowl; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_snobold_vassal"; + newscript->GetAI = &GetAI_mob_snobold_vassal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_slime_pool"; + newscript->GetAI = &GetAI_mob_slime_pool; + newscript->RegisterSelf(); + } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp index c45e733252..4b6373aa50 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -21,641 +21,812 @@ SDComment: by /dev/rsa SDCategory: Crusader Coliseum EndScriptData */ +// Twin pact - heal part not worked now by undefined reason. Need override? +// timers need correct + #include "precompiled.h" #include "trial_of_the_crusader.h" -enum BossSpells -{ - // Fjola - SPELL_TWIN_SPIKE_L = 66075, - SPELL_LIGHT_SURGE = 65766, - SPELL_LIGHT_SHIELD = 65858, - SPELL_TWIN_PACT_L = 65876, - SPELL_LIGHT_VORTEX = 66046, - SPELL_LIGHT_TOUCH = 67296, - - // Eydis - SPELL_TWIN_SPIKE_D = 66069, - SPELL_DARK_SURGE = 65768, - SPELL_DARK_SHIELD = 65874, - SPELL_TWIN_PACT_D = 65875, - SPELL_DARK_VORTEX = 66058, - SPELL_DARK_TOUCH = 67281, - - SPELL_TWIN_POWER = 65916, - - SPELL_LIGHT_ESSENCE = 65686, - SPELL_DARK_ESSENCE = 65684, - - SPELL_EMPOWERED_DARK = 67215, - SPELL_EMPOWERED_LIGHT = 65748, - - SPELL_BERSERK = 64238, - SPELL_REMOVE_TOUCH = 68084, - SPELL_NONE = 0, - - SPELL_UNLEASHED_DARK = 65808, - SPELL_UNLEASHED_LIGHT = 65795, -}; - enum Equipment { - EQUIP_MAIN_1 = 49303, - EQUIP_OFFHAND_1 = 47146, - EQUIP_RANGED_1 = 47267, - EQUIP_MAIN_2 = 45990, - EQUIP_OFFHAND_2 = 47470, - EQUIP_RANGED_2 = 47267, - EQUIP_DONE = EQUIP_NO_CHANGE, + EQUIP_MAIN_1 = 49303, + EQUIP_OFFHAND_1 = 47146, + EQUIP_RANGED_1 = 47267, + EQUIP_MAIN_2 = 45990, + EQUIP_OFFHAND_2 = 47470, + EQUIP_RANGED_2 = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, }; enum Summons { - NPC_DARK_ESSENCE = 34567, - NPC_LIGHT_ESSENCE = 34568, + NPC_DARK_ESSENCE = 34567, + NPC_LIGHT_ESSENCE = 34568, - NPC_UNLEASHED_DARK = 34628, - NPC_UNLEASHED_LIGHT = 34630, + NPC_DARK_ORB = 34628, + NPC_LIGHT_ORB = 34630, }; -enum Yells +enum BossSpells { - SAY_AGGRO = -1713541, - SAY_LIGHT_VORTEX = -1713542, - SAY_SLAY_1 = -1713543, - SAY_SLAY_2 = -1713544, - SAY_PACT = -1713545, - SAY_DARK_VORTEX = -1713546, - SAY_DEATH = -1713547, - - EMOTE_LIGHT_VORTEX = -1713538, - EMOTE_PACT = -1713539, - EMOTE_DARK_VORTEX = -1713540, + SPELL_TWIN_SPIKE_L = 66075, + SPELL_LIGHT_SURGE = 65766, + // Shield of Light + SPELL_SHIELD_LIGHT_N10 = 65858, + SPELL_SHIELD_LIGHT_N25 = 67259, + SPELL_SHIELD_LIGHT_H10 = 67260, + SPELL_SHIELD_LIGHT_H25 = 67261, + + SPELL_LIGHT_VORTEX = 66046, + SPELL_LIGHT_TOUCH = 67297, + SPELL_TWIN_SPIKE_H = 66069, + SPELL_DARK_SURGE = 65768, + // Shield of Darkness + SPELL_SHIELD_DARK_N10 = 65874, + SPELL_SHIELD_DARK_N25 = 67256, + SPELL_SHIELD_DARK_H10 = 67257, + SPELL_SHIELD_DARK_H25 = 67258, + + // Twin's Pact + SPELL_TWIN_PACT_20_F = 67306, + SPELL_TWIN_PACT_50_F = 67307, + SPELL_TWIN_PACT_20_E = 67305, + SPELL_TWIN_PACT_50_E = 67304, + + SPELL_DARK_VORTEX = 66058, + SPELL_DARK_TOUCH = 67282, + SPELL_TWIN_POWER = 65916, + SPELL_QUIKNESS = 65949, + SPELL_BERSERK = 64238, + SPELL_REMOVE_TOUCH = 68084, + SPELL_NONE = 0, + + SPELL_UNLEASHED_DARK = 65808, + SPELL_UNLEASHED_LIGHT = 65795, + + // Empowered + SPELL_EMPOWERED_LIGHT_25N = 67216, + SPELL_EMPOWERED_DARK_25N = 67213, + SPELL_EMPOWERED_LIGHT_25H = 67218, + SPELL_EMPOWERED_DARK_25H = 67215, + SPELL_EMPOWERED_LIGHT_10N = 65748, + SPELL_EMPOWERED_DARK_10N = 65724, + SPELL_EMPOWERED_LIGHT_10H = 67217, + SPELL_EMPOWERED_DARK_10H = 67214 }; -enum Phases +uint32 GetRightPactId(Difficulty uiDifficulty, uint32 uiEntry) { - PHASE_NORMAL = 0, - PHASE_SPECIAL = 1, -}; + switch(uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + case RAID_DIFFICULTY_25MAN_NORMAL: + if(uiEntry == NPC_DARKBANE) + return SPELL_TWIN_PACT_20_E; + else if(uiEntry == NPC_LIGHTBANE) + return SPELL_TWIN_PACT_20_F; + case RAID_DIFFICULTY_10MAN_HEROIC: + case RAID_DIFFICULTY_25MAN_HEROIC: + if(uiEntry == NPC_DARKBANE) + return SPELL_TWIN_PACT_50_E; + else if(uiEntry == NPC_LIGHTBANE) + return SPELL_TWIN_PACT_50_F; + default: + return 0; + } +} -enum Specials +uint32 GetRightShieldId(Difficulty uiDifficulty, uint32 uiEntry) { - LIGHT_VORTEX = 0, - LIGHT_PACT = 1, - DARK_VORTEX = 2, - DARK_PACT = 3, -}; + switch(uiEntry) + { + case NPC_LIGHTBANE: + switch (uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: return SPELL_SHIELD_LIGHT_N10; + case RAID_DIFFICULTY_25MAN_NORMAL: return SPELL_SHIELD_LIGHT_N25; + case RAID_DIFFICULTY_10MAN_HEROIC: return SPELL_SHIELD_LIGHT_H10; + case RAID_DIFFICULTY_25MAN_HEROIC: return SPELL_SHIELD_LIGHT_H25; + default: return 0; + } + case NPC_DARKBANE: + switch (uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: return SPELL_SHIELD_DARK_N10; + case RAID_DIFFICULTY_25MAN_NORMAL: return SPELL_SHIELD_DARK_N25; + case RAID_DIFFICULTY_10MAN_HEROIC: return SPELL_SHIELD_DARK_H10; + case RAID_DIFFICULTY_25MAN_HEROIC: return SPELL_SHIELD_DARK_H25; + default: return 0; + } + default: + return 0; + } +} -#define MAX_X = 598.80f; -#define MIN_X = 527.54f; -#define MAX_Y = 176.33f; -#define MIN_Y = 104.54f; +uint32 GetPoweringId(Difficulty uiDifficulty) +{ + switch(uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: return SPELL_POWERUP_N10; + case RAID_DIFFICULTY_25MAN_NORMAL: return SPELL_POWERUP_N25; + case RAID_DIFFICULTY_10MAN_HEROIC: return SPELL_POWERUP_H10; + case RAID_DIFFICULTY_25MAN_HEROIC: return SPELL_POWERUP_H25; + default: return 0; + } +} -struct MANGOS_DLL_DECL boss_fjolaAI : public ScriptedAI +/*##### +# Fjola Lightbane +#####*/ +struct MANGOS_DLL_DECL boss_fjolaAI : public BSWScriptedAI { - boss_fjolaAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_fjolaAI(Creature* pCreature) : BSWScriptedAI(pCreature) { - m_pInstance = (instance_trial_of_the_crusader*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } - instance_trial_of_the_crusader* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - bool m_bAchievFailed; - float x, y, z; - - uint32 m_uiAchievTimer; - uint32 m_uiPhase; - uint32 m_uiTwinSpikeLTimer; + ScriptedInstance* m_pInstance; + uint8 stage; + uint32 m_uiPactTimer; uint32 m_uiSpecialAbilityTimer; - uint32 m_uiLightTouchTimer; - uint32 m_uiCheckTouchBuff; - uint32 m_uiOrbsTimer; - uint32 m_uiNextSpell; - - Unit *pSister; + bool m_bVortexOrPact; + bool m_bIsPact; - void Reset() + void Reset() { - if (!m_pInstance) + if(!m_pInstance) return; - pSister = NULL; - - m_uiAchievTimer = 180000; - m_uiPhase = PHASE_NORMAL; - m_uiNextSpell = urand(0,1); - m_uiTwinSpikeLTimer = 10000; - m_uiSpecialAbilityTimer = 45000; - m_uiLightTouchTimer = 15000; - m_uiCheckTouchBuff = 1000; - m_uiOrbsTimer = 2500; + m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetMaxHealth()); - m_bAchievFailed = false; SetEquipmentSlots(false, EQUIP_MAIN_1, EQUIP_OFFHAND_1, EQUIP_RANGED_1); - m_creature->SetRespawnDelay(7*DAY); - m_creature->SetHealth(m_creature->GetMaxHealth()); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + m_uiSpecialAbilityTimer = 45000; + m_bVortexOrPact = true; + m_bIsPact = false; } void JustReachedHome() { - if (!m_pInstance) + if (!m_pInstance) return; m_pInstance->SetData(TYPE_VALKIRIES, FAIL); m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetMaxHealth()); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); m_creature->ForcedDespawn(); } void JustDied(Unit* pKiller) { - if (!m_pInstance) + if (!m_pInstance) return; - DoScriptText(SAY_DEATH, m_creature); - m_pInstance->SetData(TYPE_VALKIRIES, DONE); - - if (pSister) + DoScriptText(-1713547,m_creature); + if (Creature* pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_DARKBANE)) { - if (pSister->isAlive()) - pKiller->DealDamage(pSister, pSister->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_VALKIRIES, DONE); + else + m_pInstance->SetData(TYPE_VALKIRIES, SPECIAL); } - m_pInstance->SetData(DATA_HEALTH_FJOLA, 0); } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + if (!m_pInstance) return; - - DoScriptText(SAY_SLAY_1 - urand(0, 1),m_creature,pVictim); + DoScriptText(-1713544,m_creature,pVictim); } void Aggro(Unit* pWho) { - if (!m_pInstance) + if (!m_pInstance) return; - pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_DARKBANE); - m_creature->SetInCombatWithZone(); - DoCastSpellIfCan(m_creature, SPELL_LIGHT_SURGE, CAST_TRIGGERED); - - m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetMaxHealth()); m_pInstance->SetData(TYPE_VALKIRIES, IN_PROGRESS); + DoScriptText(-1713541,m_creature); + if (m_creature->isAlive()) + m_creature->SummonCreature(NPC_LIGHT_ESSENCE, SpawnLoc[24].x, SpawnLoc[24].y, SpawnLoc[24].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (m_creature->isAlive()) + m_creature->SummonCreature(NPC_LIGHT_ESSENCE, SpawnLoc[25].x, SpawnLoc[25].y, SpawnLoc[25].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); - m_creature->SummonCreature(NPC_LIGHT_ESSENCE, SpawnLoc[24].x, SpawnLoc[24].y, SpawnLoc[24].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); - m_creature->SummonCreature(NPC_LIGHT_ESSENCE, SpawnLoc[25].x, SpawnLoc[25].y, SpawnLoc[25].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); - - DoScriptText(SAY_AGGRO, m_creature); + m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetMaxHealth()); + doCast(SPELL_LIGHT_SURGE); } void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) { - if (!m_pInstance) + if (!m_pInstance) return; if (!m_creature || !m_creature->isAlive()) return; - if (pDoneBy->GetObjectGuid() == m_creature->GetObjectGuid()) + if (pDoneBy->GetObjectGuid() == m_creature->GetObjectGuid()) return; - if (pDoneBy->GetTypeId() == TYPEID_PLAYER) + if (pDoneBy->GetEntry() == NPC_DARKBANE) { - if (pDoneBy->HasAura(SPELL_LIGHT_ESSENCE)) - uiDamage /= 2; - else if (pDoneBy->HasAura(SPELL_DARK_ESSENCE)) - uiDamage += uiDamage/2; + uiDamage = 0; + return; } m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetHealth() >= uiDamage ? m_creature->GetHealth() - uiDamage : 0); } - void UpdateAI(const uint32 uiDiff) + //hacky workaround for interrupt Twin's Pact + void SpellHit(Unit* who, const SpellEntry* spell) { - if (!m_pInstance) + // don't self interrupt + if (!who->IsControlledByPlayer()) return; - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + if (m_bIsPact) + { + if (spell->EffectMechanic[0] == MECHANIC_INTERRUPT || spell->EffectMechanic[1] == MECHANIC_INTERRUPT || spell->EffectMechanic[2] == MECHANIC_INTERRUPT) + { + if (!m_creature->HasAura(GetRightShieldId(currentDifficulty, m_creature->GetEntry()))) + { + m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL); + m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); - if (!pSister) - return; + Creature* pSis = m_pInstance->GetSingleCreatureFromStorage(NPC_DARKBANE); + if (pSis && pSis->isAlive()) + { + pSis->RemoveAurasDueToSpell(SPELL_TWIN_POWER); + pSis->RemoveAurasDueToSpell(SPELL_QUIKNESS); + } - if (m_creature->GetHealth() > m_pInstance->GetData(DATA_HEALTH_EYDIS) && - m_pInstance->GetData(DATA_HEALTH_EYDIS) != 0) - m_creature->SetHealth(m_pInstance->GetData(DATA_HEALTH_EYDIS)); + m_bIsPact = false; + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + } + } + } + } + + Unit* SelectOppositeColorTarget() + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &pList = pMap->GetPlayers(); + if (pList.isEmpty()) return NULL; + + std::vector lTargetable; + lTargetable.clear(); - if (!m_bAchievFailed) + uint32 uiOppositeColor; + switch (currentDifficulty) { - if (m_uiAchievTimer < uiDiff) - { - m_pInstance->SetSpecialAchievementCriteria(TYPE_SALT_AND_PEPPER, false); - m_bAchievFailed = true; - } - else - m_uiAchievTimer -= uiDiff; + case RAID_DIFFICULTY_10MAN_NORMAL: + uiOppositeColor = SPELL_DARK_ESSENCE; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + uiOppositeColor = SPELL_DARK_ESSENCE_N25; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + uiOppositeColor = SPELL_DARK_ESSENCE_H10; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + uiOppositeColor = SPELL_DARK_ESSENCE_H25; + break; + default: + uiOppositeColor = 0; + break; } + if (!uiOppositeColor) + return NULL; - if (m_bIsHeroic) + for(Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) { - if (m_uiCheckTouchBuff <= uiDiff) + if (Player* pPlayer = i->getSource()) { - Map* pMap = m_creature->GetMap(); - Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) - { - Unit* pPlayer = itr->getSource(); + if (pPlayer->isGameMaster()) + continue; - if (!pPlayer) - continue; - - if (pPlayer->HasAura(SPELL_LIGHT_ESSENCE)) - pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_TOUCH); + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 50.0f)) + { + if (pPlayer->HasAura(uiOppositeColor)) + lTargetable.push_back((Unit*)pPlayer); } - m_uiCheckTouchBuff = 1000; } - else - m_uiCheckTouchBuff -= uiDiff; } - if (m_uiOrbsTimer <= uiDiff) + if (lTargetable.empty()) + return NULL; + else + return lTargetable[urand(0, lTargetable.size() - 1)]; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) + return; + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->getVictim() && m_creature->getVictim()->GetEntry() == NPC_DARKBANE) { - for (uint32 i = 33; i < 37; i++) - { - m_creature->SummonCreature(NPC_UNLEASHED_LIGHT, SpawnLoc[i].x + urand(2.0f, 10.0f), SpawnLoc[i].y + urand(2.0f, 10.0f), SpawnLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); - if (m_bIs25Man) - m_creature->SummonCreature(NPC_UNLEASHED_LIGHT, SpawnLoc[i + 8].x + urand(2.0f, 10.0f), SpawnLoc[i + 8].y + urand(2.0f, 10.0f), SpawnLoc[i + 8].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); - } - m_uiOrbsTimer = 30000; + float sisThreat = m_creature->getThreatManager().getThreat(m_creature->getVictim()); + m_creature->getThreatManager().addThreat(m_creature->getVictim(), -sisThreat); } - else - m_uiOrbsTimer -= uiDiff; - switch (m_uiPhase) + if (m_creature->GetHealth() >= m_pInstance->GetData(DATA_HEALTH_EYDIS)) + m_creature->SetHealth(m_pInstance->GetData(DATA_HEALTH_EYDIS)); + + switch (stage) { - case PHASE_NORMAL: - if (m_uiTwinSpikeLTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_TWIN_SPIKE_L) == CAST_OK) - m_uiTwinSpikeLTimer = 10000; - } - else - m_uiTwinSpikeLTimer -= uiDiff; + case 0: + timedCast(SPELL_TWIN_SPIKE_L, uiDiff); - if (m_bIsHeroic) + if(currentDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) { - if (m_uiLightTouchTimer <= uiDiff) + if (timedQuery(SPELL_LIGHT_TOUCH, uiDiff)) { - if (Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (DoCastSpellIfCan(pTarget, SPELL_LIGHT_TOUCH) == CAST_OK) - m_uiLightTouchTimer = 20000; + if (Unit* pTarget = SelectOppositeColorTarget()) + doCast(SPELL_LIGHT_TOUCH, pTarget); } - else - m_uiLightTouchTimer -= uiDiff; } - if (m_uiSpecialAbilityTimer <= uiDiff) + if (m_uiSpecialAbilityTimer < uiDiff) { - m_creature->InterruptNonMeleeSpells(true); - switch(m_uiNextSpell) + if (m_creature->GetHealthPercent() <= 50.0f) + m_bVortexOrPact = !m_bVortexOrPact; // under 50% healt use alternatively Vortex or Pact ability + else + m_bVortexOrPact = true; // over 50% use only Vortex + + if (m_bVortexOrPact) { - case LIGHT_VORTEX: // Vortex - if (DoCastSpellIfCan(m_creature, SPELL_LIGHT_VORTEX) == CAST_OK) - { - m_creature->SetLevitate(true); - m_creature->GetPosition(x, y, z); - m_creature->GetMotionMaster()->MovePoint(0, x, y, z + 5.0f); - DoScriptText(EMOTE_LIGHT_VORTEX, m_creature); - DoScriptText(SAY_LIGHT_VORTEX, m_creature); - m_uiPhase = PHASE_SPECIAL; - m_uiNextSpell = LIGHT_PACT; - } - break; - case LIGHT_PACT: // Pact - pSister->CastSpell(pSister, SPELL_TWIN_POWER, true); - m_creature->_AddAura(SPELL_LIGHT_SHIELD, 14000); - if (DoCastSpellIfCan(m_creature, SPELL_TWIN_PACT_L) == CAST_OK) - { - m_creature->SetLevitate(true); - m_creature->GetPosition(x, y, z); - m_creature->GetMotionMaster()->MovePoint(0, x, y, z + 5.0f); - DoScriptText(EMOTE_PACT, m_creature); - DoScriptText(SAY_PACT, m_creature); - m_uiPhase = PHASE_SPECIAL; - m_uiNextSpell = LIGHT_VORTEX; - } - break; - default: - break; + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_LIGHT_VORTEX); + DoScriptText(-1713538,m_creature); + stage = 1; } - m_uiSpecialAbilityTimer = 90000; + else + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, GetRightShieldId(currentDifficulty,m_creature->GetEntry())); + m_pInstance->SetData(DATA_CASTING_VALKYRS, GetRightPactId(currentDifficulty, m_creature->GetEntry())); + DoScriptText(-1713539,m_creature); + stage = 3; + } + m_uiSpecialAbilityTimer = 70000; + break; } - else - m_uiSpecialAbilityTimer -= uiDiff; + else m_uiSpecialAbilityTimer -= uiDiff; + if (m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_TWIN_PACT_20_E || m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_TWIN_PACT_50_E) + if (!m_creature->HasAura(SPELL_TWIN_POWER)) + doCast(SPELL_TWIN_POWER); break; - case PHASE_SPECIAL: - if (m_creature->IsNonMeleeSpellCasted(true)) - return; - - m_creature->SetLevitate(false); - m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); - m_uiPhase = PHASE_NORMAL; - m_uiSpecialAbilityTimer -= uiDiff; + case 1: + doCast(SPELL_LIGHT_VORTEX); + stage = 2; break; - default: + case 2: + if (!m_creature->HasAura(SPELL_LIGHT_VORTEX)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + } + break; + case 3: + DoCast(m_creature, GetRightPactId(currentDifficulty, m_creature->GetEntry())); + m_uiPactTimer = 15000; + m_bIsPact = true; + stage = 4; break; + case 4: + if (!m_creature->HasAura(GetRightShieldId(currentDifficulty,m_creature->GetEntry()))) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + } + default: + break; } + + timedCast(SPELL_BERSERK, uiDiff); + + if(m_bIsPact) + { + if (m_uiPactTimer < uiDiff) + { + uint16 pct = 0; + switch (currentDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + case RAID_DIFFICULTY_25MAN_NORMAL: + pct = 20; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + case RAID_DIFFICULTY_25MAN_HEROIC: + pct = 50; + break; + } + uint32 addhealth = m_creature->GetMaxHealth() * pct / 100; + + SpellEntry const *spell = GetSpellStore()->LookupEntry(GetRightPactId(currentDifficulty, m_creature->GetEntry())); + m_creature->DealHeal(m_creature, addhealth, spell); + m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetHealth()); + + Creature* pSis = m_pInstance->GetSingleCreatureFromStorage(NPC_DARKBANE); + if (pSis && pSis->isAlive()) + { + pSis->DealHeal(pSis, addhealth, spell); + m_pInstance->SetData(DATA_HEALTH_EYDIS, pSis->GetHealth()); + } + + pSis->RemoveAurasDueToSpell(SPELL_TWIN_POWER); + pSis->RemoveAurasDueToSpell(SPELL_QUIKNESS); + + m_bIsPact = false; + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + m_uiPactTimer = 15000; + } + else m_uiPactTimer -= uiDiff; + } + DoMeleeAttackIfReady(); } }; CreatureAI* GetAI_boss_fjola(Creature* pCreature) + { return new boss_fjolaAI(pCreature); } -struct MANGOS_DLL_DECL boss_eydisAI : public ScriptedAI +/*##### +# Edys Darkbane +#####*/ +struct MANGOS_DLL_DECL boss_eydisAI : public BSWScriptedAI { - boss_eydisAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_eydisAI(Creature* pCreature) : BSWScriptedAI(pCreature) { - m_pInstance = (instance_trial_of_the_crusader*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } - instance_trial_of_the_crusader* m_pInstance; - Difficulty m_uiMapDifficulty; - bool m_bIsHeroic; - bool m_bIs25Man; - - bool m_bAchievFailed; - - float x, y, z; - - uint32 m_uiAchievTimer; - uint32 m_uiPhase; - uint32 m_uiTwinSpikeDTimer; + ScriptedInstance* m_pInstance; + uint8 stage; + uint32 m_uiSummonTimer; + uint32 m_uiPactTimer; uint32 m_uiSpecialAbilityTimer; - uint32 m_uiDarkTouchTimer; - uint32 m_uiCheckTouchBuff; - uint32 m_uiOrbsTimer; - uint32 m_uiNextSpell; - - Unit *pSister; + bool m_bVortexOrPact; + bool m_bIsPact; void Reset() { - if (!m_pInstance) + if(!m_pInstance) return; - pSister = NULL; - - m_bAchievFailed = false; - - m_uiAchievTimer = 180000; - m_uiPhase = PHASE_NORMAL; - m_uiNextSpell = urand(2,3); - m_uiTwinSpikeDTimer = 10000; - m_uiSpecialAbilityTimer = 90000; - m_uiDarkTouchTimer = 5000; - m_uiCheckTouchBuff = 1000; - m_uiOrbsTimer = 2500; + m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetMaxHealth()); + + m_uiSummonTimer = 45000; SetEquipmentSlots(false, EQUIP_MAIN_2, EQUIP_OFFHAND_2, EQUIP_RANGED_2); - m_creature->SetRespawnDelay(7*DAY); - m_creature->SetHealth(m_creature->GetMaxHealth()); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + m_uiSpecialAbilityTimer = 80000; + m_bVortexOrPact = true; + m_bIsPact = false; } void JustReachedHome() { - if (!m_pInstance) + if (!m_pInstance) return; m_pInstance->SetData(TYPE_VALKIRIES, FAIL); m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetMaxHealth()); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); m_creature->ForcedDespawn(); } void JustDied(Unit* pKiller) { - if (!m_pInstance) + if (!m_pInstance) return; - DoScriptText(SAY_DEATH, m_creature); - m_pInstance->SetData(TYPE_VALKIRIES, DONE); - - if (pSister) + DoScriptText(-1713547,m_creature); + if (Creature* pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_LIGHTBANE)) { - if (pSister->isAlive()) - pKiller->DealDamage(pSister, pSister->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_VALKIRIES, DONE); + else m_pInstance->SetData(TYPE_VALKIRIES, SPECIAL); } - m_pInstance->SetData(DATA_HEALTH_EYDIS, 0); } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(SAY_SLAY_1 - urand(0, 1),m_creature,pVictim); + DoScriptText(-1713543,m_creature,pVictim); } void Aggro(Unit* pWho) { - if (!m_pInstance) + if (!m_pInstance) return; - pSister = m_pInstance->GetSingleCreatureFromStorage(NPC_LIGHTBANE); - m_creature->SetInCombatWithZone(); - DoCastSpellIfCan(m_creature, SPELL_DARK_SURGE, CAST_TRIGGERED); - - m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetMaxHealth()); m_pInstance->SetData(TYPE_VALKIRIES, IN_PROGRESS); + DoScriptText(-1713741,m_creature); + if (m_creature->isAlive()) + m_creature->SummonCreature(NPC_DARK_ESSENCE, SpawnLoc[22].x, SpawnLoc[22].y, SpawnLoc[22].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); - m_creature->SummonCreature(NPC_DARK_ESSENCE, SpawnLoc[22].x, SpawnLoc[22].y, SpawnLoc[22].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); - m_creature->SummonCreature(NPC_DARK_ESSENCE, SpawnLoc[23].x, SpawnLoc[23].y, SpawnLoc[23].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (m_creature->isAlive()) + m_creature->SummonCreature(NPC_DARK_ESSENCE, SpawnLoc[23].x, SpawnLoc[23].y, SpawnLoc[23].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); - DoScriptText(SAY_AGGRO, m_creature); + m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetMaxHealth()); + doCast(SPELL_DARK_SURGE); } void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) { - if (!m_pInstance) + if (!m_pInstance) return; - if (!m_creature || !m_creature->isAlive()) return; - if (pDoneBy->GetObjectGuid() == m_creature->GetObjectGuid()) + if(pDoneBy->GetObjectGuid() == m_creature->GetObjectGuid()) return; - if (pDoneBy->GetTypeId() == TYPEID_PLAYER) + if (pDoneBy->GetEntry() == NPC_LIGHTBANE) { - if (pDoneBy->HasAura(SPELL_DARK_ESSENCE)) - uiDamage /= 2; - else if (pDoneBy->HasAura(SPELL_LIGHT_ESSENCE)) - uiDamage += uiDamage/2; + uiDamage = 0; + return; } m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetHealth() >= uiDamage ? m_creature->GetHealth() - uiDamage : 0); } - void UpdateAI(const uint32 uiDiff) + //hacky workaround for interrupt Twin's Pact + void SpellHit(Unit* who, const SpellEntry* spell) { - if (!m_pInstance) + // don't self interrupt + if (!who->IsControlledByPlayer()) return; + if( m_bIsPact) + { + if (spell->EffectMechanic[0] == MECHANIC_INTERRUPT || spell->EffectMechanic[1] == MECHANIC_INTERRUPT || spell->EffectMechanic[2] == MECHANIC_INTERRUPT) + { + if (!m_creature->HasAura(GetRightShieldId(currentDifficulty, m_creature->GetEntry()))) + { + m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL); + m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + Creature* pSis = m_pInstance->GetSingleCreatureFromStorage(NPC_LIGHTBANE); + if (pSis && pSis->isAlive()) + { + pSis->RemoveAurasDueToSpell(SPELL_TWIN_POWER); + pSis->RemoveAurasDueToSpell(SPELL_QUIKNESS); + } - if (!pSister) - return; + m_bIsPact = false; + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + } + } + } + } + Unit* SelectOppositeColorTarget() + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &pList = pMap->GetPlayers(); + if (pList.isEmpty()) return NULL; - if (m_creature->GetHealth() > m_pInstance->GetData(DATA_HEALTH_FJOLA) && - m_pInstance->GetData(DATA_HEALTH_FJOLA) != 0) - m_creature->SetHealth(m_pInstance->GetData(DATA_HEALTH_FJOLA)); + std::vector lTargetable; + lTargetable.clear(); - if (!m_bAchievFailed) + uint32 uiOppositeColor; + switch (currentDifficulty) { - if (m_uiAchievTimer < uiDiff) - { - m_pInstance->SetSpecialAchievementCriteria(TYPE_SALT_AND_PEPPER, false); - m_bAchievFailed = true; - } - else - m_uiAchievTimer -= uiDiff; + case RAID_DIFFICULTY_10MAN_NORMAL: + uiOppositeColor = SPELL_LIGHT_ESSENCE; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + uiOppositeColor = SPELL_LIGHT_ESSENCE_N25; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + uiOppositeColor = SPELL_LIGHT_ESSENCE_H10; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + uiOppositeColor = SPELL_LIGHT_ESSENCE_H25; + break; + default: + uiOppositeColor = 0; + break; } + if (!uiOppositeColor) + return NULL; - if (m_bIsHeroic) + for(Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) { - if (m_uiCheckTouchBuff <= uiDiff) + if (Player* pPlayer = i->getSource()) { - Map* pMap = m_creature->GetMap(); - Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) - { - Unit* pPlayer = itr->getSource(); + if (pPlayer->isGameMaster()) + continue; - if (!pPlayer) - continue; - - if (pPlayer->HasAura(SPELL_DARK_ESSENCE)) - pPlayer->RemoveAurasDueToSpell(SPELL_DARK_TOUCH); + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 50.0f)) + { + if (pPlayer->HasAura(uiOppositeColor)) + lTargetable.push_back((Unit*)pPlayer); } - m_uiCheckTouchBuff = 1000; } - else - m_uiCheckTouchBuff -= uiDiff; } - if (m_uiOrbsTimer <= uiDiff) + if (lTargetable.empty()) + return NULL; + else + return lTargetable[urand(0, lTargetable.size() - 1)]; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->getVictim() && m_creature->getVictim()->GetEntry() == NPC_LIGHTBANE) { - for (uint32 i = 37; i < 41; i++) - { - m_creature->SummonCreature(NPC_UNLEASHED_DARK, SpawnLoc[i].x + urand(2.0f, 10.0f), SpawnLoc[i].y + urand(2.0f, 5.0f), SpawnLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); - if (m_bIs25Man) - m_creature->SummonCreature(NPC_UNLEASHED_DARK, SpawnLoc[i + 8].x + urand(2.0f, 10.0f), SpawnLoc[i + 8].y + urand(2.0f, 5.0f), SpawnLoc[i + 8].z, 0, TEMPSUMMON_TIMED_DESPAWN, 20000); - } - m_uiOrbsTimer = 30000; + float sisThreat = m_creature->getThreatManager().getThreat(m_creature->getVictim()); + m_creature->getThreatManager().addThreat(m_creature->getVictim(), -sisThreat); } - else - m_uiOrbsTimer -= uiDiff; - switch (m_uiPhase) + if (m_creature->GetHealth() >= m_pInstance->GetData(DATA_HEALTH_FJOLA)) + m_creature->SetHealth(m_pInstance->GetData(DATA_HEALTH_FJOLA)); + + + if(m_uiSummonTimer < uiDiff) { - case PHASE_NORMAL: - if (m_uiTwinSpikeDTimer <= uiDiff) + int8 black = 0; + int8 white = 0; + for (int i=0; i<20; i++) + { + double offset = urand(0, 17); + float x = SpawnLoc[1].x + RAGGIO_ARENA * cos(offset + i*18); + float y = SpawnLoc[1].y + RAGGIO_ARENA * sin(offset + i*18); + + if(white == 10) { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_TWIN_SPIKE_D) == CAST_OK) - m_uiTwinSpikeDTimer = 10000; + black++; + m_creature->SummonCreature(NPC_DARK_ORB, x, y, SpawnLoc[1].z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); + } + else if (black == 10 || urand(0,1)) + { + white++; + m_creature->SummonCreature(NPC_LIGHT_ORB, x, y, SpawnLoc[1].z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); } else - m_uiTwinSpikeDTimer -= uiDiff; + { + black++; + m_creature->SummonCreature(NPC_DARK_ORB, x, y, SpawnLoc[1].z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 45000); + } + } + m_uiSummonTimer = 45000; + } + else + m_uiSummonTimer -= uiDiff; - if (m_bIsHeroic) + switch (stage) + { + case 0: + timedCast(SPELL_TWIN_SPIKE_H, uiDiff); + + if(currentDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) { - if (m_uiDarkTouchTimer <= uiDiff) + if (timedQuery(SPELL_DARK_TOUCH, uiDiff)) { - if (Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (DoCastSpellIfCan(pTarget, SPELL_DARK_TOUCH) == CAST_OK) - m_uiDarkTouchTimer = 20000; + if (Unit* pTarget = SelectOppositeColorTarget()) + doCast(SPELL_DARK_TOUCH, pTarget); } - else - m_uiDarkTouchTimer -= uiDiff; } - if (m_uiSpecialAbilityTimer <= uiDiff) + if (m_uiSpecialAbilityTimer < uiDiff) { - m_creature->InterruptNonMeleeSpells(true); - switch(m_uiNextSpell) + if (m_creature->GetHealthPercent() <= 50.0f) + m_bVortexOrPact = !m_bVortexOrPact; // under 50% healt use alternatively Vortex or Pact ability + else + m_bVortexOrPact = true; // over 50% use only Vortex + + if (m_bVortexOrPact) { - case DARK_VORTEX: - if (DoCastSpellIfCan(m_creature, SPELL_DARK_VORTEX) == CAST_OK) - { - m_creature->SetLevitate(true); - m_creature->GetPosition(x, y, z); - m_creature->GetMotionMaster()->MovePoint(0, x, y, z + 5.0f); - DoScriptText(EMOTE_DARK_VORTEX, m_creature); - DoScriptText(SAY_DARK_VORTEX, m_creature); - m_uiPhase = PHASE_SPECIAL; - m_uiNextSpell = DARK_PACT; - } - break; - case DARK_PACT: - pSister->CastSpell(pSister, SPELL_TWIN_POWER, true); - m_creature->_AddAura(SPELL_DARK_SHIELD, 14000); - if (DoCastSpellIfCan(m_creature, SPELL_TWIN_PACT_D) == CAST_OK) - { - m_creature->SetLevitate(true); - m_creature->GetPosition(x, y, z); - m_creature->GetMotionMaster()->MovePoint(0, x, y, z + 5.0f); - DoScriptText(EMOTE_PACT, m_creature); - DoScriptText(SAY_PACT, m_creature); - m_uiPhase = PHASE_SPECIAL; - m_uiNextSpell = DARK_VORTEX; - } - break; - default: - break; + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_DARK_VORTEX); + DoScriptText(-1713540,m_creature); + stage = 1; + } + else + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, GetRightShieldId(currentDifficulty, m_creature->GetEntry())); + m_pInstance->SetData(DATA_CASTING_VALKYRS, GetRightPactId(currentDifficulty, m_creature->GetEntry())); + DoScriptText(-1713539, m_creature); + stage = 3; } - m_uiSpecialAbilityTimer = 90000; + m_uiSpecialAbilityTimer = 70000; + break; } - else - m_uiSpecialAbilityTimer -= uiDiff; + else m_uiSpecialAbilityTimer -= uiDiff; + if (m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_TWIN_PACT_20_F || m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_TWIN_PACT_50_F) + if (!m_creature->HasAura(SPELL_TWIN_POWER)) + doCast(SPELL_TWIN_POWER); break; - case PHASE_SPECIAL: - if (m_creature->IsNonMeleeSpellCasted(true)) - return; - - //m_creature->SetLevitate(false); - m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); - m_uiPhase = PHASE_NORMAL; - m_uiSpecialAbilityTimer -= uiDiff; + case 1: + doCast(SPELL_DARK_VORTEX); + stage = 2; break; - default: + case 2: + if (!m_creature->HasAura(SPELL_DARK_VORTEX)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + } + break; + case 3: + DoCast(m_creature, GetRightPactId(currentDifficulty, m_creature->GetEntry())); + m_uiPactTimer = 15000; + m_bIsPact = true; + stage = 4; + break; + case 4: + if (!m_creature->HasAura(GetRightShieldId(currentDifficulty,m_creature->GetEntry()))) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + } + default: break; } + + timedCast(SPELL_BERSERK, uiDiff); + + if(m_bIsPact) + { + if (m_uiPactTimer < uiDiff) + { + uint16 pct = 0; + switch (currentDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + case RAID_DIFFICULTY_25MAN_NORMAL: + pct = 20; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + case RAID_DIFFICULTY_25MAN_HEROIC: + pct = 50; + break; + } + uint32 addhealth = m_creature->GetMaxHealth() * pct / 100; + + SpellEntry const *spell = GetSpellStore()->LookupEntry(GetRightPactId(currentDifficulty, m_creature->GetEntry())); + m_creature->DealHeal(m_creature, addhealth, spell); + m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetHealth()); + + Creature* pSis = m_pInstance->GetSingleCreatureFromStorage(NPC_LIGHTBANE); + if (pSis && pSis->isAlive()) + { + pSis->DealHeal(pSis, addhealth, spell); + m_pInstance->SetData(DATA_HEALTH_FJOLA, pSis->GetHealth()); + } + + pSis->RemoveAurasDueToSpell(SPELL_TWIN_POWER); + pSis->RemoveAurasDueToSpell(SPELL_QUIKNESS); + + m_bIsPact = false; + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + m_uiPactTimer = 15000; + } + else m_uiPactTimer -= uiDiff; + } + DoMeleeAttackIfReady(); } }; @@ -665,9 +836,12 @@ CreatureAI* GetAI_boss_eydis(Creature* pCreature) return new boss_eydisAI(pCreature); } +/*##### +# Light Essence +#####*/ struct MANGOS_DLL_DECL mob_light_essenceAI : public ScriptedAI { - mob_light_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_light_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); @@ -675,33 +849,19 @@ struct MANGOS_DLL_DECL mob_light_essenceAI : public ScriptedAI ScriptedInstance* m_pInstance; - void Reset() + void Reset() { m_creature->SetRespawnDelay(DAY); m_creature->SetWalk(true); - SetCombatMovement(false); } void UpdateAI(const uint32 uiDiff) { - if (!m_pInstance) + if (!m_pInstance) m_creature->ForcedDespawn(); - if (m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) - { - Map* pMap = m_creature->GetMap(); - Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) - { - Unit* pPlayer = itr->getSource(); - if (!pPlayer) continue; - if (pPlayer) - pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE); - } - + if (m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) m_creature->ForcedDespawn(); - } - return; } }; @@ -713,21 +873,24 @@ CreatureAI* GetAI_mob_light_essence(Creature* pCreature) bool GossipHello_mob_light_essence(Player *player, Creature* pCreature) { ScriptedInstance *pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - - if (!pInstance) + if(!pInstance) return true; player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetObjectGuid()); player->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE); - player->CastSpell(player,SPELL_LIGHT_ESSENCE, true); - player->RemoveAurasDueToSpell(SPELL_LIGHT_TOUCH); +// player->CastSpell(player,SPELL_REMOVE_TOUCH,false); // Not worked now + player->CastSpell(player,SPELL_LIGHT_ESSENCE,false); + player->RemoveAurasDueToSpell(SPELL_LIGHT_TOUCH); // Override for REMOVE_TOUCH player->CLOSE_GOSSIP_MENU(); return true; }; +/*##### +# Dark Essence +#####*/ struct MANGOS_DLL_DECL mob_dark_essenceAI : public ScriptedAI { - mob_dark_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_dark_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); @@ -735,32 +898,19 @@ struct MANGOS_DLL_DECL mob_dark_essenceAI : public ScriptedAI ScriptedInstance* m_pInstance; - void Reset() + void Reset() { m_creature->SetRespawnDelay(DAY); m_creature->SetWalk(true); - SetCombatMovement(false); } void UpdateAI(const uint32 uiDiff) { - if (!m_pInstance) - m_creature->ForcedDespawn(); + if (!m_pInstance) + m_creature->ForcedDespawn(); - if (m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) - { - Map* pMap = m_creature->GetMap(); - Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) - { - Unit* pPlayer = itr->getSource(); - if (!pPlayer) continue; - if (pPlayer) - pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE); - } + if (m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) m_creature->ForcedDespawn(); - } - return; } }; @@ -772,197 +922,224 @@ CreatureAI* GetAI_mob_dark_essence(Creature* pCreature) bool GossipHello_mob_dark_essence(Player *player, Creature* pCreature) { ScriptedInstance *pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); - - if (!pInstance) + if(!pInstance) return true; - player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetObjectGuid()); player->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE); - player->CastSpell(player,SPELL_DARK_ESSENCE, false); - player->RemoveAurasDueToSpell(SPELL_DARK_TOUCH); +// player->CastSpell(player,SPELL_REMOVE_TOUCH,false); // Not worked now + player->CastSpell(player,SPELL_DARK_ESSENCE,false); + player->RemoveAurasDueToSpell(SPELL_DARK_TOUCH); // Override for REMOVE_TOUCH player->CLOSE_GOSSIP_MENU(); return true; } -struct MANGOS_DLL_DECL mob_unleashed_darkAI : public ScriptedAI +/*##### +# Dark Orb +#####*/ +struct MANGOS_DLL_DECL mob_dark_orbAI : public ScriptedAI { - mob_unleashed_darkAI(Creature *pCreature) : ScriptedAI(pCreature) + mob_dark_orbAI(Creature *pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - - uint32 m_uiCheckTimer; + uint32 m_uiRangeCheck_Timer; + uint32 m_uiDespawnDelay; + Difficulty currentDifficulty; void Reset() { m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->GetMotionMaster()->MoveRandom(); - - SetCombatMovement(false); + SetCombatMovement(false); + m_uiDespawnDelay = 45000; + m_uiRangeCheck_Timer = 500; - m_uiCheckTimer = 1000; + double offset = urand(0, 360); + float x = SpawnLoc[1].x + (RAGGIO_ARENA -5) * cos(offset); + float y = SpawnLoc[1].y + (RAGGIO_ARENA -5) * sin(offset); + m_creature->GetMotionMaster()->MovePoint(0, x, y, SpawnLoc[1].z); } void AttackStart(Unit *pWho) { return; } + + void MovementInform(uint32 uiMotionType, uint32 uiPointId) + { + double offset = urand(0, 360); + float x = SpawnLoc[1].x + (RAGGIO_ARENA -5) * cos(offset); + float y = SpawnLoc[1].y + (RAGGIO_ARENA -5) * sin(offset); + m_creature->GetMotionMaster()->MovePoint(0, x, y, SpawnLoc[1].z); + } void UpdateAI(const uint32 uiDiff) { if (!m_pInstance || m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if(m_uiDespawnDelay <= uiDiff) m_creature->ForcedDespawn(); - - if (m_uiCheckTimer < uiDiff) + else + m_uiDespawnDelay -= uiDiff; + + if (m_uiRangeCheck_Timer < uiDiff) { + bool bContactPositive = false; + bool bContact = false; Map* pMap = m_creature->GetMap(); Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 2.0f)) + { + bContact = true; + break; + } + } + if (bContact) { - Unit* pPlayer = itr->getSource(); - - if (!pPlayer) - continue; - - if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 4.0f)) - { - if (pPlayer->HasAura(SPELL_DARK_ESSENCE)) - { - if (pPlayer->HasAura(SPELL_EMPOWERED_LIGHT)) - pPlayer->RemoveAurasDueToSpell(SPELL_EMPOWERED_LIGHT); - - pPlayer->_AddAura(SPELL_EMPOWERED_DARK, 20000); - m_creature->ForcedDespawn(300); - } - else - { - DoCastSpellIfCan(m_creature, SPELL_UNLEASHED_DARK, CAST_TRIGGERED); - m_creature->ForcedDespawn(700); - } - } + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_DARK, true); + m_uiDespawnDelay = 500; } - m_uiCheckTimer = 500; + m_uiRangeCheck_Timer = 500; } - else - m_uiCheckTimer -= uiDiff; + else m_uiRangeCheck_Timer -= uiDiff; } + }; -CreatureAI* GetAI_mob_unleashed_dark(Creature *pCreature) +CreatureAI* GetAI_mob_dark_orb(Creature *pCreature) { - return new mob_unleashed_darkAI(pCreature); + return new mob_dark_orbAI(pCreature); } -struct MANGOS_DLL_DECL mob_unleashed_lightAI : public ScriptedAI +/*##### +# Light Orb +#####*/ +struct MANGOS_DLL_DECL mob_light_orbAI : public ScriptedAI { - mob_unleashed_lightAI(Creature *pCreature) : ScriptedAI(pCreature) + mob_light_orbAI(Creature *pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + currentDifficulty = pCreature->GetMap()->GetDifficulty(); Reset(); } ScriptedInstance* m_pInstance; - - uint32 m_uiCheckTimer; + uint32 m_uiRangeCheck_Timer; + uint32 m_uiDespawnDelay; + Difficulty currentDifficulty; void Reset() { m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->GetMotionMaster()->MoveRandom(); - - SetCombatMovement(false); + SetCombatMovement(false); + m_uiDespawnDelay = 45000; + m_uiRangeCheck_Timer = 500; - m_uiCheckTimer = 1000; + double offset = urand(0, 360); + float x = SpawnLoc[1].x + (RAGGIO_ARENA -5) * cos(offset); + float y = SpawnLoc[1].y + (RAGGIO_ARENA -5) * sin(offset); + m_creature->GetMotionMaster()->MovePoint(0, x, y, SpawnLoc[1].z); } - + void AttackStart(Unit *pWho) { return; } + + void MovementInform(uint32 uiMotionType, uint32 uiPointId) + { + double offset = urand(0, 360); + float x = SpawnLoc[1].x + (RAGGIO_ARENA -5) * cos(offset); + float y = SpawnLoc[1].y + (RAGGIO_ARENA -5) * sin(offset); + m_creature->GetMotionMaster()->MovePoint(0, x, y, SpawnLoc[1].z); + } void UpdateAI(const uint32 uiDiff) { if (!m_pInstance || m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if(m_uiDespawnDelay <= uiDiff) m_creature->ForcedDespawn(); - - if (m_uiCheckTimer < uiDiff) + else + m_uiDespawnDelay -= uiDiff; + + if (m_uiRangeCheck_Timer < uiDiff) { + bool bContact = false; Map* pMap = m_creature->GetMap(); Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 2.0f)) + { + bContact = true; + break; + } + } + + if (bContact) { - Unit* pPlayer = itr->getSource(); - - if (!pPlayer) - continue; - - if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 4.0f)) - { - if (pPlayer->HasAura(SPELL_LIGHT_ESSENCE)) - { - if (pPlayer->HasAura(SPELL_EMPOWERED_DARK)) - pPlayer->RemoveAurasDueToSpell(SPELL_EMPOWERED_DARK); - - pPlayer->_AddAura(SPELL_EMPOWERED_LIGHT, 20000); - m_creature->ForcedDespawn(300); - } - else - { - DoCastSpellIfCan(m_creature, SPELL_UNLEASHED_LIGHT, CAST_TRIGGERED); - m_creature->ForcedDespawn(700); - } - } + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_LIGHT, true); + m_uiDespawnDelay = 500; } - m_uiCheckTimer = 500; + m_uiRangeCheck_Timer = 500; } - else - m_uiCheckTimer -= uiDiff; + else m_uiRangeCheck_Timer -= uiDiff; } + }; -CreatureAI* GetAI_mob_unleashed_light(Creature *pCreature) +CreatureAI* GetAI_mob_light_orb(Creature *pCreature) { - return new mob_unleashed_lightAI(pCreature); + return new mob_light_orbAI(pCreature); } void AddSC_twin_valkyr() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_fjola"; - pNewScript->GetAI = &GetAI_boss_fjola; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_eydis"; - pNewScript->GetAI = &GetAI_boss_eydis; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_unleashed_light"; - pNewScript->GetAI = &GetAI_mob_unleashed_light; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_unleashed_dark"; - pNewScript->GetAI = &GetAI_mob_unleashed_dark; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_light_essence"; - pNewScript->GetAI = &GetAI_mob_light_essence; - pNewScript->pGossipHello = &GossipHello_mob_light_essence; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_dark_essence"; - pNewScript->GetAI = &GetAI_mob_dark_essence; - pNewScript->pGossipHello = &GossipHello_mob_dark_essence; - pNewScript->RegisterSelf(); + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_fjola"; + newscript->GetAI = &GetAI_boss_fjola; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_eydis"; + newscript->GetAI = &GetAI_boss_eydis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_unleashed_light"; + newscript->GetAI = &GetAI_mob_light_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_unleashed_dark"; + newscript->GetAI = &GetAI_mob_dark_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_light_essence"; + newscript->GetAI = &GetAI_mob_light_essence; + newscript->pGossipHello = &GossipHello_mob_light_essence; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_essence"; + newscript->GetAI = &GetAI_mob_dark_essence; + newscript->pGossipHello = &GossipHello_mob_dark_essence; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp index e0871b6671..e17cc48d20 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -24,489 +24,482 @@ EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" -instance_trial_of_the_crusader::instance_trial_of_the_crusader(Map* pMap) : BSWScriptedInstance(pMap) +struct MANGOS_DLL_DECL instance_trial_of_the_crusader : public BSWScriptedInstance { - Difficulty = pMap->GetDifficulty(); - Initialize(); -} + instance_trial_of_the_crusader(Map* pMap) : BSWScriptedInstance(pMap) + { + m_uiDifficulty = pMap->GetDifficulty(); + Initialize(); + } -void instance_trial_of_the_crusader::Initialize() -{ - for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) - m_auiEncounter[i] = NOT_STARTED; + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + uint32 m_auiEventTimer; + uint32 m_auiEventNPCId; + uint32 m_auiNorthrendBeasts[3]; + uint8 m_uiDifficulty; + std::string m_strInstData; + bool needsave; - for (uint8 i = 0; i < MAX_SPECIAL_ACHIEV_CRITS - 1; ++i) - m_bAchievCriteria[i] = false; + uint32 m_uiDataDamageFjola; + uint32 m_uiDataDamageEydis; + uint32 m_uiValkyrsCasting; - SetSpecialAchievementCriteria(TYPE_IMMORTALITY, true); + uint32 m_uiTributeChest; - m_auiEncounter[TYPE_STAGE] = 0; - m_auiEncounter[TYPE_COUNTER] = 50; - m_auiEncounter[TYPE_EVENT] = 0; + uint32 m_auiCrusadersCount; - m_auiNorthrendBeasts = NOT_STARTED; - m_auiEventTimer = 1000; - m_auiCrusadersCount = 6; - needsave = false; -} + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; -bool instance_trial_of_the_crusader::IsEncounterInProgress() const -{ - for(uint8 i = 1; i < MAX_ENCOUNTERS-2 ; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; + m_auiEncounter[0] = 0; + m_auiEncounter[7] = 50; + m_auiEncounter[8] = 0; - if (m_auiEncounter[TYPE_NORTHREND_BEASTS] == SNAKES_SPECIAL) - return true; + m_auiNorthrendBeasts[0] = NOT_STARTED; + m_auiNorthrendBeasts[1] = NOT_STARTED; + m_auiNorthrendBeasts[2] = NOT_STARTED; - return false; -} + m_auiEventTimer = 1000; + m_auiCrusadersCount = 6; + m_uiTributeChest = 0; -void instance_trial_of_the_crusader::OnPlayerEnter(Player *m_player) -{ - if (Difficulty == RAID_DIFFICULTY_10MAN_HEROIC || Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) - { - m_player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW, 1); - m_player->SendUpdateWorldState(UPDATE_STATE_UI_COUNT, GetData(TYPE_COUNTER)); + uint32 uiTwinHealt; + switch (m_uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + uiTwinHealt = 6066075; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + uiTwinHealt = 8367000; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + uiTwinHealt = 27890000; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + uiTwinHealt = 39046000; + break; + default: + uiTwinHealt = 5000000; + break; + } + m_uiDataDamageFjola = uiTwinHealt; + m_uiDataDamageEydis = uiTwinHealt; + + needsave = false; } -} -void instance_trial_of_the_crusader::OnPlayerDeath(Player* pPlayer) -{ - if (IsEncounterInProgress()) - SetSpecialAchievementCriteria(TYPE_IMMORTALITY, false); -} + bool IsEncounterInProgress() const + { + for(uint8 i = 1; i < MAX_ENCOUNTERS-2 ; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; -bool instance_trial_of_the_crusader::IsRaidWiped() -{ - Map::PlayerList const &players = instance->GetPlayers(); + return false; + } - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + void OnPlayerEnter(Player *m_player) { - if (Player* pPlayer = i->getSource()) + if (m_uiDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) { - if (pPlayer->isAlive()) - return false; - + m_player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW,1); + m_player->SendUpdateWorldState(UPDATE_STATE_UI_COUNT, GetData(TYPE_COUNTER)); } } - return true; -} -void instance_trial_of_the_crusader::UpdateWorldState() -{ - Map::PlayerList const &players = instance->GetPlayers(); - - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + bool IsRaidWiped() { - if (Player* pPlayer = i->getSource()) + Map::PlayerList const &players = instance->GetPlayers(); + + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) { - if (Difficulty == RAID_DIFFICULTY_10MAN_HEROIC || Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + if(Player* pPlayer = i->getSource()) { - pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_SHOW, 1); - pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_COUNT, GetData(TYPE_COUNTER)); + if(pPlayer->isAlive()) + return false; } } + return true; } -} - -void instance_trial_of_the_crusader::OnCreatureCreate(Creature* pCreature) -{ - if (!pCreature) - return; - - m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); -} - -void instance_trial_of_the_crusader::OnObjectCreate(GameObject *pGo) -{ - if (!pGo) - return; - - m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); -} -bool instance_trial_of_the_crusader::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/) -{ - switch (uiCriteriaId) + void OnCreatureCreate(Creature* pCreature) { - case CRITERIA_ACHIEV_UPPER_BACK_PAIN_10N: - case CRITERIA_ACHIEV_UPPER_BACK_PAIN_25N: - return m_bAchievCriteria[TYPE_UPPER_BACK_PAIN]; - case CRITERIA_ACHIEV_SIXTY_PAIN_SPIKE_10N: - case CRITERIA_ACHIEV_SIXTY_PAIN_SPIKE_25N: - return m_bAchievCriteria[TYPE_SIXTY_PAIN_SPIKE]; - case CRITERIA_ACHIEV_SALT_AND_PEPPER_10N: - case CRITERIA_ACHIEV_SALT_AND_PEPPER_10H: - case CRITERIA_ACHIEV_SALT_AND_PEPPER_25N: - case CRITERIA_ACHIEV_SALT_AND_PEPPER_25H: - return m_bAchievCriteria[TYPE_SALT_AND_PEPPER]; - case CRITERIA_ACHIEV_TRIBUTE_TO_SKILL_10: - case CRITERIA_ACHIEV_TRIBUTE_TO_SKILL_25: - return m_bAchievCriteria[TYPE_SKILL]; - case CRITERIA_ACHIEV_TRIBUTE_TO_MAD_SKILL_10: - case CRITERIA_ACHIEV_TRIBUTE_TO_MAD_SKILL_25: - return m_bAchievCriteria[TYPE_MAD_SKILL]; - case CRITERIA_ACHIEV_TRIBUTE_TO_INSANITY_10: - case CRITERIA_ACHIEV_TRIBUTE_TO_INSANITY_25: - return m_bAchievCriteria[TYPE_INSANITY]; - case CRITERIA_ACHIEV_TRIBUTE_TO_IMMORTALITY_HORDE: - case CRITERIA_ACHIEV_TRIBUTE_TO_IMMORTALITY_ALLY: - return m_bAchievCriteria[TYPE_IMMORTALITY]; - default: - return false; + if (!pCreature) + return; + m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); } -} -void instance_trial_of_the_crusader::SetSpecialAchievementCriteria(uint32 uiType, bool bIsMet) -{ - if (uiType < MAX_SPECIAL_ACHIEV_CRITS) - m_bAchievCriteria[uiType] = bIsMet; -} + void OnObjectCreate(GameObject *pGo) + { + if (!pGo) + return; + m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); + } -void instance_trial_of_the_crusader::SetData(uint32 uiType, uint32 uiData) -{ - switch(uiType) + void SetData(uint32 uiType, uint32 uiData) { - case TYPE_STAGE: - m_auiEncounter[TYPE_STAGE] = uiData; - break; - case TYPE_BEASTS: - m_auiEncounter[TYPE_BEASTS] = uiData; - if (uiData == IN_PROGRESS) - SetSpecialAchievementCriteria(TYPE_UPPER_BACK_PAIN, false); - break; - case TYPE_JARAXXUS: - m_auiEncounter[TYPE_JARAXXUS] = uiData; - if (uiData == IN_PROGRESS) - SetSpecialAchievementCriteria(TYPE_SIXTY_PAIN_SPIKE, false); - break; - case TYPE_CRUSADERS: - if (uiData == FAIL && (m_auiEncounter[TYPE_CRUSADERS] == FAIL || m_auiEncounter[TYPE_CRUSADERS] == NOT_STARTED)) - m_auiEncounter[TYPE_CRUSADERS] = NOT_STARTED; - else - m_auiEncounter[TYPE_CRUSADERS] = uiData; - if (uiData == DONE) + + if (uiData == FAIL) { - if (Creature* pTirion = GetSingleCreatureFromStorage(NPC_TIRION)) + switch (uiType) { - Map* pMap = pTirion->GetMap(); - Map::PlayerList const& pPlayers = pMap->GetPlayers(); - if (!pPlayers.isEmpty()) + case TYPE_BEASTS: + case TYPE_JARAXXUS: + case TYPE_CRUSADERS: + case TYPE_VALKIRIES: + case TYPE_ANUBARAK: + if (m_auiEncounter[uiType] != FAIL) + { + if (m_uiDifficulty >= RAID_DIFFICULTY_10MAN_HEROIC) + { + --m_auiEncounter[7]; + needsave = true; + DoUpdateWorldState(UPDATE_STATE_UI_SHOW, 1); + DoUpdateWorldState(UPDATE_STATE_UI_COUNT, m_auiEncounter[7]); + } + } + break; + default: + break; + } + } + + switch(uiType) + { + case TYPE_STAGE: m_auiEncounter[0] = uiData; break; + case TYPE_BEASTS: m_auiEncounter[1] = uiData; break; + case TYPE_JARAXXUS: m_auiEncounter[2] = uiData; break; + case TYPE_CRUSADERS: + if (uiData == FAIL && (m_auiEncounter[3] == FAIL || m_auiEncounter[3] == NOT_STARTED)) + m_auiEncounter[3] = NOT_STARTED; + else + m_auiEncounter[3] = uiData; + + if (uiData == DONE) { - for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) + uint32 uiCacheEntry = GO_CRUSADERS_CACHE_10; + + switch (instance->GetDifficulty()) { - Unit *pTarget = itr->getSource(); - if (pTarget) - pTirion->CastSpell(pTarget, 68184, true); + case RAID_DIFFICULTY_10MAN_HEROIC: + uiCacheEntry = GO_CRUSADERS_CACHE_10_H; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + uiCacheEntry = GO_CRUSADERS_CACHE_25; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + uiCacheEntry = GO_CRUSADERS_CACHE_25_H; + break; } + if (GameObject* pChest = GetSingleGameObjectFromStorage(uiCacheEntry)) + if (!pChest->isSpawned()) + pChest->SetRespawnTime(7*DAY); } - } + break; + case TYPE_CRUSADERS_COUNT: + if (uiData == 0) + --m_auiCrusadersCount; + else + m_auiCrusadersCount = uiData; + break; + case TYPE_VALKIRIES: + if (m_auiEncounter[4] == SPECIAL && uiData == SPECIAL) + uiData = DONE; - uint32 uiCacheEntry = GO_CRUSADERS_CACHE_10; + // remove light/dark essence and poweringup on success/wipe + if(uiData == DONE || uiData == FAIL) + { + Map::PlayerList const &players = instance->GetPlayers(); - switch (instance->GetDifficulty()) - { - case RAID_DIFFICULTY_10MAN_HEROIC: - uiCacheEntry = GO_CRUSADERS_CACHE_10_H; + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + if(Player* pPlayer = i->getSource()) + { + if(pPlayer && pPlayer->isAlive()) + { + switch(m_uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE); + pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE); + pPlayer->RemoveAurasDueToSpell(SPELL_POWERUP_N10); + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE_N25); + pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE_N25); + pPlayer->RemoveAurasDueToSpell(SPELL_POWERUP_N25); + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE_H10); + pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE_H10); + pPlayer->RemoveAurasDueToSpell(SPELL_POWERUP_H10); + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE_H25); + pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE_H25); + pPlayer->RemoveAurasDueToSpell(SPELL_POWERUP_H25); + break; + } + } + } + } + + if (uiData == FAIL) + { + uint32 uiTwinHealt; + switch (m_uiDifficulty) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + uiTwinHealt = 6066075; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + uiTwinHealt = 8367000; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + uiTwinHealt = 27890000; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + uiTwinHealt = 39046000; + break; + default: + uiTwinHealt = 5000000; + break; + } + m_uiDataDamageFjola = uiTwinHealt; + m_uiDataDamageEydis = uiTwinHealt; + } + } + m_auiEncounter[4] = uiData; break; - case RAID_DIFFICULTY_25MAN_NORMAL: - uiCacheEntry = GO_CRUSADERS_CACHE_25; + case TYPE_LICH_KING: m_auiEncounter[5] = uiData; break; + case TYPE_ANUBARAK: m_auiEncounter[6] = uiData; + if (uiData == DONE) + { + if (m_uiDifficulty == RAID_DIFFICULTY_10MAN_HEROIC) + { + if (m_auiEncounter[7] == 50) + m_uiTributeChest = GO_TRIBUTE_CHEST_10H_50; + else if (m_auiEncounter[7] >= 45) + m_uiTributeChest = GO_TRIBUTE_CHEST_10H_45; + else if (m_auiEncounter[7] >= 25) + m_uiTributeChest = GO_TRIBUTE_CHEST_10H_25; + else + m_uiTributeChest = GO_TRIBUTE_CHEST_10H_99; + } + if (m_uiDifficulty == RAID_DIFFICULTY_25MAN_HEROIC) + { + if (m_auiEncounter[7] == 50) + m_uiTributeChest = GO_TRIBUTE_CHEST_25H_50; + else if (m_auiEncounter[7] >= 45) + m_uiTributeChest = GO_TRIBUTE_CHEST_25H_45; + else if (m_auiEncounter[7] >= 25) + m_uiTributeChest = GO_TRIBUTE_CHEST_25H_25; + else + m_uiTributeChest = GO_TRIBUTE_CHEST_25H_99; + } + // reward for clearing TOC instance + if (m_uiTributeChest) + { + DoRespawnGameObject(GetSingleGameObjectFromStorage(m_uiTributeChest)->GetObjectGuid(), DAY); + } + } break; - case RAID_DIFFICULTY_25MAN_HEROIC: - uiCacheEntry = GO_CRUSADERS_CACHE_25_H; + case TYPE_COUNTER: m_auiEncounter[7] = uiData; uiData = DONE; break; + case TYPE_EVENT: m_auiEncounter[8] = uiData; uiData = NOT_STARTED; break; + case TYPE_EVENT_TIMER: m_auiEventTimer = uiData; uiData = NOT_STARTED; break; + case TYPE_GORMOK: + m_auiNorthrendBeasts[0] = uiData; break; - } - if (GameObject* pChest = GetSingleGameObjectFromStorage(uiCacheEntry)) - if (!pChest->isSpawned()) - pChest->SetRespawnTime(7*DAY); - }; - break; - case TYPE_CRUSADERS_COUNT: - if (uiData == 0) - --m_auiCrusadersCount; - else - m_auiCrusadersCount = uiData; - break; - case TYPE_VALKIRIES: - /*if (m_auiEncounter[4] == SPECIAL && uiData == SPECIAL) - uiData = DONE;*/ - m_auiEncounter[TYPE_VALKIRIES] = uiData; - if (uiData == IN_PROGRESS) - SetSpecialAchievementCriteria(TYPE_SALT_AND_PEPPER, true); - break; - case TYPE_LICH_KING: - m_auiEncounter[TYPE_LICH_KING] = uiData; - break; - case TYPE_ANUBARAK: - m_auiEncounter[TYPE_ANUBARAK] = uiData; - - if (uiData == IN_PROGRESS) + case TYPE_SNAKES: + m_auiNorthrendBeasts[1] = uiData; + break; + case TYPE_ICEHOWL: + m_auiNorthrendBeasts[2] = uiData; + break; + case DATA_HEALTH_FJOLA: m_uiDataDamageFjola = uiData; uiData = NOT_STARTED; break; + case DATA_HEALTH_EYDIS: m_uiDataDamageEydis = uiData; uiData = NOT_STARTED; break; + case DATA_CASTING_VALKYRS: m_uiValkyrsCasting = uiData; uiData = NOT_STARTED; break; + } + + if (IsEncounterInProgress()) { - DoCloseDoor(GO_WEB_DOOR); + DoCloseDoor(GO_EAST_PORTCULLIS); + DoCloseDoor(GO_NORTH_PORTCULLIS); + DoCloseDoor(GO_SOUTH_PORTCULLIS); } else - DoOpenDoor(GO_WEB_DOOR); + { + DoOpenDoor(GO_EAST_PORTCULLIS); + DoOpenDoor(GO_NORTH_PORTCULLIS); + DoOpenDoor(GO_SOUTH_PORTCULLIS); + } - if (uiData == DONE) + if ((uiData == DONE && uiType != TYPE_STAGE && uiType != TYPE_EVENT && uiType != TYPE_EVENT_TIMER) || needsave == true) { - if (Difficulty == RAID_DIFFICULTY_10MAN_HEROIC) - { - if (m_auiEncounter[TYPE_COUNTER] >= 25) - m_uiTributeChest1 = GO_TRIBUTE_CHEST_10H_25; - if (m_auiEncounter[TYPE_COUNTER] >= 45) - m_uiTributeChest2 = GO_TRIBUTE_CHEST_10H_45; - if (m_auiEncounter[TYPE_COUNTER] > 49) - m_uiTributeChest3 = GO_TRIBUTE_CHEST_10H_50; - - m_uiTributeChest4 = GO_TRIBUTE_CHEST_10H_99; - } - if (Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) - { - if (m_auiEncounter[TYPE_COUNTER] >= 25) - m_uiTributeChest1 = GO_TRIBUTE_CHEST_25H_25; - if (m_auiEncounter[TYPE_COUNTER] >= 45) - m_uiTributeChest2 = GO_TRIBUTE_CHEST_25H_45; - if (m_auiEncounter[TYPE_COUNTER] > 49) - m_uiTributeChest3 = GO_TRIBUTE_CHEST_25H_50; - - m_uiTributeChest4 = GO_TRIBUTE_CHEST_25H_99; - } - // Attention! It is (may be) not off-like, but spawning all Tribute Chests is real - // reward for clearing TOC instance - if (m_uiTributeChest1) - if (GameObject* pChest1 = GetSingleGameObjectFromStorage(m_uiTributeChest1)) - if (pChest1 && !pChest1->isSpawned()) - pChest1->SetRespawnTime(7*DAY); - - if (m_uiTributeChest2) - if (GameObject* pChest2 = GetSingleGameObjectFromStorage(m_uiTributeChest2)) - if (pChest2 && !pChest2->isSpawned()) - pChest2->SetRespawnTime(7*DAY); - - if (m_uiTributeChest3) - if (GameObject* pChest3 = GetSingleGameObjectFromStorage(m_uiTributeChest3)) - if (pChest3 && !pChest3->isSpawned()) - pChest3->SetRespawnTime(7*DAY); - - if (m_uiTributeChest4) - if (GameObject* pChest4 = GetSingleGameObjectFromStorage(m_uiTributeChest4)) - if (pChest4 && !pChest4->isSpawned()) - pChest4->SetRespawnTime(7*DAY); - }; - break; - case TYPE_COUNTER: - m_auiEncounter[TYPE_COUNTER] = uiData; - if (uiData < 25) - SetSpecialAchievementCriteria(TYPE_SKILL, false); - if (uiData < 45) - SetSpecialAchievementCriteria(TYPE_MAD_SKILL, false); - if (uiData < 50) - SetSpecialAchievementCriteria(TYPE_INSANITY, false); - - //uiData = DONE; - break; - case TYPE_EVENT: - m_auiEncounter[TYPE_EVENT] = uiData; - uiData = NOT_STARTED; - break; - case TYPE_EVENT_TIMER: - m_auiEventTimer = uiData; - uiData = NOT_STARTED; - break; - case TYPE_NORTHREND_BEASTS: - m_auiNorthrendBeasts = uiData; - break; - case DATA_HEALTH_FJOLA: - m_uiDataDamageFjola = uiData; uiData = NOT_STARTED; - break; - case DATA_HEALTH_EYDIS: - m_uiDataDamageEydis = uiData; uiData = NOT_STARTED; - break; - } + OUT_SAVE_INST_DATA; - if (IsEncounterInProgress()) - { - DoCloseDoor(GO_WEST_PORTCULLIS); - DoCloseDoor(GO_NORTH_PORTCULLIS); - DoCloseDoor(GO_SOUTH_PORTCULLIS); + std::ostringstream saveStream; - if (Creature* pBarrent = GetSingleCreatureFromStorage(NPC_BARRENT)) - pBarrent->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - else - { - DoOpenDoor(GO_WEST_PORTCULLIS); - DoCloseDoor(GO_NORTH_PORTCULLIS); - DoCloseDoor(GO_SOUTH_PORTCULLIS); + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; - if (Creature* pBarrent = GetSingleCreatureFromStorage(NPC_BARRENT)) - pBarrent->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - }; + m_strInstData = saveStream.str(); - if (uiData == FAIL && uiType != TYPE_STAGE && uiType != TYPE_EVENT && uiType != TYPE_COUNTER && uiType != TYPE_EVENT_TIMER) - { - if (IsRaidWiped()) - { - --m_auiEncounter[TYPE_COUNTER]; - needsave = true; - UpdateWorldState(); + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + needsave = false; } - uiData = NOT_STARTED; } - if ((uiData == DONE && uiType != TYPE_STAGE && uiType != TYPE_EVENT && uiType != TYPE_EVENT_TIMER) || needsave == true) + uint32 GetData(uint32 uiType) { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) - saveStream << m_auiEncounter[i] << " "; - - m_strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - needsave = false; - } -} + switch(uiType) + { + case TYPE_STAGE: return m_auiEncounter[0]; + case TYPE_BEASTS: return m_auiEncounter[1]; + case TYPE_JARAXXUS: return m_auiEncounter[2]; + case TYPE_CRUSADERS: return m_auiEncounter[3]; + case TYPE_VALKIRIES: return m_auiEncounter[4]; + case TYPE_LICH_KING: return m_auiEncounter[5]; + case TYPE_ANUBARAK: return m_auiEncounter[6]; + case TYPE_COUNTER: return m_auiEncounter[7]; + case TYPE_EVENT: return m_auiEncounter[8]; + case TYPE_DIFFICULTY: return m_uiDifficulty; + case TYPE_GORMOK: return m_auiNorthrendBeasts[0]; + case TYPE_SNAKES: return m_auiNorthrendBeasts[1]; + case TYPE_ICEHOWL: return m_auiNorthrendBeasts[2]; + case TYPE_EVENT_TIMER: return m_auiEventTimer; + case TYPE_CRUSADERS_COUNT: return m_auiCrusadersCount; + case TYPE_EVENT_NPC: switch (m_auiEncounter[8]) + { + case 110: + case 140: + case 150: + case 200: + case 205: + case 210: + case 300: + case 305: + case 310: + case 400: + case 666: + case 1010: + case 1180: + case 2000: + case 2030: + case 3000: + case 3001: + case 3060: + case 3061: + case 3090: + case 3091: + case 3100: + case 3110: + case 4000: + case 4010: + case 4015: + case 4040: + case 4050: + case 5000: + case 5005: + case 5020: + case 6000: + case 6005: + case 6010: + m_auiEventNPCId = NPC_TIRION; + break; + + case 5010: + case 5030: + case 5040: + case 5050: + case 5060: + case 5070: + case 5080: + m_auiEventNPCId = NPC_LICH_KING_1; + break; + + case 130: + case 132: + case 2020: + case 3080: + case 3051: + case 3071: + case 4020: + m_auiEventNPCId = NPC_RINN; + break; + + case 120: + case 122: + case 2010: + case 3050: + case 3070: + case 3081: + case 4030: + m_auiEventNPCId = NPC_GARROSH; + break; + + case 1110: + case 1120: + case 1130: + case 1132: + case 1134: + case 1135: + case 1140: + case 1142: + case 1144: + case 1145: + case 1150: + case 1160: + m_auiEventNPCId = NPC_FIZZLEBANG; + break; + + default: + m_auiEventNPCId = NPC_TIRION; + break; + + }; + return m_auiEventNPCId; -uint32 instance_trial_of_the_crusader::GetData(uint32 uiType) -{ - switch(uiType) - { - case TYPE_STAGE: return m_auiEncounter[0]; - case TYPE_BEASTS: return m_auiEncounter[1]; - case TYPE_JARAXXUS: return m_auiEncounter[2]; - case TYPE_CRUSADERS: return m_auiEncounter[3]; - case TYPE_VALKIRIES: return m_auiEncounter[4]; - case TYPE_LICH_KING: return m_auiEncounter[5]; - case TYPE_ANUBARAK: return m_auiEncounter[6]; - case TYPE_COUNTER: return m_auiEncounter[7]; - case TYPE_EVENT: return m_auiEncounter[8]; - case TYPE_DIFFICULTY: return Difficulty; - case TYPE_NORTHREND_BEASTS: return m_auiNorthrendBeasts; - case TYPE_EVENT_TIMER: return m_auiEventTimer; - case TYPE_CRUSADERS_COUNT: return m_auiCrusadersCount; - case TYPE_EVENT_NPC: - switch (m_auiEncounter[8]) - { - case 110: - case 115: - case 116: - case 140: - case 150: - case 200: - case 205: - case 210: - case 300: - case 305: - case 310: - case 400: - case 666: - case 1010: - case 1180: - case 1999: - case 2000: - case 2030: - case 3000: - case 3001: - case 3060: - case 3061: - case 3090: - case 3091: - case 3100: - case 3110: - case 4000: - case 4010: - case 4015: - case 4040: - case 4050: - case 5000: - case 5005: - case 5020: - case 6000: - case 6005: - case 6010: - m_auiEventNPCId = NPC_TIRION; - break; - case 5010: - case 5030: - case 5040: - case 5050: - case 5060: - case 5070: - case 5080: - m_auiEventNPCId = NPC_LICH_KING_1; - break; - case 130: - case 2020: - case 3080: - case 3051: - case 3071: - case 4020: - m_auiEventNPCId = NPC_RINN; - break; - case 120: - case 2010: - case 3050: - case 3070: - case 3081: - case 4030: - m_auiEventNPCId = NPC_GARROSH; - break; - case 1110: - case 1120: - case 1130: - case 1132: - case 1134: - case 1135: - case 1140: - case 1142: - case 1144: - case 1145: - case 1150: - case 1160: - case 1170: - m_auiEventNPCId = NPC_FIZZLEBANG; - break; - default: - m_auiEventNPCId = NPC_TIRION; - break; - }; - return m_auiEventNPCId; case DATA_HEALTH_FJOLA: return m_uiDataDamageFjola; case DATA_HEALTH_EYDIS: return m_uiDataDamageEydis; + case DATA_CASTING_VALKYRS: return m_uiValkyrsCasting; + } + return 0; } - return 0; -} -void instance_trial_of_the_crusader::Load(const char* strIn) -{ - if (!strIn) + const char* Save() { - OUT_LOAD_INST_DATA_FAIL; - return; + return m_strInstData.c_str(); } - OUT_LOAD_INST_DATA(strIn); + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(strIn); - std::istringstream loadStream(strIn); + std::istringstream loadStream(strIn); - for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) - { - loadStream >> m_auiEncounter[i]; + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } - m_auiEncounter[TYPE_EVENT] = 0; - m_auiEncounter[TYPE_STAGE] = 0; + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + m_auiEncounter[TYPE_EVENT] = 0; + m_auiEncounter[TYPE_STAGE] = 0; - OUT_LOAD_INST_DATA_COMPLETE; + OUT_LOAD_INST_DATA_COMPLETE; -} + } +}; InstanceData* GetInstanceData_instance_trial_of_the_crusader(Map* pMap) { @@ -515,9 +508,9 @@ InstanceData* GetInstanceData_instance_trial_of_the_crusader(Map* pMap) void AddSC_instance_trial_of_the_crusader() { - Script *pNewScript; - pNewScript = new Script; - pNewScript->Name = "instance_trial_of_the_crusader"; - pNewScript->GetInstanceData = &GetInstanceData_instance_trial_of_the_crusader; - pNewScript->RegisterSelf(); + Script *newscript; + newscript = new Script; + newscript->Name = "instance_trial_of_the_crusader"; + newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_crusader; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp index d33abedd79..1035ec8857 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -34,205 +34,164 @@ struct _Messages static _Messages _GossipMessage[]= { - {MSG_BEASTS,GOSSIP_ACTION_INFO_DEF+1,false,TYPE_BEASTS}, - {MSG_JARAXXUS,GOSSIP_ACTION_INFO_DEF+2,false,TYPE_JARAXXUS}, - {MSG_CRUSADERS,GOSSIP_ACTION_INFO_DEF+3,false,TYPE_CRUSADERS}, - {MSG_VALKIRIES,GOSSIP_ACTION_INFO_DEF+4,false,TYPE_VALKIRIES}, - {MSG_LICH_KING,GOSSIP_ACTION_INFO_DEF+5,false,TYPE_ANUBARAK}, + { MSG_BEASTS, GOSSIP_ACTION_INFO_DEF+1, false, TYPE_BEASTS }, // + { MSG_JARAXXUS, GOSSIP_ACTION_INFO_DEF+2, false, TYPE_JARAXXUS }, // + { MSG_CRUSADERS, GOSSIP_ACTION_INFO_DEF+3, false, TYPE_CRUSADERS }, // + { MSG_VALKIRIES, GOSSIP_ACTION_INFO_DEF+4, false, TYPE_VALKIRIES }, // + { MSG_LICH_KING, GOSSIP_ACTION_INFO_DEF+5, false, TYPE_ANUBARAK }, // + { MSG_ANUBARAK, GOSSIP_ACTION_INFO_DEF+6, true, TYPE_ANUBARAK }, // }; enum { - NUM_MESSAGES = 5, + NUM_MESSAGES = 6, + MAGE_TEXT_ID = 14866, SPELL_WILFRED_PORTAL = 68424, SPELL_JARAXXUS_CHAINS = 67924, + SPELL_TELEPORT_DALARAN = 53141, }; + struct MANGOS_DLL_DECL npc_toc_announcerAI : public ScriptedAI { npc_toc_announcerAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - m_uiMapDifficulty = pCreature->GetMap()->GetDifficulty(); - m_bIsHeroic = m_uiMapDifficulty > RAID_DIFFICULTY_25MAN_NORMAL; - m_bIs25Man = (m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_NORMAL || m_uiMapDifficulty == RAID_DIFFICULTY_25MAN_HEROIC); + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - ScriptedInstance* m_pInstance; - Difficulty m_uiMapDifficulty; - - bool m_bIsHeroic; - bool m_bIs25Man; - + ScriptedInstance* pInstance; uint32 DelayTimer; uint32 substage; - uint32 WormsTimer; - uint32 IcehowlTimer; - void Reset() { - if (!m_pInstance) + if (!pInstance) return; - WormsTimer = 150000; - IcehowlTimer = 150000; - - m_pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_STAGE, 0); DelayTimer = 0; m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (Creature *pHorde = GetClosestCreatureWithEntry(m_creature, NPC_THRALL, 300.0f)) - pHorde->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(Creature *pAlly = GetClosestCreatureWithEntry(m_creature, NPC_THRALL, 300.0f)) + pAlly->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (Creature *pAlly = GetClosestCreatureWithEntry(m_creature, NPC_PROUDMOORE, 300.0f)) + if(Creature *pAlly = GetClosestCreatureWithEntry(m_creature, NPC_PROUDMOORE, 300.0f)) pAlly->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetRespawnDelay(DAY); } void AttackStart(Unit *who) { + //ignore all attackstart commands return; } void UpdateAI(const uint32 diff) { - if (!m_pInstance) + if (!pInstance) return; - if (DelayTimer < diff) + if(DelayTimer < diff) { - switch (m_pInstance->GetData(TYPE_STAGE)) + switch (pInstance->GetData(TYPE_STAGE)) { - case 0: + case 0: break; case 1: - if (m_bIsHeroic) + if (pInstance->GetData(TYPE_GORMOK) == DONE) { - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == GORMOK_IN_PROGRESS) - { - if (WormsTimer <= diff) - { - m_pInstance->SetData(TYPE_STAGE,2); - m_pInstance->SetData(TYPE_EVENT,200); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS,SNAKES_IN_PROGRESS); - m_pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); - } - else - WormsTimer -= diff; - } - } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == GORMOK_DONE) - { - m_pInstance->SetData(TYPE_STAGE,2); - m_pInstance->SetData(TYPE_EVENT,200); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS,SNAKES_IN_PROGRESS); - m_pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); + pInstance->SetData(TYPE_STAGE, 2); + if (pInstance->GetData(TYPE_EVENT) != FIGHT2_END && pInstance->GetData(TYPE_EVENT) != FIGHT3_END) + pInstance->SetData(TYPE_EVENT, FIGHT2_INTRO_1); + + pInstance->SetData(TYPE_SNAKES, IN_PROGRESS); + pInstance->SetData(TYPE_BEASTS, IN_PROGRESS); + } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) + if (pInstance->GetData(TYPE_GORMOK) == FAIL) { - m_pInstance->SetData(TYPE_STAGE,0); - m_pInstance->SetData(TYPE_EVENT,666); - m_pInstance->SetData(TYPE_BEASTS, NOT_STARTED); - m_creature->SetDeathState(JUST_DIED); - m_creature->Respawn(); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_EVENT, 666); + pInstance->SetData(TYPE_BEASTS, FAIL); } break; case 2: - if (m_bIsHeroic) + if (pInstance->GetData(TYPE_SNAKES) == DONE) { - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != ICEHOWL_IN_PROGRESS) - { - if (IcehowlTimer <= diff) - { - m_pInstance->SetData(TYPE_STAGE,3); - m_pInstance->SetData(TYPE_EVENT,300); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS,ICEHOWL_IN_PROGRESS); - m_pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); - } - else - IcehowlTimer -= diff; - } - } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_DONE) - { - m_pInstance->SetData(TYPE_STAGE,3); - m_pInstance->SetData(TYPE_EVENT,300); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_IN_PROGRESS); - m_pInstance->SetData(TYPE_BEASTS, IN_PROGRESS); + pInstance->SetData(TYPE_STAGE, 3); + if (pInstance->GetData(TYPE_EVENT) != FIGHT3_END) + pInstance->SetData(TYPE_EVENT, FIGHT3_INTRO_1); + + pInstance->SetData(TYPE_ICEHOWL, IN_PROGRESS); + pInstance->SetData(TYPE_BEASTS, IN_PROGRESS); } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) + if (pInstance->GetData(TYPE_SNAKES) == FAIL) { - m_pInstance->SetData(TYPE_STAGE,0); - m_pInstance->SetData(TYPE_EVENT,666); - m_pInstance->SetData(TYPE_BEASTS, NOT_STARTED); - m_creature->SetDeathState(JUST_DIED); - m_creature->Respawn(); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_EVENT, 666); + pInstance->SetData(TYPE_BEASTS, FAIL); } break; case 3: - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == ICEHOWL_DONE) + if (pInstance->GetData(TYPE_ICEHOWL) == DONE) { - m_pInstance->SetData(TYPE_STAGE,0); - m_pInstance->SetData(TYPE_BEASTS, DONE); - m_pInstance->SetData(TYPE_EVENT,400); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, DONE); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_BEASTS, DONE); + pInstance->SetData(TYPE_EVENT, 400); } - if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) + if (pInstance->GetData(TYPE_ICEHOWL) == FAIL) { - m_pInstance->SetData(TYPE_STAGE,0); - m_pInstance->SetData(TYPE_EVENT,666); - m_pInstance->SetData(TYPE_BEASTS, NOT_STARTED); - m_creature->SetDeathState(JUST_DIED); - m_creature->Respawn(); - }; + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_EVENT, 666); + pInstance->SetData(TYPE_BEASTS, FAIL); + } break; case 4: - break; case 5: break; case 6: - if (m_pInstance->GetData(TYPE_CRUSADERS_COUNT) == 0 && m_pInstance->GetData(TYPE_CRUSADERS) == IN_PROGRESS) + if (pInstance->GetData(TYPE_CRUSADERS_COUNT) == 0 && pInstance->GetData(TYPE_CRUSADERS) == IN_PROGRESS) { - m_pInstance->SetData(TYPE_STAGE, 0); - m_pInstance->SetData(TYPE_CRUSADERS, DONE); - m_pInstance->SetData(TYPE_EVENT, 3100); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_CRUSADERS, DONE); + pInstance->SetData(TYPE_EVENT, 3100); } break; case 7: - if (m_pInstance->GetData(TYPE_VALKIRIES) == DONE) + if (pInstance->GetData(TYPE_VALKIRIES) == DONE) { - m_pInstance->SetData(TYPE_STAGE, 0); - m_pInstance->SetData(TYPE_EVENT, 4020); - m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_EVENT, 4020); } - if (m_pInstance->GetData(TYPE_VALKIRIES) == FAIL) + if (pInstance->GetData(TYPE_VALKIRIES) == FAIL) { - m_pInstance->SetData(TYPE_STAGE, 0); - m_pInstance->SetData(TYPE_EVENT, 0); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_EVENT, 0); } break; case 8: break; case 9: - if (m_pInstance->GetData(TYPE_ANUBARAK) == DONE) + if (pInstance->GetData(TYPE_ANUBARAK) == DONE) { - m_pInstance->SetData(TYPE_STAGE, 10); - m_pInstance->SetData(TYPE_EVENT, 6000); + pInstance->SetData(TYPE_STAGE, 10); + pInstance->SetData(TYPE_EVENT, 6000); } - if (m_pInstance->GetData(TYPE_ANUBARAK) == FAIL) + if (pInstance->GetData(TYPE_ANUBARAK) == FAIL) { - m_pInstance->SetData(TYPE_STAGE, 0); - m_pInstance->SetData(TYPE_EVENT, 0); + pInstance->SetData(TYPE_STAGE, 0); + pInstance->SetData(TYPE_EVENT, 0); } break; case 10: - //m_creature->ForcedDespawn(); - break; +// m_creature->ForcedDespawn(); + break; } } - else DelayTimer -= diff; + else + DelayTimer -= diff; } }; @@ -243,52 +202,50 @@ CreatureAI* GetAI_npc_toc_announcer(Creature* pCreature) bool GossipHello_npc_toc_announcer(Player* pPlayer, Creature* pCreature) { - ScriptedInstance* m_pInstance; - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); char const* _message; uint8 i; - if (!m_pInstance) + if (!pInstance) return false; - if (pPlayer->IsInCombat() || m_pInstance->IsEncounterInProgress() || m_pInstance->GetData(TYPE_EVENT)) - return true; + if( pPlayer->IsInCombat() || pInstance->IsEncounterInProgress() || pInstance->GetData(TYPE_EVENT)) + return true; switch (LocaleConstant currentlocale = pPlayer->GetSession()->GetSessionDbcLocale()) { - case LOCALE_esES: - _message = "¡Estamos listos!"; - break; - case LOCALE_esMX: - _message = "¡Estamos listos!"; - break; - case LOCALE_ruRU: - _message = "Всегда готовы!"; - break; case LOCALE_enUS: case LOCALE_koKR: case LOCALE_frFR: case LOCALE_deDE: case LOCALE_zhCN: case LOCALE_zhTW: + case LOCALE_esES: + case LOCALE_esMX: + _message = "We are ready!"; + break; + case LOCALE_ruRU: + _message = "Всегда готовы!"; + break; default: - _message = "We are ready!"; - break; - }; + _message = "We are ready!"; + break; + } - for (i = 0; i < NUM_MESSAGES; i++) + for(i = 0; i < NUM_MESSAGES; i++) { - if (!_GossipMessage[i].state && (m_pInstance->GetData(_GossipMessage[i].encounter) != DONE )) + if (!_GossipMessage[i].state && (pInstance->GetData(_GossipMessage[i].encounter) != DONE )) { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); break; } - if (_GossipMessage[i].state && m_pInstance->GetData(_GossipMessage[i].encounter) == DONE) + if (_GossipMessage[i].state && pInstance->GetData(_GossipMessage[i].encounter) == DONE) { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); break; } - }; + } pPlayer->SEND_GOSSIP_MENU(_GossipMessage[i].msgnum, pCreature->GetObjectGuid()); @@ -299,84 +256,95 @@ bool GossipSelect_npc_toc_announcer(Player* pPlayer, Creature* pCreature, uint32 { ScriptedInstance* pInstance; pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); - if (!pInstance) return false; -pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CLOSE_GOSSIP_MENU(); -switch(uiAction) { - case GOSSIP_ACTION_INFO_DEF+1: - if (pInstance->GetData(TYPE_BEASTS) != DONE) - { - pInstance->SetData(TYPE_EVENT,110); - pInstance->SetData(TYPE_NORTHREND_BEASTS,NOT_STARTED); - pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); - }; - break; - case GOSSIP_ACTION_INFO_DEF+2: - if (pInstance->GetData(TYPE_JARAXXUS) != DONE) - pInstance->SetData(TYPE_EVENT,1010); - - break; - case GOSSIP_ACTION_INFO_DEF+3: - if (pInstance->GetData(TYPE_CRUSADERS) != DONE) - { - if (pPlayer->GetTeam() == ALLIANCE) - pInstance->SetData(TYPE_EVENT,3000); - else - pInstance->SetData(TYPE_EVENT,3001); - }; - break; - case GOSSIP_ACTION_INFO_DEF+4: - if (pInstance->GetData(TYPE_VALKIRIES) != DONE) - pInstance->SetData(TYPE_EVENT,4000); - - break; - case GOSSIP_ACTION_INFO_DEF+5: - Map* pMap = pCreature->GetMap(); - Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) - { - Unit* pPlayer = itr->getSource(); - if (!pPlayer) - continue; - float x, y, z; - pPlayer->GetPosition(x, y, z); - pPlayer->MonsterMoveJump(x, y, z + 10.0f, 3.14f, 10.0f, 0.0f, true); - } - if (GameObject* pGoFloor = pInstance->GetSingleGameObjectFromStorage(GO_ARGENT_COLISEUM_FLOOR)) + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + if (pInstance->GetData(TYPE_BEASTS) != DONE) + { + pInstance->SetData(TYPE_EVENT, 110); + pInstance->SetData(TYPE_GORMOK, NOT_STARTED); + pInstance->SetData(TYPE_SNAKES, NOT_STARTED); + pInstance->SetData(TYPE_ICEHOWL, NOT_STARTED); + pInstance->SetData(TYPE_BEASTS, IN_PROGRESS); + } + break; + case GOSSIP_ACTION_INFO_DEF+2: + if (pInstance->GetData(TYPE_JARAXXUS) != DONE) + pInstance->SetData(TYPE_EVENT, 1010); + break; + case GOSSIP_ACTION_INFO_DEF+3: + if (pInstance->GetData(TYPE_CRUSADERS) != DONE) + { + if (pPlayer->GetTeam() == ALLIANCE) + pInstance->SetData(TYPE_EVENT, 3000); + else + pInstance->SetData(TYPE_EVENT, 3001); + } + break; + case GOSSIP_ACTION_INFO_DEF+4: + if (pInstance->GetData(TYPE_VALKIRIES) != DONE) + pInstance->SetData(TYPE_EVENT, 4000); + break; + case GOSSIP_ACTION_INFO_DEF+5: { - pGoFloor->SetUInt32Value(GAMEOBJECT_DISPLAYID,9060); - pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); - pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,8449); - } - pCreature->CastSpell(pCreature,69016,false); + if (pInstance->GetData(TYPE_LICH_KING) != DONE) + { + pInstance->SetData(TYPE_EVENT, 5000); + break; + } + + if (GameObject* pGoFloor = pInstance->GetSingleGameObjectFromStorage(GO_ARGENT_COLISEUM_FLOOR)) + { + pGoFloor->SetUInt32Value(GAMEOBJECT_DISPLAYID, 9060); + pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1, 8449); + } - Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_ANUBARAK); + pCreature->CastSpell(pCreature, 69016, false); + + Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_ANUBARAK); - if (!pTemp || !pTemp->isAlive()) - pCreature->SummonCreature(NPC_ANUBARAK, SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - - if (pCreature->GetVisibility() == VISIBILITY_ON) - pCreature->SetVisibility(VISIBILITY_OFF); + if (!pTemp || !pTemp->isAlive()) + pTemp = pCreature->SummonCreature(NPC_ANUBARAK, SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - break; -}; + if (pTemp) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[20].x, SpawnLoc[20].y, SpawnLoc[20].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } + + pInstance->SetData(TYPE_STAGE, 9); + pInstance->SetData(TYPE_ANUBARAK, IN_PROGRESS); + pInstance->SetData(TYPE_EVENT, 0); + + if (pCreature->GetVisibility() == VISIBILITY_ON) + pCreature->SetVisibility(VISIBILITY_OFF); + break; + } + case GOSSIP_ACTION_INFO_DEF+6: + pInstance->SetData(TYPE_STAGE, 10); + break; + } -return true; + return true; } struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI { boss_lich_king_tocAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); WayPointList.clear(); JustRespawned(); } - ScriptedInstance* m_pInstance; + ScriptedInstance* pInstance; uint32 UpdateTimer; uint32 event_state_lich_king; bool Event; @@ -385,7 +353,7 @@ struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI std::list::iterator WayPoint; uint32 WalkTimer; bool IsWalking; - ObjectGuid m_uiPortalGuid; + Creature* pPortal; void Reset() { @@ -394,27 +362,21 @@ struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI Event = false; MovementStarted = false; m_creature->SetRespawnDelay(DAY); - if (Creature* pPortal = m_creature->SummonCreature(NPC_TRIGGER, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) + + if(pPortal = m_creature->SummonCreature(NPC_TRIGGER, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) { pPortal->SetRespawnDelay(DAY); pPortal->CastSpell(pPortal, 51807, false); pPortal->SetDisplayId(17612); - m_uiPortalGuid = pPortal->GetObjectGuid(); } - if (m_pInstance) - m_pInstance->SetData(TYPE_LICH_KING,IN_PROGRESS); - } - Creature* GetCreatureFromGuid(ObjectGuid m_uiGuid) - { - if (Creature* pCreature = m_creature->GetMap()->GetCreature(m_uiGuid)) - return pCreature; - - return NULL; + if(pInstance) + pInstance->SetData(TYPE_LICH_KING, IN_PROGRESS); } void AttackStart(Unit *who) { + //ignore all attackstart commands return; } @@ -423,21 +385,26 @@ struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI Reset(); } + void MoveInLineOfSight(Unit *who) + { + } + void StartMovement() { if(!WayPointList.empty() || MovementStarted) return; AddWaypoint(0, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z); - AddWaypoint(1, SpawnLoc[18].x, SpawnLoc[18].y, SpawnLoc[18].z); + AddWaypoint(1, SpawnLoc[17].x, SpawnLoc[17].y, SpawnLoc[17].z); AddWaypoint(2, SpawnLoc[18].x, SpawnLoc[18].y, SpawnLoc[18].z); + m_creature->SetWalk(true); WayPoint = WayPointList.begin(); MovementStarted = true; IsWalking = true; WalkTimer = 200; event_state_lich_king = 1; - UpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); } void AddWaypoint(uint32 id, float x, float y, float z) @@ -448,10 +415,10 @@ struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI void UpdateAI(const uint32 diff) { - if (!m_pInstance) + if(!pInstance) return; - if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING_1) + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING_1) return; if (!MovementStarted) @@ -471,104 +438,94 @@ struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI WalkTimer -= diff; } - UpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); if (UpdateTimer <= diff) { - switch (m_pInstance->GetData(TYPE_EVENT)) + switch (pInstance->GetData(TYPE_EVENT)) { - case 5010: - DoScriptText(-1713550,m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,5020); - break; - case 5030: - DoScriptText(-1713552,m_creature); - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,5040); - break; - case 5040: - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - UpdateTimer = 1000; - m_pInstance->SetData(TYPE_EVENT,5050); - break; - case 5050: - m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - UpdateTimer = 9000; - m_pInstance->SetData(TYPE_EVENT,5060); - break; - case 5060: - if (Event) + case 5010: + DoScriptText(-1713550, m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 5020); + break; + case 5030: + DoScriptText(-1713552, m_creature); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, 5040); + break; + case 5040: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + UpdateTimer = 1000; + pInstance->SetData(TYPE_EVENT, 5050); + break; + case 5050: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 5060); + break; + case 5060: { - DoScriptText(-1713553,m_creature); - m_creature->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); - UpdateTimer = 2500; - m_pInstance->SetData(TYPE_EVENT,5070); + if (Event) + { + DoScriptText(-1713553, m_creature); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + UpdateTimer = 2500; + pInstance->SetData(TYPE_EVENT, 5070); + } + break; } - break; - case 5070: - { - m_creature->CastSpell(m_creature,68198,false); - Map* pMap = m_creature->GetMap(); - Map::PlayerList const &lPlayers = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + case 5070: { - Unit* pPlayer = itr->getSource(); - if (!pPlayer) - continue; - - float x, y, z; - pPlayer->GetPosition(x, y, z); - pPlayer->MonsterMoveJump(x, y, z + 10.0f, 3.14f, 10.0f, 0.0f, true); + m_creature->CastSpell(m_creature, 68198, false); + UpdateTimer = 1500; + pInstance->SetData(TYPE_EVENT, 5080); + break; } - UpdateTimer = 1500; - m_pInstance->SetData(TYPE_EVENT,5080); - break; - } - case 5080: - if (GameObject* pGoFloor = m_pInstance->GetSingleGameObjectFromStorage(GO_ARGENT_COLISEUM_FLOOR)) + case 5080: { - pGoFloor->SetUInt32Value(GAMEOBJECT_DISPLAYID,9060); - pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); - pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,8449); - } - - m_creature->CastSpell(m_creature,69016,false); - - if(m_pInstance) - m_pInstance->SetData(TYPE_LICH_KING,DONE); - - if (Creature *pAnubarak = m_creature->SummonCreature(NPC_ANUBARAK, SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 3.14f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) - pAnubarak->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - m_pInstance->SetData(TYPE_STAGE,9); - Event=false; - m_creature->ForcedDespawn(); + if (GameObject* pGoFloor = pInstance->GetSingleGameObjectFromStorage(GO_ARGENT_COLISEUM_FLOOR)) + { + pGoFloor->SetUInt32Value(GAMEOBJECT_DISPLAYID, 9060); + pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1, 8449); + } + m_creature->CastSpell(m_creature, 69016, false); - if (Creature* pPortal = GetCreatureFromGuid(m_uiPortalGuid)) + pInstance->SetData(TYPE_LICH_KING,DONE); + + pInstance->SetData(TYPE_ANUBARAK, IN_PROGRESS); + m_creature->SummonCreature(NPC_ANUBARAK, SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_ANUBARAK)) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[20].x, SpawnLoc[20].y, SpawnLoc[20].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } + pInstance->SetData(TYPE_STAGE, 9); + Event = false; + m_creature->ForcedDespawn(); pPortal->ForcedDespawn(); - - m_pInstance->SetData(TYPE_EVENT,0); - UpdateTimer = 20000; - break; + pInstance->SetData(TYPE_EVENT, 0); + UpdateTimer = 20000; + break; + } } } else UpdateTimer -= diff; - - m_pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); } void MovementInform(uint32 type, uint32 id) { - if(m_pInstance) + if(pInstance) { if(id == 2) - { Event = true; - } } + if(type != POINT_MOTION_TYPE) return; @@ -589,167 +546,140 @@ struct MANGOS_DLL_DECL npc_fizzlebang_tocAI : public ScriptedAI { npc_fizzlebang_tocAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (BSWScriptedInstance*)m_creature->GetInstanceData(); + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); Reset(); } - BSWScriptedInstance* m_pInstance; + ScriptedInstance* pInstance; uint32 UpdateTimer; - ObjectGuid m_uiPortalGuid; - ObjectGuid m_uiTriggerGuid; - - Creature* GetCreatureFromGuid(ObjectGuid m_uiGuid) - { - if (Creature* pCreature = m_creature->GetMap()->GetCreature(m_uiGuid)) - return pCreature; - - return NULL; - } + Creature* pPortal; + Creature* pTrigger; void JustDied(Unit* pKiller) { - m_pInstance->SetData(TYPE_EVENT, 1179); + DoScriptText(-1713715, m_creature, pKiller); + pInstance->SetData(TYPE_EVENT, 1180); - if (Creature* pPortal = GetCreatureFromGuid(m_uiPortalGuid)) + if (pPortal) pPortal->ForcedDespawn(); - - m_creature->ForcedDespawn(5000); } void Reset() { m_creature->SetRespawnDelay(DAY); m_creature->GetMotionMaster()->MovePoint(1, SpawnLoc[27].x, SpawnLoc[27].y, SpawnLoc[27].z); - m_uiPortalGuid.Clear(); + pPortal = NULL; } void UpdateAI(const uint32 diff) { - if(!m_pInstance) + if(!pInstance) return; - if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_FIZZLEBANG) + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_FIZZLEBANG) return; - UpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if(UpdateTimer <= diff) { - switch(m_pInstance->GetData(TYPE_EVENT)) - { + switch(pInstance->GetData(TYPE_EVENT)) + { case 1110: - m_pInstance->SetData(TYPE_EVENT, 1120); + pInstance->SetData(TYPE_EVENT, 1120); UpdateTimer = 3000; - m_pInstance->SetData(TYPE_JARAXXUS,IN_PROGRESS); + pInstance->SetData(TYPE_JARAXXUS,IN_PROGRESS); break; case 1120: DoScriptText(-1713511, m_creature); - m_pInstance->SetData(TYPE_EVENT, 1130); + pInstance->SetData(TYPE_EVENT, 1130); UpdateTimer = 12000; break; case 1130: m_creature->GetMotionMaster()->MovementExpired(); m_creature->HandleEmoteCommand(EMOTE_STATE_SPELL_CHANNEL_OMNI); - - if (Creature* pPortal = m_creature->SummonCreature(NPC_WILFRED_PORTAL, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5, TEMPSUMMON_MANUAL_DESPAWN, 5000)) + pPortal = m_creature->SummonCreature(NPC_WILFRED_PORTAL, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (pPortal) { pPortal->SetRespawnDelay(DAY); pPortal->SetDisplayId(22862); - pPortal->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.5f); - m_uiPortalGuid = pPortal->GetObjectGuid(); } - DoScriptText(-1713512, m_creature); - m_pInstance->SetData(TYPE_EVENT, 1132); + pInstance->SetData(TYPE_EVENT, 1132); UpdateTimer = 4000; break; - case 1132: + case 1132: m_creature->GetMotionMaster()->MovementExpired(); - m_pInstance->SetData(TYPE_EVENT, 1134); - UpdateTimer = 1000; + if (pPortal) + pPortal->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.5f); + pInstance->SetData(TYPE_EVENT, 1134); + UpdateTimer = 4000; break; - case 1134: - if (Creature* pPortal = GetCreatureFromGuid(m_uiPortalGuid)) - pPortal->ForcedDespawn(16000); - - if (Creature* pTrigger = m_creature->SummonCreature(NPC_TRIGGER, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5.0f, TEMPSUMMON_MANUAL_DESPAWN, 5000)) + case 1134: + if (pPortal) + pPortal->SetDisplayId(15900); + pTrigger = m_creature->SummonCreature(NPC_TRIGGER, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5.0f, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (pTrigger) { pTrigger->SetDisplayId(17612); + pTrigger->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false); pTrigger->SetRespawnDelay(DAY); - pTrigger->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); - m_uiTriggerGuid = pTrigger->GetObjectGuid(); } - m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI); UpdateTimer = 4000; - m_pInstance->SetData(TYPE_EVENT, 1135); + pInstance->SetData(TYPE_EVENT, 1135); break; - case 1135: - m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI); + case 1135: UpdateTimer = 3000; - m_pInstance->SetData(TYPE_EVENT, 1140); + pInstance->SetData(TYPE_EVENT, 1140); break; - case 1140: - m_pInstance->SetData(TYPE_STAGE,4); + case 1140: + pInstance->SetData(TYPE_STAGE, 4); m_creature->SummonCreature(NPC_JARAXXUS, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) { pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetWalk(true); - pTemp->GetMotionMaster()->MovePoint(1, SpawnLoc[28].x, SpawnLoc[28].y, SpawnLoc[28].z); + pTemp->CastSpell(pTemp, SPELL_JARAXXUS_CHAINS, false); } - m_pInstance->SetData(TYPE_EVENT, 1142); - UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 1142); + UpdateTimer = 5000; break; - case 1142: - if (Creature* pTrigger = GetCreatureFromGuid(m_uiTriggerGuid)) - pTrigger->RemoveAurasDueToSpell(SPELL_WILFRED_PORTAL); - - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) - pTemp->SetFacingToObject(m_creature); - + case 1142: + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 1144); DoScriptText(-1713513, m_creature); - m_creature->HandleEmoteCommand(EMOTE_ONESHOT_POINT); - m_pInstance->SetData(TYPE_EVENT, 1144); - UpdateTimer = 3000; break; - case 1144: - if (Creature* pTrigger = GetCreatureFromGuid(m_uiTriggerGuid)) + case 1144: + if (pTrigger) pTrigger->ForcedDespawn(); - - m_pInstance->SetData(TYPE_EVENT, 1145); - UpdateTimer = 9000; + pInstance->SetData(TYPE_EVENT, 1150); + UpdateTimer = 5000; break; - case 1145: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) + case 1150: + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) { - DoScriptText(-1713514, pTemp); - pTemp->HandleEmoteCommand(EMOTE_ONESHOT_POINT); + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); + pTemp->SetInCombatWithZone(); + m_creature->SetInCombatWith(pTemp); + pTemp->AddThreat(m_creature, 1000.0f); + pTemp->AI()->AttackStart(m_creature); } - - m_pInstance->SetData(TYPE_EVENT, 1150); - UpdateTimer = 5000; - break; - case 1150: DoScriptText(-1713515, m_creature); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) - pTemp->CastSpell(m_creature, 66532, false); - - m_pInstance->SetData(TYPE_EVENT, 1160); - UpdateTimer = 4000; + pInstance->SetData(TYPE_EVENT, 1160); + UpdateTimer = 3000; break; - case 1160: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JARAXXUS)) - pTemp->SetInCombatWithZone(); - + case 1160: + pInstance->SetData(TYPE_EVENT, 1170); UpdateTimer = 1000; break; - } + } } else UpdateTimer -= diff; - m_pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); } }; @@ -762,658 +692,772 @@ struct MANGOS_DLL_DECL npc_tirion_tocAI : public ScriptedAI { npc_tirion_tocAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); Reset(); } - ScriptedInstance* m_pInstance; + ScriptedInstance* pInstance; uint32 UpdateTimer; + uint32 BeastHeroTimer; uint32 crusader[12]; uint8 crusaderscount; + uint8 beastcount; + bool IsHero; void Reset() { + BeastHeroTimer = 180000; + beastcount = 0; crusaderscount = 0; memset(&crusader, 0, sizeof(crusader)); + + switch(m_creature->GetMap()->GetDifficulty()) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + case RAID_DIFFICULTY_25MAN_NORMAL: + IsHero = false; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + case RAID_DIFFICULTY_25MAN_HEROIC: + IsHero = true; + break; + default: + IsHero = false; + break; + } } void AttackStart(Unit *who) { + //ignore all attackstart commands return; } void UpdateAI(const uint32 diff) { - if (!m_pInstance) - return; - if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_TIRION) + if (!pInstance || pInstance->GetData(TYPE_EVENT_NPC) != NPC_TIRION) return; - UpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + + if (IsHero && pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS) + { + if (BeastHeroTimer <= diff) + { + switch(beastcount) + { + case 1: + DoScriptText(-1713503, m_creature); + pInstance->SetData(TYPE_EVENT, FIGHT2_SUMMON); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + case 2: + DoScriptText(-1713505, m_creature); + pInstance->SetData(TYPE_EVENT, FIGHT3_SUMMON); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + case 3: + break; + default: + break; + } + BeastHeroTimer = 180000; + } + else + BeastHeroTimer -= diff; + } if (UpdateTimer <= diff) { - switch (m_pInstance->GetData(TYPE_EVENT)) + switch (pInstance->GetData(TYPE_EVENT)) { - case 110: - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(-1713500, m_creature); - UpdateTimer = 22000; - m_pInstance->SetData(TYPE_EVENT,130); - break; - case 140: - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(-1713501, m_creature); - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,150); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 150: - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + case FIGHT1_INTRO_1: { - m_creature->SummonCreature(NPC_GORMOK, SpawnLoc[26].x, SpawnLoc[26].y, SpawnLoc[26].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_GORMOK)) - { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); - pTemp->SetInCombatWithZone(); - } + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713500, m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT, FIGHT1_INTRO_2); + //pInstance->DoUseDoorOrButton(GO_EAST_PORTCULLIS); + break; } - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,160); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - m_pInstance->SetData(TYPE_STAGE,1); - m_pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); - break; - case 200: - DoScriptText(-1713503, m_creature); - UpdateTimer = 4000; - m_pInstance->SetData(TYPE_EVENT,205); - break; - case 205: - UpdateTimer = 8000; - m_pInstance->SetData(TYPE_EVENT,210); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 210: - if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + case FIGHT1_INTRO_6: { - m_creature->SummonCreature(NPC_DREADSCALE, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - m_creature->SummonCreature(NPC_ACIDMAW, SpawnLoc[4].x, SpawnLoc[4].y, SpawnLoc[4].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_DREADSCALE)) - { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); - pTemp->SetInCombatWithZone(); - } - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ACIDMAW)) + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713501, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, FIGHT1_SUMMON); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + } + case FIGHT1_SUMMON: + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + if (pInstance->GetData(TYPE_BEASTS) != DONE) { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); - pTemp->SetInCombatWithZone(); + m_creature->SummonCreature(NPC_GORMOK, SpawnLoc[26].x, SpawnLoc[26].y, SpawnLoc[26].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_GORMOK)) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } } + beastcount = 1; + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, FIGHT1_END); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + pInstance->SetData(TYPE_STAGE, 1); + pInstance->SetData(TYPE_BEASTS, IN_PROGRESS); + BeastHeroTimer = 180000; + break; } - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,220); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 300: - DoScriptText(-1713505, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,305); - break; - case 305: - UpdateTimer = 8000; - m_pInstance->SetData(TYPE_EVENT,310); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 310: - if (m_pInstance->GetData(TYPE_BEASTS) != DONE) + case FIGHT2_INTRO_1: + { + DoScriptText(-1713503, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, FIGHT2_INTRO_2); + break; + } + case FIGHT2_INTRO_2: + { + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT, FIGHT2_SUMMON); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + } + case FIGHT2_SUMMON: { - m_creature->SummonCreature(NPC_ICEHOWL, SpawnLoc[26].x, SpawnLoc[26].y, SpawnLoc[26].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ICEHOWL)) + if (pInstance->GetData(TYPE_BEASTS) != DONE) { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); - pTemp->SetInCombatWithZone(); + m_creature->SummonCreature(NPC_DREADSCALE, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_creature->SummonCreature(NPC_ACIDMAW, SpawnLoc[4].x, SpawnLoc[4].y, SpawnLoc[4].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_DREADSCALE)) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_ACIDMAW)) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } + beastcount = 2; + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, FIGHT2_END); + pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); + BeastHeroTimer = 180000; } + break; } - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,320); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 400: - DoScriptText(-1713509, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,0); - break; - case 666: - DoScriptText(-1713709, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,0); - m_pInstance->SetData(TYPE_NORTHREND_BEASTS,NOT_STARTED); - break; - case 1010: - DoScriptText(-1713510, m_creature); - UpdateTimer = 5000; - m_creature->SummonCreature(NPC_FIZZLEBANG, SpawnLoc[21].x, SpawnLoc[21].y, SpawnLoc[21].z, 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - m_pInstance->SetData(TYPE_EVENT,1110); - break; - case 1179: - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT, 1180); - break; - case 1180: - DoScriptText(-1713516, m_creature); - UpdateTimer = 3000; - m_pInstance->SetData(TYPE_EVENT,0); - break; - - case 1999: - UpdateTimer = 6000; - m_pInstance->SetData(TYPE_EVENT,2000); - break; - case 2000: - DoScriptText(-1713526, m_creature); - UpdateTimer = 15000; - m_pInstance->SetData(TYPE_EVENT,2010); - break; - case 2030: - DoScriptText(-1713529, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,0); - break; - case 3000: - DoScriptText(-1713530, m_creature); - UpdateTimer = 8000; - m_pInstance->SetData(TYPE_EVENT,3050); - break; - case 3001: - DoScriptText(-1713530, m_creature); - UpdateTimer = 8000; - m_pInstance->SetData(TYPE_EVENT,3051); - break; - case 3060: - DoScriptText(-1713532, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,3070); - break; - case 3061: - DoScriptText(-1713532, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,3071); - break; - //Summoning crusaders - case 3091: - m_pInstance->SetData(TYPE_STAGE,6); - if (m_pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_NORMAL || m_pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + case FIGHT3_INTRO_1: { - crusaderscount = 12; - switch (urand(0,3)) - { // Healers, 3 in 25-mode - case 0: - crusader[0] = NPC_CRUSADER_1_1; - crusader[1] = NPC_CRUSADER_1_12; - crusader[2] = NPC_CRUSADER_1_13; - break; - case 1: - crusader[0] = NPC_CRUSADER_1_1; - crusader[1] = NPC_CRUSADER_1_2; - crusader[2] = NPC_CRUSADER_1_13; - break; - case 2: - crusader[0] = NPC_CRUSADER_1_1; - crusader[1] = NPC_CRUSADER_1_2; - crusader[2] = NPC_CRUSADER_1_12; - break; - case 3: - crusader[0] = NPC_CRUSADER_1_2; - crusader[1] = NPC_CRUSADER_1_12; - crusader[2] = NPC_CRUSADER_1_13; - break; - } - switch (urand(0,5)) - { // Random melee DD, 2 in 25-mode - case 0: - crusader[3] = NPC_CRUSADER_1_3; - crusader[4] = NPC_CRUSADER_1_4; - break; - case 1: - crusader[3] = NPC_CRUSADER_1_3; - crusader[4] = NPC_CRUSADER_1_5; - break; - case 2: - crusader[3] = NPC_CRUSADER_1_3; - crusader[4] = NPC_CRUSADER_1_6; - break; - case 3: - crusader[3] = NPC_CRUSADER_1_4; - crusader[4] = NPC_CRUSADER_1_5; - break; - case 4: - crusader[3] = NPC_CRUSADER_1_4; - crusader[4] = NPC_CRUSADER_1_6; - break; - case 5: - crusader[3] = NPC_CRUSADER_1_5; - crusader[4] = NPC_CRUSADER_1_6; - break; - } - switch (urand(0,3)) - { // Random magic DD, 3 in 25-mode - case 0: - crusader[5] = NPC_CRUSADER_1_7; - crusader[6] = NPC_CRUSADER_1_8; - crusader[7] = NPC_CRUSADER_1_11; - break; - case 1: - crusader[5] = NPC_CRUSADER_1_7; - crusader[6] = NPC_CRUSADER_1_8; - crusader[7] = NPC_CRUSADER_1_14; - break; - case 2: - crusader[5] = NPC_CRUSADER_1_8; - crusader[6] = NPC_CRUSADER_1_11; - crusader[7] = NPC_CRUSADER_1_14; - break; - case 3: - crusader[5] = NPC_CRUSADER_1_7; - crusader[6] = NPC_CRUSADER_1_11; - crusader[7] = NPC_CRUSADER_1_14; - break; - } - crusader[8] = NPC_CRUSADER_1_9; //Hunter+warlock - crusader[9] = NPC_CRUSADER_1_10; - crusader[10] = NPC_CRUSADER_0_1; - crusader[11] = NPC_CRUSADER_0_2; + DoScriptText(-1713505, m_creature); + UpdateTimer = 15000; + pInstance->SetData(TYPE_EVENT, FIGHT3_INTRO_2); + break; } - else + case FIGHT3_INTRO_2: { - crusaderscount = 6; - switch (urand(0,5)) - { // Healers, 2 in 10-mode - case 0: - crusader[0] = NPC_CRUSADER_1_1; - crusader[1] = NPC_CRUSADER_1_12; - break; - case 1: - crusader[0] = NPC_CRUSADER_1_1; - crusader[1] = NPC_CRUSADER_1_2; - break; - case 2: - crusader[0] = NPC_CRUSADER_1_2; - crusader[1] = NPC_CRUSADER_1_12; - break; - case 3: - crusader[0] = NPC_CRUSADER_1_1; - crusader[1] = NPC_CRUSADER_1_13; - break; - case 4: - crusader[0] = NPC_CRUSADER_1_2; - crusader[1] = NPC_CRUSADER_1_13; - break; - case 5: - crusader[0] = NPC_CRUSADER_1_12; - crusader[1] = NPC_CRUSADER_1_13; - break; - } - switch (urand(0,5)) - { // Random melee DD, 2 in 10-mode - case 0: - crusader[3] = NPC_CRUSADER_1_3; - crusader[2] = NPC_CRUSADER_1_4; - break; - case 1: - crusader[3] = NPC_CRUSADER_1_3; - crusader[2] = NPC_CRUSADER_1_5; - break; - case 2: - crusader[3] = NPC_CRUSADER_1_3; - crusader[2] = NPC_CRUSADER_1_6; - break; - case 3: - crusader[3] = NPC_CRUSADER_1_4; - crusader[2] = NPC_CRUSADER_1_5; - break; - case 4: - crusader[3] = NPC_CRUSADER_1_4; - crusader[2] = NPC_CRUSADER_1_6; - break; - case 5: - crusader[3] = NPC_CRUSADER_1_5; - crusader[2] = NPC_CRUSADER_1_6; - break; - } - switch (urand(0,5)) - { // Random magic DD, 2 in 10-mode - case 0: - crusader[4] = NPC_CRUSADER_1_7; - crusader[5] = NPC_CRUSADER_1_8; - break; - case 1: - crusader[5] = NPC_CRUSADER_1_7; - crusader[4] = NPC_CRUSADER_1_14; - break; - case 2: - crusader[5] = NPC_CRUSADER_1_7; - crusader[4] = NPC_CRUSADER_1_11; - break; - case 3: - crusader[5] = NPC_CRUSADER_1_8; - crusader[4] = NPC_CRUSADER_1_11; - break; - case 4: - crusader[5] = NPC_CRUSADER_1_8; - crusader[4] = NPC_CRUSADER_1_14; - break; - case 5: - crusader[5] = NPC_CRUSADER_1_11; - crusader[4] = NPC_CRUSADER_1_14; - break; - } + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT, FIGHT3_SUMMON); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; } - for(uint8 i = 0; i < crusaderscount; ++i) + case FIGHT3_SUMMON: { - m_creature->SummonCreature(crusader[i], SpawnLoc[i+2].x, SpawnLoc[i+2].y, SpawnLoc[i+2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(crusader[i])) + if (pInstance->GetData(TYPE_BEASTS) != DONE) { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); + m_creature->SummonCreature(NPC_ICEHOWL, SpawnLoc[26].x, SpawnLoc[26].y, SpawnLoc[26].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_ICEHOWL)) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } } + beastcount = 3; + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, FIGHT3_END); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; } - m_pInstance->SetData(TYPE_CRUSADERS_COUNT,crusaderscount); - UpdateTimer = 3000; - m_pInstance->SetData(TYPE_EVENT,0); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - m_pInstance->SetData(TYPE_CRUSADERS,IN_PROGRESS); - break; - //summoning crusaders - case 3090: - m_pInstance->SetData(TYPE_STAGE,6); - if (m_pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_NORMAL || m_pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + case 400: + { + DoScriptText(-1713509, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 0); + //pInstance->DoUseDoorOrButton(GO_EAST_PORTCULLIS); + break; + } + case 666: { - crusaderscount = 12; - switch (urand(0,3)) - { // Healers, 3 in 25-mode - case 0: - crusader[0] = NPC_CRUSADER_2_1; - crusader[1] = NPC_CRUSADER_2_12; - crusader[2] = NPC_CRUSADER_2_13; - break; - case 1: - crusader[0] = NPC_CRUSADER_2_1; - crusader[1] = NPC_CRUSADER_2_2; - crusader[2] = NPC_CRUSADER_2_13; - break; - case 2: - crusader[0] = NPC_CRUSADER_2_1; - crusader[1] = NPC_CRUSADER_2_2; - crusader[2] = NPC_CRUSADER_2_12; - break; - case 3: - crusader[0] = NPC_CRUSADER_2_2; - crusader[1] = NPC_CRUSADER_2_12; - crusader[2] = NPC_CRUSADER_2_13; - break; + DoScriptText(-1713709, m_creature); + UpdateTimer = 5000; + BeastHeroTimer = 180000; + beastcount = 0; + pInstance->SetData(TYPE_EVENT, 0); + pInstance->SetData(TYPE_GORMOK, NOT_STARTED); + pInstance->SetData(TYPE_SNAKES, NOT_STARTED); + pInstance->SetData(TYPE_ICEHOWL, NOT_STARTED); + //pInstance->DoUseDoorOrButton(GO_EAST_PORTCULLIS); + break; + } + case 1010: + { + DoScriptText(-1713510, m_creature); + UpdateTimer = 5000; + m_creature->SummonCreature(NPC_FIZZLEBANG, SpawnLoc[21].x, SpawnLoc[21].y, SpawnLoc[21].z, 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pInstance->SetData(TYPE_EVENT, 1110); + break; + } + case 1180: + { + DoScriptText(-1713516, m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 0); + break; + } + case 2000: + { + DoScriptText(-1713526, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 2010); + break; + } + case 2030: + { + DoScriptText(-1713529, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 0); + break; + } + case 3000: + { + DoScriptText(-1713530, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3050); + break; + } + case 3001: + { + DoScriptText(-1713530, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3051); + break; + } + case 3060: + { + DoScriptText(-1713532, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3070); + break; + } + case 3061: + { + DoScriptText(-1713532, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3071); + break; + } + //Summoning crusaders + case 3091: + { + pInstance->SetData(TYPE_STAGE, 6); + if (pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_NORMAL || pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + { + crusaderscount = 12; + switch (urand(0,3)) + { + // Healers, 3 in 25-mode + case 0: + crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_12; + crusader[2] = NPC_CRUSADER_1_13; + break; + case 1: + crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_2; + crusader[2] = NPC_CRUSADER_1_13; + break; + case 2: + crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_2; + crusader[2] = NPC_CRUSADER_1_12; + break; + case 3: + crusader[0] = NPC_CRUSADER_1_2; + crusader[1] = NPC_CRUSADER_1_12; + crusader[2] = NPC_CRUSADER_1_13; + break; + } + + switch (urand(0,5)) + { + // Random melee DD, 2 in 25-mode + case 0: + crusader[3] = NPC_CRUSADER_1_3; + crusader[4] = NPC_CRUSADER_1_4; + break; + case 1: + crusader[3] = NPC_CRUSADER_1_3; + crusader[4] = NPC_CRUSADER_1_5; + break; + case 2: + crusader[3] = NPC_CRUSADER_1_3; + crusader[4] = NPC_CRUSADER_1_6; + break; + case 3: + crusader[3] = NPC_CRUSADER_1_4; + crusader[4] = NPC_CRUSADER_1_5; + break; + case 4: + crusader[3] = NPC_CRUSADER_1_4; + crusader[4] = NPC_CRUSADER_1_6; + break; + case 5: + crusader[3] = NPC_CRUSADER_1_5; + crusader[4] = NPC_CRUSADER_1_6; + break; + } + switch (urand(0,3)) + { + // Random magic DD, 3 in 25-mode + case 0: + crusader[5] = NPC_CRUSADER_1_7; + crusader[6] = NPC_CRUSADER_1_8; + crusader[7] = NPC_CRUSADER_1_11; + break; + case 1: + crusader[5] = NPC_CRUSADER_1_7; + crusader[6] = NPC_CRUSADER_1_8; + crusader[7] = NPC_CRUSADER_1_14; + break; + case 2: + crusader[5] = NPC_CRUSADER_1_8; + crusader[6] = NPC_CRUSADER_1_11; + crusader[7] = NPC_CRUSADER_1_14; + break; + case 3: + crusader[5] = NPC_CRUSADER_1_7; + crusader[6] = NPC_CRUSADER_1_11; + crusader[7] = NPC_CRUSADER_1_14; + break; + } + //Hunter+warlock + crusader[8] = NPC_CRUSADER_1_9; + crusader[9] = NPC_CRUSADER_1_10; + crusader[10] = NPC_CRUSADER_0_1; + crusader[11] = NPC_CRUSADER_0_2; } - switch (urand(0,5)) - { // Random melee DD, 2 in 25-mode - case 0: - crusader[3] = NPC_CRUSADER_2_3; - crusader[4] = NPC_CRUSADER_2_4; - break; - case 1: - crusader[3] = NPC_CRUSADER_2_3; - crusader[4] = NPC_CRUSADER_2_5; - break; - case 2: - crusader[3] = NPC_CRUSADER_2_3; - crusader[4] = NPC_CRUSADER_2_6; - break; - case 3: - crusader[3] = NPC_CRUSADER_2_4; - crusader[4] = NPC_CRUSADER_2_5; - break; - case 4: crusader[3] = NPC_CRUSADER_2_4; - crusader[4] = NPC_CRUSADER_2_6; - break; - case 5: - crusader[3] = NPC_CRUSADER_2_5; - crusader[4] = NPC_CRUSADER_2_6; - break; + else + { + crusaderscount = 6; + switch (urand(0,5)) + { + // Healers, 2 in 10-mode + case 0: + crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_12; + break; + case 1: + crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_2; + break; + case 2: + crusader[0] = NPC_CRUSADER_1_2; + crusader[1] = NPC_CRUSADER_1_12; + break; + case 3: + crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_13; + break; + case 4: + crusader[0] = NPC_CRUSADER_1_2; + crusader[1] = NPC_CRUSADER_1_13; + break; + case 5: + crusader[0] = NPC_CRUSADER_1_12; + crusader[1] = NPC_CRUSADER_1_13; + break; + } + switch (urand(0,5)) + { + // Random melee DD, 2 in 10-mode + case 0: + crusader[3] = NPC_CRUSADER_1_3; + crusader[2] = NPC_CRUSADER_1_4; + break; + case 1: + crusader[3] = NPC_CRUSADER_1_3; + crusader[2] = NPC_CRUSADER_1_5; + break; + case 2: + crusader[3] = NPC_CRUSADER_1_3; + crusader[2] = NPC_CRUSADER_1_6; + break; + case 3: + crusader[3] = NPC_CRUSADER_1_4; + crusader[2] = NPC_CRUSADER_1_5; + break; + case 4: + crusader[3] = NPC_CRUSADER_1_4; + crusader[2] = NPC_CRUSADER_1_6; + break; + case 5: + crusader[3] = NPC_CRUSADER_1_5; + crusader[2] = NPC_CRUSADER_1_6; + break; + } + switch (urand(0,5)) + { + // Random magic DD, 2 in 10-mode + case 0: + crusader[4] = NPC_CRUSADER_1_7; + crusader[5] = NPC_CRUSADER_1_8; + break; + case 1: + crusader[5] = NPC_CRUSADER_1_7; + crusader[4] = NPC_CRUSADER_1_14; + break; + case 2: + crusader[5] = NPC_CRUSADER_1_7; + crusader[4] = NPC_CRUSADER_1_11; + break; + case 3: + crusader[5] = NPC_CRUSADER_1_8; + crusader[4] = NPC_CRUSADER_1_11; + break; + case 4: + crusader[5] = NPC_CRUSADER_1_8; + crusader[4] = NPC_CRUSADER_1_14; + break; + case 5: + crusader[5] = NPC_CRUSADER_1_11; + crusader[4] = NPC_CRUSADER_1_14; + break; + } } - - switch (urand(0,3)) - { // Random magic DD, 3 in 25-mode - case 0: - crusader[5] = NPC_CRUSADER_2_7; - crusader[6] = NPC_CRUSADER_2_8; - crusader[7] = NPC_CRUSADER_2_11; - break; - case 1: - crusader[5] = NPC_CRUSADER_2_7; - crusader[6] = NPC_CRUSADER_2_8; - crusader[7] = NPC_CRUSADER_2_14; - break; - case 2: - crusader[5] = NPC_CRUSADER_2_8; - crusader[6] = NPC_CRUSADER_2_11; - crusader[7] = NPC_CRUSADER_2_14; - break; - case 3: - crusader[5] = NPC_CRUSADER_2_7; - crusader[6] = NPC_CRUSADER_2_11; - crusader[7] = NPC_CRUSADER_2_14; - break; + for(uint8 i = 0; i < crusaderscount; ++i) + { + m_creature->SummonCreature(crusader[i], SpawnLoc[i+2].x, SpawnLoc[i+2].y, SpawnLoc[i+2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(crusader[i])) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + } } - crusader[8] = NPC_CRUSADER_2_9; //Hunter+warlock - crusader[9] = NPC_CRUSADER_2_10; - crusader[10] = NPC_CRUSADER_0_1; - crusader[11] = NPC_CRUSADER_0_2; + pInstance->SetData(TYPE_CRUSADERS_COUNT,crusaderscount); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,0); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + pInstance->SetData(TYPE_CRUSADERS,IN_PROGRESS); + break; } - else + //summoning crusaders + case 3090: { - crusaderscount = 6; - switch (urand(0,5)) - { // Healers, 2 in 10-mode - case 0: - crusader[0] = NPC_CRUSADER_2_1; - crusader[1] = NPC_CRUSADER_2_12; - break; - case 1: - crusader[0] = NPC_CRUSADER_2_1; - crusader[1] = NPC_CRUSADER_2_2; - break; - case 2: - crusader[0] = NPC_CRUSADER_2_2; - crusader[1] = NPC_CRUSADER_2_12; - break; - case 3: - crusader[0] = NPC_CRUSADER_2_1; - crusader[1] = NPC_CRUSADER_2_13; - break; - case 4: - crusader[0] = NPC_CRUSADER_2_2; - crusader[1] = NPC_CRUSADER_2_13; - break; - case 5: - crusader[0] = NPC_CRUSADER_2_12; - crusader[1] = NPC_CRUSADER_2_13; - break; + pInstance->SetData(TYPE_STAGE, 6); + if (pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_NORMAL || pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + { crusaderscount = 12; + switch (urand(0,3)) + { + // Healers, 3 in 25-mode + case 0: + crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_12; + crusader[2] = NPC_CRUSADER_2_13; + break; + case 1: + crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_2; + crusader[2] = NPC_CRUSADER_2_13; + break; + case 2: + crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_2; + crusader[2] = NPC_CRUSADER_2_12; + break; + case 3: + crusader[0] = NPC_CRUSADER_2_2; + crusader[1] = NPC_CRUSADER_2_12; + crusader[2] = NPC_CRUSADER_2_13; + break; + } + switch (urand(0,5)) + { + // Random melee DD, 2 in 25-mode + case 0: + crusader[3] = NPC_CRUSADER_2_3; + crusader[4] = NPC_CRUSADER_2_4; + break; + case 1: + crusader[3] = NPC_CRUSADER_2_3; + crusader[4] = NPC_CRUSADER_2_5; + break; + case 2: + crusader[3] = NPC_CRUSADER_2_3; + crusader[4] = NPC_CRUSADER_2_6; + break; + case 3: + crusader[3] = NPC_CRUSADER_2_4; + crusader[4] = NPC_CRUSADER_2_5; + break; + case 4: + crusader[3] = NPC_CRUSADER_2_4; + crusader[4] = NPC_CRUSADER_2_6; + break; + case 5: + crusader[3] = NPC_CRUSADER_2_5; + crusader[4] = NPC_CRUSADER_2_6; + break; + } + switch (urand(0,3)) + { + // Random magic DD, 3 in 25-mode + case 0: + crusader[5] = NPC_CRUSADER_2_7; + crusader[6] = NPC_CRUSADER_2_8; + crusader[7] = NPC_CRUSADER_2_11; + break; + case 1: + crusader[5] = NPC_CRUSADER_2_7; + crusader[6] = NPC_CRUSADER_2_8; + crusader[7] = NPC_CRUSADER_2_14; + break; + case 2: + crusader[5] = NPC_CRUSADER_2_8; + crusader[6] = NPC_CRUSADER_2_11; + crusader[7] = NPC_CRUSADER_2_14; + break; + case 3: + crusader[5] = NPC_CRUSADER_2_7; + crusader[6] = NPC_CRUSADER_2_11; + crusader[7] = NPC_CRUSADER_2_14; + break; + } + //Hunter+warlock + crusader[8] = NPC_CRUSADER_2_9; + crusader[9] = NPC_CRUSADER_2_10; + crusader[10] = NPC_CRUSADER_0_1; + crusader[11] = NPC_CRUSADER_0_2; } - switch (urand(0,5)) - { // Random melee DD, 2 in 10-mode - case 0: - crusader[3] = NPC_CRUSADER_2_3; - crusader[2] = NPC_CRUSADER_2_4; - break; - case 1: - crusader[3] = NPC_CRUSADER_2_3; - crusader[2] = NPC_CRUSADER_2_5; - break; - case 2: - crusader[3] = NPC_CRUSADER_2_3; - crusader[2] = NPC_CRUSADER_2_6; - break; - case 3: - crusader[3] = NPC_CRUSADER_2_4; - crusader[2] = NPC_CRUSADER_2_5; - break; - case 4: - crusader[3] = NPC_CRUSADER_2_4; - crusader[2] = NPC_CRUSADER_2_6; - break; - case 5: - crusader[3] = NPC_CRUSADER_2_5; - crusader[2] = NPC_CRUSADER_2_6; - break; + else + { + crusaderscount = 6; + switch (urand(0,5)) + { // Healers, 2 in 10-mode + case 0: + crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_12; + break; + case 1: + crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_2; + break; + case 2: + crusader[0] = NPC_CRUSADER_2_2; + crusader[1] = NPC_CRUSADER_2_12; + break; + case 3: + crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_13; + break; + case 4: + crusader[0] = NPC_CRUSADER_2_2; + crusader[1] = NPC_CRUSADER_2_13; + break; + case 5: + crusader[0] = NPC_CRUSADER_2_12; + crusader[1] = NPC_CRUSADER_2_13; + break; + } + switch (urand(0,5)) + { + // Random melee DD, 2 in 10-mode + case 0: + crusader[3] = NPC_CRUSADER_2_3; + crusader[2] = NPC_CRUSADER_2_4; + break; + case 1: + crusader[3] = NPC_CRUSADER_2_3; + crusader[2] = NPC_CRUSADER_2_5; + break; + case 2: + crusader[3] = NPC_CRUSADER_2_3; + crusader[2] = NPC_CRUSADER_2_6; + break; + case 3: + crusader[3] = NPC_CRUSADER_2_4; + crusader[2] = NPC_CRUSADER_2_5; + break; + case 4: + crusader[3] = NPC_CRUSADER_2_4; + crusader[2] = NPC_CRUSADER_2_6; + break; + case 5: + crusader[3] = NPC_CRUSADER_2_5; + crusader[2] = NPC_CRUSADER_2_6; + break; + } + switch (urand(0,5)) + { + // Random magic DD, 2 in 10-mode + case 0: + crusader[4] = NPC_CRUSADER_2_7; + crusader[5] = NPC_CRUSADER_2_8; + break; + case 1: + crusader[5] = NPC_CRUSADER_2_7; + crusader[4] = NPC_CRUSADER_2_14; + break; + case 2: + crusader[5] = NPC_CRUSADER_2_7; + crusader[4] = NPC_CRUSADER_2_11; + break; + case 3: + crusader[5] = NPC_CRUSADER_2_8; + crusader[4] = NPC_CRUSADER_2_11; + break; + case 4: + crusader[5] = NPC_CRUSADER_2_8; + crusader[4] = NPC_CRUSADER_2_14; + break; + case 5: + crusader[5] = NPC_CRUSADER_2_11; + crusader[4] = NPC_CRUSADER_2_14; + break; + } } - switch (urand(0,5)) - { // Random magic DD, 2 in 10-mode - case 0: - crusader[4] = NPC_CRUSADER_2_7; - crusader[5] = NPC_CRUSADER_2_8; - break; - case 1: - crusader[5] = NPC_CRUSADER_2_7; - crusader[4] = NPC_CRUSADER_2_14; - break; - case 2: - crusader[5] = NPC_CRUSADER_2_7; - crusader[4] = NPC_CRUSADER_2_11; - break; - case 3: - crusader[5] = NPC_CRUSADER_2_8; - crusader[4] = NPC_CRUSADER_2_11; - break; - case 4: - crusader[5] = NPC_CRUSADER_2_8; - crusader[4] = NPC_CRUSADER_2_14; - break; - case 5: - crusader[5] = NPC_CRUSADER_2_11; - crusader[4] = NPC_CRUSADER_2_14; - break; + for(uint8 i = 0; i < crusaderscount; ++i) + { + m_creature->SummonCreature(crusader[i], SpawnLoc[i+2].x, SpawnLoc[i+2].y, SpawnLoc[i+2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(crusader[i])) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + } } + pInstance->SetData(TYPE_CRUSADERS_COUNT,crusaderscount); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,0); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + pInstance->SetData(TYPE_CRUSADERS, IN_PROGRESS); + break; + } + //Crusaders battle end + case 3100: + { + DoScriptText(-1713535, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 0); + break; + } + case 4000: + { + DoScriptText(-1713536, m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 4010); + break; } - for(uint8 i = 0; i < crusaderscount; ++i) + case 4010: { - m_creature->SummonCreature(crusader[i], SpawnLoc[i+2].x, SpawnLoc[i+2].y, SpawnLoc[i+2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(crusader[i])) + DoScriptText(-1713537, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, 4015); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + } + case 4015: + { + pInstance->SetData(TYPE_STAGE, 7); + pInstance->SetData(TYPE_VALKIRIES, IN_PROGRESS); + m_creature->SummonCreature(NPC_LIGHTBANE, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_LIGHTBANE)) { pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); } + m_creature->SummonCreature(NPC_DARKBANE, SpawnLoc[4].x, SpawnLoc[4].y, SpawnLoc[4].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pInstance->GetSingleCreatureFromStorage(NPC_DARKBANE)) + { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->SetWalk(true); + pTemp->SetInCombatWithZone(); + } + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT, 4016); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; } - m_pInstance->SetData(TYPE_CRUSADERS_COUNT,crusaderscount); - UpdateTimer = 3000; - m_pInstance->SetData(TYPE_EVENT,0); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - m_pInstance->SetData(TYPE_CRUSADERS, IN_PROGRESS); - break; - //Crusaders battle end - case 3100: - DoScriptText(-1713535, m_creature); - UpdateTimer = 5000; - m_creature->CastSpell(m_creature, 68184, true); - m_pInstance->SetData(TYPE_EVENT, 0); - break; - case 4000: - if (GameObject* pGO10N = m_pInstance->GetSingleGameObjectFromStorage(GO_CRUSADERS_CACHE_10)) - pGO10N->Delete(); - - if (GameObject* pGO10H = m_pInstance->GetSingleGameObjectFromStorage(GO_CRUSADERS_CACHE_25)) - pGO10H->Delete(); - - if (GameObject* pGO25N = m_pInstance->GetSingleGameObjectFromStorage(GO_CRUSADERS_CACHE_10_H)) - pGO25N->Delete(); - - if (GameObject* pGO25H = m_pInstance->GetSingleGameObjectFromStorage(GO_CRUSADERS_CACHE_25_H)) - pGO25H->Delete(); - - DoScriptText(-1713536, m_creature); - UpdateTimer = 3000; - m_pInstance->SetData(TYPE_EVENT,4010); - break; - case 4010: - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,4015); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 4015: - m_pInstance->SetData(TYPE_STAGE,7); - m_pInstance->SetData(TYPE_VALKIRIES,IN_PROGRESS); - m_creature->SummonCreature(NPC_LIGHTBANE, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_LIGHTBANE)) + case 4040: { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); - pTemp->SetInCombatWithZone(); + UpdateTimer = 60000; + pInstance->SetData(TYPE_EVENT, 5000); + break; } - m_creature->SummonCreature(NPC_DARKBANE, SpawnLoc[4].x, SpawnLoc[4].y, SpawnLoc[4].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_DARKBANE)) + case 5000: { - pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); - pTemp->SetWalk(true); - pTemp->SetInCombatWithZone(); + DoScriptText(-1713549, m_creature); + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT, 5005); + break; + } + case 5005: + { + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT, 5010); + pInstance->SetData(TYPE_STAGE, 8); + m_creature->SummonCreature(NPC_LICH_KING_1, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, 5, TEMPSUMMON_MANUAL_DESPAWN, 0); + break; + } + case 5020: + { + DoScriptText(-1713551, m_creature); + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT, 5030); + break; + } + case 6000: + { + m_creature->NearTeleportTo(SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 4.0f); + UpdateTimer = 20000; + pInstance->SetData(TYPE_EVENT, 6005); + break; + } + case 6005: + { + DoScriptText(-1713565, m_creature); + UpdateTimer = 20000; + pInstance->SetData(TYPE_EVENT, 6010); + break; + } + case 6010: + { + // only on heroic difficulty + if (pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_10MAN_HEROIC || pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + DoScriptText(-1713566, m_creature); + UpdateTimer = 60000; + pInstance->SetData(TYPE_EVENT, 6020); + break; + } + case 6020: + { + pInstance->SetData(TYPE_STAGE, 10); + m_creature->ForcedDespawn(); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 6030); + break; } - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,4016); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 4040: - UpdateTimer = 60000; - m_pInstance->SetData(TYPE_EVENT,5000); - break; - case 5000: - DoScriptText(-1713549, m_creature); - UpdateTimer = 8000; - m_pInstance->SetData(TYPE_EVENT,5005); - break; - case 5005: - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,5010); - m_pInstance->SetData(TYPE_STAGE,8); - m_creature->SummonCreature(NPC_LICH_KING_1, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, 5, TEMPSUMMON_MANUAL_DESPAWN, 0); - break; - case 5020: - DoScriptText(-1713551, m_creature); - UpdateTimer = 8000; - m_pInstance->SetData(TYPE_EVENT,5030); - break; - case 6000: - m_creature->NearTeleportTo(SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 3.15f); - UpdateTimer = 20000; - m_pInstance->SetData(TYPE_EVENT,6005); - break; - case 6005: - DoScriptText(-1713565, m_creature); - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); - m_creature->SummonGameobject(195682, 783.57f, 124.45f, 142.21f, 0, 0); - UpdateTimer = 20000; - m_pInstance->SetData(TYPE_EVENT,6010); - break; - case 6010: - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - if (m_pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_10MAN_HEROIC || m_pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) - DoScriptText(-1713566, m_creature); - - UpdateTimer = 60000; - m_pInstance->SetData(TYPE_EVENT,6020); - break; - case 6020: - m_pInstance->SetData(TYPE_STAGE,10); - m_creature->ForcedDespawn(); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,6030); - break; } } else UpdateTimer -= diff; - m_pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); } }; @@ -1426,11 +1470,11 @@ struct MANGOS_DLL_DECL npc_garrosh_tocAI : public ScriptedAI { npc_garrosh_tocAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); Reset(); } - ScriptedInstance* m_pInstance; + ScriptedInstance* pInstance; uint32 UpdateTimer; void Reset() @@ -1445,56 +1489,60 @@ struct MANGOS_DLL_DECL npc_garrosh_tocAI : public ScriptedAI void UpdateAI(const uint32 diff) { - if (!m_pInstance) + if (!pInstance) return; - - if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_GARROSH) + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_GARROSH) return; - UpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); if (UpdateTimer <= diff) { - switch (m_pInstance->GetData(TYPE_EVENT)) - { - case 120: - m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); - DoScriptText(-1713702, m_creature); - m_pInstance->SetData(TYPE_EVENT,121); - UpdateTimer = 5000; - break; - case 2010: - DoScriptText(-1713527, m_creature); - UpdateTimer = 10000; - m_pInstance->SetData(TYPE_EVENT,2020); - break; - case 3050: - DoScriptText(-1713531, m_creature); - UpdateTimer = 15000; - m_pInstance->SetData(TYPE_EVENT,3060); - break; - case 3070: - DoScriptText(-1713533, m_creature); - UpdateTimer = 6000; - m_pInstance->SetData(TYPE_EVENT,3080); - break; - case 3081: - DoScriptText(-1713734, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,3091); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 4030: - DoScriptText(-1713748, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,4040); + switch (pInstance->GetData(TYPE_EVENT)) + { + case FIGHT1_INTRO_2: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713702, m_creature); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT, FIGHT1_INTRO_3); + break; + case FIGHT1_INTRO_3: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 130); + break; + case 2010: + DoScriptText(-1713527, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 2020); + break; + case 3050: + DoScriptText(-1713531, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3060); + break; + case 3070: + DoScriptText(-1713533, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3080); + break; + case 3081: + DoScriptText(-1713734, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3091); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + case 4030: + DoScriptText(-1713748, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 4040); break; } - } + } else UpdateTimer -= diff; - m_pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); } }; @@ -1507,11 +1555,11 @@ struct MANGOS_DLL_DECL npc_rinn_tocAI : public ScriptedAI { npc_rinn_tocAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); Reset(); } - ScriptedInstance* m_pInstance; + ScriptedInstance* pInstance; uint32 UpdateTimer; void Reset() @@ -1526,60 +1574,60 @@ struct MANGOS_DLL_DECL npc_rinn_tocAI : public ScriptedAI void UpdateAI(const uint32 diff) { - if (!m_pInstance) + if (!pInstance) return; - - if (m_pInstance->GetData(TYPE_EVENT_NPC) != NPC_RINN) + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_RINN) return; - UpdateTimer = m_pInstance->GetData(TYPE_EVENT_TIMER); + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); if (UpdateTimer <= diff) { - switch (m_pInstance->GetData(TYPE_EVENT)) - { - case 130: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TIRION)) - DoScriptText(-1713537, pTemp); - - UpdateTimer = 3000; - m_pInstance->SetData(TYPE_EVENT,140); - break; - case 2020: - DoScriptText(-1713528, m_creature); - UpdateTimer = 7000; - m_pInstance->SetData(TYPE_EVENT,2030); - break; - case 3051: - DoScriptText(-1713731, m_creature); - UpdateTimer = 15000; - m_pInstance->SetData(TYPE_EVENT,3061); - break; - case 3071: - DoScriptText(-1713733, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,3081); - break; - case 3080: - DoScriptText(-1713534, m_creature); - UpdateTimer = 5000; - m_pInstance->SetData(TYPE_EVENT,3090); - m_pInstance->DoUseDoorOrButton(GO_MAIN_GATE_DOOR); - break; - case 4020: - DoScriptText(-1713548, m_creature); - UpdateTimer = 7000; - if (Creature* pBarrent = m_pInstance->GetSingleCreatureFromStorage(NPC_BARRENT)) - pBarrent->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - m_pInstance->SetData(TYPE_EVENT,4030); + switch (pInstance->GetData(TYPE_EVENT)) + { + case FIGHT1_INTRO_4: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713502, m_creature); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT, FIGHT1_INTRO_5); + break; + case FIGHT1_INTRO_5: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 140); + break; + case 2020: + DoScriptText(-1713528, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 2030); + break; + case 3051: + DoScriptText(-1713731, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3061); + break; + case 3071: + DoScriptText(-1713733, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3081); + break; + case 3080: + DoScriptText(-1713534, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 3090); + pInstance->DoUseDoorOrButton(pInstance->GetSingleGameObjectFromStorage(GO_MAIN_GATE_DOOR)->GetObjectGuid()); + break; + case 4020: + DoScriptText(-1713548, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 4030); break; - } + } } - else + else UpdateTimer -= diff; - m_pInstance->SetData(TYPE_EVENT_TIMER,UpdateTimer); + pInstance->SetData(TYPE_EVENT_TIMER,UpdateTimer); } }; @@ -1588,39 +1636,78 @@ CreatureAI* GetAI_npc_rinn_toc(Creature* pCreature) return new npc_rinn_tocAI(pCreature); }; +bool GossipHello_npc_argent_mage(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + char const* _message; + + if (!pInstance) + return false; + + if(pInstance->GetData(TYPE_ANUBARAK) != DONE ) + return true; + + _message = "I'm ready, let's teleport me to Dalaran!"; + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(MAGE_TEXT_ID, pCreature->GetObjectGuid()); + + return true; +} + +bool GossipSelect_npc_argent_mage(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + if (!pInstance) + return false; + + if (pInstance->GetData(TYPE_ANUBARAK) != DONE) + return false; + pCreature->CastSpell(pPlayer, SPELL_TELEPORT_DALARAN, false); + + return true; +} void AddSC_trial_of_the_crusader() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "npc_toc_announcer"; - pNewScript->GetAI = &GetAI_npc_toc_announcer; - pNewScript->pGossipHello = &GossipHello_npc_toc_announcer; - pNewScript->pGossipSelect = &GossipSelect_npc_toc_announcer; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_lich_king_toc"; - pNewScript->GetAI = &GetAI_boss_lich_king_toc; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_fizzlebang_toc"; - pNewScript->GetAI = &GetAI_npc_fizzlebang_toc; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_tirion_toc"; - pNewScript->GetAI = &GetAI_npc_tirion_toc; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_garrosh_toc"; - pNewScript->GetAI = &GetAI_npc_garrosh_toc; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_rinn_toc"; - pNewScript->GetAI = &GetAI_npc_rinn_toc; - pNewScript->RegisterSelf(); + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "npc_toc_announcer"; + NewScript->GetAI = &GetAI_npc_toc_announcer; + NewScript->pGossipHello = &GossipHello_npc_toc_announcer; + NewScript->pGossipSelect = &GossipSelect_npc_toc_announcer; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_lich_king_toc"; + NewScript->GetAI = &GetAI_boss_lich_king_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_fizzlebang_toc"; + NewScript->GetAI = &GetAI_npc_fizzlebang_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_tirion_toc"; + NewScript->GetAI = &GetAI_npc_tirion_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_garrosh_toc"; + NewScript->GetAI = &GetAI_npc_garrosh_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_rinn_toc"; + NewScript->GetAI = &GetAI_npc_rinn_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_argent_mage"; + NewScript->pGossipHello = &GossipHello_npc_argent_mage; + NewScript->pGossipSelect = &GossipSelect_npc_argent_mage; + NewScript->RegisterSelf(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h index 34a9924a68..efe929897a 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h @@ -1,18 +1,6 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ #ifndef DEF_CRUSADER_H #define DEF_CRUSADER_H @@ -32,15 +20,9 @@ enum TYPE_EVENT = 8, MAX_ENCOUNTERS = 9, - TYPE_UPPER_BACK_PAIN = 0, - TYPE_SIXTY_PAIN_SPIKE = 1, - TYPE_SALT_AND_PEPPER = 2, - TYPE_SKILL = 3, - TYPE_MAD_SKILL = 4, - TYPE_INSANITY = 5, - TYPE_DEDICATED_INSANITY = 6, - TYPE_IMMORTALITY = 7, - MAX_SPECIAL_ACHIEV_CRITS = 8, + TYPE_GORMOK = 11, + TYPE_SNAKES = 12, + TYPE_ICEHOWL = 13, NPC_BARRENT = 34816, NPC_TIRION = 34996, @@ -92,8 +74,8 @@ enum NPC_CRUSADER_2_13 = 34445, //Holy paladin NPC_CRUSADER_2_14 = 34459, //Moonkin - NPC_CRUSADER_0_1 = 35465, - NPC_CRUSADER_0_2 = 35610, + NPC_CRUSADER_0_1 = 35465, //Warlock's pet: Zhaagrym + NPC_CRUSADER_0_2 = 35610, //Hunter's pet: Cat NPC_LIGHTBANE = 34497, NPC_DARKBANE = 34496, @@ -117,100 +99,69 @@ enum GO_ARGENT_COLISEUM_FLOOR = 195527, //20943 GO_MAIN_GATE_DOOR = 195647, - GO_WEB_DOOR = 195485, - GO_WEST_PORTCULLIS = 195589, - GO_SOUTH_PORTCULLIS = 195590, - GO_NORTH_PORTCULLIS = 195591, + GO_EAST_PORTCULLIS = 195648, + GO_SOUTH_PORTCULLIS = 195649, + GO_NORTH_PORTCULLIS = 195650, TYPE_DIFFICULTY = 101, TYPE_EVENT_TIMER = 102, TYPE_EVENT_NPC = 103, - TYPE_NORTHREND_BEASTS = 104, TYPE_CRUSADERS_COUNT = 105, DATA_HEALTH_EYDIS = 201, DATA_HEALTH_FJOLA = 202, + DATA_CASTING_VALKYRS = 203, DESPAWN_TIME = 300000, - CRITERIA_ACHIEV_UPPER_BACK_PAIN_10N = 11779, - CRITERIA_ACHIEV_UPPER_BACK_PAIN_25N = 11780, - - CRITERIA_ACHIEV_SIXTY_PAIN_SPIKE_10N = 11838, - CRITERIA_ACHIEV_SIXTY_PAIN_SPIKE_25N = 11839, - - CRITERIA_ACHIEV_SALT_AND_PEPPER_10N = 11778, - CRITERIA_ACHIEV_SALT_AND_PEPPER_10H = 12258, - CRITERIA_ACHIEV_SALT_AND_PEPPER_25N = 11818, - CRITERIA_ACHIEV_SALT_AND_PEPPER_25H = 11860, - - CRITERIA_ACHIEV_TRIBUTE_TO_SKILL_10 = 12344, - CRITERIA_ACHIEV_TRIBUTE_TO_SKILL_25 = 12338, - CRITERIA_ACHIEV_TRIBUTE_TO_MAD_SKILL_10 = 12347, - CRITERIA_ACHIEV_TRIBUTE_TO_MAD_SKILL_25 = 12341, - CRITERIA_ACHIEV_TRIBUTE_TO_INSANITY_10 = 12349, - CRITERIA_ACHIEV_TRIBUTE_TO_INSANITY_25 = 12343, - CRITERIA_ACHIEV_TRIBUTE_TO_IMMORTALITY_HORDE = 12247, - CRITERIA_ACHIEV_TRIBUTE_TO_IMMORTALITY_ALLY = 12359, - CRITERIA_ACHIEV_TRIBUTE_TO_DEDICATED_INSANITY = 12360, + RAGGIO_ARENA = 50, + // Val'kyr Essences + SPELL_LIGHT_ESSENCE = 65686, + SPELL_LIGHT_ESSENCE_N25 = 67222, + SPELL_LIGHT_ESSENCE_H10 = 67223, + SPELL_LIGHT_ESSENCE_H25 = 67224, + SPELL_DARK_ESSENCE = 65684, + SPELL_DARK_ESSENCE_N25 = 67176, + SPELL_DARK_ESSENCE_H10 = 67177, + SPELL_DARK_ESSENCE_H25 = 67178, + // Power Up + SPELL_POWERUP_N10 = 67590, + SPELL_POWERUP_N25 = 67602, + SPELL_POWERUP_H10 = 67603, + SPELL_POWERUP_H25 = 67604, }; static Locations SpawnLoc[]= { - {559.257996f, 90.266197f, 395.122986f}, // 0 Barrent - {563.672974f, 139.571f, 393.837006f}, // 1 Center - {563.833008f, 187.244995f, 394.5f}, // 2 Backdoor - {577.347839f, 185.338888f, 395.14f}, // 3 - Right - {550.955933f, 185.338888f, 395.14f}, // 4 - Left - {575.042358f, 195.260727f, 395.137146f}, // 5 - {552.248901f, 195.331955f, 395.132658f}, // 6 - {573.342285f, 195.515823f, 395.135956f}, // 7 - {554.239929f, 195.825577f, 395.137909f}, // 8 - {571.042358f, 195.260727f, 395.137146f}, // 9 - {556.720581f, 195.015472f, 395.132658f}, // 10 - {569.534119f, 195.214478f, 395.139526f}, // 11 - {569.231201f, 195.941071f, 395.139526f}, // 12 - {558.811610f, 195.985779f, 394.671661f}, // 13 - {567.641724f, 195.351501f, 394.659943f}, // 14 - {560.633972f, 195.391708f, 395.137543f}, // 15 - {565.816956f, 195.477921f, 395.136810f}, // 16 - {563.549f, 152.474f, 394.393f}, // 17 - Lich king start - {563.547f, 141.613f, 393.908f}, // 18 - Lich king end - {787.932556f, 133.28978f, 142.612152f}, // 19 - Anub'arak start location + {559.257996f, 90.266197f, 395.122986f}, // 0 Barrent + {563.672974f, 139.571f, 393.837006f}, // 1 Center + {563.833008f, 184.244995f, 394.5f}, // 2 Backdoor + {577.347839f, 184.338888f, 395.14f}, // 3 - Right + {550.955933f, 184.338888f, 395.14f}, // 4 - Left + {575.042358f, 184.260727f, 395.137146f}, // 5 + {552.248901f, 184.331955f, 395.132658f}, // 6 + {573.342285f, 184.515823f, 395.135956f}, // 7 + {554.239929f, 184.825577f, 395.137909f}, // 8 + {571.042358f, 184.260727f, 395.137146f}, // 9 + {556.720581f, 184.015472f, 395.132658f}, // 10 + {569.534119f, 184.214478f, 395.139526f}, // 11 + {569.231201f, 184.941071f, 395.139526f}, // 12 + {558.811610f, 184.985779f, 394.671661f}, // 13 + {567.641724f, 184.351501f, 394.659943f}, // 14 + {560.633972f, 184.391708f, 395.137543f}, // 15 + {565.816956f, 184.477921f, 395.136810f}, // 16 + {563.549f, 152.474f, 394.393f}, // 17 - Lich king start + {563.547f, 141.613f, 393.908f}, // 18 - Lich king end + {787.932556f, 133.28978f, 142.612152f}, // 19 - Anub'arak start location {618.157898f, 132.640869f, 139.559769f}, // 20 - Anub'arak move point location - {563.813660f, 182.842819f, 395.128052f}, // 21 - Fizzlebang start location + {508.104767f, 138.247345f, 395.128052f}, // 21 - Fizzlebang start location {586.060242f, 117.514809f, 394.314026f}, // 22 - Dark essence 1 {541.602112f, 161.879837f, 394.587952f}, // 23 - Dark essence 2 {541.021118f, 117.262932f, 395.314819f}, // 24 - Light essence 1 {586.200562f, 162.145523f, 394.626129f}, // 25 - Light essence 2 - {563.833008f, 195.244995f, 394.585561f}, // 26 - outdoor - {563.938477f, 149.210571f, 394.321838f}, // 27 - Fizzlebang end - {563.710999f, 131.058319f, 394.321838f}, // 28 - Jaraxxus - {750.78f, 158.48f, 142.68f }, // 29 - Frost Sphere 1 - {749.69f, 129.47f, 142.68f }, // 30 - Frost Sphere 2 - {702.69f, 126.47f, 142.68f }, // 31 - Frost Sphere 3 - {702.53f, 154.69f, 142.68f }, // 32 - Frost Sphere 4 - {530.80f, 108.18f, 395.14f }, // 33 - Unleashed light 1 - {530.49f, 172.75f, 395.14f }, // 34 - Unleashed light 2 - {591.52f, 167.06f, 395.14f }, // 35 - Unleashed light 3 - {589.40f, 114.05f, 395.14f }, // 36 - Unleashed light 4 - {516.64f, 139.74f, 395.14f }, // 37 - Unleashed dark 1 - {563.88f, 169.17f, 395.14f }, // 38 - Unleashed dark 2 - {604.99f, 139.63f, 395.14f }, // 39 - Unleashed dark 3 - {563.65f, 103.28f, 395.14f }, // 40 - Unleashed dark 4 - {519.75f, 119.29f, 395.14f }, // 41 - Unleashed light 1 extra (25) - {548.70f, 170.04f, 395.14f }, // 42 - Unleashed light 2 extra (25) - {575.52f, 144.13f, 395.14f }, // 43 - Unleashed light 3 extra (25) - {570.38f, 122.28f, 395.14f }, // 44 - Unleashed light 4 extra (25) - {550.53f, 145.74f, 395.14f }, // 45 - Unleashed dark 1 extra (25) - {577.57f, 174.08f, 395.14f }, // 46 - Unleashed dark 2 extra (25) - {605.72f, 119.60f, 395.14f }, // 47 - Unleashed dark 3 extra (25) - {554.94f, 123.42f, 395.14f }, // 48 - Unleashed dark 4 extra (25) - {697.73f, 118.48f, 142.68f }, // 49 - Frost Sphere 5 - {733.33f, 153.44f, 142.68f }, // 50 - Frost Sphere 6 - {731.40f, 90.90f, 142.68f }, // 51 - Frost Sphere 7 - {794.34f, 150.48f, 142.68f }, // 52 - Frost Sphere 8 + {563.833008f, 184.244995f, 394.585561f}, // 26 - outdoor + {548.610596f, 139.807800f, 394.321838f}, // 27 - fizzlebang end }; enum uiWorldStates @@ -219,78 +170,40 @@ enum uiWorldStates UPDATE_STATE_UI_COUNT = 4389, }; -enum NorthrendBeasts +enum Snakes { - GORMOK_IN_PROGRESS = 1000, - GORMOK_DONE = 1001, - SNAKES_IN_PROGRESS = 2000, - DREADSCALE_SUBMERGED = 2001, - ACIDMAW_SUBMERGED = 2002, - SNAKES_SPECIAL = 2003, - SNAKES_DONE = 2004, - ICEHOWL_IN_PROGRESS = 3000, - ICEHOWL_DONE = 3001, + DREADSCALE_SUBMERGED = 5, + ACIDMAW_SUBMERGED = 6, }; enum AnnounserMessages { - MSG_BEASTS = 724001, - MSG_JARAXXUS = 724002, - MSG_CRUSADERS = 724003, - MSG_VALKIRIES = 724004, - MSG_LICH_KING = 724005, - MSG_ANUBARAK = 724006, + MSG_BEASTS = 724001, + MSG_JARAXXUS = 724002, + MSG_CRUSADERS = 724003, + MSG_VALKIRIES = 724004, + MSG_LICH_KING = 724005, + MSG_ANUBARAK = 724006, }; -class MANGOS_DLL_DECL instance_trial_of_the_crusader : public BSWScriptedInstance +enum FightPhases { -public: - instance_trial_of_the_crusader(Map* pMap); - ~instance_trial_of_the_crusader() {} - - void Initialize(); - - bool IsEncounterInProgress() const; - void OnPlayerEnter(Player *m_player); - void OnPlayerDeath(Player *m_player); - - bool IsRaidWiped(); - void UpdateWorldState(); - - void OnCreatureCreate(Creature* pCreature); - void OnObjectCreate(GameObject *pGo); - - bool CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/); - void SetSpecialAchievementCriteria(uint32 uiType, bool bIsMet); - - void SetData(uint32 uiType, uint32 uiData); - uint32 GetData(uint32 uiType); - - const char* Save() { return m_strInstData.c_str(); } - - void Load(const char* chrIn); - -private: - - uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; - uint32 m_auiEventTimer; - uint32 m_auiEventNPCId; - uint32 m_auiNorthrendBeasts; - uint8 Difficulty; - std::string m_strInstData; - bool needsave; - - bool m_bAchievCriteria[MAX_SPECIAL_ACHIEV_CRITS]; - - uint32 m_uiDataDamageFjola; - uint32 m_uiDataDamageEydis; - - uint32 m_uiTributeChest1; - uint32 m_uiTributeChest2; - uint32 m_uiTributeChest3; - uint32 m_uiTributeChest4; - - uint32 m_auiCrusadersCount; + FIGHT1_INTRO_1 = 110, + FIGHT1_INTRO_2 = 120, + FIGHT1_INTRO_3 = 122, + FIGHT1_INTRO_4 = 130, + FIGHT1_INTRO_5 = 132, + FIGHT1_INTRO_6 = 140, + FIGHT1_SUMMON = 150, + FIGHT1_END = 160, + FIGHT2_INTRO_1 = 200, + FIGHT2_INTRO_2 = 205, + FIGHT2_SUMMON = 210, + FIGHT2_END = 220, + FIGHT3_INTRO_1 = 300, + FIGHT3_INTRO_2 = 305, + FIGHT3_SUMMON = 310, + FIGHT3_END = 320, }; #endif diff --git a/scripts/northrend/dalaran.cpp b/scripts/northrend/dalaran.cpp index 1eb3e31d53..7c63cb842e 100644 --- a/scripts/northrend/dalaran.cpp +++ b/scripts/northrend/dalaran.cpp @@ -23,6 +23,7 @@ EndScriptData */ /* ContentData npc_dalaran_guardian_mage +npc_zirdomi EndContentData */ #include "precompiled.h" @@ -74,12 +75,111 @@ CreatureAI* GetAI_npc_dalaran_guardian_mage(Creature* pCreature) return new npc_dalaran_guardian_mageAI(pCreature); } +/*###### +## npc_zidormi +######*/ + +#define GOSSIP_ITEM_ZIDORMI1 "Take me to the Caverns of Time." + +enum +{ + SPELL_TELEPORT_COT = 46343, + GOSSIP_TEXTID_ZIDORMI1 = 14066 +}; + +bool GossipHello_npc_zidormi(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->getLevel() >= 65) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ZIDORMI1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + } + else + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ZIDORMI1, pCreature->GetObjectGuid()); + + return true; +} + +bool GossipSelect_npc_zidormi(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + pPlayer->CastSpell(pPlayer,SPELL_TELEPORT_COT,false); + + return true; +} + +/***************/ +/* npc_maloric */ +/***************/ + +enum +{ + SPELL_INCAPACITATE_MALORIC = 63124 +}; + +struct MANGOS_DLL_DECL npc_maloricAI : public ScriptedAI +{ + npc_maloricAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiCheckTimer; + + void Reset() + { + m_uiCheckTimer = 0; + m_creature->RemoveAurasDueToSpell(SPELL_INCAPACITATE_MALORIC); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_INCAPACITATE_MALORIC) + { + if(!m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiCheckTimer < uiDiff) + { + if(!m_creature->HasAura(SPELL_INCAPACITATE_MALORIC)) + { + if(m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK)) + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + m_uiCheckTimer = 1000; + } + else + m_uiCheckTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_maloric(Creature* pCreature) +{ + return new npc_maloricAI(pCreature); +} + void AddSC_dalaran() { - Script* pNewScript; + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_dalaran_guardian_mage"; + newscript->GetAI = &GetAI_npc_dalaran_guardian_mage; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "npc_dalaran_guardian_mage"; - pNewScript->GetAI = &GetAI_npc_dalaran_guardian_mage; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_zidormi"; + newscript->pGossipHello = &GossipHello_npc_zidormi; + newscript->pGossipSelect = &GossipSelect_npc_zidormi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_maloric"; + newscript->GetAI = &GetAI_npc_maloric; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/draktharon_keep/boss_tharonja.cpp b/scripts/northrend/draktharon_keep/boss_tharonja.cpp index bbbeb65d9a..61b39dba11 100644 --- a/scripts/northrend/draktharon_keep/boss_tharonja.cpp +++ b/scripts/northrend/draktharon_keep/boss_tharonja.cpp @@ -80,7 +80,7 @@ enum PhaseChangeTimer { PHASE_CHANGE_SKELETON = 12000, PHASE_CHANGE_REAL = 6000, - PHASE_CHANGE_FLESH = 20000 + PHASE_CHANGE_FLESH = 20000 }; /*###### @@ -98,19 +98,20 @@ struct MANGOS_DLL_DECL boss_tharonjaAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 PhaseChangeTimer; - uint32 Phase; - uint32 CurseOfLife_Timer; - uint32 SkeletonSpells_Timer; - uint32 PoisonCloud_Timer; - uint32 FleshSpells_Timer; + uint32 m_uiPhaseChangeTimer; + uint32 m_uiPhase; + uint32 m_uiCurseOfLifeTimer; + uint32 m_uiSkeletonSpellsTimer; + uint32 m_uiPoisonCloudTimer; + uint32 m_uiFleshSpellsTimer; void Reset() { - PhaseChangeTimer = PHASE_CHANGE_SKELETON; - Phase = PHASE_SKELETON; - SkeletonSpells_Timer = urand (5000, 10000); - CurseOfLife_Timer = urand (5000, 10000); + m_creature->SetRespawnDelay(DAY); + m_uiPhaseChangeTimer = PHASE_CHANGE_SKELETON; + m_uiPhase = PHASE_SKELETON; + m_uiSkeletonSpellsTimer = urand(5000, 10000); + m_uiCurseOfLifeTimer = urand(5000, 10000); } void Aggro(Unit* pWho) @@ -146,90 +147,105 @@ struct MANGOS_DLL_DECL boss_tharonjaAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Phase == PHASE_SKELETON) + switch (m_uiPhase) { - if (CurseOfLife_Timer < uiDiff) + case PHASE_SKELETON: { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CURSE_OF_LIFE : H_SPELL_CURSE_OF_LIFE); - CurseOfLife_Timer = urand (5000, 10000); - }else CurseOfLife_Timer -= uiDiff; + if (m_uiCurseOfLifeTimer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CURSE_OF_LIFE : H_SPELL_CURSE_OF_LIFE); + m_uiCurseOfLifeTimer = urand (5000, 10000); + } + else m_uiCurseOfLifeTimer -= uiDiff; - if (SkeletonSpells_Timer < uiDiff) - { - switch(urand(0, 1)) + if (m_uiSkeletonSpellsTimer < uiDiff) { - case 0: - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_VOLLEY : H_SPELL_SHADOW_VOLLEY); - case 1: - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_RAIN_OF_FIRE : H_SPELL_RAIN_OF_FIRE); + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_VOLLEY : H_SPELL_SHADOW_VOLLEY); + case 1: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_RAIN_OF_FIRE : H_SPELL_RAIN_OF_FIRE); + } + m_uiSkeletonSpellsTimer = urand (5000, 10000); } - SkeletonSpells_Timer = urand (5000, 10000); - }else SkeletonSpells_Timer -= uiDiff; + else m_uiSkeletonSpellsTimer -= uiDiff; - if (PhaseChangeTimer < uiDiff) - { - m_creature->CastSpell(m_creature, SPELL_DECAY_FLESH, true); - PhaseChangeTimer = PHASE_CHANGE_REAL; - Phase = PHASE_INTOFLESH; - }else PhaseChangeTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - if (Phase == PHASE_INTOFLESH) - { - if (PhaseChangeTimer < uiDiff) - { - m_creature->CastSpell(m_creature, SPELL_GIFT_OF_THARONJA, true); - m_creature->SetDisplayId(27073); - PhaseChangeTimer = PHASE_CHANGE_FLESH; - Phase = PHASE_FLESH; - FleshSpells_Timer = 1500; - PoisonCloud_Timer = 10000; - }else PhaseChangeTimer -= uiDiff; - } - - if (Phase == PHASE_FLESH) - { - if (PhaseChangeTimer < uiDiff) + if (m_uiPhaseChangeTimer < uiDiff) + { + m_creature->CastSpell(m_creature, SPELL_DECAY_FLESH, true); + m_uiPhaseChangeTimer = PHASE_CHANGE_REAL; + m_uiPhase = PHASE_INTOFLESH; + } + else m_uiPhaseChangeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + break; + } + case PHASE_INTOFLESH: { - DoCast(m_creature, SPELL_RETURN_FLESH); - PhaseChangeTimer = PHASE_CHANGE_REAL; - Phase = PHASE_INTOSKELETON; - }else PhaseChangeTimer -= uiDiff; + if (m_uiPhaseChangeTimer < uiDiff) + { + m_creature->CastSpell(m_creature, SPELL_GIFT_OF_THARONJA, true); + m_creature->SetDisplayId(27073); + m_uiPhaseChangeTimer = PHASE_CHANGE_FLESH; + m_uiPhase = PHASE_FLESH; + m_uiFleshSpellsTimer = 1500; + m_uiPoisonCloudTimer = 10000; + } + else m_uiPhaseChangeTimer -= uiDiff; - if (PoisonCloud_Timer < uiDiff) + break; + } + case PHASE_FLESH: { - DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_POISON_CLOUD : H_SPELL_POSION_CLOUD); - PoisonCloud_Timer = 10000; - }else PoisonCloud_Timer -= uiDiff; + if (m_uiPhaseChangeTimer < uiDiff) + { + DoCast(m_creature, SPELL_RETURN_FLESH); + m_uiPhaseChangeTimer = PHASE_CHANGE_REAL; + m_uiPhase = PHASE_INTOSKELETON; + } + else m_uiPhaseChangeTimer -= uiDiff; - if (FleshSpells_Timer < uiDiff) - { - switch(urand(0, 3)) + if (m_uiPoisonCloudTimer < uiDiff) { - case 0: - case 1: - case 2: - DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_LIGHTNING_BREATH : H_SPELL_LIGHTNING_BREATH); - case 3: - DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_EYE_BEAM : SPELL_EYE_BEAM); + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_POISON_CLOUD : H_SPELL_POSION_CLOUD); + m_uiPoisonCloudTimer = 10000; } - FleshSpells_Timer = 1500; - }else FleshSpells_Timer -= uiDiff; - } - - if (Phase == PHASE_INTOSKELETON) - { - if (PhaseChangeTimer < uiDiff) + else m_uiPoisonCloudTimer -= uiDiff; + + if (m_uiFleshSpellsTimer < uiDiff) + { + switch(urand(0, 3)) + { + case 0: + case 1: + case 2: + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_LIGHTNING_BREATH : H_SPELL_LIGHTNING_BREATH); + case 3: + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_EYE_BEAM : SPELL_EYE_BEAM); + } + m_uiFleshSpellsTimer = 1500; + } + else m_uiFleshSpellsTimer -= uiDiff; + + DoMeleeAttackIfReady(); + break; + } + case PHASE_INTOSKELETON: { - DoCast(m_creature, SPELL_DECAY_FLESH); - m_creature->SetDisplayId(27072); - PhaseChangeTimer = PHASE_CHANGE_SKELETON; - Phase = PHASE_SKELETON; - SkeletonSpells_Timer = urand (5000, 10000); - CurseOfLife_Timer = urand (5000, 10000); - }else PhaseChangeTimer -= uiDiff; + if (m_uiPhaseChangeTimer < uiDiff) + { + m_creature->SetDisplayId(27072); + m_uiPhaseChangeTimer = PHASE_CHANGE_SKELETON; + m_uiPhase = PHASE_SKELETON; + m_uiSkeletonSpellsTimer = urand(5000, 10000); + m_uiCurseOfLifeTimer = urand(5000, 10000); + } + else m_uiPhaseChangeTimer -= uiDiff; + + break; + } } } }; diff --git a/scripts/northrend/gundrak/boss_colossus.cpp b/scripts/northrend/gundrak/boss_colossus.cpp index e3f2a82e23..736da4b6b4 100644 --- a/scripts/northrend/gundrak/boss_colossus.cpp +++ b/scripts/northrend/gundrak/boss_colossus.cpp @@ -31,16 +31,21 @@ enum EMOTE_GLOW = -1604010, // collosus' abilities - SPELL_EMERGE = 54850, - SPELL_MIGHTY_BLOW = 54719, - SPELL_MORTAL_STRIKES = 54715, - SPELL_MORTAL_STRIKES_H = 59454, + SPELL_EMERGE = 54850, + SPELL_MIGHTY_BLOW = 54719, + SPELL_SUMMON_ELEMENTAL = 54851, // elemental's abilities - SPELL_MERGE = 54878, - SPELL_SURGE = 54801, - SPELL_MOJO_VOLLEY = 59453, - SPELL_MOJO_VOLLEY_H = 54849 + SPELL_MERGE = 54878, + SPELL_SURGE = 54801, + SPELL_SURGE_EFFECT = 54827, + SPELL_MOJO_PUDDLE = 55627, + SPELL_MOJO_PUDDLE_H = 58994, + SPELL_MOJO_WAVE = 55626, + SPELL_MOJO_WAVE_H = 58993, + SPELL_FREEZE = 16245, + + NPC_LIVING_MOJO = 29830 }; /*###### @@ -58,76 +63,383 @@ struct MANGOS_DLL_DECL boss_colossusAI : public ScriptedAI instance_gundrak* m_pInstance; bool m_bIsRegularMode; + bool m_bMergeMojoEvent; + bool m_bMergeMojoEventStarted; + + uint32 m_uiMojoEventTimer; + uint32 m_uiSummonEventTimer; + bool m_bFirstEmerge; + bool m_bSecondEmerge; + bool m_bSummonElemental; + bool m_bElementalDead; uint32 m_uiMightyBlowTimer; void Reset() { + m_bMergeMojoEvent = false; + m_bMergeMojoEventStarted = false; + + m_uiMojoEventTimer = 3000; + m_uiSummonEventTimer = 2500; + m_bFirstEmerge = false; + m_bSecondEmerge = false; + m_bSummonElemental = false; + m_bElementalDead = false; + m_uiMightyBlowTimer = 10000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(m_pInstance) + { + if(Creature* pElemental = m_pInstance->GetSingleCreatureFromStorage(NPC_ELEMENTAL)) + pElemental->ForcedDespawn(); + } } - void Agrro() + void Aggro() { - DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_MORTAL_STRIKES : SPELL_MORTAL_STRIKES_H); - if (m_pInstance) m_pInstance->SetData(TYPE_COLOSSUS, IN_PROGRESS); } + void AttackStart(Unit *pWho) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(pWho); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_COLOSSUS, NOT_STARTED); + + std::list pLivingMojos; + GetCreatureListWithEntryInGrid(pLivingMojos, m_creature, NPC_LIVING_MOJO, 15.0f); + + if(!pLivingMojos.empty()) + { + for (std::list::iterator iter = pLivingMojos.begin(); iter != pLivingMojos.end(); ++iter) + (*iter)->Respawn(); + } + } + void JustDied(Unit* pKiller) { if (m_pInstance) m_pInstance->SetData(TYPE_COLOSSUS, DONE); } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + void JustSummoned(Creature *pSummoned) { - if (pSpell->Id == SPELL_MERGE) + // Second summon - when colossus nearly dead + if (pSummoned->GetEntry() == NPC_ELEMENTAL) + if (m_bSecondEmerge) + pSummoned->SetHealthPercent(50.0f); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage >= m_creature->GetHealth()) { - // re-activate colossus here + if (!m_bElementalDead) + { + uiDamage = 0; + m_creature->SetHealth(1); + } } + + if (m_bSummonElemental) + uiDamage = 0; } - void JustSummoned(Creature* pSummoned) + void Activate() { - if (pSummoned->GetEntry() == NPC_ELEMENTAL) + m_creature->RemoveAurasDueToSpell(SPELL_FREEZE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit* pVictim = m_creature->getVictim()) + m_creature->GetMotionMaster()->MoveChase(pVictim); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_COLOSSUS) == IN_PROGRESS && !m_bMergeMojoEvent) + { + m_bMergeMojoEvent = true; + + std::list pLivingMojos; + GetCreatureListWithEntryInGrid(pLivingMojos, m_creature, NPC_LIVING_MOJO, 15.0f); + + if (!pLivingMojos.empty()) + { + for (std::list::iterator iter = pLivingMojos.begin(); iter != pLivingMojos.end(); ++iter) + { + (*iter)->SetWalk(false); + (*iter)->GetMotionMaster()->MovePoint(1, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); + } + } + } + } + + if (m_bMergeMojoEvent && !m_bMergeMojoEventStarted) + { + if (m_uiMojoEventTimer <= uiDiff) + { + m_bMergeMojoEventStarted = true; + Activate(); + } + else + m_uiMojoEventTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiMightyBlowTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIGHTY_BLOW); + m_uiMightyBlowTimer = 10000; + } + else + m_uiMightyBlowTimer -= uiDiff; + + if (m_creature->GetHealthPercent() < 50.0f && !m_bFirstEmerge) + { + m_creature->SetUInt32Value(UNIT_FIELD_TARGET, 0); + m_bFirstEmerge = true; + m_bSummonElemental = true; + m_uiSummonEventTimer = 2500; + DoCast(m_creature, SPELL_EMERGE); + } + + if (!m_bSecondEmerge && m_creature->GetHealthPercent() < 20.0f) + { + m_creature->SetUInt32Value(UNIT_FIELD_TARGET, 0); + m_bSecondEmerge = true; + m_bSummonElemental = true; + m_uiSummonEventTimer = 2500; + DoCast(m_creature, SPELL_EMERGE); + } + + if (m_bSummonElemental) + { + if (m_uiSummonEventTimer <= uiDiff) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + m_creature->CastSpell(m_creature, SPELL_SUMMON_ELEMENTAL, true); + m_creature->GetMotionMaster()->Clear(); + m_creature->SetUInt32Value(UNIT_FIELD_TARGET, 0); + SetCombatMovement(false); + m_creature->CastSpell(m_creature, SPELL_FREEZE, true); + m_bSummonElemental = false; + } + else + m_uiSummonEventTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_elementalAI : public ScriptedAI +{ + boss_elementalAI (Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (instance_gundrak*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + instance_gundrak* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiSurgeTimer; + uint32 m_uiMojoPuddleTimer; + uint32 m_uiMojoWaveTimer; + + bool m_bMerge; + + void Reset() + { + m_uiSurgeTimer = 7000; + m_uiMojoPuddleTimer = 3000; + m_uiMojoWaveTimer = 10000; + + m_bMerge = false; + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) { - // handle elemental stuff + if (Creature* pColossus = m_pInstance->GetSingleCreatureFromStorage(NPC_COLOSSUS)) + { + ((boss_colossusAI*)pColossus->AI())->m_bElementalDead = true; + pColossus->DealDamage(pColossus, pColossus->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + + void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_MERGE && pTarget->GetEntry() == NPC_COLOSSUS) + { + if (Creature* pColossus = m_pInstance->GetSingleCreatureFromStorage(NPC_COLOSSUS)) + { + ((boss_colossusAI*)pColossus->AI())->Activate(); + m_creature->ForcedDespawn(); + } } } void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if (!m_bFirstEmerge && m_creature->GetHealthPercent() < 50.0f) + if (m_bMerge) + uiDamage = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!m_bMerge && m_creature->GetHealthPercent() < 50.0f && m_pInstance) { - m_bFirstEmerge = true; - DoCastSpellIfCan(m_creature, SPELL_EMERGE); + if (Creature* pColossus = m_pInstance->GetSingleCreatureFromStorage(NPC_COLOSSUS)) + { + if (pColossus->GetHealthPercent() > 20.0f) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + DoCast(pColossus, SPELL_MERGE); + m_creature->GetMotionMaster()->Clear(); + m_creature->SetUInt32Value(UNIT_FIELD_TARGET, 0); + SetCombatMovement(false); + m_bMerge = true; + } + } + } + + //need core fix spell Surge, cause it makes mob go in texture and resets! + /*if (m_uiSurgeTimer <= uiDiff) + { + DoScriptText(EMOTE_SURGE, m_creature); + + if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pVictim, SPELL_SURGE); + + m_uiSurgeTimer = 15000; + } + else + m_uiSurgeTimer -= uiDiff;*/ + + if (m_uiMojoPuddleTimer <= uiDiff) + { + if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pVictim, m_bIsRegularMode ? SPELL_MOJO_PUDDLE : SPELL_MOJO_PUDDLE_H); + + m_uiMojoPuddleTimer = 3000; + } + else + m_uiMojoPuddleTimer -= uiDiff; + + if (m_uiMojoWaveTimer <= uiDiff) + { + if (Unit *pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pVictim, m_bIsRegularMode ? SPELL_MOJO_WAVE : SPELL_MOJO_WAVE_H); + + m_uiMojoWaveTimer = urand(7000, 1000); + } + else + m_uiMojoWaveTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL npc_living_mojoAI : public ScriptedAI +{ + npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (instance_gundrak*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + instance_gundrak* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiMojoWaveTimer; + uint32 m_uiMojoPuddleTimer; + + void Reset() + { + m_uiMojoWaveTimer = 2000; + m_uiMojoPuddleTimer = 7000; + + if (Creature* pColossus = m_pInstance->GetSingleCreatureFromStorage(NPC_COLOSSUS)) + { + if (m_creature->GetDistance2d(pColossus) < 15.0f) + SetCombatMovement(false); } - else if (m_creature->GetHealth() - uiDamage <= 0) + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) { - // prevent boss from dying if players deal the final blow - if (pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself()) + if (Creature* pColossus = m_pInstance->GetSingleCreatureFromStorage(NPC_COLOSSUS)) { - uiDamage = 0; - DoCastSpellIfCan(m_creature, SPELL_EMERGE); + if (m_creature->GetDistance2d(pColossus) < 15.0f) + m_pInstance->SetData(TYPE_COLOSSUS, IN_PROGRESS); } } } + void MovementInform(uint32 uiMoveType, uint32 uiPointId) + { + if (uiMoveType != POINT_MOTION_TYPE) + return; + + if (uiPointId == 1) + m_creature->ForcedDespawn(); + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiMightyBlowTimer < uiDiff) + if (m_pInstance) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIGHTY_BLOW); - m_uiMightyBlowTimer = 10000; + if (m_pInstance->GetData(TYPE_COLOSSUS) == IN_PROGRESS) + return; + } + + if (m_uiMojoWaveTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_MOJO_WAVE : SPELL_MOJO_WAVE_H); + m_uiMojoWaveTimer = urand(12000, 15000); } else - m_uiMightyBlowTimer -= uiDiff; + m_uiMojoWaveTimer -= uiDiff; + + if (m_uiMojoPuddleTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_MOJO_PUDDLE : SPELL_MOJO_PUDDLE_H); + m_uiMojoPuddleTimer = urand(10000, 20000); + } + else + m_uiMojoPuddleTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -138,12 +450,32 @@ CreatureAI* GetAI_boss_colossus(Creature* pCreature) return new boss_colossusAI(pCreature); } +CreatureAI* GetAI_boss_elemental(Creature* pCreature) +{ + return new boss_elementalAI(pCreature); +} + +CreatureAI* GetAI_npc_living_mojo(Creature* pCreature) +{ + return new npc_living_mojoAI(pCreature); +} + void AddSC_boss_colossus() { - Script* pNewScript; + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_colossus"; + newscript->GetAI = &GetAI_boss_colossus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_elemental"; + newscript->GetAI = &GetAI_boss_elemental; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "boss_colossus"; - pNewScript->GetAI = &GetAI_boss_colossus; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_living_mojo"; + newscript->GetAI = &GetAI_npc_living_mojo; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/gundrak/boss_eck.cpp b/scripts/northrend/gundrak/boss_eck.cpp index e35219296c..d86337cb8c 100644 --- a/scripts/northrend/gundrak/boss_eck.cpp +++ b/scripts/northrend/gundrak/boss_eck.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: boss_eck -SD%Complete: 80% -SDComment: Timers need improval, Spring Spells are not clear. +SD%Complete: 100% +SDComment: SDCategory: Gundrak EndScriptData */ @@ -25,13 +25,22 @@ EndScriptData */ #include "gundrak.h" enum -{ - SPELL_ECK_BITE = 55813, - SPELL_ECK_SPIT = 55814, - SPELL_ECK_SPRING = 55815, - SPELL_ECK_BERSERK = 55816, - SPELL_ECK_RESIDUE = 55817, - SPELL_ECK_SPRING_ALT = 55837, // Purpose unknown +{ + SAY_AGGRO = -1533021, + SAY_DEATH = -1533021, + EMOTE_SPITE = -1533021, + EMOTE_SPRING = -1533021, + EMOTE_BIT = -1533021, + EMOTE_BERSERK = -1533021, + + SPELL_ECK_RESIDUE_DEBUFF = 55817, + SPELL_ECK_SPITE = 55814, + + SPELL_ECK_SPRING_WHERE = 55837, + SPELL_ECK_SPRING = 55815, + + SPELL_ECK_BIT = 55813, + SPELL_ECK_BERSERK = 55816 }; /*###### @@ -47,30 +56,36 @@ struct MANGOS_DLL_DECL boss_eckAI : public ScriptedAI } instance_gundrak* m_pInstance; - bool m_bIsBerserk; - - uint32 m_uiSpitTimer; - uint32 m_uiSpringTimer; - uint32 m_uiBiteTimer; - uint32 m_uiBerserkTimer; - + bool m_bIsRegularMode; + bool m_bBerserk; + + uint32 m_uiEckSpiteTimer; + uint32 m_uiEckSpringTimer; + uint32 m_uiEckBitTimer; + uint32 m_uiEckBerserkTimer; + void Reset() { - m_uiSpitTimer = urand(10000, 20000); - m_uiSpringTimer = urand(15000, 25000); - m_uiBiteTimer = urand(5000, 15000); - m_uiBerserkTimer = urand(60000, 90000); // Enrange at 20% HP or after 60-90 seconds - m_bIsBerserk = false; + m_uiEckSpiteTimer = 15000; + m_uiEckSpringTimer = 8000; + m_uiEckBitTimer = 5000; + m_uiEckBerserkTimer = urand(60000, 90000); + m_bBerserk = false; + + if (m_creature->HasAura(SPELL_ECK_RESIDUE_DEBUFF)) + m_creature->RemoveAurasDueToSpell(SPELL_ECK_RESIDUE_DEBUFF); } - void Aggro(Unit* pWho) { + DoScriptText(SAY_AGGRO, m_creature); + if (m_pInstance) m_pInstance->SetData(TYPE_ECK, IN_PROGRESS); } - void JustDied(Unit* pKiller) { + DoScriptText(SAY_DEATH, m_creature); + if (m_pInstance) m_pInstance->SetData(TYPE_ECK, DONE); } @@ -80,59 +95,71 @@ struct MANGOS_DLL_DECL boss_eckAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_ECK, FAIL); } - - // As the Eck Spite spell has no dummy or similar effect, applying the residue aura has to be done with spellHitTarget + void SpellHitTarget (Unit* pUnit, const SpellEntry* pSpellEntry) { - if (pSpellEntry->Id == SPELL_ECK_SPIT && pUnit->GetTypeId() == TYPEID_PLAYER && !pUnit->HasAura(SPELL_ECK_RESIDUE)) - pUnit->CastSpell(pUnit, SPELL_ECK_RESIDUE, true); + if (pSpellEntry->Id == SPELL_ECK_SPITE && pUnit->GetTypeId() == TYPEID_PLAYER + && !pUnit->HasAura(SPELL_ECK_RESIDUE_DEBUFF)) + pUnit->CastSpell(pUnit, SPELL_ECK_RESIDUE_DEBUFF, true); } - + void UpdateAI(const uint32 uiDiff) - { + { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - - if (m_uiSpitTimer < uiDiff) + + if (m_uiEckSpiteTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_ECK_SPIT) == CAST_OK) - m_uiSpitTimer = urand(10000, 20000); + DoCastSpellIfCan(m_creature, SPELL_ECK_SPITE); + m_uiEckSpiteTimer = 15000; } - else - m_uiSpitTimer -= uiDiff; + else + m_uiEckSpiteTimer -= uiDiff; - if (m_uiSpringTimer < uiDiff) + if (m_uiEckSpringTimer < uiDiff) { - Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1); - if (!pTarget) - pTarget = m_creature->getVictim(); - - if (DoCastSpellIfCan(pTarget, SPELL_ECK_SPRING) == CAST_OK) + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) { - DoResetThreat(); - m_uiSpringTimer = urand(15000, 25000); + DoCastSpellIfCan(target, SPELL_ECK_SPRING); + m_creature->DeleteThreatList(); + m_creature->SetInCombatWith(target); + m_creature->AddThreat(target, 1.0f); + m_creature->Attack(target, true); } + m_uiEckSpringTimer = 8000; } - else - m_uiSpringTimer -= uiDiff; + else + m_uiEckSpringTimer -= uiDiff; - if (m_uiBiteTimer < uiDiff) + if (m_uiEckBitTimer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_ECK_BITE); - m_uiBiteTimer = urand(5000, 15000); + if (Unit* target = m_creature->getVictim()) + DoCastSpellIfCan(target, SPELL_ECK_BIT); + m_uiEckBitTimer = 5000; } else - m_uiBiteTimer -= uiDiff; + m_uiEckBitTimer -= uiDiff; + + if (!m_bBerserk) + { + if (m_creature->GetHealthPercent() <= 20.0f) + { + DoScriptText(EMOTE_BERSERK, m_creature); + DoCastSpellIfCan(m_creature, SPELL_ECK_BERSERK); + m_bBerserk = true; + } + } - if (!m_bIsBerserk) // Go into Berserk after time, or when below 20% health + if (!m_bBerserk) { - if (m_creature->GetHealthPercent() <= 20.0f || m_uiBerserkTimer < uiDiff) + if (m_uiEckBerserkTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_ECK_BERSERK) == CAST_OK) - m_bIsBerserk = true; + DoCastSpellIfCan(m_creature, SPELL_ECK_BERSERK); + DoScriptText(EMOTE_BERSERK, m_creature); + m_bBerserk = true; } - else - m_uiBerserkTimer -= uiDiff; + else + m_uiEckBerserkTimer -= uiDiff; } DoMeleeAttackIfReady(); diff --git a/scripts/northrend/gundrak/boss_galdarah.cpp b/scripts/northrend/gundrak/boss_galdarah.cpp index 5b800ccd5d..de4becafe3 100644 --- a/scripts/northrend/gundrak/boss_galdarah.cpp +++ b/scripts/northrend/gundrak/boss_galdarah.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss_Galdarah -SD%Complete: 80% -SDComment: achievements need to be implemented, channeling before engage is missing +SD%Complete: 100% +SDComment: SDCategory: Gundrak EndScriptData */ @@ -26,42 +26,39 @@ EndScriptData */ enum { - SAY_AGGRO = -1604019, - SAY_TRANSFORM_1 = -1604020, - SAY_TRANSFORM_2 = -1604021, - SAY_SUMMON_1 = -1604022, - SAY_SUMMON_2 = -1604023, - SAY_SUMMON_3 = -1604024, - SAY_SLAY_1 = -1604025, - SAY_SLAY_2 = -1604026, - SAY_SLAY_3 = -1604027, - SAY_DEATH = -1604028, - - EMOTE_IMPALED = -1604030, - - ACHIEVEMENT_WHAT_THE_ECK = 1864, - ACHIEVEMENT_SHARE_THE_LOVE = 2152, - - NPC_RHINO_SPIRIT = 29791, - SPELL_STAMPEDE_RHINO = 55220, - SPELL_STAMPEDE_RHINO_H = 59823, - - // troll form spells - SPELL_STAMPEDE = 55218, - SPELL_WHIRLING_SLASH = 55250, - SPELL_WHIRLING_SLASH_H = 59824, - SPELL_RHINO_TRANSFORM = 55297, - SPELL_PUNCTURE = 55276, - SPELL_PUNCTURE_H = 59826, - - // rhino form spells - SPELL_TROLL_TRANSFORM = 55299, - SPELL_ENRAGE = 55285, - SPELL_ENRAGE_H = 59828, - SPELL_IMPALING_CHARGE = 54956, - SPELL_IMPALING_CHARGE_H = 59827, - SPELL_STOMP = 55292, - SPELL_STOMP_H = 59829, + SAY_AGGRO = -1604019, + SAY_TRANSFORM_1 = -1604020, + SAY_TRANSFORM_2 = -1604021, + SAY_SUMMON_1 = -1604022, + SAY_SUMMON_2 = -1604023, + SAY_SUMMON_3 = -1604024, + SAY_SLAY_1 = -1604025, + SAY_SLAY_2 = -1604026, + SAY_SLAY_3 = -1604027, + SAY_DEATH = -1604028, + + SPELL_STAMPEDE = 55220, + SPELL_STAMPEDE_H = 59823, + SPELL_CHARGE = 74399, + SPELL_WHIRLING_SLASH = 55250, + SPELL_WHIRLING_SLASH_H = 59824, + SPELL_IMPALING_CHARGE = 54956, + SPELL_IMPALING_CHARGE_H = 59827, + SPELL_KNOCK_BACK = 56104, + SPELL_PUNCTURE = 55276, + SPELL_PUNCTURE_H = 59826, + SPELL_STOMP = 55292, + SPELL_STOMP_H = 59829, + SPELL_ENRAGE = 55285, + SPELL_ENRAGE_H = 59828, + + NPC_RHINO_SPIRIT = 29791, + + MODELID_HUMAN = 27061, + MODELID_RHINO = 26265, + + AURA_ECK_RESIDUE = 55817, + ACHIEV_WHAT_THE_ECK_H = 1864 }; /*###### @@ -79,33 +76,47 @@ struct MANGOS_DLL_DECL boss_galdarahAI : public ScriptedAI instance_gundrak* m_pInstance; bool m_bIsRegularMode; - bool m_bIsTrollPhase; + bool m_bRhinoPhase; + bool m_bUseStampede; + + uint32 m_uiChangePhaseTimer; uint32 m_uiStampedeTimer; - uint32 m_uiPhaseChangeTimer; - uint32 m_uiSpecialAbilityTimer; // Impaling Charge and Whirling Slash - uint32 m_uiPunctureTimer; + uint32 m_uiWhirlingSlashTimer; uint32 m_uiStompTimer; uint32 m_uiEnrageTimer; - uint8 m_uiAbilityCount; + uint32 m_uiImpalingChargeTimer; + uint32 m_uiPunctureTimer; + + ObjectGuid m_uiRhinoGUID; void Reset() { - m_bIsTrollPhase = true; + m_bRhinoPhase = false; + m_bUseStampede = false; + + m_uiChangePhaseTimer = 40000; + m_uiStampedeTimer = 6000; + m_uiWhirlingSlashTimer = 8000; + m_uiStompTimer = 5000; + m_uiEnrageTimer = 4000; + m_uiImpalingChargeTimer = 7000; + m_uiPunctureTimer = 10000; - m_uiStampedeTimer = 10000; - m_uiSpecialAbilityTimer = 12000; - m_uiPunctureTimer = 25000; - m_uiPhaseChangeTimer = 7000; - m_uiAbilityCount = 0; + m_uiRhinoGUID.Clear(); + + m_creature->SetDisplayId(MODELID_HUMAN); + + if (m_pInstance) + m_pInstance->SetData(TYPE_GALDARAH, NOT_STARTED); } void Aggro(Unit* pWho) { - DoScriptText(SAY_AGGRO, m_creature); - if (m_pInstance) - m_pInstance->SetData(TYPE_GALDARAH , IN_PROGRESS); + m_pInstance->SetData(TYPE_GALDARAH, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, m_creature); } void KilledUnit(Unit* pVictim) @@ -118,52 +129,47 @@ struct MANGOS_DLL_DECL boss_galdarahAI : public ScriptedAI } } - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_GALDARAH, NOT_STARTED); - } - void JustDied(Unit* pKiller) { - DoScriptText(SAY_DEATH, m_creature); - if (m_pInstance) m_pInstance->SetData(TYPE_GALDARAH, DONE); - } - void JustSummoned(Creature* pSummoned) - { - pSummoned->setFaction(m_creature->getFaction()); + DoScriptText(SAY_DEATH, m_creature); - if (pSummoned->GetEntry() == NPC_RHINO_SPIRIT) + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - pSummoned->CastSpell(pTarget, m_bIsRegularMode ? SPELL_STAMPEDE_RHINO : SPELL_STAMPEDE_RHINO_H, false, NULL, NULL, m_creature->GetObjectGuid()); + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (itr->getSource()->HasAura(AURA_ECK_RESIDUE) && !m_bIsRegularMode) + itr->getSource()->CompletedAchievement(ACHIEV_WHAT_THE_ECK_H); } } - void DoPhaseSwitch() + void ChangePhase() { - if (!m_bIsTrollPhase) - m_creature->RemoveAurasDueToSpell(SPELL_RHINO_TRANSFORM); - - m_bIsTrollPhase = !m_bIsTrollPhase; + m_bRhinoPhase ? m_bRhinoPhase = false : m_bRhinoPhase = true; + m_creature->SetDisplayId(m_creature->GetDisplayId() == MODELID_HUMAN ? MODELID_RHINO : MODELID_HUMAN); + } - if (m_bIsTrollPhase) - DoCastSpellIfCan(m_creature, SPELL_TROLL_TRANSFORM); - else + void SummonRhinoSpirit() + { + Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + if(pTarget) { - DoScriptText(urand(0, 1) ? SAY_TRANSFORM_1 : SAY_TRANSFORM_2, m_creature); - DoCastSpellIfCan(m_creature, SPELL_RHINO_TRANSFORM); - - m_uiEnrageTimer = 4000; - m_uiStompTimer = 1000; + float x = pTarget->GetPositionX() + 20.0f; + float y = pTarget->GetPositionY() + 20.0f; + float z = pTarget->GetPositionZ(); + Creature* cRhino = m_creature->SummonCreature(NPC_RHINO_SPIRIT, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 1800); + if (cRhino) + { + m_uiRhinoGUID = cRhino->GetObjectGuid(); + cRhino->CastSpell(pTarget, SPELL_CHARGE, true); + cRhino->SetInCombatWith(pTarget); + cRhino->AddThreat(pTarget, 1000.0f); + } } - - m_uiAbilityCount = 0; - m_uiPhaseChangeTimer = 7000; - m_uiSpecialAbilityTimer = 12000; + m_bUseStampede = true; } void UpdateAI(const uint32 uiDiff) @@ -171,87 +177,89 @@ struct MANGOS_DLL_DECL boss_galdarahAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiAbilityCount == 2) - { - if (m_uiPhaseChangeTimer < uiDiff) - DoPhaseSwitch(); - else - m_uiPhaseChangeTimer -= uiDiff; - } + DoMeleeAttackIfReady(); - if (m_bIsTrollPhase) + if (m_bUseStampede) { - if (m_uiPunctureTimer < uiDiff) + if (Creature* cRhino = m_creature->GetMap()->GetCreature(m_uiRhinoGUID)) { - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_PUNCTURE : SPELL_PUNCTURE_H); - m_uiPunctureTimer = 25000; + if (cRhino->getVictim()) + { + if (cRhino->getVictim()->GetDistance(cRhino) < ATTACK_DISTANCE) + { + cRhino->CastSpell(cRhino->getVictim(), m_bIsRegularMode ? SPELL_STAMPEDE : SPELL_STAMPEDE_H, true); + m_bUseStampede = false; + } + } } - else - m_uiPunctureTimer -= uiDiff; + } + if (m_uiChangePhaseTimer < uiDiff) + { + ChangePhase(); + m_uiChangePhaseTimer = 40000; + } + else + m_uiChangePhaseTimer -= uiDiff; + + if (!m_bRhinoPhase) + { if (m_uiStampedeTimer < uiDiff) { - switch(urand(0, 2)) - { - case 0: DoScriptText(SAY_SUMMON_1, m_creature); break; - case 1: DoScriptText(SAY_SUMMON_2, m_creature); break; - case 2: DoScriptText(SAY_SUMMON_3, m_creature); break; - } - - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STAMPEDE); - m_uiStampedeTimer = 15000; + SummonRhinoSpirit(); + m_uiStampedeTimer = urand(8000, 11000); } - else + else m_uiStampedeTimer -= uiDiff; - if (m_uiSpecialAbilityTimer < uiDiff) + if (m_uiWhirlingSlashTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_WHIRLING_SLASH : SPELL_WHIRLING_SLASH_H) == CAST_OK) - m_uiSpecialAbilityTimer = 12000; - - ++m_uiAbilityCount; + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_WHIRLING_SLASH : SPELL_WHIRLING_SLASH_H); + m_uiWhirlingSlashTimer = urand(15000, 23000); + if (m_uiChangePhaseTimer < 5000) + m_uiChangePhaseTimer = 5000; } - else - m_uiSpecialAbilityTimer -= uiDiff; - + else + m_uiWhirlingSlashTimer -= uiDiff; } else { - if (m_uiEnrageTimer < uiDiff) - { - DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_ENRAGE : SPELL_ENRAGE_H); - m_uiEnrageTimer = 15000; - } - else - m_uiEnrageTimer -= uiDiff; - if (m_uiStompTimer < uiDiff) { DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_STOMP : SPELL_STOMP_H); - m_uiStompTimer = 10000; + m_uiStompTimer = urand(12000, 15000); } - else + else m_uiStompTimer -= uiDiff; - if (m_uiSpecialAbilityTimer < uiDiff) + if (m_uiEnrageTimer < uiDiff) { - Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1); - if (!pTarget) - pTarget = m_creature->getVictim(); + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_ENRAGE : SPELL_ENRAGE_H); + m_uiEnrageTimer = urand(12000, 15000); + } + else + m_uiEnrageTimer -= uiDiff; - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_IMPALING_CHARGE : SPELL_IMPALING_CHARGE_H) == CAST_OK) + if (m_uiImpalingChargeTimer < uiDiff) + { + if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - DoScriptText(EMOTE_IMPALED, m_creature, pTarget); - m_uiSpecialAbilityTimer = 12000; - - ++m_uiAbilityCount; + DoCastSpellIfCan(pVictim, m_bIsRegularMode ? SPELL_IMPALING_CHARGE : SPELL_IMPALING_CHARGE_H); + DoCastSpellIfCan(pVictim, SPELL_KNOCK_BACK); } + m_uiImpalingChargeTimer = urand(7000, 9000); } - else - m_uiSpecialAbilityTimer -= uiDiff; - } + else + m_uiImpalingChargeTimer -= uiDiff; - DoMeleeAttackIfReady(); + if (m_uiPunctureTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_PUNCTURE : SPELL_PUNCTURE_H); + m_uiPunctureTimer = urand(20000, 25000); + } + else + m_uiPunctureTimer -= uiDiff; + } } }; @@ -262,10 +270,11 @@ CreatureAI* GetAI_boss_galdarah(Creature* pCreature) void AddSC_boss_galdarah() { - Script* pNewScript; + Script *pNewscript; - pNewScript = new Script; - pNewScript->Name = "boss_galdarah"; - pNewScript->GetAI = &GetAI_boss_galdarah; - pNewScript->RegisterSelf(); + pNewscript = new Script; + pNewscript->Name = "boss_galdarah"; + pNewscript->GetAI = &GetAI_boss_galdarah; + pNewscript->RegisterSelf(); } + diff --git a/scripts/northrend/gundrak/boss_moorabi.cpp b/scripts/northrend/gundrak/boss_moorabi.cpp index a0c65b377a..c80782f397 100644 --- a/scripts/northrend/gundrak/boss_moorabi.cpp +++ b/scripts/northrend/gundrak/boss_moorabi.cpp @@ -48,6 +48,9 @@ enum SPELL_DETERMINED_GORE_H = 59444, SPELL_QUAKE = 55101, SPELL_NUMBING_ROAR = 55100, + + // Achievment + ACHIEV_LESS_RABI = 2040, }; /*###### @@ -110,6 +113,24 @@ struct MANGOS_DLL_DECL boss_moorabiAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_MOORABI, DONE); + + if (!m_bIsRegularMode) + { + if(!m_creature->HasAura(SPELL_TRANSFORMATION, EFFECT_INDEX_0)) + { + AchievementEntry const *AchievLessRabi = GetAchievementStore()->LookupEntry(ACHIEV_LESS_RABI); + if (AchievLessRabi) + { + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievLessRabi); + } + } + } + } } void UpdateAI(const uint32 uiDiff) diff --git a/scripts/northrend/howling_fjord.cpp b/scripts/northrend/howling_fjord.cpp index a5b7327264..2d2f9fce3a 100644 --- a/scripts/northrend/howling_fjord.cpp +++ b/scripts/northrend/howling_fjord.cpp @@ -768,7 +768,7 @@ bool GossipSelect_npc_jack_adams(Player* pPlayer, Creature* pCreature, uint32 ui { pPlayer->CLOSE_GOSSIP_MENU(); ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_JACK_ADAMS_DEBT, 1, false); + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_JACK_ADAMS_DEBT, 1, NULL); if (msg == EQUIP_ERR_OK) pPlayer->StoreNewItem(dest, ITEM_JACK_ADAMS_DEBT, 1, true); pCreature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); diff --git a/scripts/northrend/icecrown.cpp b/scripts/northrend/icecrown.cpp index 177d0308d7..bb5ca694f8 100644 --- a/scripts/northrend/icecrown.cpp +++ b/scripts/northrend/icecrown.cpp @@ -32,6 +32,8 @@ npc_black_knights_gryphon EndContentData */ #include "precompiled.h" +#include "Vehicle.h" +#include "GossipDef.h" #include "escort_ai.h" #include "TemporarySummon.h" @@ -110,6 +112,329 @@ bool GossipSelect_npc_dame_evniki_kapsalis(Player* pPlayer, Creature* pCreature, return true; } +/*###### +## npc_argent_tournament_questgiver +######*/ + +namespace ArgentTournament +{ + Races GetRaceFromNPCId(uint32 id) + // finds the race of argent tournament NPCs + { + switch (id) + { + case 33225: return RACE_HUMAN; + case 33361: return RACE_ORC; + case 33312: return RACE_DWARF; + case 33592: return RACE_NIGHTELF; + case 33373: return RACE_UNDEAD; + case 33403: return RACE_TAUREN; + case 33335: return RACE_GNOME; + case 33372: return RACE_TROLL; + case 33379: return RACE_BLOODELF; + case 33593: return RACE_DRAENEI; + + default: + return Races(0); // invalid + } + } + + #define MAX_RACES 12 + // information about valiants given by race-specific questgivers + static const uint32 InitialValiantsForRace[MAX_RACES] = {0 /*0 = invalid*/,13593 /*1 = human */,13707 /*2 = orc*/, + 13703 /*3 = dwarf*/,13706 /*4 = nightelf*/,13710 /*5 = undead*/,13709 /*6 = tauren*/,13704 /*7 = gnome*/, + 13708 /*8 = troll*/,0 /*invalid: 9 = goblin*/,13711 /*10 = bloodelf*/,13705/*11 = draenei*/}; + static const uint32 FinalValiantsForRace[MAX_RACES] = {0 /*0 = invalid*/,13699 /*1 = human */,13726 /*2 = orc*/, + 13713 /*3 = dwarf*/,13725 /*4 = nightelf*/,13729 /*5 = undead*/,13728 /*6 = tauren*/,13723 /*7 = gnome*/, + 13727 /*8 = troll*/,0 /*invalid: 9 = goblin*/,13731 /*10 = bloodelf*/,13724/*11 = draenei*/}; + + bool CompletedValiantForHisRace(Player * pl) + { + if (pl->getRace() >= MAX_RACES) + return false; // ?!? + + return pl->GetQuestRewardStatus(FinalValiantsForRace[pl->getRace()]); + } + + bool HasValiantActiveForRace(Player * pl,uint32 race) + { + if (uint32 initial = InitialValiantsForRace[race]) + if (pl->GetQuestStatus(initial)) // has quest chain? + if (uint32 final = FinalValiantsForRace[race]) + if (!pl->GetQuestRewardStatus(final)) // is it not complete? + return true; + + return false; + } + + bool HasValiantActive(Player * pl,uint32 exceptRace = 0) + { + // search all valiant quest chains on player + for (uint32 i = 0; i < MAX_RACES; i++) + if (i != exceptRace && HasValiantActiveForRace(pl,i)) + return true; + + return false; // all complete or none found + } + + bool IsQuestgiverActiveFor(Creature * qg,Player * pl) + { + Races race = GetRaceFromNPCId(qg->GetEntry()); + if (!race) + { + error_log("SD2: Argent tournament: unknown race for NPC entry %u, guid %u",qg->GetEntry(),qg->GetGUIDLow()); + return false; + } + + if (race == pl->getRace()) + return true; // always enabled for player of current race (if quest already complete, none will be shown) + + if (CompletedValiantForHisRace(pl) && !HasValiantActive(pl,race)) + return true; // enable questgiver + + return false; + } + + bool HasAchievement(Player * player,uint32 id) + { + if (!player || !id) + return false; + + return player->GetAchievementMgr().HasAchievement(id); + } + + bool IsQuestVisibleFor(Player * player, uint32 questid) + { + if (!player || !questid) + return false; + + if (questid == 13664) + // must have completed 13663 and (13700 or 13701) + return (player->GetQuestRewardStatus(13663) && (player->GetQuestRewardStatus(13700) || player->GetQuestRewardStatus(13701))); + + return true; + } + + enum + { + ACHIEVEMENT_EAC_HORDE = 2816, // Exalted Argent Champion of the Horde + ACHIEVEMENT_EAC_ALLIANCE = 2817 // Exalted Argent Champion of the Alliance + }; +} + +bool GossipHello_npc_argent_tournament_questgiver(Player* pPlayer, Creature* pCreature) +{ + if (!pCreature->isQuestGiver()) + return false; // error + + if (ArgentTournament::IsQuestgiverActiveFor(pCreature,pPlayer)) + return false; // return not handled message: the NPC will behave like a common questgiver + + // else, send empty gossip menu + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipHello_npc_argent_tournament_requires_EAC(Player* pPlayer, Creature* pCreature) +// all creatures with this script must be enabled only when Exalted Argent Champion of the Alliance or Horde has been achieved +{ + if (pPlayer->GetTeam() == ALLIANCE && ArgentTournament::HasAchievement(pPlayer,ArgentTournament::ACHIEVEMENT_EAC_ALLIANCE)) + return false; // behave like a common NPC + + if (pPlayer->GetTeam() == HORDE && ArgentTournament::HasAchievement(pPlayer,ArgentTournament::ACHIEVEMENT_EAC_HORDE)) + return false; + + // else, send empty gossip menu + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +/*###### +## npc_rhydalla +######*/ + +bool GossipHello_npc_rhydalla(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + { + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + QuestMenu &qm = pPlayer->PlayerTalkClass->GetQuestMenu(); + + for (uint32 count = 0; count < qm.MenuItemCount(); ++count ) + { + QuestMenuItem const& qmi = qm.GetItem(count); +#ifndef WIN32 + if (ArgentTournament::IsQuestVisibleFor(pPlayer, qmi.m_qId)) + qm.RemoveItem(qmi.m_qId); +#endif + } + } + return true; +} + +/*###### +## npc_squire_david +######*/ + +enum eSquireDavid +{ + QUEST_THE_ASPIRANT_S_CHALLENGE_H = 13680, + QUEST_THE_ASPIRANT_S_CHALLENGE_A = 13679, + + NPC_ARGENT_VALIANT = 33448, + + GOSSIP_TEXTID_READYTOBATTLE = 14407, + GOSSIP_TEXTID_HOWTO = 14476, + + SOUND_EVENTSTART = 15852 +}; + +#define GOSSIP_SQUIRE_ITEM_1 "I am ready to fight!" +#define GOSSIP_SQUIRE_ITEM_2 "How do the Argent Crusader raiders fight?" + +bool GossipHello_npc_squire_david(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_H) == QUEST_STATUS_INCOMPLETE || + pPlayer->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_A) == QUEST_STATUS_INCOMPLETE )//We need more info about it. + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + } + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_READYTOBATTLE, pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_squire_david(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->SummonCreature(NPC_ARGENT_VALIANT, 8575.451f, 952.472f, 547.554f, 0.38f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + pCreature->PlayDirectSound(SOUND_EVENTSTART); + } + else if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_HOWTO, pCreature->GetObjectGuid()); + + return true; +} + +enum eArgentValiant +{ + SPELL_CHARGE = 63010, + SPELL_SHIELD_BREAKER = 62575, + + NPC_ARGENT_VALIANT_CREDIT = 24108 +}; + +#define SAY_VALIANT_AGGRO "The rank of valiant is not easily won. Prepare yourself!" +#define SAY_VALIANT_DEFEAT "Impressive skills indeed. I believe that you are more than ready for the rank of valiant." + +struct npc_argent_valiantAI : public ScriptedAI +{ + npc_argent_valiantAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->GetMotionMaster()->MovePoint(0.0f,8599.258f,963.951f,547.553f); + pCreature->setFaction(35); //wrong faction in db? + } + + uint32 uiRangedActionTimer; + bool GoingRanged; + bool CanCastRanged; + + void Reset() + { + uiRangedActionTimer = 10000; + GoingRanged = false; + CanCastRanged = false; + } + + void Aggro(Unit* pWho) + { + m_creature->MonsterSay(SAY_VALIANT_AGGRO, LANG_UNIVERSAL, NULL); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth() + && pDoneBy->GetTypeId() == TYPEID_UNIT + && pDoneBy->GetVehicleKit() + && pDoneBy->GetVehicleKit()->GetPassenger(0)) + { + uiDamage = 0; + ((Player*)pDoneBy->GetVehicleKit()->GetPassenger(0))->KilledMonsterCredit(NPC_ARGENT_VALIANT_CREDIT); + m_creature->setFaction(35); + m_creature->ForcedDespawn(5000); + m_creature->SetCombatStartPosition(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ()); + CreatureCreatePos pos(m_creature->GetMap(), m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(), m_creature->GetPhaseMask()); + m_creature->SetSummonPoint(pos); + m_creature->MonsterSay(SAY_VALIANT_DEFEAT, LANG_UNIVERSAL, NULL); + pDoneBy->CastSpell(pDoneBy, 64892, true); + EnterEvadeMode(); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if(type != POINT_MOTION_TYPE) + return; + + if(m_creature->getVictim()) + { + if(!m_creature->IsWithinDistInMap(m_creature->getVictim(), 5) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25)) + CanCastRanged = true; + else + { + float X = m_creature->getVictim()->GetPositionX() + urand(7,11); + float Y = m_creature->getVictim()->GetPositionY() + urand(7,11); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(0.0f, X, Y, m_creature->getVictim()->GetPositionZ()); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (uiRangedActionTimer <= uiDiff) + { + if(!GoingRanged) + { + float X = m_creature->getVictim()->GetPositionX() + urand(7,11); + float Y = m_creature->getVictim()->GetPositionY() + urand(7,11); + GoingRanged = true; + + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(0.0f, X, Y, m_creature->getVictim()->GetPositionZ()); + } + + if(CanCastRanged) + { + uint32 radomspell = urand(0,1) ? SPELL_SHIELD_BREAKER : SPELL_CHARGE; + + if (DoCastSpellIfCan(m_creature->getVictim(), radomspell) == CAST_OK) + { + uiRangedActionTimer = urand(7000,12000); + GoingRanged = false; + CanCastRanged = false; + } + } + } else + uiRangedActionTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_argent_valiant(Creature* pCreature) +{ + return new npc_argent_valiantAI (pCreature); +} + + /*###### ## npc_scourge_conventor //quest 14107 ######*/ @@ -207,7 +532,10 @@ enum struct MANGOS_DLL_DECL npc_fallen_hero_spiritAI : public ScriptedAI { - npc_fallen_hero_spiritAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + npc_fallen_hero_spiritAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } uint32 m_uiStrike_Timer; @@ -246,7 +574,7 @@ struct MANGOS_DLL_DECL npc_fallen_hero_spiritAI : public ScriptedAI if (m_uiStrike_Timer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_STRIKE); + DoCastSpellIfCan(m_creature->getVictim(), SPELL_STRIKE); m_uiStrike_Timer = 10000; } else @@ -405,4 +733,30 @@ void AddSC_icecrown() pNewScript->Name = "npc_champions"; pNewScript->GetAI = &GetAI_npc_champions; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_argent_tournament_questgiver"; + pNewScript->pGossipHello = &GossipHello_npc_argent_tournament_questgiver; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_argent_tournament_requires_EAC"; + pNewScript->pGossipHello = &GossipHello_npc_argent_tournament_requires_EAC; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_rhydalla"; + pNewScript->pGossipHello = &GossipHello_npc_rhydalla; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_squire_david"; + pNewScript->pGossipHello = &GossipHello_npc_squire_david; + pNewScript->pGossipSelect = &GossipSelect_npc_squire_david; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_argent_valiant"; + pNewScript->GetAI = &GetAI_npc_argent_valiant; + pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp index 0385cd1817..d8ec0d2c8d 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp @@ -26,25 +26,22 @@ EndScriptData */ enum BossSpells { - //common - SPELL_BERSERK = 47008, - //yells - //summons - NPC_SOUL_FRAGMENT = 36535, - //Abilities - SPELL_MAGIC_BANE = 68793, - SPELL_CORRUPT_SOUL = 68839, - SPELL_CONSUME_SOUL = 68858, - SPELL_TELEPORT = 68988, - SPELL_SOULSTORM = 68872, - SPELL_SOULSTORM_2 = 68921, - SPELL_FEAR = 68950, - SPELL_SHADOW_BOLT = 70043, + //common + SPELL_BERSERK = 47008, + //Abilities + SPELL_MAGIC_BANE = 68793, + SPELL_CORRUPT_SOUL = 68839, + SPELL_CONSUME_SOUL = 68858, + SPELL_TELEPORT = 68988, + SPELL_SOULSTORM = 68872, + SPELL_SOULSTORM_2 = 68921, + SPELL_FEAR = 68950, + SPELL_SHADOW_BOLT = 70043, /*Music*/ - Battle01 = 6077, - Battle02 = 6078, - Battle03 = 6079, + Battle01 = 6077, + Battle02 = 6078, + Battle03 = 6079, }; @@ -63,33 +60,36 @@ struct MANGOS_DLL_DECL boss_bronjahmAI : public BSWScriptedAI void Reset() { - if(pInstance) pInstance->SetData(TYPE_BRONJAHM, NOT_STARTED); + if(pInstance) + pInstance->SetData(TYPE_BRONJAHM, NOT_STARTED); + resetTimers(); stage = 0; } void Aggro(Unit *who) { - Music = (urand(0, 2)); - switch(Music) - { - case 0: - m_creature->PlayDirectSound(Battle01); - BattleMusicTimer = 48000; - break; - case 1: - m_creature->PlayDirectSound(Battle02); - BattleMusicTimer = 27000; - break; - case 2: - m_creature->PlayDirectSound(Battle03); - BattleMusicTimer = 36000; - break; + Music = (urand(0, 2)); + switch(Music) + { + case 0: + m_creature->PlayDirectSound(Battle01); + BattleMusicTimer = 48000; + break; + case 1: + m_creature->PlayDirectSound(Battle02); + BattleMusicTimer = 27000; + break; + case 2: + m_creature->PlayDirectSound(Battle03); + BattleMusicTimer = 36000; + break; } if(pInstance) pInstance->SetData(TYPE_BRONJAHM, IN_PROGRESS); DoScriptText(-1632001,m_creature,who); - SetCombatMovement(true); + + SetCombatMovement(true); } void JustDied(Unit *killer) @@ -101,14 +101,15 @@ struct MANGOS_DLL_DECL boss_bronjahmAI : public BSWScriptedAI void KilledUnit(Unit* pVictim) { - switch (urand(0,1)) { - case 0: - DoScriptText(-1632002,m_creature,pVictim); - break; - case 1: - DoScriptText(-1632003,m_creature,pVictim); - break; - }; + switch (urand(0,1)) + { + case 0: + DoScriptText(-1632002,m_creature,pVictim); + break; + case 1: + DoScriptText(-1632003,m_creature,pVictim); + break; + } } void UpdateAI(const uint32 diff) @@ -119,61 +120,67 @@ struct MANGOS_DLL_DECL boss_bronjahmAI : public BSWScriptedAI switch(stage) { case 0: - if (timedQuery(SPELL_CORRUPT_SOUL, diff)) + if (timedQuery(SPELL_CORRUPT_SOUL, diff)) + { + if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if (doCast(SPELL_CORRUPT_SOUL, pTarget) == CAST_OK) { - if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (doCast(SPELL_CORRUPT_SOUL, pTarget) == CAST_OK) - { - DoScriptText(-1632006,m_creature,pTarget); - float fPosX, fPosY, fPosZ; - pTarget->GetPosition(fPosX, fPosY, fPosZ); - doSummon(NPC_SOUL_FRAGMENT,fPosX, fPosY, fPosZ); - } - } + DoScriptText(-1632006,m_creature,pTarget); + float fPosX, fPosY, fPosZ; + pTarget->GetPosition(fPosX, fPosY, fPosZ); + doSummon(NPC_CORRUPTED_SOUL_FRAGMENT,fPosX, fPosY, fPosZ); } - break; + } + } + break; case 1: - if (timedCast(SPELL_TELEPORT, diff) == CAST_OK) stage = 2; - break; + if (timedCast(SPELL_TELEPORT, diff) == CAST_OK) + stage = 2; + + break; case 2: - if (timedCast(SPELL_SOULSTORM, diff) == CAST_OK) { - DoScriptText(-1632005,m_creature); - SetCombatMovement(false); - stage = 3; - } - break; + if (timedCast(SPELL_SOULSTORM, diff) == CAST_OK) + { + DoScriptText(-1632005,m_creature); + SetCombatMovement(false); + stage = 3; + } + + break; case 3: - timedCast(SPELL_FEAR, diff); - break; + timedCast(SPELL_FEAR, diff); + break; } timedCast(SPELL_SHADOW_BOLT, diff); timedCast(SPELL_MAGIC_BANE, diff); - if (m_creature->GetHealthPercent() <= 30.0f && stage == 0) stage = 1; + if (m_creature->GetHealthPercent() <= 30.0f && stage == 0) + stage = 1; DoMeleeAttackIfReady(); if (BattleMusicTimer < diff && m_creature->isAlive()) { - switch(Music) - { - case 0: - m_creature->PlayDirectSound(Battle01); - BattleMusicTimer = 49000; - break; - case 1: - m_creature->PlayDirectSound(Battle02); - BattleMusicTimer = 28000; - break; - case 2: - m_creature->PlayDirectSound(Battle03); - BattleMusicTimer = 37000; - break; + switch(Music) + { + case 0: + m_creature->PlayDirectSound(Battle01); + BattleMusicTimer = 49000; + break; + case 1: + m_creature->PlayDirectSound(Battle02); + BattleMusicTimer = 28000; + break; + case 2: + m_creature->PlayDirectSound(Battle03); + BattleMusicTimer = 37000; + break; } - } else BattleMusicTimer -= diff; + } + else BattleMusicTimer -= diff; } }; @@ -191,22 +198,22 @@ struct MANGOS_DLL_DECL mob_soul_fragmentAI : public ScriptedAI void Reset() { m_uiRangeCheck_Timer = 1000; - if (!m_pInstance) return; + if (!m_pInstance) + return; + Creature* pBoss = m_pInstance->GetSingleCreatureFromStorage(NPC_BRONJAHM); m_creature->SetSpeedRate(MOVE_RUN, 0.2f); + if (Creature* pBoss = m_pInstance->GetSingleCreatureFromStorage(NPC_BRONJAHM)) m_creature->GetMotionMaster()->MoveChase(pBoss); - m_creature->SetRespawnDelay(DAY); - } - void AttackStart(Unit* pWho) - { - return; + m_creature->SetRespawnDelay(DAY); } void UpdateAI(const uint32 uiDiff) { - if (!m_pInstance || m_pInstance->GetData(TYPE_BRONJAHM) != IN_PROGRESS ) m_creature->ForcedDespawn(); + if (!m_pInstance || m_pInstance->GetData(TYPE_BRONJAHM) != IN_PROGRESS) + m_creature->ForcedDespawn(); if (m_uiRangeCheck_Timer < uiDiff) { @@ -215,8 +222,10 @@ struct MANGOS_DLL_DECL mob_soul_fragmentAI : public ScriptedAI if (pBoss->IsWithinDistInMap(m_creature, 2.0f)) { pBoss->CastSpell(pBoss, SPELL_CONSUME_SOUL, false); + m_pInstance->OnCreatureDeath(m_creature); m_creature->ForcedDespawn(); - } else m_creature->GetMotionMaster()->MoveChase(pBoss); + } + else m_creature->GetMotionMaster()->MoveChase(pBoss); } else m_creature->ForcedDespawn(); diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp index 514f12e3e9..5e72f7faf3 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp @@ -27,25 +27,25 @@ EndScriptData */ enum { - SAY_JAINA_FS01 = -1632040, - SAY_JAINA_FS02 = -1632041, - SAY_JAINA_FS03 = -1632042, - SAY_JAINA_FS04 = -1632043, - SAY_JAINA_FS05 = -1632044, - SAY_JAINA_FS06 = -1632045, - SAY_JAINA_FS07 = -1632046, - SAY_JAINA_FS08 = -1632047, - SAY_JAINA_FS09_EXTRO = -1632029, - - SAY_SYLVANA_FS01 = -1632050, - SAY_SYLVANA_FS02 = -1632051, - SAY_SYLVANA_FS03 = -1632052, - SAY_SYLVANA_FS04 = -1632053, - SAY_SYLVANA_FS05 = -1632054, - SAY_SYLVANA_FS06 = -1632055, - SAY_SYLVANA_FS07_EXTRO = -1632030, - - GOSSIP_SPEECHINTRO = 13525, + SAY_JAINA_FS01 = -1632040, + SAY_JAINA_FS02 = -1632041, + SAY_JAINA_FS03 = -1632042, + SAY_JAINA_FS04 = -1632043, + SAY_JAINA_FS05 = -1632044, + SAY_JAINA_FS06 = -1632045, + SAY_JAINA_FS07 = -1632046, + SAY_JAINA_FS08 = -1632047, + SAY_JAINA_FS09_EXTRO = -1632029, + + SAY_SYLVANA_FS01 = -1632050, + SAY_SYLVANA_FS02 = -1632051, + SAY_SYLVANA_FS03 = -1632052, + SAY_SYLVANA_FS04 = -1632053, + SAY_SYLVANA_FS05 = -1632054, + SAY_SYLVANA_FS06 = -1632055, + SAY_SYLVANA_FS07_EXTRO = -1632030, + + GOSSIP_SPEECHINTRO = 13525, }; struct MANGOS_DLL_DECL npc_jaina_and_sylvana_FSintroAI : public ScriptedAI @@ -57,159 +57,182 @@ struct MANGOS_DLL_DECL npc_jaina_and_sylvana_FSintroAI : public ScriptedAI Reset(); } -ScriptedInstance* m_pInstance; + ScriptedInstance* m_pInstance; -uint32 StepTimer; -uint32 Step; -bool StartEvent; + uint32 m_uiStepTimer; + uint32 m_uiStep; + bool m_bStartEvent; void Reset() { - if(m_pInstance) - if(m_pInstance->GetData(TYPE_DEVOURER_OF_SOULS) == DONE) - m_creature->SetVisibility(VISIBILITY_OFF); + if(m_pInstance) + { + if(m_pInstance->GetData(TYPE_DEVOURER_OF_SOULS) == DONE) + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - Step = 0; - StepTimer = 100; + m_uiStep = 0; + m_uiStepTimer = 100; + if(m_pInstance->GetData(TYPE_INTRO) == DONE) { m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - Step = 8; + m_uiStep = 8; } + } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { DoMeleeAttackIfReady(); - if(!m_pInstance) return; + if(!m_pInstance) + return; - if(StartEvent != true) return; + if(m_bStartEvent != true) + return; - if(StepTimer < diff) - { - switch(Step) - { + if(m_uiStepTimer < uiDiff) + { + switch(m_uiStep) + { case 0: m_pInstance->SetData(TYPE_INTRO, DONE); m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS01, m_creature); - StepTimer = 7000; - } + m_uiStepTimer = 7000; + } + if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - StepTimer = 100; - ++Step; + m_uiStepTimer = 100; + + ++m_uiStep; break; case 1: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS02, m_creature); - StepTimer = 9000; - } + m_uiStepTimer = 9000; + } + if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - { + { DoScriptText(SAY_SYLVANA_FS01, m_creature); - StepTimer = 12000; - } - ++Step; + m_uiStepTimer = 12000; + } + + ++m_uiStep; break; case 2: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS03, m_creature); - StepTimer = 8000; - } + m_uiStepTimer = 8000; + } if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - { + { DoScriptText(SAY_SYLVANA_FS02, m_creature); - StepTimer = 11000; - } - ++Step; + m_uiStepTimer = 11000; + } + + ++m_uiStep; break; case 3: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS04, m_creature); - StepTimer = 10000; - } + m_uiStepTimer = 10000; + } + if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - { + { DoScriptText(SAY_SYLVANA_FS03, m_creature); - StepTimer = 11000; - } - ++Step; + m_uiStepTimer = 11000; + } + + ++m_uiStep; break; case 4: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS05, m_creature); - StepTimer = 8000; - } + m_uiStepTimer = 8000; + } + if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - { + { DoScriptText(SAY_SYLVANA_FS04, m_creature); - StepTimer = 12000; - } - ++Step; + m_uiStepTimer = 12000; + } + + ++m_uiStep; break; case 5: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS06, m_creature); - StepTimer = 12000; - } + m_uiStepTimer = 12000; + } + if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - { + { DoScriptText(SAY_SYLVANA_FS05, m_creature); - StepTimer = 7000; - } - ++Step; + m_uiStepTimer = 7000; + } + + ++m_uiStep; break; case 6: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS07, m_creature); - StepTimer = 7000; - } + m_uiStepTimer = 7000; + } + if(m_creature->GetEntry() == NPC_SILVANA_BEGIN) - { + { DoScriptText(SAY_SYLVANA_FS06, m_creature); - StepTimer = 4000; - } - ++Step; + m_uiStepTimer = 4000; + } + + ++m_uiStep; break; case 7: if(m_creature->GetEntry() == NPC_JAINA_BEGIN ) - { + { DoScriptText(SAY_JAINA_FS08, m_creature); - StepTimer = 5000; - } - ++Step; + m_uiStepTimer = 5000; + } + + ++m_uiStep; break; - } - } else StepTimer -= diff; + } + } + else m_uiStepTimer -= uiDiff; } }; bool GossipHello_npc_jaina_and_sylvana_FSintro(Player* pPlayer, Creature* pCreature) { - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu( pCreature->GetObjectGuid()); - switch(pCreature->GetEntry()) - { - case 37597: - if(((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->StartEvent != true) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What would you have of me, My Lady?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - break; - case 37596: - if(((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->StartEvent != true) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What would you have of me, Banshee Queen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - break; - } + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + switch(pCreature->GetEntry()) + { + case 37597: + if(((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->m_bStartEvent != true) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What would you have of me, My Lady?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + break; + case 37596: + if(((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->m_bStartEvent != true) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What would you have of me, Banshee Queen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + break; + } pPlayer->PlayerTalkClass->SendGossipMenu(907,pCreature->GetObjectGuid()); //907 return true; @@ -218,7 +241,7 @@ bool GossipHello_npc_jaina_and_sylvana_FSintro(Player* pPlayer, Creature* pCreat bool GossipSelect_npc_jaina_and_sylvana_FSintro(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { pPlayer->CLOSE_GOSSIP_MENU(); - ((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->StartEvent = true; + ((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->m_bStartEvent = true; return true; } @@ -232,76 +255,76 @@ struct MANGOS_DLL_DECL npc_jaina_and_sylvana_FSextroAI : public ScriptedAI Reset(); } -ScriptedInstance* m_pInstance; + ScriptedInstance* m_pInstance; -uint32 StepTimer; -uint32 Step; -uint64 m_uiLiderGUID; -uint32 uiSummon_counter; + uint32 m_uiStepTimer; + uint32 m_uiStep; + uint32 uiSummon_counter; void Reset() { - if (m_pInstance) - if (m_pInstance->GetData(TYPE_DEVOURER_OF_SOULS) != DONE) - { - m_pInstance->SetData(TYPE_DEVOURER_OF_SOULS, NOT_STARTED); - Step = 0; - m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } else Step = 10; - StepTimer = 100; - m_creature->SetVisibility(VISIBILITY_OFF); + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_DEVOURER_OF_SOULS) != DONE) + { + m_pInstance->SetData(TYPE_DEVOURER_OF_SOULS, NOT_STARTED); + m_uiStep = 0; + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + else m_uiStep = 10; + } + m_uiStepTimer = 100; + m_creature->SetVisibility(VISIBILITY_OFF); } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { DoMeleeAttackIfReady(); - if (!m_pInstance) return; + if (!m_pInstance) + return; if (m_pInstance->GetData(TYPE_DEVOURER_OF_SOULS) == DONE) { - - if(StepTimer < diff) - { - switch(Step) - { - case 0: - m_creature->SetVisibility(VISIBILITY_ON); - m_creature->SetWalk(false); - m_creature->GetMotionMaster()->MovePoint(0, 5653.337f, 2496.407f, 708.829f); - uiSummon_counter = 0; - StepTimer = 400; - ++Step; - break; - case 1: - break; - case 2: - break; - case 3: - break; - case 4: - if(m_creature->GetEntry() == NPC_JAINA_END) - { - DoScriptText(SAY_JAINA_FS09_EXTRO, m_creature); - StepTimer = 6000; - } - if(m_creature->GetEntry() == NPC_SILVANA_END) - { - DoScriptText(SAY_SYLVANA_FS07_EXTRO, m_creature); - StepTimer = 3000; - } - ++Step; - break; - case 5: - m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - ++Step; - break; - } - } else StepTimer -= diff; - } - return; + if(m_uiStepTimer < uiDiff) + { + switch(m_uiStep) + { + case 0: + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->SetWalk(false); + m_creature->GetMotionMaster()->MovePoint(0, 5653.337f, 2496.407f, 708.829f); + uiSummon_counter = 0; + m_uiStepTimer = 400; + ++m_uiStep; + break; + case 1: + case 2: + case 3: + break; + case 4: + if(m_creature->GetEntry() == NPC_JAINA_END) + { + DoScriptText(SAY_JAINA_FS09_EXTRO, m_creature); + m_uiStepTimer = 6000; + } + if(m_creature->GetEntry() == NPC_SILVANA_END) + { + DoScriptText(SAY_SYLVANA_FS07_EXTRO, m_creature); + m_uiStepTimer = 3000; + } + ++m_uiStep; + break; + case 5: + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + ++m_uiStep; + break; + } + } + else m_uiStepTimer -= uiDiff; + } } }; diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.h b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.h index 4813a31a03..b9ab4caa78 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.h +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.h @@ -14,8 +14,6 @@ enum TYPE_DEVOURER_OF_SOULS = 2, TYPE_ACHIEV_PHANTOM_BLAST = 3, - DATA_SOULFRAGMENT_REMOVE = 4, // on Death and on Use - NPC_BRONJAHM = 36497, NPC_DEVOURER_OF_SOULS = 36502, NPC_CORRUPTED_SOUL_FRAGMENT = 36535, @@ -99,10 +97,10 @@ class MANGOS_DLL_DECL instance_forge_of_souls : public ScriptedInstance void Initialize(); void OnCreatureCreate(Creature* pCreature); + void OnCreatureDeath(Creature* pCreature); void SetData(uint32 uiType, uint32 uiData); uint32 GetData(uint32 uiType); - void SetData64(uint32 uiType, uint64 uiData); void OnPlayerEnter(Player* pPlayer); void ProcessEventNpcs(Player* pPlayer, bool bChanged); diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp index 243f1a7c7e..209e3c8cf7 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp @@ -51,6 +51,16 @@ void instance_forge_of_souls::OnCreatureCreate(Creature* pCreature) } } +void instance_forge_of_souls::OnCreatureDeath(Creature* pCreature) +{ + switch (pCreature->GetEntry()) + { + case NPC_CORRUPTED_SOUL_FRAGMENT: + m_luiSoulFragmentAliveGUIDs.remove(pCreature->GetObjectGuid()); + break; + } +} + void instance_forge_of_souls::OnPlayerEnter(Player* pPlayer) { if (!m_uiTeam) // very first player to enter @@ -192,12 +202,6 @@ uint32 instance_forge_of_souls::GetData(uint32 uiType) } } -void instance_forge_of_souls::SetData64(uint32 uiType, uint64 uiData) -{ - if (uiType == DATA_SOULFRAGMENT_REMOVE) - m_luiSoulFragmentAliveGUIDs.remove(ObjectGuid(uiData)); -} - InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) { return new instance_forge_of_souls(pMap); diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp index 332bc252f9..767923c3f2 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp @@ -152,4 +152,4 @@ void AddSC_icecrown_teleporter() newscript->Name = "go_frostwing_sigil"; newscript->pGOUse = &GOHello_go_frostwing_sigil; newscript->RegisterSelf(); -} +} \ No newline at end of file diff --git a/scripts/northrend/naxxramas/boss_anubrekhan.cpp b/scripts/northrend/naxxramas/boss_anubrekhan.cpp index 552baf4576..79c910dd51 100644 --- a/scripts/northrend/naxxramas/boss_anubrekhan.cpp +++ b/scripts/northrend/naxxramas/boss_anubrekhan.cpp @@ -50,8 +50,9 @@ enum SPELL_SELF_SPAWN_5 = 29105, //This spawns 5 corpse scarabs ontop of us (most likely the pPlayer casts this on death) SPELL_SELF_SPAWN_10 = 28864, //This is used by the crypt guards when they die - - NPC_CRYPT_GUARD = 16573 + + NPC_CRYPT_GUARD = 16573, + CORPSE_SCARAB = 16698 }; struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI @@ -83,7 +84,8 @@ struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI { //Force the player to spawn corpse scarabs via spell if (pVictim->GetTypeId() == TYPEID_PLAYER) - pVictim->CastSpell(pVictim, SPELL_SELF_SPAWN_5, true); + for(uint8 t=0 ; t<5 ; t++) + m_creature->SummonCreature(CORPSE_SCARAB, pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); if (urand(0, 4)) return; @@ -99,6 +101,11 @@ struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI case 1: DoScriptText(SAY_AGGRO2, m_creature); break; case 2: DoScriptText(SAY_AGGRO3, m_creature); break; } + + for(uint8 i = 0; i < (m_bIsRegularMode ? 1 : 2); i++) + { + DoSpawnCreature(NPC_CRYPT_GUARD, 0, 5, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + } if (m_pInstance) m_pInstance->SetData(TYPE_ANUB_REKHAN, IN_PROGRESS); @@ -115,6 +122,15 @@ struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_ANUB_REKHAN, FAIL); } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_CRYPT_GUARD) + { + for(uint8 t=0 ; t<5 ; t++) + m_creature->SummonCreature(CORPSE_SCARAB, pSummoned->GetPositionX()+urand(0,5), pSummoned->GetPositionY()+urand(0,5), pSummoned->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + } + } void MoveInLineOfSight(Unit* pWho) { @@ -146,7 +162,7 @@ struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI // Do NOT cast it when we are afflicted by locust swarm if (!m_creature->HasAura(SPELL_LOCUSTSWARM) && !m_creature->HasAura(SPELL_LOCUSTSWARM_H)) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H); } @@ -159,6 +175,7 @@ struct MANGOS_DLL_DECL boss_anubrekhanAI : public ScriptedAI if (m_uiLocustSwarmTimer < uiDiff) { DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_LOCUSTSWARM :SPELL_LOCUSTSWARM_H); + DoSpawnCreature(NPC_CRYPT_GUARD, 0, 5, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); m_uiLocustSwarmTimer = 90000; } else diff --git a/scripts/northrend/naxxramas/boss_faerlina.cpp b/scripts/northrend/naxxramas/boss_faerlina.cpp index e0ab9a6f27..4d46acd625 100644 --- a/scripts/northrend/naxxramas/boss_faerlina.cpp +++ b/scripts/northrend/naxxramas/boss_faerlina.cpp @@ -47,6 +47,8 @@ enum SPELL_RAIN_OF_FIRE_H = 54099, SPELL_WIDOWS_EMBRACE = 28732, SPELL_WIDOWS_EMBRACE_H = 54097, + SPELL_FIREBALL = 54095, + SPELL_FIREBALL_H = 54096, }; struct MANGOS_DLL_DECL boss_faerlinaAI : public ScriptedAI @@ -133,6 +135,7 @@ struct MANGOS_DLL_DECL boss_faerlinaAI : public ScriptedAI m_uiEnrageTimer = 60000; m_creature->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_ENRAGE : SPELL_ENRAGE_H); + pCaster->DealDamage(pCaster, pCaster->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); bIsFrenzyRemove = true; } @@ -194,6 +197,64 @@ CreatureAI* GetAI_boss_faerlina(Creature* pCreature) return new boss_faerlinaAI(pCreature); } +struct MANGOS_DLL_DECL mob_worshipperAI : public ScriptedAI +{ + mob_worshipperAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (instance_naxxramas*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + instance_naxxramas* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiFireballTimer; + bool m_bHasTaunted; + + void Reset() + { + m_uiFireballTimer = 5000; + } + + void JustDied(Unit* pKiller) + { + if(m_pInstance && m_bIsRegularMode) + { + if (Creature* pFaerlina = m_pInstance->GetSingleCreatureFromStorage(NPC_FAERLINA)) + { + pFaerlina->RemoveAurasDueToSpell(SPELL_ENRAGE); + pFaerlina->CastSpell(pFaerlina, m_bIsRegularMode ? SPELL_WIDOWS_EMBRACE : SPELL_WIDOWS_EMBRACE_H, true); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + // Only if not charmed + if(!m_creature->isCharmed()) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiFireballTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H); + m_uiFireballTimer = 4000 + urand(0,1000); + } + else + m_uiFireballTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_worshipper(Creature* pCreature) +{ + return new mob_worshipperAI(pCreature); +} + void AddSC_boss_faerlina() { Script* pNewScript; @@ -202,4 +263,9 @@ void AddSC_boss_faerlina() pNewScript->Name = "boss_faerlina"; pNewScript->GetAI = &GetAI_boss_faerlina; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "mob_worshipper"; + pNewScript->GetAI = &GetAI_mob_worshipper; + pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/boss_four_horsemen.cpp b/scripts/northrend/naxxramas/boss_four_horsemen.cpp index e87301195f..682d864dfc 100644 --- a/scripts/northrend/naxxramas/boss_four_horsemen.cpp +++ b/scripts/northrend/naxxramas/boss_four_horsemen.cpp @@ -28,7 +28,7 @@ enum { //all horsemen SPELL_SHIELDWALL = 29061, - SPELL_BESERK = 26662, + SPELL_BERSERK = 26662, //lady blaumeux SAY_BLAU_AGGRO = -1533044, @@ -39,14 +39,12 @@ enum SAY_BLAU_SLAY = -1533049, SAY_BLAU_DEATH = -1533050, - EMOTE_UNYIELDING_PAIN = -1533156, // NYI - SPELL_MARK_OF_BLAUMEUX = 28833, SPELL_UNYILDING_PAIN = 57381, SPELL_VOIDZONE = 28863, - SPELL_VOIDZONE_H = 57463, + H_SPELL_VOIDZONE = 57463, SPELL_SHADOW_BOLT = 57374, - SPELL_SHADOW_BOLT_H = 57464, + H_SPELL_SHADOW_BOLT = 57464, //baron rivendare SAY_RIVE_AGGRO1 = -1533065, @@ -62,7 +60,7 @@ enum SPELL_MARK_OF_RIVENDARE = 28834, SPELL_UNHOLY_SHADOW = 28882, - SPELL_UNHOLY_SHADOW_H = 57369, + H_SPELL_UNHOLY_SHADOW = 57369, //thane korthazz SAY_KORT_AGGRO = -1533051, @@ -74,8 +72,11 @@ enum SAY_KORT_DEATH = -1533057, SPELL_MARK_OF_KORTHAZZ = 28832, - SPELL_METEOR = 26558, // m_creature->getVictim() auto-area spell but with a core problem - +/* + SPELL_METEOR = 26558, + H_SPELL_METEOR = 57467,*/ + SPELL_METEOR = 26553, // spell dbc hack + H_SPELL_METEOR = 57451, // spell dbc hack //sir zeliek SAY_ZELI_AGGRO = -1533058, SAY_ZELI_TAUNT1 = -1533059, @@ -85,13 +86,12 @@ enum SAY_ZELI_SLAY = -1533063, SAY_ZELI_DEATH = -1533064, - EMOTE_CONDEMATION = -1533157, // NYI - SPELL_MARK_OF_ZELIEK = 28835, SPELL_HOLY_WRATH = 28883, - SPELL_HOLY_WRATH_H = 57466, + H_SPELL_HOLY_WRATH = 57466, SPELL_HOLY_BOLT = 57376, - SPELL_HOLY_BOLT_H = 57465, + H_SPELL_HOLY_BOLT = 57465, + SPELL_CONDEMNATION = 57377, // horseman spirits NPC_SPIRIT_OF_BLAUMEUX = 16776, @@ -100,26 +100,251 @@ enum NPC_SPIRIT_OF_ZELIREK = 16777 }; -struct MANGOS_DLL_DECL boss_lady_blaumeuxAI : public ScriptedAI +/*walk coords*/ +#define WALKX_KORT 2462.112f +#define WALKY_KORT -2956.598f +#define WALKZ_KORT 241.276f + +#define WALKX_BLAU 2529.108f +#define WALKY_BLAU -3015.303f +#define WALKZ_BLAU 241.32f + +#define WALKX_ZELI 2579.571f +#define WALKY_ZELI -2960.945f +#define WALKZ_ZELI 241.32f + +#define WALKX_RIVE 2521.039f +#define WALKY_RIVE -2891.633f +#define WALKZ_RIVE 241.276f + +#define HIGH_THREAT 50.0f + +struct MANGOS_DLL_DECL boss_horsemen_commonAI : public ScriptedAI { - boss_lady_blaumeuxAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + boss_horsemen_commonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + memset(&m_auiHorsemenGUIDs, 0, sizeof(m_auiHorsemenGUIDs)); + + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + ObjectGuid m_auiHorsemenGUIDs[4]; + + bool Move_Check; + bool Attack_Check; + bool ShieldWall1; + bool ShieldWall2; + uint32 Berserk_Timer; + + void Reset() + { + ShieldWall1 = true; + ShieldWall2 = true; + Move_Check = true; + Attack_Check = true; + Berserk_Timer = 15*100*IN_MILLISECONDS; + SetCombatMovement(true); + + m_creature->SetWalk(false); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AcquireGUIDs() + { + if (!m_pInstance) + return; + + m_auiHorsemenGUIDs[0] = m_pInstance->GetSingleCreatureFromStorage(NPC_ZELIEK)->GetObjectGuid(); + m_auiHorsemenGUIDs[1] = m_pInstance->GetSingleCreatureFromStorage(NPC_THANE)->GetObjectGuid(); + m_auiHorsemenGUIDs[2] = m_pInstance->GetSingleCreatureFromStorage(NPC_BLAUMEUX)->GetObjectGuid(); + m_auiHorsemenGUIDs[3] = m_pInstance->GetSingleCreatureFromStorage(NPC_RIVENDARE)->GetObjectGuid(); + } + + Unit *PickNearestPlayer() + { + Unit *nearp = NULL; + float neardist = 0.0f; + + ThreatList const& vThreatList = m_creature->getThreatManager().getThreatList(); + if (vThreatList.empty()) + return NULL; + + for (ThreatList::const_iterator itr = vThreatList.begin();itr != vThreatList.end(); ++itr) + { + if (Player* pUnit = m_creature->GetMap()->GetPlayer((*itr)->getUnitGuid())) + { + float pudist = pUnit->GetDistance((const Creature *)m_creature); + if (!nearp || (neardist > pudist)) + { + nearp = pUnit; + neardist = pudist; + } + } + } + + return nearp; + } + + void Cast(int32 spellId1,int32 spellId2) + { + if (Unit* pTarget = PickNearestPlayer()) + { + AttackStart(pTarget); + if (pTarget->IsWithinDist(m_creature, 40.0f)) + DoCastSpellIfCan(pTarget, spellId1); + else if (spellId2) + DoCastSpellIfCan(m_creature, spellId2, CAST_TRIGGERED); + } + } + + void CheckPosition(float x, float y, float z) + { + //run on aggro + if (m_creature->getVictim() && Move_Check) + { + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovePoint(0, x, y, z); + Move_Check = false; + return; + } + //when reach position, set possible to attack + if ((m_creature->GetDistance2d(x, y) <= 10.0f) && Attack_Check) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if ((m_creature->GetObjectGuid() == m_auiHorsemenGUIDs[3]) ||(m_creature->GetObjectGuid() == m_auiHorsemenGUIDs[1])) + { + SetCombatMovement(true); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + if ((m_creature->GetObjectGuid() == m_auiHorsemenGUIDs[0]) ||(m_creature->GetObjectGuid() == m_auiHorsemenGUIDs[2])) + SetCombatMovement(false); + Attack_Check = false; + } + } + + void JustReachedHome() + { + for (uint8 i = 0; i < 4; ++i) + { + if (Creature* pCreature = m_creature->GetMap()->GetCreature(m_auiHorsemenGUIDs[i])) + { + if (pCreature == m_creature) + continue; // skip this + + if (!pCreature->isAlive()) + pCreature->Respawn(); + else if (pCreature->isInCombat()) + pCreature->AI()->EnterEvadeMode(); + } + } + + if (m_pInstance && m_pInstance->GetData(TYPE_FOUR_HORSEMEN) == IN_PROGRESS) + m_pInstance->SetData(TYPE_FOUR_HORSEMEN, NOT_STARTED); + } + + void Aggro(Unit *who) + { + AcquireGUIDs(); + + for (uint8 i = 0; i < 4; i++) // respawn other horsemen if needed + if (Creature * pHorseM = m_creature->GetMap()->GetCreature(m_auiHorsemenGUIDs[i])) + if ((pHorseM != m_creature) && !(pHorseM->isAlive())) + pHorseM->Respawn(); + + if (m_pInstance && m_pInstance->GetData(TYPE_FOUR_HORSEMEN) != IN_PROGRESS) + m_pInstance->SetData(TYPE_FOUR_HORSEMEN, IN_PROGRESS); + + m_creature->AddThreat(who, HIGH_THREAT); + m_creature->CallForHelp(100.0f); + } + + void JustDied(Unit* Killer) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_FOUR_HORSEMEN, SPECIAL); + + if (m_pInstance && m_pInstance->GetData(TYPE_FOUR_HORSEMEN) == SPECIAL) + { + bool horsemanDone = true; + for (uint8 i = 0; i < 4; ++i) + { + if (Creature* pCreature = m_creature->GetMap()->GetCreature(m_auiHorsemenGUIDs[i])) + { + if (pCreature == m_creature) + continue; // skip this + + if (pCreature->isAlive()) + { + horsemanDone = false; + break; + } + } + } + if (horsemanDone) + m_pInstance->SetData(TYPE_FOUR_HORSEMEN, DONE); + } + } + + void UpdateAI(const uint32 uiDiff) + { + // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds + if (ShieldWall1 && (m_creature->GetHealthPercent() < 50.0f)) + { + DoCastSpellIfCan(m_creature, SPELL_SHIELDWALL, CAST_INTERRUPT_PREVIOUS); + ShieldWall1 = false; + } + + if (ShieldWall2 && (m_creature->GetHealthPercent() < 20.0f)) + { + DoCastSpellIfCan(m_creature, SPELL_SHIELDWALL, CAST_INTERRUPT_PREVIOUS); + ShieldWall2 = false; + } + if (Berserk_Timer < uiDiff) + { + if (!m_creature->HasAura(SPELL_BERSERK)) + DoCast(m_creature, SPELL_BERSERK, true); + + Berserk_Timer = 5000; + } + else + Berserk_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } + +}; + +struct MANGOS_DLL_DECL boss_lady_blaumeuxAI : public boss_horsemen_commonAI +{ + boss_lady_blaumeuxAI(Creature* pCreature) : boss_horsemen_commonAI(pCreature) + { + Reset(); + } + + uint32 Cast_Timer; uint32 Mark_Timer; uint32 VoidZone_Timer; - bool ShieldWall1; - bool ShieldWall2; void Reset() { + boss_horsemen_commonAI::Reset(); Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. VoidZone_Timer = 12000; // right - ShieldWall1 = true; - ShieldWall2 = true; + Cast_Timer = 9000; } - void Aggro(Unit *who) + void Aggro(Unit *pWho) { - DoScriptText(SAY_BLAU_AGGRO, m_creature); + DoScriptText(SAY_BLAU_AGGRO, m_creature); + boss_horsemen_commonAI::Aggro(pWho); } void KilledUnit(Unit* Victim) @@ -129,7 +354,8 @@ struct MANGOS_DLL_DECL boss_lady_blaumeuxAI : public ScriptedAI void JustDied(Unit* Killer) { - DoScriptText(SAY_BLAU_DEATH, m_creature); + DoScriptText(SAY_BLAU_DEATH, m_creature); + boss_horsemen_commonAI::JustDied(Killer); } void UpdateAI(const uint32 uiDiff) @@ -137,40 +363,43 @@ struct MANGOS_DLL_DECL boss_lady_blaumeuxAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + CheckPosition(WALKX_BLAU, WALKY_BLAU, WALKZ_BLAU); + + // won't attack before reaching the corner + if (Attack_Check) + return; + // Mark of Blaumeux if (Mark_Timer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_MARK_OF_BLAUMEUX); - Mark_Timer = 12000; - }else Mark_Timer -= uiDiff; - - // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds - if (ShieldWall1 && m_creature->GetHealthPercent() < 50.0f) - { - if (ShieldWall1) - { - DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); - ShieldWall1 = false; - } + DoCast(m_creature->getVictim(), SPELL_MARK_OF_BLAUMEUX, true); + Mark_Timer = 15000; } - if (ShieldWall2 && m_creature->GetHealthPercent() < 20.0f) + else + Mark_Timer -= uiDiff; + + if (Cast_Timer < uiDiff) { - if (ShieldWall2) - { - DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); - ShieldWall2 = false; - } + boss_horsemen_commonAI::Cast(m_bIsRegularMode ? SPELL_SHADOW_BOLT : H_SPELL_SHADOW_BOLT, SPELL_UNYILDING_PAIN); + Cast_Timer = 2100; } + else + Cast_Timer -= uiDiff; // Void Zone if (VoidZone_Timer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_VOIDZONE); - VoidZone_Timer = 12000; - }else VoidZone_Timer -= uiDiff; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_VOIDZONE : H_SPELL_VOIDZONE, CAST_INTERRUPT_PREVIOUS); + VoidZone_Timer = 12000; + } + } + else + VoidZone_Timer -= uiDiff; - DoMeleeAttackIfReady(); - } + boss_horsemen_commonAI::UpdateAI(uiDiff); + } }; CreatureAI* GetAI_boss_lady_blaumeux(Creature* pCreature) @@ -178,15 +407,108 @@ CreatureAI* GetAI_boss_lady_blaumeux(Creature* pCreature) return new boss_lady_blaumeuxAI(pCreature); } -struct MANGOS_DLL_DECL boss_rivendare_naxxAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_sir_zeliekAI : public boss_horsemen_commonAI { - boss_rivendare_naxxAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + boss_sir_zeliekAI(Creature* pCreature) : boss_horsemen_commonAI(pCreature) + { + Reset(); + } + + uint32 Mark_Timer; + uint32 HolyWrath_Timer; + uint32 Cast_Timer; void Reset() { + boss_horsemen_commonAI::Reset(); + Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. + HolyWrath_Timer = 12000; // right + Cast_Timer = 9000; } - void Aggro(Unit *who) + void Aggro(Unit *pWho) + { + DoScriptText(SAY_ZELI_AGGRO, m_creature); + boss_horsemen_commonAI::Aggro(pWho); + } + + void KilledUnit(Unit* Victim) + { + DoScriptText(SAY_ZELI_SLAY, m_creature); + } + + void JustDied(Unit* Killer) + { + DoScriptText(SAY_ZELI_DEATH, m_creature); + boss_horsemen_commonAI::JustDied(Killer); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + CheckPosition(WALKX_ZELI, WALKY_ZELI, WALKZ_ZELI); + + // won't attack before reaching the corner + if (Attack_Check) + return; + + // Mark of Zeliek + if (Mark_Timer < uiDiff) + { + DoCast(m_creature->getVictim(),SPELL_MARK_OF_ZELIEK, true); + Mark_Timer = 15000; + } + else + Mark_Timer -= uiDiff; + + // Cast + if (Cast_Timer < uiDiff) + { + Cast(m_bIsRegularMode ? SPELL_HOLY_BOLT : H_SPELL_HOLY_BOLT, SPELL_CONDEMNATION); + Cast_Timer = 2100; + } + else + Cast_Timer -= uiDiff; + + // Holy Wrath + if (HolyWrath_Timer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(),m_bIsRegularMode ? SPELL_HOLY_WRATH : H_SPELL_HOLY_WRATH, CAST_INTERRUPT_PREVIOUS); + HolyWrath_Timer = 12000; + } + else + HolyWrath_Timer -= uiDiff; + + boss_horsemen_commonAI::UpdateAI(uiDiff); + } +}; + +CreatureAI* GetAI_boss_sir_zeliek(Creature* pCreature) +{ + return new boss_sir_zeliekAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_rivendare_naxxAI : public boss_horsemen_commonAI +{ + boss_rivendare_naxxAI(Creature* pCreature) : boss_horsemen_commonAI(pCreature) + { + Reset(); + } + + uint32 Mark_Timer; + uint32 UnholyShadow_Timer; + + void Reset() + { + boss_horsemen_commonAI::Reset(); + Mark_Timer = 20000; + UnholyShadow_Timer = 15000; + } + + void Aggro(Unit *pWho) { switch(urand(0, 2)) { @@ -194,6 +516,8 @@ struct MANGOS_DLL_DECL boss_rivendare_naxxAI : public ScriptedAI case 1: DoScriptText(SAY_RIVE_AGGRO2, m_creature); break; case 2: DoScriptText(SAY_RIVE_AGGRO3, m_creature); break; } + + boss_horsemen_commonAI::Aggro(pWho); } void KilledUnit(Unit* Victim) @@ -204,14 +528,38 @@ struct MANGOS_DLL_DECL boss_rivendare_naxxAI : public ScriptedAI void JustDied(Unit* Killer) { DoScriptText(SAY_RIVE_DEATH, m_creature); + boss_horsemen_commonAI::JustDied(Killer); } void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + CheckPosition(WALKX_RIVE, WALKY_RIVE, WALKZ_RIVE); - DoMeleeAttackIfReady(); + // won't attack before reaching the corner + if (Attack_Check) + return; + + // Mark of Rivendare + if (Mark_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_MARK_OF_RIVENDARE, true); + Mark_Timer = 15000; + } + else + Mark_Timer -= uiDiff; + + if (UnholyShadow_Timer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_UNHOLY_SHADOW : H_SPELL_UNHOLY_SHADOW, CAST_INTERRUPT_PREVIOUS); + UnholyShadow_Timer = 15000; + } + else + UnholyShadow_Timer -= uiDiff; + + boss_horsemen_commonAI::UpdateAI(uiDiff); } }; @@ -220,26 +568,27 @@ CreatureAI* GetAI_boss_rivendare_naxx(Creature* pCreature) return new boss_rivendare_naxxAI(pCreature); } -struct MANGOS_DLL_DECL boss_thane_korthazzAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_thane_korthazzAI : public boss_horsemen_commonAI { - boss_thane_korthazzAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + boss_thane_korthazzAI(Creature* pCreature) : boss_horsemen_commonAI(pCreature) + { + Reset(); + } uint32 Mark_Timer; uint32 Meteor_Timer; - bool ShieldWall1; - bool ShieldWall2; void Reset() { + boss_horsemen_commonAI::Reset(); Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. Meteor_Timer = 30000; // wrong - ShieldWall1 = true; - ShieldWall2 = true; } - void Aggro(Unit *who) + void Aggro(Unit *pWho) { DoScriptText(SAY_KORT_AGGRO, m_creature); + boss_horsemen_commonAI::Aggro(pWho); } void KilledUnit(Unit* Victim) @@ -249,7 +598,8 @@ struct MANGOS_DLL_DECL boss_thane_korthazzAI : public ScriptedAI void JustDied(Unit* Killer) { - DoScriptText(SAY_KORT_DEATH, m_creature); + DoScriptText(SAY_KORT_DEATH, m_creature); + boss_horsemen_commonAI::JustDied(Killer); } void UpdateAI(const uint32 uiDiff) @@ -257,39 +607,34 @@ struct MANGOS_DLL_DECL boss_thane_korthazzAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + CheckPosition(WALKX_KORT, WALKY_KORT, WALKZ_KORT); + + // won't attack before reaching the corner + if (Attack_Check) + return; + // Mark of Korthazz if (Mark_Timer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_MARK_OF_KORTHAZZ); + DoCast(m_creature->getVictim(), SPELL_MARK_OF_KORTHAZZ, true); Mark_Timer = 12000; - }else Mark_Timer -= uiDiff; - - // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds - if (ShieldWall1 && m_creature->GetHealthPercent() < 50.0f) - { - if (ShieldWall1) - { - DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); - ShieldWall1 = false; - } - } - if (ShieldWall2 && m_creature->GetHealthPercent() < 20.0f) - { - if (ShieldWall2) - { - DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); - ShieldWall2 = false; - } } + else + Mark_Timer -= uiDiff; // Meteor if (Meteor_Timer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_METEOR); - Meteor_Timer = 20000; // wrong - }else Meteor_Timer -= uiDiff; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_METEOR : H_SPELL_METEOR, CAST_INTERRUPT_PREVIOUS); + Meteor_Timer = 20000; // wrong + } + } + else + Meteor_Timer -= uiDiff; - DoMeleeAttackIfReady(); + boss_horsemen_commonAI::UpdateAI(uiDiff); } }; @@ -298,106 +643,76 @@ CreatureAI* GetAI_boss_thane_korthazz(Creature* pCreature) return new boss_thane_korthazzAI(pCreature); } -struct MANGOS_DLL_DECL boss_sir_zeliekAI : public ScriptedAI +struct MANGOS_DLL_DECL npc_void_zoneAI : public Scripted_NoMovementAI { - boss_sir_zeliekAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} - - uint32 Mark_Timer; - uint32 HolyWrath_Timer; - bool ShieldWall1; - bool ShieldWall2; - - void Reset() - { - Mark_Timer = 20000; // First Horsemen Mark is applied at 20 sec. - HolyWrath_Timer = 12000; // right - ShieldWall1 = true; - ShieldWall2 = true; - } - - void Aggro(Unit *who) + npc_void_zoneAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) { - DoScriptText(SAY_ZELI_AGGRO, m_creature); + Reset(); } - void KilledUnit(Unit* Victim) - { - DoScriptText(SAY_ZELI_SLAY, m_creature); - } + uint32 Effect_Timer; + uint32 Despawn_Timer; - void JustDied(Unit* Killer) + void Reset() { - DoScriptText(SAY_ZELI_DEATH, m_creature); + Effect_Timer = 1000; + Despawn_Timer = 75000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } void UpdateAI(const uint32 uiDiff) { - //Return since we have no target - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - // Mark of Zeliek - if (Mark_Timer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_MARK_OF_ZELIEK); - Mark_Timer = 12000; - }else Mark_Timer -= uiDiff; - - // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds - if (ShieldWall1 && m_creature->GetHealthPercent() < 50.0f) + if (Effect_Timer < uiDiff) { - if (ShieldWall1) - { - DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); - ShieldWall1 = false; - } + if (!m_creature->HasAura(46262)) + DoCast(m_creature, 46262, true); + + Effect_Timer = 2000; } - if (ShieldWall2 && m_creature->GetHealthPercent() < 20.0f) + else + Effect_Timer -= uiDiff; + + if (Despawn_Timer < uiDiff) { - if (ShieldWall2) - { - DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); - ShieldWall2 = false; - } + m_creature->ForcedDespawn(); } - - // Holy Wrath - if (HolyWrath_Timer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_HOLY_WRATH); - HolyWrath_Timer = 12000; - }else HolyWrath_Timer -= uiDiff; - - DoMeleeAttackIfReady(); + else + Despawn_Timer -= uiDiff; } }; -CreatureAI* GetAI_boss_sir_zeliek(Creature* pCreature) +CreatureAI* GetAI_npc_void_zone(Creature* pCreature) { - return new boss_sir_zeliekAI(pCreature); + return new npc_void_zoneAI(pCreature); } void AddSC_boss_four_horsemen() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_lady_blaumeux"; - pNewScript->GetAI = &GetAI_boss_lady_blaumeux; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_rivendare_naxx"; - pNewScript->GetAI = &GetAI_boss_rivendare_naxx; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_thane_korthazz"; - pNewScript->GetAI = &GetAI_boss_thane_korthazz; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "boss_sir_zeliek"; - pNewScript->GetAI = &GetAI_boss_sir_zeliek; - pNewScript->RegisterSelf(); + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_lady_blaumeux"; + NewScript->GetAI = &GetAI_boss_lady_blaumeux; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_rivendare_naxx"; + NewScript->GetAI = &GetAI_boss_rivendare_naxx; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_thane_korthazz"; + NewScript->GetAI = &GetAI_boss_thane_korthazz; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_sir_zeliek"; + NewScript->GetAI = &GetAI_boss_sir_zeliek; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_void_zone"; + NewScript->GetAI = &GetAI_npc_void_zone; + NewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/boss_gluth.cpp b/scripts/northrend/naxxramas/boss_gluth.cpp index 996867f71d..d3fa089f92 100644 --- a/scripts/northrend/naxxramas/boss_gluth.cpp +++ b/scripts/northrend/naxxramas/boss_gluth.cpp @@ -32,6 +32,7 @@ enum SPELL_MORTALWOUND = 25646, SPELL_DECIMATE = 28374, + SPELL_DECIMATE_EFFECT = 28375, SPELL_ENRAGE = 28371, SPELL_ENRAGE_H = 54427, SPELL_BERSERK = 26662, @@ -93,6 +94,9 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI uint32 m_uiSummonTimer; uint32 m_uiBerserkTimer; + + std::list m_lZombieGUIDList; + uint32 m_uiRangeCheck_Timer; void Reset() { @@ -102,14 +106,33 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI m_uiSummonTimer = 10000; m_uiBerserkTimer = MINUTE*8*IN_MILLISECONDS; + + m_uiRangeCheck_Timer = 1000; + m_lZombieGUIDList.clear(); + DespawnZombies(); } void JustDied(Unit* pKiller) { + DespawnZombies(); if (m_pInstance) m_pInstance->SetData(TYPE_GLUTH, DONE); } + void DespawnZombies() + { + if (m_lZombieGUIDList.empty()) + return; + + for (std::list::iterator itr = m_lZombieGUIDList.begin(); itr != m_lZombieGUIDList.end(); ++itr) + { + Creature* pZombie = m_creature->GetMap()->GetCreature(*itr); + if (pZombie && pZombie->isAlive()) + pZombie->ForcedDespawn(); + } + m_lZombieGUIDList.clear(); + } + void Aggro(Unit* pWho) { if (m_pInstance) @@ -130,7 +153,7 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI // Mortal Wound if (m_uiMortalWoundTimer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTALWOUND); + DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTALWOUND); m_uiMortalWoundTimer = 10000; } else @@ -139,7 +162,19 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI // Decimate if (m_uiDecimateTimer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_DECIMATE); + DoCastSpellIfCan(m_creature, SPELL_DECIMATE); + // Move Zombies + if (!m_lZombieGUIDList.empty()) + { + for(std::list::iterator itr = m_lZombieGUIDList.begin(); itr != m_lZombieGUIDList.end(); ++itr) + if (Creature* pTemp = (Creature*)m_creature->GetMap()->GetUnit( *itr)) + if (pTemp->isAlive()) + { + pTemp->GetMotionMaster()->Clear(); + pTemp->GetMotionMaster()->MoveFollow(m_creature, 0.0f, 0.0f); + pTemp->AddThreat(m_creature, 1000000000.0f); // force move toward to Gluth + } + } m_uiDecimateTimer = 100000; } else @@ -161,6 +196,10 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) pZombie->AddThreat(pTarget); + + pZombie->GetMotionMaster()->Clear(); + pZombie->GetMotionMaster()->MoveFollow(m_creature, 0.0f, 0.0f); + m_lZombieGUIDList.push_back(pZombie->GetObjectGuid()); } if (!m_bIsRegularMode) @@ -169,6 +208,10 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) pZombie->AddThreat(pTarget); + + pZombie->GetMotionMaster()->Clear(); + pZombie->GetMotionMaster()->MoveFollow(m_creature, 0.0f, 0.0f); + m_lZombieGUIDList.push_back(pZombie->GetObjectGuid()); } } @@ -176,6 +219,22 @@ struct MANGOS_DLL_DECL boss_gluthAI : public ScriptedAI } else m_uiSummonTimer -= uiDiff; + + if (m_uiRangeCheck_Timer < uiDiff) // consume zombie check + { + if (!m_lZombieGUIDList.empty()) + { + for(std::list::iterator itr = m_lZombieGUIDList.begin(); itr != m_lZombieGUIDList.end(); ++itr) + if (Creature* pTemp = (Creature*)m_creature->GetMap()->GetUnit( *itr)) + if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, ATTACK_DISTANCE)) + { + DoScriptText(EMOTE_ZOMBIE, m_creature); + m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth() * 0.05); + pTemp->ForcedDespawn(); + } + } + m_uiRangeCheck_Timer = 1000; + }else m_uiRangeCheck_Timer -= uiDiff; // Berserk if (m_uiBerserkTimer < uiDiff) @@ -195,12 +254,55 @@ CreatureAI* GetAI_boss_gluth(Creature* pCreature) return new boss_gluthAI(pCreature); } -void AddSC_boss_gluth() +struct MANGOS_DLL_DECL mob_zombie_chowAI : public ScriptedAI { - Script* pNewScript; + mob_zombie_chowAI(Creature* pCreature) : ScriptedAI(pCreature) + {Reset();} + + void Reset() {} + + void MoveInLineOfSight(Unit* pWho){} - pNewScript = new Script; - pNewScript->Name = "boss_gluth"; - pNewScript->GetAI = &GetAI_boss_gluth; - pNewScript->RegisterSelf(); + void AttackStart(Unit *pWho) + { + ScriptedAI::AttackStart(pWho); + m_creature->SetSpeedRate(MOVE_WALK, 1.0f); + } + + void SpellHit(Unit *pCaster, const SpellEntry *spellInfo) + { + if (!pCaster || !spellInfo) + return; + + if (spellInfo->Id == SPELL_DECIMATE_EFFECT) + { + m_creature->SetSpeedRate(MOVE_RUN, 1.0f); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveFollow(pCaster, 0.0f, 0.0f); + } + } + + void UpdateAI(const uint32 uiDiff) + { + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_zombie_chow(Creature* pCreature) +{ + return new mob_zombie_chowAI(pCreature); +} + +void AddSC_boss_gluth() +{ + Script* NewScript; + NewScript = new Script; + NewScript->Name = "boss_gluth"; + NewScript->GetAI = &GetAI_boss_gluth; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_zombie_chow"; + NewScript->GetAI = &GetAI_mob_zombie_chow; + NewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/boss_gothik.cpp b/scripts/northrend/naxxramas/boss_gothik.cpp index 16c723dde8..d4a7be307e 100644 --- a/scripts/northrend/naxxramas/boss_gothik.cpp +++ b/scripts/northrend/naxxramas/boss_gothik.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss_Gothik -SD%Complete: 95 -SDComment: Prevent Gothik from turning and "in combat state" while on balcony +SD%Complete: 60 +SDComment: Only base implemented. Todo: control adds at summon. Handle case of raid not splitted in two sides SDCategory: Naxxramas EndScriptData */ @@ -40,13 +40,13 @@ enum PHASE_SPEECH = 0, PHASE_BALCONY = 1, - PHASE_STOP_SUMMONING = 2, - PHASE_TELEPORTING = 3, - PHASE_STOP_TELEPORTING = 4, + PHASE_GROUND = 2, + PHASE_END = 3, - // Right is right side from gothik (eastern) - SPELL_TELEPORT_RIGHT = 28025, - SPELL_TELEPORT_LEFT = 28026, + MAX_WAVES = 19, + + SPELL_TELEPORT_LEFT = 28025, // guesswork + SPELL_TELEPORT_RIGHT = 28026, // could be defined as dead or live side, left or right facing north SPELL_HARVESTSOUL = 28679, SPELL_SHADOWBOLT = 29317, @@ -81,81 +81,43 @@ struct MANGOS_DLL_DECL boss_gothikAI : public ScriptedAI instance_naxxramas* m_pInstance; bool m_bIsRegularMode; - GUIDList m_lSummonedAddGuids; - GUIDList m_lTraineeSummonPosGuids; - GUIDList m_lDeathKnightSummonPosGuids; - GUIDList m_lRiderSummonPosGuids; - uint8 m_uiPhase; - uint8 m_uiSpeech; - uint32 m_uiTraineeTimer; - uint32 m_uiDeathKnightTimer; - uint32 m_uiRiderTimer; + uint8 m_uiSpeechCount; + uint32 m_uiSpeechTimer; + + uint8 m_uiSummonCount; + uint32 m_uiSummonTimer; + uint32 m_uiTeleportTimer; uint32 m_uiShadowboltTimer; uint32 m_uiHarvestSoulTimer; - uint32 m_uiPhaseTimer; - uint32 m_uiControlZoneTimer; - uint32 m_uiSpeechTimer; void Reset() { - // Remove immunity - m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, false); - m_uiPhase = PHASE_SPEECH; - m_uiSpeech = 1; - m_uiTraineeTimer = 24*IN_MILLISECONDS; - m_uiDeathKnightTimer = 74*IN_MILLISECONDS; - m_uiRiderTimer = 134*IN_MILLISECONDS; - m_uiTeleportTimer = 20*IN_MILLISECONDS; - m_uiShadowboltTimer = 2*IN_MILLISECONDS; - m_uiHarvestSoulTimer = 2500; - m_uiPhaseTimer = 4*MINUTE*IN_MILLISECONDS + 7*IN_MILLISECONDS; // last summon at 4:04, next would be 4:09 - m_uiControlZoneTimer = urand(120*IN_MILLISECONDS,150*IN_MILLISECONDS); - m_uiSpeechTimer = 1*IN_MILLISECONDS; + m_uiSpeechCount = 0; + m_uiSpeechTimer = 5000; - // Despawn Adds - for (GUIDList::const_iterator itr = m_lSummonedAddGuids.begin(); itr != m_lSummonedAddGuids.end(); itr++) - { - if (Creature* pCreature = m_creature->GetMap()->GetCreature(*itr)) - pCreature->ForcedDespawn(); - } + m_uiSummonCount = 0; + m_uiSummonTimer = 5000; - m_lSummonedAddGuids.clear(); - m_lTraineeSummonPosGuids.clear(); - m_lDeathKnightSummonPosGuids.clear(); - m_lRiderSummonPosGuids.clear(); + m_uiTeleportTimer = 15000; + m_uiShadowboltTimer = 2500; + m_uiHarvestSoulTimer = 2500; } void Aggro(Unit* pWho) { + DoScriptText(SAY_SPEECH_1, m_creature); + if (!m_pInstance) return; m_pInstance->SetData(TYPE_GOTHIK, IN_PROGRESS); - // Make immune - m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, true); - m_pInstance->SetGothTriggers(); - PrepareSummonPlaces(); - } - - bool IsCentralDoorClosed() - { - return m_pInstance && m_pInstance->GetData(TYPE_GOTHIK) != SPECIAL; - } - - void ProcessCentralDoor() - { - if (IsCentralDoorClosed()) - { - m_pInstance->SetData(TYPE_GOTHIK, SPECIAL); - DoScriptText(EMOTE_GATE, m_creature); - } } bool HasPlayersInLeftSide() @@ -169,7 +131,7 @@ struct MANGOS_DLL_DECL boss_gothikAI : public ScriptedAI { if (Player* pPlayer = itr->getSource()) { - if (!m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive()) + if (!m_pInstance->IsInRightSideGothArea(pPlayer)) return true; } } @@ -197,88 +159,110 @@ struct MANGOS_DLL_DECL boss_gothikAI : public ScriptedAI m_pInstance->SetData(TYPE_GOTHIK, FAIL); } - void PrepareSummonPlaces() + void SummonAdds(bool bRightSide, uint32 uiSummonEntry) { std::list lSummonList; - m_pInstance->GetGothSummonPointCreatures(lSummonList, true); + m_pInstance->GetGothSummonPointCreatures(lSummonList, bRightSide); if (lSummonList.empty()) return; - // Trainees and Rider - uint8 index = 0; - uint8 uiTraineeCount = m_bIsRegularMode ? 2 : 3; - lSummonList.sort(ObjectDistanceOrder(m_creature)); - for (std::list::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) + uint8 uiCount = 2; + + switch(uiSummonEntry) { - if (*itr) - { - if (uiTraineeCount == 0) - break; - if (index == 1) - m_lRiderSummonPosGuids.push_back((*itr)->GetObjectGuid()); - else - { - m_lTraineeSummonPosGuids.push_back((*itr)->GetObjectGuid()); - --uiTraineeCount; - } - index++; - } + case NPC_UNREL_TRAINEE: + lSummonList.sort(ObjectDistanceOrder(m_creature)); + break; + case NPC_UNREL_DEATH_KNIGHT: + case NPC_UNREL_RIDER: + uiCount = 1; + lSummonList.sort(ObjectDistanceOrderReversed(m_creature)); + break; } - // DeathKnights - uint8 uiDeathKnightCount = m_bIsRegularMode ? 1 : 2; - lSummonList.sort(ObjectDistanceOrderReversed(m_creature)); - for (std::list::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) + for(std::list::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) { - if (*itr) - { - if (uiDeathKnightCount == 0) - break; - m_lDeathKnightSummonPosGuids.push_back((*itr)->GetObjectGuid()); - --uiDeathKnightCount; - } + if (uiCount == 0) + break; + + m_creature->SummonCreature(uiSummonEntry, (*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + --uiCount; } } - void SummonAdds(bool bRightSide, uint32 uiSummonEntry) + bool IsCentralDoorClosed() { - GUIDList* plSummonPosGuids; - switch(uiSummonEntry) - { - case NPC_UNREL_TRAINEE: plSummonPosGuids = &m_lTraineeSummonPosGuids; break; - case NPC_UNREL_DEATH_KNIGHT: plSummonPosGuids = &m_lDeathKnightSummonPosGuids; break; - case NPC_UNREL_RIDER: plSummonPosGuids = &m_lRiderSummonPosGuids; break; - default: - return; - } - if (plSummonPosGuids->empty()) - return; + return m_pInstance && m_pInstance->GetData(TYPE_GOTHIK) != SPECIAL; + } + + Player* SelectPlayerInASide(bool bLeft) + { + if(!m_pInstance) + return NULL; - for (GUIDList::iterator itr = plSummonPosGuids->begin(); itr != plSummonPosGuids->end(); ++itr) + Map::PlayerList const& lPlayers = m_pInstance->instance->GetPlayers(); + if (!lPlayers.isEmpty()) { - if (Creature* pPos = m_creature->GetMap()->GetCreature(*itr)) - m_creature->SummonCreature(uiSummonEntry, pPos->GetPositionX(), pPos->GetPositionY(), pPos->GetPositionZ(), pPos->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if (bLeft) + { + if(!m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive()) + { + return pPlayer; + } + } + else + { + if(m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive()) + { + return pPlayer; + } + } + } + } } + return NULL; } void JustSummoned(Creature* pSummoned) { - m_lSummonedAddGuids.push_back(pSummoned->GetObjectGuid()); if (!IsCentralDoorClosed()) pSummoned->SetInCombatWithZone(); + else + { + bool bSpectral; + switch(pSummoned->GetEntry()) + { + case NPC_UNREL_TRAINEE: + case NPC_UNREL_DEATH_KNIGHT: + case NPC_UNREL_RIDER: + bSpectral = false; + break; + case NPC_SPECT_TRAINEE: + case NPC_SPECT_DEATH_KNIGHT: + case NPC_SPECT_HORSE: + case NPC_SPECT_RIDER: + bSpectral = true; + break; + } + Player* pPlayer = SelectPlayerInASide(bSpectral); + if(pPlayer) + pSummoned->AI()->AttackStart(pPlayer); + } } void SummonedCreatureJustDied(Creature* pSummoned) { - m_lSummonedAddGuids.remove(pSummoned->GetObjectGuid()); - if (!m_pInstance) return; if (Creature* pAnchor = m_pInstance->GetClosestAnchorForGoth(pSummoned, true)) { - switch (pSummoned->GetEntry()) + switch(pSummoned->GetEntry()) { // Wrong caster, it expected to be pSummoned. // Mangos deletes the spell event at caster death, so for delayed spell like this @@ -295,151 +279,134 @@ struct MANGOS_DLL_DECL boss_gothikAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - switch (m_uiPhase) + switch(m_uiPhase) { case PHASE_SPEECH: + { if (m_uiSpeechTimer < uiDiff) { - switch(m_uiSpeech) + m_uiSpeechTimer = 5000; + ++m_uiSpeechCount; + + switch(m_uiSpeechCount) { - case 1: DoScriptText(SAY_SPEECH_1, m_creature); m_uiSpeechTimer = 4*IN_MILLISECONDS; break; - case 2: DoScriptText(SAY_SPEECH_2, m_creature); m_uiSpeechTimer = 6*IN_MILLISECONDS; break; - case 3: DoScriptText(SAY_SPEECH_3, m_creature); m_uiSpeechTimer = 5*IN_MILLISECONDS; break; - case 4: DoScriptText(SAY_SPEECH_4, m_creature); m_uiPhase = PHASE_BALCONY; break; + case 1: DoScriptText(SAY_SPEECH_2, m_creature); break; + case 2: DoScriptText(SAY_SPEECH_3, m_creature); break; + case 3: DoScriptText(SAY_SPEECH_4, m_creature); break; + case 4: m_uiPhase = PHASE_BALCONY; break; } - m_uiSpeech++; } else m_uiSpeechTimer -= uiDiff; - // No break here - - case PHASE_BALCONY: // Do summoning - if (m_uiTraineeTimer < uiDiff) - { - SummonAdds(true, NPC_UNREL_TRAINEE); - m_uiTraineeTimer = 20*IN_MILLISECONDS; - } - else - m_uiTraineeTimer -= uiDiff; - if (m_uiDeathKnightTimer < uiDiff) - { - SummonAdds(true, NPC_UNREL_DEATH_KNIGHT); - m_uiDeathKnightTimer = 25*IN_MILLISECONDS; - } - else - m_uiDeathKnightTimer -= uiDiff; - if (m_uiRiderTimer < uiDiff) - { - SummonAdds(true, NPC_UNREL_RIDER); - m_uiRiderTimer = 30*IN_MILLISECONDS; - } - else - m_uiRiderTimer -= uiDiff; - - if (m_uiPhaseTimer < uiDiff) - { - m_uiPhase = PHASE_STOP_SUMMONING; - m_uiPhaseTimer = 27*IN_MILLISECONDS; - } - else - m_uiPhaseTimer -= uiDiff; - break; - - case PHASE_STOP_SUMMONING: - if (m_uiPhaseTimer < uiDiff) + } + case PHASE_BALCONY: + { + if (m_uiSummonTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_TELEPORT_RIGHT, CAST_TRIGGERED) == CAST_OK) + if (m_uiSummonCount >= MAX_WAVES) { - m_uiPhase = m_pInstance ? PHASE_TELEPORTING : PHASE_STOP_TELEPORTING; - DoScriptText(SAY_TELEPORT, m_creature); DoScriptText(EMOTE_TO_FRAY, m_creature); - - // Remove Immunity - m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, false); - - DoResetThreat(); - m_creature->SetInCombatWithZone(); + DoCastSpellIfCan(m_creature, SPELL_TELEPORT_RIGHT); + m_uiPhase = PHASE_GROUND; + return; } + + // npc, npc, npc, timer + static uint32 const auiSummonData[MAX_WAVES][4] = + { + {NPC_UNREL_TRAINEE, 0, 0, 20000}, + {NPC_UNREL_TRAINEE, 0, 0, 20000}, + {NPC_UNREL_TRAINEE, 0, 0, 10000}, + {NPC_UNREL_DEATH_KNIGHT, 0, 0, 10000}, + {NPC_UNREL_TRAINEE, 0, 0, 15000}, + {NPC_UNREL_DEATH_KNIGHT, 0, 0, 10000}, + {NPC_UNREL_TRAINEE, 0, 0, 15000}, + {NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_TRAINEE, 0, 10000}, + {NPC_UNREL_RIDER, 0, 0, 10000}, + {NPC_UNREL_TRAINEE, 0, 0, 5000}, + {NPC_UNREL_DEATH_KNIGHT, 0, 0, 15000}, + {NPC_UNREL_TRAINEE, NPC_UNREL_RIDER, 0, 10000}, + {NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_DEATH_KNIGHT, 0, 10000}, + {NPC_UNREL_TRAINEE, 0, 0, 10000}, + {NPC_UNREL_RIDER, 0, 0, 5000}, + {NPC_UNREL_DEATH_KNIGHT, 0, 0, 5000}, + {NPC_UNREL_TRAINEE, 0, 0, 20000}, + {NPC_UNREL_RIDER, NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_TRAINEE, 15000}, + {NPC_UNREL_TRAINEE, 0, 0, 30000}, + }; + + SummonAdds(true, auiSummonData[m_uiSummonCount][0]); + + if (auiSummonData[m_uiSummonCount][1]) + SummonAdds(true, auiSummonData[m_uiSummonCount][1]); + + if (auiSummonData[m_uiSummonCount][2]) + SummonAdds(true, auiSummonData[m_uiSummonCount][2]); + + m_uiSummonTimer = auiSummonData[m_uiSummonCount][3]; + + ++m_uiSummonCount; } else - m_uiPhaseTimer -= uiDiff; + m_uiSummonTimer -= uiDiff; break; - - case PHASE_TELEPORTING: // Phase is only reached if m_pInstance is valid - if (m_uiTeleportTimer < uiDiff) + } + case PHASE_GROUND: + case PHASE_END: + { + if (m_uiPhase == PHASE_GROUND) { - uint32 uiTeleportSpell = m_pInstance->IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT; - if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK) + if (m_creature->GetHealthPercent() < 30.0f) + { + if (m_pInstance->IsInRightSideGothArea(m_creature)) + { + DoScriptText(EMOTE_GATE, m_creature); + m_pInstance->SetData(TYPE_GOTHIK, SPECIAL); + m_uiPhase = PHASE_END; + m_uiShadowboltTimer = 2000; + return; + } + } + + if (m_uiTeleportTimer < uiDiff) { - m_uiTeleportTimer = 20*IN_MILLISECONDS; - m_uiShadowboltTimer = 2*IN_MILLISECONDS; + uint32 uiTeleportSpell = m_pInstance->IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT; + + if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK) + { + DoResetThreat(); + m_uiTeleportTimer = 15000; + m_uiShadowboltTimer = 2000; + return; + } } + else + m_uiTeleportTimer -= uiDiff; } - else - m_uiTeleportTimer -= uiDiff; - if (m_creature->GetHealthPercent() <= 30.0f) + if (m_uiShadowboltTimer < uiDiff) { - m_uiPhase = PHASE_STOP_TELEPORTING; - ProcessCentralDoor(); - // as the doors now open, recheck whether mobs are standing around - m_uiControlZoneTimer = 1; + if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOWBOLT: SPELL_SHADOWBOLT_H) == CAST_OK) + m_uiShadowboltTimer = 1500; } - // no break here + else + m_uiShadowboltTimer -= uiDiff; - case PHASE_STOP_TELEPORTING: if (m_uiHarvestSoulTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_HARVESTSOUL) == CAST_OK) - m_uiHarvestSoulTimer = 15*IN_MILLISECONDS; + m_uiHarvestSoulTimer = 15000; } else m_uiHarvestSoulTimer -= uiDiff; - if (m_uiShadowboltTimer) - { - if (m_uiShadowboltTimer <= uiDiff) - m_uiShadowboltTimer = 0; - else - m_uiShadowboltTimer -= uiDiff; - } - // Shadowbold cooldown finished, cast when ready - else if (!m_creature->IsNonMeleeSpellCasted(true)) - { - // Select valid target - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0, SPELL_SHADOWBOLT, SELECT_FLAG_IN_LOS)) - DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOWBOLT : SPELL_SHADOWBOLT_H); - } - + DoMeleeAttackIfReady(); // possibly no melee at all break; - } - - // Control Check, if Death zone empty - if (m_uiControlZoneTimer) - { - if (m_uiControlZoneTimer <= uiDiff) - { - m_uiControlZoneTimer = 0; - - if (m_pInstance && !HasPlayersInLeftSide()) - { - ProcessCentralDoor(); - for (GUIDList::const_iterator itr = m_lSummonedAddGuids.begin(); itr != m_lSummonedAddGuids.end(); itr++) - { - if (Creature* pCreature = m_pInstance->instance->GetCreature(*itr)) - { - if (!pCreature->isInCombat()) - pCreature->SetInCombatWithZone(); - } - } - } } - else - m_uiControlZoneTimer -= uiDiff; } } }; @@ -519,10 +486,10 @@ bool EffectDummyCreature_spell_anchor(Unit* pCaster, uint32 uiSpellId, SpellEffe else if (uiSpellId == SPELL_C_TO_SKULL) uiNpcEntry = NPC_SPECT_RIDER; - pGoth->SummonCreature(uiNpcEntry, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), pCreatureTarget->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); + pGoth->SummonCreature(uiNpcEntry, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), pCreatureTarget->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); if (uiNpcEntry == NPC_SPECT_RIDER) - pGoth->SummonCreature(NPC_SPECT_HORSE, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), pCreatureTarget->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); + pGoth->SummonCreature(NPC_SPECT_HORSE, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), pCreatureTarget->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); } return true; } diff --git a/scripts/northrend/naxxramas/boss_grobbulus.cpp b/scripts/northrend/naxxramas/boss_grobbulus.cpp index 5a72245f30..9a879f4973 100644 --- a/scripts/northrend/naxxramas/boss_grobbulus.cpp +++ b/scripts/northrend/naxxramas/boss_grobbulus.cpp @@ -42,7 +42,8 @@ enum SPELL_SLIME_SPRAY_H = 54364, SPELL_BERSERK = 26662, - NPC_FALLOUT_SLIME = 16290 + NPC_FALLOUT_SLIME = 16290, + NPC_POISON_CLOUD = 16363 }; struct MANGOS_DLL_DECL boss_grobbulusAI : public ScriptedAI @@ -196,7 +197,7 @@ struct MANGOS_DLL_DECL boss_grobbulusAI : public ScriptedAI // Poison Cloud if (m_uiPoisonCloudTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_POISON_CLOUD) == CAST_OK) + if (m_creature->SummonCreature(NPC_POISON_CLOUD, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 75000)) m_uiPoisonCloudTimer = 15*IN_MILLISECONDS; } else @@ -206,11 +207,41 @@ struct MANGOS_DLL_DECL boss_grobbulusAI : public ScriptedAI } }; +struct MANGOS_DLL_DECL npc_grobbulus_poison_cloudAI : public Scripted_NoMovementAI +{ + npc_grobbulus_poison_cloudAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + uint32 Cloud_Timer; + + void Reset() + { + Cloud_Timer = 1000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (Cloud_Timer < uiDiff) + { + DoCast(m_creature, 59116); + Cloud_Timer = 10000; + }else Cloud_Timer -= uiDiff; + } +}; + CreatureAI* GetAI_boss_grobbulus(Creature* pCreature) { return new boss_grobbulusAI(pCreature); } +CreatureAI* GetAI_npc_grobbulus_poison_cloud(Creature* pCreature) +{ + return new npc_grobbulus_poison_cloudAI(pCreature); +} + void AddSC_boss_grobbulus() { Script* pNewScript; @@ -219,4 +250,9 @@ void AddSC_boss_grobbulus() pNewScript->Name = "boss_grobbulus"; pNewScript->GetAI = &GetAI_boss_grobbulus; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_grobbulus_poison_cloud"; + pNewScript->GetAI = &GetAI_npc_grobbulus_poison_cloud; + pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/boss_noth.cpp b/scripts/northrend/naxxramas/boss_noth.cpp index ceab11a0ea..442e997d91 100644 --- a/scripts/northrend/naxxramas/boss_noth.cpp +++ b/scripts/northrend/naxxramas/boss_noth.cpp @@ -158,6 +158,12 @@ struct MANGOS_DLL_DECL boss_nothAI : public ScriptedAI DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_CRIPPLE : SPELL_CRIPPLE_H); } + void DamageTaken (Unit* pDoneBy, uint32 &uiDamage) + { + if (m_uiPhase == PHASE_BALCONY) + uiDamage = 0; + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) diff --git a/scripts/northrend/naxxramas/boss_razuvious.cpp b/scripts/northrend/naxxramas/boss_razuvious.cpp index 1f22dad2f7..fae6700754 100644 --- a/scripts/northrend/naxxramas/boss_razuvious.cpp +++ b/scripts/northrend/naxxramas/boss_razuvious.cpp @@ -41,7 +41,11 @@ enum SPELL_DISRUPTING_SHOUT = 55543, SPELL_DISRUPTING_SHOUT_H = 29107, SPELL_JAGGED_KNIFE = 55550, - SPELL_HOPELESS = 29125 + SPELL_HOPELESS = 29125, + // Cristalls + SPELL_FORCE_OBEDIENCE = 55479, + + NPC_DEATH_KNIGHT_UNDERSTUDY = 16803 }; struct MANGOS_DLL_DECL boss_razuviousAI : public ScriptedAI @@ -169,6 +173,105 @@ CreatureAI* GetAI_boss_razuvious(Creature* pCreature) return new boss_razuviousAI(pCreature); } +struct MANGOS_DLL_DECL npc_death_knight_understudyAI : public ScriptedAI +{ + npc_death_knight_understudyAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (instance_naxxramas*)pCreature->GetInstanceData(); + Reset(); + } + + instance_naxxramas* m_pInstance; + + uint32 m_uiBoneArmorTimer; + uint32 m_uiBloodStrikeTimer; + + void Reset() + { + m_uiBoneArmorTimer = 1000; + m_uiBloodStrikeTimer = 7000; + } + + void Aggro(Unit* pWho) + { + m_creature->HandleEmote(0); + m_creature->CallForHelp(20.0f); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiBoneArmorTimer < uiDiff) + { + if (DoCastSpellIfCan(m_creature, 29061, CAST_AURA_NOT_PRESENT | CAST_INTERRUPT_PREVIOUS) == CAST_OK) + m_uiBoneArmorTimer = 30000; + } + else + m_uiBoneArmorTimer -= uiDiff; + + if (m_uiBloodStrikeTimer < uiDiff) + { + if (DoCastSpellIfCan(m_creature->getVictim(), 61696) == CAST_OK) + m_uiBloodStrikeTimer = urand(4000, 6000); + } + else + m_uiBloodStrikeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_death_knight_understudy(Creature* pCreature) +{ + return new npc_death_knight_understudyAI(pCreature); +} + +bool GossipHello_npc_obedience_crystal(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + + if (!pInstance || pInstance->GetData(TYPE_RAZUVIOUS) == DONE) + return true; + + if (!pCreature->GetMap()->IsRegularDifficulty()) + return true; + + Creature* pRazuvious = pInstance->GetSingleCreatureFromStorage(NPC_RAZUVIOUS); + if (!pRazuvious) + return false; + + pPlayer->RemoveAurasDueToSpell(55520); + pPlayer->CastSpell(pCreature, SPELL_FORCE_OBEDIENCE, true); + + if (!pRazuvious->isInCombat()) + pRazuvious->SetInCombatWithZone(); + + std::list lUnitList; + GetCreatureListWithEntryInGrid(lUnitList, pCreature, NPC_DEATH_KNIGHT_UNDERSTUDY, 100.0f); + if (lUnitList.empty()) + return true; + + for(std::list::iterator itr = lUnitList.begin(); itr != lUnitList.end(); ++itr) + { + if ((*itr)->isAlive() && (*itr)->HasAura(SPELL_FORCE_OBEDIENCE)) + { + if (!pRazuvious->isInCombat()) + { + (*itr)->HandleEmote(0); + pRazuvious->AI()->AttackStart((*itr)); + } + + pRazuvious->AddThreat((*itr), 5000.0f); + + return true; + } + } + + return true; +} + void AddSC_boss_razuvious() { Script* pNewScript; @@ -177,4 +280,14 @@ void AddSC_boss_razuvious() pNewScript->Name = "boss_razuvious"; pNewScript->GetAI = &GetAI_boss_razuvious; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_obedience_crystal"; + pNewScript->pGossipHello = &GossipHello_npc_obedience_crystal; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_death_knight_understudy"; + pNewScript->GetAI = &GetAI_npc_death_knight_understudy; + pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/boss_sapphiron.cpp b/scripts/northrend/naxxramas/boss_sapphiron.cpp index 502e171506..c7e7558481 100644 --- a/scripts/northrend/naxxramas/boss_sapphiron.cpp +++ b/scripts/northrend/naxxramas/boss_sapphiron.cpp @@ -16,63 +16,35 @@ /* ScriptData SDName: Boss_Sapphiron -SD%Complete: 80 -SDComment: Some spells need core implementation +SD%Complete: 0 +SDComment: Place Holder SDCategory: Naxxramas EndScriptData */ -/* Additional comments: - * Bugged spells: 28560 (needs maxTarget = 1, Summon of 16474 implementation, TODO, 30s duration) - * 28526 (needs ScriptEffect to cast 28522 onto random target) - * - * Achievement-criteria check needs implementation - * - * Frost-Breath ability: the dummy spell 30101 is self cast, so it won't take the needed delay of ~7s until it reaches its target - * As Sapphiron is displayed visually in hight (hovering), and the spell is cast with target=self-location - * which is still on the ground, the client shows a nice slow falling of the visual animation - * Insisting on using the Dummy-Effect to cast the breath-dmg spells, would require, to relocate Sapphi internally, - * and to hack the targeting to be "on the ground" - Hence the prefered way as it is now! - */ - #include "precompiled.h" #include "naxxramas.h" enum { - EMOTE_BREATH = -1533082, - EMOTE_GENERIC_ENRAGED = -1000003, - EMOTE_FLY = -1533022, - EMOTE_GROUND = -1533083, - - SPELL_CLEAVE = 19983, - SPELL_TAIL_SWEEP = 55697, - SPELL_TAIL_SWEEP_H = 55696, - SPELL_ICEBOLT = 28526, - SPELL_FROST_BREATH_DUMMY = 30101, - SPELL_FROST_BREATH_A = 28524, - SPELL_FROST_BREATH_B = 29318, - SPELL_FROST_AURA = 28531, - SPELL_FROST_AURA_H = 55799, - SPELL_LIFE_DRAIN = 28542, - SPELL_LIFE_DRAIN_H = 55665, - SPELL_CHILL = 28547, - SPELL_CHILL_H = 55699, - SPELL_SUMMON_BLIZZARD = 28560, - SPELL_BESERK = 26662, - SPELL_ACHIEVEMENT_CHECK = 60539, // unused - - NPC_YOU_KNOW_WHO = 16474, -}; - -static const float aLiftOffPosition[3] = {3522.386f, -5236.784f, 137.709f}; - -enum Phases -{ - PHASE_GROUND = 1, - PHASE_LIFT_OFF = 2, - PHASE_AIR_BOLTS = 3, - PHASE_AIR_BREATH = 4, - PHASE_LANDING = 5, + EMOTE_BREATH = -1533082, + EMOTE_ENRAGE = -1533083, + + SPELL_ICEBOLT = 28522, + SPELL_FROST_BREATH = 28524, + SPELL_FROST_AURA = 28531, + SPELL_LIFE_DRAIN = 28542, + SPELL_LIFE_DRAIN_H = 55665, + SPELL_BLIZZARD = 28547, + SPELL_BERSERK = 26662, + SPELL_CLEAVE = 19983, + SPELL_TAIL_LASH = 55697, + SPELL_TAIL_LASH_H = 55696, + SPELL_ICEBOLT_VISUAL = 45776, + SPELL_WING_BUFFET = 29328, + + SAPPHIRON_X = 3522, + SAPPHIRON_Y = -5236, + SAPPHIRON_Z = 137 }; struct MANGOS_DLL_DECL boss_sapphironAI : public ScriptedAI @@ -81,48 +53,59 @@ struct MANGOS_DLL_DECL boss_sapphironAI : public ScriptedAI { m_pInstance = (instance_naxxramas*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Icebolt_Number = m_bIsRegularMode ? 2 : 3; Reset(); } instance_naxxramas* m_pInstance; bool m_bIsRegularMode; + uint32 Icebolt_Count; + uint32 Icebolt_Timer; + uint32 FrostBreath_Timer; + uint32 FrostAura_Timer; + uint32 LifeDrain_Timer; + uint32 Blizzard_Timer; + uint32 Fly_Timer; + uint32 Beserk_Timer; uint32 m_uiCleaveTimer; - uint32 m_uiTailSweepTimer; - uint32 m_uiIceboltTimer; - uint32 m_uiFrostBreathTimer; - uint32 m_uiLifeDrainTimer; - uint32 m_uiBlizzardTimer; - uint32 m_uiFlyTimer; - uint32 m_uiBerserkTimer; - uint32 m_uiLandTimer; - - uint32 m_uiIceboltCount; - Phases m_Phase; + uint32 m_uiTailSweepTimer; + uint32 phase; + bool landoff; + uint32 land_Timer; + ObjectGuid triggerGuid; + uint32 deIce_Timer; + bool deIce; + uint32 Icebolt_Number; + + std::list IceBlockedList; void Reset() { - m_uiCleaveTimer = 5000; - m_uiTailSweepTimer = 12000; - m_uiFrostBreathTimer = 7000; - m_uiLifeDrainTimer = 11000; - m_uiBlizzardTimer = 15000; // "Once the encounter starts,based on your version of Naxx, this will be used x2 for normal and x6 on HC" - m_uiFlyTimer = 46000; - m_uiIceboltTimer = 5000; - m_uiLandTimer = 0; - m_uiBerserkTimer = 15 * MINUTE * IN_MILLISECONDS; - m_Phase = PHASE_GROUND; - m_uiIceboltCount = 0; - + FrostAura_Timer = 2000; + FrostBreath_Timer = 2500; + LifeDrain_Timer = 24000; + Blizzard_Timer = 20000; + Fly_Timer = 45000; + Icebolt_Timer = 4000; + land_Timer = 2000; + Beserk_Timer = 900000; + m_uiCleaveTimer = 7000; + m_uiTailSweepTimer = 20000; + phase = 1; + Icebolt_Count = 0; + landoff = false; + triggerGuid.Clear(); + deIce_Timer = 1000; + deIce = false; SetCombatMovement(true); - m_creature->SetLevitate(false); + m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 15); + m_creature->SetFloatValue(UNIT_FIELD_COMBATREACH, 15); //m_creature->ApplySpellMod(SPELL_FROST_AURA, SPELLMOD_DURATION, -1); } void Aggro(Unit* pWho) { - DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FROST_AURA : SPELL_FROST_AURA_H); - if (m_pInstance) m_pInstance->SetData(TYPE_SAPPHIRON, IN_PROGRESS); } @@ -133,187 +116,234 @@ struct MANGOS_DLL_DECL boss_sapphironAI : public ScriptedAI m_pInstance->SetData(TYPE_SAPPHIRON, DONE); } + void SpellHitTarget(Unit *target, const SpellEntry *spell) + { + if (spell->Id == SPELL_ICEBOLT && target->isAlive()) + target->SetInFront(m_creature); + } + + void DamageDeal(Unit* pDoneTo, uint32& uiDamage) + { + if (pDoneTo->HasAura(SPELL_ICEBOLT)) + uiDamage = 0; + else if (uiDamage > 50000 && isInBackIceBlock(pDoneTo)) + uiDamage = 0; + } + + bool isInBackIceBlock(Unit* target) + { + for(std::list::iterator itr = IceBlockedList.begin(); itr != IceBlockedList.end(); ++itr) + { + if (Player* pIceBlock = m_creature->GetMap()->GetPlayer(*itr)) + { + if (pIceBlock->isInBack(target, 20.0f, M_PI_F/1.5f) && pIceBlock->HasAura(SPELL_ICEBOLT)) + return true; + } + } + + return false; + } + void JustReachedHome() { if (m_pInstance) m_pInstance->SetData(TYPE_SAPPHIRON, FAIL); + + if (m_creature->isHover()) + m_creature->SetHover(false); } void JustSummoned(Creature* pSummoned) { - if (pSummoned->GetEntry() == NPC_YOU_KNOW_WHO) + if (pSummoned->GetEntry() == 16082) { - if (Unit* pEnemy = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pEnemy); + triggerGuid = pSummoned->GetObjectGuid(); + pSummoned->addUnitState(UNIT_STAT_ROOT); + DoCastSpellIfCan(pSummoned, 30101, CAST_TRIGGERED); } - } - - void MovementInform(uint32 uiType, uint32 uiPointId) + } + + void DoMeleeAttackIfReady() { - if (uiType == POINT_MOTION_TYPE && m_Phase == PHASE_LIFT_OFF) + //Make sure our attack is ready before checking distance + if (m_creature->isAttackReady()) { - DoScriptText(EMOTE_FLY, m_creature); - m_creature->HandleEmote(EMOTE_ONESHOT_LIFTOFF); - m_creature->SetLevitate(true); - m_Phase = PHASE_AIR_BOLTS; - - m_uiFrostBreathTimer = 5000; - m_uiIceboltTimer = 5000; - m_uiIceboltCount = 0; + //If we are within range melee the target + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 45)) + { + m_creature->AttackerStateUpdate(m_creature->getVictim()); + m_creature->resetAttackTimer(); + } } } - + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - switch (m_Phase) + if (phase == 1) { - case PHASE_GROUND: - if (m_uiCleaveTimer < uiDiff) + if (deIce) + { + if (deIce_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK) - m_uiCleaveTimer = urand(5000, 10000); + deIce = false; + for(std::list::iterator itr = IceBlockedList.begin(); itr != IceBlockedList.end(); ++itr) + { + if (Player* pIceBlock = m_creature->GetMap()->GetPlayer(*itr)) + { + pIceBlock->RemoveAurasDueToSpell(SPELL_ICEBOLT_VISUAL); + pIceBlock->RemoveAurasDueToSpell(SPELL_ICEBOLT); + } + } + + IceBlockedList.clear(); + deIce_Timer = 1000; } else - m_uiCleaveTimer -= uiDiff; + deIce_Timer -= uiDiff; + } + + if (FrostAura_Timer < uiDiff) + { + DoCastSpellIfCan(m_creature, SPELL_FROST_AURA, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); + FrostAura_Timer = 5000; + } + else + FrostAura_Timer -= uiDiff; - if (m_uiTailSweepTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_TAIL_SWEEP : SPELL_TAIL_SWEEP_H) == CAST_OK) - m_uiTailSweepTimer = urand(7000, 10000); - } - else - m_uiTailSweepTimer -= uiDiff; + if (LifeDrain_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_LIFE_DRAIN : SPELL_LIFE_DRAIN_H); - if (m_uiLifeDrainTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_LIFE_DRAIN : SPELL_LIFE_DRAIN_H) == CAST_OK) - m_uiLifeDrainTimer = 23000; - } - else - m_uiLifeDrainTimer -= uiDiff; + LifeDrain_Timer = 24000; + } + else + LifeDrain_Timer -= uiDiff; - if (m_uiBlizzardTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_BLIZZARD) == CAST_OK) - m_uiBlizzardTimer = 20000; - } - else - m_uiBlizzardTimer -= uiDiff; + if (Blizzard_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCastSpellIfCan(target, SPELL_BLIZZARD); - if (m_creature->GetHealthPercent() > 10.0f) - { - if (m_uiFlyTimer < uiDiff) - { - m_Phase = PHASE_LIFT_OFF; - m_creature->InterruptNonMeleeSpells(false); - SetCombatMovement(false); - m_creature->GetMotionMaster()->Clear(false); - m_creature->GetMotionMaster()->MovePoint(1, aLiftOffPosition[0], aLiftOffPosition[1], aLiftOffPosition[2]); - // TODO This should clear the target, too + Blizzard_Timer = 20000; + } + else + Blizzard_Timer -= uiDiff; + + // Cleave + if (m_uiCleaveTimer < uiDiff) + { + DoCastSpellIfCan(m_creature, SPELL_CLEAVE, CAST_INTERRUPT_PREVIOUS); + m_uiCleaveTimer = urand(7000, 10000); + } + else + m_uiCleaveTimer -= uiDiff; - return; - } - else - m_uiFlyTimer -= uiDiff; - } + // Tail Sweep + if (m_uiTailSweepTimer < uiDiff) + { + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H, CAST_INTERRUPT_PREVIOUS); + m_uiTailSweepTimer = urand(15000, 20000); + } + else + m_uiTailSweepTimer -= uiDiff; - // Only Phase in which we have melee attack! - DoMeleeAttackIfReady(); - break; - case PHASE_LIFT_OFF: - break; - case PHASE_AIR_BOLTS: - // WOTLK Changed, originally was 5 - if (m_uiIceboltCount == (uint32)(m_bIsRegularMode ? 2 : 3)) + if (m_creature->GetHealthPercent() > 10.0f) + { + if (Fly_Timer < uiDiff) { - if (m_uiFrostBreathTimer < uiDiff) - { - m_Phase = PHASE_AIR_BREATH; - DoScriptText(EMOTE_BREATH, m_creature); - DoCastSpellIfCan(m_creature, SPELL_FROST_BREATH_DUMMY); - m_uiFrostBreathTimer = 7000; - } - else - m_uiFrostBreathTimer -= uiDiff; + phase = 2; + m_creature->InterruptNonMeleeSpells(false); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + DoCastSpellIfCan(m_creature, SPELL_WING_BUFFET, CAST_TRIGGERED); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MovePoint(1, SAPPHIRON_X, SAPPHIRON_Y, SAPPHIRON_Z + 5); + DoCastSpellIfCan(m_creature, 11010); + m_creature->SetHover(true); + + Icebolt_Timer = 4000; + Icebolt_Count = 0; + landoff = false; + IceBlockedList.clear(); } else - { - if (m_uiIceboltTimer < uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_ICEBOLT); - - ++m_uiIceboltCount; - m_uiIceboltTimer = 4000; - } - else - m_uiIceboltTimer -= uiDiff; - } + Fly_Timer -= uiDiff; + } + } - break; - case PHASE_AIR_BREATH: - if (m_uiFrostBreathTimer) + if (phase == 2) + { + if (Icebolt_Timer < uiDiff && Icebolt_Count < Icebolt_Number) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (m_uiFrostBreathTimer <= uiDiff) + Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (pPlayer && (DoCastSpellIfCan(pPlayer, SPELL_ICEBOLT, CAST_AURA_NOT_PRESENT) == CAST_OK)) { - DoCastSpellIfCan(m_creature, SPELL_FROST_BREATH_A, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_FROST_BREATH_B, CAST_TRIGGERED); - m_uiFrostBreathTimer = 0; - - m_uiLandTimer = 4000; + IceBlockedList.push_back(pPlayer->GetObjectGuid()); + ++Icebolt_Count; + Icebolt_Timer = 4000; + + if (Icebolt_Count == Icebolt_Number) + DoScriptText(EMOTE_BREATH, m_creature); } - else - m_uiFrostBreathTimer -= uiDiff; - } + } + } + else + Icebolt_Timer -= uiDiff; - if (m_uiLandTimer) + if (Icebolt_Count == Icebolt_Number && !landoff) + { + if (FrostBreath_Timer < uiDiff) { - if (m_uiLandTimer <= uiDiff) - { - // Begin Landing - DoScriptText(EMOTE_GROUND, m_creature); - m_creature->HandleEmote(EMOTE_ONESHOT_LAND); - m_creature->SetLevitate(false); + //DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FROST_BREATH : SPELL_FROST_BREATH_H, CAST_INTERRUPT_PREVIOUS); + // workaround effect + m_creature->SummonCreature(16082, SAPPHIRON_X, SAPPHIRON_Y, SAPPHIRON_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); - m_Phase = PHASE_LANDING; - m_uiLandTimer = 2000; - } - else - m_uiLandTimer -= uiDiff; + land_Timer = 9000; + landoff = true; + FrostBreath_Timer = 5000; } + else + FrostBreath_Timer -= uiDiff; + } - break; - case PHASE_LANDING: - if (m_uiLandTimer < uiDiff) + if (landoff) + { + if (land_Timer < uiDiff) { - m_Phase = PHASE_GROUND; - - SetCombatMovement(true); - m_creature->GetMotionMaster()->Clear(false); - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); - - m_uiFlyTimer = 67000; - m_uiLandTimer = 0; + phase = 1; + if (Creature* pTrigger = m_creature->GetMap()->GetCreature(triggerGuid)) + pTrigger->CastSpell(pTrigger, SPELL_FROST_BREATH, true, NULL, NULL, m_creature->GetObjectGuid()); + + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + m_creature->SetHover(false); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MovePoint(1, SAPPHIRON_X, SAPPHIRON_Y, SAPPHIRON_Z); + SetCombatMovement(false); + deIce = true; + Fly_Timer = 67000; } else - m_uiLandTimer -= uiDiff; - - break; + land_Timer -= uiDiff; + } } - - // Enrage can happen in any phase - if (m_uiBerserkTimer < uiDiff) + + if (Beserk_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_BESERK) == CAST_OK) - { - DoScriptText(EMOTE_GENERIC_ENRAGED, m_creature); - m_uiBerserkTimer = 300000; + if (DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT) == CAST_OK) + DoScriptText(EMOTE_ENRAGE, m_creature); + + Beserk_Timer = 5000; } - } else - m_uiBerserkTimer -= uiDiff; + Beserk_Timer -= uiDiff; + + if (phase != 2) + DoMeleeAttackIfReady(); } }; @@ -324,10 +354,9 @@ CreatureAI* GetAI_boss_sapphiron(Creature* pCreature) void AddSC_boss_sapphiron() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_sapphiron"; - pNewScript->GetAI = &GetAI_boss_sapphiron; - pNewScript->RegisterSelf(); + Script* NewScript; + NewScript = new Script; + NewScript->Name = "boss_sapphiron"; + NewScript->GetAI = &GetAI_boss_sapphiron; + NewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/boss_thaddius.cpp b/scripts/northrend/naxxramas/boss_thaddius.cpp index dc62fafbe1..2ba14ef2b8 100644 --- a/scripts/northrend/naxxramas/boss_thaddius.cpp +++ b/scripts/northrend/naxxramas/boss_thaddius.cpp @@ -89,190 +89,6 @@ enum SPELL_SHOCK = 28099, }; -/************ -** boss_thaddius -************/ - -// Actually this boss behaves like a NoMovement Boss (SPELL_BALL_LIGHTNING) - but there are some movement packages used, unknown what this means! -struct MANGOS_DLL_DECL boss_thaddiusAI : public Scripted_NoMovementAI -{ - boss_thaddiusAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - m_pInstance = (instance_naxxramas*)pCreature->GetInstanceData(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - - Reset(); - } - - instance_naxxramas* m_pInstance; - bool m_bIsRegularMode; - - uint32 m_uiPolarityShiftTimer; - uint32 m_uiChainLightningTimer; - uint32 m_uiBallLightningTimer; - uint32 m_uiBerserkTimer; - - void Reset() - { - m_uiPolarityShiftTimer = 15*IN_MILLISECONDS; - m_uiChainLightningTimer = 8*IN_MILLISECONDS; - m_uiBallLightningTimer = 1*IN_MILLISECONDS; - m_uiBerserkTimer = 6*MINUTE*IN_MILLISECONDS; - - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void Aggro(Unit* pWho) - { - switch (urand(0,2)) - { - case 0: DoScriptText(SAY_AGGRO_1, m_creature); break; - case 1: DoScriptText(SAY_AGGRO_2, m_creature); break; - case 2: DoScriptText(SAY_AGGRO_3, m_creature); break; - } - } - - void JustReachedHome() - { - if (m_pInstance) - { - m_pInstance->SetData(TYPE_THADDIUS, FAIL); - - // Respawn Adds: - Creature* pFeugen = m_pInstance->GetSingleCreatureFromStorage(NPC_FEUGEN); - Creature* pStalagg = m_pInstance->GetSingleCreatureFromStorage(NPC_STALAGG); - if (pFeugen) - { - pFeugen->ForcedDespawn(); - pFeugen->Respawn(); - } - if (pStalagg) - { - pStalagg->ForcedDespawn(); - pStalagg->Respawn(); - } - } - } - - void KilledUnit(Unit* pVictim) - { - if (pVictim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(SAY_SLAY, m_creature); - } - - void JustDied(Unit* pKiller) - { - DoScriptText(SAY_DEATH, m_creature); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_THADDIUS, DONE); - - // Force Despawn of Adds - Creature* pFeugen = m_pInstance->GetSingleCreatureFromStorage(NPC_FEUGEN); - Creature* pStalagg = m_pInstance->GetSingleCreatureFromStorage(NPC_STALAGG); - - if (pFeugen) - pFeugen->ForcedDespawn(); - if (pStalagg) - pStalagg->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_pInstance) - return; - - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - // Berserk - if (m_uiBerserkTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_BESERK) == CAST_OK) // allow combat movement? - m_uiBerserkTimer = 10*MINUTE*IN_MILLISECONDS; - } - else - m_uiBerserkTimer -= uiDiff; - - // Polarity Shift - if (m_uiPolarityShiftTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_POLARITY_SHIFT, CAST_INTERRUPT_PREVIOUS) == CAST_OK) - { - DoScriptText(SAY_ELECT, m_creature); - DoScriptText(EMOTE_POLARITY_SHIFT, m_creature); - m_uiPolarityShiftTimer = 30*IN_MILLISECONDS; - } - } - else - m_uiPolarityShiftTimer -= uiDiff; - - // Chain Lightning - if (m_uiChainLightningTimer < uiDiff) - { - Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); - if (pTarget && DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H) == CAST_OK) - m_uiChainLightningTimer = 15*IN_MILLISECONDS; - } - else - m_uiChainLightningTimer -= uiDiff; - - // Ball Lightning if target not in melee range - // TODO: Verify, likely that the boss should attack any enemy in melee range before starting to cast - if (!m_creature->CanReachWithMeleeAttack(m_creature->getVictim())) - { - if (m_uiBallLightningTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_BALL_LIGHTNING) == CAST_OK) - m_uiBallLightningTimer = 1*IN_MILLISECONDS; - } - else - m_uiBallLightningTimer -= uiDiff; - } - else - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thaddius(Creature* pCreature) -{ - return new boss_thaddiusAI(pCreature); -} - -bool EffectDummyNPC_spell_thaddius_encounter(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget) -{ - switch (uiSpellId) - { - case SPELL_SHOCK_OVERLOAD: - if (uiEffIndex == EFFECT_INDEX_0) - { - // Only do something to Thaddius, and on the first hit. - if (pCreatureTarget->GetEntry() != NPC_THADDIUS || !pCreatureTarget->HasAura(SPELL_THADIUS_SPAWN)) - return true; - // remove Stun and then Cast - pCreatureTarget->RemoveAurasDueToSpell(SPELL_THADIUS_SPAWN); - pCreatureTarget->CastSpell(pCreatureTarget, SPELL_THADIUS_LIGHTNING_VISUAL, false); - } - return true; - case SPELL_THADIUS_LIGHTNING_VISUAL: - if (uiEffIndex == EFFECT_INDEX_0 && pCreatureTarget->GetEntry() == NPC_THADDIUS) - { - if (instance_naxxramas* pInstance = (instance_naxxramas*)pCreatureTarget->GetInstanceData()) - { - // Make Attackable - pCreatureTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pCreatureTarget->SetInCombatWithZone(); - } - } - return true; - } - return false; -} - /************ ** npc_tesla_coil ************/ @@ -386,10 +202,13 @@ struct MANGOS_DLL_DECL npc_tesla_coilAI : public Scripted_NoMovementAI if (m_uiOverloadTimer <= uiDiff) { m_uiOverloadTimer = 0; - m_creature->RemoveAurasDueToSpell(m_bToFeugen ? SPELL_FEUGEN_TESLA_PASSIVE : SPELL_STALAGG_TESLA_PASSIVE); - DoCastSpellIfCan(m_creature, SPELL_SHOCK_OVERLOAD, CAST_INTERRUPT_PREVIOUS); - DoScriptText(EMOTE_TESLA_OVERLOAD, m_creature); - m_pInstance->DoUseDoorOrButton(m_bToFeugen ? GO_CONS_NOX_TESLA_FEUGEN : GO_CONS_NOX_TESLA_STALAGG); + if (Creature* pThaddius = m_pInstance->GetSingleCreatureFromStorage(NPC_THADDIUS)) + { + m_creature->RemoveAurasDueToSpell(m_bToFeugen ? SPELL_FEUGEN_TESLA_PASSIVE : SPELL_STALAGG_TESLA_PASSIVE); + DoCastSpellIfCan(pThaddius, SPELL_SHOCK_OVERLOAD, CAST_INTERRUPT_PREVIOUS); + DoScriptText(EMOTE_TESLA_OVERLOAD, m_creature); + m_pInstance->DoUseDoorOrButton(m_bToFeugen ? GO_CONS_NOX_TESLA_FEUGEN : GO_CONS_NOX_TESLA_STALAGG); + } } else m_uiOverloadTimer -= uiDiff; @@ -422,19 +241,18 @@ struct MANGOS_DLL_DECL boss_thaddiusAddsAI : public ScriptedAI instance_naxxramas* m_pInstance; bool m_bIsRegularMode; - bool m_bFakeDeath; - bool m_bBothDead; + bool m_bIsDeath; uint32 m_uiHoldTimer; uint32 m_uiReviveTimer; uint32 m_uiMagneticPullTimer; + uint32 m_uiDeathCheck_Timer; void Reset() { - m_bFakeDeath = false; - m_bBothDead = false; + m_bIsDeath = false; - m_uiReviveTimer = 5*IN_MILLISECONDS; + m_uiDeathCheck_Timer = 1*IN_MILLISECONDS; m_uiHoldTimer = 2*IN_MILLISECONDS; m_uiMagneticPullTimer = 20*IN_MILLISECONDS; @@ -498,84 +316,51 @@ struct MANGOS_DLL_DECL boss_thaddiusAddsAI : public ScriptedAI if (Creature* pOther = GetOtherAdd()) { - if (boss_thaddiusAddsAI* pOtherAI = dynamic_cast (pOther->AI())) - { - if (pOtherAI->IsCountingDead()) - { - pOther->ForcedDespawn(); - pOther->Respawn(); - } - } + if (!pOther->isAlive()) + pOther->Respawn(); } // Reapply Chains if needed - if (!m_creature->HasAura(SPELL_FEUGEN_CHAIN) && !m_creature->HasAura(SPELL_STALAGG_CHAIN)) - JustRespawned(); + JustRespawned(); m_pInstance->SetData(TYPE_THADDIUS, FAIL); } - void Revive() - { - DoResetThreat(); - PauseCombatMovement(); - Reset(); - } - - bool IsCountingDead() - { - return m_bFakeDeath || m_creature->isDead(); - } - void PauseCombatMovement() { SetCombatMovement(false); - m_uiHoldTimer = 1500; + m_uiHoldTimer = 3000; } virtual void UpdateAddAI(const uint32 uiDiff) {} // Used for Add-specific spells void UpdateAI(const uint32 uiDiff) { - if (m_bBothDead) // This is the case while fighting Thaddius + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_bFakeDeath) + if (m_uiDeathCheck_Timer < uiDiff) { - if (m_uiReviveTimer < uiDiff) + if (m_pInstance) { - if (Creature* pOther = GetOtherAdd()) + if (Creature* Other = GetOtherAdd()) { - if (boss_thaddiusAddsAI* pOtherAI = dynamic_cast (pOther->AI())) + if (!Other->isAlive() && !m_bIsDeath) { - if (!pOtherAI->IsCountingDead()) // Raid was to slow to kill the second add - Revive(); - else - { - m_bBothDead = true; // Now both adds are counting dead - pOtherAI->m_bBothDead = true; - // Set both Teslas to overload - GUIDList lTeslaGUIDList; - m_pInstance->GetThadTeslaCreatures(lTeslaGUIDList); - for (GUIDList::const_iterator itr = lTeslaGUIDList.begin(); itr != lTeslaGUIDList.end(); ++itr) - { - if (Creature* pTesla = m_pInstance->instance->GetCreature(*itr)) - { - if (npc_tesla_coilAI* pTeslaAI = dynamic_cast (pTesla->AI())) - pTeslaAI->SetOverloading(); - } - } - } + m_bIsDeath = true; + m_uiDeathCheck_Timer = 6000; } + else if (!Other->isAlive() && m_bIsDeath) + { + Other->Respawn(); + m_bIsDeath = false; + m_uiDeathCheck_Timer = 1000; + } + else + m_uiDeathCheck_Timer = 1000; } } - else - m_uiReviveTimer -= uiDiff; - return; - } - - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + }else m_uiDeathCheck_Timer -= uiDiff; if (m_uiHoldTimer) // A short timer preventing combat movement after revive { @@ -603,37 +388,6 @@ struct MANGOS_DLL_DECL boss_thaddiusAddsAI : public ScriptedAI DoMeleeAttackIfReady(); } - void DamageTaken(Unit* pKiller, uint32& uiDamage) - { - if (uiDamage < m_creature->GetHealth()) - return; - - // Prevent glitch if in fake death - if (m_bFakeDeath) - { - uiDamage = 0; - return; - } - - // prevent death - uiDamage = 0; - m_bFakeDeath = true; - - m_creature->InterruptNonMeleeSpells(false); - m_creature->SetHealth(1); - m_creature->StopMoving(); - m_creature->ClearComboPointHolders(); - m_creature->RemoveAllAurasOnDeath(); - m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->ClearAllReactives(); - m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MoveIdle(); - m_creature->SetStandState(UNIT_STAND_STATE_DEAD); - - JustDied(pKiller); // Texts - } }; /************ @@ -740,6 +494,248 @@ CreatureAI* GetAI_boss_feugen(Creature* pCreature) return new boss_feugenAI(pCreature); } + +/************ +** boss_thaddius +************/ + +// Actually this boss behaves like a NoMovement Boss (SPELL_BALL_LIGHTNING) - but there are some movement packages used, unknown what this means! +struct MANGOS_DLL_DECL boss_thaddiusAI : public ScriptedAI +{ + boss_thaddiusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (instance_naxxramas*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + + Reset(); + } + + instance_naxxramas* m_pInstance; + bool m_bIsRegularMode; + bool m_bIsActiveCheck; + bool m_bIsActived; + + uint32 m_uiPolarityShiftTimer; + uint32 m_uiChainLightningTimer; + uint32 m_uiBallLightningTimer; + uint32 m_uiBerserkTimer; + uint32 m_uiActive_Timer; + + void Reset() + { + m_bIsActiveCheck = false; + m_bIsActived = false; + + m_uiActive_Timer = 1*IN_MILLISECONDS; + m_uiPolarityShiftTimer = 15*IN_MILLISECONDS; + m_uiChainLightningTimer = 8*IN_MILLISECONDS; + m_uiBallLightningTimer = 1*IN_MILLISECONDS; + m_uiBerserkTimer = 6*MINUTE*IN_MILLISECONDS; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void Aggro(Unit* pWho) + { + switch (urand(0,2)) + { + case 0: DoScriptText(SAY_AGGRO_1, m_creature); break; + case 1: DoScriptText(SAY_AGGRO_2, m_creature); break; + case 2: DoScriptText(SAY_AGGRO_3, m_creature); break; + } + } + + void JustReachedHome() + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_THADDIUS, FAIL); + + // Respawn Adds: + if (Creature* pFeugen = m_pInstance->GetSingleCreatureFromStorage(NPC_FEUGEN)) + { + if (!pFeugen->isAlive()) + pFeugen->Respawn(); + } + if (Creature* pStalagg = m_pInstance->GetSingleCreatureFromStorage(NPC_STALAGG)) + { + if (!pStalagg->isAlive()) + pStalagg->Respawn(); + } + } + + // Reset + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + // Delay reloading of CreatureAddon until Reached home for proper handling + // Also note that m_creature->LoadCreatureAddon(); must _not_ be called before m_creature->GetMotionMaster()->MoveTargetedHome(); + // Done this way, because MoveTargetHome ensures proper positioning (orientation) + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + + if (m_creature->isAlive()) + m_creature->GetMotionMaster()->MoveTargetedHome(); + + Reset(); + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(SAY_SLAY, m_creature); + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_THADDIUS, DONE); + } + + void SpellHit(Unit* who, const SpellEntry* pSpell) + { + switch (pSpell->Id) + { + case SPELL_SHOCK_OVERLOAD: + // Only do something to Thaddius, and on the first hit. + if (!m_creature->HasAura(SPELL_THADIUS_SPAWN)) + return; + // remove Stun and then Cast + m_creature->RemoveAurasDueToSpell(SPELL_THADIUS_SPAWN); + m_creature->CastSpell(m_creature, SPELL_THADIUS_LIGHTNING_VISUAL, true); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + break; + default: + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) + return; + + if (!m_bIsActived) + { + if (m_bIsActiveCheck) + { + if (m_uiActive_Timer < uiDiff) + { + m_bIsActived = true; + m_creature->CastSpell(m_creature, SPELL_THADIUS_LIGHTNING_VISUAL, true); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + m_uiActive_Timer = 1000; + }else m_uiActive_Timer -= uiDiff; + } + else + { + if (m_uiActive_Timer < uiDiff) + { + if(m_pInstance) + { + bool m_bIsAlive = false; + Creature* pStalagg; + Creature* pFeugen; + if (pStalagg = m_pInstance->GetSingleCreatureFromStorage(NPC_STALAGG)) + if (pStalagg->isAlive()) + m_bIsAlive = true; + if (pFeugen = m_pInstance->GetSingleCreatureFromStorage(NPC_FEUGEN)) + if (pFeugen->isAlive()) + m_bIsAlive = true; + + if (!m_bIsAlive) + { + m_bIsActiveCheck = true; + m_uiActive_Timer = 15000; + + GUIDList lTeslaGUIDList; + m_pInstance->GetThadTeslaCreatures(lTeslaGUIDList); + for (GUIDList::const_iterator itr = lTeslaGUIDList.begin(); itr != lTeslaGUIDList.end(); ++itr) + { + if (Creature* pTesla = m_pInstance->instance->GetCreature(*itr)) + { + if (npc_tesla_coilAI* pTeslaAI = dynamic_cast (pTesla->AI())) + pTeslaAI->SetOverloading(); + } + } + } + else + { + m_uiActive_Timer = 1000; + } + } + }else m_uiActive_Timer -= uiDiff; + } + } + else + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // Berserk + if (m_uiBerserkTimer < uiDiff) + { + if (DoCastSpellIfCan(m_creature, SPELL_BESERK) == CAST_OK) + m_uiBerserkTimer = 10*MINUTE*IN_MILLISECONDS; + } + else + m_uiBerserkTimer -= uiDiff; + + // Polarity Shift + if (m_uiPolarityShiftTimer < uiDiff) + { + if (DoCastSpellIfCan(m_creature, SPELL_POLARITY_SHIFT, CAST_INTERRUPT_PREVIOUS) == CAST_OK) + { + DoScriptText(SAY_ELECT, m_creature); + DoScriptText(EMOTE_POLARITY_SHIFT, m_creature); + m_uiPolarityShiftTimer = 30*IN_MILLISECONDS; + } + } + else + m_uiPolarityShiftTimer -= uiDiff; + + // Chain Lightning + if (m_uiChainLightningTimer < uiDiff) + { + Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + if (pTarget && DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H) == CAST_OK) + m_uiChainLightningTimer = 15*IN_MILLISECONDS; + } + else + m_uiChainLightningTimer -= uiDiff; + + // Ball Lightning if target not in melee range + if (!m_creature->CanReachWithMeleeAttack(m_creature->getVictim(), 10.0f)) + { + SetCombatMovement(false); + if (m_uiBallLightningTimer < uiDiff) + { + if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_BALL_LIGHTNING) == CAST_OK) + m_uiBallLightningTimer = 1*IN_MILLISECONDS; + } + else + m_uiBallLightningTimer -= uiDiff; + } + else + { + SetCombatMovement(true); + DoMeleeAttackIfReady(); + } + } + } +}; + +CreatureAI* GetAI_boss_thaddius(Creature* pCreature) +{ + return new boss_thaddiusAI(pCreature); +} + void AddSC_boss_thaddius() { Script* pNewScript; @@ -747,7 +743,6 @@ void AddSC_boss_thaddius() pNewScript = new Script; pNewScript->Name = "boss_thaddius"; pNewScript->GetAI = &GetAI_boss_thaddius; - pNewScript->pEffectDummyNPC = &EffectDummyNPC_spell_thaddius_encounter; pNewScript->RegisterSelf(); pNewScript = new Script; @@ -763,6 +758,5 @@ void AddSC_boss_thaddius() pNewScript = new Script; pNewScript->Name = "npc_tesla_coil"; pNewScript->GetAI = &GetAI_npc_tesla_coil; - pNewScript->pEffectDummyNPC = &EffectDummyNPC_spell_thaddius_encounter; pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/naxxramas/instance_naxxramas.cpp b/scripts/northrend/naxxramas/instance_naxxramas.cpp index 0c70bfc698..26ceb5cab7 100644 --- a/scripts/northrend/naxxramas/instance_naxxramas.cpp +++ b/scripts/northrend/naxxramas/instance_naxxramas.cpp @@ -68,6 +68,7 @@ void instance_naxxramas::OnCreatureCreate(Creature* pCreature) case NPC_BLAUMEUX: case NPC_RIVENDARE: case NPC_GOTHIK: + case NPC_RAZUVIOUS: case NPC_KELTHUZAD: case NPC_THE_LICHKING: m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); @@ -263,6 +264,7 @@ void instance_naxxramas::SetData(uint32 uiType, uint32 uiData) if (uiData == DONE) { DoUseDoorOrButton(GO_ARAC_FAER_DOOR); + DoUseDoorOrButton(GO_ARAC_FAER_WEB); DoUseDoorOrButton(GO_ARAC_MAEX_OUTER_DOOR); } m_auiEncounter[uiType] = uiData; @@ -335,13 +337,27 @@ void instance_naxxramas::SetData(uint32 uiType, uint32 uiData) break; case TYPE_FOUR_HORSEMEN: m_auiEncounter[uiType] = uiData; - DoUseDoorOrButton(GO_MILI_HORSEMEN_DOOR); + if (uiData != SPECIAL) + DoUseDoorOrButton(GO_MILI_HORSEMEN_DOOR); if (uiData == DONE) { DoUseDoorOrButton(GO_MILI_EYE_RAMP); DoRespawnGameObject(GO_MILI_PORTAL, 30*MINUTE); DoRespawnGameObject(instance->IsRegularDifficulty() ? GO_CHEST_HORSEMEN_NORM : GO_CHEST_HORSEMEN_HERO, 30*MINUTE); m_uiTauntTimer = 5000; + + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + pPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_HORSEMEN_CREDIT); + } + } + } } break; case TYPE_PATCHWERK: @@ -453,10 +469,10 @@ uint32 instance_naxxramas::GetData(uint32 uiType) switch(uiType) { // Number of Heigan traps per area - case TYPE_MAX_HEIGAN_TRAPS_1: return m_avuiHeiganTraps[0].size(); - case TYPE_MAX_HEIGAN_TRAPS_2: return m_avuiHeiganTraps[1].size(); - case TYPE_MAX_HEIGAN_TRAPS_3: return m_avuiHeiganTraps[2].size(); - case TYPE_MAX_HEIGAN_TRAPS_4: return m_avuiHeiganTraps[3].size(); + case TYPE_MAX_HEIGAN_TRAPS_1: return m_alHeiganTrapGuids[0].size(); + case TYPE_MAX_HEIGAN_TRAPS_2: return m_alHeiganTrapGuids[1].size(); + case TYPE_MAX_HEIGAN_TRAPS_3: return m_alHeiganTrapGuids[2].size(); + case TYPE_MAX_HEIGAN_TRAPS_4: return m_alHeiganTrapGuids[3].size(); } return 0; } @@ -693,6 +709,34 @@ bool AreaTrigger_at_naxxramas(Player* pPlayer, AreaTriggerEntry const* pAt) } } } + + if (pAt->id == AREATRIGGER_SAPPHIRON) + { + instance_naxxramas* pInstance = (instance_naxxramas*)pPlayer->GetInstanceData(); + + if (!pInstance) + return false; + + if (pPlayer->isGameMaster()) + return false; + + uint8 uiWingsCleared = 0; + + if (pInstance->GetData(TYPE_MAEXXNA) == DONE) + ++uiWingsCleared; + + if (pInstance->GetData(TYPE_LOATHEB) == DONE) + ++uiWingsCleared; + +// if (pInstance->GetData(TYPE_FOUR_HORSEMEN) == DONE) + if (pInstance->GetData(TYPE_GOTHIK) == DONE) + ++uiWingsCleared; + + if (pInstance->GetData(TYPE_THADDIUS) == DONE) + ++uiWingsCleared; + + return !(uiWingsCleared == 4); // return true->stop + } return false; } diff --git a/scripts/northrend/naxxramas/naxxramas.h b/scripts/northrend/naxxramas/naxxramas.h index e07e01ab2a..599b30b1a0 100644 --- a/scripts/northrend/naxxramas/naxxramas.h +++ b/scripts/northrend/naxxramas/naxxramas.h @@ -72,6 +72,8 @@ enum NPC_FEUGEN = 15930, NPC_TESLA_COIL = 16218, + NPC_RAZUVIOUS = 16061, + NPC_ZELIEK = 16063, NPC_THANE = 16064, NPC_BLAUMEUX = 16065, @@ -151,6 +153,10 @@ enum AREATRIGGER_KELTHUZAD = 4112, AREATRIGGER_GOTHIK = 4116, AREATRIGGER_THADDIUS_DOOR = 4113, + AREATRIGGER_SAPPHIRON = 4156, + + + SPELL_HORSEMEN_CREDIT = 59450, // Achievement-related ACHIEV_CRIT_SAFETY_DANCE_N = 7264, // Heigan, achievs 1996, 2139 @@ -225,9 +231,6 @@ class MANGOS_DLL_DECL instance_naxxramas : public ScriptedInstance void GetGothSummonPointCreatures(std::list &lList, bool bRightSide); bool IsInRightSideGothArea(Unit* pUnit); - // Heigan - uint64 GetHeiganTrapData64(uint8 uiAreaIndex, uint32 uiIndex); - // thaddius void GetThadTeslaCreatures(GUIDList &lList){ lList = m_lThadTeslaCoilList; }; @@ -247,8 +250,6 @@ class MANGOS_DLL_DECL instance_naxxramas : public ScriptedInstance UNORDERED_MAP m_mGothTriggerMap; GUIDList m_alHeiganTrapGuids[MAX_HEIGAN_TRAP_AREAS]; - std::vector m_avuiHeiganTraps[MAX_HEIGAN_TRAP_AREAS]; - float m_fChamberCenterX; float m_fChamberCenterY; float m_fChamberCenterZ; diff --git a/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp b/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp index c15ca424a3..700832eeb6 100644 --- a/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp +++ b/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp @@ -41,6 +41,7 @@ enum SPELL_ARCANE_STORM_H = 61694, SPELL_VORTEX = 56105, SPELL_VORTEX_DMG_AURA = 56266, // on 10 sec, deal 2000 damage all player around caster + SPELL_VORTEX_DMG_TICK = 56256, SPELL_VORTEX_VISUAL = 55873, // visual effect around platform. summon trigger SPELL_VORTEX_CHANNEL = 56237, // Malygos Channel Effect SPELL_POWER_SPARK = 56152, // if spark reach malygos then buff him @@ -166,7 +167,15 @@ enum //hacks SPELL_FLIGHT = 59553, - MODEL_ID_INVISIBLE = 11686 + MODEL_ID_INVISIBLE = 11686, + + ACHIEV_DENYIN_THE_SCION = 2148, + ACHIEV_DENYIN_THE_SCION_H = 2149, + ACHIEV_SPELLWEAVERS_DOWNFALL = 622, + ACHIEV_SPELLWEAVERS_DOWNFALL_H = 623, + ACHIEV_YOU_DONT_HAVE_ETERNITY = 1874, //Speedkill + ACHIEV_YOU_DONT_HAVE_ETERNITY_H = 1875 + }; struct LocationsXY @@ -256,13 +265,15 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI uint32 m_uiSurgeOfPowerTimer; uint32 m_uiCheckTimer; uint32 m_uiMovingSteps; + uint32 m_uiVortexDmgCount; + uint32 m_uiSpeedKillTimer; ObjectGuid m_uiTargetSparkPortalGUID; uint8 m_uiWP; bool m_bReadyForWPMove; bool m_bPortalNeedRes; - + bool m_bIsInTimeAchiev; float m_fAngle; void Reset() @@ -271,6 +282,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI m_uiMovingSteps = 0; m_bReadyForWPMove = true; m_bPortalNeedRes = false; + m_bIsInTimeAchiev = true; m_uiPortalNeedResTimer = 0; m_uiPhase = PHASE_INTRO; m_uiSubPhase = 0; @@ -287,7 +299,10 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI m_uiArcanePulseTimer = 1000; m_uiSurgeOfPowerTimer = 8000; m_uiCheckTimer = 1000; + m_uiVortexDmgCount = 20; + m_uiSpeedKillTimer = 6*MINUTE*IN_MILLISECONDS; + m_uiTargetSparkPortalGUID.Clear(); m_uiWP = 0; m_uiSpeechCount = 0; m_uiSpeechTimer = 15000; @@ -295,6 +310,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI m_creature->SetSpeedRate(MOVE_WALK, 6.0f); m_creature->SetSpeedRate(MOVE_FLIGHT, 2.0f); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); m_creature->SetLevitate(true); m_creature->GetMotionMaster()->Clear(); @@ -329,14 +345,33 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_MALYGOS, IN_PROGRESS); + + if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + m_creature->SetRespawnTime(999999999); } void JustDied(Unit* pKiller) { DoScriptText(SAY_DEATH, m_creature); DespawnCreatures(NPC_STATIC_FIELD); + Map* pMap = m_creature->GetMap(); + + AchievementEntry const* YouDontHaveEternity = GetAchievementStore()->LookupEntry(m_bIsRegularMode?ACHIEV_YOU_DONT_HAVE_ETERNITY:ACHIEV_YOU_DONT_HAVE_ETERNITY_H); + AchievementEntry const* SpellweaversDownfall = GetAchievementStore()->LookupEntry(m_bIsRegularMode?ACHIEV_SPELLWEAVERS_DOWNFALL:ACHIEV_SPELLWEAVERS_DOWNFALL_H); + + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + itr->getSource()->KilledMonsterCredit(NPC_MALYGOS); + itr->getSource()->CompletedAchievement(SpellweaversDownfall); + if(m_bIsInTimeAchiev) + itr->getSource()->CompletedAchievement(YouDontHaveEternity); + } m_creature->SummonCreature(NPC_ALEXSTRASZA, CENTER_X+20.0f, CENTER_Y+20.0f, AIR_Z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); - m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z-500.0f, 0); + m_creature->SetRespawnTime(999999999); + pMap->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z-500.0f, 0); m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z-400.0f, 26); } @@ -387,7 +422,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI if (uiEntry == NPC_STATIC_FIELD) { - pSummoned->CastSpell(m_creature, SPELL_STATIC_FIELD, false, 0, 0, m_creature->GetObjectGuid()); + pSummoned->CastSpell(pSummoned, SPELL_STATIC_FIELD, false, 0, 0, m_creature->GetObjectGuid()); pSummoned->ForcedDespawn(30000); } @@ -403,17 +438,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI pSummoned->EnterVehicle(pDiskVehicle, 0); } pSummoned->SetInCombatWithZone(); - } - } - - void SummonedCreatureJustDied(Creature* pSummoned) - { - if (Creature* pDisk = m_creature->getVictim()->SummonCreature(NPC_HOVER_DISK, pSummoned->GetPositionX(), pSummoned->GetPositionY(), pSummoned->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - pDisk->setFaction(35); - pDisk->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); - pDisk->CastSpell(pDisk, SPELL_FLIGHT, true); - pDisk->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pSummoned->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } } @@ -507,7 +532,6 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI if (m_uiSubPhase == SUBPHASE_TALK) { DoScriptText(SAY_AGGRO2, m_creature); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); AntiMagicShell(); m_uiShellTimer = urand(15000, 17000); m_uiSubPhase = 0; @@ -646,13 +670,15 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI Map::PlayerList const &lPlayers = pMap->GetPlayers(); for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { - if (itr->getSource()->isDead()) + if (itr->getSource()->isDead() || itr->getSource()->isGameMaster()) continue; //Far sight, should be vehicle but this is enough //Crash the server in group update far members, dunno why //I will try to use this again, maybe I have fix... itr->getSource()->GetCamera().SetView(pVortex); + m_uiVortexDmgCount = 20; + // this one does not work good somehow itr->getSource()->CastSpell(itr->getSource(), SPELL_VORTEX_DMG_AURA, true); } } @@ -667,12 +693,20 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI { if (Creature *pVortex = m_creature->SummonCreature(NPC_VORTEX, VortexLoc[m_uiVortexPhase-4].x, VortexLoc[m_uiVortexPhase-4].y, FLOOR_Z+urand(10, 25), 0, TEMPSUMMON_TIMED_DESPAWN, 3000)) { + bool bDoVortexDmg = false; + + if ((m_uiVortexDmgCount--)%2) + bDoVortexDmg = true; + Map::PlayerList const &lPlayers = pMap->GetPlayers(); for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { - if (itr->getSource()->isDead()) + if (!itr->getSource() || itr->getSource()->isDead() || itr->getSource()->isGameMaster()) continue; + if (bDoVortexDmg && !itr->getSource()->HasAura(SPELL_VORTEX_DMG_AURA)) + itr->getSource()->CastSpell(itr->getSource(),SPELL_VORTEX_DMG_TICK,true); + itr->getSource()->KnockBackFrom(pVortex, -float(pVortex->GetDistance2d(itr->getSource())), 7); } } @@ -719,6 +753,9 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI { DoCast(m_creature, m_bIsRegularMode ? SPELL_ARCANE_BREATH : SPELL_ARCANE_BREATH_H); m_uiArcaneBreathTimer = urand(13000, 16000); + // Don't explode during vortex + if (m_uiVortexTimer < 7000) + m_uiVortexTimer = 7000; } else m_uiArcaneBreathTimer -= uiDiff; @@ -789,7 +826,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI m_uiTimer = 2000; } else - m_uiTimer -= uiDiff; + m_uiTimer -= uiDiff; } else if (m_uiPhase == PHASE_ADDS) { @@ -802,6 +839,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI m_uiWP = urand(0, 3); m_creature->GetMotionMaster()->MovePoint(POINT_ID_PHASE_2_WP, WPs[m_uiWP].x, WPs[m_uiWP].y, AIR_Z); m_uiTimer = 15000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } else m_uiTimer -= uiDiff; @@ -869,18 +907,21 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI m_uiTimer -= uiDiff; } - if (m_uiSubPhase != SUBPHASE_DEEP_BREATH && m_uiShellTimer <= uiDiff) + if (m_uiShellTimer <= uiDiff) { - m_creature->GetMotionMaster()->Clear(); - m_creature->StopMoving(); + if (m_uiSubPhase != SUBPHASE_DEEP_BREATH) + { + m_creature->GetMotionMaster()->Clear(); + m_creature->StopMoving(); - if (!urand(0, 3)) - DoScriptText(SAY_ARCANE_OVERLOAD, m_creature); + if (!urand(0, 3)) + DoScriptText(SAY_ARCANE_OVERLOAD, m_creature); - AntiMagicShell(); - m_uiShellTimer = urand(15000, 17000); - m_bReadyForWPMove = true; - m_uiTimer = 2000; + AntiMagicShell(); + m_uiShellTimer = urand(15000, 17000); + m_bReadyForWPMove = true; + m_uiTimer = 2000; + } } else m_uiShellTimer -= uiDiff; @@ -912,6 +953,7 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI pTempCaster->CastSpell(pTempCaster, SPELL_DESTROY_PLATFORM_BOOM, false); } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); m_creature->SetInCombatWithZone(); m_uiSubPhase = SUBPHASE_DESTROY_PLATFORM_2; @@ -1039,8 +1081,13 @@ struct MANGOS_DLL_DECL boss_malygosAI : public ScriptedAI else m_uiSurgeOfPowerTimer -= uiDiff; } + if(m_uiSpeedKillTimer < uiDiff) + m_bIsInTimeAchiev = false; + else + m_uiSpeedKillTimer -= uiDiff; - DoMeleeAttackIfReady(); + if (m_uiPhase != PHASE_DRAGONS) + DoMeleeAttackIfReady(); } }; @@ -1090,9 +1137,12 @@ struct MANGOS_DLL_DECL npc_power_sparkAI : public ScriptedAI m_creature->RemoveAllAuras(); m_creature->SetHealth(1); m_creature->CastSpell(m_creature, SPELL_POWER_SPARK_PLAYERS, true); + m_creature->SetDisplayId(MODEL_ID_INVISIBLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->GetMotionMaster()->Clear(); m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z+1.5f, 0); - m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z+1.5f,26); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z+1.5f, 1000); m_creature->ForcedDespawn(60000); } } @@ -1160,10 +1210,26 @@ struct MANGOS_DLL_DECL npc_nexus_lordAI : public ScriptedAI m_fVehicleOldY = 0.0f; m_uiArcaneShockTimer = urand(8000, 9000); m_uiHasteTimer = urand(10000, 12000); + m_creature->clearUnitState(UNIT_STAT_CAN_NOT_REACT); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth()) + { + if (Creature* pDisk = m_creature->SummonCreature(NPC_HOVER_DISK, m_creature->GetPositionX(), m_creature->GetPositionY(), 267.00f, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 9000000)) + { + pDisk->SetLevitate(true); + pDisk->CastSpell(pDisk, SPELL_FLIGHT, true); + pDisk->SetSpeedRate(MOVE_WALK, 1.5f); + } + } } void UpdateAI(const uint32 uiDiff) { + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -1182,7 +1248,14 @@ struct MANGOS_DLL_DECL npc_nexus_lordAI : public ScriptedAI m_fVehicleOldX = fX; m_fVehicleOldY = fY; - Unit* pTarget = m_creature->getVictim(); + Unit* pTarget = NULL; + + //We want to attack the Player on the Disc and not the Disc itself + if(m_creature->getVictim()->GetEntry() == NPC_HOVER_DISK) + pTarget = m_creature->getVictim()->GetVehicle()->GetPassenger(0); + else + pTarget = m_creature->getVictim(); + if (m_creature->IsWithinDistInMap(pTarget, 4.0f)) { pDisk->GetMotionMaster()->Clear(); @@ -1227,7 +1300,7 @@ struct MANGOS_DLL_DECL npc_nexus_lordAI : public ScriptedAI DoMeleeAttackIfReady(); } -}; +}; /*###### ## npc_scion_of_eternity @@ -1249,21 +1322,62 @@ struct MANGOS_DLL_DECL npc_scion_of_eternityAI : public ScriptedAI m_uiArcaneBarrageTimer = urand(4000, 12000); } + void JustDied(Unit* killer) + { + if(killer->GetTypeId() == TYPEID_PLAYER) + { + Player* pPlayer = (Player*)killer; + + if(pPlayer->GetVehicle()) + { + AchievementEntry const *DenyinTheSc = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_DENYIN_THE_SCION : ACHIEV_DENYIN_THE_SCION_H); + if(DenyinTheSc) + { + pPlayer->CompletedAchievement(DenyinTheSc); + } + } + } + + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(damage > m_creature->GetHealth()) + { + if (Creature* pDisk = m_creature->SummonCreature(NPC_HOVER_DISK, m_creature->GetPositionX(), m_creature->GetPositionY(), 267.00f, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 9000000)) + { + pDisk->SetLevitate(true); + pDisk->CastSpell(pDisk, SPELL_FLIGHT, true); + pDisk->SetSpeedRate(MOVE_WALK, 1.5f); + } + } + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (VehicleKit* pDiskVehicle = m_creature->GetVehicle()) + { + if (Unit* pDiskUnit = pDiskVehicle->GetBase()) + { + //We want to attack the Player on the Disc and not the Disc itself + if (m_creature->getVictim()->GetEntry() == NPC_HOVER_DISK && m_creature->getVictim()->GetVehicle()) + if (m_creature->getVictim()->GetVehicle()->GetPassenger(0)) + m_creature->Attack(m_creature->getVictim()->GetVehicle()->GetPassenger(0), false); + } + } + if (m_uiArcaneBarrageTimer <= uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (!pTarget->GetVehicle()) - { - int32 uiDmg = m_bIsRegularMode ? urand(14138, 15862) : urand(16965, 19035); - m_creature->CastCustomSpell(pTarget, SPELL_ARCANE_BARRAGE, &uiDmg, 0, 0, true); - m_uiArcaneBarrageTimer = urand(4000, 12000); - } + if (pTarget->GetVehicle()) + pTarget = pTarget->GetVehicle()->GetPassenger(0); + int32 uiDmg = m_bIsRegularMode ? urand(14138, 15862) : urand(16965, 19035); + m_creature->CastCustomSpell(pTarget, SPELL_ARCANE_BARRAGE, &uiDmg, 0, 0, true); + m_uiArcaneBarrageTimer = urand(4000, 12000); } } else @@ -1271,7 +1385,7 @@ struct MANGOS_DLL_DECL npc_scion_of_eternityAI : public ScriptedAI DoMeleeAttackIfReady(); } -}; +}; /*###### ## npc_hover_disk @@ -1303,6 +1417,11 @@ struct MANGOS_DLL_DECL npc_hover_diskAI : public ScriptedAI { } + void DamageTaken(Unit *done_by, uint32 &damage) + { // hover disk should not be damaged + damage = 0; + } + void UpdateAI(const uint32 uiDiff) { if (m_uiCheckTimer <= uiDiff) @@ -1320,7 +1439,7 @@ struct MANGOS_DLL_DECL npc_hover_diskAI : public ScriptedAI m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z+1.5f, 0); - m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z+1.5f, 26); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), FLOOR_Z+1.5f, 4000); m_bMoved = true; m_bPassengerHere = false; } @@ -1374,7 +1493,7 @@ struct MANGOS_DLL_DECL npc_alexstraszaAI : public ScriptedAI { case 0: if (m_pInstance) - if (Creature* pMalygos = m_pInstance->GetSingleCreatureFromStorage(NPC_MALYGOS)) + if (Creature* pMalygos = m_pInstance->GetSingleCreatureFromStorage(NPC_MALYGOS)) pMalygos->RemoveCorpse(); DoScriptText(SAY_OUTRO1, m_creature); m_uiTimer = 5000; @@ -1392,7 +1511,7 @@ struct MANGOS_DLL_DECL npc_alexstraszaAI : public ScriptedAI m_uiTimer = 19500; break; case 4: - DoCast(m_creature, SPELL_ALEXSTRASZAS_GIFT_BEAM); + DoCast(m_creature, SPELL_ALEXSTRASZAS_GIFT_BEAM, true); m_uiTimer = 3000; break; case 5: @@ -1444,17 +1563,17 @@ CreatureAI* GetAI_npc_power_spark(Creature* pCreature) CreatureAI* GetAI_npc_nexus_lord(Creature* pCreature) { return new npc_nexus_lordAI(pCreature); -} +} CreatureAI* GetAI_npc_scion_of_eternity(Creature* pCreature) { return new npc_scion_of_eternityAI(pCreature); -} +} CreatureAI* GetAI_npc_hover_disk(Creature* pCreature) { return new npc_hover_diskAI(pCreature); -} +} CreatureAI* GetAI_npc_alexstrasza(Creature* pCreature) { diff --git a/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp b/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp index 3d6b369076..678f9c4734 100644 --- a/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp +++ b/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp @@ -27,41 +27,22 @@ EndScriptData */ struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance { - instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) - { - difficulty = pMap->GetDifficulty(); - Initialize(); - } + instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();} std::string strInstData; uint32 m_auiEncounter[MAX_ENCOUNTER]; - Difficulty difficulty; - - uint32 m_uiFocusingIrisGUID; - uint32 m_uiGiftGUID; - uint32 m_uiHeartGUID; + uint32 m_uiFocusingIrisActualEntry; + ObjectGuid m_uiGiftActualGuid; + ObjectGuid m_uiHeartActualGuid; void Initialize() { memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - switch (difficulty) - { - case RAID_DIFFICULTY_10MAN_NORMAL: - m_uiFocusingIrisGUID = GO_FOCUSING_IRIS; - m_uiGiftGUID = GO_ALEXSTRASZAS_GIFT; - m_uiHeartGUID = GO_HEART_OF_MAGIC; - break; - case RAID_DIFFICULTY_25MAN_NORMAL: - m_uiFocusingIrisGUID = GO_FOCUSING_IRIS_H; - m_uiGiftGUID = GO_ALEXSTRASZAS_GIFT_H; - m_uiHeartGUID = GO_HEART_OF_MAGIC_H; - break; - default: - break; - }; - + m_uiFocusingIrisActualEntry = 0; + m_uiGiftActualGuid.Clear(); + m_uiHeartActualGuid.Clear(); } void OnCreatureCreate(Creature* pCreature) @@ -69,27 +50,33 @@ struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance switch(pCreature->GetEntry()) { case NPC_MALYGOS: - m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); pCreature->SetActiveObjectState(true); break; } + m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); } - + void OnObjectCreate(GameObject* pGo) { switch(pGo->GetEntry()) { case GO_PLATFORM: case GO_EXIT_PORTAL: + break; case GO_FOCUSING_IRIS: case GO_FOCUSING_IRIS_H: + m_uiFocusingIrisActualEntry = pGo->GetEntry(); + break; case GO_ALEXSTRASZAS_GIFT: case GO_ALEXSTRASZAS_GIFT_H: + m_uiGiftActualGuid = pGo->GetObjectGuid(); + break; case GO_HEART_OF_MAGIC: case GO_HEART_OF_MAGIC_H: - m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); + m_uiHeartActualGuid = pGo->GetObjectGuid(); break; } + m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); } bool IsEncounterInProgress() const @@ -109,7 +96,7 @@ struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance { if (uiData == NOT_STARTED) { - if (GameObject* pFocusingIris = GetSingleGameObjectFromStorage(m_uiFocusingIrisGUID)) + if (GameObject* pFocusingIris = GetSingleGameObjectFromStorage(m_uiFocusingIrisActualEntry)) { pFocusingIris->SetGoState(GO_STATE_READY); pFocusingIris->SetPhaseMask(1, true); @@ -121,7 +108,7 @@ struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance } if (uiData == IN_PROGRESS) { - if (GameObject* pFocusingIris = GetSingleGameObjectFromStorage(m_uiFocusingIrisGUID)) + if (GameObject* pFocusingIris = GetSingleGameObjectFromStorage(m_uiFocusingIrisActualEntry)) pFocusingIris->SetPhaseMask(2, true); if (GameObject* pExitPortal = GetSingleGameObjectFromStorage(GO_EXIT_PORTAL)) pExitPortal->SetPhaseMask(2, true); @@ -130,8 +117,14 @@ struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance { if (GameObject* pExitPortal = GetSingleGameObjectFromStorage(GO_EXIT_PORTAL)) pExitPortal->SetPhaseMask(1, true); - DoRespawnGameObject(m_uiGiftGUID, HOUR*IN_MILLISECONDS); - DoRespawnGameObject(m_uiHeartGUID, HOUR*IN_MILLISECONDS); + DoRespawnGameObject(m_uiGiftActualGuid, HOUR*IN_MILLISECONDS); + DoRespawnGameObject(m_uiHeartActualGuid, HOUR*IN_MILLISECONDS); + //hack to make loot accessible + if (GameObject* pPlatform = GetSingleGameObjectFromStorage(GO_PLATFORM)) + { + pPlatform->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED); + pPlatform->Respawn(); + } } m_auiEncounter[0] = uiData; break; @@ -183,7 +176,6 @@ struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance } return 0; } - }; InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) diff --git a/scripts/northrend/nexus/nexus/boss_ormorok.cpp b/scripts/northrend/nexus/nexus/boss_ormorok.cpp index 78c0ff0b56..54acc6b149 100644 --- a/scripts/northrend/nexus/nexus/boss_ormorok.cpp +++ b/scripts/northrend/nexus/nexus/boss_ormorok.cpp @@ -84,7 +84,7 @@ struct MANGOS_DLL_DECL boss_ormorokAI : public ScriptedAI void Reset() { - m_uiSpellCrystalSpikesTimer = 12*IN_MILLISECONDS; + m_uiSpellCrystalSpikesTimer = 12*IN_MILLISECONDS; m_uiTrampleTimer = 10*IN_MILLISECONDS; m_uiReflectionTimer = 30*IN_MILLISECONDS; m_uiSummonTanglerTimer = 17*IN_MILLISECONDS; @@ -98,6 +98,9 @@ struct MANGOS_DLL_DECL boss_ormorokAI : public ScriptedAI void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ORMOROK, IN_PROGRESS); } void JustDied(Unit* pKiller) @@ -113,7 +116,7 @@ struct MANGOS_DLL_DECL boss_ormorokAI : public ScriptedAI DoScriptText(SAY_KILL, m_creature); } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -225,7 +228,7 @@ struct MANGOS_DLL_DECL mob_crystal_spikeAI : public Scripted_NoMovementAI m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 uiDiff) { if (m_uiCrystalSpikePreVisualTimer < uiDiff) { @@ -242,8 +245,8 @@ struct MANGOS_DLL_DECL mob_crystal_spikeAI : public Scripted_NoMovementAI } else m_uiCrystallSpikeDamageTimer -= uiDiff; - } -}; + } +}; CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) { @@ -261,7 +264,7 @@ struct MANGOS_DLL_DECL mob_crystalline_tanglerAI : public ScriptedAI m_uiRootsTimer = 1*IN_MILLISECONDS; } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 uiDiff) { if (m_uiRootsTimer < uiDiff) { @@ -272,9 +275,9 @@ struct MANGOS_DLL_DECL mob_crystalline_tanglerAI : public ScriptedAI else m_uiRootsTimer -= uiDiff; - DoMeleeAttackIfReady(); - } -}; + DoMeleeAttackIfReady(); + } +}; CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) { diff --git a/scripts/northrend/nexus/nexus/instance_nexus.cpp b/scripts/northrend/nexus/nexus/instance_nexus.cpp index 8caa0d4f3c..6f7c28fbb1 100644 --- a/scripts/northrend/nexus/nexus/instance_nexus.cpp +++ b/scripts/northrend/nexus/nexus/instance_nexus.cpp @@ -31,13 +31,20 @@ bool GOUse_go_containment_sphere(Player* pPlayer, GameObject* pGo) if (!pInstance) return false; + uint32 type = 0; + switch(pGo->GetEntry()) { - case GO_CONTAINMENT_SPHERE_TELESTRA: pInstance->SetData(TYPE_TELESTRA, SPECIAL); break; - case GO_CONTAINMENT_SPHERE_ANOMALUS: pInstance->SetData(TYPE_ANOMALUS, SPECIAL); break; - case GO_CONTAINMENT_SPHERE_ORMOROK: pInstance->SetData(TYPE_ORMOROK, SPECIAL); break; + case GO_CONTAINMENT_SPHERE_TELESTRA: type = TYPE_TELESTRA; break; + case GO_CONTAINMENT_SPHERE_ANOMALUS: type = TYPE_ANOMALUS; break; + case GO_CONTAINMENT_SPHERE_ORMOROK: type = TYPE_ORMOROK; break; + default: + return false; } + if (pInstance->GetData(type) == DONE) + pInstance->SetData(type, SPECIAL); + if (Creature *pCaster = GetClosestCreatureWithEntry(pGo, NPC_BREATH_CASTER, 15.0f)) pCaster->ForcedDespawn(); @@ -150,11 +157,9 @@ void instance_nexus::SetData(uint32 uiType, uint32 uiData) Creature* pCreature = GetSingleCreatureFromStorage(NPC_KERISTRASZA); if (pCreature && pCreature->isAlive()) { - if (pCreature->isAlive()) - { - pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - pCreature->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); - } + pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE | UNIT_FLAG_OOC_NOT_ATTACKABLE + | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + pCreature->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); } } @@ -212,6 +217,9 @@ void instance_nexus::Load(const char* chrIn) { if (m_auiEncounter[i] == IN_PROGRESS) m_auiEncounter[i] = NOT_STARTED; + + if (m_auiEncounter[i] == SPECIAL) + m_auiEncounter[i] = (i == TYPE_KERISTRASZA) ? NOT_STARTED : DONE; } OUT_LOAD_INST_DATA_COMPLETE; diff --git a/scripts/northrend/nexus/oculus/boss_drakos.cpp b/scripts/northrend/nexus/oculus/boss_drakos.cpp index 98806afdba..339873fcab 100644 --- a/scripts/northrend/nexus/oculus/boss_drakos.cpp +++ b/scripts/northrend/nexus/oculus/boss_drakos.cpp @@ -93,7 +93,7 @@ struct MANGOS_DLL_DECL boss_drakosAI : public ScriptedAI MagicPull20 = false; } - void Aggro(Unit* who) + void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); @@ -101,7 +101,7 @@ struct MANGOS_DLL_DECL boss_drakosAI : public ScriptedAI m_pInstance->SetData(TYPE_DRAKOS, IN_PROGRESS); } - void JustDied(Unit* killer) + void JustDied(Unit* pKiller) { DoScriptText(SAY_DEATH, m_creature); @@ -109,7 +109,7 @@ struct MANGOS_DLL_DECL boss_drakosAI : public ScriptedAI m_pInstance->SetData(TYPE_DRAKOS, DONE); } - void KilledUnit(Unit *victim) + void KilledUnit(Unit* pVictim) { switch (urand(0, 2)) { @@ -119,9 +119,9 @@ struct MANGOS_DLL_DECL boss_drakosAI : public ScriptedAI } } - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + void SpellHitTarget(Unit *pTarget, const SpellEntry *pSpell) { - if (spell->Id == SPELL_MAGIC_PULL) + if (pSpell->Id == SPELL_MAGIC_PULL) if (pTarget->GetTypeId() == TYPEID_PLAYER) DoCast(pTarget, SPELL_MAGIC_PULL_EFFECT, true); } diff --git a/scripts/northrend/nexus/oculus/boss_eregos.cpp b/scripts/northrend/nexus/oculus/boss_eregos.cpp index 02024d6327..8f3d32d286 100644 --- a/scripts/northrend/nexus/oculus/boss_eregos.cpp +++ b/scripts/northrend/nexus/oculus/boss_eregos.cpp @@ -104,29 +104,25 @@ struct MANGOS_DLL_DECL boss_eregosAI : public ScriptedAI void MoveInLineOfSight(Unit* pWho) { - if(pWho->GetTypeId() == TYPEID_PLAYER - && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) - && !((Player*)pWho)->isGameMaster() - && m_creature->IsWithinDistInMap(pWho, 100.0f) - && pWho->GetVehicle() - && m_pInstance->GetData(TYPE_UROM) == DONE) + if(pWho->GetTypeId() == TYPEID_PLAYER && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) + && !((Player*)pWho)->isGameMaster() && m_creature->IsWithinDistInMap(pWho, 100.0f) + && pWho->GetVehicle() && m_pInstance->GetData(TYPE_UROM) == DONE) { m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } ScriptedAI::MoveInLineOfSight(pWho); } - void Aggro(Unit* who) + void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); if (m_pInstance) m_pInstance->SetData(TYPE_EREGOS, IN_PROGRESS); } - void KilledUnit(Unit *victim) + void KilledUnit(Unit* pVictim) { - uint8 uiText = urand(0, 2); - switch (uiText) + switch (urand(0, 2)) { case 0: DoScriptText(SAY_KILL_1, m_creature); break; case 1: DoScriptText(SAY_KILL_2, m_creature); break; @@ -134,19 +130,24 @@ struct MANGOS_DLL_DECL boss_eregosAI : public ScriptedAI } } - void JustDied(Unit* killer) + void JustDied(Unit* pKiller) { - m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()-100.0f, 0); + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->KilledMonsterCredit(NPC_EREGOS); + + pMap->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()-100.0f, 0); m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()-100.0f, 26); - DoScriptText(SAY_DEATH, m_creature); + DoScriptText(SAY_DEATH, m_creature); if (m_pInstance) m_pInstance->SetData(TYPE_EREGOS, DONE); } - void DamageTaken(Unit *done_by, uint32 &damage) + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { if(m_creature->HasAura(SPELL_PLANAR_SHIFT)) - damage = 0; + uiDamage = 0; } void JustSummoned(Creature* pSummoned) @@ -167,15 +168,15 @@ struct MANGOS_DLL_DECL boss_eregosAI : public ScriptedAI } } - void AttackStart(Unit* who) + void AttackStart(Unit* pWho) { - if (!who) + if (!pWho) return; if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; - ScriptedAI::AttackStart(who); + ScriptedAI::AttackStart(pWho); } void SummonAnomalies() @@ -192,7 +193,7 @@ struct MANGOS_DLL_DECL boss_eregosAI : public ScriptedAI } } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -228,37 +229,37 @@ struct MANGOS_DLL_DECL boss_eregosAI : public ScriptedAI m_creature->StopMoving(); } - if(uiArcaneBarrageTimer <= diff) + if(uiArcaneBarrageTimer <= uiDiff) { if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) DoCast(pTarget, m_bIsRegularMode ? SPELL_ARCANE_BARRAGE_N : SPELL_ARCANE_BARRAGE_H); uiArcaneBarrageTimer = 3000; - } else uiArcaneBarrageTimer -= diff; + } else uiArcaneBarrageTimer -= uiDiff; - if(uiSummonTimer <= diff) + if(uiSummonTimer <= uiDiff) { for(uint8 i = 1; i < 3; i++) DoCast(m_creature, SPELL_SUMMON_DRAKE, true); uiSummonTimer = 15000; - } else uiSummonTimer -= diff; + } else uiSummonTimer -= uiDiff; - if(uiArcaneVolleyTimer <= diff) + if(uiArcaneVolleyTimer <= uiDiff) { DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ARCANE_VOLLEY_N : SPELL_ARCANE_VOLLEY_H); uiArcaneVolleyTimer = 17000; - } else uiArcaneVolleyTimer -= diff; + } else uiArcaneVolleyTimer -= uiDiff; - if(uiEnragedAssaultTimer <= diff) + if(uiEnragedAssaultTimer <= uiDiff) { DoCast(m_creature, SPELL_ENRAGED_ASSAULT, true); uiEnragedAssaultTimer = 44000; - } else uiEnragedAssaultTimer -= diff; + } else uiEnragedAssaultTimer -= uiDiff; } }; struct MANGOS_DLL_DECL npc_planar_anomalyAI : public ScriptedAI { - npc_planar_anomalyAI(Creature *pCreature) : ScriptedAI(pCreature) + npc_planar_anomalyAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } @@ -279,18 +280,18 @@ struct MANGOS_DLL_DECL npc_planar_anomalyAI : public ScriptedAI uiPulseTimer = 19000; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { - if (uiPulseTimer < diff) + if (uiPulseTimer < uiDiff) { m_creature->RemoveAurasDueToSpell(SPELL_PLANAR_ANOMALIES_VISUAL); m_creature->CastSpell(m_creature, SPELL_PLANAR_ANOMALIES_DMG, true); uiPulseTimer = 6000; - } else uiPulseTimer -= diff; + } else uiPulseTimer -= uiDiff; - if (uiDeathTimer < diff) - m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - else uiDeathTimer -= diff; + if (uiDeathTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else uiDeathTimer -= uiDiff; } }; diff --git a/scripts/northrend/nexus/oculus/boss_urom.cpp b/scripts/northrend/nexus/oculus/boss_urom.cpp index 915b126e3b..6a01f76cb1 100644 --- a/scripts/northrend/nexus/oculus/boss_urom.cpp +++ b/scripts/northrend/nexus/oculus/boss_urom.cpp @@ -53,20 +53,22 @@ enum NPC_PHANTASMAL_MAMMOTH = 27642, NPC_PHANTASMAL_WOLF = 27644, NPC_PHANTASMAL_CLOUDSCRAPER = 27645, + NPC_PHANTASMAL_OGRE = 27647, NPC_PHANTASMAL_NAGA = 27648, NPC_PHANTASMAL_MURLOC = 27649, + NPC_PHANTASMAL_AIR = 27650, NPC_PHANTASMAL_FIRE = 27651, NPC_PHANTASMAL_WATER = 27653 }; -/* -struct Locations + +/*struct Locations { float x, y, z, o; uint32 id; -}; -*/ +};*/ + struct Locations Teleport[]= { {1177.469f, 937.721f, 527.405f, 2.21f}, //first platform @@ -76,9 +78,9 @@ struct Locations Teleport[]= {1103.659f, 1049.88f, 518.148f, 5.80f} //oculus center }; -struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI +struct MANGOS_DLL_DECL boss_uromAI : public ScriptedAI { - boss_uromAI(Creature *pCreature) : BSWScriptedAI(pCreature) + boss_uromAI(Creature *pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); @@ -129,19 +131,46 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI } } - void DoSummon(uint32 Entry01, uint32 Entry02, uint32 Entry03, uint32 Entry04, uint32 Entry05 = 0) + void DoSummonAndAttack(Unit* pWho, uint32 Entry01, uint32 Entry02, uint32 Entry03, uint32 Entry04, uint32 Entry05 = 0) { - m_creature->SummonCreature(Entry01, m_creature->GetPositionX() - (10.0f) * cos(M_PI / 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI / 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - m_creature->SummonCreature(Entry02, m_creature->GetPositionX() - (10.0f) * cos(M_PI * 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI * 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - m_creature->SummonCreature(Entry03, m_creature->GetPositionX() - (10.0f) * cos(M_PI + M_PI / 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI + M_PI / 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - m_creature->SummonCreature(Entry04, m_creature->GetPositionX() - (10.0f) * cos(M_PI), m_creature->GetPositionY() - (10.0f) * sin(M_PI), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); - if(Entry05 != 0) - m_creature->SummonCreature(Entry05, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + Creature* pTemp; + if (pTemp = m_creature->SummonCreature(Entry01, m_creature->GetPositionX() - (10.0f) * cos(M_PI / 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI / 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 15000)) + { + pTemp->SetInCombatWith(pWho); + pTemp->AddThreat(pWho,100.0f); + } + + if (pTemp = m_creature->SummonCreature(Entry02, m_creature->GetPositionX() - (10.0f) * cos(M_PI * 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI * 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 15000)) + { + pTemp->SetInCombatWith(pWho); + pTemp->AddThreat(pWho,100.0f); + } + + if (pTemp = m_creature->SummonCreature(Entry03, m_creature->GetPositionX() - (10.0f) * cos(M_PI + M_PI / 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI + M_PI / 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 15000)) + { + pTemp->SetInCombatWith(pWho); + pTemp->AddThreat(pWho,100.0f); + } + + if (pTemp = m_creature->SummonCreature(Entry04, m_creature->GetPositionX() - (10.0f) * cos(M_PI), m_creature->GetPositionY() - (10.0f) * sin(M_PI), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 15000)) + { + pTemp->SetInCombatWith(pWho); + pTemp->AddThreat(pWho,100.0f); + } + + if(Entry05 != 0) + { + if (pTemp = m_creature->SummonCreature(Entry05, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 15000)) + { + pTemp->SetInCombatWith(pWho); + pTemp->AddThreat(pWho,100.0f); + } + } } void SpellHit(Unit* pCaster, const SpellEntry* pSpell) { - if(pSpell->Id == SPELL_SUMMON_MENAGERIE) //|| pSpell->Id == SPELL_SUMMON_MENAGERIE_2 || pSpell->Id == SPELL_SUMMON_MENAGERIE_3) + if(pSpell->Id == SPELL_SUMMON_MENAGERIE) m_bIsTalk = false; if(pSpell->Id == SPELL_SUMMON_MENAGERIE_2) m_bIsTalk = false; @@ -149,11 +178,11 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI m_bIsTalk = false; } - void TeleportBoss(float X, float Y, float Z, float O) + void TeleportBoss(float fX, float fY, float fZ, float fO) { - m_creature->GetMap()->CreatureRelocation(m_creature, X, Y, Z, O); - m_creature->MonsterMoveWithSpeed(X, Y, Z, 26); - m_creature->Relocate(X, Y, Z, O); + m_creature->GetMap()->CreatureRelocation(m_creature, fX, fY, fZ, fO); + m_creature->MonsterMoveWithSpeed(fX, fY, fZ, 26); + m_creature->Relocate(fX, fY, fZ, fO); } void AttackStart(Unit* pWho) @@ -175,48 +204,45 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI if (!m_pInstance) return; - if(pWho->GetTypeId() == TYPEID_PLAYER - && !((Player*)pWho)->isGameMaster() - && m_creature->IsWithinDistInMap(pWho, 30.0f) - && !pWho->GetVehicle() - && m_pInstance->GetData(TYPE_VAROS) == DONE - && !m_bIsTalk) + if(pWho->GetTypeId() == TYPEID_PLAYER && !((Player*)pWho)->isGameMaster() + && m_creature->IsWithinDistInMap(pWho, 30.0f) && !pWho->GetVehicle() + && m_pInstance->GetData(TYPE_VAROS) == DONE && !m_bIsTalk) { switch(m_pInstance->GetData(TYPE_UROM_PHASE)) { - case 0: - m_bIsTalk = true; - SetCombatMovement(false); - m_pInstance->SetData(TYPE_UROM, IN_PROGRESS); - m_creature->InterruptNonMeleeSpells(false); - m_creature->RemoveAurasDueToSpell(53813); - DoScriptText(SAY_SUMMON_1, m_creature); - DoSummon(NPC_PHANTASMAL_FIRE, NPC_PHANTASMAL_FIRE, NPC_PHANTASMAL_AIR, NPC_PHANTASMAL_WATER); - DoCast(m_creature, SPELL_SUMMON_MENAGERIE); - m_pInstance->SetData(TYPE_UROM_PHASE, 1); - break; - case 1: - m_bIsTalk = true; - DoScriptText(SAY_SUMMON_2, m_creature); - DoSummon(NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_NAGA, NPC_PHANTASMAL_MURLOC); - DoCast(m_creature, SPELL_SUMMON_MENAGERIE_2); - m_pInstance->SetData(TYPE_UROM_PHASE, 2); - break; - case 2: - m_bIsTalk = true; - DoScriptText(SAY_SUMMON_3, m_creature); - DoSummon(NPC_PHANTASMAL_MAMMOTH, NPC_PHANTASMAL_WOLF, NPC_PHANTASMAL_WOLF, NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_CLOUDSCRAPER); - DoCast(m_creature, SPELL_SUMMON_MENAGERIE_3); - m_pInstance->SetData(TYPE_UROM_PHASE, 3); - break; - case 3: - m_bIsTalk = true; - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - SetCombatMovement(true); - AttackStart(pWho); - break; - default: - break; + case 0: + m_bIsTalk = true; + SetCombatMovement(false); + m_pInstance->SetData(TYPE_UROM, IN_PROGRESS); + m_creature->InterruptNonMeleeSpells(false); + m_creature->RemoveAurasDueToSpell(SPELL_ARCANE_BARRIER); + DoScriptText(SAY_SUMMON_1, m_creature); + DoSummonAndAttack(pWho, NPC_PHANTASMAL_FIRE, NPC_PHANTASMAL_FIRE, NPC_PHANTASMAL_AIR, NPC_PHANTASMAL_WATER); + DoCast(m_creature, SPELL_SUMMON_MENAGERIE); + m_pInstance->SetData(TYPE_UROM_PHASE, 1); + break; + case 1: + m_bIsTalk = true; + DoScriptText(SAY_SUMMON_2, m_creature); + DoSummonAndAttack(pWho, NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_NAGA, NPC_PHANTASMAL_MURLOC); + DoCast(m_creature, SPELL_SUMMON_MENAGERIE_2); + m_pInstance->SetData(TYPE_UROM_PHASE, 2); + break; + case 2: + m_bIsTalk = true; + DoScriptText(SAY_SUMMON_3, m_creature); + DoSummonAndAttack(pWho, NPC_PHANTASMAL_MAMMOTH, NPC_PHANTASMAL_WOLF, NPC_PHANTASMAL_WOLF, NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_CLOUDSCRAPER); + DoCast(m_creature, SPELL_SUMMON_MENAGERIE_3); + m_pInstance->SetData(TYPE_UROM_PHASE, 3); + break; + case 3: + m_bIsTalk = true; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(true); + AttackStart(pWho); + break; + default: + break; } } @@ -230,31 +256,23 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI else DoScriptText(SAY_AGGRO, m_creature); } - void JustSummoned(Creature* summoned) - { - if(!m_pInstance || !summoned) return; - - if (Unit* pTarget = doSelectRandomPlayerAtRange(100.0f)) - { - summoned->SetInCombatWith(pTarget); - summoned->AddThreat(pTarget,100.0f); - } - } - void EnterEvadeMode() { if (!m_pInstance) return; - if( m_pInstance->GetData(TYPE_UROM_PHASE) < 3) + if (m_bIsTeleported) + return; + + if(m_pInstance->GetData(TYPE_UROM_PHASE) < 3) { Map::PlayerList const &pList = m_creature->GetMap()->GetPlayers(); if (!pList.isEmpty()) return; } m_pInstance->SetData(TYPE_UROM, FAIL); - m_pInstance->SetData(TYPE_UROM_PHASE, 1); + m_pInstance->SetData(TYPE_UROM_PHASE, 0); ScriptedAI::EnterEvadeMode(); } @@ -266,10 +284,9 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI m_pInstance->SetData(TYPE_UROM, DONE); } - void KilledUnit(Unit *victim) + void KilledUnit(Unit* pVictim) { - uint8 uiText = urand(0, 2); - switch (uiText) + switch (urand(0, 2)) { case 0: DoScriptText(SAY_KILL_1, m_creature); break; case 1: DoScriptText(SAY_KILL_2, m_creature); break; @@ -297,11 +314,11 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI void UpdateAI(const uint32 uiDiff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - if(!m_bIsTeleported) { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + if(m_uiFrostBombTimer < uiDiff) { m_creature->CastSpell(m_creature->getVictim(), SPELL_FROSTBOMB, false); @@ -351,7 +368,7 @@ struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI if(m_uiBackTimer < uiDiff) { - TeleportBoss((m_creature->getVictim())->GetPositionX(),(m_creature->getVictim())->GetPositionY(),(m_creature->getVictim())->GetPositionZ(),(m_creature->getVictim())->GetOrientation()); + TeleportBoss(m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), m_creature->getVictim()->GetOrientation()); m_creature->SetLevitate(false); if(m_creature->getVictim()) m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); diff --git a/scripts/northrend/nexus/oculus/boss_varos.cpp b/scripts/northrend/nexus/oculus/boss_varos.cpp index 2420fd2162..fedd5df1b6 100644 --- a/scripts/northrend/nexus/oculus/boss_varos.cpp +++ b/scripts/northrend/nexus/oculus/boss_varos.cpp @@ -156,18 +156,18 @@ struct MANGOS_DLL_DECL boss_varosAI : public ScriptedAI } } - void Aggro(Unit* who) + void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); if(m_pInstance) m_pInstance->SetData(TYPE_VAROS, IN_PROGRESS); - if(Creature* Dragon = m_creature->SummonCreature(NPC_AZURE_CAPTAIN, (m_creature->GetPositionX()-45)+rand()%90, (m_creature->GetPositionY()-45)+rand()%90, m_creature->GetPositionZ() + 30.0f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 100)) + if(Creature* pDragon = m_creature->SummonCreature(NPC_AZURE_CAPTAIN, (m_creature->GetPositionX()-45)+rand()%90, (m_creature->GetPositionY()-45)+rand()%90, m_creature->GetPositionZ() + 30.0f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 100)) { - Dragon->SetLevitate(true); - Dragon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_uiAzureDrakeGUID = Dragon->GetObjectGuid(); + pDragon->SetLevitate(true); + pDragon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiAzureDrakeGUID = pDragon->GetObjectGuid(); } } @@ -181,7 +181,7 @@ struct MANGOS_DLL_DECL boss_varosAI : public ScriptedAI } - void JustDied(Unit* killer) + void JustDied(Unit* pKiller) { DoScriptText(SAY_DEATH, m_creature); @@ -407,7 +407,7 @@ struct MANGOS_DLL_DECL npc_varos_orbAI : public ScriptedAI { } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { } }; @@ -426,11 +426,11 @@ struct MANGOS_DLL_DECL npc_varos_beam_targetAI : public ScriptedAI uiDeathTimer = 15000; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { - if (uiDeathTimer < diff) + if (uiDeathTimer < uiDiff) m_creature->ForcedDespawn(); - else uiDeathTimer -= diff; + else uiDeathTimer -= uiDiff; } }; diff --git a/scripts/northrend/nexus/oculus/instance_oculus.cpp b/scripts/northrend/nexus/oculus/instance_oculus.cpp index 09664c5879..7a42bfdd9f 100644 --- a/scripts/northrend/nexus/oculus/instance_oculus.cpp +++ b/scripts/northrend/nexus/oculus/instance_oculus.cpp @@ -39,7 +39,7 @@ enum struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance { - instance_oculus(Map* pMap) : ScriptedInstance(pMap) + instance_oculus(Map* pMap) : ScriptedInstance(pMap) { m_bIsRegularMode = pMap->IsRegularDifficulty(); Initialize(); @@ -64,6 +64,9 @@ struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance switch(pGo->GetEntry()) { case GO_DRAGON_CAGE_DOOR: + case GO_SPOTLIGHT: + case GO_EREGOS_CACHE: + case GO_EREGOS_CACHE_H: break; default: @@ -91,26 +94,30 @@ struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); } - void SetData(uint32 type, uint32 data) + void SetData(uint32 uiType, uint32 uiData) { - switch(type) + switch(uiType) { case TYPE_DRAKOS: case TYPE_VAROS: case TYPE_UROM: - m_auiEncounter[type] = data; + m_auiEncounter[uiType] = uiData; break; case TYPE_EREGOS: - m_auiEncounter[type] = data; - if (data == DONE) + m_auiEncounter[uiType] = uiData; + if (uiData == DONE) { - DoRespawnGameObject(m_bIsRegularMode ? GO_EREGOS_CACHE : GO_EREGOS_CACHE_H, HOUR); - DoRespawnGameObject(GO_SPOTLIGHT, HOUR); + if (GameObject* pTemp = GetSingleGameObjectFromStorage(m_bIsRegularMode ? GO_EREGOS_CACHE : GO_EREGOS_CACHE_H)) + { + DoRespawnGameObject(pTemp->GetObjectGuid(), DAY); + } + if (GameObject* pTemp = GetSingleGameObjectFromStorage(GO_SPOTLIGHT)) + DoRespawnGameObject(pTemp->GetObjectGuid(), DAY); } break; case TYPE_ROBOTS: - m_auiEncounter[type] = m_auiEncounter[type] - data; - if(m_auiEncounter[type] == 0) + m_auiEncounter[uiType] = m_auiEncounter[uiType] - uiData; + if(m_auiEncounter[uiType] == 0) { if(Creature* pVaros = GetSingleCreatureFromStorage(NPC_VAROS)) { @@ -120,15 +127,15 @@ struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance pVaros->RemoveAurasDueToSpell(50053); } } - data = NOT_STARTED; + uiData = NOT_STARTED; break; case TYPE_UROM_PHASE: - m_auiEncounter[type] = data; - data = NOT_STARTED; + m_auiEncounter[uiType] = uiData; + uiData = NOT_STARTED; break; } - if (data == DONE) + if (uiData == DONE) { OUT_SAVE_INST_DATA; @@ -144,9 +151,9 @@ struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance } } - uint32 GetData(uint32 type) + uint32 GetData(uint32 uiType) { - switch(type) + switch(uiType) { case TYPE_DRAKOS: case TYPE_VAROS: @@ -154,7 +161,7 @@ struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance case TYPE_EREGOS: case TYPE_ROBOTS: case TYPE_UROM_PHASE: - return m_auiEncounter[type]; + return m_auiEncounter[uiType]; default: return 0; } @@ -206,7 +213,7 @@ bool GOUse_go_oculus_portal(Player* pPlayer, GameObject* pGo) switch(pGo->GetEntry()) { case GO_ORB_OF_NEXUS: - pPlayer->TeleportTo(571,3876.159912f,6984.439941f,106.32f,6.279f); + pPlayer->TeleportTo(571, 3876.159912f, 6984.439941f, 106.32f, 6.279f); return true; } return false; diff --git a/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp b/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp index e4f3e57db4..59103be302 100644 --- a/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp +++ b/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss Sartharion -SD%Complete: 95% -SDComment: Used some workarounds. +SD%Complete: 100% +SDComment: It's alive! ;) Now this is script is alive realy! (c) MaxXx2021 and PSZ SDCategory: Obsidian Sanctum EndScriptData */ @@ -27,108 +27,105 @@ EndScriptData */ enum { //Sartharion Yell - SAY_SARTHARION_AGGRO = -1615018, - SAY_SARTHARION_BERSERK = -1615019, - SAY_SARTHARION_BREATH = -1615020, - SAY_SARTHARION_CALL_SHADRON = -1615021, - SAY_SARTHARION_CALL_TENEBRON = -1615022, - SAY_SARTHARION_CALL_VESPERON = -1615023, - SAY_SARTHARION_DEATH = -1615024, - SAY_SARTHARION_SPECIAL_1 = -1615025, - SAY_SARTHARION_SPECIAL_2 = -1615026, - SAY_SARTHARION_SPECIAL_3 = -1615027, - SAY_SARTHARION_SPECIAL_4 = -1615028, - SAY_SARTHARION_SLAY_1 = -1615029, - SAY_SARTHARION_SLAY_2 = -1615030, - SAY_SARTHARION_SLAY_3 = -1615031, - - WHISPER_LAVA_CHURN = -1615032, - - WHISPER_SHADRON_DICIPLE = -1615008, - WHISPER_VESPERON_DICIPLE = -1615041, - WHISPER_HATCH_EGGS = -1615017, - WHISPER_OPEN_PORTAL = -1615042, // whisper, shared by two dragons + SAY_SARTHARION_AGGRO = -1615018, + SAY_SARTHARION_BERSERK = -1615019, + SAY_SARTHARION_BREATH = -1615020, + SAY_SARTHARION_CALL_SHADRON = -1615021, + SAY_SARTHARION_CALL_TENEBRON = -1615022, + SAY_SARTHARION_CALL_VESPERON = -1615023, + SAY_SARTHARION_DEATH = -1615024, + SAY_SARTHARION_SPECIAL_1 = -1615025, + SAY_SARTHARION_SPECIAL_2 = -1615026, + SAY_SARTHARION_SPECIAL_3 = -1615027, + SAY_SARTHARION_SPECIAL_4 = -1615028, + SAY_SARTHARION_SLAY_1 = -1615029, + SAY_SARTHARION_SLAY_2 = -1615030, + SAY_SARTHARION_SLAY_3 = -1615031, + + WHISPER_LAVA_CHURN = -1615032, + + WHISPER_SHADRON_DICIPLE = -1615008, + WHISPER_VESPERON_DICIPLE = -1615041, + WHISPER_HATCH_EGGS = -1615017, + WHISPER_OPEN_PORTAL = -1615042, // whisper, shared by two dragons //Sartharion Spells - SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min. - SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets. - SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster. - SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster. - SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. - SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. - SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. - SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) - SPELL_LAVA_STRIKE_DMG = 57591, - SPELL_CYCLONE_AURA = 57560, // knock back aura - SPELL_CYCLONE_AURA_2 = 57598, - SPELL_TWILIGHT_REVENGE = 60639, - - SPELL_PYROBUFFET = 58907, // currently used for hard enrage after 15 minutes - SPELL_PYROBUFFET_RANGE = 56916, // possibly used when player get too far away from dummy creatures (2x creature entry 30494) - - SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO - SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase - SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) - - SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase + SPELL_BERSERK = 27680, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min. Should be 61632, but that doesn't work... + SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets. + SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster. + SPELL_FLAME_BREATH_H = 58956, // Inflicts 10938 to 14062 Fire damage to enemies in a cone in front of the caster. + SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. + SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. + SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. + SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) + SPELL_CYCLONE_AURA_2 = 57598, + SPELL_TWILIGHT_REVENGE = 60639, + + SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes + SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x creature entry 30494) + + SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO + SPELL_TWILIGHT_SHIFT_DMG = 57874, // damage during being in twilight realm + SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase + SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) + + //Mini bosses common spells + SPELL_TWILIGHT_RESIDUE = 61885, // makes immune to shadow damage, applied when leave phase //Miniboses (Vesperon, Shadron, Tenebron) - SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster. - SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster. + SPELL_SHADOW_BREATH_H = 59126, // Inflicts 8788 to 10212 Fire damage to enemies in a cone in front of the caster. + SPELL_SHADOW_BREATH = 57570, // Inflicts 6938 to 8062 Fire damage to enemies in a cone in front of the caster. - SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec. - SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec. + SPELL_SHADOW_FISSURE_H = 59127, // Deals 9488 to 13512 Shadow damage to any enemy within the Shadow fissure after 5 sec. + SPELL_SHADOW_FISSURE = 57579, // Deals 6188 to 8812 Shadow damage to any enemy within the Shadow fissure after 5 sec. //Vesperon //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times - SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%. - SPELL_TWILIGHT_TORMENT_VESP_SOLO = 57948, // (Shadow only) trigger 57935 then 57988 - SPELL_TWILIGHT_TORMENT_VESP_SARTH = 58853, // (Fire and Shadow) trigger 58835 then 57988 - SPELL_TWILIGHT_TORMENT_AURA = 57935, - SPELL_TWILIGHT_TORMENT_DEBUFF = 58835, + NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon + SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%. + SPELL_TWILIGHT_TORMENT_VESP = 57948, // (Shadow only) trigger 57935 then 57988 + SPELL_TWILIGHT_TORMENT_VESP_ACO = 58853, // (Fire and Shadow) trigger 58835 then 57988 //Shadron //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times - SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%. - SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron - SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion + NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron + SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%. + SPELL_GIFT_OF_TWILIGTH_SHA = 57835, // TARGET_SCRIPT shadron + SPELL_GIFT_OF_TWILIGTH_SAR = 58766, // TARGET_SCRIPT sartharion //Tenebron - //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708 - SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%. + //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708 + SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%. + //Tenebron, dummy spell + SPELL_SUMMON_TWILIGHT_WHELP = 58035, // doesn't work, will spawn NPC_TWILIGHT_WHELP + SPELL_SUMMON_SARTHARION_TWILIGHT_WHELP = 58826, // doesn't work, will spawn NPC_SHARTHARION_TWILIGHT_WHELP - SPELL_HATCH_EGGS = 58542, - SPELL_HATCH_SARTHARION_EGGS = 59189, - SPELL_HATCH_EGGS_EFFECT_H = 59190, - SPELL_HATCH_EGGS_EFFECT = 58685, + SPELL_HATCH_EGGS_H = 59189, + SPELL_HATCH_EGGS = 58542, + SPELL_HATCH_EGGS_EFFECT_H = 59190, + SPELL_HATCH_EGGS_EFFECT = 58685, - SPELL_SUMMON_TWILIGHT_WHELP = 58035, - SPELL_SUMMON_SARTH_TWILIGHT_WHELP = 58826, - - NPC_TWILIGHT_EGG = 30882, - NPC_SARTHARION_TWILIGHT_EGG = 31204, - NPC_TWILIGHT_EGG_CONTROLLER = 31138, + NPC_TWILIGHT_EGG = 30882, //Whelps - NPC_TWILIGHT_WHELP = 30890, - NPC_SARTHARION_TWILIGHT_WHELP = 31214, - SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s + NPC_TWILIGHT_WHELP = 30890, + NPC_SHARTHARION_TWILIGHT_WHELP = 31214, + SPELL_FADE_ARMOR = 60708, // Reduces the armor of an enemy by 1500 for 15s //flame tsunami - SPELL_FLAME_TSUNAMI = 57494, // the visual dummy - SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction - SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura - SPELL_FLAME_TSUNAMI_DMG = 57491, // damage players - SPELL_FLAME_TSUNAMI_BUFF = 60430, // buff Lava Blazes + SPELL_FLAME_TSUNAMI = 57494, // the visual dummy + SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction + SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura + SPELL_FLAME_TSUNAMI_DMG = 57491, // damage players + SPELL_FLAME_TSUNAMI_BUFF = 60430, // buff Lava Blazes - NPC_FLAME_TSUNAMI = 30616, // for the flame waves - NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike - NPC_FIRE_CYCLONE = 30648, - NPC_ORB_TARGET = 25640, // used for summoning Lava Blazes + NPC_FLAME_TSUNAMI = 30616, // for the flame waves + NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike + NPC_FIRE_CYCLONE = 30648, //using these custom points for dragons start and end - POINT_ID_INIT = 100, - POINT_ID_LAND = 200 + POINT_ID_INIT = 100, + POINT_ID_LAND = 200 }; struct Waypoint @@ -139,46 +136,47 @@ struct Waypoint //each dragons special points. First where fly to before connect to connon, second where land point is. Waypoint m_aTene[]= { - {3212.854f, 575.597f, 109.856f}, // init - {3246.425f, 565.367f, 61.249f} // end + {3212.854f, 575.597f, 109.856f}, //init + {3246.425f, 565.367f, 61.249f} //end }; Waypoint m_aShad[]= { {3293.238f, 472.223f, 106.968f}, - {3227.268f, 533.238f, 59.995f} + {3271.669f, 526.907f, 61.931f} }; Waypoint m_aVesp[]= { {3193.310f, 472.861f, 102.697f}, - {3271.669f, 526.907f, 61.931f} + {3227.268f, 533.238f, 59.995f} }; //points around raid "isle", counter clockwise. should probably be adjusted to be more alike Waypoint m_aDragonCommon[]= { - {3214.012f, 468.932f, 90.652f}, - {3244.950f, 468.427f, 90.652f}, - {3283.520f, 496.869f, 90.652f}, - {3287.316f, 555.875f, 90.652f}, - {3250.479f, 585.827f, 90.652f}, - {3209.969f, 566.523f, 90.652f} + {3214.012f, 468.932f, 98.652f}, + {3244.950f, 468.427f, 98.652f}, + {3283.520f, 496.869f, 98.652f}, + {3287.316f, 555.875f, 98.652f}, + {3250.479f, 585.827f, 98.652f}, + {3209.969f, 566.523f, 98.652f} }; float m_afTsunamiStartLoc[5][4]= { //left to right - {3201.0f, 481.82f, 58.6f, 6.23f}, // covers 470.82 - 481.82 - 492.82 - {3201.0f, 524.50f, 58.6f, 6.23f}, // covers 513.50 - 524.50 - 535.50 - {3201.0f, 566.64f, 58.6f, 6.23f}, // covers 555.64 - 566.64 - 577.64 + {3201.0f, 487.75f, 58.6f, 6.23f}, + {3201.0f, 533.54f, 58.6f, 6.23f}, + {3201.0f, 579.14f, 58.6f, 6.23f}, //right to left - {3287.5f, 545.50f, 58.6f, 3.19f}, // covers 534.50 - 545.50 - 556.50 - {3287.5f, 503.00f, 58.6f, 3.19f}, // covers 492.00 - 503.00 - 514.00 + {3287.5f, 552.53f, 58.6f, 3.19f}, + {3287.5f, 511.10f, 58.6f, 3.19f}, }; - - +ObjectGuid m_uiAcolyteShadronGUID; +ObjectGuid m_uiAcolyteVesperonGUID; +std::list m_lEggsGUIDList; /*###### ## Boss Sartharion @@ -188,7 +186,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI { boss_sartharionAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); m_bTenebronHelpedInFight = false; m_bShadronHelpedInFight = false; @@ -196,7 +194,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI Reset(); } - instance_obsidian_sanctum* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; bool m_bIsBerserk; @@ -205,8 +203,9 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI uint32 m_uiEnrageTimer; bool m_bIsHardEnraged; - uint32 m_uiCurrentCallDragonData; - uint32 m_uiCallDragonTimer; + uint32 m_uiTenebronTimer; + uint32 m_uiShadronTimer; + uint32 m_uiVesperonTimer; uint32 m_uiFlameTsunamiTimer; uint32 m_uiFlameBreathTimer; @@ -223,7 +222,6 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI bool bCanUseWill; bool bFirstWill; - uint32 m_uiSarthHealth; uint32 m_uiTeneHealth; uint32 m_uiShadHealth; @@ -238,14 +236,15 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI m_bIsBerserk = false; m_bIsSoftEnraged = false; - m_uiEnrageTimer = 15*MINUTE*IN_MILLISECONDS; + m_uiEnrageTimer = MINUTE*15*IN_MILLISECONDS; m_bIsHardEnraged = false; - m_uiCallDragonTimer = 30000; - m_uiCurrentCallDragonData = 0; + m_uiTenebronTimer = 30000; + m_uiShadronTimer = 75000; + m_uiVesperonTimer = 120000; - m_uiFlameTsunamiTimer = 30000; - m_uiFlameBreathTimer = 20000; + m_uiFlameTsunamiTimer = m_bIsRegularMode ? 30000 : 20000; + m_uiFlameBreathTimer = m_bIsRegularMode ? 20000 : 10000; m_uiTailSweepTimer = 5000; m_uiCleaveTimer = 7000; m_uiCycloneAuraTimer = 10000; @@ -254,8 +253,8 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI m_bHasCalledShadron = false; m_bHasCalledVesperon = false; - bCanUseWill = false; bFirstWill = true; + bCanUseWill = false; m_uiCheckTwilightTimer = 2000; @@ -271,6 +270,13 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI pTene->Respawn(); else pTene->AI()->EnterEvadeMode(); + if (!m_lEggsGUIDList.empty()) //inserito per facilitare il reset dopo il fight, in modo da eliminare le uova non schiuse rimaste + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pEgg = m_creature->GetMap()->GetCreature( *itr)) + pEgg->ForcedDespawn(); + m_lEggsGUIDList.clear(); + if (pTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pTene->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } if (m_bShadronHelpedInFight && pShad) @@ -279,6 +285,11 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI pShad->Respawn(); else pShad->AI()->EnterEvadeMode(); + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID))//inserito per facilitare il reset dopo il fight, in modo da eliminare l'accolito eventualmente rimasto vivo + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_uiAcolyteShadronGUID.Clear(); + if (pShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pShad->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } if (m_bVesperonHelpedInFight && pVesp) @@ -287,151 +298,153 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI pVesp->Respawn(); else pVesp->AI()->EnterEvadeMode(); + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID))//inserito per facilitare il reset dopo il fight, in modo da eliminare l'accolito eventualmente rimasto vivo + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_uiAcolyteVesperonGUID.Clear(); + if (pVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pVesp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } - - m_pInstance->m_lHitByVolcanoGUIDList.clear(); } + m_lFireCyclones.clear(); + GetCreatureListWithEntryInGrid(m_lFireCyclones, m_creature, NPC_FIRE_CYCLONE, 100.0f); + m_bTenebronHelpedInFight = false; m_bShadronHelpedInFight = false; m_bVesperonHelpedInFight = false; + + m_creature->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR); + m_creature->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); } void JustReachedHome() { - if (!m_pInstance) - return; - - m_pInstance->SetData(TYPE_SARTHARION_EVENT, FAIL); - - if (m_pInstance->m_lBlazesGUIDList.empty() ) - return; - - for (GUIDList::iterator i = m_pInstance->m_lBlazesGUIDList.begin(); i != m_pInstance->m_lBlazesGUIDList.end(); i++) - if (Creature *pBlaze = m_pInstance->instance->GetCreature(*i)) - if (pBlaze->isAlive()) - pBlaze->ForcedDespawn(); - m_pInstance->m_lBlazesGUIDList.clear(); + if (m_pInstance) + m_pInstance->SetData(TYPE_SARTHARION_EVENT, NOT_STARTED); } void Aggro(Unit* pWho) { DoScriptText(SAY_SARTHARION_AGGRO,m_creature); - DoCastSpellIfCan(m_creature, SPELL_PYROBUFFET_RANGE, CAST_TRIGGERED); - - m_creature->SetInCombatWithZone(); if (m_pInstance) { - // trash mobs in the area should help Sartharion in the fight - if (!m_pInstance->m_lTrashMobsGUIDlist.empty()) - { - for (GUIDList::iterator itr = m_pInstance->m_lTrashMobsGUIDlist.begin(); itr != m_pInstance->m_lTrashMobsGUIDlist.end(); itr++) - { - if (Creature *pCreature = m_pInstance->instance->GetCreature(*itr) ) - pCreature->AI()->AttackStart(pWho); - } - } - m_pInstance->SetData(TYPE_SARTHARION_EVENT, IN_PROGRESS); FetchDragons(); } } - void JustDied(Unit* pKiller) + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) { - DoScriptText(SAY_SARTHARION_DEATH, m_creature); + if (uiDamage > m_creature->GetHealth()) + { + uint8 uiHardMode = m_pInstance->GetData(TYPE_ALIVE_DRAGONS); - if (!m_pInstance) - return; + if (uiHardMode) + m_creature->UpdateEntry(m_creature->GetEntry()*10+uiHardMode); + } + } - // Hard Mode implementation - uint8 uiHardMode = 0; - if (m_bTenebronHelpedInFight) - ++uiHardMode; - if (m_bShadronHelpedInFight) - ++uiHardMode; - if (m_bVesperonHelpedInFight) - ++uiHardMode; + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_SARTHARION_DEATH, m_creature); - if (uiHardMode) + // we kill the dragons that hadn't helped the boss + if (!m_bTenebronHelpedInFight) { - for (int8 i = uiHardMode; i > 0; i--) - m_pInstance->SetData(i + 1, DONE); + Creature* pTene = m_pInstance->GetSingleCreatureFromStorage(NPC_TENEBRON); + if (pTene && pTene->isAlive()) + pTene->DealDamage(pTene, pTene->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + if (!m_bShadronHelpedInFight) + { + Creature* pShad = m_pInstance->GetSingleCreatureFromStorage(NPC_SHADRON); + if (pShad && pShad->isAlive()) + pShad->DealDamage(pShad, pShad->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + if (!m_bVesperonHelpedInFight) + { + Creature* pVesp = m_pInstance->GetSingleCreatureFromStorage(NPC_VESPERON); + if (pVesp && pVesp->isAlive()) + pVesp->DealDamage(pVesp, pVesp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } - m_pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); + if (m_pInstance) + m_pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); } void KilledUnit(Unit* pVictim) { - DoScriptText(SAY_SARTHARION_SLAY_1 - urand(0, 2), m_creature); + switch (urand(0, 2)) + { + case 0: DoScriptText(SAY_SARTHARION_SLAY_1, m_creature); break; + case 1: DoScriptText(SAY_SARTHARION_SLAY_2, m_creature); break; + case 2: DoScriptText(SAY_SARTHARION_SLAY_3, m_creature); break; + } } void FetchDragons() { - if (!m_pInstance) - return; - Creature* pTene = m_pInstance->GetSingleCreatureFromStorage(NPC_TENEBRON); Creature* pShad = m_pInstance->GetSingleCreatureFromStorage(NPC_SHADRON); Creature* pVesp = m_pInstance->GetSingleCreatureFromStorage(NPC_VESPERON); //if at least one of the dragons are alive and are being called + uint8 uiCountFetchableDragons = 0; + if (pTene && pTene->isAlive() && !pTene->getVictim()) { - m_bTenebronHelpedInFight = true; - bCanUseWill = true; - pTene->CastSpell(pTene, SPELL_POWER_OF_TENEBRON, false); + ++uiCountFetchableDragons; pTene->SetLevitate(true); pTene->SetWalk(false); - pTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTene->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + DoCastSpellIfCan(pTene, 11010); + pTene->SetHover(true); pTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ); + + if (!pTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pTene->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } if (pShad && pShad->isAlive() && !pShad->getVictim()) { - m_bShadronHelpedInFight = true; - bCanUseWill = true; - pShad->CastSpell(pShad, SPELL_POWER_OF_SHADRON, false); + ++uiCountFetchableDragons; pShad->SetLevitate(true); pShad->SetWalk(false); - pShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pShad->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + DoCastSpellIfCan(pShad, 11010); + pShad->SetHover(true); pShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ); + + if (!pShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pShad->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } if (pVesp && pVesp->isAlive() && !pVesp->getVictim()) { - m_bVesperonHelpedInFight = true; - bCanUseWill = true; - pVesp->CastSpell(pVesp, SPELL_POWER_OF_VESPERON, false); + ++uiCountFetchableDragons; pVesp->SetLevitate(true); pVesp->SetWalk(false); - pVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pVesp->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + DoCastSpellIfCan(pVesp, 11010); + pVesp->SetHover(true); pVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ); - } - if (bCanUseWill) - DoCast(m_creature, SPELL_WILL_OF_SARTHARION); - } - - bool CallDragon(uint32 uiDataId) - { - uint32 uiEntry; + if (!pVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + pVesp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } - switch (uiDataId) + if (uiCountFetchableDragons) { - case DATA_TENEBRON: - uiEntry = NPC_TENEBRON; - break; - case DATA_SHADRON: - uiEntry = NPC_SHADRON; - break; - case DATA_VESPERON: - uiEntry = NPC_VESPERON; - break; + DoCastSpellIfCan(m_creature, SPELL_WILL_OF_SARTHARION); + bCanUseWill = true; } + m_pInstance->SetData(TYPE_ALIVE_DRAGONS, uiCountFetchableDragons); + } + + void CallDragon(uint32 uiEntry) + { if (m_pInstance) { Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(uiEntry); @@ -439,46 +452,50 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (pTemp && pTemp->isAlive() && !pTemp->getVictim()) { pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetWalk(false); m_uiSarthHealth = m_creature->GetHealth(); - DoCast(m_creature, SPELL_WILL_OF_SARTHARION); + DoCast(m_creature, SPELL_WILL_OF_SARTHARION, false); bCanUseWill = true; int32 iTextId = 0; Creature* pAdd = NULL; - if (pAdd = m_pInstance->GetSingleCreatureFromStorage(NPC_TENEBRON)) + pAdd = m_pInstance->GetSingleCreatureFromStorage(NPC_TENEBRON); + if (pAdd) m_uiTeneHealth = pAdd->GetHealth(); - if (pAdd = m_pInstance->GetSingleCreatureFromStorage(NPC_SHADRON)) + pAdd = m_pInstance->GetSingleCreatureFromStorage(NPC_SHADRON); + if (pAdd) m_uiShadHealth = pAdd->GetHealth(); - if (pAdd = m_pInstance->GetSingleCreatureFromStorage(NPC_VESPERON)) + pAdd = m_pInstance->GetSingleCreatureFromStorage(NPC_VESPERON); + if (pAdd) m_uiVespHealth = pAdd->GetHealth(); - switch (pTemp->GetEntry()) + switch(uiEntry) { case NPC_TENEBRON: iTextId = SAY_SARTHARION_CALL_TENEBRON; - pTemp->GetMotionMaster()->MovementExpired(true); pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ); + m_bTenebronHelpedInFight = true; + pTemp->CastSpell(pTemp, SPELL_POWER_OF_TENEBRON, false); break; case NPC_SHADRON: iTextId = SAY_SARTHARION_CALL_SHADRON; - pTemp->GetMotionMaster()->MovementExpired(true); pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ); + m_bShadronHelpedInFight = true; + pTemp->CastSpell(pTemp, SPELL_POWER_OF_SHADRON, false); break; case NPC_VESPERON: iTextId = SAY_SARTHARION_CALL_VESPERON; - pTemp->GetMotionMaster()->MovementExpired(true); pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ); + m_bVesperonHelpedInFight = true; + pTemp->CastSpell(pTemp, SPELL_POWER_OF_VESPERON, false); break; } - + pTemp->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + pTemp->SetHover(false); DoScriptText(iTextId, m_creature); - return true; } } - return false; } void SendFlameTsunami() @@ -505,27 +522,62 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI uiTsunamiWavesAmount = 2; for (uint8 i = uiTsunamiDirection*3; i < uiTsunamiDirection*3+uiTsunamiWavesAmount; ++i) { - // Tsunami visual - dummy npc - if (Creature *pTsunami1 = m_creature->SummonCreature(NPC_FLAME_TSUNAMI, m_afTsunamiStartLoc[i][0], m_afTsunamiStartLoc[i][1], m_afTsunamiStartLoc[i][2], m_afTsunamiStartLoc[i][3], TEMPSUMMON_TIMED_DESPAWN, 12000)) - pTsunami1->CastSpell(pTsunami1, SPELL_FLAME_TSUNAMI, true); - // Tsunami dmg aura - 2 dummy npcs - if (Creature *pTsunami2 = m_creature->SummonCreature(NPC_FLAME_TSUNAMI, m_afTsunamiStartLoc[i][0], m_afTsunamiStartLoc[i][1] - 5.0f, m_afTsunamiStartLoc[i][2], m_afTsunamiStartLoc[i][3], TEMPSUMMON_TIMED_DESPAWN, 12000)) - pTsunami2->CastSpell(pTsunami2, SPELL_FLAME_TSUNAMI_DMG_AURA, true); - if (Creature *pTsunami2 = m_creature->SummonCreature(NPC_FLAME_TSUNAMI, m_afTsunamiStartLoc[i][0], m_afTsunamiStartLoc[i][1] + 5.0f, m_afTsunamiStartLoc[i][2], m_afTsunamiStartLoc[i][3], TEMPSUMMON_TIMED_DESPAWN, 12000)) - pTsunami2->CastSpell(pTsunami2, SPELL_FLAME_TSUNAMI_DMG_AURA, true); + m_creature->SummonCreature(NPC_FLAME_TSUNAMI, m_afTsunamiStartLoc[i][0], m_afTsunamiStartLoc[i][1], m_afTsunamiStartLoc[i][2], m_afTsunamiStartLoc[i][3], TEMPSUMMON_TIMED_DESPAWN, 18000); + } + } + + //Removes debuff from players + void RemoveDebuff(uint32 uiSpellId) + { + Map* pMap = m_creature->GetMap(); + + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + i->getSource()->RemoveAurasDueToSpell(uiSpellId); + if (uiSpellId == SPELL_TWILIGHT_SHIFT_ENTER) + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_DMG); + } } } + void CheckTwilightRealm() + { + bool bNoAliveTwilightRealm = true; + if (m_pInstance) + { + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID)) + if (pAcolyte->isAlive()) + bNoAliveTwilightRealm = false; + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID)) + if (pAcolyte->isAlive()) + bNoAliveTwilightRealm = false; + if (!m_lEggsGUIDList.empty()) + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( *itr)) + if (pTemp->isAlive()) + { + bNoAliveTwilightRealm = false; + break; + } + if (bNoAliveTwilightRealm) + RemoveDebuff(SPELL_TWILIGHT_SHIFT_ENTER); + } + } + void UpdateAI(const uint32 uiDiff) { //Return since we have no target if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // If the current target is in other realm, then Sartharion will lose his threat on the target - if (!(m_creature->GetPhaseMask() & m_creature->getVictim()->GetPhaseMask()) ) - m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(), -100); - + //check for hard mode buff if (bCanUseWill) { if (bFirstWill) @@ -550,28 +602,37 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI bFirstWill = false; } - - // Enrage - cast if any drake is still alive at Sartharion's 25% - if (!m_bIsBerserk && m_creature->GetHealthPercent() <= 25.0f) + //berserk - cast if any drake is still alive at Sartharion's 35% + if (!m_bIsBerserk && (m_creature->GetHealthPercent() <= 35.0f)) { + bool canBerserk =false; Creature* pTemp = NULL; - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TENEBRON); - if (!pTemp || !pTemp->isAlive()) - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_SHADRON); - if (!pTemp || !pTemp->isAlive()) - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_VESPERON); - if (pTemp && pTemp->isAlive() ) + pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TENEBRON); + if (pTemp && pTemp->isAlive()) + canBerserk = true; + pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_SHADRON); + if (pTemp && pTemp->isAlive()) + canBerserk = true; + pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_VESPERON); + if (pTemp && pTemp->isAlive()) + canBerserk = true; + if (canBerserk) { DoScriptText(SAY_SARTHARION_BERSERK, m_creature); DoCast(m_creature, SPELL_BERSERK); - m_bIsBerserk = true; } + m_bIsBerserk = true; } //soft enrage if (!m_bIsSoftEnraged && m_creature->GetHealthPercent() <= 10.0f) { + if (!m_lFireCyclones.empty()) + for (std::list::iterator iter = m_lFireCyclones.begin(); iter != m_lFireCyclones.end(); ++iter) + if (*iter) + (*iter)->CastSpell(*iter, SPELL_CYCLONE_AURA_2, true); + m_bIsSoftEnraged = true; } @@ -591,8 +652,15 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (m_uiFlameTsunamiTimer < uiDiff) { SendFlameTsunami(); - DoScriptText(SAY_SARTHARION_SPECIAL_1 - urand(0, 3), m_creature); - m_uiFlameTsunamiTimer = 30000; + switch(urand(0, 3)) + { + case 0: DoScriptText(SAY_SARTHARION_SPECIAL_1, m_creature); break; + case 1: DoScriptText(SAY_SARTHARION_SPECIAL_2, m_creature); break; + case 2: DoScriptText(SAY_SARTHARION_SPECIAL_3, m_creature); break; + case 3: DoScriptText(SAY_SARTHARION_SPECIAL_4, m_creature); break; + } + + m_uiFlameTsunamiTimer = m_bIsRegularMode ? 30000 : 20000; } else m_uiFlameTsunamiTimer -= uiDiff; @@ -602,7 +670,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI { DoScriptText(SAY_SARTHARION_BREATH, m_creature); DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); - m_uiFlameBreathTimer = urand(25000, 35000); + m_uiFlameBreathTimer = urand(25000, 35000) * (m_bIsRegularMode ? 1 : 0.8); } else m_uiFlameBreathTimer -= uiDiff; @@ -611,7 +679,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (m_uiTailSweepTimer < uiDiff) { DoCast(m_creature, m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H); - m_uiTailSweepTimer = urand(5000, 7000); + m_uiTailSweepTimer = urand(5000, 7000) * (m_bIsRegularMode ? 1 : 0.8); } else m_uiTailSweepTimer -= uiDiff; @@ -620,81 +688,77 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (m_uiCleaveTimer < uiDiff) { DoCast(m_creature->getVictim(), SPELL_CLEAVE); - m_uiCleaveTimer = urand(7000, 10000); + m_uiCleaveTimer = urand(7000, 10000) * (m_bIsRegularMode ? 1 : 0.8); } else m_uiCleaveTimer -= uiDiff; - // Call dragon - if ((m_uiCurrentCallDragonData < 3) && m_uiCallDragonTimer < uiDiff) - { - if (CallDragon(DATA_TENEBRON + m_uiCurrentCallDragonData++)) - m_uiCallDragonTimer = 45000 + (m_uiCurrentCallDragonData - 1) * 10000; - } - else - m_uiCallDragonTimer -= uiDiff; - - // Check if any player should leave the Twilight Realm - if (m_uiCheckTwilightTimer < uiDiff) + // Lavas Strike + if (m_uiCycloneAuraTimer < uiDiff) { - if (m_pInstance) + if (!m_lFireCyclones.empty()) { - bool bNoAliveTwilightRealm = true; - - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_SHADRON)) + std::list::iterator iter = m_lFireCyclones.begin(); + advance(iter, urand(0, m_lFireCyclones.size()-1)); + if (*iter) { - if (pAcolyte->isAlive()) - bNoAliveTwilightRealm = false; - } - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_VESPERON)) - { - if (pAcolyte->isAlive()) - { - bNoAliveTwilightRealm = false; + (*iter)->CastSpell(*iter, SPELL_CYCLONE_AURA_2, true); - // Sartharion event is in progress - SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(58835); - if (pTempSpell) - { - pTempSpell->StackAmount = 1; - pTempSpell->procCharges = 1; - m_creature->CastSpell(m_creature, pTempSpell, true); - } + switch(urand(0, 15)) + { + case 0: DoScriptText(SAY_SARTHARION_SPECIAL_1, m_creature); break; + case 1: DoScriptText(SAY_SARTHARION_SPECIAL_2, m_creature); break; + case 2: DoScriptText(SAY_SARTHARION_SPECIAL_3, m_creature); break; } } - if (!m_pInstance->m_lEggsGUIDList.empty()) - for (GUIDList::iterator itr = m_pInstance->m_lEggsGUIDList.begin(); itr != m_pInstance->m_lEggsGUIDList.end(); ++itr) - if (Creature* pTemp = m_pInstance->instance->GetCreature(*itr)) - if (pTemp->isAlive()) - bNoAliveTwilightRealm = false; + } + if (m_bIsSoftEnraged) + m_uiCycloneAuraTimer = m_bIsRegularMode ? 10000 : 8000; + else + m_uiCycloneAuraTimer = urand(20000, 25000) * (m_bIsRegularMode ? 1 : 0.8); + } + else + m_uiCycloneAuraTimer -= uiDiff; - // probably correct way, since removing from twilight realm should only occur, - // when no creatures are present in it. or maybe there should be some dummy npc for this? - if (bNoAliveTwilightRealm) - { - Map* pMap = m_creature->GetMap(); + // call tenebron + if (!m_bHasCalledTenebron && m_uiTenebronTimer < uiDiff) + { + CallDragon(NPC_TENEBRON); + m_bHasCalledTenebron = true; + } + else + m_uiTenebronTimer -= uiDiff; - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); + // call shadron + if (!m_bHasCalledShadron && m_uiShadronTimer < uiDiff) + { + CallDragon(NPC_SHADRON); + m_bHasCalledShadron = true; + } + else + m_uiShadronTimer -= uiDiff; - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT_ENTER)) - i->getSource()->CastSpell(i->getSource(), SPELL_TWILIGHT_SHIFT_REMOVAL, true); - } - } - } - } - } - m_uiCheckTwilightTimer = 3000; + // call vesperon + if (!m_bHasCalledVesperon && m_uiVesperonTimer < uiDiff) + { + CallDragon(NPC_VESPERON); + m_bHasCalledVesperon = true; + } + else + m_uiVesperonTimer -= uiDiff; + + // check for alive acolytes or eggs in twilight realm + if (m_uiCheckTwilightTimer < uiDiff) + { + CheckTwilightRealm(); + m_uiCheckTwilightTimer = 2000; } else m_uiCheckTwilightTimer -= uiDiff; DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); } }; @@ -705,51 +769,51 @@ CreatureAI* GetAI_boss_sartharion(Creature* pCreature) enum TeneText { - SAY_TENEBRON_AGGRO = -1615009, - SAY_TENEBRON_SLAY_1 = -1615010, - SAY_TENEBRON_SLAY_2 = -1615011, - SAY_TENEBRON_DEATH = -1615012, - SAY_TENEBRON_BREATH = -1615013, - SAY_TENEBRON_RESPOND = -1615014, - SAY_TENEBRON_SPECIAL_1 = -1615015, - SAY_TENEBRON_SPECIAL_2 = -1615016 + SAY_TENEBRON_AGGRO = -1615009, + SAY_TENEBRON_SLAY_1 = -1615010, + SAY_TENEBRON_SLAY_2 = -1615011, + SAY_TENEBRON_DEATH = -1615012, + SAY_TENEBRON_BREATH = -1615013, + SAY_TENEBRON_RESPOND = -1615014, + SAY_TENEBRON_SPECIAL_1 = -1615015, + SAY_TENEBRON_SPECIAL_2 = -1615016 }; enum ShadText { - SAY_SHADRON_AGGRO = -1615000, - SAY_SHADRON_SLAY_1 = -1615001, - SAY_SHADRON_SLAY_2 = -1615002, - SAY_SHADRON_DEATH = -1615003, - SAY_SHADRON_BREATH = -1615004, - SAY_SHADRON_RESPOND = -1615005, - SAY_SHADRON_SPECIAL_1 = -1615006, - SAY_SHADRON_SPECIAL_2 = -1615007 + SAY_SHADRON_AGGRO = -1615000, + SAY_SHADRON_SLAY_1 = -1615001, + SAY_SHADRON_SLAY_2 = -1615002, + SAY_SHADRON_DEATH = -1615003, + SAY_SHADRON_BREATH = -1615004, + SAY_SHADRON_RESPOND = -1615005, + SAY_SHADRON_SPECIAL_1 = -1615006, + SAY_SHADRON_SPECIAL_2 = -1615007 }; enum VespText { - SAY_VESPERON_AGGRO = -1615033, - SAY_VESPERON_SLAY_1 = -1615034, - SAY_VESPERON_SLAY_2 = -1615035, - SAY_VESPERON_DEATH = -1615036, - SAY_VESPERON_BREATH = -1615037, - SAY_VESPERON_RESPOND = -1615038, - SAY_VESPERON_SPECIAL_1 = -1615039, - SAY_VESPERON_SPECIAL_2 = -1615040 + SAY_VESPERON_AGGRO = -1615033, + SAY_VESPERON_SLAY_1 = -1615034, + SAY_VESPERON_SLAY_2 = -1615035, + SAY_VESPERON_DEATH = -1615036, + SAY_VESPERON_BREATH = -1615037, + SAY_VESPERON_RESPOND = -1615038, + SAY_VESPERON_SPECIAL_1 = -1615039, + SAY_VESPERON_SPECIAL_2 = -1615040 }; -// to control each dragon's common abilities +//to control each dragons common abilities struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI { dummy_dragonAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = ((instance_obsidian_sanctum*)pCreature->GetInstanceData()); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_obsidian_sanctum* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiWaypointId; @@ -758,10 +822,8 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI void Reset() { - m_creature->SetLevitate(true); - m_creature->SetWalk(false); - if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiWaypointId = 0; m_uiMoveNextTimer = 500; m_bCanMoveFree = false; @@ -785,8 +847,7 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI void JustReachedHome() { - if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetWalk(false); } void MovementInform(uint32 uiType, uint32 uiPointId) @@ -799,7 +860,6 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI //if healers messed up the raid and we was already initialized if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) { - m_creature->GetMotionMaster()->Clear(); EnterEvadeMode(); return; } @@ -809,6 +869,7 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI { m_creature->GetMotionMaster()->Clear(); m_bCanMoveFree = false; + m_creature->SetWalk(false); m_creature->SetInCombatWithZone(); return; } @@ -862,13 +923,9 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { + i->getSource()->RemoveAurasDueToSpell(uiSpellId); if (uiSpellId == SPELL_TWILIGHT_SHIFT_ENTER) - { - if (i->getSource() && i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT_ENTER)) - i->getSource()->CastSpell(i->getSource(), SPELL_TWILIGHT_SHIFT_REMOVAL, true); - } - else - i->getSource()->RemoveAurasDueToSpell(uiSpellId); + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_DMG); } } } @@ -890,25 +947,28 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI { case NPC_TENEBRON: iTextId = WHISPER_HATCH_EGGS; - m_creature->SummonCreature(NPC_TWILIGHT_EGG_CONTROLLER, pPortal->GetPositionX(), pPortal->GetPositionY(), pPortal->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); - iPortalRespawnTime = 30; + m_lEggsGUIDList.clear(); + for (uint8 i=0; i<6; ++i) + { + if (Creature* pEgg = m_creature->SummonCreature(NPC_TWILIGHT_EGG, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) + { + pEgg->SetPhaseMask(16, true); + m_lEggsGUIDList.push_back(pEgg->GetObjectGuid()); + } + } + iPortalRespawnTime = 20; break; case NPC_SHADRON: iTextId = WHISPER_OPEN_PORTAL; if (m_pInstance) { - pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_SHADRON); + pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID); if (!pAcolyte || (pAcolyte && pAcolyte->isDead())) { pAcolyte = NULL; - - uint32 uiShadronAddEntry = NPC_DISCIPLE_OF_SHADRON; - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - uiShadronAddEntry = NPC_ACOLYTE_OF_SHADRON; - - if (pAcolyte = m_creature->SummonCreature(uiShadronAddEntry, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 7*DAY)) + if (pAcolyte = m_creature->SummonCreature(NPC_ACOLYTE_OF_SHADRON, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000)) { - m_pInstance->SetAcolyteGuid(NPC_ACOLYTE_OF_SHADRON, pAcolyte->GetObjectGuid()); + m_uiAcolyteShadronGUID = pAcolyte->GetObjectGuid(); pAcolyte->SetPhaseMask(16, true); } } @@ -939,22 +999,17 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI if (pTempSpell) { pTempSpell->StackAmount = 1; - pTempSpell->procCharges = 1; + pTempSpell->procCharges = 0; m_creature->CastSpell(m_creature, pTempSpell, true); } - pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_VESPERON); + pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID); if (!pAcolyte || (pAcolyte && pAcolyte->isDead())) { pAcolyte = NULL; - - uint32 uiVesperonAddEntry = NPC_DISCIPLE_OF_VESPERON; - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - uiVesperonAddEntry = NPC_ACOLYTE_OF_VESPERON; - - if (pAcolyte = m_creature->SummonCreature(uiVesperonAddEntry, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 7*DAY*IN_MILLISECONDS)) + if (pAcolyte = m_creature->SummonCreature(NPC_ACOLYTE_OF_VESPERON, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000)) { - m_pInstance->SetAcolyteGuid(NPC_ACOLYTE_OF_VESPERON, pAcolyte->GetObjectGuid()); + m_uiAcolyteVesperonGUID = pAcolyte->GetObjectGuid(); pAcolyte->SetPhaseMask(16, true); } } @@ -967,48 +1022,35 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI //By using SetRespawnTime() we will actually "spawn" the object with our defined time. //Once time is up, portal will disappear again. - + pPortal->SetRespawnTime(iPortalRespawnTime); - pPortal->Refresh(); + pPortal->UpdateObjectVisibility(); //Unclear what are expected to happen if one drake has a portal open already //Refresh respawnTime so time again are set to 30secs? } } + void CheckTwilightRealm() { bool bNoAliveTwilightRealm = true; if (m_pInstance) { - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_SHADRON)) + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID)) if (pAcolyte->isAlive()) bNoAliveTwilightRealm = false; - - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_VESPERON)) + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID)) if (pAcolyte->isAlive()) - { bNoAliveTwilightRealm = false; - - // Sartharion event not in progress - SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(57935); - if (pTempSpell) - { - pTempSpell->StackAmount = 1; - pTempSpell->procCharges = 1; - m_creature->CastSpell(m_creature, pTempSpell, true); - } - } - - if (!m_pInstance->m_lEggsGUIDList.empty()) - for (GUIDList::iterator itr = m_pInstance->m_lEggsGUIDList.begin(); itr != m_pInstance->m_lEggsGUIDList.end(); ++itr) - if (Creature* pTemp = m_pInstance->instance->GetCreature(*itr)) + if (!m_lEggsGUIDList.empty()) + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( *itr)) if (pTemp->isAlive()) { bNoAliveTwilightRealm = false; break; } - if (bNoAliveTwilightRealm) RemoveDebuff(SPELL_TWILIGHT_SHIFT_ENTER); } @@ -1016,75 +1058,65 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI void JustDied(Unit* pKiller) { - if (!m_pInstance) - return; - int32 iTextId = 0; switch(m_creature->GetEntry()) { case NPC_TENEBRON: { - m_pInstance->SetData(TYPE_TENEBRON, DONE); iTextId = SAY_TENEBRON_DEATH; - - if (!m_pInstance->m_lEggsGUIDList.empty()) - for (GUIDList::iterator itr = m_pInstance->m_lEggsGUIDList.begin(); itr != m_pInstance->m_lEggsGUIDList.end(); ++itr) - if (Creature* pEgg = m_pInstance->instance->GetCreature(*itr)) + + if (!m_lEggsGUIDList.empty()) + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pEgg = m_creature->GetMap()->GetCreature( *itr)) pEgg->ForcedDespawn(); break; } case NPC_SHADRON: { - m_pInstance->SetData(TYPE_SHADRON, DONE); iTextId = SAY_SHADRON_DEATH; + + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID)) + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; } case NPC_VESPERON: { - m_pInstance->SetData(TYPE_VESPERON, DONE); iTextId = SAY_VESPERON_DEATH; - // kill Disciple of Vesperon if solo fight or died after killing Sartharion - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_VESPERON)) - pAcolyte->ForcedDespawn(); + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID)) + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; } } DoScriptText(iTextId, m_creature); - // not if solo mini-boss fight - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - { - // bind to the instance only when solo fighting - if (Player *pCreditPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself() ) - ((DungeonMap *)pCreditPlayer->GetMap())->PermBindAllPlayers(pCreditPlayer); - RemoveDebuff(SPELL_TWILIGHT_SHIFT_ENTER); - } - // Twilight Revenge to main boss - else if (Unit* pSartharion = m_pInstance->GetSingleCreatureFromStorage(NPC_SARTHARION)) + if (m_pInstance) { - if (pSartharion->isAlive()) - m_creature->CastSpell(pSartharion, SPELL_TWILIGHT_REVENGE, true, 0, 0, pSartharion->GetObjectGuid()); + // not if solo mini-boss fight + if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + RemoveDebuff(SPELL_TWILIGHT_SHIFT_ENTER); + return; + } + + // Twilight Revenge to main boss + if (Creature* pSartharion = m_pInstance->GetSingleCreatureFromStorage(NPC_SARTHARION)) + { + if (pSartharion->isAlive()) + m_creature->CastSpell(pSartharion, SPELL_TWILIGHT_REVENGE, true, 0, 0, pSartharion->GetObjectGuid()); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } } - // emblems should be in Sartharion's body if fighting in any hard mode - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS || m_pInstance->GetData(TYPE_SARTHARION_EVENT) == DONE) - m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - else - m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } void UpdateAI(const uint32 uiDiff) { if (m_bCanMoveFree && m_uiMoveNextTimer) { - if (!m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - { - m_uiMoveNextTimer = 0; - return; - } if (m_uiMoveNextTimer <= uiDiff) { m_creature->GetMotionMaster()->MovePoint(m_uiWaypointId, @@ -1107,63 +1139,35 @@ struct MANGOS_DLL_DECL mob_tenebronAI : public dummy_dragonAI { mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); Reset(); } - instance_obsidian_sanctum *m_pInstance; - uint32 m_uiShadowBreathTimer; uint32 m_uiShadowFissureTimer; - uint32 m_uiSpawnEggsTimer; - uint32 m_uiHatchEggsTimer; + uint32 m_uiHatchEggTimer; uint32 m_uiCheckTimer; void Reset() { m_uiShadowBreathTimer = 10000; m_uiShadowFissureTimer = 8000; - m_uiSpawnEggsTimer = 15000; - m_uiHatchEggsTimer = 15000 + 15000; // cast dummy spell 15 seconds after eggs spawned + m_uiHatchEggTimer = 15000; m_uiCheckTimer = 2000; - - if (!m_pInstance) - return; - - m_pInstance->SetData(TYPE_TENEBRON, NOT_STARTED); - - if (!m_pInstance->m_lEggsGUIDList.empty()) - for (GUIDList::iterator i = m_pInstance->m_lEggsGUIDList.begin(); i != m_pInstance->m_lEggsGUIDList.end(); i++) - if (Creature *pEgg = m_pInstance->instance->GetCreature(*i)) - if (pEgg->isAlive()) - pEgg->ForcedDespawn(); - m_pInstance->m_lEggsGUIDList.clear(); - - if (!m_pInstance->m_lWhelpsGUIDList.empty()) - for (GUIDList::iterator i = m_pInstance->m_lWhelpsGUIDList.begin(); i != m_pInstance->m_lWhelpsGUIDList.end(); i++) - if (Creature *pWhelp = m_pInstance->instance->GetCreature(*i)) - if (pWhelp->isAlive()) - pWhelp->ForcedDespawn(); - m_pInstance->m_lWhelpsGUIDList.clear(); + if (!m_lEggsGUIDList.empty()) //inserito per facilitare il reset dopo il fight, in modo da eliminare le uova non schiuse rimaste + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pEgg = m_creature->GetMap()->GetCreature( *itr)) + pEgg->ForcedDespawn(); + m_lEggsGUIDList.clear(); } void Aggro(Unit* pWho) { - if (!m_pInstance) - return; - - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - DoScriptText(SAY_TENEBRON_RESPOND,m_creature); - else - { - m_pInstance->SetData(TYPE_TENEBRON, IN_PROGRESS); - DoScriptText(SAY_TENEBRON_AGGRO,m_creature); - } + DoScriptText(SAY_TENEBRON_AGGRO, m_creature); } void KilledUnit(Unit* pVictim) { - DoScriptText(SAY_TENEBRON_SLAY_1 - urand(0, 1), m_creature); + DoScriptText(urand(0, 1) ? SAY_TENEBRON_SLAY_1 : SAY_TENEBRON_SLAY_2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -1196,34 +1200,13 @@ struct MANGOS_DLL_DECL mob_tenebronAI : public dummy_dragonAI else m_uiShadowBreathTimer -= uiDiff; - // Spawn eggs in the Twilight Realm - if (m_uiSpawnEggsTimer < uiDiff) + if (m_uiHatchEggTimer < uiDiff) { OpenPortal(); - m_uiSpawnEggsTimer = 45000; + m_uiHatchEggTimer = 45000; } else - m_uiSpawnEggsTimer -= uiDiff; - - // Cast Hatch Eggs - Twilight Whelps spawn - if (m_uiHatchEggsTimer < uiDiff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - { - DoCastSpellIfCan(m_creature, SPELL_HATCH_SARTHARION_EGGS, CAST_INTERRUPT_PREVIOUS); - m_uiHatchEggsTimer = m_uiSpawnEggsTimer + 17500; - } - else - { - DoCastSpellIfCan(m_creature, SPELL_HATCH_EGGS, CAST_INTERRUPT_PREVIOUS); - m_uiHatchEggsTimer = m_uiSpawnEggsTimer + 15000; - } - } - } - else - m_uiHatchEggsTimer -= uiDiff; + m_uiHatchEggTimer -= uiDiff; if (m_uiCheckTimer < uiDiff && m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) { @@ -1250,12 +1233,9 @@ struct MANGOS_DLL_DECL mob_shadronAI : public dummy_dragonAI { mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); Reset(); } - instance_obsidian_sanctum *m_pInstance; - uint32 m_uiShadowBreathTimer; uint32 m_uiShadowFissureTimer; uint32 m_uiAcolyteShadronTimer; @@ -1267,33 +1247,19 @@ struct MANGOS_DLL_DECL mob_shadronAI : public dummy_dragonAI m_uiShadowFissureTimer = 8000; m_uiAcolyteShadronTimer = 15000; m_uiCheckTimer = 2000; - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_SHADRON, NOT_STARTED); - - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_SHADRON)) - pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID))//inserito per facilitare il reset dopo il fight, in modo da eliminare l'accolito eventualmente rimasto vivo + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_uiAcolyteShadronGUID.Clear(); } void Aggro(Unit* pWho) { - if (!m_pInstance) - return; - - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - DoScriptText(SAY_SHADRON_RESPOND,m_creature); - else - { - DoScriptText(SAY_SHADRON_AGGRO,m_creature); - m_pInstance->SetData(TYPE_SHADRON, IN_PROGRESS); - } + DoScriptText(SAY_SHADRON_AGGRO,m_creature); } void KilledUnit(Unit* pVictim) { - DoScriptText(SAY_SHADRON_SLAY_1 - urand(0, 1), m_creature); + DoScriptText(urand(0, 1) ? SAY_SHADRON_SLAY_1 : SAY_SHADRON_SLAY_2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -1359,51 +1325,33 @@ struct MANGOS_DLL_DECL mob_vesperonAI : public dummy_dragonAI { mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); Reset(); } - instance_obsidian_sanctum *m_pInstance; - uint32 m_uiShadowBreathTimer; uint32 m_uiShadowFissureTimer; uint32 m_uiAcolyteVesperonTimer; uint32 m_uiCheckTimer; - uint32 m_uiTwilightRevengeTimer; void Reset() { m_uiShadowBreathTimer = 10000; m_uiShadowFissureTimer = 8000; m_uiAcolyteVesperonTimer = 15000; - m_uiCheckTimer = 3000; - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_VESPERON, NOT_STARTED); - - if (Creature* pAcolyte = m_pInstance->GetSingleCreatureFromStorage(NPC_ACOLYTE_OF_VESPERON)) - pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } + m_uiCheckTimer = 2000; + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID))//inserito per facilitare il reset dopo il fight, in modo da eliminare l'accolito eventualmente rimasto vivo + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_uiAcolyteVesperonGUID.Clear(); } void Aggro(Unit* pWho) { - if (!m_pInstance) - return; - - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - DoScriptText(SAY_VESPERON_RESPOND,m_creature); - else - { - m_pInstance->SetData(TYPE_VESPERON, IN_PROGRESS); - DoScriptText(SAY_VESPERON_AGGRO,m_creature); - } + DoScriptText(SAY_VESPERON_AGGRO,m_creature); } void KilledUnit(Unit* pVictim) { - DoScriptText(SAY_VESPERON_SLAY_1 - urand(0, 1), m_creature); + DoScriptText(urand(0, 1) ? SAY_VESPERON_SLAY_1 : SAY_VESPERON_SLAY_2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -1447,7 +1395,7 @@ struct MANGOS_DLL_DECL mob_vesperonAI : public dummy_dragonAI if (m_uiCheckTimer < uiDiff && m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) { CheckTwilightRealm(); - m_uiCheckTimer = 3000; + m_uiCheckTimer = 2000; } else m_uiCheckTimer -= uiDiff; @@ -1469,14 +1417,15 @@ struct MANGOS_DLL_DECL mob_acolyte_of_shadronAI : public ScriptedAI { mob_acolyte_of_shadronAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_obsidian_sanctum* m_pInstance; + ScriptedInstance* m_pInstance; - void Reset(){} - void MoveInLineOfSight(Unit *pWho){} + void Reset() + { + } void JustDied(Unit* killer) { @@ -1499,14 +1448,6 @@ struct MANGOS_DLL_DECL mob_acolyte_of_shadronAI : public ScriptedAI if (pDebuffTarget && pDebuffTarget->isAlive() && pDebuffTarget->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) pDebuffTarget->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); - - // remove from twilight realm - Map::PlayerList const &PlayerList = m_pInstance->instance->GetPlayers(); - - if (!PlayerList.isEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_TWILIGHT_SHIFT_ENTER)) - i->getSource()->CastSpell(i->getSource(), SPELL_TWILIGHT_SHIFT_REMOVAL, true); } } } @@ -1533,20 +1474,42 @@ struct MANGOS_DLL_DECL mob_acolyte_of_vesperonAI : public ScriptedAI { mob_acolyte_of_vesperonAI(Creature* pCreature) : ScriptedAI(pCreature) { - //m_pInstance = (instance_obsidian_sanctum*)pCreature->GetInstanceData(); - //Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); } - //instance_obsidian_sanctum* m_pInstance; + ScriptedInstance* m_pInstance; - void Reset(){} + void Reset() + { + } - void MoveInLineOfSight(Unit *pWho){} + void JustDied(Unit* pKiller) + { + // remove twilight torment + Map* pMap = m_creature->GetMap(); + + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + i->getSource()->RemoveAurasDueToSpell(57935); + i->getSource()->RemoveAurasDueToSpell(58835); + } + } + } void UpdateAI(const uint32 uiDiff) { - if (m_creature->SelectHostileTarget() && m_creature->getVictim()) - DoMeleeAttackIfReady(); + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); } }; @@ -1561,107 +1524,43 @@ CreatureAI* GetAI_mob_acolyte_of_vesperon(Creature* pCreature) struct MANGOS_DLL_DECL mob_twilight_eggsAI : public ScriptedAI { - mob_twilight_eggsAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); - Reset(); - } - - instance_obsidian_sanctum *m_pInstance; + mob_twilight_eggsAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } - void Reset(){} - void AttackStart(Unit* pWho){} - void MoveInLineOfSight(Unit* pWho){} - void UpdateAI(const uint32 uiDiff){} + uint32 m_uiSummonWhelpTimer; - void JustSummoned(Creature *pCreature) + void Reset() { - if (!m_pInstance) - return; - - m_pInstance->m_lWhelpsGUIDList.push_back(pCreature->GetObjectGuid()); - pCreature->SetPhaseMask(1, true); - pCreature->SetInCombatWithZone(); - m_creature->ForcedDespawn(); + m_uiSummonWhelpTimer = 20000; } -}; -CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) -{ - return new mob_twilight_eggsAI(pCreature); -} - -/*###### -## Mob Twilight Egg Controller -######*/ - -struct MANGOS_DLL_DECL mob_twilight_egg_controllerAI : public ScriptedAI -{ - mob_twilight_egg_controllerAI(Creature* pCreature) : ScriptedAI(pCreature) + void AttackStart(Unit* pWho) { - pCreature->SetDisplayId(11686); - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); - Reset(); } - instance_obsidian_sanctum *m_pInstance; - - void Reset() + void MoveInLineOfSight(Unit* pWho) { - if (!m_pInstance) - return; - - uint32 uiEggEntry = 0; - - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - uiEggEntry = NPC_SARTHARION_TWILIGHT_EGG; - else - uiEggEntry = NPC_TWILIGHT_EGG; - - m_pInstance->m_lEggsGUIDList.clear(); + } - for (uint8 i=0; i<6; ++i) + void UpdateAI(const uint32 uiDiff) + { + if (m_uiSummonWhelpTimer < uiDiff) { - if (Creature* pEgg = m_creature->SummonCreature(uiEggEntry, m_creature->GetPositionX()-10+urand(0, 20), m_creature->GetPositionY()-10+urand(0, 20), m_creature->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) + if (Creature* pWhelp = DoSpawnCreature(NPC_TWILIGHT_WHELP, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { - pEgg->SetPhaseMask(16, true); - m_pInstance->m_lEggsGUIDList.push_back(pEgg->GetObjectGuid()); + pWhelp->SetPhaseMask(1, true); + pWhelp->SetInCombatWithZone(); } + m_uiSummonWhelpTimer = 20000; + m_creature->ForcedDespawn(); } - } - void AttackStart(Unit* pWho){} - void MoveInLineOfSight(Unit* pWho){} - void UpdateAI(const uint32 uiDiff){} - - void SpellHit(Unit *pCaster, const SpellEntry *spellInfo) - { - if (!m_pInstance) - return; - - uint32 spell = 0; - - if (spellInfo->Id == SPELL_HATCH_EGGS) - spell = SPELL_SUMMON_TWILIGHT_WHELP; - else if (spellInfo->Id == SPELL_HATCH_SARTHARION_EGGS) - spell = SPELL_SUMMON_SARTH_TWILIGHT_WHELP; else - return; - - if (m_pInstance->m_lEggsGUIDList.empty()) - return; - - for (GUIDList::iterator i = m_pInstance->m_lEggsGUIDList.begin(); i != m_pInstance->m_lEggsGUIDList.end(); i++) - if (Creature *pEgg = m_pInstance->instance->GetCreature(*i)) - if (pEgg->isAlive()) - pEgg->CastSpell(pEgg, spell, true); - - m_creature->ForcedDespawn(); + m_uiSummonWhelpTimer -= uiDiff; } }; -CreatureAI* GetAI_mob_twilight_egg_controller(Creature* pCreature) +CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) { - return new mob_twilight_egg_controllerAI(pCreature); + return new mob_twilight_eggsAI(pCreature); } /*###### @@ -1670,17 +1569,13 @@ CreatureAI* GetAI_mob_twilight_egg_controller(Creature* pCreature) struct MANGOS_DLL_DECL mob_twilight_whelpAI : public ScriptedAI { - mob_twilight_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); - Reset(); - } + mob_twilight_whelpAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } - instance_obsidian_sanctum *m_pInstance; uint32 m_uiFadeArmorTimer; void Reset() { + m_creature->SetRespawnDelay(DAY); m_uiFadeArmorTimer = 1000; } @@ -1690,14 +1585,10 @@ struct MANGOS_DLL_DECL mob_twilight_whelpAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // Whelps travel through both realms when chasing their target - if (!(m_creature->GetPhaseMask() & m_creature->getVictim()->GetPhaseMask()) ) - m_creature->SetPhaseMask(m_creature->GetPhaseMask() | m_creature->getVictim()->GetPhaseMask(), true); - - // Fade Armor + // twilight torment if (m_uiFadeArmorTimer < uiDiff) { - m_creature->CastSpell(m_creature->getVictim(), SPELL_FADE_ARMOR, false); + DoCast(m_creature->getVictim(), SPELL_FADE_ARMOR); m_uiFadeArmorTimer = urand(5000, 10000); } else @@ -1720,119 +1611,63 @@ struct MANGOS_DLL_DECL mob_fire_cycloneAI : public ScriptedAI { mob_fire_cycloneAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)pCreature->GetInstanceData(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_obsidian_sanctum* m_pInstance; - bool m_bIsRegularMode; - - uint32 m_uiRefreshTimer; uint32 m_uiLavaStrikeTimer; - uint8 m_uiLavaBlazeCount; + uint8 m_uiLavaStrikesCount; bool m_bLavaStrikeAllowed; + void Reset() { m_bLavaStrikeAllowed = false; - m_uiRefreshTimer = (urand(1000, 60000)); } - void DamageTaken(Unit *pDoneBy, uint32 &uiDamage) + void AttackStart(Unit* pWho) { - uiDamage = 0; } - void AttackStart(Unit* pWho){} - void MoveInLineOfSight(Unit* pWho){} - - void SpellHitTarget(Unit *pVictim, const SpellEntry *spellInfo) + void MoveInLineOfSight(Unit* pWho) { - if (spellInfo->Id == SPELL_LAVA_STRIKE_DMG) - if (m_pInstance && pVictim) - m_pInstance->m_lHitByVolcanoGUIDList.push_back(pVictim->GetObjectGuid()); } - void JustSummoned(Creature* pSummoned) + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) { - if (!m_pInstance || !pSummoned || pSummoned->GetEntry() != NPC_LAVA_BLAZE) - return; - - if(Creature* pSartharion = m_pInstance->GetSingleCreatureFromStorage(NPC_SARTHARION)) + if (pSpell->Id == SPELL_CYCLONE_AURA_2) { - if(pSartharion->isAlive() ) - { - if(((boss_sartharionAI*)pSartharion->AI())->m_bIsSoftEnraged) - { - m_pInstance->m_lBlazesGUIDList.push_back(pSummoned->GetObjectGuid()); - pSummoned->setFaction(14); - pSummoned->SetInCombatWithZone(); - } - else - { - if (roll_chance_i(m_bIsRegularMode ? 8 : 18)) - { - m_pInstance->m_lBlazesGUIDList.push_back(pSummoned->GetObjectGuid()); - pSummoned->setFaction(14); - pSummoned->SetInCombatWithZone(); - } - else - pSummoned->ForcedDespawn(); - } - } + DoCast(m_creature, 57560, true); + m_bLavaStrikeAllowed = true; + m_uiLavaStrikeTimer = 0; + m_uiLavaStrikesCount = 0; } } + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_LAVA_BLAZE) + if (urand(0, 3)) //25% to stay + pSummoned->ForcedDespawn(); + else + pSummoned->SetInCombatWithZone(); + } + void UpdateAI(const uint32 uiDiff) { - if(m_pInstance && m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) - return; - // workaround for Lava Strike - missing implementation for EffectImplicitTargetA/B 53/74 if (m_bLavaStrikeAllowed) { if (m_uiLavaStrikeTimer < uiDiff) { - if (Creature *pSarth = m_pInstance->GetSingleCreatureFromStorage(NPC_SARTHARION)) - { - Unit *pTarget = pSarth->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1); - - if (Creature* pTemp = m_creature->SummonCreature(NPC_ORB_TARGET, pTarget ? (pTarget->GetPositionX()-20.0f+urand(0, 40)) : urand(3220, 3275), pTarget ? (pTarget->GetPositionY()-20.0f+urand(0, 40)) : urand(486, 575), 58.8f, 0, TEMPSUMMON_TIMED_DESPAWN, 8000)) - { - pTemp->SetDisplayId(11686); - pTemp->setFaction(35); - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(pTemp, SPELL_LAVA_STRIKE); - } - } - m_uiLavaStrikeTimer = urand(1000, 3000); - m_uiLavaBlazeCount++; - if (m_uiLavaBlazeCount>=12) - { + m_creature->CastSpell(urand(3220, 3275), urand(486, 575), 58.8f, SPELL_LAVA_STRIKE, true); + m_uiLavaStrikeTimer = 1000; + ++m_uiLavaStrikesCount; + if (m_uiLavaStrikesCount>=5) m_bLavaStrikeAllowed = false; - m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - } } else m_uiLavaStrikeTimer -= uiDiff; } - - if (!m_bLavaStrikeAllowed) - { - if (m_uiRefreshTimer < uiDiff) - { - DoCast(m_creature, SPELL_CYCLONE_AURA_2); - DoCast(m_creature, SPELL_CYCLONE_AURA, true); - m_bLavaStrikeAllowed = true; - m_uiLavaStrikeTimer = 0; - m_uiLavaBlazeCount = 0; - m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.5f); - m_uiRefreshTimer = urand(15000, 45000); - } - else - m_uiRefreshTimer -= uiDiff; - } } }; @@ -1849,23 +1684,43 @@ struct MANGOS_DLL_DECL mob_flame_tsunamiAI : public ScriptedAI { mob_flame_tsunamiAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_obsidian_sanctum*)m_creature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_obsidian_sanctum *m_pInstance; + ScriptedInstance* m_pInstance; + + uint32 m_uiTickTimer; uint32 m_uiMovementStartTimer; + ObjectGuid m_uiDummyDamagerGUID; void Reset() { m_creature->SetDisplayId(11686); + DoCast(m_creature, SPELL_FLAME_TSUNAMI, true); m_creature->SetLevitate(true); - m_creature->SetSpeedRate(MOVE_WALK, 4.5f, true); + m_creature->SetWalk(false); m_uiMovementStartTimer = 4000; + m_uiTickTimer = 1000; + m_uiDummyDamagerGUID.Clear(); + if (Creature* pDummyDamager = DoSpawnCreature(31103, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 18000)) + { + pDummyDamager->SetDisplayId(11686); + pDummyDamager->CastSpell(pDummyDamager, SPELL_FLAME_TSUNAMI_DMG_AURA, true); + pDummyDamager->setFaction(14); + pDummyDamager->SetWalk(false); + pDummyDamager->SetSpeedRate(MOVE_RUN, m_creature->GetSpeedRate(MOVE_RUN)); + m_uiDummyDamagerGUID = pDummyDamager->GetObjectGuid(); + } } - void AttackStart(Unit* pWho){} - void MoveInLineOfSight(Unit* pWho){} + void AttackStart(Unit* pWho) + { + } + + void MoveInLineOfSight(Unit* pWho) + { + } void UpdateAI(const uint32 uiDiff) { @@ -1875,10 +1730,59 @@ struct MANGOS_DLL_DECL mob_flame_tsunamiAI : public ScriptedAI if (m_creature->GetPositionX() > 3240.0f) uiDirection = -1; m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX()+uiDirection*86.5f, m_creature->GetPositionY(), m_creature->GetPositionZ()); + if (m_pInstance) + if (Creature* pDummyDamager = m_pInstance->instance->GetCreature(m_uiDummyDamagerGUID)) + pDummyDamager->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX()+uiDirection*86.5f, m_creature->GetPositionY(), m_creature->GetPositionZ()); m_uiMovementStartTimer = 30000; } else m_uiMovementStartTimer -= uiDiff; + + if (m_uiTickTimer < uiDiff) + { + if (m_pInstance) + if (Creature* pDummyDamager = m_pInstance->instance->GetCreature(m_uiDummyDamagerGUID)) + pDummyDamager->CastSpell(pDummyDamager, SPELL_FLAME_TSUNAMI_DMG, false); + + std::list lLavaBlazes; + GetCreatureListWithEntryInGrid(lLavaBlazes, m_creature, NPC_LAVA_BLAZE, 6.0f); + if (!lLavaBlazes.empty()) + { + SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_FLAME_TSUNAMI_BUFF); + if (pTempSpell) + { + pTempSpell->EffectImplicitTargetA[0] = TARGET_SELF; + pTempSpell->EffectImplicitTargetB[0] = 0; + pTempSpell->EffectImplicitTargetA[1] = TARGET_SELF; + pTempSpell->EffectImplicitTargetB[1] = 0; + pTempSpell->EffectImplicitTargetA[2] = TARGET_SELF; + pTempSpell->EffectImplicitTargetB[2] = 0; + for (std::list::iterator iter = lLavaBlazes.begin(); iter != lLavaBlazes.end(); ++iter) + { + (*iter)->CastSpell(*iter, pTempSpell, false); + (*iter)->SetHealth((*iter)->GetHealth()*4); + } + } + } + + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()) <= 5.0f) + { + i->getSource()->SetOrientation(m_creature->GetOrientation()); + i->getSource()->CastSpell(i->getSource(), SPELL_FLAME_TSUNAMI_LEAP, true); + } + } + + m_uiTickTimer = 1000; + } + else + m_uiTickTimer -= uiDiff; } }; @@ -1887,6 +1791,29 @@ CreatureAI* GetAI_mob_flame_tsunami(Creature* pCreature) return new mob_flame_tsunamiAI(pCreature); } +struct MANGOS_DLL_DECL mob_lava_blazeAI : public ScriptedAI +{ + mob_lava_blazeAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + m_creature->ForcedDespawn(); + DoMeleeAttackIfReady(); + } +}; + // Twilight Portals - don't allow entering, when the dragon/all dragons is/are dead // if fighting solo, then drakes shouldn'e be moved more far away then 70yd from their portal // nor during Sartharion event. @@ -1916,6 +1843,11 @@ bool GOobsidian_sanctum_portals(Player* pPlayer, GameObject* pGo) return true; } +CreatureAI* GetAI_mob_lava_blaze(Creature* pCreature) +{ + return new mob_lava_blazeAI(pCreature); +}; + void AddSC_boss_sartharion() { Script *newscript; @@ -1955,11 +1887,6 @@ void AddSC_boss_sartharion() newscript->GetAI = &GetAI_mob_twilight_eggs; newscript->RegisterSelf(); - newscript = new Script; - newscript->Name = "mob_twilight_egg_controller"; - newscript->GetAI = &GetAI_mob_twilight_egg_controller; - newscript->RegisterSelf(); - newscript = new Script; newscript->Name = "mob_twilight_whelp"; newscript->GetAI = &GetAI_mob_twilight_whelp; @@ -1975,6 +1902,11 @@ void AddSC_boss_sartharion() newscript->GetAI = &GetAI_mob_flame_tsunami; newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "mob_lava_blaze"; + newscript->GetAI = &GetAI_mob_lava_blaze; + newscript->RegisterSelf(); + newscript = new Script; newscript->Name = "obsidian_sanctum_portals"; newscript->pGOUse = &GOobsidian_sanctum_portals; diff --git a/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp b/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp index b84cdf9740..45d9925b73 100644 --- a/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp +++ b/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -16,7 +16,7 @@ /* ScriptData SDName: Instance_Obsidian_Sanctum -SD%Complete: 95% +SD%Complete: 80% SDComment: SDCategory: Obsidian Sanctum EndScriptData */ @@ -28,129 +28,77 @@ EndScriptData */ 0 - Sartharion */ -instance_obsidian_sanctum::instance_obsidian_sanctum(Map* pMap) : ScriptedInstance(pMap) -{ - Initialize(); -}; +instance_obsidian_sanctum::instance_obsidian_sanctum(Map* pMap) : ScriptedInstance(pMap), + m_uiAliveDragons(0) + { + Initialize(); + } void instance_obsidian_sanctum::Initialize() { memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiAcolyteShadronGUID.Clear(); - m_uiAcolyteVesperonGUID.Clear(); - - m_lTrashMobsGUIDlist.clear(); - m_lTrashMobsGUIDlist.clear(); - m_lEggsGUIDList.clear(); - m_lWhelpsGUIDList.clear(); - m_lBlazesGUIDList.clear(); - m_lHitByVolcanoGUIDList.clear(); } void instance_obsidian_sanctum::OnCreatureCreate(Creature* pCreature) { switch(pCreature->GetEntry()) { - case NPC_SARTHARION: - //three dragons below set to active state once created. - //we must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences + // The three dragons below set to active state once created. + // We must expect bigger raid to encounter main boss, and then three dragons must be active due to grid differences case NPC_TENEBRON: case NPC_SHADRON: case NPC_VESPERON: - m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); pCreature->SetActiveObjectState(true); - break; - // trash mobs aggro when Sartharion is engaged - case NPC_ONYX_BROOD_GENERAL: - case NPC_ONYX_BLAZE_MISTRESS: - case NPC_ONYX_FLIGHT_CAPTAIN: - case NPC_ONYX_SANCTUM_GUARDIAN: - m_lTrashMobsGUIDlist.push_back(pCreature->GetObjectGuid()); + case NPC_SARTHARION: + m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); break; } } -void instance_obsidian_sanctum::SetAcolyteGuid(uint32 uiEntry, ObjectGuid guid) -{ - m_mNpcEntryGuidStore[uiEntry] = guid; -} - void instance_obsidian_sanctum::SetData(uint32 uiType, uint32 uiData) { - m_auiEncounter[uiType - 1] = uiData; -} + switch (uiType) + { + case TYPE_SARTHARION_EVENT: + m_auiEncounter[0] = uiData; + break; + case TYPE_ALIVE_DRAGONS: + m_uiAliveDragons = uiData; + break; + } -uint32 instance_obsidian_sanctum::GetData(uint32 uiType) -{ - return m_auiEncounter[uiType - 1]; + // No need to save anything here } -bool instance_obsidian_sanctum::IsEncounterInProgress() const +uint32 instance_obsidian_sanctum::GetData(uint32 uiType) { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; -} + switch(uiType) + { + case TYPE_SARTHARION_EVENT: + return m_auiEncounter[0]; + case TYPE_ALIVE_DRAGONS: + return m_uiAliveDragons; + } -bool instance_obsidian_sanctum::CheckConditionCriteriaMeet(Player const* pSource, uint32 uiMapId, uint32 uiInstanceConditionId) -{ - return (GetData(uiInstanceConditionId) == DONE); + return 0; } -bool instance_obsidian_sanctum::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1) +bool instance_obsidian_sanctum::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/) { switch (uiCriteriaId) { - case ACHIEV_CRIT_ASSIST_10: - if (instance->IsRegularDifficulty()) - return GetData(TYPE_SARTH_HARD_ONE) == DONE; - break; - case ACHIEV_CRIT_ASSIST_25: - if (!instance->IsRegularDifficulty()) - return GetData(TYPE_SARTH_HARD_ONE) == DONE; - break; - case ACHIEV_CRIT_DUO_10: - if (instance->IsRegularDifficulty()) - return GetData(TYPE_SARTH_HARD_TWO) == DONE; - break; - case ACHIEV_CRIT_DUO_25: - if (!instance->IsRegularDifficulty()) - return GetData(TYPE_SARTH_HARD_TWO) == DONE; - break; - case ACHIEV_CRIT_ZONE_10: - if (instance->IsRegularDifficulty()) - return GetData(TYPE_SARTH_HARD_THREE) == DONE; - break; - case ACHIEV_CRIT_ZONE_25: - if (!instance->IsRegularDifficulty()) - return GetData(TYPE_SARTH_HARD_THREE) == DONE; - break; - case ACHIEV_CRIT_VOLCANO_10: - if (instance->IsRegularDifficulty()) - { - for (GUIDList::iterator i = m_lHitByVolcanoGUIDList.begin(); i != m_lHitByVolcanoGUIDList.end(); i++) - if (pSource->GetObjectGuid() == *i) - return false; - - return true; - } - break; - case ACHIEV_CRIT_VOLCANO_25: - if (!instance->IsRegularDifficulty()) - { - for (GUIDList::iterator i = m_lHitByVolcanoGUIDList.begin(); i != m_lHitByVolcanoGUIDList.end(); i++) - if (pSource->GetObjectGuid() == *i) - return false; - - return true; - } - break; + case ACHIEV_DRAGONS_ALIVE_1_N: + case ACHIEV_DRAGONS_ALIVE_1_H: + return m_uiAliveDragons >= 1; + case ACHIEV_DRAGONS_ALIVE_2_N: + case ACHIEV_DRAGONS_ALIVE_2_H: + return m_uiAliveDragons >= 2; + case ACHIEV_DRAGONS_ALIVE_3_N: + case ACHIEV_DRAGONS_ALIVE_3_H: + return m_uiAliveDragons >= 3; + default: + return false; } - - return false; } InstanceData* GetInstanceData_instance_obsidian_sanctum(Map* pMap) @@ -160,9 +108,10 @@ InstanceData* GetInstanceData_instance_obsidian_sanctum(Map* pMap) void AddSC_instance_obsidian_sanctum() { - Script *newscript; - newscript = new Script; - newscript->Name = "instance_obsidian_sanctum"; - newscript->GetInstanceData = GetInstanceData_instance_obsidian_sanctum; - newscript->RegisterSelf(); + Script* pNewScript; + + pNewScript = new Script; + pNewScript->Name = "instance_obsidian_sanctum"; + pNewScript->GetInstanceData = GetInstanceData_instance_obsidian_sanctum; + pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h b/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h index 359efcec68..1e5527a28e 100644 --- a/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h +++ b/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * This program is free software licensed under GPL version 2 * Please see the included DOCS/LICENSE.TXT for more information */ @@ -7,85 +7,48 @@ enum { - MAX_ENCOUNTER = 7, + MAX_ENCOUNTER = 1, TYPE_SARTHARION_EVENT = 1, - - // Hard Modes for loot conditions - TYPE_SARTH_HARD_ONE = 2, - TYPE_SARTH_HARD_TWO = 3, - TYPE_SARTH_HARD_THREE = 4, - - // solo fights - TYPE_TENEBRON = 5, - TYPE_SHADRON = 6, - TYPE_VESPERON = 7, - - DATA_SARTHARION = 10, - DATA_TENEBRON = 11, - DATA_SHADRON = 12, - DATA_VESPERON = 13, - - DATA_ACOL_SHAD = 14, - DATA_ACOL_VESP = 15, + // internal used types for achievement + TYPE_ALIVE_DRAGONS = 2, NPC_SARTHARION = 28860, NPC_TENEBRON = 30452, NPC_SHADRON = 30451, NPC_VESPERON = 30449, - NPC_ACOLYTE_OF_VESPERON = 31219, // spawns when fighting with Sartharion - NPC_DISCIPLE_OF_VESPERON = 30858, // spawns when solo fighting - NPC_ACOLYTE_OF_SHADRON = 31218, // spawns when fighting with Sartharion - NPC_DISCIPLE_OF_SHADRON = 30688, // spawns when solo fighting - // trash mobs - NPC_ONYX_BROOD_GENERAL = 30680, - NPC_ONYX_BLAZE_MISTRESS = 30681, - NPC_ONYX_FLIGHT_CAPTAIN = 30682, - NPC_ONYX_SANCTUM_GUARDIAN = 30453, - GO_TWILIGHT_PORTAL = 193988, - // achievement criterias - ACHIEV_CRIT_VOLCANO_10 = 7326, - ACHIEV_CRIT_VOLCANO_25 = 7327, - ACHIEV_CRIT_ASSIST_10 = 7328, - ACHIEV_CRIT_ASSIST_25 = 7331, - ACHIEV_CRIT_DUO_10 = 7329, - ACHIEV_CRIT_DUO_25 = 7332, - ACHIEV_CRIT_ZONE_10 = 7330, - ACHIEV_CRIT_ZONE_25 = 7333 + // Achievement related + ACHIEV_CRIT_VOLCANO_BLOW_N = 7326, // achievs 2047, 2048 (Go When the Volcano Blows) -- This is individual achievement! + ACHIEV_CRIT_VOLCANO_BLOW_H = 7327, + ACHIEV_DRAGONS_ALIVE_1_N = 7328, // achievs 2049, 2052 (Twilight Assist) + ACHIEV_DRAGONS_ALIVE_1_H = 7331, + ACHIEV_DRAGONS_ALIVE_2_N = 7329, // achievs 2050, 2053 (Twilight Duo) + ACHIEV_DRAGONS_ALIVE_2_H = 7332, + ACHIEV_DRAGONS_ALIVE_3_N = 7330, // achievs 2051, 2054 (The Twilight Zone) + ACHIEV_DRAGONS_ALIVE_3_H = 7333, }; class MANGOS_DLL_DECL instance_obsidian_sanctum : public ScriptedInstance { - protected: - uint32 m_auiEncounter[MAX_ENCOUNTER]; - ObjectGuid m_uiSartharionGUID; - ObjectGuid m_uiTenebronGUID; - ObjectGuid m_uiShadronGUID; - ObjectGuid m_uiVesperonGUID; + public: + instance_obsidian_sanctum(Map* pMap); + + void Initialize(); + + void OnCreatureCreate(Creature* pCreature); - void Initialize(); - void OnCreatureCreate(Creature* pCreature); + void SetData(uint32 uiType, uint32 uiData); + uint32 GetData(uint32 uiType); - public: - instance_obsidian_sanctum(Map* pMap); + bool CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/); - GUIDList m_lTrashMobsGUIDlist; - GUIDList m_lEggsGUIDList; - GUIDList m_lWhelpsGUIDList; - GUIDList m_lBlazesGUIDList; - GUIDList m_lHitByVolcanoGUIDList; - ObjectGuid m_uiAcolyteShadronGUID; - ObjectGuid m_uiAcolyteVesperonGUID; + private: + uint32 m_auiEncounter[MAX_ENCOUNTER]; - void SetData(uint32 uiType, uint32 uiData); - void SetAcolyteGuid(uint32 uiEntry, ObjectGuid guid); - uint32 GetData(uint32 uiType); - bool IsEncounterInProgress() const; - bool CheckConditionCriteriaMeet(Player const* pSource, uint32 uiMapId, uint32 uiInstanceConditionId); - bool CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 = 0); + uint8 m_uiAliveDragons; }; #endif diff --git a/scripts/northrend/ruby_sanctum/boss_halion.cpp b/scripts/northrend/ruby_sanctum/boss_halion.cpp index 8b826522ae..e16fe80e7f 100644 --- a/scripts/northrend/ruby_sanctum/boss_halion.cpp +++ b/scripts/northrend/ruby_sanctum/boss_halion.cpp @@ -140,11 +140,11 @@ struct MANGOS_DLL_DECL boss_halion_realAI : public BSWScriptedAI m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (GameObject* pGoPortal = pInstance->GetSingleGameObjectFromStorage(GO_HALION_PORTAL_1)) - pGoPortal->Delete(); + pGoPortal->Delete(); if (GameObject* pGoPortal = pInstance->GetSingleGameObjectFromStorage(GO_HALION_PORTAL_2)) - pGoPortal->Delete(); + pGoPortal->Delete(); if (GameObject* pGoPortal = pInstance->GetSingleGameObjectFromStorage(GO_HALION_PORTAL_3)) - pGoPortal->Delete(); + pGoPortal->Delete(); } void MoveInLineOfSight(Unit* pWho) @@ -826,7 +826,7 @@ struct MANGOS_DLL_DECL mob_halion_controlAI : public BSWScriptedAI m_lastBuffTwilight = Buff[buffnum].twilight; } - debug_log("ruby_sanctum: Buff num = %u, m_diff = %d ", buffnum, m_diff); + debug_log("ruby_sanctum: Buff num = %u, m_diff = %f ", buffnum, m_diff); pInstance->SetData(TYPE_COUNTER, (uint32)Buff[buffnum].disp_corp); diff --git a/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp b/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp index 2cc4bd4775..0b58e43c4b 100644 --- a/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp +++ b/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp @@ -46,33 +46,6 @@ struct MANGOS_DLL_DECL instance_ruby_sanctum : public BSWScriptedInstance uint32 m_auiOrbNState; uint32 m_auiOrbSState; - uint64 m_uiHalion_pGUID; - uint64 m_uiHalion_tGUID; - uint64 m_uiHalionControlGUID; - uint64 m_uiRagefireGUID; - uint64 m_uiZarithrianGUID; - uint64 m_uiBaltharusGUID; - uint64 m_uiCloneGUID; - uint64 m_uiXerestraszaGUID; - - uint64 m_uiOrbNGUID; - uint64 m_uiOrbSGUID; - uint64 m_uiOrbFocusGUID; - uint64 m_uiOrbCarrierGUID; - - //object GUID - uint64 m_uiHalionPortal1GUID; - uint64 m_uiHalionPortal2GUID; - uint64 m_uiHalionPortal3GUID; - uint64 m_uiHalionFireWallSGUID; - uint64 m_uiHalionFireWallMGUID; - uint64 m_uiHalionFireWallLGUID; - uint64 m_uiBaltharusTargetGUID; - - uint64 m_uiFireFieldGUID; - uint64 m_uiFlameWallsGUID; - uint64 m_uiFlameRingGUID; - void Initialize() { for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) @@ -80,24 +53,6 @@ struct MANGOS_DLL_DECL instance_ruby_sanctum : public BSWScriptedInstance m_auiEventTimer = 1000; - m_uiHalion_pGUID = 0; - m_uiHalion_tGUID = 0; - m_uiRagefireGUID = 0; - m_uiZarithrianGUID = 0; - m_uiBaltharusGUID = 0; - m_uiCloneGUID = 0; - m_uiHalionPortal1GUID = 0; - m_uiHalionPortal2GUID = 0; - m_uiHalionPortal3GUID = 0; - m_uiXerestraszaGUID = 0; - m_uiHalionFireWallSGUID = 0; - m_uiHalionFireWallMGUID = 0; - m_uiHalionFireWallLGUID = 0; - m_uiBaltharusTargetGUID = 0; - m_auiOrbDirection = 0; - m_uiOrbNGUID = 0; - m_uiOrbSGUID = 0; - m_uiOrbFocusGUID = 0; m_auiOrbNState = NOT_STARTED; m_auiOrbSState = NOT_STARTED; @@ -205,66 +160,89 @@ struct MANGOS_DLL_DECL instance_ruby_sanctum : public BSWScriptedInstance { switch(uiType) { - case TYPE_EVENT: m_auiEncounter[uiType] = uiData; uiData = NOT_STARTED; break; - case TYPE_RAGEFIRE: m_auiEncounter[uiType] = uiData; - OpenAllDoors(); - break; - case TYPE_BALTHARUS: m_auiEncounter[uiType] = uiData; - OpenAllDoors(); - break; - case TYPE_XERESTRASZA: m_auiEncounter[uiType] = uiData; - if (uiData == IN_PROGRESS) - DoOpenDoor(GO_FIRE_FIELD); - else if (uiData == NOT_STARTED) - { - DoCloseDoor(GO_FIRE_FIELD); - OpenAllDoors(); - } - else if (uiData == DONE) - { - OpenAllDoors(); - if (m_auiEncounter[TYPE_ZARITHRIAN] == DONE) - { - m_auiEncounter[TYPE_EVENT] = 200; - m_auiEventTimer = 30000; - }; - } - break; - case TYPE_ZARITHRIAN: m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - { - DoOpenDoor(GO_FLAME_WALLS); - m_auiEncounter[TYPE_EVENT] = 200; - m_auiEventTimer = 30000; - } - else if (uiData == IN_PROGRESS) - DoCloseDoor(GO_FLAME_WALLS); - else if (uiData == FAIL) - DoOpenDoor(GO_FLAME_WALLS); - break; - case TYPE_HALION: m_auiEncounter[uiType] = uiData; - if (uiData == IN_PROGRESS) - DoCloseDoor(GO_FLAME_RING); - else - DoOpenDoor(GO_FLAME_RING); - break; - case TYPE_HALION_EVENT: m_auiHalionEvent = uiData; uiData = NOT_STARTED; break; - case TYPE_EVENT_TIMER: m_auiEventTimer = uiData; uiData = NOT_STARTED; break; - - case DATA_ORB_DIRECTION: m_auiOrbDirection = uiData; uiData = NOT_STARTED; break; - case DATA_ORB_N: m_auiOrbNState = uiData; uiData = NOT_STARTED; break; - case DATA_ORB_S: m_auiOrbSState = uiData; uiData = NOT_STARTED; break; + case TYPE_EVENT: + m_auiEncounter[uiType] = uiData; + uiData = NOT_STARTED; + break; + case TYPE_RAGEFIRE: + m_auiEncounter[uiType] = uiData; + OpenAllDoors(); + break; + case TYPE_BALTHARUS: + m_auiEncounter[uiType] = uiData; + OpenAllDoors(); + break; + case TYPE_XERESTRASZA: + m_auiEncounter[uiType] = uiData; + if (uiData == IN_PROGRESS) + DoOpenDoor(GO_FIRE_FIELD); + else if (uiData == NOT_STARTED) + { + DoCloseDoor(GO_FIRE_FIELD); + OpenAllDoors(); + } + else if (uiData == DONE) + { + OpenAllDoors(); + if (m_auiEncounter[TYPE_ZARITHRIAN] == DONE) + { + m_auiEncounter[TYPE_EVENT] = 200; + m_auiEventTimer = 30000; + } + } + break; + case TYPE_ZARITHRIAN: + m_auiEncounter[uiType] = uiData; + if (uiData == DONE) + { + DoOpenDoor(GO_FLAME_WALLS); + m_auiEncounter[TYPE_EVENT] = 200; + m_auiEventTimer = 30000; + } + else if (uiData == IN_PROGRESS) + DoCloseDoor(GO_FLAME_WALLS); + else if (uiData == FAIL) + DoOpenDoor(GO_FLAME_WALLS); + break; + case TYPE_HALION: + m_auiEncounter[uiType] = uiData; + if (uiData == IN_PROGRESS) + DoCloseDoor(GO_FLAME_RING); + else + DoOpenDoor(GO_FLAME_RING); + break; + case TYPE_HALION_EVENT: + m_auiHalionEvent = uiData; + uiData = NOT_STARTED; + break; + case TYPE_EVENT_TIMER: + m_auiEventTimer = uiData; + uiData = NOT_STARTED; + break; + + case DATA_ORB_DIRECTION: + m_auiOrbDirection = uiData; + uiData = NOT_STARTED; + break; + case DATA_ORB_N: + m_auiOrbNState = uiData; + uiData = NOT_STARTED; + break; + case DATA_ORB_S: + m_auiOrbSState = uiData; + uiData = NOT_STARTED; + break; case TYPE_COUNTER: - if (uiData == COUNTER_OFF) - { - UpdateWorldState(false,0); - } - else - { - UpdateWorldState(true,uiData); - } - uiData = NOT_STARTED; - break; + if (uiData == COUNTER_OFF) + { + UpdateWorldState(false,0); + } + else + { + UpdateWorldState(true,uiData); + } + uiData = NOT_STARTED; + break; } if (uiData == DONE) @@ -303,28 +281,27 @@ struct MANGOS_DLL_DECL instance_ruby_sanctum : public BSWScriptedInstance case TYPE_HALION_EVENT: return m_auiHalionEvent; case TYPE_EVENT_TIMER: return m_auiEventTimer; - case TYPE_EVENT_NPC: switch (m_auiEncounter[TYPE_EVENT]) - { - case 10: - case 20: - case 30: - case 40: - case 50: - case 60: - case 70: - case 80: - case 90: - case 100: - case 110: - case 200: - case 210: - return NPC_XERESTRASZA; - break; - default: - break; - }; - return 0; - + case TYPE_EVENT_NPC: + switch (m_auiEncounter[TYPE_EVENT]) + { + case 10: + case 20: + case 30: + case 40: + case 50: + case 60: + case 70: + case 80: + case 90: + case 100: + case 110: + case 200: + case 210: + return NPC_XERESTRASZA; + default: + break; + } + return 0; case DATA_ORB_DIRECTION: return m_auiOrbDirection; case DATA_ORB_N: return m_auiOrbNState; case DATA_ORB_S: return m_auiOrbSState; diff --git a/scripts/northrend/sholazar_basin.cpp b/scripts/northrend/sholazar_basin.cpp index f7cc602d72..f53794b659 100644 --- a/scripts/northrend/sholazar_basin.cpp +++ b/scripts/northrend/sholazar_basin.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Sholazar_Basin SD%Complete: 100 -SDComment: Quest support: 12570, 12580, 12688 +SDComment: Quest support: 12573, 12570, 12580, 12644, 12645, 12688, SDCategory: Sholazar Basin EndScriptData */ @@ -25,6 +25,16 @@ EndScriptData */ npc_helice npc_injured_rainspeaker npc_mosswalker_victim +npc_vekjik - TODO, can be moved to database (already exist) +NPC_HEMET_NESINGWAY +NPC_HADRIUS_HARLOWE +NPC_TAMARA_WOBBLESPROCKET +Tipsy McManus +GO_BARREL_OF_ORANGES +GO_BARREL_OF_PAPAYAS +GO_BARREL_OF_BANANAS +GO_PRESSURE_VALVE +GO_BRAZIER EndContentData */ #include "precompiled.h" @@ -409,6 +419,60 @@ bool GossipSelect_npc_mosswalker_victim(Player* pPlayer, Creature* pCreature, ui return true; } +/*###### +## npc_vekjik - TODO, can be moved to database (already exist) +######*/ + +#define GOSSIP_VEKJIK_ITEM1 "Shaman Vekjik, I have spoken with the big-tongues and they desire peace. I have brought this offering on their behalf." +#define GOSSIP_VEKJIK_ITEM2 "No no... I had no intentions of betraying your people. I was only defending myself. it was all a misunderstanding." + +enum +{ + GOSSIP_TEXTID_VEKJIK1 = 13137, + GOSSIP_TEXTID_VEKJIK2 = 13138, + + SAY_TEXTID_VEKJIK1 = -1000208, + + SPELL_FREANZYHEARTS_FURY = 51469, + + QUEST_MAKING_PEACE = 12573 +}; + +bool GossipHello_npc_vekjik(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + if (pPlayer->GetQuestStatus(QUEST_MAKING_PEACE) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VEKJIK1, pCreature->GetObjectGuid()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_vekjik(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VEKJIK_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VEKJIK2, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + DoScriptText(SAY_TEXTID_VEKJIK1, pCreature, pPlayer); + pPlayer->AreaExploredOrEventHappens(QUEST_MAKING_PEACE); + pCreature->CastSpell(pPlayer, SPELL_FREANZYHEARTS_FURY, false); + break; + } + + return true; +} + /*###################### # Quest The Taste Test # ######################*/ @@ -494,18 +558,18 @@ CreatureAI* GetAI_mob_taste_test(Creature* pCreature) enum { QUEST_STILL_AT_IT = 12644, - SAY_EVENT_STARTED = -1999792, - SAY_ADD_BANNANAS = -1999793, - SAY_ADD_PAPAYA = -1999794, - SAY_GOOD_JOB_1 = -1999795, - SAY_BRAZIER = -1999796, - SAY_GOOD_JOB_2 = -1999797, - SAY_OPEN_VALVE = -1999798, - SAY_GOOD_JOB_3 = -1999799, - SAY_GOOD_JOB_4 = -1999800, - SAY_EVENT_END = -1999801, - SAY_ADD_ORANGE = -1999802, - SAY_FAIL = -1999803, + SAY_EVENT_STARTED = -1760000, + SAY_ADD_BANNANAS = -1760001, + SAY_ADD_PAPAYA = -1760002, + SAY_GOOD_JOB_1 = -1760003, + SAY_BRAZIER = -1760004, + SAY_GOOD_JOB_2 = -1760005, + SAY_OPEN_VALVE = -1760006, + SAY_GOOD_JOB_3 = -1760007, + SAY_GOOD_JOB_4 = -1760008, + SAY_EVENT_END = -1760009, + SAY_ADD_ORANGE = -1760010, + SAY_FAIL = -1760011, GO_JUNGLE_PUNCH = 190643 }; #define GOSSIP_TIPSY_MCMANUS "I am ready to start the event." @@ -709,6 +773,326 @@ bool GOUse_go_still_at_it_quest(Player* pPlayer, GameObject* pGo) return false; }; +/*####################### +# npc_artruis_heartless # +#######################*/ +enum +{ + SPELL_FROSTBOLT = 15530, + SPELL_ICE_LANCE = 54261, + SPELL_ICY_VEINS = 54792, + SPELL_FROST_NOVA = 11831, + SPELL_BINDINGS_OF_SUBMISSION = 52185, + GO_ARTRUISS_PYLACTERY = 190777, + SAY_AGGRO = -1780000, + EMOTE_SHIELDED = -1780001, + NPC_ZEPIK = 28668, + NPC_JALOOT = 28667, + +}; +struct MANGOS_DLL_DECL npc_artruisAI : public ScriptedAI +{ + npc_artruisAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + uint32 m_uiFrostboltTimer; + uint32 m_uiIcyVeinsTimer; + uint32 m_uiIceLanceTimer; + uint32 m_uiFrostNovaTimer; + bool bIsBinded; + bool bCastedBindings; + + void Reset() + { + m_uiFrostboltTimer = 1000; + m_uiIceLanceTimer = 200; + m_uiFrostNovaTimer = 100; + m_uiIcyVeinsTimer = 4500; + bIsBinded = false ; + bCastedBindings = false ; + + m_creature->RemoveAurasDueToSpell(SPELL_BINDINGS_OF_SUBMISSION); + } + void Aggro(Unit* pWho) + { + DoScriptText(SAY_AGGRO, m_creature); + } + + void JustDied(Unit* pKiller) + { + if(GameObject* pGo = GetClosestGameObjectWithEntry(m_creature, GO_ARTRUISS_PYLACTERY, 60.0f)) + { + pGo->SetRespawnTime(3*MINUTE); + pGo->Respawn(); + } + } + + void UpdateAI (uint32 const uiDiff) + { + if(m_creature->isInCombat() && !m_creature->getVictim()) + { + Reset(); + } + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(!bIsBinded) + { + if (m_uiIceLanceTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_ICE_LANCE); + m_uiIceLanceTimer = 7000; + } else m_uiIceLanceTimer -= uiDiff; + + if (m_uiFrostNovaTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_FROST_NOVA); + m_uiFrostNovaTimer = 14000; + } else m_uiFrostNovaTimer -= uiDiff; + + if (m_uiFrostboltTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_FROSTBOLT); + m_uiFrostboltTimer = 4000; + } else m_uiFrostboltTimer -= uiDiff; + + if (m_uiIcyVeinsTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_ICY_VEINS); + m_uiIcyVeinsTimer = 25000; + } else m_uiIcyVeinsTimer -= uiDiff; + + if(!bCastedBindings &&(m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature->getVictim(), SPELL_BINDINGS_OF_SUBMISSION); + DoScriptText(EMOTE_SHIELDED, m_creature); + bCastedBindings = true; + bIsBinded = true; + + } + } + + + } + + +}; + +/*################## +# npc_jaloot_zepik # +##################*/ +enum +{ + SPELL_TOMB_OF_HEARTLESS = 52182, + SPELL_Z_OPEN_WOUND = 52873, + SPELL_Z_SPIKE_TRAP = 52886, + SPELL_J_LIGHTNING_WHIRL = 52943, + SPELL_J_SPARK_FRENZY = 52964, + FACTION_MONSTER = 14, + FACTION_TO_RESTORE = 250, + NPC_ARTRUIS_HEARTLESS = 28659, +}; + +struct MANGOS_DLL_DECL npc_jaloot_zepikAI : public ScriptedAI +{ + npc_jaloot_zepikAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + uint32 m_uiZOpenWoundTimer; + uint32 m_uiZSpikeTrapTimer; + uint32 m_uiJLightningWhirlTimer; + uint32 m_uiJSparkFrenzyTimer; + uint32 m_uiCheckArtruisTimer; + + void Reset() + { + m_creature->setFaction(FACTION_TO_RESTORE); + m_creature->CastSpell(m_creature, SPELL_TOMB_OF_HEARTLESS,false); + m_uiZOpenWoundTimer = 2000; + m_uiZSpikeTrapTimer = 4000; + m_uiJLightningWhirlTimer = 2000; + m_uiJSparkFrenzyTimer = 4000; + m_uiCheckArtruisTimer = 5000; + } + + void SpellHit(Unit* pCaster, const SpellEntry *pSpell) + { + switch (pSpell->Id) + { + case 52185: m_creature->RemoveAurasDueToSpell(SPELL_TOMB_OF_HEARTLESS); + if(Creature* pArtruis = GetClosestCreatureWithEntry(m_creature, NPC_ARTRUIS_HEARTLESS, 60.0f)) + { + m_creature->Attack( pArtruis->getVictim(),true); + m_creature->GetMotionMaster()->MoveChase(pArtruis->getVictim()); + } + m_creature->setFaction(FACTION_MONSTER); + break; + } + } + + void AttackStart(Unit* pWho) + { + if(pWho->GetTypeId() == TYPEID_PLAYER) + { + switch(m_creature->GetEntry()) + { + case NPC_ZEPIK: if(Creature* pJaloot = GetClosestCreatureWithEntry(m_creature, NPC_JALOOT, 60.0f)) + { + pJaloot->AddThreat(m_creature->getVictim(),9999.9f,false); + pJaloot->Attack( m_creature->getVictim(),true); + } + break; + + case NPC_JALOOT: if(Creature* pZepik = GetClosestCreatureWithEntry(m_creature, NPC_ZEPIK, 60.0f)) + { + pZepik->AddThreat(m_creature->getVictim(),9999.9f,false); + pZepik->Attack( m_creature->getVictim(),true); + } + break; + + default: break; + } + } + + } + void UpdateAI(const uint32 uiDiff) + { + if(!m_creature->getVictim()) + { + Reset(); + } + if(m_creature->isInCombat()) + { + if (m_uiCheckArtruisTimer <= uiDiff) + { + if(Creature* pArtruis = GetClosestCreatureWithEntry(m_creature, NPC_ARTRUIS_HEARTLESS, 30.0f)) + { + if(!pArtruis->isAlive()) + Reset(); + } + + } else m_uiCheckArtruisTimer -= uiDiff; + + } + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(m_creature->GetEntry()) + { + case NPC_ZEPIK: + Zepik_UpdateAI(uiDiff); + break; + + case NPC_JALOOT: + Jaloot_UpdateAI(uiDiff); + break; + default: break; + } + + DoMeleeAttackIfReady(); + + } + + void Zepik_UpdateAI(const uint32 uiDiff) + { + if (m_uiZOpenWoundTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_Z_OPEN_WOUND); + m_uiZOpenWoundTimer = 4000; + } else m_uiZOpenWoundTimer -= uiDiff; + + if (m_uiZSpikeTrapTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_Z_SPIKE_TRAP); + m_uiZSpikeTrapTimer = 4000; + } else m_uiZSpikeTrapTimer -= uiDiff; + } + + void Jaloot_UpdateAI(const uint32 uiDiff) + { + if (m_uiJLightningWhirlTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_J_LIGHTNING_WHIRL); + m_uiJLightningWhirlTimer = 4000; + } else m_uiJLightningWhirlTimer -= uiDiff; + + if (m_uiJSparkFrenzyTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_J_SPARK_FRENZY); + m_uiJSparkFrenzyTimer = 4000; + } else m_uiJSparkFrenzyTimer -= uiDiff; + + } + + void JustDied(Unit* pKiller) + { + switch(m_creature->GetEntry()) + { + case NPC_ZEPIK: if(Creature* pJaloot = GetClosestCreatureWithEntry(m_creature, NPC_JALOOT, 30.0f)) + { + pJaloot->setFaction(FACTION_TO_RESTORE); + + if(Creature* pArtruis = GetClosestCreatureWithEntry(pJaloot, NPC_ARTRUIS_HEARTLESS, 60.0f)) + { + pJaloot->AddThreat(pArtruis, 999999.9f,true); + pJaloot->Attack( pArtruis,true); + m_creature->GetMotionMaster()->MoveChase(pArtruis); + pArtruis->RemoveAurasDueToSpell(SPELL_BINDINGS_OF_SUBMISSION); + } + } + break; + + case NPC_JALOOT: if(Creature* pZepik = GetClosestCreatureWithEntry(m_creature, NPC_ZEPIK, 60.0f)) + { + pZepik->setFaction(FACTION_TO_RESTORE); + if(Creature* pArtruis = GetClosestCreatureWithEntry(pZepik, NPC_ARTRUIS_HEARTLESS, 60.0f)) + { + pZepik->AddThreat(pArtruis, 999999.9f,true); + pZepik->Attack( pArtruis,true); + m_creature->GetMotionMaster()->MoveChase(pArtruis); + pArtruis->RemoveAurasDueToSpell(SPELL_BINDINGS_OF_SUBMISSION); + } + } + break; + + default: break; + } + if(Creature* pArtruis = GetClosestCreatureWithEntry(m_creature, NPC_ARTRUIS_HEARTLESS, 30.0f)) + { + if (npc_artruisAI* pArtruisAI = dynamic_cast(pArtruis->AI())) + { + pArtruisAI->bIsBinded = false; + } + } + + } + + void JustReachedHome() + { + m_creature->CastSpell(m_creature, SPELL_TOMB_OF_HEARTLESS,false); + if(Creature* pArtruis = GetClosestCreatureWithEntry(m_creature, NPC_ARTRUIS_HEARTLESS, 90.0f)) + { + if(pArtruis->isAlive()) + { + if (npc_artruisAI* pArtruisAI = dynamic_cast(pArtruis->AI())) + { + pArtruisAI->Reset(); + } + } + } + } + +}; + +CreatureAI* GetAI_npc_artruis(Creature* pCreature) +{ + return new npc_artruisAI(pCreature); +} + +CreatureAI* GetAI_npc_jaloot_zepik(Creature* pCreature) +{ + return new npc_jaloot_zepikAI(pCreature); +} + void AddSC_sholazar_basin() { Script* pNewScript; @@ -733,7 +1117,25 @@ void AddSC_sholazar_basin() pNewScript->pGossipSelect = &GossipSelect_npc_mosswalker_victim; pNewScript->RegisterSelf(); - pNewScript = new Script; + pNewScript = new Script; + pNewScript->Name = "npc_vekjik"; + pNewScript->pGossipHello = &GossipHello_npc_vekjik; + pNewScript->pGossipSelect = &GossipSelect_npc_vekjik; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "go_still_at_it_quest"; + pNewScript->pGOUse = &GOUse_go_still_at_it_quest; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_tipsy_mcmanus"; + pNewScript->GetAI = &GetAI_npc_tipsy_mcmanus; + pNewScript->pGossipHello = &GossipHello_npc_tipsy_mcmanus; + pNewScript->pGossipSelect = &GossipSelect_npc_tipsy_mcmanus; + pNewScript->RegisterSelf(); + + pNewScript = new Script; pNewScript->Name = "mob_taste_test"; pNewScript->GetAI = &GetAI_mob_taste_test; pNewScript->pEffectDummyNPC = &EffectDummyNPC_mob_taste_test; @@ -750,4 +1152,14 @@ void AddSC_sholazar_basin() pNewScript->pGossipHello = &GossipHello_npc_tipsy_mcmanus; pNewScript->pGossipSelect = &GossipSelect_npc_tipsy_mcmanus; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_jaloot_zepik"; + pNewScript->GetAI = &GetAI_npc_jaloot_zepik; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_artruis"; + pNewScript->GetAI = &GetAI_npc_artruis; + pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/storm_peaks.cpp b/scripts/northrend/storm_peaks.cpp index 6689a0ce2c..a0affd3fce 100644 --- a/scripts/northrend/storm_peaks.cpp +++ b/scripts/northrend/storm_peaks.cpp @@ -16,16 +16,586 @@ /* ScriptData SDName: Storm_Peaks -SD%Complete: 0 -SDComment: Placeholder +SD%Complete: 100 +SDComment: Vendor Support (31247). Quest support: 12970, 12684 SDCategory: Storm Peaks EndScriptData */ /* ContentData +npc_loklira_the_crone +npc_roxi_ramrocket +npc_frostborn_scout EndContentData */ #include "precompiled.h" +#include "escort_ai.h" +#include "Vehicle.h" + +/*###### +## npc_frostborn_scout +######*/ + +enum Scout +{ + QUEST_MISSING_SCOUT = 12864, + + GOSSIP_TEXTID_SCOUT_1 = 13611, + GOSSIP_TEXTID_SCOUT_2 = 13612, + GOSSIP_TEXTID_SCOUT_3 = 13613, + GOSSIP_TEXTID_SCOUT_4 = 13614 + +}; + +#define GOSSIP_ITEM_SCOUT_1 "Are you okay? I've come to take you back to Frosthold if you can stand." +#define GOSSIP_ITEM_SCOUT_2 "I'm sorry that I didn't get here sooner. What happened?" +#define GOSSIP_ITEM_SCOUT_3 "I'll go get some help. Hang in there." + +bool GossipHello_npc_frostborn_scout(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_MISSING_SCOUT) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SCOUT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SCOUT_1, pCreature->GetObjectGuid()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_frostborn_scout(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SCOUT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SCOUT_2, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SCOUT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SCOUT_3, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SCOUT_4, pCreature->GetObjectGuid()); + pPlayer->AreaExploredOrEventHappens(QUEST_MISSING_SCOUT); + break; + } + return true; +} + +/*###### +## npc_loklira_the_crone +######*/ + +#define GOSSIP_ITEM_TELL_ME "Tell me about this proposal." +#define GOSSIP_ITEM_WHAT_HAPPENED "What happened then?" +#define GOSSIP_ITEM_YOU_WANT_ME "You want me to take part in the Hyldsmeet to end the war?" +#define GOSSIP_ITEM_VERY_WELL "Very well. I'll take part in this competition." + +enum +{ + GOSSIP_TEXTID_LOKLIRA1 = 13777, + GOSSIP_TEXTID_LOKLIRA2 = 13778, + GOSSIP_TEXTID_LOKLIRA3 = 13779, + GOSSIP_TEXTID_LOKLIRA4 = 13780, + + QUEST_THE_HYLDSMEET = 12970, + + CREDIT_LOKLIRA = 30467 +}; + +bool GossipHello_npc_loklira_the_crone(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + if (pPlayer->GetQuestStatus(QUEST_THE_HYLDSMEET) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELL_ME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOKLIRA1, pCreature->GetObjectGuid()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_loklira_the_crone(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WHAT_HAPPENED, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOKLIRA2, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_YOU_WANT_ME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOKLIRA3, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERY_WELL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_LOKLIRA4, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->TalkedToCreature(CREDIT_LOKLIRA, pCreature->GetObjectGuid()); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + return true; +} + +/*###### +## npc_thorim +######*/ + +#define GOSSIP_ITEM_THORIM1 "Can you tell me what became of Sif?" +#define GOSSIP_ITEM_THORIM2 "He did more than that, Thorim. He controls Ulduar now." +#define GOSSIP_ITEM_THORIM3 "It needn't end this way." + +enum +{ + QUEST_SIBLING_RIVALRY = 13064, + + SPELL_THORIM_STORY_KILL_CREDIT = 56940, + + GOSSIP_TEXTID_THORIM1 = 13799, + GOSSIP_TEXTID_THORIM2 = 13801, + GOSSIP_TEXTID_THORIM3 = 13802, + GOSSIP_TEXTID_THORIM4 = 13803 +}; + +bool GossipHello_npc_thorim(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + if (pPlayer->GetQuestStatus(QUEST_SIBLING_RIVALRY) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THORIM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM1, pCreature->GetObjectGuid()); + } + else + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + + return true; +} + +bool GossipSelect_npc_thorim(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THORIM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM2, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THORIM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM3, pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_THORIM4, pCreature->GetObjectGuid()); + pCreature->CastSpell(pPlayer, SPELL_THORIM_STORY_KILL_CREDIT, true); + break; + } + + return true; +} + +/*###### +## npc_roxi_ramrocket +######*/ + +#define GOSSIP_TEXT_RAMROCKET1 "How do you fly in this cold climate?" +#define GOSSIP_TEXT_RAMROCKET2 "I hear you sell motorcycle parts." + +enum +{ + SPELL_MECHANO_HOG = 60866, + SPELL_MEKGINEER_CHOPPER = 60867 +}; + +bool GossipHello_npc_roxi_ramrocket(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isTrainer()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_TEXT_RAMROCKET1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN); + + if (pCreature->isVendor()) + { + if (pPlayer->HasSpell(SPELL_MECHANO_HOG) || pPlayer->HasSpell(SPELL_MEKGINEER_CHOPPER)) + { + if (pPlayer->HasSkill(SKILL_ENGINEERING) && pPlayer->GetBaseSkillValue(SKILL_ENGINEERING) >= 450) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_RAMROCKET2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); + } + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_roxi_ramrocket(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_TRAIN: + pPlayer->SEND_TRAINERLIST(pCreature->GetObjectGuid()); + break; + case GOSSIP_ACTION_TRADE: + pPlayer->SEND_VENDORLIST(pCreature->GetObjectGuid()); + break; + } + + return true; +} + +/*###### +## npc_freed_protodrake +######*/ + +enum +{ + ENTRY_LIBERATED_BRUNNHILDAR = 29734, + ENTRY_FREED_PROTODRAKE = 29709, +}; + +struct MANGOS_DLL_DECL npc_freed_protodrakeAI : public npc_escortAI +{ + npc_freed_protodrakeAI(Creature* pCreature) : npc_escortAI(pCreature) + { + Reset(); + } + + bool m_bNotOnRoute; + + void Reset() + { + m_bNotOnRoute = false; + if (m_creature->getFaction() != m_creature->GetCreatureInfo()->faction_A) + m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A); + } + + void WaypointReached(uint32 uiPointId) + { + + if (uiPointId == 5) //reached village, give credits + { + Unit* pPlayer = m_creature->GetVehicleKit()->GetPassenger(0); + if (pPlayer && pPlayer->GetTypeId() == TYPEID_PLAYER) + { + for (uint8 i = 1; i < 4; ++i) + if (Unit* pPrisoner = m_creature->GetVehicleKit()->GetPassenger(i)) + { + ((Player*)pPlayer)->KilledMonsterCredit(ENTRY_LIBERATED_BRUNNHILDAR); + pPrisoner->ExitVehicle(); + } + + ((Player*)pPlayer)->KilledMonsterCredit(ENTRY_FREED_PROTODRAKE); + pPlayer->ExitVehicle(); + } + + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->ForcedDespawn(1000); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_bNotOnRoute && m_creature->GetPositionY() > -2595.0f) + if (m_creature->isCharmed()) + { + ((Player*)(m_creature->GetCharmer()))->SetClientControl(m_creature, 0); + m_bNotOnRoute = true; + + //flight he don't accept so we walk o_O + m_creature->SetSpeedRate(MOVE_WALK, 3.0f,true); + + m_creature->setFaction(35); + + Start(false, (Player*)(m_creature->GetCharmer())); + } + npc_escortAI::UpdateAI(uiDiff); + } +}; + +CreatureAI* GetAI_npc_freed_protodrake(Creature* pCreature) +{ + return new npc_freed_protodrakeAI(pCreature); +} + +/*###### +## npc_brunnhildar_prisoner +######*/ + +enum +{ + SPELL_ICE_BLOCK = 54894, + SPELL_ICE_SHARD = 55046, + SPELL_ICE_SHARD_IMPACT = 55047 +}; + +struct npc_brunnhildar_prisonerAI : public ScriptedAI +{ + npc_brunnhildar_prisonerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiCheckTimer; + + void Reset() + { + m_uiCheckTimer = 10000; + m_creature->CastSpell(m_creature, SPELL_ICE_BLOCK, true); + } + + void SpellHit(Unit *pCaster, const SpellEntry *spell) + { + if (spell->Id == SPELL_ICE_SHARD) + { + m_creature->CastSpell(m_creature, SPELL_ICE_SHARD_IMPACT, true); + + if (pCaster->IsVehicle()) + { + m_creature->EnterVehicle(pCaster->GetVehicleKit()); + m_creature->RemoveAurasDueToSpell(SPELL_ICE_BLOCK); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (m_uiCheckTimer < diff) + { + if (!m_creature->hasUnitState(UNIT_STAT_ON_VEHICLE)) + { + //return home if not passenger + float x; + float y; + float z; + + m_creature->GetRespawnCoord(x, y, z); + + if(m_creature->GetDistance(x,y,z) > 20.0f) + { + m_creature->SetDeathState(JUST_DIED); + m_creature->Respawn(); + } + } + m_uiCheckTimer = 10000; + } + else + m_uiCheckTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_brunnhildar_prisoner(Creature* pCreature) +{ + return new npc_brunnhildar_prisonerAI(pCreature); +} + +/*###### +## npc_kirgaraak +######*/ + +enum +{ + QUEST_THE_WARM_UP = 12996, + NPC_KIRGARAAK_CREDIT = 30221 +}; + +struct MANGOS_DLL_DECL npc_kirgaraakAI : public ScriptedAI +{ + npc_kirgaraakAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + bool m_bKirgaraakBeaten; + + void Reset() + { + m_bKirgaraakBeaten = false; + m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth() || (m_creature->GetHealth() - uiDamage)*100 / m_creature->GetMaxHealth() < 10) + { + if (Player* pPlayer = pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + if (!m_bKirgaraakBeaten && pPlayer->GetQuestStatus(QUEST_THE_WARM_UP) == QUEST_STATUS_INCOMPLETE) + { + uiDamage = 0; + + m_creature->setFaction(35); + m_creature->CombatStop(true); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + pPlayer->KilledMonsterCredit(NPC_KIRGARAAK_CREDIT); + m_bKirgaraakBeaten = true; + } + } + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (pWho->GetTypeId() == TYPEID_PLAYER) + { + if (pWho->hasUnitState(UNIT_STAT_ON_VEHICLE) && ((Player*)pWho)->GetQuestStatus(QUEST_THE_WARM_UP) == QUEST_STATUS_INCOMPLETE) + { + m_creature->setFaction(90); + } + } + } +}; + +CreatureAI* GetAI_npc_kirgaraak(Creature* pCreature) +{ + return new npc_kirgaraakAI(pCreature); +} + +/*##### +## npc_harnessed_icemaw_matriarch +#####*/ + +enum +{ + NPC_ASTRID = 29839, + KC_ICEMAW_MATRIARCH = 29563, + QUEST_THE_LAST_OF_HER_KIND = 12983 +}; + +struct MANGOS_DLL_DECL npc_harnessed_icemaw_matriarchAI : public ScriptedAI +{ + npc_harnessed_icemaw_matriarchAI(Creature*pCreature) : ScriptedAI(pCreature){} + void Reset(){} + void UpdateAI(const uint32 uiDiff){} + + void MoveInLineOfSight(Unit *pWho) + { + if (pWho->GetEntry() == NPC_ASTRID) + { + if (pWho->GetDistance2d(m_creature) < 30.0f) + { + if (Player *pPlayer = m_creature->GetMap()->GetPlayer(m_creature->GetCreatorGuid())) + { + pPlayer->KilledMonsterCredit(KC_ICEMAW_MATRIARCH, m_creature->GetObjectGuid()); + pPlayer->CompleteQuest(QUEST_THE_LAST_OF_HER_KIND); // hack: kill credit alone doesn't allow turning the quest in :/ + //pPlayer->ExitVehicle(); + } + m_creature->ForcedDespawn(1000); + } + } + } +}; + +CreatureAI* GetAI_npc_harnessed_icemaw_matriarch(Creature* pCreature) +{ + return new npc_harnessed_icemaw_matriarchAI(pCreature); +} + +/*##### +## npc_time_lost_proto_drake +#####*/ + +struct MANGOS_DLL_DECL npc_time_lost_proto_drakeAI : public ScriptedAI +{ + npc_time_lost_proto_drakeAI(Creature*pCreature) : ScriptedAI(pCreature) + { + m_bWasVisible = false; + Reset(); + } + + uint32 m_uiTime2Spawn; + bool m_bNeedInvisible; + bool m_bWasVisible; + + void Reset() + { + if (m_bWasVisible) + return; + + //set appearance between 6h and 6h 30m + m_uiTime2Spawn = 21600000 + rand()%1800000; + //set drake invisible and not selectable + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + m_bNeedInvisible = true; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_bNeedInvisible) + { + if (m_uiTime2Spawn <= uiDiff) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_ON); + m_bNeedInvisible = false; + m_bWasVisible = true; + } + else + m_uiTime2Spawn -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_time_lost_proto_drake(Creature* pCreature) +{ + return new npc_time_lost_proto_drakeAI(pCreature); +} void AddSC_storm_peaks() { + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_frostborn_scout"; + newscript->pGossipHello = &GossipHello_npc_frostborn_scout; + newscript->pGossipSelect = &GossipSelect_npc_frostborn_scout; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_loklira_the_crone"; + newscript->pGossipHello = &GossipHello_npc_loklira_the_crone; + newscript->pGossipSelect = &GossipSelect_npc_loklira_the_crone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thorim"; + newscript->pGossipHello = &GossipHello_npc_thorim; + newscript->pGossipSelect = &GossipSelect_npc_thorim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_roxi_ramrocket"; + newscript->pGossipHello = &GossipHello_npc_roxi_ramrocket; + newscript->pGossipSelect = &GossipSelect_npc_roxi_ramrocket; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_freed_protodrake"; + newscript->GetAI = &GetAI_npc_freed_protodrake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_brunnhildar_prisoner"; + newscript->GetAI = &GetAI_npc_brunnhildar_prisoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_kirgaraak"; + newscript->GetAI = &GetAI_npc_kirgaraak; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_harnessed_icemaw_matriarch"; + newscript->GetAI = &GetAI_npc_harnessed_icemaw_matriarch; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_time_lost_proto_drake"; + newscript->GetAI = &GetAI_npc_time_lost_proto_drake; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp index 727a2b135b..da256334bc 100644 --- a/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp +++ b/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp @@ -72,27 +72,26 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI bool m_bIsRegularMode; - bool m_bIsDesperseCasting; bool m_bIsSplitPhase; - uint32 m_uiSplitTimer; + bool m_bHasSplitted; + uint32 m_uiSplit_Timer; uint32 m_uiSparkAtHomeCount; - uint32 m_uiStaticOverloadTimer; - uint32 m_uiBallLightningTimer; - - uint32 m_uiHealthAmountModifier; + uint32 m_uiStaticOverload_Timer; + uint32 m_uiBallLightning_Timer; void Reset() { + m_lSparkGUIDList.clear(); + m_bIsSplitPhase = true; - m_bIsDesperseCasting = false; - m_uiSplitTimer = 25000; + m_uiSplit_Timer = 25000; m_uiSparkAtHomeCount = 0; - m_uiStaticOverloadTimer = urand(5000, 6000); - m_uiBallLightningTimer = urand(10000, 11000); + m_uiStaticOverload_Timer = urand(5000, 6000); + m_uiBallLightning_Timer = urand(10000, 11000); - m_uiHealthAmountModifier = 1; + m_bHasSplitted = false; if (m_creature->GetVisibility() == VISIBILITY_OFF) m_creature->SetVisibility(VISIBILITY_ON); @@ -109,7 +108,7 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI AttackStart(pAttacker); } - void Aggro(Unit* who) + void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); @@ -120,9 +119,7 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI void JustReachedHome() { if (m_pInstance) - m_pInstance->SetData(TYPE_IONAR, FAIL); - - DespawnSpark(); + m_pInstance->SetData(TYPE_IONAR, NOT_STARTED); } void AttackStart(Unit* pWho) @@ -138,7 +135,7 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI } } - void JustDied(Unit* killer) + void JustDied(Unit* pKiller) { DoScriptText(SAY_DEATH, m_creature); DespawnSpark(); @@ -147,7 +144,7 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI m_pInstance->SetData(TYPE_IONAR, DONE); } - void KilledUnit(Unit *victim) + void KilledUnit(Unit *pVictim) { switch(urand(0, 2)) { @@ -159,7 +156,10 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI void DespawnSpark() { - for (GUIDList::const_iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr) + if (m_lSparkGUIDList.empty()) + return; + + for(GUIDList::const_iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { @@ -171,10 +171,14 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI m_lSparkGUIDList.clear(); } - // make sparks come back + //make sparks come back void CallBackSparks() { - for (GUIDList::const_iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr) + //should never be empty here, but check + if (m_lSparkGUIDList.empty()) + return; + + for(GUIDList::const_iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr) { if (Creature* pSpark = m_creature->GetMap()->GetCreature(*itr)) { @@ -184,8 +188,6 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI if (ScriptedAI* pSparkAI = dynamic_cast(pSpark->AI())) pSparkAI->SetCombatMovement(false); - pSpark->SetSpeedRate(MOVE_RUN,2); - pSpark->GetMotionMaster()->MovePoint(POINT_CALLBACK, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); } } @@ -212,15 +214,18 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI void UpdateAI(const uint32 uiDiff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - // Splitted if (m_creature->GetVisibility() == VISIBILITY_OFF) { - if (m_uiSplitTimer < uiDiff) + if (!m_creature->isInCombat()) { - m_uiSplitTimer = 2500; + Reset(); + return; + } + + if (m_uiSplit_Timer < uiDiff) + { + m_uiSplit_Timer = 2500; // Return sparks to where Ionar splitted if (m_bIsSplitPhase) @@ -229,15 +234,16 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI m_bIsSplitPhase = false; } // Lightning effect and restore Ionar - else + else if (m_uiSparkAtHomeCount == MAX_SPARKS) { m_creature->SetVisibility(VISIBILITY_ON); - DoCastSpellIfCan(m_creature, SPELL_SPARK_DESPAWN); + m_creature->CastSpell(m_creature, SPELL_SPARK_DESPAWN, false); + + DespawnSpark(); m_uiSparkAtHomeCount = 0; - m_uiSplitTimer = 25000; + m_uiSplit_Timer = 25000; m_bIsSplitPhase = true; - m_bIsDesperseCasting = false; if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) { @@ -247,51 +253,48 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI } } else - m_uiSplitTimer -= uiDiff; + m_uiSplit_Timer -= uiDiff; return; } - if (m_uiStaticOverloadTimer < uiDiff) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiStaticOverload_Timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_STATIC_OVERLOAD_N : SPELL_STATIC_OVERLOAD_H) == CAST_OK) - m_uiStaticOverloadTimer = urand(5000, 6000); - } + DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_STATIC_OVERLOAD_N : SPELL_STATIC_OVERLOAD_H); + + m_uiStaticOverload_Timer = urand(5000, 6000); } else - m_uiStaticOverloadTimer -= uiDiff; + m_uiStaticOverload_Timer -= uiDiff; - if (m_uiBallLightningTimer < uiDiff) + if (m_uiBallLightning_Timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_BALL_LIGHTNING_N : SPELL_BALL_LIGHTNING_H) == CAST_OK) - m_uiBallLightningTimer = urand(10000, 11000); - } + m_creature->CastSpell(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), m_bIsRegularMode ? SPELL_BALL_LIGHTNING_N : SPELL_BALL_LIGHTNING_H, false, NULL, NULL, m_creature->GetObjectGuid()); + m_uiBallLightning_Timer = urand(10000, 11000); } else - m_uiBallLightningTimer -= uiDiff; + m_uiBallLightning_Timer -= uiDiff; // Health check - if (!m_bIsDesperseCasting && m_creature->GetHealthPercent() < float(100 - 20*m_uiHealthAmountModifier)) + if (m_creature->GetHealthPercent() < 50.0f && !m_bHasSplitted) { - ++m_uiHealthAmountModifier; + m_bHasSplitted = true; + + DoScriptText(urand(0, 1) ? SAY_SPLIT_1 : SAY_SPLIT_2, m_creature); if (m_creature->IsNonMeleeSpellCasted(false)) m_creature->InterruptNonMeleeSpells(false); - if (!m_bIsDesperseCasting && DoCastSpellIfCan(m_creature, SPELL_DISPERSE, CAST_INTERRUPT_PREVIOUS) == CAST_OK) - { - DoScriptText(urand(0, 1) ? SAY_SPLIT_1 : SAY_SPLIT_2, m_creature); - m_bIsDesperseCasting = true; - } + DoCastSpellIfCan(m_creature, SPELL_DISPERSE); // reset timers - don't interrupt Disperse - m_uiBallLightningTimer = urand(10000, 11000); - m_uiStaticOverloadTimer = urand(5000, 6000); - + m_uiBallLightning_Timer = urand(10000, 11000); + m_uiStaticOverload_Timer = urand(5000, 6000); } DoMeleeAttackIfReady(); @@ -311,7 +314,7 @@ bool EffectDummyCreature_boss_ionar(Unit* pCaster, uint32 uiSpellId, SpellEffect if (pCreatureTarget->GetEntry() != NPC_IONAR) return true; - for (uint8 i = 0; i < MAX_SPARKS; ++i) + for(uint8 i = 0; i < MAX_SPARKS; ++i) pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); pCreatureTarget->AttackStop(); @@ -324,16 +327,6 @@ bool EffectDummyCreature_boss_ionar(Unit* pCaster, uint32 uiSpellId, SpellEffect //always return true when we are handling this spell and effect return true; } - else if (uiSpellId == SPELL_SPARK_DESPAWN && uiEffIndex == EFFECT_INDEX_0) - { - if (pCreatureTarget->GetEntry() != NPC_IONAR) - return true; - - if (boss_ionarAI* pIonarAI = dynamic_cast (pCreatureTarget->AI())) - pIonarAI->DespawnSpark(); - - return true; - } return false; } @@ -375,6 +368,8 @@ struct MANGOS_DLL_DECL mob_spark_of_ionarAI : public ScriptedAI m_creature->ForcedDespawn(); } } + + void UpdateAI(const uint32 uiDiff) {} }; CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) @@ -397,3 +392,4 @@ void AddSC_boss_ionar() pNewScript->GetAI = &GetAI_mob_spark_of_ionar; pNewScript->RegisterSelf(); } + diff --git a/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp b/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp index 5b14565143..980f2ee594 100644 --- a/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp +++ b/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp @@ -125,7 +125,7 @@ struct MANGOS_DLL_DECL boss_lokenAI : public ScriptedAI if (m_bIsAura) { // workaround for PULSING_SHOCKWAVE - if (m_uiPulsingShockwave_Timer < uiDiff) + /*if (m_uiPulsingShockwave_Timer < uiDiff) { Map *map = m_creature->GetMap(); if (map->IsDungeon()) @@ -150,7 +150,7 @@ struct MANGOS_DLL_DECL boss_lokenAI : public ScriptedAI } } m_uiPulsingShockwave_Timer = 2000; - }else m_uiPulsingShockwave_Timer -= uiDiff; + }else m_uiPulsingShockwave_Timer -= uiDiff;*/ } else { diff --git a/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp index bbb49d197c..ac70865c25 100644 --- a/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp +++ b/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss Volkhan -SD%Complete: 80% -SDComment: The dummy spells need more research and should be handled in core +SD%Complete: 60% +SDComment: Not considered complete. Some events may fail and need further development SDCategory: Halls of Lightning EndScriptData */ @@ -38,30 +38,38 @@ enum EMOTE_TO_ANVIL = -1602041, EMOTE_SHATTER = -1602042, - SPELL_HEAT = 52387, + SPELL_HEAT_N = 52387, SPELL_HEAT_H = 59528, - SPELL_SHATTERING_STOMP = 52237, + SPELL_SHATTERING_STOMP_N = 52237, SPELL_SHATTERING_STOMP_H = 59529, //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss - //SPELL_TEMPER_VISUAL = 52661, //summons GO + + //SPELL_TEMPER_VISUAL = 52661, //summons GO SPELL_SUMMON_MOLTEN_GOLEM = 52405, //Molten Golem SPELL_BLAST_WAVE = 23113, - SPELL_IMMOLATION_STRIKE = 52433, + SPELL_IMMOLATION_STRIKE_N = 52433, SPELL_IMMOLATION_STRIKE_H = 59530, - SPELL_SHATTER = 52429, + SPELL_SHATTER_N = 52429, SPELL_SHATTER_H = 59527, NPC_MOLTEN_GOLEM = 28695, NPC_BRITTLE_GOLEM = 28681, + POINT_ID_ANVIL = 0, MAX_GOLEM = 2, - MAX_ACHIEV_GOLEMS = 4 + + // Slag + SPELL_MELT_ARMOR_N = 61509, + SPELL_MELT_ARMOR_H = 61510, + SPELL_BLAST_WAVE_N = 23113, + SPELL_BLAST_WAVE_H = 22424, + }; /*###### @@ -82,19 +90,33 @@ struct MANGOS_DLL_DECL boss_volkhanAI : public ScriptedAI GUIDList m_lGolemGUIDList; bool m_bIsRegularMode; + bool m_bHasTemper; + bool m_bIsStriking; + bool m_bCanShatterGolem; bool m_bHasShattered; - uint32 m_uiShatterTimer; - uint32 m_uiHeatTimer; - uint32 m_uiTemperTimer; + uint32 m_uiPause_Timer; + uint32 m_uiShatter_Timer; + + uint32 m_uiHealthAmountModifier; void Reset() { + m_bIsStriking = false; + m_bHasTemper = false; + m_bCanShatterGolem = false; m_bHasShattered = false; - m_uiShatterTimer = 3000; - m_uiHeatTimer = 30000; - m_uiTemperTimer = 10000; + m_uiPause_Timer = 3500; + m_uiShatter_Timer = 5000; + + m_uiHealthAmountModifier = 1; + + DespawnGolem(); + m_lGolemGUIDList.clear(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); } void Aggro(Unit* pWho) @@ -105,21 +127,26 @@ struct MANGOS_DLL_DECL boss_volkhanAI : public ScriptedAI m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); } - void JustDied(Unit* pKiller) + void AttackStart(Unit* pWho) { - DoScriptText(SAY_DEATH, m_creature); - DespawnGolems(); + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, DONE); + if (!m_bHasTemper) + m_creature->GetMotionMaster()->MoveChase(pWho); + } } - void JustReachedHome() + void JustDied(Unit* pKiller) { - DespawnGolems(); + DoScriptText(SAY_DEATH, m_creature); + DespawnGolem(); if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, FAIL); + m_pInstance->SetData(TYPE_VOLKHAN, DONE); } void KilledUnit(Unit* pVictim) @@ -132,7 +159,7 @@ struct MANGOS_DLL_DECL boss_volkhanAI : public ScriptedAI } } - void DespawnGolems() + void DespawnGolem() { if (m_lGolemGUIDList.empty()) return; @@ -145,34 +172,30 @@ struct MANGOS_DLL_DECL boss_volkhanAI : public ScriptedAI pTemp->ForcedDespawn(); } } + + m_lGolemGUIDList.clear(); } - void ShatterGolems() + void ShatterGolem() { if (m_lGolemGUIDList.empty()) return; - uint8 m_uiBrittleGolemsCount = 0; - for(GUIDList::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { // only shatter brittle golems - if (pTemp->GetEntry() == NPC_BRITTLE_GOLEM) - { - pTemp->CastSpell(pTemp, m_bIsRegularMode ? SPELL_SHATTER : SPELL_SHATTER_H, true); - ++m_uiBrittleGolemsCount; - } + if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) + pTemp->CastSpell(pTemp, m_bIsRegularMode ? SPELL_SHATTER_N : SPELL_SHATTER_H, false); } } + } - // If shattered more than 4 golems mark achiev as failed - if (m_uiBrittleGolemsCount > MAX_ACHIEV_GOLEMS) - { - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, SPECIAL); - } + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_TEMPER_DUMMY) + m_bIsStriking = true; } void JustSummoned(Creature* pSummoned) @@ -183,16 +206,10 @@ struct MANGOS_DLL_DECL boss_volkhanAI : public ScriptedAI if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) pSummoned->AI()->AttackStart(pTarget); - } - } - void MovementInform(uint32 uiMoveType, uint32 uiPointId) - { - if (uiMoveType != POINT_MOTION_TYPE || !uiPointId) - return; - - DoCastSpellIfCan(m_creature, SPELL_TEMPER); - SetCombatMovement(true); + //why healing when just summoned? + pSummoned->CastSpell(pSummoned, m_bIsRegularMode ? SPELL_HEAT_N : SPELL_HEAT_H, false, NULL, NULL, m_creature->GetObjectGuid()); + } } void UpdateAI(const uint32 uiDiff) @@ -201,64 +218,66 @@ struct MANGOS_DLL_DECL boss_volkhanAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // he shatters only one time, at 25% - if (m_creature->GetHealthPercent() <= 25.0f && !m_bHasShattered) + if (m_bIsStriking) + { + if (m_uiPause_Timer < uiDiff) + { + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) + { + if (m_creature->getVictim()) + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + + m_bHasTemper = false; + m_bIsStriking = false; + m_uiPause_Timer = 3500; + } + else + m_uiPause_Timer -= uiDiff; + + return; + } + + // he shatters only one time, at 20% + if (m_creature->GetHealthPercent() <= 20.0f && !m_bHasShattered) { // should he stomp even if he has no brittle golem to shatter? <-yes! - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SHATTERING_STOMP : SPELL_SHATTERING_STOMP_H) == CAST_OK) + if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SHATTERING_STOMP_N : SPELL_SHATTERING_STOMP_H) == CAST_OK) { DoScriptText(urand(0, 1) ? SAY_STOMP_1 : SAY_STOMP_2, m_creature); DoScriptText(EMOTE_SHATTER, m_creature); - m_uiShatterTimer = 3000; + m_bCanShatterGolem = true; m_bHasShattered = true; } } // Shatter Golems 3 seconds after Shattering Stomp - if (m_uiShatterTimer) + if (m_bCanShatterGolem) { - if (m_uiShatterTimer <= uiDiff) + if (m_uiShatter_Timer < uiDiff) { - ShatterGolems(); - m_uiShatterTimer = 0; + ShatterGolem(); + m_uiShatter_Timer = 3000; + m_bCanShatterGolem = false; } else - m_uiShatterTimer -= uiDiff; + m_uiShatter_Timer -= uiDiff; } - // Summon Golems only when over 25% hp - if (m_creature->GetHealthPercent() > 25.0f) + // Health check + if (!m_bCanShatterGolem && m_creature->GetHealthPercent() < float(100 - 20*m_uiHealthAmountModifier)) { - if (m_uiTemperTimer < uiDiff) - { - DoScriptText(EMOTE_TO_ANVIL, m_creature); - DoScriptText(urand(0, 1) ? SAY_FORGE_1 : SAY_FORGE_2, m_creature); - SetCombatMovement(false); + ++m_uiHealthAmountModifier; - if (m_pInstance) - { - if (Creature* pAnvil = m_pInstance->GetSingleCreatureFromStorage(NPC_VOLKHAN_ANVIL)) - { - float fX, fY, fZ; - pAnvil->GetContactPoint(m_creature, fX, fY, fZ, INTERACTION_DISTANCE); - m_creature->GetMotionMaster()->MovePoint(1, fX, fY, fZ); - } - else - error_log("SD2: Npc %u couldn't be found or something really bad happened.", NPC_VOLKHAN_ANVIL); - } - m_uiTemperTimer = 30000; - } - else - m_uiTemperTimer -= uiDiff; - } + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); - if (m_uiHeatTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_HEAT : SPELL_HEAT_H) == CAST_OK) - m_uiHeatTimer = urand(10000, 15000); + DoScriptText(urand(0, 1) ? SAY_FORGE_1 : SAY_FORGE_2, m_creature); + + m_bHasTemper = true; + + m_creature->CastSpell(m_creature, SPELL_TEMPER, false); } - else - m_uiHeatTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -277,9 +296,16 @@ bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, SpellEffe if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) return true; - for (uint8 i = 0; i < MAX_GOLEM; ++i) + for(uint8 i = 0; i < MAX_GOLEM; ++i) + { pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); + //TODO: remove this line of hack when summon effect implemented + pCreatureTarget->SummonCreature(NPC_MOLTEN_GOLEM, + pCaster->GetPositionX(), pCaster->GetPositionY(), pCaster->GetPositionZ(), 0.0f, + TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + } + //always return true when we are handling this spell and effect return true; } @@ -299,14 +325,20 @@ bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, Spel if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) return true; - pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); - // ToDo: research how the visual spell is used + DoScriptText(EMOTE_TO_ANVIL, pCaster); - if (pCaster->getVictim()) - { - pCaster->GetMotionMaster()->Clear(); - pCaster->GetMotionMaster()->MoveChase(pCaster->getVictim()); - } + float fX, fY, fZ; + pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); + + pCaster->AttackStop(); + + if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) + pCaster->GetMotionMaster()->MovementExpired(); + + ((Creature*)pCaster)->GetMap()->CreatureRelocation((Creature*)pCaster, fX, fY, fZ, pCreatureTarget->GetOrientation()); + ((Creature*)pCaster)->MonsterMoveWithSpeed(fX, fY, fZ, 1); + + pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); //always return true when we are handling this spell and effect return true; @@ -331,76 +363,94 @@ struct MANGOS_DLL_DECL mob_molten_golemAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + bool m_bIsFrozen; - uint32 m_uiBlastTimer; - uint32 m_uiImmolationTimer; + uint32 m_uiBlast_Timer; + uint32 m_uiDeathDelay_Timer; + uint32 m_uiImmolation_Timer; void Reset() { - m_uiBlastTimer = 20000; - m_uiImmolationTimer = 5000; + m_bIsFrozen = false; + + m_uiBlast_Timer = 20000; + m_uiDeathDelay_Timer = 0; + m_uiImmolation_Timer = 5000; } - void EnterEvadeMode() + void AttackStart(Unit* pWho) { - // Evade but keep the current location - m_creature->RemoveAllAuras(); - m_creature->DeleteThreatList(); - m_creature->CombatStop(true); - m_creature->LoadCreatureAddon(true); - - m_creature->SetLootRecipient(NULL); + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); - // Update creature to Brittle Golem - // Note: the npc has the proper flags in DB and won't engate in combat anymore - m_creature->UpdateEntry(NPC_BRITTLE_GOLEM); + if (!m_bIsFrozen) + m_creature->GetMotionMaster()->MoveChase(pWho); + } } void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) { - // Transform intro Brittle when damaged to 0 HP - if (uiDamage >= m_creature->GetHealth()) + if (m_bIsFrozen) { + //workaround for now, brittled should be immune to any kind of attacks uiDamage = 0; + return; + } + + if (uiDamage > m_creature->GetHealth()) + { + m_bIsFrozen = true; if (m_creature->IsNonMeleeSpellCasted(false)) m_creature->InterruptNonMeleeSpells(false); - EnterEvadeMode(); + m_creature->RemoveAllAuras(); + m_creature->AttackStop(); + + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) + m_creature->GetMotionMaster()->MovementExpired(); + + uiDamage = m_creature->GetHealth()-1; + + m_creature->UpdateEntry(NPC_BRITTLE_GOLEM); + m_creature->SetHealth(1); } } void SpellHit(Unit* pCaster, const SpellEntry* pSpell) { - // This is the dummy effect of the spells - Note: should be handled as a dummy effect in core - if (pSpell->Id == SPELL_SHATTER || pSpell->Id == SPELL_SHATTER_H) + //this is the dummy effect of the spells + if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) { if (m_creature->GetEntry() == NPC_BRITTLE_GOLEM) - m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->ForcedDespawn(); } } void UpdateAI(const uint32 uiDiff) { //Return since we have no target or if we are frozen - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() || m_bIsFrozen) return; - if (m_uiBlastTimer < uiDiff) + if (m_uiBlast_Timer < uiDiff) { DoCastSpellIfCan(m_creature, SPELL_BLAST_WAVE); - m_uiBlastTimer = 20000; + m_uiBlast_Timer = 20000; } else - m_uiBlastTimer -= uiDiff; + m_uiBlast_Timer -= uiDiff; - if (m_uiImmolationTimer < uiDiff) + if (m_uiImmolation_Timer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_IMMOLATION_STRIKE : SPELL_IMMOLATION_STRIKE_H); - m_uiImmolationTimer = 5000; + DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_IMMOLATION_STRIKE_N : SPELL_IMMOLATION_STRIKE_H); + m_uiImmolation_Timer = 5000; } else - m_uiImmolationTimer -= uiDiff; + m_uiImmolation_Timer -= uiDiff; DoMeleeAttackIfReady(); } @@ -411,23 +461,79 @@ CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) return new mob_molten_golemAI(pCreature); } +/*###### +## npc_slag +######*/ + +struct MANGOS_DLL_DECL npc_slagAI : public ScriptedAI +{ + npc_slagAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + bool m_bDeath; + + uint32 m_uiMelt_Timer; + + void Reset() + { + m_uiMelt_Timer = 15000; + m_bDeath = false; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiMelt_Timer < diff) + { + DoCast (m_creature->getVictim(), m_bIsRegularMode ? SPELL_MELT_ARMOR_N : SPELL_MELT_ARMOR_H); + m_uiMelt_Timer = 30000; + }else m_uiMelt_Timer -= diff; + + if (!m_bDeath && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 1)) + { + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_BLAST_WAVE_N : SPELL_BLAST_WAVE_H); + m_bDeath = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_slag(Creature* pCreature) +{ + return new npc_slagAI(pCreature); +} + void AddSC_boss_volkhan() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_volkhan"; - pNewScript->GetAI = &GetAI_boss_volkhan; - pNewScript->pEffectDummyNPC = &EffectDummyCreature_boss_volkhan; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_volkhan_anvil"; - pNewScript->pEffectDummyNPC = &EffectDummyCreature_npc_volkhan_anvil; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_molten_golem"; - pNewScript->GetAI = &GetAI_mob_molten_golem; - pNewScript->RegisterSelf(); + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_volkhan"; + newscript->GetAI = &GetAI_boss_volkhan; + newscript->pEffectDummyNPC = &EffectDummyCreature_boss_volkhan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_volkhan_anvil"; + newscript->pEffectDummyNPC = &EffectDummyCreature_npc_volkhan_anvil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_molten_golem"; + newscript->GetAI = &GetAI_mob_molten_golem; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_slag"; + newscript->GetAI = &GetAI_npc_slag; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp b/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp index 3df44438d4..cc265a7ab0 100644 --- a/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp @@ -110,7 +110,7 @@ struct MANGOS_DLL_DECL boss_krystallusAI : public ScriptedAI if (m_uiToss_Timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, m_bIsRegularMode ? SPELL_BOULDER_TOSS_H : SPELL_BOULDER_TOSS); + DoCast(pTarget, m_bIsRegularMode ? SPELL_BOULDER_TOSS : SPELL_BOULDER_TOSS_H); m_uiToss_Timer = 9000 + rand()%6000; } else @@ -127,7 +127,7 @@ struct MANGOS_DLL_DECL boss_krystallusAI : public ScriptedAI if (m_uiStomp_Timer < uiDiff) { - DoCast(m_creature, m_bIsRegularMode ? SPELL_STOMP_H : SPELL_STOMP); + DoCast(m_creature, m_bIsRegularMode ? SPELL_STOMP : SPELL_STOMP_H); m_uiStomp_Timer = 20000 + rand()%9000; } else @@ -147,7 +147,7 @@ struct MANGOS_DLL_DECL boss_krystallusAI : public ScriptedAI { if (m_uiShatter_Timer < uiDiff) { - DoCast(m_creature, m_bIsRegularMode ? SPELL_SHATTER_H : SPELL_SHATTER); + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHATTER : SPELL_SHATTER_H); m_bIsSlam = false; m_uiShatter_Timer = 0; } diff --git a/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp index c2cae08761..069ed69ac2 100644 --- a/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp @@ -41,6 +41,8 @@ enum SPELL_SHOCK_OF_SORROW_H = 59726, SPELL_STORM_OF_GRIEF = 50752, SPELL_STORM_OF_GRIEF_H = 59772, + + ACHIEV_GOOD_GRIEF = 1866, }; /*###### @@ -58,11 +60,13 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + bool m_bIsInTimeAchiev; uint32 m_uiPartingSorrow_Timer; uint32 m_uiPillarWoe_Timer; uint32 m_uiShockSorrow_Timer; uint32 m_uiStorm_Timer; + uint32 m_uiGoodGrief_Timer; void Reset() { @@ -70,6 +74,9 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI m_uiPillarWoe_Timer = 3000 + rand()%4000; m_uiStorm_Timer = 10000 + rand()%5000; m_uiShockSorrow_Timer = 20000 + rand()%5000; + m_uiGoodGrief_Timer = 60000; + + m_bIsInTimeAchiev = true; if(m_pInstance) m_pInstance->SetData(TYPE_GRIEF, NOT_STARTED); @@ -100,6 +107,21 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_GRIEF, DONE); + + if (m_bIsInTimeAchiev && !m_bIsRegularMode) + { + AchievementEntry const *AchievGoodGrief = GetAchievementStore()->LookupEntry(ACHIEV_GOOD_GRIEF); + if (AchievGoodGrief) + { + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievGoodGrief); + } + } + } } void UpdateAI(const uint32 uiDiff) @@ -119,7 +141,7 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI if (m_uiPillarWoe_Timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, m_bIsRegularMode ? SPELL_PILLAR_OF_WOE_H : SPELL_PILLAR_OF_WOE); + DoCast(pTarget, m_bIsRegularMode ? SPELL_PILLAR_OF_WOE : SPELL_PILLAR_OF_WOE_H); m_uiPillarWoe_Timer = 9000 + rand()%4000; } else @@ -127,7 +149,7 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI if (m_uiStorm_Timer < uiDiff) { - DoCast(m_creature, m_bIsRegularMode ? SPELL_STORM_OF_GRIEF_H : SPELL_STORM_OF_GRIEF); + DoCast(m_creature, m_bIsRegularMode ? SPELL_STORM_OF_GRIEF : SPELL_STORM_OF_GRIEF_H); m_uiStorm_Timer = 20000 + rand()%5000; } else @@ -136,12 +158,19 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI if (m_uiShockSorrow_Timer < uiDiff) { DoScriptText(SAY_STUN, m_creature); - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHOCK_OF_SORROW_H : SPELL_SHOCK_OF_SORROW); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHOCK_OF_SORROW : SPELL_SHOCK_OF_SORROW_H); m_uiShockSorrow_Timer = 20000 + rand()%5000; } else m_uiShockSorrow_Timer -= uiDiff; + if (m_uiGoodGrief_Timer < uiDiff) + { + m_bIsInTimeAchiev = false; + } + else + m_uiGoodGrief_Timer -= uiDiff; + DoMeleeAttackIfReady(); } }; diff --git a/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp b/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp index 284c6c8ace..84e33a4d4b 100644 --- a/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp @@ -93,7 +93,6 @@ enum TEXT_ID_START = 13100, TEXT_ID_PROGRESS = 13101, - NPC_TRIBUNAL_OF_THE_AGES = 28234, NPC_BRANN_BRONZEBEARD = 28070, SPELL_STEALTH = 58506, @@ -111,13 +110,12 @@ enum SPELL_SEARING_GAZE_H = 59867, NPC_SEARING_GAZE_TARGET = 28265, - SPELL_ACHIEVEMENT_CHECK = 59046, // Doesn't exist in client dbc - NPC_DARK_RUNE_PROTECTOR = 27983, NPC_DARK_RUNE_STORMCALLER = 27984, NPC_IRON_GOLEM_CUSTODIAN = 27985, QUEST_HALLS_OF_STONE = 13207, + SPELL_TRIBUNAL_CREDIT = 59046, }; #define GOSSIP_ITEM_START "Brann, it would be our honor!" @@ -147,15 +145,14 @@ struct MANGOS_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); + m_bIsEnd = false; Reset(); } ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - GUIDList m_lKaddrakGUIDList; - //std::list m_lMarnakGUIDList; - //std::list m_lAbedneumGUIDList; + bool m_bIsEnd; bool m_bIsActivateKaddrak; bool m_bIsActivateMarnak; @@ -165,6 +162,56 @@ struct MANGOS_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI uint32 m_uiMarnak_Encounter_timer; uint32 m_uiAbedneum_Encounter_timer; + void ActivateObject(uint32 object,bool activate) + // object may be: DATA_GO_KADDRAK, DATA_GO_MARNAK, DATA_GO_ABEDNEUM, DATA_GO_SKY_FLOOR, DATA_GO_TRIBUNAL_CONSOLE + { + if (!m_pInstance) + return; + + GameObject * pObject; + if (!(pObject = m_pInstance->GetSingleGameObjectFromStorage(object))) + { + error_log("SD2: Halls of Stone: Tribunal of Ages: couldn't find object: %u",(unsigned int)object); + return; + } + + if (pObject->getLootState() == GO_READY && activate) // not active, needs to be active + pObject->UseDoorOrButton(0,false); + else + if (pObject->getLootState() == GO_ACTIVATED && !activate) // active, needs to be not active + pObject->ResetDoorOrButton(); + } + + void ActivateFace(uint32 face, bool activate) + // face may be: DATA_GO_KADDRAK, DATA_GO_MARNAK, DATA_GO_ABEDNEUM + { + ActivateObject(face, activate); + + switch (face) + { + case GO_KADDRAK: + m_bIsActivateKaddrak = activate; + break; + case GO_MARNAK: + m_bIsActivateMarnak = activate; + break; + case GO_ABEDNEUM: + m_bIsActivateAbedneum = activate; + break; + } + } + + void ResetFaces() + { + // disable all faces + ActivateFace(GO_KADDRAK,false); + ActivateFace(GO_MARNAK,false); + ActivateFace(GO_ABEDNEUM,false); + // disable effects + ActivateObject(GO_TRIBUNAL_SKY_FLOOR,false); + ActivateObject(GO_TRIBUNAL_CONSOLE,false); + } + void Reset() { m_bIsActivateKaddrak = false; @@ -175,75 +222,42 @@ struct MANGOS_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI m_uiMarnak_Encounter_timer = 10000; m_uiAbedneum_Encounter_timer = 10000; - m_lKaddrakGUIDList.clear(); - //m_lMarnakGUIDList.clear(); - //m_lAbedneumGUIDList.clear(); - } - - void UpdateFacesList() - { - std::list m_lKaddrakList; - m_lKaddrakGUIDList.clear(); - GetCreatureListWithEntryInGrid(m_lKaddrakList, m_creature, NPC_KADDRAK, 50.0f); - if (!m_lKaddrakGUIDList.empty()) - { - uint32 uiPositionCounter = 0; - for(std::list::iterator itr = m_lKaddrakList.begin(); itr != m_lKaddrakList.end(); ++itr) - { - if (!(*itr)) continue; - - if (Creature* c = (Creature *)(*itr)) - { - m_lKaddrakGUIDList.push_back((*itr)->GetObjectGuid()); - if (c->isAlive()) - { - if (uiPositionCounter == 0) - { - c->GetMap()->CreatureRelocation((*itr), 927.265f, 333.200f, 218.780f, (*itr)->GetOrientation()); - c->MonsterMoveWithSpeed(927.265f, 333.200f, 218.780f, 1); - } - else - { - c->GetMap()->CreatureRelocation((*itr), 921.745f, 328.076f, 218.780f, (*itr)->GetOrientation()); - c->MonsterMoveWithSpeed(921.745f, 328.076f, 218.780f, 1); - } - } - ++uiPositionCounter; - } - } - } - //GetCreatureListWithEntryInGrid(m_lMarnakGUIDList, m_creature, NPC_MARNAK, 50.0f); - //GetCreatureListWithEntryInGrid(m_lAbedneumGUIDList, m_creature, NPC_ABEDNEUM, 50.0f); + if (!m_bIsEnd) + ResetFaces(); } void UpdateAI(const uint32 uiDiff) { if (m_bIsActivateKaddrak) - { + { if (m_uiKaddrak_Encounter_timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (!m_lKaddrakGUIDList.empty()) - for(GUIDList::iterator itr = m_lKaddrakGUIDList.begin(); itr != m_lKaddrakGUIDList.end(); ++itr) - if (Creature* pCreature = m_creature->GetMap()->GetCreature(*itr)) - if (pCreature->isAlive()) - pCreature->CastSpell(pTarget, m_bIsRegularMode ? SPELL_GLARE_OF_THE_TRIBUNAL_H : SPELL_GLARE_OF_THE_TRIBUNAL, true); - - m_uiKaddrak_Encounter_timer = 1500; + { + std::list m_lKaddrakList; + GetCreatureListWithEntryInGrid(m_lKaddrakList, m_creature, NPC_KADDRAK, 50.0f); + + if (!m_lKaddrakList.empty()) + for(std::list::iterator itr = m_lKaddrakList.begin(); itr != m_lKaddrakList.end(); ++itr) + if ((*itr) && (*itr)->isAlive()) + (*itr)->CastSpell(pTarget, m_bIsRegularMode ? SPELL_GLARE_OF_THE_TRIBUNAL : SPELL_GLARE_OF_THE_TRIBUNAL_H, true); + m_uiKaddrak_Encounter_timer = 1500; + } } else m_uiKaddrak_Encounter_timer -= uiDiff; } + if (m_bIsActivateMarnak) { if (m_uiMarnak_Encounter_timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (Creature* pTemp = m_creature->SummonCreature(NPC_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + if (Creature* pTemp = m_creature->SummonCreature(NPC_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 3500)) { - pTemp->SetDisplayId(11686); + pTemp->SetDisplayId(15882); + pTemp->setFaction(16); pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->CastSpell(pTarget, m_bIsRegularMode ? SPELL_DARK_MATTER_H : SPELL_DARK_MATTER, true); } m_uiMarnak_Encounter_timer = 30000 + rand()%1000; @@ -259,8 +273,10 @@ struct MANGOS_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI if (Creature* pTemp = m_creature->SummonCreature(NPC_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 10000)) { pTemp->SetDisplayId(11686); + pTemp->setFaction(14); + pTemp->GetMotionMaster()->MoveIdle(); pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->CastSpell(pTemp, m_bIsRegularMode ? SPELL_SEARING_GAZE_H : SPELL_SEARING_GAZE, true); + pTemp->CastSpell(pTemp, m_bIsRegularMode ? SPELL_SEARING_GAZE : SPELL_SEARING_GAZE_H, true); } m_uiAbedneum_Encounter_timer = 30000 + rand()%1000; @@ -268,6 +284,8 @@ struct MANGOS_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI else m_uiAbedneum_Encounter_timer -= uiDiff; } + + m_creature->SelectHostileTarget(); } }; @@ -292,8 +310,12 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI uint32 m_uiStep; uint32 m_uiPhase_timer; - ObjectGuid m_uiControllerGUID; - GUIDList m_lDwarfGUIDList; + std::list m_lDwarfGUIDList; + + void SelfDestruct() + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } void Reset() { @@ -305,8 +327,6 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI m_uiStep = 0; m_uiPhase_timer = 0; - m_uiControllerGUID.Clear(); - DespawnDwarf(); if(m_pInstance) @@ -335,16 +355,9 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI { switch(uiPointId) { - case 7: - if (Creature* pCreature = GetClosestCreatureWithEntry(m_creature, NPC_TRIBUNAL_OF_THE_AGES, 100.0f)) - { - if (!pCreature->isAlive()) - pCreature->Respawn(); - ((mob_tribuna_controllerAI*)pCreature->AI())->UpdateFacesList(); - m_uiControllerGUID = pCreature->GetObjectGuid(); - } - break; - case 13: + case 13: + if (Creature* pCreature = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES)) + ((mob_tribuna_controllerAI*)pCreature->AI())->ResetFaces(); DoScriptText(SAY_EVENT_INTRO_1, m_creature); SetEscortPaused(true); SetRun(true); @@ -353,7 +366,7 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI case 17: DoScriptText(SAY_EVENT_INTRO_2, m_creature); if (m_pInstance) - m_pInstance->DoUseDoorOrButton(GO_TRIBUNAL_CONSOLE); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetSingleGameObjectFromStorage(GO_TRIBUNAL_CONSOLE)->GetObjectGuid()); m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); SetEscortPaused(true); JumpToNextStep(8500); @@ -384,7 +397,7 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI if (m_lDwarfGUIDList.empty()) return; - for(GUIDList::iterator itr = m_lDwarfGUIDList.begin(); itr != m_lDwarfGUIDList.end(); ++itr) + for(std::list::iterator itr = m_lDwarfGUIDList.begin(); itr != m_lDwarfGUIDList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { @@ -421,7 +434,6 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI void JustSummoned(Creature* pSummoned) { m_lDwarfGUIDList.push_back(pSummoned->GetObjectGuid()); - pSummoned->SetRespawnDelay(7*DAY); pSummoned->AddThreat(m_creature, 0.0f); pSummoned->AI()->AttackStart(m_creature); } @@ -432,6 +444,25 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI m_uiStep++; } + bool CanStartEvent() + { + if (!m_pInstance) + return false; + if (m_pInstance->GetData(TYPE_BRANN) != NOT_STARTED) + return false; + Creature * pC; + if (!(pC = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES))) + return false; + if (!dynamic_cast(pC->AI())) + return false; + if (!pC->isAlive()) // using tribunal death to save event end + return false; + if (pC->isInCombat()) + return false; + + return true; + } + void UpdateEscortAI(const uint32 uiDiff) { if (m_uiPhase_timer < uiDiff) @@ -440,19 +471,22 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI { case 0: // unused break; - case 1: - if (m_pInstance) + case 1: + // instance check + if (!CanStartEvent()) { - if (m_pInstance->GetData(TYPE_BRANN) != NOT_STARTED) - return; - - m_pInstance->SetData(TYPE_BRANN, IN_PROGRESS); + error_log("SD2: Halls of Stone: Tribunal of Ages: CanStartEvent() is false, event aborted!"); + SelfDestruct(); + return; } + + m_pInstance->SetData(TYPE_BRANN, IN_PROGRESS); + m_bIsBattle = false; DoScriptText(SAY_ESCORT_START, m_creature); JumpToNextStep(0); break; - case 3: + case 3: SetEscortPaused(false); JumpToNextStep(0); break; @@ -460,24 +494,44 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); - JumpToNextStep(5500); + JumpToNextStep(8500); break; case 6: DoScriptText(SAY_EVENT_A_1, m_creature); - JumpToNextStep(5500); + JumpToNextStep(6500); break; case 7: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_KADDRAK)) DoScriptText(SAY_EVENT_A_2_KADD, pTemp); - JumpToNextStep(8500); + JumpToNextStep(12500); break; case 8: DoScriptText(SAY_EVENT_A_3, m_creature); if (m_pInstance) - m_pInstance->DoUseDoorOrButton(GO_KADDRAK); - if (Creature* pTemp = m_creature->GetMap()->GetCreature(m_uiControllerGUID)) - ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsActivateKaddrak = true; + { + if (m_pInstance) + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES)) + { + ((mob_tribuna_controllerAI*)pTemp->AI())->ActivateFace(GO_KADDRAK, true); + Player * pPl = GetPlayerForEscort(); + if (!pPl || !pPl->isAlive()) + { + SelfDestruct(); + ((mob_tribuna_controllerAI*)pTemp->AI())->EnterEvadeMode(); + return; + } + // initialize threat list + typedef Map::PlayerList PlayerList; + PlayerList const& plist = m_creature->GetMap()->GetPlayers(); + for (PlayerList::const_iterator iter = plist.begin(); iter != plist.end(); ++iter) + { + Player * pl = iter->getSource(); + if (pl && pl->isAlive()) + pTemp->AddThreat(pl, 1.0f); + } + } + } JumpToNextStep(5000); break; case 9: @@ -486,21 +540,20 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI break; case 10: DoScriptText(SAY_EVENT_B_1, m_creature); - JumpToNextStep(7000); + JumpToNextStep(6000); break; case 11: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MARNAK)) DoScriptText(SAY_EVENT_B_2_MARN, pTemp); SpawnDwarf(1); - JumpToNextStep(10000); + JumpToNextStep(20000); break; case 12: DoScriptText(SAY_EVENT_B_3, m_creature); if (m_pInstance) - m_pInstance->DoUseDoorOrButton(GO_MARNAK); - if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_uiControllerGUID)) - ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsActivateMarnak = true; + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES)) + ((mob_tribuna_controllerAI*)pTemp->AI())->ActivateFace(GO_MARNAK, true); JumpToNextStep(10000); break; case 13: @@ -525,15 +578,14 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_C_2_ABED, pTemp); SpawnDwarf(1); - JumpToNextStep(10000); + JumpToNextStep(20000); break; case 18: DoScriptText(SAY_EVENT_C_3, m_creature); if (m_pInstance) - m_pInstance->DoUseDoorOrButton(GO_ABEDNEUM); - if (Creature* pTemp = m_creature->GetMap()->GetCreature(m_uiControllerGUID)) - ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsActivateAbedneum = true; - JumpToNextStep(6000); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES)) + ((mob_tribuna_controllerAI*)pTemp->AI())->ActivateFace(GO_ABEDNEUM, true); + JumpToNextStep(5000); break; case 19: SpawnDwarf(2); @@ -553,7 +605,7 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_D_2_ABED, pTemp); SpawnDwarf(1); - JumpToNextStep(6000); + JumpToNextStep(5000); break; case 23: SpawnDwarf(2); @@ -562,11 +614,11 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI case 24: DoScriptText(SAY_EVENT_D_3, m_creature); SpawnDwarf(3); - JumpToNextStep(6000); + JumpToNextStep(5000); break; case 25: SpawnDwarf(1); - JumpToNextStep(6000); + JumpToNextStep(5000); break; case 26: SpawnDwarf(2); @@ -583,132 +635,148 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI DoScriptText(SAY_EVENT_END_01, m_creature); m_creature->SetStandState(UNIT_STAND_STATE_STAND); if (m_pInstance) - m_pInstance->DoUseDoorOrButton(GO_TRIBUNAL_SKY_FLOOR); - if (Creature* pTemp = m_creature->GetMap()->GetCreature(m_uiControllerGUID)) - pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + { + m_pInstance->DoUseDoorOrButton(m_pInstance->GetSingleGameObjectFromStorage(GO_TRIBUNAL_SKY_FLOOR)->GetObjectGuid()); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES)) + { + ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsEnd = true; + pTemp->AI()->EnterEvadeMode(); + } + } + DespawnDwarf(); m_bIsBattle = true; SetEscortPaused(false); - JumpToNextStep(5500); + JumpToNextStep(3500); break; case 29: DoScriptText(SAY_EVENT_END_02, m_creature); - JumpToNextStep(5500); + JumpToNextStep(3500); break; case 30: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_END_03_ABED, pTemp); - JumpToNextStep(8000); + JumpToNextStep(4500); break; case 31: DoScriptText(SAY_EVENT_END_04, m_creature); - JumpToNextStep(10000); + JumpToNextStep(6500); break; case 32: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_END_05_ABED, pTemp); - JumpToNextStep(11500); + JumpToNextStep(6500); break; case 33: DoScriptText(SAY_EVENT_END_06, m_creature); - JumpToNextStep(5000); + JumpToNextStep(2500); break; case 34: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_END_07_ABED, pTemp); - JumpToNextStep(16500); + JumpToNextStep(10500); break; case 35: DoScriptText(SAY_EVENT_END_08, m_creature); - JumpToNextStep(7000); + JumpToNextStep(4500); break; case 36: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_KADDRAK)) DoScriptText(SAY_EVENT_END_09_KADD, pTemp); - JumpToNextStep(15500); + JumpToNextStep(7500); break; case 37: DoScriptText(SAY_EVENT_END_10, m_creature); - JumpToNextStep(5000); + JumpToNextStep(2500); break; case 38: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_KADDRAK)) DoScriptText(SAY_EVENT_END_11_KADD, pTemp); - JumpToNextStep(18000); + JumpToNextStep(10500); break; case 39: DoScriptText(SAY_EVENT_END_12, m_creature); - JumpToNextStep(3000); + JumpToNextStep(2500); break; case 40: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_KADDRAK)) DoScriptText(SAY_EVENT_END_13_KADD, pTemp); - JumpToNextStep(18000); + JumpToNextStep(9500); break; case 41: DoScriptText(SAY_EVENT_END_14, m_creature); - JumpToNextStep(9000); + JumpToNextStep(5500); break; case 42: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MARNAK)) DoScriptText(SAY_EVENT_END_15_MARN, pTemp); - JumpToNextStep(8500); + JumpToNextStep(3500); break; case 43: DoScriptText(SAY_EVENT_END_16, m_creature); - JumpToNextStep(6000); + JumpToNextStep(3500); break; case 44: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MARNAK)) DoScriptText(SAY_EVENT_END_17_MARN, pTemp); - JumpToNextStep(19500); + JumpToNextStep(11500); break; case 45: DoScriptText(SAY_EVENT_END_18, m_creature); - JumpToNextStep(19500); + JumpToNextStep(10500); break; case 46: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MARNAK)) DoScriptText(SAY_EVENT_END_19_MARN, pTemp); - JumpToNextStep(5000); + JumpToNextStep(2500); break; case 47: DoScriptText(SAY_EVENT_END_20, m_creature); - JumpToNextStep(7000); + JumpToNextStep(4500); break; case 48: if (m_pInstance) if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_ABEDNEUM)) DoScriptText(SAY_EVENT_END_21_ABED, pTemp); - JumpToNextStep(5000); + JumpToNextStep(3500); break; case 49: { if (m_pInstance) { - m_pInstance->DoUseDoorOrButton(GO_KADDRAK); - m_pInstance->DoUseDoorOrButton(GO_MARNAK); - m_pInstance->DoUseDoorOrButton(GO_ABEDNEUM); - m_pInstance->DoUseDoorOrButton(GO_TRIBUNAL_SKY_FLOOR); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetSingleGameObjectFromStorage(GO_KADDRAK)->GetObjectGuid()); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetSingleGameObjectFromStorage(GO_MARNAK)->GetObjectGuid()); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetSingleGameObjectFromStorage(GO_ABEDNEUM)->GetObjectGuid()); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetSingleGameObjectFromStorage(GO_TRIBUNAL_SKY_FLOOR)->GetObjectGuid()); m_pInstance->SetData(TYPE_BRANN, DONE); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_TRIBUNAL_OF_THE_AGES)) // mark controller death + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } - //if (Player* pPlayer = GetPlayerForEscort()) - //pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, m_creature); - DoCastSpellIfCan(m_creature, SPELL_ACHIEVEMENT_CHECK, CAST_TRIGGERED); +#ifndef WIN32 + // reward achievement + typedef Map::PlayerList PlayerList; + PlayerList const& plist = m_creature->GetMap()->GetPlayers(); + for (PlayerList::const_iterator iter = plist.begin(); iter != plist.end(); ++iter) + { + Player * pl = iter->getSource(); + if (pl) + pl->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_TRIBUNAL_CREDIT); + } +#endif m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); - JumpToNextStep(30000); + JumpToNextStep(180000); break; } case 50: @@ -730,19 +798,19 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) { - ScriptedInstance* m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); if (pCreature->isQuestGiver()) pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); - if (m_pInstance->GetData(TYPE_BRANN) != DONE) + if (((npc_brann_hosAI*)pCreature->AI())->CanStartEvent()) pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetObjectGuid()); //pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_PROGRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); //pPlayer->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, pCreature->GetObjectGuid()); - return true; } @@ -751,8 +819,11 @@ bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 uiS if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) { pPlayer->CLOSE_GOSSIP_MENU(); - ((npc_brann_hosAI*)pCreature->AI())->m_uiStep = 1; - ((npc_brann_hosAI*)pCreature->AI())->Start(false, pPlayer); + if (((npc_brann_hosAI*)pCreature->AI())->CanStartEvent()) + { + ((npc_brann_hosAI*)pCreature->AI())->m_uiStep = 1; + ((npc_brann_hosAI*)pCreature->AI())->Start(false, pPlayer); + } } return true; @@ -768,6 +839,55 @@ CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) return new mob_tribuna_controllerAI (pCreature); } +struct MANGOS_DLL_DECL npc_dark_matter_targetAI : public ScriptedAI +{ + npc_dark_matter_targetAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsHeroicMode = !pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + uint32 darkMatterTimer; + bool m_bIsHeroicMode; + + void Reset() + { + darkMatterTimer = 3000; + } + + void UpdateAI(const uint32 diff) + { + if (diff > darkMatterTimer) + { + if (Map * map = m_creature->GetMap()) + { + typedef Map::PlayerList PlayerList; + PlayerList const& plist = map->GetPlayers(); + + for (PlayerList::const_iterator pi = plist.begin(); pi != plist.end(); ++pi) + { + Player * pl = pi->getSource(); + if (pl && pl->isAlive() && pl->IsWithinDistInMap(m_creature,5.0f)) + { + m_creature->NearTeleportTo(pl->GetPositionX(),pl->GetPositionY(),pl->GetPositionZ(),0); + m_creature->CastSpell(pl,m_bIsHeroicMode ? SPELL_DARK_MATTER_H : SPELL_DARK_MATTER,true); // has a 0 yard range + break; + } + } + } + + darkMatterTimer = 4000; // will never repeat, but creature must wait 0.2 s before despawn + } + else + darkMatterTimer -= diff; + } +}; + +CreatureAI* GetAI_npc_dark_matter_target(Creature* pCreature) +{ + return new npc_dark_matter_targetAI(pCreature); +} + void AddSC_halls_of_stone() { Script *newscript; @@ -783,4 +903,9 @@ void AddSC_halls_of_stone() newscript->Name = "mob_tribuna_controller"; newscript->GetAI = &GetAI_mob_tribuna_controller; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dark_matter_target"; + newscript->GetAI = &GetAI_npc_dark_matter_target; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h b/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h index 3dabe26633..dc2132167b 100644 --- a/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h +++ b/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h @@ -10,21 +10,6 @@ enum { MAX_ENCOUNTER = 4, - DATA_KRYSTALLUS = 1, - DATA_GRIEF = 2, - DATA_BRANN = 3, - DATA_SJONNIR = 4, - - DATA_KADDRAK = 5, - DATA_ABEDNEUM = 6, - DATA_MARNAK = 7, - - DATA_GO_TRIBUNAL_CONSOLE = 8, - DATA_GO_SKY_FLOOR = 9, - DATA_GO_KADDRAK = 10, - DATA_GO_ABEDNEUM = 11, - DATA_GO_MARNAK = 12, - TYPE_KRYSTALLUS = 20, TYPE_GRIEF = 21, TYPE_BRANN = 22, @@ -34,6 +19,7 @@ enum NPC_GRIEF = 27975, NPC_BRANN = 28070, NPC_SJONNIR = 27978, + NPC_TRIBUNAL_OF_THE_AGES = 28234, NPC_KADDRAK = 30898, // left NPC_ABEDNEUM = 30899, // middle diff --git a/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp b/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp index b7be17b77a..3b64e797e9 100644 --- a/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp @@ -43,10 +43,42 @@ struct MANGOS_DLL_DECL instance_halls_of_stone : public ScriptedInstance bool Regular; std::string strSaveData; + void OpenDoor(uint32 entry) + { + if (entry) + { + ObjectGuid guid = GetSingleGameObjectFromStorage(entry)->GetObjectGuid(); + + if(!guid) + return; + + GameObject* pGo = instance->GetGameObject(guid); + + if(pGo) + pGo->SetGoState(GO_STATE_ACTIVE); + } + } + + void CloseDoor(uint32 entry) + { + if (entry) + { + ObjectGuid guid = GetSingleGameObjectFromStorage(entry)->GetObjectGuid(); + + if(!guid) + return; + + GameObject* pGo = instance->GetGameObject(guid); + + if(pGo) + pGo->SetGoState(GO_STATE_READY); + } + } + void Initialize() { for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i]=NOT_STARTED; + m_auiEncounter[i]=NOT_STARTED; } void OnCreatureCreate(Creature* pCreature) @@ -60,6 +92,7 @@ struct MANGOS_DLL_DECL instance_halls_of_stone : public ScriptedInstance case NPC_KADDRAK: case NPC_ABEDNEUM: case NPC_MARNAK: + case NPC_TRIBUNAL_OF_THE_AGES: m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); break; } @@ -71,45 +104,66 @@ struct MANGOS_DLL_DECL instance_halls_of_stone : public ScriptedInstance { case GO_GRIEF_DOOR: if (m_auiEncounter[0] != DONE) - pGo->SetGoState(GO_STATE_READY); - else - pGo->SetGoState(GO_STATE_ACTIVE); + CloseDoor(GO_GRIEF_DOOR); + else OpenDoor(GO_GRIEF_DOOR); break; case GO_BRANN_DOOR: if (m_auiEncounter[1] != DONE) - pGo->SetGoState(GO_STATE_READY); - else - pGo->SetGoState(GO_STATE_ACTIVE); + CloseDoor(GO_BRANN_DOOR); + else OpenDoor(GO_BRANN_DOOR); break; case GO_SJONNIR_DOOR: if (m_auiEncounter[2] != DONE) - pGo->SetGoState(GO_STATE_READY); - else - pGo->SetGoState(GO_STATE_ACTIVE); + CloseDoor(GO_SJONNIR_DOOR); + else OpenDoor(GO_SJONNIR_DOOR); + break; + case GO_TRIBUNAL_CONSOLE: + case GO_TRIBUNAL_CHEST: + case GO_TRIBUNAL_CHEST_H: + case GO_TRIBUNAL_SKY_FLOOR: + case GO_KADDRAK: + case GO_ABEDNEUM: + case GO_MARNAK: break; } m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); } + void OnPlayerEnter(Unit* pPlayer) + { + if (m_auiEncounter[0] != DONE) + CloseDoor(GO_GRIEF_DOOR); + else OpenDoor(GO_GRIEF_DOOR); + + if (m_auiEncounter[1] != DONE) + CloseDoor(GO_BRANN_DOOR); + else OpenDoor(GO_BRANN_DOOR); + + if (m_auiEncounter[2] != DONE) + CloseDoor(GO_SJONNIR_DOOR); + else OpenDoor(GO_SJONNIR_DOOR); + } + void SetData(uint32 uiType, uint32 uiData) { switch(uiType) { case TYPE_KRYSTALLUS: if (uiData == DONE) - DoUseDoorOrButton(GO_GRIEF_DOOR); + OpenDoor(GO_GRIEF_DOOR); m_auiEncounter[0] = uiData; break; case TYPE_GRIEF: if (uiData == DONE) - DoUseDoorOrButton(GO_BRANN_DOOR); + OpenDoor(GO_BRANN_DOOR); m_auiEncounter[1] = uiData; break; case TYPE_BRANN: if (uiData == DONE) { - DoUseDoorOrButton(GO_SJONNIR_DOOR); - DoRespawnGameObject(instance->IsRegularDifficulty() ? GO_TRIBUNAL_CHEST : GO_TRIBUNAL_CHEST_H); + OpenDoor(GO_SJONNIR_DOOR); + ObjectGuid chestGuid = GetSingleGameObjectFromStorage(Regular ? GO_TRIBUNAL_CHEST : GO_TRIBUNAL_CHEST_H)->GetObjectGuid(); + DoRespawnGameObject(chestGuid); } m_auiEncounter[2] = uiData; break; diff --git a/scripts/northrend/ulduar/ulduar/assembly_of_iron.cpp b/scripts/northrend/ulduar/ulduar/assembly_of_iron.cpp index 8399f1ab78..0db89c4ce9 100644 --- a/scripts/northrend/ulduar/ulduar/assembly_of_iron.cpp +++ b/scripts/northrend/ulduar/ulduar/assembly_of_iron.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: boss_iron_council SD%Complete: -SDComment: Achievment(Can't Do That While Stunned, +SDComment: Supercharge is bugged SDCategory: Ulduar EndScriptData */ @@ -27,83 +27,81 @@ EndScriptData */ enum { //yells - SAY_MOLGEIM_AGGRO = -1603060, - SAY_MOLGEIM_DEATH1 = -1603061, - SAY_MOLGEIM_DEATH2 = -1603062, - SAY_MOLGEIM_DEATH_RUNE = -1603063, - SAY_MOLGEIM_SUMMON = -1603064, - SAY_MOLGEIM_SLAY1 = -1603065, - SAY_MOLGEIM_SLAY2 = -1603066, - SAY_MOLGEIM_BERSERK = -1603067, - - SAY_STEEL_AGGRO = -1603070, - SAY_STEEL_DEATH1 = -1603071, - SAY_STEEL_DEATH2 = -1603072, - SAY_STEEL_SLAY1 = -1603073, - SAY_STEEL_SLAY2 = -1603074, - SAY_STEEL_OVERWHELMING = -1603075, - SAY_STEEL_BERSERK = -1603076, - - SAY_BRUNDIR_AGGR0 = -1603080, - SAY_BRUNDIR_WHIRL = -1603081, - SAY_BRUNDIR_DEATH1 = -1603082, - SAY_BRUNDIR_DEATH2 = -1603083, - SAY_BRUNDIR_SLAY1 = -1603084, - SAY_BRUNDIR_SLAY2 = -1603085, - SAY_BRUNDIR_BERSERK = -1603086, - SAY_BRUNDIR_FLY = -1603087, + SAY_MOLGEIM_AGGRO = -1603040, + SAY_MOLGEIM_DEATH1 = -1603041, + SAY_MOLGEIM_DEATH2 = -1603042, + SAY_MOLGEIM_DEATH_RUNE = -1603043, + SAY_MOLGEIM_SUMMON = -1603044, + SAY_MOLGEIM_SLAY1 = -1603045, + SAY_MOLGEIM_SLAY2 = -1603046, + SAY_MOLGEIM_BERSERK = -1603047, + + SAY_STEEL_AGGRO = -1603050, + SAY_STEEL_DEATH1 = -1603051, + SAY_STEEL_DEATH2 = -1603052, + SAY_STEEL_SLAY1 = -1603053, + SAY_STEEL_SLAY2 = -1603054, + SAY_STEEL_OVERWHELMING = -1603055, + SAY_STEEL_BERSERK = -1603056, + + SAY_BRUNDIR_AGGR0 = -1603060, + SAY_BRUNDIR_WHIRL = -1603062, + SAY_BRUNDIR_DEATH1 = -1603063, + SAY_BRUNDIR_DEATH2 = -1603064, + SAY_BRUNDIR_SLAY1 = -1603065, + SAY_BRUNDIR_SLAY2 = -1603066, + SAY_BRUNDIR_BERSERK = -1603067, + SAY_BRUNDIR_FLY = -1603068, //all - SPELL_BERSERK = 47008, - SPELL_SUPERCHARGE = 61920, - SPELL_IRON_COUNCIL_CREDIT = 65195, // custom spell in spell_dbc.sql - + SPELL_BERSERK = 47008, + SPELL_SUPERCHARGE = 61920, // spell is bugged. Should be cast on other bosses not on players!!! //steelbreaker - SPELL_HIGH_VOLTAGE = 61890, + SPELL_HIGH_VOLTAGE = 61890, SPELL_HIGH_VOLTAGE_H = 63498, - SPELL_FUSION_PUNCH = 61903, + SPELL_FUSION_PUNCH = 61903, SPELL_FUSION_PUNCH_H = 63493, - SPELL_STATIC_DISRUPTION = 44008, - SPELL_STATIC_DISRUPTION_H = 63494, - SPELL_POWER = 64637, - SPELL_POWER_H = 61888, - SPELL_ELECTRICAL_CHARGE = 61902, - + SPELL_STATIC_DISRUPTION = 44008, + SPELL_STATIC_DISRUPTION_H = 63494, + SPELL_POWER = 64637, + SPELL_POWER_H = 61888, + SPELL_ELECTRICAL_CHARGE = 61902, //runemaster molgeim SPELL_SHIELD = 62274, - SPELL_SHIELD_H = 63489, - SPELL_RUNE_OF_POWER = 63513, - SPELL_RUNE_OF_DEATH = 62269, - SPELL_RUNE_OF_DEATH_H = 63490, - SPELL_RUNE_OF_SUMMONING = 62273, + SPELL_SHIELD_H = 63489, + SPELL_RUNE_OF_POWER = 63513, + SPELL_RUNE_OF_DEATH = 62269, + SPELL_RUNE_OF_DEATH_H = 63490, + SPELL_RUNE_OF_SUMMONING = 62273, //rune of power - AURA_RUNE_OF_POWER = 61974, + AURA_RUNE_OF_POWER = 61974, //rune of summoning - AURA_RUNE_OF_SUMMONING = 62019, + AURA_RUNE_OF_SUMMONING = 62019, //lightning elemental - SPELL_LIGHTNING_BLAST = 62054, - SPELL_LIGHTNING_BLAST_H = 63491, - + SPELL_LIGHTNING_BLAST = 62054, + SPELL_LIGHTNING_BLAST_H = 63491, //stormcaller brundir - SPELL_CHAIN_LIGHTNING = 61879, - SPELL_CHAIN_LIGHTNING_H = 63479, - SPELL_OVERLOAD = 61869, - SPELL_LIGHTNING_WHIRL = 61915, - SPELL_LIGHTNING_WHIRL_H = 63483, - SPELL_STORMSHIELD = 64187, + SPELL_CHAIN_LIGHTNING = 61879, + SPELL_CHAIN_LIGHTNING_H = 63479, + SPELL_OVERLOAD = 61869, + SPELL_LIGHTNING_WHIRL = 61915, + SPELL_LIGHTNING_WHIRL_H = 63483, + SPELL_STORMSHIELD = 64187, SPELL_LIGHTNING_TENDRILS = 61887, - SPELL_LIGHTNING_TENDRILS_H = 63486, - LIGHTNING_TENDRILS_VISUAL = 61883, + SPELL_LIGHTNING_TENDRILS_H = 63486, + LIGHTNING_TENDRILS_VISUAL = 61883, //NPC ids - MOB_LIGHTNING_ELEMENTAL = 32958, -}; + MOB_LIGHTNING_ELEMENTAL = 32958, -enum BrundirPhase -{ - PHASE_NORMAL = 1, - PHASE_UP = 2, - PHASE_TENDRILS = 3, - PHASE_DOWN = 4, + ACHIEV_ON_YOUR_SIDE = 2945, + ACHIEV_ON_YOUR_SIDE_H = 2946, + + ACHIEV_CHOOSE_BRUNDIR = 2940, + ACHIEV_CHOOSE_BRUNDIR_H = 2943, + ACHIEV_CHOOSE_MOLGEIM = 2939, + ACHIEV_CHOOSE_MOLGEIM_H = 2942, + ACHIEV_CHOOSE_STEELBREAKER = 2941, + ACHIEV_CHOOSE_STEELBREAKER_H= 2944, }; // Rune of Power @@ -144,11 +142,11 @@ struct MANGOS_DLL_DECL mob_ulduar_lightning_elementalAI : public ScriptedAI { mob_ulduar_lightning_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiDeath_Timer; @@ -194,12 +192,12 @@ struct MANGOS_DLL_DECL mob_rune_of_summoningAI : public ScriptedAI { mob_rune_of_summoningAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiDeath_Timer; uint32 m_uiSummon_Timer; @@ -226,9 +224,9 @@ struct MANGOS_DLL_DECL mob_rune_of_summoningAI : public ScriptedAI { if (m_uiSummon_Timer < diff) { - if (/*Creature* pTemp = */m_creature->SummonCreature(MOB_LIGHTNING_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + if (Creature* pTemp = m_creature->SummonCreature(MOB_LIGHTNING_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) ++m_uiSummonNum; - + if (m_uiSummonNum > 9) m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); @@ -247,74 +245,135 @@ struct MANGOS_DLL_DECL boss_brundirAI : public ScriptedAI { boss_brundirAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiChain_Lightning_Timer; uint32 m_uiOverload_Timer; uint32 m_uiWhirl_Timer; - uint32 m_uiTendrilsTimer; - uint32 m_uiTendrilsEndTimer; + uint32 m_uiTendrils_start_Timer; + uint32 m_uiTendrils_Change; + uint32 m_uiTendrils_end_Timer; + uint32 m_uiDie_delay; uint32 m_uiEnrage_Timer; + uint32 m_uiCheckTimer; bool m_bHasSupercharge1; bool m_bHasSupercharge2; + bool m_bIsTendrils; + bool m_bMustDie; + bool m_bIsSteelbreakerDead; + bool m_bIsMolgeimDead; bool m_bIsEnrage; - BrundirPhase brundirPhase; - void Reset() { - m_creature->SetLevitate(false); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); m_uiChain_Lightning_Timer = 0; - brundirPhase = PHASE_NORMAL; m_uiOverload_Timer = 35000; m_uiEnrage_Timer = 900000; + m_uiCheckTimer = 1000; m_bIsEnrage = false; m_bHasSupercharge1 = false; m_bHasSupercharge2 = false; + m_bIsTendrils = false; + m_bIsSteelbreakerDead = false; + m_bIsMolgeimDead = false; + m_bMustDie = false; + if (m_creature->HasAura(SPELL_SUPERCHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_SUPERCHARGE); } - void SpellHit(Unit* caster, const SpellEntry* spell) + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if (spell->Id == SPELL_SUPERCHARGE) + if (uiDamage > m_creature->GetHealth() && !m_bMustDie) { - m_creature->SetHealth(m_creature->GetMaxHealth()); - if (m_bHasSupercharge1) - { - m_bHasSupercharge2 = true; - m_uiTendrilsTimer = 40000; - } - else + uiDamage = 0; + m_creature->CastStop(); + m_creature->RemoveAllAuras(); + DoCast(m_creature, SPELL_SUPERCHARGE); + m_uiDie_delay = 500; + m_bMustDie = true; + } + } + + void OnYourSide() + { + /* hacky way to complete achievements; use only if you have this function + Map* pMap = m_creature->GetMap(); + AchievementEntry const *AchievYourSide = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_ON_YOUR_SIDE : ACHIEV_ON_YOUR_SIDE_H); + if(AchievYourSide && pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) { - m_bHasSupercharge1 = true; - m_uiWhirl_Timer = 10000; + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer->HasAura(SPELL_IRON_BOOT_AURA, EFFECT_INDEX_0)) + pPlayer->CompletedAchievement(AchievYourSide); + } + } } } + */ } void JustDied(Unit* pKiller) { - if (m_bHasSupercharge2) - { - m_pInstance->SetData(TYPE_ASSEMBLY, DONE); - DoCast(m_creature, SPELL_IRON_COUNCIL_CREDIT, true); - } - else + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + // if all of them are dead + if (m_pInstance) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_YOU_BRUNDIR, false); - m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - DoCast(m_creature, SPELL_SUPERCHARGE, true); + // remove supercharge from players -> spell bug + //m_pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SUPERCHARGE); + // if the others are dead then give loot + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (!pTemp->isAlive()) + { + if (Creature* p2Temp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (!p2Temp->isAlive()) + { + m_pInstance->SetData(TYPE_ASSEMBLY, DONE); + // only the current one has loot, because loot modes are implemented in sql + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // I'm on your side + OnYourSide(); + + // ChooseBrundir + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHOOSE_BRUNDIR : ACHIEV_CHOOSE_BRUNDIR_H); + } + } + } + } + + // else make them full hp + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } } - DoScriptText(urand(0,1) ? SAY_BRUNDIR_DEATH1 : SAY_BRUNDIR_DEATH2 , m_creature); + if(irand(0,1)) + DoScriptText(SAY_BRUNDIR_DEATH1, m_creature); + else + DoScriptText(SAY_BRUNDIR_DEATH2, m_creature); } void Aggro(Unit* pWho) @@ -340,6 +399,16 @@ struct MANGOS_DLL_DECL boss_brundirAI : public ScriptedAI void JustReachedHome() { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } if (m_pInstance) { if(m_pInstance->GetData(TYPE_ASSEMBLY) != FAIL) @@ -347,9 +416,12 @@ struct MANGOS_DLL_DECL boss_brundirAI : public ScriptedAI } } - void KilledUnit(Unit *pWho) + void KilledUnit(Unit *who) { - DoScriptText(urand(0,1) ? SAY_BRUNDIR_SLAY1 : SAY_BRUNDIR_SLAY2 , m_creature); + if(irand(0,1)) + DoScriptText(SAY_BRUNDIR_SLAY1, m_creature); + else + DoScriptText(SAY_BRUNDIR_SLAY2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -357,137 +429,148 @@ struct MANGOS_DLL_DECL boss_brundirAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiEnrage_Timer < uiDiff && !m_bIsEnrage) + // level 1 spells + if (m_uiChain_Lightning_Timer < uiDiff && !m_bIsTendrils) { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) - { - m_bIsEnrage = true; - DoScriptText(SAY_BRUNDIR_BERSERK, m_creature); - } - } - else - m_uiEnrage_Timer -= uiDiff; + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H); + m_uiChain_Lightning_Timer = 2000; + }else m_uiChain_Lightning_Timer -= uiDiff; - switch (brundirPhase) + if (m_uiOverload_Timer < uiDiff && !m_bIsTendrils) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_OVERLOAD); + m_uiOverload_Timer = 40000; + }else m_uiOverload_Timer -= uiDiff; + + // level 2 spells + if (m_uiWhirl_Timer < uiDiff && !m_bIsTendrils && m_bHasSupercharge1) + { + m_creature->CastStop(); + DoScriptText(SAY_BRUNDIR_WHIRL, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_WHIRL : SPELL_LIGHTNING_WHIRL_H); + m_uiWhirl_Timer = 15000; + }else m_uiWhirl_Timer -= uiDiff; + + // level 3 spells + // boss doesn't fly during tendrils, needs fixing! + if (m_uiTendrils_start_Timer < uiDiff && m_bHasSupercharge2) { - case PHASE_NORMAL: + if (!m_bIsTendrils) { - // level 1 spells - if (m_uiChain_Lightning_Timer < uiDiff) + DoScriptText(SAY_BRUNDIR_FLY, m_creature); + m_creature->CastStop(); + DoCast(m_creature, LIGHTNING_TENDRILS_VISUAL); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - if (DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H) == CAST_OK) - m_uiChain_Lightning_Timer = 2000; + m_creature->AddThreat(pTarget,0.0f); + m_creature->AI()->AttackStart(pTarget); } - else - m_uiChain_Lightning_Timer -= uiDiff; + m_bIsTendrils = true; + m_creature->SetSpeedRate(MOVE_RUN, 0.8f); + m_uiTendrils_start_Timer = 3000; + m_uiTendrils_end_Timer = 40000; + m_uiTendrils_Change = 5000; + } + else + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_TENDRILS : SPELL_LIGHTNING_TENDRILS_H); + m_uiTendrils_start_Timer = 90000; + } + }else m_uiTendrils_start_Timer -= uiDiff; - if (m_uiOverload_Timer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_OVERLOAD) == CAST_OK) - m_uiOverload_Timer = 40000; - } - else - m_uiOverload_Timer -= uiDiff; + if (m_uiTendrils_Change < uiDiff && m_bIsTendrils) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->AddThreat(pTarget,0.0f); + m_creature->AI()->AttackStart(pTarget); + } + m_uiTendrils_Change = 6000; + }else m_uiTendrils_Change -= uiDiff; - // level 2 spells - if (m_bHasSupercharge1) + if (m_uiTendrils_end_Timer < uiDiff && m_bIsTendrils) + { + if (m_creature->HasAura(SPELL_LIGHTNING_TENDRILS)) + m_creature->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS); + if (m_creature->HasAura(SPELL_LIGHTNING_TENDRILS_H)) + m_creature->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_H); + if (m_creature->HasAura(LIGHTNING_TENDRILS_VISUAL)) + m_creature->RemoveAurasDueToSpell(LIGHTNING_TENDRILS_VISUAL); + m_uiTendrils_start_Timer = 90000; + m_creature->SetSpeedRate(MOVE_RUN, 1.8f); + m_bIsTendrils = false; + m_uiChain_Lightning_Timer = 5000; + m_uiOverload_Timer = 35000; + m_uiWhirl_Timer = 10000; + }else m_uiTendrils_end_Timer -= uiDiff; + + // die after casting supercharge + if (m_uiDie_delay < uiDiff && m_bMustDie) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDie_delay -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bIsEnrage) + { + DoScriptText(SAY_BRUNDIR_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bIsEnrage = true; + }else m_uiEnrage_Timer -= uiDiff; + + // check if the others are dead + if (m_uiCheckTimer < uiDiff && !m_bHasSupercharge2) + { + if (!m_bIsSteelbreakerDead) + { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) { - if (m_uiWhirl_Timer < uiDiff) + if (!pTemp->isAlive()) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_WHIRL : SPELL_LIGHTNING_WHIRL_H) == CAST_OK) + m_bIsSteelbreakerDead = true; + if (!m_bHasSupercharge1) { - DoScriptText(SAY_BRUNDIR_WHIRL, m_creature); - m_uiWhirl_Timer = 15000; + m_bHasSupercharge1 = true; + m_uiWhirl_Timer = 10000; + } + else + { + m_bHasSupercharge2 = true; + m_uiTendrils_start_Timer = 40000; + m_uiTendrils_end_Timer = 60000; + m_uiTendrils_Change = 6000; } } - else - m_uiWhirl_Timer -= uiDiff; - - // level 3 spells - if (m_bHasSupercharge2) + } + } + if (!m_bIsMolgeimDead) + { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (!pTemp->isAlive()) { - // boss doesn't fly during tendrils, needs fixing! - if (m_uiTendrilsTimer < uiDiff) + m_bIsMolgeimDead = true; + if (!m_bHasSupercharge1) { - brundirPhase = PHASE_UP; - DoScriptText(SAY_BRUNDIR_FLY, m_creature); - - m_creature->SetLevitate(true); - m_creature->SetWalk(false); - m_creature->GetMotionMaster()->MovePoint(1, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 5); - m_creature->SetSpeedRate(MOVE_RUN, 0.8f); - m_uiTendrilsTimer = 4000; + m_bHasSupercharge1 = true; + m_uiWhirl_Timer = 10000; } else - m_uiTendrilsTimer -= uiDiff; - - DoCastSpellIfCan(m_creature, SPELL_STORMSHIELD, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); + { + m_bHasSupercharge2 = true; + m_uiTendrils_start_Timer = 40000; + m_uiTendrils_end_Timer = 60000; + m_uiTendrils_Change = 6000; + } } } - break; - } - case PHASE_UP: - if (m_uiTendrilsTimer < uiDiff) - { - brundirPhase = PHASE_TENDRILS; - DoCast(m_creature, LIGHTNING_TENDRILS_VISUAL, true); - DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_TENDRILS : SPELL_LIGHTNING_TENDRILS_H,true); - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) - m_creature->GetMotionMaster()->MovePoint(1, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ() + 5); - m_uiTendrilsTimer = 4000; - m_uiTendrilsEndTimer = 40000; - } - else - m_uiTendrilsTimer -= uiDiff; - - break; - case PHASE_TENDRILS: - if (m_uiTendrilsTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) - m_creature->GetMotionMaster()->MovePoint(1, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ() + 5); - m_uiTendrilsTimer = 4000; - } - else - m_uiTendrilsTimer -= uiDiff; - - if (m_uiTendrilsEndTimer < uiDiff) - { - brundirPhase = PHASE_DOWN; - - m_uiTendrilsTimer = 2000; - m_creature->SetLevitate(false); - m_creature->SetWalk(true); - float x = m_creature->GetPositionX(); - float y = m_creature->GetPositionY(); - float z = m_creature->GetTerrain()->GetWaterOrGroundLevel(x,y,m_creature->GetPositionZ()); - m_creature->GetMotionMaster()->MovePoint(1, x, y, z); - m_creature->SetSpeedRate(MOVE_RUN, 1.8f); - m_uiChain_Lightning_Timer = 5000; - m_uiOverload_Timer = 35000; - m_uiWhirl_Timer = 10000; - } - else - m_uiTendrilsEndTimer -= uiDiff; - break; - case PHASE_DOWN: - if (m_uiTendrilsTimer < uiDiff) - { - brundirPhase = PHASE_NORMAL; - m_uiTendrilsTimer = 90000; - if (m_creature->HasAura(SPELL_LIGHTNING_TENDRILS)) - m_creature->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS); - if (m_creature->HasAura(SPELL_LIGHTNING_TENDRILS_H)) - m_creature->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_H); - if (m_creature->HasAura(LIGHTNING_TENDRILS_VISUAL)) - m_creature->RemoveAurasDueToSpell(LIGHTNING_TENDRILS_VISUAL); - } - else - m_uiTendrilsTimer -= uiDiff; - break; - } + m_uiCheckTimer = 1000; + }else m_uiCheckTimer -= uiDiff; + + if (!m_bIsTendrils && !m_bMustDie) + DoMeleeAttackIfReady(); } }; @@ -501,22 +584,27 @@ struct MANGOS_DLL_DECL boss_molgeimAI : public ScriptedAI { boss_molgeimAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiShield_Timer; uint32 m_uiRune_Power_Timer; uint32 m_uiRune_Death_Timer; uint32 m_uiRune_Summon_Timer; + uint32 m_uiDie_delay; uint32 m_uiEnrage_Timer; + uint32 m_uiCheckTimer; - bool m_bHasSupercharge1; - bool m_bHasSupercharge2; + bool m_bSupercharge1; + bool m_bSupercharge2; + bool m_bMustDie; + bool m_bBrundirDead; + bool m_bSteelbreakerDead; bool m_bEnrage; void Reset() @@ -525,45 +613,102 @@ struct MANGOS_DLL_DECL boss_molgeimAI : public ScriptedAI m_uiShield_Timer = 20000; m_uiRune_Power_Timer = 10000; m_uiEnrage_Timer = 900000; + m_uiCheckTimer = 1000; m_bEnrage = false; - m_bHasSupercharge1 = false; - m_bHasSupercharge2 = false; + m_bBrundirDead = false; + m_bSteelbreakerDead = false; + m_bSupercharge1 = false; + m_bSupercharge2 = false; + m_bMustDie = false; + if (m_creature->HasAura(SPELL_SUPERCHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_SUPERCHARGE); } - void SpellHit(Unit* caster, const SpellEntry* spell) + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if (spell->Id == SPELL_SUPERCHARGE) + if (uiDamage > m_creature->GetHealth() && !m_bMustDie) { - m_creature->SetHealth(m_creature->GetMaxHealth()); - if (m_bHasSupercharge1) - { - m_bHasSupercharge2 = true; - m_uiRune_Summon_Timer = 20000; - } - else + uiDamage = 0; + m_creature->RemoveAllAuras(); + m_creature->CastStop(); + DoCast(m_creature, SPELL_SUPERCHARGE); + m_uiDie_delay = 500; + m_bMustDie = true; + } + } + + void OnYourSide() + { + /* hacky way to complete achievements; use only if you have this function + Map* pMap = m_creature->GetMap(); + AchievementEntry const *AchievYourSide = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_ON_YOUR_SIDE : ACHIEV_ON_YOUR_SIDE_H); + if(AchievYourSide && pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) { - m_bHasSupercharge1 = true; - m_uiRune_Death_Timer = 10000; + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer->HasAura(SPELL_IRON_BOOT_AURA, EFFECT_INDEX_0)) + pPlayer->CompletedAchievement(AchievYourSide); + } + } } } + */ } void JustDied(Unit* pKiller) { - if (m_bHasSupercharge2) - { - m_pInstance->SetData(TYPE_ASSEMBLY, DONE); - DoCast(m_creature, SPELL_IRON_COUNCIL_CREDIT, true); - } - else + //death yell + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (m_pInstance) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_YOU_MOLGEIM, false); - m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - DoCast(m_creature, SPELL_SUPERCHARGE, true); + // remove supercharge from players -> spell bug + //m_pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SUPERCHARGE); + // if the others are dead then give loot + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (!pTemp->isAlive()) + { + if (Creature* p2Temp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (!p2Temp->isAlive()) + { + m_pInstance->SetData(TYPE_ASSEMBLY, DONE); + // only the current one has loot, because loot modes are implemented in sql + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // I'm on your side + OnYourSide(); + + // ChooseMolgeim + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHOOSE_MOLGEIM : ACHIEV_CHOOSE_MOLGEIM_H); + } + } + } + } + + // else make them full hp + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } } - DoScriptText(urand(0,1) ? SAY_MOLGEIM_DEATH1 : SAY_MOLGEIM_DEATH2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_MOLGEIM_DEATH1, m_creature); + else + DoScriptText(SAY_MOLGEIM_DEATH2, m_creature); } void Aggro(Unit* pWho) @@ -589,6 +734,16 @@ struct MANGOS_DLL_DECL boss_molgeimAI : public ScriptedAI void JustReachedHome() { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } if (m_pInstance) { if(m_pInstance->GetData(TYPE_ASSEMBLY) != FAIL) @@ -598,7 +753,10 @@ struct MANGOS_DLL_DECL boss_molgeimAI : public ScriptedAI void KilledUnit(Unit *who) { - DoScriptText(urand(0,1) ? SAY_MOLGEIM_SLAY1 : SAY_MOLGEIM_SLAY2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_MOLGEIM_SLAY1, m_creature); + else + DoScriptText(SAY_MOLGEIM_SLAY2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -609,92 +767,118 @@ struct MANGOS_DLL_DECL boss_molgeimAI : public ScriptedAI // level 1 spells if (m_uiShield_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SHIELD : SPELL_SHIELD_H) == CAST_OK) - m_uiShield_Timer = 50000; - } - else - m_uiShield_Timer -= uiDiff; + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHIELD : SPELL_SHIELD_H); + m_uiShield_Timer = 50000; + }else m_uiShield_Timer -= uiDiff; if (m_uiRune_Power_Timer < uiDiff) { switch(urand(0, 2)) { - case 0: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) - { - if (pTemp->isAlive()) - DoCast(pTemp, SPELL_RUNE_OF_POWER); - else - DoCast(m_creature, SPELL_RUNE_OF_POWER); - } - break; - case 1: - if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) - { - if (pTemp->isAlive()) - DoCast(pTemp, SPELL_RUNE_OF_POWER); - else - DoCast(m_creature, SPELL_RUNE_OF_POWER); - } - break; - case 2: - DoCast(m_creature, SPELL_RUNE_OF_POWER); - break; + case 0: + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_RUNE_OF_POWER); + else + DoCast(m_creature, SPELL_RUNE_OF_POWER); + } + break; + case 1: + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) + { + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_RUNE_OF_POWER); + else + DoCast(m_creature, SPELL_RUNE_OF_POWER); + } + break; + case 2: + DoCast(m_creature, SPELL_RUNE_OF_POWER); + break; } m_uiRune_Power_Timer = 30000; - } - else - m_uiRune_Power_Timer -= uiDiff; + }else m_uiRune_Power_Timer -= uiDiff; // level2 spells - if (m_bHasSupercharge1) + if (m_uiRune_Death_Timer < uiDiff && m_bSupercharge1) + { + DoScriptText(SAY_MOLGEIM_DEATH_RUNE, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RUNE_OF_DEATH : SPELL_RUNE_OF_DEATH_H); + m_uiRune_Death_Timer = 30000; + }else m_uiRune_Death_Timer -= uiDiff; + + // level 3 spells + if (m_uiRune_Summon_Timer < uiDiff && m_bSupercharge2) + { + DoScriptText(SAY_MOLGEIM_SUMMON, m_creature); + m_creature->CastStop(); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); + m_uiRune_Summon_Timer = 30000; + }else m_uiRune_Summon_Timer -= uiDiff; + + // die after overloading + if (m_uiDie_delay < uiDiff && m_bMustDie) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDie_delay -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bEnrage) + { + DoScriptText(SAY_MOLGEIM_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bEnrage = true; + }else m_uiEnrage_Timer -= uiDiff; + + if (m_uiCheckTimer < uiDiff) { - if (m_uiRune_Death_Timer < uiDiff) + if (!m_bSteelbreakerDead) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_STEELBREAKER)) { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_RUNE_OF_DEATH : SPELL_RUNE_OF_DEATH_H) == CAST_OK) + if (!pTemp->isAlive()) { - DoScriptText(SAY_MOLGEIM_DEATH_RUNE, m_creature); - m_uiRune_Death_Timer = 30000; + m_bSteelbreakerDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiRune_Death_Timer = 10000; + } + else + { + m_bSupercharge2 = true; + m_uiRune_Summon_Timer = 20000; + } } } } - else - m_uiRune_Death_Timer -= uiDiff; - - // level 3 spells - if (m_bHasSupercharge2) + if (!m_bBrundirDead) { - if (m_uiRune_Summon_Timer < uiDiff) + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) { - m_creature->CastStop(); - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if (!pTemp->isAlive()) { - if (DoCastSpellIfCan(pTarget, SPELL_RUNE_OF_SUMMONING) == CAST_OK) + m_bBrundirDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiRune_Death_Timer = 10000; + } + else { - DoScriptText(SAY_MOLGEIM_SUMMON, m_creature); - m_uiRune_Summon_Timer = 30000; + m_bSupercharge2 = true; + m_uiRune_Summon_Timer = 20000; } } } - else - m_uiRune_Summon_Timer -= uiDiff; } - } - - if (m_uiEnrage_Timer < uiDiff && !m_bEnrage) - { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) - { - m_bEnrage = true; - DoScriptText(SAY_MOLGEIM_BERSERK, m_creature); - } - } - else - m_uiEnrage_Timer -= uiDiff; - - DoMeleeAttackIfReady(); + m_uiCheckTimer = 1000; + }else m_uiCheckTimer -= uiDiff; + + if (!m_bMustDie) + DoMeleeAttackIfReady(); } }; @@ -708,23 +892,26 @@ struct MANGOS_DLL_DECL boss_steelbreakerAI : public ScriptedAI { boss_steelbreakerAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiFusion_Punch_Timer; uint32 m_uiStatic_Disruption_Timer; uint32 m_uiPower_Timer; + uint32 m_uiDie_delay; uint32 m_uiEnrage_Timer; + uint32 m_uiCheckTimer; bool m_bBrundirDead; bool m_bMolgeimDead; - bool m_bHasSupercharge1; - bool m_bHasSupercharge2; + bool m_bSupercharge1; + bool m_bSupercharge2; + bool m_bMustDie; bool m_bEnrage; void Reset() @@ -732,55 +919,119 @@ struct MANGOS_DLL_DECL boss_steelbreakerAI : public ScriptedAI m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); m_uiFusion_Punch_Timer = 20000; m_uiEnrage_Timer = 900000; + m_uiCheckTimer = 1000; m_bEnrage = false; m_bBrundirDead = false; m_bMolgeimDead = false; - m_bHasSupercharge1 = false; - m_bHasSupercharge2 = false; + m_bSupercharge1 = false; + m_bSupercharge2 = false; + m_bMustDie = false; + if (m_creature->HasAura(SPELL_SUPERCHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_SUPERCHARGE); + if (m_creature->HasAura(SPELL_ELECTRICAL_CHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_ELECTRICAL_CHARGE); + if (m_creature->HasAura(SPELL_HIGH_VOLTAGE)) + m_creature->RemoveAurasDueToSpell(SPELL_HIGH_VOLTAGE); + if (m_creature->HasAura(SPELL_HIGH_VOLTAGE_H)) + m_creature->RemoveAurasDueToSpell(SPELL_HIGH_VOLTAGE_H); } void KilledUnit(Unit* pVictim) { - if (m_bHasSupercharge2) + if (m_bSupercharge2) DoCast(m_creature, SPELL_ELECTRICAL_CHARGE); - DoScriptText(urand(0,1) ? SAY_STEEL_SLAY1 : SAY_STEEL_SLAY2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_STEEL_SLAY1, m_creature); + else + DoScriptText(SAY_STEEL_SLAY2, m_creature); } - void SpellHit(Unit* caster, const SpellEntry* spell) + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if (spell->Id == SPELL_SUPERCHARGE) + if (uiDamage > m_creature->GetHealth() && !m_bMustDie) { - m_creature->SetHealth(m_creature->GetMaxHealth()); - if (m_bHasSupercharge1) - { - m_bHasSupercharge2 = true; - m_uiPower_Timer = 5000; - } - else + uiDamage = 0; + m_creature->CastStop(); + m_creature->RemoveAllAuras(); + DoCast(m_creature, SPELL_SUPERCHARGE); + m_uiDie_delay = 500; + m_bMustDie = true; + } + } + + void OnYourSide() + { + /* hacky way to complete achievements; use only if you have this function + Map* pMap = m_creature->GetMap(); + AchievementEntry const *AchievYourSide = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_ON_YOUR_SIDE : ACHIEV_ON_YOUR_SIDE_H); + if(AchievYourSide && pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) { - m_bHasSupercharge1 = true; - m_uiStatic_Disruption_Timer = 12000; + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer->HasAura(SPELL_IRON_BOOT_AURA, EFFECT_INDEX_0)) + pPlayer->CompletedAchievement(AchievYourSide); + } + } } } + */ } - void JustDied(Unit* pKiller) { - if (m_bHasSupercharge2) + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (m_pInstance) { - m_pInstance->SetData(TYPE_ASSEMBLY, DONE); - DoCast(m_creature, SPELL_IRON_COUNCIL_CREDIT, true); + // remove supercharge from players -> spell bug + // m_pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SUPERCHARGE); + // if the others are dead then give loot + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (!pTemp->isAlive()) + { + if (Creature* p2Temp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (!p2Temp->isAlive()) + { + m_pInstance->SetData(TYPE_ASSEMBLY, DONE); + m_pInstance->SetData(TYPE_ASSEMBLY_HARD, DONE); + // only the current one has loot, because loot modes are implemented in sql + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // I'm on your side + OnYourSide(); + + // ChooseSteelbreaker + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHOOSE_STEELBREAKER : ACHIEV_CHOOSE_STEELBREAKER_H); + } + } + } + } + + // else make them full hp + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } } + + if(irand(0,1)) + DoScriptText(SAY_STEEL_DEATH1, m_creature); else - { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_YOU_STEELBREAKER, false); - m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - DoCast(m_creature, SPELL_SUPERCHARGE, true); - } - DoScriptText(urand(0,1) ? SAY_STEEL_DEATH1 : SAY_STEEL_DEATH2, m_creature); + DoScriptText(SAY_STEEL_DEATH2, m_creature); } void Aggro(Unit* pWho) @@ -795,6 +1046,7 @@ struct MANGOS_DLL_DECL boss_steelbreakerAI : public ScriptedAI if (pTemp->isAlive()) pTemp->SetInCombatWithZone(); } + DoCast(m_creature, m_bIsRegularMode ? SPELL_HIGH_VOLTAGE : SPELL_HIGH_VOLTAGE_H); if (m_pInstance) { if(m_pInstance->GetData(TYPE_ASSEMBLY) != IN_PROGRESS) @@ -806,6 +1058,16 @@ struct MANGOS_DLL_DECL boss_steelbreakerAI : public ScriptedAI void JustReachedHome() { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } if (m_pInstance) { if(m_pInstance->GetData(TYPE_ASSEMBLY) != FAIL) @@ -818,60 +1080,90 @@ struct MANGOS_DLL_DECL boss_steelbreakerAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_HIGH_VOLTAGE : SPELL_HIGH_VOLTAGE_H, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); // level 1 spells if (m_uiFusion_Punch_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FUSION_PUNCH : SPELL_FUSION_PUNCH_H)) - m_uiFusion_Punch_Timer = urand(17000,22000); - } - else - m_uiFusion_Punch_Timer -= uiDiff; - + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FUSION_PUNCH : SPELL_FUSION_PUNCH_H); + m_uiFusion_Punch_Timer = 20000; + }else m_uiFusion_Punch_Timer -= uiDiff; + // level 2 spells - if (m_bHasSupercharge1) + if (m_uiStatic_Disruption_Timer < uiDiff && m_bSupercharge1) { - if (m_uiStatic_Disruption_Timer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, (uint32)0, SELECT_FLAG_PLAYER)) - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_STATIC_DISRUPTION : SPELL_STATIC_DISRUPTION_H) == CAST_OK) - m_uiStatic_Disruption_Timer = 60000; - } - else - m_uiStatic_Disruption_Timer -= uiDiff; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_STATIC_DISRUPTION : SPELL_STATIC_DISRUPTION_H); + m_uiStatic_Disruption_Timer = 60000; + }else m_uiStatic_Disruption_Timer -= uiDiff; + + // level 3 spells + if (m_uiPower_Timer < uiDiff && m_bSupercharge2) + { + m_creature->CastStop(); + DoScriptText(SAY_STEEL_OVERWHELMING, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_POWER : SPELL_POWER_H); + m_uiPower_Timer = m_bIsRegularMode ? 65000 : 35000; + }else m_uiPower_Timer -= uiDiff; + + if (m_uiDie_delay < uiDiff && m_bMustDie) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDie_delay -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bEnrage) + { + DoScriptText(SAY_STEEL_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bEnrage = true; + }else m_uiEnrage_Timer -= uiDiff; - // level 3 spells - if (m_bHasSupercharge2) + if (m_uiCheckTimer < uiDiff) + { + if (!m_bBrundirDead) { - if (m_uiPower_Timer < uiDiff) + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_BRUNDIR)) { - - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + if (!pTemp->isAlive()) { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_POWER : SPELL_POWER_H) == CAST_OK) + m_bBrundirDead = true; + if (!m_bSupercharge1) { - DoScriptText(SAY_STEEL_OVERWHELMING, m_creature); - m_uiPower_Timer = m_bIsRegularMode ? 65000 : 35000; + m_bSupercharge1 = true; + m_uiStatic_Disruption_Timer = 12000; + } + else + { + m_bSupercharge2 = true; + m_uiPower_Timer = 5000; } } } - else - m_uiPower_Timer -= uiDiff; } - } - - if (m_uiEnrage_Timer < uiDiff && !m_bEnrage) - { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) + if (!m_bMolgeimDead) { - m_bEnrage = true; - DoScriptText(SAY_STEEL_BERSERK, m_creature); + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_MOLGEIM)) + { + if (!pTemp->isAlive()) + { + m_bMolgeimDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiStatic_Disruption_Timer = 22000; + } + else + { + m_bSupercharge2 = true; + m_uiPower_Timer = 5000; + } + } + } } - } - else - m_uiEnrage_Timer -= uiDiff; - - DoMeleeAttackIfReady(); + m_uiCheckTimer = 1000; + }else m_uiCheckTimer -= uiDiff; + + if (!m_bMustDie) + DoMeleeAttackIfReady(); } }; diff --git a/scripts/northrend/ulduar/ulduar/boss_algalon.cpp b/scripts/northrend/ulduar/ulduar/boss_algalon.cpp index ac16219644..a93de9b801 100644 --- a/scripts/northrend/ulduar/ulduar/boss_algalon.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_algalon.cpp @@ -122,13 +122,13 @@ struct MANGOS_DLL_DECL mob_black_holeAI : public ScriptedAI { mob_black_holeAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bHasAura; uint32 m_uiRaidCheckTimer; @@ -187,7 +187,7 @@ struct MANGOS_DLL_DECL boss_algalonAI : public ScriptedAI { boss_algalonAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_bHasStarted = false; // flag used to check if the encounter has been started from the console @@ -200,7 +200,7 @@ struct MANGOS_DLL_DECL boss_algalonAI : public ScriptedAI Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiBerserk_Timer; @@ -499,7 +499,7 @@ struct MANGOS_DLL_DECL boss_algalonAI : public ScriptedAI // berserk if(m_uiBerserk_Timer < uiDiff) { - DoScriptText(SAY_BERSERK, m_creature); + DoScriptText(SAY_BERSERK, m_creature); DoCast(m_creature, SPELL_BERSERK); m_uiBerserk_Timer = 360000; }else m_uiBerserk_Timer -= uiDiff; @@ -574,6 +574,8 @@ struct MANGOS_DLL_DECL boss_algalonAI : public ScriptedAI m_uiOutroTimer = 5000; break; case 3: + // make boss kneel +// m_creature->SetSplineFlags(SPLINEFLAG_UNKNOWN12); if(m_bIsDespawned) { DoScriptText(SAY_DESPAWN1, m_creature); @@ -669,12 +671,12 @@ struct MANGOS_DLL_DECL mob_collapsing_starAI : public ScriptedAI { mob_collapsing_starAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiHealthTimer; @@ -729,7 +731,7 @@ struct MANGOS_DLL_DECL mob_collapsing_starAI : public ScriptedAI m_creature->DealDamage(m_creature, (m_creature->GetMaxHealth() * 0.01), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); m_uiHealthTimer = 1000; }else m_uiHealthTimer -= uiDiff; - } + } }; //Living constellation @@ -737,12 +739,12 @@ struct MANGOS_DLL_DECL mob_living_constellationAI : public ScriptedAI { mob_living_constellationAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiArcaneBarrageTimer; @@ -775,7 +777,7 @@ struct MANGOS_DLL_DECL mob_cosmic_smash_targetAI : public ScriptedAI { mob_cosmic_smash_targetAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); @@ -783,7 +785,7 @@ struct MANGOS_DLL_DECL mob_cosmic_smash_targetAI : public ScriptedAI Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiSpellTimer; @@ -807,13 +809,13 @@ struct MANGOS_DLL_DECL mob_cosmic_smash_targetAI : public ScriptedAI DoCast(m_creature, SPELL_COSMIC_SMASH_MISSILE); m_uiSpellTimer = 60000; }else m_uiSpellTimer -= uiDiff; - } + } }; bool GOHello_go_celestial_acces(Player* pPlayer, GameObject* pGo) { - instance_ulduar* m_pInstance = (instance_ulduar*)pGo->GetInstanceData(); + ScriptedInstance* m_pInstance = (ScriptedInstance*)pGo->GetInstanceData(); bool m_bIsRegularMode = pGo->GetMap()->IsRegularDifficulty(); bool m_bHasItem = false; @@ -851,8 +853,7 @@ bool GOHello_go_celestial_acces(Player* pPlayer, GameObject* pGo) pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); // open celestial door - if(GameObject* pDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_CELESTIAL_DOOR)) - m_pInstance->DoUseDoorOrButton(pDoor->GetObjectGuid()); + m_pInstance->DoUseDoorOrButton(GO_CELESTIAL_DOOR); } } diff --git a/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp b/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp index 8bcbca3cfb..fc0af600c4 100644 --- a/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp @@ -27,462 +27,573 @@ EndScriptData */ enum { //yells - SAY_AGGRO = -1603110, - SAY_SLAY_1 = -1603112, - SAY_SLAY_2 = -1603111, - SAY_BERSERK = -1603113, - SAY_DEATH = -1603114, - EMOTE_SCREECH = -1603115, - EMOTE_DEFENDER = -1603116, + SAY_AGGRO = -1603070, + SAY_SLAY1 = -1603071, + SAY_SLAY2 = -1603072, + SAY_BERSERK = -1603073, + SAY_DEATH = -1603074, + EMOTE_SCREECH = -1603358, + EMOTE_DEFENDER = -1603359, + + //auriaya + SPELL_BERSERK = 47008, + SPELL_GUARDIAN_SWARM = 64396, // broken + SPELL_SENTINEL_BLAST = 64389, + SPELL_SENTINEL_BLAST_H = 64678, + SPELL_SONIC_SCREECH = 64422, + SPELL_SONIC_SCREECH_H = 64688, + SPELL_FEAR = 64386, + + //feral defender + SPELL_FEIGN_DEATH = 57685, + SPELL_FERAL_ESSENCE = 64455, + SPELL_FERAL_POUNCE = 64478, + SPELL_FERAL_POUNCE_H = 64669, + SPELL_FERAL_RUSH = 64496, + SPELL_FERAL_RUSH_H = 64674, //sanctum sentry - SPELL_RIP_FLESH = 64375, - SPELL_RIP_FLESH_H = 64667, - SPELL_SAVAGE_POUNCE = 64666, - SPELL_SAVAGE_POUNCE_H = 64374, - SPELL_STRENGHT_OF_PACK = 64369, - SPELL_STRENGHT_OF_PACK_BUFF = 64381, - - // Auriaya - SPELL_BERSERK = 47008, - SPELL_GUARDIAN_SWARM = 64396, // triggers 64397 - SPELL_SENTINEL_BLAST = 64389, // triggers 64392 - SPELL_SENTINEL_BLAST_H = 64678, // triggers 64679 - SPELL_SONIC_SCREECH = 64422, - SPELL_SONIC_SCREECH_H = 64688, - SPELL_TERRIFYING_SCREECH = 64386, - SPELL_ACTIVATE_FERAL_DEFENDER = 64449, // triggers 64447 - SPELL_ACTIVATE_FERAL_DEFENDER_TRIGG = 64448, - - // Feral Defender spells - SPELL_FERAL_ESSENCE = 64455, - SPELL_FERAL_ESSENCE_REMOVAL = 64456, // remove 1 stack of 64455 - SPELL_FERAL_POUNCE = 64478, - SPELL_FERAL_POUNCE_H = 64669, - //SPELL_FERAL_RUSH = 64489, // should trigger repeatedly on random targets 64496 - 64674 - SPELL_SEEPING_FERAL_ESSENCE_SUMMON = 64457, - SPELL_FEIGN_DEATH = 64461, // dummy - possible related to the feral defender feign death - not used - SPELL_FULL_HEAL = 64460, // on feign death remove - SPELL_FEIGN_DEATH_2 = 57685, - SPELL_FERAL_RUSH = 64496, - SPELL_FERAL_RUSH_H = 64674, - - // Seeping Feral Essence - SPELL_SEEPING_FERAL_ESSENCE = 64458, - SPELL_SEEPING_FERAL_ESSENCE_H = 64676, - - //NPC_SEEPING_FERAL_ESSENCE = 34098, // summoned by the feral defender on feign death - //NPC_GUARDIAN_SWARN = 34034, // summoned by spell - NPC_FERAL_DEFENDER_STALKER = 34096, - //NPC_FERAL_DEFENDER = 34035, + SPELL_RIP_FLESH = 64375, + SPELL_RIP_FLESH_H = 64667, + SPELL_SAVAGE_POUNCE = 64666, + SPELL_SAVAGE_POUNCE_H = 64374, + SPELL_STRENGHT_OF_PACK = 64369, + //seeping feral essence + AURA_VOID_ZONE = 64458, + AURA_VOID_ZONE_H = 64676, + //NPC ids + MOB_VOID_ZONE = 34098, + MOB_FERAL_DEFENDER = 34035, + MOB_GUARDIAN_SWARN = 34034, + + ACHIEV_CRAZY_CAT_LADY = 3006, + ACHIEV_CRAZY_CAT_LADY_H = 3007, + + ACHIEV_NINE_LIVES = 3076, + ACHIEV_NINE_LIVES_H = 3077, }; -struct MANGOS_DLL_DECL boss_auriayaAI : public ScriptedAI +bool m_bCrazyCatLady; +bool m_bNineLives; + +// Seeping Feral Essence +struct MANGOS_DLL_DECL mob_seeping_feral_essenceAI : public ScriptedAI { - boss_auriayaAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_seeping_feral_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + pCreature->setFaction(14); + pCreature->SetDisplayId(11686); // make invisible Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiEnrageTimer; - uint32 m_uiSwarmTimer; - uint32 m_uiSonicScreechTimer; - uint32 m_uiSentinelBlastTimer; - uint32 m_uiTerrifyingScreechTimer; - uint32 m_uiDefenderTimer; - void Reset() { - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - m_uiEnrageTimer = 10*MINUTE*IN_MILLISECONDS; - m_uiSwarmTimer = 50000; - m_uiSonicScreechTimer = 58000; - m_uiSentinelBlastTimer = 40000; - m_uiTerrifyingScreechTimer = 38000; - m_uiDefenderTimer = 1*MINUTE*IN_MILLISECONDS; - - for (GUIDList::iterator itr = m_pInstance->m_lSanctumSentryGuids.begin(); itr != m_pInstance->m_lSanctumSentryGuids.end(); ++itr) - { - if (Creature* pSanity = m_creature->GetMap()->GetCreature(*itr)) - { - if (!pSanity->isAlive()) - { - pSanity->Respawn(); - pSanity->NearTeleportTo(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0.0f); - } - } - } + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, m_bIsRegularMode ? AURA_VOID_ZONE : AURA_VOID_ZONE_H); + m_creature->SetRespawnDelay(DAY); } - void JustDied(Unit* pKiller) + void UpdateAI(const uint32 uiDiff) { - DoScriptText(SAY_DEATH, m_creature); - - if (m_pInstance) - m_pInstance->SetData(TYPE_AURIAYA, DONE); + if (m_pInstance->GetData(TYPE_AURIAYA) != IN_PROGRESS) + m_creature->ForcedDespawn(); } +}; - void Aggro(Unit* pWho) +CreatureAI* GetAI_mob_seeping_feral_essence(Creature* pCreature) +{ + return new mob_seeping_feral_essenceAI(pCreature); +} + +// Sanctum Sentry +struct MANGOS_DLL_DECL mob_sanctum_sentryAI : public ScriptedAI +{ + mob_sanctum_sentryAI(Creature* pCreature) : ScriptedAI(pCreature) { - if (m_pInstance) - m_pInstance->SetData(TYPE_AURIAYA, IN_PROGRESS); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } - for (GUIDList::iterator itr = m_pInstance->m_lSanctumSentryGuids.begin(); itr != m_pInstance->m_lSanctumSentryGuids.end(); ++itr) - { - if (Creature* pSanity = m_creature->GetMap()->GetCreature(*itr)) - { - if (pSanity->isAlive()) - pSanity->SetInCombatWithZone(); - } - } + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; - DoScriptText(SAY_AGGRO, m_creature); - } + uint32 m_uiRip_Flesh_Timer; + uint32 m_uiJump_Timer; - void KilledUnit(Unit* pVictim) - { - DoScriptText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, m_creature); - } + std::list lSentrys; - void JustReachedHome() + void Reset() { - if (m_pInstance) - m_pInstance->SetData(TYPE_AURIAYA, FAIL); - } + m_uiRip_Flesh_Timer = 13000; + m_uiJump_Timer = 0; - void JustSummoned(Creature *pSummoned) - { - // Summon the feral defender - if (pSummoned->GetEntry() == NPC_FERAL_DEFENDER_STALKER) - DoCastSpellIfCan(pSummoned, SPELL_ACTIVATE_FERAL_DEFENDER, CAST_INTERRUPT_PREVIOUS); + lSentrys.clear(); } - void UpdateAI(const uint32 uiDiff) + void Aggro(Unit* pWho) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if (m_uiTerrifyingScreechTimer < uiDiff) + if (m_pInstance) { - if (DoCastSpellIfCan(m_creature, SPELL_TERRIFYING_SCREECH) == CAST_OK) + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_AURIAYA)) { - DoScriptText(EMOTE_SCREECH, m_creature); - m_uiTerrifyingScreechTimer = 35000; - m_uiSentinelBlastTimer = 2000; + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); } } - else - m_uiTerrifyingScreechTimer -= uiDiff; - if (m_uiSentinelBlastTimer < uiDiff) + GetCreatureListWithEntryInGrid(lSentrys, m_creature, NPC_SANCTUM_SENTRY, DEFAULT_VISIBILITY_INSTANCE); + if (!lSentrys.empty()) { - // Cast Sentinel blast right after terrifying screech - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SENTINEL_BLAST : SPELL_SENTINEL_BLAST_H) == CAST_OK) - m_uiSentinelBlastTimer = 35000; + for(std::list::iterator iter = lSentrys.begin(); iter != lSentrys.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->SetInCombatWithZone(); + } } - else - m_uiSentinelBlastTimer -= uiDiff; - if (m_uiDefenderTimer) + DoCast(m_creature, SPELL_STRENGHT_OF_PACK); + } + + void JustDied(Unit* pKiller) + { + m_bCrazyCatLady = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) { - if (m_uiDefenderTimer <= uiDiff) + // they should follow Auriaya, but this looks ugly! + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_AURIAYA)) { - // Summon the feral defender trigger - if (DoCastSpellIfCan(m_creature, SPELL_ACTIVATE_FERAL_DEFENDER_TRIGG) == CAST_OK) + if (pTemp->isAlive() && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) { - DoScriptText(EMOTE_DEFENDER, m_creature); - m_uiDefenderTimer = 0; + + float angle = m_creature->GetAngle(pTemp); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveFollow(pTemp, PET_FOLLOW_DIST, angle); } } - else - m_uiDefenderTimer -= uiDiff; } - if (m_uiSonicScreechTimer < uiDiff) + if (m_uiRip_Flesh_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SONIC_SCREECH : SPELL_SONIC_SCREECH_H) == CAST_OK) - m_uiSonicScreechTimer = 27000; - } - else - m_uiSonicScreechTimer -= uiDiff; + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_RIP_FLESH : SPELL_RIP_FLESH_H); + m_uiRip_Flesh_Timer = 13000; + }else m_uiRip_Flesh_Timer -= uiDiff; - if (m_uiSwarmTimer < uiDiff) + if (m_uiJump_Timer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER | SELECT_FLAG_NOT_IN_MELEE_RANGE)) - { - if (DoCastSpellIfCan(m_creature, SPELL_GUARDIAN_SWARM) == CAST_OK) - m_uiSwarmTimer = 37000; - } - } - else - m_uiSwarmTimer -= uiDiff; - - if (m_uiEnrageTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) - { - DoScriptText(SAY_BERSERK, m_creature); - m_uiEnrageTimer = 10*MINUTE*IN_MILLISECONDS; - } - } - else - m_uiEnrageTimer -= uiDiff; + if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25)) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SAVAGE_POUNCE : SPELL_SAVAGE_POUNCE_H); + m_uiJump_Timer = 1000; + }else m_uiJump_Timer -= uiDiff; DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_auriaya(Creature* pCreature) +CreatureAI* GetAI_mob_sanctum_sentry(Creature* pCreature) { - return new boss_auriayaAI(pCreature); + return new mob_sanctum_sentryAI(pCreature); } -struct MANGOS_DLL_DECL boss_feral_defenderAI : public ScriptedAI +// Feral Defender +struct MANGOS_DLL_DECL mob_feral_defenderAI : public ScriptedAI { - boss_feral_defenderAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_feral_defenderAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiPounceTimer; - uint32 m_uiFeralRushTimer; - uint32 m_uiReviveDelayTimer; - uint32 m_uiKilledCount; + uint32 m_uiPounce_Timer; + uint32 m_uiRush_Start_Timer; + uint32 m_uiRush_Finish_Timer; + uint32 m_uiRush_Delay; + uint32 m_uiRevive_Delay; + + bool m_bIsRush; + bool m_bIsDead; + + bool m_bHasAura; void Reset() { - m_uiReviveDelayTimer = 0; - m_uiPounceTimer = 5000; - m_uiFeralRushTimer = 10000; - m_uiKilledCount = 0; + m_uiPounce_Timer = 5000; + m_uiRush_Start_Timer = 9000; + m_bIsRush = false; + m_bIsDead = false; + m_bHasAura = false; + m_creature->SetRespawnDelay(DAY); + } - DoCastSpellIfCan(m_creature, SPELL_FERAL_ESSENCE); + void Aggro(Unit* pWho) + { + if (!m_bHasAura) + DoCast(m_creature, SPELL_FERAL_ESSENCE); } void JustDied(Unit* pKiller) { - // Set achiev criteria to true - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_NINE_LIVES, true); + m_bNineLives = true; } + // feign death void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - // If we don't have the feral essence anymore then ignore this - if (m_uiKilledCount >= 8) // 9-1 == 8 - return; - - if (m_uiReviveDelayTimer) // Already faking - { - uiDamage = 0; - return; - } - - if (uiDamage > m_creature->GetHealth()) + if (m_creature->HasAura(SPELL_FERAL_ESSENCE)) { - if (m_creature->HasAura(SPELL_FERAL_ESSENCE)) + if (uiDamage > m_creature->GetHealth()) { uiDamage = 0; - - m_creature->InterruptNonMeleeSpells(true); - m_creature->SetHealth(0); - m_creature->StopMoving(); - m_creature->ClearComboPointHolders(); - //m_creature->RemoveAllAurasOnDeath(); // TODO Should only remove negative auras - m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + m_creature->CastStop(); + m_creature->RemoveArenaAuras(true); + m_creature->SummonCreature(MOB_VOID_ZONE, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + DoCast(m_creature, SPELL_FEIGN_DEATH); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->ClearAllReactives(); - m_creature->GetMotionMaster()->Clear(); - m_creature->GetMotionMaster()->MoveIdle(); - m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - // Remove one aura stack and summon a feral essence - DoCastSpellIfCan(m_creature, SPELL_FERAL_ESSENCE_REMOVAL, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_SEEPING_FERAL_ESSENCE_SUMMON, CAST_TRIGGERED); + // remove 1 stack of the aura + if(SpellAuraHolderPtr strenght = m_creature->GetSpellAuraHolder(SPELL_FERAL_ESSENCE)) + { + if(strenght->ModStackAmount(-1)) + m_creature->RemoveAurasDueToSpell(SPELL_FERAL_ESSENCE); + } - m_uiReviveDelayTimer = 30000; - ++m_uiKilledCount; + m_uiRevive_Delay = 500; + m_bIsDead = true; } } } - void JustSummoned(Creature* pSummoned) - { - // Cast seeping feral essence on the summoned - pSummoned->CastSpell(pSummoned, m_bIsRegularMode ? SPELL_SEEPING_FERAL_ESSENCE : SPELL_SEEPING_FERAL_ESSENCE_H, true, NULL, NULL, m_creature->GetObjectGuid()); - } - void UpdateAI(const uint32 uiDiff) { + if (m_pInstance && m_pInstance->GetData(TYPE_AURIAYA) != IN_PROGRESS) + m_creature->ForcedDespawn(); + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiReviveDelayTimer) + // hacky way of stacking aura, needs fixing + if (!m_bHasAura) { - if (m_uiReviveDelayTimer <= uiDiff) + if(SpellAuraHolderPtr essence = m_creature->GetSpellAuraHolder(SPELL_FERAL_ESSENCE)) { - if (DoCastSpellIfCan(m_creature, SPELL_FULL_HEAL) == CAST_OK) + if(essence->GetStackAmount() < 9) { - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->SetStandState(UNIT_STAND_STATE_STAND); - - DoResetThreat(); - m_uiReviveDelayTimer = 0; - - // Assume Attack - it should jump to victim - if (m_creature->getVictim()) - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_bHasAura = true; + essence->SetStackAmount(9); } } - else - m_uiReviveDelayTimer -= uiDiff; - - // No Further action while faking - return; } - if (m_uiPounceTimer < uiDiff) + if (m_uiPounce_Timer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_FERAL_POUNCE : SPELL_FERAL_POUNCE_H) == CAST_OK) - m_uiPounceTimer = 5000; + DoCast(target, m_bIsRegularMode ? SPELL_FERAL_POUNCE : SPELL_FERAL_POUNCE_H); + m_creature->AddThreat(target,0.0f); + m_creature->AI()->AttackStart(target); } - } - else - m_uiPounceTimer -= uiDiff; + m_uiPounce_Timer = 5000; + }else m_uiPounce_Timer -= uiDiff; + + if (m_uiRush_Start_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(target, m_bIsRegularMode ? SPELL_FERAL_RUSH : SPELL_FERAL_RUSH_H); + m_creature->AddThreat(target,0.0f); + m_creature->AI()->AttackStart(target); + } + m_uiRush_Start_Timer = 35000; + m_uiRush_Finish_Timer = m_bIsRegularMode ? 2500 : 5000; + m_uiRush_Delay = 500; + m_bIsRush = true; + }else m_uiRush_Start_Timer -= uiDiff; - if (m_uiFeralRushTimer < uiDiff) + if (m_uiRush_Delay < uiDiff && m_bIsRush) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_FERAL_RUSH : SPELL_FERAL_RUSH_H) == CAST_OK) - m_uiFeralRushTimer = 12000; + DoCast(target, m_bIsRegularMode ? SPELL_FERAL_RUSH : SPELL_FERAL_RUSH_H); + m_creature->AddThreat(target,0.0f); + m_creature->AI()->AttackStart(target); } + m_uiRush_Delay = 500; + }else m_uiRush_Delay -= uiDiff; + + if (m_uiRush_Finish_Timer < uiDiff) + m_bIsRush = false; + else m_uiRush_Finish_Timer -= uiDiff; + + if (m_bIsDead) + { + if (m_uiRevive_Delay < uiDiff) + { + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsDead = false; + } else m_uiRevive_Delay -= uiDiff; } - else - m_uiFeralRushTimer -= uiDiff; DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_feral_defender(Creature* pCreature) +CreatureAI* GetAI_mob_feral_defender(Creature* pCreature) { - return new boss_feral_defenderAI(pCreature); + return new mob_feral_defenderAI(pCreature); } -// Sanctum Sentry -struct MANGOS_DLL_DECL boss_sanctum_sentryAI : public ScriptedAI +// Auriaya +struct MANGOS_DLL_DECL boss_auriayaAI : public ScriptedAI { - boss_sanctum_sentryAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_auriayaAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - bool m_bIsFollowing; + uint32 m_uiEnrage_Timer; + uint32 m_uiSwarm_Timer; + uint32 m_uiSonic_Screech_Timer; + uint32 m_uiSentinel_Blast_Timer; + uint32 m_uiFear_Timer; + uint32 m_uiSummon_Timer; + uint32 m_uiDefenderCheck_Timer; + uint8 m_uiSwarmcount; - uint32 m_uiRip_Flesh_Timer; - uint32 m_uiJump_Timer; + Creature* m_pDefender; + std::list lSentrys; + + bool m_bHasBerserk; + bool m_bIsDefender; void Reset() { - m_uiRip_Flesh_Timer = 13000; - m_uiJump_Timer = 0; - m_bIsFollowing = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_uiEnrage_Timer = 600000; + m_uiSwarm_Timer = urand(50000, 60000); + m_uiSonic_Screech_Timer = urand(90000, 100000); + m_uiSentinel_Blast_Timer = 62000; + m_uiFear_Timer = 60000; + m_uiSummon_Timer = urand(60000, 70000); + m_uiSwarmcount = 10; + m_uiDefenderCheck_Timer = 1000; + m_bHasBerserk = false; + m_bIsDefender = false; + + m_pDefender = NULL; + lSentrys.clear(); + + // achievs + m_bCrazyCatLady = true; + m_bNineLives = false; + } + + void JustDied(Unit* pKiller) + { + //death yell + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_AURIAYA, DONE); + + // hacky way to complete achievements; use only if you have this function + if (m_bCrazyCatLady) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CRAZY_CAT_LADY : ACHIEV_CRAZY_CAT_LADY_H); + } + + if (m_bNineLives) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_NINE_LIVES : ACHIEV_NINE_LIVES_H); + } } void Aggro(Unit* pWho) { if (m_pInstance) + m_pInstance->SetData(TYPE_AURIAYA, IN_PROGRESS); + + GetCreatureListWithEntryInGrid(lSentrys, m_creature, NPC_SANCTUM_SENTRY, DEFAULT_VISIBILITY_INSTANCE); + if (!lSentrys.empty()) { - if (Creature* pAuriaya = m_pInstance->GetSingleCreatureFromStorage(NPC_AURIAYA)) + for(std::list::iterator iter = lSentrys.begin(); iter != lSentrys.end(); ++iter) { - if (pAuriaya->isAlive()) - pAuriaya->SetInCombatWithZone(); + if ((*iter) && (*iter)->isAlive()) + (*iter)->SetInCombatWithZone(); } + } + + DoScriptText(SAY_AGGRO, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } - for (GUIDList::iterator itr = m_pInstance->m_lSanctumSentryGuids.begin(); itr != m_pInstance->m_lSanctumSentryGuids.end(); ++itr) + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_AURIAYA, FAIL); + + GetCreatureListWithEntryInGrid(lSentrys, m_creature, NPC_SANCTUM_SENTRY, DEFAULT_VISIBILITY_INSTANCE); + if (!lSentrys.empty()) + { + for(std::list::iterator iter = lSentrys.begin(); iter != lSentrys.end(); ++iter) { - if (Creature* pSanity = m_creature->GetMap()->GetCreature(*itr)) - { - if (pSanity->isAlive()) - pSanity->SetInCombatWithZone(); - } + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); } } - DoCast(m_creature, SPELL_STRENGHT_OF_PACK); } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - { - if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) - if (m_pInstance) - if (Creature *pAuriaya = m_pInstance->GetSingleCreatureFromStorage(NPC_AURIAYA)) - m_creature->GetMotionMaster()->MoveFollow(pAuriaya, 5.0f, urand(60, 250)/100.0f); return; + + if (m_uiFear_Timer < uiDiff) + { + DoScriptText(EMOTE_SCREECH, m_creature); + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FEAR); + m_uiFear_Timer = 35000; + m_uiSentinel_Blast_Timer = 2500; } + else m_uiFear_Timer -= uiDiff; - if (m_uiRip_Flesh_Timer < diff) + if (m_uiSentinel_Blast_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_RIP_FLESH : SPELL_RIP_FLESH_H) == CAST_OK) - m_uiRip_Flesh_Timer = 13000; + DoCast(m_creature, m_bIsRegularMode ? SPELL_SENTINEL_BLAST : SPELL_SENTINEL_BLAST_H); + m_uiSentinel_Blast_Timer = urand(30000, 40000); } - else - m_uiRip_Flesh_Timer -= diff; + else m_uiSentinel_Blast_Timer -= uiDiff; - if (m_uiJump_Timer < diff) + if (!m_bIsDefender) { - if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25)) - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SAVAGE_POUNCE : SPELL_SAVAGE_POUNCE_H); - m_uiJump_Timer = 1000; + if (m_uiSummon_Timer < uiDiff) + { + if (m_pDefender = m_creature->SummonCreature(MOB_FERAL_DEFENDER, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000)) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_pDefender->AddThreat(pTarget,0.0f); + m_pDefender->AI()->AttackStart(pTarget); + } + DoScriptText(EMOTE_DEFENDER, m_creature); + m_bIsDefender = true; + } + } + else m_uiSummon_Timer -= uiDiff; } else - m_uiJump_Timer -= diff; + { + if (m_uiDefenderCheck_Timer < uiDiff) + { + if (m_pDefender->isAlive() && m_pDefender->HasAura(SPELL_FEIGN_DEATH)) + m_pDefender->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH); + + m_uiDefenderCheck_Timer = 1000; + } + else m_uiDefenderCheck_Timer -= uiDiff; + } + + if (m_uiSonic_Screech_Timer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SONIC_SCREECH : SPELL_SONIC_SCREECH_H); + m_uiSonic_Screech_Timer = 27000; + } + else m_uiSonic_Screech_Timer -= uiDiff; + + // summon swarm, spell needs core fix + if (m_uiSwarm_Timer < uiDiff) + { + for(int i = 0; i < 10; i++) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = m_creature->GetPositionX() + 10*cos(angle*(M_PI/180)); + float homeY = m_creature->GetPositionY() + 10*sin(angle*(M_PI/180)); + if (Creature* pTemp = m_creature->SummonCreature(MOB_GUARDIAN_SWARN, homeX, homeY, m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 10000)) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_GUARDIAN_SWARM); + pTemp->AddThreat(pTarget, 100.0f); + pTemp->SetInCombatWithZone(); + } + } + } + m_uiSwarm_Timer = 35000; + } + else m_uiSwarm_Timer -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bHasBerserk) + { + DoScriptText(SAY_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bHasBerserk = true; + } + else m_uiEnrage_Timer -= uiDiff; DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_sanctum_sentry(Creature* pCreature) +CreatureAI* GetAI_boss_auriaya(Creature* pCreature) { - return new boss_sanctum_sentryAI(pCreature); + return new boss_auriayaAI(pCreature); } void AddSC_boss_auriaya() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_auriaya"; - pNewScript->GetAI = GetAI_boss_auriaya; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_sanctum_sentry"; - pNewScript->GetAI = &GetAI_boss_sanctum_sentry; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_feral_defender"; - pNewScript->GetAI = &GetAI_boss_feral_defender; - pNewScript->RegisterSelf(); + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_auriaya"; + NewScript->GetAI = &GetAI_boss_auriaya; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_seeping_feral_essence"; + NewScript->GetAI = &GetAI_mob_seeping_feral_essence; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_sanctum_sentry"; + NewScript->GetAI = &GetAI_mob_sanctum_sentry; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_feral_defender"; + NewScript->GetAI = &GetAI_mob_feral_defender; + NewScript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp b/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp index c7bbf8ce71..2ea7dd7aa4 100644 --- a/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp @@ -1,23 +1,23 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* 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, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/* Copyright (C) 2006 - 2011 ScriptDev2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* ScriptData SDName: boss_leviathan SD%Complete: -SDComment: needs vehicles , add Flying Mobs, Throw Passenger, Grab Crate +SDComment: needs vehicles SDCategory: Ulduar EndScriptData */ @@ -44,7 +44,7 @@ enum say SAY_ENERGY_TOWER = -1603215, SAY_NATURE_TOWER = -1603216, - EMOTE_PURSUE = -1603352, + EMOTE_PURSUE = -1603217, }; enum spells @@ -53,7 +53,6 @@ enum spells SPELL_MISSILE_BARRAGE = 62400, SPELL_FLAME_VENTS = 62396, - SPELL_FLAME_VENTS_TIGGER= 63847, SPELL_BATTERING_RAM = 62376, SPELL_GATHERING_SPEED = 62375, @@ -66,37 +65,23 @@ enum spells SPELL_FLAME_CANNON = 62395, //SPELL_FLAME_CANNON = 64692, trigger the same spell - + SPELL_BLAZE = 62292, + // used by players -> to be added later SPELL_ELECTROSHOCK = 62522, SPELL_SMOKE_TRAIL = 63575, // tower of nature - SPELL_LASH = 65062, - SPELL_FREYA_WARD = 62906, + SPELL_FREYAS_WARD = 62906, SPELL_TOWER_OF_LIFE = 64482, // tower of flames SPELL_MIMIRON_INFERNO = 62910, SPELL_TOWER_OF_FLAMES = 65075, // tower of frost - SPELL_TOWER_OF_FROST = 65079, - SPELL_HODIR_FURY = 62533, + SPELL_HODIR_FURY = 62297, // also + 10% hp // tower of storms - SPELL_THORIMS_HAMMER = 62911, - SPELL_TOWER_OF_STORMS = 65076, - - // pool of tar - SPELL_TAR_PASSIV = 62288, - SPELL_BLAZE = 62292, - - // Pyrit Vehicles - SPELL_LIQUID_PYRITE = 62494, - - - AURA_DUMMY_BLUE = 63294, - AURA_DUMMY_GREEN = 63295, - AURA_DUMMY_YELLOW = 63292, - + SPELL_THORIMS_HAMMER = 62912, + SPELL_TOWER_OF_STORMS = 65076 }; enum Mobs @@ -104,15 +89,6 @@ enum Mobs MOB_MECHANOLIFT = 33214, MOB_LIQUID = 33189, MOB_CONTAINER = 33218, - - MOB_THORIM_BEACON = 33365, - MOB_MIMIRON_BEACON = 33370, - MOB_HODIR_BEACON = 33212, - MOB_FREYA_BEACON = 33367, - NPC_THORIM_TARGET_BEACON = 33364, - NPC_MIMIRON_TARGET_BEACON = 33369, - NPC_HODIR_TARGET_BEACON = 33108, - NPC_FREYA_TARGET_BEACON = 33366, DEFENSE_TURRET = 33142, KEEPER_OF_NORGANNON = 33686 @@ -123,77 +99,6 @@ enum Seats SEAT_PLAYER = 0, SEAT_TURRET = 1, SEAT_DEVICE = 2, - SEAT_CANNON = 7, -}; - -enum Vehicles -{ - VEHICLE_SIEGE = 33060, - VEHICLE_CHOPPER = 33062, - VEHICLE_DEMOLISHER = 33109, -}; - -enum eAchievementData -{ - ACHIEV_10_ORBITAL_BOMBARDMENT = 2913, // one Tower - ACHIEV_25_ORBITAL_BOMBARDMENT = 2918, - ACHIEV_10_ORBITAL_DEVASTATION = 2914, // two Towers - ACHIEV_25_ORBITAL_DEVASTATION = 2916, - ACHIEV_10_NUKED_FROM_ORBIT = 2915, // three Towers - ACHIEV_25_NUKED_FROM_ORBIT = 2917, - ACHIEV_10_ORBIT_UARY = 3056, - ACHIEV_25_ORBIT_UARY = 3057, -/* Nicht implementiert - ACHIEV_10_SHUTOUT = 2911, - ACHIEV_25_SHUTOUT = 2912, - ACHIEV_10_THREE_CAR_GARAGE = 2907, - ACHIEV_25_THREE_CAR_GARAGE = 2908, - ACHIEV_10_UNBROKEN = 2905, - ACHIEV_25_UNBROKEN = 2906,*/ -}; - -struct Positions -{ - float x,y,z,o; -}; -static Positions Center[]= -{ - {354.8771f, -12.90240f, 409.803650f, 0.0f}, -}; - -const Positions PosSiege[5] = -{ - {-814.59f,-64.54f,429.92f,5.969f}, - {-784.37f,-33.31f,429.92f,5.096f}, - {-808.99f,-52.10f,429.92f,5.668f}, - {-798.59f,-44.00f,429.92f,5.663f}, - {-812.83f,-77.71f,429.92f,0.046f}, -}; - -const Positions PosChopper[5] = -{ - {-717.83f,-106.56f,430.02f,0.122f}, - {-717.83f,-114.23f,430.44f,0.122f}, - {-717.83f,-109.70f,430.22f,0.122f}, - {-718.45f,-118.24f,430.26f,0.052f}, - {-718.45f,-123.58f,430.41f,0.085f}, -}; - -const Positions PosDemolisher[5] = -{ - {-724.12f,-176.64f,430.03f,2.543f}, - {-766.70f,-225.03f,430.50f,1.710f}, - {-729.54f,-186.26f,430.12f,1.902f}, - {-756.01f,-219.23f,430.50f,2.369f}, - {-798.01f,-227.24f,429.84f,1.446f}, -}; - -const float WayMimironBeacon[4][3] = -{ - {161.45f, -37.50f, 409.80f}, - {275.14f, 64.12f, 409.80f}, - {349.67f, -31.71f, 409.80f}, - {246.72f,-129.38f, 409.80f}, }; @@ -201,12 +106,16 @@ struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI { boss_flame_leviathan(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + // ### unit disabled, please remove if you want to test it! +// pCreature->setFaction(35); // remove this when vehicules fixed! +// pCreature->SetVisibility(VISIBILITY_OFF); + // ### Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiBatteringRamTimer; @@ -217,9 +126,6 @@ struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI uint32 m_uiSummonFlyerTimer; uint8 maxFlyers; - uint8 uiActiveTowers; - uint8 uiShutdown; - bool isHardMode; bool isHodirsTower; bool isFreyasTower; @@ -233,56 +139,30 @@ struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI void Reset() { - if (m_pInstance) - m_pInstance->SetData(TYPE_LEVIATHAN, NOT_STARTED); - - m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); - m_creature->ApplySpellImmune(49560, 0, 0, true); - - m_creature->RemoveAurasDueToSpell(SPELL_TOWER_OF_FROST); - m_creature->RemoveAurasDueToSpell(SPELL_TOWER_OF_STORMS); - m_creature->RemoveAurasDueToSpell(SPELL_TOWER_OF_FLAMES); - m_creature->RemoveAurasDueToSpell(SPELL_TOWER_OF_LIFE); - m_uiBatteringRamTimer = 15000 + rand()%20000; m_uiFlameVentsTimer = 15000 + rand()%10000; m_uiMissileBarrageTimer = 1000; - m_uiPursueTimer = 0; + m_uiPursueTimer = 30000; m_uiGatheringSpeedTimer = 50000; m_uiSummonFlyerTimer = 2000; maxFlyers = 10; - uiActiveTowers = 0; - isHardMode = false; isHodirsTower = false; isFreyasTower = false; isMimironsTower = false; isThorimsTower = false; - m_uiFreyaWardTimer = urand(1000, 10000); - m_uiMimironInfernoTimer = urand(1000, 10000); - m_uiHodirFuryTimer = urand(1000, 10000); - m_uiThorimHammerTimer = urand(1000, 10000); + m_uiFreyaWardTimer = 40000 + urand(1000, 10000); + m_uiMimironInfernoTimer = 40000 + urand(1000, 10000); + m_uiHodirFuryTimer = 40000 + urand(1000, 10000); + m_uiThorimHammerTimer = 40000 + urand(1000, 10000); m_creature->SetSpeedRate(MOVE_RUN, 0.3f); } - void StartFreyaEvent()//summon these 4 on each corner wich wil spawn additional hostile mobs - { - if (Creature* pFreayaBeacon = m_creature->SummonCreature(MOB_FREYA_BEACON, 377.02f, -119.10f, 409.81f, 0.0f ,TEMPSUMMON_MANUAL_DESPAWN, 0)) - DoCast(pFreayaBeacon,AURA_DUMMY_GREEN, true); - if (Creature* pFreayaBeacon = m_creature->SummonCreature(MOB_FREYA_BEACON, 377.02f, 54.78f, 409.81f, 0.0f ,TEMPSUMMON_MANUAL_DESPAWN, 0)) - DoCast(pFreayaBeacon,AURA_DUMMY_GREEN, true); - if (Creature* pFreayaBeacon = m_creature->SummonCreature(MOB_FREYA_BEACON, 185.62f, 54.78f, 409.81f, 0.0f ,TEMPSUMMON_MANUAL_DESPAWN, 0)) - DoCast(pFreayaBeacon,AURA_DUMMY_GREEN, true); - if (Creature* pFreayaBeacon = m_creature->SummonCreature(MOB_FREYA_BEACON, 185.62f, -119.10f, 409.81f, 0.0f ,TEMPSUMMON_MANUAL_DESPAWN, 0)) - DoCast(pFreayaBeacon,AURA_DUMMY_GREEN, true); - } - void Aggro(Unit *who) { - CheckForTowers(); if(m_pInstance) { m_pInstance->SetData(TYPE_LEVIATHAN, IN_PROGRESS); @@ -300,21 +180,6 @@ struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI m_pInstance->SetData(TYPE_LEVIATHAN, DONE); if(isHardMode) m_pInstance->SetData(TYPE_LEVIATHAN_HARD, DONE); - - if (uiActiveTowers) - { - switch (uiActiveTowers) - { - case 4: - m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_10_ORBIT_UARY : ACHIEV_25_ORBIT_UARY); - case 3: - m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_10_NUKED_FROM_ORBIT : ACHIEV_25_NUKED_FROM_ORBIT); - case 2: - m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_10_ORBITAL_DEVASTATION : ACHIEV_25_ORBITAL_DEVASTATION); - case 1: - m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_10_ORBITAL_BOMBARDMENT : ACHIEV_25_ORBITAL_BOMBARDMENT); - } - } } DoScriptText(SAY_DEATH, m_creature); @@ -353,77 +218,8 @@ struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI uiDamage += uiDamage/2; } - bool CollossusDead() - { - std::list lCreatureList; - GetCreatureListWithEntryInGrid(lCreatureList, m_creature, 33237, 100.0f); - if (!lCreatureList.empty()) - for(std::list::iterator itr = lCreatureList.begin(); itr != lCreatureList.end(); ++itr) - if ((*itr)->isAlive()) - return false; - - return true; - } - - void CheckForTowers() - { - if (!isHodirsTower) - { - if (GameObject* pTower = m_pInstance->GetSingleGameObjectFromStorage(GO_TOWER_OF_FROST)) - if (pTower->GetHealth()) - { - isHodirsTower = true; - m_creature->CastSpell(m_creature, SPELL_TOWER_OF_FROST,true); - isHardMode = true; - uiActiveTowers++; - } - } - if (!isFreyasTower) - { - if (GameObject* pTower = m_pInstance->GetSingleGameObjectFromStorage(GO_TOWER_OF_LIFE)) - if (pTower->GetHealth()) - { - isFreyasTower = true; - m_creature->CastSpell(m_creature, SPELL_TOWER_OF_LIFE,true); - isHardMode = true; - uiActiveTowers++; - } - } - if (!isMimironsTower) - { - if (GameObject* pTower = m_pInstance->GetSingleGameObjectFromStorage(GO_TOWER_OF_FLAME)) - if (pTower->GetHealth()) - { - isMimironsTower = true; - m_creature->CastSpell(m_creature, SPELL_TOWER_OF_FLAMES,true); - isHardMode = true; - uiActiveTowers++; - } - } - if (!isThorimsTower) - { - if (GameObject* pTower = m_pInstance->GetSingleGameObjectFromStorage(GO_TOWER_OF_STORMS)) - if (pTower->GetHealth()) - { - isThorimsTower = true; - m_creature->CastSpell(m_creature, SPELL_TOWER_OF_STORMS,true); - isHardMode = true; - uiActiveTowers++; - } - } - m_creature->SetHealth(m_creature->GetMaxHealth()); - } - - void UpdateAI(const uint32 uiDiff) { - if(m_pInstance && (m_pInstance->GetData(TYPE_LEVIATHAN) == NOT_STARTED || m_pInstance->GetData(TYPE_LEVIATHAN) == FAIL)) - if (CollossusDead()) - { - m_creature->GetMotionMaster()->MovePoint(1,342.896f , -14.113f, 409.804f); - m_pInstance->SetData(TYPE_LEVIATHAN, SPECIAL); - } - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -491,59 +287,57 @@ struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI // this part should be done in other way // tower of freya - if(isFreyasTower && m_uiFreyaWardTimer) + if(isFreyasTower) { + DoCast(m_creature, SPELL_TOWER_OF_LIFE); + if(m_uiFreyaWardTimer < uiDiff) { - StartFreyaEvent(); - m_uiFreyaWardTimer = 0; + DoCast(m_creature, SPELL_FREYAS_WARD); + m_uiFreyaWardTimer = 40000 + urand(1000, 10000); } else m_uiFreyaWardTimer -= uiDiff; } // tower of mimiron - if(isMimironsTower && m_uiMimironInfernoTimer) + if(isMimironsTower) { + DoCast(m_creature, SPELL_TOWER_OF_FLAMES); + if(m_uiMimironInfernoTimer < uiDiff) { - if (Creature* pMimironBeacon = m_creature->SummonCreature(MOB_MIMIRON_BEACON, WayMimironBeacon[0][0], WayMimironBeacon[0][1], WayMimironBeacon[0][2],0, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - DoCast(pMimironBeacon, AURA_DUMMY_YELLOW, true); - m_uiMimironInfernoTimer = 0; - } - } + DoCast(m_creature, SPELL_FREYAS_WARD); + m_uiMimironInfernoTimer = 40000 + urand(1000, 10000); + } else m_uiMimironInfernoTimer -= uiDiff; } // tower of hodir - if(isHodirsTower && m_uiHodirFuryTimer) + if(isHodirsTower) { + m_creature->SetHealth(m_creature->GetHealth() + 0.1* m_creature->GetHealth()); + if(m_uiHodirFuryTimer < uiDiff) { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pHodir = DoSpawnCreature(MOB_HODIR_BEACON, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) - DoCast(pHodir, AURA_DUMMY_BLUE, true); - } - m_uiHodirFuryTimer = 0; + DoCast(m_creature, SPELL_HODIR_FURY); + m_uiHodirFuryTimer = 40000 + urand(1000, 10000); } else m_uiHodirFuryTimer -= uiDiff; } // tower of thorim - if(isThorimsTower && m_uiThorimHammerTimer) + if(isThorimsTower) { + DoCast(m_creature, SPELL_TOWER_OF_STORMS); + if(m_uiThorimHammerTimer < uiDiff) { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pThorim = DoSpawnCreature(MOB_THORIM_BEACON, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) - DoCast(pThorim, AURA_DUMMY_BLUE, true); - } - m_uiThorimHammerTimer = 0; + DoCast(m_creature, SPELL_THORIMS_HAMMER); + m_uiThorimHammerTimer = 40000 + urand(1000, 10000); } else m_uiThorimHammerTimer -= uiDiff; } + DoMeleeAttackIfReady(); } }; @@ -578,286 +372,6 @@ struct MANGOS_DLL_DECL mob_defense_turretAI : public ScriptedAI } }; -struct MANGOS_DLL_DECL mob_pool_of_tarAI : public ScriptedAI -{ - mob_pool_of_tarAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} - - void Reset() - { - DoCast(m_creature, SPELL_TAR_PASSIV, true); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - SetCombatMovement(false); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if(spell->SchoolMask & SPELL_SCHOOL_MASK_FIRE && !m_creature->HasAura(SPELL_BLAZE)) - DoCast(m_creature,SPELL_BLAZE,true); - } - void DamageTaken(Unit * killer, uint32 &uidamage) - { - uidamage = 0; - } -}; - -struct MANGOS_DLL_DECL mob_mechanoliftAI : public ScriptedAI -{ - mob_mechanoliftAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} - - void Reset() - { - } - - void JustDied(Unit* pKiller) - { - if (Creature* pLiquid = DoSpawnCreature(MOB_LIQUID,0,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 30000)) - { - pLiquid->CastSpell(pLiquid, SPELL_LIQUID_PYRITE, true); - } - - } -}; - -struct MANGOS_DLL_DECL mob_freyas_wardAI : public ScriptedAI -{ - mob_freyas_wardAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - Reset(); - } - - instance_ulduar* m_pInstance; - - uint32 summonTimer ; - - void Reset() - { - summonTimer = 5000 ; - } - - void UpdateAI(const uint32 uiDiff) - { - if(summonTimer <= uiDiff) - { - DoCast(m_creature,SPELL_FREYA_WARD, true); - summonTimer = 20000; - } - else - summonTimer -= uiDiff ; - - if (!m_creature->HasAura(AURA_DUMMY_GREEN, EFFECT_INDEX_1)) - DoCast(m_creature, AURA_DUMMY_GREEN,true); - - if (m_pInstance->GetData(TYPE_LEVIATHAN) != IN_PROGRESS) - { - m_creature->ForcedDespawn(); - } - } -}; - -struct MANGOS_DLL_DECL mob_hodirs_furyAI : public ScriptedAI -{ - mob_hodirs_furyAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - Reset(); - } - - instance_ulduar* m_pInstance; - - uint32 m_uiHodirFuryTimer; - uint32 m_uiSwitchTargetTimer; //hack for RandomMovement - - bool m_bHodirFuryReady; - - void Reset() - { - m_uiHodirFuryTimer = 0; - m_bHodirFuryReady = true; - - m_uiSwitchTargetTimer = 30000; - } - - void MoveInLineOfSight(Unit* who) - { - if (who->GetTypeId() == TYPEID_PLAYER && m_creature->IsInRange(who,0,5,false) && m_bHodirFuryReady) - { - if (Creature* pTrigger = DoSpawnCreature(NPC_HODIR_TARGET_BEACON, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 1000)) - pTrigger->CastSpell(who, SPELL_HODIR_FURY, true); - m_uiHodirFuryTimer = 4000; - m_bHodirFuryReady = false; - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->HasAura(AURA_DUMMY_BLUE, EFFECT_INDEX_1)) - DoCast(m_creature, AURA_DUMMY_BLUE,true); - if (m_pInstance->GetData(TYPE_LEVIATHAN) != IN_PROGRESS) - { - m_creature->ForcedDespawn(); - } - - if (!m_bHodirFuryReady) - { - if(m_uiHodirFuryTimer <= uiDiff) - { - m_bHodirFuryReady = true; - } - else - m_uiHodirFuryTimer -= uiDiff; - } - - - if(m_uiSwitchTargetTimer <= uiDiff) - { - SwitchTarget(); - } - else - m_uiSwitchTargetTimer -= uiDiff; - } - - void SwitchTarget() - { - if (m_pInstance) - { - if (Player* target = m_pInstance->GetPlayerInMap(true, true)) - m_creature->GetMotionMaster()->MoveChase(target); - } - } -}; - -struct MANGOS_DLL_DECL mob_mimirons_infernoAI : public ScriptedAI -{ - mob_mimirons_infernoAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - Reset(); - } - - instance_ulduar* m_pInstance; - uint32 infernoTimer; - uint32 m_uiWalkTimer; - uint8 waypointId; - - void Reset() - { - waypointId = 0; - m_uiWalkTimer = 200; - infernoTimer = 4000; - m_creature->GetMotionMaster()->MovePoint(waypointId,WayMimironBeacon[waypointId][0],WayMimironBeacon[waypointId][1],WayMimironBeacon[waypointId][2]); - } - - void MovementInform(uint32 type, uint32 id) - { - ++waypointId; - m_uiWalkTimer = 200; - if (waypointId > 3) - waypointId = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - if (m_uiWalkTimer) - { - if (m_uiWalkTimer <= uiDiff) - { - m_creature->GetMotionMaster()->MovePoint(waypointId,WayMimironBeacon[waypointId][0],WayMimironBeacon[waypointId][1],WayMimironBeacon[waypointId][2]); - m_uiWalkTimer = 0; - }else m_uiWalkTimer -= uiDiff; - } - - if(infernoTimer <= uiDiff) - { - if (Creature* pTrigger = DoSpawnCreature(NPC_MIMIRON_TARGET_BEACON, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) - { - pTrigger->CastSpell(pTrigger, SPELL_MIMIRON_INFERNO, true); - infernoTimer = 4000; - } - } - else - infernoTimer -= uiDiff; - - if (!m_creature->HasAura(AURA_DUMMY_YELLOW, EFFECT_INDEX_1)) - DoCast(m_creature, AURA_DUMMY_YELLOW,true); - if (m_pInstance->GetData(TYPE_LEVIATHAN) != IN_PROGRESS) - { - m_creature->ForcedDespawn(); - } - } -}; - -struct MANGOS_DLL_DECL mob_thorims_hammerAI : public ScriptedAI -{ - mob_thorims_hammerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - Reset(); - } - - instance_ulduar* m_pInstance; - uint32 m_uiHammerTimer; - uint32 m_uiSwitchTargetTimer; //hack for RandomMovement - - bool m_bHammerReady; - - void Reset() - { - m_uiHammerTimer = 0; - m_bHammerReady = true; - - m_uiSwitchTargetTimer = 30000; - } - - void MoveInLineOfSight(Unit* who) - { - if (who->GetTypeId() == TYPEID_PLAYER && m_creature->IsInRange(who,0,10,false) && m_bHammerReady) - { - if (Creature* pTrigger = DoSpawnCreature(NPC_THORIM_TARGET_BEACON,0 ,0 ,0 ,0 , TEMPSUMMON_TIMED_DESPAWN, 1000)) - pTrigger->CastSpell(who, SPELL_THORIMS_HAMMER, true); - m_bHammerReady = false; - m_uiHammerTimer = 4000; - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_bHammerReady) - { - if(m_uiHammerTimer <= uiDiff) - { - m_bHammerReady = true; - } - else - m_uiHammerTimer -= uiDiff; - } - - if(m_uiSwitchTargetTimer <= uiDiff) - { - SwitchTarget(); - } - else - m_uiSwitchTargetTimer -= uiDiff; - - - if (!m_creature->HasAura(AURA_DUMMY_BLUE, EFFECT_INDEX_1)) - DoCast(m_creature, AURA_DUMMY_BLUE,true); - if (m_pInstance->GetData(TYPE_LEVIATHAN) != IN_PROGRESS) - { - m_creature->ForcedDespawn(); - } - } - - void SwitchTarget() - { - if (m_pInstance) - { - if (Player* target = m_pInstance->GetPlayerInMap(true, true)) - m_creature->GetMotionMaster()->MoveChase(target); - } - } -}; - CreatureAI* GetAI_mob_defense_turret(Creature* pCreature) { return new mob_defense_turretAI(pCreature); @@ -868,67 +382,6 @@ CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature) return new boss_flame_leviathan(pCreature); } -CreatureAI* GetAI_mob_pool_of_tar(Creature* pCreature) -{ - return new mob_pool_of_tarAI(pCreature); -} - -CreatureAI* GetAI_mob_mechanolift(Creature* pCreature) -{ - return new mob_mechanoliftAI(pCreature); -} - -CreatureAI* GetAI_mob_freyas_ward(Creature* pCreature) -{ - return new mob_freyas_wardAI(pCreature); -} - -CreatureAI* GetAI_mob_hodirs_fury(Creature* pCreature) -{ - return new mob_hodirs_furyAI(pCreature); -} - -CreatureAI* GetAI_mob_mimirons_inferno(Creature* pCreature) -{ - return new mob_mimirons_infernoAI(pCreature); -} - -CreatureAI* GetAI_mob_thorims_hammer(Creature* pCreature) -{ - return new mob_thorims_hammerAI(pCreature); -} - -bool GossipHello_mob_lorekeeper(Player *player, Creature *pCreature) -{ - player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, "Gib mir Macht mit einen Zerstrer." , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, "Gib mir Strke mit einer Belagerungsmaschine." , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->ADD_GOSSIP_ITEM( GOSSIP_ICON_CHAT, "Gib mir Geschwindigkeit mit einen Moped." , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetObjectGuid()); - return true; -} - -bool GossipSelect_mob_lorekeeper(Player *pPlayer, Creature *pCreature, uint32 sender, uint32 uiAction ) -{ - uint32 i = urand(0,4); - if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->SummonCreature(VEHICLE_DEMOLISHER, PosSiege[i].x, PosSiege[i].y, PosSiege[i].z, PosSiege[i].o, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF + 2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->SummonCreature(VEHICLE_SIEGE, PosDemolisher[i].x, PosDemolisher[i].y, PosDemolisher[i].z, PosDemolisher[i].o, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF + 3) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->SummonCreature(VEHICLE_CHOPPER, PosChopper[i].x, PosChopper[i].y, PosChopper[i].z, PosChopper[i].o, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); - - } - return true; -} - void AddSC_boss_leviathan() { Script *newscript; @@ -941,40 +394,4 @@ void AddSC_boss_leviathan() newscript->Name = "mob_defense_turret"; newscript->GetAI = &GetAI_mob_defense_turret; newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_pool_of_tar"; - newscript->GetAI = &GetAI_mob_pool_of_tar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_mechanolift"; - newscript->GetAI = &GetAI_mob_mechanolift; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_freyas_ward"; - newscript->GetAI = &GetAI_mob_freyas_ward; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hodirs_fury"; - newscript->GetAI = &GetAI_mob_hodirs_fury; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_mimiron_inferno"; - newscript->GetAI = &GetAI_mob_mimirons_inferno; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_thorims_hammer"; - newscript->GetAI = &GetAI_mob_thorims_hammer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lorekeeper"; - newscript->pGossipHello = &GossipHello_mob_lorekeeper; - newscript->pGossipSelect = &GossipSelect_mob_lorekeeper; - newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_freya.cpp b/scripts/northrend/ulduar/ulduar/boss_freya.cpp index 6bb1c4983b..7381e34d1e 100644 --- a/scripts/northrend/ulduar/ulduar/boss_freya.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_freya.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2011 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -17,7 +17,7 @@ /* ScriptData SDName: boss_freya SD%Complete: -SDComment: Achiements: Con-speed-atory, Deforestation +SDComment: aura stacking need core support after the recent aura changes SDCategory: Ulduar EndScriptData */ @@ -28,19 +28,19 @@ enum { /* YELLS */ // freya - SAY_AGGRO = -1603140, - SAY_AGGRO_HARD = -1603141, - SAY_ADDS_CONSERVATOR = -1603142, - SAY_ADDS_TRIO = -1603143, - SAY_ADDS_LASHER = -1603144, - SAY_SLAY1 = -1603145, - SAY_SLAY2 = -1603146, - SAY_DEATH = -1603147, - SAY_BERSERK = -1603148, - EMOTE_ALLIES_NATURE = -1603150, - EMOTE_LIFEBINDERS_GIFT = -1603151, - EMOTE_GROUND_TREMMOR = -1603152, - EMOTE_IRON_ROOTS = -1603153, + SAY_AGGRO = -1603000, + SAY_AGGRO_HARD = -1603001, + SAY_SUMMON1 = -1603002, + SAY_SUMMON2 = -1603003, + SAY_SUMMON3 = -1603004, + SAY_SLAY1 = -1603005, + SAY_SLAY2 = -1603006, + SAY_DEATH = -1603007, + SAY_BERSERK = -1603008, + EMOTE_ALLIES_NATURE = -1603362, + EMOTE_LIFEBINDERS_GIFT = -1603363, + EMOTE_GROUND_TREMMOR = -1603364, + EMOTE_IRON_ROOTS = -1603365, //brightleaf SAY_BRIGHTLEAF_AGGRO = -1603160, SAY_BRIGHTLEAF_SLAY1 = -1603161, @@ -57,58 +57,46 @@ enum SAY_STONEBARK_SLAY2 = -1603182, SAY_STONEBARK_DEATH = -1603183, - SPELL_FREYA_CREDIT = 65074, - /* BOSS SPELLS */ - SPELL_ATTUNED_TO_NATURE = 62519, //increases healing, start at 150 stacks - SPELL_ATTUNED_10_STACKS = 62525, - SPELL_ATTUNED_2_STACKS = 62524, - SPELL_ATTUNED_25_STACKS = 62521, - SPELL_TOUCH_OF_EONAR = 62528, //heals Freya, 6k per second - SPELL_TOUCH_OF_EONAR_H = 62892, //heals Freya, 24k per second - SPELL_SUNBEAM = 62623, - SPELL_SUNBEAM_H = 62872, - SPELL_BERSERK = 47008, // 10 min - SPELL_NATURE_BOMB = 64604, // 5 Targets (Core) + SPELL_ATTUNED_TO_NATURE = 62519, //increases healing, start at 150 stacks + SPELL_ATTUNED_10_STACKS = 62525, + SPELL_ATTUNED_2_STACKS = 62524, + SPELL_ATTUNED_25_STACKS = 62521, + SPELL_TOUCH_OF_EONAR = 62528, //heals Freya, 6k per second + SPELL_TOUCH_OF_EONAR_H = 62892, //heals Freya, 24k per second + SPELL_SUNBEAM = 62623, + SPELL_SUNBEAM_H = 62872, + SPELL_BERSERK = 47008, // 10 min /* HARD MODE SPELLS */ - SPELL_DRAINED_OF_POWER = 62467, + SPELL_DRAINED_OF_POWER = 62467, // brightleaf - SPELL_BRIGHTLEAF_ESSENCE_CHANNEL = 62485, - SPELL_BRIGHTLEAF_ESSENCE_CHANNEL_H = 65587, - - SPELL_UNSTABLE_ENERGY_FREYA = 62451, - SPELL_UNSTABLE_ENERGY_FREYA_H = 62865, - + SPELL_UNSTABLE_ENERGY_FREYA = 62451, + SPELL_UNSTABLE_ENERGY_FREYA_H = 62865, + SPELL_BRIGHTLEAFS_ESSENCE = 62968, //62385, + SPELL_EFFECT_BRIGHTLEAF = 63294, // ironbrach - SPELL_IRONBRANCH_ESSENCE_CHANNEL = 62484, - SPELL_IRONBRANCH_ESSENCE_CHANNEL_H = 65588, - - SPELL_STRENGHTEN_IRON_ROOTS = 63601, - NPC_STRENGHENED_IRON_ROOTS = 33168, - SPELL_IRON_ROOTS_FREYA = 62438, - SPELL_IRON_ROOTS_FREYA_H = 62861, - + SPELL_STRENGHTEN_IRON_ROOTS = 63601, + NPC_STRENGHENED_IRON_ROOTS = 33168, + SPELL_IRON_ROOTS_FREYA = 62438, + SPELL_IRON_ROOTS_FREYA_H = 62861, + SPELL_IRONBRANCH_ESSENCE = 62713, //62387, + SPELL_EFFECT_IRONBRANCH = 63292, // stonebark - SPELL_STONEBARK_ESSEMCE_CHANNEL = 62483, - SPELL_STONEBARK_ESSEMCE_CHANNEL_H = 65589, - - - SPELL_GROUND_TREMOR_FREYA = 62437, - SPELL_GROUND_TREMOR_FREYA_H = 62859, - SPELL_STONEBARKS_ESSENCE = 65590, - SPELL_STONEBARKS_ESSENCE_H = 62386, - SPELL_EFFECT_STONEBARK = 63295, + SPELL_GROUND_TREMOR_FREYA = 62437, + SPELL_GROUND_TREMOR_FREYA_H = 62859, + SPELL_STONEBARKS_ESSENCE = 65590, //62386, + SPELL_EFFECT_STONEBARK = 63295, - NPC_SUN_BEAM = 33170, - NPC_UNSTABLE_SUN_BEAM = 33050, + NPC_SUN_BEAM = 33170, + NPC_UNSTABLE_SUN_BEAM = 33050, // sanctuary adds - NPC_EONARS_GIFT = 33228, - SPELL_LIFEBINDERS_GIFT = 62584, // after 12 secs, heals Freya & her allies for 30% - SPELL_LIFEBINDERS_GIFT_H = 64185, // the same but for 60% - SPELL_PHEROMONES = 62619, // protects from conservators grip - NPC_HEALTHY_SPORE = 33215, + NPC_EONARS_GIFT = 33228, + SPELL_LIFEBINDERS_GIFT = 62584, // after 12 secs, heals Freya & her allies for 30% + SPELL_LIFEBINDERS_GIFT_H = 64185, // the same but for 60% + SPELL_PHEROMONES = 62619, // protects from conservators grip + NPC_HEALTHY_SPORE = 33215, /* ADDS */ // 6 waves of adds. 1 of the 3 each min @@ -139,15 +127,14 @@ enum NPC_SNAPLASHER = 32916, // spells - SPELL_HARDENED_BARK = 62664, - SPELL_HARDENED_BARK_H = 64191, + SPELL_HARDENED_BARK = 62663, + SPELL_HARDENED_BARK_H = 64190, // nature bomb - SPELL_SUMMON_GO_NATURE_BOMB = 64600, NPC_NATURE_BOMB = 34129, GO_NATURE_BOMB = 194902, - SPELL_NATURE_BOMB_EX = 64587, - SPELL_NATURE_BOMB_EX_H = 64650, + SPELL_NATURE_BOMB = 64587, + SPELL_NATURE_BOMB_H = 64650, /* ELDERS */ // used in phase 1 ELDER_BRIGHTLEAF = 32915, @@ -158,9 +145,8 @@ enum SPELL_BRIGHTLEAF_FLUX = 62262, SPELL_SOLAR_FLARE = 62240, SPELL_SOLAR_FLARE_H = 62920, - SPELL_UNSTABLE_SUN_BEAM = 62221, - SPELL_UNSTABLE_SUN_BEAM_A = 62211, - SPELL_UNSTABLE_SUN_BEAM_BUFF= 62243, + SPELL_UNSTABLE_SUN_BEAM = 62211, + SPELL_UNSTABLE_SUN_BEAM_A = 62243, SPELL_UNSTABLE_ENERGY = 62217, // cancels sun bean SPELL_UNSTABLE_ENERGY_H = 62922, SPELL_PHOTOSYNTHESIS = 62209, @@ -171,8 +157,8 @@ enum SPELL_IRON_ROOTS = 62283, SPELL_IRON_ROOTS_H = 62930, NPC_IRON_ROOTS = 33088, - SPELL_THORN_SWARM = 62285, - SPELL_THORN_SWARM_H = 62931, + SPELL_THORM_SWARM = 62285, + SPELL_THORM_SWARM_H = 62931, // stonebark spells SPELL_FIST_OF_STONE = 62344, @@ -192,11 +178,12 @@ enum SPELL_SUMMON_CHEST_7 = 62957, SPELL_SUMMON_CHEST_8 = 62958, - SPELL_SUMMON_ALLIES_OF_NATURE = 62678, // better do that in sd2 + SPELL_SUMMON_ALLIES_OF_NATURE = 62678, //better do that in sd2 SPELL_SUMMON_LASHERS = 62688, // lashers - broken - SPELL_SUMMON_ELEMENTALS = 62686, // elementals -> better in spell + SPELL_SUMMON_ELEMENTALS = 62686, // elementals -> better in sd2 SPELL_SUMMON_CONSERVATOR = 62685, // conservator - SPELL_LIFEBINDERS_GIFT_SUMMON = 62572, // with missle + SPELL_LIFEBINDERS_GIFT_SUMMON = 62869, + SPELL_NATURE_BOMB_SUMMON = 64606, SPELL_SPORE_SUMMON_NE = 62591, SPELL_SPORE_SUMMON_SE = 62592, @@ -204,11 +191,23 @@ enum SPELL_SPORE_SUMMON_NW = 62582, SPELL_HEALTHY_SPORE_VISUAL = 62538, + SPELL_NATURE_BOMB_VISUAL = 64604, SPELL_LIFEBINDERS_VISUAL = 62579, - SPELL_GROW = 44833, + SPELL_LIFEBINDER_GROW = 44833, SPELL_PHEROMONES_LG = 62619, SPELL_POTENT_PHEROMONES = 62541, + + SPELL_FREYA_CREDIT = 65074, + + ACHIEV_BACK_TO_NATURE = 2982, + ACHIEV_BACK_TO_NATURE_H = 2983, + ACHIEV_KNOCK_WOOD = 3177, + ACHIEV_KNOCK_WOOD_H = 3185, + ACHIEV_KNOCK_KNOCK_WOOD = 3178, + ACHIEV_KNOCK_KNOCK_WOOD_H = 3186, + ACHIEV_KNOCK_KNOCK_KNOCK_WOOD = 3179, + ACHIEV_KNOCK_KNOCK_KNOCK_WOOD_H = 3187, }; // Iron roots & stranghned iron roots @@ -216,47 +215,83 @@ struct MANGOS_DLL_DECL mob_iron_rootsAI : public ScriptedAI { mob_iron_rootsAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - m_uiCreatureEntry = m_creature->GetEntry(); - m_creature->setFaction(16); SetCombatMovement(false); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; + ObjectGuid m_uiVictimGUID; uint32 m_uiCreatureEntry; - void Reset(){} + void Reset() + { + m_uiVictimGUID.Clear(); + m_uiCreatureEntry = m_creature->GetEntry(); + } - void KilledUnit(Unit* pVictim) + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) { - m_creature->ForcedDespawn(500); + if (uiDamage > m_creature->GetHealth()) + { + if (m_uiVictimGUID) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiVictimGUID)) + { + switch(m_uiCreatureEntry) + { + case NPC_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + break; + case NPC_STRENGHENED_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + break; + } + } + } + } } - void JustDied(Unit *pKiller) + void KilledUnit(Unit* pVictim) { - if (!m_pInstance) - return; + if (pVictim) + { + switch(m_uiCreatureEntry) + { + case NPC_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + break; + case NPC_STRENGHENED_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + break; + } + } + } - if (Unit* pVictim = m_pInstance->instance->GetUnit(m_creature->GetCreatorGuid())) + void JustDied(Unit* Killer) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiVictimGUID)) { switch(m_uiCreatureEntry) { - case NPC_IRON_ROOTS: - pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); - break; - case NPC_STRENGHENED_IRON_ROOTS: - pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); - break; + case NPC_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + break; + case NPC_STRENGHENED_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + break; } } - m_creature->ForcedDespawn(500); } - void UpdateAI(const uint32 uiuiDiff){} + void UpdateAI(const uint32 uiuiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + } }; // Elder Brightleaf @@ -264,18 +299,19 @@ struct MANGOS_DLL_DECL boss_elder_brightleafAI : public ScriptedAI { boss_elder_brightleafAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiBrightleafFluxTimer; uint32 m_uiSolarFlareTimer; uint32 m_uiUnstableSunBeanTimer; uint32 m_uiUnstabelEnergyTimer; + uint32 m_uiSunbeamStacks; uint32 m_uiHealTimer; bool m_bHasSunbeam; @@ -285,6 +321,7 @@ struct MANGOS_DLL_DECL boss_elder_brightleafAI : public ScriptedAI m_uiSolarFlareTimer = 10000 + urand(1000, 5000); m_uiUnstableSunBeanTimer = 15000; m_uiUnstabelEnergyTimer = 30000; + m_uiSunbeamStacks = 1; m_bHasSunbeam = false; } @@ -295,7 +332,10 @@ struct MANGOS_DLL_DECL boss_elder_brightleafAI : public ScriptedAI void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_BRIGHTLEAF_SLAY1 : SAY_BRIGHTLEAF_SLAY2, m_creature); + if (irand(0,1)) + DoScriptText(SAY_BRIGHTLEAF_SLAY1, m_creature); + else + DoScriptText(SAY_BRIGHTLEAF_SLAY2, m_creature); } void JustDied(Unit *killer) @@ -308,32 +348,51 @@ struct MANGOS_DLL_DECL boss_elder_brightleafAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if(m_uiBrightleafFluxTimer < uiDiff) + // this needs core suport + if (m_uiBrightleafFluxTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_BRIGHTLEAF_FLUX) == CAST_OK) - m_uiBrightleafFluxTimer = 5000; + DoCast(m_creature, SPELL_BRIGHTLEAF_FLUX); + m_uiBrightleafFluxTimer = 5000; } - else - m_uiBrightleafFluxTimer -= uiDiff; + else m_uiBrightleafFluxTimer -= uiDiff; - if(m_uiSolarFlareTimer < uiDiff) + if (m_uiSolarFlareTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SOLAR_FLARE : SPELL_SOLAR_FLARE_H) == CAST_OK) - m_uiSolarFlareTimer = 10000 + urand(1000, 5000); - } + DoCast(pTarget, m_bIsRegularMode ? SPELL_SOLAR_FLARE : SPELL_SOLAR_FLARE_H); + m_uiSolarFlareTimer = 10000 + urand(1000, 5000); } - else - m_uiSolarFlareTimer -= uiDiff; + else m_uiSolarFlareTimer -= uiDiff; - if(m_uiUnstableSunBeanTimer < uiDiff) + // also the following spells need some core support -> hacky way of use + // PLEASE FIX FOR REVISION! + if (m_uiUnstableSunBeanTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_UNSTABLE_SUN_BEAM) == CAST_OK) - m_uiUnstableSunBeanTimer = urand(7000, 12000); + DoCast(m_creature, SPELL_UNSTABLE_SUN_BEAM); + m_bHasSunbeam = true; + m_uiHealTimer = 1000; + m_uiUnstableSunBeanTimer = urand(7000, 12000); } - else - m_uiUnstableSunBeanTimer -= uiDiff; + else m_uiUnstableSunBeanTimer -= uiDiff; + + // cast after the unstable sun bean + if (m_uiHealTimer < uiDiff && m_bHasSunbeam) + { + DoCast(m_creature, SPELL_PHOTOSYNTHESIS); + m_bHasSunbeam = false; + } + else m_uiHealTimer -= uiDiff; + + // removes photosynthesis when standing inside + if (m_uiUnstabelEnergyTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY: SPELL_UNSTABLE_ENERGY_H); + m_creature->RemoveAurasDueToSpell(SPELL_UNSTABLE_SUN_BEAM_A); + m_creature->RemoveAurasDueToSpell(SPELL_PHOTOSYNTHESIS); + m_uiSunbeamStacks = 1; + m_uiUnstabelEnergyTimer = urand(20000, 30000); + } + else m_uiUnstabelEnergyTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -349,13 +408,13 @@ struct MANGOS_DLL_DECL boss_elder_ironbranchAI : public ScriptedAI { boss_elder_ironbranchAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiImpaleTimer; uint32 m_uiIronrootsTimer; @@ -380,7 +439,10 @@ struct MANGOS_DLL_DECL boss_elder_ironbranchAI : public ScriptedAI void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_IRONBRANCH_SLAY1 : SAY_IRONBRANCH_SLAY2, m_creature); + if (irand(0,1)) + DoScriptText(SAY_IRONBRANCH_SLAY1, m_creature); + else + DoScriptText(SAY_IRONBRANCH_SLAY2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -388,33 +450,29 @@ struct MANGOS_DLL_DECL boss_elder_ironbranchAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if(m_uiImpaleTimer < uiDiff) + if (m_uiImpaleTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H) == CAST_OK) - m_uiImpaleTimer = 10000 + urand (1000, 5000); - } + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H); + m_uiImpaleTimer = 10000 + urand (1000, 5000); } - else - m_uiImpaleTimer -= uiDiff; + else m_uiImpaleTimer -= uiDiff; - if(m_uiIronrootsTimer < uiDiff) + if (m_uiIronrootsTimer < uiDiff) { - if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - target->CastSpell(target, m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H, true); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(target, m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); m_uiIronrootsTimer = 20000 + urand (1000, 7000); } - else - m_uiIronrootsTimer -= uiDiff; + else m_uiIronrootsTimer -= uiDiff; - if(m_uiThornSwarmTimer < uiDiff) + if (m_uiThornSwarmTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_THORN_SWARM : SPELL_THORN_SWARM_H) == CAST_OK) - m_uiThornSwarmTimer = 30000; + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(target, m_bIsRegularMode ? SPELL_THORM_SWARM : SPELL_THORM_SWARM_H); + m_uiThornSwarmTimer = 30000; } - else - m_uiThornSwarmTimer -= uiDiff; + else m_uiThornSwarmTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -430,13 +488,13 @@ struct MANGOS_DLL_DECL boss_elder_stonebarkAI : public ScriptedAI { boss_elder_stonebarkAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiFistsOfStoneTimer; uint32 m_uiGroundTremorTimer; @@ -450,7 +508,7 @@ struct MANGOS_DLL_DECL boss_elder_stonebarkAI : public ScriptedAI } void Aggro(Unit* pWho) - { + { DoScriptText(SAY_STONEBARK_AGGRO, m_creature); } @@ -461,7 +519,10 @@ struct MANGOS_DLL_DECL boss_elder_stonebarkAI : public ScriptedAI void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_STONEBARK_SLAY1 : SAY_STONEBARK_SLAY2, m_creature); + if (irand(0,1)) + DoScriptText(SAY_STONEBARK_SLAY1, m_creature); + else + DoScriptText(SAY_STONEBARK_SLAY2, m_creature); } void UpdateAI(const uint32 uiDiff) @@ -469,29 +530,26 @@ struct MANGOS_DLL_DECL boss_elder_stonebarkAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if(m_uiFistsOfStoneTimer < uiDiff) + if (m_uiFistsOfStoneTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_FIST_OF_STONE) == CAST_OK) - m_uiFistsOfStoneTimer = 30000; + DoCast(m_creature, SPELL_FIST_OF_STONE); + m_uiFistsOfStoneTimer = 30000; } - else - m_uiFistsOfStoneTimer -= uiDiff; + else m_uiFistsOfStoneTimer -= uiDiff; - if(m_uiGroundTremorTimer < uiDiff) + if (m_uiGroundTremorTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_GROUND_TREMOR : SPELL_GROUND_TREMOR_H) == CAST_OK) - m_uiGroundTremorTimer = 15000 + urand (1000, 5000); + DoCast(m_creature, m_bIsRegularMode ? SPELL_GROUND_TREMOR : SPELL_GROUND_TREMOR_H); + m_uiGroundTremorTimer = 15000 + urand (1000, 5000); } - else - m_uiGroundTremorTimer -= uiDiff; + else m_uiGroundTremorTimer -= uiDiff; - if(m_uiPetrifiedBarkTimer < uiDiff) + if (m_uiPetrifiedBarkTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_PETRIFIED_BARK : SPELL_PETRIFIED_BARK_H) == CAST_OK) - m_uiPetrifiedBarkTimer = 20000 + urand (1000, 5000); + DoCast(m_creature, m_bIsRegularMode ? SPELL_PETRIFIED_BARK : SPELL_PETRIFIED_BARK_H); + m_uiPetrifiedBarkTimer = 20000 + urand (1000, 5000); } - else - m_uiPetrifiedBarkTimer -= uiDiff; + else m_uiPetrifiedBarkTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -507,12 +565,12 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI { boss_freyaAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiSummonTimer; @@ -522,7 +580,13 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI uint32 m_uiSunbeamTimer; uint32 m_uiEnrageTimer; + //timers for the elemental wave + uint32 m_uiWaterSpiritTimer; + uint32 m_uiStormLasherTimer; + uint32 m_uiSnapLasherTimer; + bool m_bIsHardMode; + bool m_bHasAura; uint32 m_uiNatureBombTimer; uint32 m_uiLifebindersGiftTimer; @@ -536,6 +600,7 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI uint32 m_uiStrenghtenIronRootsTimer; uint32 m_uiGroundTremorTimer; + uint32 m_uiThreeWaveCheckTimer; uint32 m_uiThreeWaveRespawnTimer; bool m_bThreeWaveCheckTimerStarted; @@ -549,6 +614,7 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI bool m_bIsStonebarkAlive; uint32 m_uiAchievProgress; + bool m_bNature; void Reset() { @@ -563,19 +629,26 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI m_uiUnstableEnergyTimer = 25000; m_uiStrenghtenIronRootsTimer = 25000 + urand(1000, 5000); m_uiGroundTremorTimer = 20000; - m_uiNatureBombTimer = 7000; + m_uiNatureBombTimer = 45000; + m_uiAchievProgress = 10000; + m_uiThreeWaveCheckTimer = 1000; m_bWaveCheck = false; m_bThreeWaveCheckTimerStarted = false; m_uiThreeWaveRespawnTimer = 12000; + m_uiWaterSpiritGUID.Clear(); + m_uiStormLasherGUID.Clear(); + m_uiSnapLasherGUID.Clear(); m_uiOutroTimer = 10000; m_uiStep = 1; m_bIsOutro = false; m_uiAchievProgress = 0; + m_bNature = false; + m_bHasAura = false; - if(m_pInstance) + if (m_pInstance) { // remove elder auras if (Creature* pBrightleaf = m_pInstance->GetSingleCreatureFromStorage(NPC_BRIGHTLEAF)) @@ -598,9 +671,10 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI void Aggro(Unit *who) { - DoCast(m_creature, SPELL_ATTUNED_TO_NATURE, true); - DoCast(m_creature, m_bIsRegularMode ? SPELL_TOUCH_OF_EONAR : SPELL_TOUCH_OF_EONAR_H, true); - if(m_pInstance) + // aura should stack up to 150 when casted, need core support + DoCast(m_creature, SPELL_ATTUNED_TO_NATURE); + + if (m_pInstance) { m_pInstance->SetData(TYPE_FREYA, IN_PROGRESS); @@ -609,10 +683,10 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI { if (pBrightleaf->isAlive()) { - pBrightleaf->CastSpell(pBrightleaf, SPELL_DRAINED_OF_POWER, true); - pBrightleaf->CastSpell(m_creature, m_bIsRegularMode ? SPELL_BRIGHTLEAF_ESSENCE_CHANNEL : SPELL_BRIGHTLEAF_ESSENCE_CHANNEL_H, true); + pBrightleaf->CastSpell(pBrightleaf, SPELL_DRAINED_OF_POWER, false); + pBrightleaf->CastSpell(m_creature, SPELL_EFFECT_BRIGHTLEAF, false); m_bIsBrightleafAlive = true; - m_uiAchievProgress++; + m_uiAchievProgress += 1; } else m_bIsBrightleafAlive = false; @@ -623,10 +697,10 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI { if (pIronbranch->isAlive()) { - pIronbranch->CastSpell(pIronbranch, SPELL_DRAINED_OF_POWER, true); - pIronbranch->CastSpell(m_creature, m_bIsRegularMode ? SPELL_IRONBRANCH_ESSENCE_CHANNEL : SPELL_IRONBRANCH_ESSENCE_CHANNEL_H, true); + pIronbranch->CastSpell(pIronbranch, SPELL_DRAINED_OF_POWER, false); + pIronbranch->CastSpell(m_creature, SPELL_EFFECT_IRONBRANCH, false); m_bIsIronbranchAlive = true; - m_uiAchievProgress++; + m_uiAchievProgress += 1; } else m_bIsIronbranchAlive = false; @@ -637,10 +711,10 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI { if (pStonebark->isAlive()) { - pStonebark->CastSpell(pStonebark, SPELL_DRAINED_OF_POWER, true); - pStonebark->CastSpell(m_creature, m_bIsRegularMode ? SPELL_STONEBARK_ESSEMCE_CHANNEL : SPELL_STONEBARK_ESSEMCE_CHANNEL_H, true); + pStonebark->CastSpell(pStonebark, SPELL_DRAINED_OF_POWER, false); + pStonebark->CastSpell(m_creature, SPELL_EFFECT_STONEBARK, false); m_bIsStonebarkAlive = true; - m_uiAchievProgress++; + m_uiAchievProgress += 1; } else m_bIsStonebarkAlive = false; @@ -649,7 +723,7 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI m_bIsHardMode = CheckHardMode(); - if(!m_bIsHardMode) + if (!m_bIsHardMode) DoScriptText(SAY_AGGRO, m_creature); else DoScriptText(SAY_AGGRO_HARD, m_creature); @@ -658,88 +732,94 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI void JustReachedHome() { if (m_pInstance) - { m_pInstance->SetData(TYPE_FREYA, FAIL); - m_pInstance->SetData(TYPE_FREYA_HARD, FAIL); - } } void DoOutro() { - if(m_pInstance) + if (m_pInstance) { - switch(m_uiAchievProgress) + m_pInstance->SetData(TYPE_FREYA_HARD, 0); + + // hacky way to complete achievements; use only if you have this function + if(m_uiAchievProgress == 1) + { + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_KNOCK_WOOD : ACHIEV_KNOCK_WOOD_H); + m_pInstance->SetData(TYPE_FREYA_HARD, 1); + } + else if (m_uiAchievProgress == 2) + { + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_KNOCK_KNOCK_WOOD : ACHIEV_KNOCK_KNOCK_WOOD_H); + m_pInstance->SetData(TYPE_FREYA_HARD, 2); + } + else if (m_uiAchievProgress == 3) { - case 3: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_KNOCK_KNOCK_WOOD, true); - m_pInstance->SetData(TYPE_FREYA_HARD, DONE); - case 2: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_KNOCK_WOOD, true); - case 1: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_WOOD, true); - break; + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_KNOCK_KNOCK_KNOCK_WOOD : ACHIEV_KNOCK_KNOCK_KNOCK_WOOD_H); + m_pInstance->SetData(TYPE_FREYA_HARD, 3); } + + if (m_bNature) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_BACK_TO_NATURE : ACHIEV_BACK_TO_NATURE_H); + m_pInstance->SetData(TYPE_FREYA, DONE); } - DoCast(m_creature, SPELL_FREYA_CREDIT, true); + + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + + pPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_FREYA_CREDIT); + } + m_creature->ForcedDespawn(); } // for debug only! void JustDied(Unit* pKiller) { - if(m_pInstance) + if (m_pInstance) { - switch(m_uiAchievProgress) - { - case 3: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_KNOCK_KNOCK_WOOD, true); - m_pInstance->SetData(TYPE_FREYA_HARD, DONE); - case 2: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_KNOCK_WOOD, true); - case 1: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_WOOD, true); - break; - } m_pInstance->SetData(TYPE_FREYA, DONE); + if (m_bIsHardMode) + m_pInstance->SetData(TYPE_FREYA_HARD, DONE); } - DoCast(m_creature, SPELL_FREYA_CREDIT, true); } void DamageTaken(Unit *done_by, uint32 &uiDamage) { - if(m_creature->GetHealth() < uiDamage || m_creature->GetHealthPercent() < 1.0f) + if (m_creature->GetHealthPercent() < 1.0f || m_bIsOutro) { uiDamage = 0; + m_creature->SetHealthPercent(1.0f); m_bIsOutro = true; } } void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_SLAY1 : SAY_SLAY2, m_creature); - } - - bool CheckHardMode() - { - if(m_bIsBrightleafAlive && m_bIsIronbranchAlive && m_bIsStonebarkAlive) - return true; - return false; + if (irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); } - // summon 10 Lashers. Should be done by a spell which needs core fix + // summon 12 Lashers. Should be done by a spell which needs core fix void SummonLashers() { + DoScriptText(SAY_SUMMON3, m_creature); int i; float x,y; - for(i = 0; i < 10; ++i) + for(i = 0; i < 12; ++i) { x = (rand_norm() * 30.0f) - 15.0f; y = (rand_norm() * 30.0f) - 15.0f; - if(Creature* pLasher = DoSpawnCreature(NPC_DETONATING_LASHER, x, y, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) + if (Creature* pLasher = DoSpawnCreature(NPC_DETONATING_LASHER, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000)) { - pLasher->setFaction(m_creature->getFaction()); - if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) pLasher->AddThreat(pTarget, 1.0f); } } @@ -748,12 +828,12 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI // summon conservator. Should be done by a spell which needs core fix void SummonConservator() { + DoScriptText(SAY_SUMMON1, m_creature); float x = (rand_norm() * 30.0f) - 15.0f; float y = (rand_norm() * 30.0f) - 15.0f; - if(Creature* pAdd = DoSpawnCreature(NPC_ANCIENT_CONSERVATOR, x, y, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) + if (Creature* pAdd = DoSpawnCreature(NPC_ANCIENT_CONSERVATOR, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000)) { - pAdd->setFaction(m_creature->getFaction()); - if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) pAdd->AddThreat(pTarget, 1.0f); } } @@ -761,6 +841,10 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI // summmon the 3 elementals. Should be done by a spell which needs core fix. void SummonElementals() { + DoScriptText(SAY_SUMMON2, m_creature); + m_bWaveCheck = true; + m_uiThreeWaveCheckTimer = 1000; + if(Creature* pSpirit = DoSpawnCreature(NPC_WATER_SPIRIT, 0, 0, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7*DAY*IN_MILLISECONDS)) { pSpirit->setFaction(m_creature->getFaction()); @@ -786,263 +870,293 @@ struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI } } - void initNextWave() + void SummonedCreatureJustDied(Creature* pSummoned) { - m_uiWaveType = (m_uiWaveType + m_uiWaveTypeInc) % 3; - ++m_uiWaveNumber; - m_uiSummonTimer = 60000; + switch(pSummoned->GetEntry()) + { + case NPC_WATER_SPIRIT: + case NPC_STORM_LASHER: + case NPC_SNAPLASHER: + break; + case NPC_ANCIENT_CONSERVATOR: + if (SpellAuraHolderPtr pNatureAura = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) + { + if (pNatureAura->ModStackAmount(-25)) + m_creature->RemoveAurasDueToSpell(SPELL_ATTUNED_TO_NATURE); + } + break; + case NPC_DETONATING_LASHER: + if (SpellAuraHolderPtr pNatureAura = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) + { + if (pNatureAura->ModStackAmount(-2)) + m_creature->RemoveAurasDueToSpell(SPELL_ATTUNED_TO_NATURE); + } + break; + default: + break; + } + } + + bool CheckHardMode() + { + if (m_bIsBrightleafAlive && m_bIsIronbranchAlive && m_bIsStonebarkAlive) + return true; + return false; } void UpdateAI(const uint32 uiDiff) { - if(!m_bIsOutro) + if (!m_bIsOutro) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // check if the 3 elementals die at the same time - if (m_bWaveCheck) + // hacky way of stacking aura. Please remove when fixed in core! + if (SpellAuraHolderPtr pNatureAura = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) { - if(m_uiThreeWaveCheckTimer < uiDiff) + if (!m_bHasAura && pNatureAura->GetStackAmount() < 150) { - Creature* pWaterSpirit = m_creature->GetMap()->GetCreature(m_uiWaterSpiritGUID); - Creature* pStormLasher = m_creature->GetMap()->GetCreature(m_uiStormLasherGUID); - Creature* pSnapLasher = m_creature->GetMap()->GetCreature(m_uiSnapLasherGUID); + m_bHasAura = true; + pNatureAura->SetStackAmount(150); + } + } - if(pWaterSpirit && pStormLasher && pSnapLasher) + if (!m_creature->HasAura(m_bIsRegularMode ? SPELL_TOUCH_OF_EONAR : SPELL_TOUCH_OF_EONAR_H)) + DoCast(m_creature, m_bIsRegularMode ? SPELL_TOUCH_OF_EONAR : SPELL_TOUCH_OF_EONAR_H); + + // check if the 3 elementals die at the same time + if(m_uiThreeWaveCheckTimer < uiDiff && m_bWaveCheck) + { + Creature* pWaterSpirit = m_pInstance->instance->GetCreature(m_uiWaterSpiritGUID); + Creature* pStormLasher = m_pInstance->instance->GetCreature(m_uiStormLasherGUID); + Creature* pSnapLasher = m_pInstance->instance->GetCreature(m_uiSnapLasherGUID); + + if(pWaterSpirit && pStormLasher && pSnapLasher) + { + // if all 3 are dead then mod stack amount + if(!pWaterSpirit->isAlive() && !pStormLasher->isAlive() && !pSnapLasher->isAlive()) { - if(!pWaterSpirit->isAlive() && !pStormLasher->isAlive() && !pSnapLasher->isAlive()) + m_bWaveCheck = false; + m_bThreeWaveCheckTimerStarted = false; + if(SpellAuraHolderPtr natureAura = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) { - m_bWaveCheck = false; - m_bThreeWaveCheckTimerStarted = false; - - m_creature->CastSpell(m_creature, SPELL_ATTUNED_10_STACKS, true); - m_creature->CastSpell(m_creature, SPELL_ATTUNED_10_STACKS, true); - m_creature->CastSpell(m_creature, SPELL_ATTUNED_10_STACKS, true); + if(natureAura->ModStackAmount(-30)) + m_creature->RemoveAurasDueToSpell(SPELL_ATTUNED_TO_NATURE); } - else if (!m_bThreeWaveCheckTimerStarted) + } + else if (!m_bThreeWaveCheckTimerStarted) + { + // if at least 1 is alive + if (!pWaterSpirit->isAlive() || !pSnapLasher->isAlive() || !pStormLasher->isAlive()) { - // if at least 1 is alive - if (!pWaterSpirit->isAlive() || !pSnapLasher->isAlive() || !pStormLasher->isAlive()) - { - m_bThreeWaveCheckTimerStarted = true; - m_uiThreeWaveRespawnTimer = 12000; - } + m_bThreeWaveCheckTimerStarted = true; + m_uiThreeWaveRespawnTimer = 12000; } } - m_uiThreeWaveCheckTimer = 1000; } - else - m_uiThreeWaveCheckTimer -= uiDiff; + m_uiThreeWaveCheckTimer = 1000; + } + else + m_uiThreeWaveCheckTimer -= uiDiff; - // respawn 3 adds after 12 sec from one's death - if (m_bThreeWaveCheckTimerStarted) + // respawn 3 adds after 12 sec from one's death + if (m_bThreeWaveCheckTimerStarted) + { + if (m_uiThreeWaveRespawnTimer <= uiDiff) { - if (m_uiThreeWaveRespawnTimer <= uiDiff) - { - Creature* pWaterSpirit = m_creature->GetMap()->GetCreature(m_uiWaterSpiritGUID); - Creature* pStormLasher = m_creature->GetMap()->GetCreature(m_uiStormLasherGUID); - Creature* pSnapLasher = m_creature->GetMap()->GetCreature(m_uiSnapLasherGUID); + Creature* pWaterSpirit = m_pInstance->instance->GetCreature(m_uiWaterSpiritGUID); + Creature* pStormLasher = m_pInstance->instance->GetCreature(m_uiStormLasherGUID); + Creature* pSnapLasher = m_pInstance->instance->GetCreature(m_uiSnapLasherGUID); - if (pWaterSpirit && !pWaterSpirit->isAlive()) - { - pWaterSpirit->Respawn(); - } - if (pStormLasher && !pStormLasher->isAlive()) - { - pStormLasher->Respawn(); - } - if (pSnapLasher && !pSnapLasher->isAlive()) - { - pSnapLasher->Respawn(); - } - m_bThreeWaveCheckTimerStarted = false; - m_uiThreeWaveRespawnTimer = 12000; + if (pWaterSpirit && !pWaterSpirit->isAlive()) + { + Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + pWaterSpirit->Respawn(); + pWaterSpirit->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim()); } - else - m_uiThreeWaveRespawnTimer -= uiDiff; - } + if (pStormLasher && !pStormLasher->isAlive()) + { + Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + pStormLasher->Respawn(); + pStormLasher->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim()); + } + if (pSnapLasher && !pSnapLasher->isAlive()) + { + Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + pSnapLasher->Respawn(); + pSnapLasher->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim()); + } + m_bThreeWaveCheckTimerStarted = false; + m_uiThreeWaveRespawnTimer = 12000; + }else m_uiThreeWaveRespawnTimer -= uiDiff; } // Hardmode - if(m_bIsBrightleafAlive) + if (m_bIsBrightleafAlive) { + if(!m_creature->HasAura(SPELL_BRIGHTLEAFS_ESSENCE, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_BRIGHTLEAFS_ESSENCE); + // hacky way, should be done by spell - if(m_uiUnstableEnergyTimer < uiDiff) + if (m_uiUnstableEnergyTimer < uiDiff) { //DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY_FREYA : SPELL_UNSTABLE_ENERGY_FREYA_H); - for(int8 i = 0; i < 3; ++i) + for (int8 i = 0; i < 3; ++i) { - if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - m_creature->SummonCreature(NPC_SUN_BEAM, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 20000); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + { + float x = target->GetPositionX(); + float y = target->GetPositionY(); + float z = target->GetPositionZ(); + m_creature->SummonCreature(NPC_SUN_BEAM, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 20000); + } } m_uiUnstableEnergyTimer = urand(25000, 30000); } - else - m_uiUnstableEnergyTimer -= uiDiff; + else m_uiUnstableEnergyTimer -= uiDiff; } - if(m_bIsIronbranchAlive) + if (m_bIsIronbranchAlive) { - if(m_uiStrenghtenIronRootsTimer < uiDiff) + if (!m_creature->HasAura(SPELL_IRONBRANCH_ESSENCE, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_IRONBRANCH_ESSENCE); + + if (m_uiStrenghtenIronRootsTimer < uiDiff) { - if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { DoScriptText(EMOTE_IRON_ROOTS, m_creature, target); - target->CastSpell(target, m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H, true); + DoCast(target, m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); } m_uiStrenghtenIronRootsTimer = 50000 + urand(10000, 20000); } - else - m_uiStrenghtenIronRootsTimer -= uiDiff; + else m_uiStrenghtenIronRootsTimer -= uiDiff; } - if(m_bIsStonebarkAlive) + if (m_bIsStonebarkAlive) { - if(m_uiGroundTremorTimer < uiDiff) + // aura doesn't work. Needs core fix + if(!m_creature->HasAura(SPELL_STONEBARKS_ESSENCE, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_STONEBARKS_ESSENCE); + + if (m_uiGroundTremorTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_GROUND_TREMOR_FREYA : SPELL_GROUND_TREMOR_FREYA_H) == CAST_OK) - { - DoScriptText(EMOTE_GROUND_TREMMOR, m_creature); - m_uiGroundTremorTimer = 20000; - } + DoScriptText(EMOTE_GROUND_TREMMOR, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_GROUND_TREMOR_FREYA : SPELL_GROUND_TREMOR_FREYA_H); + m_uiGroundTremorTimer = 20000; } - else - m_uiGroundTremorTimer -= uiDiff; + else m_uiGroundTremorTimer -= uiDiff; } //Phase 1, waves of adds - if(m_uiWaveNumber < 6) + if (m_uiWaveNumber < 6) { - if(m_uiSummonTimer < uiDiff) + if (m_uiSummonTimer < uiDiff) { DoScriptText(EMOTE_ALLIES_NATURE, m_creature); switch(m_uiWaveType) { - case 0: - if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_LASHERS) == CAST_OK) - { - /*SummonLashers();*/ - DoScriptText(SAY_ADDS_LASHER, m_creature); - initNextWave(); - } - break; - case 1: - if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_CONSERVATOR) == CAST_OK) - { - /*SummonConservator();*/ - DoScriptText(SAY_ADDS_CONSERVATOR, m_creature); - initNextWave(); - } - break; - case 2: - //DoCast(m_creature, SPELL_SUMMON_ELEMENTALS); - SummonElementals(); - DoScriptText(SAY_ADDS_TRIO, m_creature); - m_bWaveCheck = true; - m_uiThreeWaveCheckTimer = 1000; - initNextWave(); - break; - default: - break; + case 0: SummonLashers(); break; + case 1: SummonConservator(); break; + case 2: SummonElementals(); break; } - + m_uiWaveType = (m_uiWaveType + m_uiWaveTypeInc) % 3; + ++m_uiWaveNumber; + m_uiSummonTimer = 60000; } - else - m_uiSummonTimer -= uiDiff; + else m_uiSummonTimer -= uiDiff; } // Phase 2 else { - if(m_uiNatureBombTimer < uiDiff) + // nature bomb. Should be done by spell, not by summon. + if (m_uiNatureBombTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_NATURE_BOMB) == CAST_OK) + DoCast(m_creature, SPELL_NATURE_BOMB_VISUAL); + DoCast(m_creature, SPELL_NATURE_BOMB_SUMMON); + + int8 count = urand(8, 10); + for (int8 i = 0; i < count; ++i) { - m_uiNatureBombTimer = urand(7000, 12000); + float radius = 30* rand_norm_f(); + float angle = 2.0f * M_PI_F * rand_norm_f(); + float x = m_creature->GetPositionX() + cos(angle) * radius; + float y = m_creature->GetPositionY() + sin(angle) * radius; + float z = m_creature->GetTerrain()->GetHeight(x, y, MAX_HEIGHT); + m_creature->SummonCreature(NPC_NATURE_BOMB, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 20000); } + m_uiNatureBombTimer = 10000; } - else - m_uiNatureBombTimer -= uiDiff; + else m_uiNatureBombTimer -= uiDiff; } //All phases - if(m_uiSunbeamTimer < uiDiff) + if (m_uiSunbeamTimer < uiDiff) { - if (Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, (uint32)0, SELECT_FLAG_PLAYER)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SUNBEAM : SPELL_SUNBEAM_H) == CAST_OK) - { - m_uiSunbeamTimer = 6000 + rand()%10000; - } - } + if(Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_SUNBEAM : SPELL_SUNBEAM_H); + m_uiSunbeamTimer = 6000 + rand()%10000; } - else - m_uiSunbeamTimer -= uiDiff; + else m_uiSunbeamTimer -= uiDiff; - if(m_uiLifebindersGiftTimer < uiDiff) + if (m_uiLifebindersGiftTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_LIFEBINDERS_GIFT_SUMMON) == CAST_OK) - { - DoScriptText(EMOTE_LIFEBINDERS_GIFT, m_creature); - m_uiLifebindersGiftTimer = 30000; - } + DoScriptText(EMOTE_LIFEBINDERS_GIFT, m_creature); + if(Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_LIFEBINDERS_GIFT_SUMMON); + m_uiLifebindersGiftTimer = 30000; } - else - m_uiLifebindersGiftTimer -= uiDiff; + else m_uiLifebindersGiftTimer -= uiDiff; - if(m_uiEnrageTimer < uiDiff) + if (m_uiEnrageTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT) == CAST_OK) - { - DoScriptText(SAY_BERSERK, m_creature); - m_uiEnrageTimer = 30000; - } + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_BERSERK); + m_uiEnrageTimer = 30000; } - else - m_uiEnrageTimer -= uiDiff; + else m_uiEnrageTimer -= uiDiff; + + if (m_creature->GetHealthPercent() <= 1.0f) + m_bIsOutro = true; DoMeleeAttackIfReady(); } // outro - if(m_bIsOutro) + if (m_bIsOutro) { switch(m_uiStep) { - case 1: - if(SpellAuraHolderPtr pTempHolder = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) - { - if(pTempHolder->GetStackAmount() >= 25) - { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_BACK_TO_NATURE, true); - } - } - m_creature->setFaction(35); - m_creature->RemoveAllAuras(); - m_creature->DeleteThreatList(); - m_creature->CombatStop(true); - m_creature->InterruptNonMeleeSpells(false); - m_creature->SetHealth(m_creature->GetMaxHealth()); - m_creature->GetMotionMaster()->MovePoint(0, 2359.40f, -52.39f, 425.64f); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - ++m_uiStep; - m_uiOutroTimer = 7000; - break; - case 3: - DoScriptText(SAY_DEATH, m_creature); - ++m_uiStep; - m_uiOutroTimer = 10000; - break; - case 5: - DoOutro(); - ++m_uiStep; - m_uiOutroTimer = 10000; - break; + case 1: + if (m_creature->HasAura(SPELL_ATTUNED_TO_NATURE, EFFECT_INDEX_0)) + { + if (m_creature->GetAura(SPELL_ATTUNED_TO_NATURE, EFFECT_INDEX_0)->GetStackAmount() >= 25) + m_bNature = true; + } + m_creature->setFaction(35); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->GetMotionMaster()->MovePoint(0, 2359.40f, -52.39f, 425.64f); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++m_uiStep; + m_uiOutroTimer = 7000; + break; + case 3: + DoScriptText(SAY_DEATH, m_creature); + ++m_uiStep; + m_uiOutroTimer = 10000; + break; + case 5: + DoOutro(); + ++m_uiStep; + m_uiOutroTimer = 10000; + break; } } - else - return; + else return; if (m_uiOutroTimer <= uiDiff) { @@ -1062,74 +1176,82 @@ struct MANGOS_DLL_DECL mob_freya_groundAI : public ScriptedAI { mob_freya_groundAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiNatureBomb; - uint32 m_uiOpenNatureBomb; + uint32 m_uiNatureBomb_Timer; uint32 m_uiDieTimer; - uint32 m_uiEonarsGift; - uint32 m_uiNonSelectable; + uint32 m_uiEonarsGift_Timer; + uint32 m_uiNonSelectable_Timer; uint32 m_uiGrow_Timer; - uint32 m_uiUnstableEnergy; - uint32 m_uiHealthyGrow; + uint32 m_uiSunBeamDespawn_Timer; + uint32 m_uiUnstableEnergy_Timer; + uint32 m_uiHealthyGrow_Timer; + ObjectGuid m_uiNatureBombGUID; float m_fSize; + bool m_bNpcNatureBomb; + bool m_bNpcEonarsGift; + bool m_bNpcHealthySpore; + bool m_bNpcSunBeamFreya; + bool m_bNpcSunBeamBright; + bool m_bHasGrow; void Reset() { - m_uiNatureBomb = urand(9000,11000); - m_uiOpenNatureBomb = m_uiNatureBomb - 2000; - m_uiDieTimer = 60000; - m_uiEonarsGift = urand(11000,13000); - m_uiNonSelectable = 5000; - m_uiUnstableEnergy = 10500; - m_uiGrow_Timer = 0; - m_bHasGrow = true; - m_uiHealthyGrow = urand(3000,12000); + m_uiNatureBomb_Timer = urand(9000,11000); + m_uiDieTimer = 60000; + m_uiEonarsGift_Timer = urand(11000,13000); + m_uiNonSelectable_Timer = 5000; + m_uiUnstableEnergy_Timer = 1000; + m_uiGrow_Timer = 0; + m_uiSunBeamDespawn_Timer = urand(10000,11000); + m_bHasGrow = true; + m_uiHealthyGrow_Timer = urand(3000,12000); + m_bNpcNatureBomb = false; + m_bNpcEonarsGift = false; + m_bNpcHealthySpore = false; + m_bNpcSunBeamFreya = false; + m_bNpcSunBeamBright = false; // the invisible displayIds should be set in DB. switch(m_creature->GetEntry()) { case NPC_NATURE_BOMB: + m_bNpcNatureBomb = true; m_creature->setFaction(14); m_fSize = 1; m_creature->SetDisplayId(25865); // invisible - DoCast(m_creature, SPELL_SUMMON_GO_NATURE_BOMB ,true); + DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); break; case NPC_EONARS_GIFT: + m_bNpcEonarsGift = true; m_fSize = float(0.1); - m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); break; case NPC_HEALTHY_SPORE: - DoCast(m_creature, SPELL_HEALTHY_SPORE_VISUAL, true); - DoCast(m_creature, SPELL_POTENT_PHEROMONES, true); + m_bNpcHealthySpore = true; + DoCast(m_creature, SPELL_HEALTHY_SPORE_VISUAL); + DoCast(m_creature, SPELL_POTENT_PHEROMONES); break; case NPC_SUN_BEAM: - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bNpcSunBeamFreya = true; m_creature->SetDisplayId(25865); // invisible DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY_FREYA : SPELL_UNSTABLE_ENERGY_FREYA_H); - DoCast(m_creature, SPELL_PHOTOSYNTHESIS, true); - m_creature->ForcedDespawn(11000); break; case NPC_UNSTABLE_SUN_BEAM: + m_bNpcSunBeamBright = true; m_creature->SetDisplayId(25865); // invisible - DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL, true); - DoCast(m_creature, SPELL_PHOTOSYNTHESIS, true); - DoCast(m_creature, SPELL_UNSTABLE_SUN_BEAM_A, true); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->ForcedDespawn(11000); + DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); + //DoCast(m_creature, SPELL_PHOTOSYNTHESIS); // spell needs core fix, should be casted on Brighleaf! break; } @@ -1141,117 +1263,91 @@ struct MANGOS_DLL_DECL mob_freya_groundAI : public ScriptedAI { return; } - - void DamageTaken(Unit *pDoneBy, uint32 &uiDamage) - { - if (m_creature->GetEntry() == NPC_HEALTHY_SPORE) - uiDamage = 0; - } void UpdateAI(const uint32 uiDiff) { if (m_pInstance && m_pInstance->GetData(TYPE_FREYA) != IN_PROGRESS) - { m_creature->ForcedDespawn(); - } if(!m_creature->isAlive()) return; - switch(m_creature->GetEntry()) + // NATURE BOMB + if(m_bNpcNatureBomb) { - case NPC_NATURE_BOMB: + if(m_uiNatureBomb_Timer < uiDiff) { - if(m_uiOpenNatureBomb < uiDiff) - { - if (GameObject* pNaturBomb = GetClosestGameObjectWithEntry(m_creature, GO_NATURE_BOMB, 10.0f)) - { - pNaturBomb->Use(m_creature); - } - m_uiOpenNatureBomb = 5000; - } - else - m_uiOpenNatureBomb -= uiDiff; + DoCast(m_creature, m_bIsRegularMode ? SPELL_NATURE_BOMB : SPELL_NATURE_BOMB_H); + m_uiDieTimer = 500; + m_uiNatureBomb_Timer = 10000; + }else m_uiNatureBomb_Timer -= uiDiff; + + if(m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + else m_uiDieTimer -= uiDiff; + } - if(m_uiNatureBomb < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_NATURE_BOMB_EX : SPELL_NATURE_BOMB_EX_H) == CAST_OK) - { - if (GameObject* pNaturBomb = GetClosestGameObjectWithEntry(m_creature, GO_NATURE_BOMB, 10.0f)) - { - pNaturBomb->Delete(); - } - m_creature->ForcedDespawn(1000); - m_uiNatureBomb = 3000; - } - } - else - m_uiNatureBomb -= uiDiff; - break; - } - case NPC_EONARS_GIFT: + // EONAR GIFT + if(m_bNpcEonarsGift) + { + if (m_uiGrow_Timer > 500 && m_fSize < 1.5) { - if (m_creature->GetFloatValue(OBJECT_FIELD_SCALE_X) < 1.5) - { - DoCast(m_creature, SPELL_GROW, true); - } + m_fSize += float(m_uiGrow_Timer)/8000; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); + m_uiGrow_Timer = 0; + }else m_uiGrow_Timer += uiDiff; - if(m_uiEonarsGift < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_LIFEBINDERS_GIFT : SPELL_LIFEBINDERS_GIFT_H) == CAST_OK) - m_uiEonarsGift = 5000; - } - else - m_uiEonarsGift -= uiDiff; + if(m_uiEonarsGift_Timer < uiDiff) + { + if (Creature* pFreya = m_pInstance->GetSingleCreatureFromStorage(NPC_FREYA)) + DoCast(pFreya, m_bIsRegularMode ? SPELL_LIFEBINDERS_GIFT : SPELL_LIFEBINDERS_GIFT_H); + m_uiEonarsGift_Timer = 1000; + }else m_uiEonarsGift_Timer -= uiDiff; - if(m_uiNonSelectable < uiDiff && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - if (DoCastSpellIfCan(m_creature, SPELL_PHEROMONES_LG) == CAST_OK) - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - else - m_uiNonSelectable -= uiDiff; - break; - } - case NPC_HEALTHY_SPORE: + if(m_uiNonSelectable_Timer < uiDiff && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) { - if(!m_bHasGrow && m_fSize < 0.25) - m_creature->ForcedDespawn(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_PHEROMONES_LG); + }else m_uiNonSelectable_Timer -= uiDiff; + } - if(m_uiHealthyGrow < uiDiff) - { - if(m_bHasGrow) - { - m_fSize = float(urand(150,225))/100; - m_bHasGrow = false; - } - else - m_fSize = float(urand(1,300))/100; - if(m_fSize < 1) - m_fSize = 0.1f; - m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); - m_uiHealthyGrow = urand(3000,5000); - } - else - m_uiHealthyGrow -= uiDiff; + // HEALTHY SPORE + if(m_bNpcHealthySpore) + { + if(!m_bHasGrow && m_fSize < 0.25) + m_creature->ForcedDespawn(); - break; - } - case NPC_UNSTABLE_SUN_BEAM: + if(m_uiHealthyGrow_Timer < uiDiff) { - if(m_uiUnstableEnergy < uiDiff) + if(m_bHasGrow) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY : SPELL_UNSTABLE_ENERGY_H) == CAST_OK) - m_uiUnstableEnergy = 10000; + m_fSize = float(urand(150,225))/100; + m_bHasGrow = false; } else - m_uiUnstableEnergy -= uiDiff; + m_fSize = float(urand(1,300))/100; + if(m_fSize < 1) + m_fSize = 0.1f; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); + m_uiHealthyGrow_Timer = urand(3000,5000); + }else m_uiHealthyGrow_Timer -= uiDiff; + } - break; - } - default: - break; + // SUN BEAM + if(m_bNpcSunBeamBright) + { + if(m_uiUnstableEnergy_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY : SPELL_UNSTABLE_ENERGY_H); + m_uiUnstableEnergy_Timer = 1000; + }else m_uiUnstableEnergy_Timer -= uiDiff; + } + if(m_bNpcSunBeamFreya || m_bNpcSunBeamBright) + { + if(m_uiSunBeamDespawn_Timer < uiDiff) + m_creature->ForcedDespawn(); + else m_uiSunBeamDespawn_Timer -= uiDiff; } } }; @@ -1261,70 +1357,60 @@ struct MANGOS_DLL_DECL mob_freya_spawnedAI : public ScriptedAI { mob_freya_spawnedAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiTidalWave; - uint32 m_uiStormbolt; - uint32 m_uiLightningLash; - uint32 m_uiFlameLash; - uint32 m_uiResetAggro; - uint32 m_uiNaturesFury; - uint32 m_uiRespawnSpores; + bool m_bHasExploded; + + uint32 m_uiDeathCountdown; + uint32 m_uiTidalWave_Timer; + uint32 m_uiStormbolt_Timer; + uint32 m_uiLightningLash_Timer; + uint32 m_uiFlameLash_Timer; + uint32 m_uiNaturesFury_Timer; + uint32 m_uiWave3_DeathCountdown; + uint32 m_uiRespawnSpores_Timer; + uint32 m_uiDieTimer; + uint8 m_uiHealthMultiplier; void Reset() { - m_uiTidalWave = urand(2000,4000); - m_uiStormbolt = 1000; - m_uiLightningLash = urand(11000,14000); - m_uiFlameLash = urand(5000,10000); - m_uiResetAggro = 5000; - m_uiNaturesFury = urand(8000,10000); - m_uiRespawnSpores = 5000; + m_uiDieTimer = 120000; + m_uiDeathCountdown = 10000; + m_uiTidalWave_Timer = urand(2000,4000); + m_uiStormbolt_Timer = 1000; + m_uiLightningLash_Timer = urand(11000,14000); + m_uiFlameLash_Timer = urand(5000,10000); + m_uiNaturesFury_Timer = urand(8000,10000); + m_uiRespawnSpores_Timer = 5000; + m_uiHealthMultiplier = 1; switch(m_creature->GetEntry()) { - case NPC_ANCIENT_CONSERVATOR: - { - DoSpores(10); - break; - } - case NPC_WATER_SPIRIT: - case NPC_SNAPLASHER: - case NPC_STORM_LASHER: - { - m_creature->SetRespawnTime(30); - m_creature->SetCorpseDelay(30); - m_creature->SetRespawnDelay(30); - break; - } - default: - break; + // The Conservator's Grip needs core fix. It should be canceled by pheronomes! + case NPC_ANCIENT_CONSERVATOR: + DoSpores(10); + break; + case NPC_SNAPLASHER: + DoCast(m_creature, m_bIsRegularMode ? SPELL_HARDENED_BARK : SPELL_HARDENED_BARK_H); + break; } + m_creature->SetRespawnDelay(DAY); } - void JustDied(Unit* Killer) + void DamageTaken(Unit *done_by, uint32 &uiDamage) { - switch (m_creature->GetEntry()) + if (m_creature->GetEntry() == NPC_DETONATING_LASHER && uiDamage > m_creature->GetHealth() && !m_bHasExploded) { - case NPC_ANCIENT_CONSERVATOR: - { - DoCast(m_creature, SPELL_ATTUNED_25_STACKS, true); - break; - } - case NPC_DETONATING_LASHER: - { - DoCast(m_creature, m_bIsRegularMode ? SPELL_DETONATE : SPELL_DETONATE_H, true); - DoCast(m_creature, SPELL_ATTUNED_2_STACKS, true); - break; - } - default: - break; + DoCast(m_creature, m_bIsRegularMode ? SPELL_DETONATE : SPELL_DETONATE_H); + uiDamage = 0; + m_bHasExploded = true; + m_uiDieTimer = 500; } } @@ -1343,94 +1429,67 @@ struct MANGOS_DLL_DECL mob_freya_spawnedAI : public ScriptedAI if (m_pInstance && m_pInstance->GetData(TYPE_FREYA) != IN_PROGRESS) m_creature->ForcedDespawn(); - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if (!m_creature->isAlive()) return; - switch(m_creature->GetEntry()) + switch (m_creature->GetEntry()) { + // DETONATING LASHERS case NPC_DETONATING_LASHER: - { - if(m_uiFlameLash < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FLAME_LASH) == CAST_OK) - m_uiFlameLash = urand(5000,10000); - } - else - m_uiFlameLash -= uiDiff; - - if(m_uiResetAggro < uiDiff) + if(m_uiFlameLash_Timer < uiDiff) { - DoResetThreat(); - m_uiResetAggro = 5000; - } - else - m_uiResetAggro -= uiDiff; + DoCast(m_creature->getVictim(), SPELL_FLAME_LASH); + m_uiFlameLash_Timer = urand(5000,10000); + } else m_uiFlameLash_Timer -= uiDiff; + + if(m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + else m_uiDieTimer -= uiDiff; break; - } + // ANCIENT CONSERVATOR case NPC_ANCIENT_CONSERVATOR: - { - DoCastSpellIfCan(m_creature, SPELL_CONSERVATORS_GRIP, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); - if(m_uiNaturesFury < uiDiff) + if (m_uiNaturesFury_Timer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, (uint32)0, SELECT_FLAG_PLAYER)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_NATURES_FURY : SPELL_NATURES_FURY_H) == CAST_OK) - m_uiNaturesFury = urand(5000,6000); - } - } - else - m_uiNaturesFury -= uiDiff; + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_NATURES_FURY : SPELL_NATURES_FURY_H); + m_uiNaturesFury_Timer = urand(5000,6000); + } else m_uiNaturesFury_Timer -= uiDiff; - if(m_uiRespawnSpores < uiDiff) + if (m_uiRespawnSpores_Timer < uiDiff) { DoSpores(3); - m_uiRespawnSpores = 5000; - } - else - m_uiRespawnSpores -= uiDiff; + m_uiRespawnSpores_Timer = 5000; + } else m_uiRespawnSpores_Timer -= uiDiff; break; - } + // WATER SPIRIT case NPC_WATER_SPIRIT: - { - if (m_uiTidalWave < uiDiff) + if( m_uiTidalWave_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_TIDAL_WAVE : SPELL_TIDAL_WAVE_H) == CAST_OK) - m_uiTidalWave = urand(7000,9000); - } - else - m_uiTidalWave -= uiDiff; + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_TIDAL_WAVE : SPELL_TIDAL_WAVE_H); + m_uiTidalWave_Timer = urand(7000, 9000); + } else m_uiTidalWave_Timer -= uiDiff; break; - } + // STORM LASHER case NPC_STORM_LASHER: - { - if (m_uiLightningLash < uiDiff) + if (m_uiLightningLash_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_LIGHTNING_LASH : SPELL_LIGHTNING_LASH_H) == CAST_OK) - m_uiLightningLash = urand(11000,14000); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_LIGHTNING_LASH : SPELL_LIGHTNING_LASH_H); + m_uiLightningLash_Timer = urand(11000, 14000); } else - m_uiLightningLash -= uiDiff; - - if (m_uiStormbolt < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STORMBOLT : SPELL_STORMBOLT_H) == CAST_OK) - m_uiStormbolt = 2000; + m_uiLightningLash_Timer -= uiDiff; + if (m_uiStormbolt_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STORMBOLT : SPELL_STORMBOLT_H); + m_uiStormbolt_Timer = 2000; + } else m_uiStormbolt_Timer -= uiDiff; } - else - m_uiStormbolt -= uiDiff; - - break; - } - case NPC_SNAPLASHER: - { - DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_HARDENED_BARK : SPELL_HARDENED_BARK_H, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); - } - default: break; } + DoMeleeAttackIfReady(); } }; diff --git a/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp b/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp index 2f5ae46604..666db3e81e 100644 --- a/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp @@ -15,9 +15,9 @@ */ /* ScriptData -SDName: boss_general_vezax -SD%Complete: 80% -SDComment: TODO Achievments: Shadowdodger +SDName: boss_vezax +SD%Complete: +SDComment: mark of the faceless needs core support. Searing flames needs fixing, cannot be interrupted SDCategory: Ulduar EndScriptData */ @@ -26,48 +26,52 @@ EndScriptData */ enum { - SAY_AGGRO = -1603350, - SAY_SLAY_1 = -1603351, - SAY_SLAY_2 = -1603352, - SAY_SURGE = -1603353, - SAY_DEATH = -1603354, - SAY_ENRAGE = -1603355, - SAY_HARD_MODE = -1603356, - - EMOTE_VAPOR = -1603357, - EMOTE_SURGE = -1603358, - EMOTE_ANIMUS = -1603359, - - SPELL_AURA_OF_DESPAIR = 62692, - SPELL_SHADOW_CRASH = 62660, - SPELL_MARK_OF_FACELESS = 63276, // triggers 63278 - SPELL_SEARING_FLAMES = 62661, - SPELL_SURGE_OF_DARKNESS = 62662, - SPELL_BERSERK = 26662, - SPELL_SARONITE_BARRIER = 63364, // also sends event 9735 - SPELL_SUMMON_ANIMUS = 63145, // the animus should spam 63420 on target - to be done in acid - SPELL_SUMMON_VAPORS = 63081, - SPELL_ANIMUS_FORMATION = 63319, // visual aura on the vapors - SPELL_SARONITE_VAPORS = 63323, // cast by vapor on death - SPELL_CORRUPTED_RAGE = 68415, // Unused - SPELL_CORRUPTED_WISDOM = 64646, - - MAX_HARD_MODE_VAPORS = 6, - - NPC_SARONITE_VAPOR = 33488, - NPC_SARONITE_ANIMUS = 33524, - SPELL_PROFOUND_DARKNESS = 63420, + SAY_AGGRO = -1603120, + SAY_SURGE = -1603123, + SAY_HARD = -1603126, + SAY_SLAY1 = -1603121, + SAY_SLAY2 = -1603122, + SAY_BERSERK = -1603125, + SAY_DEATH = -1603124, + EMOTE_VAPORS = -1603366, + EMOTE_SURGE = -1603367, + EMOTE_ANIMUS = -1603368, + + SPELL_AURA_OF_DESPAIR = 62692, + SPELL_SHADOW_CRASH = 62660, + SPELL_MARK_OF_FACELESS = 63276, + SPELL_MARK_SIMPHON = 63278, + SPELL_SEARING_FLAMES = 62661, + SPELL_SURGE_OF_DARKNESS = 62662, + SPELL_BERSERK = 26662, + SPELL_SARONITE_BARRIER = 63364, + SPELL_SUMMON_ANIMUS = 63145, + SPELL_SUMMON_VAPORS = 63081, + + NPC_SARONITE_VAPOR = 33488, + SPELL_SARONITE_VAPORS = 63323, + + NPC_SARONITE_ANIMUS = 33524, + SPELL_PROFOUND_DARKNESS = 63420, + SPELL_ANIMUS_FORMATION = 63319, + + ACHIEV_MORNING_SARONITE = 3181, + ACHIEV_MORNING_SARONITE_H = 3188, }; -struct MANGOS_DLL_DECL boss_general_vezaxAI : public ScriptedAI +uint8 m_uiSaroniteVaporCount; + +struct MANGOS_DLL_DECL boss_vezaxAI : public ScriptedAI { - boss_general_vezaxAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_vezaxAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; uint32 m_uiEnrageTimer; uint32 m_uiCrashTimer; @@ -75,33 +79,50 @@ struct MANGOS_DLL_DECL boss_general_vezaxAI : public ScriptedAI uint32 m_uiFlamesTimer; uint32 m_uiSurgeTimer; uint32 m_uiSaroniteVaporTimer; - uint32 m_uiSaroniteBarrierTimer; + uint32 m_uiSimphonTimer; + uint32 m_uiEndSimphonTimer; + uint32 m_uiSummonAnimusTimer; + ObjectGuid m_uiMarkTargetGUID; + uint32 m_uiMarkCheckTimer; + uint32 m_uiMarkEndTimer; - uint8 m_uiVaporsGathered; + std::list lVapors; - GUIDList m_lVaporsGuids; + bool m_bIsHardMode; + bool m_bActiveHardMode; + bool m_bHasMark; + bool m_bHasSimphon; + bool m_bIsAnimusAlive; void Reset() { - m_uiEnrageTimer = 10*MINUTE*IN_MILLISECONDS; - m_uiFlamesTimer = 8000; - m_uiSaroniteVaporTimer = 30000; - m_uiSurgeTimer = 60000; - m_uiMarkTimer = 20000; - m_uiCrashTimer = 15000; - m_uiSaroniteBarrierTimer = 0; - m_uiVaporsGathered = 0; + m_uiEnrageTimer = 600000; //10 minutes + m_uiFlamesTimer = 10000; + m_uiSaroniteVaporTimer = 30000; + m_bIsHardMode = false; + m_bActiveHardMode = false; + m_bHasMark = false; + m_bHasSimphon = false; + m_bIsAnimusAlive = false; + + m_uiSurgeTimer = 60000; + m_uiMarkTimer = urand(10000, 35000); + m_uiCrashTimer = 10000; + m_uiSimphonTimer = 1000; + m_uiEndSimphonTimer = 10000; + m_uiMarkTargetGUID.Clear(); + + lVapors.clear(); + + m_uiSaroniteVaporCount = 0; } - void Aggro(Unit* pWho) + void Aggro(Unit *who) { - if (m_pInstance) - { + if(m_pInstance) m_pInstance->SetData(TYPE_VEZAX, IN_PROGRESS); - m_pInstance->SetData(TYPE_VEZAX_HARD, NOT_STARTED); - } - DoCastSpellIfCan(m_creature, SPELL_AURA_OF_DESPAIR); + DoCast(m_creature, SPELL_AURA_OF_DESPAIR); DoScriptText(SAY_AGGRO, m_creature); } @@ -110,91 +131,131 @@ struct MANGOS_DLL_DECL boss_general_vezaxAI : public ScriptedAI { if (m_pInstance) m_pInstance->SetData(TYPE_VEZAX, FAIL); + + m_creature->RemoveAurasDueToSpell(SPELL_SARONITE_BARRIER); } - void JustDied(Unit* pKiller) + void JustDied(Unit *killer) { - if (m_pInstance) + if(m_pInstance) + { m_pInstance->SetData(TYPE_VEZAX, DONE); + if(m_bIsHardMode) + { + m_pInstance->SetData(TYPE_VEZAX_HARD, DONE); + + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_MORNING_SARONITE : ACHIEV_MORNING_SARONITE_H); + // hack used when the hard mode loot is within the Animus corpse + // PLEASE REMOVE FOR REVISION + if(Creature* pAnimus = m_pInstance->GetSingleCreatureFromStorage(NPC_SARONITE_ANIMUS)) + pAnimus->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + DoScriptText(SAY_DEATH, m_creature); } void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); } - void JustSummoned(Creature* pSummoned) + void PrepareHardMode() { - if (pSummoned->GetEntry() == NPC_SARONITE_VAPOR) - { - m_lVaporsGuids.push_back(pSummoned->GetObjectGuid()); - pSummoned->SetRespawnTime(DAY*IN_MILLISECONDS); - pSummoned->SetCorpseDelay(DAY*IN_MILLISECONDS); - pSummoned->SetRespawnDelay(DAY*IN_MILLISECONDS); - - // if vapors have reached the max number for hard mode then summon animus - if (m_lVaporsGuids.size() == MAX_HARD_MODE_VAPORS) - DoPrepareAnimusIfCan(); - } - // ToDo: faction should be set in DB - else if (pSummoned->GetEntry() == NPC_SARONITE_ANIMUS) - pSummoned->setFaction(14); - } + m_bActiveHardMode = true; + m_uiSummonAnimusTimer = 7000; - void SummonedCreatureJustDied(Creature* pSummoned) - { - // decrease the number of vapors when they die - if (pSummoned->GetEntry() == NPC_SARONITE_VAPOR) - { - pSummoned->CastSpell(pSummoned, SPELL_SARONITE_VAPORS, true, 0, 0, m_creature->GetObjectGuid()); - m_lVaporsGuids.remove(pSummoned->GetObjectGuid()); - } - // remove saronite barrier when animus dies - else if (pSummoned->GetEntry() == NPC_SARONITE_ANIMUS) - { - m_creature->RemoveAurasDueToSpell(SPELL_SARONITE_BARRIER); + GetCreatureListWithEntryInGrid(lVapors, m_creature, NPC_SARONITE_VAPOR, 200.0f); - if (m_creature->isAlive() && m_pInstance) - m_pInstance->SetData(TYPE_VEZAX_HARD, DONE); + if (!lVapors.empty()) + { + // vapors need more speed + for(std::list::iterator iter = lVapors.begin(); iter != lVapors.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + { + (*iter)->RemoveAllAuras(); + (*iter)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + (*iter)->SetSpeedRate(MOVE_RUN, 3.0f); + (*iter)->SetWalk(false); + (*iter)->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); + } + } } } - void SummonedMovementInform(Creature* pSummoned, uint32 uiMoveType, uint32 uiPointId) + + //hacky workaround for interrupt searing flames (need core fix) + void SpellHit(Unit* who, const SpellEntry* spell) { - if (uiMoveType != POINT_MOTION_TYPE || uiPointId != 0 || pSummoned->GetEntry() != NPC_SARONITE_VAPOR) + // don't self interrupt + if (!who->IsControlledByPlayer()) return; - ++m_uiVaporsGathered; + if (spell->EffectMechanic[0] == MECHANIC_INTERRUPT || spell->EffectMechanic[1] == MECHANIC_INTERRUPT || spell->EffectMechanic[2] == MECHANIC_INTERRUPT) + m_creature->InterruptNonMeleeSpells(false, SPELL_SEARING_FLAMES); + } - // Cast the saronite formation aura when all vapors arive - if (m_uiVaporsGathered == MAX_HARD_MODE_VAPORS) + void ActivateHardMode() + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_SARONITE_BARRIER); + //DoCast(m_creature, SPELL_SUMMON_ANIMUS); // make it by summon creature because of better handling the auras + DoScriptText(EMOTE_ANIMUS, m_creature); + DoScriptText(SAY_HARD, m_creature); + + if(Creature* pAnimus = m_creature->SummonCreature(NPC_SARONITE_ANIMUS, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 900000)) { - pSummoned->CastSpell(pSummoned, SPELL_ANIMUS_FORMATION, true); + pAnimus->SetInCombatWithZone(); + } - // Despawn the vapors - for (GUIDList::const_iterator itr = m_lVaporsGuids.begin(); itr != m_lVaporsGuids.end(); ++itr) + if (!lVapors.empty()) + { + for(std::list::iterator iter = lVapors.begin(); iter != lVapors.end(); ++iter) { - if (Creature* pVapor = m_creature->GetMap()->GetCreature(*itr)) - pVapor->ForcedDespawn(4000); + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); } - - DoScriptText(EMOTE_ANIMUS, m_creature); - m_uiSaroniteBarrierTimer = 4000; } + + m_bIsHardMode = true; + m_bIsAnimusAlive = true; } - // Merge vapors - void DoPrepareAnimusIfCan() + // hacky way for the mark of the faceless, needs core support + // PLEASE REMOVE FOR REVISION! + void CheckForMark(ObjectGuid m_uiTargetGUID) { - // Gather the vapors to the boss - NOTE: not sure if position is ok - for (GUIDList::const_iterator itr = m_lVaporsGuids.begin(); itr != m_lVaporsGuids.end(); ++itr) + if(!m_uiTargetGUID) + return; + + m_bHasSimphon = false; + Map *pMap = m_creature->GetMap(); + Unit* pTarget = pMap->GetUnit(m_uiTargetGUID); + if (pMap->IsDungeon()) { - // Better place: near him or some fixed position? - if (Creature* pVapor = m_creature->GetMap()->GetCreature(*itr)) - pVapor->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); - } + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + { + if(pTarget && pTarget->isAlive() && !m_bHasSimphon && m_uiTargetGUID != itr->getSource()->GetObjectGuid()) + { + if (itr->getSource()->isAlive() && pTarget->GetDistance2d(itr->getSource()) < 10.0f) + { + DoCast(pTarget, SPELL_MARK_SIMPHON); + m_bHasSimphon = true; + } + } + } + } } void UpdateAI(const uint32 uiDiff) @@ -202,131 +263,134 @@ struct MANGOS_DLL_DECL boss_general_vezaxAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiSaroniteBarrierTimer) + // prepare hard mode + if(m_uiSaroniteVaporCount == 6 && !m_bIsHardMode && !m_bActiveHardMode) + PrepareHardMode(); + + // summon animus + if(m_uiSummonAnimusTimer < uiDiff && !m_bIsHardMode && m_bActiveHardMode) + ActivateHardMode(); + else m_uiSummonAnimusTimer -= uiDiff; + + // saronite vapor + if(m_uiSaroniteVaporTimer < uiDiff && !m_bIsHardMode) { - if (m_uiSaroniteBarrierTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_SARONITE_BARRIER) == CAST_OK) - m_uiSaroniteBarrierTimer = 0; - } - else - m_uiSaroniteBarrierTimer -= uiDiff; + m_creature->CastStop(); + DoCast(m_creature, SPELL_SUMMON_VAPORS); + DoScriptText(EMOTE_VAPORS, m_creature); + m_uiSaroniteVaporCount += 1; + m_uiSaroniteVaporTimer = 30000; } + else m_uiSaroniteVaporTimer -= uiDiff; - // summon saronite vapors before the hard mode - if (m_pInstance && m_pInstance->GetData(TYPE_VEZAX_HARD) == NOT_STARTED) + // searing flames + if(m_uiFlamesTimer < uiDiff && !m_bIsAnimusAlive) { - if (m_uiSaroniteVaporTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_VAPORS) == CAST_OK) - { - DoScriptText(EMOTE_VAPOR, m_creature); - m_uiSaroniteVaporTimer = 30000; - } - } - else - m_uiSaroniteVaporTimer -= uiDiff; + DoCast(m_creature, SPELL_SEARING_FLAMES); + m_uiFlamesTimer = 11000; } + else m_uiFlamesTimer -= uiDiff; - if (m_uiFlamesTimer < uiDiff) + // surge of darkness + if(m_uiSurgeTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_SEARING_FLAMES) == CAST_OK) - m_uiFlamesTimer = urand(5000, 10000); + m_creature->CastStop(); + DoScriptText(SAY_SURGE, m_creature); + DoScriptText(EMOTE_SURGE, m_creature); + DoCast(m_creature, SPELL_SURGE_OF_DARKNESS); + m_uiSurgeTimer = 60000; } - else - m_uiFlamesTimer -= uiDiff; + else m_uiSurgeTimer -= uiDiff; - if (m_uiSurgeTimer < uiDiff) + // mark of faceless + if(m_uiMarkTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_SURGE_OF_DARKNESS) == CAST_OK) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) { - DoScriptText(SAY_SURGE, m_creature); - DoScriptText(EMOTE_SURGE, m_creature); - m_uiSurgeTimer = 62000; + m_uiMarkTargetGUID = pTarget->GetObjectGuid(); + DoCast(pTarget, SPELL_MARK_OF_FACELESS); } + m_bHasMark = true; + m_uiMarkCheckTimer = 1000; + m_uiMarkEndTimer = 10000; + m_uiMarkTimer = urand(25000, 30000); } - else - m_uiSurgeTimer -= uiDiff; + else m_uiMarkTimer -= uiDiff; - if (m_uiMarkTimer < uiDiff) + // HACK FOR MARK OF THE FACELESS + // mark check ending + if(m_uiMarkEndTimer < uiDiff && m_bHasMark) + m_bHasMark = false; + else m_uiMarkEndTimer -= uiDiff; + + // simphon life every sec + if(m_uiMarkCheckTimer < uiDiff && m_bHasMark) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, SPELL_MARK_OF_FACELESS, SELECT_FLAG_PLAYER)) - { - if (DoCastSpellIfCan(pTarget, SPELL_MARK_OF_FACELESS) == CAST_OK) - m_uiMarkTimer = urand(25000, 30000); - } + CheckForMark(m_uiMarkTargetGUID); + m_uiMarkCheckTimer = 1000; } - else - m_uiMarkTimer -= uiDiff; + else m_uiMarkCheckTimer -= uiDiff; - if (m_uiCrashTimer < uiDiff) + // shadow crash + if(m_uiCrashTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, SPELL_SHADOW_CRASH, SELECT_FLAG_NOT_IN_MELEE_RANGE | SELECT_FLAG_PLAYER)) - { - if (DoCastSpellIfCan(pTarget, SPELL_SHADOW_CRASH) == CAST_OK) - m_uiCrashTimer = 15000; - } + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_SHADOW_CRASH); + m_uiCrashTimer = 10000; } - else - m_uiCrashTimer -= uiDiff; + else m_uiCrashTimer -= uiDiff; - if (m_uiEnrageTimer < uiDiff) + // enrage 10 min + if(m_uiEnrageTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK) - { - DoScriptText(SAY_ENRAGE, m_creature); - m_uiEnrageTimer = 30000; - } + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_BERSERK); + m_uiEnrageTimer = 30000; } - else - m_uiEnrageTimer -= uiDiff; + else m_uiEnrageTimer -= uiDiff; DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_general_vezax(Creature* pCreature) -{ - return new boss_general_vezaxAI(pCreature); -} - -bool ProcessEventId_event_spell_saronite_barrier(uint32 uiEventId, Object* pSource, Object* pTarget, bool bIsStart) -{ - if (pSource->GetTypeId() == TYPEID_UNIT && ((Creature*)pSource)->GetEntry() == NPC_VEZAX) - { - if (instance_ulduar* pInstance = (instance_ulduar*)((Creature*)pSource)->GetInstanceData()) - { - // Start hard mode for Vezax and summon the Animus - pInstance->SetData(TYPE_VEZAX_HARD, IN_PROGRESS); - - ((Creature*)pSource)->CastSpell((Creature*)pSource, SPELL_SUMMON_ANIMUS, true); - DoScriptText(SAY_HARD_MODE, (Creature*)pSource); - - return true; - } - } - return false; -} - // Saronite animus struct MANGOS_DLL_DECL mob_saronite_animusAI : public ScriptedAI { mob_saronite_animusAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiProfoundDarknessTimer; void Reset() { m_uiProfoundDarknessTimer = 3000; + DoCast(m_creature, SPELL_ANIMUS_FORMATION); m_creature->SetRespawnDelay(DAY); } + void JustDied(Unit *killer) + { + if(m_pInstance) + { + if (Creature* pVezax = m_pInstance->GetSingleCreatureFromStorage(NPC_VEZAX)) + { + if (pVezax->isAlive()) + { + pVezax->RemoveAurasDueToSpell(SPELL_SARONITE_BARRIER); + ((boss_vezaxAI*)pVezax->AI())->m_bIsAnimusAlive = false; + } + } + } + // used for hard mode loot + // REMOVE THIS FOR REVISION + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + void UpdateAI(const uint32 uiDiff) { if (m_pInstance && m_pInstance->GetData(TYPE_VEZAX) != IN_PROGRESS) @@ -335,44 +399,109 @@ struct MANGOS_DLL_DECL mob_saronite_animusAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - DoCastSpellIfCan(m_creature, SPELL_ANIMUS_FORMATION, CAST_AURA_NOT_PRESENT); - if(m_uiProfoundDarknessTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_PROFOUND_DARKNESS) == CAST_OK) - m_uiProfoundDarknessTimer = urand(2000, 3000); + DoCast(m_creature, SPELL_PROFOUND_DARKNESS); + m_uiProfoundDarknessTimer = urand(2000, 3000); } - else - m_uiProfoundDarknessTimer -= uiDiff; + else m_uiProfoundDarknessTimer -= uiDiff; DoMeleeAttackIfReady(); } }; +struct MANGOS_DLL_DECL mob_saronite_vaporAI : public ScriptedAI +{ + mob_saronite_vaporAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + ScriptedInstance* m_pInstance; + uint32 m_uiDieTimer; + bool m_bDie; + + void Reset() + { + m_bDie = false; + m_uiDieTimer = 36000; + m_creature->SetRespawnDelay(DAY); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void JustDied(Unit *killer) + { + m_uiSaroniteVaporCount -= 1; + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + // Mana regen pool + if(uiDamage >= m_creature->GetHealth()) + { + uiDamage = 0; + if (!m_bDie) + { + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TAPPED); + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_bDie = true; + DoCast(m_creature, SPELL_SARONITE_VAPORS); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_VEZAX) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_bDie) + { + if (m_uiDieTimer < diff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDieTimer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_vezax(Creature* pCreature) +{ + return new boss_vezaxAI(pCreature); +} CreatureAI* GetAI_mob_saronite_animus(Creature* pCreature) { return new mob_saronite_animusAI(pCreature); } -void AddSC_boss_general_vezax() +CreatureAI* GetAI_mob_saronite_vapor(Creature* pCreature) +{ + return new mob_saronite_vaporAI(pCreature); +} + +void AddSC_boss_vezax() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_general_vezax"; - pNewScript->GetAI = &GetAI_boss_general_vezax; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "event_spell_saronite_barrier"; - pNewScript->pProcessEventId = &ProcessEventId_event_spell_saronite_barrier; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_saronite_animus"; - pNewScript->GetAI = &GetAI_mob_saronite_animus; - pNewScript->RegisterSelf(); + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vezax"; + newscript->GetAI = &GetAI_boss_vezax; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_saronite_animus"; + newscript->GetAI = &GetAI_mob_saronite_animus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_saronite_vapor"; + newscript->GetAI = &GetAI_mob_saronite_vapor; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_hodir.cpp b/scripts/northrend/ulduar/ulduar/boss_hodir.cpp index 305c84f1b5..941a09a0e6 100644 --- a/scripts/northrend/ulduar/ulduar/boss_hodir.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_hodir.cpp @@ -16,10 +16,10 @@ /* ScriptData SDName: boss_hodir -SD%Complete: -SDComment: Encounter overview: Hodir casts regular Icicles all the time (as triggered casts from aura, every 2sec, - on 10man there are 2sec. breaks every 2 icicles). - Flash Freeze has precast spell, marking random 2-3 already existing . +SD%Complete: +SDComment: Encounter overview: + Hodir casts regular Icicles all the time (as triggered casts from aura, every 2sec, on 10man there are 2sec. breaks every 2 icicles). + Flash Freeze has precast spell, marking random 2-3 already existing. When the spell is cast, there is a spell triggered that targets all regular Icicles. They spawn Snowpacked Icicles that spawn Snowdrifts and have area aura marking targets to be safe from Flash Freeze. All above fixed in core, so refer to commit history of instance_Ulduar file. @@ -45,7 +45,6 @@ enum EMOTE_SPEEDKILL = -1603130, SPELL_ENRAGE = 26662, - SPELL_HODIR_CREDIT = 64899, // custom spell in spell_dbc.sql SPELL_FROZEN_BLOWS = 62478, SPELL_FROZEN_BLOWS_H = 63512, @@ -55,7 +54,7 @@ enum SPELL_ICICLE_FLASH_MARKS = 62476, // casts this right befor flash freeze, triggers SPELL_ICICLE_SNOWPACKED. should target Icicles dummy NPCs SPELL_ICICLE_FLASH_MARKS_H = 62477, SPELL_ICICLE = 62234, // regular Icicle throughout the whole encounter - SPELL_ICICLE_SNOW_DAMAGE = 62460, // regular Icicle throughout the whole encounter, spell triggered by dummy NPC + SPELL_ICICLE_SNOW_DAMAGE = 62460, // regular Icicle throughout the whole encounter, spell triggered by dummy NPC SPELL_ICICLE_DAMAGE_NORMAL = 62236, SPELL_ICICLE_SNOWPACKED_SUM = 62462, // icicles right before flash freeze that summon snowdrifts SPELL_ICICLE_SNOWDRIFT = 62460, @@ -81,6 +80,13 @@ enum NPC_FLASH_FREEZE = 32926, NPC_FLASH_FREEZE_NPC = 32938, + NPC_HELPER_DRUID = 32941, + NPC_HELPER_SHAMAN = 32950, + NPC_HELPER_MAGE = 32946, + NPC_HELPER_PRIEST = 32948, + + SPELL_HODIR_CREDIT = 64899, + ACHIEV_RARE_CACHE = 3182, ACHIEV_RARE_CACHE_H = 3184, ACHIEV_COOLEST_FRIEND = 2963, @@ -115,17 +121,18 @@ enum SPELL_DISPEL_MAGIC = 63499, //friendly }; +bool m_bCoolestFriend; + // Script for the Flash freeze which is enchasing the npcs in ice at the begining of the fight -struct MANGOS_DLL_DECL mob_npc_flashFreezeAI : public ScriptedAI +struct MANGOS_DLL_DECL mob_npc_flashFreezeAI : public Scripted_NoMovementAI { - mob_npc_flashFreezeAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_npc_flashFreezeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - SetCombatMovement(false); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiFreezeNPCTimer; @@ -185,13 +192,13 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI { boss_hodirAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; // hard mode timer uint32 m_uiSpeedKillTimer; @@ -206,7 +213,8 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI uint32 m_uiOutroTimer; uint32 m_uiStep; - bool m_bhardmode; + bool m_bIsCheese; + bool m_bhardmode; void Reset() { @@ -220,6 +228,7 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI m_uiStep = 1; m_bIsOutro = false; m_bhardmode = true; + m_bIsCheese = true; if (Creature* pMage = m_pInstance->GetSingleCreatureFromStorage(NPC_HELPER_MAGE)) { @@ -283,11 +292,28 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI { m_pInstance->SetData(TYPE_HODIR_HARD, DONE); m_pInstance->SetData(TYPE_HODIR, DONE); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_RARE_CACHE : ACHIEV_RARE_CACHE_H); } else m_pInstance->SetData(TYPE_HODIR, DONE); + + // hacky way to complete achievements; use only if you have this function + if (m_bCoolestFriend) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_COOLEST_FRIEND : ACHIEV_COOLEST_FRIEND_H); + + if (m_bIsCheese) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHEESE_FREEZE : ACHIEV_CHEESE_FREEZE_H); + } + + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + pPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_HODIR_CREDIT); } - DoCast(m_creature, SPELL_HODIR_CREDIT, true); m_creature->ForcedDespawn(); } @@ -329,8 +355,8 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI { if (pTarget->GetTypeId() == TYPEID_PLAYER) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_CHEESE_FREEZE, false); + m_bIsCheese = false; + if (pTarget->HasAura(SPELL_FLASH_FREEZE_DEBUFF)) DoCastSpellIfCan(pTarget, SPELL_FLASH_FREEZE_KILL, CAST_TRIGGERED); else @@ -360,8 +386,6 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI { m_bhardmode = false; DoScriptText(EMOTE_SPEEDKILL, m_creature); - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_RARE_CACHE, false); } } @@ -461,13 +485,12 @@ struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI }; // script for Icicles -struct MANGOS_DLL_DECL mob_icicleAI : public ScriptedAI +struct MANGOS_DLL_DECL mob_icicleAI : public Scripted_NoMovementAI { - mob_icicleAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_icicleAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - SetCombatMovement(false); m_uiSpellId = 0; m_uiActionTimer = 10000; switch (m_creature->GetEntry()) @@ -488,11 +511,11 @@ struct MANGOS_DLL_DECL mob_icicleAI : public ScriptedAI break; default: break; - } + } pCreature->SetRespawnDelay(7*DAY*IN_MILLISECONDS); } - instance_ulduar *m_pInstance; + ScriptedInstance *m_pInstance; bool m_bIsRegularMode; uint32 m_uiActionTimer; uint32 m_uiSpellId; @@ -514,19 +537,18 @@ struct MANGOS_DLL_DECL mob_icicleAI : public ScriptedAI }; // script for Flash freeze -struct MANGOS_DLL_DECL mob_flashFreezeAI : public ScriptedAI +struct MANGOS_DLL_DECL mob_flashFreezeAI : public Scripted_NoMovementAI { - mob_flashFreezeAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_flashFreezeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetDisplayId(11686); // make invisible - SetCombatMovement(false); m_bIsFrozen = false; m_uiCheckTimer = 1000; Reset(); } - instance_ulduar *m_pInstance; + ScriptedInstance *m_pInstance; bool m_bIsFrozen; uint32 m_uiCheckTimer; @@ -574,13 +596,13 @@ struct MANGOS_DLL_DECL npc_hodir_helperAI : public ScriptedAI { npc_hodir_helperAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } - instance_ulduar *m_pInstance; + ScriptedInstance *m_pInstance; bool m_bIsRegularMode; @@ -609,10 +631,9 @@ struct MANGOS_DLL_DECL npc_hodir_helperAI : public ScriptedAI uiDamage = 0; } - void JustDied( Unit* pKiller) + void JustDied(Unit* pKiller) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_COOLEST_FRIEND, false); + m_bCoolestFriend = false; } void JustReachedHome() @@ -636,8 +657,8 @@ struct MANGOS_DLL_DECL npc_hodir_helperAI : public ScriptedAI { if (m_creature->GetDistance(pHodir) > 30) { - float x,y,z; - m_creature->GetContactPoint(pHodir, x,y,z, 15.0f); + float x, y, z; + m_creature->GetContactPoint(pHodir, x, y, z, 15.0f); m_creature->GetMotionMaster()->MovementExpired(false); m_creature->GetMotionMaster()->MovePoint(1,x,y,z); m_uiCeckMove = 4000; diff --git a/scripts/northrend/ulduar/ulduar/boss_ignis.cpp b/scripts/northrend/ulduar/ulduar/boss_ignis.cpp index a1115d187f..fa3fe3e355 100644 --- a/scripts/northrend/ulduar/ulduar/boss_ignis.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_ignis.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2011 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -23,137 +23,207 @@ EndScriptData */ #include "precompiled.h" #include "ulduar.h" -#include "Vehicle.h" enum { //yells - SAY_AGGRO = -1603020, - SAY_SCORCH1 = -1603021, - SAY_SCORCH2 = -1603022, - SAY_SLAGPOT = -1603023, - EMOTE_FLAMEJETS = -1603024, - SAY_SUMMON = -1603025, - SAY_SLAY_1 = -1603026, - SAY_SLAY_2 = -1603027, - SAY_BERSERK = -1603028, - SAY_DEATH = -1603029, + SAY_AGGRO = -1603010, + SAY_SCORCH1 = -1603011, + SAY_SCORCH2 = -1603012, + SAY_SLAGPOT = -1603013, + EMOTE_FLAMEJETS = -1603014, + SAY_SUMMON = -1603015, + SAY_SLAY1 = -1603016, + SAY_SLAY2 = -1603017, + SAY_BERSERK = -1603018, + SAY_DEATH = -1603019, //ignis the furnace master SPELL_FLAME_JETS = 62680, - SPELL_FLAME_JETS_H = 63472, - SPELL_SCORCH_CHANNELED = 62546, - SPELL_SCORCH_CHANNELED_H = 63474, - SPELL_CHARGE_SLAG_POT = 62707, - SPELL_CHARGE_SLAG_POT_H = 63535, - SPELL_SLAG_POT_AURA = 62717, - SPELL_SLAG_POT_AURA_H = 63477, - - SPELL_SLAG_POT_DMG = 65722, + SPELL_FLAME_JETS_H = 63472, + SPELL_SLAG_POT = 62717, + SPELL_SLAG_POT_H = 63477, + SPELL_SLAG_POT_DMG = 65722, SPELL_SLAG_POT_DMG_H = 65723, + SPELL_SCORCH = 62546, + SPELL_SCORCH_H = 63474, + BUFF_STRENGHT_OF_CREATOR = 64473, + SPELL_STRENGHT_OF_CREATOR2 = 64474, + SPELL_STRENGHT_OF_CREATOR3 = 64475, + SPELL_HASTE = 66045, + SPELL_ENRAGE = 26662, + //iron construct + SPELL_HEAT = 65667, + SPELL_MOLTEN = 62373, + SPELL_BRITTLE = 62382, + SPELL_SHATTER = 62383, + //scorch target + AURA_SCORCH = 62548, + AURA_SCORCH_H = 63476, + AURA_HEAT = 65667, + SPELL_FREEZE_ANIM = 16245, + //NPC ids + MOB_IRON_CONSTRUCT = 33121, + MOB_SCORCH_TARGET = 33221, - SPELL_HASTE = 62836, + ACHIEV_STOKIN_THE_FURNACE = 2930, + ACHIEV_STOKIN_THE_FURNACE_H = 2929, + ACHIEV_SHATTERED = 2925, + ACHIEV_SHATTERED_H = 2926, +}; - // Scorch trigger - SPELL_SCORCH_AURA = 62548, - SPELL_SCORCH_AURA_H = 63476, +#define HOME_X 586.747009f +#define HOME_Y 381.997986f +// scorch target +struct MANGOS_DLL_DECL mob_scorch_targetAI : public ScriptedAI +{ + mob_scorch_targetAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + SetCombatMovement(false); + Reset(); + } - //iron construct - //NPC_IRON_CONSTRUCT = 33121, - SPELL_STONED = 62468, - SPELL_HEAT_AURA = 65667, - SPELL_MOLTEN = 62373, - SPELL_BRITTLE = 67114, - SPELL_BRITTLE_H = 62382, - SPELL_SHATTER = 62383, - SPELL_ACTIVATE_CONSTRUCT = 62488, - SPELL_STRENGTH_OF_THE_CREATOR = 64474, - SPELL_STRENGHT_OF_CREATOR_DIE= 64475, + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + uint32 m_uiDeath_Timer; - //NPC ids - SPELL_SUMMON_SCORCH_TRIGGER = 62551, - SPELL_SLAG_IMBUED = 62836, - SPELL_SLAG_IMBUED2 = 63536, - SPELL_MOLTEN_STUN = 65208, // couldn't find proper spell, so using this one - SCORCH_DESPAWN_TIME = 40000, + void Reset() + { + m_uiDeath_Timer = 55000; + m_creature->SetDisplayId(11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, m_bIsRegularMode ? AURA_SCORCH : AURA_SCORCH_H); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + if (m_uiDeath_Timer < diff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDeath_Timer -= diff; + } }; +CreatureAI* GetAI_mob_scorch_target(Creature* pCreature) +{ + return new mob_scorch_targetAI(pCreature); +} + // iron construct struct MANGOS_DLL_DECL mob_iron_constructAI : public ScriptedAI { mob_iron_constructAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; - bool m_bIsRegularMode; - bool m_bIsStoned; - bool m_bIsActive; - uint32 m_uiBrittleCheckTimer; + ScriptedInstance* m_pInstance; + + uint32 m_uiDeath_Timer; + uint32 m_uiAura_Check_Timer; + uint32 m_uiScorchTimer; + uint32 m_uiMoltenTimer; + uint32 m_uiBrittleTimer; + bool m_bIsBrittle; + bool m_bIsShatter; + bool m_bIsMolten; + bool m_bIsInCombat; + + uint32 m_uiWaterCheckTimer; void Reset() { - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_bIsStoned = false; - m_bIsActive = false; - m_uiBrittleCheckTimer = 500; + m_bIsShatter = false; + m_bIsBrittle = false; + m_bIsMolten = false; + m_bIsInCombat = false; + m_uiWaterCheckTimer = 1000; + m_uiScorchTimer = 5000; + m_uiAura_Check_Timer = 1000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); } - void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + void JustDied(Unit* pKiller) { - if (!m_bIsActive) - { - uiDamage = 0; + if (!m_pInstance) return; - } - if (m_creature->HasAura(SPELL_BRITTLE) || m_creature->HasAura(SPELL_BRITTLE_H)) + // remove 1 stack of the buff from Ignis, hacky way, should be done by spell + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_IGNIS)) { - if (uiDamage > (m_bIsRegularMode ? 3000 : 5000)) + if (pTemp->isAlive()) { - uiDamage = 0; - if (DoCastSpellIfCan(m_creature, SPELL_SHATTER, CAST_TRIGGERED) == CAST_OK) + if (pTemp->HasAura(BUFF_STRENGHT_OF_CREATOR)) { - m_creature->ForcedDespawn(1000); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(SpellAuraHolderPtr pStrenght = pTemp->GetSpellAuraHolder(BUFF_STRENGHT_OF_CREATOR)) + { + if(pStrenght->ModStackAmount(-1)) + pTemp->RemoveAurasDueToSpell(BUFF_STRENGHT_OF_CREATOR); + } } } } } - void JustDied(Unit* killer) + // shatter if is brittle + void DamageTaken(Unit *done_by, uint32 &uiDamage) { - DoCast(m_creature, SPELL_STRENGHT_OF_CREATOR_DIE, true); + if (m_bIsBrittle) + { + if (uiDamage > 5000) + { + DoCast(m_creature, SPELL_SHATTER); + m_bIsShatter = true; + m_bIsBrittle = false; + m_uiDeath_Timer = 500; + } + } } - void SpellHit(Unit* pCaster, const SpellEntry *spellInfo) + void AttackStart(Unit* pWho) { - if (spellInfo->Id == SPELL_ACTIVATE_CONSTRUCT) - { - m_creature->RemoveAurasDueToSpell(SPELL_STONED); + if(!m_bIsInCombat) + return; - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - m_bIsActive = true; - m_creature->SetInCombatWithZone(); - - DoCast(pCaster, SPELL_STRENGTH_OF_THE_CREATOR, true); + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho); } - else if (spellInfo->Id == SPELL_HEAT_AURA) + } + + // set in combat + void GetInCombat() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (m_creature->HasAura(SPELL_FREEZE_ANIM, EFFECT_INDEX_0)) + m_creature->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + m_bIsInCombat = true; + + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_IGNIS)) { - if (Aura* pHeat = m_creature->GetAura(SPELL_HEAT_AURA, EFFECT_INDEX_1)) + if (pTemp->isAlive()) { - if (pHeat->GetStackAmount() > 9) + m_creature->SetWalk(false); + m_creature->GetMotionMaster()->MovePoint(0, pTemp->GetPositionX(), pTemp->GetPositionY(), pTemp->GetPositionZ()); + + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - m_creature->RemoveAurasDueToSpell(SPELL_HEAT_AURA); - DoCastSpellIfCan(m_creature, SPELL_MOLTEN, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_MOLTEN_STUN, CAST_TRIGGERED); + m_creature->AddThreat(pTarget,100.0f); + m_creature->AI()->AttackStart(pTarget); + m_creature->SetInCombatWithZone(); } } } @@ -161,32 +231,54 @@ struct MANGOS_DLL_DECL mob_iron_constructAI : public ScriptedAI void UpdateAI(const uint32 uiDiff) { - if (!m_bIsStoned) - { - if (DoCastSpellIfCan(m_creature, SPELL_STONED) == CAST_OK) - m_bIsStoned = true; - } - - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() ) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (!m_bIsActive) - m_creature->AI()->EnterEvadeMode(); + // death after casted shatter + if (m_uiDeath_Timer < uiDiff && m_bIsShatter) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDeath_Timer -= uiDiff; - if (m_uiBrittleCheckTimer <= uiDiff) + // check for aura + if (m_uiAura_Check_Timer < uiDiff && !m_bIsMolten) { - if (m_creature->HasAura(SPELL_MOLTEN) && !m_creature->HasAura(SPELL_BRITTLE) ) + if(Aura* aura = m_creature->GetAura(SPELL_HEAT,EFFECT_INDEX_0)) { - if (m_creature->IsInWater()) + if(aura->GetStackAmount() > 9) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_BRITTLE : SPELL_BRITTLE_H, CAST_TRIGGERED) == CAST_OK) - m_creature->RemoveAurasDueToSpell(SPELL_MOLTEN); + DoCast(m_creature, SPELL_MOLTEN); + m_creature->RemoveAurasDueToSpell(SPELL_HEAT); + m_uiMoltenTimer = 30000; + m_bIsMolten = true; } } - m_uiBrittleCheckTimer = 500; + m_uiAura_Check_Timer = 1000; + }else m_uiAura_Check_Timer -= uiDiff; + + //Water checks + if(m_bIsMolten) + { + // should work with Vmaps3 + if (m_uiWaterCheckTimer <= uiDiff) + { + if(m_creature->IsInWater()) + { + DoCast(m_creature, SPELL_BRITTLE); + m_bIsBrittle = true; + m_bIsMolten = false; + } + // workaround + /* else use workaround + if( m_creature->GetDistance2d(524.15f, 277.0f) < 18 || m_creature->GetDistance2d(648.5f, 277.0f) < 18) + { + DoCast(m_creature, SPELL_BRITTLE); + m_creature->RemoveAurasDueToSpell(SPELL_MOLTEN); + m_bIsBrittle = true; + m_bIsMolten = false; + }*/ + m_uiWaterCheckTimer = 500; + }else m_uiWaterCheckTimer -= uiDiff; } - else - m_uiBrittleCheckTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -200,87 +292,130 @@ CreatureAI* GetAI_mob_iron_construct(Creature* pCreature) //ignis the furnace master struct MANGOS_DLL_DECL boss_ignisAI : public ScriptedAI { - boss_ignisAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_ignisAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - bool m_bIsSlagPot; - uint32 m_uiScorchTimer; - uint32 m_uiSlagPotTimer; - uint32 m_uiSlagPotSwitchTimer; - uint32 m_uiSlagPotExitTimer; - uint32 m_uiSlagPotDmgTimer; - uint32 m_uiFlameJetsTimer; - uint32 m_uiActivateConstructTimer; + std::list m_lIronConstructGUIDList; - uint32 m_uiBerserkerTimer; + uint32 m_uiFlame_Jets_Timer; + uint32 m_uiSlag_Pot_Timer; + uint32 m_uiSlag_Pot_Veichle_Timer; + uint32 m_uiScorch_Timer; + uint32 m_uiSummon_Timer; + uint32 m_uiPotDmgCount; + uint32 m_uiEnrageTimer; - void Reset() - { - m_uiScorchTimer = 12000; - m_uiSlagPotTimer = 19000; - m_uiFlameJetsTimer = 21000; - m_uiActivateConstructTimer = 25000; + ObjectGuid m_uiPotTargetGUID; + std::list lConstructs; - m_uiBerserkerTimer = 600000; // 10 Minutes + uint32 m_uiEncounterTimer; + bool m_bHasSlagPotCasted; - m_bIsSlagPot = false; + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + m_uiFlame_Jets_Timer = 20000; + m_uiSlag_Pot_Timer = 25000; + m_uiSlag_Pot_Veichle_Timer = 26000; + m_uiScorch_Timer = 13000; + m_uiSummon_Timer = 10000; + m_uiEnrageTimer = 600000; // 10 MIN + m_uiPotDmgCount = 0; + m_uiPotTargetGUID.Clear(); + m_lIronConstructGUIDList.clear(); + + m_uiEncounterTimer = 0; + m_bHasSlagPotCasted = false; } - void Aggro(Unit* pWho) + void JustDied(Unit* pKiller) { - DoScriptText(SAY_AGGRO, m_creature); - if (m_pInstance) - m_pInstance->SetData(TYPE_IGNIS , IN_PROGRESS); + m_pInstance->SetData(TYPE_IGNIS, DONE); + + DoScriptText(SAY_DEATH, m_creature); + + // kills constructs that are still in combat + GetCreatureListWithEntryInGrid(lConstructs, m_creature, MOB_IRON_CONSTRUCT, 200.0f); + if (!lConstructs.empty()) + { + for(std::list::iterator iter = lConstructs.begin(); iter != lConstructs.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive() && !(*iter)->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + (*iter)->DealDamage((*iter), (*iter)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + if (m_uiEncounterTimer < 240000) + { + // hacky way to complete achievements; use only if you have this function + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_STOKIN_THE_FURNACE : ACHIEV_STOKIN_THE_FURNACE_H); + } } - void JustReachedHome() + Creature* SelectRandomConstruct(float fRange) { - if (m_pInstance) - m_pInstance->SetData(TYPE_IGNIS, FAIL); - if (VehicleKit *pVehKit = m_creature->GetVehicleKit()) - pVehKit->RemoveAllPassengers(); + std::list lConstructList; + GetCreatureListWithEntryInGrid(lConstructList, m_creature, MOB_IRON_CONSTRUCT, fRange); + + if (lConstructList.empty()) + { + m_uiSummon_Timer = 5000; + return NULL; + } + + std::list::iterator iter = lConstructList.begin(); + advance(iter, urand(0, lConstructList.size()-1)); + + if((*iter)->isAlive()) + return *iter; + else + { + m_uiSummon_Timer = 500; + return NULL; + } } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() == TYPEID_PLAYER) - DoScriptText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); } - void JustDied(Unit* pKiller) + void Aggro(Unit* pWho) { - DoScriptText(SAY_DEATH, m_creature); - if (m_pInstance) - m_pInstance->SetData(TYPE_IGNIS, DONE); + m_pInstance->SetData(TYPE_IGNIS, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, m_creature); } - void JustSummoned(Creature* pCreature) + void JustReachedHome() { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SCORCH_CHANNELED : SPELL_SCORCH_CHANNELED_H) == CAST_OK && !pCreature->IsInWater()) + if (m_pInstance) + m_pInstance->SetData(TYPE_IGNIS, FAIL); + + // respawn constructs + GetCreatureListWithEntryInGrid(lConstructs, m_creature, MOB_IRON_CONSTRUCT, 200.0f); + if (!lConstructs.empty()) { - m_creature->AddThreat(pCreature, 100000000000000.0f, true); - m_creature->SetFacingToObject(pCreature); - pCreature->SetDisplayId(11686); - pCreature->SetInCombatWithZone(); - pCreature->ForcedDespawn(SCORCH_DESPAWN_TIME); + for(std::list::iterator iter = lConstructs.begin(); iter != lConstructs.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } } - else - pCreature->ForcedDespawn(); - } - - void DamageTaken(Unit *pDoneBy, uint32 &uiDamage) - { - if (pDoneBy->HasAura(SPELL_SLAG_POT_AURA) || pDoneBy->HasAura(SPELL_SLAG_POT_AURA_H)) - uiDamage = 0; } void UpdateAI(const uint32 uiDiff) @@ -288,108 +423,101 @@ struct MANGOS_DLL_DECL boss_ignisAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiScorchTimer <= uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_SCORCH_TRIGGER, CAST_TRIGGERED) == CAST_OK) - { - DoScriptText(urand(0,1) ? SAY_SCORCH1 : SAY_SCORCH2, m_creature); - m_uiScorchTimer = urand(20000, 25000); - } - } - else - m_uiScorchTimer -= uiDiff; + m_uiEncounterTimer += uiDiff; - if (m_uiSlagPotTimer <= uiDiff) + // enrage + if(m_uiEnrageTimer < uiDiff) { - if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - if (Player *pTarget = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself()) - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_CHARGE_SLAG_POT : SPELL_CHARGE_SLAG_POT_H) == CAST_OK) - { - DoScriptText(SAY_SLAGPOT, m_creature); - pTarget->EnterVehicle(m_creature->GetVehicleKit(), 0); - pTarget->CastSpell(pTarget, m_bIsRegularMode ? SPELL_SLAG_POT_AURA : SPELL_SLAG_POT_AURA_H, true, 0,0, m_creature->GetObjectGuid()); - m_bIsSlagPot = true; - m_uiSlagPotSwitchTimer = 1500; - m_uiSlagPotDmgTimer = 2000; - m_uiSlagPotExitTimer = 10000; - m_uiSlagPotTimer = urand(15000, 25000); - } + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_ENRAGE); + m_uiEnrageTimer = 30000; } - else - m_uiSlagPotTimer -= uiDiff; + else m_uiEnrageTimer -= uiDiff; - if (m_bIsSlagPot) + if (m_uiFlame_Jets_Timer < uiDiff) { - if (m_uiSlagPotSwitchTimer <= uiDiff) - { - if (VehicleKit *pVehKit = m_creature->GetVehicleKit()) - if (Unit *pPassenger = pVehKit->GetPassenger(0)) - { - pVehKit->RemovePassenger(pPassenger); - pVehKit->AddPassenger(pPassenger, 1); - } - m_uiSlagPotSwitchTimer = 10000; - m_uiSlagPotDmgTimer = 500; - } - else - m_uiSlagPotSwitchTimer -= uiDiff; + DoScriptText(EMOTE_FLAMEJETS, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_JETS : SPELL_FLAME_JETS_H); + m_uiFlame_Jets_Timer = 35000; + }else m_uiFlame_Jets_Timer -= uiDiff; - if (m_uiSlagPotDmgTimer <= uiDiff) + // need vehicle support!!! + if (m_uiSlag_Pot_Timer < uiDiff) + { + // to avoid the two spell to be casted too close + if (m_uiFlame_Jets_Timer < 4000) { - if (VehicleKit *pVehKit = m_creature->GetVehicleKit()) - if (Unit *pPassenger = pVehKit->GetPassenger(1)) - { - pPassenger->CastSpell(pPassenger, m_bIsRegularMode ? SPELL_SLAG_POT_DMG : SPELL_SLAG_POT_DMG_H, true ,0 ,0, m_creature->GetObjectGuid()); - } - m_uiSlagPotDmgTimer = 3000; + m_uiSlag_Pot_Timer += 5000; } else - m_uiSlagPotDmgTimer -= uiDiff; - - if (m_uiSlagPotExitTimer <= uiDiff) { - if (VehicleKit *pVehKit = m_creature->GetVehicleKit()) - pVehKit->RemoveAllPassengers(); - m_uiSlagPotExitTimer = 10000; - m_bIsSlagPot = false; + DoScriptText(SAY_SLAGPOT, m_creature); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + { + DoCast(target, m_bIsRegularMode ? SPELL_SLAG_POT : SPELL_SLAG_POT_H); + m_uiPotTargetGUID = target->GetObjectGuid(); + if(m_creature->GetVehicleKit()) + target->EnterVehicle(m_creature->GetVehicleKit(), 0); + } + m_uiSlag_Pot_Timer = 30000; + m_uiSlag_Pot_Veichle_Timer = 10000; + m_bHasSlagPotCasted = true; + m_uiPotDmgCount = 0; } - else - m_uiSlagPotExitTimer -= uiDiff; - } + }else m_uiSlag_Pot_Timer -= uiDiff; - if (m_uiFlameJetsTimer <= uiDiff) + // hacky way of removing veichle + if (m_uiSlag_Pot_Veichle_Timer < uiDiff && m_bHasSlagPotCasted) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FLAME_JETS : SPELL_FLAME_JETS_H) == CAST_OK) + if (Unit* pPotTarget = m_creature->GetMap()->GetUnit(m_uiPotTargetGUID)) { - DoScriptText(EMOTE_FLAMEJETS, m_creature); - m_uiFlameJetsTimer = urand(20000, 25000); + if(pPotTarget->isAlive()) + { + pPotTarget->CastSpell(pPotTarget, SPELL_HASTE, false); + pPotTarget->ExitVehicle(); + } + m_bHasSlagPotCasted = false; } - } - else - m_uiFlameJetsTimer -= uiDiff; + }else m_uiSlag_Pot_Veichle_Timer -= uiDiff; - if (m_uiActivateConstructTimer <= uiDiff) + // call the golems + if (m_uiSummon_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_ACTIVATE_CONSTRUCT) == CAST_OK) + DoScriptText(SAY_SUMMON, m_creature); + + if(Creature* pConstruct = SelectRandomConstruct(200.0f)) { - DoScriptText(SAY_SUMMON, m_creature); - m_uiActivateConstructTimer = m_bIsRegularMode ? 30000 : 40000; + ((mob_iron_constructAI*)pConstruct->AI())->GetInCombat(); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pConstruct->AddThreat(target, 100.0f); } - } - else - m_uiActivateConstructTimer -= uiDiff; - if (m_uiBerserkerTimer <= uiDiff) + m_uiSummon_Timer = 40000; + + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, BUFF_STRENGHT_OF_CREATOR); + }else m_uiSummon_Timer -= uiDiff; + + if (m_uiScorch_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature, 26662, CAST_AURA_NOT_PRESENT | CAST_TRIGGERED) == CAST_OK) + if(irand(0,1)) + DoScriptText(SAY_SCORCH1, m_creature); + else + DoScriptText(SAY_SCORCH2, m_creature); + + DoCast(m_creature, m_bIsRegularMode ? SPELL_SCORCH : SPELL_SCORCH_H); + if (Creature* pTemp = m_creature->SummonCreature(MOB_SCORCH_TARGET, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) { - DoScriptText(SAY_BERSERK, m_creature); + pTemp->AddThreat(m_creature->getVictim(),0.0f); + pTemp->AI()->AttackStart(m_creature->getVictim()); } - } - else - m_uiBerserkerTimer -= uiDiff; + m_uiScorch_Timer = 28000; + }else m_uiScorch_Timer -= uiDiff; DoMeleeAttackIfReady(); + + if (m_creature->GetDistance2d(HOME_X, HOME_Y) > 200) + EnterEvadeMode(); } }; @@ -407,6 +535,11 @@ void AddSC_boss_ignis() NewScript->GetAI = GetAI_boss_ignis; NewScript->RegisterSelf(); + NewScript = new Script; + NewScript->Name = "mob_scorch_target"; + NewScript->GetAI = &GetAI_mob_scorch_target; + NewScript->RegisterSelf(); + NewScript = new Script; NewScript->Name = "mob_iron_construct"; NewScript->GetAI = &GetAI_mob_iron_construct; diff --git a/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp b/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp index 361a776486..87d729b593 100644 --- a/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2011 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -16,103 +16,97 @@ /* ScriptData SDName: boss_kologarn -SD%Complete: achievment Wenn Blicke tten knnten -SDComment: eye beam +SD%Complete: +SDComment: SDCategory: Ulduar EndScriptData */ #include "precompiled.h" #include "ulduar.h" -#include "Vehicle.h" enum { //yells - SAY_AGGRO = -1603090, - SAY_SHOCKWEAVE = -1603091, - SAY_GRAB = -1603092, - SAY_LEFT_ARM_LOST = -1603093, - SAY_RIGHT_ARM_LOST = -1603094, - SAY_SLAY1 = -1603095, - SAY_SLAY2 = -1603096, - SAY_BERSERK = -1603097, - SAY_DEATH = -1603098, - EMOTE_RIGHT_ARM = -1603099, - EMOTE_LEFT_ARM = -1603100, - EMOTE_STONE_GRIP = -1603101, - - //kologarn - SPELL_OVERHEAD_SMASH = 63356, - SPELL_OVERHEAD_SMASH_H = 64003, - SPELL_ONE_ARMED_SMASH = 63573, - SPELL_ONE_ARMED_SMASH_H = 64006, - SPELL_STONE_SHOUT = 63716, - SPELL_STONE_SHOUT_H = 64005, - SPELL_PETRIFYING_BREATH = 62030, - SPELL_PETRIFYING_BREATH_H = 63980, - // Focused Eyebeam - SPELL_FOCUSED_EYEBEAM = 63342, - NPC_FOCUSED_EYEBEAM_RIGHT = 33802, - NPC_FOCUSED_EYEBEAM_LEFT = 33632, - SPELL_EYEBEAM_PERIODIC = 63347, - SPELL_EYEBEAM_PERIODIC_H = 63977, - SPELL_EYEBEAM_PERIODIC_VIS = 63369, - SPELL_EYEBEAM_SUMMON_LEFT = 63343, - SPELL_EYEBEAM_SUMMON_RIGHT = 63701, - SPELL_EYEBEAM_VISUAL_LEFT = 63352, - SPELL_EYEBEAM_VISUAL_LEFT_2 = 63702, - SPELL_EYEBEAM_VISUAL_RIGHT = 63676, - - SPELL_ENRAGE = 26662, - //left arm - SPELL_ARM_SWEEP = 63766, - SPELL_ARM_SWEEP_H = 63983, - SPELL_SHOCKWAVE = 63783, - SPELL_SHOCKWAVE_H = 63982, - //right arm - SPELL_STONE_GRIP_GRAB = 62166, - SPELL_STONE_GRIP_GRAB_H = 63981, - SPELL_STONE_GRIP = 64290, - SPELL_STONE_GRIP_H = 64292, - SPELL_STONE_GRIP_VEH = 62056, - SPELL_STONE_GRIP_VEH_H = 63985, - //both - SPELL_ARM_VISUAL = 64753, - //rubble - SPELL_RUMBLE = 63818, // on 10 man - SPELL_STONE_NOVA = 63978, // on 25 man + SAY_AGGRO = -1603150, + SAY_SHOCKWEAVE = -1603151, + SAY_GRAB = -1603152, + SAY_LEFT_ARM_LOST = -1603153, + SAY_RIGHT_ARM_LOST = -1603154, + SAY_SLAY1 = -1603155, + SAY_SLAY2 = -1603156, + SAY_BERSERK = -1603157, + SAY_DEATH = -1603158, + EMOTE_RIGHT_ARM = -1603355, + EMOTE_LEFT_ARM = -1603356, + EMOTE_STONE_GRIP = -1603357, + + //Kologarn + SPELL_OVERHEAD_SMASH = 63356, + SPELL_OVERHEAD_SMASH_H = 64003, + SPELL_ONE_ARMED_SMASH = 63573, + SPELL_ONE_ARMED_SMASH_H = 64006, + SPELL_STONE_SHOUT = 63716, + SPELL_STONE_SHOUT_H = 64005, + SPELL_PETRIFYING_BREATH = 62030, + SPELL_PETRIFYING_BREATH_H = 63980, + SPELL_FOCUSED_EYEBEAM_MOB = 63676, + SPELL_FOCUSED_EYEBEAM_RIGHT = 63702, + SPELL_FOCUSED_EYEBEAM_KOLOGARN = 63348, + SPELL_FOCUSED_EYEBEAM_DMG = 63347, + SPELL_FOCUSED_EYEBEAM_DMG_H = 63977, + SPELL_FOCUSED_EYEBEAM = 63346, + SPELL_FOCUSED_EYEBEAM_H = 63976, + + SPELL_ENRAGE = 26662, + //Left Arm + SPELL_ARM_SWEEP = 63766, + SPELL_ARM_SWEEP_H = 63983, + //Right Arm + SPELL_STONE_GRIP = 64290, + SPELL_STONE_GRIP_H = 64292, + //both arms + SPELL_ARM_VISUAL = 64753, + //Rubble + SPELL_RUMBLE = 63818, + SPELL_STONE_NOVA = 63978, //NPC ids - MOB_RUBBLE = 33768, - - RIGHT_ARM_SLOT = 1, - LEFT_ARM_SLOT = 0, - - - ACHIEV_RUBBLE_AND_ROLL = 2959, - ACHIEV_RUBBLE_AND_ROLL_H = 2960, - ACHIEV_WITH_OPEN_ARMS = 2951, - ACHIEV_WITH_OPEN_ARMS_H = 2952, - ACHIEV_DISARMED = 2953, - ACHIEV_DISARMED_H = 2954, - ACHIEV_IF_LOOKS_COULD_KILL = 2955, - ACHIEV_IF_LOOKS_COULD_KILL_H= 2956, + MOB_RUBBLE = 33768, + NPC_ARM_SWEEP_TARGET = 33661, + NPC_FOCUSED_EYEBEAM = 33632, + NPC_FOCUSED_EYEBEAM_RIGHT = 33802, + + POS_X = 1784, + POS_LEFT_Y = -45, + POS_RIGHT_Y = -4, + POS_Z = 449, + + MODEL_ID_INVISIBLE = 11686, + + ACHIEV_RUBBLE_AND_ROLL = 2959, + ACHIEV_RUBBLE_AND_ROLL_H = 2960, + ACHIEV_WITH_OPEN_ARMS = 2951, + ACHIEV_WITH_OPEN_ARMS_H = 2952, + ACHIEV_DISARMED = 2953, + ACHIEV_DISARMED_H = 2954, + ACHIEV_IF_LOOKS_COULD_KILL = 2955, + ACHIEV_IF_LOOKS_COULD_KILL_H = 2956, }; -float LeftArm[3] = {1784.742f, -39.962f, 448.805f}; -float RightArm[3] = {1785.615f, -5.516f, 448.810f}; -const float KoloFront[3] = {1771.683f, -24.230f, 448.806f}; +#define DEAD_X 1797.15f +#define DEAD_Y -24.4f +#define DEAD_Z 448.275f // Rubble struct MANGOS_DLL_DECL mob_ulduar_rubbleAI : public ScriptedAI { mob_ulduar_rubbleAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiStone_Nova_Timer; @@ -120,13 +114,15 @@ struct MANGOS_DLL_DECL mob_ulduar_rubbleAI : public ScriptedAI void Reset() { m_uiStone_Nova_Timer = urand(8000, 12000); - m_creature->SetRespawnDelay(DAY); } void UpdateAI(const uint32 diff) { - if (m_pInstance && m_pInstance->GetData(TYPE_KOLOGARN) != IN_PROGRESS) + if (m_pInstance && m_pInstance->GetData(TYPE_KOLOGARN) != IN_PROGRESS) + { m_creature->ForcedDespawn(); + return; + } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -135,7 +131,9 @@ struct MANGOS_DLL_DECL mob_ulduar_rubbleAI : public ScriptedAI { DoCast(m_creature, m_bIsRegularMode ? SPELL_RUMBLE : SPELL_STONE_NOVA); m_uiStone_Nova_Timer = urand(7000, 9000); - }else m_uiStone_Nova_Timer -= diff; + } + else + m_uiStone_Nova_Timer -= diff; DoMeleeAttackIfReady(); } @@ -146,548 +144,684 @@ CreatureAI* GetAI_mob_ulduar_rubble(Creature* pCreature) return new mob_ulduar_rubbleAI(pCreature); } -// Kologarn -struct MANGOS_DLL_DECL boss_kologarnAI : public ScriptedAI +// Left Arm +struct MANGOS_DLL_DECL boss_left_armAI : public ScriptedAI { - boss_kologarnAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_left_armAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - vehicle = m_creature->GetVehicleKit(); - SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; - VehicleKit* vehicle; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiSpell_Timer; - uint32 m_uiRange_Timer; - uint32 m_uiEyebeam_Timer; - uint32 m_uiRespawnRightTimer; - uint32 m_uiRespawnLeftTimer; - uint32 m_uiEnrageTimer; - - uint32 m_uiRubbleNo; - bool m_bHasLeftDied; - bool m_bHasRightDied; - uint32 m_uiDisarmedTimer; - bool m_bOpenArms; - bool m_bReset; - - bool m_bIsRightDead; - bool m_bIsLeftDead; - - ObjectGuid m_uiRightArmGuid; - ObjectGuid m_uiLeftArmGuid; + uint32 m_uiArmSweep_Timer; void Reset() { - if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - m_uiSpell_Timer = 10000; - m_uiRange_Timer = 1000; - m_uiEnrageTimer = 600000; - m_uiEyebeam_Timer = 10000 + urand(1000, 5000); - - m_bIsRightDead = false; - m_bIsLeftDead = false; - - m_bReset = false; - - - m_uiRubbleNo = 0; - m_bHasLeftDied = false; - m_bHasRightDied = false; - m_bOpenArms = true; - m_uiDisarmedTimer = 0; - - if (Unit* pRightArm = vehicle->GetPassenger(RIGHT_ARM_SLOT)) - { - pRightArm->SetVisibility(VISIBILITY_OFF); - pRightArm->DealDamage(pRightArm, pRightArm->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); - } - if (Unit *pLeftArm = vehicle->GetPassenger(LEFT_ARM_SLOT)) + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->ExitVehicle(); + m_uiArmSweep_Timer = 10000; + + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) { - pLeftArm->SetVisibility(VISIBILITY_OFF); - pLeftArm->DealDamage(pLeftArm, pLeftArm->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + if(Unit* TmpTarget = pKologarn->getVictim()) + m_creature->SetInCombatWith(TmpTarget); } - InstallLeftArm(); - InstallRightArm(); + m_creature->SetRespawnDelay(DAY); } - void JustDied(Unit* pKiller) + void JustRespawned() { - DoScriptText(SAY_DEATH, m_creature); - - if (m_pInstance) - m_pInstance->SetData(TYPE_KOLOGARN, DONE); - + DoCast(m_creature, SPELL_ARM_VISUAL); + m_creature->SetInCombatWithZone(); } - void LeftArmDead() + void Aggro(Unit* pWho) { - DoScriptText(SAY_LEFT_ARM_LOST, m_creature); - m_uiRespawnLeftTimer = 48000; - m_bIsLeftDead = true; - for(uint8 i = 0; i < 5; i ++) - { - if(Creature* pRubble = m_creature->SummonCreature(MOB_RUBBLE, LeftArm[0] - urand(0, 5), LeftArm[1] + urand(0, 10), LeftArm[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - pRubble->AddThreat(pTarget,0.0f); - } - m_uiRubbleNo = m_uiRubbleNo +5; if (m_pInstance) { - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_OPEN_ARMS, false); - if (m_uiRubbleNo >= 25) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_RUBBLE_AND_ROLL, true); - if (m_bIsRightDead) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_DISARMED, true); - else - m_uiDisarmedTimer = 0; + if (Creature* pRightArm = m_pInstance->GetSingleCreatureFromStorage(NPC_RIGHT_ARM)) + { + if (pRightArm->isAlive()) + pRightArm->SetInCombatWithZone(); + } + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + { + if (!m_creature->GetVehicle() && pKologarn->isAlive()) + { + m_creature->EnterVehicle(pKologarn->GetVehicleKit(), 0); + pKologarn->SetInCombatWithZone(); + } + } } + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->SetInCombatWithZone(); } - void RightArmDead() + void JustDied(Unit* pKiller) { - DoScriptText(SAY_RIGHT_ARM_LOST, m_creature); - m_uiRespawnRightTimer = 48000; - m_bIsRightDead = true; - m_bOpenArms = false; - for(uint8 i = 0; i < 5; i ++) + if (!m_pInstance) + return; + + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) { - if(Creature* pRubble = m_creature->SummonCreature(MOB_RUBBLE, RightArm[0] - urand(0, 5), RightArm[1] + urand(0, 10), RightArm[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - pRubble->AddThreat(pTarget,0.0f); + DoScriptText(SAY_LEFT_ARM_LOST, pTemp); + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } - m_uiRubbleNo = m_uiRubbleNo +5; - if (m_pInstance) + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiArmSweep_Timer < diff) { - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_OPEN_ARMS, false); - if (m_uiRubbleNo >= 25) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_RUBBLE_AND_ROLL, true); - if (m_bIsLeftDead) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_DISARMED, true); - else - m_uiDisarmedTimer = 0; + if (m_pInstance) + { + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + DoScriptText(SAY_SHOCKWEAVE, pKologarn); + } + + if (Creature* pArmSweepTarget = m_creature->SummonCreature(NPC_ARM_SWEEP_TARGET, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 500)) + { + pArmSweepTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pArmSweepTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, m_bIsRegularMode ? SPELL_ARM_SWEEP : SPELL_ARM_SWEEP_H); + } + m_uiArmSweep_Timer = 25000; } + else + m_uiArmSweep_Timer -= diff; } +}; - void Aggro(Unit* pWho) +CreatureAI* GetAI_boss_left_arm(Creature* pCreature) +{ + return new boss_left_armAI(pCreature); +} + +// Right Arm +struct MANGOS_DLL_DECL boss_right_armAI : public ScriptedAI +{ + boss_right_armAI(Creature* pCreature) : ScriptedAI(pCreature) { - if (m_pInstance) - m_pInstance->SetData(TYPE_KOLOGARN, IN_PROGRESS); - //aggro yell - DoScriptText(SAY_AGGRO, m_creature); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); } - void KilledUnit(Unit* pVictim) + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiStone_Grip_Timer; + uint32 m_uiFreeDamage; + uint32 m_uiMaxDamage; + ObjectGuid m_uiGripTargetGUID[3]; + uint8 m_uiMaxTargets; + bool m_bStoneGrip; + + void Reset() { - DoScriptText(urand(0,1) ? SAY_SLAY1 : SAY_SLAY2, m_creature); + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->ExitVehicle(); + m_uiStone_Grip_Timer = 16000; + m_uiMaxTargets = m_bIsRegularMode ? 1 : 3; + for (uint8 i = 0; i < m_uiMaxTargets; ++i) + m_uiGripTargetGUID[i].Clear(); + m_uiFreeDamage = 0; + m_bStoneGrip = false; + m_uiMaxDamage = m_bIsRegularMode ? 100000 : 480000; + + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + { + if(Unit* TmpTarget = pKologarn->getVictim()) + m_creature->SetInCombatWith(TmpTarget); + } + m_creature->SetRespawnDelay(DAY); } - void JustReachedHome() + void JustRespawned() { - if (m_pInstance) - m_pInstance->SetData(TYPE_KOLOGARN, FAIL); + DoCast(m_creature, SPELL_ARM_VISUAL); + m_creature->SetInCombatWithZone(); } - void InstallRightArm() + void Aggro(Unit* pWho) { - if (vehicle->HasEmptySeat(RIGHT_ARM_SLOT)) + if (m_pInstance) { - if (Creature *pRightArm = DoSpawnCreature(NPC_RIGHT_ARM, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 30000)) + if (Creature* pLeftArm = m_pInstance->GetSingleCreatureFromStorage(NPC_LEFT_ARM)) { - pRightArm->SetCreatorGuid(m_creature->GetObjectGuid()); - pRightArm->EnterVehicle(vehicle, RIGHT_ARM_SLOT); - pRightArm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - pRightArm->SendHeartBeat(); - m_uiRightArmGuid = pRightArm->GetObjectGuid(); + if (pLeftArm->isAlive()) + pLeftArm->SetInCombatWithZone(); } - } - DoScriptText(EMOTE_RIGHT_ARM, m_creature); - m_uiRespawnRightTimer = 48000; - m_bIsRightDead = false; - } - - void InstallLeftArm() - { - if (vehicle->HasEmptySeat(LEFT_ARM_SLOT)) - { - if (Creature *pLeftArm = DoSpawnCreature(NPC_LEFT_ARM, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 30000)) + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) { - pLeftArm->SetCreatorGuid(m_creature->GetObjectGuid()); - pLeftArm->EnterVehicle(vehicle, LEFT_ARM_SLOT); - pLeftArm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - pLeftArm->SendHeartBeat(); - m_uiLeftArmGuid = pLeftArm->GetObjectGuid(); + if (!m_creature->GetVehicle() && pKologarn->isAlive()) + { + m_creature->EnterVehicle(pKologarn->GetVehicleKit(), 1); + pKologarn->SetInCombatWithZone(); + } } } - DoScriptText(EMOTE_LEFT_ARM, m_creature); - m_uiRespawnLeftTimer = 48000; - m_bIsLeftDead = false; + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->SetInCombatWithZone(); } void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { - if (pDoneBy->GetObjectGuid() == m_creature->GetObjectGuid()) - uiDamage = 0; + if (m_bStoneGrip) + m_uiFreeDamage += uiDamage; } - - void UpdateAI(const uint32 uiDiff) + void JustDied(Unit* pKiller) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if (!m_pInstance) return; - // disarmed achiev check - if (m_bHasLeftDied || m_bHasRightDied) - m_uiDisarmedTimer += uiDiff; + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + { + DoScriptText(SAY_RIGHT_ARM_LOST, pTemp); + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } - if (m_uiDisarmedTimer > 12 * IN_MILLISECONDS) + for (uint8 i = 0; i < m_uiMaxTargets; ++i) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_DISARMED, false); + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiGripTargetGUID[i])) + { + pVictim->RemoveAurasDueToSpell(SPELL_STONE_GRIP); + pVictim->RemoveAurasDueToSpell(SPELL_STONE_GRIP_H); + pVictim->MonsterMoveJump(POS_X, POS_RIGHT_Y, POS_Z, 0, 60.0f, 2.0f); + } } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - if (m_uiRange_Timer < uiDiff) + if (m_bStoneGrip) { - m_bReset = true; - if (Map* pMap = m_creature->GetMap()) + if (m_uiFreeDamage > m_uiMaxDamage) { - Map::PlayerList const& pPlayers = pMap->GetPlayers(); - if (!pPlayers.isEmpty()) + for (uint8 i = 0; i < m_uiMaxTargets; ++i) { - for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiGripTargetGUID[i])) { - Player* pTarget = itr->getSource(); - if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, 45)) - { - m_bReset = false; - break; - } + pVictim->RemoveAurasDueToSpell(SPELL_STONE_GRIP); + pVictim->RemoveAurasDueToSpell(SPELL_STONE_GRIP_H); + pVictim->ExitVehicle(); + pVictim->MonsterMoveJump(POS_X, POS_RIGHT_Y, POS_Z, 0, 60.0f, 2.0f); } + m_uiGripTargetGUID[i].Clear(); } + m_bStoneGrip = false; } - if (m_bReset) - EnterEvadeMode(); - m_uiRange_Timer = 1000; - }else - m_uiRange_Timer -= uiDiff; - - // Hack for unexpected lose of one arm; often the right arm - if (!vehicle->GetPassenger(LEFT_ARM_SLOT)) - { - if (Map* pMap = m_creature->GetMap()) - if (Creature* pLeftArm = pMap->GetCreature(m_uiLeftArmGuid)) - if (pLeftArm->isAlive()) - pLeftArm->EnterVehicle(vehicle, LEFT_ARM_SLOT); } - if (!vehicle->GetPassenger(RIGHT_ARM_SLOT)) + if (m_uiStone_Grip_Timer < diff) { - if (Map* pMap = m_creature->GetMap()) - if (Creature* pRightArm = pMap->GetCreature(m_uiRightArmGuid)) - if (pRightArm->isAlive()) - pRightArm->EnterVehicle(vehicle, RIGHT_ARM_SLOT); - } - - if (m_uiSpell_Timer < uiDiff) - { - if (!m_bIsRightDead && !m_bIsLeftDead) - { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_OVERHEAD_SMASH : SPELL_OVERHEAD_SMASH_H); - m_uiSpell_Timer = 20000; - } - else if (m_bIsRightDead && m_bIsLeftDead) - { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STONE_SHOUT : SPELL_STONE_SHOUT_H); - m_uiSpell_Timer = 2000; - } - else + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) { - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ONE_ARMED_SMASH : SPELL_ONE_ARMED_SMASH_H); - m_uiSpell_Timer = 20000; - } - }else - m_uiSpell_Timer -= uiDiff; + DoScriptText(SAY_GRAB, pKologarn); + DoScriptText(EMOTE_STONE_GRIP, pKologarn); - if (m_uiEyebeam_Timer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, m_bIsRegularMode ? 4 : 10)) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) + for (uint8 i = 0; i < m_uiMaxTargets; ++i) { - //DoCast(m_creature->getVictim(), SPELL_FOCUSED_EYEBEAM, true); - if (Creature *pLeft = m_creature->SummonCreature(NPC_FOCUSED_EYEBEAM_LEFT, pTarget->GetPositionX(), pTarget->GetPositionY()-4.0f, pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 10000)) + Unit* pTarget = NULL; + for (uint8 j = 0; j < 25; ++j) { - pLeft->SetInCombatWithZone(); - pLeft->SetDisplayId(11686); - pLeft->SetSpeedRate(MOVE_RUN, 1.0); - pLeft->CastSpell(pLeft, m_bIsRegularMode ? SPELL_EYEBEAM_PERIODIC : SPELL_EYEBEAM_PERIODIC_H, true); - pLeft->CastSpell(pLeft, SPELL_EYEBEAM_VISUAL_LEFT_2, true); - pLeft->AI()->AttackStart(pTarget); + pTarget = pKologarn->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && !pTarget->GetVehicle()) + break; } - if (Creature *pRight = m_creature->SummonCreature(NPC_FOCUSED_EYEBEAM_RIGHT, pTarget->GetPositionX(), pTarget->GetPositionY()+4.0f, pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 10000)) + if (pTarget) { - pRight->SetInCombatWithZone(); - pRight->SetDisplayId(11686); - pRight->SetSpeedRate(MOVE_RUN, 1.0); - pRight->CastSpell(pRight, SPELL_EYEBEAM_PERIODIC_VIS, true); - pRight->CastSpell(pRight, SPELL_EYEBEAM_VISUAL_RIGHT, true); - pRight->AI()->AttackStart(pTarget); + pTarget->EnterVehicle(m_creature->GetVehicleKit(), i); + m_uiGripTargetGUID[i] = pTarget->GetObjectGuid(); + pTarget->CastSpell(pTarget, m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H, true); } - m_uiEyebeam_Timer = 10000 + urand(1000, 5000); } } - }else - m_uiEyebeam_Timer -= uiDiff; - - // respawn arms - if (m_bIsLeftDead) - { - if (m_uiRespawnLeftTimer < uiDiff && m_bIsLeftDead) - { - InstallLeftArm(); - }else - m_uiRespawnLeftTimer -= uiDiff; - } - if (m_bIsRightDead) - { - if (m_uiRespawnRightTimer < uiDiff) - { - InstallRightArm(); - }else - m_uiRespawnRightTimer -= uiDiff; - } - - //Petrifying breath - if (m_creature->GetCombatDistance(m_creature->getVictim()) >= ATTACK_DISTANCE) - DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_PETRIFYING_BREATH : SPELL_PETRIFYING_BREATH_H); - - if(m_uiEnrageTimer < uiDiff) - { - DoScriptText(SAY_BERSERK, m_creature); - DoCast(m_creature, SPELL_ENRAGE); - m_uiEnrageTimer = 30000; + m_uiFreeDamage = 0; + m_bStoneGrip = true; + m_uiStone_Grip_Timer = 16000; } else - m_uiEnrageTimer -= uiDiff; - - DoMeleeAttackIfReady(); + m_uiStone_Grip_Timer -= diff; } }; -CreatureAI* GetAI_boss_kologarn(Creature* pCreature) +CreatureAI* GetAI_boss_right_arm(Creature* pCreature) { - return new boss_kologarnAI(pCreature); + return new boss_right_armAI(pCreature); } -// Left Arm -struct MANGOS_DLL_DECL boss_left_armAI : public ScriptedAI +// Kologarn +struct MANGOS_DLL_DECL boss_kologarnAI : public ScriptedAI { - boss_left_armAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_kologarnAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - pCreature->SetRespawnDelay(7*DAY); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiShockwave_Timer; + uint32 m_uiSpell_Timer; + uint32 m_uiCheck_Timer; + uint32 m_uiEyebeam_Timer; + uint32 m_uiRespawnRightTimer; + uint32 m_uiRespawnLeftTimer; + uint32 m_uiEnrageTimer; + + bool m_bIsRightDead; + bool m_bIsLeftDead; + + uint32 m_uiRubbleNo; + uint32 m_uiDisarmedTimer; + bool m_bOpenArms; + bool m_bIfLooksCouldKill; void Reset() { - m_uiShockwave_Timer = 30000; - DoCast(m_creature, SPELL_ARM_VISUAL); + m_creature->SetStandState(UNIT_STAND_STATE_CUSTOM); + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_KOLOGARN) == DONE) + { + m_creature->SetDeathState(JUST_DIED); + m_creature->GetMap()->CreatureRelocation(m_creature, DEAD_X, DEAD_Y, DEAD_Z, 3.14159265358979323846f); + m_creature->MonsterMoveWithSpeed(DEAD_X, DEAD_Y, DEAD_Z, 10); + m_creature->SetCorpseDelay(WEEK); + return; + } + else + { + if (Creature* pLeftArm = m_pInstance->GetSingleCreatureFromStorage(NPC_LEFT_ARM)) + { + if (pLeftArm->isDead()) + pLeftArm->Respawn(); + else + pLeftArm->AI()->EnterEvadeMode(); + } + if (Creature* pRightArm = m_pInstance->GetSingleCreatureFromStorage(NPC_RIGHT_ARM)) + { + if (pRightArm->isDead()) + pRightArm->Respawn(); + else + pRightArm->AI()->EnterEvadeMode(); + } + } + } + + m_uiSpell_Timer = urand(15000, 20000); + m_uiCheck_Timer = 15000; + m_uiEnrageTimer = 600000; + m_uiEyebeam_Timer = 10000 + urand(1000, 5000); + m_uiRespawnLeftTimer = 30000; + m_uiRespawnRightTimer = 30000; + m_bIsRightDead = false; + m_bIsLeftDead = false; + + m_uiRubbleNo = 0; + m_bOpenArms = true; + m_uiDisarmedTimer = 0; + m_bIfLooksCouldKill = true; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_KOLOGARN, FAIL); + } + + void Aggro(Unit* pWho) + { + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_AGGRO, m_creature); + m_creature->SetInCombatWithZone(); + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_KOLOGARN, IN_PROGRESS); + + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_LEFT_ARM)) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_RIGHT_ARM)) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + } + } + + void KilledUnit(Unit* pVictim) + { + if (urand(0, 1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); } void JustDied(Unit* pKiller) { - if (!m_pInstance) - return; + DoScriptText(SAY_DEATH, m_creature); - if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + if (m_pInstance) { - if (pKologarn->isAlive()) - pKologarn->DealDamage(pKologarn, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + // hacky way to complete achievements; use only if you have this function + // Rubble and Roll + if (m_uiRubbleNo >= 25) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_RUBBLE_AND_ROLL : ACHIEV_RUBBLE_AND_ROLL_H); + + // With Open Arms + if (m_bOpenArms) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_WITH_OPEN_ARMS : ACHIEV_WITH_OPEN_ARMS_H); + + // Disarmed + if (m_bIsRightDead && m_bIsLeftDead && m_uiDisarmedTimer <= 12000) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_DISARMED : ACHIEV_DISARMED_H); - boss_kologarnAI* KologarnAI = (boss_kologarnAI*)pKologarn->AI(); - if(KologarnAI) + // If Looks Could Kill + if (m_bIfLooksCouldKill) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_IF_LOOKS_COULD_KILL : ACHIEV_IF_LOOKS_COULD_KILL_H); + + // Death yell + m_pInstance->SetData(TYPE_KOLOGARN, DONE); + + // Destroy arms + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_LEFT_ARM)) { - KologarnAI->LeftArmDead(); + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, pTemp->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_RIGHT_ARM)) + { + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, pTemp->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } } + + m_creature->SetDeathState(JUST_DIED); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+20.3f, 3.14159265358979323846f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+20.3f, 10); + m_creature->SetCorpseDelay(WEEK); } void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + { + Reset(); return; + } - if (m_uiShockwave_Timer < uiDiff) + if (m_uiSpell_Timer < uiDiff) { - if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) - DoScriptText(SAY_SHOCKWEAVE, pKologarn); + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + m_uiSpell_Timer = urand(15000, 20000); + if (!m_bIsRightDead && !m_bIsLeftDead) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_OVERHEAD_SMASH : SPELL_OVERHEAD_SMASH_H); + else if (m_bIsRightDead && m_bIsLeftDead) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STONE_SHOUT : SPELL_STONE_SHOUT_H); + m_uiSpell_Timer = 3000; + } + else + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ONE_ARMED_SMASH : SPELL_ONE_ARMED_SMASH_H); + } + } + else + m_uiSpell_Timer -= uiDiff; + + if (m_uiEyebeam_Timer < uiDiff) + { + Unit* pTarget = NULL; + for (uint8 i=0; i<25; ++i) + { + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + if (pTarget && m_creature->GetDistance2d(pTarget) > ATTACK_DISTANCE) + break; + } + if (!pTarget) + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + if (pTarget) + { + if (Creature* pTemp = m_creature->SummonCreature(NPC_FOCUSED_EYEBEAM, pTarget->GetPositionX(), pTarget->GetPositionY()+4.0f, pTarget->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + pTemp->CastSpell(m_creature, SPELL_FOCUSED_EYEBEAM_MOB, true); + pTemp->AddThreat(pTarget, 100000.0f); + } + if (Creature* pTemp = m_creature->SummonCreature(NPC_FOCUSED_EYEBEAM_RIGHT, pTarget->GetPositionX(), pTarget->GetPositionY()-4.0f, pTarget->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0)) + { + pTemp->CastSpell(m_creature, SPELL_FOCUSED_EYEBEAM_RIGHT, true); + pTemp->AddThreat(pTarget, 100000.0f); + } + } + m_uiEyebeam_Timer = urand(20000, 25000); + } + else + m_uiEyebeam_Timer -= uiDiff; + + // respawn arms + if (m_bIsLeftDead) + { + if (m_uiRespawnLeftTimer < uiDiff) + { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_LEFT_ARM)) + { + pTemp->Respawn(); + m_bIsLeftDead = false; + DoScriptText(EMOTE_LEFT_ARM, m_creature); + } + } + else + m_uiRespawnLeftTimer -= uiDiff; + } + + if (m_bIsRightDead) + { + if (m_uiRespawnRightTimer < uiDiff) + { + if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_RIGHT_ARM)) + { + pTemp->Respawn(); + m_bIsRightDead = false; + DoScriptText(EMOTE_RIGHT_ARM, m_creature); + } + } + else + m_uiRespawnRightTimer -= uiDiff; + } + + // check if arms are dead and if there is no player in melee range + if (m_uiCheck_Timer < uiDiff) + { + if (Creature* pLeftArm = m_pInstance->GetSingleCreatureFromStorage(NPC_LEFT_ARM)) + { + if (pLeftArm->isDead() && !m_bIsLeftDead) + { + m_bOpenArms = false; + + if (m_bIsRightDead) + { + m_uiSpell_Timer = 0; + m_uiDisarmedTimer = 0; + } - DoCast(m_creature, m_bIsRegularMode ? SPELL_ARM_SWEEP : SPELL_ARM_SWEEP_H); - m_uiShockwave_Timer = 17000; - }else m_uiShockwave_Timer -= uiDiff; + for (uint8 i = 0; i < 5; i ++) + { + if (Creature* pRubble = m_creature->SummonCreature(MOB_RUBBLE, POS_X-3+irand(0, 6), POS_LEFT_Y-5+irand(0, 10), POS_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pRubble->SetInCombatWithZone(); + m_uiRubbleNo += 1; + } + } + m_bIsLeftDead = true; + m_uiRespawnLeftTimer = 30000; + } + } + if (Creature* pRightArm = m_pInstance->GetSingleCreatureFromStorage(NPC_RIGHT_ARM)) + { + if (pRightArm->isDead() && !m_bIsRightDead) + { + m_bOpenArms = false; + + if (m_bIsLeftDead) + { + m_uiSpell_Timer = 0; + m_uiDisarmedTimer = 0; + } + + for (uint8 i = 0; i < 5; i ++) + { + if (Creature* pRubble = m_creature->SummonCreature(MOB_RUBBLE, POS_X-3+irand(0, 6), POS_RIGHT_Y-5+irand(0, 10), POS_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pRubble->SetInCombatWithZone(); + m_uiRubbleNo += 1; + } + } + m_bIsRightDead = true; + m_uiRespawnRightTimer = 30000; + } + } + + //Petrifying breath + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + if (m_creature->GetDistance2d(m_creature->getVictim()) > ATTACK_DISTANCE) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_PETRIFYING_BREATH : SPELL_PETRIFYING_BREATH_H); + } + + m_uiCheck_Timer = 1000; + } + else + m_uiCheck_Timer -= uiDiff; + + if (m_uiEnrageTimer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_ENRAGE); + m_uiEnrageTimer = 30000; + } + else + m_uiEnrageTimer -= uiDiff; + + if (!m_bIsRightDead || !m_bIsLeftDead) + DoMeleeAttackIfReady(); + else + m_uiDisarmedTimer += uiDiff; + + m_creature->SetUInt32Value(UNIT_FIELD_TARGET, 0); } }; -CreatureAI* GetAI_boss_left_arm(Creature* pCreature) +CreatureAI* GetAI_boss_kologarn(Creature* pCreature) { - return new boss_left_armAI(pCreature); + return new boss_kologarnAI(pCreature); } -// Right Arm -struct MANGOS_DLL_DECL boss_right_armAI : public ScriptedAI +// Focused Eyebeam +struct MANGOS_DLL_DECL mob_focused_eyebeamAI : public ScriptedAI { - boss_right_armAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_focused_eyebeamAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - vehicle = m_creature->GetVehicleKit(); - pCreature->SetRespawnDelay(7*DAY); - SetCombatMovement(false); + m_uiEntry = m_creature->GetEntry(); Reset(); } - instance_ulduar* m_pInstance; - VehicleKit* vehicle; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiStone_Grip_Timer; - uint32 m_uiFreeDamage; - uint32 m_uiMaxDamage; - std::list m_lGripTargetGUIDList; + uint32 m_uiEntry; + + uint32 m_uiStartMove_Timer; + uint32 m_uiStartDmg_Timer; void Reset() { - m_uiStone_Grip_Timer = 20000; - m_uiFreeDamage = 0; - m_uiMaxDamage = m_bIsRegularMode ? 80000 : 380000; - m_lGripTargetGUIDList.clear(); - DoCast(m_creature, SPELL_ARM_VISUAL); + SetCombatMovement(false); + m_creature->SetDisplayId(MODEL_ID_INVISIBLE); + m_uiStartMove_Timer = 1300; + m_uiStartDmg_Timer = 2000; + m_creature->ForcedDespawn(10000); } - void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) { - m_uiFreeDamage += uiDamage; - if (m_uiFreeDamage > m_uiMaxDamage) + if ((pSpell->Id == SPELL_FOCUSED_EYEBEAM || pSpell->Id == SPELL_FOCUSED_EYEBEAM_H) && pTarget->GetTypeId() == TYPEID_PLAYER) { - if (!m_lGripTargetGUIDList.empty()) + if (m_pInstance) { - for(std::list::iterator itr = m_lGripTargetGUIDList.begin(); itr != m_lGripTargetGUIDList.end(); ++itr) - if (Unit* pTemp = m_creature->GetMap()->GetUnit(*itr)) - { - pTemp->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H); - //pTemp->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP_VEH : SPELL_STONE_GRIP_VEH_H); - pTemp->RemoveAurasDueToSpell(54661); //HACK - pTemp->ExitVehicle(); - DoTeleportPlayer(pTemp,KoloFront[0],KoloFront[1],KoloFront[2],0.0f); - } + if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + ((boss_kologarnAI*)pKologarn->AI())->m_bIfLooksCouldKill = false; } - m_lGripTargetGUIDList.clear(); } } - void JustDied(Unit* pKiller) + void UpdateAI(const uint32 diff) { - if (!m_pInstance) - return; - - if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + if (m_pInstance && m_pInstance->GetData(TYPE_KOLOGARN) != IN_PROGRESS) { - if (pKologarn->isAlive()) - pKologarn->DealDamage(pKologarn, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - - boss_kologarnAI* KologarnAI = (boss_kologarnAI*)pKologarn->AI(); - if(KologarnAI) - { - KologarnAI->RightArmDead(); - } + m_creature->ForcedDespawn(); + return; } - if (!m_lGripTargetGUIDList.empty()) - { - for(std::list::iterator itr = m_lGripTargetGUIDList.begin(); itr != m_lGripTargetGUIDList.end(); ++itr) - if (Unit* pTemp = m_creature->GetMap()->GetUnit(*itr)) - { - pTemp->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H); - //pTemp->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP_VEH : SPELL_STONE_GRIP_VEH_H); - pTemp->RemoveAurasDueToSpell(54661); //HACK - pTemp->ExitVehicle(); - DoTeleportPlayer(pTemp,KoloFront[0],KoloFront[1],KoloFront[2],0.0f); - } - } - m_lGripTargetGUIDList.clear(); - } + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; - /*void SpellHitTarget(Unit* victim, const SpellEntry* spell) - { - if (spell->Id == SPELL_STONE_GRIP_GRAB || spell->Id == SPELL_STONE_GRIP_GRAB_H) + if (m_uiStartMove_Timer < diff) { - victim->CastSpell(victim, 54661 , true); //HACK - m_lGripTargetGUIDList.push_back(victim->GetObjectGuid()); - victim->EnterVehicle(vehicle); + float fDy = -4.0f; + if (m_uiEntry == NPC_FOCUSED_EYEBEAM_RIGHT) + fDy = 4.0f; + m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY()+fDy, m_creature->GetPositionZ()); + m_uiStartMove_Timer = 10000; } - }*/ - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + else + m_uiStartMove_Timer -= diff; - if (m_uiStone_Grip_Timer < uiDiff) + if (m_uiStartDmg_Timer < diff) { - if (Creature* pKologarn = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + if (m_uiEntry == NPC_FOCUSED_EYEBEAM_RIGHT) { - DoScriptText(SAY_GRAB, pKologarn); - DoScriptText(EMOTE_STONE_GRIP, m_creature); - for (int i = 0; i < (m_bIsRegularMode ? 1 : 3); ++i) - { - if (Unit* pTarget = pKologarn->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - pTarget->CastSpell(pTarget, 54661 , true);//HACK - pTarget->CastSpell(pTarget, m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H, true, 0, 0, pKologarn->GetObjectGuid()); - m_lGripTargetGUIDList.push_back(pTarget->GetObjectGuid()); - pTarget->EnterVehicle(vehicle, i+1); - } - } - m_uiFreeDamage = 0; - m_uiStone_Grip_Timer = 30000; - //DoCast(m_creature, m_bIsRegularMode ? SPELL_STONE_GRIP_GRAB : SPELL_STONE_GRIP_GRAB_H, true); + m_creature->ForcedDespawn(); + return; } - }else m_uiStone_Grip_Timer -= uiDiff; + DoCast(m_creature, SPELL_FOCUSED_EYEBEAM_KOLOGARN, true); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FOCUSED_EYEBEAM_DMG : SPELL_FOCUSED_EYEBEAM_DMG_H, true); + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_uiStartDmg_Timer = 10000; + } + else + m_uiStartDmg_Timer -= diff; } }; -CreatureAI* GetAI_boss_right_arm(Creature* pCreature) -{ - return new boss_right_armAI(pCreature); -} - -// Focused Eyebeam trigger mobs - just make them not attack in melee -struct MANGOS_DLL_DECL mob_eyebeam_triggerAI : public ScriptedAI -{ - mob_eyebeam_triggerAI(Creature* pCreature) : ScriptedAI(pCreature){} - void Reset(){} - void UpdateAI(const uint32 uiDiff){} -}; -CreatureAI* GetAI_mob_eyebeam_trigger(Creature* pCreature) +CreatureAI* GetAI_mob_focused_eyebeam(Creature* pCreature) { - return new mob_eyebeam_triggerAI(pCreature); + return new mob_focused_eyebeamAI(pCreature); } // kologarn kill pit bunny - kills players that fall down into the pit. also handling bridge respawn after server restarts @@ -695,11 +829,11 @@ struct MANGOS_DLL_DECL mob_kologarn_pit_kill_bunnyAI : public ScriptedAI { mob_kologarn_pit_kill_bunnyAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_fPositionZ = m_creature->GetPositionZ(); m_bBridgeLocked = false; } - instance_ulduar *m_pInstance; + ScriptedInstance* m_pInstance; float m_fPositionZ; bool m_bBridgeLocked; void Reset(){} @@ -709,19 +843,17 @@ struct MANGOS_DLL_DECL mob_kologarn_pit_kill_bunnyAI : public ScriptedAI { if (m_pInstance) { - if (Creature *pKolo = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN)) + Creature *pKolo = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN); + if (!pKolo || pKolo && !pKolo->isAlive()) { - if (!pKolo->isAlive()) - { - if (GameObject *pGo = m_pInstance->GetSingleGameObjectFromStorage(GO_KOLOGARN_BRIDGE)) - { - pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); - pGo->SetGoState(GO_STATE_READY); - } - if (Creature *pBridge = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN_BRIDGE_DUMMY)) - pBridge->SetVisibility(VISIBILITY_ON); - m_bBridgeLocked = true; + if (GameObject *pGo = m_pInstance->GetSingleGameObjectFromStorage(GO_KOLOGARN_BRIDGE)) + { + pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGo->SetGoState(GO_STATE_READY); } + if (Creature *pBridge = m_pInstance->GetSingleCreatureFromStorage(NPC_KOLOGARN_BRIDGE_DUMMY)) + pBridge->SetVisibility(VISIBILITY_ON); + m_bBridgeLocked = true; } } } @@ -734,6 +866,7 @@ struct MANGOS_DLL_DECL mob_kologarn_pit_kill_bunnyAI : public ScriptedAI pWho->DealDamage(pWho, pWho->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); } }; + CreatureAI* GetAI_mob_kologarn_pit_kill_bunny(Creature* pCreature) { return new mob_kologarn_pit_kill_bunnyAI(pCreature); @@ -753,21 +886,21 @@ void AddSC_boss_kologarn() NewScript->GetAI = &GetAI_mob_ulduar_rubble; NewScript->RegisterSelf(); + NewScript = new Script; + NewScript->Name = "mob_focused_eyebeam"; + NewScript->GetAI = &GetAI_mob_focused_eyebeam; + NewScript->RegisterSelf(); + NewScript = new Script; NewScript->Name = "boss_left_arm"; NewScript->GetAI = &GetAI_boss_left_arm; NewScript->RegisterSelf(); - + NewScript = new Script; NewScript->Name = "boss_right_arm"; NewScript->GetAI = &GetAI_boss_right_arm; NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "mob_eyebeam_trigger"; - NewScript->GetAI = &GetAI_mob_eyebeam_trigger; - NewScript->RegisterSelf(); - + NewScript = new Script; NewScript->Name = "mob_kologarn_pit_kill_bunny"; NewScript->GetAI = &GetAI_mob_kologarn_pit_kill_bunny; diff --git a/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp b/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp index 6410b62b9a..b93bf68180 100644 --- a/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp @@ -17,39 +17,37 @@ /* ScriptData SDName: boss_mimiron SD%Complete: -SDComment: TODO Achievments: Set Up Us the Bomb;Not-So-Friendly Fire +SDComment: needs vehicles SDCategory: Ulduar EndScriptData */ #include "precompiled.h" #include "ulduar.h" -#include "Vehicle.h" enum { //yells - SAY_AGGRO = -1603220, - SAY_HARD_MODE = -1603221, - SAY_BERSERK = -1603222, - SAY_TANK_ACTIVE = -1603223, - SAY_TANK_SLAY1 = -1603224, - SAY_TANK_SLAY2 = -1603225, - SAY_TANK_DEATH = -1603226, - SAY_TORSO_ACTIVE = -1603227, - SAY_TORSO_SLAY1 = -1603228, - SAY_TORSO_SLAY2 = -1603229, - SAY_TORSO_DEATH = -1603230, - SAY_HEAD_ACTIVE = -1603231, - SAY_HEAD_SLAY1 = -1603232, - SAY_HEAD_SLAY2 = -1603233, - SAY_HEAD_DEATH = -1603234, - SAY_ROBOT_ACTIVE = -1603235, - SAY_ROBOT_SLAY1 = -1603236, - SAY_ROBOT_SLAY2 = -1603237, - SAY_ROBOT_DEATH = -1603238, - - EMOTE_PLASMA_BLAST = -1603240, - EMOTE_LASER_SLAVE = -1603241, + SAY_AGGRO = -1603241, + SAY_HARD_MODE = -1603242, + SAY_BERSERK = -1603243, + SAY_TANK_ACTIVE = -1603244, + SAY_TANK_SLAY1 = -1603245, + SAY_TANK_SLAY2 = -1603246, + SAY_TANK_DEATH = -1603247, + SAY_TORSO_ACTIVE = -1603248, + SAY_TORSO_SLAY1 = -1603249, + SAY_TORSO_SLAY2 = -1603250, + SAY_TORSO_DEATH = -1603251, + SAY_HEAD_ACTIVE = -1603252, + SAY_HEAD_SLAY1 = -1603253, + SAY_HEAD_SLAY2 = -1603254, + SAY_HEAD_DEATH = -1603255, + SAY_ROBOT_ACTIVE = -1603256, + SAY_ROBOT_SLAY1 = -1603257, + SAY_ROBOT_SLAY2 = -1603258, + SAY_ROBOT_DEATH = -1603259, + + EMOTE_PLASMA_BLAST = -1603371, SPELL_JET_PACK = 63341, // used by mimiron to change seats SPELL_SELF_REPAIR = 64383, @@ -69,7 +67,7 @@ enum //spells //leviathan SPELL_PROXIMITY_MINES = 63016, // also in phase 4 - SPELL_MINE_SUMMON_10 = 63027, + SPELL_MINE_SUMMON = 65347, MOB_PROXIMITY_MINE = 34362, SPELL_EXPLOSION = 66351, SPELL_EXPLOSION_H = 63009, @@ -82,25 +80,18 @@ enum LEVIATHAN_TURRET = 34071, //vx001 - SPELL_RAPID_BURST_LEFT = 63387, - SPELL_RAPID_BURST_RIGHT = 64019, - SPELL_RAPID_BURST_LEFT_H= 64531, - SPELL_RAPID_BURST_RIGHT_H= 64532, + SPELL_RAPID_BURST = 63387, + SPELL_RAPID_BURST_H = 64531, SPELL_LASER_BARRAGE = 63293, // also in phase 4 SPELL_LASER_VISUAL = 63300, SPELL_LASER_TRIGG = 63274, - SPELL_LASER_SLAVE = 63414, SPELL_ROCKET_STRIKE = 64064, - SPELL_ROCKET_TRIGGER = 63036, - NPC_ROCKET_STRIKE = 34047, + NPC_MIMIRON_FOCUS = 33835, //33369 SPELL_HEAT_WAVE = 63677, SPELL_HEAT_WAVE_H = 64533, - SPELL_HAND_PULSE_LEFT = 64348, // only in phase 4 - SPELL_HAND_PULSE_RIGHT = 64352, - SPELL_HAND_PULSE_LEFT_H = 64536, - SPELL_HAND_PULSE_RIGHT_H= 64537, - + SPELL_HAND_PULSE = 64348, // only in phase 4 SPELL_FLAME_SUPRESS = 65192, // used by robot in melee range + SPELL_HAND_PULSE_H = 64536, // frostbomb SPELL_FROST_BOMB_EXPL = 64626, @@ -109,10 +100,8 @@ enum SPELL_FROST_BOMB_SUMMON = 64627, // summon the frostbomb //aerial unit - SPELL_PLASMA_BALL_FLY = 63689, // in phase 2 - SPELL_PLASMA_BALL_FLY_H = 64535, // in phase 2 - SPELL_PLASMA_BALL = 65647, // in phase 4, i use this spell also in phase 2, because aerial unit not move - SPELL_PLASMA_BALL_H = 65648, // in phase 4 + SPELL_PLASMA_BALL = 63689, // also in phase 4 + SPELL_PLASMA_BALL_H = 64535, // also in phase 4 MOB_ASSALT_BOT = 34057, MOB_BOMB_BOT = 33836, MOB_BOMB_BOT_321 = 33346, @@ -137,9 +126,6 @@ enum SPELL_MIMIRONS_INFERNO2 = 62909, // maybe hard mode SPELL_BERSERK = 26662, - // vehicle - SEAT_FOR_ROBOT = 3, - ACHIEV_FIREFIGHTER = 3180, ACHIEV_FIREFIGHTER_H = 3189, }; @@ -186,15 +172,14 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI { boss_leviathan_mkAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - pVehicleTank = pCreature->GetVehicleKit(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; - VehicleKit* pVehicleTank; + ScriptedInstance* m_pInstance; bool m_bStartAttack; @@ -203,18 +188,17 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI uint32 m_uiPlasmaBlastTimer; uint32 m_uiShockBlastTimer; - bool m_bHasSuppresed; + bool m_bHasSuppresed; uint32 m_uiSupressTimer; uint32 m_uiSetFireTimer; // outro - bool m_bIsOutro; + bool m_bIsOutro; uint32 m_uiOutroTimer; uint32 m_uiOutroStep; - bool m_bMustRepair; - - ObjectGuid m_TurretGuid; + bool m_bMustRepair; + uint32 m_uiRepairTimer; void Reset() { @@ -231,23 +215,12 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI m_uiOutroStep = 1; m_bIsOutro = false; m_bMustRepair = false; + m_uiRepairTimer = 15000; m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if(m_pInstance) m_pInstance->SetData(TYPE_LEVIATHAN_MK, NOT_STARTED); - - if (Creature* pTurret = m_creature->GetMap()->GetCreature(m_TurretGuid)) - pTurret->ForcedDespawn(); - - if (!pVehicleTank->GetPassenger(SEAT_FOR_ROBOT)) - { - if (Creature* pTurret = DoSpawnCreature(LEVIATHAN_TURRET, 0, 0, 0, 0, TEMPSUMMON_DEAD_DESPAWN, 60000)) - { - pTurret->EnterVehicle(pVehicleTank, SEAT_FOR_ROBOT); - m_TurretGuid = pTurret->GetObjectGuid(); - } - } } void AttackStart(Unit* pWho) @@ -255,38 +228,44 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI if(!m_bStartAttack) return; - if (m_creature->Attack(pWho, true)) - { - m_creature->AddThreat(pWho); - m_creature->SetInCombatWith(pWho); - pWho->SetInCombatWith(m_creature); - if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN || m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) - DoStartMovement(pWho); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + DoStartMovement(pWho); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } - void DamageTaken(Unit* pDealer, uint32& uiDamage) + void DamageTaken(Unit *done_by, uint32 &uiDamage) { - if (m_pInstance) + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + { + if(m_creature->GetHealthPercent() < 1.0f) + { + uiDamage = 0; + m_bIsOutro = true; + } + } + // hacky way for feign death + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - if(m_creature->GetHealth() <= uiDamage) + if(uiDamage > m_creature->GetHealth() && !m_bMustRepair) { uiDamage = 0; - if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) - m_bIsOutro = true; + m_creature->SetHealth(0); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); + m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + m_bMustRepair = true; + m_uiRepairTimer = 15000; + DoCast(m_creature, SPELL_SELF_REPAIR); - // for feign death - else if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) - { - if (m_pInstance->GetData(TYPE_LEVIATHAN_MK) != SPECIAL) - m_creature->InterruptNonMeleeSpells(true); - m_creature->SetStandState(UNIT_STAND_STATE_DEAD); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - m_bMustRepair = true; - DoCast(m_creature, SPELL_SELF_REPAIR); + if(m_pInstance) m_pInstance->SetData(TYPE_LEVIATHAN_MK, SPECIAL); - } } } } @@ -297,88 +276,45 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI { if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) { - DoScriptText(urand(0,1) ? SAY_TANK_SLAY1 : SAY_TANK_SLAY2, pMimiron); + if(irand(0,1)) + DoScriptText(SAY_TANK_SLAY1, pMimiron); + else + DoScriptText(SAY_TANK_SLAY2, pMimiron); } if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - DoScriptText(urand(0,1) ? SAY_ROBOT_SLAY1 : SAY_ROBOT_SLAY2, pMimiron); + if(irand(0,1)) + DoScriptText(SAY_ROBOT_SLAY1, pMimiron); + else + DoScriptText(SAY_ROBOT_SLAY2, pMimiron); } } } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + // hacky way for phase 4. needs rewriging when vehicles are fixed + void SetPhase() { - if (pSpell->Id == SPELL_SELF_REPAIR) - { - m_creature->MonsterSay("Selbst reperatur hat mich getroffen",0); - m_bMustRepair = false; - m_creature->SetStandState(UNIT_STAND_STATE_STAND); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - m_bIsOutro = false; - m_uiMinesTimer = 10000; - m_uiShockBlastTimer = 30000; - m_bStartAttack = true; - m_creature->SetInCombatWithZone(); - - if(m_pInstance) - m_pInstance->SetData(TYPE_LEVIATHAN_MK, IN_PROGRESS); - } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsOutro = false; + m_uiMinesTimer = 10000; + m_uiShockBlastTimer = 30000; + m_bStartAttack = true; + // look like a robot + SetCombatMovement(false); } - void MovementInform(uint32 uiMovementType, uint32 uiData) + // hacky way for phase 4. needs rewriging when vehicles are fixed + void Repair() { - if (m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_INTRO) - { - m_bStartAttack = true; - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetInCombatWithZone(); - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_LEVIATHAN); - } - else if (m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_TRANS_3) - { - if (Creature* pMimiron = m_pInstance->GetSingleCreatureFromStorage(NPC_MIMIRON)) - { - DoScriptText(SAY_ROBOT_ACTIVE, pMimiron); - } - - m_bStartAttack = true; - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetInCombatWithZone(); - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_ROBOT); - m_creature->SetHealthPercent(50.0f); - if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) - { - if (VehicleKit* pVehicleTank = m_creature->GetVehicleKit()) - { - pVehicleTank->RemoveAllPassengers(); - pTorso->EnterVehicle(pVehicleTank, SEAT_FOR_ROBOT); - } - - if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) - { - if (VehicleKit* pVehicleTorso = pTorso->GetVehicleKit()) - { - pHead->EnterVehicle(pVehicleTorso, SEAT_FOR_ROBOT); - } - } - else - m_creature->MonsterSay("Kopf nicht gefunden",0); - }else - m_creature->MonsterSay("Torso nicht gefunden.", 0); - } + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.5); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); + SetPhase(); - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) - { - // start again 3 fires - for(uint8 i = 0; i < 3; i++) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - pTarget->InterruptNonMeleeSpells(true); - pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); - } - } - } + if(m_pInstance) + m_pInstance->SetData(TYPE_LEVIATHAN_MK, IN_PROGRESS); } void JustSummoned(Creature* pSummon) @@ -408,74 +344,104 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if(m_uiRepairTimer < uiDiff && m_bMustRepair) + { + SetPhase(); + Repair(); + m_bMustRepair = false; + } + else m_uiRepairTimer -= uiDiff; + // return if repairing if(m_bMustRepair) return; + // this should be removed when vehicles are implemented! The are casted by the turret + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + { + if(m_uiPlasmaBlastTimer < uiDiff) + { + DoScriptText(EMOTE_PLASMA_BLAST, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BLAST : SPELL_PLASMA_BLAST_H); + m_uiPlasmaBlastTimer = 30000; + } + else m_uiPlasmaBlastTimer -= uiDiff; + + if(m_uiNapalmTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if(!m_creature->IsWithinDistInMap(pTarget, 15)) + { + DoCast(pTarget, m_bIsRegularMode ? SPELL_NAPALM_SHELL : SPELL_NAPALM_SHELL_H); + m_uiNapalmTimer = 7000; + } + } + } + else m_uiNapalmTimer -= uiDiff; + } + // proximity mines if(m_uiMinesTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_MINE_SUMMON_10) == CAST_OK) - m_uiMinesTimer = 30000; + //DoCast(m_crreature, SPELL_PROXIMITY_MINES); + for(uint8 i = 0; i < urand(8, 10); i++) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = m_creature->GetPositionX() + 15*cos(angle*(M_PI/180)); + float homeY = m_creature->GetPositionY() + 15*sin(angle*(M_PI/180)); + m_creature->SummonCreature(MOB_PROXIMITY_MINE, homeX, homeY, m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 10000); + } + m_uiMinesTimer = 30000; } - else - m_uiMinesTimer -= uiDiff; + else m_uiMinesTimer -= uiDiff; // shock blast if(m_uiShockBlastTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_SHOCK_BLAST) == CAST_OK) - m_uiShockBlastTimer = 50000; + DoCast(m_creature, SPELL_SHOCK_BLAST); + m_uiShockBlastTimer = 50000; } - else - m_uiShockBlastTimer -= uiDiff; + else m_uiShockBlastTimer -= uiDiff; // hard mode script - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS && m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) { - DoCastSpellIfCan(m_creature, SPELL_EMERGENCY_MODE, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); - - if (m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + if(m_creature->GetHealthPercent() < 50.0f && !m_bHasSuppresed) { - if(m_creature->GetHealthPercent() < 50.0f && !m_bHasSuppresed) - { - if (DoCastSpellIfCan(m_creature, SPELL_FLAME_SUPRESSANT) == CAST_OK) - { - m_bHasSuppresed = true; - m_uiSupressTimer = 2000; - m_uiSetFireTimer = 10000; - } - } + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FLAME_SUPRESSANT); + m_bHasSuppresed = true; + m_uiSupressTimer = 2000; + m_uiSetFireTimer = 10000; + } - if(m_uiSupressTimer < uiDiff && m_bHasSuppresed) - { - SuppressFires(); - m_uiSupressTimer = 600000; - } - else - m_uiSupressTimer -= uiDiff; + if(m_uiSupressTimer < uiDiff && m_bHasSuppresed) + { + SuppressFires(); + m_uiSupressTimer = 600000; + } + else m_uiSupressTimer -= uiDiff; - if(m_uiSetFireTimer < uiDiff && m_bHasSuppresed) + if(m_uiSetFireTimer < uiDiff && m_bHasSuppresed) + { + // start again 3 fires + for(uint8 i = 0; i < 3; i++) { - // start again 3 fires - for(uint8 i = 0; i < 3; i++) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - pTarget->InterruptNonMeleeSpells(true); - pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); - } + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); } - m_uiSetFireTimer = 600000; } - else - m_uiSetFireTimer -= uiDiff; + m_uiSetFireTimer = 600000; } + else m_uiSetFireTimer -= uiDiff; } DoMeleeAttackIfReady(); } - // outro for phase 1 if(m_bIsOutro) { @@ -511,7 +477,7 @@ struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI { ++m_uiOutroStep; m_uiOutroTimer = 330000; - } m_uiOutroTimer -= uiDiff; + } m_uiOutroTimer -= uiDiff; } }; @@ -520,63 +486,57 @@ struct MANGOS_DLL_DECL boss_vx001AI : public ScriptedAI { boss_vx001AI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bStartAttack; uint32 m_uiAttackStartTimer; + uint32 m_uiRapidBurstTimer; uint32 m_uiLaserBarrageTimer; - uint32 m_uiLaserBarrageTick; uint32 m_uiRocketStrikeTimer; uint32 m_uiHeatWaveTimer; + uint32 m_uiHandPulseTimer; uint32 m_uiFlameSuppressTimer; uint32 m_uiFrostBombTimer; uint32 m_uiSpreadFiresTimer; + uint32 m_uiRepairTimer; bool m_bMustRepair; - uint32 m_uiStandardAttack; - - bool m_bFireLeft; - void Reset() { - m_bFireLeft = true; - m_bStartAttack = false; m_uiAttackStartTimer = 12000; m_bMustRepair = false; + m_uiRepairTimer = 15000; + m_uiRapidBurstTimer = 1000; m_uiLaserBarrageTimer = 60000; - m_uiLaserBarrageTick = 100; m_uiRocketStrikeTimer = 25000; m_uiHeatWaveTimer = 20000; - - m_uiStandardAttack = 1000; + m_uiHandPulseTimer = 1000; m_uiFlameSuppressTimer = urand(10000, 15000); m_uiFrostBombTimer = urand(25000, 30000); m_uiSpreadFiresTimer = urand(40000, 50000); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if(m_pInstance) m_pInstance->SetData(TYPE_VX001, NOT_STARTED); - } void AttackStart(Unit* pWho) { - if(!m_bStartAttack && m_pInstance->GetData(TYPE_MIMIRON_PHASE) != PHASE_ROBOT) + if(!m_bStartAttack) return; if (m_creature->Attack(pWho, true)) @@ -594,57 +554,89 @@ struct MANGOS_DLL_DECL boss_vx001AI : public ScriptedAI { if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) { - DoScriptText(urand(0,1) ? SAY_TORSO_SLAY1 : SAY_TORSO_SLAY2, pMimiron); + if(irand(0,1)) + DoScriptText(SAY_TORSO_SLAY1, pMimiron); + else + DoScriptText(SAY_TORSO_SLAY2, pMimiron); } if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - DoScriptText(urand(0,1) ? SAY_ROBOT_SLAY1 : SAY_ROBOT_SLAY2, pMimiron); + if(irand(0,1)) + DoScriptText(SAY_ROBOT_SLAY1, pMimiron); + else + DoScriptText(SAY_ROBOT_SLAY2, pMimiron); + } + } + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void SetPhase() + { + //SetCombatMovement(true); + m_uiLaserBarrageTimer = 60000; + m_uiRocketStrikeTimer = 25000; + m_uiHandPulseTimer = 1000; + + // look like a robot + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 3, 0.0f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 3, 26); + } + + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + { + if (Creature* pMimiron = m_pInstance->GetSingleCreatureFromStorage(NPC_MIMIRON)) + DoScriptText(SAY_TORSO_DEATH, pMimiron); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_2); + m_pInstance->SetData(TYPE_VX001, DONE); } } } void DamageTaken(Unit *done_by, uint32 &uiDamage) { - if (m_pInstance) + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + return; + + // hacky way for feign death, needs fixing + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - if(m_creature->GetHealth() <= uiDamage) + if(uiDamage > m_creature->GetHealth()) { uiDamage = 0; + m_creature->SetHealth(0); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); m_bMustRepair = true; - if (m_pInstance->GetData(TYPE_VX001) != SPECIAL) - m_creature->InterruptNonMeleeSpells(true); + m_uiRepairTimer = 15000; m_creature->SetStandState(UNIT_STAND_STATE_DEAD); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) - { - if (Creature* pMimiron = m_pInstance->GetSingleCreatureFromStorage(NPC_MIMIRON)) - DoScriptText(SAY_TORSO_DEATH, pMimiron); - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_2); - m_pInstance->SetData(TYPE_VX001, DONE); - } - else if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) - { - DoCast(m_creature, SPELL_SELF_REPAIR); + if(m_pInstance) m_pInstance->SetData(TYPE_VX001, SPECIAL); - } } } } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + // hacky way for phase 4. needs rewriging when vehicles are fixed + void Repair() { - if (pSpell->Id == SPELL_SELF_REPAIR) - { - m_bMustRepair = false; - m_creature->SetStandState(UNIT_STAND_STATE_STAND); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - m_uiLaserBarrageTimer = 60000; - m_uiRocketStrikeTimer = 25000; - m_creature->SetInCombatWithZone(); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.5); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); + SetPhase(); - if(m_pInstance) - m_pInstance->SetData(TYPE_VX001, IN_PROGRESS); - } + if(m_pInstance) + m_pInstance->SetData(TYPE_VX001, IN_PROGRESS); } void SuppressFires() @@ -686,136 +678,105 @@ struct MANGOS_DLL_DECL boss_vx001AI : public ScriptedAI } } - void JustSummoned(Creature* pSummend) - { - if (pSummend->GetEntry() == NPC_ROCKET_STRIKE) - { - pSummend->CastSpell(m_creature, SPELL_ROCKET_STRIKE, false); - pSummend->ForcedDespawn(10 * IN_MILLISECONDS); - } - } - void UpdateAI(const uint32 uiDiff) { if (m_uiAttackStartTimer < uiDiff && !m_bStartAttack) { - if(GameObject* pLift = m_pInstance->GetSingleGameObjectFromStorage(GO_MIMIRON_ELEVATOR)) + if(GameObject* pLift = GetClosestGameObjectWithEntry(m_creature, GO_MIMIRON_ELEVATOR, DEFAULT_VISIBILITY_INSTANCE)) pLift->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetInCombatWithZone(); m_bStartAttack = true; } - else - m_uiAttackStartTimer -= uiDiff; + else m_uiAttackStartTimer -= uiDiff; - // HACK against the lose of an vehicle part - if (m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiRepairTimer < uiDiff && m_bMustRepair) { - if (Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) - { - if (VehicleKit* pTankV = pTank->GetVehicleKit()) - { - if (!pTankV->GetPassenger(SEAT_FOR_ROBOT)) - { - m_creature->EnterVehicle(pTankV, SEAT_FOR_ROBOT); - } - } - } - if (VehicleKit* pVX001V = m_creature->GetVehicleKit()) - { - if (!pVX001V->GetPassenger(SEAT_FOR_ROBOT)) - { - if (Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) - { - pHead->EnterVehicle(pVX001V,SEAT_FOR_ROBOT); - } - } - } + SetPhase(); + Repair(); + m_bMustRepair = false; } + else m_uiRepairTimer -= uiDiff; // return if repairing if(m_bMustRepair) return; - // turning if mob has dummy aura from Laser Barrage - if (m_creature->HasAura(SPELL_LASER_VISUAL)) + // only in VX001 phase + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) { - if (m_uiLaserBarrageTick < uiDiff) + if(m_uiRapidBurstTimer < uiDiff) { - // Sweep around - float newAngle = m_creature->GetOrientation() +M_PI*0.015; - if (newAngle > 2*M_PI_F) - newAngle -= 2*M_PI_F; - - m_creature->SetFacingTo(newAngle); - m_uiLaserBarrageTick = 100; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RAPID_BURST : SPELL_RAPID_BURST_H); + m_uiRapidBurstTimer = 1000; } - else - m_uiLaserBarrageTick -= uiDiff; - } - - // no turn with SelectHostileTarget in Laser Barrage - if (m_creature->HasAura(SPELL_LASER_SLAVE) || m_creature->HasAura(SPELL_LASER_VISUAL)) - return; + else m_uiRapidBurstTimer -= uiDiff; - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; - - if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) - { if(m_uiHeatWaveTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_HEAT_WAVE : SPELL_HEAT_WAVE_H) == CAST_OK) - m_uiHeatWaveTimer = urand(18000,22000); + DoCast(m_creature, m_bIsRegularMode ? SPELL_HEAT_WAVE : SPELL_HEAT_WAVE_H); + m_uiHeatWaveTimer = 10000; } - else - m_uiHeatWaveTimer -=uiDiff; + else m_uiHeatWaveTimer -= uiDiff; } - if (m_uiLaserBarrageTimer < uiDiff) + // only in robot phase + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if(m_uiHandPulseTimer < uiDiff) { - if (DoCastSpellIfCan(pTarget, SPELL_LASER_SLAVE) == CAST_OK) - { - m_creature->SetFacingTo(m_creature->GetAngle(pTarget)); - m_uiLaserBarrageTimer = 46000; - } + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_HAND_PULSE : SPELL_HAND_PULSE_H); + m_uiHandPulseTimer = 1000; } + else m_uiHandPulseTimer -= uiDiff; } - else - m_uiLaserBarrageTimer -= uiDiff; + if(m_uiLaserBarrageTimer < uiDiff) + { + DoCast(m_creature, SPELL_LASER_TRIGG); + m_uiLaserBarrageTimer = urand(50000, 60000); + } + else m_uiLaserBarrageTimer -= uiDiff; + + // this needs vehicles in order to make the rocket move to the target if(m_uiRocketStrikeTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_ROCKET_TRIGGER, SELECT_FLAG_PLAYER)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (DoCastSpellIfCan(pTarget, SPELL_ROCKET_TRIGGER) == CAST_OK) - m_uiRocketStrikeTimer = urand(8000, 12000); + if(Creature* pTemp = m_creature->SummonCreature(NPC_MIMIRON_FOCUS, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) + { + pTemp->setFaction(14); + pTemp->GetMotionMaster()->MoveIdle(); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->CombatStop(); + pTemp->SetDisplayId(11686); // make invisible + pTemp->CastSpell(pTemp, SPELL_ROCKET_STRIKE, false); + } } + m_uiRocketStrikeTimer = urand(25000, 30000); } - else - m_uiRocketStrikeTimer -= uiDiff; + else m_uiRocketStrikeTimer -= uiDiff; // hard mode if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) { - - DoCastSpellIfCan(m_creature, SPELL_EMERGENCY_MODE, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); - // only in VX001 phase if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) { if(m_uiFlameSuppressTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_FLAME_SUPRESS) == CAST_OK) - { - SuppressFires(); - m_uiFlameSuppressTimer = urand(9000, 10000); - } + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FLAME_SUPRESS); + SuppressFires(); + m_uiFlameSuppressTimer = urand(9000, 10000); } - else - m_uiFlameSuppressTimer -= uiDiff; + else m_uiFlameSuppressTimer -= uiDiff; } if(m_uiFrostBombTimer < uiDiff) @@ -825,8 +786,7 @@ struct MANGOS_DLL_DECL boss_vx001AI : public ScriptedAI m_uiFrostBombTimer = urand(50000, 60000); m_uiSpreadFiresTimer = urand(15000, 20000); } - else - m_uiFrostBombTimer -= uiDiff; + else m_uiFrostBombTimer -= uiDiff; if(m_uiSpreadFiresTimer < uiDiff) { @@ -841,62 +801,10 @@ struct MANGOS_DLL_DECL boss_vx001AI : public ScriptedAI } m_uiSpreadFiresTimer = 60000; } - else - m_uiSpreadFiresTimer -= uiDiff; + else m_uiSpreadFiresTimer -= uiDiff; } - if (m_uiStandardAttack < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) - { - if (m_bFireLeft) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_RAPID_BURST_LEFT : SPELL_RAPID_BURST_LEFT_H) == CAST_OK) - { - m_creature->SetInFront(pTarget); - m_creature->SetTargetGuid(pTarget->GetObjectGuid()); - m_bFireLeft = false; - } - } - else - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_RAPID_BURST_RIGHT : SPELL_RAPID_BURST_RIGHT_H) ==CAST_OK) - { - m_creature->SetInFront(pTarget); - m_creature->SetTargetGuid(pTarget->GetObjectGuid()); - m_bFireLeft = true; - } - } - m_uiStandardAttack = 500; - } - else if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) - { - if (m_bFireLeft) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_HAND_PULSE_LEFT : SPELL_HAND_PULSE_LEFT_H) ==CAST_OK) - { - m_creature->SetInFront(pTarget); - m_creature->SetTargetGuid(pTarget->GetObjectGuid()); - m_bFireLeft = false; - } - } - else - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_HAND_PULSE_RIGHT : SPELL_HAND_PULSE_RIGHT_H) ==CAST_OK) - { - m_creature->SetInFront(pTarget); - m_creature->SetTargetGuid(pTarget->GetObjectGuid()); - m_bFireLeft = true; - } - } - m_uiStandardAttack = 1000; - } - } - } - else - m_uiStandardAttack -= uiDiff; + DoMeleeAttackIfReady(); } }; @@ -905,12 +813,12 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI { boss_aerial_command_unitAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; bool m_bStartAttack; @@ -922,6 +830,7 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI bool m_bIsGrounded; uint32 m_uiSpreadFiresTimer; + uint32 m_uiRepairTimer; bool m_bMustRepair; void Reset() @@ -932,21 +841,23 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI m_uiPlasmaBallTimer = 3000; m_uiSummonWavesTimer = 10000; - m_bIsGrounded = false; + m_bIsGrounded = false; m_bMustRepair = false; + m_uiRepairTimer = 15000; - MakeBossLand(); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); if(m_pInstance) m_pInstance->SetData(TYPE_AERIAL_UNIT, NOT_STARTED); + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } void AttackStart(Unit* pWho) { - if(!m_bStartAttack && m_pInstance->GetData(TYPE_MIMIRON_PHASE) != PHASE_ROBOT) + if(!m_bStartAttack) return; if (m_creature->Attack(pWho, true)) @@ -962,62 +873,72 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI { if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) { - MakeBossFly(); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, 0.0f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, 26); } } - void MakeBossLand() - { - m_creature->SetLevitate(false); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); - } - - void MakeBossFly() - { - m_creature->SetLevitate(true); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); - } - void DamageTaken(Unit *done_by, uint32 &uiDamage) { - if(m_pInstance) + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + if(m_creature->HasAura(SPELL_MAGNETIC_CORE, EFFECT_INDEX_0)) + uiDamage += uiDamage; + return; + } + + // hacky way for feign death + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - if(m_creature->GetHealth() <= uiDamage) + if(uiDamage > m_creature->GetHealth()) { uiDamage = 0; - m_bMustRepair = true; - if (m_pInstance->GetData(TYPE_AERIAL_UNIT) != SPECIAL) - m_creature->InterruptNonMeleeSpells(true); + m_creature->SetHealth(0); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); + m_bMustRepair = true; + m_uiRepairTimer = 15000; m_creature->SetStandState(UNIT_STAND_STATE_DEAD); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) - { - DoCast(m_creature, SPELL_SELF_REPAIR); + + if(m_pInstance) m_pInstance->SetData(TYPE_AERIAL_UNIT, SPECIAL); - } - else if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) - { - if (Creature* pMimiron = m_pInstance->GetSingleCreatureFromStorage(NPC_MIMIRON)) - DoScriptText(SAY_HEAD_DEATH, pMimiron); - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_3); - m_pInstance->SetData(TYPE_AERIAL_UNIT, DONE); - } } } } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + // hacky way for phase 4. needs rewriging when vehicles are fixed + void Repair() + { + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.5); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); + SetPhase(); + + if(m_pInstance) + m_pInstance->SetData(TYPE_AERIAL_UNIT, IN_PROGRESS); + } + + void JustDied(Unit *killer) { - if (pSpell->Id == SPELL_SELF_REPAIR) + if(m_pInstance) { - MakeBossLand(); - m_bMustRepair = false; - m_creature->SetStandState(UNIT_STAND_STATE_STAND); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - m_uiPlasmaBallTimer = 3000; - m_creature->SetInCombatWithZone(); - if(m_pInstance) - m_pInstance->SetData(TYPE_AERIAL_UNIT, IN_PROGRESS); + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + if (Creature* pMimiron = m_pInstance->GetSingleCreatureFromStorage(NPC_MIMIRON)) + DoScriptText(SAY_HEAD_DEATH, pMimiron); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_3); + m_pInstance->SetData(TYPE_AERIAL_UNIT, DONE); + } } } @@ -1027,21 +948,42 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI { if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) { - DoScriptText(urand(0,1) ? SAY_HEAD_SLAY1 : SAY_HEAD_SLAY2, pMimiron); + if(irand(0,1)) + DoScriptText(SAY_HEAD_SLAY1, pMimiron); + else + DoScriptText(SAY_HEAD_SLAY2, pMimiron); } if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) { - DoScriptText(urand(0,1) ? SAY_ROBOT_SLAY1 : SAY_ROBOT_SLAY2, pMimiron); + if(irand(0,1)) + DoScriptText(SAY_ROBOT_SLAY1, pMimiron); + else + DoScriptText(SAY_ROBOT_SLAY2, pMimiron); } } } + // hacky way for phase 4. needs rewriging when vehicles are fixed + void SetPhase() + { + m_uiPlasmaBallTimer = 3000; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 6.5f, 0.0f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 6.5f, 26); + } + // get the boss down by the magnetic core void SetToGround() { - m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), 364.0f, 24.0f); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), CENTER_Z, 0); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), CENTER_Z, 26); m_bIsGrounded = true; - MakeBossLand(); + // make boss land + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); m_uiGroundTimer = 20000; } @@ -1058,52 +1000,49 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI m_creature->SetInCombatWithZone(); m_bStartAttack = true; } - else - m_uiAttackStartTimer -= uiDiff; + else m_uiAttackStartTimer -= uiDiff; if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if(m_uiRepairTimer < uiDiff && m_bMustRepair) + { + SetPhase(); + Repair(); + m_bMustRepair = false; + } + else m_uiRepairTimer -= uiDiff; + // return if repairing if(m_bMustRepair) return; - // return if grounded - if (m_creature->HasAura(SPELL_MAGNETIC_CORE)) + if (m_creature->HasAura(SPELL_MAGNETIC_CORE, EFFECT_INDEX_0)) return; - if (m_bIsGrounded) + if (m_uiGroundTimer < uiDiff && m_bIsGrounded) { + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, 0.0f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, 26); m_bIsGrounded = false; - MakeBossFly(); + // make boss fly + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->InterruptNonMeleeSpells(true); DoCast(m_creature, SPELL_BOMB_BOT_SUMMON); - } - + }else m_uiGroundTimer -= uiDiff; + if(m_uiPlasmaBallTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BALL : SPELL_PLASMA_BALL_H) == CAST_OK) - { - m_uiPlasmaBallTimer = urand(3000, 5000); - } - } - } - else - m_uiPlasmaBallTimer -= uiDiff; - - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) - { - DoCastSpellIfCan(m_creature, SPELL_EMERGENCY_MODE, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); + DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BALL : SPELL_PLASMA_BALL_H); + m_uiPlasmaBallTimer = urand(3000, 5000); } + else m_uiPlasmaBallTimer -= uiDiff; // spawn adds in arena, only in phase 3 if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) { - // mobs at a specific height, maybe someother work; i think best is hoverheight, but doesn't work - if (m_creature->GetPositionZ() < 372.0f) - m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), 372.0f, 24.0f); - if(m_uiSummonWavesTimer < uiDiff) { uint32 m_uiCreatureEntry; @@ -1123,9 +1062,6 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI case 4: m_uiCreatureEntry = MOB_ASSALT_BOT; break; - default: - m_uiCreatureEntry = MOB_JUNK_BOT; - break; } } else @@ -1139,19 +1075,15 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI case 2: m_uiCreatureEntry = MOB_ASSALT_BOT; break; - default: - m_uiCreatureEntry = MOB_JUNK_BOT; - break; } } uint8 m_uiSummonLoc = urand(0, 8); if(m_uiCreatureEntry != 0) - m_creature->SummonCreature(m_uiCreatureEntry, SummonLoc[m_uiSummonLoc].x, SummonLoc[m_uiSummonLoc].y, CENTER_Z, 0, TEMPSUMMON_DEAD_DESPAWN, 10000); + m_creature->SummonCreature(m_uiCreatureEntry, SummonLoc[m_uiSummonLoc].x, SummonLoc[m_uiSummonLoc].y, CENTER_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); m_uiSummonWavesTimer = urand (10000, 15000); } - else - m_uiSummonWavesTimer -= uiDiff; + else m_uiSummonWavesTimer -= uiDiff; if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) { @@ -1168,8 +1100,7 @@ struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI } m_uiSpreadFiresTimer = urand(40000, 50000); } - else - m_uiSpreadFiresTimer -= uiDiff; + else m_uiSpreadFiresTimer -= uiDiff; } } } @@ -1181,53 +1112,74 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI { boss_mimironAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } bool m_bIsRegularMode; - instance_ulduar *m_pInstance; + ScriptedInstance *m_pInstance; + bool m_bIsHardMode; uint32 m_uiSelfDestructTimer; uint32 m_uiUseLiftTimer; uint32 m_uiPhaseDelayTimer; uint32 m_uiRobotDelayTimer; + uint32 m_uiSelfRepairTimer; uint32 m_uiBerserkTimer; + bool m_bHasChecked; uint32 m_uiOutroTimer; + uint32 m_uiHpCheckTimer; + bool m_bHasMoreHp; uint32 m_uiIntroTimer; uint32 m_uiIntroStep; bool m_bIsIntro; bool m_bIsRobotReady; + bool m_bIsTankDead; + bool m_bIsTorsoDead; + bool m_bIsHeadDead; + void Reset() { + m_bIsHardMode = false; m_uiSelfDestructTimer = 460000; // 8 min m_bIsIntro = true; m_uiPhaseDelayTimer = 7000; m_uiUseLiftTimer = 4000; m_uiBerserkTimer = 900000; // 15 min + m_bHasChecked = false; + m_bHasMoreHp = false; m_bIsRobotReady = false; m_uiIntroTimer = 10000; m_uiIntroStep = 1; + m_bIsTankDead = false; + m_bIsTorsoDead = false; + m_bIsHeadDead = false; + // reset button if(GameObject* pButton = m_pInstance->GetSingleGameObjectFromStorage(GO_MIMIRON_BUTTON)) + { pButton->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + if (pButton->GetGoState() == GO_STATE_ACTIVE) + pButton->SetGoState(GO_STATE_READY); + } + // reset elevator - if(GameObject* pLift = m_pInstance->GetSingleGameObjectFromStorage(GO_MIMIRON_ELEVATOR)) + if(GameObject* pLift = GetClosestGameObjectWithEntry(m_creature, GO_MIMIRON_ELEVATOR, DEFAULT_VISIBILITY_INSTANCE)) pLift->SetGoState(GO_STATE_ACTIVE); // kill torso and Head - if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) - pTorso->ForcedDespawn(); + if(Creature* pTorso = GetClosestCreatureWithEntry(m_creature, NPC_VX001, 80.0f)) + pTorso->DealDamage(pTorso, pTorso->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) - pHead->ForcedDespawn(); + if(Creature* pHead = GetClosestCreatureWithEntry(m_creature, NPC_AERIAL_UNIT, 80.0f)) + pHead->DealDamage(pHead, pHead->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); // reset tank if (Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) @@ -1239,7 +1191,10 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI } if(m_pInstance) + { m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_IDLE); + m_pInstance->SetData(TYPE_MIMIRON_HARD, NOT_STARTED); + } m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } @@ -1247,10 +1202,7 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI void JustReachedHome() { if(m_pInstance) - { - m_pInstance->SetData(TYPE_MIMIRON, FAIL); - m_pInstance->SetData(TYPE_MIMIRON_HARD, FAIL); - } + m_pInstance->SetData(TYPE_MIMIRON, NOT_STARTED); } // start event @@ -1274,12 +1226,24 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI { if(m_pInstance) { - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + if(m_bIsHardMode) { m_pInstance->SetData(TYPE_MIMIRON_HARD, DONE); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_FIREFIGHTER : ACHIEV_FIREFIGHTER_H); } m_pInstance->SetData(TYPE_MIMIRON, DONE); } + + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + pPlayer->KilledMonsterCredit(NPC_LEVIATHAN_MK); + } m_creature->ForcedDespawn(); } @@ -1288,9 +1252,9 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI { if(m_pInstance) { - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) - m_pInstance->SetData(TYPE_MIMIRON_HARD, DONE); m_pInstance->SetData(TYPE_MIMIRON, DONE); + if(m_bIsHardMode) + m_pInstance->SetData(TYPE_MIMIRON_HARD, DONE); } } @@ -1301,7 +1265,7 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI switch(m_pInstance->GetData(TYPE_MIMIRON_PHASE)) { - case PHASE_INTRO: + case PHASE_INTRO: { if(m_bIsIntro) { @@ -1315,7 +1279,7 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI case 3: if(GameObject* pButton = m_pInstance->GetSingleGameObjectFromStorage(GO_MIMIRON_BUTTON)) pButton->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + if(m_bIsHardMode) { DoScriptText(SAY_HARD_MODE, m_creature); ++m_uiIntroStep; @@ -1342,95 +1306,158 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI m_uiIntroTimer = 18000; break; case 7: - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + { + if(m_bIsHardMode) + { + pTank->CastSpell(pTank, SPELL_EMERGENCY_MODE, false); + ++m_uiIntroStep; + m_uiIntroTimer = 1000; + } + else + { + if(m_pInstance) + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_LEVIATHAN); + ((boss_leviathan_mkAI*)pTank->AI())->m_bStartAttack = true; + pTank->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTank->SetInCombatWithZone(); + m_uiBerserkTimer = 900000; // 15 min + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + } + } + break; + case 9: + if(m_bIsHardMode) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_LEVIATHAN); + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + { + pTank->SetHealth(pTank->GetMaxHealth()+ (pTank->GetMaxHealth() * 0.3)); + ((boss_leviathan_mkAI*)pTank->AI())->m_bStartAttack = true; + pTank->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTank->SetInCombatWithZone(); + } m_uiSelfDestructTimer = 460000; // 8 min - m_uiBerserkTimer = 900000; // 15 min - m_bIsIntro = false; - ++m_uiIntroStep; - m_uiIntroTimer = 9000; + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + } break; } } - else - return; + else return; if (m_uiIntroTimer <= uiDiff) { ++m_uiIntroStep; m_uiIntroTimer = 330000; - } - else - m_uiIntroTimer -= uiDiff; + } + m_uiIntroTimer -= uiDiff; break; } - case PHASE_LEVIATHAN: - // leviathan MK phase: see above script - break; - case PHASE_TRANS_1: + case PHASE_LEVIATHAN: + // leviathan MK phase: see above script + break; + case PHASE_TRANS_1: { if(m_uiUseLiftTimer < uiDiff) { - m_pInstance->DoUseDoorOrButton(GO_MIMIRON_ELEVATOR); + if(GameObject* pLift = GetClosestGameObjectWithEntry(m_creature, GO_MIMIRON_ELEVATOR, DEFAULT_VISIBILITY_INSTANCE)) + m_pInstance->DoUseDoorOrButton(pLift->GetObjectGuid()); m_uiUseLiftTimer = 60000; } - else - m_uiUseLiftTimer -= uiDiff; + else m_uiUseLiftTimer -= uiDiff; - if(m_uiPhaseDelayTimer < uiDiff) + if(m_uiPhaseDelayTimer < uiDiff && !m_bHasMoreHp) { DoScriptText(SAY_TORSO_ACTIVE, m_creature); - if(/*Creature* pTorso = */m_creature->SummonCreature(NPC_VX001, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + if(Creature* pTorso = m_creature->SummonCreature(NPC_VX001, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000)) { - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + if(m_bIsHardMode) { - for(uint8 i = 0; i < 3; i++) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - pTarget->InterruptNonMeleeSpells(true); - pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); - } - } - } - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_VX001); - m_uiPhaseDelayTimer = 10000; + pTorso->CastSpell(pTorso, SPELL_EMERGENCY_MODE, false); + m_bHasMoreHp = true; + m_uiHpCheckTimer = 1000; + } + else + { + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_VX001); + m_uiPhaseDelayTimer = 10000; + } } } - else - m_uiPhaseDelayTimer -= uiDiff; + else m_uiPhaseDelayTimer -= uiDiff; + + if (m_uiHpCheckTimer <= uiDiff && m_bHasMoreHp) + { + if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) + pTorso->SetHealth(pTorso->GetMaxHealth()+ (pTorso->GetMaxHealth() * 0.3)); + m_bHasMoreHp = false; + m_uiPhaseDelayTimer = 10000; + m_uiHpCheckTimer = 10000; + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_VX001); + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + } + else m_uiHpCheckTimer -= uiDiff; break; } - case PHASE_VX001: - // VX001 phase: see above script - break; - case PHASE_TRANS_2: + case PHASE_VX001: + // VX001 phase: see above script + break; + case PHASE_TRANS_2: { - if(m_uiPhaseDelayTimer < uiDiff) + if(m_uiPhaseDelayTimer < uiDiff && !m_bHasMoreHp) { DoScriptText(SAY_HEAD_ACTIVE, m_creature); - if(/*Creature* pHead = */m_creature->SummonCreature(NPC_AERIAL_UNIT, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_DEAD_DESPAWN, 10000)) + if(Creature* pHead = m_creature->SummonCreature(NPC_AERIAL_UNIT, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000)) { - if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + if(m_bIsHardMode) { - // start again 3 fires - for(uint8 i = 0; i < 3; i++) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - pTarget->InterruptNonMeleeSpells(true); - pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); - } - } + pHead->CastSpell(pHead, SPELL_EMERGENCY_MODE, false); + m_bHasMoreHp = true; + m_uiHpCheckTimer = 1000; + } + else + { + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_AERIAL); + m_uiPhaseDelayTimer = 15000; + } + } + } + else m_uiPhaseDelayTimer -= uiDiff; + if (m_uiHpCheckTimer <= uiDiff && m_bHasMoreHp) + { + if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) + pHead->SetHealth(pHead->GetMaxHealth()+ (pHead->GetMaxHealth() * 0.3)); + m_bHasMoreHp = false; + m_uiPhaseDelayTimer = 15000; + m_uiHpCheckTimer = 10000; + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_AERIAL); + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); } - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_AERIAL); - m_uiPhaseDelayTimer = 15000; } } - else - m_uiPhaseDelayTimer -= uiDiff; + else m_uiHpCheckTimer -= uiDiff; break; } @@ -1446,15 +1473,6 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI if(pTank->isAlive()) { pTank->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); - if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) - { - pTorso->CastSpell(pTorso, SPELL_SELF_REPAIR, false); - } - if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) - { - pHead->CastSpell(pHead, SPELL_SELF_REPAIR, false); - } - m_bIsRobotReady = true; m_uiRobotDelayTimer = 15000; } @@ -1463,39 +1481,144 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI } m_uiPhaseDelayTimer = 100000; } - else - m_uiPhaseDelayTimer -= uiDiff; + else m_uiPhaseDelayTimer -= uiDiff; - if(m_uiRobotDelayTimer < uiDiff && m_bIsRobotReady) + if(m_uiRobotDelayTimer < uiDiff && m_bIsRobotReady && !m_bHasMoreHp) { + DoScriptText(SAY_ROBOT_ACTIVE, m_creature); + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + ((boss_leviathan_mkAI*)pTank->AI())->SetPhase(); + + if(Creature* pTorso = m_creature->SummonCreature(NPC_VX001, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 30000)) + { + ((boss_vx001AI*)pTorso->AI())->SetPhase(); + } + if(Creature* pHead = m_creature->SummonCreature(NPC_AERIAL_UNIT, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_DESPAWN, 30000)) + { + ((boss_aerial_command_unitAI*)pHead->AI())->SetPhase(); + } + + if(m_bIsHardMode) + { + if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) + pTorso->CastSpell(pTorso, SPELL_EMERGENCY_MODE, false); + if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) + pHead->CastSpell(pHead, SPELL_EMERGENCY_MODE, false); + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + pTank->CastSpell(pTank, SPELL_EMERGENCY_MODE, false); + m_bHasMoreHp = true; + m_uiHpCheckTimer = 1000; + } + else + { + if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) + pTorso->SetHealth(pTorso->GetMaxHealth() * 0.5); + if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) + pHead->SetHealth(pHead->GetMaxHealth() * 0.5); + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + pTank->SetHealth(pTank->GetMaxHealth() * 0.5); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_ROBOT); + } m_uiRobotDelayTimer = 100000; } - else - m_uiRobotDelayTimer -= uiDiff; + else m_uiRobotDelayTimer -= uiDiff; + + if (m_uiHpCheckTimer <= uiDiff && m_bHasMoreHp) + { + if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) + pHead->SetHealth(pHead->GetMaxHealth() * 0.5); + if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) + pTorso->SetHealth(pTorso->GetMaxHealth()* 0.5); + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + pTank->SetHealth(pTank->GetMaxHealth()* 0.5); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_ROBOT); + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + m_uiHpCheckTimer = 10000; + } + else m_uiHpCheckTimer -= uiDiff; break; } - case PHASE_ROBOT: + case PHASE_ROBOT: { - if(m_pInstance->GetData(TYPE_LEVIATHAN_MK) == SPECIAL && m_pInstance->GetData(TYPE_VX001) == SPECIAL && m_pInstance->GetData(TYPE_AERIAL_UNIT) == SPECIAL) + if(m_pInstance->GetData(TYPE_LEVIATHAN_MK) == SPECIAL && !m_bHasChecked) { - if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) - m_creature->DealDamage(pTank, pTank->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) - m_creature->DealDamage(pHead, pHead->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) - m_creature->DealDamage(pTorso, pTorso->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - DoScriptText(SAY_ROBOT_DEATH, m_creature); - m_uiOutroTimer = 15000; - m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_OUTRO); + m_uiSelfRepairTimer = 15000; + m_bIsTankDead = true; + m_bHasChecked = true; } + if(m_pInstance->GetData(TYPE_VX001) == SPECIAL && !m_bHasChecked) + { + m_uiSelfRepairTimer = 15000; + m_bIsTorsoDead = true; + m_bHasChecked = true; + } + if(m_pInstance->GetData(TYPE_AERIAL_UNIT) == SPECIAL && !m_bHasChecked) + { + m_uiSelfRepairTimer = 15000; + m_bIsHeadDead = true; + m_bHasChecked = true; + } + + if(m_uiSelfRepairTimer < uiDiff && m_bHasChecked) + { + if(m_pInstance->GetData(TYPE_LEVIATHAN_MK) == SPECIAL) + m_bIsTankDead = true; + if(m_pInstance->GetData(TYPE_VX001) == SPECIAL) + m_bIsTorsoDead = true; + if(m_pInstance->GetData(TYPE_AERIAL_UNIT) == SPECIAL) + m_bIsHeadDead = true; + + if(m_bIsTankDead && m_bIsTorsoDead && m_bIsHeadDead) + { + DoScriptText(SAY_ROBOT_DEATH, m_creature); + m_uiOutroTimer = 15000; + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_OUTRO); + } + else + { + m_bHasChecked = false; + if(m_bIsTankDead) + { + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + ((boss_leviathan_mkAI*)pTank->AI())->Repair(); + } + if(m_bIsTorsoDead) + { + if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) + ((boss_vx001AI*)pTorso->AI())->Repair(); + } + if(m_bIsHeadDead) + { + if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) + ((boss_aerial_command_unitAI*)pHead->AI())->Repair(); + } + } + m_uiSelfRepairTimer = 1000; + } + else m_uiSelfRepairTimer -= uiDiff; + break; } - case PHASE_OUTRO: + case PHASE_OUTRO: { if(m_uiOutroTimer < uiDiff) { + if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + m_creature->DealDamage(pTank, pTank->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if(Creature* pHead = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) + m_creature->DealDamage(pHead, pHead->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if(Creature* pTorso = m_pInstance->GetSingleCreatureFromStorage(NPC_VX001)) + m_creature->DealDamage(pTorso, pTorso->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); DoOutro(); m_uiOutroTimer = 60000; } @@ -1503,14 +1626,11 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI break; } - default: - break; } // berserk if (m_uiBerserkTimer <= uiDiff) { - DoScriptText(SAY_BERSERK, m_creature); if(Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) { if(pTank && pTank->isAlive()) @@ -1535,17 +1655,17 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI m_uiBerserkTimer -= uiDiff; // self destruct platform in hard mode - if (m_uiSelfDestructTimer < uiDiff && (m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS)) + if (m_uiSelfDestructTimer < uiDiff && m_bIsHardMode) { m_creature->SummonCreature(NPC_MIMIRON_INFERNO, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); // visual part, hacky way - /*if(Creature* pTemp = m_creature->SummonCreature(NPC_MIMIRON_FOCUS, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + if(Creature* pTemp = m_creature->SummonCreature(NPC_MIMIRON_FOCUS, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) { pTemp->GetMotionMaster()->MoveIdle(); pTemp->CombatStop(); pTemp->SetDisplayId(11686); // make invisible pTemp->CastSpell(pTemp, SPELL_SELF_DESTRUCTION, false); - }*/ + } m_uiSelfDestructTimer = 60000; } else m_uiSelfDestructTimer -= uiDiff; @@ -1553,16 +1673,20 @@ struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI }; // Leviathan MK turret +// used in phase 1; should be attached by a vehicle seat to the Leviathan MK struct MANGOS_DLL_DECL leviathan_turretAI : public ScriptedAI { leviathan_turretAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetVisibility(VISIBILITY_OFF); + //pCreature->setFaction(14); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiPlasmaBlastTimer; @@ -1576,36 +1700,36 @@ struct MANGOS_DLL_DECL leviathan_turretAI : public ScriptedAI void UpdateAI(const uint32 uiDiff) { - if (m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiPlasmaBlastTimer < uiDiff) { - if(m_uiPlasmaBlastTimer < uiDiff) + if (Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) { - if (Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) - { - DoScriptText(EMOTE_PLASMA_BLAST, m_creature); - if (Unit* pTarget = pTank->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) - DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BLAST : SPELL_PLASMA_BLAST_H); - } - m_uiPlasmaBlastTimer = 30000; + DoScriptText(EMOTE_PLASMA_BLAST, m_creature); + if (Unit* pTarget = pTank->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BLAST : SPELL_PLASMA_BLAST_H); } - else m_uiPlasmaBlastTimer -= uiDiff; + m_uiPlasmaBlastTimer = 30000; + } + else m_uiPlasmaBlastTimer -= uiDiff; - if(m_uiNapalmShellTimer < uiDiff) + if(m_uiNapalmShellTimer < uiDiff) + { + if (Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) { - if (Creature* pTank = m_pInstance->GetSingleCreatureFromStorage(NPC_LEVIATHAN_MK)) + if (Unit* pTarget = pTank->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (Unit* pTarget = pTank->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if(!pTank->IsWithinDistInMap(pTarget, 15)) { - if(!pTank->IsWithinDistInMap(pTarget, 15)) - { - DoCast(pTarget, m_bIsRegularMode ? SPELL_NAPALM_SHELL : SPELL_NAPALM_SHELL_H); - m_uiNapalmShellTimer = 7000; - } + DoCast(pTarget, m_bIsRegularMode ? SPELL_NAPALM_SHELL : SPELL_NAPALM_SHELL_H); + m_uiNapalmShellTimer = 7000; } } } - else m_uiNapalmShellTimer -= uiDiff; } + else m_uiNapalmShellTimer -= uiDiff; } }; @@ -1613,23 +1737,25 @@ struct MANGOS_DLL_DECL mob_proximity_mineAI : public ScriptedAI { mob_proximity_mineAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiExplosionTimer; uint32 m_uiRangeCheckTimer; + uint32 m_uiDieTimer; void Reset() { m_uiExplosionTimer = 60000; m_uiRangeCheckTimer = 1000; + m_uiDieTimer = 65000; } void UpdateAI(const uint32 uiDiff) @@ -1640,32 +1766,31 @@ struct MANGOS_DLL_DECL mob_proximity_mineAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else + m_uiDieTimer -= uiDiff; + if(m_uiExplosionTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_EXPLOSION : SPELL_EXPLOSION_H) == CAST_OK) - { - m_creature->ForcedDespawn(500); - m_uiExplosionTimer = 20000; - } + DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLOSION : SPELL_EXPLOSION_H); + m_uiDieTimer = 500; + m_uiExplosionTimer = 20000; } - else - m_uiExplosionTimer -= uiDiff; + else m_uiExplosionTimer -= uiDiff; if (m_uiRangeCheckTimer < uiDiff) { - if (GetPlayerAtMinimumRange(2.0f)) + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 2)) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_EXPLOSION : SPELL_EXPLOSION_H) == CAST_OK) - { - m_creature->ForcedDespawn(500); - m_uiRangeCheckTimer = 5000; - } + DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLOSION : SPELL_EXPLOSION_H); + m_uiDieTimer = 500; + m_uiRangeCheckTimer = 5000; } else m_uiRangeCheckTimer = 500; } - else - m_uiRangeCheckTimer -= uiDiff; + else m_uiRangeCheckTimer -= uiDiff; } }; @@ -1808,7 +1933,7 @@ struct MANGOS_DLL_DECL mob_frost_bomb_ulduarAI : public ScriptedAI { mob_frost_bomb_ulduarAI(Creature* pCreature) : ScriptedAI(pCreature) { - pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); pCreature->setFaction(14); @@ -1816,7 +1941,7 @@ struct MANGOS_DLL_DECL mob_frost_bomb_ulduarAI : public ScriptedAI Reset(); } - instance_ulduar *pInstance; + ScriptedInstance *pInstance; bool m_bIsRegularMode; uint32 m_uiExplosionTimer; @@ -1867,7 +1992,7 @@ struct MANGOS_DLL_DECL mob_mimiron_flamesAI : public ScriptedAI { mob_mimiron_flamesAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pCreature->setFaction(14); @@ -1875,7 +2000,7 @@ struct MANGOS_DLL_DECL mob_mimiron_flamesAI : public ScriptedAI Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiFlamesSpreadTimer; @@ -1904,7 +2029,7 @@ struct MANGOS_DLL_DECL mob_mimiron_infernoAI : public ScriptedAI { mob_mimiron_infernoAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pCreature->setFaction(14); @@ -1913,7 +2038,7 @@ struct MANGOS_DLL_DECL mob_mimiron_infernoAI : public ScriptedAI Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiFlamesTimer; @@ -1942,12 +2067,12 @@ struct MANGOS_DLL_DECL mob_magnetic_coreAI : public ScriptedAI { mob_magnetic_coreAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiSpellTimer; uint32 m_uiDieTimer; @@ -1962,15 +2087,12 @@ struct MANGOS_DLL_DECL mob_magnetic_coreAI : public ScriptedAI { if(m_uiSpellTimer < uiDiff) { - if (m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + if(Creature* pAerial = GetClosestCreatureWithEntry(m_creature, NPC_AERIAL_UNIT, 10.0f)) { - if(Creature* pAerial = m_pInstance->GetSingleCreatureFromStorage(NPC_AERIAL_UNIT)) - { - DoCast(pAerial, SPELL_MAGNETIC_CORE); - ((boss_aerial_command_unitAI*)pAerial->AI())->SetToGround(); - } - m_uiSpellTimer = 100000; + DoCast(pAerial, SPELL_MAGNETIC_CORE); + ((boss_aerial_command_unitAI*)pAerial->AI())->SetToGround(); } + m_uiSpellTimer = 100000; } else m_uiSpellTimer -= uiDiff; @@ -1984,18 +2106,18 @@ struct MANGOS_DLL_DECL mob_magnetic_coreAI : public ScriptedAI // Red button -> used to start the hard mode bool GOHello_go_red_button(Player* pPlayer, GameObject* pGo) { - instance_ulduar* m_pInstance = (instance_ulduar*)pGo->GetInstanceData(); + ScriptedInstance* m_pInstance = (ScriptedInstance*)pGo->GetInstanceData(); if (!m_pInstance) return false; if (Creature* pMimiron = m_pInstance->GetSingleCreatureFromStorage(NPC_MIMIRON)) { - m_pInstance->SetData(TYPE_MIMIRON_HARD, IN_PROGRESS); - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_FIREFIGHTER, true); - pMimiron->SetInCombatWithZone(); pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); pPlayer->CastSpell(pPlayer, SPELL_FLAMES_SUMMON, false); + if(pMimiron->isAlive() && m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_INTRO) + ((boss_mimironAI*)pMimiron->AI())->m_bIsHardMode = true; + m_pInstance->SetData(TYPE_MIMIRON_HARD, IN_PROGRESS); } return false; @@ -2125,7 +2247,7 @@ void AddSC_boss_mimiron() newscript->RegisterSelf(); newscript = new Script; - newscript->Name = "mob_mimirons_inferno"; + newscript->Name = "mob_mimiron_inferno"; newscript->GetAI = &GetAI_mob_mimiron_inferno; newscript->RegisterSelf(); diff --git a/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp b/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp index d9b7a0296b..75992c4680 100644 --- a/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp @@ -27,38 +27,35 @@ EndScriptData */ enum { //yells/emotes - SAY_INTRO = -1603030, - SAY_AGGRO1 = -1603031, - SAY_AGGRO2 = -1603032, - SAY_AGGRO3 = -1603033, - SAY_GROUND = -1603034, - EMOTE_DEEP_BREATH = -1603035, - SAY_FIRES_EXTINGUISH = -1603036, - EMOTE_HARPOON = -1603337, - EMOTE_GROUNDED = -1603338, + SAY_INTRO = -1603020, + SAY_AGGRO1 = -1603021, + SAY_AGGRO2 = -1603022, + SAY_AGGRO3 = -1603023, + SAY_GROUND = -1603024, + EMOTE_DEEP_BREATH = -1603025, + SAY_FIRES_EXTINGUISH = -1603026, + EMOTE_HARPOON = -1603027, + EMOTE_GROUNDED = -1603028, //razorscale air phase - SPELL_FIREBALL = 62796, - SPELL_FIREBALL_H = 63815, - SPELL_WING_BUFFET = 62666, - SPELL_STUN = 62794, - SPELL_SUMMON_DWARF = 62916, + SPELL_FIREBALL = 62796, + SPELL_FIREBALL_H = 63815, + SPELL_WING_BUFFET = 62666, + SPELL_STUN = 62794, + SPELL_SUMMON_DWARF = 62916, //both - SPELL_BERSERK = 47008, - DEVOURING_FLAME_MISSILE = 63236, - SPELL_FLAME_BREATH = 63317, - SPELL_FLAME_BREATH_H = 64021, - NPC_CONTROLLER = 33233, // used for casting deep breath on turrets + SPELL_BERSERK = 47008, + DEVOURING_FLAME_VISUAL = 63236, + SPELL_FLAME_BREATH = 63317, + SPELL_FLAME_BREATH_H = 64021, //ground - SPELL_FLAME_BUFFET = 64016, - SPELL_FLAME_BUFFET_H = 64023, - SPELL_FUSE_ARMOR = 64771, + SPELL_FLAME_BUFFET = 64016, + SPELL_FLAME_BUFFET_H = 64023, + SPELL_FUSE_ARMOR = 64771, //devouring flame target - NPC_DEVOURING_TARGET = 34188, - NPC_DEVOURING_TARGET_H = 34189, - AURA_DEVOURING_FLAME = 64709, - AURA_DEVOURING_FLAME_H = 64734, + AURA_DEVOURING_FLAME = 64709, + AURA_DEVOURING_FLAME_H = 64734, // mole machine NPC_MOLE_MACHINE = 33245, // used to summon adds in phase 1 @@ -67,30 +64,33 @@ enum // harpoons SPELL_HARPOON_SHOT = 63659, - GO_REPAIR_HARPOON_4 = 194543, // BROKEN HARBOON 194565 - GO_REPAIR_HARPOON_3 = 194542, - GO_REPAIR_HARPOON_2 = 194541, - GO_REPAIR_HARPOON_1 = 194519, + GO_HARPOON = 194543, // 41, 42, 194519 + //dark rune watcher - SPELL_LIGHTNING_BOLT = 63809, - SPELL_LIGHTNING_BOLT_H = 64696, - SPELL_CHAIN_LIGHTNING = 64758, - SPELL_CHAIN_LIGHTNING_H = 64759, + SPELL_LIGHTNING_BOLT = 63809, + SPELL_LIGHTNING_BOLT_H = 64696, + SPELL_CHAIN_LIGHTNING = 64758, + SPELL_CHAIN_LIGHTNING_H = 64759, //dark rune sentinel - SPELL_BATTLE_SHOUT = 46763, - SPELL_BATTLE_SHOUT_H = 64062, - SPELL_WHIRLWIND = 63808, + SPELL_BATTLE_SHOUT = 46763, + SPELL_BATTLE_SHOUT_H = 64062, + SPELL_WHIRLWIND = 63808, //dark rune guardian - SPELL_STORMSTRIKE = 64757, + SPELL_STORMSTRIKE = 64757, //NPC ids - MOB_DARK_RUNE_WATCHER = 33453, - MOB_DARK_RUNE_SENTINEL = 33846, - MOB_DARK_RUNE_GUARDIAN = 33388, + MOB_DARK_RUNE_WATCHER = 33453, + MOB_DARK_RUNE_SENTINEL = 33846, + MOB_DARK_RUNE_GUARDIAN = 33388, - NPC_EXP_ENGINEER = 33287, + NPC_EXP_ENGINEER = 33287, + + ACHIEV_QUICK_SHAVE = 2919, + ACHIEV_QUICK_SHAVE_H = 2921, + ACHIEV_MEDIUM_RARE = 2923, + ACHIEV_MEDIUM_RARE_H = 2924, }; //Positional defines @@ -106,21 +106,13 @@ static LocationsXY PositionLoc[]= {564.140198f, -222.049149f, 391.517212f},//left {591.629761f, -209.629761f, 392.629761f},//middle {587.629761f, -179.022522f, 391.625061f},//ground - {587.629761f, -179.022522f, 450.415070f},//air + {587.629761f, -179.022522f, 435.415070f},//air }; - #define HOME_X 587.546997f #define HOME_Y -174.927002f -#define GOSSIP_START "Holt Klingenschuppe auf den Boden!" - -enum RazorscalePhase -{ - PHASE_AIR = 1, - PHASE_GROUND = 2, - PHASE_PERMAGROUND = 3, -}; +#define GOSSIP_START "Bring Razorscale down!" //expedition commander // start the event @@ -128,12 +120,12 @@ struct MANGOS_DLL_DECL npc_expedition_commanderAI : public ScriptedAI { npc_expedition_commanderAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bHasPlayerNear = false; Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bHasPlayerNear; bool m_bIsIntro; @@ -225,7 +217,7 @@ CreatureAI* GetAI_npc_expedition_commander(Creature* pCreature) bool GossipHello_npc_expedition_commander(Player* pPlayer, Creature* pCreature) { - instance_ulduar* pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance* pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); if(pInstance->GetData(TYPE_RAZORSCALE) != DONE) pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); @@ -251,12 +243,12 @@ struct MANGOS_DLL_DECL mob_devouring_flame_targetAI : public ScriptedAI { mob_devouring_flame_targetAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiDeath_Timer; @@ -275,7 +267,6 @@ struct MANGOS_DLL_DECL mob_devouring_flame_targetAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // think that unnecessary because summon spell 63308 with duration 22 seconds if (m_uiDeath_Timer < uiDiff) m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); else m_uiDeath_Timer -= uiDiff; @@ -292,12 +283,12 @@ struct MANGOS_DLL_DECL mob_dark_rune_watcherAI : public ScriptedAI { mob_dark_rune_watcherAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiSpell_Timer; @@ -325,7 +316,7 @@ struct MANGOS_DLL_DECL mob_dark_rune_watcherAI : public ScriptedAI } m_uiSpell_Timer = urand(5000, 10000); }else m_uiSpell_Timer -= diff; - + DoMeleeAttackIfReady(); } }; @@ -340,12 +331,12 @@ struct MANGOS_DLL_DECL mob_dark_rune_sentinelAI : public ScriptedAI { mob_dark_rune_sentinelAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiWhirl_Timer; @@ -364,20 +355,16 @@ struct MANGOS_DLL_DECL mob_dark_rune_sentinelAI : public ScriptedAI if (m_uiWhirl_Timer < diff) { - if (DoCastSpellIfCan(m_creature, SPELL_WHIRLWIND) == CAST_OK) - m_uiWhirl_Timer = urand(10000, 15000); - } - else - m_uiWhirl_Timer -= diff; + DoCast(m_creature, SPELL_WHIRLWIND); + m_uiWhirl_Timer = urand(10000, 15000); + }else m_uiWhirl_Timer -= diff; if (m_uiShout_Timer < diff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_BATTLE_SHOUT : SPELL_BATTLE_SHOUT_H) == CAST_OK) - m_uiShout_Timer = 30000; - } - else - m_uiShout_Timer -= diff; - + DoCast(m_creature, m_bIsRegularMode ? SPELL_BATTLE_SHOUT : SPELL_BATTLE_SHOUT_H); + m_uiShout_Timer = 30000; + }else m_uiShout_Timer -= diff; + DoMeleeAttackIfReady(); } @@ -393,11 +380,11 @@ struct MANGOS_DLL_DECL mob_dark_rune_guardianAI : public ScriptedAI { mob_dark_rune_guardianAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiStormstrike_Timer; @@ -414,12 +401,10 @@ struct MANGOS_DLL_DECL mob_dark_rune_guardianAI : public ScriptedAI if (m_uiStormstrike_Timer < diff) { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_STORMSTRIKE) == CAST_OK) - m_uiStormstrike_Timer = urand(7000, 13000); - } - else - m_uiStormstrike_Timer -= diff; - + DoCast(m_creature->getVictim(), SPELL_STORMSTRIKE); + m_uiStormstrike_Timer = urand(7000, 13000); + }else m_uiStormstrike_Timer -= diff; + DoMeleeAttackIfReady(); } }; @@ -435,13 +420,13 @@ struct MANGOS_DLL_DECL mob_mole_machineAI : public ScriptedAI { mob_mole_machineAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetDisplayId(11686); // make invisible SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiSummonTimer; bool m_bIsSentinel; @@ -495,12 +480,12 @@ struct MANGOS_DLL_DECL boss_razorscaleAI : public ScriptedAI { boss_razorscaleAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiFireball_Timer; @@ -508,48 +493,59 @@ struct MANGOS_DLL_DECL boss_razorscaleAI : public ScriptedAI uint32 m_uiFlame_Buffet_Timer; uint32 m_uiFuse_Armor_Timer; uint32 m_uiFlame_Breath_Timer; - uint32 m_uiWave_spawn; + uint32 m_uiWave1_spawn; //right side, 1 of each + uint32 m_uiWave2_spawn; //left side, 1 of each + uint32 m_uiWave3_spawn; // big guy uint32 m_uiBerserk_Timer; - uint32 m_uiGroundStepTimer; - uint32 m_uiGroundStepCount; + uint32 m_uiGrounded_Timer; // 8 secs after ground fase is over, adds come + uint32 m_uiGround_Cast; + uint32 m_uiGround_Knockback; uint32 m_uiRepairHarpoonTimer; - uint8 m_uiHarpoonsRepaired; uint8 m_uiMaxHarpoons; + ObjectGuid m_uiHarpoonsGUID[4]; + uint32 m_uiTimetoground; + uint32 m_uiStun_Timer; + bool m_bAirphase; + bool m_bIsGrounded; + bool m_bHasBerserk; + bool m_bKnockback; uint8 m_uiHarpoonsUsed; uint8 m_uiFlyNo; - uint8 m_uiScorchedDwarves; - GUIDList m_lRepairHarpoonsGUID; - GUIDList m_lHarpoonsDummyGUID; - - RazorscalePhase razorscalePhase; + std::list lHarpoons; void Reset() { - m_uiMaxHarpoons = m_bIsRegularMode ? 2 : 4; - //if (m_pInstance->m_lBreakHarpoonGUID.size() != m_uiMaxHarpoons) - //m_creature->MonsterSay("Fehler in der Suche der Harpoonen", LANG_UNIVERSAL); - BreakHarpoons(); - - m_uiFireball_Timer = 10000; // 10 secs for the first - m_uiDevouring_Flame_Timer = 18000; // 18 secs first, 12 seconds after - m_uiWave_spawn = urand(5000, 10000); - m_uiBerserk_Timer = 600000; // 10 min - m_uiRepairHarpoonTimer = 51000; - m_uiHarpoonsRepaired = 0; - - razorscalePhase = PHASE_AIR; + m_uiFireball_Timer = 10000; // 10 secs for the first, fckin spam after that ~2secs + m_uiDevouring_Flame_Timer = 18000; // 18 secs first, 12 seconds after + m_uiWave1_spawn = urand(5000, 10000); + m_uiWave2_spawn = urand(5000, 10000); + m_uiWave3_spawn = urand(5000, 10000); + m_uiBerserk_Timer = 600000; // 10 min + m_uiTimetoground = 80000; + m_uiRepairHarpoonTimer = 53000; + m_uiHarpoonsRepaired = 0; + m_uiMaxHarpoons = m_bIsRegularMode ? 2 : 4; + for(int i = 0; i < m_uiMaxHarpoons; i++) + m_uiHarpoonsGUID[i].Clear(); + m_bAirphase = false; + m_bIsGrounded = false; + m_bHasBerserk = false; + m_bKnockback = false; m_uiFlyNo = 0; m_uiHarpoonsUsed = 0; - m_uiScorchedDwarves = 0; - m_creature->SetWalk(true); - SetCombatMovement(false); - // make boss fly - m_creature->SetLevitate(true); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); + lHarpoons.clear(); + + if(m_creature->GetPositionZ() < 435.0f) + { + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->MonsterMoveWithSpeed(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 26); + } - m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->GetMotionMaster()->MoveConfused(); if (Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_COMMANDER)) pCommander->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); @@ -560,335 +556,266 @@ struct MANGOS_DLL_DECL boss_razorscaleAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_RAZORSCALE, DONE); - BreakHarpoons(); + if (m_uiFlyNo < 2) + { + // hacky way to complete achievements; use only if you have this function + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_QUICK_SHAVE : ACHIEV_QUICK_SHAVE_H); + } } void Aggro(Unit* pWho) { if (m_pInstance) m_pInstance->SetData(TYPE_RAZORSCALE, IN_PROGRESS); - m_creature->MonsterMoveWithSpeed(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 28); - } - void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_FLAME_BREATH || pSpell->Id == SPELL_FLAME_BREATH_H) + GetGameObjectListWithEntryInGrid(lHarpoons, m_creature, GO_BROKEN_HARPOON, 200.0f); + if (!lHarpoons.empty()) { - if (pTarget->GetEntry() == MOB_DARK_RUNE_GUARDIAN) // only this one + int i = 0; + for(std::list::iterator iter = lHarpoons.begin(); iter != lHarpoons.end(); ++iter) { - ++m_uiScorchedDwarves; - if (m_uiScorchedDwarves > 25) - { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_IRON_DWARF_MEDIUM_RARE, true); - } - m_creature->DealDamage(pTarget, pTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if ((*iter)) + { + m_uiHarpoonsGUID[i] = (*iter)->GetObjectGuid(); + i += 1; + } } } + + m_bAirphase = true; + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->MonsterMoveWithSpeed(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 26); } void JustReachedHome() { if (m_pInstance) - m_pInstance->SetData(TYPE_RAZORSCALE, FAIL); + m_pInstance->SetData(TYPE_RAZORSCALE, NOT_STARTED); + + BreakHarpoons(); } void BreakHarpoons() { // reset harpoons - for (GUIDVector::iterator iter = m_pInstance->m_lBreakHarpoonGUID.begin(); iter != m_pInstance->m_lBreakHarpoonGUID.end(); ++iter) + if (!lHarpoons.empty()) { - if (GameObject* pBreakHarpoon = m_creature->GetMap()->GetGameObject(*iter)) + for(std::list::iterator iter = lHarpoons.begin(); iter != lHarpoons.end(); ++iter) { - pBreakHarpoon->SetPhaseMask(1, true); + if ((*iter)) + { + (*iter)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + //(*iter)->SetUInt32Value(GAMEOBJECT_DISPLAYID, 8631); + } } } - for (GUIDList::iterator iter = m_lRepairHarpoonsGUID.begin(); iter != m_lRepairHarpoonsGUID.end(); ++iter) + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // AIR PHASE + // air position check (sometimes it falls to the ground like a rock + if(m_creature->GetPositionZ() < 430.0f && m_bAirphase && !m_bIsGrounded) { - if (GameObject* pRepairHarpoon = m_creature->GetMap()->GetGameObject(*iter)) - { - pRepairHarpoon->Delete(); - } + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->MonsterMoveWithSpeed(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 26); } - for (GUIDList::iterator iter = m_lHarpoonsDummyGUID.begin(); iter != m_lHarpoonsDummyGUID.end(); ++iter) + + // air spells + if (m_uiFireball_Timer < uiDiff && m_bAirphase && !m_bIsGrounded) { - if (Creature* pHarpoonDummy = m_creature->GetMap()->GetCreature(*iter)) - { - pHarpoonDummy->ForcedDespawn(); - } - } - m_lHarpoonsDummyGUID.clear(); - m_lRepairHarpoonsGUID.clear(); - } + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H); + m_uiFireball_Timer = 2000; + }else m_uiFireball_Timer -= uiDiff; - void RepairHarpoons() - { - if(GameObject* pHarpoon = m_creature->GetMap()->GetGameObject(m_pInstance->m_lBreakHarpoonGUID.at(m_uiHarpoonsRepaired))) + if (m_uiDevouring_Flame_Timer < uiDiff && !m_bIsGrounded) { - switch(m_uiHarpoonsRepaired) + if (m_bAirphase) { - case 0: - { - if (GameObject* pRepairHarpoon = pHarpoon->SummonGameobject(GO_REPAIR_HARPOON_1, pHarpoon->GetPositionX(),pHarpoon->GetPositionY(),pHarpoon->GetPositionZ(), 4.732974f, 0)) - { - m_lRepairHarpoonsGUID.push_back(pRepairHarpoon->GetObjectGuid()); - } - break; - } - case 1: - { - if (GameObject* pRepairHarpoon = pHarpoon->SummonGameobject(GO_REPAIR_HARPOON_2, pHarpoon->GetPositionX(),pHarpoon->GetPositionY(),pHarpoon->GetPositionZ(), 5.269379f, 0)) - { - m_lRepairHarpoonsGUID.push_back(pRepairHarpoon->GetObjectGuid()); - } - break; - } - case 2: - { - if (GameObject* pRepairHarpoon = pHarpoon->SummonGameobject(GO_REPAIR_HARPOON_3, pHarpoon->GetPositionX(),pHarpoon->GetPositionY(),pHarpoon->GetPositionZ(), pHarpoon->GetOrientation(), 0)) - m_lRepairHarpoonsGUID.push_back(pRepairHarpoon->GetObjectGuid()); - break; - } - case 3: - { - if (GameObject* pRepairHarpoon = pHarpoon->SummonGameobject(GO_REPAIR_HARPOON_4, pHarpoon->GetPositionX(),pHarpoon->GetPositionY(),pHarpoon->GetPositionZ(), pHarpoon->GetAngle(m_creature), 0)) - m_lRepairHarpoonsGUID.push_back(pRepairHarpoon->GetObjectGuid()); - break; - } + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, DEVOURING_FLAME_VISUAL); } - if (Creature* pHarpoonDummy = pHarpoon->SummonCreature(NPC_HARPOONS_DUMMY, pHarpoon->GetPositionX(), pHarpoon->GetPositionY(), pHarpoon->GetPositionZ(),0 , TEMPSUMMON_DEAD_DESPAWN, 0)) + else { - m_lHarpoonsDummyGUID.push_back(pHarpoonDummy->GetObjectGuid()); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(target, DEVOURING_FLAME_VISUAL); } - pHarpoon->SetPhaseMask(128,true); - } - } - - void SetToGroundPhase() - { - if(Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_COMMANDER)) - DoScriptText(SAY_GROUND, pCommander); - - // make boss land - m_creature->SetLevitate(false); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); - - // ground position - m_creature->MonsterMoveWithSpeed(PositionLoc[3].x, PositionLoc[3].y, PositionLoc[3].z, 40.0f); - - // timers - m_uiHarpoonsUsed = 0; - m_uiGroundStepTimer = 2000; - m_uiGroundStepCount = 0; - razorscalePhase = PHASE_GROUND; - } + m_uiDevouring_Flame_Timer = 12000; + }else m_uiDevouring_Flame_Timer -= uiDiff; - void SetToAirPhase() - { - if(Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_COMMANDER)) - DoScriptText(SAY_FIRES_EXTINGUISH, pCommander); - // make boss fly - m_creature->SetLevitate(true); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); - razorscalePhase = PHASE_AIR; - m_uiFireball_Timer = 10000; - m_uiDevouring_Flame_Timer = 18000; - m_uiWave_spawn = urand(5000, 10000); - m_uiRepairHarpoonTimer = 50000; - m_uiHarpoonsRepaired = 0; - - // achiev counter - m_uiFlyNo++; - if (m_uiFlyNo > 1) + // repair harpoons + if (m_uiRepairHarpoonTimer < uiDiff && m_bAirphase && !m_bIsGrounded && m_uiHarpoonsRepaired <= m_uiMaxHarpoons) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_QUICK_SHAVE, false); + if(GameObject* pHarpoon = m_pInstance->instance->GetGameObject(m_uiHarpoonsGUID[m_uiHarpoonsRepaired])) + { + pHarpoon->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + //pHarpoon->SetUInt32Value(GAMEOBJECT_DISPLAYID, 8245); + m_uiHarpoonsRepaired += 1; + } + DoScriptText(EMOTE_HARPOON, m_creature); + m_uiRepairHarpoonTimer = 20000; } - } - - void SetToPermGroundedPhase() - { - if (m_creature->HasAura(SPELL_STUN)) - m_creature->RemoveAurasDueToSpell(SPELL_STUN); - - DoScriptText(EMOTE_GROUNDED, m_creature); - razorscalePhase = PHASE_PERMAGROUND; - m_uiDevouring_Flame_Timer = 12000; - m_uiFlame_Buffet_Timer = 10000; //every 10 secs - m_uiFuse_Armor_Timer = 13000; //every ~13 - m_uiFlame_Breath_Timer = 6000; //every 14 - SetCombatMovement(true); - BreakHarpoons(); - // make boss land - m_creature->SetLevitate(false); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); - } + else m_uiRepairHarpoonTimer -= uiDiff; - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + // ground adds + if (m_uiWave1_spawn < uiDiff && m_bAirphase && !m_bIsGrounded) + { + m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[0].x, PositionLoc[0].y, PositionLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + m_uiWave1_spawn = urand(40000, 50000); + }else m_uiWave1_spawn -= uiDiff; - // make boss land at 50% hp - if (m_creature->GetHealthPercent() < 50 && razorscalePhase != PHASE_PERMAGROUND) + if (m_uiWave2_spawn < uiDiff && m_bAirphase && !m_bIsGrounded) { - SetToPermGroundedPhase(); - } + m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[1].x, PositionLoc[1].y, PositionLoc[1].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + m_uiWave2_spawn = urand(40000, 50000); + }else m_uiWave2_spawn -= uiDiff; - switch(razorscalePhase) + if (m_uiWave3_spawn < uiDiff && m_bAirphase && !m_bIsGrounded) { - case PHASE_AIR: + switch(urand(0, 2)) //33% chance of spawning { - // Switch from Air to Ground Phase - if (m_uiHarpoonsUsed == m_uiMaxHarpoons) - { - SetToGroundPhase(); - return; - } - // air position check (sometimes it falls to the ground like a rock - if(m_creature->GetPositionZ() < 440.0f) - { - m_creature->MonsterMoveWithSpeed(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 28); - } - - // air spells - if (m_uiFireball_Timer < uiDiff) - { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) - DoCast(target, m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H); - m_uiFireball_Timer = 2000; - }else - m_uiFireball_Timer -= uiDiff; - - if (m_uiDevouring_Flame_Timer < uiDiff) - { - if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) - DoCast(target, DEVOURING_FLAME_MISSILE); - m_uiDevouring_Flame_Timer = 12000; - }else - m_uiDevouring_Flame_Timer -= uiDiff; - - // repair harpoons - if (m_uiRepairHarpoonTimer < uiDiff && m_uiHarpoonsRepaired <= m_uiMaxHarpoons) - { - RepairHarpoons(); - ++m_uiHarpoonsRepaired; - DoScriptText(EMOTE_HARPOON, m_creature); - m_uiRepairHarpoonTimer = 20000; - } - else - m_uiRepairHarpoonTimer -= uiDiff; - + case 0: break; - } - case PHASE_GROUND: - { - if (m_uiGroundStepTimer < uiDiff) - { - switch (m_uiGroundStepCount) - { - case 0: - DoCast(m_creature, SPELL_STUN, true); - m_uiGroundStepTimer = 33000; - break; - case 1: - if (Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_COMMANDER)) - m_creature->SetFacingToObject(pCommander); - m_creature->RemoveAurasDueToSpell(SPELL_STUN); - DoScriptText(EMOTE_DEEP_BREATH, m_creature); - DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); - m_uiGroundStepTimer = 7000; - break; - case 2: - DoCast(m_creature, SPELL_WING_BUFFET); - BreakHarpoons(); - m_uiGroundStepTimer = 4000; - break; - case 3: - SetToAirPhase(); - m_uiGroundStepTimer = 4000; - break; - default: // debug next action Fly - m_uiGroundStepCount = 2; - m_creature->RemoveAurasDueToSpell(SPELL_STUN); - m_uiGroundStepTimer = 4000; - break; - } - ++m_uiGroundStepCount; - } - else - m_uiGroundStepTimer -= uiDiff; - + case 1: + if(Creature* pTemp = m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[2].x, PositionLoc[2].y, PositionLoc[2].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + ((mob_mole_machineAI*)pTemp->AI())->m_bIsSentinel = true; + break; + case 2: break; } - case PHASE_PERMAGROUND: - { - if (m_uiDevouring_Flame_Timer < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), DEVOURING_FLAME_MISSILE) == CAST_OK) - m_uiDevouring_Flame_Timer = 12000; - } - else - m_uiDevouring_Flame_Timer -= uiDiff; + m_uiWave3_spawn = urand(40000, 50000); + }else m_uiWave3_spawn -= uiDiff; - if (m_uiFuse_Armor_Timer < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FUSE_ARMOR) == CAST_OK) - m_uiFuse_Armor_Timer = 13000; - } - else - m_uiFuse_Armor_Timer -= uiDiff; + // berserk + if (m_uiBerserk_Timer < uiDiff && !m_bHasBerserk) + { + DoCast(m_creature, SPELL_BERSERK); + m_bHasBerserk = true; + }else m_uiBerserk_Timer -= uiDiff; - if (m_uiFlame_Buffet_Timer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FLAME_BUFFET : SPELL_FLAME_BUFFET_H) == CAST_OK) - m_uiFlame_Buffet_Timer = 13000; - } - else - m_uiFlame_Buffet_Timer -= uiDiff; + if (m_uiHarpoonsUsed == m_uiMaxHarpoons && m_bAirphase) + { + if(Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_COMMANDER)) + DoScriptText(SAY_GROUND, pCommander); + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[3].x, PositionLoc[3].y, PositionLoc[3].z, 1.5); + m_creature->MonsterMoveWithSpeed(PositionLoc[3].x, PositionLoc[3].y, PositionLoc[3].z, 26); + // timers + m_uiHarpoonsUsed = 0; + m_bIsGrounded = true; + m_uiStun_Timer = 2000; + m_uiGround_Cast = 35000; + m_uiGrounded_Timer = 45000; + // make boss land + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + }else m_uiTimetoground -= uiDiff; + + if (m_uiStun_Timer < uiDiff && m_bIsGrounded) + { + DoCast(m_creature, SPELL_STUN); + m_uiStun_Timer = 60000; + }else m_uiStun_Timer -= uiDiff; - if (m_uiFlame_Breath_Timer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H) == CAST_OK) - { - DoScriptText(EMOTE_DEEP_BREATH, m_creature); - m_uiFlame_Breath_Timer = 14000; - } - } - else - m_uiFlame_Breath_Timer -= uiDiff; + if (m_uiGround_Cast < uiDiff && m_bIsGrounded) + { + if (Creature* pCommander = m_pInstance->GetSingleCreatureFromStorage(NPC_COMMANDER)) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pCommander->GetObjectGuid().GetRawValue()); + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + DoScriptText(EMOTE_DEEP_BREATH, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); + m_uiGround_Cast = 15000; + m_uiGround_Knockback = 7000; + }else m_uiGround_Cast -= uiDiff; - DoMeleeAttackIfReady(); + if (m_uiGround_Knockback < uiDiff && m_bIsGrounded) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_WING_BUFFET); + m_uiGround_Knockback = 15000; + m_uiGrounded_Timer = 3000; + }else m_uiGround_Knockback -= uiDiff; - break; - } - default: - EnterEvadeMode(); - } + if (m_uiGrounded_Timer < uiDiff && m_bIsGrounded) + { + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->MonsterMoveWithSpeed(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 26); + + m_bIsGrounded = false; + m_uiFireball_Timer = 10000; + m_uiDevouring_Flame_Timer = 18000; + m_uiWave1_spawn = urand(5000, 10000); + m_uiWave2_spawn = urand(5000, 10000); + m_uiWave3_spawn = urand(5000, 10000); + m_uiRepairHarpoonTimer = 50000; + m_uiHarpoonsRepaired = 0; + BreakHarpoons(); + // make boss fly + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + // achiev counter + m_uiFlyNo += 1; + }else m_uiGrounded_Timer -= uiDiff; - // ground adds only in Air and grounded phase NOT in Permagrounded Phase - if (m_uiWave_spawn < uiDiff && razorscalePhase != PHASE_PERMAGROUND) + // make boss land at 50% hp + if (m_bAirphase && m_creature->GetHealthPercent() < 50) { - m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[0].x, PositionLoc[0].y, PositionLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); - m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[1].x, PositionLoc[1].y, PositionLoc[1].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); - if (roll_chance_i(33)) - { - if(Creature* pTemp = m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[2].x, PositionLoc[2].y, PositionLoc[2].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) - if (mob_mole_machineAI* molAI = (mob_mole_machineAI*)pTemp->AI()) - molAI->m_bIsSentinel = true; - } - m_uiWave_spawn = urand(40000, 50000); - } - else - m_uiWave_spawn -= uiDiff; + if (m_creature->HasAura(SPELL_STUN)) + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + + DoScriptText(EMOTE_GROUNDED, m_creature); + m_uiGround_Knockback = m_bIsGrounded ? 0 : 3000; + m_bAirphase = false; + m_bIsGrounded = false; + m_uiDevouring_Flame_Timer = 12000; + m_uiFlame_Buffet_Timer = 10000; //every 10 secs + m_uiFuse_Armor_Timer = 13000; //every ~13 + m_uiFlame_Breath_Timer = 6000; //every 14 + SetCombatMovement(true); + + // make boss land + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + + // LAND PHASE + // knockback at the beginning at the land phase + if (m_uiGround_Knockback < uiDiff && !m_bKnockback && !m_bAirphase) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_WING_BUFFET); + m_bKnockback = true; + }else m_uiGround_Knockback -= uiDiff; - // berserk - if (m_uiBerserk_Timer < uiDiff) + if (m_uiFuse_Armor_Timer < uiDiff && !m_bAirphase) { - DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT); - } - else - m_uiBerserk_Timer -= uiDiff; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_FUSE_ARMOR); + m_uiFuse_Armor_Timer = 13000; + } else m_uiFuse_Armor_Timer -= uiDiff; + + if (m_uiFlame_Buffet_Timer < uiDiff && !m_bAirphase) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BUFFET : SPELL_FLAME_BUFFET_H); + m_uiFlame_Buffet_Timer = 13000; + }else m_uiFlame_Buffet_Timer -= uiDiff; + + if (m_uiFlame_Breath_Timer < uiDiff && !m_bAirphase) + { + DoScriptText(EMOTE_DEEP_BREATH, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); + m_uiFlame_Breath_Timer = 14000; + }else m_uiFlame_Breath_Timer -= uiDiff; + + if (!m_bAirphase && !m_bIsGrounded) + DoMeleeAttackIfReady(); if (m_creature->GetDistance2d(HOME_X, HOME_Y) > 100) EnterEvadeMode(); @@ -900,15 +827,16 @@ CreatureAI* GetAI_boss_razorscale(Creature* pCreature) return new boss_razorscaleAI(pCreature); } -bool GOHello_go_repair_harpoon(Player* pPlayer, GameObject* pGo) +bool GOHello_go_broken_harpoon(Player* pPlayer, GameObject* pGo) { - instance_ulduar* m_pInstance = (instance_ulduar*)pGo->GetInstanceData(); + ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData(); - if (!m_pInstance) + if (!pInstance) return false; - if (Creature* pRazor = m_pInstance->GetSingleCreatureFromStorage(NPC_RAZORSCALE)) - if (boss_razorscaleAI* pRazorAI = (boss_razorscaleAI*)pRazor->AI()) - pRazorAI->m_uiHarpoonsUsed++; + + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + if (Creature* pRazor = pInstance->GetSingleCreatureFromStorage(NPC_RAZORSCALE)) + ((boss_razorscaleAI*)pRazor->AI())->m_uiHarpoonsUsed += 1; return false; } @@ -955,7 +883,7 @@ void AddSC_boss_razorscale() NewScript->RegisterSelf(); NewScript = new Script; - NewScript->Name = "go_repair_harpoon"; - NewScript->pGOUse = &GOHello_go_repair_harpoon; + NewScript->Name = "go_broken_harpoon"; + NewScript->pGOUse = &GOHello_go_broken_harpoon; NewScript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_thorim.cpp b/scripts/northrend/ulduar/ulduar/boss_thorim.cpp index 18d5db8ff9..943b3980cb 100644 --- a/scripts/northrend/ulduar/ulduar/boss_thorim.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_thorim.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2011 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -17,10 +17,7 @@ /* ScriptData SDName: boss_thorim SD%Complete: -SDComment: better solution for teleport into arena - Implement lightning orbs, summon Sit on the platform in the first 3 min. - Runic Smash from Runic Colossus need core support, unknow trigger spell 62406 and 62403 - Achievments: Don't Stand in the Lightning, Who Needs Bloodlust? +SDComment: Implement lightning orbs, summon Sit on the platform in the first 3 min. SDCategory: Ulduar EndScriptData */ @@ -30,30 +27,28 @@ EndScriptData */ enum { //yells - SAY_AGGRO1 = -1603190, - SAY_AGGRO2 = -1603191, - SAY_SPECIAL1 = -1603192, - SAY_SPECIAL2 = -1603193, - SAY_SPECIAL3 = -1603194, - SAY_JUMP = -1603195, - SAY_SLAY1 = -1603196, - SAY_SLAY2 = -1603197, - SAY_BERSERK = -1603198, - SAY_ARENA_WIPE = -1603199, - SAY_DEATH = -1603200, - SAY_OUTRO1 = -1603201, - SAY_OUTRO2 = -1603202, - SAY_OUTRO3 = -1603203, - SAY_OUTRO_HARD1 = -1603204, - SAY_OUTRO_HARD2 = -1603205, - SAY_OUTRO_HARD3 = -1603206, + SAY_AGGRO1 = -1603221, + SAY_AGGRO2 = -1603222, + SAY_SPECIAL1 = -1603223, + SAY_SPECIAL2 = -1603224, + SAY_SPECIAL3 = -1603225, + SAY_JUMP = -1603226, + SAY_SLAY1 = -1603227, + SAY_SLAY2 = -1603228, + SAY_BERSERK = -1603229, + SAY_ARENA_WIPE = -1603230, + SAY_DEATH = -1603231, + SAY_OUTRO1 = -1603232, + SAY_OUTRO2 = -1603233, + SAY_OUTRO3 = -1603234, + SAY_OUTRO_HARD1 = -1603235, + SAY_OUTRO_HARD2 = -1603236, + SAY_OUTRO_HARD3 = -1603237, // Sif - SAY_SIF_INTRO = -1603210, - SAY_SIF_EVENT = -1603211, - SAY_SIF_DESPAWN = -1603212, - - SPELL_THORIM_CREDIT = 64985, // custom spell in spell_dbc.sql + SAY_SIF_INTRO = -1603185, + SAY_SIF_EVENT = -1603186, + SAY_SIF_DESPAWN = -1603187, // spells // phase1 @@ -65,6 +60,7 @@ enum NPC_THUNDER_ORB = 33378, // npc used to cast charged orb SPELL_BERSERK_ADDS = 62560, // 5 min phase 1 -> for adds SPELL_SUMMON_LIGHTNING_ORB = 62391, + NPC_LIGHTNING_ORB = 33138, // phase2 SPELL_TOUTCH_OF_DOMINION = 62565, // not available in hard mode SPELL_CHAIN_LIGHTNING = 62131, @@ -91,10 +87,10 @@ enum MOB_DARK_RUNE_WARBRINGER = 32877, // traps - NPC_TRAP_BUNNY = 33725, - NPC_TRAP_BUNNY2 = 33054, - SPELL_PARALYTIC_FIELD = 63540, - SPELL_PARALYTIC_FIELD2 = 62241, + NPC_TRAP_BUNNY = 33725, + NPC_TRAP_BUNNY2 = 33054, + SPELL_PARALYTIC_FIELD = 63540, + SPELL_PARALYTIC_FIELD2 = 62241, // mobs spells // acolyte @@ -135,15 +131,12 @@ enum // hallway MOB_DARK_RUNE_ACOLYTE = 33110, MOB_IRON_RING_GUARD = 32874, - - MOB_IRON_HONOR_GUARD = 33125, - - // Colossus - SPELL_SMASH = 62339, - //SPELL_SMASH_RIGHT = 62414, - SPELL_RUNIC_SMASH_L = 62058, - SPELL_RUNIC_SMASH_R = 62057, - SPELL_RUNIC_SMASH_DMG = 62465, + MINIBOSS_RUNIC_COLOSSUS = 32872, + SPELL_SMASH = 62339, + //SPELL_SMASH_RIGHT = 62414, + SPELL_RUNIC_SMASH = 62058, + SPELL_RUNIC_SMASH2 = 62057, + SPELL_RUNIC_SMASH_DMG = 62465, SPELL_RUNIC_BARRIER = 62338, SPELL_CHARGE = 62613, SPELL_CHARGE_H = 62614, @@ -156,17 +149,23 @@ enum SPELL_RUNE_DETONATION = 62526, // pre adds: - SPELL_ACID_BREATH = 62315, - SPELL_ACID_BREATH_H = 62415, - SPELL_SWEEP = 62316, - SPELL_SWEEP_H = 62417, + SPELL_ACID_BREATH = 62315, + SPELL_ACID_BREATH_H = 62415, + SPELL_SWEEP = 62316, + SPELL_SWEEP_H = 62417, // captains - SPELL_DEVASTATE = 62317, - SPELL_HEROIC_STRIKE = 62444, + NPC_CAPTAIN_ALY = 32908, + NPC_CAPTAIN_HORDE = 32907, + SPELL_DEVASTATE = 62317, + SPELL_HEROIC_STRIKE = 62444, // mercenary - SPELL_SHOOT = 16496, - SPELL_BARBED_SHOT = 62318, - SPELL_WING_CLIP = 40652, + NPC_MERCENARY_ALY = 32885, + NPC_MERCENARY_HORDE = 32883, + SPELL_SHOOT = 16496, + SPELL_BARBED_SHOT = 62318, + SPELL_WING_CLIP = 40652, + + SPELL_THORIM_CREDIT = 64985, ACHIEV_LOSE_ILLUSION = 3176, ACHIEV_LOSE_ILLUSION_H = 3183, @@ -176,11 +175,11 @@ enum enum phases { - PHASE_PREADDS = 0, - PHASE_INTRO = 1, - PHASE_BALCONY = 2, - PHASE_ARENA = 3, - PHASE_OUTRO = 4, + PHASE_PREADDS = 0, + PHASE_INTRO = 1, + PHASE_BALCONY = 2, + PHASE_ARENA = 3, + PHASE_OUTRO = 4, }; #define LOC_Z 419.5f @@ -321,6 +320,11 @@ struct MANGOS_DLL_DECL mob_dark_rune_championAI : public ScriptedAI m_uiSpell_Timer = urand(3000, 6000); } + void JustReachedHome() + { + m_creature->ForcedDespawn(); + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) @@ -367,6 +371,11 @@ struct MANGOS_DLL_DECL mob_dark_rune_commonerAI : public ScriptedAI m_uiSpell_Timer = urand(3000, 6000); } + void JustReachedHome() + { + m_creature->ForcedDespawn(); + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) @@ -378,10 +387,10 @@ struct MANGOS_DLL_DECL mob_dark_rune_commonerAI : public ScriptedAI { case 0: DoCast(m_creature->getVictim(), SPELL_LOW_BLOW); - break; + break; case 1: DoCast(m_creature->getVictim(), SPELL_PUMMEL); - break; + break; } m_uiSpell_Timer = urand(3000, 6000); }else m_uiSpell_Timer -= uiDiff; @@ -425,15 +434,15 @@ struct MANGOS_DLL_DECL mob_dark_rune_evokerAI : public ScriptedAI case 1: if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) DoCast(pTarget, m_bIsRegularMode ? SPELL_RUNIC_LIGHTNING : SPELL_RUNIC_LIGHTNING_H); - break; + break; case 2: case 3: if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) DoCast(pTarget, m_bIsRegularMode ? SPELL_RUNIC_MENDING : SPELL_RUNIC_MENDING_H); - break; + break; case 4: DoCast(m_creature, m_bIsRegularMode ? SPELL_RUNIC_SHIELD : SPELL_RUNIC_SHIELD_H); - break; + break; } m_uiSpell_Timer = urand(3000, 6000); }else m_uiSpell_Timer -= uiDiff; @@ -581,13 +590,13 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI { boss_thorimAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiPhase; @@ -598,7 +607,6 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI uint32 m_uiDeafeningThunderTimer; uint32 m_uiChargeOrbTimer; uint32 m_uiSummonWavesTimer; - uint32 m_uiJumpTimer; ObjectGuid m_uiStormTargetGUID; uint32 m_uiChainLightningTimer; @@ -606,17 +614,15 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI uint32 m_uiOrbChargeTimer; uint32 m_uiUnbalancingStrikeTimer; + uint32 m_uiPhase2Timer; uint32 m_uiHardModeTimer; - bool m_bIsPhaseOneEnd; + bool m_bIsPhaseEnd; bool m_bIsHardMode; uint32 m_uiPreAddsKilled; ObjectGuid m_uiSifGUID; - //Arena Door - uint32 m_uiDoorArenaTimer; - // intro & outro bool m_bIsOutro; uint32 m_uiOutroTimer; @@ -626,25 +632,23 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI uint32 m_uiIntroStep; // mob list check - GUIDList lIronDwarfes; - GUIDList m_lOrbsGUIDList; - GUIDList m_lArenaSummonGUID; + std::list lIronDwarfes; + std::list m_lOrbs; void Reset() { - m_uiPreAddsKilled = 0; - m_uiPhase = PHASE_PREADDS; + m_uiPreAddsKilled = 0; + m_uiPhase = PHASE_PREADDS; SetCombatMovement(false); m_bIsHardMode = true; - m_bIsPhaseOneEnd = false; + m_bIsPhaseEnd = false; m_uiArenaBerserkTimer = 280000; // 5 min - 20 secs intro m_uiBerserkTimer = 300000; // 5 min m_uiHardModeTimer = 160000; // 3 min - 20 sec intro m_uiArenaYellTimer = 30000; m_uiSummonWavesTimer = 10000; - m_uiJumpTimer = 5000; m_uiStormHammerTimer = 20000; m_uiDeafeningThunderTimer = 22000; @@ -661,50 +665,86 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI m_uiIntroTimer = 10000; m_uiIntroStep = 1; m_bIsOutro = false; + m_uiSifGUID.Clear(); lIronDwarfes.clear(); - m_lOrbsGUIDList.clear(); + m_lOrbs.clear(); // exploit check m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - for (GUIDList::iterator itr = m_lArenaSummonGUID.begin(); itr != m_lArenaSummonGUID.end(); itr++) + // orbs + GetCreatureListWithEntryInGrid(m_lOrbs, m_creature, NPC_THUNDER_ORB, 100.0f); + if (!m_lOrbs.empty()) { - if (Creature *pTmp = m_creature->GetMap()->GetCreature(*itr)) + for(std::list::iterator iter = m_lOrbs.begin(); iter != m_lOrbs.end(); ++iter) { - pTmp->ForcedDespawn(); + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + (*iter)->setFaction(35); } } - if (m_pInstance) + + // respawn adds + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, MOB_IRON_RING_GUARD, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, MOB_DARK_RUNE_ACOLYTE, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, MOB_IRON_HOHOR_GUARD, DEFAULT_VISIBILITY_INSTANCE); + // preadds + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_MERCENARY_ALY, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_MERCENARY_HORDE, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_CAPTAIN_ALY, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_CAPTAIN_HORDE, DEFAULT_VISIBILITY_INSTANCE); + if (!lIronDwarfes.empty()) { - for (GUIDList::iterator itr = m_pInstance->m_lThorimMobsGuids.begin(); itr != m_pInstance->m_lThorimMobsGuids.end(); itr++) - if (Creature *pTmp = m_pInstance->instance->GetCreature(*itr)) - if (!pTmp->isAlive()) - pTmp->Respawn(); + for(std::list::iterator iter = lIronDwarfes.begin(); iter != lIronDwarfes.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } } + if(m_pInstance) + { + // respawn runic colossus + if (Creature* pColossus = m_pInstance->GetSingleCreatureFromStorage(NPC_RUNIC_COLOSSUS)) + { + if (!pColossus->isAlive()) + pColossus->Respawn(); + } + + // respawn ancient rune giant + if (Creature* pRuneGiant = m_pInstance->GetSingleCreatureFromStorage(NPC_RUNE_GIANT)) + { + if (!pRuneGiant->isAlive()) + pRuneGiant->Respawn(); + } - + // respawn jormungar + if (Creature* pJormungar = m_pInstance->GetSingleCreatureFromStorage(NPC_JORMUNGAR_BEHEMOTH)) + { + if (!pJormungar->isAlive()) + pJormungar->Respawn(); + } + } } - // support CORE!!! + void SpellHitTarget(Unit* pSpellTarget, const SpellEntry* pSpell) { if(pSpell->Id == SPELL_STORMHAMMER) - pSpellTarget->CastSpell(pSpellTarget, SPELL_DEAFENING_THUNDER, false,0,0,m_creature->GetObjectGuid()); + pSpellTarget->CastSpell(pSpellTarget, SPELL_DEAFENING_THUNDER, false); } void JustReachedHome() { if(m_pInstance) - { - m_pInstance->SetData(TYPE_THORIM, FAIL); - m_pInstance->SetData(TYPE_THORIM_HARD, FAIL); - } - + m_pInstance->SetData(TYPE_THORIM, NOT_STARTED); } void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_SLAY1 : SAY_SLAY2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); } void DoOutro() @@ -714,36 +754,64 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI if(m_bIsHardMode) { m_pInstance->SetData(TYPE_THORIM_HARD, DONE); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_LOSE_ILLUSION : ACHIEV_LOSE_ILLUSION_H); } m_pInstance->SetData(TYPE_THORIM, DONE); } - DoCast(m_creature, SPELL_THORIM_CREDIT, true); + + if (!m_lOrbs.empty()) + { + for(std::list::iterator iter = m_lOrbs.begin(); iter != m_lOrbs.end(); ++iter) + { + (*iter)->setFaction(35); + } + } + + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (!pPlayer) + continue; + pPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_THORIM_CREDIT); + } m_creature->ForcedDespawn(); } // for debug only void JustDied(Unit* pKiller) { - if(m_pInstance) + if(m_pInstance) { if(m_bIsHardMode) m_pInstance->SetData(TYPE_THORIM_HARD, DONE); m_pInstance->SetData(TYPE_THORIM, DONE); } - DoCast(m_creature, SPELL_THORIM_CREDIT, true); } - // start outro + // start phase 2 and outro void DamageTaken(Unit *done_by, uint32 &uiDamage) { - // outro - if((m_creature->GetHealthPercent() < 1.0f || m_creature->GetHealth() <= uiDamage) && m_uiPhase == PHASE_ARENA) + // phase 2 + if(uiDamage > 0 && m_uiPhase == PHASE_BALCONY && !m_bIsPhaseEnd) { - if (m_bIsHardMode) + if(m_pInstance->GetData(TYPE_RUNIC_COLOSSUS) == DONE && m_pInstance->GetData(TYPE_RUNE_GIANT) == DONE) { - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_LOSE_YOUR_ILLUSION, true); + // say + DoScriptText(SAY_JUMP, m_creature); + // move in arena + m_creature->GetMotionMaster()->MovePoint(0, 2134.719f, -263.148f, 419.846f); + m_creature->SetWalk(false); + m_bIsPhaseEnd = true; + m_uiPhase2Timer = 9000; } + } + + // outro + if(m_creature->GetHealthPercent() < 1.0f && m_uiPhase == PHASE_ARENA) + { uiDamage = 0; m_uiPhase = PHASE_OUTRO; } @@ -751,42 +819,30 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI void StartEncounter() { - m_uiPhase = PHASE_INTRO; - m_bIsIntro = true; - } + m_uiPhase = PHASE_INTRO; + m_bIsIntro = true; - // hacky way for berserk in phase 1 :) - void KillPlayers() - { - Map *map = m_creature->GetMap(); - if (map->IsDungeon()) + if (!m_lOrbs.empty()) { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + for(std::list::iterator iter = m_lOrbs.begin(); iter != m_lOrbs.end(); ++iter) { - if (i->getSource()->isAlive() && m_creature->GetDistance(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()) < 200.0f) - i->getSource()->DealDamage(i->getSource(), i->getSource()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + (*iter)->setFaction(14); } - } + } } + Creature* SelectRandomOrb() { - std::list lThunderList; - GetCreatureListWithEntryInGrid(lThunderList, m_creature, NPC_THUNDER_ORB, 100.0f); - //This should not appear! - if (lThunderList.empty()){ + if (m_lOrbs.empty()) + { m_uiChargeOrbTimer = 5000; return NULL; } - std::list::iterator iter = lThunderList.begin(); - advance(iter, urand(0, lThunderList.size()-1)); + std::list::iterator iter = m_lOrbs.begin(); + advance(iter, urand(0, m_lOrbs.size()-1)); return *iter; } @@ -796,53 +852,51 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI switch(m_uiPhase) { // start the encounter when all the preadds have died - case PHASE_PREADDS: - if(m_uiPreAddsKilled == 4) - StartEncounter(); - break; + case PHASE_PREADDS: + if(m_uiPreAddsKilled >= 4) + StartEncounter(); + break; // do intro - case PHASE_INTRO: + case PHASE_INTRO: { // intro if(m_bIsIntro) { switch(m_uiIntroStep) { - case 1: - // wait 10 secs - ++m_uiIntroStep; - m_uiIntroTimer = 10000; - break; - case 3: - DoScriptText(SAY_AGGRO1, m_creature); - DoCast(m_creature, SPELL_SHEAT_OF_LIGHTNING); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetInCombatWithZone(); - if (m_pInstance) - m_pInstance->SetData(TYPE_THORIM, IN_PROGRESS); - ++m_uiIntroStep; - m_uiIntroTimer = 10000; - break; - case 5: - DoScriptText(SAY_AGGRO2, m_creature); - if(Creature* pSif = m_creature->SummonCreature(NPC_SIF, m_creature->GetPositionX() + 10, m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) - { - pSif->setFaction(35); - m_uiSifGUID = pSif->GetObjectGuid(); - } - ++m_uiIntroStep; - m_uiIntroTimer = 9000; - break; - case 7: - if(Creature* pSif = m_pInstance->instance->GetCreature(m_uiSifGUID)) - DoScriptText(SAY_SIF_INTRO, pSif); - m_uiPhase = PHASE_BALCONY; - m_bIsIntro = false; - ++m_uiIntroStep; - m_uiIntroTimer = 9000; - break; - default: - break; + case 1: + // wait 10 secs + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + case 3: + DoScriptText(SAY_AGGRO1, m_creature); + DoCast(m_creature, SPELL_SHEAT_OF_LIGHTNING); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + if (m_pInstance) + m_pInstance->SetData(TYPE_THORIM, IN_PROGRESS); + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + case 5: + DoScriptText(SAY_AGGRO2, m_creature); + if(Creature* pSif = m_creature->SummonCreature(NPC_SIF, m_creature->GetPositionX() + 10, m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 700000)) + { + pSif->setFaction(35); + m_uiSifGUID = pSif->GetObjectGuid(); + } + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + break; + case 7: + if(Creature* pSif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + DoScriptText(SAY_SIF_INTRO, pSif); + m_uiPhase = PHASE_BALCONY; + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + break; } } else return; @@ -856,60 +910,42 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI break; } // balcony phase - case PHASE_BALCONY: + case PHASE_BALCONY: { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // phase 2 - if(!m_bIsPhaseOneEnd) + // phase 2 prepared + if(m_uiPhase2Timer < uiDiff && m_bIsPhaseEnd) { - if(m_pInstance->GetData(TYPE_RUNIC_COLOSSUS) == DONE && m_pInstance->GetData(TYPE_RUNE_GIANT) == DONE) + m_creature->RemoveAurasDueToSpell(SPELL_SHEAT_OF_LIGHTNING); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(!m_bIsHardMode) + DoCast(m_creature, SPELL_TOUTCH_OF_DOMINION); + if(m_bIsHardMode) { - if (GetPlayerAtMinimumRange(15.0f)) - { - // say - DoScriptText(SAY_JUMP, m_creature); - m_creature->RemoveAurasDueToSpell(SPELL_SHEAT_OF_LIGHTNING); - // move in arena - SetCombatMovement(true); - m_bIsPhaseOneEnd = true; - if(m_bIsHardMode) - { - if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) - { - Sif->setFaction(14); - DoScriptText(SAY_SIF_EVENT, Sif); - Sif->SetInCombatWithZone(); - Sif->MonsterMoveJump(2134.719f, -263.148f, 419.846f, 0, 30, 30); - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_SIFFED, true); - } - } - else - { - DoCast(m_creature, SPELL_TOUTCH_OF_DOMINION, true); - } + if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + { + Sif->setFaction(14); + DoScriptText(SAY_SIF_EVENT, Sif); + Sif->SetInCombatWithZone(); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_SIFFED : ACHIEV_SIFFED_H); } } + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + m_uiPhase = PHASE_ARENA; + m_bIsPhaseEnd = false; } - if (m_bIsPhaseOneEnd) - { - if(m_uiJumpTimer < uiDiff && m_bIsPhaseOneEnd) - { - m_creature->GetMap()->CreatureRelocation(m_creature, 2134.719f, -263.148f, 419.846f, 0); - m_creature->Relocate(2134.719f, -263.148f, 419.846f, 0); - m_creature->GetMotionMaster()->MovePoint(0, 2134.719f, -263.148f, 419.846f); - m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + else m_uiPhase2Timer -= uiDiff; - m_uiPhase = PHASE_ARENA; - } - else - m_uiJumpTimer -= uiDiff; - } + // return if jumping to second phase + if(m_bIsPhaseEnd) + return; // hard mode check - if (m_uiHardModeTimer <= uiDiff && m_bIsHardMode) + if (m_uiHardModeTimer < uiDiff && m_bIsHardMode) { m_bIsHardMode = false; if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) @@ -921,7 +957,8 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI } } m_uiHardModeTimer = 330000; - } m_uiHardModeTimer -= uiDiff; + } + else m_uiHardModeTimer -= uiDiff; // spawn adds in arena if(m_uiSummonWavesTimer < uiDiff) @@ -935,21 +972,35 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI uint8 k; switch(urand(0, 4)) { - case 0: - i = urand(0, 5); - if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_CHAMPION, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) + case 0: + i = urand(0, 5); + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_CHAMPION, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) { - pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); - if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) - { - pTemp->AI()->AttackStart(m_creature->getVictim()); - pTemp->AddThreat(m_creature->getVictim(), 100.0f); - } + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); } - break; - case 1: - i = urand(0, 5); - if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_EVOKER, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) + } + break; + case 1: + i = urand(0, 5); + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_EVOKER, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + break; + case 2: + i = urand(5, 6); + for(uint8 j = 0; j < i; j++) + { + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_COMMONER, ArenaLoc[j].x, ArenaLoc[j].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) @@ -958,41 +1009,14 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI pTemp->AddThreat(m_creature->getVictim(), 100.0f); } } - break; - case 2: - i = urand(5, 6); - for(uint8 j = 0; j < i; j++) - { - if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_COMMONER, ArenaLoc[j].x, ArenaLoc[j].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) - { - pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); - if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) - { - pTemp->AI()->AttackStart(m_creature->getVictim()); - pTemp->AddThreat(m_creature->getVictim(), 100.0f); - } - } - } - break; - case 3: - k = urand(0, 3); - i = urand(k + 1, k + 2); - for(uint8 j = k; j < i; j++) - { - if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_WARBRINGER, ArenaLoc[j].x, ArenaLoc[j].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) - { - pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); - if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) - { - pTemp->AI()->AttackStart(m_creature->getVictim()); - pTemp->AddThreat(m_creature->getVictim(), 100.0f); - } - } - } - break; - case 4: - i = urand(0, 5); - if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_ACOLYTE, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) + } + break; + case 3: + k = urand(0, 3); + i = urand(k + 1, k + 2); + for(uint8 j = k; j < i; j++) + { + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_WARBRINGER, ArenaLoc[j].x, ArenaLoc[j].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) @@ -1001,15 +1025,27 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI pTemp->AddThreat(m_creature->getVictim(), 100.0f); } } - break; + } + break; + case 4: + i = urand(0, 5); + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_ACOLYTE, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + break; } - m_uiSummonWavesTimer = urand (5000, 7000); + m_uiSummonWavesTimer = urand (7000, 10000); } else m_uiSummonWavesTimer -= uiDiff; // phase 1 spells // charge orb - // doesn't work right, needs fixing if(m_uiChargeOrbTimer < uiDiff) { if (Creature* pOrb = SelectRandomOrb()) @@ -1021,15 +1057,9 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI // storm hammer if(m_uiStormHammerTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - // should target only the players in the arena! - if(pTarget->IsInRange2d(2134.0f, -263.0f ,0 , 50)) // middle point of arena - width of arena ~45m - { - DoCast(pTarget, SPELL_STORMHAMMER); - m_uiStormHammerTimer = 15000; - } - } + // need to find a way to ignore LOS + DoCast(m_creature, SPELL_STORMHAMMER); + m_uiStormHammerTimer = 15000; } else m_uiStormHammerTimer -= uiDiff; @@ -1037,9 +1067,9 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI { switch(urand(0, 2)) { - case 0: DoScriptText(SAY_SPECIAL1, m_creature); break; - case 1: DoScriptText(SAY_SPECIAL2, m_creature); break; - case 2: DoScriptText(SAY_SPECIAL3, m_creature); break; + case 0: DoScriptText(SAY_SPECIAL1, m_creature); break; + case 1: DoScriptText(SAY_SPECIAL2, m_creature); break; + case 2: DoScriptText(SAY_SPECIAL3, m_creature); break; } m_uiArenaYellTimer = 30000; } @@ -1049,10 +1079,10 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI if(m_uiArenaBerserkTimer < uiDiff) { DoScriptText(SAY_ARENA_WIPE, m_creature); - //DoCast(m_creature, SPELL_BERSERK_ADDS); - // workaround because berserk doesn't work. It's casted on players not on adds. Needs core fix - KillPlayers(); - DoCast(m_creature, SPELL_SUMMON_LIGHTNING_ORB); + // half working, it affects thorim but not his army of adds... + DoCast(m_creature, SPELL_BERSERK_ADDS); + // should be done by spell + DoSpawnCreature(NPC_LIGHTNING_ORB, 0, 5.0f, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 120000); m_uiArenaBerserkTimer = 30000; } else m_uiArenaBerserkTimer -= uiDiff; @@ -1060,7 +1090,7 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI break; } // arena phase - case PHASE_ARENA: + case PHASE_ARENA: { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -1116,7 +1146,7 @@ struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI break; } // outro - case PHASE_OUTRO: + case PHASE_OUTRO: { switch(m_uiOutroStep) { @@ -1210,30 +1240,29 @@ struct MANGOS_DLL_DECL boss_runic_colossusAI : public ScriptedAI { boss_runic_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiSpellTimer; uint32 m_uiRunicBarrierTimer; uint32 m_uiSmashTimer; - uint32 m_uiTriggerSmashTimer; + ObjectGuid m_uiSmashTargetGUID; bool m_bIsSmash; - - bool m_bIsLeft; + bool m_bMustSmash; void Reset() { m_uiSpellTimer = urand(5000, 10000); m_uiRunicBarrierTimer = 15000; m_uiSmashTimer = 3000; - m_uiTriggerSmashTimer = 20000; - m_bIsSmash = true; - m_bIsLeft = false; + m_uiSmashTargetGUID.Clear(); + m_bIsSmash = false; + m_bMustSmash = true; if(m_pInstance) m_pInstance->SetData(TYPE_RUNIC_COLOSSUS, NOT_STARTED); @@ -1245,70 +1274,35 @@ struct MANGOS_DLL_DECL boss_runic_colossusAI : public ScriptedAI m_pInstance->SetData(TYPE_RUNIC_COLOSSUS, DONE); } - void AttackedBy(Unit* pWho) + void MoveInLineOfSight(Unit* pWho) { - if (m_bIsSmash && pWho->GetTypeId() == TYPEID_PLAYER) + // start smashing + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && + !m_bIsSmash && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 70) && m_creature->IsWithinLOSInMap(pWho)) { - m_creature->SetInCombatWithZone(); - m_creature->InterruptNonMeleeSpells(false); - m_bIsSmash = false; + m_uiSmashTargetGUID = pWho->GetObjectGuid(); + m_creature->GetMotionMaster()->MoveIdle(); + m_bIsSmash = true; } - } - void UpdateAI(const uint32 uiDiff) - { - if(m_uiSmashTimer < uiDiff && m_bIsSmash) + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && + m_bIsSmash && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 5) && m_creature->IsWithinLOSInMap(pWho)) { - switch(urand(0,1)) - { - case 0: - DoCast(m_creature, SPELL_RUNIC_SMASH_L); - m_bIsLeft = true; - break; - case 1: - DoCast(m_creature, SPELL_RUNIC_SMASH_R); - m_bIsLeft = false; - break; - } - m_uiSmashTimer = 8000; - m_uiTriggerSmashTimer = 5000; - + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_bMustSmash = false; } - else - m_uiSmashTimer -= uiDiff; + } - if (m_uiTriggerSmashTimer < uiDiff && m_bIsSmash) + void UpdateAI(const uint32 uiDiff) + { + // smash, doesn't work. Spell needs core fix + if(m_uiSmashTimer < uiDiff && m_bIsSmash && m_bMustSmash) { - if (m_pInstance) - { - if (Map* pMap = m_creature->GetMap()) - { - if (m_bIsLeft) - { - for (GUIDList::iterator itr = m_pInstance->m_lLeftHandTriggerGuids.begin(); itr != m_pInstance->m_lLeftHandTriggerGuids.end(); ++itr) - { - if (Unit* trigger = pMap->GetUnit(*itr)) - { - trigger->CastSpell(trigger, SPELL_RUNIC_SMASH_DMG, false, 0, 0, m_creature->GetObjectGuid()); - } - } - } - else - { - for (GUIDList::iterator itr = m_pInstance->m_lRightHandTriggerGuids.begin(); itr != m_pInstance->m_lRightHandTriggerGuids.end(); ++itr) - { - if (Unit* trigger = pMap->GetUnit(*itr)) - { - trigger->CastSpell(trigger, SPELL_RUNIC_SMASH_DMG, false, 0, 0, m_creature->GetObjectGuid()); - } - } - } - } - } - m_uiTriggerSmashTimer = 20000; + if(Unit* pTarget = m_creature->GetMap()->GetUnit(m_uiSmashTargetGUID)) + DoCast(pTarget, SPELL_RUNIC_SMASH_DMG); + m_uiSmashTimer = 10000; } - else - m_uiTriggerSmashTimer -= uiDiff; + else m_uiSmashTimer -= uiDiff; if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -1317,26 +1311,22 @@ struct MANGOS_DLL_DECL boss_runic_colossusAI : public ScriptedAI { switch(urand(0, 1)) { - case 0: - DoCast(m_creature, SPELL_SMASH); - break; - case 1: - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, m_bIsRegularMode ? SPELL_CHARGE : SPELL_CHARGE_H); - break; + case 0: + DoCast(m_creature, SPELL_SMASH); + break; + case 1: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_CHARGE : SPELL_CHARGE_H); + break; } m_uiSpellTimer = urand(5000, 10000); - } - else - m_uiSpellTimer -= uiDiff; + }else m_uiSpellTimer -= uiDiff; if (m_uiRunicBarrierTimer < uiDiff) { - if (DoCastSpellIfCan(m_creature, SPELL_RUNIC_BARRIER) == CAST_OK) - m_uiRunicBarrierTimer = urand(25000, 30000); - } - else - m_uiRunicBarrierTimer -= uiDiff; + DoCast(m_creature, SPELL_RUNIC_BARRIER); + m_uiRunicBarrierTimer = urand(25000, 30000); + }else m_uiRunicBarrierTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -1351,23 +1341,25 @@ struct MANGOS_DLL_DECL boss_ancient_rune_giantAI : public ScriptedAI { boss_ancient_rune_giantAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiSpellTimer; uint32 m_uiSummonTimer; bool m_bIsSummoning; + bool m_bSummonStop; void Reset() { m_uiSpellTimer = urand(5000, 10000); - m_uiSummonTimer = 5000; - m_bIsSummoning = true; + m_uiSummonTimer = 10000; + m_bIsSummoning = false; + m_bSummonStop = false; if(m_pInstance) m_pInstance->SetData(TYPE_RUNE_GIANT, NOT_STARTED); @@ -1379,33 +1371,44 @@ struct MANGOS_DLL_DECL boss_ancient_rune_giantAI : public ScriptedAI m_pInstance->SetData(TYPE_RUNE_GIANT, DONE); } - void AttackedBy(Unit* pWho) + void Aggro(Unit *who) { - if (m_bIsSummoning && pWho->GetTypeId() == TYPEID_PLAYER) - { - m_creature->SetInCombatWith(pWho); - DoCast(m_creature, SPELL_RUNIC_FORTIFICATION, true); - m_bIsSummoning = false; - } + // should be cast on adds, spell needs core fix + //DoCast(m_creature, SPELL_RUNIC_FORTIFICATION); + m_bSummonStop = true; + m_bIsSummoning = false; } void UpdateAI(const uint32 uiDiff) { - if ((m_pInstance->GetData(TYPE_RUNIC_COLOSSUS) == DONE) && m_bIsSummoning) + if(m_pInstance->GetData(TYPE_RUNIC_COLOSSUS) == DONE && !m_bIsSummoning && !m_bSummonStop) + m_bIsSummoning = true; + + // summon adds before aggro and after the runic colossus has died + if(m_uiSummonTimer < uiDiff && m_bIsSummoning) { - // summon adds before aggro and after the runic colossus has died - if(m_uiSummonTimer < uiDiff) + switch(urand(0, 1)) { + case 0: + // ring guard + if(Creature* pTemp = m_creature->SummonCreature(32874, OrbLoc[0].x + 30, OrbLoc[0].y, OrbLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, OrbLoc[1].x, OrbLoc[1].y, OrbLoc[1].z); + pTemp->SetInCombatWithZone(); + } + break; + case 1: // honor guard - if(Creature* pTemp = m_creature->SummonCreature(MOB_IRON_HONOR_GUARD, OrbLoc[0].x + 30, OrbLoc[0].y, OrbLoc[0].z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000)) + if(Creature* pTemp = m_creature->SummonCreature(33125, OrbLoc[0].x + 30, OrbLoc[0].y, OrbLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { pTemp->GetMotionMaster()->MovePoint(0, OrbLoc[1].x, OrbLoc[1].y, OrbLoc[1].z); pTemp->SetInCombatWithZone(); } - m_uiSummonTimer = 7000; + break; } - else m_uiSummonTimer -= uiDiff; + m_uiSummonTimer = 10000; } + else m_uiSummonTimer -= uiDiff; if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -1438,13 +1441,13 @@ struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI { mob_thorim_preaddsAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } bool m_bIsRegularMode; - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; // jormungar uint32 m_uiAcidBreathTimer; @@ -1462,19 +1465,39 @@ struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI void Reset() { // jormungar - m_uiAcidBreathTimer = urand(7000, 14000); - m_uiSweepTimer = urand(15000, 20000); + m_uiAcidBreathTimer = urand(7000, 14000); + m_uiSweepTimer = urand(15000, 20000); // captain - m_uiDevastateTimer = urand(3000, 7000); + m_uiDevastateTimer = urand(3000, 7000); m_uiHeroicStrikeTimer = urand(8000, 15000); // mercenary - m_uiShootTimer = 1000; - m_uiBarbedShotTimer = urand(7000, 10000); + m_uiShootTimer = 1000; + m_uiBarbedShotTimer = urand(7000, 10000); m_uiWingClipTimer = urand(10000, 15000); } + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + // this to avoid that the preadds to kill themselves + if (pDoneBy->GetTypeId() != TYPEID_PLAYER) + { + switch(pDoneBy->GetEntry()) + { + case NPC_JORMUNGAR_BEHEMOTH: + case NPC_CAPTAIN_ALY: + case NPC_CAPTAIN_HORDE: + case NPC_MERCENARY_ALY: + case NPC_MERCENARY_HORDE: + uiDamage = 0; + break; + default: + break; + } + } + } + void AttackStart(Unit* pWho) { if (m_creature->Attack(pWho, true)) @@ -1495,7 +1518,7 @@ struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI if (Creature* pThorim = m_pInstance->GetSingleCreatureFromStorage(NPC_THORIM)) { if(pThorim->isAlive()) - ((boss_thorimAI*)pThorim->AI())->m_uiPreAddsKilled++; + ((boss_thorimAI*)pThorim->AI())->m_uiPreAddsKilled += 1; } } @@ -1506,7 +1529,7 @@ struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI switch(m_creature->GetEntry()) { - case NPC_JORMUNGAR_BEHEMOTH: + case NPC_JORMUNGAR_BEHEMOTH: { if(m_uiAcidBreathTimer < uiDiff) { @@ -1524,8 +1547,8 @@ struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI break; } - case NPC_CAPTAIN_ALY: - case NPC_CAPTAIN_HORDE: + case NPC_CAPTAIN_ALY: + case NPC_CAPTAIN_HORDE: { if(m_uiDevastateTimer < uiDiff) { @@ -1544,8 +1567,8 @@ struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI break; } - case NPC_MERCENARY_ALY: - case NPC_MERCENARY_HORDE: + case NPC_MERCENARY_ALY: + case NPC_MERCENARY_HORDE: { if(m_uiShootTimer < uiDiff) { @@ -1588,14 +1611,14 @@ struct MANGOS_DLL_DECL npc_sifAI : public ScriptedAI { npc_sifAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - //pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - //pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiSpellTimer; @@ -1632,17 +1655,17 @@ struct MANGOS_DLL_DECL npc_sifAI : public ScriptedAI { switch(urand(0, 2)) { - case 0: - DoCast(m_creature, m_bIsRegularMode? SPELL_FROSTBOLT_VOLLEY : SPELL_FROSTBOLT_VOLLEY_H); - break; - case 1: - DoCast(m_creature, m_bIsRegularMode? SPELL_FROST_NOVA : SPELL_FROST_NOVA_H); - break; - case 2: - // it should be casted around the room! - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, m_bIsRegularMode? SPELL_BLIZZARD : SPELL_BLIZZARD_H); - break; + case 0: + DoCast(m_creature, m_bIsRegularMode? SPELL_FROSTBOLT_VOLLEY : SPELL_FROSTBOLT_VOLLEY_H); + break; + case 1: + DoCast(m_creature, m_bIsRegularMode? SPELL_FROST_NOVA : SPELL_FROST_NOVA_H); + break; + case 2: + // it should be casted around the room! + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode? SPELL_BLIZZARD : SPELL_BLIZZARD_H); + break; } m_uiSpellTimer = urand(3000, 6000); @@ -1655,28 +1678,44 @@ CreatureAI* GetAI_npc_sif(Creature* pCreature) return new npc_sifAI(pCreature); } +// thunder orb +struct MANGOS_DLL_DECL npc_thunder_orbAI : public ScriptedAI +{ + npc_thunder_orbAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + } + + void Reset(){} +}; + +CreatureAI* GetAI_npc_thunder_orb(Creature* pCreature) +{ + return new npc_thunder_orbAI(pCreature); +} + // script for the orb on the hallway which should wipe the raid. Needs more research! struct MANGOS_DLL_DECL npc_lightning_orbAI : public ScriptedAI { npc_lightning_orbAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); pCreature->setFaction(14); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; - bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + uint32 m_uiKillTimer; uint32 m_uiMoveTimer; uint8 m_uiWaypoint; void Reset() { + m_uiKillTimer = 500; m_uiMoveTimer = 1000; m_uiWaypoint = 0; m_creature->SetRespawnDelay(DAY); @@ -1693,6 +1732,24 @@ struct MANGOS_DLL_DECL npc_lightning_orbAI : public ScriptedAI if (m_pInstance && m_pInstance->GetData(TYPE_THORIM) != IN_PROGRESS) m_creature->ForcedDespawn(); + if (m_uiKillTimer < uiDiff) + { + Map *map = m_creature->GetMap(); + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && m_creature->GetDistance(i->getSource()) < 30.0f) + if (m_creature->IsWithinLOSInMap(i->getSource())) + i->getSource()->DealDamage(i->getSource(), i->getSource()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + m_uiKillTimer = 500; + } + else m_uiKillTimer -= uiDiff; + if (m_uiMoveTimer < uiDiff && m_uiWaypoint < 4) { m_creature->GetMotionMaster()->MovePoint(0, OrbLoc[m_uiWaypoint].x, OrbLoc[m_uiWaypoint].y, OrbLoc[m_uiWaypoint].z); @@ -1708,6 +1765,16 @@ CreatureAI* GetAI_npc_lightning_orb(Creature* pCreature) return new npc_lightning_orbAI(pCreature); } +// door lever +bool pGOUse_go_thorim_lever(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData(); + if(GameObject* pDoor = pInstance->GetSingleGameObjectFromStorage(GO_DARK_IRON_PORTCULIS)) + { + pDoor->SetGoState(GO_STATE_ACTIVE); + } + return true; +} void AddSC_boss_thorim() { @@ -1737,6 +1804,11 @@ void AddSC_boss_thorim() newscript->GetAI = &GetAI_npc_lightning_orb; newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_thunder_orb"; + newscript->GetAI = &GetAI_npc_thunder_orb; + newscript->RegisterSelf(); + newscript = new Script; newscript->Name = "mob_dark_rune_acolyte"; newscript->GetAI = &GetAI_mob_dark_rune_acolyte; @@ -1782,5 +1854,8 @@ void AddSC_boss_thorim() newscript->GetAI = &GetAI_mob_thorim_trap_bunny; newscript->RegisterSelf(); - -} \ No newline at end of file + newscript = new Script; + newscript->Name = "go_thorim_lever"; + newscript->pGOUse = &pGOUse_go_thorim_lever; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ulduar/ulduar/boss_xt_002.cpp b/scripts/northrend/ulduar/ulduar/boss_xt_002.cpp index eca986206e..8293e9f456 100644 --- a/scripts/northrend/ulduar/ulduar/boss_xt_002.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_xt_002.cpp @@ -1,23 +1,23 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* 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, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ +/* Copyright (C) 2006 - 2011 ScriptDev2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ /* ScriptData SDName: boss_xt002 SD%Complete: -SDComment: correct number of adds in 25man missing; Void Zone Damage; Heart Life; Achievment Nerf Gravity Bombs +SDComment: need core support for light and gravity bomb. correct number of adds in 25man missing SDCategory: Ulduar EndScriptData */ @@ -27,18 +27,17 @@ EndScriptData */ enum { //xt yells - - SAY_DEATH = -1603040, - SAY_BERSERK = -1603041, - SAY_ADDS = -1603042, - SAY_HEART_CLOSE = -1603043, - SAY_HEART_OPEN = -1603044, - SAY_SLAY_02 = -1603045, - SAY_SLAY_01 = -1603046, - SAY_TANCTRUM = -1603047, - SAY_AGGRO = -1603048, - EMOTE_HEART = -1603049, - EMOTE_REPAIR = -1603050, + SAY_AGGRO = -1603038, + SAY_DEATH = -1603030, + SAY_TANCTRUM = -1603037, + SAY_SLAY_01 = -1603036, + SAY_SLAY_02 = -1603035, + SAY_BERSERK = -1603031, + SAY_ADDS = -1603032, + SAY_HEART_OPEN = -1603034, + SAY_HEART_CLOSE = -1603033, + EMOTE_HEART = -1603350, + EMOTE_REPAIR = -1603351, //xt-002 SPELL_TANCTRUM = 62776, @@ -49,7 +48,6 @@ enum SPELL_GRAVITY_BOMB_H = 64234, SPELL_ENRAGE = 47008, SPELL_STUN = 3618, - SPELL_ENERGY_ORB = 62790, // hard mode SPELL_HEARTBREAK = 65737, @@ -58,22 +56,17 @@ enum SPELL_VOIDZONE_H = 64235, SPELL_VOIDZONE_EFFECT = 46264, SPELL_LIFE_SPARK = 64210, - - // Life Spark - SPELL_SHOCK = 64230, SPELL_STATIC_CHARGED = 64227, SPELL_STATIC_CHARGED_H = 64236, - // Aura Void Zone!? + NPC_VOIDZONE = 34001, + NPC_LIFESPARK = 34004, //heart of the deconstructor SPELL_EXPOSED_HEART = 63849, - //XS-013 Scrapbot - SPELL_SCRAP_REPAIR = 62832, - //XE-321 Boombot - SPELL_BOOM = 38831, // right spell 62834 + SPELL_BOOM = 38831, // replacing real spell //XM-024 Pummeller SPELL_CLEAVE = 8374, @@ -81,21 +74,24 @@ enum SPELL_UPPERCUT = 10966, //NPC ids - NPC_HEART = 33329, - NPC_SCRAPBOT = 33343, - NPC_BOOMBOT = 33346, - NPC_PUMMELER = 33344, - NPC_VOIDZONE = 34001, - NPC_LIFESPARK = 34004, + NPC_HEART = 33329, + NPC_SCRAPBOT = 33343, + NPC_BOOMBOT = 33346, + NPC_PUMMELER = 33344, + + // Achievs + ACHIEV_HEARTBREAKER = 3058, + ACHIEV_HEARTBREAKER_H = 3059, + ACHIEV_DECONSTRUCT_FAST = 2937, + ACHIEV_DECONSTRUCT_FAST_H = 2938, + ACHIEV_NERF_ENGINEERING = 2931, + ACHIEV_NERF_ENGINEERING_H = 2932, + ACHIEV_NERF_GRAVITY_BOMBS = 2934, + ACHIEV_NERF_GRAVITY_BOMBS_H = 2936, + ACHIEV_NERF_SCRAPBOTS = 2933, + ACHIEV_NERF_SCRAPBOTS_H = 2935, }; -enum XT002Phase -{ - PHASE_NORMAL = 1, - PHASE_ADDS = 2, -}; - - //Positional defines struct LocationsXY { @@ -114,7 +110,7 @@ static LocationsXY SummonLoc[]= // void zone struct MANGOS_DLL_DECL mob_voidzoneAI : public ScriptedAI { - mob_voidzoneAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_voidzoneAI(Creature* pCreature) : ScriptedAI(pCreature) { m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -124,29 +120,31 @@ struct MANGOS_DLL_DECL mob_voidzoneAI : public ScriptedAI Reset(); } - uint32 Spell_Timer; + uint32 m_uiSpell_Timer; + SpellEntry const *pSpellInfo; bool m_bIsRegularMode; - SpellEntry const *spellInfo; void Reset() { - spellInfo = (SpellEntry*)GetSpellStore()->LookupEntry(m_bIsRegularMode ? SPELL_VOIDZONE : SPELL_VOIDZONE_H); - Spell_Timer = 1000; + pSpellInfo = (SpellEntry*)GetSpellStore()->LookupEntry(m_bIsRegularMode ? SPELL_VOIDZONE : SPELL_VOIDZONE_H); + m_uiSpell_Timer = 1000; } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { - // should be an aura here. Couldn't find it - // hacky way, needs fixing! - if (Spell_Timer < diff) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) { - if (spellInfo) + if (pSpellInfo) { - int32 damage = spellInfo->CalculateSimpleValue(EFFECT_INDEX_1); - m_creature->CastCustomSpell(m_creature, SPELL_VOIDZONE_EFFECT, &damage, 0, 0, true); + int32 uiDamage = pSpellInfo->CalculateSimpleValue(EFFECT_INDEX_1); + m_creature->CastCustomSpell(m_creature, SPELL_VOIDZONE_EFFECT, &uiDamage, 0, 0, true); } - Spell_Timer = 1000; - }else Spell_Timer -= diff; + m_uiSpell_Timer = 10000; + } + else m_uiSpell_Timer -= uiDiff; } }; @@ -160,30 +158,21 @@ struct MANGOS_DLL_DECL mob_lifesparkAI : public ScriptedAI { mob_lifesparkAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_bIsRegular = m_creature->GetMap()->IsRegularDifficulty(); Reset(); } - bool m_bIsRegularMode; - uint32 m_uiSpell_Timer; + bool m_bIsRegular; void Reset() { - DoCast(m_creature, m_bIsRegularMode ? SPELL_STATIC_CHARGED : SPELL_STATIC_CHARGED_H); - m_uiSpell_Timer = 1000; + DoCast(m_creature, m_bIsRegular ? SPELL_STATIC_CHARGED : SPELL_STATIC_CHARGED_H); } - void UpdateAI(const uint32 uidiff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - - if (m_uiSpell_Timer < uidiff) - { - DoCast(m_creature->getVictim(), SPELL_SHOCK); - m_uiSpell_Timer = urand(4000, 7000); - } else m_uiSpell_Timer -= uidiff; - DoMeleeAttackIfReady(); } }; @@ -195,41 +184,36 @@ CreatureAI* GetAI_mob_lifespark(Creature* pCreature) // XM-024 Pummeller struct MANGOS_DLL_DECL mob_pummelerAI : public ScriptedAI { - mob_pummelerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - Reset(); - } + mob_pummelerAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} - instance_ulduar* m_pInstance; uint32 Spell_Timer; void Reset() - { + { Spell_Timer = urand(5000, 10000); } - - void UpdateAI(const uint32 diff) + + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (Spell_Timer < diff) + if (Spell_Timer < uiDiff) { switch(urand(0, 2)) { - case 0: - DoCast(m_creature->getVictim(), SPELL_CLEAVE); - break; - case 1: - DoCast(m_creature->getVictim(), SPELL_TRAMPLE); - break; - case 2: - DoCast(m_creature->getVictim(), SPELL_UPPERCUT); - break; + case 0: + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + break; + case 1: + DoCast(m_creature->getVictim(), SPELL_TRAMPLE); + break; + case 2: + DoCast(m_creature->getVictim(), SPELL_UPPERCUT); + break; } Spell_Timer = urand(5000, 10000); - }else Spell_Timer -= diff; + }else Spell_Timer -= uiDiff; DoMeleeAttackIfReady(); } @@ -243,16 +227,10 @@ CreatureAI* GetAI_mob_pummeler(Creature* pCreature) // XE-321 Boombot struct MANGOS_DLL_DECL mob_boombotAI : public ScriptedAI { - mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - Reset(); - } - - instance_ulduar* m_pInstance; + mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} void Reset() - { + { } void DamageTaken(Unit* pDoneBy, uint32& uiDamage) @@ -271,7 +249,7 @@ struct MANGOS_DLL_DECL mob_boombotAI : public ScriptedAI DoCast(m_creature, SPELL_BOOM); } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; @@ -290,12 +268,12 @@ struct MANGOS_DLL_DECL mob_xtheartAI : public ScriptedAI { mob_xtheartAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiDeathTimer; uint32 m_uiTotalDamage; @@ -304,7 +282,6 @@ struct MANGOS_DLL_DECL mob_xtheartAI : public ScriptedAI { DoCast(m_creature, SPELL_EXPOSED_HEART); m_creature->SetRespawnDelay(DAY); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_uiTotalDamage = 0; m_uiDeathTimer = 30000; } @@ -312,6 +289,8 @@ struct MANGOS_DLL_DECL mob_xtheartAI : public ScriptedAI void DamageTaken(Unit* pDoneBy, uint32& uiDamage) { m_uiTotalDamage += uiDamage; + // double damage + uiDamage += uiDamage; } void JustDied(Unit* pKiller) @@ -323,10 +302,10 @@ struct MANGOS_DLL_DECL mob_xtheartAI : public ScriptedAI m_pInstance->SetData(TYPE_XT002_HARD, IN_PROGRESS); } - void UpdateAI(const uint32 diff) + void UpdateAI(const uint32 uiDiff) { // despawns the creature if not killed in 30 secs - if(m_uiDeathTimer < diff) + if(m_uiDeathTimer < uiDiff) { // pass damage to boss if (Creature* pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_XT002)) @@ -337,7 +316,7 @@ struct MANGOS_DLL_DECL mob_xtheartAI : public ScriptedAI m_creature->ForcedDespawn(); } else - m_uiDeathTimer -= diff; + m_uiDeathTimer -= uiDiff; } }; @@ -347,72 +326,94 @@ CreatureAI* GetAI_mob_xtheart(Creature* pCreature) } //XT-002 Deconstructor -struct MANGOS_DLL_DECL boss_xt_002AI : public ScriptedAI +struct MANGOS_DLL_DECL boss_xt002AI : public ScriptedAI { - boss_xt_002AI(Creature* pCreature) : ScriptedAI(pCreature) + boss_xt002AI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - XT002Phase m_Phase; + std::list m_lScrapbotsGUIDList; + std::list m_lBoombotsGUIDList; + std::list m_lPummelerGUIDList; // spell timers - uint32 m_uiHeartTimer; - uint32 m_uiLightBombTimer; - uint32 m_uiGravityBombTimer; - uint32 m_uiTanctrumTimer; - uint32 m_uiEnrageTimer; - uint32 m_uiRangeCheckTimer; + uint32 m_uiHeart_Timer; + uint32 m_uiLight_Bomb_Timer; + uint32 m_uiGravity_Bomb_Timer; + uint32 m_uiTanctrum_Timer; + uint32 m_uiEnrage_Timer; + uint32 m_uiRange_Check_Timer; uint32 m_uiVoidZoneTimer; uint32 m_uiLifeSparkTimer; - // Summon - uint32 m_uiSummonTimer; - bool m_bSayAdds; - GUIDList m_lScrapbotsGUIDList; - GUIDList m_lBoombotsGUIDList; - GUIDList m_lPummelerGUIDList; + // summon timers + uint32 m_uiScrapbotTimer; + uint32 m_uiBoombotTimer; + uint32 m_uiPummellerTimer; + uint32 m_uiScrapbotCount; + uint32 m_uiBoombotCount; + uint32 m_uiPummellerCount; + uint32 m_uiMaxScrapbot; + uint32 m_uiMaxBoombot; // health timers - float m_fHealthPercent; - bool m_bIsEnrage; + uint32 m_uiHealthPercent; + uint32 m_uiHpDelayTimer; + bool m_bIsEnrage; + bool m_bPhase2; - ObjectGuid m_uiXtHeartGUID; + ObjectGuid pLightBombTarGUID; + ObjectGuid pGravityBombTarGUID; bool m_bIsHardMode; + bool m_bHasMoreHealth; + + uint32 uiEncounterTimer; + bool m_bIsEngineer; void Reset() { m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - m_Phase = PHASE_NORMAL; // spell timers - m_uiLightBombTimer = 5000; // 7 seconds the first 14 secs all after(7 secs in 25man) - m_uiGravityBombTimer = 30000; // 11 seconds first 18 secs all after(11 secs in 25man) - m_uiTanctrumTimer = 35000; // 38 seconds first 40 secs all after - m_uiEnrageTimer = 600000; // 10 min - m_uiRangeCheckTimer = 1000; - m_uiVoidZoneTimer = 60000; - m_uiLifeSparkTimer = 60000; - - // Summon - m_uiSummonTimer = 5000; - m_bSayAdds = false; + m_uiLight_Bomb_Timer = 5000; // 7 seconds the first 14 secs all after(7 secs in 25man) + m_uiGravity_Bomb_Timer = 30000; // 11 seconds first 18 secs all after(11 secs in 25man) + m_uiTanctrum_Timer = 35000; // 38 seconds first 40 secs all after + m_uiEnrage_Timer = 600000; // 10 min + m_uiRange_Check_Timer = 1000; + m_uiVoidZoneTimer = 60000; + m_uiLifeSparkTimer = urand (5000, 10000); + // summon timers + m_uiScrapbotTimer = 5000; + m_uiBoombotTimer = 5000; + m_uiPummellerTimer = 5000; + m_uiScrapbotCount = 0; + m_uiBoombotCount = 0; + m_uiPummellerCount = 0; + m_uiMaxScrapbot = 0; + m_uiMaxBoombot = 0; + // health timers + m_uiHealthPercent = 75; + + m_bIsEnrage = false; + m_bPhase2 = false; + m_bIsHardMode = false; + m_bHasMoreHealth = false; m_lScrapbotsGUIDList.clear(); m_lBoombotsGUIDList.clear(); m_lPummelerGUIDList.clear(); - // health timers - m_fHealthPercent = 75.0f; - + pLightBombTarGUID.Clear(); + pGravityBombTarGUID.Clear(); - m_bIsEnrage = false; - m_bIsHardMode = false; + uiEncounterTimer = 0; + m_bIsEngineer = true; } void JustDied(Unit* pKiller) @@ -421,7 +422,14 @@ struct MANGOS_DLL_DECL boss_xt_002AI : public ScriptedAI { m_pInstance->SetData(TYPE_XT002, DONE); if(m_bIsHardMode) + { m_pInstance->SetData(TYPE_XT002_HARD, DONE); + // make the heart give the loot for hard mode + // hacky way of giving hard mode loot, used only when hard mode loot is within the heart's corpse + // PLEASE REMOVE FOR REVISION! + if(Creature* pHeart = m_pInstance->GetSingleCreatureFromStorage(NPC_HEART)) + pHeart->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } } DoScriptText(SAY_DEATH, m_creature); @@ -430,22 +438,44 @@ struct MANGOS_DLL_DECL boss_xt_002AI : public ScriptedAI if (!m_lScrapbotsGUIDList.empty()) { - for(GUIDList::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) + for(std::list::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) pTemp->ForcedDespawn(); } if (!m_lBoombotsGUIDList.empty()) { - for(GUIDList::iterator itr = m_lBoombotsGUIDList.begin(); itr != m_lBoombotsGUIDList.end(); ++itr) + for(std::list::iterator itr = m_lBoombotsGUIDList.begin(); itr != m_lBoombotsGUIDList.end(); ++itr) if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) pTemp->ForcedDespawn(); } if (!m_lPummelerGUIDList.empty()) { - for(GUIDList::iterator itr = m_lPummelerGUIDList.begin(); itr != m_lPummelerGUIDList.end(); ++itr) + for(std::list::iterator itr = m_lPummelerGUIDList.begin(); itr != m_lPummelerGUIDList.end(); ++itr) if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) pTemp->ForcedDespawn(); } + + // hacky way to complete achievements; use only if you have this function + // Deconstruct Fast + if (uiEncounterTimer < 205000) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_DECONSTRUCT_FAST : ACHIEV_DECONSTRUCT_FAST_H); + } + + // Heartbreaker + if (m_bIsHardMode) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_HEARTBREAKER : ACHIEV_HEARTBREAKER_H); + } + + // Nerf Engineer + if(m_bIsEngineer) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_NERF_ENGINEERING : ACHIEV_NERF_ENGINEERING_H); + } } void Aggro(Unit* pWho) @@ -468,238 +498,276 @@ struct MANGOS_DLL_DECL boss_xt_002AI : public ScriptedAI m_pInstance->SetData(TYPE_XT002_HARD, NOT_STARTED); } - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetStandState(UNIT_STAND_STATE_STAND); - - if (!m_lScrapbotsGUIDList.empty()) - { - for(GUIDList::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) - if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) - pTemp->ForcedDespawn(); - } - if (!m_lBoombotsGUIDList.empty()) - { - for(GUIDList::iterator itr = m_lBoombotsGUIDList.begin(); itr != m_lBoombotsGUIDList.end(); ++itr) - if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) - pTemp->ForcedDespawn(); - } - if (!m_lPummelerGUIDList.empty()) - { - for(GUIDList::iterator itr = m_lPummelerGUIDList.begin(); itr != m_lPummelerGUIDList.end(); ++itr) - if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) - pTemp->ForcedDespawn(); - } } void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_SLAY_01 : SAY_SLAY_02, m_creature); + switch(urand(0, 1)) + { + case 0: DoScriptText(SAY_SLAY_01, m_creature); break; + case 1: DoScriptText(SAY_SLAY_02, m_creature); break; + } } - void SummonAdds() + void UpdateAI(const uint32 uiDiff) { - if (m_bSayAdds == false) - { - DoScriptText(SAY_ADDS, m_creature); - m_bSayAdds = true; - } - - for (int j = 0; j < (m_bIsRegularMode ? 3 : 5); ++j) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // Achiev timer + uiEncounterTimer += uiDiff; + + // light bomb + if (m_uiLight_Bomb_Timer < uiDiff && !m_bPhase2) { - uint32 addentry = 0; - switch(urand(0,5)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - case 0: - case 1: addentry = NPC_SCRAPBOT; break; - case 2: - case 3: addentry = NPC_BOOMBOT; break; - case 4: addentry = NPC_PUMMELER; break; - default:addentry = NPC_SCRAPBOT; + // fix spell range + DoCast(pTarget, m_bIsRegularMode ? SPELL_LIGHT_BOMB : SPELL_LIGHT_BOMB_H); + pLightBombTarGUID = pTarget->GetObjectGuid(); } - uint8 i = urand(0, 3); - if (Creature* pTemp = m_creature->SummonCreature(addentry, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + + // spawn a life spark from the target + if(m_bIsHardMode) + m_uiLifeSparkTimer = 9000; + + m_uiLight_Bomb_Timer = 10000; + } + else m_uiLight_Bomb_Timer -= uiDiff; + + // graviti bomb + if (m_uiGravity_Bomb_Timer < uiDiff && !m_bPhase2) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - DoCast(pTemp, SPELL_ENERGY_ORB, true); - pTemp->SetInCombatWithZone(); - switch (addentry) - { - case NPC_SCRAPBOT: - m_lScrapbotsGUIDList.push_back(pTemp->GetObjectGuid()); - pTemp->GetMotionMaster()->MoveChase(m_creature); - break; - case NPC_BOOMBOT: - m_lBoombotsGUIDList.push_back(pTemp->GetObjectGuid()); - break; - case NPC_PUMMELER: - m_lPummelerGUIDList.push_back(pTemp->GetObjectGuid()); - break; - } + // fix spell range + DoCast(pTarget, m_bIsRegularMode ? SPELL_GRAVITY_BOMB : SPELL_GRAVITY_BOMB_H); + pGravityBombTarGUID = pTarget->GetObjectGuid(); } - } - } - void SwitchIntoPhaseOne() - { - m_Phase = PHASE_NORMAL; - DoScriptText(SAY_HEART_CLOSE, m_creature); - m_creature->SetStandState(UNIT_STAND_STATE_STAND); - m_creature->RemoveAurasDueToSpell(SPELL_STUN); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - m_uiLightBombTimer = 7000; - m_uiGravityBombTimer= 11000; - m_uiTanctrumTimer = 38000; - } + // spawn a void zone from the target + if(m_bIsHardMode) + m_uiVoidZoneTimer = 9000; - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + m_uiGravity_Bomb_Timer = 25000; + } + else m_uiGravity_Bomb_Timer -= uiDiff; + + if (m_uiTanctrum_Timer < uiDiff && !m_bPhase2) + { + DoCast(m_creature, SPELL_TANCTRUM); + DoScriptText(SAY_TANCTRUM, m_creature); + m_uiTanctrum_Timer = 60000; + }else m_uiTanctrum_Timer -= uiDiff; // enrage timer - if (m_uiEnrageTimer < uiDiff && !m_bIsEnrage) + if (!m_bIsEnrage && m_uiEnrage_Timer < uiDiff && !m_bPhase2) { - if (DoCastSpellIfCan(m_creature, SPELL_ENRAGE) == CAST_OK) + DoCast(m_creature, SPELL_ENRAGE); + if (m_creature->HasAura(SPELL_ENRAGE)) { m_bIsEnrage = true; DoScriptText(SAY_BERSERK, m_creature); } - } - else - m_uiEnrageTimer -= uiDiff; + else + m_uiEnrage_Timer = 5000; + }else m_uiEnrage_Timer -= uiDiff; - // adds range check - if (m_uiRangeCheckTimer < uiDiff) + if (m_uiRange_Check_Timer < uiDiff) { if (!m_lScrapbotsGUIDList.empty()) { - for(GUIDList::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) + for(std::list::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { - if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, 10.0f)) + if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, ATTACK_DISTANCE)) { - DoCast(pTemp, SPELL_SCRAP_REPAIR, true); + m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth() * 0.01); pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_bIsEngineer = false; DoScriptText(EMOTE_REPAIR, m_creature); - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_NERF_ENGINEERING, false); } } } } - m_uiRangeCheckTimer = 1000; - }else - m_uiRangeCheckTimer -= uiDiff; - - switch (m_Phase) - { - case PHASE_NORMAL: + if (!m_lBoombotsGUIDList.empty()) { - if (m_uiLightBombTimer < uiDiff) + for(std::list::iterator itr = m_lBoombotsGUIDList.begin(); itr != m_lBoombotsGUIDList.end(); ++itr) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_LIGHT_BOMB : SPELL_LIGHT_BOMB_H) == CAST_OK) - { - m_uiLightBombTimer = urand(10000, 14000); - } + if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, ATTACK_DISTANCE)) + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } } - else - m_uiLightBombTimer -= uiDiff; + } + m_uiRange_Check_Timer = 1000; + }else m_uiRange_Check_Timer -= uiDiff; - if (m_uiGravityBombTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_GRAVITY_BOMB : SPELL_GRAVITY_BOMB_H) == CAST_OK) - { - m_uiGravityBombTimer = urand(25000, 30000); - } - } - - } - else - m_uiGravityBombTimer -= uiDiff; + // Hard mode + if (!m_bIsHardMode && m_pInstance->GetData(TYPE_XT002_HARD) == IN_PROGRESS) + { + DoScriptText(SAY_HEART_CLOSE, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->AI()->AttackStart(m_creature->getVictim()); + + DoCast(m_creature, m_bIsRegularMode ? SPELL_HEARTBREAK : SPELL_HEARTBREAK_H); + m_uiHpDelayTimer = 500; + m_bHasMoreHealth = true; + m_bIsHardMode = true; + } - if (m_uiTanctrumTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_TANCTRUM) == CAST_OK) - { - DoScriptText(SAY_TANCTRUM, m_creature); - m_uiTanctrumTimer = 60000; - } - } - else - m_uiTanctrumTimer -= uiDiff; + if(m_bIsHardMode) + { + m_bPhase2 = false; - if (m_creature->GetHealthPercent() < m_fHealthPercent && !m_bIsHardMode) + // the spell doesn't increase the boss' health. Override + if(m_bHasMoreHealth && m_uiHpDelayTimer < uiDiff) + { + m_creature->SetHealth(m_creature->GetMaxHealth()+ (m_creature->GetMaxHealth() * m_bIsRegularMode ? 0.5 : 0.6)); + m_bHasMoreHealth = false; + } + else m_uiHpDelayTimer -= uiDiff; + + if (m_uiLifeSparkTimer < uiDiff) + { + if (Unit* pTarget = m_creature->GetMap()->GetUnit(pLightBombTarGUID)) { - m_fHealthPercent = m_fHealthPercent - 25; - m_uiHeartTimer = 30000; - m_creature->CastStop(); - m_Phase = PHASE_ADDS; - - DoScriptText(SAY_HEART_OPEN, m_creature); - DoCast(m_creature, SPELL_STUN); - DoScriptText(EMOTE_HEART, m_creature); - m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - // timers - m_uiSummonTimer = 5000; - m_bSayAdds = false; - - if(Creature* Heart = m_creature->SummonCreature(NPC_HEART, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 900000)) - m_uiXtHeartGUID = Heart->GetObjectGuid(); + Creature * LifeSpark = m_creature->SummonCreature(NPC_LIFESPARK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); + if(m_bIsRegularMode) + LifeSpark->SetHealth(50400); } + m_uiLifeSparkTimer = 60000; + } + else m_uiLifeSparkTimer -= uiDiff; - DoMeleeAttackIfReady(); - break; + if (m_uiVoidZoneTimer < uiDiff) + { + if (Unit* pTarget = m_creature->GetMap()->GetUnit(pGravityBombTarGUID)) + m_creature->SummonCreature(NPC_VOIDZONE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + m_uiVoidZoneTimer = 60000; + } + else m_uiVoidZoneTimer -= uiDiff; + } + + if (!m_bPhase2 && m_creature->GetHealthPercent() < m_uiHealthPercent && !m_bIsHardMode) + { + m_uiHeart_Timer = 30000; + m_creature->CastStop(); + m_uiHealthPercent = m_uiHealthPercent - 25; + m_bPhase2 = true; + DoScriptText(SAY_HEART_OPEN, m_creature); + DoCast(m_creature, SPELL_STUN); + DoScriptText(EMOTE_HEART, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + // timers + m_uiScrapbotTimer = urand(3000, 5000); + m_uiBoombotTimer = urand(3000, 5000); + m_uiPummellerTimer = 5000; + m_uiMaxScrapbot = urand(7, 10) * 5; + m_uiMaxBoombot = urand(3, 7); + m_uiScrapbotCount = 0; + m_uiBoombotCount = 0; + m_uiPummellerCount = 0; + + if(Creature *pHeart = m_creature->SummonCreature(NPC_HEART, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 900000)) + { + // this needs fixing in DB + if(!m_bIsRegularMode) + pHeart->SetMaxHealth(7199999); } - case PHASE_ADDS: + } + + if (m_bPhase2 && m_uiHeart_Timer < uiDiff) + { + DoScriptText(SAY_HEART_CLOSE, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->AI()->AttackStart(m_creature->getVictim()); + m_bPhase2 = false; + m_uiLight_Bomb_Timer = 7000; + m_uiGravity_Bomb_Timer = 11000; + m_uiTanctrum_Timer = 38000; + }else m_uiHeart_Timer -= uiDiff; + + //adds + if(m_bPhase2 && !m_bIsHardMode) + { + // pummeller + if(m_uiPummellerTimer < uiDiff && m_uiPummellerCount < 2) { - if (m_uiSummonTimer < uiDiff) + if(m_uiPummellerCount == 0) + DoScriptText(SAY_ADDS, m_creature); + uint8 i = urand(0, 4); + if (Creature* pTemp = m_creature->SummonCreature(NPC_PUMMELER, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { - SummonAdds(); - m_uiSummonTimer = urand(3000, 5000); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTemp->AddThreat(pTarget,0.0f); + pTemp->AI()->AttackStart(pTarget); + m_lPummelerGUIDList.push_back(pTemp->GetObjectGuid()); + } } - else - m_uiSummonTimer -= uiDiff; + m_uiPummellerCount += 1; + m_uiPummellerTimer = 4000; + } + else m_uiPummellerTimer -= uiDiff; - // Switch into Phase 1 - if (m_uiHeartTimer < uiDiff) + // boombot + if(m_uiBoombotTimer < uiDiff && m_uiBoombotCount < m_uiMaxBoombot) + { + uint8 i = urand(0, 4); + if (Creature* pTemp = m_creature->SummonCreature(NPC_BOOMBOT, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) { - SwitchIntoPhaseOne(); + pTemp->AddThreat(m_creature->getVictim(),1000.0f); + pTemp->AI()->AttackStart(m_creature->getVictim()); + m_lBoombotsGUIDList.push_back(pTemp->GetObjectGuid()); } - else - m_uiHeartTimer -= uiDiff; + m_uiBoombotCount += 1; + m_uiBoombotTimer = 4000; + } + else m_uiBoombotTimer -= uiDiff; - if (m_pInstance->GetData(TYPE_XT002_HARD) == IN_PROGRESS) + // scrapbot + if(m_uiScrapbotTimer < uiDiff && m_uiScrapbotCount < m_uiMaxScrapbot) + { + uint8 i = urand(0, 4); + for(int j = 0; j < 5; j++) { - SwitchIntoPhaseOne(); - DoCast(m_creature, m_bIsRegularMode ? SPELL_HEARTBREAK : SPELL_HEARTBREAK_H); - if (m_pInstance) - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_HEARTBREAKER, true); - m_bIsHardMode = true; + if (Creature* pTemp = m_creature->SummonCreature(NPC_SCRAPBOT, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MoveFollow(m_creature, 0, 0); + m_lScrapbotsGUIDList.push_back(pTemp->GetObjectGuid()); + m_uiScrapbotCount += 1; + } } - - break; + m_uiScrapbotTimer = 3000; } - default: - SwitchIntoPhaseOne(); - break; + else m_uiScrapbotTimer -= uiDiff; } + + if (!m_bPhase2) + DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_xt_002(Creature* pCreature) +CreatureAI* GetAI_boss_xt002(Creature* pCreature) { - return new boss_xt_002AI(pCreature); + return new boss_xt002AI(pCreature); } void AddSC_boss_xt002() @@ -707,8 +775,8 @@ void AddSC_boss_xt002() Script* NewScript; NewScript = new Script; - NewScript->Name = "boss_xt_002"; - NewScript->GetAI = GetAI_boss_xt_002; + NewScript->Name = "boss_xt002"; + NewScript->GetAI = GetAI_boss_xt002; NewScript->RegisterSelf(); NewScript = new Script; diff --git a/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp b/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp index b502de17ed..8875c1b577 100644 --- a/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp @@ -17,72 +17,70 @@ /* ScriptData SDName: boss_yogg_saron SD%Complete: -SDComment: TODO: Achievments: Drive Me Crazy, In His House He Waits Dreaming +SDComment: Implement sanity, some other spells need core support. If the topaggro target is teleported into a vision, the boss resets -> needs fixing! SDCategory: Ulduar EndScriptData */ #include "precompiled.h" #include "ulduar.h" -#include "Vehicle.h" enum { //yells - //sara - SAY_AGGRO = -1603360, - SAY_HELP1 = -1603361, - SAY_HELP2 = -1603362, - SAY_KILL1 = -1603363, - SAY_KILL2 = -1603364, - SAY_SPECIAL1 = -1603365, - SAY_SPECIAL2 = -1603366, - SAY_INTRO1 = -1603367, - SAY_INTRO2 = -1603368, - SAY_WIPE = -1603369, + //sara + SAY_INTRO1 = -1603307, + SAY_INTRO2 = -1603308, + SAY_AGGRO = -1603300, + SAY_HELP1 = -1603301, + SAY_HELP2 = -1603302, + SAY_SPECIAL1 = -1603305, + SAY_SPECIAL2 = -1603306, + SAY_KILL1 = -1603303, + SAY_KILL2 = -1603304, + SAY_WIPE = -1603309, //yogg - SAY_PHASE2 = -1603370, - SAY_VISION = -1603371, - SAY_PHASE3 = -1603372, - SAY_SLAY1 = -1603373, - SAY_SLAY2 = -1603374, - SAY_DEATH = -1603375, - SAY_INSANITY1 = -1603376, - SAY_INSANITY2 = -1603377, - EMOTE_PORTALS = -1603378, - EMOTE_SHATTER = -1603379, + SAY_PHASE2 = -1603321, + SAY_VISION = -1603322, + EMOTE_PORTALS = -1603372, + EMOTE_SHATTER = -1603373, + SAY_PHASE3 = -1603323, + SAY_SLAY1 = -1603324, + SAY_SLAY2 = -1603325, + SAY_DEATH = -1603326, + SAY_INSANITY1 = -1603327, + SAY_INSANITY2 = -1603328, //visions //stormwind - SAY_GARONA1 = -1603400, - SAY_GARONA2 = -1603401, - SAY_GARONA3 = -1603402, - SAY_YOGG_V1_1 = -1603403, - SAY_YOGG_V1_2 = -1603404, - SAY_ILANE = -1603405, - SAY_GARONA4 = -1603406, - SAY_YOGG_V1_3 = -1603407, + SAY_GARONA1 = -1603341, + SAY_GARONA2 = -1603342, + SAY_YOGG_V1_1 = -1603343, + SAY_YOGG_V1_2 = -1603344, + SAY_GARONA3 = -1603345, + SAY_GARONA4 = -1603346, + SAY_YOGG_V1_3 = -1603347, //dragons - SAY_NELTHARION1 = -1603390, - SAY_YSERA = -1603391, - SAY_NELTHARION2 = -1603392, - SAY_MALYGOS = -1603393, - SAY_YOGG_V2 = -1603394, + SAY_NELTHARION1 = -1603336, + SAY_YSERA = -1603337, + SAY_NELTHARION2 = -1603338, + SAY_MALYGOS = -1603339, + SAY_YOGG_V2 = -1603340, //lich king - SAY_LICH_KING1 = -1603380, - SAY_CHAMPION1 = -1603381, - SAY_CHAMPION2 = -1603382, - SAY_LICH_KING2 = -1603383, - SAY_YOGG_V3_1 = -1603384, - SAY_YOGG_V3_2 = -1603385, + SAY_LICH_KING1 = -1603330, + SAY_CHAMPION1 = -1603331, + SAY_CHAMPION2 = -1603332, + SAY_LICH_KING2 = -1603333, + SAY_YOGG_V3_1 = -1603334, + SAY_YOGG_V3_2 = -1603335, //keepers yells - SAY_HODIR_ACTIVE = -1603126, - SAY_FREYA_ACTIVE = -1603149, - SAY_THORIM_ACTIVE = -1603207, - SAY_MIMIRON_ACTIVE = -1603239, + SAY_HODIR_ACTIVE = -1603086, + SAY_FREYA_ACTIVE = -1603009, + SAY_THORIM_ACTIVE = -1603238, + SAY_MIMIRON_ACTIVE = -1603260, //vision npc //stormwind @@ -111,6 +109,7 @@ enum NPC_VOICE_OF_YOGG_SARON = 33280, MOB_VISION_TENTACLE = 33943, + MOB_VISION_TENTACLE_H = 33959, SPELL_GRIM_REPRISAL = 63305, // npc hp: 15k on 10 man; 40k on 25 man // npc no: 10 @@ -129,8 +128,9 @@ enum // clouds SPELL_OMINOUS_CLOUD_VISUAL = 63084, - SPELL_SUMMON_GUARDIAN = 62978, // cast von yogg saron ,with spell Script target at cloud - SPELL_SUMMON_GUARDIAN2 = 63031, // cloud spell (target Self) + SPELL_SUMMON_GUARDIAN = 62978, + SPELL_SUMMON_GUARDIAN2 = 63031, + NPC_OMINOUS_CLOUD = 33292, //phase2 SPELL_SHADOWY_BARRIER = 64775, @@ -138,12 +138,13 @@ enum SPELL_SANITY = 63050, SPELL_PHYCHOSIS = 65301, SPELL_PHYCHOSIS_H = 63795, - SPELL_MALADY_OF_THE_MIND = 63830, // in core fix - SPELL_BRAIN_LINK = 63802, // in core fix, BUT visual mistake - SPELL_DEATH_RAY_SUMMON = 63891, //summons orb + SPELL_MALADY_OF_THE_MIND = 63830, + SPELL_BRAIN_LINK = 63802, + SPELL_BRAIN_LINK_DMG = 63803, + SPELL_BRAIN_LINK_NON_DMG = 63804, + SPELL_DEATH_RAY = 63891, //summons orb SPELL_DEATH_RAY_TRIGG = 63883, - SPELL_DEATH_RAY_VISUAL_W = 63882, - SPELL_DEATH_RAY_VISUAL_D = 63886, + SPELL_DEATH_RAY_VISUAL = 63886, SPELL_DEATH_RAY_VISUAL_ORI = 63893, MOB_DEATH_ORB = 33882, @@ -161,20 +162,13 @@ enum // portals MOB_DESCEND_INTO_MADNESS = 34072, - SPELL_LUNATIC_GAZE = 64167, //target fix for targets in core + SPELL_LUNATIC_GAZE = 64167, //affects players which take the portal to madness NPC_LAUGHING_SKULL = 33990, SKULL_DISPLAY_ID = 25206, - // teleports - SPELL_TELEPORT_TO_STORMWIND_ILLUSION= 63989, // Stormwind - SPELL_TELEPORT_TO_CHAMBER_ILLUSION = 63997, // Wyrmruh - SPELL_TELEPORT_TO_ICEECROWN_ILLUSION= 63998, // Lich King - SPELL_TELEPORT_BACK_TO_MAIN_ROOM = 63992, // To Yogg Saron - // brain's chamber MOB_BRAIN_OF_YOGG_SARON = 33890, SPELL_SHATTERED_ILLUSION = 64173, - SPELL_SHATTERED_ILLUSION2 = 65238, SPELL_INDUCE_MADNESS = 64059, SPELL_ILLUSION_ROOM = 63988, // reduce speed SPELL_ILLUSION_CANCEL = 63993, @@ -182,40 +176,36 @@ enum // tentacules MOB_CRUSHER_TENTACLE = 33966, - SPELL_ERUPT = 64144, //also used by the corruptor and constrictor tentacle + MOB_CRUSHER_TENTACLE_H = 33967, + SPELL_ERUPT = 64144, //also used by the corruptor tentacle SPELL_DIMINISH_POWER = 64145, SPELL_FOCUSED_ANGER = 57689, SPELL_FOCUSED_ANGER_TRIGG = 57688, - SPELL_CRUSH = 64147, SPELL_SUMMON_CRUSHER = 64139, MOB_CONSTRICTOR_TENTACLE = 33983, - SPELL_SQUEEZE_GRAB = 64123, + MOB_CONSTRICTOR_TENTACLE_H = 33984, SPELL_SQUEEZE = 64125, SPELL_SQUEEZE_H = 64126, SPELL_SUMMON_CONSTRICTOR = 64133, MOB_CORRUPTOR_TENTACLE = 33985, + MOB_CORRUPTOR_TENTACLE_H = 33986, SPELL_APATHY = 64156, SPELL_BLACK_PLAGUE = 64153, SPELL_CURSE_OF_DOOM = 64157, SPELL_DRAINING_POISON = 64152, - SPELL_SUMMON_CORRUPTOR = 64143, // phase 3 - SPELL_LUNATIC_GAZE_YOGG = 64163, // target fix in core - SPELL_SHADOW_BEACON = 64465, // with script target a chain of spells - //SPELL_EMPOWERING_SHADOWS = 64468, // in core fix - //SPELL_EMPOWERING_SHADOWS_H = 64486, // in core fix + SPELL_LUNATIC_GAZE_YOGG = 64163, + SPELL_SHADOW_BEACON = 64465, + SPELL_EMPOWERING_SHADOWS = 64468, + SPELL_EMPOWERING_SHADOWS_H = 64486, SPELL_DEAFENING_ROAR = 64189, //only cast on 25 player with 0-3 keepes active MOB_IMMORTAL_GUARDIAN = 33988, - //SPELL_EMPOWERED = 65294, //starts with 9 stacks and loses 1 stak at 10% hp; fix in core - SPELL_EMPOWERED_AURA = 64161, // standard aura, dummy tick for stackhandling of spell 65294 - SPELL_RECENTLY_SPAWNED = 64497, // for spell 64465, that this unit is no target - SPELL_DRAIN_LIFE = 64159, - SPELL_DRAIN_LIFE_H = 64160, - //SPELL_WEAKENED = 64162, // mob ready for thorim kill; fix in core + SPELL_EMPOWERED = 65294, //starts with 9 stacks and loses 1 stak at 10% hp + SPELL_EMPOWERED_AURA = 64161, SPELL_BERSERK = 64166, //extinguish all life @@ -231,18 +221,16 @@ enum SPELL_FORTITUDE_OF_FROST = 62650, SPELL_HODIRS_PROTECTIVE_GAZE= 64174, // saves players from killing blows ~25secs cd - // mimiron + // thorim SPELL_SPEED_OF_INVENTION = 62671, SPELL_DESTABILIZATION_MATRIX= 65210, // cast in phase 2 on the tentacules - // thorim + // mimiron SPELL_FURY_OF_THE_STORM = 62702, SPELL_TITANIC_STORM = 64171, // used in phase 3 to kill guardians SPELL_TITANIC_STORM_DMG = 64172, }; -#define LAYERCUT 290.0f - enum phases { // yogg phases @@ -257,6 +245,20 @@ enum phases PHASE_VISION_RETURN = 4, // used to set the portals to return to main chamber = idle }; +enum achievs +{ + ACHIEV_ALONE = 3159, + ACHIEV_ALONE_H = 3164, + ACHIEV_ONE_LIGHT = 3158, + ACHIEV_ONE_LIGHT_H = 3163, + ACHIEV_TWO_LIGHTS = 3141, + ACHIEV_TWO_LIGHTS_H = 3162, + ACHIEV_THREE_LIGHTS = 3157, + ACHIEV_THREE_LIGHTS_H = 3161, + ACHIEV_NOT_GETTING_OLDER = 3012, + ACHIEV_NOT_GETTING_OLDER_H = 3013, +}; + //Positional defines struct LocationsXY { @@ -408,7 +410,7 @@ static VisionLocXY SkullIcecrownLoc[]= {1940.515625f, -152.933945f, 239.989868f}, {1889.130371f, -122.932549f, 239.98986f}, {1908.828003f, -88.593613f, 239.98986f}, -}; +}; // location of the minds eye: // X: 1981.422974 Y: -22.442831 Z: 236.104813 @@ -423,53 +425,43 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI { boss_yogg_saronAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiBerserkTimer; uint32 m_uiSanityTimer; uint32 m_uiKeepersActive; - uint32 m_uiSummonGuardianTimer; - uint32 m_uiSummonGuardianCounter; - uint32 m_uiLunaticGazaTimer; uint32 m_uiShadowBeaconTimer; uint32 m_uiEmpoweringShadowsTimer; uint32 m_uiSummonTimer; - uint32 m_uiSummonCrusherTentacleTimer; // ~ 40 sek - uint32 m_uiSummonCorruptorTentacleTimer; // ~ 30 sek - uint32 m_uiSummonConstrictorTentacleTimer; // ~ 10 sek uint32 m_uiDeafeningRoarTimer; + bool m_bIsShatter; + + uint32 m_uiAchievTimer; - GUIDList m_lKeeperGUID; + std::list lClouds; void Reset() { - DoCast(m_creature, SPELL_CLEAR_INSANE, true); - m_uiSanityTimer = 10000; m_uiKeepersActive = 0; - - // phase 1 - m_uiSummonGuardianTimer = 10000; - m_uiSummonGuardianCounter = 0; + // phase 3 m_uiLunaticGazaTimer = 20000; m_uiShadowBeaconTimer = 15000; m_uiEmpoweringShadowsTimer = 60000; m_uiSummonTimer = 40000; - m_uiSummonCrusherTentacleTimer = urand(35000, 45000); - m_uiSummonCorruptorTentacleTimer = urand(25000, 35000); - m_uiSummonConstrictorTentacleTimer = urand(7000, 13000); - m_uiDeafeningRoarTimer = 30000; + m_uiAchievTimer = 0; + m_bIsShatter = false; m_uiBerserkTimer = 900000; // 15 min m_creature->SetVisibility(VISIBILITY_OFF); @@ -483,24 +475,25 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI { m_pInstance->SetData(TYPE_YOGG_PHASE, PHASE_IDLE); m_pInstance->SetData(TYPE_VISION_PHASE, PHASE_VISION_RETURN); - m_pInstance->SetData(TYPE_YOGGSARON, FAIL); } - for (GUIDList::iterator iter = m_lKeeperGUID.begin(); iter != m_lKeeperGUID.end(); ++iter) + + // respawn clouds + GetCreatureListWithEntryInGrid(lClouds, m_creature, NPC_OMINOUS_CLOUD, DEFAULT_VISIBILITY_INSTANCE); + if (!lClouds.empty()) { - if (Creature* pTemp = m_creature->GetMap()->GetCreature(*iter)) + for(std::list::iterator iter = lClouds.begin(); iter != lClouds.end(); ++iter) { - pTemp->ForcedDespawn(); + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); } } - m_lKeeperGUID.clear(); } void Aggro(Unit *who) { m_creature->SetInCombatWithZone(); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(m_creature, SPELL_SANITY_TRIGG, true); - DoCast(m_creature, SPELL_INSANE_TRIGG, true); + StartSanity(); if(m_pInstance) { @@ -509,53 +502,26 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI // summon thorim if(m_pInstance->GetData(TYPE_KEEPER_THORIM) == DONE) { - if (Creature* pThorim = m_creature->SummonCreature(KEEPER_THORIM, KeepersLoc[0].x, KeepersLoc[0].y, KeepersLoc[0].z, KeepersLoc[0].o, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - DoScriptText(SAY_THORIM_ACTIVE, pThorim); - m_lKeeperGUID.push_back(pThorim->GetObjectGuid()); - m_uiKeepersActive += 1; - } + m_creature->SummonCreature(KEEPER_THORIM, KeepersLoc[0].x, KeepersLoc[0].y, KeepersLoc[0].z, KeepersLoc[0].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; } // summon hodir if(m_pInstance->GetData(TYPE_KEEPER_HODIR) == DONE) { - if (Creature* pHodir = m_creature->SummonCreature(KEEPER_HODIR, KeepersLoc[1].x, KeepersLoc[1].y, KeepersLoc[1].z, KeepersLoc[1].o, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - DoScriptText(SAY_HODIR_ACTIVE, pHodir); - m_lKeeperGUID.push_back(pHodir->GetObjectGuid()); - m_uiKeepersActive += 1; - } + m_creature->SummonCreature(KEEPER_HODIR, KeepersLoc[1].x, KeepersLoc[1].y, KeepersLoc[1].z, KeepersLoc[1].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; } // summon freya if(m_pInstance->GetData(TYPE_KEEPER_FREYA) == DONE) { - if (Creature* pFreya = m_creature->SummonCreature(KEEPER_FREYA, KeepersLoc[2].x, KeepersLoc[2].y, KeepersLoc[2].z, KeepersLoc[2].o, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - DoScriptText(SAY_FREYA_ACTIVE, pFreya); - m_lKeeperGUID.push_back(pFreya->GetObjectGuid()); - m_uiKeepersActive += 1; - } + m_creature->SummonCreature(KEEPER_FREYA, KeepersLoc[2].x, KeepersLoc[2].y, KeepersLoc[2].z, KeepersLoc[2].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; } // summon mimiron if(m_pInstance->GetData(TYPE_KEEPER_MIMIRON) == DONE) { - if (Creature* pMimiron = m_creature->SummonCreature(KEEPER_MIMIRON, KeepersLoc[3].x, KeepersLoc[3].y, KeepersLoc[3].z, KeepersLoc[3].o, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - DoScriptText(SAY_MIMIRON_ACTIVE, pMimiron); - m_lKeeperGUID.push_back(pMimiron->GetObjectGuid()); - m_uiKeepersActive += 1; - } - } - switch (m_uiKeepersActive) - { - case 0: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_ALONE, true); - case 1: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_ONE_LIGHT, true); - case 2: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_TWO_LIGHTS, true); - case 3: - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_THREE_LIGHTS, true); + m_creature->SummonCreature(KEEPER_MIMIRON, KeepersLoc[3].x, KeepersLoc[3].y, KeepersLoc[3].z, KeepersLoc[3].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; } if(Creature* pSara = m_pInstance->GetSingleCreatureFromStorage(NPC_SARA)) @@ -566,41 +532,69 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI void JustReachedHome() { if (m_pInstance) - m_pInstance->SetData(TYPE_YOGGSARON, FAIL); + { + m_pInstance->SetData(TYPE_YOGGSARON, NOT_STARTED); + + if(Creature* pSara = m_pInstance->GetSingleCreatureFromStorage(NPC_SARA)) + { + if(!pSara->isAlive()) + pSara->Respawn(); + else + pSara->AI()->EnterEvadeMode(); + } + + if (Creature* pYoggBrain = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGG_BRAIN)) + { + if(!pYoggBrain->isAlive()) + pYoggBrain->Respawn(); + else + pYoggBrain->AI()->EnterEvadeMode(); + } + } } void KilledUnit(Unit* pVictim) { - DoScriptText(urand(0,1) ? SAY_SLAY1 : SAY_SLAY2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); } void JustDied(Unit *killer) { - DoCast(m_creature, SPELL_CLEAR_INSANE, true); DoScriptText(SAY_DEATH, m_creature); if(m_pInstance) { m_pInstance->SetData(TYPE_YOGGSARON, DONE); - m_pInstance->SetData(TYPE_YOGGSARON_HARD, FAIL); - m_pInstance->SetData(TYPE_YOGGSARON_HARD_4, FAIL); + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 0); + // hacky way to complete achievements; use only if you have this function if(m_uiKeepersActive == 0) { - m_pInstance->SetData(TYPE_YOGGSARON_HARD_4, DONE); - m_pInstance->SetData(TYPE_YOGGSARON_HARD, DONE); + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 4); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_ALONE : ACHIEV_ALONE_H); } else if (m_uiKeepersActive == 1) { - m_pInstance->SetData(TYPE_YOGGSARON_HARD, DONE); + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 3); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_ONE_LIGHT : ACHIEV_ONE_LIGHT_H); } else if (m_uiKeepersActive == 2) { - m_pInstance->SetData(TYPE_YOGGSARON_HARD, FAIL); + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 2); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_TWO_LIGHTS : ACHIEV_TWO_LIGHTS_H); } else if (m_uiKeepersActive == 3) { - m_pInstance->SetData(TYPE_YOGGSARON_HARD, FAIL); + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 1); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_THREE_LIGHTS : ACHIEV_THREE_LIGHTS_H); } + + // under 7 min + if(m_uiAchievTimer < 420000) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_NOT_GETTING_OLDER : ACHIEV_NOT_GETTING_OLDER_H); + } if(Creature* pSara = m_pInstance->GetSingleCreatureFromStorage(NPC_SARA)) @@ -620,14 +614,17 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI { m_creature->SetVisibility(VISIBILITY_ON); DoCast(m_creature, SPELL_SHADOWY_BARRIER_YOGG); + //StartSanity(); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (m_pInstance) + GetCreatureListWithEntryInGrid(lClouds, m_creature, NPC_OMINOUS_CLOUD, DEFAULT_VISIBILITY_INSTANCE); + if (!lClouds.empty()) { - //remove Clouds - for(GUIDList::iterator iter = m_pInstance->m_lCLoudGuids.begin(); iter != m_pInstance->m_lCLoudGuids.end(); ++iter) - if (Creature *pTmp = m_pInstance->instance->GetCreature(*iter)) - pTmp->ForcedDespawn(); + for(std::list::iterator iter = lClouds.begin(); iter != lClouds.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } } m_uiSummonTimer = urand(3000, 7000); @@ -648,90 +645,157 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI pYoggBrain->DealDamage(pYoggBrain, pYoggBrain->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } - void SummonTentacle(uint32 pEntry) + // hacky way of doing sanity before the recent aura changes + void StartSanity() + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + m_creature->CastSpell(i->getSource(), SPELL_SANITY, true); + i->getSource()->GetSpellAuraHolder(SPELL_SANITY)->SetStackAmount(100); + } + } + } + } + + void DoCastSanity() + { + uint8 m_uiStacks; + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + // reduce sanity + if(i->getSource()->HasAura(SPELL_SANITY, EFFECT_INDEX_0)) + { + if(Aura *aura = i->getSource()->GetAura(SPELL_SANITY, EFFECT_INDEX_0)) + { + m_uiStacks = aura->GetStackAmount(); + if(m_uiStacks == 100) + DoCast(i->getSource(), SPELL_INSANE); + /*if(m_uiStacks > 1) + i->getSource()->GetAura(SPELL_SANITY, EFFECT_INDEX_0)->SetStackAmount(stack - 1); + else + { + i->getSource()->RemoveAurasDueToSpell(SPELL_SANITY); + DoCast(i->getSource(), SPELL_INSANE); + }*/ + } + } + } + } + } + } + + Creature* SelectRandomGuardian(float fRange) + { + std::list lGuardiansList; + GetCreatureListWithEntryInGrid(lGuardiansList, m_creature, MOB_IMMORTAL_GUARDIAN, fRange); + + //This should not appear! + if (lGuardiansList.empty()){ + m_uiEmpoweringShadowsTimer = 30000; + return NULL; + } + + std::list::iterator iter = lGuardiansList.begin(); + advance(iter, urand(0, lGuardiansList.size()-1)); + + return *iter; + } + + void SummonTentacles() { + float homeZ = 0; float creatureDist = 0; - creatureDist = urand(20, 45); + // set tentacle entry + uint32 m_uiTentacles[] = {m_bIsRegularMode ? MOB_CONSTRICTOR_TENTACLE : MOB_CONSTRICTOR_TENTACLE_H, m_bIsRegularMode ? MOB_CORRUPTOR_TENTACLE : MOB_CORRUPTOR_TENTACLE_H, m_bIsRegularMode ? MOB_CRUSHER_TENTACLE : MOB_CRUSHER_TENTACLE_H}; + uint32 m_uiEntry = urand(0, 2); + if(Creature* pTemp = GetClosestCreatureWithEntry(m_creature, m_uiTentacles[2], 100.0f)) + { + if(pTemp->isAlive()) + m_uiEntry = urand(0, 1); + } + uint32 m_uiTentacleEntry = m_uiTentacles[m_uiEntry]; + + // set distance + // Z factor needs some fixing, in some cases it should be smaller + switch(urand(0, 1)) + { + case 0: + creatureDist = urand(20, 30); + homeZ = 326 + creatureDist * 0.05f; + break; + case 1: + creatureDist = urand(30, 45); + homeZ = 328 + creatureDist * 0.05f; + break; + } // set coordonates float angle = (float) rand()*360/RAND_MAX + 1; float homeX = m_creature->GetPositionX() + creatureDist*cos(angle*(M_PI/180)); float homeY = m_creature->GetPositionY() + creatureDist*sin(angle*(M_PI/180)); - float homeZ = m_creature->GetTerrain()->GetWaterOrGroundLevel(homeX, homeY, m_creature->GetPositionZ()); // summon tentacle - if(Creature *pTemp = m_creature->SummonCreature(pEntry, homeX, homeY, homeZ, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + if(Creature *pTemp = m_creature->SummonCreature(m_uiTentacleEntry, homeX, homeY, homeZ, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) pTemp->SetInCombatWithZone(); } void UpdateAI(const uint32 uiDiff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if (!m_creature->SelectHostileTarget() || (m_creature->getVictim() && !m_creature->getVictim()->IsControlledByPlayer())) return; + // achiev timer + m_uiAchievTimer += uiDiff; + switch(m_pInstance->GetData(TYPE_YOGG_PHASE)) { - case PHASE_SARA: + case PHASE_SARA: // Friendly Sara phase: see script below + break; + case PHASE_TENTACLES: { - if (m_uiSummonGuardianTimer < uiDiff) + if (m_uiSanityTimer < uiDiff) { - DoCast(m_creature, SPELL_SUMMON_GUARDIAN); // with Script Target to Cloud - m_uiSummonGuardianTimer = 25000 - (700 * m_uiSummonGuardianCounter++); - if (m_uiSummonGuardianTimer < 3000) - m_uiSummonGuardianTimer = 3000; + //DoCastSanity(); + //DoCast(m_creature, SPELL_SANITY); + m_uiSanityTimer = 20000; } - else - m_uiSummonGuardianTimer -= uiDiff; - - break; - } - case PHASE_TENTACLES: - { - // Yogg Saron is Stun, no timer change and no summon - if (m_creature->HasAura(64173)) - return; + else m_uiSanityTimer -= uiDiff; // summon tentacles - if (m_uiSummonConstrictorTentacleTimer < uiDiff) + if (m_uiSummonTimer < uiDiff && !m_bIsShatter) { - if (m_pInstance) - { - if (Player* pPlayer = m_pInstance->GetPlayerInMap(true, false)) - { - if (pPlayer->GetPositionZ() > LAYERCUT) - { - pPlayer->CastSpell(pPlayer, SPELL_SUMMON_CONSTRICTOR, true, 0, 0, m_creature->GetObjectGuid()); - m_uiSummonConstrictorTentacleTimer = urand(13000, 20000); - } - } - } - } - else m_uiSummonConstrictorTentacleTimer -= uiDiff; - - if (m_uiSummonCorruptorTentacleTimer < uiDiff) - { - SummonTentacle(MOB_CORRUPTOR_TENTACLE); - //DoCast(m_creature, SPELL_SUMMON_CORRUPTOR, true); - m_uiSummonCorruptorTentacleTimer = urand(20000, 35000); + SummonTentacles(); + m_uiSummonTimer = urand(10000, 15000); } - else m_uiSummonCorruptorTentacleTimer -= uiDiff; - - if (m_uiSummonCrusherTentacleTimer < uiDiff) - { - SummonTentacle(MOB_CRUSHER_TENTACLE); - //DoCast(m_creature, SPELL_SUMMON_CRUSHER, true); - m_uiSummonCrusherTentacleTimer = urand(350000, 45000); - } - else m_uiSummonCrusherTentacleTimer -= uiDiff; + else m_uiSummonTimer -= uiDiff; break; } - case PHASE_OLD_GOD: + case PHASE_OLD_GOD: { if (m_uiSummonTimer < uiDiff) { - // spell 64158 radius to high - if(Creature *pTemp = m_creature->SummonCreature(MOB_IMMORTAL_GUARDIAN, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + if(Creature *pTemp = m_creature->SummonCreature(MOB_IMMORTAL_GUARDIAN, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) pTemp->SetInCombatWithZone(); m_uiSummonTimer = 30000; } @@ -739,25 +803,28 @@ struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI if (m_uiLunaticGazaTimer < uiDiff) { - DoCast(m_creature, SPELL_LUNATIC_GAZE_YOGG, true); + DoCast(m_creature, SPELL_LUNATIC_GAZE_YOGG); m_uiLunaticGazaTimer = urand(10000, 13000); } else m_uiLunaticGazaTimer -= uiDiff; if (m_uiEmpoweringShadowsTimer < uiDiff) { - DoCast(m_creature, SPELL_SHADOW_BEACON, true); // with script target to guardian + if (Creature* pGuardian = SelectRandomGuardian(80.0f)) + DoCast(pGuardian, SPELL_SHADOW_BEACON); m_uiEmpoweringShadowsTimer = 45000; } else m_uiEmpoweringShadowsTimer -= uiDiff; if (m_uiDeafeningRoarTimer < uiDiff && !m_bIsRegularMode && m_uiKeepersActive < 4) { - DoCast(m_creature, SPELL_DEAFENING_ROAR, true); + DoCast(m_creature, SPELL_DEAFENING_ROAR); m_uiDeafeningRoarTimer = 30000; } else m_uiDeafeningRoarTimer -= uiDiff; + DoMeleeAttackIfReady(); + break; } } @@ -776,13 +843,13 @@ struct MANGOS_DLL_DECL mob_madness_portalAI : public ScriptedAI { mob_madness_portalAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint8 m_uiDestination; @@ -794,21 +861,19 @@ struct MANGOS_DLL_DECL mob_madness_portalAI : public ScriptedAI m_uiCheckTimer = 500; m_bHasTeleported = false; m_creature->SetRespawnDelay(DAY); + if(m_pInstance) + m_uiDestination = m_pInstance->GetData(TYPE_VISION_PHASE) - 1; } void UpdateAI(const uint32 uiDiff) { - if(m_creature->GetPositionZ() < LAYERCUT) - m_uiDestination = PHASE_VISION_RETURN; + if(m_creature->GetPositionZ() < 245.0f) + m_uiDestination = 3; + // hacky way. This should be done by a spell // this uses the Type_vision_phase in order to set vision destination if(m_uiCheckTimer < uiDiff && !m_bHasTeleported) { - if (m_bHasTeleported) - { - m_creature->ForcedDespawn(); - return; - } Map *map = m_creature->GetMap(); if (map->IsDungeon()) { @@ -819,37 +884,17 @@ struct MANGOS_DLL_DECL mob_madness_portalAI : public ScriptedAI for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()) < 2) + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()->GetPositionX(), i->getSource()->GetPositionY()) < 2) { - if (i->getSource()->HasAura(63988) || m_creature->GetPositionZ() < LAYERCUT) // with Buff Illusion Room always teleport back or if the portal in brain chamber + i->getSource()->TeleportTo(i->getSource()->GetMapId(), TeleportLoc[m_uiDestination].x, TeleportLoc[m_uiDestination].y, TeleportLoc[m_uiDestination].z, i->getSource()->GetOrientation()); + if(m_uiDestination < 3) { - i->getSource()->CastSpell(i->getSource(), SPELL_TELEPORT_BACK_TO_MAIN_ROOM, true); - i->getSource()->RemoveAurasDueToSpell(63988); // remove Illusion Room buff + i->getSource()->CastSpell(i->getSource(), SPELL_ILLUSION_ROOM, false); + i->getSource()->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + m_creature->ForcedDespawn(); } else - { - switch(m_pInstance->GetData(TYPE_VISION_PHASE)) - { - case PHASE_VISION_STORMWIND: - i->getSource()->CastSpell(i->getSource(), SPELL_TELEPORT_TO_STORMWIND_ILLUSION, true); - m_bHasTeleported = true; - break; - case PHASE_VISION_WYRMREST: - i->getSource()->CastSpell(i->getSource(), SPELL_TELEPORT_TO_CHAMBER_ILLUSION, true); - m_bHasTeleported = true; - break; - case PHASE_VISION_ICECROWN: - i->getSource()->CastSpell(i->getSource(), SPELL_TELEPORT_TO_ICEECROWN_ILLUSION, true); - m_bHasTeleported = true; - break; - case PHASE_VISION_RETURN: // for save - default: - i->getSource()->CastSpell(i->getSource(), SPELL_TELEPORT_BACK_TO_MAIN_ROOM, true); - i->getSource()->RemoveAurasDueToSpell(63988); // remove Illusion Room buff - break; - } - } - i->getSource()->RemoveAurasDueToSpell(63802); // remove Brain Link + i->getSource()->RemoveAurasDueToSpell(SPELL_ILLUSION_ROOM); } } } @@ -862,13 +907,13 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI { boss_brain_of_yogg_saronAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiVisionPhase; @@ -889,8 +934,6 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI ObjectGuid m_uiYseraGUID; ObjectGuid m_uiVoiceOfYoggGUID; - GUIDList m_lVisionTentacle; - void Reset() { m_bIsPhaseFinished = false; @@ -913,16 +956,13 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI if(m_pInstance) m_pInstance->SetData(TYPE_YOGG_BRAIN, NOT_STARTED); - if (m_pInstance) - { - // close doors on reset - if(GameObject* pVisionDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_BRAIN_DOOR1)) - pVisionDoor->SetGoState(GO_STATE_READY); - if(GameObject* pVisionDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_BRAIN_DOOR2)) - pVisionDoor->SetGoState(GO_STATE_READY); - if(GameObject* pVisionDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_BRAIN_DOOR3)) - pVisionDoor->SetGoState(GO_STATE_READY); - } + // close doors on reset + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR1, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR2, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR3, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); } // for debug @@ -940,7 +980,12 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI { if(uiDamage > 0 && !m_bHasShattered) { - DoCast(m_creature, SPELL_SHATTERED_ILLUSION, true); // script Target auf Yogg Saron und Tentakeln + if (Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) + { + ((boss_yogg_saronAI*)pYogg->AI())->m_bIsShatter = true; + // spell bugged, need core fix. It should be cast on tentacles, not on players! + //pYogg->CastSpell(pYogg, SPELL_SHATTERED_ILLUSION, true); + } m_bHasShattered = true; } } @@ -961,28 +1006,20 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI m_uiMadnessTimer = 60000; m_bIsVisionFinished = false; m_bHasShattered = false; - for(GUIDList::iterator itr = m_lVisionTentacle.begin(); itr != m_lVisionTentacle.end(); itr++) - { - if (Creature* pVisionTentacle = m_creature->GetMap()->GetCreature(*itr)) - { - pVisionTentacle->ForcedDespawn(); - } - } - m_lVisionTentacle.clear(); - + // close doors on new vision + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR1, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR2, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR3, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); } // check if all the tentacles are dead bool IsThereAnyAdd(WorldObject *pSource) { - for(GUIDList::iterator itr = m_lVisionTentacle.begin(); itr != m_lVisionTentacle.end(); itr++) - { - if (Creature* pVisionTentacle = m_creature->GetMap()->GetCreature(*itr)) - { - if (pVisionTentacle->isAlive()) - return true; - } - } + if(GetClosestCreatureWithEntry(pSource, m_bIsRegularMode ? MOB_VISION_TENTACLE : MOB_VISION_TENTACLE_H, 80.0f)) + return true; if(m_pInstance) { @@ -990,18 +1027,19 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI switch(m_pInstance->GetData(TYPE_VISION_PHASE)) { case PHASE_VISION_STORMWIND: - if(GameObject* pVisionDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_BRAIN_DOOR3)) + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR3, 100.0f)) pVisionDoor->SetGoState(GO_STATE_ACTIVE); break; case PHASE_VISION_WYRMREST: - if(GameObject* pVisionDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_BRAIN_DOOR1)) + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR1, 100.0f)) pVisionDoor->SetGoState(GO_STATE_ACTIVE); break; case PHASE_VISION_ICECROWN: - if(GameObject* pVisionDoor = m_pInstance->GetSingleGameObjectFromStorage(GO_BRAIN_DOOR2)) + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR2, 100.0f)) pVisionDoor->SetGoState(GO_STATE_ACTIVE); break; } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } return false; } @@ -1010,7 +1048,7 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI { switch(m_pInstance->GetData(TYPE_VISION_PHASE)) { - case PHASE_VISION_STORMWIND: + case PHASE_VISION_STORMWIND: { if(m_uiSpeechTimer < uiDiff) { @@ -1028,17 +1066,15 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI } for(uint8 i = 0; i < 8; i++) { - if(Creature *pTemp = m_creature->SummonCreature(MOB_VISION_TENTACLE, KeepLoc[i].x, KeepLoc[i].y, KeepLoc[i].z, KeepLoc[i].o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 80000)) + if(Creature *pTemp = m_creature->SummonCreature(m_bIsRegularMode ? MOB_VISION_TENTACLE : MOB_VISION_TENTACLE_H, KeepLoc[i].x, KeepLoc[i].y, KeepLoc[i].z, KeepLoc[i].o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 80000)) { - m_lVisionTentacle.push_back(pTemp->GetObjectGuid()); pTemp->SetDisplayId(28621); - pTemp->SetMaxHealth(m_bIsRegularMode ? 15000 : 40000); pTemp->setFaction(7); pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); } } for(uint8 i = 0; i < 3; i++) - m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullKeepLoc[i].x, SkullKeepLoc[i].y, SkullKeepLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 80000); + m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullKeepLoc[i].x, SkullKeepLoc[i].y, SkullKeepLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); ++m_uiVisionPhase; m_uiSpeechTimer = 1000; break; @@ -1074,13 +1110,7 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI break; case 6: if(Creature* Garona = m_pInstance->instance->GetCreature(m_uiGaronaGUID)) - { Garona->GetMotionMaster()->MovePoint(0, 1931.348f, 61.033f, 241.709f); - } - if(Creature* KingLlane = m_pInstance->instance->GetCreature(m_uiKingLlaneGUID)) - { - DoScriptText(SAY_ILANE, KingLlane); - } ++m_uiVisionPhase; m_uiSpeechTimer = 6000; break; @@ -1114,155 +1144,151 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI break; } - case PHASE_VISION_WYRMREST: + case PHASE_VISION_WYRMREST: { if(m_uiSpeechTimer < uiDiff) { switch(m_uiVisionPhase) { - case 0: - m_creature->SummonCreature(NPC_ALEXSTRASZA, PosAlexstrasza[0], PosAlexstrasza[1], PosAlexstrasza[2], PosAlexstrasza[3], TEMPSUMMON_TIMED_DESPAWN, 60000); - if(Creature* Neltharion = m_creature->SummonCreature(NPC_NELTHARION, PosNeltharion[0], PosNeltharion[1], PosNeltharion[2], PosNeltharion[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) - m_uiNeltharionGUID = Neltharion->GetObjectGuid(); - if(Creature* Malygos = m_creature->SummonCreature(NPC_MALYGOS, PosMalygos[0], PosMalygos[1], PosMalygos[2], PosMalygos[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) - m_uiMalygosGUID = Malygos->GetObjectGuid(); - if(Creature* Ysera = m_creature->SummonCreature(NPC_YSERA, PosYsera[0], PosYsera[1], PosYsera[2], PosYsera[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) - m_uiYseraGUID = Ysera->GetObjectGuid(); - if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceDragon[0], PosVoiceDragon[1], PosVoiceDragon[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) - { - m_uiVoiceOfYoggGUID = VoiceOfYogg->GetObjectGuid(); - VoiceOfYogg->SetVisibility(VISIBILITY_OFF); - } - for(uint8 i = 0; i < 10; i++) + case 0: + m_creature->SummonCreature(NPC_ALEXSTRASZA, PosAlexstrasza[0], PosAlexstrasza[1], PosAlexstrasza[2], PosAlexstrasza[3], TEMPSUMMON_TIMED_DESPAWN, 60000); + if(Creature* Neltharion = m_creature->SummonCreature(NPC_NELTHARION, PosNeltharion[0], PosNeltharion[1], PosNeltharion[2], PosNeltharion[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiNeltharionGUID = Neltharion->GetObjectGuid(); + if(Creature* Malygos = m_creature->SummonCreature(NPC_MALYGOS, PosMalygos[0], PosMalygos[1], PosMalygos[2], PosMalygos[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiMalygosGUID = Malygos->GetObjectGuid(); + if(Creature* Ysera = m_creature->SummonCreature(NPC_YSERA, PosYsera[0], PosYsera[1], PosYsera[2], PosYsera[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiYseraGUID = Ysera->GetObjectGuid(); + if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceDragon[0], PosVoiceDragon[1], PosVoiceDragon[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + m_uiVoiceOfYoggGUID = VoiceOfYogg->GetObjectGuid(); + VoiceOfYogg->SetVisibility(VISIBILITY_OFF); + } + for(uint8 i = 0; i < 10; i++) + { + if(Creature *pTemp = m_creature->SummonCreature(m_bIsRegularMode ? MOB_VISION_TENTACLE : MOB_VISION_TENTACLE_H, DragonLoc[i].x, DragonLoc[i].y, DragonLoc[i].z, DragonLoc[i].o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 80000)) { - if(Creature *pTemp = m_creature->SummonCreature(MOB_VISION_TENTACLE, DragonLoc[i].x, DragonLoc[i].y, DragonLoc[i].z, DragonLoc[i].o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 80000)) - { - m_lVisionTentacle.push_back(pTemp->GetObjectGuid()); - pTemp->SetDisplayId(DisplayDragons[i]); - pTemp->SetMaxHealth(m_bIsRegularMode ? 15000 : 40000); - pTemp->setFaction(7); - pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); - } + pTemp->SetDisplayId(DisplayDragons[i]); + pTemp->setFaction(7); + pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); } - for(uint8 i = 0; i < 3; i++) - m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullDragonLoc[i].x, SkullDragonLoc[i].y, SkullDragonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 80000); - ++m_uiVisionPhase; - m_uiSpeechTimer = 1000; - break; - case 1: - if(Creature* Neltharion = m_pInstance->instance->GetCreature(m_uiNeltharionGUID)) - DoScriptText(SAY_NELTHARION1, Neltharion); - ++m_uiVisionPhase; - m_uiSpeechTimer = 10000; - break; - case 2: - if(Creature* Ysera = m_pInstance->instance->GetCreature(m_uiYseraGUID)) - DoScriptText(SAY_YSERA, Ysera); - ++m_uiVisionPhase; - m_uiSpeechTimer = 7000; - break; - case 3: - if(Creature* Neltharion = m_pInstance->instance->GetCreature(m_uiNeltharionGUID)) - DoScriptText(SAY_NELTHARION2, Neltharion); - ++m_uiVisionPhase; - m_uiSpeechTimer = 6000; - break; - case 4: - if(Creature* Malygos = m_pInstance->instance->GetCreature(m_uiMalygosGUID)) - DoScriptText(SAY_MALYGOS, Malygos); - ++m_uiVisionPhase; - m_uiSpeechTimer = 9000; - break; - case 5: - if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) - DoScriptText(SAY_YOGG_V2, VoiceOfYogg); - ++m_uiVisionPhase; - m_uiSpeechTimer = 10000; - break; - default: - m_uiSpeechTimer = 100000; + } + for(uint8 i = 0; i < 3; i++) + m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullDragonLoc[i].x, SkullDragonLoc[i].y, SkullDragonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + ++m_uiVisionPhase; + m_uiSpeechTimer = 1000; + break; + case 1: + if(Creature* Neltharion = m_pInstance->instance->GetCreature(m_uiNeltharionGUID)) + DoScriptText(SAY_NELTHARION1, Neltharion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 10000; + break; + case 2: + if(Creature* Ysera = m_pInstance->instance->GetCreature(m_uiYseraGUID)) + DoScriptText(SAY_YSERA, Ysera); + ++m_uiVisionPhase; + m_uiSpeechTimer = 7000; + break; + case 3: + if(Creature* Neltharion = m_pInstance->instance->GetCreature(m_uiNeltharionGUID)) + DoScriptText(SAY_NELTHARION2, Neltharion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 6000; + break; + case 4: + if(Creature* Malygos = m_pInstance->instance->GetCreature(m_uiMalygosGUID)) + DoScriptText(SAY_MALYGOS, Malygos); + ++m_uiVisionPhase; + m_uiSpeechTimer = 9000; + break; + case 5: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V2, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 10000; + break; + default: + m_uiSpeechTimer = 100000; } }else m_uiSpeechTimer -= uiDiff; break; } - case PHASE_VISION_ICECROWN: + case PHASE_VISION_ICECROWN: { if(m_uiSpeechTimer < uiDiff) { switch(m_uiVisionPhase) { - case 0: - if(Creature* LichKing = m_creature->SummonCreature(NPC_LICH_KING, PosLichKing[0], PosLichKing[1], PosLichKing[2], PosLichKing[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) - m_uiLichKingGUID = LichKing->GetObjectGuid(); - if(Creature* Champion = m_creature->SummonCreature(NPC_IMMOLATED_CHAMPION, PosChampion[0], PosChampion[1], PosChampion[2], PosChampion[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) - m_uiChampionGUID = Champion->GetObjectGuid(); - if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceIcecrown[0], PosVoiceIcecrown[1], PosVoiceIcecrown[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) - { - m_uiVoiceOfYoggGUID = VoiceOfYogg->GetObjectGuid(); - VoiceOfYogg->SetVisibility(VISIBILITY_OFF); - } - for(uint8 i = 0; i < 9; i++) + case 0: + if(Creature* LichKing = m_creature->SummonCreature(NPC_LICH_KING, PosLichKing[0], PosLichKing[1], PosLichKing[2], PosLichKing[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiLichKingGUID = LichKing->GetObjectGuid(); + if(Creature* Champion = m_creature->SummonCreature(NPC_IMMOLATED_CHAMPION, PosChampion[0], PosChampion[1], PosChampion[2], PosChampion[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiChampionGUID = Champion->GetObjectGuid(); + if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceIcecrown[0], PosVoiceIcecrown[1], PosVoiceIcecrown[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + m_uiVoiceOfYoggGUID = VoiceOfYogg->GetObjectGuid(); + VoiceOfYogg->SetVisibility(VISIBILITY_OFF); + } + for(uint8 i = 0; i < 9; i++) + { + if(Creature *pTemp = m_creature->SummonCreature(m_bIsRegularMode ? MOB_VISION_TENTACLE : MOB_VISION_TENTACLE_H, IcecrownLoc[i].x, IcecrownLoc[i].y, IcecrownLoc[i].z, IcecrownLoc[i].o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 80000)) { - if(Creature *pTemp = m_creature->SummonCreature(MOB_VISION_TENTACLE, IcecrownLoc[i].x, IcecrownLoc[i].y, IcecrownLoc[i].z, IcecrownLoc[i].o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 80000)) - { - m_lVisionTentacle.push_back(pTemp->GetObjectGuid()); - pTemp->SetMaxHealth(m_bIsRegularMode ? 15000 : 40000); - pTemp->SetDisplayId(25627); - pTemp->setFaction(7); - pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); - } + pTemp->SetDisplayId(25627); + pTemp->setFaction(7); + pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); } - for(uint8 i = 0; i < 4; i++) - m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullIcecrownLoc[i].x, SkullIcecrownLoc[i].y, SkullIcecrownLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 80000); - ++m_uiVisionPhase; - m_uiSpeechTimer = 1000; - break; - case 1: - if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + } + for(uint8 i = 0; i < 4; i++) + m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullIcecrownLoc[i].x, SkullIcecrownLoc[i].y, SkullIcecrownLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + ++m_uiVisionPhase; + m_uiSpeechTimer = 1000; + break; + case 1: + if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + { + Champion->SetStandFlags(UNIT_STAND_STATE_KNEEL); + if(Creature* LichKing = m_pInstance->instance->GetCreature(m_uiLichKingGUID)) { - Champion->SetStandFlags(UNIT_STAND_STATE_KNEEL); - if(Creature* LichKing = m_pInstance->instance->GetCreature(m_uiLichKingGUID)) - { - LichKing->CastSpell(Champion, 54142, false); - DoScriptText(SAY_LICH_KING1, LichKing); - } + LichKing->CastSpell(Champion, 54142, false); + DoScriptText(SAY_LICH_KING1, LichKing); } - ++m_uiVisionPhase; - m_uiSpeechTimer = 5000; - break; - case 2: - if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) - DoScriptText(SAY_CHAMPION1, Champion); - ++m_uiVisionPhase; - m_uiSpeechTimer = 8000; - break; - case 3: - if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) - DoScriptText(SAY_CHAMPION2, Champion); - ++m_uiVisionPhase; - m_uiSpeechTimer = 8000; - break; - case 4: - if(Creature* LichKing = m_pInstance->instance->GetCreature(m_uiLichKingGUID)) - DoScriptText(SAY_LICH_KING2, LichKing); - ++m_uiVisionPhase; - m_uiSpeechTimer = 7000; - break; - case 5: - if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) - DoScriptText(SAY_YOGG_V3_1, VoiceOfYogg); - ++m_uiVisionPhase; - m_uiSpeechTimer = 5000; - break; - case 6: - if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) - DoScriptText(SAY_YOGG_V3_2, VoiceOfYogg); - ++m_uiVisionPhase; - m_uiSpeechTimer = 10000; - break; - default: - m_uiSpeechTimer = 100000; + } + ++m_uiVisionPhase; + m_uiSpeechTimer = 5000; + break; + case 2: + if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + DoScriptText(SAY_CHAMPION1, Champion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 8000; + break; + case 3: + if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + DoScriptText(SAY_CHAMPION2, Champion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 8000; + break; + case 4: + if(Creature* LichKing = m_pInstance->instance->GetCreature(m_uiLichKingGUID)) + DoScriptText(SAY_LICH_KING2, LichKing); + ++m_uiVisionPhase; + m_uiSpeechTimer = 7000; + break; + case 5: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V3_1, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 5000; + break; + case 6: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V3_2, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 10000; + break; + default: + m_uiSpeechTimer = 100000; } }else m_uiSpeechTimer -= uiDiff; @@ -1277,11 +1303,14 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI { m_pInstance->SetData(TYPE_YOGG_BRAIN, DONE); m_pInstance->SetData(TYPE_YOGG_PHASE, PHASE_OLD_GOD); - if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) - ((boss_yogg_saronAI*)pYogg->AI())->StartThirdPhase(); } m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(m_creature, SPELL_SHATTERED_ILLUSION2, true); + if (Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) + { + ((boss_yogg_saronAI*)pYogg->AI())->StartThirdPhase(); + pYogg->RemoveAurasDueToSpell(SPELL_SHATTERED_ILLUSION); + } + m_creature->CastStop(); m_bIsPhaseFinished = true; } @@ -1304,14 +1333,40 @@ struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI else m_uiTentacleCheckTimer -= uiDiff; // make boss unattackable -> exploit check + // Induced madness need core support, it should make the players insane if (m_uiMadnessTimer < uiDiff) { - DoCast(m_creature, SPELL_SHATTERED_ILLUSION2, true); + if (Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) + { + ((boss_yogg_saronAI*)pYogg->AI())->m_bIsShatter = false; + ((boss_yogg_saronAI*)pYogg->AI())->m_uiSummonTimer = urand(5000, 8000); + pYogg->RemoveAurasDueToSpell(SPELL_SHATTERED_ILLUSION); + } + + Map::PlayerList const &PlayerList = m_creature->GetMap()->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + Unit *pTemp = i->getSource(); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDist(pTemp, 60.0f)) //player above don't have to be hit + { + //workaround for remove sanity + if(SpellAuraHolderPtr sanityAura = pTemp->GetSpellAuraHolder(SPELL_SANITY)) + { + if(sanityAura->ModStackAmount(-100)) + { + pTemp->RemoveAurasDueToSpell(SPELL_SANITY); + m_creature->CastSpell(pTemp, SPELL_INSANE, false); + } + } + } + } m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_bIsVisionFinished = true; m_uiMadnessTimer = 300000; } - else m_uiMadnessTimer -= uiDiff; + else m_uiMadnessTimer -= uiDiff; } }; @@ -1320,31 +1375,32 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI { boss_saraAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); m_bIsIntroDone = false; Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; // intro - bool m_bIsIntro; + bool m_bIsIntro; uint32 m_uiIntro_Phase; uint32 m_uiSpeech_Timer; - bool m_bIsIntroDone; - bool m_bIsFactionSet; + bool m_bIsIntroDone; + bool m_bIsFactionSet; // phase 1 uint32 m_uiPhaseYellTimer; + uint32 m_uiSummonTimer; uint32 m_uiSarasFervorTimer; uint32 m_uiSarasBlessingTimer; uint32 m_uiSarasAngerTimer; uint32 m_uiAllVisions; // transition - bool m_bIsOutro; + bool m_bIsOutro; uint32 m_uiOutroTimer; uint32 m_uiOutroStep; @@ -1353,11 +1409,17 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI uint32 m_uiPortalsTimer; uint32 m_uiMaladyTimer; uint32 m_uiBrainLinkTimer; - uint32 m_uiDeathRaySummonTimer; + uint32 m_uiDeathRayTimer; + uint32 m_uiBrainLinkEndTimer; + uint32 m_uiBrainLinkTickTimer; + bool m_bIsBrainLink; uint32 m_uiFirstVision; uint32 m_uiSecondVision; + ObjectGuid m_uiLinkTarget1GUID; + ObjectGuid m_uiLinkTarget2GUID; + void Reset() { // intro @@ -1368,6 +1430,7 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI // phase 1 m_uiPhaseYellTimer = 30000; + m_uiSummonTimer = 10000 + urand (1000, 5000); m_uiSarasFervorTimer = urand(10000, 15000); m_uiSarasBlessingTimer = urand(15000, 20000); m_uiSarasAngerTimer = urand(20000, 25000); @@ -1383,11 +1446,17 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI m_uiPsychosisTimer = 15000; m_uiMaladyTimer = 20000; m_uiBrainLinkTimer = 25000; - m_uiDeathRaySummonTimer = 30000; + m_uiDeathRayTimer = 30000; + m_uiBrainLinkTickTimer = 1000; + m_uiBrainLinkEndTimer = 0; + m_bIsBrainLink = false; - m_uiFirstVision = 0; + m_uiFirstVision = 0; m_uiSecondVision = 0; + m_uiLinkTarget1GUID.Clear(); + m_uiLinkTarget2GUID.Clear(); + if(m_creature->HasAura(SPELL_SHADOWY_BARRIER)) m_creature->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER); @@ -1398,12 +1467,16 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); m_creature->SetLevitate(true); - m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, 5.9f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, 26); } void KilledUnit(Unit* pVictim) { - DoScriptText(urand (0,1) ? SAY_KILL1 : SAY_KILL2, m_creature); + if(irand(0,1)) + DoScriptText(SAY_KILL1, m_creature); + else + DoScriptText(SAY_KILL2, m_creature); } void DamageTaken(Unit *done_by, uint32 &uiDamage) @@ -1422,7 +1495,7 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI if(m_pInstance->GetData(TYPE_YOGG_PHASE) == PHASE_IDLE) { if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && !m_bIsIntro && !m_bIsIntroDone && - pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 60) && m_creature->IsWithinLOSInMap(pWho)) + pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 110) && m_creature->IsWithinLOSInMap(pWho)) m_bIsIntro = true; } } @@ -1444,6 +1517,45 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI return *iter; } + void DoBrainLink() + { + // workaround here + Unit * pTarget1 = m_creature->GetMap()->GetUnit(m_uiLinkTarget1GUID); + Unit * pTarget2 = m_creature->GetMap()->GetUnit(m_uiLinkTarget2GUID); + if (!pTarget1 || !pTarget1->isAlive() || !pTarget1->HasAura(SPELL_BRAIN_LINK)) + { + pTarget2->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + m_bIsBrainLink = false; + return; + } + if (!pTarget2 || !pTarget2->isAlive() || !pTarget2->HasAura(SPELL_BRAIN_LINK)) + { + pTarget1->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + m_bIsBrainLink = false; + return; + } + if (!pTarget1->IsWithinDist(pTarget2, 20.0f)) + { + //workaround for remove sanity + if(SpellAuraHolderPtr sanityAura = pTarget1->GetSpellAuraHolder(SPELL_SANITY)) + { + if(sanityAura->ModStackAmount(-2)) + { + pTarget1->RemoveAurasDueToSpell(SPELL_SANITY); + m_creature->CastSpell(pTarget1, SPELL_INSANE, false); + } + } + if(SpellAuraHolderPtr sanityAura = pTarget2->GetSpellAuraHolder(SPELL_SANITY)) + { + if(sanityAura->ModStackAmount(-2)) + { + pTarget2->RemoveAurasDueToSpell(SPELL_SANITY); + m_creature->CastSpell(pTarget2, SPELL_INSANE, false); + } + } + } + } + void SummonPortals() { uint8 maxPortals = m_bIsRegularMode ? 4 : 10; @@ -1483,22 +1595,16 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI } else if(m_uiSecondVision == 0) { - do - { - m_uiVisionType = GetCurrentVision(); - } + do m_uiVisionType = GetCurrentVision(); while(m_uiVisionType == m_uiFirstVision); m_uiSecondVision = m_uiVisionType; } else { - do - { - m_uiVisionType = GetCurrentVision(); - } + do m_uiVisionType = GetCurrentVision(); while(m_uiVisionType == m_uiFirstVision || m_uiVisionType == m_uiSecondVision); } - + // set instance data for vision if(m_uiVisionType != 0) m_pInstance->SetData(TYPE_VISION_PHASE, m_uiVisionType); @@ -1519,7 +1625,7 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI { switch(m_pInstance->GetData(TYPE_YOGG_PHASE)) { - case PHASE_IDLE: + case PHASE_IDLE: { // intro if (m_bIsIntro && !m_bIsIntroDone) @@ -1535,6 +1641,7 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI m_creature->GetMotionMaster()->MoveIdle(); SetCombatMovement(false); m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, 5.9f); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, 1); ++m_uiIntro_Phase; m_uiSpeech_Timer = 8000; break; @@ -1544,8 +1651,6 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI m_uiSpeech_Timer = 8000; break; case 2: - if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) - pYogg->SetInCombatWithZone(); m_bIsIntro = false; m_bIsIntroDone = true; m_uiSpeech_Timer = 12000; @@ -1558,74 +1663,73 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI } break; } - case PHASE_SARA: + case PHASE_SARA: { if(!m_bIsOutro) { // wipe check - if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) + if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) { if(!pYogg->getVictim() || !pYogg->SelectHostileTarget() || pYogg->getVictim() == m_creature) { - pYogg->getThreatManager().modifyThreatPercent(m_creature, -100); - if (pYogg->getThreatManager().getThreatList().size() <= 2) - { - pYogg->AI()->EnterEvadeMode(); - DoScriptText(SAY_WIPE, m_creature); - } + pYogg->AI()->EnterEvadeMode(); + DoScriptText(SAY_WIPE, m_creature); } } if (m_uiPhaseYellTimer < uiDiff) { - DoScriptText(urand(0,1) ? SAY_HELP1 : SAY_HELP2, m_creature); + switch(urand(0, 1)) + { + case 0: DoScriptText(SAY_HELP1, m_creature); break; + case 1: DoScriptText(SAY_HELP2, m_creature); break; + } m_uiPhaseYellTimer = 30000; - } - else - m_uiPhaseYellTimer -= uiDiff; + }else m_uiPhaseYellTimer -= uiDiff; + + if (m_uiSummonTimer < uiDiff) + { + if (Creature* pCloud = SelectRandomNpc(120.0f, NPC_OMINOUS_CLOUD)) + pCloud->CastSpell(pCloud, SPELL_SUMMON_GUARDIAN2, false); + m_uiSummonTimer = urand(15000, 20000); + }else m_uiSummonTimer -= uiDiff; if (m_uiSarasFervorTimer < uiDiff) { if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) { - if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (DoCastSpellIfCan(pTarget, SPELL_SARAS_FERVOR) == CAST_OK) + if(pTarget != m_creature) { + DoCast(pTarget, SPELL_SARAS_FERVOR); m_uiSarasFervorTimer = urand(20000, 30000); } } } - } - else - m_uiSarasFervorTimer -= uiDiff; + }else m_uiSarasFervorTimer -= uiDiff; if (m_uiSarasBlessingTimer < uiDiff) { if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) { - if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, (uint32)0, SELECT_FLAG_PLAYER)) + if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (DoCastSpellIfCan(pTarget, SPELL_SARAS_BLESSING) == CAST_OK) + if(pTarget != m_creature) { + DoCast(pTarget, SPELL_SARAS_BLESSING); m_uiSarasBlessingTimer = urand(20000, 30000); } } } - } - else - m_uiSarasBlessingTimer -= uiDiff; + }else m_uiSarasBlessingTimer -= uiDiff; if (m_uiSarasAngerTimer < uiDiff) { if (Creature* pGuardian = SelectRandomNpc(80.0f, MOB_GUARDIAN_OF_YOGG)) - { - if (DoCastSpellIfCan(pGuardian, SPELL_SARAS_ANGER) == CAST_OK) - m_uiSarasAngerTimer = urand(20000, 30000); - } - } - else - m_uiSarasAngerTimer -= uiDiff; + DoCast(pGuardian, SPELL_SARAS_ANGER); + m_uiSarasAngerTimer = urand(20000, 30000); + }else m_uiSarasAngerTimer -= uiDiff; } // Phase 1 outro if(m_bIsOutro) @@ -1661,7 +1765,7 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI DoCast(m_creature, SPELL_SHADOWY_BARRIER); m_creature->SetHealth(m_creature->GetMaxHealth()); m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 10, 5.9f); - m_creature->GetMotionMaster()->MovePoint(0,m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 10); + m_creature->MonsterMoveWithSpeed(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 10, 1); if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) ((boss_yogg_saronAI*)pYogg->AI())->StartSecondPhase(); m_uiPhaseYellTimer = 30000 + urand(5000, 10000); @@ -1687,15 +1791,8 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI // wipe check if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) { - if(!pYogg->getVictim() || !pYogg->SelectHostileTarget() || pYogg->getVictim() == m_creature) - { - pYogg->getThreatManager().modifyThreatPercent(m_creature, -100); - if (pYogg->getThreatManager().getThreatList().size() <= 2) - { - pYogg->AI()->EnterEvadeMode(); - DoScriptText(SAY_WIPE, m_creature); - } - } + if(!pYogg->getVictim() || !pYogg->SelectHostileTarget()) + pYogg->AI()->EnterEvadeMode(); } if (m_uiPhaseYellTimer < uiDiff) @@ -1710,7 +1807,7 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI else m_uiPhaseYellTimer -= uiDiff; // summon madness portals - if (m_uiPortalsTimer < uiDiff) + if (m_uiPortalsTimer < uiDiff && m_uiAllVisions < 3) { SetVisionPhase(); if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) @@ -1724,44 +1821,86 @@ struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { DoCast(pTarget, m_bIsRegularMode ? SPELL_PHYCHOSIS : SPELL_PHYCHOSIS_H); - m_uiPsychosisTimer = urand(15000, 20000); + + //workaround for remove sanity + if(SpellAuraHolderPtr sanityAura = pTarget->GetSpellAuraHolder(SPELL_SANITY)) + { + if(sanityAura->ModStackAmount(m_bIsRegularMode ? -12 : -9)) + { + pTarget->RemoveAurasDueToSpell(SPELL_SANITY); + m_creature->CastSpell(pTarget, SPELL_INSANE, false); + } + } } + m_uiPsychosisTimer = urand(15000, 20000); } else m_uiPsychosisTimer -= uiDiff; if (m_uiMaladyTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { DoCast(pTarget, SPELL_MALADY_OF_THE_MIND); + + //workaround for remove sanity + if(SpellAuraHolderPtr sanityAura = pTarget->GetSpellAuraHolder(SPELL_SANITY)) + { + if(sanityAura->ModStackAmount(-3)) + { + pTarget->RemoveAurasDueToSpell(SPELL_SANITY); + m_creature->CastSpell(pTarget, SPELL_INSANE, false); + } + } + } m_uiMaladyTimer = urand(20000, 25000); } else m_uiMaladyTimer -= uiDiff; if (m_uiBrainLinkTimer < uiDiff) { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_uiLinkTarget1GUID = pTarget->GetObjectGuid(); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + m_uiLinkTarget2GUID = pTarget->GetObjectGuid(); DoCast(m_creature, SPELL_BRAIN_LINK); - m_uiBrainLinkTimer = urand(25000, 30000); + m_bIsBrainLink = true; + m_uiBrainLinkEndTimer = 30000; + m_uiBrainLinkTickTimer = 3000; + m_uiBrainLinkTimer = 30000; } else m_uiBrainLinkTimer -= uiDiff; - if (m_uiDeathRaySummonTimer < uiDiff) + // workaround for brainlink + // spell need core support + // REMOVE FOR REVISION! + if (m_uiBrainLinkTickTimer < uiDiff && m_bIsBrainLink) + { + DoBrainLink(); + m_uiBrainLinkTickTimer = 3000; + } + else m_uiBrainLinkTickTimer -= uiDiff; + + if (m_uiBrainLinkEndTimer < uiDiff && m_bIsBrainLink) + m_bIsBrainLink = false; + else m_uiBrainLinkEndTimer -= uiDiff; + + // workaround, should be done by spell + if (m_uiDeathRayTimer < uiDiff) { - for(int32 count = 0; count < 4; ++count) + if(Creature* pYogg = m_pInstance->GetSingleCreatureFromStorage(NPC_YOGGSARON)) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + for(int i = 0; i < irand(3, 4); i++) { - if (pTarget->GetPositionZ() > LAYERCUT) - { - //DoCastSpellIfCan(pTarget, SPELL_DEATH_RAY_SUMMON, CAST_TRIGGERED); // spell doesn't work correct, therefor a manuell summon - m_creature->SummonCreature(MOB_DEATH_ORB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 18000); - } - else - count--; + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = pYogg->GetPositionX() + urand(20, 40)*cos(angle*(M_PI/180)); + float homeY = pYogg->GetPositionY() + urand(20, 40)*sin(angle*(M_PI/180)); + m_creature->SummonCreature(MOB_DEATH_ORB, homeX, homeY, pYogg->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000); } } - m_uiDeathRaySummonTimer = 30000; + //DoCast(m_creature, SPELL_DEATH_RAY); + m_uiDeathRayTimer = 30000; } - else m_uiDeathRaySummonTimer -= uiDiff; + else m_uiDeathRayTimer -= uiDiff; break; } @@ -1776,11 +1915,11 @@ struct MANGOS_DLL_DECL keeper_hodirAI : public ScriptedAI { keeper_hodirAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiHodirProtectivGazeTimer; @@ -1810,11 +1949,11 @@ struct MANGOS_DLL_DECL keeper_freyaAI : public ScriptedAI { keeper_freyaAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; void Reset() { @@ -1841,11 +1980,11 @@ struct MANGOS_DLL_DECL keeper_thorimAI : public ScriptedAI { keeper_thorimAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bHasTitanicStorm; @@ -1873,11 +2012,11 @@ struct MANGOS_DLL_DECL keeper_mimironAI : public ScriptedAI { keeper_mimironAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiDestabilizationMatrixTimer; std::list lTentacleList; @@ -1892,8 +2031,8 @@ struct MANGOS_DLL_DECL keeper_mimironAI : public ScriptedAI Creature* SelectRandomTentacle(float fRange) { - GetCreatureListWithEntryInGrid(lTentacleList, m_creature, MOB_CRUSHER_TENTACLE, fRange); - GetCreatureListWithEntryInGrid(lTentacleList, m_creature, MOB_CORRUPTOR_TENTACLE, fRange); + GetCreatureListWithEntryInGrid(lTentacleList, m_creature, m_creature->GetMap()->GetDifficulty() ? MOB_CRUSHER_TENTACLE : MOB_CRUSHER_TENTACLE_H, fRange); + GetCreatureListWithEntryInGrid(lTentacleList, m_creature, m_creature->GetMap()->GetDifficulty() ? MOB_CORRUPTOR_TENTACLE :MOB_CORRUPTOR_TENTACLE_H, fRange); if (lTentacleList.empty()){ m_uiDestabilizationMatrixTimer = 30000; @@ -1918,7 +2057,6 @@ struct MANGOS_DLL_DECL keeper_mimironAI : public ScriptedAI if(Unit* pTentacle = SelectRandomTentacle(120.0f)) DoCast(pTentacle, SPELL_DESTABILIZATION_MATRIX); m_uiDestabilizationMatrixTimer = 30000 + urand(10000,30000); - lTentacleList.clear(); } else m_uiDestabilizationMatrixTimer -= uiDiff; } @@ -1932,49 +2070,86 @@ struct MANGOS_DLL_DECL mob_immortal_guardianAI : public ScriptedAI { mob_immortal_guardianAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - pCreature->SetRespawnTime(WEEK * IN_MILLISECONDS); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiDrainLifeTimer; + uint32 m_uiStack; + uint32 m_uiHealth; + bool m_bHasAura; void Reset() { + m_uiStack = 0; + m_uiHealth = 90; + m_bHasAura = false; m_creature->SetRespawnDelay(DAY); - DoCast(m_creature, SPELL_RECENTLY_SPAWNED, true); - DoCast(m_creature, SPELL_EMPOWERED_AURA, true); } void DamageTaken(Unit *done_by, uint32 &uiDamage) { - if(m_creature->GetHealth() < uiDamage) + if(m_creature->GetHealthPercent() < 5) { - uiDamage = 0; + if(uiDamage > m_creature->GetHealth()) + uiDamage = 0; } } + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if(m_creature->GetHealthPercent() < 5) + { + if(spell->Id == SPELL_TITANIC_STORM_DMG && caster->GetEntry() == KEEPER_THORIM) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void Aggro(Unit *who) + { + DoCast(m_creature, SPELL_EMPOWERED); + } + void UpdateAI(const uint32 uiDiff) { - //if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) - //m_creature->ForcedDespawn(); + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiDrainLifeTimer < uiDiff) + // hacky way of stacking aura, needs fixing + if(SpellAuraHolderPtr empoweredAura = m_creature->GetSpellAuraHolder(SPELL_EMPOWERED)) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if(empoweredAura->GetStackAmount() < 9 && !m_bHasAura) + { + m_bHasAura = true; + empoweredAura->SetStackAmount(9); + } + } + + if(m_creature->GetHealthPercent() > 10) + { + if(m_creature->GetHealthPercent() < m_uiHealth) { - DoCast(pTarget, m_bIsRegularMode ? SPELL_DRAIN_LIFE : SPELL_DRAIN_LIFE_H, false); - m_uiDrainLifeTimer = urand(15000, 20000); + if(SpellAuraHolderPtr empoweredAura = m_creature->GetSpellAuraHolder(SPELL_EMPOWERED)) + { + if(empoweredAura->ModStackAmount(-1)) + m_creature->RemoveAurasDueToSpell(SPELL_EMPOWERED); + } + m_uiHealth -= 10; } - }else - m_uiDrainLifeTimer -= uiDiff; + } + + // empowering shadows, needs more research and core fix + if(m_creature->GetHealthPercent() > m_uiHealth + 10) + { + DoCast(m_creature, SPELL_EMPOWERED); + m_uiHealth += 10; + } DoMeleeAttackIfReady(); } @@ -1984,23 +2159,21 @@ struct MANGOS_DLL_DECL mob_guardian_of_yogg_saronAI : public ScriptedAI { mob_guardian_of_yogg_saronAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiDarkVolleyTimer; uint32 m_uiDieTimer; - uint32 m_uiDominateMindTimer; bool m_bHasCasted; void Reset() { m_uiDarkVolleyTimer = 10000; - m_uiDominateMindTimer = 30000; m_bHasCasted = false; m_creature->SetRespawnDelay(DAY); } @@ -2012,10 +2185,27 @@ struct MANGOS_DLL_DECL mob_guardian_of_yogg_saronAI : public ScriptedAI uiDamage = 0; if(!m_bHasCasted) { - m_creature->InterruptNonMeleeSpells(false); DoCast(m_creature, m_bIsRegularMode ? SPELL_SHADOW_NOVA : SPELL_SHADOW_NOVA_H); m_bHasCasted = true; m_uiDieTimer = 500; + m_creature->SetHealth(m_creature->GetMaxHealth()); + + // workaround for dmg Sara + // need to find a way to damage Sara by spell! + if(Creature* pSara = m_pInstance->GetSingleCreatureFromStorage(NPC_SARA)) + { + if(m_creature->IsWithinDist2d(pSara->GetPositionX(), pSara->GetPositionY(), 15.0f)) + { + uint32 maxHealth = m_bIsRegularMode ? 21994 : 27500; + if(pSara->GetHealth() > maxHealth) + pSara->DealDamage(pSara, m_bIsRegularMode ? urand(20000, 21994) : urand(25000, 27500), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + else + { + ((boss_saraAI*)pSara->AI())->m_bIsOutro = true; + pSara->SetHealth(pSara->GetMaxHealth()); + } + } + } } } } @@ -2028,7 +2218,6 @@ struct MANGOS_DLL_DECL mob_guardian_of_yogg_saronAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - // workaround that no atacck against sara if(Creature* pSara = m_pInstance->GetSingleCreatureFromStorage(NPC_SARA)) { if(m_creature->getVictim() == pSara) @@ -2046,14 +2235,6 @@ struct MANGOS_DLL_DECL mob_guardian_of_yogg_saronAI : public ScriptedAI } else m_uiDarkVolleyTimer -= uiDiff; - if (m_uiDominateMindTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DOMINATE_MIND); - m_uiDominateMindTimer = 30000; - } - else m_uiDominateMindTimer -= uiDiff; - if (m_uiDieTimer < uiDiff && m_bHasCasted) m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); else m_uiDieTimer -= uiDiff; @@ -2069,13 +2250,13 @@ struct MANGOS_DLL_DECL mob_corruptor_tentacleAI : public ScriptedAI { mob_corruptor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; uint32 m_uiEruptTimer; @@ -2108,22 +2289,22 @@ struct MANGOS_DLL_DECL mob_corruptor_tentacleAI : public ScriptedAI { switch(urand(0, 3)) { - case 0: - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLACK_PLAGUE); - break; - case 1: - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_APATHY); - break; - case 2: - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CURSE_OF_DOOM); - break; - case 3: - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DRAINING_POISON); - break; + case 0: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLACK_PLAGUE); + break; + case 1: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_APATHY); + break; + case 2: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CURSE_OF_DOOM); + break; + case 3: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DRAINING_POISON); + break; } m_uiSpellTimer = urand(5000, 10000); } @@ -2137,28 +2318,21 @@ struct MANGOS_DLL_DECL mob_constrictor_tentacleAI : public ScriptedAI { mob_constrictor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); - pCreature->SetRespawnTime(WEEK * IN_MILLISECONDS); Reset(); } bool m_bIsRegularMode; - instance_ulduar *m_pInstance; - - uint32 m_uiEruptTimer; - bool m_bHasErupted; + ScriptedInstance *m_pInstance; uint32 m_uiSqueezeTimer; ObjectGuid m_uiVictimGUID; void Reset() { - m_uiEruptTimer = 500; - m_bHasErupted = false; - - m_uiSqueezeTimer = 1000; + m_uiSqueezeTimer = 10000; m_creature->SetRespawnDelay(DAY); } @@ -2191,32 +2365,28 @@ struct MANGOS_DLL_DECL mob_constrictor_tentacleAI : public ScriptedAI void UpdateAI(const uint32 uiDiff) { - /*if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) { if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiVictimGUID)) pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H); m_creature->ForcedDespawn(); - }*/ + } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiEruptTimer < uiDiff && !m_bHasErupted) - { - DoCast(m_creature, SPELL_ERUPT); - m_bHasErupted = true; - }else m_uiEruptTimer -= uiDiff; - - if (m_uiSqueezeTimer < uiDiff) { - if (Unit* pTarget = GetPlayerAtMinimumRange(5.0f)) + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - pTarget->CastSpell(m_creature, SPELL_SQUEEZE_GRAB, true); + // spell needs vehicles + pTarget->CastSpell(pTarget, m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H, false); m_uiVictimGUID = pTarget->GetObjectGuid(); - m_uiSqueezeTimer = 30000; - } + } + m_uiSqueezeTimer = 30000; }else m_uiSqueezeTimer -= uiDiff; + + DoMeleeAttackIfReady(); } }; @@ -2224,25 +2394,24 @@ struct MANGOS_DLL_DECL mob_crusher_tentacleAI : public ScriptedAI { mob_crusher_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); SetCombatMovement(false); - pCreature->SetRespawnTime(WEEK * IN_MILLISECONDS); Reset(); } - instance_ulduar *m_pInstance; + ScriptedInstance *m_pInstance; bool m_bIsRegularMode; uint32 m_uiEruptTimer; bool m_bHasErupted; - uint32 m_uiCrushTimer; + uint32 m_uiDiminishPowerTimer; void Reset() { m_uiEruptTimer = 500; m_bHasErupted = false; - m_uiCrushTimer = 10000; + m_uiDiminishPowerTimer = 10000; m_creature->SetRespawnDelay(DAY); DoCast(m_creature, SPELL_FOCUSED_ANGER_TRIGG); } @@ -2262,18 +2431,12 @@ struct MANGOS_DLL_DECL mob_crusher_tentacleAI : public ScriptedAI } else m_uiEruptTimer -= uiDiff; - if (Player* pTarget = GetPlayerAtMinimumRange(23.0f)) // radius auf SPELL_CRUSH + if (m_uiDiminishPowerTimer < uiDiff) { - m_creature->InterruptNonMeleeSpells(false, SPELL_DIMINISH_POWER); - if (m_uiCrushTimer < uiDiff) - { - DoCast(pTarget, SPELL_CRUSH); - m_uiCrushTimer = 10000; - }else - m_uiCrushTimer -= uiDiff; - }else{ DoCast(m_creature, SPELL_DIMINISH_POWER); + m_uiDiminishPowerTimer = 10000 + urand(1000, 5000); } + else m_uiDiminishPowerTimer -= uiDiff; DoMeleeAttackIfReady(); } @@ -2295,7 +2458,10 @@ struct MANGOS_DLL_DECL mob_vision_tentacleAI : public ScriptedAI void DamageTaken(Unit *done_by, uint32 &uiDamage) { if(uiDamage > 0 && m_creature->GetDisplayId() != 28813) + { m_creature->SetDisplayId(28813); + m_creature->setFaction(14); + } } void UpdateAI(const uint32 uiDiff) @@ -2314,59 +2480,32 @@ struct MANGOS_DLL_DECL mob_death_orbAI : public ScriptedAI { mob_death_orbAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->SetDisplayId(16946); SetCombatMovement(false); pCreature->setFaction(14); Reset(); } - instance_ulduar* m_pInstance; - - bool m_bIsWarning; - - uint32 m_uiPlayerChange; - uint32 m_uiDamageTime; + uint32 m_uiAuraTimer; + bool m_bHasAura; void Reset() { - m_creature->SetSpeedRate(MOVE_WALK, 0.7f, true); - m_creature->SetSpeedRate(MOVE_RUN, 0.7f, true); - DoCast(m_creature, SPELL_DEATH_RAY_VISUAL_W, true); - - m_uiPlayerChange = 1000; - m_uiDamageTime = 5000; + m_uiAuraTimer = 500; + m_bHasAura = false; + DoCast(m_creature, SPELL_DEATH_RAY_VISUAL); + m_creature->GetMotionMaster()->MoveConfused(); } void UpdateAI(const uint32 uiDiff) { - if (m_uiDamageTime < uiDiff) - { - DoCastSpellIfCan(m_creature, SPELL_DEATH_RAY_TRIGG, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_DEATH_RAY_VISUAL_D, CAST_TRIGGERED); - m_uiDamageTime = 600000; - } - else - m_uiDamageTime -= uiDiff; - - if (m_uiPlayerChange < uiDiff) + if(m_uiAuraTimer < uiDiff && !m_bHasAura) { - if (Creature* pSara = m_pInstance->GetSingleCreatureFromStorage(NPC_SARA)) - { - if (Unit* pTarget = pSara->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (pTarget->GetPositionZ() > LAYERCUT) - { - m_creature->GetMotionMaster()->MoveFollow(pTarget, 0, 0); - m_uiPlayerChange = 4000; - } - } - } + DoCast(m_creature, SPELL_DEATH_RAY_TRIGG); + m_bHasAura = true; } - else - m_uiPlayerChange -= uiDiff; + else m_uiAuraTimer -= uiDiff; } }; @@ -2374,14 +2513,15 @@ struct MANGOS_DLL_DECL mob_sanity_wellAI : public ScriptedAI { mob_sanity_wellAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pCreature->SetDisplayId(11686); // make invisible + pCreature->setFaction(14); SetCombatMovement(false); Reset(); } - instance_ulduar* m_pInstance; + ScriptedInstance* m_pInstance; uint32 m_uiAuraDelayTimer; bool m_bHasAura; @@ -2390,8 +2530,7 @@ struct MANGOS_DLL_DECL mob_sanity_wellAI : public ScriptedAI { m_uiAuraDelayTimer = 1000; m_bHasAura = false; - DoCast(m_creature, SPELL_SANITY_WELL_VISUAL, true); - DoCast(m_creature, SPELL_SANITY_WELL, true); + DoCast(m_creature, SPELL_SANITY_WELL_VISUAL); m_creature->SetRespawnDelay(DAY); } @@ -2448,20 +2587,25 @@ struct MANGOS_DLL_DECL mob_ominous_cloudAI : public ScriptedAI { mob_ominous_cloudAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); SetCombatMovement(false); pCreature->setFaction(14); Reset(); } - instance_ulduar *m_pInstance; + ScriptedInstance *m_pInstance; + + uint32 m_uiRangeCheckTimer; + bool m_bSummonGuardian; void Reset() { + m_uiRangeCheckTimer = 1000; + m_bSummonGuardian = false; DoCast(m_creature, SPELL_OMINOUS_CLOUD_VISUAL); m_creature->SetRespawnDelay(DAY); - m_creature->GetMotionMaster()->MoveConfused(); } void AttackStart(Unit* pWho) @@ -2469,14 +2613,6 @@ struct MANGOS_DLL_DECL mob_ominous_cloudAI : public ScriptedAI return; } - void MoveInLineOfSight(Unit* pWho) - { - if (m_creature->IsWithinDist(pWho, 5.0f, true)) - if (pWho->GetTypeId() == TYPEID_PLAYER && pWho->isAlive()) - if (!m_creature->HasAura(SPELL_SUMMON_GUARDIAN2)) - DoCast(m_creature, SPELL_SUMMON_GUARDIAN2, false); - } - void JustSummoned(Creature* pSummon) { pSummon->SetInCombatWithZone(); @@ -2484,6 +2620,34 @@ struct MANGOS_DLL_DECL mob_ominous_cloudAI : public ScriptedAI void UpdateAI(const uint32 uiDiff) { + if (m_uiRangeCheckTimer < uiDiff) + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()->GetPositionX(), i->getSource()->GetPositionY()) <= 5) + m_bSummonGuardian = true; + + } + } + // cast summon guard + if(m_bSummonGuardian) + { + DoCast(m_creature, SPELL_SUMMON_GUARDIAN2); + m_uiRangeCheckTimer = 11000; + m_bSummonGuardian = false; + } + else + m_uiRangeCheckTimer = 1000; + } + else m_uiRangeCheckTimer -= uiDiff; } }; @@ -2577,96 +2741,6 @@ CreatureAI* GetAI_mob_ominous_cloud(Creature* pCreature) return new mob_ominous_cloudAI(pCreature); } -bool pGossipHello_adventurer(Player *pPlayer, Creature *pCreature) -{ - instance_ulduar* m_pInstance = (instance_ulduar*)pCreature->GetInstanceData(); - - if (!m_pInstance) - return false; - - if(m_pInstance->GetData(TYPE_KEEPER_THORIM) != DONE) - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Thorim soll am Kampf teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - } - else - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Thorim soll am Kampf nicht teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - } - - if(m_pInstance->GetData(TYPE_KEEPER_HODIR) != DONE) - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Hodir soll am Kampf teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - } - else - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Hodir soll am Kampf nicht teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - } - - if(m_pInstance->GetData(TYPE_KEEPER_FREYA) != DONE) - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Freya soll am Kampf teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - } - else - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Freya soll am Kampf nicht teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - } - - if(m_pInstance->GetData(TYPE_KEEPER_MIMIRON) != DONE) - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Mimiron soll am Kampf teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - } - else - { - pPlayer->ADD_GOSSIP_ITEM( 0,"Mimiron soll am Kampf nicht teilnehmen.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); - } - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); - return true; -} - -bool pGossipSelect_adventurer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); - pPlayer->CLOSE_GOSSIP_MENU(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - m_pInstance->SetData(TYPE_KEEPER_THORIM, DONE); - pCreature->MonsterSay("Okay, Thorim wird mit euch in die Schlacht ziehen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+2: - m_pInstance->SetData(TYPE_KEEPER_THORIM, FAIL); - pCreature->MonsterSay("Okay, Thorim wird sich nicht einmischen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+3: - m_pInstance->SetData(TYPE_KEEPER_HODIR, DONE); - pCreature->MonsterSay("Okay, Hodir wird mit euch in die Schlacht ziehen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+4: - m_pInstance->SetData(TYPE_KEEPER_HODIR, FAIL); - pCreature->MonsterSay("Okay, Hodir wird sich nicht einmischen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+5: - m_pInstance->SetData(TYPE_KEEPER_FREYA, DONE); - pCreature->MonsterSay("Okay, Freya wird mit euch in die Schlacht ziehen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+6: - m_pInstance->SetData(TYPE_KEEPER_FREYA, FAIL); - pCreature->MonsterSay("Okay, Freya wird sich nicht einmischen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+7: - m_pInstance->SetData(TYPE_KEEPER_MIMIRON, DONE); - pCreature->MonsterSay("Okay, Mimiron wird mit euch in die Schlacht ziehen." , LANG_UNIVERSAL); - break; - case GOSSIP_ACTION_INFO_DEF+8: - m_pInstance->SetData(TYPE_KEEPER_MIMIRON, FAIL); - pCreature->MonsterSay("Okay, Mimiron wird sich nicht einmischen." , LANG_UNIVERSAL); - break; - default: - pCreature->MonsterSay("Unbekannte Antwort", LANG_UNIVERSAL); - } - return true; -} - void AddSC_boss_yogg_saron() { Script *newscript; @@ -2759,10 +2833,4 @@ void AddSC_boss_yogg_saron() newscript->Name = "mob_ominous_cloud"; newscript->GetAI = &GetAI_mob_ominous_cloud; newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "adventurer"; - newscript->pGossipHello = &pGossipHello_adventurer; - newscript->pGossipSelect = &pGossipSelect_adventurer; - newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp b/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp index ce6713ea51..91d25ec055 100644 --- a/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp +++ b/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp @@ -24,1068 +24,744 @@ EndScriptData */ #include "precompiled.h" #include "ulduar.h" -instance_ulduar::instance_ulduar(Map* pMap) : ScriptedInstance(pMap) +struct MANGOS_DLL_DECL instance_ulduar : public ScriptedInstance { - Initialize(); -} - -void instance_ulduar::Initialize() -{ - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - memset(&m_auiHardBoss, 0, sizeof(m_auiHardBoss)); - memset(&m_auiUlduarKeepers, 0, sizeof(m_auiUlduarKeepers)); - memset(&m_auiUlduarTeleporters, 0, sizeof(m_auiUlduarTeleporters)); - - for(uint8 i = 0; i < 6; i++) - m_auiMiniBoss[i] = NOT_STARTED; + instance_ulduar(Map* pMap) : ScriptedInstance(pMap) + { + m_bRegular = pMap->IsRegularDifficulty(); + Initialize(); + } - for (uint8 i = 0; i < MAX_SPECIAL_ACHIEV_CRITS; ++i) - m_abAchievCriteria[i] = false; + bool m_bRegular; - m_uiMimironPhase = 0; - m_uiYoggPhase = 0; - m_uiVisionPhase = 0; + // initialize the encouter variables + std::string m_strInstData; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 m_auiHardBoss[HARD_ENCOUNTER]; + uint32 m_auiUlduarKeepers[KEEPER_ENCOUNTER]; + uint32 m_auiUlduarTeleporters[3]; + uint32 m_auiMiniBoss[6]; - // Leviathan not implemented, so set it as DONE - SetData(TYPE_LEVIATHAN, DONE); - SetData(TYPE_LEVIATHAN_TP, DONE); -} + // boss phases which need to be used inside the instance script + uint32 m_uiMimironPhase; + uint32 m_uiYoggPhase; + uint32 m_uiVisionPhase; -bool instance_ulduar::IsEncounterInProgress() const -{ - for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + void Initialize() { - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - } + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + memset(&m_auiHardBoss, 0, sizeof(m_auiHardBoss)); + memset(&m_auiUlduarKeepers, 0, sizeof(m_auiUlduarKeepers)); + memset(&m_auiUlduarTeleporters, 0, sizeof(m_auiUlduarTeleporters)); - return false; -} + for(uint8 i = 0; i < 6; i++) + m_auiMiniBoss[i] = NOT_STARTED; + } -void instance_ulduar::OnCreatureCreate(Creature* pCreature) -{ - switch(pCreature->GetEntry()) + bool IsEncounterInProgress() const { - case NPC_LEVIATHAN: - case NPC_IGNIS: - break; - case NPC_IRON_CONSTRUCT: - m_lIronConstructsGuids.push_back(pCreature->GetObjectGuid()); - return; - case NPC_RAZORSCALE: - case NPC_COMMANDER: - case NPC_XT002: - // Assembly of Iron - case NPC_STEELBREAKER: - case NPC_MOLGEIM: - case NPC_BRUNDIR: - // Kologarn - case NPC_KOLOGARN: - case NPC_KOLOGARN_BRIDGE_DUMMY: - // Auriaya - case NPC_AURIAYA: - case NPC_FERAL_DEFENDER: - // Mimiron - case NPC_AERIAL_UNIT: - case NPC_VX001: - case NPC_MIMIRON: - case NPC_LEVIATHAN_MK: - // Hodir - case NPC_HODIR: - case NPC_HELPER_DRUID: - case NPC_HELPER_MAGE: - case NPC_HELPER_SHAMAN: - case NPC_HELPER_PRIEST: - //Thorim - case NPC_THORIM: - case NPC_RUNIC_COLOSSUS: - break; - case NPC_RIGHT_HAND_TRIGGER: - m_lRightHandTriggerGuids.push_back(pCreature->GetObjectGuid()); - return; - case NPC_LEFT_HAND_TRIGGER: - m_lLeftHandTriggerGuids.push_back(pCreature->GetObjectGuid()); - return; - case NPC_RUNE_GIANT: - case NPC_JORMUNGAR_BEHEMOTH: - case NPC_FREYA: - case NPC_BRIGHTLEAF: - case NPC_IRONBRACH: - case NPC_STONEBARK: - case NPC_VEZAX: - case NPC_ANIMUS: - case NPC_YOGGSARON: - case NPC_SARA: - case NPC_YOGG_BRAIN: - case NPC_ALGALON: - break; - case NPC_OMINOUS_CLOUD: - m_lCLoudGuids.push_back(pCreature->GetObjectGuid()); - return; - case NPC_SANCTUM_SENTRY: - m_lSanctumSentryGuids.push_back(pCreature->GetObjectGuid()); - return; + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + } - // used to handle the keepers images - // set to invisible by default and only made visible if the encounter is done - case HODIR_IMAGE: - pCreature->SetVisibility(VISIBILITY_OFF); - if(m_auiEncounter[8] == DONE) - pCreature->SetVisibility(VISIBILITY_ON); - break; - case FREYA_IMAGE: - pCreature->SetVisibility(VISIBILITY_OFF); - if(m_auiEncounter[10] == DONE) - pCreature->SetVisibility(VISIBILITY_ON); - break; - case THORIM_IMAGE: - pCreature->SetVisibility(VISIBILITY_OFF); - if(m_auiEncounter[9] == DONE) - pCreature->SetVisibility(VISIBILITY_ON); - break; - case MIMIRON_IMAGE: - pCreature->SetVisibility(VISIBILITY_OFF); - if(m_auiEncounter[7] == DONE) - pCreature->SetVisibility(VISIBILITY_ON); - break; - default: - return; + return false; } - m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); -} -void instance_ulduar::OnObjectCreate(GameObject *pGo) -{ - switch(pGo->GetEntry()) + void OnCreatureCreate(Creature* pCreature) { - // doors & other - // The siege - case GO_SHIELD_WALL: - break; - case GO_LEVIATHAN_GATE: - if(m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_XT002_GATE: - pGo->SetGoState(GO_STATE_READY); - if(m_auiEncounter[0] == DONE || m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_BROKEN_HARPOON: - m_lBreakHarpoonGUID.push_back(pGo->GetObjectGuid()); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); - break; + switch(pCreature->GetEntry()) + { + case NPC_LEVIATHAN: + case NPC_IGNIS: + case NPC_RAZORSCALE: + case NPC_COMMANDER: + case NPC_XT002: + case NPC_STEELBREAKER: + case NPC_MOLGEIM: + case NPC_BRUNDIR: + case NPC_KOLOGARN: + case NPC_RIGHT_ARM: + case NPC_LEFT_ARM: + case NPC_AURIAYA: + case NPC_FERAL_DEFENDER: + case NPC_MIMIRON: + case NPC_LEVIATHAN_MK: + case NPC_HODIR: + case NPC_THORIM: + case NPC_RUNIC_COLOSSUS: + case NPC_RUNE_GIANT: + case NPC_JORMUNGAR_BEHEMOTH: + case NPC_FREYA: + case NPC_BRIGHTLEAF: + case NPC_IRONBRACH: + case NPC_STONEBARK: + case NPC_VEZAX: + case NPC_ANIMUS: + case NPC_YOGGSARON: + case NPC_SARA: + case NPC_YOGG_BRAIN: + case NPC_ALGALON: + break; + // used to handle the keepers images + // set to invisible by default and only made visible if the encounter is done + case HODIR_IMAGE: + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[8] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + case FREYA_IMAGE: + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[10] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + case THORIM_IMAGE: + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[9] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + case MIMIRON_IMAGE: + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[7] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + } + m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); + } + void OnObjectCreate(GameObject *pGo) + { + switch(pGo->GetEntry()) + { + // doors & other + // The siege + case GO_SHIELD_WALL: + break; + case GO_LEVIATHAN_GATE: + if(m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_XT002_GATE: + pGo->SetGoState(GO_STATE_READY); + if(m_auiEncounter[TYPE_XT002] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + if(m_auiEncounter[TYPE_IGNIS] == DONE && m_auiEncounter[TYPE_RAZORSCALE] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_BROKEN_HARPOON: + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + break; // Archivum - case GO_IRON_ENTRANCE_DOOR: - break; - case GO_ARCHIVUM_DOOR: - pGo->SetGoState(GO_STATE_READY); - if(m_auiEncounter[4]) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_ARCHIVUM_CONSOLE: - case GO_UNIVERSE_FLOOR_ARCHIVUM: + case GO_IRON_ENTRANCE_DOOR: + break; + case GO_ARCHIVUM_DOOR: + if(m_auiEncounter[TYPE_ASSEMBLY]) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_ARCHIVUM_CONSOLE: + break; + case GO_UNIVERSE_FLOOR_ARCHIVUM: + break; // Celestial Planetarium - case GO_CELESTIAL_ACCES: - case GO_CELESTIAL_DOOR: - case GO_UNIVERSE_FLOOR_CELESTIAL: - case GO_AZEROTH_GLOBE: - break; + case GO_CELESTIAL_ACCES: + case GO_CELESTIAL_DOOR: + case GO_UNIVERSE_FLOOR_CELESTIAL: + case GO_AZEROTH_GLOBE: + break; // Shattered Hallway - case GO_KOLOGARN_BRIDGE: - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_SHATTERED_DOOR: - break; + case GO_KOLOGARN_BRIDGE: + pGo->SetGoState(GO_STATE_ACTIVE); + if(m_auiEncounter[TYPE_KOLOGARN] == DONE) + { + pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGo->SetGoState(GO_STATE_READY); + } + break; + case GO_SHATTERED_DOOR: + break; // The keepers // Hodir - case GO_HODIR_EXIT: - if(m_auiEncounter[TYPE_HODIR] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_HODIR_ICE_WALL: - if(m_auiEncounter[TYPE_HODIR] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_HODIR_ENTER: - pGo->SetGoState(GO_STATE_ACTIVE); - break; + case GO_HODIR_EXIT: + if(m_auiEncounter[TYPE_HODIR]) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_HODIR_ICE_WALL: + if(m_auiEncounter[TYPE_HODIR]) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_HODIR_ENTER: + break; // Mimiron - case GO_MIMIRON_TRAM: - if (m_auiEncounter[TYPE_AURIAYA] == DONE) - { - pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); - pGo->SetGoState(GO_STATE_READY); - } - break; - case GO_MIMIRON_BUTTON: - if (m_auiEncounter[TYPE_MIMIRON] == NOT_STARTED) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); - break; - case GO_MIMIRON_DOOR_1: - case GO_MIMIRON_DOOR_2: - case GO_MIMIRON_DOOR_3: - case GO_MIMIRON_ELEVATOR: - case GO_MIMIRON_TEL1: - case GO_MIMIRON_TEL2: - case GO_MIMIRON_TEL3: - case GO_MIMIRON_TEL4: - case GO_MIMIRON_TEL5: - case GO_MIMIRON_TEL6: - case GO_MIMIRON_TEL7: - case GO_MIMIRON_TEL8: - case GO_MIMIRON_TEL9: + case GO_MIMIRON_TRAM: + if (m_auiEncounter[TYPE_AURIAYA] == DONE) + { + pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGo->SetGoState(GO_STATE_READY); + } + break; + case GO_MIMIRON_BUTTON: + if (m_auiEncounter[TYPE_MIMIRON] == NOT_STARTED) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + break; + case GO_MIMIRON_DOOR_1: + case GO_MIMIRON_DOOR_2: + case GO_MIMIRON_DOOR_3: + case GO_MIMIRON_ELEVATOR: + case GO_MIMIRON_TEL1: + case GO_MIMIRON_TEL2: + case GO_MIMIRON_TEL3: + case GO_MIMIRON_TEL4: + case GO_MIMIRON_TEL5: + case GO_MIMIRON_TEL6: + case GO_MIMIRON_TEL7: + case GO_MIMIRON_TEL8: + case GO_MIMIRON_TEL9: + break; // Thorim - case GO_DARK_IRON_PORTCULIS: - case GO_RUNED_STONE_DOOR: - case GO_THORIM_STONE_DOOR: - case GO_LIGHTNING_FIELD: - break; - case GO_DOOR_LEVER: - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); - break; - + case GO_DARK_IRON_PORTCULIS: + case GO_RUNED_STONE_DOOR: + case GO_THORIM_STONE_DOOR: + case GO_LIGHTNING_FIELD: + break; + case GO_DOOR_LEVER: + if (m_auiEncounter[TYPE_THORIM] != DONE) + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + else + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + break; // Prison - case GO_ANCIENT_GATE: - DoOpenMadnessDoorIfCan(); - break; - case GO_VEZAX_GATE: - pGo->SetGoState(GO_STATE_READY); - if(m_auiEncounter[11]) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_YOGG_GATE: - case GO_BRAIN_DOOR1: - case GO_BRAIN_DOOR2: - case GO_BRAIN_DOOR3: + case GO_ANCIENT_GATE: + DoOpenMadnessDoorIfCan(); + break; + case GO_VEZAX_GATE: + pGo->SetGoState(GO_STATE_READY); + if(m_auiEncounter[TYPE_VEZAX]) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_YOGG_GATE: + case GO_BRAIN_DOOR1: + case GO_BRAIN_DOOR2: + case GO_BRAIN_DOOR3: + break; // loot // Kologarn - case GO_CACHE_OF_LIVING_STONE: - case GO_CACHE_OF_LIVING_STONE_H: - + case GO_CACHE_OF_LIVING_STONE: + case GO_CACHE_OF_LIVING_STONE_H: // Hodir - case GO_CACHE_OF_WINTER: - case GO_CACHE_OF_RARE_WINTER: - case GO_CACHE_OF_WINTER_H: - case GO_CACHE_OF_RARE_WINTER_H: + case GO_CACHE_OF_WINTER: + case GO_CACHE_OF_WINTER_H: + // Hodir rare + case GO_CACHE_OF_RARE_WINTER: + case GO_CACHE_OF_RARE_WINTER_H: // Freya - case GO_FREYA_GIFT: - case GO_FREYA_GIFT_HARD: - case GO_FREYA_GIFT_H: - case GO_FREYA_GIFT_HARD_H: + case GO_FREYA_GIFT: + case GO_FREYA_GIFT_H: + // Freya rare + case GO_FREYA_GIFT_1: + case GO_FREYA_GIFT_H_1: + case GO_FREYA_GIFT_2: + case GO_FREYA_GIFT_H_2: + case GO_FREYA_GIFT_3: + case GO_FREYA_GIFT_H_3: // Thorim - case GO_CACHE_OF_STORMS: - case GO_CACHE_OF_RARE_STORMS: - case GO_CACHE_OF_STORMS_H: - case GO_CACHE_OF_RARE_STORMS_H: + case GO_CACHE_OF_STORMS: + case GO_CACHE_OF_STORMS_H: + // Thorim rare + case GO_CACHE_OF_RARE_STORMS: + case GO_CACHE_OF_RARE_STORMS_H: // Mimiron - case GO_CACHE_OF_INOV: - case GO_CACHE_OF_INOV_HARD: - case GO_CACHE_OF_INOV_H: - case GO_CACHE_OF_INOV_HARD_H: + case GO_CACHE_OF_INOV: + case GO_CACHE_OF_INOV_H: + case GO_CACHE_OF_INOV_HARD: + case GO_CACHE_OF_INOV_HARD_H: // Alagon - case GO_GIFT_OF_OBSERVER: - case GO_GIFT_OF_OBSERVER_H: - break; - default: - return; + case GO_GIFT_OF_OBSERVER: + case GO_GIFT_OF_OBSERVER_H: + break; + } + m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); } - m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); -} -void instance_ulduar::OnCreatureDeath(Creature * pCreature) -{ - if (GetData(TYPE_IGNIS) == IN_PROGRESS && pCreature->GetEntry() == NPC_IRON_CONSTRUCT) + // used in order to unlock the door to Vezax and make vezax attackable + void DoOpenMadnessDoorIfCan() { - if (m_bOneIsDeath) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_SHATTERED, true); - } - else + if (m_auiEncounter[TYPE_MIMIRON] == DONE && m_auiEncounter[TYPE_HODIR] == DONE && m_auiEncounter[TYPE_THORIM] == DONE && m_auiEncounter[TYPE_FREYA] == DONE) { - m_bOneIsDeath = true; - m_uiShatterTimer = 5 * IN_MILLISECONDS; + if (GameObject* pDoor = GetSingleGameObjectFromStorage(GO_ANCIENT_GATE)) + pDoor->SetGoState(GO_STATE_ACTIVE); } } - if (GetData(TYPE_AURIAYA) == IN_PROGRESS && pCreature->GetEntry() == NPC_SANCTUM_SENTRY) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_CRAZY_CAT_LADY, false); - } - if (GetData(TYPE_THORIM) == IN_PROGRESS // Thorim - || pCreature->GetEntry() == NPC_JORMUNGAR_BEHEMOTH // Preadds - || pCreature->GetEntry() == NPC_CAPTAIN_ALY - || pCreature->GetEntry() == NPC_CAPTAIN_HORDE - || pCreature->GetEntry() == NPC_MERCENARY_ALY - || pCreature->GetEntry() == NPC_MERCENARY_HORDE) + + // used to open the door to XT (custom script because Leviathan is disabled) + // this will be removed when the Leviathan will be implemented + void OpenXtDoor() { - m_lThorimMobsGuids.push_back(pCreature->GetObjectGuid()); + if(m_auiEncounter[TYPE_IGNIS] == DONE && m_auiEncounter[TYPE_RAZORSCALE] == DONE) + DoUseDoorOrButton(GO_XT002_GATE); } -} - -// functions to open or close some doors -void instance_ulduar::OpenDoor(uint32 uiEntry) -{ - if(!uiEntry) - return; - - GameObject* pGo = GetSingleGameObjectFromStorage(uiEntry); - - if(pGo) - pGo->SetGoState(GO_STATE_ACTIVE); -} - -void instance_ulduar::CloseDoor(uint32 uiEntry) -{ - if(!uiEntry) - return; - - GameObject* pGo = GetSingleGameObjectFromStorage(uiEntry); - if(pGo) - pGo->SetGoState(GO_STATE_READY); -} - -// used in order to unlock the door to Vezax and make vezax attackable -void instance_ulduar::DoOpenMadnessDoorIfCan() -{ - if(m_auiEncounter[TYPE_MIMIRON] == DONE && m_auiEncounter[TYPE_HODIR] == DONE && m_auiEncounter[TYPE_THORIM] == DONE && m_auiEncounter[TYPE_FREYA] == DONE) - OpenDoor(GO_ANCIENT_GATE); -} - -void instance_ulduar::SetData(uint32 uiType, uint32 uiData) -{ - switch(uiType) + void SetData(uint32 uiType, uint32 uiData) { - case TYPE_LEVIATHAN: - m_auiEncounter[uiType] = uiData; - DoUseDoorOrButton(GO_SHIELD_WALL); - if (uiData == DONE) - OpenDoor(GO_LEVIATHAN_GATE); - break; - case TYPE_IGNIS: - m_auiEncounter[uiType] = uiData; - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_SHATTERED, false); - DoStartTimedAchievement(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEV_START_IGNIS_ID); - } - // Add respawn and kill - if (uiData == FAIL) - { - for (GUIDList::iterator itr = m_lIronConstructsGuids.begin(); itr != m_lIronConstructsGuids.end(); ++itr) - { - if (Creature *pAdd = instance->GetCreature(*itr)) - if (!pAdd->isAlive()) - pAdd->Respawn(); - } - } - if (uiData == DONE) - { - for (GUIDList::iterator itr = m_lIronConstructsGuids.begin(); itr != m_lIronConstructsGuids.end(); ++itr) - { - if (Creature *pAdd = instance->GetCreature(*itr)) - if (pAdd->isAlive()) - pAdd->DealDamage(pAdd, pAdd->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); - } - } - break; - case TYPE_RAZORSCALE: - m_auiEncounter[uiType] = uiData; - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_QUICK_SHAVE, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_IRON_DWARF_MEDIUM_RARE, false); - } - break; - case TYPE_XT002: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE || uiData == FAIL) - OpenDoor(GO_XT002_GATE); - else if (uiData == IN_PROGRESS) - { - CloseDoor(GO_XT002_GATE); - SetSpecialAchievementCriteria(TYPE_ACHIEV_NERF_ENGINEERING, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_HEARTBREAKER, false); - DoStartTimedAchievement(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEV_START_XT_002_ID); - } - break; - case TYPE_ASSEMBLY: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - { - OpenDoor(GO_IRON_ENTRANCE_DOOR); - OpenDoor(GO_ARCHIVUM_DOOR); - OpenDoor(GO_SHATTERED_DOOR); - } - else if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_YOU_BRUNDIR, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_YOU_MOLGEIM, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_YOU_STEELBREAKER, true); - CloseDoor(GO_IRON_ENTRANCE_DOOR); - } - else if (uiData == FAIL) + switch(uiType) { - if (Creature* pBrundir = GetSingleCreatureFromStorage(NPC_BRUNDIR)) + case TYPE_LEVIATHAN: + m_auiEncounter[TYPE_LEVIATHAN] = uiData; + DoUseDoorOrButton(GO_SHIELD_WALL); + if (uiData == DONE) { - if (!pBrundir->isAlive()) - pBrundir->Respawn(); + DoUseDoorOrButton(GO_XT002_GATE); + DoUseDoorOrButton(GO_LEVIATHAN_GATE); } - if (Creature* pMolgeim = GetSingleCreatureFromStorage(NPC_MOLGEIM)) - { - if (!pMolgeim->isAlive()) - pMolgeim->Respawn(); - } - if (Creature* pSteelbreaker = GetSingleCreatureFromStorage(NPC_STEELBREAKER)) - { - if (!pSteelbreaker->isAlive()) - pSteelbreaker->Respawn(); - } - OpenDoor(GO_IRON_ENTRANCE_DOOR); - } - break; - case TYPE_KOLOGARN: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_CACHE_OF_LIVING_STONE, 30*MINUTE); - } - else - { - DoRespawnGameObject(GO_CACHE_OF_LIVING_STONE_H, 30*MINUTE); - } - if (GameObject* pGo = GetSingleGameObjectFromStorage(GO_KOLOGARN_BRIDGE)) - { - pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); - pGo->SetGoState(GO_STATE_READY); - } - } - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_DISARMED, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_OPEN_ARMS, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_RUBBLE_AND_ROLL, false); - } - break; - case TYPE_AURIAYA: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - { - if (GameObject* pGO = GetSingleGameObjectFromStorage(GO_MIMIRON_TRAM)) - { - pGO->SetUInt32Value(GAMEOBJECT_LEVEL, 0); - pGO->SetGoState(GO_STATE_READY); - } - } - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_NINE_LIVES, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_CRAZY_CAT_LADY, true); - } - break; - // Keepers - case TYPE_MIMIRON: - m_auiEncounter[uiType] = uiData; - DoUseDoorOrButton(GO_MIMIRON_DOOR_1); - DoUseDoorOrButton(GO_MIMIRON_DOOR_2); - DoUseDoorOrButton(GO_MIMIRON_DOOR_3); - if (uiData == DONE) - { - if (m_auiHardBoss[3] != DONE) - { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_CACHE_OF_INOV, 30*MINUTE); - } - else - { - DoRespawnGameObject(GO_CACHE_OF_INOV_H, 30*MINUTE); - } - } - // used to make the friendly keeper visible - if(Creature* pImage = GetSingleCreatureFromStorage(KEEPER_MIMIRON)) - pImage->SetVisibility(VISIBILITY_ON); - DoOpenMadnessDoorIfCan(); - } - if (uiData == IN_PROGRESS) - SetSpecialAchievementCriteria(TYPE_ACHIEV_FIREFIGHTER, false); - break; - case TYPE_HODIR: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - { - OpenDoor(GO_HODIR_ENTER); - DoUseDoorOrButton(GO_HODIR_ICE_WALL); - DoUseDoorOrButton(GO_HODIR_EXIT); - if(instance->IsRegularDifficulty()) + break; + case TYPE_IGNIS: + m_auiEncounter[TYPE_IGNIS] = uiData; + OpenXtDoor(); // remove when leviathan implemented + break; + case TYPE_RAZORSCALE: + m_auiEncounter[TYPE_RAZORSCALE] = uiData; + OpenXtDoor(); // remove when leviathan implemented + break; + case TYPE_XT002: + m_auiEncounter[TYPE_XT002] = uiData; + if (uiData == DONE) + DoUseDoorOrButton(GO_XT002_GATE); + else if (uiData == IN_PROGRESS) + DoUseDoorOrButton(GO_XT002_GATE); + break; + case TYPE_ASSEMBLY: + m_auiEncounter[TYPE_ASSEMBLY] = uiData; + DoUseDoorOrButton(GO_IRON_ENTRANCE_DOOR); + if (uiData == DONE) { - DoRespawnGameObject(GO_CACHE_OF_WINTER, 30*MINUTE); + DoUseDoorOrButton(GO_ARCHIVUM_DOOR); + CheckIronCouncil(); // used for a hacky achiev, remove for revision! } - else + break; + case TYPE_KOLOGARN: + m_auiEncounter[TYPE_KOLOGARN] = uiData; + DoUseDoorOrButton(GO_SHATTERED_DOOR); + if (uiData == DONE) { - DoRespawnGameObject(GO_CACHE_OF_WINTER_H, 30*MINUTE); + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_LIVING_STONE : GO_CACHE_OF_LIVING_STONE_H, 30*MINUTE); + if (GameObject* pBridge = GetSingleGameObjectFromStorage(GO_KOLOGARN_BRIDGE)) + pBridge->SetGoState(GO_STATE_READY); } - // used to make the friendly keeper visible - if(Creature* pImage = GetSingleCreatureFromStorage(KEEPER_HODIR)) - pImage->SetVisibility(VISIBILITY_ON); - - DoOpenMadnessDoorIfCan(); - } - else if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_CHEESE_FREEZE, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_COOLEST_FRIEND, true); - SetSpecialAchievementCriteria(TYPE_ACHIEV_RARE_CACHE, true); - CloseDoor(GO_HODIR_ENTER); - } - else if (uiData == FAIL) - OpenDoor(GO_HODIR_ENTER); - break; - case TYPE_THORIM: - m_auiEncounter[uiType] = uiData; - DoUseDoorOrButton(GO_LIGHTNING_FIELD); - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_SIFFED, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_LOSE_YOUR_ILLUSION, false); - DoUseDoorOrButton(GO_DARK_IRON_PORTCULIS); - } - if (uiData == DONE) - { - if(m_auiHardBoss[5] != DONE) + break; + case TYPE_AURIAYA: + m_auiEncounter[TYPE_AURIAYA] = uiData; + if (uiData == DONE) { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_CACHE_OF_STORMS, 30*MINUTE); - } - else + if (GameObject* pGO = GetSingleGameObjectFromStorage(GO_MIMIRON_TRAM)) { - DoRespawnGameObject(GO_CACHE_OF_STORMS_H, 30*MINUTE); + pGO->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGO->SetGoState(GO_STATE_READY); } } - // used to make the friendly keeper visible - if(Creature* pImage = GetSingleCreatureFromStorage(KEEPER_THORIM)) - pImage->SetVisibility(VISIBILITY_ON); - DoOpenMadnessDoorIfCan(); - } - break; - case TYPE_FREYA: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - { - // do this in order to see how many elders were alive and spawn the correct chest - // hard mode drop - if(m_auiHardBoss[6] != DONE) + break; + // Keepers + case TYPE_MIMIRON: + m_auiEncounter[TYPE_MIMIRON] = uiData; + DoUseDoorOrButton(GO_MIMIRON_DOOR_1); + DoUseDoorOrButton(GO_MIMIRON_DOOR_2); + DoUseDoorOrButton(GO_MIMIRON_DOOR_3); + if (uiData == DONE) { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_FREYA_GIFT, 30*MINUTE); - } - else - { - DoRespawnGameObject(GO_FREYA_GIFT_H, 30*MINUTE); - } + if(m_auiHardBoss[3] != DONE) + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_INOV : GO_CACHE_OF_INOV_H, 30*MINUTE); + // used to make the friendly keeper visible + if(Creature* pImage = GetSingleCreatureFromStorage(MIMIRON_IMAGE)) + pImage->SetVisibility(VISIBILITY_ON); + DoOpenMadnessDoorIfCan(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } - // used to make the friendly keeper visible - if(Creature* pImage = GetSingleCreatureFromStorage(KEEPER_FREYA)) - pImage->SetVisibility(VISIBILITY_ON); - DoOpenMadnessDoorIfCan(); - } - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_BACK_TO_NATURE, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_WOOD, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_KNOCK_WOOD, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_KNOCK_KNOCK_KNOCK_WOOD, false); - } - break; - // Prison - case TYPE_VEZAX: - m_auiEncounter[uiType] = uiData; - if (uiData == DONE) - DoUseDoorOrButton(GO_VEZAX_GATE); - if (uiData == IN_PROGRESS) - { - SetSpecialAchievementCriteria(TYPE_ACHIEV_MORNING_SARONITE, false); - } - break; - case TYPE_YOGGSARON: - m_auiEncounter[uiType] = uiData; - DoUseDoorOrButton(GO_YOGG_GATE); - if (uiData == IN_PROGRESS) - { - DoStartTimedAchievement(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEV_START_YOGG_SARON_ID); - SetSpecialAchievementCriteria(TYPE_ACHIEV_THREE_LIGHTS, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_TWO_LIGHTS, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_ONE_LIGHT, false); - SetSpecialAchievementCriteria(TYPE_ACHIEV_ALONE, false); - } - if (uiData == FAIL) - { - // respawn clouds - for(GUIDList::iterator iter = m_lCLoudGuids.begin(); iter != m_lCLoudGuids.end(); ++iter) - if (Creature *pTmp = instance->GetCreature(*iter)) - pTmp->Respawn(); - // respawn Sara - if(Creature* pSara = GetSingleCreatureFromStorage(NPC_SARA)) + break; + case TYPE_HODIR: + m_auiEncounter[TYPE_HODIR] = uiData; + DoUseDoorOrButton(GO_HODIR_ENTER); + if (uiData == DONE) { - if (!pSara->isAlive()) - pSara->Respawn(); - else - pSara->AI()->EnterEvadeMode(); + GetSingleGameObjectFromStorage(GO_HODIR_ICE_WALL)->SetGoState(GO_STATE_ACTIVE); + DoUseDoorOrButton(GO_HODIR_EXIT); + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_WINTER : GO_CACHE_OF_WINTER_H, 30*MINUTE); + // used to make the friendly keeper visible + if(Creature* pImage = GetSingleCreatureFromStorage(HODIR_IMAGE)) + pImage->SetVisibility(VISIBILITY_ON); + DoOpenMadnessDoorIfCan(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } - if (Creature* pYoggBrain = GetSingleCreatureFromStorage(NPC_YOGG_BRAIN)) + break; + case TYPE_THORIM: + m_auiEncounter[TYPE_THORIM] = uiData; + if (GameObject* pLever =GetSingleGameObjectFromStorage(GO_DOOR_LEVER)) { - if(!pYoggBrain->isAlive()) - pYoggBrain->Respawn(); - else - pYoggBrain->AI()->EnterEvadeMode(); + if (pLever->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT)) + pLever->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + if (pLever->getLootState() == GO_ACTIVATED) + pLever->SetGoState(GO_STATE_READY); } - } - break; - - // Celestial Planetarium - case TYPE_ALGALON: - m_auiEncounter[uiType] = uiData; - DoUseDoorOrButton(GO_CELESTIAL_DOOR); - DoUseDoorOrButton(GO_UNIVERSE_FLOOR_CELESTIAL); - if (uiData == DONE) - DoRespawnGameObject(GO_GIFT_OF_OBSERVER, 30*MINUTE); - break; + DoUseDoorOrButton(GO_LIGHTNING_FIELD); + if (uiData == IN_PROGRESS || uiData == NOT_STARTED) + DoUseDoorOrButton(GO_DARK_IRON_PORTCULIS); - // Hard modes - case TYPE_LEVIATHAN_HARD: - m_auiHardBoss[0] = uiData; - break; - case TYPE_XT002_HARD: - m_auiHardBoss[1] = uiData; - break; - case TYPE_ASSEMBLY_HARD: - m_auiHardBoss[2] = uiData; - break; - case TYPE_MIMIRON_HARD: - m_auiHardBoss[3] = uiData; - if(uiData == DONE) - { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_CACHE_OF_INOV_HARD, 30*MINUTE); - } - else - { - DoRespawnGameObject(GO_CACHE_OF_INOV_HARD_H, 30*MINUTE); - } - } - break; - case TYPE_HODIR_HARD: - m_auiHardBoss[4] = uiData; - if(uiData == DONE) - { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_CACHE_OF_RARE_WINTER, 30*MINUTE); - } - else - { - DoRespawnGameObject(GO_CACHE_OF_RARE_WINTER_H, 30*MINUTE); - } - } - break; - case TYPE_THORIM_HARD: - m_auiHardBoss[5] = uiData; - if(uiData == DONE) - { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_CACHE_OF_RARE_STORMS, 30*MINUTE); - } - else + if (uiData == DONE) { - DoRespawnGameObject(GO_CACHE_OF_RARE_STORMS_H, 30*MINUTE); - } - } - break; - case TYPE_FREYA_HARD: - m_auiHardBoss[6] = uiData; - if(uiData == DONE) - { - if (instance->IsRegularDifficulty()) - { - DoRespawnGameObject(GO_FREYA_GIFT_HARD, 30*MINUTE); + if(m_auiHardBoss[5] != DONE) + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_STORMS : GO_CACHE_OF_STORMS_H, 30*MINUTE); + // used to make the friendly keeper visible + if(Creature* pImage = GetSingleCreatureFromStorage(THORIM_IMAGE)) + pImage->SetVisibility(VISIBILITY_ON); + DoOpenMadnessDoorIfCan(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } - else + break; + case TYPE_FREYA: + m_auiEncounter[TYPE_FREYA] = uiData; + if (uiData == DONE) { - DoRespawnGameObject(GO_FREYA_GIFT_HARD_H, 30*MINUTE); + // do this in order to see how many elders were alive and spawn the correct chest + if(m_auiHardBoss[6] == 0) + DoRespawnGameObject(m_bRegular ? GO_FREYA_GIFT : GO_FREYA_GIFT_H, 30*MINUTE); + else if(m_auiHardBoss[6] == 1) + DoRespawnGameObject(m_bRegular ? GO_FREYA_GIFT_1 : GO_FREYA_GIFT_H_1, 30*MINUTE); + else if(m_auiHardBoss[6] == 2) + DoRespawnGameObject(m_bRegular ? GO_FREYA_GIFT_2 : GO_FREYA_GIFT_H_2, 30*MINUTE); + else if(m_auiHardBoss[6] == 3) + DoRespawnGameObject(m_bRegular ? GO_FREYA_GIFT_3 : GO_FREYA_GIFT_H_3, 30*MINUTE); + // used to make the friendly keeper visible + if(Creature* pImage = GetSingleCreatureFromStorage(FREYA_IMAGE)) + pImage->SetVisibility(VISIBILITY_ON); + DoOpenMadnessDoorIfCan(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } - } - break; - case TYPE_VEZAX_HARD: - m_auiHardBoss[7] = uiData; - break; - case TYPE_YOGGSARON_HARD: - m_auiHardBoss[8] = uiData; - break; + break; - // Ulduar keepers - case TYPE_KEEPER_HODIR: - m_auiUlduarKeepers[0] = uiData; - break; - case TYPE_KEEPER_THORIM: - m_auiUlduarKeepers[1] = uiData; - break; - case TYPE_KEEPER_FREYA: - m_auiUlduarKeepers[2] = uiData; - break; - case TYPE_KEEPER_MIMIRON: - m_auiUlduarKeepers[3] = uiData; - break; + // Prison + case TYPE_VEZAX: + m_auiEncounter[TYPE_VEZAX] = uiData; + if (uiData == DONE) + DoUseDoorOrButton(GO_VEZAX_GATE); + break; + case TYPE_YOGGSARON: + m_auiEncounter[TYPE_YOGGSARON] = uiData; + DoUseDoorOrButton(GO_YOGG_GATE); + break; - // teleporters - case TYPE_LEVIATHAN_TP: - m_auiUlduarTeleporters[0] = uiData; - break; - case TYPE_XT002_TP: - m_auiUlduarTeleporters[1] = uiData; - break; - case TYPE_MIMIRON_TP: - m_auiUlduarTeleporters[2] = uiData; - break; + // Celestial Planetarium + case TYPE_ALGALON: + m_auiEncounter[TYPE_ALGALON] = uiData; + DoUseDoorOrButton(GO_CELESTIAL_DOOR); + DoUseDoorOrButton(GO_UNIVERSE_FLOOR_CELESTIAL); + if (uiData == DONE) + DoRespawnGameObject(m_bRegular ? GO_GIFT_OF_OBSERVER : GO_GIFT_OF_OBSERVER_H, 30*MINUTE); + break; - // mini boss - case TYPE_RUNIC_COLOSSUS: - m_auiMiniBoss[0] = uiData; - if (uiData == DONE) - OpenDoor(GO_RUNED_STONE_DOOR); - else - CloseDoor(GO_RUNED_STONE_DOOR); - break; - case TYPE_RUNE_GIANT: - m_auiMiniBoss[1] = uiData; - if (uiData == DONE) - OpenDoor(GO_THORIM_STONE_DOOR); - else - CloseDoor(GO_THORIM_STONE_DOOR); - break; - case TYPE_LEVIATHAN_MK: - m_auiMiniBoss[2] = uiData; - break; - case TYPE_VX001: - m_auiMiniBoss[3] = uiData; - /*if (uiData == DONE) // just for animation :) - { - for(uint8 i = 0; i < 9; i++) - DoUseDoorOrButton(m_uiMimironTelGUID[i]); - }*/ - break; - case TYPE_AERIAL_UNIT: - m_auiMiniBoss[4] = uiData; - break; - case TYPE_YOGG_BRAIN: - m_auiMiniBoss[5] = uiData; - break; + // Hard modes + case TYPE_LEVIATHAN_HARD: + m_auiHardBoss[0] = uiData; // todo: add extra loot + break; + case TYPE_XT002_HARD: + m_auiHardBoss[1] = uiData; // hard mode loot in sql -> hacky way + break; + case TYPE_HODIR_HARD: + m_auiHardBoss[4] = uiData; + if(uiData == DONE) + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_RARE_WINTER : GO_CACHE_OF_RARE_WINTER_H, 30*MINUTE); + break; + case TYPE_ASSEMBLY_HARD: + m_auiHardBoss[2] = uiData; // hard mode loot in sql + break; + case TYPE_FREYA_HARD: + m_auiHardBoss[6] = uiData; // hard mode loot in the script above + break; + case TYPE_THORIM_HARD: + m_auiHardBoss[5] = uiData; + if(uiData == DONE) + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_RARE_STORMS : GO_CACHE_OF_RARE_STORMS_H, 30*MINUTE); + break; + case TYPE_MIMIRON_HARD: + m_auiHardBoss[3] = uiData; + if(uiData == DONE) + DoRespawnGameObject(m_bRegular ? GO_CACHE_OF_INOV_HARD : GO_CACHE_OF_INOV_HARD_H, 30*MINUTE); + break; + case TYPE_VEZAX_HARD: + m_auiHardBoss[7] = uiData; // hard mode loot in sql -> hacky way + break; + case TYPE_YOGGSARON_HARD: + m_auiHardBoss[8] = uiData; // todo: add extra loot + break; - //phases - case TYPE_MIMIRON_PHASE: - m_uiMimironPhase = uiData; - break; - case TYPE_YOGG_PHASE: - m_uiYoggPhase = uiData; - break; - case TYPE_VISION_PHASE: - m_uiVisionPhase = uiData; - break; - } + // Ulduar keepers + case TYPE_KEEPER_HODIR: + m_auiUlduarKeepers[0] = uiData; + break; + case TYPE_KEEPER_THORIM: + m_auiUlduarKeepers[1] = uiData; + break; + case TYPE_KEEPER_FREYA: + m_auiUlduarKeepers[2] = uiData; + break; + case TYPE_KEEPER_MIMIRON: + m_auiUlduarKeepers[3] = uiData; + break; - if (uiData == DONE || uiData == FAIL) - { - OUT_SAVE_INST_DATA; + // teleporters + case TYPE_LEVIATHAN_TP: + m_auiUlduarTeleporters[0] = uiData; + break; + case TYPE_XT002_TP: + m_auiUlduarTeleporters[1] = uiData; + break; + case TYPE_MIMIRON_TP: + m_auiUlduarTeleporters[2] = uiData; + break; - // save all encounters, hard bosses and keepers - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " - << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " - << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11] << " " - << m_auiEncounter[12] << " " << m_auiEncounter[13] << " " << m_auiHardBoss[0] << " " - << m_auiHardBoss[1] << " " << m_auiHardBoss[2] << " " << m_auiHardBoss[2] << " " - << m_auiHardBoss[4] << " " << m_auiHardBoss[5] << " " << m_auiHardBoss[6] << " " - << m_auiHardBoss[7] << " " << m_auiHardBoss[8] << " " << m_auiUlduarKeepers[0] << " " - << m_auiUlduarKeepers[1] << " " << m_auiUlduarKeepers[2] << " " << m_auiUlduarKeepers[3] << " " - << m_auiUlduarTeleporters[0] << " " << m_auiUlduarTeleporters[1] << " " << m_auiUlduarTeleporters[2]; + // mini boss + case TYPE_RUNIC_COLOSSUS: + m_auiMiniBoss[0] = uiData; + DoUseDoorOrButton(GO_RUNED_STONE_DOOR); + break; + case TYPE_RUNE_GIANT: + m_auiMiniBoss[1] = uiData; + DoUseDoorOrButton(GO_THORIM_STONE_DOOR); + break; + case TYPE_LEVIATHAN_MK: + m_auiMiniBoss[2] = uiData; + break; + case TYPE_VX001: + m_auiMiniBoss[3] = uiData; + if (uiData == DONE) // just for animation :) + { + DoUseDoorOrButton(GO_MIMIRON_TEL1); + DoUseDoorOrButton(GO_MIMIRON_TEL2); + DoUseDoorOrButton(GO_MIMIRON_TEL3); + DoUseDoorOrButton(GO_MIMIRON_TEL4); + DoUseDoorOrButton(GO_MIMIRON_TEL5); + DoUseDoorOrButton(GO_MIMIRON_TEL6); + DoUseDoorOrButton(GO_MIMIRON_TEL7); + DoUseDoorOrButton(GO_MIMIRON_TEL8); + DoUseDoorOrButton(GO_MIMIRON_TEL9); + } + break; + case TYPE_AERIAL_UNIT: + m_auiMiniBoss[4] = uiData; + break; + case TYPE_YOGG_BRAIN: + m_auiMiniBoss[5] = uiData; + break; - m_strInstData = saveStream.str(); + //phases + case TYPE_MIMIRON_PHASE: + m_uiMimironPhase = uiData; + break; + case TYPE_YOGG_PHASE: + m_uiYoggPhase = uiData; + break; + case TYPE_VISION_PHASE: + m_uiVisionPhase = uiData; + break; + } - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; + if (uiData == DONE || uiData == FAIL) + { + OUT_SAVE_INST_DATA; + + // save all encounters, hard bosses and keepers + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " + << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " + << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11] << " " + << m_auiEncounter[12] << " " << m_auiEncounter[13] << " " << m_auiHardBoss[0] << " " + << m_auiHardBoss[1] << " " << m_auiHardBoss[2] << " " << m_auiHardBoss[2] << " " + << m_auiHardBoss[4] << " " << m_auiHardBoss[5] << " " << m_auiHardBoss[6] << " " + << m_auiHardBoss[7] << " " << m_auiHardBoss[8] << " " << m_auiUlduarKeepers[0] << " " + << m_auiUlduarKeepers[1] << " " << m_auiUlduarKeepers[2] << " " << m_auiUlduarKeepers[3] << " " + << m_auiUlduarTeleporters[0] << " " << m_auiUlduarTeleporters[1] << " " << m_auiUlduarTeleporters[2]; + + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } } -} -void instance_ulduar::SetSpecialAchievementCriteria(uint32 uiType, bool bIsMet) -{ - if (uiType < MAX_SPECIAL_ACHIEV_CRITS) - m_abAchievCriteria[uiType] = bIsMet; -} -bool instance_ulduar::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/) -{ - switch (uiCriteriaId) + // TODO: implement all achievs here! + bool CheckAchievementCriteriaMeet(uint32 criteria_id, const Player *source) { - case ACHIEV_CRIT_SHATTERED: - case ACHIEV_CRIT_SHATTERED_H: - return m_abAchievCriteria[TYPE_ACHIEV_SHATTERED]; - case ACHIEV_CRIT_QUICK_SHAVE: - case ACHIEV_CRIT_QUICK_SHAVE_H: - return m_abAchievCriteria[TYPE_ACHIEV_QUICK_SHAVE]; - case ACHIEV_CRIT_IRON_DWARF_MEDIUM_RARE: - case ACHIEV_CRIT_IRON_DWARF_MEDIUM_RARE_H: - return m_abAchievCriteria[TYPE_ACHIEV_IRON_DWARF_MEDIUM_RARE]; - case ACHIEV_CRIT_NERF_ENGINEERING: - case ACHIEV_CRIT_NERF_ENGINEERING_H: - return m_abAchievCriteria[TYPE_ACHIEV_NERF_ENGINEERING]; - case ACHIEV_CRIT_HEARTBREAKER: - case ACHIEV_CRIT_HEARTBREAKER_H: - return m_abAchievCriteria[TYPE_ACHIEV_HEARTBREAKER]; - case ACHIEV_CRIT_YOU_BRUNDIR: - case ACHIEV_CRIT_YOU_BRUNDIR_H: - return m_abAchievCriteria[TYPE_ACHIEV_YOU_BRUNDIR]; - case ACHIEV_CRIT_YOU_MOLGEIM: - case ACHIEV_CRIT_YOU_MOLGEIM_H: - return m_abAchievCriteria[TYPE_ACHIEV_YOU_MOLGEIM]; - case ACHIEV_CRIT_YOU_STEELBREAKER: - case ACHIEV_CRIT_YOU_STEELBREAKER_H: - return m_abAchievCriteria[TYPE_ACHIEV_YOU_STEELBREAKER]; - case ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_BRUNDIR: - case ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_BRUNDIR_H: - case ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_MOLGEIM: - case ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_MOLGEIM_H: - case ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_STEELBREAKER: - case ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_STEELBREAKER_H: + switch(criteria_id) { - if (GetData(TYPE_ASSEMBLY) == DONE) - { - if (pSource->HasAura(SPELL_IRON_BOOT_AURA)) - return true; - } - } - case ACHIEV_CRIT_DISARMED: - case ACHIEV_CRIT_DISARMED_H: - return m_abAchievCriteria[TYPE_ACHIEV_DISARMED]; - case ACHIEV_CRIT_OPEN_ARMS: - case ACHIEV_CRIT_OPEN_ARMS_H: - return m_abAchievCriteria[TYPE_ACHIEV_OPEN_ARMS]; - case ACHIEV_CRIT_RUBBLE_AND_ROLL: - case ACHIEV_CRIT_RUBBLE_AND_ROLL_H: - return m_abAchievCriteria[TYPE_ACHIEV_RUBBLE_AND_ROLL]; - case ACHIEV_CRIT_NINE_LIVES: - case ACHIEV_CRIT_NINE_LIVES_H: - return m_abAchievCriteria[TYPE_ACHIEV_NINE_LIVES]; - case ACHIEV_CRIT_CRAZY_CAT_LADY: - case ACHIEV_CRIT_CRAZY_CAT_LADY_H: - return m_abAchievCriteria[TYPE_ACHIEV_CRAZY_CAT_LADY]; - case ACHIEV_CRIT_CHEESE_FREEZE: - case ACHIEV_CRIT_CHEESE_FREEZE_H: - return m_abAchievCriteria[TYPE_ACHIEV_CHEESE_FREEZE]; - case ACHIEV_CRIT_COOLEST_FRIEND: - case ACHIEV_CRIT_COOLEST_FRIEND_H: - return m_abAchievCriteria[TYPE_ACHIEV_COOLEST_FRIEND]; - case ACHIEV_CRIT_RARE_CACHE: - case ACHIEV_CRIT_RARE_CACHE_H: - return m_abAchievCriteria[TYPE_ACHIEV_RARE_CACHE]; - case ACHIEV_CRIT_SIFFED: - case ACHIEV_CRIT_SIFFED_H: - return m_abAchievCriteria[TYPE_ACHIEV_SIFFED]; - case ACHIEV_CRIT_LOSE_YOUR_ILLUSION: - case ACHIEV_CRIT_LOSE_YOUR_ILLUSION_H: - return m_abAchievCriteria[TYPE_ACHIEV_LOSE_YOUR_ILLUSION]; - case ACHIEV_CRIT_BACK_TO_NATURE: - case ACHIEV_CRIT_BACK_TO_NATURE_H: - return m_abAchievCriteria[TYPE_ACHIEV_BACK_TO_NATURE]; - case ACHIEV_CRIT_KNOCK_WOOD: - case ACHIEV_CRIT_KNOCK_WOOD_H: - return m_abAchievCriteria[TYPE_ACHIEV_KNOCK_WOOD]; - case ACHIEV_CRIT_KNOCK_KNOCK_WOOD: - case ACHIEV_CRIT_KNOCK_KNOCK_WOOD_H: - return m_abAchievCriteria[TYPE_ACHIEV_KNOCK_KNOCK_WOOD]; - case ACHIEV_CRIT_KNOCK_KNOCK_KNOCK_WOOD: - case ACHIEV_CRIT_KNOCK_KNOCK_KNOCK_WOOD_H: - return m_abAchievCriteria[TYPE_ACHIEV_KNOCK_KNOCK_KNOCK_WOOD]; - case ACHIEV_CRIT_FIREFIGHTER: - case ACHIEV_CRIT_FIREFIGHTER_H: - return m_abAchievCriteria[TYPE_ACHIEV_FIREFIGHTER]; - case ACHIEV_CRIT_SARONITE_N: - case ACHIEV_CRIT_SARONITE_H: - return m_abAchievCriteria[TYPE_ACHIEV_MORNING_SARONITE]; - case ACHIEV_CRIT_THREE_LIGHTS: - case ACHIEV_CRIT_THREE_LIGHTS_H: - return m_abAchievCriteria[TYPE_ACHIEV_THREE_LIGHTS]; - case ACHIEV_CRIT_TWO_LIGHTS: - case ACHIEV_CRIT_TWO_LIGHTS_H: - return m_abAchievCriteria[TYPE_ACHIEV_TWO_LIGHTS]; - case ACHIEV_CRIT_ONE_LIGHT: - case ACHIEV_CRIT_ONE_LIGHT_H: - return m_abAchievCriteria[TYPE_ACHIEV_ONE_LIGHT]; - case ACHIEV_CRIT_ALONE: - case ACHIEV_CRIT_ALONE_H: - return m_abAchievCriteria[TYPE_ACHIEV_ALONE]; - } - return false; -} + case ACHIEV_CRIT_SARONITE_N: + case ACHIEV_CRIT_SARONITE_H: + return GetData(TYPE_VEZAX_HARD) == DONE; -bool instance_ulduar::CheckConditionCriteriaMeet(Player const* source, uint32 map_id, uint32 instance_condition_id) -{ - if (map_id != instance->GetId()) + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + break; + } return false; + } - if (GetData(instance_condition_id) == DONE) + // TODO: implement all hard mode loot here! + bool CheckConditionCriteriaMeet(Player const* source, uint32 map_id, uint32 instance_condition_id) + { + if (map_id != instance->GetId()) + return false; + switch (instance_condition_id) + { + case TYPE_XT002_HARD: + break; + } return true; + } - return false; -} - -void instance_ulduar::Update(uint32 uiDiff) -{ - if (m_bOneIsDeath) + uint32 GetData(uint32 uiType) { - if (m_uiShatterTimer < uiDiff) + switch(uiType) { - m_bOneIsDeath = false; + case TYPE_LEVIATHAN: + return m_auiEncounter[0]; + case TYPE_IGNIS: + return m_auiEncounter[1]; + case TYPE_RAZORSCALE: + return m_auiEncounter[2]; + case TYPE_XT002: + return m_auiEncounter[3]; + case TYPE_ASSEMBLY: + return m_auiEncounter[4]; + case TYPE_KOLOGARN: + return m_auiEncounter[5]; + case TYPE_AURIAYA: + return m_auiEncounter[6]; + case TYPE_MIMIRON: + return m_auiEncounter[7]; + case TYPE_HODIR: + return m_auiEncounter[8]; + case TYPE_THORIM: + return m_auiEncounter[9]; + case TYPE_FREYA: + return m_auiEncounter[10]; + case TYPE_VEZAX: + return m_auiEncounter[11]; + case TYPE_YOGGSARON: + return m_auiEncounter[12]; + case TYPE_ALGALON: + return m_auiEncounter[13]; + + // hard modes + case TYPE_LEVIATHAN_HARD: + return m_auiHardBoss[0]; + case TYPE_XT002_HARD: + return m_auiHardBoss[1]; + case TYPE_ASSEMBLY_HARD: + return m_auiHardBoss[2]; + case TYPE_MIMIRON_HARD: + return m_auiHardBoss[3]; + case TYPE_HODIR_HARD: + return m_auiHardBoss[4]; + case TYPE_THORIM_HARD: + return m_auiHardBoss[5]; + case TYPE_FREYA_HARD: + return m_auiHardBoss[6]; + case TYPE_VEZAX_HARD: + return m_auiHardBoss[7]; + case TYPE_YOGGSARON_HARD: + return m_auiHardBoss[8]; + + // ulduar keepers + case TYPE_KEEPER_HODIR: + return m_auiUlduarKeepers[0]; + case TYPE_KEEPER_THORIM: + return m_auiUlduarKeepers[1]; + case TYPE_KEEPER_FREYA: + return m_auiUlduarKeepers[2]; + case TYPE_KEEPER_MIMIRON: + return m_auiUlduarKeepers[3]; + + // teleporters + case TYPE_LEVIATHAN_TP: + return m_auiUlduarTeleporters[0]; + case TYPE_XT002_TP: + return m_auiUlduarTeleporters[1]; + case TYPE_MIMIRON_TP: + return m_auiUlduarTeleporters[2]; + + // mini boss + case TYPE_RUNE_GIANT: + return m_auiMiniBoss[1]; + case TYPE_RUNIC_COLOSSUS: + return m_auiMiniBoss[0]; + case TYPE_LEVIATHAN_MK: + return m_auiMiniBoss[2]; + case TYPE_VX001: + return m_auiMiniBoss[3]; + case TYPE_AERIAL_UNIT: + return m_auiMiniBoss[4]; + case TYPE_YOGG_BRAIN: + return m_auiMiniBoss[5]; + + case TYPE_MIMIRON_PHASE: + return m_uiMimironPhase; + case TYPE_YOGG_PHASE: + return m_uiYoggPhase; + case TYPE_VISION_PHASE: + return m_uiVisionPhase; } - else - m_uiShatterTimer -= uiDiff; + + return 0; } -} -uint32 instance_ulduar::GetData(uint32 uiType) -{ - switch(uiType) + const char* Save() { - case TYPE_LEVIATHAN: - return m_auiEncounter[0]; - case TYPE_IGNIS: - return m_auiEncounter[1]; - case TYPE_RAZORSCALE: - return m_auiEncounter[2]; - case TYPE_XT002: - return m_auiEncounter[3]; - case TYPE_ASSEMBLY: - return m_auiEncounter[4]; - case TYPE_KOLOGARN: - return m_auiEncounter[5]; - case TYPE_AURIAYA: - return m_auiEncounter[6]; - case TYPE_MIMIRON: - return m_auiEncounter[7]; - case TYPE_HODIR: - return m_auiEncounter[8]; - case TYPE_THORIM: - return m_auiEncounter[9]; - case TYPE_FREYA: - return m_auiEncounter[10]; - case TYPE_VEZAX: - return m_auiEncounter[11]; - case TYPE_YOGGSARON: - return m_auiEncounter[12]; - case TYPE_ALGALON: - return m_auiEncounter[13]; + return m_strInstData.c_str(); + } - // hard modes - case TYPE_LEVIATHAN_HARD: - return m_auiHardBoss[0]; - case TYPE_XT002_HARD: - return m_auiHardBoss[1]; - case TYPE_ASSEMBLY_HARD: - return m_auiHardBoss[2]; - case TYPE_MIMIRON_HARD: - return m_auiHardBoss[3]; - case TYPE_HODIR_HARD: - return m_auiHardBoss[4]; - case TYPE_THORIM_HARD: - return m_auiHardBoss[5]; - case TYPE_FREYA_HARD: - return m_auiHardBoss[6]; - case TYPE_VEZAX_HARD: - return m_auiHardBoss[7]; - case TYPE_YOGGSARON_HARD: - return m_auiHardBoss[8]; + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - // ulduar keepers - case TYPE_KEEPER_HODIR: - return m_auiUlduarKeepers[0]; - case TYPE_KEEPER_THORIM: - return m_auiUlduarKeepers[1]; - case TYPE_KEEPER_FREYA: - return m_auiUlduarKeepers[2]; - case TYPE_KEEPER_MIMIRON: - return m_auiUlduarKeepers[3]; + OUT_LOAD_INST_DATA(strIn); - // teleporters - case TYPE_LEVIATHAN_TP: - return m_auiUlduarTeleporters[0]; - case TYPE_XT002_TP: - return m_auiUlduarTeleporters[1]; - case TYPE_MIMIRON_TP: - return m_auiUlduarTeleporters[2]; + std::istringstream loadStream(strIn); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] + >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11] + >> m_auiEncounter[12] >> m_auiEncounter[13] >> m_auiHardBoss[0] >> m_auiHardBoss[1] + >> m_auiHardBoss[2] >> m_auiHardBoss[3] >> m_auiHardBoss[4] >> m_auiHardBoss[5] + >> m_auiHardBoss[6] >> m_auiHardBoss[7] >> m_auiHardBoss[8] >> m_auiUlduarKeepers[0] + >> m_auiUlduarKeepers[1] >> m_auiUlduarKeepers[2] >> m_auiUlduarKeepers[3] >> m_auiUlduarTeleporters[0] + >> m_auiUlduarTeleporters[1] >> m_auiUlduarTeleporters[2]; - // mini boss - case TYPE_RUNE_GIANT: - return m_auiMiniBoss[1]; - case TYPE_RUNIC_COLOSSUS: - return m_auiMiniBoss[0]; - case TYPE_LEVIATHAN_MK: - return m_auiMiniBoss[2]; - case TYPE_VX001: - return m_auiMiniBoss[3]; - case TYPE_AERIAL_UNIT: - return m_auiMiniBoss[4]; - case TYPE_YOGG_BRAIN: - return m_auiMiniBoss[5]; + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } - case TYPE_MIMIRON_PHASE: - return m_uiMimironPhase; - case TYPE_YOGG_PHASE: - return m_uiYoggPhase; - case TYPE_VISION_PHASE: - return m_uiVisionPhase; + OUT_LOAD_INST_DATA_COMPLETE; } - return 0; -} - -const char* instance_ulduar::Save() -{ - return m_strInstData.c_str(); -} - -void instance_ulduar::Load(const char* strIn) -{ - if (!strIn) + // Hacky way of completing some achievs + // PLEASE REMOVE FOR REVISION! + void CheckIronCouncil() { - OUT_LOAD_INST_DATA_FAIL; - return; + // check if the other bosses in the antechamber are dead + // hacky way to complete achievements; use only if you have this function + if(m_auiEncounter[4] == DONE && m_auiEncounter[5] == DONE && m_auiEncounter[6] == DONE) + DoCompleteAchievement(instance->IsRegularDifficulty() ? ACHIEV_IRON_COUNCIL : ACHIEV_IRON_COUNCIL_H); } - OUT_LOAD_INST_DATA(strIn); - - std::istringstream loadStream(strIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] - >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11] - >> m_auiEncounter[12] >> m_auiEncounter[13] >> m_auiHardBoss[0] >> m_auiHardBoss[1] - >> m_auiHardBoss[2] >> m_auiHardBoss[3] >> m_auiHardBoss[4] >> m_auiHardBoss[5] - >> m_auiHardBoss[6] >> m_auiHardBoss[7] >> m_auiHardBoss[8] >> m_auiUlduarKeepers[0] - >> m_auiUlduarKeepers[1] >> m_auiUlduarKeepers[2] >> m_auiUlduarKeepers[3] >> m_auiUlduarTeleporters[0] - >> m_auiUlduarTeleporters[1] >> m_auiUlduarTeleporters[2]; - - for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + void CheckKeepers() { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + // check if the other bosses in the antechamber are dead + // hacky way to complete achievements; use only if you have this function + if(m_auiEncounter[7] == DONE && m_auiEncounter[8] == DONE && m_auiEncounter[9] == DONE && m_auiEncounter[10] == DONE) + DoCompleteAchievement(instance->IsRegularDifficulty() ? ACHIEV_KEEPERS : ACHIEV_KEEPERS_H); } - - OUT_LOAD_INST_DATA_COMPLETE; -} +}; InstanceData* GetInstanceData_instance_ulduar(Map* pMap) { @@ -1095,7 +771,6 @@ InstanceData* GetInstanceData_instance_ulduar(Map* pMap) void AddSC_instance_ulduar() { Script *newscript; - newscript = new Script; newscript->Name = "instance_ulduar"; newscript->GetInstanceData = &GetInstanceData_instance_ulduar; diff --git a/scripts/northrend/ulduar/ulduar/ulduar.cpp b/scripts/northrend/ulduar/ulduar/ulduar.cpp index f3cf83cd60..054c4484ce 100644 --- a/scripts/northrend/ulduar/ulduar/ulduar.cpp +++ b/scripts/northrend/ulduar/ulduar/ulduar.cpp @@ -15,8 +15,8 @@ */ /* ScriptData -SDName: ulduar -SD%Complete: 0% +SDName: Ulduar teleport +SD%Complete: SDComment: SDCategory: Ulduar EndScriptData */ @@ -42,7 +42,7 @@ EndScriptData */ // HODIR bool GossipHello_hodir_image(Player* pPlayer, Creature* pCreature) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_HODIR) != DONE && m_pInstance->GetData(TYPE_KEEPER_HODIR) != FAIL) { @@ -56,7 +56,7 @@ bool GossipHello_hodir_image(Player* pPlayer, Creature* pCreature) bool GossipSelect_hodir_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); pPlayer->CLOSE_GOSSIP_MENU(); if (uiAction == GOSSIP_ACTION_INFO_DEF+1) @@ -75,7 +75,7 @@ bool GossipSelect_hodir_image(Player* pPlayer, Creature* pCreature, uint32 uiSen // FREYA bool GossipHello_freya_image(Player* pPlayer, Creature* pCreature) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_FREYA) != DONE && m_pInstance->GetData(TYPE_KEEPER_FREYA) != FAIL) { @@ -89,7 +89,7 @@ bool GossipHello_freya_image(Player* pPlayer, Creature* pCreature) bool GossipSelect_freya_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); pPlayer->CLOSE_GOSSIP_MENU(); if (uiAction == GOSSIP_ACTION_INFO_DEF+1) @@ -107,7 +107,7 @@ bool GossipSelect_freya_image(Player* pPlayer, Creature* pCreature, uint32 uiSen // MIMIRON bool GossipHello_mimiron_image(Player* pPlayer, Creature* pCreature) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_MIMIRON) != DONE && m_pInstance->GetData(TYPE_KEEPER_MIMIRON) != FAIL) { @@ -121,7 +121,7 @@ bool GossipHello_mimiron_image(Player* pPlayer, Creature* pCreature) bool GossipSelect_mimiron_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); pPlayer->CLOSE_GOSSIP_MENU(); if (uiAction == GOSSIP_ACTION_INFO_DEF+1) @@ -140,7 +140,7 @@ bool GossipSelect_mimiron_image(Player* pPlayer, Creature* pCreature, uint32 uiS // THORIM bool GossipHello_thorim_image(Player* pPlayer, Creature* pCreature) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_THORIM) != DONE && m_pInstance->GetData(TYPE_KEEPER_THORIM) != FAIL) { @@ -154,7 +154,7 @@ bool GossipHello_thorim_image(Player* pPlayer, Creature* pCreature) bool GossipSelect_thorim_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { - instance_ulduar *m_pInstance = (instance_ulduar *) pCreature->GetInstanceData(); + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); pPlayer->CLOSE_GOSSIP_MENU(); if (uiAction == GOSSIP_ACTION_INFO_DEF+1) @@ -170,124 +170,32 @@ bool GossipSelect_thorim_image(Player* pPlayer, Creature* pCreature, uint32 uiSe return true; } -/*##### -## Teleporters -#####*/ - -enum TeleportParams -{ - PORTALS_COUNT = 9, - TELEPORT_GOSSIP_MESSAGE = 14424, - - // spells - SPELL_TELEPORT_BASE_CAMP = 64014, - SPELL_TELEPORT_GROUNDS = 64032, - SPELL_TELEPORT_FORGE = 64028, - SPELL_TELEPORT_SCRAPYARD = 64031, - SPELL_TELEPORT_ANTECHAMBER = 64030, - SPELL_TELEPORT_WALKWAY = 64029, - SPELL_TELEPORT_CONSERVATORY = 64024, - SPELL_TELEPORT_SPARK = 65061, - SPELL_TELEPORT_PRISON = 65042, -}; - -struct t_Locations -{ - int textNum; - uint32 map_num; - float x, y, z, o; - uint32 spellID; - bool state; - bool active; - uint32 encounter; -}; - -static t_Locations PortalLoc[]= -{ -{-3050001,603, -706.122f, -92.6024f, 430.176f, 4.19f, SPELL_TELEPORT_BASE_CAMP, true,true, TYPE_LEVIATHAN}, // base camp -{-3050002,603, 131.248f, -35.3802f, 410.104f, 0, SPELL_TELEPORT_GROUNDS, true,true, TYPE_LEVIATHAN_TP}, // formation ground -{-3050003,603, 553.233f, -12.3247f, 409.979f, 0, SPELL_TELEPORT_FORGE, false,true,TYPE_LEVIATHAN}, // -{-3050004,603, 926.292f, -11.4635f, 418.895f, 3.19f, SPELL_TELEPORT_SCRAPYARD, false,true,TYPE_XT002_TP}, // -{-3050005,603, 1498.09f, -24.246f, 421.267f, 0, SPELL_TELEPORT_ANTECHAMBER, false,true,TYPE_XT002}, // -{-3050006,603, 1859.45f, -24.1f, 449.2f, 0, SPELL_TELEPORT_WALKWAY, false,true,TYPE_KOLOGARN}, // -{-3050007,603, 2086.27f, -24.3134f, 421.539f, 0, SPELL_TELEPORT_CONSERVATORY,false,true,TYPE_AURIAYA}, // -{-3050008,603, 2517.3979f, 2568.89f, 412.99f, 6.17f, SPELL_TELEPORT_SPARK, false,true,TYPE_MIMIRON_TP}, // -{-3050009,603, 1854.782f, -11.3819f, 335.27f, 5.86f, SPELL_TELEPORT_PRISON, false,true,TYPE_VEZAX}, // -}; - - -bool GossipSelect_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo, uint32 sender, uint32 action) -{ - int32 damage = 0; - if(sender != GOSSIP_SENDER_MAIN) return false; - - if(pPlayer->IsInCombat()) - return false; - - if(action >= 0 && action <= PORTALS_COUNT) - pPlayer->TeleportTo(PortalLoc[action].map_num, PortalLoc[action].x, PortalLoc[action].y, PortalLoc[action].z, PortalLoc[action].o); - if (PortalLoc[action].spellID != 0 ) - if (SpellEntry const* spell = (SpellEntry *)GetSpellStore()->LookupEntry(PortalLoc[action].spellID)) - { - SpellAuraHolderPtr holder = CreateSpellAuraHolder(spell, pPlayer, pPlayer); - Aura* aura = holder->CreateAura(AURA_CLASS_AURA, EFFECT_INDEX_2, NULL, holder, pPlayer, pPlayer, NULL); - pPlayer->AddSpellAuraHolder(holder); - } - - pPlayer->CLOSE_GOSSIP_MENU(); - return true; -} - -bool GossipHello_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo) -{ - ScriptedInstance *pInstance = (ScriptedInstance *) pGo->GetInstanceData(); - - if (!pInstance || !pPlayer) return false; - if (pPlayer->isInCombat()) return true; - - for(uint8 i = 0; i < PORTALS_COUNT; i++) { - if ((PortalLoc[i].active == true && - (PortalLoc[i].state == true || - pInstance->GetData(PortalLoc[i].encounter) == DONE || - pInstance->GetData(PortalLoc[i].encounter) == IN_PROGRESS)) - || pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_TAXI, PortalLoc[i].textNum, GOSSIP_SENDER_MAIN, i); - }; - pPlayer->SEND_GOSSIP_MENU(TELEPORT_GOSSIP_MESSAGE, pGo->GetObjectGuid()); - return true; -} - void AddSC_ulduar() { - Script *pNewScript; - - pNewScript = new Script; - pNewScript->Name = "hodir_image"; - pNewScript->pGossipHello = &GossipHello_hodir_image; - pNewScript->pGossipSelect = &GossipSelect_hodir_image; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "freya_image"; - pNewScript->pGossipHello = &GossipHello_freya_image; - pNewScript->pGossipSelect = &GossipSelect_freya_image; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "thorim_image"; - pNewScript->pGossipHello = &GossipHello_thorim_image; - pNewScript->pGossipSelect = &GossipSelect_thorim_image; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mimiron_image"; - pNewScript->pGossipHello = &GossipHello_mimiron_image; - pNewScript->pGossipSelect = &GossipSelect_mimiron_image; - pNewScript->RegisterSelf(); + Script *newscript; + + newscript = new Script; + newscript->Name = "hodir_image"; + newscript->pGossipHello = &GossipHello_hodir_image; + newscript->pGossipSelect = &GossipSelect_hodir_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "freya_image"; + newscript->pGossipHello = &GossipHello_freya_image; + newscript->pGossipSelect = &GossipSelect_freya_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "thorim_image"; + newscript->pGossipHello = &GossipHello_thorim_image; + newscript->pGossipSelect = &GossipSelect_thorim_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mimiron_image"; + newscript->pGossipHello = &GossipHello_mimiron_image; + newscript->pGossipSelect = &GossipSelect_mimiron_image; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "go_ulduar_teleporter"; - pNewScript->pGossipHelloGO = &GossipHello_go_ulduar_teleporter; - pNewScript->pGossipSelectGO = &GossipSelect_go_ulduar_teleporter; - pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/ulduar.h b/scripts/northrend/ulduar/ulduar/ulduar.h index 652655fc18..e72a6130d2 100644 --- a/scripts/northrend/ulduar/ulduar/ulduar.h +++ b/scripts/northrend/ulduar/ulduar/ulduar.h @@ -1,6 +1,6 @@ /* Copyright (C) 2006 - 2011 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ #ifndef DEF_ULDUAR_H #define DEF_ULDUAR_H @@ -9,10 +9,8 @@ enum { // encounters MAX_ENCOUNTER = 14, - HARD_MODE_ENCOUNTER = 9, + HARD_ENCOUNTER = 9, KEEPER_ENCOUNTER = 4, - FREYA_ELDERS_ENCOUNTER = 3, - TELEPORTER_ENCOUNTER = 3, // boss types TYPE_LEVIATHAN = 0, @@ -37,21 +35,20 @@ enum TYPE_MIMIRON_HARD = 40, TYPE_HODIR_HARD = 41, TYPE_THORIM_HARD = 42, - TYPE_FREYA_HARD = 43, // this means 3 elders up + TYPE_FREYA_HARD = 43, TYPE_VEZAX_HARD = 44, TYPE_YOGGSARON_HARD = 45, - TYPE_YOGGSARON_HARD_4 = 46, // keepers help at Yogg - TYPE_KEEPER_HODIR = 47, - TYPE_KEEPER_FREYA = 48, - TYPE_KEEPER_THORIM = 49, - TYPE_KEEPER_MIMIRON = 50, + TYPE_KEEPER_HODIR = 46, + TYPE_KEEPER_FREYA = 47, + TYPE_KEEPER_THORIM = 48, + TYPE_KEEPER_MIMIRON = 49, // teleporters - TYPE_LEVIATHAN_TP = 51, - TYPE_XT002_TP = 52, - TYPE_MIMIRON_TP = 53, + TYPE_LEVIATHAN_TP = 50, + TYPE_XT002_TP = 51, + TYPE_MIMIRON_TP = 52, //other-> these won't be saved to db TYPE_RUNE_GIANT = 14, @@ -67,7 +64,6 @@ enum // siege NPC_LEVIATHAN = 33113, NPC_IGNIS = 33118, - NPC_IRON_CONSTRUCT = 33121, NPC_RAZORSCALE = 33186, NPC_COMMANDER = 33210, NPC_XT002 = 33293, @@ -82,42 +78,27 @@ enum NPC_AURIAYA = 33515, NPC_SANCTUM_SENTRY = 34014, NPC_FERAL_DEFENDER = 34035, - // Mimiron + // keepers NPC_MIMIRON = 33350, NPC_LEVIATHAN_MK = 33432, NPC_VX001 = 33651, NPC_AERIAL_UNIT = 33670, - // Hodir NPC_HODIR = 32845, - NPC_HELPER_DRUID = 32941, - NPC_HELPER_SHAMAN = 32950, - NPC_HELPER_MAGE = 32946, - NPC_HELPER_PRIEST = 32948, - // Thorim NPC_THORIM = 32865, NPC_RUNIC_COLOSSUS = 32872, - NPC_RIGHT_HAND_TRIGGER = 33140, - NPC_LEFT_HAND_TRIGGER = 33141, NPC_RUNE_GIANT = 32873, NPC_JORMUNGAR_BEHEMOTH = 32882, - NPC_CAPTAIN_ALY = 32908, - NPC_CAPTAIN_HORDE = 32907, - NPC_MERCENARY_ALY = 32885, - NPC_MERCENARY_HORDE = 32883, - // Freya NPC_FREYA = 32906, NPC_BRIGHTLEAF = 32915, NPC_IRONBRACH = 32913, NPC_STONEBARK = 32914, - // Madness + // madness NPC_VEZAX = 33271, NPC_ANIMUS = 33524, NPC_YOGGSARON = 33288, NPC_ALGALON = 32871, NPC_SARA = 33134, NPC_YOGG_BRAIN = 33890, - NPC_OMINOUS_CLOUD = 33292, - // keepers images used to start the encounter THORIM_IMAGE = 33413, MIMIRON_IMAGE = 33412, @@ -132,7 +113,7 @@ enum // loot chests // Kologarn GO_CACHE_OF_LIVING_STONE = 195046, - GO_CACHE_OF_LIVING_STONE_H = 195047, + GO_CACHE_OF_LIVING_STONE_H = 195047, // Hodir GO_CACHE_OF_WINTER = 194307, GO_CACHE_OF_WINTER_H = 194308, @@ -141,19 +122,23 @@ enum // Thorim GO_CACHE_OF_STORMS = 194312, GO_CACHE_OF_RARE_STORMS = 194313, - GO_CACHE_OF_STORMS_H = 194315, - GO_CACHE_OF_RARE_STORMS_H = 194314, + GO_CACHE_OF_STORMS_H = 194314, + GO_CACHE_OF_RARE_STORMS_H = 194315, // Alagon GO_GIFT_OF_OBSERVER_H = 194821, GO_GIFT_OF_OBSERVER = 194822, GO_GIFT_OF_OBSERVER_HH = 194823, // unk - // Freya -> each chest is for a mode + // Freya -> each chest is for a mode = more elders alive = more items in chest // 10 man GO_FREYA_GIFT = 194324,//10 normal - GO_FREYA_GIFT_HARD = 194327,//10 3 elders + GO_FREYA_GIFT_1 = 194325,//10 1 elder + GO_FREYA_GIFT_2 = 194326,//10 2 elders + GO_FREYA_GIFT_3 = 194327,//10 3 elders // 25 man GO_FREYA_GIFT_H = 194328,//25 normal - GO_FREYA_GIFT_HARD_H = 194331,//25 3 elders + GO_FREYA_GIFT_H_1 = 194329,//25 1 elder + GO_FREYA_GIFT_H_2 = 194330,//25 2 elder + GO_FREYA_GIFT_H_3 = 194331,//25 3 elders // Mimiron GO_CACHE_OF_INOV = 194789, GO_CACHE_OF_INOV_H = 194956, @@ -162,7 +147,6 @@ enum // doors // the siege - GO_LIGHTNING_DOOR = 194905, GO_SHIELD_WALL = 194416, GO_LEVIATHAN_GATE = 194630, GO_XT002_GATE = 194631, @@ -205,6 +189,7 @@ enum GO_DARK_IRON_PORTCULIS = 194560, GO_RUNED_STONE_DOOR = 194557, GO_THORIM_STONE_DOOR = 194558, + GO_LIGHTNING_DOOR = 194905, GO_LIGHTNING_FIELD = 194559, GO_DOOR_LEVER = 194264, //Yogg @@ -215,12 +200,6 @@ enum GO_BRAIN_DOOR2 = 194636, GO_BRAIN_DOOR3 = 194637, - //Tower - GO_TOWER_OF_FROST = 194370, - GO_TOWER_OF_FLAME = 194371, - GO_TOWER_OF_LIFE = 194375, - GO_TOWER_OF_STORMS = 194377, - ACHIEV_IRON_COUNCIL = 2888, ACHIEV_IRON_COUNCIL_H = 2889, @@ -231,194 +210,13 @@ enum SPELL_ALGALON_ACHIEV_TRIGG = 65184, ACHIEV_DEATHS_DEMISE = 3117, // realm first yogg + // Achievement related + ACHIEV_CRIT_SARONITE_N = 10451, // General Vezax, achievs 3181, 3188 + ACHIEV_CRIT_SARONITE_H = 10462, + // World state used for algalon timer WORLD_STATE_TIMER = 4132, WORLD_STATE_TIMER_COUNT = 4131, - - // achievements - MAX_SPECIAL_ACHIEV_CRITS = 28, - - TYPE_ACHIEV_SHATTERED = 0, - TYPE_ACHIEV_QUICK_SHAVE = 1, - TYPE_ACHIEV_IRON_DWARF_MEDIUM_RARE = 2, - TYPE_ACHIEV_NERF_ENGINEERING= 3, - TYPE_ACHIEV_HEARTBREAKER = 4, - TYPE_ACHIEV_YOU_BRUNDIR = 5, - TYPE_ACHIEV_YOU_MOLGEIM = 6, - TYPE_ACHIEV_YOU_STEELBREAKER= 7, - TYPE_ACHIEV_DISARMED = 8, - TYPE_ACHIEV_OPEN_ARMS = 9, - TYPE_ACHIEV_RUBBLE_AND_ROLL = 10, - TYPE_ACHIEV_NINE_LIVES = 11, - TYPE_ACHIEV_CRAZY_CAT_LADY = 12, - TYPE_ACHIEV_CHEESE_FREEZE = 13, // Hodir - TYPE_ACHIEV_COOLEST_FRIEND = 14, - TYPE_ACHIEV_RARE_CACHE = 15, - TYPE_ACHIEV_SIFFED = 16, //Thorim - TYPE_ACHIEV_LOSE_YOUR_ILLUSION = 17, - TYPE_ACHIEV_BACK_TO_NATURE = 18, // Freya - TYPE_ACHIEV_KNOCK_WOOD = 19, - TYPE_ACHIEV_KNOCK_KNOCK_WOOD= 20, - TYPE_ACHIEV_KNOCK_KNOCK_KNOCK_WOOD = 21, - TYPE_ACHIEV_FIREFIGHTER = 22, - TYPE_ACHIEV_MORNING_SARONITE= 23, - TYPE_ACHIEV_THREE_LIGHTS = 24, - TYPE_ACHIEV_TWO_LIGHTS = 25, - TYPE_ACHIEV_ONE_LIGHT = 26, - TYPE_ACHIEV_ALONE = 27, - - ACHIEV_CRIT_SHATTERED = 10068, // Ignis, achievs 2925, 2926 - ACHIEV_CRIT_SHATTERED_H = 10069, - ACHIEV_CRIT_QUICK_SHAVE = 10062, // Razorscale, achievs 2919, 2921 - ACHIEV_CRIT_QUICK_SHAVE_H = 10063, - ACHIEV_CRIT_IRON_DWARF_MEDIUM_RARE = 10066, // Razorscale, achievs 2923, 2924 - ACHIEV_CRIT_IRON_DWARF_MEDIUM_RARE_H = 10067, - ACHIEV_CRIT_NERF_ENGINEERING = 10074, // XT-002 Deconstructor, achievs 2931, 2932 - ACHIEV_CRIT_NERF_ENGINEERING_H = 10075, - ACHIEV_CRIT_HEARTBREAKER = 10221, // XT-002 Deconstructor, achievs 3058, 3059 - ACHIEV_CRIT_HEARTBREAKER_H = 10220, - - ACHIEV_CRIT_YOU_BRUNDIR = 10083, // Iron Council, achievs 2940, 2943 - ACHIEV_CRIT_YOU_BRUNDIR_H = 10086, - ACHIEV_CRIT_YOU_MOLGEIM = 10082, // Iron Council, achievs 2939, 2942 - ACHIEV_CRIT_YOU_MOLGEIM_H = 10085, - ACHIEV_CRIT_YOU_STEELBREAKER = 10084, // Iron Council, achievs 2941, 2944 - ACHIEV_CRIT_YOU_STEELBREAKER_H = 10087, - ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_BRUNDIR = 10418, // Iron Council, achiev 2945 - ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_MOLGEIM = 10088, - ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_STEELBREAKER = 10419, - ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_BRUNDIR_H = 10089, // Iron Council, achiev 2946 - ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_MOLGEIM_H = 10421, - ACHIEV_CRIT_BUT_I_AM_ON_YOUR_SIDE_STEELBREAKER_H = 10420, - // Kologarn - ACHIEV_CRIT_DISARMED = 10284, // achiev 2953 - ACHIEV_CRIT_DISARMED_H = 10722, // achiev 2954 - ACHIEV_CRIT_OPEN_ARMS = 10285, // achiev 2951 - ACHIEV_CRIT_OPEN_ARMS_H = 10095, // achiev 2952 - ACHIEV_CRIT_RUBBLE_AND_ROLL = 10290, // achiev 2959 - ACHIEV_CRIT_RUBBLE_AND_ROLL_H= 10133, // achiev 2960 - // Auriaya - ACHIEV_CRIT_NINE_LIVES = 10399, // achiev 3076 - ACHIEV_CRIT_NINE_LIVES_H = 10243, // achiev 3077 - ACHIEV_CRIT_CRAZY_CAT_LADY = 10400, // achiev 3006 - ACHIEV_CRIT_CRAZY_CAT_LADY_H= 10184, // achiev 3007 - // Hodir - ACHIEV_CRIT_CHEESE_FREEZE = 10259, // achiev 2961 - ACHIEV_CRIT_CHEESE_FREEZE_H = 10261, // achiev 2962 - ACHIEV_CRIT_COOLEST_FRIEND = 10258, // achiev 2963 - ACHIEV_CRIT_COOLEST_FRIEND_H= 10260, // achiev 2965 - ACHIEV_CRIT_RARE_CACHE = 10452, // achiev 3182 - ACHIEV_CRIT_RARE_CACHE_H = 10458, // achiev 3184 - //Thorim - ACHIEV_CRIT_SIFFED = 10289, // achiev 2977 - ACHIEV_CRIT_SIFFED_H = 10314, // achiev 2978 - ACHIEV_CRIT_LOSE_YOUR_ILLUSION = 10440, // achiev 3176 - ACHIEV_CRIT_LOSE_YOUR_ILLUSION_H = 10457, // achiev 3183 - // Freya - ACHIEV_CRIT_BACK_TO_NATURE = 10445, // achiev 2982 - ACHIEV_CRIT_BACK_TO_NATURE_H = 10758, // achiev 2983 - ACHIEV_CRIT_KNOCK_WOOD = 10447, // achiev 3177 - ACHIEV_CRIT_KNOCK_WOOD_H = 10459, // achiev 3185 - ACHIEV_CRIT_KNOCK_KNOCK_WOOD = 10448, // achiev 3178 - ACHIEV_CRIT_KNOCK_KNOCK_WOOD_H = 10460, // achiev 3186 - ACHIEV_CRIT_KNOCK_KNOCK_KNOCK_WOOD = 10449, // achiev 3179 - ACHIEV_CRIT_KNOCK_KNOCK_KNOCK_WOOD_H= 10461, // achiev 3187 - // Mimiron - ACHIEV_CRIT_FIREFIGHTER = 10450, // achiev 3180 - ACHIEV_CRIT_FIREFIGHTER_H = 10463, // achiev 3189 - // Vezax - ACHIEV_CRIT_SARONITE_N = 10451, // General Vezax, achievs 3181, 3188 - ACHIEV_CRIT_SARONITE_H = 10462, - // Yogg - ACHIEV_CRIT_THREE_LIGHTS = 10410, // achiev 3157 - ACHIEV_CRIT_THREE_LIGHTS_H = 10414, // achiev 3161 - ACHIEV_CRIT_TWO_LIGHTS = 10388, // achiev 3141 - ACHIEV_CRIT_TWO_LIGHTS_H = 10415, // achiev 3162 - ACHIEV_CRIT_ONE_LIGHT = 10409, // achiev 3158 - ACHIEV_CRIT_ONE_LIGHT_H = 10416, // achiev 3163 - ACHIEV_CRIT_ALONE = 10412, // achiev 3159 - ACHIEV_CRIT_ALONE_H = 10417, // achiev 3164 - - - // Timed achievement criterias - ACHIEV_START_IGNIS_ID = 20951, - ACHIEV_START_XT_002_ID = 21027, - ACHIEV_START_YOGG_SARON_ID = 21001, - - // Special Auras for Achievments - SPELL_IRON_BOOT_AURA = 58501, - - -}; - -class MANGOS_DLL_DECL instance_ulduar : public ScriptedInstance -{ - public: - instance_ulduar(Map* pMap); - ~instance_ulduar() {} - - void Initialize(); - bool IsEncounterInProgress() const; - - void OnCreatureCreate(Creature* pCreature); - void OnCreatureDeath(Creature * pCreature); - void OnObjectCreate(GameObject* pGo); - - void SetData(uint32 uiType, uint32 uiData); - uint32 GetData(uint32 uiType); - - const char* Save(); - void Load(const char* chrIn); - - void Update(uint32 uiDiff); - - // Dummy, leave till correct solution for hardmode found - bool CheckConditionCriteriaMeet(Player const* pSource, uint32 uiMapId, uint32 uiInstanceConditionId); - - void SetSpecialAchievementCriteria(uint32 uiType, bool bIsMet); - bool CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/); - - void OpenDoor(uint32 uiEntry); - void CloseDoor(uint32 uiEntry); - void DoOpenMadnessDoorIfCan(); - void OpenXtDoor(); - void CheckIronCouncil(); - void CheckKeepers(); - void SpawnFriendlyKeeper(uint32 uiWho); - - GUIDList m_lThorimMobsGuids; - GUIDList m_lLeftHandTriggerGuids; - GUIDList m_lRightHandTriggerGuids; - GUIDList m_lSanctumSentryGuids; - GUIDList m_lCLoudGuids; - - - GUIDVector m_lBreakHarpoonGUID; - - - protected: - - - // initialize the encouter variables - std::string m_strInstData; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 m_auiHardBoss[HARD_MODE_ENCOUNTER]; - uint32 m_auiUlduarKeepers[KEEPER_ENCOUNTER]; - uint32 m_auiUlduarTeleporters[3]; - uint32 m_auiMiniBoss[6]; - - // boss phases which need to be used inside the instance script - uint32 m_uiMimironPhase; - uint32 m_uiYoggPhase; - uint32 m_uiVisionPhase; - - bool m_abAchievCriteria[MAX_SPECIAL_ACHIEV_CRITS]; - - uint32 m_uiShatterTimer; // Ignis Achievement - bool m_bOneIsDeath; - - - GUIDList m_lIronConstructsGuids; }; #endif diff --git a/scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp b/scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp new file mode 100644 index 0000000000..e0ad4b242d --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp @@ -0,0 +1,119 @@ +/* Copyright (C) 2006 - 2011 ScriptDev2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: ulduar_teleport +SD%Complete: 95% +SDComment: by /dev/rsa +SDCategory: Ulduar instance +EndScriptData */ + +#include "precompiled.h" +#include "ulduar.h" + +enum +{ + PORTALS_COUNT = 9, + TELEPORT_GOSSIP_MESSAGE = 14424, + + // spells + SPELL_TELEPORT_BASE_CAMP = 64014, + SPELL_TELEPORT_GROUNDS = 64032, + SPELL_TELEPORT_FORGE = 64028, + SPELL_TELEPORT_SCRAPYARD = 64031, + SPELL_TELEPORT_ANTECHAMBER = 64030, + SPELL_TELEPORT_WALKWAY = 64029, + SPELL_TELEPORT_CONSERVATORY = 64024, + SPELL_TELEPORT_SPARK = 65061, + SPELL_TELEPORT_PRISON = 65042, +}; + +struct t_Locations +{ + int textNum; + uint32 map_num; + float x, y, z, o; + uint32 spellID; + bool state; + bool active; + uint32 encounter; +}; + +static t_Locations PortalLoc[]= +{ +{-3050001,603, -706.122f, -92.6024f, 430.176f, 4.19f, SPELL_TELEPORT_BASE_CAMP, true,true, TYPE_LEVIATHAN}, // base camp +{-3050002,603, 131.248f, -35.3802f, 410.104f, 0, SPELL_TELEPORT_GROUNDS, true,true, TYPE_LEVIATHAN_TP}, // formation ground +{-3050003,603, 553.233f, -12.3247f, 409.979f, 0, SPELL_TELEPORT_FORGE, false,true,TYPE_LEVIATHAN}, // +{-3050004,603, 926.292f, -11.4635f, 418.895f, 3.19f, SPELL_TELEPORT_SCRAPYARD, false,true,TYPE_XT002_TP}, // +{-3050005,603, 1498.09f, -24.246f, 421.267f, 0, SPELL_TELEPORT_ANTECHAMBER, false,true,TYPE_XT002}, // +{-3050006,603, 1859.45f, -24.1f, 449.2f, 0, SPELL_TELEPORT_WALKWAY, false,true,TYPE_KOLOGARN}, // +{-3050007,603, 2086.27f, -24.3134f, 421.539f, 0, SPELL_TELEPORT_CONSERVATORY,false,true,TYPE_AURIAYA}, // +{-3050008,603, 2517.3979f, 2568.89f, 412.99f, 6.17f, SPELL_TELEPORT_SPARK, false,true,TYPE_MIMIRON_TP}, // +{-3050009,603, 1854.782f, -11.3819f, 335.27f, 5.86f, SPELL_TELEPORT_PRISON, false,true,TYPE_VEZAX}, // +}; + + +bool GOGossipSelect_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo, uint32 sender, uint32 action) +{ + int32 damage = 0; + if(sender != GOSSIP_SENDER_MAIN) return false; + + if(pPlayer->IsInCombat()) + return false; + + if(action >= 0 && action <= PORTALS_COUNT) + pPlayer->TeleportTo(PortalLoc[action].map_num, PortalLoc[action].x, PortalLoc[action].y, PortalLoc[action].z, PortalLoc[action].o); + if (PortalLoc[action].spellID != 0 ) + if (SpellEntry const* spell = (SpellEntry *)GetSpellStore()->LookupEntry(PortalLoc[action].spellID)) + { + SpellAuraHolderPtr holder = CreateSpellAuraHolder(spell, pPlayer, pPlayer); + Aura* aura = holder->CreateAura(AURA_CLASS_AURA, EFFECT_INDEX_2, NULL, holder, pPlayer, pPlayer, NULL); + pPlayer->AddSpellAuraHolder(holder); + } + + pPlayer->CLOSE_GOSSIP_MENU(); + return true; +} + +bool GOGossipHello_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo) +{ + ScriptedInstance *pInstance = (ScriptedInstance *) pGo->GetInstanceData(); + + if (!pInstance || !pPlayer) return false; + if (pPlayer->isInCombat()) return true; + + for(uint8 i = 0; i < PORTALS_COUNT; i++) { + if ((PortalLoc[i].active == true && + (PortalLoc[i].state == true || + pInstance->GetData(PortalLoc[i].encounter) == DONE || + pInstance->GetData(PortalLoc[i].encounter) == IN_PROGRESS)) + || pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_TAXI, PortalLoc[i].textNum, GOSSIP_SENDER_MAIN, i); + }; + pPlayer->SEND_GOSSIP_MENU(TELEPORT_GOSSIP_MESSAGE, pGo->GetObjectGuid()); + return true; +} + +void AddSC_ulduar_teleport() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_ulduar_teleporter"; + newscript->pGossipHelloGO = &GOGossipHello_go_ulduar_teleporter; + newscript->pGossipSelectGO = &GOGossipSelect_go_ulduar_teleporter; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar.cpp b/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar.cpp index dd1af1e204..5d99f30007 100644 --- a/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -15,76 +15,64 @@ */ /* ScriptData -SDName: Boss_Ingvar -SD%Complete: 70% -SDComment: TODO: correct timers, spell 42912 requires proper position fix in core -SDCategory: Utgarde Keep +SDName: Boss_Ingvar_The_Plunderer +SD%Complete: 95 +SDComment: Some Problems with Annhylde Movement, Blizzlike Timers +SDCategory: Udgarde Keep EndScriptData */ #include "precompiled.h" #include "utgarde_keep.h" -enum +enum eEnums { - SAY_AGGRO_FIRST = -1574005, - SAY_AGGRO_SECOND = -1574006, - SAY_DEATH_FIRST = -1574007, - SAY_DEATH_SECOND = -1574008, - SAY_KILL_FIRST = -1574009, - SAY_KILL_SECOND = -1574010, - EMOTE_ROAR = -1574022, - SAY_ANNHYLDE_REZ = -1574023, - - NPC_ANNHYLDE = 24068, - NPC_THROW_TARGET = 23996, // the target, casting spell and target of moving dummy - NPC_THROW_DUMMY = 23997, // the axe, moving to target - NPC_GROUND_VISUAL = 24012, // has SPELL_SCOURGE_RES_BUBBLE aura - - //phase 1 - SPELL_CLEAVE = 42724, - - SPELL_SMASH = 42669, - SPELL_SMASH_H = 59706, - - SPELL_ENRAGE = 42705, - SPELL_ENRAGE_H = 59707, - - SPELL_STAGGERING_ROAR = 42708, - SPELL_STAGGERING_ROAR_H = 59708, - - //phase 2 - SPELL_DARK_SMASH_H = 42723, - - SPELL_DREADFUL_ROAR = 42729, - SPELL_DREADFUL_ROAR_H = 59734, - - SPELL_WOE_STRIKE = 42730, - SPELL_WOE_STRIKE_H = 59735, - - SPELL_SHADOW_AXE = 42748, - SPELL_SHADOW_AXE_PROC = 42750, // triggers 42751 - SPELL_SHADOW_AXE_PROC_H = 59719, // triggers 59720 - - //ressurection sequenze - SPELL_ASTRAL_TELEPORT = 34427, // aura cast by Annhylde on spawn - SPELL_SUMMON_BANSHEE = 42912, // summons Annhylde and sets a glow aura - SPELL_FEIGN_DEATH = 42795, - SPELL_TRANSFORM = 42796, - SPELL_SCOURGE_RES_SUMMON = 42863, // summones a dummy target - SPELL_SCOURGE_RES_HEAL = 42704, // heals max HP - SPELL_SCOURGE_RES_BUBBLE = 42862, // black bubble - SPELL_SCOURGE_RES_CHANNEL = 42857, // the whirl from annhylde - - POINT_ID_ANNHYLDE = 1 + //Achievements + ACHIEVEMENT_UTGARDE_KEEP_N = 477, + ACHIEVEMENT_UTGARDE_KEEP_H = 489, + + //Yells Ingvar + YELL_AGGRO_1 = -1574005, + YELL_AGGRO_2 = -1574006, + + YELL_DEAD_1 = -1574007, + YELL_DEAD_2 = -1574008, + + YELL_KILL_1 = -1574009, + YELL_KILL_2 = -1574010, + + //Ingvar Spells human form + MOB_INGVAR_HUMAN = 23954, + SPELL_CLEAVE = 42724, + SPELL_SMASH = 42669, + H_SPELL_SMASH = 59706, + SPELL_STAGGERING_ROAR = 42708, + H_SPELL_STAGGERING_ROAR = 59708, + SPELL_ENRAGE = 42705, + H_SPELL_ENRAGE = 59707, + + MOB_ANNHYLDE_THE_CALLER = 24068, + SPELL_INGVAR_FEIGN_DEATH = 42795, + SPELL_SUMMON_BANSHEE = 42912, + SPELL_SCOURG_RESURRECTION_EFFEKTSPAWN = 42863, //Spawn resurrecteffekt around Ingvar + + MODEL_INGVAR_UNDEAD = 26351, + MODEL_INGVAR_HUMAN = 21953, + + //Ingvar Spells undead form + MOB_INGVAR_UNDEAD = 23980, + SPELL_DARK_SMASH = 42723, + SPELL_DREADFUL_ROAR = 42729, + H_SPELL_DREADFUL_ROAR = 59734, + SPELL_WOE_STRIKE = 42730, + H_SPELL_WOE_STRIKE = 59735, + + ENTRY_THROW_TARGET = 23996, + SPELL_SHADOW_AXE_SUMMON = 42749 }; -/*###### -## boss_ingvar -######*/ - struct MANGOS_DLL_DECL boss_ingvarAI : public ScriptedAI { - boss_ingvarAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_ingvarAI(Creature *pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); @@ -94,186 +82,221 @@ struct MANGOS_DLL_DECL boss_ingvarAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - bool m_bIsResurrected; - bool m_bIsFakingDeath; + bool undead; + bool event_inProgress; - uint32 m_uiCleaveTimer; - uint32 m_uiSmashTimer; - uint32 m_uiStaggeringRoarTimer; - uint32 m_uiEnrageTimer; + uint32 Cleave_Timer; + uint32 Smash_Timer; + uint32 Enrage_Timer; + uint32 Roar_Timer; + uint32 SpawnResTimer; + uint32 wait_Timer; void Reset() { - m_bIsResurrected = false; - m_bIsFakingDeath = false; + if (undead) // Visual Hack + m_creature->SetDisplayId(MODEL_INGVAR_HUMAN); - m_uiCleaveTimer = urand(5000, 7000); - m_uiSmashTimer = urand(8000, 15000); - m_uiStaggeringRoarTimer = urand(10000, 25000); - m_uiEnrageTimer = 30000; - } + undead = false; + event_inProgress = false; - void Aggro(Unit* pWho) - { - // don't yell for her - if (pWho->GetEntry() == NPC_ANNHYLDE) - return; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + + Cleave_Timer = 2000; + Smash_Timer = 5000; + Enrage_Timer = 10000; + Roar_Timer = 15000; + + SpawnResTimer = 3000; + + wait_Timer = 0; - // ToDo: it shouldn't yell this aggro text after removing the feign death aura - DoScriptText(SAY_AGGRO_FIRST, m_creature); + if (m_pInstance) + m_pInstance->SetData(TYPE_INGVAR, NOT_STARTED); } - void DamageTaken(Unit* pDealer, uint32& uiDamage) + void DamageTaken(Unit *done_by, uint32 &damage) { - if (m_bIsResurrected) - return; - - if (m_bIsFakingDeath) + if (damage >= m_creature->GetHealth() && !undead) { - uiDamage = 0; - return; + //DoCast(m_creature, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? + // visuel hack + m_creature->SetHealth(1); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetDisplayId(MODEL_INGVAR_UNDEAD); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + // visuel hack end + + event_inProgress = true; + undead = true; + + DoScriptText(YELL_DEAD_1,m_creature); } - if (uiDamage >= m_creature->GetHealth()) + if (event_inProgress) { - uiDamage = 0; - - DoScriptText(SAY_DEATH_FIRST, m_creature); + damage = 0; + } + } - DoCastSpellIfCan(m_creature, SPELL_SUMMON_BANSHEE, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_FEIGN_DEATH, CAST_TRIGGERED); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + void StartZombiePhase() + { + undead = true; + event_inProgress = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); - m_bIsFakingDeath = true; - } + DoScriptText(YELL_AGGRO_2,m_creature); } - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + void EnterCombat(Unit *who) { - if (pSpell->Id == SPELL_TRANSFORM) - { - DoScriptText(SAY_AGGRO_SECOND, m_creature); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->UpdateEntry(pSpell->EffectMiscValue[EFFECT_INDEX_0]); - m_bIsResurrected = true; - m_bIsFakingDeath = false; - } + DoScriptText(YELL_AGGRO_1,m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_INGVAR, IN_PROGRESS); } - void JustSummoned(Creature* pSummoned) + void JustDied(Unit* killer) { - switch (pSummoned->GetEntry()) + DoScriptText(YELL_DEAD_2,m_creature); + + // complete burg utgarde achievements, not really blizzlike (should complete criterias) + // normal achievement on both difficulties + AchievementEntry const *AchievUtgardeKeepNorm = GetAchievementStore()->LookupEntry(ACHIEVEMENT_UTGARDE_KEEP_N); + if (AchievUtgardeKeepNorm) { - case NPC_THROW_DUMMY: - // ToDo: should this move to the target? - pSummoned->CastSpell(pSummoned, m_bIsRegularMode ? SPELL_SHADOW_AXE_PROC : SPELL_SHADOW_AXE_PROC_H, true); - break; - - case NPC_ANNHYLDE: - // This is not blizzlike - npc should be summoned above the boss and should move slower - pSummoned->CastSpell(pSummoned, SPELL_ASTRAL_TELEPORT, false); - pSummoned->SetLevitate(true); - pSummoned->GetMotionMaster()->MovePoint(POINT_ID_ANNHYLDE, pSummoned->GetPositionX(), pSummoned->GetPositionY(), pSummoned->GetPositionZ() + 15.0f); - break; - - case NPC_GROUND_VISUAL: - pSummoned->CastSpell(pSummoned, SPELL_SCOURGE_RES_BUBBLE, false); - // npc doesn't despawn on time - pSummoned->ForcedDespawn(8000); - break; + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievUtgardeKeepNorm); + } + } + if(!m_bIsRegularMode) + { + AchievementEntry const *AchievUtgardeKeepHero = GetAchievementStore()->LookupEntry(ACHIEVEMENT_UTGARDE_KEEP_H); + if (AchievUtgardeKeepHero) + { + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievUtgardeKeepHero); + } + } } - } - void JustDied(Unit* pKiller) - { - DoScriptText(SAY_DEATH_SECOND, m_creature); + if (m_pInstance) + m_pInstance->SetData(TYPE_INGVAR, DONE); } - void KilledUnit(Unit* pVictim) + void KilledUnit(Unit *victim) { - if (urand(0, 1)) - DoScriptText(m_bIsResurrected ? SAY_KILL_SECOND : SAY_KILL_FIRST, m_creature); + if (undead) { DoScriptText(YELL_KILL_1,m_creature); } + else { DoScriptText(YELL_KILL_2,m_creature); } } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 diff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() || m_bIsFakingDeath) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (!m_bIsResurrected) // First phase + if (event_inProgress) { - if (m_uiCleaveTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK) - m_uiCleaveTimer = urand(2500, 7000); - } - else - m_uiCleaveTimer -= uiDiff; + if (SpawnResTimer) + if (SpawnResTimer <= diff) + { + DoCast(m_creature, SPELL_SUMMON_BANSHEE); // Summons direktly on caster position + //DoCast(m_creature, SPELL_SCOURG_RESURRECTION_EFFEKTSPAWN); // Dont needet ? + SpawnResTimer = 0; + } else SpawnResTimer -= diff; - if (m_uiSmashTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_SMASH : SPELL_SMASH_H) == CAST_OK) - m_uiSmashTimer = urand(8000, 15000); - } - else - m_uiSmashTimer -= uiDiff; + return; + } - if (m_uiStaggeringRoarTimer < uiDiff) + // This is used for a spell queue ... the spells should not castet if one spell is already casting + if (wait_Timer) + if (wait_Timer <= diff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_STAGGERING_ROAR : SPELL_STAGGERING_ROAR_H) == CAST_OK) - { - DoScriptText(EMOTE_ROAR, m_creature); - m_uiStaggeringRoarTimer = urand(15000, 30000); - } - } - else - m_uiStaggeringRoarTimer -= uiDiff; + wait_Timer = 0; + } else wait_Timer -= diff; - if (m_uiEnrageTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_ENRAGE : SPELL_ENRAGE_H) == CAST_OK) - m_uiEnrageTimer = urand(10000, 20000); - } - else - m_uiEnrageTimer -= uiDiff; - } - else // Second phase + if (Cleave_Timer <= diff) { - if (m_uiCleaveTimer < uiDiff) + if (!wait_Timer) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode? SPELL_WOE_STRIKE : SPELL_WOE_STRIKE_H) == CAST_OK) - m_uiCleaveTimer = urand(2500, 7000); + if (undead) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_WOE_STRIKE : H_SPELL_WOE_STRIKE); + else + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + Cleave_Timer = rand()%5000 + 2000; + + wait_Timer = 1000; } - else - m_uiCleaveTimer -= uiDiff; + } else Cleave_Timer -= diff; - if (m_uiSmashTimer < uiDiff) + if (Smash_Timer <= diff) + { + if (!wait_Timer) { - if (DoCastSpellIfCan(m_creature, SPELL_DARK_SMASH_H) == CAST_OK) - m_uiSmashTimer = urand(8000, 15000); + if (undead) + DoCast(m_creature->getVictim(), SPELL_DARK_SMASH); + else + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SMASH : H_SPELL_SMASH); + Smash_Timer = 10000; + + wait_Timer = 5000; } - else - m_uiSmashTimer -= uiDiff; + } else Smash_Timer -= diff; - if (m_uiStaggeringRoarTimer < uiDiff) + if (!undead) + { + if (Enrage_Timer <= diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_ENRAGE : H_SPELL_ENRAGE); + Enrage_Timer = 10000; + } else Enrage_Timer -= diff; + } else // In Undead form used to summon weapon + { + if (Enrage_Timer <= diff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_DREADFUL_ROAR : SPELL_DREADFUL_ROAR_H) == CAST_OK) + if (!wait_Timer) { - DoScriptText(EMOTE_ROAR, m_creature); - m_uiStaggeringRoarTimer = urand(15000, 30000); + // Spawn target for Axe + Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 1); + if (pTarget) + { + Creature* temp = m_creature->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); + + DoCast(m_creature, SPELL_SHADOW_AXE_SUMMON); + } + Enrage_Timer = 30000; } - } - else - m_uiStaggeringRoarTimer -= uiDiff; + } else Enrage_Timer -= diff; + } - if (m_uiEnrageTimer < uiDiff) + if (Roar_Timer <= diff) + { + if (!wait_Timer) { - if (DoCastSpellIfCan(m_creature, SPELL_SHADOW_AXE) == CAST_OK) - m_uiEnrageTimer = urand(10000, 20000); + if (undead) + DoCast(m_creature, m_bIsRegularMode ? SPELL_DREADFUL_ROAR : H_SPELL_DREADFUL_ROAR); + else + DoCast(m_creature, m_bIsRegularMode ? SPELL_STAGGERING_ROAR : H_SPELL_STAGGERING_ROAR); + Roar_Timer = 10000; + + wait_Timer = 5000; } - else - m_uiEnrageTimer -= uiDiff; - } + } else Roar_Timer -= diff; DoMeleeAttackIfReady(); } @@ -281,113 +304,188 @@ struct MANGOS_DLL_DECL boss_ingvarAI : public ScriptedAI CreatureAI* GetAI_boss_ingvar(Creature* pCreature) { - return new boss_ingvarAI(pCreature); + return new boss_ingvarAI (pCreature); } -/*###### -## npc_annhylde -######*/ +enum eSpells +{ + //we don't have that text in db so comment it until we get this text + // YELL_RESSURECT = -1574025, + + //Spells for Annhylde + SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura + SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde + SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? + SPELL_INGVAR_TRANSFORM = 42796 +}; -struct MANGOS_DLL_DECL npc_annhyldeAI : public ScriptedAI +struct MANGOS_DLL_DECL mob_annhylde_the_callerAI : public ScriptedAI { - npc_annhyldeAI(Creature* pCreature) : ScriptedAI(pCreature) + mob_annhylde_the_callerAI(Creature *pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; - uint32 m_uiResurrectTimer; - uint8 m_uiResurrectPhase; + float x,y,z; + uint32 Resurect_Timer; + uint32 Resurect_Phase; void Reset() { - m_uiResurrectTimer = 0; - m_uiResurrectPhase = 0; - } + m_creature->SetLevitate(true); + m_creature->SetSpeedRate(MOVE_SWIM , 1.0f); + m_creature->SetSpeedRate(MOVE_RUN , 1.0f); + m_creature->SetSpeedRate(MOVE_WALK , 1.0f); + //m_creature->SetSpeed(MOVE_FLIGHT , 1.0f); - // No attacking - void MoveInLineOfSight(Unit*) {} - void AttackStart(Unit*) {} + m_creature->GetPosition(x,y,z); + m_creature->NearTeleportTo(x+1,y,z+30,0); - void MovementInform(uint32 uiMotionType, uint32 uiPointId) - { - if (uiMotionType != POINT_MOTION_TYPE || uiPointId != POINT_ID_ANNHYLDE) - return; + Unit* ingvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR); + if (ingvar) + { + m_creature->GetMotionMaster()->MovePoint(1,x,y,z+15); - DoScriptText(SAY_ANNHYLDE_REZ, m_creature); - m_uiResurrectTimer = 3000; + //DoScriptText(YELL_RESSURECT,m_creature); + } } - void UpdateAI(const uint32 uiDiff) + void MovementInform(uint32 type, uint32 id) { - if (m_uiResurrectTimer) + if (type != POINT_MOTION_TYPE) + return; + Unit* ingvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR); + if (ingvar) { - if (m_uiResurrectTimer <= uiDiff) + switch (id) { - if (!m_pInstance) - return; + case 1: + ingvar->RemoveAura(SPELL_SUMMON_BANSHEE, EFFECT_INDEX_0); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); + DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); + Resurect_Timer = 8000; + Resurect_Phase = 1; + break; + case 2: + m_creature->DealDamage(m_creature,m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + break; + } + } + } - switch (m_uiResurrectPhase) + void UpdateAI(const uint32 diff) + { + if (Resurect_Timer) + if (Resurect_Timer <= diff) + { + if (Resurect_Phase == 1) + { + Unit* ingvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR); + if (ingvar) + { + ingvar->SetStandState(UNIT_STAND_STATE_STAND); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); + } + Resurect_Timer = 3000; + Resurect_Phase = 2; + } else if (Resurect_Phase == 2) { - case 0: - DoCastSpellIfCan(m_creature, SPELL_SCOURGE_RES_CHANNEL); - if (Creature* pIngvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR)) - { - if (pIngvar->HasAura(SPELL_SUMMON_BANSHEE)) - pIngvar->RemoveAurasDueToSpell(SPELL_SUMMON_BANSHEE); - } - m_uiResurrectTimer = 3000; - break; - case 1: - if (Creature* pIngvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR)) - { - pIngvar->CastSpell(pIngvar, SPELL_SCOURGE_RES_SUMMON, true); - // Workaround - set Feign death again because it's removed by the previous casted spell - pIngvar->CastSpell(pIngvar, SPELL_FEIGN_DEATH, true); - } - m_uiResurrectTimer = 5000; - break; - case 2: - if (Creature* pIngvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR)) - pIngvar->CastSpell(pIngvar, SPELL_SCOURGE_RES_HEAL, false); - m_uiResurrectTimer = 3000; - break; - case 3: - if (Creature* pIngvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR)) - pIngvar->CastSpell(pIngvar, SPELL_TRANSFORM, false); - // despawn the creature - m_creature->GetMotionMaster()->MovePoint(2, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 50); - m_creature->ForcedDespawn(5000); - m_uiResurrectTimer = 0; - break; + // DA RIVEDERE E CORREGGERE + Creature* ingvar = m_pInstance->GetSingleCreatureFromStorage(NPC_INGVAR); + if (ingvar) + { + ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); + //ingvar->CastSpell(ingvar,SPELL_INGVAR_TRANSFORM,false); + //ingvar->SetDisplayId(MODEL_INGVAR_UNDEAD); // Visual Hack - when he dies he becomes human model -> wrong + if (Creature* c_ingvar = ingvar) + if (boss_ingvarAI* pIngvar = dynamic_cast(c_ingvar->AI())) + pIngvar->StartZombiePhase(); + + m_creature->GetMotionMaster()->MovePoint(2,x+1,y,z+30); + ++Resurect_Phase; + } } - ++m_uiResurrectPhase; - } - else - m_uiResurrectTimer -= uiDiff; - } + } else Resurect_Timer -= diff; } }; -CreatureAI* GetAI_npc_annhylde(Creature* pCreature) +CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) { - return new npc_annhyldeAI(pCreature); + return new mob_annhylde_the_callerAI (pCreature); } -void AddSC_boss_ingvar() +enum eShadowAxe { - Script* pNewScript; + SPELL_SHADOW_AXE_DAMAGE = 42750, + H_SPELL_SHADOW_AXE_DAMAGE = 59719 +}; - pNewScript = new Script; - pNewScript->Name = "boss_ingvar"; - pNewScript->GetAI = &GetAI_boss_ingvar; - pNewScript->RegisterSelf(); +struct MANGOS_DLL_DECL mob_ingvar_throw_dummyAI : public ScriptedAI +{ + mob_ingvar_throw_dummyAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Despawn_Timer; + + void Reset() + { + Unit *pTarget = GetClosestCreatureWithEntry(m_creature, ENTRY_THROW_TARGET,50); + if (pTarget) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHADOW_AXE_DAMAGE : H_SPELL_SHADOW_AXE_DAMAGE); + float x,y,z; + pTarget->GetPosition(x,y,z); + m_creature->GetMotionMaster()->MovePoint(0,x,y,z); + } + Despawn_Timer = 7000; + } + + void UpdateAI(const uint32 diff) + { + if (Despawn_Timer <= diff) + { + m_creature->DealDamage(m_creature,m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->RemoveCorpse(); + Despawn_Timer = 0; + } else Despawn_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) +{ + return new mob_ingvar_throw_dummyAI (pCreature); +} - pNewScript = new Script; - pNewScript->Name = "npc_annhylde"; - pNewScript->GetAI = &GetAI_npc_annhylde; - pNewScript->RegisterSelf(); +void AddSC_boss_ingvar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ingvar"; + newscript->GetAI = &GetAI_boss_ingvar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_annhylde"; + newscript->GetAI = &GetAI_mob_annhylde_the_caller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ingvar_throw_dummy"; + newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_and_dalronn.cpp b/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_and_dalronn.cpp index 6d6c441b91..7332822826 100644 --- a/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_and_dalronn.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_and_dalronn.cpp @@ -15,68 +15,50 @@ */ /* ScriptData -SDName: Boss_Skarvald_and_Dalronn -SD%Complete: 60% -SDComment: TODO: correct timers +SDName: Boss_Skarvald_Dalronn +SD%Complete: 95 +SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB SDCategory: Utgarde Keep EndScriptData */ #include "precompiled.h" #include "utgarde_keep.h" -enum +enum eEnums { - SAY_SKA_AGGRO = -1574011, - SAY_SKA_DEATH = -1574012, - SAY_SKA_DEATH_REAL = -1574013, - SAY_SKA_KILL = -1574014, - SAY_SKA_DAL_DIES_REPLY = -1574015, - - SAY_DAL_AGGRO_REPLY = -1574016, - SAY_DAL_DEATH = -1574017, - SAY_DAL_DEATH_REAL = -1574018, - SAY_DAL_KILL = -1574019, - SAY_DAL_SKA_DIES_REPLY = -1574020, - - SPELL_SUMMON_DAL_GHOST = 48612, - SPELL_SUMMON_SKA_GHOST = 48613, - - NPC_DAL_GHOST = 27389, - NPC_SKA_GHOST = 27390, - - NPC_SKELETAL = 28878, //summoned guardian in heroic - - //skarvald - SPELL_CHARGE = 43651, - SPELL_STONE_STRIKE = 48583, - SPELL_ENRAGE = 48193, - - //dalronn - SPELL_SHADOW_BOLT = 43649, - SPELL_SHADOW_BOLT_H = 59575, - - SPELL_DEBILITATE = 43650, - SPELL_DEBILITATE_H = 59577, - - SPELL_SUMMON_SKELETONS = 52611 -}; - -struct Yell -{ - int32 m_iTextId; - int32 m_iTextReplyId; + //signed for 24200, but used by 24200,27390 + YELL_SKARVALD_AGGRO = -1574011, + YELL_SKARVALD_DAL_DIED = -1574012, + YELL_SKARVALD_SKA_DIEDFIRST = -1574013, + YELL_SKARVALD_KILL = -1574014, + YELL_SKARVALD_DAL_DIEDFIRST = -1574015, + + //signed for 24201, but used by 24201,27389 + YELL_DALRONN_AGGRO = -1574016, + YELL_DALRONN_SKA_DIED = -1574017, + YELL_DALRONN_DAL_DIEDFIRST = -1574018, + YELL_DALRONN_KILL = -1574019, + YELL_DALRONN_SKA_DIEDFIRST = -1574020, + + //Spells of Skarvald and his Ghost + MOB_SKARVALD_THE_CONSTRUCTOR = 24200, + SPELL_CHARGE = 43651, + SPELL_STONE_STRIKE = 48583, + SPELL_SUMMON_SKARVALD_GHOST = 48613, + MOB_SKARVALD_GHOST = 27390, + //Spells of Dalronn and his Ghost + MOB_DALRONN_THE_CONTROLLER = 24201, + SPELL_SHADOW_BOLT = 43649, + H_SPELL_SHADOW_BOLT = 59575, + H_SPELL_SUMMON_SKELETONS = 52611, + SPELL_DEBILITATE = 43650, + SPELL_SUMMON_DALRONN_GHOST = 48612, + MOB_DALRONN_GHOST = 27389 }; -Yell m_aYell[] = +struct MANGOS_DLL_DECL boss_skarvald_the_constructorAI : public ScriptedAI { - {SAY_SKA_AGGRO, SAY_DAL_AGGRO_REPLY}, - {SAY_SKA_DEATH, SAY_DAL_SKA_DIES_REPLY}, - {SAY_DAL_DEATH, SAY_SKA_DAL_DIES_REPLY} -}; - -struct MANGOS_DLL_DECL boss_s_and_d_dummyAI : public ScriptedAI -{ - boss_s_and_d_dummyAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_skarvald_the_constructorAI(Creature *pCreature) : ScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); @@ -84,253 +66,334 @@ struct MANGOS_DLL_DECL boss_s_and_d_dummyAI : public ScriptedAI } ScriptedInstance* m_pInstance; - bool m_bIsRegularMode; - ObjectGuid m_ghostGuid; - - Creature* GetBuddy() - { - if (!m_pInstance) - return NULL; + bool m_bIsRegularMode; - return m_pInstance->GetSingleCreatureFromStorage(m_creature->GetEntry() == NPC_DALRONN ? NPC_SKARVALD : NPC_DALRONN); - } + bool ghost; + uint32 Charge_Timer; + uint32 StoneStrike_Timer; + uint32 Response_Timer; + uint32 Check_Timer; + bool Dalronn_isDead; - void Reset() { } + Creature* pGhost; - void JustReachedHome() + void Reset() { - if (Creature* pBuddy = GetBuddy()) - { - if (pBuddy->isDead()) - pBuddy->Respawn(); - } + Charge_Timer = 5000; + StoneStrike_Timer = 10000; + Dalronn_isDead = false; + Check_Timer = 5000; - if (Creature* pGhost = m_creature->GetMap()->GetCreature(m_ghostGuid)) + ghost = (m_creature->GetEntry() == MOB_SKARVALD_GHOST); + if (!ghost && m_pInstance) { - if (pGhost->isAlive()) - pGhost->ForcedDespawn(); - } - } - - void EnterCombat(Unit* pWho) - { - if (!pWho) - return; + Unit* dalronn = m_pInstance->GetSingleCreatureFromStorage(NPC_DALRONN); + if (dalronn && dalronn->isDead()) + ((Creature*)dalronn)->Respawn(); - if (Creature* pBuddy = GetBuddy()) - { - if (!pBuddy->getVictim()) - pBuddy->AI()->AttackStart(pWho); + m_pInstance->SetData(TYPE_SKARVALD_DALRONN, NOT_STARTED); } - - Aggro(pWho); } - void JustSummoned(Creature* pSummoned) + void EnterCombat(Unit *who) { - // EventAI can probably handle ghosts - if (pSummoned->GetEntry() == NPC_DAL_GHOST || pSummoned->GetEntry() == NPC_SKA_GHOST) - m_ghostGuid = pSummoned->GetObjectGuid(); - - Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO,1); + if (!ghost && m_pInstance) + { + DoScriptText(YELL_SKARVALD_AGGRO,m_creature); - if (m_creature->getVictim()) - pSummoned->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim()); + Unit* dalronn = m_pInstance->GetSingleCreatureFromStorage(NPC_DALRONN); + if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) + dalronn->getThreatManager().addThreat(who,0.0f); - pSummoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_pInstance->SetData(TYPE_SKARVALD_DALRONN, IN_PROGRESS); + } } - void JustDied(Unit* pKiller) + void JustDied(Unit* Killer) { - if (Creature* pBuddy = GetBuddy()) + if (!ghost && m_pInstance) { - if (pBuddy->isAlive()) + Unit* dalronn = m_pInstance->GetSingleCreatureFromStorage(NPC_DALRONN); + if (dalronn) { - DoScriptText(m_creature->GetEntry() == NPC_SKARVALD ? m_aYell[1].m_iTextId : m_aYell[2].m_iTextId, m_creature); - DoScriptText(m_creature->GetEntry() == NPC_SKARVALD ? m_aYell[1].m_iTextReplyId : m_aYell[2].m_iTextReplyId, pBuddy); - - pBuddy->CastSpell(m_creature, m_creature->GetEntry() == NPC_SKARVALD ? SPELL_SUMMON_SKA_GHOST : SPELL_SUMMON_DAL_GHOST, true); - - m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - else - { - if (Creature* pGhost = m_creature->GetMap()->GetCreature(m_ghostGuid)) - pGhost->ForcedDespawn(); - - pBuddy->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (dalronn->isDead()) + { + DoScriptText(YELL_SKARVALD_DAL_DIED,m_creature); + + m_pInstance->SetData(TYPE_SKARVALD_DALRONN, DONE); + + if(pGhost = GetClosestCreatureWithEntry(m_creature, MOB_DALRONN_GHOST, 1000)) + pGhost->ForcedDespawn(); + } + else + { + DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,m_creature); + + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(m_creature, SPELL_SUMMON_SKARVALD_GHOST, true); + Creature* temp = m_creature->SummonCreature(MOB_SKARVALD_GHOST,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } } } } -}; - -/*###### -## boss_skarvald -######*/ -struct MANGOS_DLL_DECL boss_skarvaldAI : public boss_s_and_d_dummyAI -{ - boss_skarvaldAI(Creature* pCreature) : boss_s_and_d_dummyAI(pCreature) { Reset(); } - - uint32 m_uiYellDelayTimer; - uint32 m_uiChargeTimer; - uint32 m_uiEnrageTimer; - uint32 m_uiStoneStrikeTimer; - - void Reset() - { - m_uiYellDelayTimer = 0; - m_uiChargeTimer = urand(2000, 6000); - m_uiEnrageTimer = 15000; - m_uiStoneStrikeTimer = 8000; - } - - void Aggro(Unit* pWho) + void KilledUnit(Unit *victim) { - DoScriptText(m_aYell[0].m_iTextId, m_creature); - m_uiYellDelayTimer = 5000; + if (!ghost) + { + DoScriptText(YELL_SKARVALD_KILL,m_creature); + } } - void KilledUnit(Unit* pVictim) + void UpdateAI(const uint32 diff) { - DoScriptText(SAY_SKA_KILL, m_creature); - } + if (ghost) + { + if (m_pInstance && m_pInstance->GetData(TYPE_SKARVALD_DALRONN) != IN_PROGRESS) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } - void UpdateAI(const uint32 uiDiff) - { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiYellDelayTimer) + if (!ghost) { - if (m_uiYellDelayTimer <= uiDiff) - { - if (Creature* pBuddy = GetBuddy()) - DoScriptText(m_aYell[0].m_iTextReplyId, pBuddy); - - m_uiYellDelayTimer = 0; - } - else - m_uiYellDelayTimer -= uiDiff; + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* dalronn = m_pInstance->GetSingleCreatureFromStorage(NPC_DALRONN); + if (dalronn && dalronn->isDead()) + { + Dalronn_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Dalronn_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,m_creature); + + Response_Timer = 0; + } else Response_Timer -= diff; } - if (m_uiChargeTimer < uiDiff) + if (Charge_Timer <= diff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) - DoCastSpellIfCan(pTarget, SPELL_CHARGE); + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1), SPELL_CHARGE); + Charge_Timer = 5000+rand()%5000; + } else Charge_Timer -= diff; - m_uiChargeTimer = urand(8000, 16000); - } - else - m_uiChargeTimer -= uiDiff; - - if (m_uiEnrageTimer < uiDiff) + if (StoneStrike_Timer <= diff) { - DoCastSpellIfCan(m_creature, SPELL_ENRAGE); - m_uiEnrageTimer = 20000; - } - else - m_uiEnrageTimer -= uiDiff; - - if (m_uiStoneStrikeTimer < uiDiff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_STONE_STRIKE); - m_uiStoneStrikeTimer = urand(5000, 15000); - } - else - m_uiStoneStrikeTimer -= uiDiff; + DoCast(m_creature->getVictim(), SPELL_STONE_STRIKE); + StoneStrike_Timer = 5000+rand()%5000; + } else StoneStrike_Timer -= diff; DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_skarvald(Creature* pCreature) +CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) { - return new boss_skarvaldAI(pCreature); + return new boss_skarvald_the_constructorAI (pCreature); } -/*###### -## boss_dalronn -######*/ - -struct MANGOS_DLL_DECL boss_dalronnAI : public boss_s_and_d_dummyAI +struct MANGOS_DLL_DECL boss_dalronn_the_controllerAI : public ScriptedAI { - boss_dalronnAI(Creature* pCreature) : boss_s_and_d_dummyAI(pCreature) { Reset(); } + boss_dalronn_the_controllerAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + bool ghost; + uint32 ShadowBolt_Timer; + uint32 Debilitate_Timer; + uint32 Summon_Timer; + + uint32 Response_Timer; + uint32 Check_Timer; + uint32 AggroYell_Timer; + bool Skarvald_isDead; - uint32 m_uiDebilitateTimer; - uint32 m_uiShadowBoltTimer; - uint32 m_uiSkeletonTimer; + Creature* pGhost; void Reset() { - m_uiDebilitateTimer = urand(5000, 10000); - m_uiShadowBoltTimer = urand(2500, 6000); - m_uiSkeletonTimer = urand(25000, 35000); + ShadowBolt_Timer = 1000; + Debilitate_Timer = 5000; + Summon_Timer = 10000; + Check_Timer = 5000; + Skarvald_isDead = false; + AggroYell_Timer = 0; + + ghost = m_creature->GetEntry() == MOB_DALRONN_GHOST; + if (!ghost && m_pInstance) + { + Unit* skarvald = m_pInstance->GetSingleCreatureFromStorage(NPC_SKARVALD); + if (skarvald && skarvald->isDead()) + ((Creature*)skarvald)->Respawn(); + + m_pInstance->SetData(TYPE_SKARVALD_DALRONN, NOT_STARTED); + } + } + + void EnterCombat(Unit *who) + { + if (!ghost && m_pInstance) + { + Unit* skarvald = m_pInstance->GetSingleCreatureFromStorage(NPC_SKARVALD); + if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) + skarvald->getThreatManager().addThreat(who,0.0f); + + AggroYell_Timer = 5000; + + if (m_pInstance) + m_pInstance->SetData(TYPE_SKARVALD_DALRONN, IN_PROGRESS); + } } - void KilledUnit(Unit* pVictim) + void JustDied(Unit* Killer) { - DoScriptText(SAY_DAL_KILL, m_creature); + if (!ghost && m_pInstance) + { + Unit* skarvald = m_pInstance->GetSingleCreatureFromStorage(NPC_SKARVALD); + if (skarvald) + if (skarvald->isDead()) + { + DoScriptText(YELL_DALRONN_SKA_DIED,m_creature); + + m_pInstance->SetData(TYPE_SKARVALD_DALRONN, DONE); + + if(pGhost = GetClosestCreatureWithEntry(m_creature, MOB_SKARVALD_GHOST, 1000)) + pGhost->ForcedDespawn(); + } + else + { + DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,m_creature); + + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(m_creature, SPELL_SUMMON_DALRONN_GHOST, true); + Creature* temp = m_creature->SummonCreature(MOB_DALRONN_GHOST,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } } - void UpdateAI(const uint32 uiDiff) + void KilledUnit(Unit *victim) { + if (!ghost) + { + DoScriptText(YELL_DALRONN_KILL,m_creature); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (m_pInstance && m_pInstance->GetData(TYPE_SKARVALD_DALRONN) != IN_PROGRESS) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiDebilitateTimer < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_DEBILITATE : SPELL_DEBILITATE_H); + if (AggroYell_Timer) + if (AggroYell_Timer <= diff) + { + DoScriptText(YELL_DALRONN_AGGRO,m_creature); - m_uiDebilitateTimer = urand(12000, 20000); - } - else - m_uiDebilitateTimer -= uiDiff; + AggroYell_Timer = 0; + } else AggroYell_Timer -= diff; - if (m_uiShadowBoltTimer < uiDiff) + if (!ghost) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_BOLT : SPELL_SHADOW_BOLT_H); - - m_uiShadowBoltTimer = urand(3000, 6000); + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* skarvald = m_pInstance->GetSingleCreatureFromStorage(NPC_SKARVALD); + if (skarvald && skarvald->isDead()) + { + Skarvald_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Skarvald_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,m_creature); + + Response_Timer = 0; + } else Response_Timer -= diff; } - else - m_uiShadowBoltTimer -= uiDiff; - if (!m_bIsRegularMode) + if (ShadowBolt_Timer <= diff) { - if (m_uiSkeletonTimer < uiDiff) + if (!m_creature->IsNonMeleeSpellCasted(false)) { - if (!m_creature->FindGuardianWithEntry(NPC_SKELETAL)) - DoCastSpellIfCan(m_creature, SPELL_SUMMON_SKELETONS); + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_SHADOW_BOLT : H_SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 1000; + } + } else ShadowBolt_Timer -= diff; - m_uiSkeletonTimer = 30000; + if (Debilitate_Timer <= diff) + { + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), SPELL_DEBILITATE); + Debilitate_Timer = 5000+rand()%5000; } - else - m_uiSkeletonTimer -= uiDiff; - } + } else Debilitate_Timer -= diff; + + if (!m_bIsRegularMode) + if (Summon_Timer <= diff) + { + DoCast(m_creature, H_SPELL_SUMMON_SKELETONS); + Summon_Timer = (rand()%10000) + 20000; + } else Summon_Timer -= diff; DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_dalronn(Creature* pCreature) +CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) { - return new boss_dalronnAI(pCreature); + return new boss_dalronn_the_controllerAI (pCreature); } void AddSC_boss_skarvald_and_dalronn() { - Script* pNewScript; + Script *newscript; - pNewScript = new Script; - pNewScript->Name = "boss_skarvald"; - pNewScript->GetAI = &GetAI_boss_skarvald; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "boss_skarvald"; + newscript->GetAI = &GetAI_boss_skarvald_the_constructor; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "boss_dalronn"; - pNewScript->GetAI = &GetAI_boss_dalronn; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "boss_dalronn"; + newscript->GetAI = &GetAI_boss_dalronn_the_controller; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp b/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp index 62ad27f5b8..717115d850 100644 --- a/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -25,6 +25,7 @@ EndScriptData */ #include "utgarde_keep.h" instance_utgarde_keep::instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap), + m_bKelesethAchievFailed(false) { Initialize(); @@ -50,7 +51,7 @@ void instance_utgarde_keep::OnCreatureCreate(Creature* pCreature) void instance_utgarde_keep::OnObjectCreate(GameObject* pGo) { - switch (pGo->GetEntry()) + switch(pGo->GetEntry()) { case GO_BELLOW_1: if (m_auiEncounter[TYPE_BELLOW_1] == DONE) @@ -76,9 +77,6 @@ void instance_utgarde_keep::OnObjectCreate(GameObject* pGo) if (m_auiEncounter[TYPE_BELLOW_3] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; - - default: - return; } m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid(); } diff --git a/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_gortok.cpp b/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_gortok.cpp index e645c02ab8..6ee23ed8d7 100644 --- a/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_gortok.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_gortok.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -16,16 +16,11 @@ /* ScriptData SDName: Boss_Gortok -SD%Complete: 20% +SD%Complete: SDComment: SDCategory: Utgarde Pinnacle EndScriptData */ -/* TODO -implement Orb - a red ball-> this Orb activate the mobs -*/ - - #include "precompiled.h" #include "utgarde_pinnacle.h" @@ -36,8 +31,15 @@ enum SAY_SLAY_2 = -1575017, SAY_DEATH = -1575018, + //Others Spells + + SPELL_ORB_VISUAL = 48044, + SPELL_ORB_CHANNEL = 48048, SPELL_FREEZE_ANIM = 16245, + SPELL_WAKEUP_GORTOK = 47670, + SPELL_AWAKEN_SUBBOSS = 47669, + //Gortok Spell's SPELL_IMPALE = 48261, SPELL_IMPALE_H = 59268, @@ -46,26 +48,139 @@ enum SPELL_ARCING_SMASH = 48260, - SPELL_ORB_VISUAL = 48044, // not used - - SPELL_FREEZE = 16245 + //FurlBorg Spell's + SPELL_CHAIN_LIGHTING_N = 48140, + SPELL_CHAIN_LIGHTING_H = 59273, + SPELL_CRAZED = 48139, + SPELL_TERRIFYING_ROAR = 48144, + + //Worgen Spells + SPELL_MORTAL_WOUND_N = 48137, + SPELL_MORTAL_WOUND_H = 59265, + SPELL_ENRAGE_1 = 48138, + SPELL_ENRAGE_2 = 48142, + + //Rhino Spells + SPELL_GORE_N = 48130, + SPELL_GORE_H = 59264, + SPELL_GRIEVOUS_WOUND_N = 48105, + SPELL_GRIEVOUS_WOUND_H = 59263, + SPELL_STOMP = 48131, + + //Jormungar Spells + SPELL_ACID_SPIT = 48132, + SPELL_ACID_SPLATTER_N = 48136, + SPELL_ACID_SPLATTER_H = 59272, + SPELL_POISON_BREATH_N = 48133, + SPELL_POISON_BREATH_H = 59271, + + POINT_ID_ORB = 1 }; -enum Phase -{ - PHASE_BEGIN = 0, - PHASE_FRENZIED_WORGEN = 1, - PHASE_RAVENOUS_FURLBORG = 2, - PHASE_MASSIVE_JORMUNGAR = 3, - PHASE_FEROCIOUS_RHINO = 4, - PHASE_GORTOK_PALEHOOF = 5, -}; +#define ORB_SPAWN_X 238.61f +#define ORB_SPAWN_Y -460.71f +#define ORB_MOVE_X 279.11f +#define ORB_MOVE_Y -452.01f +#define ORB_Z 109.57f -enum SubBossSteps +struct MANGOS_DLL_DECL npc_gortok_orbAI : public ScriptedAI { - PHASE_SUB_BOSS_BEGIN = 0, - PHASE_SUB_BOSS_INFIGHT = 1, - PHASE_SUB_BOSS_END = 2, + npc_gortok_orbAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiStepTimer; + uint32 m_uiStep; + bool m_bTimeToAct; + uint32 m_uiBossEntry; + uint8 m_uiBossCount; + + void Reset() + { + m_uiStepTimer = 4000; + m_uiStep = 1; + m_bTimeToAct = true; + m_uiBossEntry = urand(NPC_WORGEN, NPC_RHINO); + m_uiBossCount = 0; + m_creature->SetLevitate(true); + m_creature->SetDisplayId(16925); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE); + m_creature->CastSpell(m_creature, SPELL_ORB_VISUAL, true); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPointId == POINT_ID_ORB) + DoAction(); + } + + void DoAction() + { + m_uiStepTimer = 2000; + m_uiStep = 3; + m_bTimeToAct = true; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) + return; + + if (m_bTimeToAct) + if (m_uiStepTimer <= uiDiff) + { + switch (m_uiStep) + { + case 1: + m_creature->MonsterMoveWithSpeed(ORB_SPAWN_X, ORB_SPAWN_Y, ORB_Z+4.0f, 4000); + m_creature->GetMap()->CreatureRelocation(m_creature, ORB_SPAWN_X, ORB_SPAWN_Y, ORB_Z+4.0f, 0); + m_uiStepTimer = 4000; + break; + case 2: + m_creature->GetMotionMaster()->MovePoint(POINT_ID_ORB, ORB_MOVE_X, ORB_MOVE_Y, ORB_Z+2.0f); + m_bTimeToAct = false; + break; + case 3: + if (Creature* pBoss = m_pInstance->GetSingleCreatureFromStorage(m_uiBossEntry)) + { + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (m_uiBossCount < 4) + m_creature->CastSpell(pBoss, SPELL_AWAKEN_SUBBOSS, false); + else if (m_uiBossCount == 4) + m_creature->CastSpell(pBoss, SPELL_WAKEUP_GORTOK, false); + } + m_uiStepTimer = 10000; + break; + case 4: + if (Creature* pBoss = m_pInstance->GetSingleCreatureFromStorage(m_uiBossEntry)) + { + pBoss->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pBoss->setFaction(974); + pBoss->SetInCombatWithZone(); + } + ++m_uiBossCount; + ++m_uiBossEntry; + if (m_uiBossEntry > NPC_RHINO) + m_uiBossEntry = NPC_WORGEN; + if (m_uiBossCount == 4) + m_uiBossEntry = NPC_GORTOK; + if (m_uiBossCount == 5) + m_creature->ForcedDespawn(); + m_bTimeToAct = false; + break; + } + ++m_uiStep; + } + else + m_uiStepTimer -= uiDiff; + } }; /*###### @@ -76,73 +191,85 @@ struct MANGOS_DLL_DECL boss_gortokAI : public ScriptedAI { boss_gortokAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_pinnacle*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_pinnacle* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - Phase m_uiPhase; - uint8 m_uiSubBossSteps; - uint8 m_uiSubBossCount; - uint8 m_uiSubBossMax; - - uint32 m_uiCheckForDeathSubBoss; - - uint32 m_uiWitheringRoar; - uint32 m_uiImpale; - uint32 m_uiArcingSmash; + uint32 uiArcingSmashTimer; + uint32 uiImpaleTimer; + uint32 uiWhiteringRoarTimer; void Reset() { - m_uiPhase = PHASE_BEGIN; - m_uiSubBossSteps = PHASE_SUB_BOSS_BEGIN; - m_uiSubBossCount = 0; - m_uiSubBossMax = m_bIsRegularMode ? 2 : 4; - m_uiCheckForDeathSubBoss = 2000; + uiArcingSmashTimer = 15000; + uiImpaleTimer = 12000; + uiWhiteringRoarTimer = 10000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_GORTOK, NOT_STARTED); + + Creature* pTemp; + if (pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_WORGEN)) + { + pTemp->setFaction(35); + if (pTemp->isDead()) + pTemp->Respawn(); + } + if (pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_RHINO)) + { + pTemp->setFaction(35); + if (pTemp->isDead()) + pTemp->Respawn(); + } + if (pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JORMUNGAR)) + { + pTemp->setFaction(35); + if (pTemp->isDead()) + pTemp->Respawn(); + } + if (pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_FURBOLG)) + { + pTemp->setFaction(35); + if (pTemp->isDead()) + pTemp->Respawn(); + } + + if (GameObject* pGo = m_pInstance->GetSingleGameObjectFromStorage(GO_STASIS_GENERATOR)) + { + pGo->SetGoState(GO_STATE_READY); + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + } - m_uiWitheringRoar = urand(7000,11000); - m_uiImpale = 9000; - m_uiArcingSmash = 5000; + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_STASIS_CONTROLLER)) + pController->ForcedDespawn(); + } } - void Aggro(Unit* pWho) + void JustReachedHome() { - DoScriptText(SAY_AGGRO, m_creature); + DoCast(m_creature, SPELL_FREEZE_ANIM); } - void MoveInLineOfSight(Unit* pWho) + void Aggro(Unit* pWho) { - ScriptedAI::MoveInLineOfSight(pWho); - if (m_creature->IsWithinDistInMap(pWho, m_creature->GetAttackDistance(pWho)) && m_creature->IsWithinLOSInMap(pWho)) - { - if (m_uiPhase==PHASE_BEGIN) - { - if (m_pInstance) - { - switch(urand(0,3)) - { - case 0: m_uiPhase = PHASE_FRENZIED_WORGEN; break; - case 1: m_uiPhase = PHASE_RAVENOUS_FURLBORG; break; - case 2: m_uiPhase = PHASE_MASSIVE_JORMUNGAR; break; - case 3: m_uiPhase = PHASE_FEROCIOUS_RHINO; break; - default: m_uiPhase = PHASE_FRENZIED_WORGEN; break; - } - } - } - } + DoScriptText(SAY_AGGRO, m_creature); } - void AttackStart(Unit* pWho) + void AttackStart(Unit* who) { - if (m_uiPhase==PHASE_GORTOK_PALEHOOF) - { - m_creature->RemoveAurasDueToSpell(SPELL_FREEZE); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - ScriptedAI::AttackStart(pWho); - } + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); } void KilledUnit(Unit* pVictim) @@ -154,210 +281,475 @@ struct MANGOS_DLL_DECL boss_gortokAI : public ScriptedAI { DoScriptText(SAY_DEATH, m_creature); + if(m_pInstance) + m_pInstance->SetData(TYPE_GORTOK, DONE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (uiArcingSmashTimer <= uiDiff) + { + DoCast(m_creature, SPELL_ARCING_SMASH); + uiArcingSmashTimer = urand(13000, 17000); + } + else + uiArcingSmashTimer -= uiDiff; + + if (uiImpaleTimer <= uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_IMPALE); + uiImpaleTimer = urand(8000, 12000); + } + else + uiImpaleTimer -= uiDiff; + + if (uiWhiteringRoarTimer <= uiDiff) + { + DoCast(m_creature, SPELL_WITHERING_ROAR); + uiWhiteringRoarTimer = urand(8000, 12000); + } + else + uiWhiteringRoarTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL npc_furlborgAI : public ScriptedAI +{ + npc_furlborgAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + uint32 uiChainLightingTimer; + uint32 uiCrazedTimer; + uint32 uiTerrifyingRoarTimer; + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + void Reset() + { + uiChainLightingTimer = 5000; + uiCrazedTimer = 10000; + uiTerrifyingRoarTimer = 15000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); + if (m_pInstance) - m_pInstance->SetData(TYPE_GORTOK, DONE); + if (Creature* pGortok = m_pInstance->GetSingleCreatureFromStorage(NPC_GORTOK)) + if (pGortok->isAlive()) + ((boss_gortokAI*)pGortok->AI())->Reset(); + } + + void JustReachedHome() + { + DoCast(m_creature, SPELL_FREEZE_ANIM); + } + + void AttackStart(Unit* who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); } - void EnterEvadeMode() + void JustDied(Unit* killer) { - ScriptedAI::EnterEvadeMode(); + if (m_pInstance) + { + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_STASIS_CONTROLLER)) + ((npc_gortok_orbAI*)pController->AI())->DoAction(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (uiChainLightingTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CHAIN_LIGHTING_N : SPELL_CHAIN_LIGHTING_H); + uiChainLightingTimer = 5000 + rand()%5000; + } + else + uiChainLightingTimer -= uiDiff; + + if (uiCrazedTimer <= uiDiff) + { + DoCast(m_creature, SPELL_CRAZED); + uiCrazedTimer = 8000 + rand()%4000; + } + else + uiCrazedTimer -= uiDiff; + + if (uiTerrifyingRoarTimer <= uiDiff) + { + DoCast(m_creature, SPELL_TERRIFYING_ROAR); + uiTerrifyingRoarTimer = 10000 + rand()%10000; + } + else + uiTerrifyingRoarTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL npc_worgenAI : public ScriptedAI +{ + npc_worgenAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + uint32 uiMortalWoundTimer; + uint32 uiEnrage1Timer; + uint32 uiEnrage2Timer; + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + void Reset() + { + uint32 uiMortalWoundTimer = 5000; + uint32 uiEnrage1Timer = 15000; + uint32 uiEnrage2Timer = 10000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); + if (m_pInstance) - m_pInstance->SetData(TYPE_GORTOK, FAIL); + if (Creature* pGortok = m_pInstance->GetSingleCreatureFromStorage(NPC_GORTOK)) + if (pGortok->isAlive()) + ((boss_gortokAI*)pGortok->AI())->Reset(); + } + + void JustReachedHome() + { + DoCast(m_creature, SPELL_FREEZE_ANIM); + } + + void AttackStart(Unit* who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); } - void BeginSubBossPhase() + void JustDied(Unit* killer) { if (m_pInstance) { - Creature* pTemp; - switch(m_uiPhase) - { - case PHASE_FRENZIED_WORGEN: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_WORGEN); - break; - } - case PHASE_RAVENOUS_FURLBORG: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_FURBOLG); - break; - } - case PHASE_MASSIVE_JORMUNGAR: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JORMUNGAR); - break; - } - case PHASE_FEROCIOUS_RHINO: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_RHINO); - break; - } - default: - break; - } - if (pTemp) - { - pTemp->RemoveAurasDueToSpell(SPELL_FREEZE); - pTemp->SetInCombatWithZone(); - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_STASIS_CONTROLLER)) + ((npc_gortok_orbAI*)pController->AI())->DoAction(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (uiMortalWoundTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_MORTAL_WOUND_N : SPELL_MORTAL_WOUND_H); + uiMortalWoundTimer = 3000 + rand()%4000; + } + else + uiMortalWoundTimer -= uiDiff; + + if (uiEnrage1Timer <= uiDiff) + { + DoCast(m_creature, SPELL_ENRAGE_1); + uiEnrage1Timer = 15000; + } + else + uiEnrage1Timer -= uiDiff; + + if (uiEnrage2Timer <= uiDiff) + { + DoCast(m_creature, SPELL_ENRAGE_2); + uiEnrage2Timer = 10000; } + else + uiEnrage2Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL npc_rhinoAI : public ScriptedAI +{ + npc_rhinoAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + uint32 uiStompTimer; + uint32 uiGoreTimer; + uint32 uiGrievousWoundTimer; + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + void Reset() + { + uiStompTimer = 10000; + uiGoreTimer = 15000; + uiGrievousWoundTimer = 20000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); + + if (m_pInstance) + if (Creature* pGortok = m_pInstance->GetSingleCreatureFromStorage(NPC_GORTOK)) + if (pGortok->isAlive()) + ((boss_gortokAI*)pGortok->AI())->Reset(); } - Phase getValityPhase() + void JustReachedHome() { - uint32 result = m_uiPhase; - ++result; - if (result > PHASE_FEROCIOUS_RHINO) - result = PHASE_FRENZIED_WORGEN; - return (Phase)result; + DoCast(m_creature, SPELL_FREEZE_ANIM); } - bool IsSubBossDead() + void AttackStart(Unit* who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void JustDied(Unit* killer) { - bool result = false; if (m_pInstance) { - Creature* pTemp; - switch(m_uiPhase) - { - case PHASE_FRENZIED_WORGEN: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_WORGEN); - break; - } - case PHASE_RAVENOUS_FURLBORG: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_FURBOLG); - break; - } - case PHASE_MASSIVE_JORMUNGAR: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_JORMUNGAR); - break; - } - case PHASE_FEROCIOUS_RHINO: - { - pTemp = m_pInstance->GetSingleCreatureFromStorage(NPC_RHINO); - break; - } - default: - break; - } - if (pTemp) - { - pTemp->RemoveAurasDueToSpell(SPELL_FREEZE); - if (pTemp->isDead()) - result = true; - } + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_STASIS_CONTROLLER)) + ((npc_gortok_orbAI*)pController->AI())->DoAction(); } - return result; } void UpdateAI(const uint32 uiDiff) { - switch(m_uiPhase) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (uiStompTimer <= uiDiff) { - case PHASE_BEGIN: - // Nothing - break; - case PHASE_FRENZIED_WORGEN: - case PHASE_RAVENOUS_FURLBORG: - case PHASE_MASSIVE_JORMUNGAR: - case PHASE_FEROCIOUS_RHINO: - switch(m_uiSubBossSteps) - { - case PHASE_SUB_BOSS_BEGIN: - { - ++m_uiSubBossCount; - BeginSubBossPhase(); - m_uiSubBossSteps = PHASE_SUB_BOSS_INFIGHT; - break; - } - case PHASE_SUB_BOSS_INFIGHT: - { - if (m_uiCheckForDeathSubBoss < uiDiff) - { - if (IsSubBossDead()) - { - m_uiSubBossSteps = PHASE_SUB_BOSS_END; - } - m_uiCheckForDeathSubBoss = 2000; - } - else - m_uiCheckForDeathSubBoss -= uiDiff; - - break; - } - case PHASE_SUB_BOSS_END: - { - if (m_uiSubBossCount >= m_uiSubBossMax) - { - m_uiPhase = PHASE_GORTOK_PALEHOOF; - m_creature->SetInCombatWithZone(); - return; - } - m_uiPhase = getValityPhase(); - m_uiSubBossSteps = PHASE_SUB_BOSS_BEGIN; - break; - } - default: - m_uiSubBossSteps = PHASE_SUB_BOSS_BEGIN; + DoCast(m_creature->getVictim(), SPELL_STOMP); + uiStompTimer = 8000 + rand()%4000; + } + else + uiStompTimer -= uiDiff; - } - break; - case PHASE_GORTOK_PALEHOOF: + if (uiGoreTimer <= uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_GORE_N : SPELL_GORE_H); + uiGoreTimer = 13000 + rand()%4000; + } + else + uiGoreTimer -= uiDiff; - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + if (uiGrievousWoundTimer <= uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_GRIEVOUS_WOUND_N : SPELL_GRIEVOUS_WOUND_H); + uiGrievousWoundTimer = 18000 + rand()%4000; + } + else + uiGrievousWoundTimer -= uiDiff; - if (m_uiWitheringRoar < uiDiff) - { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_WITHERING_ROAR : SPELL_WITHERING_ROAR_H) == CAST_OK) - m_uiWitheringRoar = urand(7000,11000); - } - else - m_uiWitheringRoar -= uiDiff; - - if (m_uiImpale < uiDiff) - { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, 0.0f, SELECT_FLAG_PLAYER)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H) == CAST_OK) - m_uiImpale = 9000; - } - } - else - m_uiImpale -= uiDiff; + DoMeleeAttackIfReady(); + } +}; - if (m_uiArcingSmash < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ARCING_SMASH) == CAST_OK) - m_uiArcingSmash = 5000; - } - else - m_uiArcingSmash -= uiDiff; - - DoMeleeAttackIfReady(); - break; - default: - m_uiPhase = PHASE_BEGIN; +struct MANGOS_DLL_DECL npc_jormungarAI : public ScriptedAI +{ + npc_jormungarAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + uint32 uiAcidSpitTimer; + uint32 uiAcidSplatterTimer; + uint32 uiPoisonBreathTimer; + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + void Reset() + { + uiAcidSpitTimer = 3000; + uiAcidSplatterTimer = 12000; + uiPoisonBreathTimer = 10000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); + + if (m_pInstance) + if (Creature* pGortok = m_pInstance->GetSingleCreatureFromStorage(NPC_GORTOK)) + if (pGortok->isAlive()) + ((boss_gortokAI*)pGortok->AI())->Reset(); + } + + void JustReachedHome() + { + DoCast(m_creature, SPELL_FREEZE_ANIM); + } + + void AttackStart(Unit* who) + { + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void JustDied(Unit* killer) + { + if (m_pInstance) + { + if (Creature* pController = m_pInstance->GetSingleCreatureFromStorage(NPC_STASIS_CONTROLLER)) + ((npc_gortok_orbAI*)pController->AI())->DoAction(); } } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (uiAcidSpitTimer <= uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ACID_SPIT); + uiAcidSpitTimer = 2000 + rand()%2000; + } + else + uiAcidSpitTimer -= uiDiff; + + if (uiAcidSplatterTimer <= uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_ACID_SPLATTER_N : SPELL_ACID_SPLATTER_H); + uiAcidSplatterTimer = 10000 + rand()%4000; + } + else + uiAcidSplatterTimer -= uiDiff; + + if (uiPoisonBreathTimer <= uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_POISON_BREATH_N : SPELL_POISON_BREATH_H); + uiPoisonBreathTimer = 8000 + rand()%4000; + } + else + uiPoisonBreathTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } }; +bool GOUse_gortok_generator(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* m_pInstance = (ScriptedInstance*)pPlayer->GetInstanceData(); + + if (m_pInstance && m_pInstance->GetData(TYPE_GORTOK) == NOT_STARTED) + { + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NO_INTERACT); + pGo->SetGoState(GO_STATE_ACTIVE); + Creature* pController = pGo->SummonCreature(NPC_STASIS_CONTROLLER, ORB_SPAWN_X, ORB_SPAWN_Y, ORB_Z, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + m_pInstance->SetData(TYPE_GORTOK, IN_PROGRESS); + } + return true; +} + CreatureAI* GetAI_boss_gortok(Creature* pCreature) { return new boss_gortokAI(pCreature); } -void AddSC_boss_gortok() +CreatureAI* GetAI_npc_worgen(Creature* pCreature) +{ + return new npc_worgenAI(pCreature); +} + +CreatureAI* GetAI_npc_furlborg(Creature* pCreature) +{ + return new npc_furlborgAI(pCreature); +} + +CreatureAI* GetAI_npc_rhino(Creature* pCreature) { - Script* pNewScript; + return new npc_rhinoAI(pCreature); +} - pNewScript = new Script; - pNewScript->Name = "boss_gortok"; - pNewScript->GetAI = &GetAI_boss_gortok; - pNewScript->RegisterSelf(); +CreatureAI* GetAI_npc_jormungar(Creature* pCreature) +{ + return new npc_jormungarAI(pCreature); +} + +CreatureAI* GetAI_npc_gortok_orb(Creature* pCreature) +{ + return new npc_gortok_orbAI(pCreature); +} + +void AddSC_boss_gortok() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_gortok"; + newscript->GetAI = &GetAI_boss_gortok; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_worgen"; + newscript->GetAI = &GetAI_npc_worgen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_furlborg"; + newscript->GetAI = &GetAI_npc_furlborg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_rhino"; + newscript->GetAI = &GetAI_npc_rhino; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jormungar"; + newscript->GetAI = &GetAI_npc_jormungar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_gortok_orb"; + newscript->GetAI = &GetAI_npc_gortok_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_gortok_generator"; + newscript->pGOUse=&GOUse_gortok_generator; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp b/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp index 8df5d1805c..be0693d6a3 100644 --- a/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -16,21 +16,13 @@ /* ScriptData SDName: Boss_Skadi -SD%Complete: 20% -SDComment: starts at trigger 4991 +SD%Complete: 95% +SDComment: TODO: harpoon spells not working 100% blizzlike SDCategory: Utgarde Pinnacle EndScriptData */ - -/* TODO -better fly script -remove hacks like the shoot at grauf -trigger mob should use summon spells -*/ #include "precompiled.h" #include "utgarde_pinnacle.h" -#include "Vehicle.h" -#include "MotionMaster.h" enum { @@ -46,6 +38,7 @@ enum SAY_DEATH = -1575028, SAY_DRAKE_DEATH = -1575029, EMOTE_HARPOON_RANGE = -1575030, + EMOTE_DRAKE_BREATH = -1575041, SPELL_CRUSH = 50234, SPELL_CRUSH_H = 59330, @@ -55,8 +48,8 @@ enum SPELL_POISONED_SPEAR = 50255, SPELL_POISONED_SPEAR_H = 59331, - - SPELL_SKADI_TELEPORT = 61790, + SPELL_POISONED = 50258, + SPELL_POISONED_H = 59334, // casted with base of creature 22515 (World Trigger), so we must make sure // to use the close one by the door leading further in to instance. @@ -65,79 +58,243 @@ enum SPELL_GAUNTLET_PERIODIC = 47546, // what is this? Unknown use/effect, but probably related - SPELL_LAUNCH_HARPOON = 48641, // this spell hit drake to reduce HP (force triggered from 48641) + SPELL_LAUNCH_HARPOON = 48642, // this spell hit drake to reduce HP (force triggered from 48641) + NPC_DUMMY_TARGET = 22515, + + MODEL_ID_INVISIBLE = 11686, + + ITEM_HARPOON = 37372, + SPELL_SUMMON_HARPOON = 56789, + + GO_HARPOON1 = 192175, + GO_HARPOON2 = 192176, + GO_HARPOON3 = 192177, + + ACHIEV_LODI_DODI = 1873, + ACHIEV_MY_GIRL_LIKES_TO_SKADI = 2156, // needs script support - SPELL_SUMMON_1 = 48631, - SPELL_SUMMON_2 = 48632, - SPELL_SUMMON_3 = 48633, - SPELL_SUMMON_4 = 48634, - SPELL_SUMMON_5 = 48635, - SPELL_SUMMON_6 = 48636, }; -#define HIT_GRAUF_MESSAGE "Ich habe Grauf getroffen" -/*###### -## boss_skadi -######*/ +uint32 goHarpoons[3] = +{ + GO_HARPOON1, + GO_HARPOON2, + GO_HARPOON3 +}; -enum CombatPhase +struct Locations { - FLYING, - SKADI + float x, y, z; + int id; }; -struct FlightPositionSkadi +static Locations MobSpawnLoc[] = { - float x, y,z; + {340.556f, -511.493f, 104.352f}, + {367.741f, -512.865f, 104.828f}, + {399.546f, -512.755f, 104.834f}, + {430.551f, -514.320f, 105.055f}, + {468.931f, -513.555f, 104.723f} }; -static FlightPositionSkadi FlightPosition[]= +static Locations BreathSpawnLocLeft[] = { - {341.740997f, -516.955017f, 104.668999f}, // Start - {293.299f, -505.95f, 142.03f}, // short time after start - {301.664f, -535.164f, 146.097f}, // rotating position - {526.896f, -546.387f, 119.209f}, // shoot position - // PONTOS DO BREACH - {485.4577f, -511.2515f, 115.3011f}, // Breath 1 - {435.1892f, -514.5232f, 118.6719f}, // Breath 1 + {481.4f, -517.6f}, + {471.7f, -517.2f}, + {463.2f, -515.7f}, + {453.6f, -517.2f}, + {443.6f, -519.4f}, + {433.5f, -519.4f}, + {424.8f, -520.9f}, + {415.7f, -518.3f}, + {406.1f, -516.9f}, + {396.7f, -514.9f}, + {387.3f, -515.3f}, + {378.2f, -517.0f}, + {368.6f, -517.9f}, + {358.7f, -517.6f}, + {348.3f, -516.6f}, + {338.0f, -516.4f}, + {327.7f, -515.1f}, + {317.7f, -514.7f}, + {307.1f, -514.9f}, +}; + +#define BREATH_TRIGGER_Z 104.6f +#define OFFSET_RIGHT_X 0.4f +#define OFFSET_RIGHT_Y 8.2f - {413.9327f, -540.9407f, 138.2614f}, // fly over the wall +enum waypoints +{ + END_BREATH = 0, + OUTSIDE_1 = 1, + OUTSIDE_2 = 2, + OUTSIDE_3 = 3, + HARPOONS = 4, + BREATH_L = 5, + BREATH_R = 6 +}; - {477.311981f, -509.296814f, 104.723083f}, // Postion where skadi "jump" after graufs death +static Locations waypoints[]= +{ + {340.2f, -510.5f, 120.8f, END_BREATH}, + {303.3f, -507.4f, 136.8f, OUTSIDE_1}, + {299.8f, -550.2f, 148.1f, OUTSIDE_2}, + {511.9f, -561.3f, 127.9f, OUTSIDE_3}, + {510.2f, -536.2f, 121.1f, HARPOONS}, + {483.5f, -519.8f, 122.9f, BREATH_L}, + {485.3f, -506.3f, 122.0f, BREATH_R} }; +/*###### +## boss_skadi +######*/ + struct MANGOS_DLL_DECL boss_skadiAI : public ScriptedAI { boss_skadiAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_pinnacle*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); Reset(); } - instance_pinnacle* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - CombatPhase m_CombatPhase; + //Land Phase + uint32 m_uiCrushTimer; + uint32 m_uiPoisonedSpearTimer; + uint32 m_uiWirlwhindTimer; + bool m_bIsLandPhase; + + //Event Phase + bool m_bIsInHarpoonRange; + uint32 m_uiIsInHarpoonRangeTimer; + + uint32 m_uiNextWaveTimer; + uint8 m_uiWaveCounter; + + uint32 m_uiGraufBreathTimer; + bool m_bGraufBreath; + uint8 m_uiBreathTrack; + uint8 m_uiBreathCount; - uint32 m_uiCrush; - uint32 m_uiWhirlwind; - uint32 m_uiPoisonedSpear; + uint32 m_uiEventTimer; // achievement timer + uint8 m_uiphase; + uint32 m_uiPlayerCheck_Timer; // check for player death + uint8 m_uiHarpoonHitsInPass; // count for achievement + + uint8 m_uiHarpoonHits; + bool m_bAchievement; void Reset() { - m_CombatPhase = SKADI; - m_uiCrush = 10000; - m_uiWhirlwind = urand(2000, 5000); - m_uiPoisonedSpear = 6000; - if (m_pInstance) + //Land Phase + m_uiCrushTimer = urand(5000,10000); + m_uiPoisonedSpearTimer = urand(5000,10000); + m_uiWirlwhindTimer = urand(5000,10000); + m_bIsLandPhase = false; + + //Event Phase + m_uiGraufBreathTimer = 30000; + m_uiIsInHarpoonRangeTimer = urand(5000,10000); + m_uiNextWaveTimer = urand(5000,10000); + m_uiWaveCounter = 0; + m_uiBreathCount = 0; + m_uiphase = 0; + m_bIsInHarpoonRange = false; + m_bGraufBreath = false; + m_uiPlayerCheck_Timer = 1000; + m_uiHarpoonHits = 0; + m_uiEventTimer = 0; + m_uiHarpoonHitsInPass = 0; + m_bAchievement = false; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->Unmount(); + + if(Creature* pGrauf = m_pInstance->GetSingleCreatureFromStorage(NPC_GRAUF)) { + pGrauf->Respawn(); + pGrauf->setFaction(14); + pGrauf->SetVisibility(VISIBILITY_ON); + } + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + } + + void JustReachedHome() + { + if (m_pInstance) m_pInstance->SetData(TYPE_SKADI, FAIL); - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_MY_GIRL_LOVES_SKADI_ALL_THE_TIME, false); - if (Creature* pGrauf = m_pInstance->GetSingleCreatureFromStorage(NPC_GRAUF)) + } + + void HarpoonHit() + { + if (m_bIsInHarpoonRange) + { + ++m_uiHarpoonHits; + if (++m_uiHarpoonHitsInPass >= 3) // achievement check, kill grauf(=3 harpoons) in 1 pass + m_bAchievement = true; + } + else + return; + + if (m_uiHarpoonHits == 1) + DoScriptText(SAY_DRAKE_HARPOON_1,m_creature); + else if (m_uiHarpoonHits == 2) + DoScriptText(SAY_DRAKE_HARPOON_2,m_creature); + } + + void AttackStart(Unit* pWho) + { + if (m_uiphase < 2) + return; + + if (!pWho || pWho == m_creature) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho, 0.0f); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(pWho) && + !m_uiphase && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 20)) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_SKADI, IN_PROGRESS); + + if(Creature* pGrauf = GetClosestCreatureWithEntry(m_creature,NPC_GRAUF, 20.f)) { - pGrauf->Respawn(); + pGrauf->setFaction(35); + pGrauf->SetVisibility(VISIBILITY_OFF); + pGrauf->DealDamage(pGrauf, pGrauf->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } + + DoScriptText(SAY_AGGRO, m_creature); + + m_creature->SetInCombatWithZone(); + m_creature->Mount(27043); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetWalk(false); + m_creature->SetLevitate(true); + m_creature->GetMotionMaster()->MovePoint(waypoints[END_BREATH].id, waypoints[END_BREATH].x, waypoints[END_BREATH].y, waypoints[END_BREATH].z); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_uiphase = 1; } } @@ -149,7 +306,6 @@ struct MANGOS_DLL_DECL boss_skadiAI : public ScriptedAI if (Creature* pGrauf = m_pInstance->GetSingleCreatureFromStorage(NPC_GRAUF)) { m_creature->EnterVehicle(pGrauf->GetVehicleKit(),0); - m_CombatPhase = FLYING; } } } @@ -170,250 +326,236 @@ struct MANGOS_DLL_DECL boss_skadiAI : public ScriptedAI if (m_pInstance) m_pInstance->SetData(TYPE_SKADI, DONE); + + if(!m_bIsRegularMode && m_pInstance) + { + if (m_uiEventTimer <= 180000) + m_pInstance->DoCompleteAchievement(ACHIEV_LODI_DODI); + + if (m_bAchievement) + m_pInstance->DoCompleteAchievement(ACHIEV_MY_GIRL_LIKES_TO_SKADI); + } } - void UpdateAI(const uint32 uiDiff) + void MovementInform(uint32 uiType, uint32 uiPointId) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - return; + if(uiType != POINT_MOTION_TYPE) + return; - switch (m_CombatPhase) + switch(uiPointId) { - case FLYING: - // Nothing + case END_BREATH: + m_creature->SetSpeedRate(MOVE_FLIGHT, 2.f, true); + m_bGraufBreath = false; + case OUTSIDE_1: + case OUTSIDE_2: + case OUTSIDE_3: + m_creature->GetMotionMaster()->MovePoint(++uiPointId,waypoints[uiPointId].x,waypoints[uiPointId].y,waypoints[uiPointId].z); break; - case SKADI: - { - - if (m_uiCrush < uiDiff) - { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CRUSH : SPELL_CRUSH_H) == CAST_OK) - m_uiCrush = 10000; - } - else - m_uiCrush -= uiDiff; - - if (m_uiWhirlwind < uiDiff) + case HARPOONS: + m_uiIsInHarpoonRangeTimer = 8000; + m_uiHarpoonHitsInPass = 0; + m_bIsInHarpoonRange = true; + DoScriptText(EMOTE_HARPOON_RANGE,m_creature); + break; + case BREATH_L: + case BREATH_R: + DoScriptText(EMOTE_DRAKE_BREATH,m_creature); + switch(urand(0, 2)) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_WHIRLWIND : SPELL_WHIRLWIND_H) == CAST_OK) - m_uiWhirlwind = urand(15000, 20000); + case 0: DoScriptText(SAY_DRAKEBREATH_1, m_creature); break; + case 1: DoScriptText(SAY_DRAKEBREATH_2, m_creature); break; + case 2: DoScriptText(SAY_DRAKEBREATH_3, m_creature); break; } - else - m_uiWhirlwind -= uiDiff; + m_creature->SetSpeedRate(MOVE_FLIGHT, 4.0f, true); + m_creature->GetMotionMaster()->MovePoint(END_BREATH,waypoints[END_BREATH].x,waypoints[END_BREATH].y,waypoints[END_BREATH].z); + m_uiGraufBreathTimer = 200; + m_uiBreathCount = 0; + m_bGraufBreath = true; + break; + default: break; + } + } - if (m_uiPoisonedSpear < uiDiff) + void SpawnMobs(uint8 uiSpot) + { + uint8 maxSpawn = (m_bIsRegularMode ? 4 : 5); + for(uint8 i = 0; i < maxSpawn; ++i) + { + Creature* pTemp; + switch (rand()%3) + { + case 0: pTemp = m_creature->SummonCreature(NPC_YMIRJAR_WARRIOR, MobSpawnLoc[uiSpot].x+rand()%5, MobSpawnLoc[uiSpot].y+rand()%5, MobSpawnLoc[uiSpot].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 1: pTemp = m_creature->SummonCreature(NPC_YMIRJAR_WITCH_DOCTOR, MobSpawnLoc[uiSpot].x+rand()%5, MobSpawnLoc[uiSpot].y+rand()%5, MobSpawnLoc[uiSpot].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 2: pTemp = m_creature->SummonCreature(NPC_YMIRJAR_HARPOONER, MobSpawnLoc[uiSpot].x+rand()%5, MobSpawnLoc[uiSpot].y+rand()%5, MobSpawnLoc[uiSpot].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + } + if (pTemp) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, 0.0f, SELECT_FLAG_PLAYER)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_POISONED_SPEAR : SPELL_POISONED_SPEAR_H) == CAST_OK) - m_uiPoisonedSpear = 6000; - } + pTemp->AddThreat(pTarget, 0.0f); + pTemp->AI()->AttackStart(pTarget); } - else - m_uiPoisonedSpear -= uiDiff; - - DoMeleeAttackIfReady(); } } } -}; - -CreatureAI* GetAI_boss_skadi(Creature* pCreature) -{ - return new boss_skadiAI(pCreature); -} - -struct boss_skadi_graufAI : public ScriptedAI -{ - boss_skadi_graufAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_pinnacle*)pCreature->GetInstanceData(); - vehicle = m_creature->GetVehicleKit(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - SetCombatMovement(false); - } - - instance_pinnacle* m_pInstance; - VehicleKit* vehicle; - bool m_bIsRegularMode; - - bool isInFlight; - uint32 uiWaypointId; - uint32 uiMovementTimer; - - uint8 m_uiHarpoonHitCounter; - uint8 m_uiHarpoonHitCounterAchiev; - uint32 m_uiSummon; - - void Reset() - { - isInFlight = false; - uiWaypointId = 0; - uiMovementTimer = 1000; - m_uiHarpoonHitCounter = 0; - m_uiHarpoonHitCounterAchiev = 0; - m_uiSummon = 5000; - } - void JustReachedHome() + void SummonedCreatureJustDied(Creature* pCreature) { - if (Unit* passenger = vehicle->GetPassenger(0)) - { - passenger->ExitVehicle(); - if (passenger->GetTypeId() != TYPEID_PLAYER) - ((Creature*)passenger)->AI()->EnterEvadeMode(); - } - // make boss land - m_creature->SetLevitate(false); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); - m_creature->SetWalk(true); + if (pCreature->GetEntry() == NPC_YMIRJAR_HARPOONER) + if (Creature* pDummyCaster = pCreature->SummonCreature(1921, pCreature->GetPositionX(), pCreature->GetPositionY(), pCreature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 2000)) + { + pDummyCaster->SetDisplayId(MODEL_ID_INVISIBLE); + pDummyCaster->setFaction(35); + pDummyCaster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SpellEntry* pTempSpell = const_cast(GetSpellStore()->LookupEntry(SPELL_SUMMON_HARPOON)); + if (pTempSpell) + { + pTempSpell->Effect[EFFECT_INDEX_2] = 0; + pDummyCaster->CastSpell(pDummyCaster, pTempSpell, true); + } + } } - void MovementInform(uint32 uiMovementType, uint32 uiData) + void UpdateAI(const uint32 uiDiff) { - if (uiMovementType != POINT_MOTION_TYPE) - return; + if (m_uiphase == 0) + return; + else + m_uiEventTimer += uiDiff; //Achievement counter - switch(uiData) + // Flying & adds + if (m_uiphase == 1) { - case 1: // short after start - case 2: // rotating position - ++uiWaypointId; - uiMovementTimer = 1000; - break; - case 3: // shoot position + if (m_uiPlayerCheck_Timer < uiDiff) // check player alive { - ++uiWaypointId; - uiMovementTimer = 15000; - break; - } - case 4: // Breath 1 - m_uiHarpoonHitCounterAchiev = 0; - ++uiWaypointId; - if (m_pInstance) + Map *map = m_creature->GetMap(); + if (m_pInstance->GetData(TYPE_SKADI) == IN_PROGRESS) { - if (Creature* pSkadi = m_pInstance->GetSingleCreatureFromStorage(NPC_SKADI)) - DoScriptText(SAY_DRAKEBREATH_1, pSkadi); - m_pInstance->DoMakeFreezingCloud(); + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + bool bIsAlive = false; + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive() && !i->getSource()->isGameMaster()) + bIsAlive = true; + + if (!bIsAlive) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->StopMoving(); + EnterEvadeMode(); + return; + } } - uiMovementTimer = 1000; - break; - case 5: // Breath 2 - ++uiWaypointId; - if (m_pInstance) + m_uiPlayerCheck_Timer = 1000; + } + else + m_uiPlayerCheck_Timer -= uiDiff; + + if (m_bIsInHarpoonRange) + if (m_uiIsInHarpoonRangeTimer < uiDiff) { - if (Creature* pSkadi = m_pInstance->GetSingleCreatureFromStorage(NPC_SKADI)) - DoScriptText(SAY_DRAKEBREATH_2, pSkadi); + m_bIsInHarpoonRange = false; + m_uiBreathTrack = urand(BREATH_L,BREATH_R); + m_creature->GetMotionMaster()->MovePoint(waypoints[m_uiBreathTrack].id, waypoints[m_uiBreathTrack].x, waypoints[m_uiBreathTrack].y, waypoints[m_uiBreathTrack].z); } - uiMovementTimer = 1000; - break; - case 6: // fly over wall - uiWaypointId= 3; - if (m_pInstance) + else + m_uiIsInHarpoonRangeTimer -= uiDiff; + + if (m_bGraufBreath) + if(m_uiGraufBreathTimer < uiDiff) { - if (Creature* pSkadi = m_pInstance->GetSingleCreatureFromStorage(NPC_SKADI)) - DoScriptText(SAY_DRAKEBREATH_3, pSkadi); - } - uiMovementTimer = 1000; - break; - default: - uiWaypointId = 0; - uiMovementTimer = 1000; - break; - } + float x = m_uiBreathTrack == BREATH_L ? BreathSpawnLocLeft[m_uiBreathCount].x : BreathSpawnLocLeft[m_uiBreathCount].x + OFFSET_RIGHT_X; + float y = m_uiBreathTrack == BREATH_L ? BreathSpawnLocLeft[m_uiBreathCount].y : BreathSpawnLocLeft[m_uiBreathCount].y + OFFSET_RIGHT_Y; + if (Creature* pCreature = m_creature->SummonCreature(NPC_FLAME_BREATH_TRIGGER,x,y,BREATH_TRIGGER_Z,0,TEMPSUMMON_TIMED_DESPAWN,15000)) + { + pCreature->setFaction(14); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + pCreature->CastSpell(pCreature,SPELL_FREEZING_CLOUD,true); + } - if ( uiWaypointId > 6 ) - error_log("SD2: Instance Pinnacle: Skadi Grauf try move to point %u!", uiWaypointId); - } + if (++m_uiBreathCount > 18) + m_bGraufBreath = false; - void JustDied(Unit* pTarget) - { - if (m_pInstance) - { - if (Creature* pSkadi = m_pInstance->GetSingleCreatureFromStorage(NPC_SKADI)) + m_uiGraufBreathTimer = 200; + } + else + m_uiGraufBreathTimer -= uiDiff; + + if(m_uiNextWaveTimer < uiDiff) // spawn mobs { - DoScriptText(SAY_DRAKE_DEATH, pSkadi); + if (m_uiWaveCounter < 4) + ++m_uiWaveCounter; + SpawnMobs(m_uiWaveCounter); + m_uiNextWaveTimer = urand(20000,30000); } - if (m_uiHarpoonHitCounterAchiev == m_uiHarpoonHitCounter) + else + m_uiNextWaveTimer -= uiDiff; + + if (m_uiHarpoonHits >= 3) // start land phase { - m_pInstance->SetSpecialAchievementCriteria(TYPE_ACHIEV_MY_GIRL_LOVES_SKADI_ALL_THE_TIME, true); + m_creature->GetMotionMaster()->Clear(); + m_creature->Unmount(); + m_uiphase = 2; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_DRAKE_DEATH, m_creature); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + AttackStart(pTarget); } } - } - - void HarpoonHit() - { - ++m_uiHarpoonHitCounter; - ++m_uiHarpoonHitCounterAchiev; - if (m_uiHarpoonHitCounter > 6) + // Land & attack + else if (m_uiphase == 2) { - if (m_pInstance) + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiPoisonedSpearTimer < uiDiff) { - if (Creature* pSkadi = m_pInstance->GetSingleCreatureFromStorage(NPC_SKADI)) + if(Unit* pPlayer = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) { - pSkadi->ExitVehicle(); - pSkadi->CastSpell(pSkadi, SPELL_SKADI_TELEPORT, true); - if (boss_skadiAI* skadiAI = dynamic_cast (pSkadi->AI())) - { - skadiAI->m_CombatPhase = SKADI; - } + if (DoCastSpellIfCan(pPlayer, m_bIsRegularMode ? SPELL_POISONED_SPEAR : SPELL_POISONED_SPEAR_H, false) == CAST_OK) + pPlayer->CastSpell(pPlayer, m_bIsRegularMode ? SPELL_POISONED : SPELL_POISONED_H, true); } + m_uiPoisonedSpearTimer = urand(10000,20000); } - m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); - } - } - - void UpdateAI(const uint32 uiDiff) - { - if (!m_creature->getVictim() || (!uiWaypointId && !m_creature->SelectHostileTarget())) - return; + else + m_uiPoisonedSpearTimer -= uiDiff; - if (vehicle->GetPassenger(0) && !isInFlight) - { - isInFlight = true; - m_creature->SetLevitate(true); - m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); - m_creature->SetWalk(false); - uiWaypointId = 1; - uiMovementTimer = 1000; - } - - if (isInFlight && m_creature->isAlive()) - { - if (uiMovementTimer < uiDiff) + if(m_uiCrushTimer < uiDiff) { - m_creature->GetMotionMaster()->Clear(true,true); - if ( uiWaypointId < 7) - m_creature->GetMotionMaster()->MovePoint(uiWaypointId, FlightPosition[uiWaypointId].x, FlightPosition[uiWaypointId].y, FlightPosition[uiWaypointId].z); - uiMovementTimer = 20000; + DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CRUSH : SPELL_CRUSH_H, false); + m_uiCrushTimer = urand(10000,15000); } - else - uiMovementTimer -= uiDiff; + else + m_uiCrushTimer -= uiDiff; - if (m_uiSummon < uiDiff) + if(m_uiWirlwhindTimer < uiDiff) { - if (Creature* pTemp = m_creature->SummonCreature(NPC_YMIRJAR_WARRIOR, 471.0f +irand(-5,5), -506.0f+irand(-5,5), 105.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) - pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_creature->SummonCreature(NPC_YMIRJAR_HARPOONER, 471.0f+irand(-5,5), -506.0f+irand(-5,5), 105.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) - pTemp->SetInCombatWithZone(); - if (Creature* pTemp = m_creature->SummonCreature(NPC_YMIRJAR_WITCH_DOCTOR, 471.0f+irand(-5,5), -506.0f+irand(-5,5), 105.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT_OR_DEAD_DESPAWN, 120000)) - pTemp->SetInCombatWithZone(); - m_uiSummon = m_bIsRegularMode ? 30000 : 25000; + DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_WHIRLWIND : SPELL_WHIRLWIND_H, false); + m_uiWirlwhindTimer = urand(30000,45000); } else - m_uiSummon -= uiDiff; + m_uiWirlwhindTimer -= uiDiff; } + + DoMeleeAttackIfReady(); } }; -CreatureAI* GetAI_boss_skadi_grauf(Creature* pCreature) +CreatureAI* GetAI_boss_skadi(Creature* pCreature) { - return new boss_skadi_graufAI(pCreature); + return new boss_skadiAI(pCreature); } bool AreaTrigger_at_skadi(Player* pPlayer, AreaTriggerEntry const* pAt) { - if (instance_pinnacle* pInstance = (instance_pinnacle*)pPlayer->GetInstanceData()) + if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData()) { if (pInstance->GetData(TYPE_SKADI) == NOT_STARTED) pInstance->SetData(TYPE_SKADI, SPECIAL); @@ -422,46 +564,51 @@ bool AreaTrigger_at_skadi(Player* pPlayer, AreaTriggerEntry const* pAt) return false; } -bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) +bool GOHello_go_skadi_harpoonlauncher(Player* pPlayer, GameObject* pGo) { - if (instance_pinnacle* pInstance = (instance_pinnacle*)pGO->GetInstanceData()) + if (Creature* pSkadi = GetClosestCreatureWithEntry(pGo, NPC_SKADI, 100)) { - if (Creature* pGrauf = pInstance->GetSingleCreatureFromStorage(NPC_GRAUF)) - { - if (pGO->HasInArc(M_PI_F, pGrauf)) - { - if (boss_skadi_graufAI* graufAI = (boss_skadi_graufAI*)pGrauf->AI()) - { - graufAI->HarpoonHit(); - pPlayer->MonsterSay(HIT_GRAUF_MESSAGE,LANG_UNIVERSAL); - } - } - } + if (boss_skadiAI* pSkadiAI = dynamic_cast(pSkadi->AI())) + pSkadiAI->HarpoonHit(); + pPlayer->CastSpell(pSkadi, SPELL_LAUNCH_HARPOON, true); } return true; } +// harpoons +bool GOUse_skadi_harpoon(Player* pPlayer, GameObject* pGo) +{ + if (pPlayer) + if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_HARPOON, 1)) + { + pPlayer->SendNewItem(pItem, 1, true, false); + pGo->Delete(); + } + + return true; +} + void AddSC_boss_skadi() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_skadi"; - pNewScript->GetAI = &GetAI_boss_skadi; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_skadi_grauf"; - pNewScript->GetAI = &GetAI_boss_skadi_grauf; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "at_skadi"; - pNewScript->pAreaTrigger = &AreaTrigger_at_skadi; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "harpoon_Skadi"; - pNewScript->pGOUse = &GOHello_go_harpoon_launcher; - pNewScript->RegisterSelf(); + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skadi"; + newscript->GetAI = &GetAI_boss_skadi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "at_skadi"; + newscript->pAreaTrigger = &AreaTrigger_at_skadi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_skadi_harpoon"; + newscript->pGOUse=&GOUse_skadi_harpoon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_skadi_harpoonlauncher"; + newscript->pGOUse = &GOHello_go_skadi_harpoonlauncher; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp b/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp index ef96f0be8b..2d38b8ef69 100644 --- a/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2012 ScriptDev2 +/* Copyright (C) 2006 - 2011 ScriptDev2 * 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 @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss_Svala -SD%Complete: 30% -SDComment: The way spells for intro works could use more research. +SD%Complete: 90% +SDComment: TODO: Call Flames need correct spell, some visual bugs, the way spells for intro works could use more research. SDCategory: Utgarde Pinnacle EndScriptData */ @@ -45,8 +45,9 @@ enum NPC_SVALA_SORROW = 26668, NPC_ARTHAS_IMAGE = 29280, + NPC_SPECTATOR = 26667, NPC_RITUAL_TARGET = 27327, - NPC_PARALYSER = 27281, + NPC_RITUAL_CHANNELER = 27281, SPELL_ARTHAS_VISUAL = 54134, @@ -56,65 +57,97 @@ enum SPELL_TRANSFORMING_CHANNEL = 54142, SPELL_RITUAL_OF_SWORD = 48276, - SPELL_CALL_FLAMES = 48258, + SPELL_RITUAL_STRIKE_TRIGGER = 48331, // triggers 48277 & 59930, needs NPC_RITUAL_TARGET as spell_script_target + SPELL_RITUAL_STRIKE_EFF_1 = 48277, + SPELL_RITUAL_STRIKE_EFF_2 = 59930, + SPELL_RITUAL_CHANNELER_1 = 48271, + SPELL_RITUAL_CHANNELER_2 = 48274, + SPELL_RITUAL_CHANNELER_3 = 48275, + + SPELL_CALL_FLAMES = 48258, // caster effect only, triggers event 17841 SPELL_SINISTER_STRIKE = 15667, SPELL_SINISTER_STRIKE_H = 59409, + // used by channelers + SPELL_SHADOWS_IN_THE_DARK = 59407, SPELL_PARALYZE = 48278, + + ACHIEV_THE_INCREDIBLE_HULK = 2043 }; /*###### ## boss_svala ######*/ +static const float spectatorWP[2][3] = +{ + {267.8f,-346.7f,86.5f}, + {236.2f,-345.2f,84.3f} +}; + struct MANGOS_DLL_DECL boss_svalaAI : public ScriptedAI { boss_svalaAI(Creature* pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_pinnacle*)pCreature->GetInstanceData(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); m_bIsIntroDone = false; Reset(); } - instance_pinnacle* m_pInstance; + ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - ObjectGuid ArthasGuid; + ObjectGuid m_uiArthasGUID; + ObjectGuid m_uiChanneler1GUID; + ObjectGuid m_uiChanneler2GUID; + ObjectGuid m_uiChanneler3GUID; + ObjectGuid m_uiRitualVictimGUID; bool m_bIsIntroDone; uint32 m_uiIntroTimer; uint32 m_uiIntroCount; - - uint32 m_uiSinisterStrike; + uint32 m_uiSinisterStrikeTimer; + uint8 m_uiRitualCount; + uint8 m_uiRitualProgress; uint32 m_uiCallFlamesTimer; - uint32 m_uiMoveToTarget; - float m_uiRitualPercent; void Reset() { + m_uiArthasGUID.Clear(); + m_uiChanneler1GUID.Clear(); + m_uiChanneler2GUID.Clear(); + m_uiChanneler3GUID.Clear(); + m_uiRitualVictimGUID.Clear(); + m_uiIntroTimer = 2500; m_uiIntroCount = 0; + m_uiSinisterStrikeTimer = 2000; + m_uiRitualCount = 0; + m_uiRitualProgress = 0; + m_uiCallFlamesTimer = 5000; - m_uiSinisterStrike = 2000; - m_uiCallFlamesTimer = urand(10000, 15000); - m_uiMoveToTarget = 0; - m_uiRitualPercent = 75; - - if (m_creature->isAlive() && m_pInstance && m_pInstance->GetData(TYPE_SVALA) > IN_PROGRESS) + if (m_pInstance && m_pInstance->GetData(TYPE_SVALA) > IN_PROGRESS) { + m_bIsIntroDone = true; + if (m_creature->GetEntry() != NPC_SVALA_SORROW) m_creature->UpdateEntry(NPC_SVALA_SORROW); + m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); + m_creature->SetLevitate(true); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - m_bIsIntroDone = true; + } + else + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } } void JustReachedHome() { - DoMoveToPosition(); + if (m_pInstance) + m_pInstance->SetData(TYPE_SVALA, FAIL); } void MoveInLineOfSight(Unit* pWho) @@ -130,8 +163,19 @@ struct MANGOS_DLL_DECL boss_svalaAI : public ScriptedAI // we assume m_creature is spawned in proper location m_creature->SummonCreature(NPC_ARTHAS_IMAGE, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000); - } + // spectators flee event + std::list lspectatorList; + GetCreatureListWithEntryInGrid(lspectatorList, m_creature, NPC_SPECTATOR, 100.0f); + for(std::list::iterator itr = lspectatorList.begin(); itr != lspectatorList.end(); ++itr) + { + if ((*itr)->isAlive()) + { + (*itr)->SetWalk(false); + (*itr)->GetMotionMaster()->MovePoint(1,spectatorWP[0][0],spectatorWP[0][1],spectatorWP[0][2]); + } + } + } return; } @@ -140,7 +184,8 @@ struct MANGOS_DLL_DECL boss_svalaAI : public ScriptedAI void Aggro(Unit* pWho) { - //m_creature->SetLevitate(false); + m_creature->SetLevitate(false); + DoScriptText(SAY_AGGRO, m_creature); } @@ -149,19 +194,28 @@ struct MANGOS_DLL_DECL boss_svalaAI : public ScriptedAI if (pSummoned->GetEntry() == NPC_ARTHAS_IMAGE) { pSummoned->CastSpell(pSummoned, SPELL_ARTHAS_VISUAL, true); - ArthasGuid = pSummoned->GetObjectGuid(); + m_uiArthasGUID = pSummoned->GetObjectGuid(); pSummoned->SetFacingToObject(m_creature); } } + void SummonedCreatureDespawn(Creature* pDespawned) + { + if (pDespawned->GetEntry() == NPC_ARTHAS_IMAGE) + m_uiArthasGUID.Clear(); + } + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) { if (pSpell->Id == SPELL_TRANSFORMING) { - if (Creature* pArthas = m_creature->GetMap()->GetCreature(ArthasGuid)) + if (Creature* pArthas = m_creature->GetMap()->GetCreature(m_uiArthasGUID)) pArthas->InterruptNonMeleeSpells(true); m_creature->UpdateEntry(NPC_SVALA_SORROW); + m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2); + m_creature->SetLevitate(true); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } } @@ -173,6 +227,9 @@ struct MANGOS_DLL_DECL boss_svalaAI : public ScriptedAI case 1: DoScriptText(SAY_SLAY_2, m_creature); break; case 2: DoScriptText(SAY_SLAY_3, m_creature); break; } + + if (!m_bIsRegularMode && pVictim->GetEntry() == NPC_SCOURGE_HULK && m_pInstance) + m_pInstance->DoCompleteAchievement(ACHIEV_THE_INCREDIBLE_HULK); } void JustDied(Unit* pKiller) @@ -189,155 +246,236 @@ struct MANGOS_DLL_DECL boss_svalaAI : public ScriptedAI m_creature->GetRespawnCoord(fX, fY, fZ); m_creature->SetLevitate(true); - m_creature->GetMotionMaster()->MovePoint(0, fX, fY, fZ + 5.0f); + + if (m_uiRitualProgress == 1) + m_creature->GetMotionMaster()->MovePoint(1,fX,fY,fZ+8.f); + else + { +// m_creature->MonsterMoveWithSpeed(fX, fY, fZ + 5.0f, m_uiIntroTimer); + m_creature->MonsterMoveWithSpeed(fX, fY, fZ + 5.0f, 3); + m_creature->GetMap()->CreatureRelocation(m_creature, fX, fY, fZ + 5.0f, m_creature->GetOrientation()); + } + } + + void MovementInform(uint32 uiMotionType, uint32 uiPointId) + { + if (m_uiRitualProgress == 1 && uiMotionType == POINT_MOTION_TYPE && uiPointId == 1) + { + m_uiRitualProgress = 2; + } + } + + void SpellHitTarget (Unit* pUnit, const SpellEntry* pSpellEntry) + { + if (pSpellEntry->Id == SPELL_RITUAL_STRIKE_EFF_1) + { + m_uiRitualProgress = 4; + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiRitualVictimGUID)) + { + pVictim->DealDamage(pVictim, pVictim->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_uiRitualVictimGUID.Clear(); + } + if (Creature* pChanneler1 = m_creature->GetMap()->GetCreature(m_uiChanneler1GUID)) + pChanneler1->ForcedDespawn(); + if (Creature* pChanneler2 = m_creature->GetMap()->GetCreature(m_uiChanneler2GUID)) + pChanneler2->ForcedDespawn(); + if (Creature* pChanneler3 = m_creature->GetMap()->GetCreature(m_uiChanneler3GUID)) + pChanneler3->ForcedDespawn(); + } } void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) { + if (m_bIsIntroDone) return; - if (Creature* pArthas = m_creature->GetMap()->GetCreature(ArthasGuid)) + if (Creature* pArthas = m_creature->GetMap()->GetCreature(m_uiArthasGUID)) { - if (pArthas->isAlive()) + if (m_uiIntroTimer < uiDiff) { - if (m_uiIntroTimer < uiDiff) + m_uiIntroTimer = 10000; + + switch(m_uiIntroCount) { - m_uiIntroTimer = 10000; - - switch(m_uiIntroCount) - { - case 0: - DoScriptText(SAY_INTRO_1, m_creature); - break; - case 1: - DoScriptText(SAY_INTRO_2_ARTHAS, pArthas); - break; - case 2: - pArthas->CastSpell(m_creature, SPELL_TRANSFORMING_CHANNEL, false); - m_creature->CastSpell(m_creature, SPELL_TRANSFORMING_FLOATING, false); - DoMoveToPosition(); - break; - case 3: - m_creature->CastSpell(m_creature, SPELL_TRANSFORMING, false); - DoScriptText(SAY_INTRO_3, m_creature); - break; - case 4: - DoScriptText(SAY_INTRO_4_ARTHAS, pArthas); - break; - case 5: - DoScriptText(SAY_INTRO_5, m_creature); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->RemoveAurasDueToSpell(SPELL_TRANSFORMING_FLOATING); - m_bIsIntroDone = true; - break; - } - - ++m_uiIntroCount; + case 0: + DoScriptText(SAY_INTRO_1, m_creature); + break; + case 1: + DoScriptText(SAY_INTRO_2_ARTHAS, pArthas); + break; + case 2: + pArthas->CastSpell(m_creature, SPELL_TRANSFORMING_CHANNEL, false); + m_creature->CastSpell(m_creature, SPELL_TRANSFORMING_FLOATING, false); + DoMoveToPosition(); + break; + case 3: + m_creature->CastSpell(m_creature, SPELL_TRANSFORMING, false); + DoScriptText(SAY_INTRO_3, m_creature); + break; + case 4: + DoScriptText(SAY_INTRO_4_ARTHAS, pArthas); + break; + case 5: + DoScriptText(SAY_INTRO_5, m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsIntroDone = true; + break; } - else - m_uiIntroTimer -= uiDiff; + + ++m_uiIntroCount; } + else + m_uiIntroTimer -= uiDiff; } return; } - if (m_uiSinisterStrike < uiDiff) + if ((m_uiRitualCount == 0 && m_creature->GetHealthPercent() < 75.f) || + (m_uiRitualCount == 1 && m_creature->GetHealthPercent() < 50.f) || + (m_uiRitualCount == 2 && m_creature->GetHealthPercent() < 25.f)) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SINISTER_STRIKE : SPELL_SINISTER_STRIKE_H) == CAST_OK) - m_uiSinisterStrike = urand(5000, 7000); - } - else - m_uiSinisterStrike -= uiDiff; + ++m_uiRitualCount; + m_uiRitualProgress = 1; + DoMoveToPosition(); - if(m_uiCallFlamesTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_CALL_FLAMES) == CAST_OK) - m_uiCallFlamesTimer = urand(10000, 15000); } - else - m_uiCallFlamesTimer -= uiDiff; - if (m_creature->GetHealthPercent() < m_uiRitualPercent) + if (m_uiRitualProgress == 2) { - if (DoCastSpellIfCan(m_creature, SPELL_RITUAL_OF_SWORD) == CAST_OK) + m_creature->StopMoving(); + m_creature->GetMotionMaster()->MoveIdle(); + + // crap to select a random player + Map::PlayerList const &pPlayers = m_creature->GetMap()->GetPlayers(); + std::vector list; + list.clear(); + + for(Map::PlayerList::const_iterator i = pPlayers.begin(); i != pPlayers.end(); ++i) + if (Player* player = i->getSource()) { - m_uiRitualPercent -= 25.0f; + if (!player->isAlive() || player->isGameMaster()) + continue; + + list.push_back(player); } - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_svala(Creature* pCreature) -{ - return new boss_svalaAI(pCreature); -} -struct MANGOS_DLL_DECL npc_paralyzerAI : public ScriptedAI -{ - npc_paralyzerAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = (instance_pinnacle*)pCreature->GetInstanceData(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); - Reset(); - } + Player* pVictim; + if (!list.empty()) + { + pVictim = list[urand(0,list.size() - 1)]; + } - instance_pinnacle* m_pInstance; - bool m_bIsRegularMode; + if (!pVictim) + return; - uint32 spellTimer; + // finally we have our victim.. + m_uiRitualVictimGUID = pVictim->GetObjectGuid(); - void Reset() - { - spellTimer = 200; - } + // spawn ritual channelers + m_creature->CastSpell(m_creature, SPELL_RITUAL_CHANNELER_1, true); + m_creature->CastSpell(m_creature, SPELL_RITUAL_CHANNELER_2, true); + m_creature->CastSpell(m_creature, SPELL_RITUAL_CHANNELER_3, true); - void UpdateAI(const uint32 uiDiff) - { - if (spellTimer < uiDiff) - { - if (DoCastSpellIfCan(m_creature, SPELL_PARALYZE) == CAST_OK) - spellTimer = 40000; + // teleport selected player + float fX,fY,fZ; + m_creature->GetRespawnCoord(fX,fY,fZ); + pVictim->NearTeleportTo(fX,fY,fZ,pVictim->GetOrientation()); + + // cast ritual channelers spells + int count = 0; + std::list lChannelerList; + GetCreatureListWithEntryInGrid(lChannelerList, m_creature, NPC_RITUAL_CHANNELER, 100.0f); + for(std::list::iterator itr = lChannelerList.begin(); itr != lChannelerList.end(); ++itr) + { + if (!m_bIsRegularMode) + (*itr)->CastSpell((*itr),SPELL_SHADOWS_IN_THE_DARK, true); + (*itr)->CastSpell(pVictim,SPELL_PARALYZE,true); + + switch(++count) + { + case 1: m_uiChanneler1GUID = (*itr)->GetObjectGuid(); break; + case 2: m_uiChanneler2GUID = (*itr)->GetObjectGuid(); break; + case 3: m_uiChanneler3GUID = (*itr)->GetObjectGuid(); break; + } + } + + m_creature->CastSpell(pVictim,SPELL_RITUAL_STRIKE_TRIGGER,true); + m_uiRitualProgress = 3; } - else - spellTimer -= uiDiff; - } -}; + else if (m_uiRitualProgress == 3) + { + m_creature->StopMoving(); + m_creature->GetMotionMaster()->MoveIdle(); -CreatureAI* GetAI_npc_paralyzer(Creature* pCreature) -{ - return new npc_paralyzerAI(pCreature); -} + bool allChannelersDead = true; -struct MANGOS_DLL_DECL npc_ritual_targetAI : public ScriptedAI -{ - npc_ritual_targetAI(Creature* pCreature) : ScriptedAI(pCreature) - { - Reset(); - } + std::list lChannelerList; + GetCreatureListWithEntryInGrid(lChannelerList, m_creature, NPC_RITUAL_CHANNELER, 100.0f); + if (!lChannelerList.empty()) + for (std::list::iterator itr = lChannelerList.begin(); itr != lChannelerList.end(); ++itr) + { + if((*itr)->isAlive()) + { + allChannelersDead = false; break; + } + } - void AttackStart(Unit* pWho){} + if (allChannelersDead) + m_uiRitualProgress = 4; - void Reset(){} + return; + } + else if (m_uiRitualProgress == 4) + { + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_uiRitualProgress = 0; + } - void UpdateAI(const uint32 uiDiff){} -}; + if (m_uiSinisterStrikeTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(),m_bIsRegularMode ? SPELL_SINISTER_STRIKE : SPELL_SINISTER_STRIKE_H); + m_uiSinisterStrikeTimer = urand(4000,7000); + } + else + m_uiSinisterStrikeTimer -= uiDiff; + if (m_uiCallFlamesTimer < uiDiff) + { + if (DoCastSpellIfCan(m_creature,SPELL_CALL_FLAMES) == CAST_OK) // hack for spell damage.. spell that is really used is unknown to me + { + std::list lBrazierList; + GetCreatureListWithEntryInGrid(lBrazierList, m_creature, NPC_FLAME_BRAZIER, 120.0f); + if (!lBrazierList.empty()) + for(std::list::iterator itr = lBrazierList.begin(); itr != lBrazierList.end(); ++itr) + { + uint32 dmg = urand(1900,2600); + if (!m_bIsRegularMode) + dmg *= 2; + if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + m_creature->DealDamage(pVictim,dmg,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_FIRE,NULL, false); + } + } + m_uiCallFlamesTimer = urand(5000,8000); + } + else + m_uiCallFlamesTimer -= uiDiff; + DoMeleeAttackIfReady(); + } +}; -CreatureAI* GetAI_ritual_target(Creature* pCreature) +CreatureAI* GetAI_boss_svala(Creature* pCreature) { - return new npc_ritual_targetAI(pCreature); + return new boss_svalaAI(pCreature); } - bool AreaTrigger_at_svala_intro(Player* pPlayer, AreaTriggerEntry const* pAt) { - if (instance_pinnacle* pInstance = (instance_pinnacle*)pPlayer->GetInstanceData()) + if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData()) { if (pInstance->GetData(TYPE_SVALA) == NOT_STARTED) pInstance->SetData(TYPE_SVALA, IN_PROGRESS); @@ -346,42 +484,50 @@ bool AreaTrigger_at_svala_intro(Player* pPlayer, AreaTriggerEntry const* pAt) return false; } -bool ProcessEventId_event_call_flames(uint32 uiEventId, Object* pSource, Object* pTarget, bool bIsStart) +struct MANGOS_DLL_DECL npc_spectatorAI : public ScriptedAI { - if (instance_pinnacle* pInstance = (instance_pinnacle*)((Creature*)pSource)->GetInstanceData()) + npc_spectatorAI(Creature* pCreature) : ScriptedAI(pCreature) { - pInstance->DoProcessCallFlamesEvent(); - return true; + Reset(); } - return false; + + void Reset() + { + } + + void MovementInform(uint32 uiMotionType, uint32 uiPointId) + { + if (uiMotionType == POINT_MOTION_TYPE) + { + if (uiPointId == 1) + m_creature->GetMotionMaster()->MovePoint(2,spectatorWP[1][0],spectatorWP[1][1],spectatorWP[1][2]); + else if (uiPointId == 2) + m_creature->ForcedDespawn(); + } + } +}; + +CreatureAI* GetAI_npc_spectator(Creature* pCreature) +{ + return new npc_spectatorAI(pCreature); } void AddSC_boss_svala() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "boss_svala"; - pNewScript->GetAI = &GetAI_boss_svala; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_paralyzer"; - pNewScript->GetAI = &GetAI_npc_paralyzer; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_ritual_target"; - pNewScript->GetAI = &GetAI_ritual_target; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "at_svala_intro"; - pNewScript->pAreaTrigger = &AreaTrigger_at_svala_intro; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "event_call_flames"; - pNewScript->pProcessEventId = &ProcessEventId_event_call_flames; - pNewScript->RegisterSelf(); + Script *pNewscript; + + pNewscript = new Script; + pNewscript->Name = "boss_svala"; + pNewscript->GetAI = &GetAI_boss_svala; + pNewscript->RegisterSelf(); + + pNewscript = new Script; + pNewscript->Name = "npc_spectator"; + pNewscript->GetAI = &GetAI_npc_spectator; + pNewscript->RegisterSelf(); + + pNewscript = new Script; + pNewscript->Name = "at_svala_intro"; + pNewscript->pAreaTrigger = &AreaTrigger_at_svala_intro; + pNewscript->RegisterSelf(); } diff --git a/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_utgarde_pinnacle.cpp b/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_utgarde_pinnacle.cpp index d6517b9421..6466725963 100644 --- a/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_utgarde_pinnacle.cpp +++ b/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_utgarde_pinnacle.cpp @@ -63,6 +63,7 @@ void instance_pinnacle::OnCreatureCreate(Creature* pCreature) case NPC_WORGEN: case NPC_JORMUNGAR: case NPC_RHINO: + case NPC_STASIS_CONTROLLER: m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid(); break; case NPC_FLAME_BRAZIER: diff --git a/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h b/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h index 6ec48200d9..dedbb1a3ed 100644 --- a/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h +++ b/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h @@ -24,7 +24,9 @@ enum NPC_WORGEN = 26683, NPC_JORMUNGAR = 26685, NPC_RHINO = 26686, - + NPC_STASIS_CONTROLLER = 26086, + + NPC_GORTOK = 26687, NPC_GRAUF = 26893, NPC_SKADI = 26693, NPC_YMIRJAR_WARRIOR = 26690, diff --git a/scripts/northrend/vault_of_archavon/boss_archavon.cpp b/scripts/northrend/vault_of_archavon/boss_archavon.cpp index 0e79a3815b..00bb82cec5 100644 --- a/scripts/northrend/vault_of_archavon/boss_archavon.cpp +++ b/scripts/northrend/vault_of_archavon/boss_archavon.cpp @@ -61,7 +61,7 @@ struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI uint32 m_uiRockShardsProgressTimer; uint32 m_uiRockShardTimer; bool m_bRLRockShard; - ObjectGuid m_pRockShardsTargetGuid; + Unit* m_pRockShardsTarget; uint32 m_uiCrushingLeapTimer; Unit* m_pCrushingLeapTarget; bool m_bCrushingLeapInProgress; @@ -80,7 +80,7 @@ struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI m_uiRockShardsProgressTimer = 3000; m_uiRockShardTimer = 0; m_bRLRockShard = true; - m_pRockShardsTargetGuid.Clear(); + m_pRockShardsTarget = NULL; m_uiCrushingLeapTimer = 30000; m_pCrushingLeapTarget = NULL; m_bCrushingLeapInProgress = false; @@ -156,7 +156,8 @@ struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI { m_creature->getThreatManager().addThreat(m_pCrushingLeapTarget, -100000000.0f); m_creature->SetSpeedRate(MOVE_RUN, m_fDefaultMoveSpeed); - DoCastSpellIfCan(m_pCrushingLeapTarget, m_bIsRegularMode ? SPELL_CRUSHING_LEAP_N : SPELL_CRUSHING_LEAP_H, true); + m_creature->CastSpell(m_pCrushingLeapTarget, m_bIsRegularMode ? SPELL_CRUSHING_LEAP_N : SPELL_CRUSHING_LEAP_H, true); + //DoCastSpellIfCan(m_pCrushingLeapTarget, m_bIsRegularMode ? SPELL_CRUSHING_LEAP_N : SPELL_CRUSHING_LEAP_H, true); m_bCrushingLeapInProgress = false; } else @@ -170,9 +171,8 @@ struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI if (m_uiRockShardsProgressTimer < uiDiff) { m_bRockShardsInProgress = false; - if (!m_pRockShardsTargetGuid.IsEmpty()) - if (Unit* m_pRockShardsTarget = m_creature->GetMap()->GetUnit(m_pRockShardsTargetGuid)) - m_creature->getThreatManager().addThreat(m_pRockShardsTarget, -100000000.0f); + if (m_pRockShardsTarget) + m_creature->getThreatManager().addThreat(m_pRockShardsTarget, -100000000.0f); return; } else @@ -180,13 +180,12 @@ struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI if (m_uiRockShardTimer < uiDiff) { - if (Unit* m_pRockShardsTarget = m_creature->GetMap()->GetUnit(m_pRockShardsTargetGuid)) - if (m_pRockShardsTarget->isAlive()) - { - DoCast(m_pRockShardsTarget, m_bIsRegularMode ? (m_bRLRockShard ? SPELL_ROCK_SHARDS_LEFT_N : SPELL_ROCK_SHARDS_RIGHT_N) : (m_bRLRockShard ? SPELL_ROCK_SHARDS_LEFT_H : SPELL_ROCK_SHARDS_RIGHT_H)); - m_bRLRockShard = !m_bRLRockShard; - } - m_uiRockShardTimer = 100; + if (m_pRockShardsTarget && m_pRockShardsTarget->isAlive()) + { + DoCast(m_pRockShardsTarget, m_bIsRegularMode ? (m_bRLRockShard ? SPELL_ROCK_SHARDS_LEFT_N : SPELL_ROCK_SHARDS_RIGHT_N) : (m_bRLRockShard ? SPELL_ROCK_SHARDS_LEFT_H : SPELL_ROCK_SHARDS_RIGHT_H)); + m_bRLRockShard = !m_bRLRockShard; + } + m_uiRockShardTimer = 100; } else m_uiRockShardsTimer -= uiDiff; @@ -199,11 +198,9 @@ struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI m_bRockShardsInProgress = true; m_uiRockShardsProgressTimer = 3000; m_bRLRockShard = true; - if (Unit* m_pRockShardsTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - m_pRockShardsTargetGuid = m_pRockShardsTarget->GetObjectGuid(); + m_pRockShardsTarget = NULL; + if (m_pRockShardsTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) m_creature->getThreatManager().addThreat(m_pRockShardsTarget, 100000000.0f); - } m_uiRockShardsTimer = 15000+rand()%15000; return; } diff --git a/scripts/northrend/vault_of_archavon/boss_emalon.cpp b/scripts/northrend/vault_of_archavon/boss_emalon.cpp index f7b6bf629d..13c6cff585 100644 --- a/scripts/northrend/vault_of_archavon/boss_emalon.cpp +++ b/scripts/northrend/vault_of_archavon/boss_emalon.cpp @@ -90,7 +90,10 @@ struct MANGOS_DLL_DECL npc_tempest_minionAI : public ScriptedAI void Aggro(Unit* pWho) { - m_creature->CallForHelp(80.0f); + m_creature->SetInCombatWithZone(); + + if (Creature* pEmalon = m_pInstance->GetSingleCreatureFromStorage(NPC_EMALON)) + pEmalon->AI()->AttackStart(pWho); } void FakeDeath() @@ -126,6 +129,13 @@ struct MANGOS_DLL_DECL npc_tempest_minionAI : public ScriptedAI } } + void JustDied(Unit* pKiller) + { + if (m_pInstance->GetData(TYPE_EMALON) == DONE) + return; + m_creature->Respawn(); + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) @@ -257,7 +267,14 @@ struct MANGOS_DLL_DECL boss_emalonAI : public ScriptedAI m_auiTempestMinion[3] = m_pInstance->GetSingleCreatureFromStorage(DATA_TEMPEST_MINION_4); } - m_creature->CallForHelp(80.0f); + m_creature->SetInCombatWithZone(); + + for (uint8 i=0; i<4; ++i) + { + Creature* pMinion = m_auiTempestMinion[i]; + if (pMinion) + pMinion->AI()->AttackStart(pWho); + } if (m_pInstance) m_pInstance->SetData(TYPE_EMALON, IN_PROGRESS); @@ -269,7 +286,7 @@ struct MANGOS_DLL_DECL boss_emalonAI : public ScriptedAI m_pInstance->SetData(TYPE_EMALON, DONE); for (uint8 i=0; i<4; ++i) { - Creature* pMinion = m_auiTempestMinion[i]; + Creature *pMinion = m_auiTempestMinion[i]; if (pMinion) pMinion->DealDamage(pMinion, pMinion->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } @@ -284,7 +301,6 @@ struct MANGOS_DLL_DECL boss_emalonAI : public ScriptedAI { if (m_creature->GetDistance2d(-219.119f, -289.037f) > 80.0f) EnterEvadeMode(); - m_creature->CallForHelp(80.0f); m_uiEvadeCheckCooldown = 2000; } else diff --git a/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp b/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp index dd6dae4494..1a486778a0 100644 --- a/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp +++ b/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp @@ -43,7 +43,6 @@ struct MANGOS_DLL_DECL instance_vault_of_archavon : public ScriptedInstance { switch (pCreature->GetEntry()) { - case NPC_TORAVON: case NPC_ARCHAVON: case NPC_EMALON: case NPC_KORALON: @@ -59,7 +58,6 @@ struct MANGOS_DLL_DECL instance_vault_of_archavon : public ScriptedInstance m_mNpcEntryGuidStore[m_uiMinion + DATA_TEMPEST_MINION_1] = pCreature->GetObjectGuid(); ++m_uiMinion; break; - case 4: default: m_uiMinion = 0; break; @@ -116,7 +114,6 @@ struct MANGOS_DLL_DECL instance_vault_of_archavon : public ScriptedInstance return 0; } - const char* Save() { return strInstData.c_str(); diff --git a/scripts/northrend/vault_of_archavon/vault_of_archavon.h b/scripts/northrend/vault_of_archavon/vault_of_archavon.h index adbab59713..1608e947d7 100644 --- a/scripts/northrend/vault_of_archavon/vault_of_archavon.h +++ b/scripts/northrend/vault_of_archavon/vault_of_archavon.h @@ -19,12 +19,10 @@ enum DATA_TEMPEST_MINION_3 = 103, DATA_TEMPEST_MINION_4 = 104, - - NPC_TORAVON = 38433, NPC_ARCHAVON = 31125, NPC_EMALON = 33993, NPC_KORALON = 35013, - NPC_TEMPEST_MINION = 33998, + NPC_TEMPEST_MINION = 33998 }; #endif diff --git a/scripts/northrend/violet_hold/boss_zuramat.cpp b/scripts/northrend/violet_hold/boss_zuramat.cpp index 6fd5a65a9b..673ce5133d 100644 --- a/scripts/northrend/violet_hold/boss_zuramat.cpp +++ b/scripts/northrend/violet_hold/boss_zuramat.cpp @@ -70,6 +70,7 @@ struct MANGOS_DLL_DECL boss_zuramatAI : public ScriptedAI void Reset() { + DespawnSentry(); m_uiShroudDarkness_Timer = urand(8000, 9000); m_uiSummonVoidSentry_Timer = 10000; m_uiVoidShift_Timer = 10000; diff --git a/scripts/northrend/zuldrak.cpp b/scripts/northrend/zuldrak.cpp index 3ca38d13cd..867dca6d15 100644 --- a/scripts/northrend/zuldrak.cpp +++ b/scripts/northrend/zuldrak.cpp @@ -17,15 +17,17 @@ /* ScriptData SDName: Zuldrak SD%Complete: 100 -SDComment: Quest support: 12934. +SDComment: Quest support: 12663, 12664, 12934. SDCategory: Zuldrak EndScriptData */ /* ContentData npc_gurgthock +npc_flying_fiend_vehicle EndContentData */ #include "precompiled.h" +#include "Vehicle.h" /*###### ## npc_gurgthock @@ -94,6 +96,198 @@ CreatureAI* GetAI_npc_gurgthock(Creature* pCreature) return new npc_gurgthockAI(pCreature); } +/*###### +## npc_ghoul_feeding_bunny +######*/ +enum +{ + NPC_DECAYING_GHOUL = 28565, + NPC_GHOUL_FEEDING_KC = 28591, + QUEST_FEEDIN_DA_GOOLZ = 12652 + +}; + +struct MANGOS_DLL_DECL npc_ghoul_feeding_bunnyAI : public ScriptedAI +{ + npc_ghoul_feeding_bunnyAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + + uint32 uiKaboomTimer; + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 1000; + uiKaboomTimer = 11000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiCheckTimer <= uiDiff) + { + if(Creature *pGhoul = GetClosestCreatureWithEntry(m_creature, NPC_DECAYING_GHOUL, 20.0f)) + { + if(pGhoul->isAlive()) + { + pGhoul->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); + + + } + } + + } else uiCheckTimer -= uiDiff; + + if( uiKaboomTimer <= uiDiff) + { + if(Player *pPlayer = m_creature->GetMap()->GetPlayer(m_creature->GetCreatorGuid())) + { + if(pPlayer->GetQuestStatus(QUEST_FEEDIN_DA_GOOLZ) == QUEST_STATUS_INCOMPLETE) + { + pPlayer->KilledMonsterCredit(NPC_GHOUL_FEEDING_KC); + } + } + m_creature->ForcedDespawn(); + if(Creature *pGhoul = GetClosestCreatureWithEntry(m_creature, NPC_DECAYING_GHOUL, 10.0f)) + { + pGhoul->ForcedDespawn(); + } + } + else uiKaboomTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_ghoul_feeding_bunny(Creature* pCreature) +{ + return new npc_ghoul_feeding_bunnyAI(pCreature); +} + +/*###### +## npc_flying_fiend_vehicle +######*/ + +enum +{ + SAY_1 = -1999810, + SAY_2 = -1999809, + SAY_3 = -1999808, + SAY_4 = -1999807, + SAY_5 = -1999806, + SAY_6 = -1999805, + + SPELL_KILL_CREDIT = 52220, + SPELL_SUMMON_GARGOYLE_VEHICLE = 52194, // force cast 52190 + SPELL_SCOURGE_DISGUISE = 52193, // force cast 52192 + SPELL_ABANDON_VEHICLE = 52203, + NPC_OVERLORD_DRAKURU = 28717, + MAX_NODE = 35 +}; + +struct NodeData +{ + float fPosX; + float fPosY; + float fPosZ; + int32 uiSay; +}; + +NodeData NodeInfo[MAX_NODE] = +{ + {6067.32f, -2091.65f, 435.74f}, // tarrace + {6034.02f, -2108.75f, 439.35f}, + {5943.64f, -2194.36f, 395.83f, SAY_1}, // SAY_1 + {5389.98f, -2298.10f, 400.00f, SAY_2}, // SAY2 + {5338.34f, -2559.86f, 354.92f}, + {5572.49f, -3228.05f, 437.08f}, + {5749.56f, -3505.60f, 416.47f}, // Zim'Torga + {5790.66f, -3675.21f, 407.28f}, + {6192.40f, -3871.92f, 502.15f}, + {6503.82f, -4182.26f, 491.74f}, + {6658.25f, -4282.02f, 496.58f}, + {6911.33f, -4325.27f, 557.03f, SAY_3}, // SAY3 + {7009.48f, -4345.52f, 549.51f}, + {7017.40f, -4407.66f, 539.99f}, + {6723.51f, -4696.85f, 558.85f}, + {6667.91f, -4693.66f, 543.37f, SAY_4}, // SAY4 + {6245.38f, -4051.44f, 512.56f}, + {6045.13f, -4067.68f, 468.06f}, // rynna + {5592.85f, -3620.97f, 456.91f}, + {5399.42f, -3367.07f, 410.16f}, + {5212.14f, -3381.96f, 362.84f, SAY_5}, //SAY5 + {5032.75f, -3191.35f, 358.82f}, + {5016.12f, -3036.15f, 330.83f}, + {5367.02f, -2677.88f, 342.06f}, + {5430.66f, -2589.67f, 357.61f}, // The Argent Stand + {5452.66f, -2287.13f, 357.07f}, + {5650.79f, -2150.54f, 299.41f}, + {5779.82f, -2095.38f, 276.80f}, + {6018.34f, -2082.39f, 278.90f}, + {6079.77f, -1922.40f, 369.19f, SAY_6}, // SAY6 + {5952.33f, -1899.84f, 485.97f}, + {5962.76f, -2083.12f, 469.24f}, + {6034.02f, -2108.75f, 439.35f}, + {6057.18f, -2100.97f, 429.08f}, + {6071.75f, -2087.93f, 426.97f} +}; + +struct MANGOS_DLL_DECL npc_flying_fiend_vehicleAI : public ScriptedAI +{ + npc_flying_fiend_vehicleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetOwnerGuid(m_creature->GetCreatorGuid()); + m_creature->SetSpeedRate(MOVE_FLIGHT, 2.0f); + m_creature->SetWalk(false); + DoCastSpellIfCan(m_creature, SPELL_SCOURGE_DISGUISE); + uiNode = 0; + FlyToNextNode(); + } + + uint32 uiNode; + + void Reset(){} + + void FlyToNextNode() + { + m_creature->GetMotionMaster()->MovePoint(uiNode, NodeInfo[uiNode].fPosX, NodeInfo[uiNode].fPosY, NodeInfo[uiNode].fPosZ); + } + + void MovementInform(uint32 uiType, uint32 uiPoint) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPoint == uiNode) + { + Unit* pPassinger = m_creature->GetMap()->GetUnit(m_creature->GetCreatorGuid()); + if (!pPassinger) + { + m_creature->ForcedDespawn(); + return; + } + + if (NodeInfo[uiNode].uiSay) + if (Creature* pOverlord = GetClosestCreatureWithEntry(m_creature, NPC_OVERLORD_DRAKURU, DEFAULT_VISIBILITY_DISTANCE)) + DoScriptText(NodeInfo[uiNode].uiSay, pOverlord, pPassinger); + + if (++uiNode < MAX_NODE) + FlyToNextNode(); + else + { + pPassinger->RemoveAurasDueToSpell(52192); + DoCastSpellIfCan(m_creature, SPELL_ABANDON_VEHICLE,CAST_TRIGGERED); + DoCastSpellIfCan(m_creature, SPELL_KILL_CREDIT, CAST_TRIGGERED); + m_creature->ForcedDespawn(3000); + } + } + } + +}; + +CreatureAI* GetAI_npc_flying_fiend_vehicle(Creature* pCreature) +{ + return new npc_flying_fiend_vehicleAI(pCreature); +} + void AddSC_zuldrak() { Script* pNewScript; @@ -103,4 +297,14 @@ void AddSC_zuldrak() pNewScript->GetAI = &GetAI_npc_gurgthock; pNewScript->pQuestAcceptNPC = &QuestAccept_npc_gurgthock; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_ghoul_feeding_bunny"; + pNewScript->GetAI = &GetAI_npc_ghoul_feeding_bunny; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_flying_fiend_vehicle"; + pNewScript->GetAI = &GetAI_npc_flying_fiend_vehicle; + pNewScript->RegisterSelf(); } diff --git a/scripts/outland/black_temple/black_temple.h b/scripts/outland/black_temple/black_temple.h index 85d9d988d6..de127feb6d 100644 --- a/scripts/outland/black_temple/black_temple.h +++ b/scripts/outland/black_temple/black_temple.h @@ -58,7 +58,7 @@ class MANGOS_DLL_DECL instance_black_temple : public ScriptedInstance void SetData(uint32 uiType, uint32 uiData); uint32 GetData(uint32 uiType); - uint64 GetData64(uint32 uiData); + ObjectGuid GetGuid(uint32 uiData); const char* Save() { return m_strInstData.c_str(); } void Load(const char* chrIn); diff --git a/scripts/outland/black_temple/instance_black_temple.cpp b/scripts/outland/black_temple/instance_black_temple.cpp index 0dadef8eae..24b10fff49 100644 --- a/scripts/outland/black_temple/instance_black_temple.cpp +++ b/scripts/outland/black_temple/instance_black_temple.cpp @@ -189,14 +189,13 @@ uint32 instance_black_temple::GetData(uint32 uiType) return 0; } -uint64 instance_black_temple::GetData64(uint32 uiData) +ObjectGuid instance_black_temple::GetGuid(uint32 uiData) { switch(uiData) { - case NPC_AKAMA: return m_akamaGuid.GetRawValue(); - case NPC_ILLIDAN_STORMRAGE: return m_illidanStormrageGuid.GetRawValue(); - default: - return 0; + case NPC_AKAMA: return m_akamaGuid; + case NPC_ILLIDAN_STORMRAGE: return m_illidanStormrageGuid; + default: return ObjectGuid(); } } diff --git a/scripts/outland/coilfang_reservoir/serpent_shrine/instance_serpent_shrine.cpp b/scripts/outland/coilfang_reservoir/serpent_shrine/instance_serpent_shrine.cpp index ec86231574..95f21483b9 100644 --- a/scripts/outland/coilfang_reservoir/serpent_shrine/instance_serpent_shrine.cpp +++ b/scripts/outland/coilfang_reservoir/serpent_shrine/instance_serpent_shrine.cpp @@ -69,18 +69,18 @@ void instance_serpentshrine_cavern::OnCreatureCreate(Creature* pCreature) } } -void instance_serpentshrine_cavern::SetData64(uint32 uiType, uint64 uiData) +void instance_serpentshrine_cavern::SetGuid(uint32 uiType, ObjectGuid uiData) { if (uiType == DATA_KARATHRESS_STARTER) - m_karathressEventStarterGuid = ObjectGuid(uiData); + m_karathressEventStarterGuid = uiData; } -uint64 instance_serpentshrine_cavern::GetData64(uint32 uiData) +ObjectGuid instance_serpentshrine_cavern::GetGuid(uint32 uiData) { if (uiData == DATA_KARATHRESS_STARTER) - return m_karathressEventStarterGuid.GetRawValue(); + return m_karathressEventStarterGuid; - return 0; + return ObjectGuid(); } void instance_serpentshrine_cavern::SetData(uint32 uiType, uint32 uiData) diff --git a/scripts/outland/coilfang_reservoir/serpent_shrine/serpent_shrine.h b/scripts/outland/coilfang_reservoir/serpent_shrine/serpent_shrine.h index cce375d521..e82f166517 100644 --- a/scripts/outland/coilfang_reservoir/serpent_shrine/serpent_shrine.h +++ b/scripts/outland/coilfang_reservoir/serpent_shrine/serpent_shrine.h @@ -44,8 +44,8 @@ class MANGOS_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance void SetData(uint32 uiType, uint32 uiData); uint32 GetData(uint32 uiType); - void SetData64(uint32 uiType, uint64 uiData); - uint64 GetData64(uint32 uiData); + void SetGuid(uint32 uiType, ObjectGuid uiData); + ObjectGuid GetGuid(uint32 uiData); const char* Save() { return m_strInstData.c_str(); } void Load(const char* chrIn); diff --git a/scripts/outland/hellfire_peninsula.cpp b/scripts/outland/hellfire_peninsula.cpp index 3bef663fd5..52b2dbc24a 100644 --- a/scripts/outland/hellfire_peninsula.cpp +++ b/scripts/outland/hellfire_peninsula.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Hellfire_Peninsula SD%Complete: 100 -SDComment: Quest support: 9375, 9410, 9418, 10838 +SDComment: Quest support: 9375, 9410, 9418, 10629, 10838 SDCategory: Hellfire Peninsula EndScriptData */ @@ -27,6 +27,7 @@ npc_ancestral_wolf npc_demoniac_scryer npc_tracy_proudwell npc_wounded_blood_elf +npc_felguard_hound EndContentData */ #include "precompiled.h" @@ -474,6 +475,68 @@ bool QuestAccept_npc_wounded_blood_elf(Player* pPlayer, Creature* pCreature, con return true; } +/*#### +## npc_felguard_hound +####*/ + +#define SPELL_POO 37688 +#define NPC_DERANGED_HELBOAR 16863 + +struct MANGOS_DLL_DECL npc_felguard_houndAI : public ScriptedAI +{ + npc_felguard_houndAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + bool m_bCreatedByPlayer; + uint32 m_uiCheckTimer; + + void Reset () + { + m_bCreatedByPlayer = false; + if (Unit* pCreator = m_creature->GetCreator()) + { + if (pCreator->GetTypeId() == TYPEID_PLAYER) + { + m_creature->GetMotionMaster()->MoveFollow(pCreator, 3.0f, 1.57f); + m_bCreatedByPlayer = true; + m_uiCheckTimer = 100; + } + } + } + + void UpdateAI (const uint32 uiDiff) + { + if (m_bCreatedByPlayer) + { + if (m_uiCheckTimer < uiDiff) + { + std::list lBoarList; + GetCreatureListWithEntryInGrid(lBoarList, m_creature, NPC_DERANGED_HELBOAR, 10.0f); + if (!lBoarList.empty()) + { + for (std::list::iterator iter = lBoarList.begin(); iter != lBoarList.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + { + DoCast(m_creature, SPELL_POO); + (*iter)->ForcedDespawn(); + } + } + } + m_uiCheckTimer = 1000; + } + else m_uiCheckTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_felguard_hound(Creature* pCreature) +{ + return new npc_felguard_houndAI(pCreature); +} + void AddSC_hellfire_peninsula() { Script* pNewScript; @@ -506,4 +569,9 @@ void AddSC_hellfire_peninsula() pNewScript->GetAI = &GetAI_npc_wounded_blood_elf; pNewScript->pQuestAcceptNPC = &QuestAccept_npc_wounded_blood_elf; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "npc_felguard_hound"; + pNewScript->GetAI = &GetAI_npc_felguard_hound; + pNewScript->RegisterSelf(); } diff --git a/scripts/outland/shattrath_city.cpp b/scripts/outland/shattrath_city.cpp index 73bc27eda5..a7b51cf013 100644 --- a/scripts/outland/shattrath_city.cpp +++ b/scripts/outland/shattrath_city.cpp @@ -255,6 +255,35 @@ CreatureAI* GetAI_npc_dirty_larry(Creature* pCreature) return new npc_dirty_larryAI(pCreature); } +/*###### +## npc_ishanah +######*/ + +#define GOSSIP_ISHANAH_1 "Who are the Sha'tar?" +#define GOSSIP_ISHANAH_2 "Isn't Shattrath a draenei city? Why do you allow others here?" + +bool GossipHello_npc_ishanah(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ISHANAH_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ISHANAH_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_ishanah(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + pPlayer->SEND_GOSSIP_MENU(9458, pCreature->GetObjectGuid()); + else if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + pPlayer->SEND_GOSSIP_MENU(9459, pCreature->GetObjectGuid()); + + return true; +} + /*###### ## npc_khadgars_servant ######*/ @@ -677,6 +706,12 @@ void AddSC_shattrath_city() pNewScript->pGossipSelect = &GossipSelect_npc_dirty_larry; pNewScript->RegisterSelf(); + pNewScript = new Script; + pNewScript->Name = "npc_ishanah"; + pNewScript->pGossipHello = &GossipHello_npc_ishanah; + pNewScript->pGossipSelect = &GossipSelect_npc_ishanah; + pNewScript->RegisterSelf(); + pNewScript = new Script; pNewScript->Name = "npc_khadgars_servant"; pNewScript->GetAI = &GetAI_npc_khadgars_servant; diff --git a/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp b/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp index 1d3f71468e..d6377c5775 100644 --- a/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp +++ b/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp @@ -78,6 +78,7 @@ struct MANGOS_DLL_DECL boss_harbinger_skyrissAI : public ScriptedAI void Reset() { + m_bIntroFinished = false; m_bDidSplitImage33 = false; m_bDidSplitImage66 = false; @@ -165,7 +166,9 @@ struct MANGOS_DLL_DECL boss_harbinger_skyrissAI : public ScriptedAI break; case 3: m_bIntroFinished = true; - // TODO - Let Attack here, or change Unit_flag + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); break; } } diff --git a/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp b/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp index b4fb4a08f3..48486adf32 100644 --- a/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp +++ b/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp @@ -768,15 +768,15 @@ struct MANGOS_DLL_DECL boss_kaelthasAI : public ScriptedAI } case PHASE_4_SOLO: - case 5: - case 6: + case PHASE_5_GRAVITY: + case PHASE_6_COMPLETE: { //Return since we have no target if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; //m_uiFireball_Timer - if (!m_bInGravityLapse && !m_bChainPyros && m_uiPhase != 5) + if (!m_bInGravityLapse && !m_bChainPyros && m_uiPhase != PHASE_5_GRAVITY) { if (m_uiFireball_Timer < uiDiff) { @@ -910,7 +910,7 @@ struct MANGOS_DLL_DECL boss_kaelthasAI : public ScriptedAI DoCastSpellIfCan(m_creature, SPELL_EXPLODE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_uiPhase = 6; + m_uiPhase = PHASE_6_COMPLETE; AttackStart(m_creature->getVictim()); } else @@ -918,7 +918,7 @@ struct MANGOS_DLL_DECL boss_kaelthasAI : public ScriptedAI } //Phase 5 - if (m_uiPhase == 6) + if (m_uiPhase == PHASE_6_COMPLETE) { //m_uiGravityLapse_Timer @@ -992,6 +992,7 @@ struct MANGOS_DLL_DECL boss_kaelthasAI : public ScriptedAI m_bInGravityLapse = false; m_uiGravityLapse_Timer = 60000; m_uiGravityLapse_Phase = 0; + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); AttackStart(m_creature->getVictim()); break; } diff --git a/scripts/outland/tempest_keep/the_eye/the_eye.h b/scripts/outland/tempest_keep/the_eye/the_eye.h index 1fd2bf0cd1..4f76bb6f31 100644 --- a/scripts/outland/tempest_keep/the_eye/the_eye.h +++ b/scripts/outland/tempest_keep/the_eye/the_eye.h @@ -7,7 +7,7 @@ enum { - MAX_ENCOUNTER = 3, + MAX_ENCOUNTER = 4, TYPE_ALAR = 0, TYPE_SOLARIAN = 1, @@ -22,6 +22,7 @@ enum NPC_SANGUINAR = 20060, NPC_TELONICUS = 20063, NPC_THALADRED = 20064, + NPC_ALAR = 19514, }; enum KaelPhases diff --git a/scripts/outland/terokkar_forest.cpp b/scripts/outland/terokkar_forest.cpp index 443251460f..f699458c7b 100644 --- a/scripts/outland/terokkar_forest.cpp +++ b/scripts/outland/terokkar_forest.cpp @@ -36,6 +36,7 @@ npc_slim go_veil_skith_cage npc_captive_child npc_isla_starmane +go_ancient_skull_pile EndContentData */ #include "precompiled.h" @@ -763,7 +764,7 @@ struct MANGOS_DLL_DECL npc_mana_bomb_exp_triggerAI : public ScriptedAI m_bIsActivated = true; - pPlayer->KilledMonsterCredit(NPC_MANA_BOMB_KILL_TRIGGER); + pPlayer->KilledMonsterCredit(NPC_MANA_BOMB_KILL_TRIGGER, pGo->GetObjectGuid()); pManaBomb = pGo; } @@ -1076,6 +1077,23 @@ CreatureAI* GetAI_npc_isla_starmane(Creature* pCreature) return new npc_isla_starmaneAI(pCreature); } +/*##### +# go_ancient_skull_pile +#####*/ +enum +{ + SPELL_SUMMON_TEROKK = 41004, + ITEM_TIME_LOST_OFFERING = 32720, +}; + +bool GOUse_go_ancient_skull_pile(Player* pPlayer, GameObject* pGObject) +{ + + pPlayer->CastSpell(pPlayer, SPELL_SUMMON_TEROKK, false); + + return true; +} + void AddSC_terokkar_forest() { Script* pNewScript; @@ -1153,4 +1171,9 @@ void AddSC_terokkar_forest() pNewScript->GetAI = &GetAI_npc_isla_starmane; pNewScript->pQuestAcceptNPC = &QuestAccept_npc_isla_starmane; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "go_ancient_skull_pile"; + pNewScript->pGOUse = &GOUse_go_ancient_skull_pile; + pNewScript->RegisterSelf(); } diff --git a/scripts/world/areatrigger_scripts.cpp b/scripts/world/areatrigger_scripts.cpp index 4f19d4b29f..850a232559 100644 --- a/scripts/world/areatrigger_scripts.cpp +++ b/scripts/world/areatrigger_scripts.cpp @@ -79,10 +79,10 @@ bool AreaTrigger_at_aldurthar_gate(Player* pPlayer, AreaTriggerEntry const* pAt) { switch(pAt->id) { - case TRIGGER_SOUTH: pPlayer->KilledMonsterCredit(NPC_SOUTH_GATE); break; - case TRIGGER_CENTRAL: pPlayer->KilledMonsterCredit(NPC_CENTRAL_GATE); break; - case TRIGGER_NORTH: pPlayer->KilledMonsterCredit(NPC_NORTH_GATE); break; - case TRIGGER_NORTHWEST: pPlayer->KilledMonsterCredit(NPC_NORTHWEST_GATE); break; + case TRIGGER_SOUTH: pPlayer->KilledMonsterCredit(uint32(NPC_SOUTH_GATE)); break; + case TRIGGER_CENTRAL: pPlayer->KilledMonsterCredit(uint32(NPC_CENTRAL_GATE)); break; + case TRIGGER_NORTH: pPlayer->KilledMonsterCredit(uint32(NPC_NORTH_GATE)); break; + case TRIGGER_NORTHWEST: pPlayer->KilledMonsterCredit(uint32(NPC_NORTHWEST_GATE)); break; } return true; } @@ -152,7 +152,7 @@ enum bool AreaTrigger_at_ravenholdt(Player* pPlayer, AreaTriggerEntry const* pAt) { if (pPlayer->GetQuestStatus(QUEST_MANOR_RAVENHOLDT) == QUEST_STATUS_INCOMPLETE) - pPlayer->KilledMonsterCredit(NPC_RAVENHOLDT); + pPlayer->KilledMonsterCredit(uint32(NPC_RAVENHOLDT)); return false; } @@ -205,9 +205,9 @@ bool AreaTrigger_at_warsong_farms(Player* pPlayer, AreaTriggerEntry const* pAt) { switch(pAt->id) { - case AT_SLAUGHTERHOUSE: pPlayer->KilledMonsterCredit(NPC_CREDIT_SLAUGHTERHOUSE); break; - case AT_GRAINERY: pPlayer->KilledMonsterCredit(NPC_CREDIT_GRAINERY); break; - case AT_TORP_FARM: pPlayer->KilledMonsterCredit(NPC_CREDIT_TORP_FARM); break; + case AT_SLAUGHTERHOUSE: pPlayer->KilledMonsterCredit(uint32(NPC_CREDIT_SLAUGHTERHOUSE)); break; + case AT_GRAINERY: pPlayer->KilledMonsterCredit(uint32(NPC_CREDIT_GRAINERY)); break; + case AT_TORP_FARM: pPlayer->KilledMonsterCredit(uint32(NPC_CREDIT_TORP_FARM)); break; } } return true; diff --git a/scripts/world/go_scripts.cpp b/scripts/world/go_scripts.cpp index 8c97c3a720..0458fb25f5 100644 --- a/scripts/world/go_scripts.cpp +++ b/scripts/world/go_scripts.cpp @@ -84,19 +84,19 @@ bool GOUse_go_barov_journal(Player* pPlayer, GameObject* pGo) enum { - FACTION_LC = 1011, - FACTION_SHAT = 935, - FACTION_CE = 942, - FACTION_CON = 933, - FACTION_KT = 989, - FACTION_SPOR = 970, - - SPELL_REP_LC = 39456, - SPELL_REP_SHAT = 39457, - SPELL_REP_CE = 39460, - SPELL_REP_CON = 39474, - SPELL_REP_KT = 39475, - SPELL_REP_SPOR = 39476 + NPC_LC = 22811, + NPC_SHAT = 22812, + NPC_CE = 22810, + NPC_CON = 22813, + NPC_KT = 22815, + NPC_SPOR = 22814, + + SPELL_REP_LC = 39456, + SPELL_REP_SHAT = 39457, + SPELL_REP_CE = 39460, + SPELL_REP_CON = 39474, + SPELL_REP_KT = 39475, + SPELL_REP_SPOR = 39476 }; const uint32 uiNpcPrisonEntry[] = @@ -117,23 +117,21 @@ bool GOUse_go_ethereum_prison(Player* pPlayer, GameObject* pGo) { uint32 uiSpell = 0; - if (FactionTemplateEntry const* pFaction = pCreature->getFactionTemplateEntry()) + switch(pCreature->GetEntry()) { - switch(pFaction->faction) - { - case FACTION_LC: uiSpell = SPELL_REP_LC; break; - case FACTION_SHAT: uiSpell = SPELL_REP_SHAT; break; - case FACTION_CE: uiSpell = SPELL_REP_CE; break; - case FACTION_CON: uiSpell = SPELL_REP_CON; break; - case FACTION_KT: uiSpell = SPELL_REP_KT; break; - case FACTION_SPOR: uiSpell = SPELL_REP_SPOR; break; - } - - if (uiSpell) - pCreature->CastSpell(pPlayer,uiSpell,false); - else - error_log("SD2: go_ethereum_prison summoned creature (entry %u) but faction (%u) are not expected by script.",pCreature->GetEntry(),pCreature->getFaction()); + case NPC_LC: uiSpell = SPELL_REP_LC; break; + case NPC_SHAT: uiSpell = SPELL_REP_SHAT; break; + case NPC_CE: uiSpell = SPELL_REP_CE; break; + case NPC_CON: uiSpell = SPELL_REP_CON; break; + case NPC_KT: uiSpell = SPELL_REP_KT; break; + case NPC_SPOR: uiSpell = SPELL_REP_SPOR; break; + default: break; } + + if (uiSpell) + pCreature->CastSpell(pPlayer,uiSpell,false); + else + error_log("SD2: go_ethereum_prison summoned creature (entry %u) but faction (%u) are not expected by script.",pCreature->GetEntry(),pCreature->getFaction()); } } @@ -443,7 +441,7 @@ bool GOUse_go_scourge_enclosure(Player* pPlayer, GameObject* pGo) (*itr)->CastSpell((*itr),SPELL_GYMER_LOCK_EXPLOSION,true); } } - pPlayer->KilledMonsterCredit(NPC_GYMER_LOCK_DUMMY); + pPlayer->KilledMonsterCredit(uint32(NPC_GYMER_LOCK_DUMMY)); return true; } diff --git a/scripts/world/item_scripts.cpp b/scripts/world/item_scripts.cpp index 1bfe738661..11df9959f1 100644 --- a/scripts/world/item_scripts.cpp +++ b/scripts/world/item_scripts.cpp @@ -26,6 +26,9 @@ item_arcane_charges Prevent use if player is not flying (cannot item_flying_machine(i34060,i34061) Engineering crafted flying machines item_gor_dreks_ointment(i30175) Protecting Our Own(q10488) Item_jungle_punch_offer +item_complimentary_brewfest_sampler Brewfest event +item_ram_racing_reins Brewfest event +item_tricky_treat Hallow's End event EndContentData */ #include "precompiled.h" @@ -152,6 +155,126 @@ bool ItemUse_item_jungle_punch_sample(Player* pPlayer, Item* pItem, const SpellC } } +/*##### +# item_complimentary_brewfest_sampler +#####*/ + +enum +{ + NPC_SCOUT = 24108, + QUEST_CHUG_AND_CHUCK_A = 12022, + QUEST_CHUG_AND_CHUCK_H = 12191 +}; + +bool ItemUse_item_complimentary_brewfest_sampler(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) +{ + Map* pMap = pPlayer->GetMap(); + if (pMap) + { + Unit* pTarget = pMap->GetUnit(pPlayer->GetTargetGuid()); + if (pTarget) + { + if ((pTarget->GetEntry() == NPC_SCOUT) && ((pPlayer->GetQuestStatus(QUEST_CHUG_AND_CHUCK_A) == QUEST_STATUS_INCOMPLETE) || (pPlayer->GetQuestStatus(QUEST_CHUG_AND_CHUCK_H) == QUEST_STATUS_INCOMPLETE))) + pPlayer->KilledMonsterCredit(NPC_SCOUT); + } + } + pPlayer->CastSpell(pPlayer, 42436, false); + + return true; +} + +/*##### +# item_ram_racing_reins +#####*/ + +enum +{ + SPELL_RAMSTEIN_SWIFT_WORK_RAM = 43880, + SPELL_RENTAL_RAM = 43883, + SPELL_RAM_FATIGUE = 43052, + SPELL_SPEED_RAM_GALLOP = 42994, + SPELL_SPEED_RAM_CANTER = 42993, + SPELL_SPEED_RAM_TROT = 42992, + SPELL_SPEED_RAM_NORMAL = 43310, + SPELL_SPEED_RAM_EXHAUSED = 43332, +}; + +bool ItemUse_item_ram_racing_reins(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) +{ + if ((pPlayer->HasAura(SPELL_RENTAL_RAM) || pPlayer->HasAura(SPELL_RAMSTEIN_SWIFT_WORK_RAM)) && !pPlayer->HasAura(SPELL_SPEED_RAM_EXHAUSED)) + { + if (pPlayer->HasAura(SPELL_SPEED_RAM_NORMAL)) + { + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_NORMAL); + pPlayer->CastSpell(pPlayer, SPELL_SPEED_RAM_TROT, false); + return true; + } + if (pPlayer->HasAura(SPELL_SPEED_RAM_TROT)) + { + if (SpellAuraHolderPtr pAura = pPlayer->GetSpellAuraHolder(SPELL_SPEED_RAM_TROT)) + { + if (pAura->GetAuraDuration() >= (pAura->GetAuraMaxDuration() - 1000)) + { + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_TROT); + pPlayer->CastSpell(pPlayer, SPELL_SPEED_RAM_CANTER, true); + return true; + } + pAura->SetAuraDuration(pAura->GetAuraMaxDuration()); + } + } + if (pPlayer->HasAura(SPELL_SPEED_RAM_CANTER)) + { + if (SpellAuraHolderPtr pAura = pPlayer->GetSpellAuraHolder(SPELL_SPEED_RAM_CANTER)) + { + if (pAura->GetAuraDuration() >= (pAura->GetAuraMaxDuration() - 500)) + { + pPlayer->RemoveAurasDueToSpell(SPELL_SPEED_RAM_CANTER); + pPlayer->CastSpell(pPlayer, SPELL_SPEED_RAM_GALLOP, false); + return true; + } + pAura->SetAuraDuration(pAura->GetAuraMaxDuration()); + } + } + if (pPlayer->HasAura(SPELL_SPEED_RAM_GALLOP)) + { + if (SpellAuraHolderPtr pAura = pPlayer->GetSpellAuraHolder(SPELL_SPEED_RAM_GALLOP, pPlayer->GetObjectGuid())) + pAura->SetAuraDuration(pAura->GetAuraMaxDuration()); + } + } + else + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW ,pItem, NULL); + + + return true; +} + +/*##### +# item_tricky_treat +#####*/ + +enum +{ + SPELL_TRICKY_TREAT_0 = 44436, + SPELL_TRICKY_TREAT_RUN = 42919, + SPELL_UPSET_TUMMY = 42966, +}; + +bool ItemUse_item_tricky_treat(Player* pPlayer, Item* pItem, const SpellCastTargets &pTargets) +{ + if (pPlayer->HasAura(SPELL_UPSET_TUMMY)) + { + pPlayer->SendEquipError(EQUIP_ERR_CANT_DO_RIGHT_NOW, pItem); + return true; + } + pPlayer->CastSpell(pPlayer, SPELL_TRICKY_TREAT_RUN, true); + if (pPlayer->HasAura(SPELL_TRICKY_TREAT_RUN)) + { + if (pPlayer->GetSpellAuraHolder(SPELL_TRICKY_TREAT_RUN)->GetStackAmount() > 2 && roll_chance_i(20 * pPlayer->GetSpellAuraHolder(SPELL_TRICKY_TREAT_RUN)->GetStackAmount())) + pPlayer->CastSpell(pPlayer, SPELL_UPSET_TUMMY, true); + } + return false; +} + void AddSC_item_scripts() { Script* pNewScript; @@ -180,4 +303,20 @@ void AddSC_item_scripts() pNewScript->Name = "item_jungle_punch_sample"; pNewScript->pItemUse = &ItemUse_item_jungle_punch_sample; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "item_complimentary_brewfest_sampler"; + pNewScript->pItemUse = &ItemUse_item_complimentary_brewfest_sampler; + pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "item_ram_racing_reins"; + pNewScript->pItemUse = &ItemUse_item_ram_racing_reins; + pNewScript->RegisterSelf(); + + + pNewScript = new Script; + pNewScript->Name = "item_tricky_treat"; + pNewScript->pItemUse = &ItemUse_item_tricky_treat; + pNewScript->RegisterSelf(); } diff --git a/scripts/world/npc_companion_handler.cpp b/scripts/world/npc_companion_handler.cpp new file mode 100644 index 0000000000..05a8f74056 --- /dev/null +++ b/scripts/world/npc_companion_handler.cpp @@ -0,0 +1,504 @@ +/* Copyright (C) 2006 - 2011 ScriptDev2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: npc_companion_handler +SDAuthor: ckegg +SD%Complete: 0% +SDComment: +SDCategory: Pet behavior +INSERT INTO spell_script_target VALUES +(67400,1,34694); + +UPDATE creature_template SET ScriptNAme = 'npc_companion_handler' WHERE entry IN ( +-- Ammen Vale Lashling, Durotar Scorpion, Elwynn Lamb, Frigid Frostling +33205,33198,33200,40198, +-- Mechanopeep,Zergling,Grunty +33274,11327,34694); +UPDATE creature_template SET ScriptNAme = 'npc_companion_helper' WHERE entry IN ( +-- Elwynn Wolf +33286); +DELETE FROM script_texts WHERE entry BETWEEN -1999799 AND -1999796; +INSERT INTO `script_texts` (`entry`, `content_default`, `comment`) VALUES +('-1999799','Feed me, $N',''), +('-1999798','Feed me all night long',''), +('-1999797','Cause if you feed me, $N',''), +('-1999796','I can grow up big and strong',''); +EndScriptData */ + +#include "precompiled.h" +#include "pet_ai.h" + +enum +{ + + NPC_PEANUT = 23286, + NPC_PEANUT_PERIODIC = 41019, + + NPC_PANDA = 11325, + SPELL_PANDA_SLEEP = 19231, + SPELL_PANDA_ROAR = 40664, + + NPC_DIABLO = 11326, + SPELL_DIABLO_FLAME = 18874, + //SPELL_DIABLO = 18873, + + NPC_ZERGLING = 11327, + SPELL_ZERGLING_PERIODIC = 19226, + SPELL_ZERGLING_PASSIVE = 67399, + + NPC_GRUNTY = 34694, + SPELL_GRUNTY_PERIODIC = 67370, + + NPC_WILLY = 23231, + SPELL_WILLY_SLEEP = 40663, + //SPELL_WILLY = 40619, + //SPELL_WILLY = 40638, + + NPC_DRAGON_KITE = 25110, + SPELL_DRAGON_KITE_LIGHTNING = 45197, + + NPC_BATTLE_BOT = 34587, + SPELL_BATTLE_BOT_MELEE = 65694, + + NPC_MURKY = 15186, + NPC_LURKY = 15358, + SPELL_MURKY_DANCE = 25165, + + NPC_EGBERT = 23258, + SPELL_EGBERT_HAPPYNESS = 40669, + + //NPC_KIRIN = , + SPELL_KIRIN_ARCANE = 61479, + + NPC_MULGORE = 33219, + SPELL_MULGORE_HAPPYNESS = 62585, + + NPC_PENGU = 32595, + NPC_CHILLY = 31128, + SPELL_PENGU_SOUND = 61635, + + NPC_STINKER = 23274, + SPELL_STINKER_BROKEN_HEART = 62004, + + NPC_SCORCHLING = 25706, + SPELL_SCORCHLING_BLAST = 45889, + + NPC_SPRING_RABBIT = 32791, + SPELL_SPRING_RABBIT_IN_LOVE = 61728, + SPELL_SPRING_RABBIT_JUMP = 61724, + + NPC_STRAND_CRAWLERT = 33226, + SPELL_STRAND_CRAWLERT_BUBBLE = 62587, + + NPC_TELDRASSIL_SPROUTLING = 33188, + SPELL_SPROUTLING_SLEEP = 62499, + SPELL_SPROUTLING_DANCE = 62504, + + NPC_TIRISFAL_BATLING = 33197, + NPC_VAMPIRIC_BATLING = 28513, + SPELL_TIRISFAL_BATLING_SOUND = 62545, + + NPC_TYRAEL = 29089, + SPELL_TYRAEL_DANCE = 54398, + + NPC_TRAIN_WRECKER = 33404, + SPELL_TRAIN_WRECKER_BLOW = 62943, + + NPC_DUNMOROGH_CUB = 33194, + NPC_BLIZZARD_BEAR = 32841, + SPELL_BLIZZARD_BEAR_SIT = 61853, + + NPC_MOJO = 24480, + SPELL_FEELING_FROGGY = 43906, + SPELL_FROG_LOVE = 62537, + + EMOTE_KISS = -1799979, + + NPC_ORPHANED_MAMMOTH = 25861, + SPELL_MAMMOTH_CREDIT = 46231, + + NPC_AMMEN_VALE_LASHING = 33205, + SAY_AMMEN_VALE_LASHING_1 = -1999799, + SAY_AMMEN_VALE_LASHING_2 = -1999798, + SAY_AMMEN_VALE_LASHING_3 = -1999797, + SAY_AMMEN_VALE_LASHING_4 = -1999796, + + NPC_DUROTAR_SCORPION = 33198, + SPELL_SCORPION_PERIODIC = 62679, + + NPC_ELWYNN_LAMB = 33200, + NPC_ELWYNN_WOLF = 33286, + SPELL_SUMMON_WOLF_PERIODIC = 62703, + SPELL_WOLF_ATTACK = 62701, + SPELL_PLAY_DEAD = 19822, + SPELL_SLEEP_VISUAL = 34664, + + NPC_FRIGID_FROSTLING = 40198, + SPELL_FROSTLING_PERIODIC = 74957, + + NPC_MECHANOPEEP = 33274, + SPELL_MECHANOPEEP_PERIODIC = 62676 +}; + +struct MANGOS_DLL_DECL npc_companion_handlerAI : public ScriptedPetAI +{ + npc_companion_handlerAI(Creature* pCreature) : ScriptedPetAI(pCreature){Reset();} + + uint32 m_uiActionTimer; + uint32 m_uiBreakAction; + uint32 m_uiHelperVar; + + void Reset() + { + m_uiHelperVar = 0; + m_uiActionTimer = 3000; + m_uiBreakAction = m_uiActionTimer + 7000; + m_creature->GetCharmInfo()->SetReactState(REACT_PASSIVE); + m_creature->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + } + + bool m_bOwnerIsIdle() + { + Unit* pOwner = m_creature->GetCharmerOrOwner(); + if (pOwner && pOwner->GetTypeId() == TYPEID_PLAYER && !((Player*)pOwner)->isMoving()) + return true; + + return false; + } + + void AttackStart(Unit* who){} + + void ReceiveEmote(Player* pPlayer, uint32 emote) + { + if (!pPlayer) + return; + switch (m_creature->GetEntry()) + { + case NPC_MOJO: + if (emote == TEXTEMOTE_KISS) + { + m_creature->SetTargetGuid(pPlayer->GetObjectGuid()); + DoScriptText(EMOTE_KISS,m_creature,pPlayer); + pPlayer->CastSpell(pPlayer,SPELL_FEELING_FROGGY,true); + DoCastSpellIfCan(m_creature,SPELL_FROG_LOVE,true); + } + break; + default: break; + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + switch (m_creature->GetEntry()) + { + case NPC_ORPHANED_MAMMOTH: + { + if (!m_creature->GetOwner()) + return; + if ((m_creature->GetOwner())->GetTypeId() != TYPEID_PLAYER) + return; + if (pWho->GetEntry() == 25862 && (m_creature->GetDistance(pWho) < 2*INTERACTION_DISTANCE)) + { + m_creature->GetMotionMaster()->MoveIdle(); + pWho->SetFacingToObject(m_creature); + m_creature->SetFacingToObject(pWho); + pWho->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + DoCastSpellIfCan(m_creature, SPELL_MAMMOTH_CREDIT); + m_creature->ForcedDespawn(); + } + break; + } + default: break; + } + } + + + void UpdatePetOOCAI(const uint32 uiDiff) + { + // Do pet's action + if (m_uiActionTimer < uiDiff) + { + m_uiActionTimer = 10000 + rand()%30000; + m_uiBreakAction = 7000; + + if (!m_bOwnerIsIdle()) + return; + + PetAction(m_creature->GetEntry()); + } + else + m_uiActionTimer -= uiDiff; + + // + if (m_uiBreakAction < uiDiff) + { + if (m_bOwnerIsIdle()) + { + m_uiBreakAction = 3000; + return; + } + + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + m_uiBreakAction = m_uiActionTimer + 7000; + } + else + m_uiBreakAction -= uiDiff; + + } + + void PetAction(uint32 uiPetEntry) + { + switch(uiPetEntry) + { + case NPC_PEANUT: + { + if (!m_creature->HasAura(NPC_PEANUT_PERIODIC)) + DoCastSpellIfCan(m_creature, NPC_PEANUT_PERIODIC); + break; + } + case NPC_PANDA: + { + switch(rand()%2) + { + case 0: DoCastSpellIfCan(m_creature, SPELL_PANDA_SLEEP); break; + case 1: DoCastSpellIfCan(m_creature, SPELL_PANDA_ROAR); break; + } + break; + } + case NPC_DIABLO: + { + DoCastSpellIfCan(m_creature, SPELL_DIABLO_FLAME); + break; + } + case NPC_ZERGLING: + { + if (!m_creature->HasAura(67399)) + DoCastSpellIfCan(m_creature, SPELL_ZERGLING_PASSIVE); + + if (!m_creature->HasAura(SPELL_ZERGLING_PERIODIC)) + DoCastSpellIfCan(m_creature, SPELL_ZERGLING_PERIODIC); + break; + } + case NPC_GRUNTY: + { + if (!m_creature->HasAura(SPELL_GRUNTY_PERIODIC)) + DoCastSpellIfCan(m_creature, SPELL_GRUNTY_PERIODIC); + break; + } + case NPC_WILLY: + { + DoCastSpellIfCan(m_creature, SPELL_WILLY_SLEEP); + break; + } + case NPC_DRAGON_KITE: + { + if (Unit* pOwner = m_creature->GetCharmerOrOwner()) + DoCastSpellIfCan(pOwner, SPELL_DRAGON_KITE_LIGHTNING); + break; + } + case NPC_BATTLE_BOT: + { + if (Creature* pBattleBot = GetClosestCreatureWithEntry(m_creature, NPC_BATTLE_BOT, 3.0f)) + { + m_creature->GetMotionMaster()->MovePoint(0, pBattleBot->GetPositionX()+rand()%5, pBattleBot->GetPositionY()+rand()%5, pBattleBot->GetPositionZ()); + DoCastSpellIfCan(m_creature, SPELL_BATTLE_BOT_MELEE); + pBattleBot->CastSpell(pBattleBot, SPELL_BATTLE_BOT_MELEE, false); + m_uiActionTimer = 3000; // make bot repeats the action + } + break; + } + case NPC_MURKY: + case NPC_LURKY: + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCE); + DoCastSpellIfCan(m_creature, SPELL_MURKY_DANCE); + break; + } + case NPC_EGBERT: + { + DoCastSpellIfCan(m_creature, SPELL_EGBERT_HAPPYNESS); + break; + } + case NPC_MULGORE: + { + DoCastSpellIfCan(m_creature, SPELL_MULGORE_HAPPYNESS); + break; + } + case NPC_PENGU: + case NPC_CHILLY: + { + DoCastSpellIfCan(m_creature, SPELL_PENGU_SOUND); + m_uiActionTimer = 5000 + rand()%5000; // repeat + break; + } + case NPC_STINKER: + { + DoCastSpellIfCan(m_creature, SPELL_STINKER_BROKEN_HEART); + break; + } + case NPC_SCORCHLING: + { + DoCastSpellIfCan(m_creature, SPELL_SCORCHLING_BLAST); + break; + } + case NPC_SPRING_RABBIT: + { + switch(rand()%2) + { + case 0: DoCastSpellIfCan(m_creature, SPELL_SPRING_RABBIT_IN_LOVE); break; + case 1: DoCastSpellIfCan(m_creature, SPELL_SPRING_RABBIT_JUMP); break; + } + break; + } + case NPC_STRAND_CRAWLERT: + { + DoCastSpellIfCan(m_creature, SPELL_STRAND_CRAWLERT_BUBBLE); + break; + } + case NPC_TELDRASSIL_SPROUTLING: + { + switch(rand()%2) + { + case 0: DoCastSpellIfCan(m_creature, SPELL_SPROUTLING_SLEEP); break; + case 1: DoCastSpellIfCan(m_creature, SPELL_SPROUTLING_DANCE); break; + } + break; + } + case NPC_TIRISFAL_BATLING: + case NPC_VAMPIRIC_BATLING: + { + DoCastSpellIfCan(m_creature, SPELL_TIRISFAL_BATLING_SOUND); + break; + } + case NPC_TYRAEL: + { + DoCastSpellIfCan(m_creature, SPELL_TYRAEL_DANCE); + break; + } + case NPC_TRAIN_WRECKER: + { + DoCastSpellIfCan(m_creature, SPELL_TRAIN_WRECKER_BLOW); + break; + } + case NPC_DUNMOROGH_CUB: + case NPC_BLIZZARD_BEAR: + { + DoCastSpellIfCan(m_creature, SPELL_BLIZZARD_BEAR_SIT); + break; + } + case NPC_AMMEN_VALE_LASHING: + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); + + if (m_uiHelperVar < 4) + { + DoScriptText(SAY_AMMEN_VALE_LASHING_1 + m_uiHelperVar, m_creature, m_creature->GetCharmerOrOwner()); + m_uiActionTimer = 3000; + ++m_uiHelperVar; + } + else + { + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + m_uiHelperVar = 0; + } + + break; + } + case NPC_DUROTAR_SCORPION: + { + if (!m_creature->HasAura(SPELL_SCORPION_PERIODIC)) + DoCastSpellIfCan(m_creature, SPELL_SCORPION_PERIODIC); + break; + } + case NPC_ELWYNN_LAMB: + { + if (!m_creature->HasAura(SPELL_SUMMON_WOLF_PERIODIC)) + DoCastSpellIfCan(m_creature, SPELL_SUMMON_WOLF_PERIODIC); + break; + } + case NPC_FRIGID_FROSTLING: + { + if (!m_creature->HasAura(SPELL_FROSTLING_PERIODIC)) + DoCastSpellIfCan(m_creature, SPELL_FROSTLING_PERIODIC); + break; + } + case NPC_MECHANOPEEP: + { + if (!m_creature->HasAura(SPELL_MECHANOPEEP_PERIODIC)) + DoCastSpellIfCan(m_creature, SPELL_MECHANOPEEP_PERIODIC); + break; + } + default: break; + } + } +}; + +CreatureAI* GetAI_npc_companion_handler(Creature* pCreature) +{ + return new npc_companion_handlerAI(pCreature); +} + +// special cases (non pets) +// for now only Elwynn Wolf +struct MANGOS_DLL_DECL npc_companion_helperAI : public ScriptedAI +{ + npc_companion_helperAI(Creature* pCreature) : ScriptedAI(pCreature){Reset();} + + void Reset() + { + if (Unit* pUnit = m_creature->GetMap()->GetUnit(m_creature->GetCreatorGuid())) + { + m_creature->SetWalk(false); + m_creature->GetMotionMaster()->MoveFollow(pUnit, 0.0f, m_creature->GetAngle(pUnit)); + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (pWho->GetObjectGuid() != m_creature->GetCreatorGuid() || pWho->GetDistance(m_creature) >= ATTACK_DISTANCE/3 || + m_creature->HasAura(SPELL_SLEEP_VISUAL) || pWho->HasAura(SPELL_PLAY_DEAD)) + return; + + DoCastSpellIfCan(pWho, SPELL_WOLF_ATTACK, CAST_TRIGGERED); + pWho->CastSpell(pWho, SPELL_PLAY_DEAD, true); + DoCastSpellIfCan(m_creature, SPELL_SLEEP_VISUAL, CAST_TRIGGERED); + m_creature->ForcedDespawn(5000); + } +}; + +CreatureAI* GetAI_npc_companion_helper(Creature* pCreature) +{ + return new npc_companion_helperAI(pCreature); +} + +void AddSC_npc_companion_handler() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_companion_handler"; + newscript->GetAI = &GetAI_npc_companion_handler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_companion_helper"; + newscript->GetAI = &GetAI_npc_companion_helper; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/world/npcs_special.cpp b/scripts/world/npcs_special.cpp index 97781b99e1..ca3ff6833e 100644 --- a/scripts/world/npcs_special.cpp +++ b/scripts/world/npcs_special.cpp @@ -26,6 +26,10 @@ EndScriptData #include "escort_ai.h" #include "ObjectMgr.h" #include "GameEventMgr.h" +#include "Spell.h" +#include "PetAI.h" +#include "Pet.h" +#include "SpellMgr.h" /* ContentData npc_air_force_bots 80% support for misc (invisible) guard bots in areas where player allowed to fly. Summon guards after a preset time if tagged by spell @@ -41,8 +45,17 @@ npc_sayge 100% Darkmoon event fortune teller, buff player based npc_tabard_vendor 50% allow recovering quest related tabards, achievement related ones need core support npc_locksmith 75% list of keys needs to be confirmed npc_death_knight_gargoyle AI for summoned gargoyle of deathknights -npc_horseman_fire_bunny -npc_shade_of_horseman +npc_training_dummy 100% AI for training dummies +npc_winter_reveler 100% Winterveil event +npc_metzen 100% Winterveil event +npc_experience_eliminator NPC to stop gaining experience +pet_spring_rabbit 100% Noblegarden event +pet_orphan 100% Children's Week +npc_wormhole 100% Creates an unstable wormhole +npc_bunny_bark Brewfest event +npc_bunny_fire_training Hallow's End event +npc_bunny_fire_town Hallow's End event +npc_bunny_horseman Hallow's End event EndContentData */ /*######## @@ -1101,6 +1114,78 @@ bool GossipSelect_npc_innkeeper(Player* pPlayer, Creature* pCreature, uint32 uiS return true; } +/*###### +## npc_kingdom_of_dalaran_quests +######*/ + +enum +{ + SPELL_TELEPORT_DALARAN = 53360, + ITEM_KT_SIGNET = 39740, + QUEST_MAGICAL_KINGDOM_A = 12794, + QUEST_MAGICAL_KINGDOM_H = 12791, + QUEST_MAGICAL_KINGDOM_N = 12796 +}; + +#define GOSSIP_ITEM_TELEPORT_TO "I am ready to be teleported to Dalaran." + +bool GossipHello_npc_kingdom_of_dalaran_quests(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid()); + + if (pPlayer->HasItemCount(ITEM_KT_SIGNET,1) && (!pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_A) || + !pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_H) || !pPlayer->GetQuestRewardStatus(QUEST_MAGICAL_KINGDOM_N))) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT_TO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_kingdom_of_dalaran_quests(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer,SPELL_TELEPORT_DALARAN,false); + } + return true; +} + +/*###### +## npc_lunaclaw_spirit +######*/ + +enum +{ + QUEST_BODY_HEART_A = 6001, + QUEST_BODY_HEART_H = 6002, + + TEXT_ID_DEFAULT = 4714, + TEXT_ID_PROGRESS = 4715 +}; + +#define GOSSIP_ITEM_GRANT "You have thought well, spirit. I ask you to grant me the strength of your body and the strength of your heart." + +bool GossipHello_npc_lunaclaw_spirit(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_BODY_HEART_A) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_BODY_HEART_H) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GRANT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_DEFAULT, pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_lunaclaw_spirit(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, pCreature->GetObjectGuid()); + pPlayer->AreaExploredOrEventHappens((pPlayer->GetTeam() == ALLIANCE) ? QUEST_BODY_HEART_A : QUEST_BODY_HEART_H); + } + return true; +} + /*###### ## npc_mount_vendor ######*/ @@ -1189,6 +1274,35 @@ bool GossipSelect_npc_mount_vendor(Player* pPlayer, Creature* pCreature, uint32 return true; } +/*###### +## npc_rogue_trainer +######*/ + +bool GossipHello_npc_rogue_trainer(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->getClass() != CLASS_ROGUE) return false; + + if (pPlayer->getLevel() >= 24 && !pPlayer->HasItemCount(17126,1) && !pPlayer->GetQuestRewardStatus(6681)) + if (pCreature->isQuestGiver()) + { + pPlayer->PrepareGossipMenu(pCreature,50195); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(5996, pCreature->GetObjectGuid()); + return true; + } + return false; +} + +bool GossipSelect_npc_rogue_trainer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CastSpell(pPlayer,21100,false); + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + } else return false; +} + /*###### ## npc_sayge ######*/ @@ -1483,6 +1597,156 @@ bool GossipSelect_npc_tabard_vendor(Player* pPlayer, Creature* pCreature, uint32 } /*###### +## npc_locksmith +######*/ + +enum +{ + QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ = 10704, + QUEST_DARK_IRON_LEGACY = 3802, + QUEST_THE_KEY_TO_SCHOLOMANCE_A = 5505, + QUEST_THE_KEY_TO_SCHOLOMANCE_H = 5511, + QUEST_HOTTER_THAN_HELL_A = 10758, + QUEST_HOTTER_THAN_HELL_H = 10764, + QUEST_RETURN_TO_KHAGDAR = 9837, + QUEST_CONTAINMENT = 13159, + + ITEM_ARCATRAZ_KEY = 31084, + ITEM_SHADOWFORGE_KEY = 11000, + ITEM_SKELETON_KEY = 13704, + ITEM_SHATTERED_HALLS_KEY = 28395, + ITEM_THE_MASTERS_KEY = 24490, + ITEM_VIOLET_HOLD_KEY = 42482, + + SPELL_ARCATRAZ_KEY = 54881, + SPELL_SHADOWFORGE_KEY = 54882, + SPELL_SKELETON_KEY = 54883, + SPELL_SHATTERED_HALLS_KEY = 54884, + SPELL_THE_MASTERS_KEY = 54885, + SPELL_VIOLET_HOLD_KEY = 67253 +}; + +#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz." +#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths." +#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance." +#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls." +#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan." +#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold." + +bool GossipHello_npc_locksmith(Player* pPlayer, Creature* pCreature) +{ + + // Arcatraz Key + if (pPlayer->GetQuestRewardStatus(QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ) && !pPlayer->HasItemCount(ITEM_ARCATRAZ_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ARCATRAZ_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +1); + + // Shadowforge Key + if (pPlayer->GetQuestRewardStatus(QUEST_DARK_IRON_LEGACY) && !pPlayer->HasItemCount(ITEM_SHADOWFORGE_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHADOWFORGE_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +2); + + // Skeleton Key + if ((pPlayer->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_A) || pPlayer->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_H)) && + !pPlayer->HasItemCount(ITEM_SKELETON_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SKELETON_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +3); + + // Shatered Halls Key + if ((pPlayer->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_A) || pPlayer->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_H)) && + !pPlayer->HasItemCount(ITEM_SHATTERED_HALLS_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHATTERED_HALLS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +4); + + // Master's Key + if (pPlayer->GetQuestRewardStatus(QUEST_RETURN_TO_KHAGDAR) && !pPlayer->HasItemCount(ITEM_THE_MASTERS_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_THE_MASTERS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +5); + + // Violet Hold Key + if (pPlayer->GetQuestRewardStatus(QUEST_CONTAINMENT) && !pPlayer->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF +6); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + + return true; +} + +bool GossipSelect_npc_locksmith(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_ARCATRAZ_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SHADOWFORGE_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SKELETON_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_SHATTERED_HALLS_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+5: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_THE_MASTERS_KEY, false); + break; + case GOSSIP_ACTION_INFO_DEF+6: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->CastSpell(pPlayer, SPELL_VIOLET_HOLD_KEY, false); + break; + } + return true; +} + +/*###### +## npc_experience_eliminator +######*/ + +#define GOSSIP_ITEM_STOP_XP_GAIN "I don't want to gain experience anymore." +#define GOSSIP_CONFIRM_STOP_XP_GAIN "Are you sure you want to stop gaining experience?" +#define GOSSIP_ITEM_START_XP_GAIN "I want to be able to gain experience again." +#define GOSSIP_CONFIRM_START_XP_GAIN "Are you sure you want to be able to gain experience once again?" + +bool GossipHello_npc_experience_eliminator(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM_EXTENDED( + GOSSIP_ICON_CHAT, + pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_XP_USER_DISABLED) ? GOSSIP_ITEM_START_XP_GAIN : GOSSIP_ITEM_STOP_XP_GAIN, + GOSSIP_SENDER_MAIN, + GOSSIP_ACTION_INFO_DEF+1, + pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_XP_USER_DISABLED) ? GOSSIP_CONFIRM_START_XP_GAIN : GOSSIP_CONFIRM_STOP_XP_GAIN, + 100000, + false + ); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_experience_eliminator(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if(uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + // cheater(?) passed through client limitations + if(pPlayer->GetMoney() < 100000) + return true; + + pPlayer->ModifyMoney(-100000); + + if(pPlayer->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_XP_USER_DISABLED)) + pPlayer->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_XP_USER_DISABLED); + else + pPlayer->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_XP_USER_DISABLED); + + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + } +pPlayer->CLOSE_GOSSIP_MENU(); +return true; +} + +/*######## ## npc_mirror_image ######*/ @@ -1496,8 +1760,6 @@ enum MirrorImageSpells SPELL_FROSTBOLT = 59638, SPELL_FROSTSHIELD = 43008, SPELL_FIRESHIELD = 43046, - SPELL_ICEBLOCK = 65802, - SPELL_ICERING = 42917, }; struct MANGOS_DLL_DECL npc_mirror_imageAI : public ScriptedAI @@ -1505,7 +1767,6 @@ struct MANGOS_DLL_DECL npc_mirror_imageAI : public ScriptedAI npc_mirror_imageAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} uint32 m_uiFrostboltTimer; - uint32 m_uiFrostringTimer; uint32 m_uiFireblastTimer; bool inCombat; Unit *owner; @@ -1530,8 +1791,7 @@ struct MANGOS_DLL_DECL npc_mirror_imageAI : public ScriptedAI m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+2, owner->GetUInt32Value(PLAYER_VISIBLE_ITEM_18_ENTRYID)); m_creature->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN), true); - m_uiFrostboltTimer = urand(0,3000); - m_uiFrostringTimer = urand(2000,6000); + m_uiFrostboltTimer = 500; m_uiFireblastTimer = urand(0,3000); inCombat = false; blocked = false; @@ -1631,20 +1891,8 @@ struct MANGOS_DLL_DECL npc_mirror_imageAI : public ScriptedAI if (m_uiFireblastTimer <= diff) { DoCastSpellIfCan(m_creature->getVictim(),SPELL_FIREBLAST); - m_uiFireblastTimer = urand(1000,6000); + m_uiFireblastTimer = urand(4000,8000); } else m_uiFireblastTimer -= diff; - - if (m_uiFrostringTimer <= diff && m_creature->IsWithinDistInMap(m_creature->getVictim(),5.0f)) - { - DoCastSpellIfCan(m_creature->getVictim(),SPELL_ICERING); - m_uiFrostringTimer = urand(4000,8000); - } else m_uiFrostringTimer -= diff; - - if (!blocked && m_creature->GetHealthPercent() < 10.0f) - { - DoCastSpellIfCan(m_creature,SPELL_ICEBLOCK); - blocked = true; - } } else if (!movement) @@ -1671,72 +1919,72 @@ CreatureAI* GetAI_npc_mirror_image(Creature* pCreature) #define SPELL_DEADLY_POISON 34655 //Venomous Snake #define MOB_VIPER 19921 -#define MOB_VENOM_SNIKE 19833 struct MANGOS_DLL_DECL npc_snake_trap_serpentsAI : public ScriptedAI { npc_snake_trap_serpentsAI(Creature *c) : ScriptedAI(c) {Reset();} uint32 SpellTimer; - Unit* Owner; + bool IsViper; void Reset() { SpellTimer = 500; - Owner = m_creature->GetCharmerOrOwner(); - if (!Owner) return; - m_creature->SetLevel(Owner->getLevel()); - m_creature->setFaction(Owner->getFaction()); - } + Unit *Owner = m_creature->GetOwner(); + if (!Owner) return; - void AttackStart(Unit* pWho) - { - if (!pWho) return; + CreatureInfo const *Info = m_creature->GetCreatureInfo(); - if (m_creature->Attack(pWho, true)) - { - m_creature->SetInCombatWith(pWho); - m_creature->AddThreat(pWho, 100.0f); - SetCombatMovement(true); - m_creature->GetMotionMaster()->MoveChase(pWho); - } + if (Info->Entry == MOB_VIPER) + IsViper = true; + else + IsViper = false; } void UpdateAI(const uint32 diff) { + Unit *Owner = m_creature->GetOwner(); + + if (!Owner) return; + if (!m_creature->getVictim()) { - if (Owner && Owner->getVictim()) - AttackStart(Owner->getVictim()); - return; + if (m_creature->isInCombat()) + DoStopAttack(); + + if (Owner->getAttackerForHelper()) + AttackStart(Owner->getAttackerForHelper()); } if (SpellTimer <= diff) { - if (m_creature->GetEntry() == MOB_VIPER ) //Viper - 19921 + if (IsViper) //Viper - 19921 { - if (!urand(0,2)) //33% chance to cast + if (urand(0,2) == 0) //33% chance to cast { uint32 spell; - if (urand(0,1)) + if (urand(0,1) == 0) spell = SPELL_MIND_NUMBING_POISON; else spell = SPELL_CRIPPLING_POISON; - DoCast(m_creature->getVictim(), spell); + m_creature->CastSpell(m_creature->getVictim(), spell, true); } - SpellTimer = urand(3000, 5000); + SpellTimer = urand(4000, 7000); } - else if (m_creature->GetEntry() == MOB_VENOM_SNIKE ) //Venomous Snake - 19833 + else //Venomous Snake - 19833 { if (urand(0,1) == 0) //80% chance to cast - DoCast(m_creature->getVictim(), SPELL_DEADLY_POISON); - SpellTimer = urand(2500, 4500); + m_creature->CastSpell(m_creature->getVictim(), SPELL_DEADLY_POISON, true); + SpellTimer = urand(3500, 7500); } + } + else + { + SpellTimer -= diff; + DoMeleeAttackIfReady(); } - else SpellTimer -= diff; - DoMeleeAttackIfReady(); } }; @@ -1746,6 +1994,10 @@ CreatureAI* GetAI_npc_snake_trap_serpents(Creature* pCreature) return new npc_snake_trap_serpentsAI(pCreature); } +/*######## +# npc_rune_blade AI +#########*/ + struct MANGOS_DLL_DECL npc_rune_blade : public ScriptedAI { npc_rune_blade(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} @@ -1800,10 +2052,10 @@ CreatureAI* GetAI_npc_rune_blade(Creature* pCreature) } /*######## -# mob_death_knight_gargoyle AI +# npc_death_knight_gargoyle AI #########*/ -// UPDATE `creature_template` SET `ScriptName` = 'mob_death_knight_gargoyle' WHERE `entry` = '27829'; +// UPDATE `creature_template` SET `ScriptName` = 'npc_death_knight_gargoyle' WHERE `entry` = '27829'; enum GargoyleSpells { @@ -1926,9 +2178,66 @@ CreatureAI* GetAI_npc_death_knight_gargoyle(Creature* pCreature) return new npc_death_knight_gargoyle(pCreature); } -/*######## -# npc_risen_ally AI -#########*/ +/*###### +## npc_training_dummy +######*/ + +#define OUT_OF_COMBAT_TIME 5000 +#define STUN_DURATION 55000 +#define SPELL_STUN_4EVER 36877 + +struct MANGOS_DLL_DECL npc_training_dummyAI : public Scripted_NoMovementAI +{ + npc_training_dummyAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) + { + Reset(); + } + + uint32 combat_timer; + uint32 stun_timer; + + void Reset() + { + m_creature->CastSpell(m_creature, SPELL_STUN_4EVER, true); + stun_timer = STUN_DURATION; + combat_timer = 0; + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + combat_timer = 0; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->GetHealthPercent() < 1.0f) // allow players using finishers + m_creature->ModifyHealth(m_creature->GetMaxHealth()); + + combat_timer += diff; + if (stun_timer <= diff) + { + m_creature->CastSpell(m_creature, SPELL_STUN_4EVER, true); + stun_timer = STUN_DURATION; + } + else + stun_timer -= diff; + + if (combat_timer > OUT_OF_COMBAT_TIME) + EnterEvadeMode(); + } +}; + +CreatureAI* GetAI_npc_training_dummy(Creature* pCreature) +{ + return new npc_training_dummyAI(pCreature); +} + +/*###### +# npc_risen_ally +#######*/ struct MANGOS_DLL_DECL npc_risen_allyAI : public ScriptedAI { @@ -2000,9 +2309,9 @@ CreatureAI* GetAI_npc_risen_ally(Creature* pCreature) return new npc_risen_allyAI(pCreature); } -/*######## -# npc_explosive_decoyAI -#########*/ +/*###### +# npc_explosive_decoy +######*/ struct MANGOS_DLL_DECL npc_explosive_decoyAI : public ScriptedAI { @@ -2059,9 +2368,9 @@ CreatureAI* GetAI_npc_explosive_decoy(Creature* pCreature) return new npc_explosive_decoyAI(pCreature); } -/*######## -# npc_eye_of_kilroggAI -#########*/ +/*###### +# npc_eye_of_kilrogg +######*/ struct MANGOS_DLL_DECL npc_eye_of_kilrogg : public ScriptedAI { @@ -2098,342 +2407,972 @@ CreatureAI* GetAI_npc_eye_of_kilrogg(Creature* pCreature) return new npc_eye_of_kilrogg(pCreature); } -/*######## -# npc_fire_bunny -#########*/ +/*###### +# npc_battle_standard +######*/ -enum +#define DESPAWN_TIME 120000 // 2 minutes + +struct MANGOS_DLL_DECL npc_battle_standard : public ScriptedAI { - NPC_FIRE_BUNNY = 23686, - SPELL_THROW_BUCKET = 42339, - SPELL_EXTINGUISH_VISUAL = 42348, - SPELL_FLAMES_LARGE = 42075, - SPELL_SMOKE = 42355, - SPELL_CONFLAGRATE = 42132, - SPELL_HORSEMAN_MOUNT = 48024, - SPELL_HORSMAN_SHADE_VIS = 43904, - SPELL_Q_STOP_THE_FIRE = 42242, - SPELL_Q_LET_THE_FIRES_C = 47775, - SPELL_LAUGH_DELAYED_8 = 43893, - - PHASE_INITIAL = 0, - PHASE_1ST_SPEACH = 1, - PHASE_2ND_SPEACH = 2, - PHASE_FAIL = 3, - PHASE_END = 4, - - YELL_IGNITE = -1110001, - YELL_1ST = -1110002, - YELL_2ND = -1110003, - YELL_FAIL = -1110004, - YELL_VICTORY = -1110005, - YELL_CONFLAGRATION = -1110006 + npc_battle_standard(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + + int32 despawn_timer; + + void Reset() + { + despawn_timer = DESPAWN_TIME; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + m_creature->SetSpeedRate(MOVE_WALK, 0.0f); + m_creature->SetSpeedRate(MOVE_RUN, 0.0f); + } + + void UpdateAI(const uint32 uiDiff) + { + if (despawn_timer <= 0) + m_creature->ForcedDespawn(); + else + despawn_timer -= uiDiff; + } }; -struct MANGOS_DLL_DECL npc_horseman_fire_bunnyAI : public Scripted_NoMovementAI +CreatureAI* GetAI_npc_battle_standard(Creature* pCreature) { - npc_horseman_fire_bunnyAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) - { - Reset(); - m_creature->RemoveAllAuras(); - } + return new npc_battle_standard(pCreature); +} +namespace Pasqua2011 +{ + +#define GOSSIP_MASTRO_ERMES "Voglio fare lo Zabaione Speciale." +/*################################## +#Quest Zabaione Speciale # +###################################*/ +enum +{ + QUEST_ZABAIONE_SPECIALE = 112644, + SAY_EVENT_STARTED = -2760000, + SAY_ADD_BANNANAS = -2760001, + SAY_ADD_PAPAYA = -2760002, + SAY_GOOD_JOB_1 = -2760003, + SAY_BRAZIER = -2760004, + SAY_GOOD_JOB_2 = -2760005, + SAY_OPEN_VALVE = -2760006, + SAY_GOOD_JOB_3 = -2760007, + SAY_GOOD_JOB_4 = -2760008, + SAY_EVENT_END = -2760009, + SAY_ADD_ORANGE = -2760010, + SAY_FAIL = -2760011, + GO_JUNGLE_PUNCH = 490643 +}; +int32 GoogJobText[4] = {SAY_GOOD_JOB_1,SAY_GOOD_JOB_2,SAY_GOOD_JOB_3,SAY_GOOD_JOB_4}; +struct MANGOS_DLL_DECL npc_mastro_ermesAI : public ScriptedAI +{ + npc_mastro_ermesAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + + bool bEventCanBeStarted; + bool bEventStarted; + uint32 m_uiStepTimer; + uint32 m_uiEventStartTimer; + uint32 uiPhase; + uint32 uiObjectToClick; + uint32 uiCurrentClickedObject; + uint32 uiPhaseCounter; + /* + banana = 1 + orange = 2 + papaya = 3 + pressure valve = 4 + brazier = 5 + + */ void Reset() { - if (!m_creature->isAlive()) - m_creature->Respawn(); + bEventCanBeStarted = false; + bEventStarted = false; + m_uiStepTimer = 10000; + m_uiEventStartTimer = 5000; + uiPhase = 0; + uiObjectToClick = 0; + uiCurrentClickedObject = 0; + uiPhaseCounter = 0; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } - void SpellHit(Unit* pWho, const SpellEntry* pSpell) + bool CheckClickedObject(uint32 uiObjectToClick) { - if (pSpell->Id == SPELL_THROW_BUCKET) + if(uiObjectToClick == uiCurrentClickedObject) + return true; + + else return false; + + } + void SayEventText(uint32 uiTextIdentifier) + { + switch(uiTextIdentifier) { - pWho->CastSpell(m_creature, SPELL_EXTINGUISH_VISUAL, false); - m_creature->RemoveAurasDueToSpell(SPELL_FLAMES_LARGE); + case 1: DoScriptText(SAY_ADD_BANNANAS, m_creature); break; + case 2: DoScriptText(SAY_ADD_ORANGE, m_creature); break; + case 3: DoScriptText(SAY_ADD_PAPAYA, m_creature); break; + case 4: DoScriptText(SAY_OPEN_VALVE, m_creature); break; + case 5: DoScriptText(SAY_BRAZIER, m_creature); break; + default: break; } - if (pSpell->Id == SPELL_CONFLAGRATE) + } + + void UpdateAI (uint32 const uiDiff) + { + if (bEventCanBeStarted) { - DoCastSpellIfCan(m_creature, SPELL_FLAMES_LARGE); - m_creature->RemoveAurasDueToSpell(SPELL_CONFLAGRATE); + if (m_uiEventStartTimer <= uiDiff && !bEventStarted) + { + uiObjectToClick = urand(1,3); + SayEventText(uiObjectToClick); + m_uiEventStartTimer = 0; + bEventStarted = true; + uiPhase++; + } + else m_uiEventStartTimer -= uiDiff; + + if(bEventStarted) + { + if (m_uiStepTimer <=uiDiff) + { + switch(uiPhase) + { + case 1: + if(CheckClickedObject(uiObjectToClick)) + { + DoScriptText(GoogJobText[urand(0,3)] , m_creature); + uiObjectToClick = urand(1,3); + SayEventText(uiObjectToClick); + + uiPhaseCounter++; + if(uiPhaseCounter == 3){ uiPhase++; uiPhaseCounter=0;} + } + else {Reset(); DoScriptText(SAY_FAIL, m_creature);} + break; + + case 2: + if(CheckClickedObject(uiObjectToClick)) + { + DoScriptText(GoogJobText[urand(0,3)] , m_creature); + uiObjectToClick = urand(4,5); + SayEventText(uiObjectToClick); + uiPhase++; + } + else {Reset(); DoScriptText(SAY_FAIL, m_creature);} + break; + case 3: + if(CheckClickedObject(uiObjectToClick)) + { + DoScriptText(GoogJobText[urand(0,3)] , m_creature); + uiObjectToClick = urand(1,5); + SayEventText(uiObjectToClick); + uiPhaseCounter++; + if(uiPhaseCounter == 6)uiPhase++; + } + else {Reset(); DoScriptText(SAY_FAIL, m_creature);} + break; + case 4: + DoScriptText(SAY_EVENT_END , m_creature); + if(GameObject* pGo = GetClosestGameObjectWithEntry(m_creature, GO_JUNGLE_PUNCH, 15.0f)) + { + pGo->SetRespawnTime(3*MINUTE); //despawn object in ? seconds + pGo->Respawn(); + + Reset(); + } + break; + + default: break; + + } + m_uiStepTimer=5000; + } + else m_uiStepTimer -=uiDiff; + + } } } +}; - void UpdateAI(const uint32 uiDiff) +CreatureAI* GetAI_npc_mastro_ermes(Creature* pCreature) +{ + return new npc_mastro_ermesAI(pCreature); +}; + +bool GossipHello_npc_mastro_ermes(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetQuestStatus(QUEST_ZABAIONE_SPECIALE) == QUEST_STATUS_INCOMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MASTRO_ERMES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_mastro_ermes(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) { - if (m_creature->SelectHostileTarget() || m_creature->getVictim()) - EnterEvadeMode(); // Dunno how to prevent them from entering combat while hit by SPELL_EXTINGUISH_VISUAL (spelleffect 2) + pPlayer->CLOSE_GOSSIP_MENU(); + if (npc_mastro_ermesAI* pErmesAI = dynamic_cast(pCreature->AI())) + { + pErmesAI->bEventCanBeStarted=true; + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoScriptText(SAY_EVENT_STARTED, pCreature); + } } + return true; +} + +/*################################ +#Quest Zabaione Speciale - gameobjects # +#################################*/ +enum +{ + GO_BARREL_OF_ORANGES = 490637, + GO_BARREL_OF_PAPAYAS = 490639, + GO_BARREL_OF_BANANAS = 490638, + GO_PRESSURE_VALVE = 490635, + GO_BRAZIER = 490636, + NPC_MASTRO_ERMES = 428566, }; -CreatureAI* GetAI_npc_horseman_fire_bunny(Creature* pCreature) +bool GOUse_go_zabaione(Player* pPlayer, GameObject* pGo) { - return new npc_horseman_fire_bunnyAI (pCreature); + if (pPlayer->GetQuestStatus(QUEST_ZABAIONE_SPECIALE) == QUEST_STATUS_INCOMPLETE) + { + if(Creature* pErmes = GetClosestCreatureWithEntry(pPlayer, NPC_MASTRO_ERMES, 30.0f)) + { + if (npc_mastro_ermesAI* pErmesAI = dynamic_cast(pErmes->AI())) + { + switch (pGo->GetEntry()) + { + case GO_BARREL_OF_ORANGES: pErmesAI->uiCurrentClickedObject = 2; break; + case GO_BARREL_OF_PAPAYAS: pErmesAI->uiCurrentClickedObject = 3; break; + case GO_BARREL_OF_BANANAS: pErmesAI->uiCurrentClickedObject = 1; break; + case GO_PRESSURE_VALVE: pErmesAI->uiCurrentClickedObject = 4; break; + case GO_BRAZIER: pErmesAI->uiCurrentClickedObject = 5; break; + + break; + } + } + } + } + return false; }; -/*######## -# npc_shade of horseman -#########*/ +} -struct MANGOS_DLL_DECL npc_shade_of_horsemanAI : public ScriptedAI +#define GOSSIP_ITEM_1 "Heal me.. please.. " +#define GOSSIP_ITEM_2 "BRRRAINS! " +// Argent Healer Gossip Menu +//This function is called when the player opens the gossip menubool +bool GossipHello_npc_argent_healer(Player* pPlayer, Creature* pCreature) { - npc_shade_of_horsemanAI(Creature* pCreature) : ScriptedAI(pCreature){Reset();} + if(pPlayer->HasAura(43958)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetObjectGuid()); + } + return true; +} - uint8 uiPhase; - uint32 m_uiEventTimer; - uint32 m_uiConflagrationTimer; - uint32 m_uiConflagrationProcTimer; - bool bIsConflagrating; +bool GossipSelect_npc_argent_healer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiSender == GOSSIP_SENDER_MAIN) + { + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + //pPlayer->CastSpell(pPlayer, SPELL_SHIELD_OF_BLUE, false); + pCreature->MonsterSay("May the Light purge your infection", LANG_UNIVERSAL, pPlayer); + pCreature->CastSpell(pPlayer,528,true); + pPlayer->CLOSE_GOSSIP_MENU(); + return true; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + } + } + return true; +} - GUIDList lFireBunnies; +/*###### +## npc_winter_reveler +######*/ - void Reset() +enum +{ + AURA_MISTLETOE = 26004, + ITEM_SNOWFLAKES = 34191, + ITEM_MISTLETOE = 21519, + ITEM_FRESH_HOLLY = 21212, +}; + +struct MANGOS_DLL_DECL npc_winter_revelerAI : public ScriptedAI +{ + npc_winter_revelerAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + void ReceiveEmote(Player* pPlayer, uint32 uiEmote) { - if (!m_creature->isAlive()) - m_creature->Respawn(); + if (uiEmote == TEXTEMOTE_KISS) + { + if (!pPlayer->HasAura(AURA_MISTLETOE)) + { + switch (rand()%3) + { + case 0: + { + ItemPosCountVec dest; + InventoryResult msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_SNOWFLAKES, 1, NULL); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_SNOWFLAKES, true); + else + pPlayer->SendEquipError(msg, NULL, NULL); + break; + } + case 1: + { + ItemPosCountVec dest; + InventoryResult msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_MISTLETOE, 1, NULL); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_MISTLETOE, true); + else + pPlayer->SendEquipError(msg, NULL, NULL); + break; + } + case 2: + { + ItemPosCountVec dest; + InventoryResult msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_FRESH_HOLLY, 1, NULL); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_FRESH_HOLLY, true); + else + pPlayer->SendEquipError(msg, NULL, NULL); + break; + } + } + m_creature->CastSpell(pPlayer, AURA_MISTLETOE, false); + } + } + } - uiPhase = PHASE_INITIAL; - lFireBunnies.clear(); - bIsConflagrating = true; - m_uiEventTimer = 2.5*MINUTE*IN_MILLISECONDS; + void Reset() {} +}; + +CreatureAI* GetAI_npc_winter_reveler(Creature* pCreature) +{ + return new npc_winter_revelerAI(pCreature); +} + +/*###### +## npc_metzen +######*/ - m_uiConflagrationTimer = 30000; - m_uiConflagrationProcTimer = 2000; +#define GOSSIP_TEXT_METZEN "Berieselt Metzten mit etwas Rentierstaub" - DoCastSpellIfCan(m_creature, SPELL_HORSEMAN_MOUNT); - DoCastSpellIfCan(m_creature, SPELL_HORSMAN_SHADE_VIS); +enum +{ + QUEST_METZEN_ALLIANCE = 8762, + QUEST_METZEN_HORDE = 8746, + NPC_METZEN_KILL_CREDIT = 15664, + SPELL_REINDEER_DUST = 25952 +}; + +bool GossipHello_npc_metzen(Player* pPlayer, Creature* pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEXT_METZEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(8076, pCreature->GetObjectGuid()); + return true; +} + +bool GossipSelect_npc_metzen(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if(uiSender != GOSSIP_SENDER_MAIN) return true; + + if(uiAction == GOSSIP_ACTION_INFO_DEF) + { + if((pPlayer->GetQuestStatus(QUEST_METZEN_ALLIANCE) == QUEST_STATUS_INCOMPLETE) || (pPlayer->GetQuestStatus(QUEST_METZEN_HORDE) == QUEST_STATUS_INCOMPLETE)) + { + pPlayer->KilledMonsterCredit(NPC_METZEN_KILL_CREDIT); + pCreature->CastSpell(pCreature, SPELL_REINDEER_DUST, true); + } } + return true; +} - void UpdateAI(const uint32 uiDiff) +/*###### +# npc_wormhole +######*/ + +enum eWormhole +{ + SPELL_BOREAN_TUNDRA = 67834, + SPELL_HOWLING_FJORD = 67838, + SPELL_SHOLAZAR_BASIN = 67835, + SPELL_ICECROWN = 67836, + SPELL_STORM_PEAKS = 67837, + + TEXT_WORMHOLE = 907, + + MAP_NORTHREND = 571 +}; + +static const char* WormholeGossip[6] = +{ + "Borean Tundra.", + "Howling Fjord.", + "Sholazar Basin.", + "Icecrown.", + "Storm Peaks.", + "Underground...", +}; + +static float WormholeTele[7][4] = +{ + {3172.33f, 5608.70f, 595.01f, 1.18f}, // Borean Tundra 1 + {1180.55f, -4876.56f, 408.80f, 0.43f}, // Howling Fjord + {6234.36f, 4766.68f, 224.71f, 4.23f}, // Sholazar Basin + {8113.86f, 1352.32f, 848.87f, 0.26f}, // Icecrown + {8992.79f, -1222.29f, 1058.40f, 2.87f}, // Storm Peaks + {5859.29f, 516.25f, 599.81f, 3.15f}, // Underground (under Horde section of Dalaran) + {4297.19f, 5464.91f, 52.60f, 3.38f}, // Borean Tundra 2 +}; + +bool GossipHello_npc_wormhole(Player* pPlayer, Creature* pCreature) +{ + if (pPlayer->GetSkillValue(SKILL_ENGINEERING) >= 415) { - if (uiPhase == PHASE_INITIAL) + for (uint8 i=0; i<=5; ++i) { - DoScriptText(YELL_IGNITE, m_creature); - ++uiPhase; - return; + if (i == 5 && urand(0, 19)) + continue; + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, WormholeGossip[i], GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+i+1); } - else if (uiPhase == PHASE_END) + + pPlayer->PlayerTalkClass->SendGossipMenu(TEXT_WORMHOLE, pCreature->GetObjectGuid()); + } + return true; +} + +bool GossipSelect_npc_wormhole(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + pPlayer->PlayerTalkClass->ClearMenus(); + + uint8 uiI = uiAction - GOSSIP_ACTION_INFO_DEF - 1; + uint8 uiH; + + if (uiI != 5 && !urand(0, 9)) + uiH = urand(10, 50); + else + uiH = 0; + + pPlayer->CLOSE_GOSSIP_MENU(); + // borean tundra has two locations and we have to pick one randomly + if(uiI == 0 && urand(0,1)) + uiI = 6; + pPlayer->TeleportTo(MAP_NORTHREND, WormholeTele[uiI][0], WormholeTele[uiI][1], WormholeTele[uiI][2]+uiH, WormholeTele[uiI][3]); + pCreature->ForcedDespawn(); + return true; +}; + +/*##### +# npc_bunny_bark +#####*/ +enum +{ + NPC_BUNNY_1 = 24202, + NPC_BUNNY_2 = 24203, + NPC_BUNNY_3 = 24204, + NPC_BUNNY_4 = 24205, + + QUEST_BARK_FOR_BARLEY = 11293, + QUEST_BARK_FOR_THUNDER = 11294, + QUEST_BARK_FOR_DROHN = 11407, + QUEST_BARK_FOR_TCHALI = 11408, + + SAY_DROHN_1 = -2000001, + SAY_DROHN_2 = -2000002, + SAY_DROHN_3 = -2000003, + SAY_DROHN_4 = -2000004, + SAY_TCHALI_1 = -2000005, + SAY_TCHALI_2 = -2000006, + SAY_TCHALI_3 = -2000007, + SAY_TCHALI_4 = -2000008, + SAY_BARLEY_1 = -2000009, + SAY_BARLEY_2 = -2000010, + SAY_BARLEY_3 = -2000011, + SAY_BARLEY_4 = -2000012, + SAY_THUNDER_1 = -2000013, + SAY_THUNDER_2 = -2000014, + SAY_THUNDER_3 = -2000015, + SAY_THUNDER_4 = -2000016 +}; + +struct MANGOS_DLL_DECL npc_bunny_bark : public ScriptedAI +{ + npc_bunny_bark (Creature* pCreature) : ScriptedAI (pCreature) + { + m_pMap = pCreature->GetMap(); + Reset(); + } + + Map* m_pMap; + + void Reset () {} + + void MoveInLineOfSight (Unit* pWho) + { + // player should be near the npc + if (m_creature->GetDistance(pWho) > 10.0f) + return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + + Player* pPlayer = m_pMap->GetPlayer(pWho->GetObjectGuid()); + if (!pPlayer) return; - if (!bIsConflagrating) + if (pPlayer->GetQuestStatus(QUEST_BARK_FOR_BARLEY) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_BARK_FOR_THUNDER) == QUEST_STATUS_INCOMPLETE || + pPlayer->GetQuestStatus(QUEST_BARK_FOR_DROHN) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(QUEST_BARK_FOR_TCHALI) == QUEST_STATUS_INCOMPLETE ) { - bool IsVictory = true; - for (GUIDList::iterator itr = lFireBunnies.begin(); itr != lFireBunnies.end(); ++itr) - if (Creature* pFireBunny = m_creature->GetMap()->GetCreature(*itr)) - if (pFireBunny->HasAura(SPELL_FLAMES_LARGE)) - IsVictory = false; - if (IsVictory) + int32 iText = 0; + switch (m_creature->GetEntry()) { - DoScriptText(YELL_VICTORY, m_creature); - DoCastSpellIfCan(m_creature, SPELL_Q_STOP_THE_FIRE, CAST_TRIGGERED); - DoCastSpellIfCan(m_creature, SPELL_Q_LET_THE_FIRES_C, CAST_TRIGGERED); - m_creature->ForcedDespawn(5000); - uiPhase = PHASE_END; - return; + case NPC_BUNNY_1: + if (pPlayer->HasQuest(QUEST_BARK_FOR_BARLEY)) + iText = SAY_BARLEY_1; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_THUNDER)) + iText = SAY_THUNDER_1; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_DROHN)) + iText = SAY_DROHN_1; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_TCHALI)) + iText = SAY_TCHALI_1; + break; + case NPC_BUNNY_2: + if (pPlayer->HasQuest(QUEST_BARK_FOR_BARLEY)) + iText = SAY_BARLEY_2; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_THUNDER)) + iText = SAY_THUNDER_2; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_DROHN)) + iText = SAY_DROHN_2; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_TCHALI)) + iText = SAY_TCHALI_2; + break; + case NPC_BUNNY_3: + if (pPlayer->HasQuest(QUEST_BARK_FOR_BARLEY)) + iText = SAY_BARLEY_3; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_THUNDER)) + iText = SAY_THUNDER_3; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_DROHN)) + iText = SAY_DROHN_3; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_TCHALI)) + iText = SAY_TCHALI_3; + break; + case NPC_BUNNY_4: + if (pPlayer->HasQuest(QUEST_BARK_FOR_BARLEY)) + iText = SAY_BARLEY_4; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_THUNDER)) + iText = SAY_THUNDER_4; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_DROHN)) + iText = SAY_DROHN_4; + else if (pPlayer->HasQuest(QUEST_BARK_FOR_TCHALI)) + iText = SAY_TCHALI_4; + break; } + if (iText) + DoScriptText(iText, pPlayer, NULL); + pPlayer->KilledMonsterCredit(m_creature->GetEntry()); } + } +}; - if (m_uiEventTimer < uiDiff) - { - switch(uiPhase) - { - case PHASE_1ST_SPEACH: - DoScriptText(YELL_1ST, m_creature); - m_uiEventTimer = 2 *MINUTE*IN_MILLISECONDS; - break; +CreatureAI* GetAI_npc_bunny_bark(Creature* pCreature) +{ + return new npc_bunny_bark(pCreature); +} - case PHASE_2ND_SPEACH: - DoScriptText(YELL_2ND, m_creature); - m_uiEventTimer = 0.5 *MINUTE*IN_MILLISECONDS; - break; - case PHASE_FAIL: - DoScriptText(YELL_FAIL, m_creature); - m_creature->ForcedDespawn(10000); - for (GUIDList::iterator itr = lFireBunnies.begin(); itr != lFireBunnies.end(); ++itr) - if (Creature* pFireBunny = m_creature->GetMap()->GetCreature(*itr)) - { - if (pFireBunny->HasAura(SPELL_FLAMES_LARGE)) - pFireBunny->RemoveAurasDueToSpell(SPELL_FLAMES_LARGE); - pFireBunny->CastSpell(m_creature, SPELL_SMOKE, true); - pFireBunny->ForcedDespawn(60000); - } - break; - } - ++uiPhase; - DoCastSpellIfCan(m_creature, SPELL_LAUGH_DELAYED_8); - } - else - m_uiEventTimer -= uiDiff; +/*##### +# npc_bunny_fire_training +#####*/ +enum +{ + NPC_BUNNY_FIRE_CREDIT = 23537, + SPELL_BUCKET_LANDS = 42339 +}; + +struct MANGOS_DLL_DECL npc_bunny_fire_trainingAI : public ScriptedAI +{ + npc_bunny_fire_trainingAI (Creature* pCreature) : ScriptedAI (pCreature) + { + Reset(); + } + + void Reset () {} + + void SpellHit(Unit* pWho, const SpellEntry* pSpell) + { + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; - if (m_uiConflagrationTimer < uiDiff) + if (pSpell->Id == SPELL_BUCKET_LANDS) { - bIsConflagrating = !bIsConflagrating; - m_creature->GetMotionMaster()->MovementExpired(); - m_creature->GetMotionMaster()->MoveTargetedHome(); - m_uiConflagrationProcTimer = 2000; - m_uiConflagrationTimer = bIsConflagrating ? 10000 : 30000; - if (bIsConflagrating) - DoScriptText(YELL_CONFLAGRATION, m_creature); + ((Player*)pWho)->KilledMonsterCredit(NPC_BUNNY_FIRE_CREDIT); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->ForcedDespawn(); } - else - m_uiConflagrationTimer -= uiDiff; + } +}; - if (bIsConflagrating) - if (m_uiConflagrationProcTimer < uiDiff) - { - m_uiConflagrationProcTimer = 2000; - if (lFireBunnies.empty()) - { - std::list tempFireBunnies; - GetCreatureListWithEntryInGrid(tempFireBunnies, m_creature, NPC_FIRE_BUNNY, 50.0f); - for (std::list::iterator itr = tempFireBunnies.begin(); itr != tempFireBunnies.end(); ++itr) - lFireBunnies.push_back((*itr)->GetObjectGuid()); - } +CreatureAI* GetAI_npc_bunny_fire_training(Creature* pCreature) +{ + return new npc_bunny_fire_trainingAI(pCreature); +} + +/*##### +# npc_bunny_fire_town +#####*/ +enum +{ + NPC_BUNNY_HORSEMAN = 23543, +}; - if (lFireBunnies.empty()) +struct sLocation +{ + float x, y, z, o; + uint32 map; + uint32 zone; + uint32 area; +}; + +static sLocation asLocation [6] = +{ +// X Y Z O MapId ZoneId AreaId + {-9458.885f, 62.351f, 55.785f, 6.264f, 0, 12, 87 }, // Elwyn's Forest, Goldshire + {-5602.197f, -483.211f, 396.981f, 3.000f, 0, 1, 131 }, // Dun Murogh, Kharanos + {-4179.134f, -12483.937f, 44.348f, 6.275f, 530, 3524, 3576}, // Azuremyst Isle, Azure Watch + {2259.250f, 290.430f, 34.114f, 0.987f, 0, 85, 159 }, // Trisifal Glades, Brill + {322.1362f, -4742.212f, 9.656f, 3.180f, 1, 14, 362 }, // Durotar, Razor Hill + {9525.682f, -6830.646f, 16.493f, 2.969f, 530, 3430, 3665} // Eversong Woods, Falconing Square +}; + +struct MANGOS_DLL_DECL npc_bunny_fire_townAI : public ScriptedAI +{ + npc_bunny_fire_townAI (Creature* pCreature) : ScriptedAI (pCreature) + { + m_uiMapId = pCreature->GetMapId(); + pCreature->GetZoneAndAreaId(m_uiZoneId, m_uiAreaId); + Reset(); + } + + uint32 m_uiMapId; + uint32 m_uiAreaId; + uint32 m_uiZoneId; + bool m_bBucketReceived; + + void Reset () + { + + m_bBucketReceived = false; + } + void SpellHit(Unit* pWho, const SpellEntry* pSpell) + { + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + + if (pSpell->Id == SPELL_BUCKET_LANDS) + m_bBucketReceived = true; + } + + void UpdateAI (const uint32 uiDiff) + { + if (m_bBucketReceived) + { + uint8 uiIndex; + bool bFind = false; + for (uiIndex = 0; uiIndex < 6; uiIndex++) + { + if (m_uiMapId == asLocation[uiIndex].map && m_uiZoneId == asLocation[uiIndex].zone && m_uiAreaId == asLocation[uiIndex].area) { - m_creature->ForcedDespawn(5000); - error_log("Missing DB spawns of Fire Bunnies (Horseman Village Event)"); - uiPhase = PHASE_END; - return; + bFind = true; + break; } + } - if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) - return; - - for (GUIDList::iterator itr = lFireBunnies.begin(); itr != lFireBunnies.end(); ++itr) - if (Creature* pFireBunny = m_creature->GetMap()->GetCreature(*itr)) - if (!pFireBunny->HasAura(SPELL_FLAMES_LARGE)) - { - if (DoCastSpellIfCan(pFireBunny, SPELL_CONFLAGRATE) != CAST_OK) - { - float x,y,z; - pFireBunny->GetPosition(x,y,z); - pFireBunny->GetClosePoint(x,y,z,0,5,0); - m_creature->GetMotionMaster()->MovePoint(0, x,y,z+15); - break; - } - } + if (bFind) + { + Creature* pHorseman = m_creature->SummonCreature(NPC_BUNNY_HORSEMAN, asLocation[uiIndex].x, asLocation[uiIndex].y, asLocation[uiIndex].z, asLocation[uiIndex].o, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + pHorseman->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + pHorseman->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + pHorseman->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pHorseman->setFaction(14); + pHorseman->SetPhaseMask(2,true); } - else - m_uiConflagrationProcTimer -= uiDiff; + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->ForcedDespawn(); + } } }; -CreatureAI* GetAI_npc_shade_of_horseman(Creature* pCreature) +CreatureAI* GetAI_npc_bunny_fire_town(Creature* pCreature) { - return new npc_shade_of_horsemanAI (pCreature); + return new npc_bunny_fire_townAI(pCreature); +} + +/*##### +# npc_bunny_horseman +#####*/ +enum +{ + SPELL_SUMMON_LANTERN_MISSILE = 44255, + SPELL_SUMMON_LANTERN = 44231, + QUEST_LET_THE_FIRE_COMES_A = 12135, + QUEST_LET_THE_FIRE_COMES_H = 12139, + SAY_HORSEMAN_SHADE_SUMMONED = -2760020, + SAY_HORSEMAN_SHADE_DEATH = -2760021 }; +struct MANGOS_DLL_DECL npc_bunny_horsemanAI : ScriptedAI +{ + npc_bunny_horsemanAI (Creature* pCreature) : ScriptedAI (pCreature) + { + Reset(); + } -void AddSC_npcs_special() + void Reset() + { + DoScriptText(SAY_HORSEMAN_SHADE_SUMMONED, m_creature); + } + + void JustDied (Unit* pKiller) + { + DoCast(m_creature, SPELL_SUMMON_LANTERN); + DoScriptText(SAY_HORSEMAN_SHADE_DEATH, m_creature); + + // to give the quest completed to all player near the Horseman + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if(pPlayer) + { + // consider only player near the corpse + if (!pPlayer->IsWithinDist2d(m_creature->GetPositionX(), m_creature->GetPositionY(), 20.0f)) + continue; + + if (pPlayer->GetQuestStatus(QUEST_LET_THE_FIRE_COMES_A) == QUEST_STATUS_INCOMPLETE) + pPlayer->SetQuestStatus(QUEST_LET_THE_FIRE_COMES_A, QUEST_STATUS_COMPLETE); + + if (pPlayer->GetQuestStatus(QUEST_LET_THE_FIRE_COMES_H) == QUEST_STATUS_INCOMPLETE) + pPlayer->SetQuestStatus(QUEST_LET_THE_FIRE_COMES_H, QUEST_STATUS_COMPLETE); + } + } + } +}; + +CreatureAI* GetAI_npc_bunny_horseman(Creature* pCreature) { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "npc_air_force_bots"; - pNewScript->GetAI = &GetAI_npc_air_force_bots; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_chicken_cluck"; - pNewScript->GetAI = &GetAI_npc_chicken_cluck; - pNewScript->pQuestAcceptNPC = &QuestAccept_npc_chicken_cluck; - pNewScript->pQuestRewardedNPC = &QuestRewarded_npc_chicken_cluck; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_dancing_flames"; - pNewScript->GetAI = &GetAI_npc_dancing_flames; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_injured_patient"; - pNewScript->GetAI = &GetAI_npc_injured_patient; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_doctor"; - pNewScript->GetAI = &GetAI_npc_doctor; - pNewScript->pQuestAcceptNPC = &QuestAccept_npc_doctor; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_garments_of_quests"; - pNewScript->GetAI = &GetAI_npc_garments_of_quests; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_guardian"; - pNewScript->GetAI = &GetAI_npc_guardian; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_innkeeper"; - pNewScript->pGossipHello = &GossipHello_npc_innkeeper; - pNewScript->pGossipSelect = &GossipSelect_npc_innkeeper; - pNewScript->RegisterSelf(false); // script and error report disabled, but script can be used for custom needs, adding ScriptName - - pNewScript = new Script; - pNewScript->Name = "npc_mount_vendor"; - pNewScript->pGossipHello = &GossipHello_npc_mount_vendor; - pNewScript->pGossipSelect = &GossipSelect_npc_mount_vendor; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_sayge"; - pNewScript->pGossipHello = &GossipHello_npc_sayge; - pNewScript->pGossipSelect = &GossipSelect_npc_sayge; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_tabard_vendor"; - pNewScript->pGossipHello = &GossipHello_npc_tabard_vendor; - pNewScript->pGossipSelect = &GossipSelect_npc_tabard_vendor; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_mirror_image"; - pNewScript->GetAI = &GetAI_npc_mirror_image; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_snake_trap_serpents"; - pNewScript->GetAI = &GetAI_npc_snake_trap_serpents; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_runeblade"; - pNewScript->GetAI = &GetAI_npc_rune_blade; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_death_knight_gargoyle"; - pNewScript->GetAI = &GetAI_npc_death_knight_gargoyle; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_risen_ally"; - pNewScript->GetAI = &GetAI_npc_risen_ally; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_explosive_decoy"; - pNewScript->GetAI = &GetAI_npc_explosive_decoy; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_eye_of_kilrogg"; - pNewScript->GetAI = &GetAI_npc_eye_of_kilrogg; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_horseman_fire_bunny"; - pNewScript->GetAI = &GetAI_npc_horseman_fire_bunny; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "npc_shade_of_horseman"; - pNewScript->GetAI = &GetAI_npc_shade_of_horseman; - pNewScript->RegisterSelf(); + return new npc_bunny_horsemanAI(pCreature); +} + +void AddSC_npcs_special() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "npc_air_force_bots"; + newscript->GetAI = &GetAI_npc_air_force_bots; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_chicken_cluck"; + newscript->GetAI = &GetAI_npc_chicken_cluck; + newscript->pQuestAcceptNPC = &QuestAccept_npc_chicken_cluck; + newscript->pQuestRewardedNPC = &QuestRewarded_npc_chicken_cluck; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_dancing_flames"; + newscript->GetAI = &GetAI_npc_dancing_flames; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_injured_patient"; + newscript->GetAI = &GetAI_npc_injured_patient; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_doctor"; + newscript->GetAI = &GetAI_npc_doctor; + newscript->pQuestAcceptNPC = &QuestAccept_npc_doctor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_garments_of_quests"; + newscript->GetAI = &GetAI_npc_garments_of_quests; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_guardian"; + newscript->GetAI = &GetAI_npc_guardian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_innkeeper"; + newscript->pGossipHello = &GossipHello_npc_innkeeper; + newscript->pGossipSelect = &GossipSelect_npc_innkeeper; + newscript->RegisterSelf(false); // script and error report disabled, but script can be used for custom needs, adding ScriptName + + newscript = new Script; + newscript->Name = "npc_kingdom_of_dalaran_quests"; + newscript->pGossipHello = &GossipHello_npc_kingdom_of_dalaran_quests; + newscript->pGossipSelect = &GossipSelect_npc_kingdom_of_dalaran_quests; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lunaclaw_spirit"; + newscript->pGossipHello = &GossipHello_npc_lunaclaw_spirit; + newscript->pGossipSelect = &GossipSelect_npc_lunaclaw_spirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mount_vendor"; + newscript->pGossipHello = &GossipHello_npc_mount_vendor; + newscript->pGossipSelect = &GossipSelect_npc_mount_vendor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_rogue_trainer"; + newscript->pGossipHello = &GossipHello_npc_rogue_trainer; + newscript->pGossipSelect = &GossipSelect_npc_rogue_trainer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_sayge"; + newscript->pGossipHello = &GossipHello_npc_sayge; + newscript->pGossipSelect = &GossipSelect_npc_sayge; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tabard_vendor"; + newscript->pGossipHello = &GossipHello_npc_tabard_vendor; + newscript->pGossipSelect = &GossipSelect_npc_tabard_vendor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_locksmith"; + newscript->pGossipHello = &GossipHello_npc_locksmith; + newscript->pGossipSelect = &GossipSelect_npc_locksmith; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_experience_eliminator"; + newscript->pGossipHello = &GossipHello_npc_experience_eliminator; + newscript->pGossipSelect = &GossipSelect_npc_experience_eliminator; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mirror_image"; + newscript->GetAI = &GetAI_npc_mirror_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_snake_trap_serpents"; + newscript->GetAI = &GetAI_npc_snake_trap_serpents; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_runeblade"; + newscript->GetAI = &GetAI_npc_rune_blade; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_death_knight_gargoyle"; + newscript->GetAI = &GetAI_npc_death_knight_gargoyle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_risen_ally"; + newscript->GetAI = &GetAI_npc_risen_ally; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_explosive_decoy"; + newscript->GetAI = &GetAI_npc_explosive_decoy; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_eye_of_kilrogg"; + newscript->GetAI = &GetAI_npc_eye_of_kilrogg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_battle_standard"; + newscript->GetAI = &GetAI_npc_battle_standard; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_zabaione"; + newscript->pGOUse = &Pasqua2011::GOUse_go_zabaione; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mastro_ermes"; + newscript->GetAI = &Pasqua2011::GetAI_npc_mastro_ermes; + newscript->pGossipHello = &Pasqua2011::GossipHello_npc_mastro_ermes; + newscript->pGossipSelect = &Pasqua2011::GossipSelect_npc_mastro_ermes; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_argent_healer"; + newscript->pGossipHello = &GossipHello_npc_argent_healer; + newscript->pGossipSelect = &GossipSelect_npc_argent_healer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_training_dummy"; + newscript->GetAI = &GetAI_npc_training_dummy; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_winter_reveler"; + newscript->GetAI = &GetAI_npc_winter_reveler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_metzen"; + newscript->pGossipHello = &GossipHello_npc_metzen; + newscript->pGossipSelect = &GossipSelect_npc_metzen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_wormhole"; + newscript->pGossipHello = &GossipHello_npc_wormhole; + newscript->pGossipSelect = &GossipSelect_npc_wormhole; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bunny_bark"; + newscript->GetAI = &GetAI_npc_bunny_bark; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bunny_fire_training"; + newscript->GetAI = &GetAI_npc_bunny_fire_training; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bunny_fire_town"; + newscript->GetAI = &GetAI_npc_bunny_fire_town; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bunny_horseman"; + newscript->GetAI = &GetAI_npc_bunny_horseman; + newscript->RegisterSelf(); } diff --git a/scripts/world/spell_scripts.cpp b/scripts/world/spell_scripts.cpp index 88aebd5dfb..7803b923bc 100644 --- a/scripts/world/spell_scripts.cpp +++ b/scripts/world/spell_scripts.cpp @@ -34,7 +34,6 @@ spell 47575 spell 50706 spell 45109 spell 45111 -spell 39246 spell 52090 spell 51331 spell 51332 @@ -249,12 +248,6 @@ enum NPC_DARKSPINE_MYRMIDON = 25060, NPC_DARKSPINE_SIREN = 25073, - // quest "The Big Bone Worm" 10930 - SPELL_FUMPING = 39246, - SPELL_SUMMON_HAISHULUD = 39248, - NPC_SAND_GNOME = 22483, - NPC_MATURE_BONE_SIFTER = 22482, - // quest 12659, item 38731 SPELL_AHUNAES_KNIFE = 52090, NPC_SCALPS_KILL_CREDIT_BUNNY = 28622, @@ -525,12 +518,12 @@ bool EffectDummyCreature_spell_dummy_npc(Unit* pCaster, uint32 uiSpellId, SpellE if (pCreatureTarget->GetEntry() == NPC_ELK) { pCreatureTarget->CastSpell(pCreatureTarget, SPELL_LIQUID_FIRE_AURA, true); - ((Player*)pCaster)->KilledMonsterCredit(NPC_ELK_BUNNY); + ((Player*)pCaster)->KilledMonsterCredit(uint32(NPC_ELK_BUNNY)); } else if (pCreatureTarget->GetEntry() == NPC_GRIZZLY) { pCreatureTarget->CastSpell(pCreatureTarget, SPELL_LIQUID_FIRE_AURA, true); - ((Player*)pCaster)->KilledMonsterCredit(NPC_GRIZZLY_BUNNY); + ((Player*)pCaster)->KilledMonsterCredit(uint32(NPC_GRIZZLY_BUNNY)); } } return true; @@ -689,40 +682,6 @@ bool EffectDummyCreature_spell_dummy_npc(Unit* pCaster, uint32 uiSpellId, SpellE return true; } - case SPELL_FUMPING: - { - if (uiEffIndex == EFFECT_INDEX_2) - { - switch(urand(0,2)) - { - case 0: - { - pCaster->CastSpell(pCreatureTarget, SPELL_SUMMON_HAISHULUD, true); - break; - } - case 1: - { - for (int i = 0; i<2; ++i) - { - if (Creature* pSandGnome = pCaster->SummonCreature(NPC_SAND_GNOME, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - pSandGnome->AI()->AttackStart(pCaster); - } - break; - } - case 2: - { - for (int i = 0; i<2; ++i) - { - if (Creature* pMatureBoneSifter = pCaster->SummonCreature(NPC_MATURE_BONE_SIFTER, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - pMatureBoneSifter->AI()->AttackStart(pCaster); - } - break; - } - } - pCreatureTarget->ForcedDespawn(); - } - return true; - } case SPELL_AHUNAES_KNIFE: { if (uiEffIndex == EFFECT_INDEX_0) diff --git a/system/ScriptLoader.cpp b/system/ScriptLoader.cpp index cae50e49a5..ed3f97411f 100644 --- a/system/ScriptLoader.cpp +++ b/system/ScriptLoader.cpp @@ -11,6 +11,11 @@ extern void AddSC_battlegroundIC(); // custom extern void AddSC_mob_teleguy(); +extern void AddSC_alterac_valley(); +//extern void AddSC_npc_small_pet_handler(); +extern void AddSC_npc_companion_handler(); + +// Events extern void AddSC_npc_arena_honor(); // examples @@ -30,7 +35,6 @@ extern void AddSC_npc_professions(); extern void AddSC_npcs_special(); extern void AddSC_spell_scripts(); extern void AddSC_pet_scripts(); - extern void AddSC_world_map_scripts(); // eastern kingdoms @@ -269,6 +273,7 @@ extern void AddSC_bloodmyst_isle(); extern void AddSC_boss_azuregos(); extern void AddSC_darkshore(); extern void AddSC_desolace(); +extern void AddSC_durotar(); extern void AddSC_dustwallow_marsh(); extern void AddSC_felwood(); extern void AddSC_feralas(); @@ -352,6 +357,7 @@ extern void AddSC_boss_anubrekhan(); // naxxramas extern void AddSC_boss_four_horsemen(); extern void AddSC_boss_faerlina(); extern void AddSC_boss_gluth(); +extern void AddSC_boss_thaddius(); extern void AddSC_boss_gothik(); extern void AddSC_boss_grobbulus(); extern void AddSC_boss_kelthuzad(); @@ -371,8 +377,14 @@ extern void AddSC_boss_keristrasza(); extern void AddSC_boss_ormorok(); extern void AddSC_boss_telestra(); extern void AddSC_instance_nexus(); -extern void AddSC_oculus(); + +extern void AddSC_instance_eye_of_eternity(); + +extern void AddSC_oculus(); //Oculus +extern void AddSC_instance_oculus(); extern void AddSC_boss_drakos(); // nexus, oculus +extern void AddSC_boss_eregos(); + extern void AddSC_boss_varos(); extern void AddSC_boss_eregos(); // nexus, oculus extern void AddSC_boss_urom(); @@ -401,7 +413,7 @@ extern void AddSC_boss_algalon(); extern void AddSC_boss_auriaya(); extern void AddSC_boss_leviathan(); extern void AddSC_boss_freya(); -extern void AddSC_boss_general_vezax(); +extern void AddSC_boss_vezax(); extern void AddSC_boss_hodir(); extern void AddSC_boss_ignis(); extern void AddSC_boss_kologarn(); @@ -515,6 +527,7 @@ extern void AddSC_boss_kaelthas(); extern void AddSC_boss_void_reaver(); extern void AddSC_instance_the_eye(); extern void AddSC_the_eye(); +extern void AddSC_boss_alar(); extern void AddSC_boss_gatewatcher_iron_hand(); // TK, the_mechanar extern void AddSC_boss_nethermancer_sepethrea(); extern void AddSC_boss_pathaleon_the_calculator(); @@ -540,6 +553,10 @@ void AddScripts() // custom AddSC_mob_teleguy(); + AddSC_npc_companion_handler(); + + // OutdoorPvP zone scripts + // Must be _before_ map scripts call! AddSC_npc_arena_honor(); // examples @@ -798,6 +815,7 @@ void AddScripts() AddSC_darkshore(); AddSC_desolace(); AddSC_dustwallow_marsh(); + AddSC_durotar(); AddSC_felwood(); AddSC_feralas(); AddSC_moonglade(); @@ -880,6 +898,7 @@ void AddScripts() AddSC_boss_four_horsemen(); AddSC_boss_faerlina(); AddSC_boss_gluth(); + AddSC_boss_thaddius(); AddSC_boss_gothik(); AddSC_boss_grobbulus(); AddSC_boss_kelthuzad(); @@ -899,8 +918,14 @@ void AddScripts() AddSC_boss_ormorok(); AddSC_boss_telestra(); AddSC_instance_nexus(); - AddSC_oculus(); + + AddSC_instance_eye_of_eternity(); + + AddSC_oculus(); //Oculus + AddSC_instance_oculus(); AddSC_boss_drakos(); // nexus, oculus + AddSC_boss_eregos(); + AddSC_boss_varos(); AddSC_boss_eregos(); // nexus, oculus AddSC_boss_urom(); @@ -929,7 +954,7 @@ void AddScripts() AddSC_boss_auriaya(); AddSC_boss_leviathan(); AddSC_boss_freya(); - AddSC_boss_general_vezax(); + AddSC_boss_vezax(); AddSC_boss_hodir(); AddSC_boss_ignis(); AddSC_boss_kologarn(); @@ -1043,6 +1068,7 @@ void AddScripts() AddSC_boss_void_reaver(); AddSC_instance_the_eye(); AddSC_the_eye(); + AddSC_boss_alar(); AddSC_boss_gatewatcher_iron_hand(); // TK, the_mechanar AddSC_boss_nethermancer_sepethrea(); AddSC_boss_pathaleon_the_calculator();