diff options
author | ariel- <ariel-@users.noreply.github.com> | 2017-03-23 04:26:09 -0300 |
---|---|---|
committer | funjoker <funjoker109@gmail.com> | 2020-06-14 23:49:01 +0200 |
commit | e2bc8c538360ba753ca3f11d1ea21e7519930919 (patch) | |
tree | 69e41f2650e8576c3830c311d176af7530c5cbd3 | |
parent | d50dccbfce639203c254f488d55411970502ccdb (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)
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, |