diff options
5 files changed, 665 insertions, 649 deletions
diff --git a/sql/updates/world/master/2018_03_12_03_world_2016_12_07_00_world.sql b/sql/updates/world/master/2018_03_12_03_world_2016_12_07_00_world.sql new file mode 100644 index 00000000000..c014bd42387 --- /dev/null +++ b/sql/updates/world/master/2018_03_12_03_world_2016_12_07_00_world.sql @@ -0,0 +1,138 @@ +-- +SET @GUID:=87977; +DELETE FROM `creature` WHERE `id` IN(17256,17474) AND `map`=544; +DELETE FROM `linked_respawn` WHERE `guid` IN(90982,90981,90980,90979,90978); -- Delete Linked respawn from channelers +INSERT INTO `creature` (`guid`,`id`,`map`,`zoneId`,`areaId`,`spawnMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`,`VerifiedBuild`) VALUES +(@GUID,17474,544,0,0,16,15435,0,11.2283,2.97198,-0.320875,1.14748,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+1,17474,544,0,0,16,15435,0,10.2283,1.97198,-0.320875,1.41097,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+2,17474,544,0,0,16,15435,0,-44.0663,21.973,-0.329128,5.15817,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+3,17474,544,0,0,16,15435,0,-44.3225,22.0454,-0.329129,5.87281,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+4,17474,544,0,0,16,15435,0,-13.1443,-26.8186,-0.412466,3.70357,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+5,17474,544,0,0,16,15435,0,-14.3701,-24.6551,-0.412466,1.99314,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+6,17474,544,0,0,16,15435,0,-45.6199,-16.1769,-0.329109,5.65524,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+7,17474,544,0,0,16,15435,0,-44.6199,-15.1769,-0.329109,1.5311,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+8,17474,544,0,0,16,15435,0,-17.5166,2.10518,-0.320812,5.98416,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+9,17474,544,0,0,16,15435,0,-16.5166,3.10518,-0.320812,0.0813029,7200,15,0,3965,0,1,0,0,0,0), +(@GUID+10,17474,544,0,0,16,15435,0,-12.4546,35.4987,-0.319343,2.09894,7200,5,0,3965,0,1,0,0,0,0), +(@GUID+11,17474,544,0,0,16,15435,0,-11.6249,31.6464,-0.412482,4.08569,7200,15,0,3965,0,1,0,0,0,0); + +-- Target Trigger should walk in ground, not fly +UPDATE `creature_template` SET `InhabitType`=1 WHERE `entry`=17474; +-- Added Taunt Immunity in Magtheridon. +UPDATE `creature_template` SET `spell2`=0, `spell3`=0, `spell4`=0, `flags_extra` = `flags_extra` |256 WHERE `entry`=17257; + +-- Delete addon aura from Magtheridon +DELETE FROM `creature_addon` WHERE `guid`=91254; + +-- Added missing Fire Blast aura in Burning Abyssal creature +DELETE FROM `creature_template_addon` WHERE `entry`=17454; +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(17454, 0, 0, 0, 1, 0, 30516); +-- Removed script from Burning Abyssal creature +UPDATE `creature_template` SET `ScriptName`='' WHERE `entry`=17454; + +-- Updated condition for Shadow Grasp hits Hellfire Raid Trigger +UPDATE `conditions` SET `ConditionValue2`=17376, `Comment`='Effect_0 hits Hellfire Raid Trigger' WHERE `SourceEntry`=30410 AND `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1; +-- Added condition for Blaze hit Target Trigger +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=30541; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,30541,0,0,31,0,3,17474,0,0,0,0,'','Effect_0 hits Target Trigger'); +-- Added condition for Quake hits Target Trigger +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=30657; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,7,30657,0,0,31,0,3,17474,0,0,0,0,'','Effect_0, Effect_1, Effect_2 hits Target Trigger'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=30658; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(30658, 30571, 0, 'Quake Trigger Quake Knockback'); + +-- Making a summon group for Magtheridon. +DELETE FROM `creature_summon_groups` WHERE `summonerId`=17257; -- Magtheridon +INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES +(17257,0,1,17256,-31.7645,-35.8374,0.714268,1.37881,6,6000), -- Hellfire Channelers +(17257,0,1,17256,10.3369,-19.7942,0.714241,2.53073,6,6000), +(17257,0,1,17256,10.4777,23.9914,0.714224,3.66519,6,6000), +(17257,0,1,17256,-31.9479,40.2201,0.714251,4.93928,6,6000), +(17257,0,1,17256,-55.6891,2.17024,0.71428,0.05236,6,6000); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN('spell_magtheridon_blaze_target','spell_magtheridon_shadow_grasp','spell_magtheridon_shadow_grasp_visual'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(30541,'spell_magtheridon_blaze_target'), +(30410,'spell_magtheridon_shadow_grasp'), +(30166,'spell_magtheridon_shadow_grasp_visual'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=-30410 AND `spell_effect`=44032 AND `type`=0; + +UPDATE `creature_template` SET `flags_extra`=128, `ScriptName`='npc_magtheridon_room' WHERE `entry`=17516; + +-- UPDATE `spell_dbc` SET `AttributesEx3`=262400, `EffectImplicitTargetA1`=53, `EffectImplicitTargetB1`=0, `EffectRadiusIndex1`=16, `MaxAffectedTargets`=1, `RangeIndex`=13 WHERE `Id`=30630; + +DELETE FROM `creature_text` WHERE `CreatureID`=17257; +INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`Comment`) VALUES +(17257,0,0,'Wretched, meddling insects! Release me, and perhaps I will grant you a merciful death!',14,0,100,0,0,10247,17339,0,'Magtheridon - Taunt01'), +(17257,0,1,'Vermin! Leeches! Take my blood and choke on it!',14,0,100,0,0,10248,17340,0,'Magtheridon - Taunt02'), +(17257,0,2,'Illidan is an arrogant fool! I will crush him and reclaim Outland as my own!',14,0,100,0,0,10249,17341,0,'Magtheridon - Taunt03'), +(17257,0,3,'Away, you mindless parasites! My blood is my own!',14,0,100,0,0,10250,17342,0,'Magtheridon - Taunt04'), +(17257,0,4,'How long do you believe your pathetic sorcery can hold me?',14,0,100,0,0,10251,17343,0,'Magtheridon - Taunt05'), +(17257,0,5,'My blood will be the end of you!',14,0,100,0,0,10252,17344,0,'Magtheridon - Taunt06'), +(17257,1,0,'I... am... unleashed!',14,0,100,15,0,10253,17346,0,'Magtheridon - Free'), +(17257,2,0,'Did you think me weak? Soft? Who is the weak one now?',14,0,100,0,0,10255,17349,0,'Magtheridon - Slay'), +(17257,3,0,'Not again! Not again...',14,0,100,0,0,10256,17348,0,'Magtheridon - Banished'), +(17257,4,0,'I will not be taken so easily! Let the walls of this prison tremble... and fall!',14,0,100,0,0,10257,17336,0,'Magtheridon - Collapse'), +(17257,5,0,'The Legion will consume you all!',14,0,100,0,0,10258,17347,0,'Magtheridon - Death'), +(17257,6,0,'%s\'s bonds begin to weaken!',16,0,100,0,0,0,13689,0,'Magtheridon - Weaken'), +(17257,7,0,'%s is nearly free of his bonds!',16,0,100,0,0,0,13690,0,'Magtheridon - Nearly free'), +(17257,8,0,'%s breaks free!',16,0,100,0,0,0,13691,0,'Magtheridon - Breaks free'), +(17257,9,0,'%s begins to cast Blast Nova!',41,0,100,0,0,0,18739,0,'Magtheridon - Blast Nova'); + +UPDATE `smart_scripts` SET `event_chance`=100 WHERE `entryorguid`=18829 AND `source_type`=0; + +-- Channel Visual Group +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(-90985,-90986,-90987) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-90986,0,0,0,0,0,100,2,4800,4800,18400,27400,11,39175,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Bolt Volley\''), +(-90986,0,1,0,0,0,100,2,9000,9000,14500,21500,11,34437,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Death Coil\''), +(-90986,0,2,0,0,0,100,2,3000,3000,17000,18000,11,34435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Rain of Fire\''), +(-90986,0,3,0,0,0,100,2,4100,4100,20000,23500,11,34436,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Burst\''), +(-90986,0,4,0,0,0,100,2,1400,1400,7000,9000,11,34439,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Unstable Affliction\''), +(-90986,0,5,0,0,0,100,2,57700,57700,50000,50000,11,34441,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Word: Pain\''), +(-90986,0,6,0,1,0,100,1,1000,1000,0,0,11,33827,0,0,0,0,0,19,15384,20,0,0,0,0,0,'Hellfire Warder - Ooc no repeat - Cast Hellfire Warder Channel Visual'), +(-90987,0,0,0,0,0,100,2,4800,4800,18400,27400,11,39175,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Bolt Volley\''), +(-90987,0,1,0,0,0,100,2,9000,9000,14500,21500,11,34437,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Death Coil\''), +(-90987,0,2,0,0,0,100,2,3000,3000,17000,18000,11,34435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Rain of Fire\''), +(-90987,0,3,0,0,0,100,2,4100,4100,20000,23500,11,34436,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Burst\''), +(-90987,0,4,0,0,0,100,2,1400,1400,7000,9000,11,34439,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Unstable Affliction\''), +(-90987,0,5,0,0,0,100,2,57700,57700,50000,50000,11,34441,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Word: Pain\''), +(-90987,0,6,0,1,0,100,1,1000,1000,0,0,11,33827,0,0,0,0,0,19,15384,20,0,0,0,0,0,'Hellfire Warder - Ooc no repeat - Cast Hellfire Warder Channel Visual'), +(-90985,0,0,0,0,0,100,2,4800,4800,18400,27400,11,39175,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Bolt Volley\''), +(-90985,0,1,0,0,0,100,2,9000,9000,14500,21500,11,34437,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Death Coil\''), +(-90985,0,2,0,0,0,100,2,3000,3000,17000,18000,11,34435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Rain of Fire\''), +(-90985,0,3,0,0,0,100,2,4100,4100,20000,23500,11,34436,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Burst\''), +(-90985,0,4,0,0,0,100,2,1400,1400,7000,9000,11,34439,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Unstable Affliction\''), +(-90985,0,5,0,0,0,100,2,57700,57700,50000,50000,11,34441,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Word: Pain\''), +(-90985,0,6,0,1,0,100,1,1000,1000,0,0,11,33827,0,0,0,0,0,19,15384,20,0,0,0,0,0,'Hellfire Warder - Ooc no repeat - Cast Hellfire Warder Channel Visual'); + +-- Green Beam group +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(-91247,-91248,-91249) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-91248,0,0,0,0,0,100,2,4800,4800,18400,27400,11,39175,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Bolt Volley\''), +(-91248,0,1,0,0,0,100,2,9000,9000,14500,21500,11,34437,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Death Coil\''), +(-91248,0,2,0,0,0,100,2,3000,3000,17000,18000,11,34435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Rain of Fire\''), +(-91248,0,3,0,0,0,100,2,4100,4100,20000,23500,11,34436,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Burst\''), +(-91248,0,4,0,0,0,100,2,1400,1400,7000,9000,11,34439,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Unstable Affliction\''), +(-91248,0,5,0,0,0,100,2,57700,57700,50000,50000,11,34441,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Word: Pain\''), +(-91248,0,6,0,1,0,100,1,1000,1000,0,0,11,33346,0,0,0,0,0,19,15384,20,0,0,0,0,0,'Hellfire Warder - Ooc no repeat - Cast Green Beam'), +(-91247,0,0,0,0,0,100,2,4800,4800,18400,27400,11,39175,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Bolt Volley\''), +(-91247,0,1,0,0,0,100,2,9000,9000,14500,21500,11,34437,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Death Coil\''), +(-91247,0,2,0,0,0,100,2,3000,3000,17000,18000,11,34435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Rain of Fire\''), +(-91247,0,3,0,0,0,100,2,4100,4100,20000,23500,11,34436,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Burst\''), +(-91247,0,4,0,0,0,100,2,1400,1400,7000,9000,11,34439,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Unstable Affliction\''), +(-91247,0,5,0,0,0,100,2,57700,57700,50000,50000,11,34441,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Word: Pain\''), +(-91247,0,6,0,1,0,100,1,1000,1000,0,0,11,33346,0,0,0,0,0,19,15384,20,0,0,0,0,0,'Hellfire Warder - Ooc no repeat - Cast Green Beam'), +(-91249,0,0,0,0,0,100,2,4800,4800,18400,27400,11,39175,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Bolt Volley\''), +(-91249,0,1,0,0,0,100,2,9000,9000,14500,21500,11,34437,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Death Coil\''), +(-91249,0,2,0,0,0,100,2,3000,3000,17000,18000,11,34435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Rain of Fire\''), +(-91249,0,3,0,0,0,100,2,4100,4100,20000,23500,11,34436,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Burst\''), +(-91249,0,4,0,0,0,100,2,1400,1400,7000,9000,11,34439,0,0,0,0,0,5,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Unstable Affliction\''), +(-91249,0,5,0,0,0,100,2,57700,57700,50000,50000,11,34441,0,0,0,0,0,2,0,0,0,0,0,0,0,'Hellfire Warder - In Combat - Cast \'Shadow Word: Pain\''), +(-91249,0,6,0,1,0,100,1,1000,1000,0,0,11,33346,0,0,0,0,0,19,15384,20,0,0,0,0,0,'Hellfire Warder - Ooc no repeat - Cast Green Beam'); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index e2f6433d414..f5f43febc9c 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2518,19 +2518,6 @@ void SpellMgr::LoadSpellInfoCorrections() const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->Effect = 0; }); - // Quake - ApplySpellFix({ 30657 }, [](SpellInfo* spellInfo) - { - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TriggerSpell = 30571; - }); - - // Blaze (needs conditions entry) - ApplySpellFix({ 30541 }, [](SpellInfo* spellInfo) - { - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); - const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(); - }); - ApplySpellFix({ 63665, // Charge (Argent Tournament emote on riders) 31298, // Sleep (needs target selection script) diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp index 1a916518227..c42005e5abe 100644 --- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * 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 @@ -16,13 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Magtheridon -SD%Complete: 60 -SDComment: In Development -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - #include "ScriptMgr.h" #include "GameObject.h" #include "InstanceScript.h" @@ -32,604 +24,574 @@ EndScriptData */ #include "ScriptedCreature.h" #include "SpellInfo.h" #include "TemporarySummon.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "PassiveAI.h" enum Yells { - SAY_TAUNT = 0, - SAY_FREED = 1, - SAY_AGGRO = 2, - SAY_BANISH = 3, - SAY_CHAMBER_DESTROY = 4, - SAY_PLAYER_KILLED = 5, - SAY_DEATH = 6 + SAY_TAUNT = 0, + SAY_FREE = 1, + SAY_SLAY = 2, + SAY_BANISHED = 3, + SAY_COLLAPSE = 4, + SAY_DEATH = 5, + EMOTE_WEAKEN = 6, + EMOTE_NEARLY_FREE = 7, + EMOTE_BREAKS_FREE = 8, + EMOTE_BLAST_NOVA = 9 }; -enum Emotes +enum Spells { - EMOTE_BERSERK = 7, - EMOTE_BLASTNOVA = 8, - EMOTE_BEGIN = 9 + // Magtheridon + SPELL_BLAST_NOVA = 30616, + SPELL_CLEAVE = 30619, + SPELL_BLAZE_TARGET = 30541, + SPELL_CAMERA_SHAKE = 36455, + SPELL_BERSERK = 27680, + SPELL_QUAKE = 30657, + SPELL_DEBRIS_SERVERSIDE = 30630, + + // Player or Manticron Cube + SPELL_SHADOW_CAGE = 30168, + SPELL_SHADOW_GRASP = 30410, + SPELL_MIND_EXHAUSTION = 44032, + + // Hellfire Raid Trigger + SPELL_SHADOW_GRASP_VISUAL = 30166, + + // HellFire Channeler + SPELL_SHADOW_CAGE_C = 30205, + SPELL_SHADOW_GRASP_C = 30207, + SPELL_SHADOW_BOLT_VOLLEY = 30510, + SPELL_DARK_MENDING = 30528, + SPELL_BURNING_ABYSSAL = 30511, + SPELL_SOUL_TRANSFER = 30531, + SPELL_FEAR = 30530, + + // WorldTrigger + SPELL_DEBRIS_KNOCKDOWN = 36449, + + // Magtheridon Room + SPELL_DEBRIS_VISUAL = 30632, + SPELL_DEBRIS_DAMAGE = 30631, + + // Target Trigger + SPELL_BLAZE = 30542 }; -enum Creatures +enum Events { - NPC_MAGTHERIDON = 17257, - NPC_ROOM = 17516, - NPC_CHANNELLER = 17256, - NPC_ABYSSAL = 17454, + // Magtheridon + EVENT_BERSERK = 1, + EVENT_CLEAVE, + EVENT_BLAZE, + EVENT_BLAST_NOVA, + EVENT_QUAKE, + EVENT_START_FIGHT, + EVENT_RELEASED, + EVENT_COLLAPSE, + EVENT_DEBRIS_KNOCKDOWN, + EVENT_DEBRIS, + EVENT_NEARLY_EMOTE, + EVENT_TAUNT, + // Hellfire Channelers events + EVENT_SHADOWBOLT, + EVENT_FEAR, + EVENT_CHECK_FRIEND, + EVENT_DARK_MENDING, + EVENT_ABYSSAL }; -enum Spells +enum Phases { - SPELL_BLASTNOVA = 30616, - SPELL_CLEAVE = 30619, - SPELL_QUAKE_TRIGGER = 30657, //must be cast with 30561 as the proc spell - SPELL_QUAKE_KNOCKBACK = 30571, - SPELL_BLAZE_TARGET = 30541, - SPELL_BLAZE_TRAP = 30542, - SPELL_DEBRIS_KNOCKDOWN = 36449, - SPELL_DEBRIS_VISUAL = 30632, - SPELL_DEBRIS_DAMAGE = 30631, //core bug, does not support target 8 - SPELL_CAMERA_SHAKE = 36455, - SPELL_BERSERK = 27680, - SPELL_SHADOW_CAGE = 30168, - SPELL_SHADOW_GRASP = 30410, - SPELL_SHADOW_GRASP_VISUAL = 30166, - SPELL_MIND_EXHAUSTION = 44032, //Cast by the cubes when channeling ends - SPELL_SHADOW_CAGE_C = 30205, - SPELL_SHADOW_GRASP_C = 30207, - SPELL_SHADOW_BOLT_VOLLEY = 30510, - SPELL_DARK_MENDING = 30528, - SPELL_FEAR = 30530, //39176 - SPELL_BURNING_ABYSSAL = 30511, - SPELL_SOUL_TRANSFER = 30531, //core bug, does not support target 7 - SPELL_FIRE_BLAST = 37110, + PHASE_BANISH = 1, + PHASE_1, + PHASE_2, + PHASE_3 }; -//count of clickers needed to interrupt blast nova -#define CLICKERS_COUNT 5 - -typedef std::map<ObjectGuid, ObjectGuid> CubeMap; +enum Misc +{ + SUMMON_GROUP_CHANNELERS = 1, + ACTION_START_CHANNELERS_EVENT = 2 +}; -class npc_abyssal : public CreatureScript +class boss_magtheridon : public CreatureScript { public: - npc_abyssal() - : CreatureScript("npc_abyssal") - { - } + boss_magtheridon() : CreatureScript("boss_magtheridon") { } - struct npc_abyssalAI : public ScriptedAI + struct boss_magtheridonAI : public BossAI { - npc_abyssalAI(Creature* creature) : ScriptedAI(creature) + boss_magtheridonAI(Creature* creature) : BossAI(creature, DATA_MAGTHERIDON), _channelersCount(5) { } + + void Reset() override { - Initialize(); - trigger = 0; - Despawn_Timer = 60000; + _Reset(); + DoCastSelf(SPELL_SHADOW_CAGE_C); + me->SummonCreatureGroup(SUMMON_GROUP_CHANNELERS); + events.SetPhase(PHASE_BANISH); + _channelersCount = 5; + events.ScheduleEvent(EVENT_TAUNT, Minutes(4), Minutes(5)); } - void Initialize() + void CombatStart() { - FireBlast_Timer = 6000; + events.SetPhase(PHASE_2); + events.CancelEvent(EVENT_START_FIGHT); + events.CancelEvent(EVENT_NEARLY_EMOTE); + events.ScheduleEvent(EVENT_RELEASED, Seconds(6)); + Talk(EMOTE_BREAKS_FREE, me); + Talk(SAY_FREE); + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); } - uint32 FireBlast_Timer; - uint32 Despawn_Timer; - uint32 trigger; - - void Reset() override + void EnterEvadeMode(EvadeReason /*why*/) override { - Initialize(); + summons.DespawnAll(); + events.Reset(); + instance->SetData(DATA_MANTICRON_CUBE, ACTION_DISABLE); + instance->SetData(DATA_COLLAPSE, ACTION_DISABLE); + instance->SetData(DATA_COLLAPSE_2, ACTION_DISABLE); + + _DespawnAtEvade(); } - void SpellHit(Unit*, const SpellInfo* spell) override + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override { - if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) + if (summon->GetEntry() == NPC_HELLFIRE_CHANNELLER && events.IsInPhase(PHASE_1)) { - DoCast(me, SPELL_BLAZE_TRAP, true); - me->SetVisible(false); - Despawn_Timer = 130000; + _channelersCount--; + + if (_channelersCount == 0) + CombatStart(); } } - void SetTrigger(uint32 _trigger) + void DoAction(int32 action) override { - trigger = _trigger; - me->SetDisplayId(11686); - if (trigger == 1) //debris + if (action == ACTION_START_CHANNELERS_EVENT && events.IsInPhase(PHASE_BANISH)) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_DEBRIS_VISUAL, true); - FireBlast_Timer = 5000; - Despawn_Timer = 10000; + events.SetPhase(PHASE_1); + Talk(EMOTE_WEAKEN, me); + summons.DoZoneInCombat(NPC_HELLFIRE_CHANNELLER); + events.ScheduleEvent(EVENT_START_FIGHT, Minutes(2)); + events.ScheduleEvent(EVENT_NEARLY_EMOTE, Seconds(60)); + events.CancelEvent(EVENT_TAUNT); + instance->SetBossState(DATA_MAGTHERIDON, IN_PROGRESS); + instance->SetData(DATA_CALL_WARDERS, ACTION_ENABLE); } } - void EnterCombat(Unit* /*who*/) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - DoZoneInCombat(); + if (spell->Id == SPELL_SHADOW_CAGE) + Talk(SAY_BANISHED); } - void AttackStart(Unit* who) override + + void DamageTaken(Unit* /*who*/, uint32& damage) override { - if (!trigger) - ScriptedAI::AttackStart(who); + if (me->HealthBelowPctDamaged(30, damage) && !events.IsInPhase(PHASE_3)) + { + events.SetPhase(PHASE_3); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + Talk(SAY_COLLAPSE); + instance->SetData(DATA_COLLAPSE, ACTION_ENABLE); + DoCastAOE(SPELL_CAMERA_SHAKE); + events.ScheduleEvent(EVENT_COLLAPSE, Seconds(6)); + } } - void MoveInLineOfSight(Unit* who) override + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + _JustDied(); + instance->SetData(DATA_MANTICRON_CUBE, ACTION_DISABLE); + } + + void KilledUnit(Unit* who) override { - if (!trigger) - ScriptedAI::MoveInLineOfSight(who); + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } void UpdateAI(uint32 diff) override { - if (trigger) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - if (trigger == 1) + switch (eventId) { - if (FireBlast_Timer <= diff) - { - DoCast(me, SPELL_DEBRIS_DAMAGE, true); - trigger = 3; - } - else FireBlast_Timer -= diff; + case EVENT_BERSERK: + DoCastSelf(SPELL_BERSERK); + break; + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.Repeat(Seconds(10)); + break; + case EVENT_BLAZE: + me->CastCustomSpell(SPELL_BLAZE_TARGET, SPELLVALUE_MAX_TARGETS, 1); + events.Repeat(Seconds(20)); + break; + case EVENT_QUAKE: + me->CastCustomSpell(SPELL_QUAKE, SPELLVALUE_MAX_TARGETS, 5); + events.Repeat(Seconds(60)); + break; + case EVENT_START_FIGHT: + CombatStart(); + break; + case EVENT_RELEASED: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + me->SetInCombatWithZone(); + instance->SetData(DATA_MANTICRON_CUBE, ACTION_ENABLE); + events.ScheduleEvent(EVENT_CLEAVE, Seconds(10)); + events.ScheduleEvent(EVENT_BLAST_NOVA, Seconds(60)); + events.ScheduleEvent(EVENT_BLAZE, Seconds(20)); + events.ScheduleEvent(EVENT_QUAKE, Seconds(35)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(20)); + break; + case EVENT_COLLAPSE: + instance->SetData(DATA_COLLAPSE_2, ACTION_ENABLE); + events.ScheduleEvent(EVENT_DEBRIS_KNOCKDOWN, Seconds(4)); + break; + case EVENT_DEBRIS_KNOCKDOWN: + if (Creature* trigger = instance->GetCreature(DATA_WORLD_TRIGGER)) + { + trigger->CastSpell(trigger, SPELL_DEBRIS_KNOCKDOWN, true); + me->SetReactState(REACT_AGGRESSIVE); + events.ScheduleEvent(EVENT_DEBRIS, Seconds(20)); + } + break; + case EVENT_DEBRIS: + DoCastAOE(SPELL_DEBRIS_SERVERSIDE); + events.Repeat(Seconds(20)); + break; + case EVENT_NEARLY_EMOTE: + Talk(EMOTE_NEARLY_FREE, me); + break; + case EVENT_BLAST_NOVA: + Talk(EMOTE_BLAST_NOVA, me); + DoCastAOE(SPELL_BLAST_NOVA); + events.Repeat(Seconds(55)); + break; + case EVENT_TAUNT: + Talk(SAY_TAUNT); + events.Repeat(Minutes(4), Minutes(5)); + break; + default: + break; } - return; - } - if (Despawn_Timer <= diff) - { - me->DespawnOrUnsummon(); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } - else Despawn_Timer -= diff; if (!UpdateVictim()) return; - if (FireBlast_Timer <= diff) - { - DoCastVictim(SPELL_FIRE_BLAST); - FireBlast_Timer = 5000 + rand32() % 10000; - } - else FireBlast_Timer -= diff; - DoMeleeAttackIfReady(); } + + private: + uint8 _channelersCount; + }; CreatureAI* GetAI(Creature* creature) const override { - return GetMagtheridonsLairAI<npc_abyssalAI>(creature); + return GetMagtheridonsLairAI<boss_magtheridonAI>(creature); } }; -class boss_magtheridon : public CreatureScript +class npc_hellfire_channeler : public CreatureScript { public: + npc_hellfire_channeler() : CreatureScript("npc_hellfire_channeler") { } - boss_magtheridon() - : CreatureScript("boss_magtheridon") - { - } - - struct boss_magtheridonAI : public ScriptedAI + struct npc_hellfire_channelerAI : public ScriptedAI { - boss_magtheridonAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - } - - void Initialize() + npc_hellfire_channelerAI(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript()), _canCastDarkMending(true) { - Berserk_Timer = 1320000; - Quake_Timer = 40000; - Debris_Timer = 10000; - Blaze_Timer = 10000 + rand32() % 20000; - BlastNova_Timer = 60000; - Cleave_Timer = 15000; - RandChat_Timer = 90000; - - Phase3 = false; - NeedCheckCube = false; + SetBoundary(_instance->GetBossBoundary(DATA_MAGTHERIDON)); } - CubeMap Cube; - - InstanceScript* instance; - - uint32 Berserk_Timer; - uint32 Quake_Timer; - uint32 Cleave_Timer; - uint32 BlastNova_Timer; - uint32 Blaze_Timer; - uint32 Debris_Timer; - uint32 RandChat_Timer; - - bool Phase3; - bool NeedCheckCube; - void Reset() override { - Initialize(); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->AddUnitState(UNIT_STATE_STUNNED); - DoCast(me, SPELL_SHADOW_CAGE_C, true); + _events.Reset(); + DoCastSelf(SPELL_SHADOW_GRASP_C); + me->SetReactState(REACT_DEFENSIVE); } - void JustReachedHome() override - { - instance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); - instance->SetData(DATA_COLLAPSE, false); - } - - void SetClicker(ObjectGuid cubeGUID, ObjectGuid clickerGUID) - { - // to avoid multiclicks from 1 cube - if (!Cube[cubeGUID].IsEmpty()) - DebuffClicker(ObjectAccessor::GetUnit(*me, Cube[cubeGUID])); - Cube[cubeGUID] = clickerGUID; - NeedCheckCube = true; - } - - //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) - void DebuffClicker(Unit* clicker) + void EnterCombat(Unit* /*who*/) override { - if (!clicker || !clicker->IsAlive()) - return; - - clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells - clicker->InterruptNonMeleeSpells(false); - clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); - } + me->InterruptNonMeleeSpells(false); - void NeedCheckCubeStatus() - { - uint32 ClickerNum = 0; - // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) - // if not - apply mind exhaustion and delete from clicker's list - for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) - { - Unit* clicker = ObjectAccessor::GetUnit(*me, (*i).second); - if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) - { - DebuffClicker(clicker); - (*i).second.Clear(); - } - else - ++ClickerNum; - } + if (Creature* magtheridon = _instance->GetCreature(DATA_MAGTHERIDON)) + magtheridon->AI()->DoAction(ACTION_START_CHANNELERS_EVENT); - // if 5 clickers from other cubes apply shadow cage - if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) - { - Talk(SAY_BANISH); - DoCast(me, SPELL_SHADOW_CAGE, true); - } - else - if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + _events.ScheduleEvent(EVENT_SHADOWBOLT, Seconds(20)); + _events.ScheduleEvent(EVENT_CHECK_FRIEND, Seconds(1)); + _events.ScheduleEvent(EVENT_ABYSSAL, Seconds(30)); + _events.ScheduleEvent(EVENT_FEAR, Seconds(15), Seconds(20)); - if (!ClickerNum) - NeedCheckCube = false; } - void KilledUnit(Unit* /*victim*/) override + void JustDied(Unit* /*killer*/) override { - Talk(SAY_PLAYER_KILLED); + DoCastAOE(SPELL_SOUL_TRANSFER); } - void JustDied(Unit* /*killer*/) override + void JustSummoned(Creature* summon) override { - instance->SetData(DATA_MAGTHERIDON_EVENT, DONE); + if (Creature* magtheridon = _instance->GetCreature(DATA_MAGTHERIDON)) + magtheridon->AI()->JustSummoned(summon); - Talk(SAY_DEATH); + summon->SetInCombatWithZone(); } - void MoveInLineOfSight(Unit* /*who*/) override { } - - - void AttackStart(Unit* who) override + void EnterEvadeMode(EvadeReason /*why*/) override { - if (!me->HasUnitState(UNIT_STATE_STUNNED)) - ScriptedAI::AttackStart(who); + if (_instance->GetBossState(DATA_MAGTHERIDON) == IN_PROGRESS) + if (Creature* magtheridon = _instance->GetCreature(DATA_MAGTHERIDON)) + magtheridon->AI()->EnterEvadeMode(EVADE_REASON_OTHER); } - void EnterCombat(Unit* /*who*/) override - { - instance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); - DoZoneInCombat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); - - Talk(SAY_FREED); - } - void UpdateAI(uint32 diff) override { - if (!me->IsInCombat()) - { - if (RandChat_Timer <= diff) - { - Talk(SAY_TAUNT); - RandChat_Timer = 90000; - } - else - RandChat_Timer -= diff; - } - if (!UpdateVictim()) return; - if (NeedCheckCube) NeedCheckCubeStatus(); - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - Talk(EMOTE_BERSERK); - Berserk_Timer = 60000; - } - else - Berserk_Timer -= diff; - - if (Cleave_Timer <= diff) - { - DoCastVictim(SPELL_CLEAVE); - Cleave_Timer = 10000; - } - else - Cleave_Timer -= diff; - - if (BlastNova_Timer <= diff) - { - // to avoid earthquake interruption - if (!me->HasUnitState(UNIT_STATE_STUNNED)) - { - Talk(EMOTE_BLASTNOVA); - DoCast(me, SPELL_BLASTNOVA); - BlastNova_Timer = 60000; - } - } - else - BlastNova_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (Quake_Timer <= diff) - { - // to avoid blastnova interruption - if (!me->IsNonMeleeSpellCast(false)) - { - DoCast(me, SPELL_QUAKE_TRIGGER, true); - Quake_Timer = 50000; - } - } - else - Quake_Timer -= diff; + _events.Update(diff); - if (Blaze_Timer <= diff) + while (uint32 eventId = _events.ExecuteEvent()) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + switch (eventId) { - float x, y, z; - target->GetPosition(x, y, z); - Creature* summon = me->SummonCreature(NPC_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) - { - ENSURE_AI(npc_abyssal::npc_abyssalAI, summon->AI())->SetTrigger(2); - DoCast(summon, SPELL_BLAZE_TARGET, true); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } + case EVENT_SHADOWBOLT: + DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY); + _events.Repeat(Seconds(15), Seconds(20)); + break; + case EVENT_FEAR: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) + DoCast(target, SPELL_FEAR); + _events.Repeat(Seconds(25), Seconds(40)); + break; + case EVENT_CHECK_FRIEND: + if (_canCastDarkMending) + { + if (Unit* target = DoSelectBelowHpPctFriendlyWithEntry(NPC_HELLFIRE_CHANNELLER, 30.0f, 51, false)) + { + DoCast(target, SPELL_DARK_MENDING); + _canCastDarkMending = false; + _events.ScheduleEvent(EVENT_DARK_MENDING, Seconds(10), Seconds(20)); + } + } + _events.Repeat(Seconds(1)); + break; + case EVENT_DARK_MENDING: + _canCastDarkMending = true; + break; + case EVENT_ABYSSAL: + DoCastVictim(SPELL_BURNING_ABYSSAL); + _events.Repeat(Seconds(60)); + break; + default: + break; } - Blaze_Timer = urand(20000, 40000); - } - else - Blaze_Timer -= diff; - if (!Phase3 && HealthBelowPct(30) - && !me->IsNonMeleeSpellCast(false) // blast nova - && !me->HasUnitState(UNIT_STATE_STUNNED)) // shadow cage and earthquake - { - Phase3 = true; - Talk(SAY_CHAMBER_DESTROY); - DoCast(me, SPELL_CAMERA_SHAKE, true); - DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); - - instance->SetData(DATA_COLLAPSE, true); - } - - if (Phase3) - { - if (Debris_Timer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - target->GetPosition(x, y, z); - Creature* summon = me->SummonCreature(NPC_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) - ENSURE_AI(npc_abyssal::npc_abyssalAI, summon->AI())->SetTrigger(1); - } - Debris_Timer = 10000; - } - else - Debris_Timer -= diff; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; } DoMeleeAttackIfReady(); } + + private: + InstanceScript* _instance; + EventMap _events; + bool _canCastDarkMending; }; CreatureAI* GetAI(Creature* creature) const override { - return GetMagtheridonsLairAI<boss_magtheridonAI>(creature); + return GetMagtheridonsLairAI<npc_hellfire_channelerAI>(creature); } }; -class npc_hellfire_channeler : public CreatureScript +class npc_magtheridon_room : public CreatureScript { - public: +public: + npc_magtheridon_room() : CreatureScript("npc_magtheridon_room") { } + struct npc_magtheridon_roomAI : public PassiveAI + { + npc_magtheridon_roomAI(Creature* creature) : PassiveAI(creature) { } - npc_hellfire_channeler() - : CreatureScript("npc_hellfire_channeler") + void Reset() override { + DoCastSelf(SPELL_DEBRIS_VISUAL); + + _scheduler.Schedule(Seconds(5), [this](TaskContext /*context*/) + { + DoCastAOE(SPELL_DEBRIS_DAMAGE); + }); } - struct npc_hellfire_channelerAI : public ScriptedAI + void UpdateAI(uint32 diff) override { - npc_hellfire_channelerAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + _scheduler.Update(diff); + } - void Initialize() - { - ShadowBoltVolley_Timer = urand(8000, 10000); - DarkMending_Timer = 10000; - Fear_Timer = urand(15000, 20000); - Infernal_Timer = urand(10000, 50000); + private: + TaskScheduler _scheduler; + }; - Check_Timer = 5000; - } + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_magtheridon_roomAI(creature); + } +}; - InstanceScript* instance; +class go_manticron_cube : public GameObjectScript +{ +public: + go_manticron_cube() : GameObjectScript("go_manticron_cube") { } - uint32 ShadowBoltVolley_Timer; - uint32 DarkMending_Timer; - uint32 Fear_Timer; - uint32 Infernal_Timer; + bool OnGossipHello(Player* player, GameObject* /*go*/) override + { + if (player->HasAura(SPELL_MIND_EXHAUSTION) || player->HasAura(SPELL_SHADOW_GRASP)) + return true; - uint32 Check_Timer; + if (Creature* trigger = player->FindNearestCreature(NPC_HELFIRE_RAID_TRIGGER, 10.0f)) + trigger->CastSpell((Unit*)nullptr, SPELL_SHADOW_GRASP_VISUAL); - void Reset() override - { - Initialize(); - } + player->CastSpell((Unit*)nullptr, SPELL_SHADOW_GRASP, true); + return true; + } +}; - void EnterCombat(Unit* /*who*/) override - { - instance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); +class spell_magtheridon_blaze_target : public SpellScriptLoader +{ + public: + spell_magtheridon_blaze_target() : SpellScriptLoader("spell_magtheridon_blaze_target") { } - me->InterruptNonMeleeSpells(false); - DoZoneInCombat(); - } + class spell_magtheridon_blaze_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_magtheridon_blaze_target_SpellScript); - void JustReachedHome() override + bool Validate(SpellInfo const* /*spellInfo*/) override { - instance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); - - DoCast(me, SPELL_SHADOW_GRASP_C, false); + return ValidateSpellInfo({ SPELL_BLAZE }); } - void JustSummoned(Creature* summon) override + void HandleAura() { - summon->AI()->AttackStart(me->GetVictim()); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_BLAZE); } - void DamageTaken(Unit*, uint32 &damage) override + void Register() override { - if (damage >= me->GetHealth()) - DoCast(me, SPELL_SOUL_TRANSFER, true); + OnHit += SpellHitFn(spell_magtheridon_blaze_target_SpellScript::HandleAura); } - void JustDied(Unit* /*killer*/) override - { - instance->SetData(DATA_CHANNELER_EVENT, DONE); - } + }; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + SpellScript* GetSpellScript() const override + { + return new spell_magtheridon_blaze_target_SpellScript(); + } +}; - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowBoltVolley_Timer = urand(10000, 20000); - } - else - ShadowBoltVolley_Timer -= diff; +class spell_magtheridon_shadow_grasp : public SpellScriptLoader +{ + public: + spell_magtheridon_shadow_grasp() : SpellScriptLoader("spell_magtheridon_shadow_grasp") { } - if (DarkMending_Timer <= diff) - { - if (HealthBelowPct(50)) - DoCast(me, SPELL_DARK_MENDING); - DarkMending_Timer = 10000 + (rand32() % 10000); - } - else - DarkMending_Timer -= diff; + class spell_magtheridon_shadow_grasp_AuraScript : public AuraScript + { + PrepareAuraScript(spell_magtheridon_shadow_grasp_AuraScript); - if (Fear_Timer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) - DoCast(target, SPELL_FEAR); - Fear_Timer = urand(25000, 40000); - } - else - Fear_Timer -= diff; + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_MIND_EXHAUSTION }); + } - if (Infernal_Timer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_BURNING_ABYSSAL, true); - Infernal_Timer = urand(30000, 40000); - } - else - Infernal_Timer -= diff; + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->InterruptNonMeleeSpells(false); + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_MIND_EXHAUSTION, true); + } - DoMeleeAttackIfReady(); + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_magtheridon_shadow_grasp_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } }; - CreatureAI* GetAI(Creature* creature) const override + AuraScript* GetAuraScript() const override { - return GetMagtheridonsLairAI<npc_hellfire_channelerAI>(creature); + return new spell_magtheridon_shadow_grasp_AuraScript(); } }; -//Manticron Cube -class go_manticron_cube : public GameObjectScript +class spell_magtheridon_shadow_grasp_visual : public SpellScriptLoader { -public: - go_manticron_cube() : GameObjectScript("go_manticron_cube") - { - } + public: + spell_magtheridon_shadow_grasp_visual() : SpellScriptLoader("spell_magtheridon_shadow_grasp_visual") { } - bool OnGossipHello(Player* player, GameObject* go) override - { - InstanceScript* instance = go->GetInstanceScript(); + class spell_magtheridon_shadow_grasp_visual_AuraScript : public AuraScript + { + PrepareAuraScript(spell_magtheridon_shadow_grasp_visual_AuraScript); - if (!instance) - return true; + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SHADOW_CAGE, SPELL_SHADOW_GRASP_VISUAL }); + } - if (instance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) - return true; - Creature* Magtheridon =ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_MAGTHERIDON)); - if (!Magtheridon || !Magtheridon->IsAlive()) - return true; + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); - // if exhausted or already channeling return - if (player->HasAura(SPELL_MIND_EXHAUSTION) || player->HasAura(SPELL_SHADOW_GRASP)) - return true; + if (target->GetAuraCount(SPELL_SHADOW_GRASP_VISUAL) == 5) + target->CastSpell(target, SPELL_SHADOW_CAGE, true); + } - player->InterruptNonMeleeSpells(false); - player->CastSpell(player, SPELL_SHADOW_GRASP, true); - player->CastSpell(player, SPELL_SHADOW_GRASP_VISUAL, false); - ENSURE_AI(boss_magtheridon::boss_magtheridonAI, Magtheridon->AI())->SetClicker(go->GetGUID(), player->GetGUID()); - return true; - } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_magtheridon_shadow_grasp_visual_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_magtheridon_shadow_grasp_visual_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_magtheridon_shadow_grasp_visual_AuraScript(); + } }; void AddSC_boss_magtheridon() { new boss_magtheridon(); new npc_hellfire_channeler(); - new npc_abyssal(); + new npc_magtheridon_room(); new go_manticron_cube(); + new spell_magtheridon_blaze_target(); + new spell_magtheridon_shadow_grasp(); + new spell_magtheridon_shadow_grasp_visual(); } diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp index 5f8b9cc4def..b7e7cfb1caa 100644 --- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * 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 @@ -16,13 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Magtheridons_Lair -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - +#include "AreaBoundary.h" #include "ScriptMgr.h" #include "Creature.h" #include "CreatureAI.h" @@ -31,221 +24,116 @@ EndScriptData */ #include "magtheridons_lair.h" #include "Map.h" -enum Spells +BossBoundaryData const boundaries = { - SPELL_SOUL_TRANSFER = 30531, // core bug, does not support target 7 - SPELL_BLAZE_TARGET = 30541, // core bug, does not support target 7 + { DATA_MAGTHERIDON, new CircleBoundary(Position(-18.70f, 2.24f), 52.30) } }; -#define CHAMBER_CENTER_X -15.14 -#define CHAMBER_CENTER_Y 1.8 -#define CHAMBER_CENTER_Z -0.4 +DoorData const doorData[] = +{ + { GO_MAGTHERIDON_DOOR, DATA_MAGTHERIDON, DOOR_TYPE_ROOM }, + { 0, 0, DOOR_TYPE_ROOM } // END +}; -#define MAX_ENCOUNTER 2 +ObjectData const creatureData[] = +{ + { NPC_MAGTHERIDON, DATA_MAGTHERIDON }, + { NPC_WORLD_TRIGGER, DATA_WORLD_TRIGGER }, + { 0, 0 } // END -#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" +}; + +ObjectData const gameObjectData[] = +{ + { GO_MAGTHERIDON_HALL, DATA_MAGTHERIDON_HALL }, + { GO_MAGTHERIDON_COLUMN_0, DATA_MAGTHERIDON_COLUMN_0 }, + { GO_MAGTHERIDON_COLUMN_1, DATA_MAGTHERIDON_COLUMN_1 }, + { GO_MAGTHERIDON_COLUMN_2, DATA_MAGTHERIDON_COLUMN_2 }, + { GO_MAGTHERIDON_COLUMN_3, DATA_MAGTHERIDON_COLUMN_3 }, + { GO_MAGTHERIDON_COLUMN_4, DATA_MAGTHERIDON_COLUMN_4 }, + { GO_MAGTHERIDON_COLUMN_5, DATA_MAGTHERIDON_COLUMN_5 }, + { 0, 0 } //END +}; + +static DataTypes const collapseObjectDatas[] = +{ + DATA_MAGTHERIDON_COLUMN_0, + DATA_MAGTHERIDON_COLUMN_1, + DATA_MAGTHERIDON_COLUMN_2, + DATA_MAGTHERIDON_COLUMN_3, + DATA_MAGTHERIDON_COLUMN_4, + DATA_MAGTHERIDON_COLUMN_5, +}; class instance_magtheridons_lair : public InstanceMapScript { public: - instance_magtheridons_lair() : InstanceMapScript(MLScriptName, 544) - { - } + instance_magtheridons_lair() : InstanceMapScript("instance_magtheridons_lair", 544) { } struct instance_magtheridons_lair_InstanceMapScript : public InstanceScript { instance_magtheridons_lair_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - CageTimer = 0; - RespawnTimer = 0; + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + LoadBossBoundaries(boundaries); + LoadObjectData(creatureData, gameObjectData); } - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - ObjectGuid MagtheridonGUID; - GuidSet ChannelerGUID; - ObjectGuid DoorGUID; - GuidSet ColumnGUID; - - uint32 CageTimer; - uint32 RespawnTimer; - - bool IsEncounterInProgress() const override + void OnGameObjectCreate(GameObject* go) override { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; + InstanceScript::OnGameObjectCreate(go); - return false; + if (go->GetEntry() == GO_MANTICRON_CUBE) + cubesGUIDS.push_back(go->GetGUID()); } void OnCreatureCreate(Creature* creature) override { - switch (creature->GetEntry()) - { - case 17257: - MagtheridonGUID = creature->GetGUID(); - break; - case 17256: - ChannelerGUID.insert(creature->GetGUID()); - break; - } - } - - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) - { - case 181713: - go->SetUInt32Value(GAMEOBJECT_FLAGS, 0); - break; - case 183847: - DoorGUID = go->GetGUID(); - break; - case 184653: // hall - case 184634: // six columns - case 184635: - case 184636: - case 184637: - case 184638: - case 184639: - ColumnGUID.insert(go->GetGUID()); - break; - } - } + InstanceScript::OnCreatureCreate(creature); - ObjectGuid GetGuidData(uint32 type) const override - { - switch (type) - { - case DATA_MAGTHERIDON: - return MagtheridonGUID; - } - return ObjectGuid::Empty; + if (creature->GetEntry() == NPC_HELLFIRE_WARDER) + warderGUIDS.push_back(creature->GetGUID()); } - void SetData(uint32 type, uint32 data) override + void SetData(uint32 data, uint32 value) override { - switch (type) + switch (data) { - case DATA_MAGTHERIDON_EVENT: - m_auiEncounter[0] = data; - if (data == NOT_STARTED) - RespawnTimer = 10000; - if (data != IN_PROGRESS) - HandleGameObject(DoorGUID, true); - break; - case DATA_CHANNELER_EVENT: - switch (data) - { - case NOT_STARTED: // Reset all channelers once one is reset. - if (m_auiEncounter[1] != NOT_STARTED) - { - m_auiEncounter[1] = NOT_STARTED; - for (GuidSet::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + case DATA_MANTICRON_CUBE: + for (ObjectGuid gobGUID : cubesGUIDS) + if (GameObject* cube = instance->GetGameObject(gobGUID)) { - if (Creature* Channeler = instance->GetCreature(*i)) - { - if (Channeler->IsAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } + if (value == ACTION_ENABLE) + cube->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + else + cube->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); } - CageTimer = 0; - HandleGameObject(DoorGUID, true); - } break; - case IN_PROGRESS: // Event start. - if (m_auiEncounter[1] != IN_PROGRESS) - { - m_auiEncounter[1] = IN_PROGRESS; - // Let all five channelers aggro. - for (GuidSet::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature* Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->IsAlive()) - Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); - } - // Release Magtheridon after two minutes. - Creature* Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->IsAlive()) - { - Magtheridon->TextEmote(EMOTE_BONDS_WEAKEN); - CageTimer = 120000; - } - HandleGameObject(DoorGUID, false); - } + case DATA_COLLAPSE: + if (GameObject* hall = GetGameObject(DATA_MAGTHERIDON_HALL)) + HandleGameObject(ObjectGuid::Empty, value == ACTION_ENABLE ? true : false, hall); break; - case DONE: // Add buff and check if all channelers are dead. - for (GuidSet::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature* Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->IsAlive()) - { - //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); - data = IN_PROGRESS; - break; - } - } + case DATA_COLLAPSE_2: + for (DataTypes data : collapseObjectDatas) + if (GameObject* go = GetGameObject(data)) + HandleGameObject(ObjectGuid::Empty, value == ACTION_ENABLE ? true : false, go); + break; + case DATA_CALL_WARDERS: + for (ObjectGuid warderGuid : warderGUIDS) + if (Creature* warder = instance->GetCreature(warderGuid)) + if (warder->IsAlive()) + warder->SetInCombatWithZone(); + break; + default: break; - } - m_auiEncounter[1] = data; - break; - case DATA_COLLAPSE: - // true - collapse / false - reset - for (GuidSet::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) - DoUseDoorOrButton(*i); - break; - default: - break; } } - uint32 GetData(uint32 type) const override - { - if (type == DATA_MAGTHERIDON_EVENT) - return m_auiEncounter[0]; - return 0; - } - - void Update(uint32 diff) override - { - if (CageTimer) - { - if (CageTimer <= diff) - { - Creature* Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->IsAlive()) - { - Magtheridon->ClearUnitState(UNIT_STATE_STUNNED); - Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); - } - CageTimer = 0; - } else CageTimer -= diff; - } - - if (RespawnTimer) - { - if (RespawnTimer <= diff) - { - for (GuidSet::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature* Channeler = instance->GetCreature(*i)) - { - if (Channeler->IsAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - RespawnTimer = 0; - } else RespawnTimer -= diff; - } - } + protected: + GuidVector cubesGUIDS; + GuidVector warderGUIDS; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h index 2865ef284b5..bcbfd978ed1 100644 --- a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * 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 @@ -24,13 +23,55 @@ #define DataHeader "ML" -enum MLDataTypes +uint32 const EncounterCount = 1; + +enum DataTypes +{ + DATA_MAGTHERIDON = 0, + DATA_WORLD_TRIGGER = 1, + DATA_MAGTHERIDON_HALL = 2, + DATA_MAGTHERIDON_COLUMN_0 = 3, + DATA_MAGTHERIDON_COLUMN_1 = 4, + DATA_MAGTHERIDON_COLUMN_2 = 5, + DATA_MAGTHERIDON_COLUMN_3 = 6, + DATA_MAGTHERIDON_COLUMN_4 = 7, + DATA_MAGTHERIDON_COLUMN_5 = 8, + DATA_MANTICRON_CUBE = 9, + DATA_COLLAPSE = 10, + DATA_COLLAPSE_2 = 11, + DATA_CALL_WARDERS = 12 +}; + +enum Actions +{ + ACTION_ENABLE = 1, + ACTION_DISABLE = 2 +}; + +enum CreatureIds +{ + NPC_MAGTHERIDON = 17257, + NPC_ABYSSAL = 17454, + NPC_HELLFIRE_CHANNELLER = 17256, + NPC_TARGET_TRIGGER = 17474, + NPC_WORLD_TRIGGER = 21252, + NPC_HELFIRE_RAID_TRIGGER = 17376, + NPC_OLDWORLD_TRIGGER = 15384, + NPC_MAGTHERIDON_ROOM = 17516, + NPC_HELLFIRE_WARDER = 18829 +}; + +enum GameObjectIds { - DATA_MAGTHERIDON_EVENT = 1, - DATA_MAGTHERIDON = 3, - DATA_CHANNELER_EVENT = 2, - DATA_COLLAPSE = 6, - DATA_CHANNELER = 9 + GO_MAGTHERIDON_DOOR = 183847, + GO_MANTICRON_CUBE = 181713, + GO_MAGTHERIDON_HALL = 184653, + GO_MAGTHERIDON_COLUMN_0 = 184638, + GO_MAGTHERIDON_COLUMN_1 = 184639, + GO_MAGTHERIDON_COLUMN_2 = 184635, + GO_MAGTHERIDON_COLUMN_3 = 184634, + GO_MAGTHERIDON_COLUMN_4 = 184636, + GO_MAGTHERIDON_COLUMN_5 = 184637 }; template<typename AI> |