aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2017-03-23 04:26:09 -0300
committerfunjoker <funjoker109@gmail.com>2020-06-14 23:49:01 +0200
commite2bc8c538360ba753ca3f11d1ea21e7519930919 (patch)
tree69e41f2650e8576c3830c311d176af7530c5cbd3
parentd50dccbfce639203c254f488d55411970502ccdb (diff)
Core/Scripts: improvements on the Thorim script
Improvements done to initial work by joschiwald: - Fixed stormhammer casting and visuals - Fixed spell credits - Implemented removal of Impale when HP is higher than 90% - Corrected faction templates for the pre combat creatures - Implemeted Leap on the arena adds (thanks to joschiwald for implementing conditions) - Scripted lighting charge using AuraScript periodic - Fixed timings - Corrections on the hallway encounters (added knockback immunity to minibosses too) - Fixed multiple blizzards issue - Lever will now reset properly, should players fail to get inside. This allows the door to be opened more than once during the combat - Corrections in the outro event - Implemented paralytic field traps on the hallway. - Implemented Ancient Gate of the Keepers opening. - Changed blizzard bunny targetting to conditions entirely. - Removed obsolete scripts - Standards: delete spell script names by ScriptName instead of spell_id - Swapped factions for pre-adds (alliance should get horde trash and vs) - Fixed Leap setting home position for adds - Removed a bunch of magic numbers - Runic Colossus should finish current Runic Explosion before beginning to attack - Fixed UpdateAI logic to put it in line with other scripts (ie don't stop casts) Special thanks to: - chaodhib for the blizzard trigger waypoints and investigation on spell radius - Malcrom for creating the Conditions Creator :P Closes #15008 Closes #17072 (cherry picked from commit 4a69f5bda58fe3af5ec6000e0ec10a3b0732969a)
-rw-r--r--sql/updates/world/master/2020_06_14_09_world_2017_05_16_01_world.sql210
-rw-r--r--sql/updates/world/master/2020_06_14_09_world_2017_MM_DD_NN_world_15008.sql99
-rw-r--r--src/server/game/Spells/SpellMgr.cpp8
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp916
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp27
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h13
6 files changed, 854 insertions, 419 deletions
diff --git a/sql/updates/world/master/2020_06_14_09_world_2017_05_16_01_world.sql b/sql/updates/world/master/2020_06_14_09_world_2017_05_16_01_world.sql
new file mode 100644
index 00000000000..8e0718846b3
--- /dev/null
+++ b/sql/updates/world/master/2020_06_14_09_world_2017_05_16_01_world.sql
@@ -0,0 +1,210 @@
+/*
+ * Thorim
+ */
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (32865,32872,32873,33196);
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextID`, `comment`) VALUES
+-- Thorim
+(32865, 0,0,'Interlopers! You mortals who dare to interfere with my sport will pay... Wait--you...',14,0,100,0,0,15733,33145,'Thorim SAY_AGGRO_1'),
+(32865, 1,0,'I remember you... In the mountains... But you... what is this? Where am--',14,0,100,0,0,15734,33270,'Thorim SAY_AGGRO_2'),
+(32865, 2,0,'Do not hold back! Destroy them!',14,0,100,0,0,15736,34241,'Thorim SAY_SPECIAL'),
+(32865, 3,0,'Impertinent whelps, you dare challenge me atop my pedestal? I will crush you myself!',14,0,100,0,0,15738,33148,'Thorim SAY_JUMPDOWN'),
+(32865, 4,0,'Can''t you at least put up a fight!?',14,0,100,0,0,15739,34239,'Thorim SAY_SLAY_1'),
+(32865, 4,1,'Pathetic.',14,0,100,0,0,15740,35768,'Thorim SAY_SLAY_2'),
+(32865, 5,0,'My patience has reached its limit!',14,0,100,0,0,15741,33365,'Thorim SAY_BERSERK'),
+(32865, 6,0,'Failures! Weaklings!',14,0,100,0,0,15742,33274,'Thorim SAY_WIPE'),
+(32865, 7,0,'Stay your arms! I yield!',14,0,100,0,0,15743,33948,'Thorim SAY_DEATH'),
+(32865, 8,0,'I feel as though I am awakening from a nightmare, but the shadows in this place yet linger.',14,0,100,0,0,15744,33949,'Thorim SAY_END_NORMAL_1'),
+(32865, 9,0,'Sif... was Sif here? Impossible--she died by my brother''s hand. A dark nightmare indeed....',14,0,100,0,0,15745,33950,'Thorim SAY_END_NORMAL_2'),
+(32865,10,0,'I need time to reflect.... I will aid your cause if you should require it. I owe you at least that much. Farewell.',14,0,100,0,0,15746,33951,'Thorim SAY_END_NORMAL_3'),
+(32865,11,0,'You! Fiend! You are not my beloved! Be gone!',14,0,100,0,0,15747,33952,'Thorim SAY_END_HARD_1'),
+(32865,12,0,'Behold the hand behind all the evil that has befallen Ulduar, left my kingdom in ruins, corrupted my brother, and slain my wife.',14,0,100,0,0,15748,33953,'Thorim SAY_END_HARD_2'),
+(32865,13,0,'And now it falls to you, champions, to avenge us all. The task before you is great, but I will lend you my aid as I am able. You must prevail.',14,0,100,0,0,15749,33954,'Thorim SAY_END_HARD_3'),
+-- Runic Colossus
+(32872, 0,0,'%s surrounds itself with a crackling Runic Barrier!',41,0,100,0,0,0,33267,'Runic Colossus'),
+-- Ancient Rune Giant
+(32873, 0,0,'%s fortifies nearby allies with runic might!',41,0,100,0,0,0,33523,'Ancient Rune Giant'),
+-- Sif
+(33196, 0,0,'Thorim, my lord! Why else would these invaders have come into your sanctum but to slay you? They must be stopped!',14,0,100,0,0,15668,33325,'Sif - Start'),
+(33196, 1,0,'These pathetic mortals are harmless, beneath my station. Dispose of them!',14,0,100,0,0,15669,33368,'Sif - Despawn'),
+(33196, 2,0,'Impossible! Lord Thorim, I will bring your foes a frigid death!',14,0,100,0,0,15670,33369,'Sif - Event');
+
+-- Lever SAI
+SET @ENTRY := 194264;
+UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI' WHERE `entry`=@ENTRY;
+UPDATE `gameobject_template_addon` SET `flags`=32 WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=1;
+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
+(@ENTRY,1,0,0,70,0,100,0,2,0,0,0,9,0,0,0,0,0,0,14,34155,0,0,0,0,0,0,'Lever - On Gameobject State Changed - Activate Gameobject');
+
+-- Thorim Trap Bunny SAI
+SET @ENTRY := 33054;
+UPDATE `creature_template` SET `AIName`='SmartAI', `flags_extra`=2 WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,10,0,100,0,0,12,17000,17000,11,62241,0,0,0,0,0,1,0,0,0,0,0,0,0,'Thorim Trap Bunny - Within 0-12 Range Out of Combat LoS - Cast Paralytic Field');
+
+SET @ENTRY := 33725;
+UPDATE `creature_template` SET `AIName`='SmartAI', `flags_extra`=2 WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY 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
+(@ENTRY,0,0,0,10,0,100,0,0,12,17000,17000,11,63540,0,0,0,0,0,1,0,0,0,0,0,0,0,'Thorim Trap Bunny - Within 0-12 Range Out of Combat LoS - Cast Paralytic Field');
+
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_thorim_blizzard_effect','spell_thorim_frostbolt_volley','spell_thorim_charge_orb','spell_thorim_runic_smash','spell_thorim_stormhammer','spell_thorim_lightning_charge','spell_thorim_stormhammer_sif','spell_thorim_stormhammer_boomerang','spell_thorim_activate_lightning_orb_periodic','spell_iron_ring_guard_impale','spell_thorim_arena_leap');
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(62576,'spell_thorim_blizzard_effect'),
+(62602,'spell_thorim_blizzard_effect'),
+(62580,'spell_thorim_frostbolt_volley'),
+(62604,'spell_thorim_frostbolt_volley'),
+(62016,'spell_thorim_charge_orb'),
+(62057,'spell_thorim_runic_smash'),
+(62058,'spell_thorim_runic_smash'),
+(62042,'spell_thorim_stormhammer'),
+(62466,'spell_thorim_lightning_charge'),
+(64767,'spell_thorim_stormhammer_sif'),
+(64909,'spell_thorim_stormhammer_boomerang'),
+(62184,'spell_thorim_activate_lightning_orb_periodic'),
+(62331,'spell_iron_ring_guard_impale'),
+(62418,'spell_iron_ring_guard_impale'),
+(61934,'spell_thorim_arena_leap');
+
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=62042;
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = -62320;
+INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
+(-62320, -62398, 0, 'Aura of Celerity - Remove Visual');
+
+UPDATE `creature_template` SET `ScriptName`='boss_thorim' WHERE `entry`=32865;
+UPDATE `creature_template` SET `ScriptName`='npc_sif' WHERE `entry`=33196;
+UPDATE `creature_template` SET `ScriptName`='npc_thorim_pre_phase' WHERE `entry` IN (32885,32883,32908,32907,32882,32886);
+UPDATE `creature_template` SET `ScriptName`='npc_thorim_arena_phase' WHERE `entry` IN (32876,32904,32878,32877,32874,32875,33110);
+UPDATE `creature_template` SET `ScriptName`='npc_runic_colossus' WHERE `entry`=32872;
+UPDATE `creature_template` SET `ScriptName`='npc_ancient_rune_giant' WHERE `entry`=32873;
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x40000000 WHERE `entry` IN (32872, 32873, 33148, 33149);
+UPDATE `creature_template` SET `difficulty_entry_1`=33150 WHERE `entry`=32908; -- Swapped Difficulty entry npcs
+UPDATE `creature_template` SET `difficulty_entry_1`=33151 WHERE `entry`=32907; -- Caused swapped displayIDs in 25n
+UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128, `ScriptName`='' WHERE `entry` IN (33140,33141);
+UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128 WHERE `entry` IN (33378,32879);
+UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (32892);
+UPDATE `creature_template` SET `faction`=1692 WHERE `entry` IN (32885,32883,33152,33153,32908,33150,32907,33151);
+UPDATE `creature_template` SET `faction`=1693 WHERE `entry` IN (32882,33154);
+UPDATE `creature_template` SET `speed_walk`=2.5/2.5, `speed_run`=14.0/7.0, `BaseAttackTime`=1500, `RangeAttackTime`=1500, `flags_extra`=`flags_extra`|0x00000200 WHERE `entry` IN (32865,33147);
+
+SET @THORIM_BLIZZARD_BUNNY := 136515;
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (62577,62603,62016,62976,63238,64098,62466,62565,62942,64767,62560,61964,61934);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 62577, 0, 0, 31, 0, 3, 32892, @THORIM_BLIZZARD_BUNNY, 0, 0, 0, '', 'Spell Blizzard (effect 0) will hit the potential target of the spell if target is unit Thorim Event Bunny guid 136515.'),
+(13, 1, 62603, 0, 0, 31, 0, 3, 32892, @THORIM_BLIZZARD_BUNNY, 0, 0, 0, '', 'Spell Blizzard (effect 0) will hit the potential target of the spell if target is unit Thorim Event Bunny guid 136515.'),
+(13, 1, 62016, 0, 0, 31, 0, 3, 33378, 0, 0, 0, 0, '', 'Spell Charge Orb (effect 0) will hit the potential target of the spell if target is unit Thunder Orb.'),
+(13, 1, 62976, 0, 0, 31, 0, 3, 33378, 0, 0, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is unit Thunder Orb.'),
+(13, 1, 62976, 0, 0, 33, 0, 1, 0, 0, 1, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is not the same as condition target.'),
+(13, 1, 63238, 0, 0, 31, 0, 3, 33378, 0, 0, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is unit Thunder Orb.'),
+(13, 1, 63238, 0, 0, 33, 0, 1, 0, 0, 1, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is not the same as condition target.'),
+(13, 1, 64098, 0, 0, 31, 0, 3, 32865, 0, 0, 0, 0, '', 'Spell Lightning Bolt (effect 0) will hit the potential target of the spell if target is unit Thorim.'),
+(13, 4, 62466, 0, 0, 31, 0, 3, 32780, 0, 0, 0, 0, '', 'Spell Lightning Charge (effect 2) will hit the potential target of the spell if target is unit Invisible Stalker (All Phases).'),
+(13, 3, 62565, 0, 0, 31, 0, 3, 32865, 0, 0, 0, 0, '', 'Spell Touch of Dominion (effects 0 & 1) will hit the potential target of the spell if target is unit Thorim.'),
+(13, 7, 62942, 0, 0, 31, 0, 3, 32874, 0, 0, 0, 0, '', 'Spell Runic Fortification (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Iron Ring Guard.'),
+(13, 7, 62942, 0, 1, 31, 0, 3, 32875, 0, 0, 0, 0, '', 'Spell Runic Fortification (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Iron Honor Guard.'),
+(13, 7, 62942, 0, 2, 31, 0, 3, 33110, 0, 0, 0, 0, '', 'Spell Runic Fortification (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Acolyte.'),
+(13, 1, 64767, 0, 0, 31, 0, 3, 33196, 0, 0, 0, 0, '', 'Spell Stormhammer (effect 0) will hit the potential target of the spell if target is unit Sif.'),
+(13, 7, 62560, 0, 0, 31, 0, 3, 32876, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Champion.'),
+(13, 7, 62560, 0, 1, 31, 0, 3, 32877, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Warbringer.'),
+(13, 7, 62560, 0, 2, 31, 0, 3, 32878, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Evoker.'),
+(13, 7, 62560, 0, 3, 31, 0, 3, 32904, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Commoner.'),
+(13, 1, 61964, 0, 0, 31, 0, 3, 32882, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Jormungar Behemoth.'),
+(13, 1, 61964, 0, 1, 31, 0, 3, 32883, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Soldier.'),
+(13, 1, 61964, 0, 2, 31, 0, 3, 32885, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Soldier.'),
+(13, 1, 61964, 0, 3, 31, 0, 3, 32886, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Dark Rune Acolyte.'),
+(13, 1, 61964, 0, 4, 31, 0, 3, 32907, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Captain.'),
+(13, 1, 61964, 0, 5, 31, 0, 3, 32908, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Captain.'),
+(13, 1, 61934, 0, 0, 31, 0, 3, 32892, 0, 0, 0, 0, 'condition_thorim_arena_leap', 'Spell Leap (effect 0) will hit the potential target of the spell if target is unit Thorim Event Bunny.'),
+(13, 1, 61934, 0, 0, 31, 0, 3, 32892, @THORIM_BLIZZARD_BUNNY, 1, 0, 0, '', 'Spell Leap (effect 0) will hit the potential target of the spell if target is not unit Thorim Event Bunny guid 136515.');
+
+DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (62042,64767,45537);
+INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES
+(0, 62042, 64, '', '', 'Stormhammer - Ignore LOS'),
+(0, 64767, 64, '', '', 'Stormhammer - Ignore LOS'),
+(0, 45537, 64, '', '', 'Lightning Beam Channel - Ignore LOS');
+
+DELETE FROM `creature` WHERE `id` IN (32882,32908,32907,32885,32883,32886); -- PreAdds
+DELETE FROM `creature` WHERE `id` IN (32874,32875,33110); -- Colossus, Giant Adds
+
+-- Fix Thorim Controller multi spawns
+SET @CGUID:=136446;
+DELETE FROM `creature` WHERE `id`=32879;
+INSERT INTO `creature` (`guid`, `id`, `map`, `spawnDifficulties`, `PhaseId`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES
+(@CGUID, 32879, 603, '14,33', 0, 2134.774, -262.3073, 428.6936, 1.343904, 7200, 0, 0); -- 32879 (Area: 0) (Auras: 62184 - 62184)
+
+UPDATE `gameobject_template` SET `size`=3 WHERE `entry`=194315;
+UPDATE `gameobject_template_addon` SET `faction`=94, `flags`=16 WHERE `entry` IN (194313,194314,194315);
+
+SET @OGUID := 3926; -- 4 free guids
+DELETE FROM `gameobject` WHERE `id` IN (194312,194313,194314,194315);
+INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnDifficulties`, `PhaseId`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) values
+(@OGUID+0,194312,603,'14',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0),
+(@OGUID+1,194313,603,'14',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0),
+(@OGUID+2,194314,603,'33',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0),
+(@OGUID+3,194315,603,'33',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0);
+
+UPDATE `gameobject_loot_template` SET `LootMode`=1 WHERE `Entry`=27074;
+DELETE FROM `gameobject_loot_template` WHERE `Entry` IN (26955,26956);
+INSERT INTO `gameobject_loot_template` (`Entry`,`Item`,`Reference`,`Chance`,`QuestRequired`,`LootMode`,`GroupId`,`MinCount`,`MaxCount`,`Comment`) VALUES
+(26955,1,34372,100,0,1,0,1,1,'Thorim25 HM - normal mode loot'),
+(26955,2,12033,100,0,1,0,1,2,'Thorim25 HM - T8.5 tokens'),
+(26955,3,34154,10,0,1,0,1,1,'Thorim25 HM - Random Ulduar craft recipe'),
+(26955,45038,0,18,0,1,0,1,1,'Thorim25 HM - Val''anyr fragment'),
+(26955,45087,0,10,0,1,0,1,1,'Thorim25 HM - Runed Orb'),
+(26955,45470,0,0,0,1,1,1,1,'Thorim25 HM - Wisdom''s Hold'),
+(26955,45471,0,0,0,1,1,1,1,'Thorim25 HM - Fate''s Clutch'),
+(26955,45472,0,0,0,1,1,1,1,'Thorim25 HM - Warhelm of the Champion'),
+(26955,45473,0,0,0,1,1,1,1,'Thorim25 HM - Embrace of the Gladiator'),
+(26955,45474,0,0,0,1,1,1,1,'Thorim25 HM - Pauldrons of the Combatant'),
+(26955,45570,0,0,0,1,1,1,1,'Thorim25 HM - Skyforge Crossbow'),
+(26955,45817,0,100,1,1,0,1,1,'Thorim25 HM - Thorim''s Sigil'),
+(26955,47241,0,100,0,1,0,1,1,'Thorim25 HM - Emblem of Triumph'),
+
+(26956,1,34372,100,0,1,0,1,1,'Thorim25 - normal mode loot'),
+(26956,2,12033,100,0,1,0,1,2,'Thorim25 - T8.5 tokens'),
+(26956,3,34154,10,0,1,0,1,1,'Thorim25 - Random Ulduar craft recipe'),
+(26956,45038,0,8,0,1,0,1,1,'Thorim25 - Val''anyr fragment'),
+(26956,45087,0,10,0,1,0,1,1,'Thorim25 - Runed Orb'),
+(26956,47241,0,100,0,1,0,1,1,'Thorim25 - Emblem of Triumph');
+
+-- Pathing for Thorim Event Bunny Entry: 32892 'TDB FORMAT'
+SET @PATH := @THORIM_BLIZZARD_BUNNY * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=2148.425,`position_y`=-276.7478,`position_z`=419.5923 WHERE `guid`=@THORIM_BLIZZARD_BUNNY;
+DELETE FROM `creature_addon` WHERE `guid`=@THORIM_BLIZZARD_BUNNY;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@THORIM_BLIZZARD_BUNNY,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,2148.425,-276.7478,419.5923,0,0,0,0,100,0),
+(@PATH,2,2145.229,-278.5732,419.6016,0,0,0,0,100,0),
+(@PATH,3,2142.105,-280.7194,419.5932,0,0,0,0,100,0),
+(@PATH,4,2138.419,-281.2838,419.5999,0,0,0,0,100,0),
+(@PATH,5,2134.843,-281.9885,419.5996,0,0,0,0,100,0),
+(@PATH,6,2131.128,-281.278,419.5985,0,0,0,0,100,0),
+(@PATH,7,2127.415,-280.8166,419.5875,0,0,0,0,100,0),
+(@PATH,8,2124.459,-278.4777,419.6088,0,0,0,0,100,0),
+(@PATH,9,2121.098,-276.7148,419.5924,0,0,0,0,100,0),
+(@PATH,10,2119.281,-273.4217,419.6069,0,0,0,0,100,0),
+(@PATH,11,2116.933,-270.4605,419.5851,0,0,0,0,100,0),
+(@PATH,12,2116.359,-266.7142,419.6042,0,0,0,0,100,0),
+(@PATH,13,2115.436,-263.0562,419.5847,0,0,0,0,100,0),
+(@PATH,14,2116.543,-259.411,419.6082,0,0,0,0,100,0),
+(@PATH,15,2116.943,-255.605,419.5851,0,0,0,0,100,0),
+(@PATH,16,2119.377,-252.7493,419.6096,0,0,0,0,100,0),
+(@PATH,17,2121.183,-249.3546,419.5858,0,0,0,0,100,0),
+(@PATH,18,2124.49,-247.5925,419.6089,0,0,0,0,100,0),
+(@PATH,19,2127.329,-245.1714,419.5925,0,0,0,0,100,0),
+(@PATH,20,2131.097,-244.8609,419.6089,0,0,0,0,100,0),
+(@PATH,21,2134.792,-243.7036,419.585,0,0,0,0,100,0),
+(@PATH,22,2138.466,-244.3162,419.5979,0,0,0,0,100,0),
+(@PATH,23,2142.386,-244.7266,419.5746,0,0,0,0,100,0),
+(@PATH,24,2145.455,-247.1502,419.5968,0,0,0,0,100,0),
+(@PATH,25,2148.564,-249.0781,419.5791,0,0,0,0,100,0),
+(@PATH,26,2150.63,-252.4069,419.598,0,0,0,0,100,0),
+(@PATH,27,2153.104,-255.5907,419.5758,0,0,0,0,100,0),
+(@PATH,28,2153.286,-259.4698,419.6053,0,0,0,0,100,0),
+(@PATH,29,2154.193,-263.0425,419.6039,0,0,0,0,100,0),
+(@PATH,30,2153.279,-266.768,419.6026,0,0,0,0,100,0),
+(@PATH,31,2152.758,-270.5462,419.5822,0,0,0,0,100,0),
+(@PATH,32,2150.38,-273.4614,419.605,0,0,0,0,100,0);
diff --git a/sql/updates/world/master/2020_06_14_09_world_2017_MM_DD_NN_world_15008.sql b/sql/updates/world/master/2020_06_14_09_world_2017_MM_DD_NN_world_15008.sql
deleted file mode 100644
index e52203e4e7e..00000000000
--- a/sql/updates/world/master/2020_06_14_09_world_2017_MM_DD_NN_world_15008.sql
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Thorim
- */
-
--- todo: immunity runic colossus, rune giant grip and knockback
-
-DELETE FROM `creature_text` WHERE `CreatureID` IN (32865,32872,32873,33196);
-INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextID`, `comment`) VALUES
--- Thorim
-(32865, 0,0,'Interlopers! You mortals who dare to interfere with my sport will pay... Wait--you...',14,0,100,0,0,15733,33145,'Thorim SAY_AGGRO_1'),
-(32865, 1,0,'I remember you... In the mountains... But you... what is this? Where am--',14,0,100,0,0,15734,33270,'Thorim SAY_AGGRO_2'),
-(32865, 2,0,'Behold the power of the storms and despair!',14,0,100,0,0,15735,0,'Thorim SAY_SPECIAL_1'),
-(32865, 3,0,'Do not hold back! Destroy them!',14,0,100,0,0,15736,34241,'Thorim SAY_SPECIAL_2'),
-(32865, 4,0,'Have you begun to regret your intrusion?',14,0,100,0,0,15737,0,'Thorim SAY_SPECIAL_3'),
-(32865, 5,0,'Impertinent whelps, you dare challenge me atop my pedestal? I will crush you myself!',14,0,100,0,0,15738,33148,'Thorim SAY_JUMPDOWN'),
-(32865, 6,0,'Can''t you at least put up a fight!?',14,0,100,0,0,15739,34239,'Thorim SAY_SLAY_1'),
-(32865, 6,1,'Pathetic.',14,0,100,0,0,15740,35768,'Thorim SAY_SLAY_2'),
-(32865, 7,0,'My patience has reached its limit!',14,0,100,0,0,15741,33365,'Thorim SAY_BERSERK'),
-(32865, 8,0,'Failures! Weaklings!',14,0,100,0,0,15742,33274,'Thorim SAY_WIPE'),
-(32865, 9,0,'Stay your arms! I yield!',14,0,100,0,0,15743,33948,'Thorim SAY_DEATH'),
-(32865,10,0,'I feel as though I am awakening from a nightmare, but the shadows in this place yet linger.',14,0,100,0,0,15744,33949,'Thorim SAY_END_NORMAL_1'),
-(32865,11,0,'Sif... was Sif here? Impossible--she died by my brother''s hand. A dark nightmare indeed....',14,0,100,0,0,15745,33950,'Thorim SAY_END_NORMAL_2'),
-(32865,12,0,'I need time to reflect.... I will aid your cause if you should require it. I owe you at least that much. Farewell.',14,0,100,0,0,15746,33951,'Thorim SAY_END_NORMAL_3'),
-(32865,13,0,'You! Fiend! You are not my beloved! Be gone!',14,0,100,0,0,15747,33952,'Thorim SAY_END_HARD_1'),
-(32865,14,0,'Behold the hand behind all the evil that has befallen Ulduar, left my kingdom in ruins, corrupted my brother, and slain my wife.',14,0,100,0,0,15748,33953,'Thorim SAY_END_HARD_2'),
-(32865,15,0,'And now it falls to you, champions, to avenge us all. The task before you is great, but I will lend you my aid as I am able. You must prevail.',14,0,100,0,0,15749,33954,'Thorim SAY_END_HARD_3'),
--- Runic Colossus
-(32872, 0,0,'%s surrounds itself with a crackling Runic Barrier!',41,0,100,0,0,0,33267,'Runic Colossus'),
--- Ancient Rune Giant
-(32873, 0,0,'%s fortifies nearby allies with runic might!',41,0,100,0,0,0,33523,'Ancient Rune Giant'),
--- Sif
-(33196, 0,0,'Thorim, my lord! Why else would these invaders have come into your sanctum but to slay you? They must be stopped!',14,0,100,0,0,15668,33325,'Sif - Start'),
-(33196, 1,0,'These pathetic mortals are harmless, beneath my station. Dispose of them!',14,0,100,0,0,15669,33368,'Sif - Despawn'),
-(33196, 2,0,'Impossible! Lord Thorim, I will bring your foes a frigid death!',14,0,100,0,0,15670,33369,'Sif - Event');
-
-UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI' WHERE `entry`=194265;
-DELETE FROM `smart_scripts` WHERE `entryorguid`=194265 AND `source_type`=1;
-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
-(194265,1,0,0,70,0,100,0,2,0,0,0,9,0,0,0,0,0,0,14,34155,0,0,0,0,0,0, 'Lever - On activate - Activate Dark Iron Portcullis');
-
-DELETE FROM `spell_script_names` WHERE `spell_id` IN (62577,62603,62576,62602,62580,62604,62016,62057,62058,62042,62466,64767);
-INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
-(62577,'spell_thorim_blizzard'),
-(62603,'spell_thorim_blizzard'),
-(62576,'spell_thorim_blizzard_effect'),
-(62602,'spell_thorim_blizzard_effect'),
-(62580,'spell_thorim_frostbolt_volley'),
-(62604,'spell_thorim_frostbolt_volley'),
-(62016,'spell_thorim_charge_orb'),
-(62057,'spell_thorim_runic_smash'),
-(62058,'spell_thorim_runic_smash'),
-(62042,'spell_thorim_stormhammer'),
-(62466,'spell_thorim_lightning_charge'),
-(64767,'spell_thorim_stormhammer_sif');
-
-DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=62042;
-
-UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128, `ScriptName`='' WHERE `entry` IN (33140,33141);
-UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128 WHERE `entry` IN (33054,33378);
-UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (32892);
-
-DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (62577,62603,62016,62976,63238,64098,62466,62565,62942,64767,62560,61964);
-INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
-(13,1,62577,0,0,31,0,3,32892,0,0,0,'','Thorim - Blizzard'),
-(13,1,62603,0,0,31,0,3,32892,0,0,0,'','Thorim - Blizzard'),
-(13,1,62016,0,0,31,0,3,33378,0,0,0,'','Thorim - Charge Orb'),
-(13,1,62976,0,0,31,0,3,33378,0,0,0,'','Thorim - Lightning Pillar'),
-(13,1,62976,0,0,33,0,1,0,0,1,0,'','Thorim - Lightning Pillar'),
-(13,1,63238,0,0,31,0,3,33378,0,0,0,'','Thorim - Lightning Pillar'),
-(13,1,63238,0,0,33,0,1,0,0,1,0,'','Thorim - Lightning Pillar'),
-(13,1,64098,0,0,31,0,3,32865,0,0,0,'','Thorim - Lightning Bolt'),
-(13,4,62466,0,0,31,0,3,32780,0,0,0,'','Thorim - Lightning Charge'),
-(13,3,62565,0,0,31,0,3,32865,0,0,0,'','Thorim - Touch of Dominion'),
-(13,7,62942,0,0,31,0,3,32874,0,0,0,'','Thorim - Runic Fortification'),
-(13,7,62942,0,1,31,0,3,32875,0,0,0,'','Thorim - Runic Fortification'),
-(13,7,62942,0,2,31,0,3,33110,0,0,0,'','Thorim - Runic Fortification'),
-(13,1,64767,0,0,31,0,3,33196,0,0,0,'','Thorim - Stormhammer'),
-(13,7,62560,0,0,31,0,3,32876,0,0,0,'','Thorim - Berserk'),
-(13,7,62560,0,1,31,0,3,32877,0,0,0,'','Thorim - Berserk'),
-(13,7,62560,0,2,31,0,3,32878,0,0,0,'','Thorim - Berserk'),
-(13,7,62560,0,3,31,0,3,32904,0,0,0,'','Thorim - Berserk'),
-(13,1,61964,0,0,31,0,3,32882,0,0,0,'','Thorim - Circle of Healing'),
-(13,1,61964,0,1,31,0,3,32883,0,0,0,'','Thorim - Circle of Healing'),
-(13,1,61964,0,2,31,0,3,32885,0,0,0,'','Thorim - Circle of Healing'),
-(13,1,61964,0,3,31,0,3,32886,0,0,0,'','Thorim - Circle of Healing'),
-(13,1,61964,0,4,31,0,3,32907,0,0,0,'','Thorim - Circle of Healing'),
-(13,1,61964,0,5,31,0,3,32908,0,0,0,'','Thorim - Circle of Healing');
-
-UPDATE `gameobject_template` SET `size`=3 WHERE `entry` IN (194312,194313,194314,194315);
-UPDATE `gameobject_template_addon` SET `faction`=94 WHERE `entry` IN (194312,194313,194314,194315);
-
-DELETE FROM `gameobject` WHERE `id` IN (194312,194313,194314,194315);
-INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnDifficulties`, `PhaseId`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) values
-(360300,194312,603,'14',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0),
-(360301,194313,603,'14',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0),
-(360302,194314,603,'33',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0),
-(360303,194315,603,'33',0,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-604800,255,1,0);
-
-DELETE FROM `creature` WHERE `id`=32892 AND `position_z` < 425.0;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 1e2bc42c17d..f2afcdbc474 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3363,6 +3363,14 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY;
});
+ // Blizzard (Thorim)
+ ApplySpellFix({ 62576, 62602 }, [](SpellInfo* spellInfo)
+ {
+ // DBC data is wrong for EFFECT_0, it's a different dynobject target than EFFECT_1
+ // Both effects should be shared by the same DynObject
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_CASTER_LEFT);
+ });
+
// Spinning Up (Mimiron)
ApplySpellFix({ 63414 }, [](SpellInfo* spellInfo)
{
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
index d15a5700bd4..f5a8e693922 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp
@@ -20,17 +20,23 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "TypeContainerVisitor.h"
+#include "CellImpl.h"
+#include "GridNotifiersImpl.h"
#include "ulduar.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
-#include "GridNotifiersImpl.h"
-#include "SpellAuraEffects.h"
#include <G3D/Vector3.h>
+#include "AreaBoundary.h"
+#include "InstanceScript.h"
+#include "ObjectAccessor.h"
+#include "MotionMaster.h"
enum Spells
{
// Thorim
- SPELL_SHEAT_OF_LIGHTNING = 62276,
+ SPELL_SHEATH_OF_LIGHTNING = 62276,
SPELL_STORMHAMMER = 62042,
SPELL_STORMHAMMER_SIF = 64767,
SPELL_STORMHAMMER_BOOMERANG = 64909,
@@ -48,7 +54,8 @@ enum Spells
SPELL_LIGHTNING_PILLAR_1 = 63238, // caster high position, target low position
SPELL_UNBALANCING_STRIKE = 62130,
SPELL_BERSERK_PHASE_1 = 62560,
- SPELL_BERSERK_PHASE_2 = 26662,
+ SPELL_BERSERK_PHASE_2 = 62555,
+ SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC = 62184,
// Credits
SPELL_CREDIT_SIFFED = 64980,
@@ -100,10 +107,9 @@ enum Events
EVENT_JUMPDOWN,
EVENT_UNBALANCING_STRIKE,
EVENT_CHAIN_LIGHTNING,
- EVENT_TRANSFER_ENERGY,
- EVENT_RELEASE_ENERGY,
- EVENT_ACTIVATE_LIGHNING_FIELD,
- EVENT_CHECK_PLAYER,
+ EVENT_START_PERIODIC_CHARGE,
+ EVENT_LIGHTNING_CHARGE,
+ EVENT_ACTIVATE_LIGHTNING_FIELD,
EVENT_OUTRO_1,
EVENT_OUTRO_2,
EVENT_OUTRO_3,
@@ -138,20 +144,18 @@ enum Yells
// Thorim
SAY_AGGRO_1 = 0,
SAY_AGGRO_2 = 1,
- //SAY_SPECIAL_1 = 2,
- SAY_SPECIAL_2 = 3,
- //SAY_SPECIAL_3 = 4,
- SAY_JUMPDOWN = 5,
- SAY_SLAY = 6,
- SAY_BERSERK = 7,
- SAY_WIPE = 8,
- SAY_DEATH = 9,
- SAY_END_NORMAL_1 = 10,
- SAY_END_NORMAL_2 = 11,
- SAY_END_NORMAL_3 = 12,
- SAY_END_HARD_1 = 13,
- SAY_END_HARD_2 = 14,
- SAY_END_HARD_3 = 15,
+ SAY_SPECIAL = 2,
+ SAY_JUMPDOWN = 3,
+ SAY_SLAY = 4,
+ SAY_BERSERK = 5,
+ SAY_WIPE = 6,
+ SAY_DEATH = 7,
+ SAY_END_NORMAL_1 = 8,
+ SAY_END_NORMAL_2 = 9,
+ SAY_END_NORMAL_3 = 10,
+ SAY_END_HARD_1 = 11,
+ SAY_END_HARD_2 = 12,
+ SAY_END_HARD_3 = 13,
// Runic Colossus
EMOTE_RUNIC_BARRIER = 0,
@@ -165,27 +169,6 @@ enum Yells
SAY_SIF_EVENT = 2
};
-enum TrashTypes
-{
- // Pre Phase Trash
- BEHEMOTH,
- MERCENARY_CAPTAIN,
- MERCENARY_SOLDIER,
-
- // Arena Phase Trash
- DARK_RUNE_CHAMPION,
- DARK_RUNE_WARBRINGER,
- DARK_RUNE_COMMONER,
- DARK_RUNE_EVOKER,
-
- // Hall Way Trash
- IRON_RING_GUARD,
- IRON_HONOR_GUARD,
-
- // Shared
- DARK_RUNE_ACOLYTE
-};
-
enum PreAddSpells
{
SPELL_ACID_BREATH = 62315,
@@ -204,6 +187,8 @@ enum PreAddSpells
SPELL_HOLY_SMITE = 62335,
+ SPELL_LEAP = 61934,
+
SPELL_CHARGE = 32323,
SPELL_MORTAL_STRIKE = 35054,
SPELL_WHIRLWIND = 33500,
@@ -226,6 +211,27 @@ enum PreAddSpells
SPELL_SHIELD_SMASH = 62332,
};
+enum TrashTypes
+{
+ // Pre Phase Trash
+ BEHEMOTH,
+ MERCENARY_CAPTAIN,
+ MERCENARY_SOLDIER,
+
+ // Arena Phase Trash
+ DARK_RUNE_CHAMPION,
+ DARK_RUNE_WARBRINGER,
+ DARK_RUNE_COMMONER,
+ DARK_RUNE_EVOKER,
+
+ // Hall Way Trash
+ IRON_RING_GUARD,
+ IRON_HONOR_GUARD,
+
+ // Shared
+ DARK_RUNE_ACOLYTE
+};
+
struct ThorimTrashInfo
{
uint32 Type;
@@ -235,40 +241,39 @@ struct ThorimTrashInfo
uint32 ThirdAbility;
};
-ThorimTrashInfo const StaticThorimTrashInfo[] =
+uint8 const ThorimTrashCount = 13;
+ThorimTrashInfo const StaticThorimTrashInfo[ThorimTrashCount] =
{
// Pre Phase
- { BEHEMOTH, 32882, SPELL_ACID_BREATH, SPELL_SWEEP, 0 },
- { MERCENARY_CAPTAIN, 32908, SPELL_DEVASTATE, SPELL_HEROIC_SWIPE, SPELL_SUNDER_ARMOR }, // alliance?
- { MERCENARY_SOLDIER, 32885, SPELL_BARBED_SHOT, SPELL_SHOOT, 0 }, // alliance?
- { DARK_RUNE_ACOLYTE, 32886, SPELL_RENEW, SPELL_GREATER_HEAL, SPELL_CIRCLE_OF_HEALING },
- { MERCENARY_CAPTAIN, 32907, SPELL_DEVASTATE, SPELL_HEROIC_SWIPE, SPELL_SUNDER_ARMOR }, // horde?
- { MERCENARY_SOLDIER, 32883, SPELL_BARBED_SHOT, SPELL_SHOOT, 0 }, // horde?
+ { BEHEMOTH, NPC_JORMUNGAR_BEHEMOTH, SPELL_ACID_BREATH, SPELL_SWEEP, 0 },
+ { MERCENARY_CAPTAIN, NPC_MERCENARY_CAPTAIN_A, SPELL_DEVASTATE, SPELL_HEROIC_SWIPE, SPELL_SUNDER_ARMOR },
+ { MERCENARY_SOLDIER, NPC_MERCENARY_SOLDIER_A, SPELL_BARBED_SHOT, SPELL_SHOOT, 0 },
+ { DARK_RUNE_ACOLYTE, NPC_DARK_RUNE_ACOLYTE_PRE, SPELL_RENEW, SPELL_GREATER_HEAL, SPELL_CIRCLE_OF_HEALING },
+ { MERCENARY_CAPTAIN, NPC_MERCENARY_CAPTAIN_H, SPELL_DEVASTATE, SPELL_HEROIC_SWIPE, SPELL_SUNDER_ARMOR },
+ { MERCENARY_SOLDIER, NPC_MERCENARY_SOLDIER_H, SPELL_BARBED_SHOT, SPELL_SHOOT, 0 },
// Arena Phase
- { DARK_RUNE_CHAMPION, NPC_DARK_RUNE_CHAMPION, SPELL_MORTAL_STRIKE, SPELL_WHIRLWIND, 0 },
- { DARK_RUNE_WARBRINGER, NPC_DARK_RUNE_WARBRINGER, SPELL_RUNIC_STRIKE, 0, 0 },
- { DARK_RUNE_EVOKER, NPC_DARK_RUNE_EVOKER, SPELL_RUNIC_LIGHTNING, SPELL_RUNIC_SHIELD, SPELL_RUNIC_MENDING },
- { DARK_RUNE_COMMONER, NPC_DARK_RUNE_COMMONER, SPELL_LOW_BLOW, SPELL_PUMMEL, 0 },
+ { DARK_RUNE_CHAMPION, NPC_DARK_RUNE_CHAMPION, SPELL_MORTAL_STRIKE, SPELL_WHIRLWIND, 0 },
+ { DARK_RUNE_WARBRINGER, NPC_DARK_RUNE_WARBRINGER, SPELL_RUNIC_STRIKE, 0, 0 },
+ { DARK_RUNE_EVOKER, NPC_DARK_RUNE_EVOKER, SPELL_RUNIC_LIGHTNING, SPELL_RUNIC_SHIELD, SPELL_RUNIC_MENDING },
+ { DARK_RUNE_COMMONER, NPC_DARK_RUNE_COMMONER, SPELL_LOW_BLOW, SPELL_PUMMEL, 0 },
// Hall Way
- { IRON_RING_GUARD, NPC_IRON_RING_GUARD, SPELL_WHIRLING_TRIP, SPELL_IMPALE, 0 },
- { IRON_HONOR_GUARD, NPC_IRON_HONOR_GUARD, SPELL_CLEAVE, SPELL_SHIELD_SMASH, 0 },
- { DARK_RUNE_ACOLYTE, NPC_DARK_RUNE_ACOLYTE, SPELL_RENEW, SPELL_GREATER_HEAL, 0 },
+ { IRON_RING_GUARD, NPC_IRON_RING_GUARD, SPELL_WHIRLING_TRIP, SPELL_IMPALE, 0 },
+ { IRON_HONOR_GUARD, NPC_IRON_HONOR_GUARD, SPELL_CLEAVE, SPELL_SHIELD_SMASH, 0 },
+ { DARK_RUNE_ACOLYTE, NPC_DARK_RUNE_ACOLYTE, SPELL_RENEW, SPELL_GREATER_HEAL, 0 }
};
enum Actions
{
ACTION_INCREASE_PREADDS_COUNT,
ACTION_ACTIVATE_RUNIC_SMASH,
+ ACTION_ACTIVATE_ADDS,
+ ACTION_PILLAR_CHARGED,
ACTION_START_HARD_MODE,
- ACTION_BERSERK,
+ ACTION_BERSERK
};
-#define MAX_HARD_MODE_TIME 180000 // 3 Minutes
-
-#define IN_ARENA(who) (who->GetPositionX() < 2181.19f && who->GetPositionY() > -299.12f)
-
struct SummonLocation
{
Position pos;
@@ -277,12 +282,12 @@ struct SummonLocation
SummonLocation const PreAddLocations[] =
{
- { { 2149.68f, -263.477f, 419.679f, 3.120f }, 32882},
- { { 2131.31f, -271.640f, 419.840f, 2.188f }, 32908},
- { { 2127.24f, -259.182f, 419.974f, 5.917f }, 32885},
- { { 2123.32f, -254.770f, 419.840f, 6.170f }, 32885},
- { { 2120.10f, -258.990f, 419.840f, 6.250f }, 32885},
- { { 2129.09f, -277.142f, 419.756f, 1.222f }, 32886}
+ { { 2149.68f, -263.477f, 419.679f, 3.120f }, NPC_JORMUNGAR_BEHEMOTH },
+ { { 2131.31f, -271.640f, 419.840f, 2.188f }, NPC_MERCENARY_CAPTAIN_A },
+ { { 2127.24f, -259.182f, 419.974f, 5.917f }, NPC_MERCENARY_SOLDIER_A },
+ { { 2123.32f, -254.770f, 419.840f, 6.170f }, NPC_MERCENARY_SOLDIER_A },
+ { { 2120.10f, -258.990f, 419.840f, 6.250f }, NPC_MERCENARY_SOLDIER_A },
+ { { 2129.09f, -277.142f, 419.756f, 1.222f }, NPC_DARK_RUNE_ACOLYTE_PRE }
};
SummonLocation const ColossusAddLocations[] =
@@ -306,6 +311,18 @@ SummonLocation const GiantAddLocations[] =
Position const SifSpawnPosition = { 2148.301f, -297.8453f, 438.3308f, 2.687807f };
+enum Data
+{
+ DATA_CHARGED_PILLAR = 1,
+
+ FACTION_FRIENDLY = 35
+};
+
+enum DisplayIds
+{
+ THORIM_WEAPON_DISPLAY_ID = 45900
+};
+
uint32 const LightningOrbPathSize = 8;
G3D::Vector3 const LightningOrbPath[LightningOrbPathSize] =
{
@@ -319,10 +336,37 @@ G3D::Vector3 const LightningOrbPath[LightningOrbPathSize] =
{ 2182.310059f, -263.233093f, 414.739410f }
};
-Position const ArenaCenter = { 2135.0f, -263.0f, 420.0f, 0.0f }; // used for trash jump calculation
-Position const LightningFieldCenter = { 2135.0f, -312.5f, 438.0f, 0.0f }; // used for lightning field calculation
+// used for trash jump calculation
+Position const ArenaCenter = { 2134.77f, -262.307f };
+
+// used for lightning field calculation
+Position const LightningFieldCenter = { 2135.178f, -321.122f };
+
+CircleBoundary const ArenaFloorCircle(ArenaCenter, 45.4);
+CircleBoundary const InvertedBalconyCircle(LightningFieldCenter, 32.0, true);
+
+CreatureBoundary const ArenaBoundaries =
+{
+ &ArenaFloorCircle,
+ &InvertedBalconyCircle
+};
+
+class HeightPositionCheck
+{
+ public:
+ HeightPositionCheck(bool ret) : _ret(ret) { }
+
+ bool operator()(Position const* pos) const
+ {
+ return pos->GetPositionZ() > THORIM_BALCONY_Z_CHECK == _ret;
+ }
+
+ private:
+ bool _ret;
-// p2 start at 5357
+ static float const THORIM_BALCONY_Z_CHECK;
+};
+float const HeightPositionCheck::THORIM_BALCONY_Z_CHECK = 428.0f;
class RunicSmashExplosionEvent : public BasicEvent
{
@@ -331,7 +375,7 @@ class RunicSmashExplosionEvent : public BasicEvent
bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
{
- _owner->CastSpell((Unit*)NULL, SPELL_RUNIC_SMASH);
+ _owner->CastSpell((Unit*)nullptr, SPELL_RUNIC_SMASH);
return true;
}
@@ -344,22 +388,19 @@ class TrashJumpEvent : public BasicEvent
public:
TrashJumpEvent(Creature* owner) : _owner(owner), _stage(0) { }
- bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
+ bool Execute(uint64 eventTime, uint32 /*updateTime*/) override
{
switch (_stage)
{
case 0:
- if (Creature* stalker = _owner->FindNearestCreature(NPC_THORIM_INVISIBLE_STALKER, 30.0f))
- {
- _owner->GetMotionMaster()->MoveJump(*stalker, SPEED_CHARGE, 15.0f);
- _owner->SetHomePosition(*stalker);
- }
+ _owner->CastSpell((Unit*)nullptr, SPELL_LEAP);
++_stage;
- _owner->m_Events.AddEvent(this, _owner->m_Events.CalculateTime(2000));
+ _owner->m_Events.AddEvent(this, eventTime + 2000);
return false;
case 1:
_owner->SetReactState(REACT_AGGRESSIVE);
- _owner->AI()->DoZoneInCombat(_owner, 200.0f);
+ _owner->AI()->DoZoneInCombat(_owner);
+ _owner->AI()->SetBoundary(&ArenaBoundaries);
return true;
default:
break;
@@ -378,14 +419,14 @@ class LightningFieldEvent : public BasicEvent
public:
LightningFieldEvent(Creature* owner) : _owner(owner) { }
- bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
+ bool Execute(uint64 eventTime, uint32 /*updateTime*/) override
{
if (InstanceScript* instance = _owner->GetInstanceScript())
{
if (instance->GetBossState(BOSS_THORIM) == IN_PROGRESS)
{
- _owner->CastSpell((Unit*)NULL, SPELL_LIGHTNING_FIELD);
- _owner->m_Events.AddEvent(this, _owner->m_Events.CalculateTime(1000));
+ _owner->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_FIELD);
+ _owner->m_Events.AddEvent(this, eventTime + 1000);
return false;
}
}
@@ -426,11 +467,13 @@ class boss_thorim : public CreatureScript
if (_encounterFinished)
return;
+ SetBoundary(nullptr);
_Reset();
Initialize();
me->SetReactState(REACT_PASSIVE);
- SetCombatMovement(false);
+ me->SetDisableGravity(true);
+ me->SetControlled(true, UNIT_STATE_ROOT);
me->AddUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
events.SetPhase(PHASE_NULL);
@@ -444,8 +487,38 @@ class boss_thorim : public CreatureScript
for (SummonLocation const& s : PreAddLocations)
me->SummonCreature(s.entry, s.pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000);
- if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_THORIM_LEVER)))
- go->AddFlag(GO_FLAG_NOT_SELECTABLE);
+ if (GameObject* lever = instance->GetGameObject(DATA_THORIM_LEVER))
+ lever->AddFlag(GO_FLAG_NOT_SELECTABLE);
+
+ // Remove trigger auras
+ if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID))
+ pillar->RemoveAllAuras();
+
+ if (Creature* controller = instance->GetCreature(DATA_THORIM_CONTROLLER))
+ controller->RemoveAllAuras();
+
+ _activePillarGUID.Clear();
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ summons.DespawnAll();
+ _DespawnAtEvade();
+ }
+
+ void SetGUID(ObjectGuid guid, int32 type) override
+ {
+ if (type == DATA_CHARGED_PILLAR)
+ {
+ _activePillarGUID = guid;
+
+ if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID))
+ {
+ pillar->CastSpell(pillar, SPELL_LIGHTNING_ORB_CHARGED, true);
+ pillar->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_PILLAR_2);
+ events.ScheduleEvent(EVENT_LIGHTNING_CHARGE, 8000, 0, PHASE_2);
+ }
+ }
}
void KilledUnit(Unit* who) override
@@ -458,7 +531,7 @@ class boss_thorim : public CreatureScript
{
if (spellInfo->Id == SPELL_TOUCH_OF_DOMINION_TRIGGERED)
{
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
{
sif->AI()->Talk(SAY_SIF_DESPAWN);
sif->DespawnOrUnsummon(6000);
@@ -486,12 +559,21 @@ class boss_thorim : public CreatureScript
me->InterruptNonMeleeSpells(true);
me->RemoveAllAttackers();
me->AttackStop();
- me->SetFaction(35);
+ me->SetFaction(FACTION_FRIENDLY);
+ me->AddUnitFlag(UNIT_FLAG_RENAME);
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
+ if (Creature* controller = instance->GetCreature(DATA_THORIM_CONTROLLER))
+ controller->RemoveAllAuras();
+ if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID))
+ pillar->RemoveAllAuras();
+
+ if (_hardMode)
{
- summons.Despawn(sif);
- sif->DespawnOrUnsummon(10000);
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
+ {
+ summons.Despawn(sif);
+ sif->DespawnOrUnsummon(10000);
+ }
}
_JustDied();
@@ -504,6 +586,15 @@ class boss_thorim : public CreatureScript
me->m_Events.AddEvent(new KeeperDespawnEvent(me), me->m_Events.CalculateTime(35000));
}
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != EFFECT_MOTION_TYPE || id != EVENT_JUMP)
+ return;
+
+ me->getThreatManager().resetAllAggro();
+ SetBoundary(&ArenaBoundaries);
+ }
+
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
@@ -513,21 +604,23 @@ class boss_thorim : public CreatureScript
events.ScheduleEvent(EVENT_SAY_AGGRO_2, 9000, 0, PHASE_1);
events.ScheduleEvent(EVENT_SAY_SIF_START, 16500, 0, PHASE_1);
- events.ScheduleEvent(EVENT_START_SIF_CHANNEL, 25000, 0, PHASE_1);
+ events.ScheduleEvent(EVENT_START_SIF_CHANNEL, 22500, 0, PHASE_1);
events.ScheduleEvent(EVENT_STORMHAMMER, 40000, 0, PHASE_1);
events.ScheduleEvent(EVENT_CHARGE_ORB, 30000, 0, PHASE_1);
events.ScheduleEvent(EVENT_SUMMON_ADDS, 15000, 0, PHASE_1);
events.ScheduleEvent(EVENT_BERSERK, 369000);
- events.ScheduleEvent(EVENT_CHECK_PLAYER, 10000);
- DoCast(me, SPELL_SHEAT_OF_LIGHTNING);
+ DoCast(me, SPELL_SHEATH_OF_LIGHTNING);
- if (Creature* runic = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RUNIC_COLOSSUS)))
- runic->AI()->DoAction(ACTION_ACTIVATE_RUNIC_SMASH);
+ if (Creature* runicColossus = instance->GetCreature(DATA_RUNIC_COLOSSUS))
+ {
+ runicColossus->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
+ runicColossus->AI()->DoAction(ACTION_ACTIVATE_ADDS);
+ }
- if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_THORIM_LEVER)))
- go->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
+ if (GameObject* lever = instance->GetGameObject(DATA_THORIM_LEVER))
+ lever->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
// Summon Sif
me->SummonCreature(NPC_SIF, SifSpawnPosition);
@@ -542,8 +635,7 @@ class boss_thorim : public CreatureScript
summon->SetReactState(REACT_PASSIVE);
summon->CastSpell(summon, SPELL_LIGHTNING_DESTRUCTION, true);
- Position pos(LightningOrbPath[LightningOrbPathSize - 1].x, LightningOrbPath[LightningOrbPathSize - 1].y, LightningOrbPath[LightningOrbPathSize - 1].z);
- summon->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, pos, false);
+ summon->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, LightningOrbPath[LightningOrbPathSize - 1].x, LightningOrbPath[LightningOrbPathSize - 1].y, LightningOrbPath[LightningOrbPathSize - 1].z, false);
Movement::PointsArray path(LightningOrbPath, LightningOrbPath + LightningOrbPathSize);
@@ -587,68 +679,52 @@ class boss_thorim : public CreatureScript
Talk(SAY_AGGRO_2);
break;
case EVENT_SAY_SIF_START:
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
sif->AI()->Talk(SAY_SIF_START);
break;
case EVENT_START_SIF_CHANNEL:
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
sif->CastSpell(me, SPELL_TOUCH_OF_DOMINION);
break;
case EVENT_STORMHAMMER:
DoCast(SPELL_STORMHAMMER);
- events.ScheduleEvent(EVENT_STORMHAMMER, urand(15000, 20000), 0, PHASE_1);
+ events.Repeat(15000, 20000);
break;
case EVENT_CHARGE_ORB:
DoCastAOE(SPELL_CHARGE_ORB);
- events.ScheduleEvent(EVENT_CHARGE_ORB, urand(15000, 20000), 0, PHASE_1);
+ events.Repeat(15000, 20000);
break;
case EVENT_SUMMON_ADDS:
SummonWave();
- events.ScheduleEvent(EVENT_SUMMON_ADDS, _orbSummoned ? 3000 : 10000, 0, PHASE_1);
+ events.Repeat(_orbSummoned ? 3000 : 10000);
break;
case EVENT_JUMPDOWN:
if (_hardMode)
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
sif->AI()->DoAction(ACTION_START_HARD_MODE);
- me->RemoveAurasDueToSpell(SPELL_SHEAT_OF_LIGHTNING);
+ me->RemoveAurasDueToSpell(SPELL_SHEATH_OF_LIGHTNING);
me->SetReactState(REACT_AGGRESSIVE);
- SetCombatMovement(true);
- me->GetMotionMaster()->MoveJump(2134.79f, -263.03f, 419.84f, me->GetOrientation(), 30.0f, 20.0f);
+ me->SetDisableGravity(false);
+ me->SetControlled(false, UNIT_STATE_ROOT);
+ me->GetMotionMaster()->MoveJump(2134.8f, -263.056f, 419.983f, me->GetOrientation(), 30.0f, 20.0f);
+ events.ScheduleEvent(EVENT_START_PERIODIC_CHARGE, 2000, 0, PHASE_2);
events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, 15000, 0, PHASE_2);
events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 20000, 0, PHASE_2);
- events.ScheduleEvent(EVENT_TRANSFER_ENERGY, 20000, 0, PHASE_2);
break;
case EVENT_UNBALANCING_STRIKE:
DoCastVictim(SPELL_UNBALANCING_STRIKE);
- events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, urand(15000, 20000), 0, PHASE_2);
+ events.Repeat(15000, 20000);
break;
case EVENT_CHAIN_LIGHTNING:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
DoCast(target, SPELL_CHAIN_LIGHTNING);
- events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(7000, 15000), 0, PHASE_2);
+ events.Repeat(7000, 15000);
break;
- case EVENT_TRANSFER_ENERGY:
- {
- std::list<Creature*> triggers;
- me->GetCreatureListWithEntryInGrid(triggers, NPC_THUNDER_ORB, 200.0f);
- triggers.remove_if([](Creature* trigger)
- {
- return trigger->GetPositionZ() < 425.0f;
- });
-
- if (!triggers.empty())
- {
- Creature* pillar = Trinity::Containers::SelectRandomContainerElement(triggers);
- _activePillarGUID = pillar->GetGUID();
- pillar->CastSpell(pillar, SPELL_LIGHTNING_ORB_CHARGED, true);
- pillar->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_PILLAR_2);
- events.ScheduleEvent(EVENT_RELEASE_ENERGY, 8000, 0, PHASE_2);
- }
-
- events.ScheduleEvent(EVENT_TRANSFER_ENERGY, 16000, 0, PHASE_2);
+ case EVENT_START_PERIODIC_CHARGE:
+ if (Creature* controller = instance->GetCreature(DATA_THORIM_CONTROLLER))
+ controller->CastSpell(controller, SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC, true);
break;
- }
- case EVENT_RELEASE_ENERGY:
+ case EVENT_LIGHTNING_CHARGE:
if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID))
DoCast(pillar, SPELL_LIGHTNING_RELEASE);
break;
@@ -665,15 +741,15 @@ class boss_thorim : public CreatureScript
DoCast(me, SPELL_BERSERK_PHASE_2, true);
}
break;
- case EVENT_ACTIVATE_LIGHNING_FIELD:
+ case EVENT_ACTIVATE_LIGHTNING_FIELD:
{
std::list<Creature*> triggers;
me->GetCreatureListWithEntryInGrid(triggers, NPC_THORIM_EVENT_BUNNY, 100.0f);
triggers.remove_if([](Creature* bunny)
{
- if (bunny->GetPositionZ() < 430.0f)
+ if (HeightPositionCheck(false)(bunny))
return true;
- return LightningFieldCenter.GetExactDist2dSq(bunny) > 1225.0f;
+ return LightningFieldCenter.GetExactDist2dSq(bunny) > 1296.0f;
});
uint64 timer = 1000;
@@ -682,7 +758,7 @@ class boss_thorim : public CreatureScript
triggers.remove_if([](Creature* bunny)
{
- return LightningFieldCenter.GetExactDist2dSq(bunny) < 400.0f;
+ return LightningFieldCenter.GetExactDist2dSq(bunny) < 576.0f;
});
triggers.sort([](Creature* a, Creature* b)
@@ -690,26 +766,24 @@ class boss_thorim : public CreatureScript
return a->GetPositionX() < b->GetPositionX();
});
- for (std::list<Creature*>::const_iterator itr = triggers.begin(); itr != triggers.end();)
+ for (auto itr = triggers.cbegin(); itr != triggers.cend();)
{
- std::list<Creature*>::const_iterator prev = itr++;
+ auto prev = itr++;
if (itr != triggers.end())
(*prev)->CastSpell(*itr, SPELL_LIGHTNING_BEAM_CHANNEL);
}
break;
}
- case EVENT_CHECK_PLAYER:
- if (!me->GetMap()->GetPlayersCountExceptGMs())
- EnterEvadeMode();
- events.ScheduleEvent(EVENT_CHECK_PLAYER, 10000);
- break;
case EVENT_OUTRO_1:
Talk(_hardMode ? SAY_END_HARD_1 : SAY_END_NORMAL_1);
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
- DoCast(sif, SPELL_STORMHAMMER_SIF);
+ if (_hardMode)
+ DoCast(me, SPELL_STORMHAMMER_SIF);
break;
case EVENT_OUTRO_2:
Talk(_hardMode ? SAY_END_HARD_2 : SAY_END_NORMAL_2);
+ if (_hardMode)
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
+ sif->SetStandState(UNIT_STAND_STATE_DEAD);
break;
case EVENT_OUTRO_3:
Talk(_hardMode ? SAY_END_HARD_3 : SAY_END_NORMAL_3);
@@ -717,6 +791,9 @@ class boss_thorim : public CreatureScript
default:
break;
}
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
DoMeleeAttackIfReady();
@@ -741,7 +818,7 @@ class boss_thorim : public CreatureScript
{
// Event starts
me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
- DoZoneInCombat(me, 250.0f);
+ DoZoneInCombat(me);
}
break;
default:
@@ -754,7 +831,7 @@ class boss_thorim : public CreatureScript
me->GetCreatureListWithEntryInGrid(triggerList, NPC_THORIM_EVENT_BUNNY, 100.0f);
triggerList.remove_if([](Creature* bunny)
{
- if (bunny->GetPositionZ() < 430.0f)
+ if (HeightPositionCheck(false)(bunny))
return true;
return ArenaCenter.GetExactDist2dSq(bunny) < 3025.0f;
});
@@ -817,8 +894,8 @@ class boss_thorim : public CreatureScript
if (actor->GetTypeId() != TYPEID_PLAYER || !me->IsWithinDistInMap(actor, 10.0f))
return false;
- Creature* runicColossus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RUNIC_COLOSSUS));
- Creature* runeGiant = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RUNE_GIANT));
+ Creature* runicColossus = instance->GetCreature(DATA_RUNIC_COLOSSUS);
+ Creature* runeGiant = instance->GetCreature(DATA_RUNE_GIANT);
return runicColossus && !runicColossus->IsAlive() && runeGiant && !runeGiant->IsAlive();
}
@@ -829,14 +906,14 @@ class boss_thorim : public CreatureScript
Talk(SAY_JUMPDOWN);
events.SetPhase(PHASE_2);
events.ScheduleEvent(EVENT_JUMPDOWN, 8000);
- events.ScheduleEvent(EVENT_ACTIVATE_LIGHNING_FIELD, 15000);
+ events.ScheduleEvent(EVENT_ACTIVATE_LIGHTNING_FIELD, 15000);
events.RescheduleEvent(EVENT_BERSERK, 300000, 0, PHASE_2);
- if (Creature* sif = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SIF)))
+ if (Creature* sif = instance->GetCreature(DATA_SIF))
sif->InterruptNonMeleeSpells(false);
// Hard Mode
- if (_hardMode && events.GetTimer() <= MAX_HARD_MODE_TIME)
+ if (_hardMode)
DoCastAOE(SPELL_CREDIT_SIFFED, true);
}
else if (me->HealthBelowPctDamaged(1, damage))
@@ -867,7 +944,7 @@ struct npc_thorim_trashAI : public ScriptedAI
npc_thorim_trashAI(Creature* creature) : ScriptedAI(creature)
{
_instance = creature->GetInstanceScript();
- for (uint8 i = 0; i < 13; ++i)
+ for (uint8 i = 0; i < ThorimTrashCount; ++i)
if (me->GetEntry() == StaticThorimTrashInfo[i].Entry)
_info = &StaticThorimTrashInfo[i];
@@ -891,32 +968,14 @@ struct npc_thorim_trashAI : public ScriptedAI
return heal;
}
- /// returns heal amount of the given spell including hots
- static uint32 GetTotalHeal(uint32 spellId, Unit const* caster)
- {
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, caster->GetMap()->GetDifficultyID()))
- return GetTotalHeal(spellInfo, caster);
- return 0;
- }
-
/// returns remaining heal amount on given target
static uint32 GetRemainingHealOn(Unit* target)
{
uint32 heal = 0;
- Unit::AuraApplicationMap const& auras = target->GetAppliedAuras();
- for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
- {
- Aura const* aura = itr->second->GetBase();
+ Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
+ for (AuraEffect const* aurEff : auras)
+ heal += aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber());
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* aurEff = aura->GetEffect(i))
- {
- if (aurEff->GetAuraType() == SPELL_AURA_PERIODIC_HEAL)
- heal += aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber());
- }
- }
- }
return heal;
}
@@ -957,8 +1016,9 @@ struct npc_thorim_trashAI : public ScriptedAI
static Unit* GetUnitWithMostMissingHp(SpellInfo const* spellInfo, Unit* caster)
{
- float range = spellInfo->GetMaxRange(false);
- uint32 heal = GetTotalHeal(spellInfo, caster);
+ // use positive range, it's a healing spell
+ float const range = spellInfo->GetMaxRange(true);
+ uint32 const heal = GetTotalHeal(spellInfo, caster);
Unit* target = nullptr;
Trinity::MostHPMissingInRange checker(caster, range, heal);
@@ -968,17 +1028,13 @@ struct npc_thorim_trashAI : public ScriptedAI
return target;
}
- static Unit* GetHealTarget(uint32 spellId, Unit* caster)
+ static Unit* GetHealTarget(SpellInfo const* spellInfo, Unit* caster)
{
Unit* healTarget = nullptr;
-
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, caster->GetMap()->GetDifficultyID()))
- {
- if (!spellInfo->HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && !roll_chance_f(caster->GetHealthPct()) && !((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) > caster->GetMaxHealth()))
- healTarget = caster;
- else
- healTarget = GetUnitWithMostMissingHp(spellInfo, caster);
- }
+ if (!spellInfo->HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && !roll_chance_f(caster->GetHealthPct()) && ((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) <= caster->GetMaxHealth()))
+ healTarget = caster;
+ else
+ healTarget = GetUnitWithMostMissingHp(spellInfo, caster);
return healTarget;
}
@@ -986,34 +1042,43 @@ struct npc_thorim_trashAI : public ScriptedAI
bool UseAbility(uint32 spellId)
{
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetDifficulty());
+ if (!spellInfo)
+ return false;
+
Unit* target = nullptr;
- if (AIHelper::GetTotalHeal(spellId, me))
- target = AIHelper::GetHealTarget(spellId, me);
+ if (AIHelper::GetTotalHeal(spellInfo, me))
+ target = AIHelper::GetHealTarget(spellInfo, me);
else
target = me->GetVictim();
- if (target)
+ if (!target)
+ return false;
+
+ if (_info->Type == MERCENARY_SOLDIER)
{
- if (_info->Type == MERCENARY_SOLDIER)
+ bool allowMove = true;
+ if (me->IsInRange(target, spellInfo->GetMinRange(), spellInfo->GetMaxRange()))
+ allowMove = false;
+
+ if (IsCombatMovementAllowed() != allowMove)
{
- bool allowMove = true;
- if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetDifficulty()))
- {
- if (me->IsInRange(target, spellInfo->GetMinRange(false), spellInfo->GetMaxRange(false))
- && me->IsWithinLOSInMap(target))
- allowMove = false;
- }
SetCombatMovement(allowMove);
- }
- DoCast(target, spellId);
- return true;
+ // need relaunch movement
+ ScriptedAI::AttackStart(target);
+
+ // give some time to allow reposition, try again in a second
+ if (allowMove)
+ return false;
+ }
}
- return false;
+ DoCast(target, spellId);
+ return true;
}
- void UpdateAI(uint32 diff) override
+ void UpdateAI(uint32 diff) final override
{
if (!UpdateVictim())
return;
@@ -1026,6 +1091,9 @@ struct npc_thorim_trashAI : public ScriptedAI
while (uint32 eventId = _events.ExecuteEvent())
{
ExecuteEvent(eventId);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
if (_info->Type == DARK_RUNE_ACOLYTE)
@@ -1055,7 +1123,7 @@ class npc_thorim_pre_phase : public CreatureScript
me->setActive(true); // prevent grid unload
}
- void Reset()
+ void Reset() override
{
_events.Reset();
if (_info->PrimaryAbility)
@@ -1068,14 +1136,20 @@ class npc_thorim_pre_phase : public CreatureScript
SetCombatMovement(false);
}
- void JustDied(Unit* /*victim*/)
+ void JustDied(Unit* /*victim*/) override
{
if (Creature* thorim = _instance->GetCreature(BOSS_THORIM))
thorim->AI()->DoAction(ACTION_INCREASE_PREADDS_COUNT);
}
+ bool ShouldSparWith(Unit const* target) const override
+ {
+ return !target->GetAffectingPlayer();
+ }
+
void DamageTaken(Unit* attacker, uint32& damage) override
{
+ // nullify spell damage
if (!attacker->GetAffectingPlayer())
damage = 0;
}
@@ -1131,16 +1205,25 @@ class npc_thorim_arena_phase : public CreatureScript
case DARK_RUNE_EVOKER:
_isInArena = true;
break;
+ case DARK_RUNE_ACOLYTE:
+ {
+ _isInArena = (_info->Entry == NPC_DARK_RUNE_ACOLYTE_PRE);
+ SetBoundary(&ArenaBoundaries, !_isInArena);
+ break;
+ }
default:
_isInArena = false;
break;
}
- //_isInArena = IN_ARENA(me);
}
bool CanAIAttack(Unit const* who) const override
{
- return _isInArena == IN_ARENA(who);
+ // don't try to attack players in balcony
+ if (_isInArena && HeightPositionCheck(true)(who))
+ return false;
+
+ return CheckBoundary(who);
}
void Reset() override
@@ -1156,19 +1239,25 @@ class npc_thorim_arena_phase : public CreatureScript
_events.ScheduleEvent(EVENT_ABILITY_CHARGE, 8000);
}
- void EnterCombat(Unit* /*who*/)
+ void EnterCombat(Unit* /*who*/) override
{
if (_info->Type == DARK_RUNE_WARBRINGER)
DoCast(me, SPELL_AURA_OF_CELERITY);
+
+ if (!_isInArena)
+ if (Creature* colossus = _instance->GetCreature(DATA_RUNIC_COLOSSUS))
+ colossus->AI()->DoAction(ACTION_ACTIVATE_RUNIC_SMASH);
}
- void EnterEvadeMode(EvadeReason /*why*/) override
+ void EnterEvadeMode(EvadeReason why) override
{
+ if (why != EVADE_REASON_NO_HOSTILES && why != EVADE_REASON_BOUNDARY)
+ return;
+
// this should only happen if theres no alive player in the arena -> summon orb
- // might be called by mind control release or controllers death?
if (Creature* thorim = _instance->GetCreature(BOSS_THORIM))
thorim->AI()->DoAction(ACTION_BERSERK);
- ScriptedAI::EnterEvadeMode();
+ ScriptedAI::EnterEvadeMode(why);
}
void ExecuteEvent(uint32 eventId) override
@@ -1177,27 +1266,30 @@ class npc_thorim_arena_phase : public CreatureScript
{
case EVENT_PRIMARY_ABILITY:
if (UseAbility(_info->PrimaryAbility))
- _events.ScheduleEvent(eventId, urand(3000, 6000));
+ _events.Repeat(3000, 6000);
else
- _events.ScheduleEvent(eventId, 1000);
+ _events.Repeat(1000);
break;
case EVENT_SECONDARY_ABILITY:
if (UseAbility(_info->SecondaryAbility))
- _events.ScheduleEvent(eventId, urand(12000, 16000));
+ _events.Repeat(12000, 16000);
else
- _events.ScheduleEvent(eventId, 1000);
+ _events.Repeat(1000);
break;
case EVENT_THIRD_ABILITY:
if (UseAbility(_info->ThirdAbility))
- _events.ScheduleEvent(eventId, urand(6000, 8000));
+ _events.Repeat(6000, 8000);
else
- _events.ScheduleEvent(eventId, 1000);
+ _events.Repeat(1000);
break;
case EVENT_ABILITY_CHARGE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, [this](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(me, 8.0f, 25.0f); }))
+ {
+ Unit* referer = me;
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 25.0f); }))
DoCast(target, SPELL_CHARGE);
_events.ScheduleEvent(eventId, 12000);
break;
+ }
default:
break;
}
@@ -1218,20 +1310,35 @@ struct npc_thorim_minibossAI : public ScriptedAI
npc_thorim_minibossAI(Creature* creature) : ScriptedAI(creature), _summons(me)
{
_instance = creature->GetInstanceScript();
+
+ SetBoundary(&ArenaBoundaries, true);
+ }
+
+ bool CanAIAttack(Unit const* who) const final override
+ {
+ return CheckBoundary(who);
}
- void JustSummoned(Creature* summon) override
+ void JustSummoned(Creature* summon) final override
{
_summons.Summon(summon);
- ScriptedAI::JustSummoned(summon);
}
- void SummonedCreatureDespawn(Creature* summon) override
+ void SummonedCreatureDespawn(Creature* summon) final override
{
- ScriptedAI::SummonedCreatureDespawn(summon);
_summons.Despawn(summon);
}
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_ACTIVATE_ADDS)
+ {
+ for (ObjectGuid const& guid : _summons)
+ if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
+ summon->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
+ }
+ }
+
protected:
InstanceScript* _instance;
EventMap _events;
@@ -1247,13 +1354,20 @@ class npc_runic_colossus : public CreatureScript
{
npc_runic_colossusAI(Creature* creature) : npc_thorim_minibossAI(creature)
{
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _runicActive = false;
}
void Reset() override
{
+ Initialize();
_events.Reset();
- // Runed Door closed
+ // close the Runic Door
_instance->HandleGameObject(_instance->GetGuidData(DATA_RUNIC_DOOR), false);
// Spawn trashes
@@ -1267,19 +1381,33 @@ class npc_runic_colossus : public CreatureScript
// don't enter combat
}
+ void DoAction(int32 action) override
+ {
+ npc_thorim_minibossAI::DoAction(action);
+
+ if (_runicActive)
+ return;
+
+ if (action == ACTION_ACTIVATE_RUNIC_SMASH)
+ {
+ _runicActive = true;
+ _events.ScheduleEvent(EVENT_RUNIC_SMASH, 7000);
+ }
+ }
+
void JustDied(Unit* /*victim*/) override
{
- // Runed Door opened
+ // open the Runic Door
_instance->HandleGameObject(_instance->GetGuidData(DATA_RUNIC_DOOR), true);
if (Creature* thorim = _instance->GetCreature(BOSS_THORIM))
- thorim->AI()->Talk(SAY_SPECIAL_2);
- }
+ thorim->AI()->Talk(SAY_SPECIAL);
- void DoAction(int32 action) override
- {
- if (action == ACTION_ACTIVATE_RUNIC_SMASH)
- _events.ScheduleEvent(EVENT_RUNIC_SMASH, 12000);
+ if (Creature* giant = _instance->GetCreature(DATA_RUNE_GIANT))
+ {
+ giant->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
+ giant->AI()->DoAction(ACTION_ACTIVATE_ADDS);
+ }
}
void EnterCombat(Unit* /*who*/) override
@@ -1289,7 +1417,6 @@ class npc_runic_colossus : public CreatureScript
_events.ScheduleEvent(EVENT_RUNIC_BARRIER, urand(12000, 15000));
_events.ScheduleEvent(EVENT_SMASH, urand(15000, 18000));
_events.ScheduleEvent(EVENT_RUNIC_CHARGE, urand(20000, 24000));
- me->InterruptNonMeleeSpells(true);
}
void UpdateAI(uint32 diff) override
@@ -1305,28 +1432,31 @@ class npc_runic_colossus : public CreatureScript
{
case EVENT_RUNIC_BARRIER:
Talk(EMOTE_RUNIC_BARRIER);
- DoCast(me, SPELL_RUNIC_BARRIER);
- _events.ScheduleEvent(eventId, urand(35000, 45000));
+ DoCastAOE(SPELL_RUNIC_BARRIER);
+ _events.Repeat(35000, 45000);
break;
case EVENT_SMASH:
- DoCast(me, SPELL_SMASH);
- _events.ScheduleEvent(eventId, urand(15000, 18000));
+ DoCastAOE(SPELL_SMASH);
+ _events.Repeat(15000, 18000);
break;
case EVENT_RUNIC_CHARGE:
{
Unit* referer = me;
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 40.0f); }))
DoCast(target, SPELL_RUNIC_CHARGE);
- _events.ScheduleEvent(eventId, 20000);
+ _events.Repeat(20000);
break;
}
case EVENT_RUNIC_SMASH:
DoCast(me, RAND(SPELL_RUNIC_SMASH_LEFT, SPELL_RUNIC_SMASH_RIGHT));
- _events.ScheduleEvent(eventId, 6000);
+ _events.Repeat(6000);
break;
default:
break;
}
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
if (!UpdateVictim())
@@ -1334,6 +1464,9 @@ class npc_runic_colossus : public CreatureScript
DoMeleeAttackIfReady();
}
+
+ private:
+ bool _runicActive;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -1355,7 +1488,7 @@ class npc_ancient_rune_giant : public CreatureScript
{
_events.Reset();
- // Stone Door closed
+ // close the Stone Door
_instance->HandleGameObject(_instance->GetGuidData(DATA_STONE_DOOR), false);
// Spawn trashes
@@ -1375,7 +1508,7 @@ class npc_ancient_rune_giant : public CreatureScript
void JustDied(Unit* /*victim*/) override
{
- // Stone Door opened
+ // opem the Stone Door
_instance->HandleGameObject(_instance->GetGuidData(DATA_STONE_DOOR), true);
}
@@ -1399,16 +1532,19 @@ class npc_ancient_rune_giant : public CreatureScript
break;
case EVENT_STOMP:
DoCastAOE(SPELL_STOMP);
- _events.ScheduleEvent(eventId, urand(10000, 12000));
+ _events.Repeat(10000, 12000);
break;
case EVENT_RUNE_DETONATION:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true))
DoCast(target, SPELL_RUNE_DETONATION);
- _events.ScheduleEvent(eventId, urand(10000, 12000));
+ _events.Repeat(10000, 12000);
break;
default:
break;
}
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
DoMeleeAttackIfReady();
@@ -1428,33 +1564,22 @@ class npc_sif : public CreatureScript
struct npc_sifAI : public ScriptedAI
{
- npc_sifAI(Creature* creature) : ScriptedAI(creature), _summons(me)
+ npc_sifAI(Creature* creature) : ScriptedAI(creature)
{
SetCombatMovement(false);
+ _instance = creature->GetInstanceScript();
}
void Reset() override
{
_events.Reset();
- _summons.DespawnAll();
- }
-
- void JustSummoned(Creature* summon) override
- {
- _summons.Summon(summon);
- if (summon->GetEntry() == NPC_THORIM_EVENT_BUNNY)
- summon->GetMotionMaster()->MoveRandom(60.0f);
- }
-
- void SummonedCreatureDespawn(Creature* summon) override
- {
- _summons.Despawn(summon);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_STORMHAMMER_SIF)
{
+ me->InterruptSpell(CURRENT_GENERIC_SPELL);
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
}
@@ -1493,7 +1618,7 @@ class npc_sif : public CreatureScript
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
DoCast(target, SPELL_BLINK);
_events.ScheduleEvent(EVENT_FROST_NOVA, 0);
- _events.ScheduleEvent(eventId, urand(20000, 25000));
+ _events.Repeat(20000, 25000);
return;
case EVENT_FROST_NOVA:
DoCastAOE(SPELL_FROSTNOVA);
@@ -1501,21 +1626,22 @@ class npc_sif : public CreatureScript
case EVENT_FROSTBOLT:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
DoCast(target, SPELL_FROSTBOLT);
- _events.ScheduleEvent(eventId, 2000);
+ _events.Repeat(2000);
return;
case EVENT_FROSTBOLT_VOLLEY:
DoCastAOE(SPELL_FROSTBOLT_VOLLEY);
- _events.ScheduleEvent(eventId, urand(15000, 20000));
+ _events.Repeat(15000, 20000);
return;
case EVENT_BLIZZARD:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true))
- me->SummonCreature(NPC_THORIM_EVENT_BUNNY, *target, TEMPSUMMON_TIMED_DESPAWN, 25000);
DoCastAOE(SPELL_BLIZZARD);
- _events.ScheduleEvent(eventId, urand(35000, 45000));
+ _events.Repeat(35000, 45000);
return;
default:
break;
}
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
}
// no melee attack
@@ -1523,7 +1649,7 @@ class npc_sif : public CreatureScript
private:
EventMap _events;
- SummonList _summons;
+ InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -1532,48 +1658,6 @@ class npc_sif : public CreatureScript
}
};
-class HeightPositionCheck
-{
- public:
- HeightPositionCheck(bool ret) : _ret(ret) { }
-
- bool operator()(WorldObject* obj) const
- {
- return obj->GetPositionZ() > 425.0f == _ret;
- }
-
- private:
- bool _ret;
-};
-
-// 62577 - Blizzard
-// 62603 - Blizzard
-class spell_thorim_blizzard : public SpellScriptLoader
-{
- public:
- spell_thorim_blizzard() : SpellScriptLoader("spell_thorim_blizzard") { }
-
- class spell_thorim_blizzard_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_thorim_blizzard_SpellScript);
-
- void FilterTargets(std::list<WorldObject*>& targets)
- {
- targets.remove_if(HeightPositionCheck(true));
- }
-
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thorim_blizzard_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_thorim_blizzard_SpellScript();
- }
-};
-
// 62576 - Blizzard
// 62602 - Blizzard
class spell_thorim_blizzard_effect : public SpellScriptLoader
@@ -1600,6 +1684,7 @@ class spell_thorim_blizzard_effect : public SpellScriptLoader
return false;
}
}
+
return true;
}
@@ -1662,10 +1747,7 @@ class spell_thorim_charge_orb : public SpellScriptLoader
void FilterTargets(std::list<WorldObject*>& targets)
{
- targets.remove_if([](WorldObject* target)
- {
- return target->GetPositionZ() < 425.0f;
- });
+ targets.remove_if(HeightPositionCheck(false));
if (targets.empty())
return;
@@ -1718,7 +1800,7 @@ class spell_thorim_lightning_charge : public SpellScriptLoader
void HandleCharge()
{
- GetCaster()->CastSpell(GetCaster(), SPELL_LIGHTNING_CHARGE, true);
+ GetCaster()->CastSpell(GetCaster(), SPELL_LIGHTNING_CHARGE);
}
void Register() override
@@ -1734,6 +1816,47 @@ class spell_thorim_lightning_charge : public SpellScriptLoader
}
};
+// 61934 - Leap
+class spell_thorim_arena_leap : public SpellScriptLoader
+{
+ public:
+ spell_thorim_arena_leap() : SpellScriptLoader("spell_thorim_arena_leap") { }
+
+ class spell_thorim_arena_leap_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_thorim_arena_leap_SpellScript);
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Position const* pos = GetHitDest())
+ GetCaster()->ToCreature()->SetHomePosition(*pos);
+ }
+
+ void Register() override
+ {
+ OnEffectLaunch += SpellEffectFn(spell_thorim_arena_leap_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_JUMP_DEST);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_thorim_arena_leap_SpellScript();
+ }
+};
+
+struct OutOfArenaCheck
+{
+ bool operator()(Position const* who) const
+ {
+ return !CreatureAI::IsInBounds(ArenaBoundaries, who);
+ }
+};
+
// 62042 - Stormhammer
class spell_thorim_stormhammer : public SpellScriptLoader
{
@@ -1755,10 +1878,7 @@ class spell_thorim_stormhammer : public SpellScriptLoader
void FilterTargets(std::list<WorldObject*>& targets)
{
- targets.remove_if([](WorldObject* target)
- {
- return !IN_ARENA(target);
- });
+ targets.remove_if([](WorldObject* target) -> bool { return HeightPositionCheck(true)(target) || OutOfArenaCheck()(target); });
if (targets.empty())
{
@@ -1780,9 +1900,15 @@ class spell_thorim_stormhammer : public SpellScriptLoader
}
}
+ void LoseHammer()
+ {
+ GetCaster()->SetVirtualItem(0, 0);
+ }
+
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thorim_stormhammer_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
+ AfterCast += SpellCastFn(spell_thorim_stormhammer_SpellScript::LoseHammer);
OnEffectHitTarget += SpellEffectFn(spell_thorim_stormhammer_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
@@ -1821,8 +1947,14 @@ class spell_thorim_stormhammer_sif : public SpellScriptLoader
}
}
+ void LoseHammer()
+ {
+ GetCaster()->SetVirtualItem(0, 0);
+ }
+
void Register() override
{
+ AfterCast += SpellCastFn(spell_thorim_stormhammer_sif_SpellScript::LoseHammer);
OnEffectHitTarget += SpellEffectFn(spell_thorim_stormhammer_sif_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
@@ -1833,6 +1965,34 @@ class spell_thorim_stormhammer_sif : public SpellScriptLoader
}
};
+// 64909 - Stormhammer
+class spell_thorim_stormhammer_boomerang : public SpellScriptLoader
+{
+ public:
+ spell_thorim_stormhammer_boomerang() : SpellScriptLoader("spell_thorim_stormhammer_boomerang") { }
+
+ class spell_thorim_stormhammer_boomerang_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_thorim_stormhammer_boomerang_SpellScript);
+
+ void RecoverHammer(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ target->SetVirtualItem(0, THORIM_WEAPON_DISPLAY_ID);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_thorim_stormhammer_boomerang_SpellScript::RecoverHammer, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_thorim_stormhammer_boomerang_SpellScript();
+ }
+};
+
// 62057, 62058 - Runic Smash
class spell_thorim_runic_smash : public SpellScriptLoader
{
@@ -1852,12 +2012,12 @@ class spell_thorim_runic_smash : public SpellScriptLoader
{
PreventHitDefaultEffect(effIndex);
- std::list<Creature*> triggers;
+ std::vector<Creature*> triggers;
GetCaster()->GetCreatureListWithEntryInGrid(triggers, GetSpellInfo()->Id == SPELL_RUNIC_SMASH_LEFT ? NPC_GOLEM_LEFT_HAND_BUNNY : NPC_GOLEM_RIGHT_HAND_BUNNY, 150.0f);
- for (Creature* bunny : triggers)
+ for (Creature* trigger : triggers)
{
- float dist = GetCaster()->GetExactDist(bunny);
- bunny->m_Events.AddEvent(new RunicSmashExplosionEvent(bunny), bunny->m_Events.CalculateTime(uint64(dist * 30)));
+ float dist = GetCaster()->GetExactDist(trigger);
+ trigger->m_Events.AddEvent(new RunicSmashExplosionEvent(trigger), trigger->m_Events.CalculateTime(uint64(dist * 30.f)));
};
}
@@ -1873,6 +2033,122 @@ class spell_thorim_runic_smash : public SpellScriptLoader
}
};
+class UpperOrbCheck
+{
+ public:
+ UpperOrbCheck() : _check(true) { }
+
+ bool operator() (Creature* target) const
+ {
+ return target->GetEntry() == NPC_THUNDER_ORB && _check(target);
+ }
+
+ private:
+ HeightPositionCheck const _check;
+};
+
+// 62184 - Activate Lightning Orb Periodic
+class spell_thorim_activate_lightning_orb_periodic : public SpellScriptLoader
+{
+ public:
+ spell_thorim_activate_lightning_orb_periodic() : SpellScriptLoader("spell_thorim_activate_lightning_orb_periodic") { }
+
+ class spell_thorim_activate_lightning_orb_periodic_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_thorim_activate_lightning_orb_periodic_AuraScript);
+
+ InstanceScript* instance = nullptr;
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+
+ Unit* caster = GetCaster();
+ std::vector<Creature*> triggers;
+
+ UpperOrbCheck check;
+ Trinity::CreatureListSearcher<UpperOrbCheck> searcher(caster, triggers, check);
+ Cell::VisitGridObjects(caster, searcher, 100.f);
+
+ if (!triggers.empty())
+ {
+ Creature* target = Trinity::Containers::SelectRandomContainerElement(triggers);
+ if (Creature* thorim = instance->GetCreature(BOSS_THORIM))
+ thorim->AI()->SetGUID(target->GetGUID(), DATA_CHARGED_PILLAR);
+ }
+ }
+
+ bool Load() override
+ {
+ if (Unit* caster = GetCaster())
+ instance = caster->GetInstanceScript();
+
+ return instance != nullptr;
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_activate_lightning_orb_periodic_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_thorim_activate_lightning_orb_periodic_AuraScript();
+ }
+};
+
+// 62331, 62418 - Impale
+class spell_iron_ring_guard_impale : public SpellScriptLoader
+{
+ public:
+ spell_iron_ring_guard_impale() : SpellScriptLoader("spell_iron_ring_guard_impale") { }
+
+ class spell_iron_ring_guard_impale_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_iron_ring_guard_impale_AuraScript);
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ if (GetTarget()->HealthAbovePct(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()))
+ {
+ Remove(AURA_REMOVE_BY_ENEMY_SPELL);
+ PreventDefaultAction();
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_iron_ring_guard_impale_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_iron_ring_guard_impale_AuraScript();
+ }
+};
+
+class condition_thorim_arena_leap : public ConditionScript
+{
+ public:
+ condition_thorim_arena_leap() : ConditionScript("condition_thorim_arena_leap"), _check(false) { }
+
+ bool OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo) override
+ {
+ WorldObject* target = sourceInfo.mConditionTargets[condition->ConditionTarget];
+ InstanceScript* instance = target->GetInstanceScript();
+
+ if (!instance)
+ return false;
+
+ return _check(target);
+ }
+
+ private:
+ HeightPositionCheck _check;
+};
+
void AddSC_boss_thorim()
{
new boss_thorim();
@@ -1881,12 +2157,16 @@ void AddSC_boss_thorim()
new npc_runic_colossus();
new npc_ancient_rune_giant();
new npc_sif();
- new spell_thorim_blizzard();
new spell_thorim_blizzard_effect();
new spell_thorim_frostbolt_volley();
new spell_thorim_charge_orb();
new spell_thorim_lightning_charge();
new spell_thorim_stormhammer();
new spell_thorim_stormhammer_sif();
+ new spell_thorim_stormhammer_boomerang();
+ new spell_thorim_arena_leap();
new spell_thorim_runic_smash();
+ new spell_thorim_activate_lightning_orb_periodic();
+ new spell_iron_ring_guard_impale();
+ new condition_thorim_arena_leap();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index c07fcbc0a6d..84773bff908 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -40,7 +40,7 @@ static BossBoundaryData const boundaries =
{ BOSS_ALGALON, new CircleBoundary(Position(1632.668f, -307.7656f), 45.0) },
{ BOSS_ALGALON, new ZRangeBoundary(410.0f, 440.0f) },
{ BOSS_HODIR, new EllipseBoundary(Position(2001.5f, -240.0f), 50.0, 75.0) },
- { BOSS_THORIM, new CircleBoundary(Position(2134.73f, -263.2f), 50.0) },
+ // Thorim sets boundaries dinamically
{ BOSS_FREYA, new RectangleBoundary(2094.6f, 2520.0f, -250.0f, 200.0f) },
{ BOSS_MIMIRON, new CircleBoundary(Position(2744.0f, 2569.0f), 70.0) },
{ BOSS_VEZAX, new RectangleBoundary(1740.0f, 1930.0f, 31.0f, 228.0f) },
@@ -60,6 +60,10 @@ static DoorData const doorData[] =
{ GO_MIMIRON_DOOR_2, BOSS_MIMIRON, DOOR_TYPE_ROOM },
{ GO_MIMIRON_DOOR_3, BOSS_MIMIRON, DOOR_TYPE_ROOM },
{ GO_THORIM_ENCOUNTER_DOOR, BOSS_THORIM, DOOR_TYPE_ROOM },
+ { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_HODIR, DOOR_TYPE_PASSAGE },
+ { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_MIMIRON, DOOR_TYPE_PASSAGE },
+ { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_THORIM, DOOR_TYPE_PASSAGE },
+ { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_FREYA, DOOR_TYPE_PASSAGE },
{ GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE },
{ GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM },
{ GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM },
@@ -99,6 +103,7 @@ ObjectData const creatureData[] =
{ NPC_SIF, DATA_SIF },
{ NPC_RUNIC_COLOSSUS, DATA_RUNIC_COLOSSUS },
{ NPC_RUNE_GIANT, DATA_RUNE_GIANT },
+ { NPC_THORIM_CONTROLLER, DATA_THORIM_CONTROLLER },
{ NPC_COMPUTER, DATA_COMPUTER },
{ NPC_WORLD_TRIGGER_MIMIRON, DATA_MIMIRON_WORLD_TRIGGER },
{ NPC_VOICE_OF_YOGG_SARON, DATA_VOICE_OF_YOGG_SARON },
@@ -180,6 +185,7 @@ class instance_ulduar : public InstanceMapScript
ObjectGuid LeviathanGateGUID;
ObjectGuid KologarnChestGUID;
ObjectGuid KologarnBridgeGUID;
+ ObjectGuid ThorimDarkIronPortcullisGUID;
ObjectGuid CacheOfStormsGUID;
ObjectGuid CacheOfStormsHardmodeGUID;
ObjectGuid HodirRareCacheGUID;
@@ -338,6 +344,16 @@ class instance_ulduar : public InstanceMapScript
creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA);
break;
+ // Thorim
+ case NPC_MERCENARY_CAPTAIN_H:
+ if (TeamInInstance == HORDE)
+ creature->UpdateEntry(NPC_MERCENARY_CAPTAIN_A);
+ break;
+ case NPC_MERCENARY_SOLDIER_H:
+ if (TeamInInstance == HORDE)
+ creature->UpdateEntry(NPC_MERCENARY_SOLDIER_A);
+ break;
+
// Freya
case NPC_IRONBRANCH:
ElderGUIDs[0] = creature->GetGUID();
@@ -455,6 +471,9 @@ class instance_ulduar : public InstanceMapScript
if (GetBossState(BOSS_KOLOGARN) == DONE)
HandleGameObject(ObjectGuid::Empty, false, gameObject);
break;
+ case GO_THORIM_DARK_IRON_PORTCULLIS:
+ ThorimDarkIronPortcullisGUID = gameObject->GetGUID();
+ break;
case GO_CACHE_OF_STORMS_10:
case GO_CACHE_OF_STORMS_25:
CacheOfStormsGUID = gameObject->GetGUID();
@@ -679,8 +698,14 @@ class instance_ulduar : public InstanceMapScript
cache->RemoveFlag(GO_FLAG_NODESPAWN);
}
}
+
instance->SummonCreature(NPC_THORIM_OBSERVATION_RING, ObservationRingKeepersPos[2]);
}
+ else
+ {
+ DoCloseDoorOrButton(GetGuidData(DATA_THORIM_LEVER));
+ DoCloseDoorOrButton(ThorimDarkIronPortcullisGUID);
+ }
break;
case BOSS_ALGALON:
if (state == DONE)
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index e7279005679..885686e6fc6 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -159,6 +159,12 @@ enum UlduarNPCs
// Thorim
NPC_THORIM_INVISIBLE_STALKER = 32780,
+ NPC_JORMUNGAR_BEHEMOTH = 32882,
+ NPC_MERCENARY_CAPTAIN_A = 32908,
+ NPC_MERCENARY_CAPTAIN_H = 32907,
+ NPC_MERCENARY_SOLDIER_A = 32885,
+ NPC_MERCENARY_SOLDIER_H = 32883,
+ NPC_DARK_RUNE_ACOLYTE_PRE = 32886,
NPC_RUNIC_COLOSSUS = 32872,
NPC_RUNE_GIANT = 32873,
NPC_IRON_RING_GUARD = 32874,
@@ -174,6 +180,7 @@ enum UlduarNPCs
NPC_GOLEM_LEFT_HAND_BUNNY = 33141,
NPC_SIF = 33196,
NPC_THUNDER_ORB = 33378,
+ NPC_THORIM_CONTROLLER = 32879,
// Yogg-Saron
NPC_SARA = 33134,
@@ -249,6 +256,8 @@ enum UlduarGameObjects
GO_KOLOGARN_BRIDGE = 194232,
GO_KOLOGARN_DOOR = 194553,
+ GO_ANCIENT_GATE_OF_THE_KEEPERS = 194255,
+
// Hodir
GO_HODIR_ENTRANCE = 194442,
GO_HODIR_DOOR = 194634,
@@ -266,7 +275,8 @@ enum UlduarGameObjects
GO_THORIM_RUNIC_DOOR = 194557,
GO_THORIM_STONE_DOOR = 194558,
GO_THORIM_ENCOUNTER_DOOR = 194559,
- GO_THORIM_LEVER = 194265,
+ GO_THORIM_LEVER = 194264,
+ GO_THORIM_DARK_IRON_PORTCULLIS = 194560,
// Mimiron
GO_MIMIRON_TRAM = 194675,
@@ -439,6 +449,7 @@ enum UlduarData
DATA_RUNIC_DOOR,
DATA_STONE_DOOR,
DATA_THORIM_HARDMODE,
+ DATA_THORIM_CONTROLLER,
// Misc
DATA_BRANN_BRONZEBEARD_INTRO,