diff --git a/data/sql/updates/pending_db_world/rev_1774220399272155500.sql b/data/sql/updates/pending_db_world/rev_1774220399272155500.sql new file mode 100644 index 000000000..375e540e0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1774220399272155500.sql @@ -0,0 +1,198 @@ + +-- Ensure Grauf has RegenHealth disabled so harpoon damage persists +UPDATE `creature_template` SET `RegenHealth` = 0 WHERE `entry` IN (26893, 30775); + +-- Remove go_harpoon_canon script, use built-in GOOBER spell (48641) instead +UPDATE `gameobject_template` SET `ScriptName` = '' WHERE `entry` IN (192175, 192176, 192177); + +-- Register spell scripts +DELETE FROM `spell_script_names` WHERE `spell_id` IN (48642, 50255, 47574, 47594, 47579, 60020, 49308, 59275); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(48642, 'spell_skadi_launch_harpoon'), +(50255, 'spell_skadi_poisoned_spear'), +(47574, 'spell_freezing_cloud_area_left'), +(47594, 'spell_freezing_cloud_area_right'), +(47579, 'spell_freezing_cloud_damage'), +(60020, 'spell_freezing_cloud_damage'), +(59275, 'spell_summon_gauntlet_mobs_periodic'), +(49308, 'spell_skadi_reset_check'); + +-- Breath trigger SmartAI: on SpellHit 47563/47593 cast area spells 47574/47594 +UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE `entry` = 28351; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 28351 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 +(28351, 0, 0, 0, 8, 0, 100, 0, 47563, 0, 0, 0, 11, 47574, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Breath Trigger - On SpellHit (Freezing Cloud Left) - Cast Freezing Cloud Left Area'), +(28351, 0, 1, 0, 8, 0, 100, 0, 47593, 0, 0, 0, 11, 47594, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Breath Trigger - On SpellHit (Freezing Cloud Right) - Cast Freezing Cloud Right Area'); + +-- Conditions for freezing cloud spells to target correct entries +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` IN (47593, 47594, 47563, 48642, 47547, 49308); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 47593, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Freezing Cloud Right - Target Breath Trigger'), +(13, 1, 47594, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Freezing Cloud Right Area - Target Breath Trigger'), +(13, 1, 47563, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Freezing Cloud Left - Target Breath Trigger'), +(13, 1, 48642, 0, 0, 31, 0, 3, 26893, 0, 0, 0, 0, '', 'Launch Harpoon - Target Grauf'), +(13, 1, 48642, 0, 1, 31, 0, 3, 22515, 0, 0, 0, 0, '', 'Launch Harpoon - Target World Trigger'), +(13, 1, 47547, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Gauntlet Effect - Target Breath Trigger'), +(13, 1, 49308, 0, 0, 31, 0, 3, 28351, 0, 0, 0, 0, '', 'Gauntlet Reset Check - Target Breath Trigger'), +(13, 2, 49308, 0, 0, 31, 0, 3, 26693, 0, 0, 0, 0, '', 'Gauntlet Reset Check - Target Skadi'); + +-- Update condition for harpoon launcher spell (48641) to target trigger NPC (TC) +UPDATE `conditions` SET `ConditionValue2` = 19871 WHERE `SourceTypeOrReferenceId` = 13 AND `SourceGroup` = 1 AND `SourceEntry` = 48641; + +-- Spawn World Trigger (Not Immune NPC) near harpoon launchers (from TC TDB335) +DELETE FROM `creature` WHERE `guid` BETWEEN 5300675 AND 5300678 AND `id1` = 19871; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES +(5300675, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 389.929, -439.88, 83.0081, 2.79273, 300, 5, 0, 0, 0, 1, 0, 0, 0, '', NULL, 0, NULL), +(5300676, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 490.516, -508.443, 107.042, 5.65487, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300677, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 487.632, -517.329, 106.799, 5.55015, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300678, 19871, 0, 0, 575, 0, 0, 3, 1, 0, 480.202, -523.332, 107.042, 5.46288, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL); + +-- Skadi teleport destination (phase 2 transition) +DELETE FROM `spell_target_position` WHERE `ID` = 61790; +INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES +(61790, 0, 575, 476.799, -511.167, 104.723, 3.14159, 0); + +-- Gauntlet area aura +DELETE FROM `spell_area` WHERE `spell` = 47546; +INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +(47546, 1196, 0, 0, 0, 0, 0, 1, 64, 11); + +-- Disable LoS for Gauntlet Reset Check +DELETE FROM `disables` WHERE `sourceType` = 0 AND `entry` = 49308; +INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES +(0, 49308, 64, 0, 0, 'Disable LoS for spell Utgarde Pinnacle Reset Check'); + +-- Launch Harpoon ignore armor +DELETE FROM `spell_custom_attr` WHERE `spell_id` = 48642; +INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES +(48642, 32768); + +-- Missing spell difficulty entries +DELETE FROM `spelldifficulty_dbc` WHERE `ID` IN (50228, 50258, 49084, 49089, 49091); +INSERT INTO `spelldifficulty_dbc` (`ID`, `DifficultySpellID_1`, `DifficultySpellID_2`, `DifficultySpellID_3`, `DifficultySpellID_4`) VALUES +(49084, 49084, 59246, 0, 0), +(49089, 49089, 59247, 0, 0), +(49091, 49091, 59249, 0, 0), +(50228, 50228, 59322, 0, 0), +(50258, 50258, 59334, 0, 0); + +-- Spawn Freezing Cloud Breath Triggers along the Skadi gauntlet corridor (ported from TrinityCore TDB335) +DELETE FROM `creature` WHERE `guid` BETWEEN 5300600 AND 5300674 AND `id1` = 28351; +INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES +(5300600, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 483.221, -507.151, 104.806, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300601, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 474.404, -507.532, 104.807, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300602, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 473.898, -515.257, 104.806, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300603, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 477.645, -492.175, 104.82, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300604, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 477.021, -520.94, 104.806, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300605, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 425.011, -510.068, 104.832, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300606, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 430.051, -510.1, 104.944, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300607, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 434.669, -510.101, 104.983, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300608, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 440.11, -510.148, 104.97, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300609, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 445.131, -509.703, 104.831, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300610, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 450.289, -509.936, 104.705, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300611, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 455, -509.52, 104.757, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300612, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 460, -509.52, 104.757, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300613, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 465.341, -508.352, 104.438, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300614, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 470.032, -507.361, 104.807, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300615, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 489.557, -514.06, 105.487, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300616, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 482.133, -519.963, 104.806, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300617, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 325, -506.384, 104.419, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300618, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 330, -506.406, 104.434, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300619, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 335.192, -506.95, 105.056, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300620, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 339.973, -507.026, 104.669, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300621, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 344.931, -507.345, 104.592, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300622, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 349.864, -507.751, 104.655, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300623, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 354.289, -507.828, 104.759, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300624, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 359.405, -508.154, 104.871, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300625, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 364.746, -508.335, 104.896, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300626, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 370.505, -508.554, 104.898, 6.23082, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300627, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 374.827, -515.69, 104.877, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300628, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 379.7, -515.287, 104.841, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300629, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 384.809, -514.81, 104.812, 0.017453, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300630, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 390.011, -513.91, 104.811, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300631, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 394.974, -514.631, 104.808, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300632, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 399.738, -514.939, 104.809, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300633, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 404.576, -515.878, 104.827, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300634, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 409.497, -516.404, 105.045, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300635, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 415.076, -516.494, 105.342, 0.017453, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300636, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 420.109, -517.266, 105.089, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300637, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 488.181, -506.897, 104.806, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300638, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 477.551, -499.34, 104.81, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300639, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 485.686, -500.599, 104.806, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300640, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 471.163, -499.268, 104.81, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300641, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 478.264, -514.318, 104.806, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300642, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 483.638, -513.85, 104.806, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300643, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 471.796, -521.457, 104.806, 0.174533, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300644, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 424.786, -517.297, 105.033, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300645, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 429.779, -517.261, 105.039, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300646, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 434.894, -517.11, 105.029, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300647, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 439.402, -517.239, 105.008, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300648, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 444.91, -517.682, 104.947, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300649, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 450.614, -517.208, 104.903, 0.05236, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300650, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 455.604, -517.101, 104.832, 0.05236, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300651, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 460.245, -516.405, 104.679, 0.05236, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300652, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 465.499, -515.925, 104.59, 0.069813, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300653, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 470, -515.214, 105.112, 0.069813, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300654, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 375, -508.566, 104.878, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300655, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 380, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300656, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 385, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300657, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 390, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300658, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 395, -508.366, 104.876, 6.26573, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300659, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 400, -508.366, 104.876, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300660, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 405.287, -508.99, 105.087, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300661, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 409.909, -508.887, 105.106, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300662, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 415.074, -509.304, 105.271, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300663, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 420.093, -509.834, 104.897, 6.24828, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300664, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 478.792, -507.378, 104.806, 0.034907, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300665, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 324.531, -514.289, 104.761, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300666, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 329.63, -514.616, 104.712, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300667, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 334.909, -514.734, 104.623, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300668, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 339.554, -514.984, 104.61, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300669, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 344.693, -515.33, 104.573, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300670, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 349.831, -515.439, 104.556, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300671, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 354.77, -515.736, 104.57, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300672, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 359.338, -515.586, 104.638, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300673, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 364.401, -515.771, 104.757, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL), +(5300674, 28351, 0, 0, 575, 0, 0, 3, 1, 0, 369.849, -515.944, 104.886, 0, 300, 0, 0, 0, 0, 0, 0, 0, 0, '', NULL, 0, NULL); + +-- Grauf waypoint paths (ported from TrinityCore TDB335) +SET @PATH := 2689300; +DELETE FROM `waypoint_data` WHERE `id` IN (@PATH, @PATH+1, @PATH+2); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +-- Initial path (takeoff to breach) +(@PATH, 0, 310.2165, -510.5302, 120.5487, 0, 0, 2, 0, 100, 0), +(@PATH, 1, 300.8685, -520.3249, 133.3664, 0, 0, 2, 0, 100, 0), +(@PATH, 2, 298.3447, -529.4818, 137.2831, 0, 0, 2, 0, 100, 0), +(@PATH, 3, 309.0959, -540.3195, 134.9774, 0, 0, 2, 0, 100, 0), +(@PATH, 4, 323.6415, -547.9715, 130.3106, 0, 0, 2, 0, 100, 0), +(@PATH, 5, 357.078, -549.1597, 116.3105, 0, 0, 2, 0, 100, 0), +(@PATH, 6, 401.2573, -550.2768, 114.9216, 0, 0, 2, 0, 100, 0), +(@PATH, 7, 464.5062, -555.9442, 114.4494, 0, 0, 2, 0, 100, 0), +(@PATH, 8, 496.192, -556.9628, 114.8661, 0, 0, 2, 0, 100, 0), +(@PATH, 9, 523.2011, -548.9916, 114.8661, 0, 0, 2, 0, 100, 0), +-- Right path (breach to right end and back) +(@PATH+1, 0, 453.1242, -517.17, 120.0273, 0, 0, 2, 0, 100, 0), +(@PATH+1, 1, 388.3312, -514.3768, 121.1193, 0, 0, 2, 0, 100, 0), +(@PATH+1, 2, 340.2752, -512.0926, 122.3138, 0, 0, 2, 0, 100, 0), +(@PATH+1, 3, 313.0756, -509.138, 125.175, 0, 0, 2, 0, 100, 0), +(@PATH+1, 4, 296.6964, -522.6705, 133.7026, 0, 0, 2, 0, 100, 0), +(@PATH+1, 5, 301.2957, -549.4583, 137.4249, 0, 0, 2, 0, 100, 0), +(@PATH+1, 6, 335.0746, -552.1211, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+1, 7, 397.6237, -553.9203, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+1, 8, 459.6321, -558.0078, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+1, 9, 505.5458, -568.7815, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+1, 10, 518.099, -560.8499, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+1, 11, 520.4827, -541.5633, 119.8416, 0, 0, 2, 0, 100, 0), +-- Left path (breach to left end and back) +(@PATH+2, 0, 451.9824, -509.2508, 120.0273, 0, 0, 2, 0, 100, 0), +(@PATH+2, 1, 399.2607, -510.0719, 121.1193, 0, 0, 2, 0, 100, 0), +(@PATH+2, 2, 350.6099, -508.3901, 122.3138, 0, 0, 2, 0, 100, 0), +(@PATH+2, 3, 325.8217, -506.7769, 125.175, 0, 0, 2, 0, 100, 0), +(@PATH+2, 4, 301.2941, -516.6706, 133.7026, 0, 0, 2, 0, 100, 0), +(@PATH+2, 5, 301.2957, -549.4583, 137.4249, 0, 0, 2, 0, 100, 0), +(@PATH+2, 6, 335.0746, -552.1211, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+2, 7, 397.6237, -553.9203, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+2, 8, 459.6321, -558.0078, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+2, 9, 505.5458, -568.7815, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+2, 10, 518.099, -560.8499, 119.8416, 0, 0, 2, 0, 100, 0), +(@PATH+2, 11, 520.4827, -541.5633, 119.8416, 0, 0, 2, 0, 100, 0); diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index d19308e56..f5d1d83e2 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -1695,12 +1695,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[0].TargetB = SpellImplicitTargetInfo(); }); - // Flame Breath - ApplySpellFix({ 47592 }, [](SpellInfo* spellInfo) - { - spellInfo->Effects[EFFECT_0].Amplitude = 200; - }); - // Skarvald, Charge ApplySpellFix({ 43651 }, [](SpellInfo* spellInfo) { diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index efa101f38..c983d83a0 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -17,91 +17,129 @@ #include "CombatAI.h" #include "CreatureScript.h" -#include "GameObjectScript.h" +#include "GridNotifiers.h" #include "Player.h" #include "ScriptedCreature.h" -#include "SpellInfo.h" +#include "SpellAuras.h" +#include "SpellScript.h" +#include "SpellScriptLoader.h" #include "Vehicle.h" #include "utgarde_pinnacle.h" -enum Misc +enum Spells +{ + // Skadi + SPELL_CRUSH = 50234, + SPELL_POISONED_SPEAR = 50255, + SPELL_POISONED_SPEAR_PERIODIC = 50258, + SPELL_WHIRLWIND = 50228, + SPELL_LAUNCH_HARPOON = 48642, + SPELL_SKADI_TELEPORT = 61790, + + // Grauf + SPELL_FREEZING_CLOUD = 47579, + SPELL_FREEZING_CLOUD_RIGHT_PERIODIC = 47592, + SPELL_FREEZING_CLOUD_LEFT_PERIODIC = 47590, + SPELL_FREEZING_CLOUD_RIGHT_AREA = 47594, + SPELL_FREEZING_CLOUD_LEFT_AREA = 47574, + + // Gauntlet + SPELL_SUMMON_GAUNTLET_MOBS_PERIODIC = 59275, + SPELL_SUMMON_YMIRJAR_WARRIOR_W = 48631, + SPELL_SUMMON_YMIRJAR_WARRIOR_E = 48632, + SPELL_SUMMON_YMIRJAR_HARPOONER_W = 48633, + SPELL_SUMMON_YMIRJAR_HARPOONER_E = 48634, + SPELL_SUMMON_YMIRJAR_WITCH_DOCTOR_W = 48635, + SPELL_SUMMON_YMIRJAR_WITCH_DOCTOR_E = 48636, + SPELL_GAUNTLET_RESET_CHECK = 49308, + SPELL_GAUNTLET_EFFECT = 47547, +}; + +enum Texts { - // TEXTS SAY_AGGRO = 0, SAY_KILL = 1, SAY_DEATH = 3, SAY_DRAKE_DEATH = 5, SAY_DRAKE_BREATH = 6, - - // EMOTES EMOTE_DEEP_BREATH = 0, - EMOTE_RANGE = 1, - - // SPELLS - SPELL_CRUSH = 50234, - SPELL_POISONED_SPEAR = 50255, - SPELL_WHIRLWIND = 50228, - - SPELL_FREEZING_CLOUD_VISUAL = 47592, - SPELL_FREEZING_CLOUD = 47579, - - SPELL_LAUNCH_HARPOON = 48642, - - // NPCS - NPC_YMIRJAR_WARRIOR = 26690, - NPC_YMIRJAR_WITCH_DOCTOR = 26691, - NPC_YMIRJAR_HARPOONER = 26692, - NPC_GRAUF = 26893, - NPC_BREATH_TRIGGER = 28351, - EQUIP_MACE = 17193, - - // ACTIONS - ACTION_START_EVENT = 1, - ACTION_REMOVE_SKADI = 2, - ACTION_PHASE2 = 3, - ACTION_MYGIRL_ACHIEVEMENT = 4, - - // ACHIEVEMENTS - ACHIEV_TIMED_LODI_DODI = 17726, + EMOTE_ON_RANGE = 1, }; +enum Actions +{ + ACTION_START_ENCOUNTER = 1, + ACTION_DRAKE_BREATH = 2, + ACTION_PHASE2 = 3, + ACTION_HARPOON_HIT = 4, +}; + +enum CombatPhase +{ + PHASE_FLYING = 0, + PHASE_GROUND +}; + +enum MiscData +{ + NPC_GRAUF = 26893, + NPC_TRIGGER_RESET = 23472, + NPC_WORLD_TRIGGER = 22515, + NPC_COMBAT_TRIGGER = 38667, + + ACHIEV_TIMED_LODI_DODI = 17726, + + FIRST_WAVE_MAX_WARRIORS = 10, + FIRST_WAVE_SIZE = 13, +}; + +Position const GraufLoc = { 341.741f, -516.955f, 104.670f, 3.12414f }; +Position const SpawnLoc = { 477.581f, -484.559f, 104.822f, 4.67748f }; + +Position const FirstWaveLocations[FIRST_WAVE_SIZE] = +{ + { 458.532f, -516.254f, 104.617f }, + { 429.424f, -517.562f, 104.894f }, + { 394.496f, -514.614f, 104.724f }, + { 362.286f, -515.877f, 104.754f }, + { 333.537f, -514.794f, 104.478f }, + { 457.611f, -508.836f, 104.401f }, + { 427.403f, -510.772f, 104.880f }, + { 392.511f, -507.943f, 104.743f }, + { 362.951f, -508.412f, 104.722f }, + { 333.536f, -506.081f, 104.426f }, + { 478.310f, -511.049f, 104.724f, 3.26377f }, + { 482.250f, -514.127f, 104.723f, 3.26377f }, + { 481.388f, -507.109f, 104.724f, 3.26377f }, +}; + +Position const SecondaryWavesInitialPoint = { 478.743f, -505.576f, 104.724f }; + +enum GraufPoints +{ + POINT_BREACH = 0, + POINT_LEFT = 1, + POINT_RIGHT = 2, +}; + +uint32 const PATH_INITIAL = 2689300; +uint32 const PATH_RIGHT = 2689301; +uint32 const PATH_LEFT = 2689302; + +float const BreachFacing = 2.670354f; + enum Events { - // SKADI - EVENT_SKADI_START = 1, - EVENT_SKADI_CRUSH = 2, - EVENT_SKADI_SPEAR = 3, - EVENT_SKADI_WHIRLWIND = 4, + // Skadi + EVENT_SKADI_CRUSH = 1, + EVENT_SKADI_SPEAR = 2, + EVENT_SKADI_WHIRLWIND = 3, + EVENT_SKADI_RESET_CHECK = 4, - // GRAUF + // Grauf EVENT_GRAUF_START = 10, - EVENT_GRAUF_MOVE = 11, - EVENT_GRAUF_SUMMON_HELPERS = 12, - EVENT_GRAUF_CHECK = 13, - EVENT_GRAUF_REMOVE_SKADI = 14, -}; - -static Position TrashPosition[] = -{ - {441.236f, -512.000f, 104.930f, 0.0f}, - {478.436f, -494.475f, 104.730f, 0.0f} -}; - -static Position SkadiPosition[] = -{ - {338.679f, -507.254f, 124.122f, 0.0f}, - {338.679f, -513.254f, 124.122f, 0.0f}, - {490.096f, -510.86f, 123.368f, 0.0f}, - {490.76f, -517.389f, 123.368f, 0.0f} -}; - -enum phase -{ - PHASE_NONE, - PHASE_START, - PHASE_FLIGHT, - PHASE_LAND, - PHASE_GROUND + EVENT_GRAUF_LEAVE_BREACH = 11, + EVENT_GRAUF_REMOVE_AURA = 13, }; class boss_skadi : public CreatureScript @@ -109,155 +147,237 @@ class boss_skadi : public CreatureScript public: boss_skadi() : CreatureScript("boss_skadi") { } - CreatureAI* GetAI(Creature* pCreature) const override + CreatureAI* GetAI(Creature* creature) const override { - return GetUtgardePinnacleAI(pCreature); + return GetUtgardePinnacleAI(creature); } struct boss_skadiAI : public ScriptedAI { - boss_skadiAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) + boss_skadiAI(Creature* creature) : ScriptedAI(creature), _summons(me) { - m_pInstance = pCreature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } - InstanceScript* m_pInstance; - EventMap events; - SummonList summons; - ObjectGuid GraufGUID; - bool SecondPhase, EventStarted; - void Reset() override { - events.Reset(); - summons.DespawnAll(); - if (Creature* cr = me->SummonCreature(NPC_GRAUF, 341.741f, -516.955f, 116.669f, 3.12414f)) - { - GraufGUID = cr->GetGUID(); - summons.Summon(cr); - } - SecondPhase = false; - EventStarted = false; + _events.Reset(); + _summons.DespawnAll(); + _phase = PHASE_GROUND; + _harpoonHit = 0; + _loveSkadi = 0; + _firstWaveSummoned = false; + _encounterStarted = false; + me->SetReactState(REACT_PASSIVE); me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetImmuneToPC(false); - if (m_pInstance) + if (_instance) { - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_LODI_DODI); - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS, NOT_STARTED); - m_pInstance->SetData(SKADI_IN_RANGE, 0); - m_pInstance->SetData(SKADI_HITS, 0); - m_pInstance->SetData(DATA_SKADI_ACHIEVEMENT, false); + _instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_LODI_DODI); + _instance->SetData(DATA_SKADI_THE_RUTHLESS, NOT_STARTED); + _instance->SetData(DATA_SKADI_ACHIEVEMENT, false); } + + if (!_instance || !_instance->GetCreature(DATA_GRAUF)) + if (Creature* grauf = me->SummonCreature(NPC_GRAUF, GraufLoc)) + _summons.Summon(grauf); } - Creature* GetGrauf() { return ObjectAccessor::GetCreature(*me, GraufGUID); } + void JustSummoned(Creature* summon) override + { + switch (summon->GetEntry()) + { + case NPC_YMIRJAR_WARRIOR: + case NPC_YMIRJAR_WITCH_DOCTOR: + case NPC_YMIRJAR_HARPOONER: + if (_firstWaveSummoned) + summon->GetMotionMaster()->MovePoint(1, SecondaryWavesInitialPoint); + break; + default: + break; + } + _summons.Summon(summon); + } + + void SpawnFirstWave() + { + for (uint8 i = 0; i < FIRST_WAVE_MAX_WARRIORS; ++i) + if (Creature* summon = me->SummonCreature(NPC_YMIRJAR_WARRIOR, SpawnLoc, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) + summon->GetMotionMaster()->MovePoint(0, FirstWaveLocations[i]); + + if (Creature* crea = me->SummonCreature(NPC_YMIRJAR_WITCH_DOCTOR, SpawnLoc, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) + crea->GetMotionMaster()->MovePoint(0, FirstWaveLocations[10]); + if (Creature* crea = me->SummonCreature(NPC_YMIRJAR_HARPOONER, SpawnLoc, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) + crea->GetMotionMaster()->MovePoint(0, FirstWaveLocations[11]); + if (Creature* crea = me->SummonCreature(NPC_YMIRJAR_HARPOONER, SpawnLoc, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) + crea->GetMotionMaster()->MovePoint(0, FirstWaveLocations[12]); + + _firstWaveSummoned = true; + } + + void JustEngagedWith(Unit* /*who*/) override + { + DoAction(ACTION_START_ENCOUNTER); + } void DoAction(int32 param) override { - if (param == ACTION_START_EVENT) + switch (param) { - if (!EventStarted) - { - EventStarted = true; + case ACTION_START_ENCOUNTER: + if (_encounterStarted) + return; + + _encounterStarted = true; + _phase = PHASE_FLYING; Talk(SAY_AGGRO); - if (m_pInstance) + + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->setActive(true); + + SpawnFirstWave(); + + if (_instance) { if (IsHeroic()) - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_LODI_DODI); - - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS, IN_PROGRESS); + _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_LODI_DODI); + _instance->SetData(DATA_SKADI_THE_RUTHLESS, IN_PROGRESS); } - me->SetControlled(true, UNIT_STATE_ROOT); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - events.RescheduleEvent(EVENT_SKADI_START, 2s); - } - } - else if (param == ACTION_PHASE2) - { - SecondPhase = true; - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_SKADI_CRUSH, 8s); - events.ScheduleEvent(EVENT_SKADI_SPEAR, 10s); - events.ScheduleEvent(EVENT_SKADI_WHIRLWIND, 15s); + if (Creature* summonTrigger = me->SummonCreature(NPC_WORLD_TRIGGER, SpawnLoc)) + summonTrigger->CastSpell(summonTrigger, SPELL_SUMMON_GAUNTLET_MOBS_PERIODIC, true); - if (me->GetVictim()) - me->ResumeChasingVictim(); - else - me->SetInCombatWithZone(); + if (Creature* combatTrigger = me->SummonCreature(NPC_COMBAT_TRIGGER, SpawnLoc)) + combatTrigger->AI()->DoZoneInCombat(); + + _events.ScheduleEvent(EVENT_GRAUF_START, 2s); + _events.ScheduleEvent(EVENT_SKADI_RESET_CHECK, 6s); + break; + case ACTION_DRAKE_BREATH: + if (_loveSkadi == 1) + ++_loveSkadi; + Talk(SAY_DRAKE_BREATH); + break; + case ACTION_PHASE2: + Talk(SAY_DRAKE_DEATH); + DoCastSelf(SPELL_SKADI_TELEPORT); + _summons.DespawnEntry(NPC_WORLD_TRIGGER); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); + _phase = PHASE_GROUND; + + _events.ScheduleEvent(EVENT_SKADI_CRUSH, 8s); + _events.ScheduleEvent(EVENT_SKADI_SPEAR, 11s); + _events.ScheduleEvent(EVENT_SKADI_WHIRLWIND, 23s); + break; + case ACTION_HARPOON_HIT: + ++_harpoonHit; + if (_harpoonHit == 1) + _loveSkadi = 1; + break; } } + uint32 GetData(uint32 id) const override + { + if (id == DATA_LOVE_TO_SKADI) + return _loveSkadi; + return 0; + } + void UpdateAI(uint32 diff) override { - if (!UpdateVictim() && SecondPhase) - return; + _events.Update(diff); - events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + if (_phase == PHASE_FLYING) { - case EVENT_SKADI_START: + switch (_events.ExecuteEvent()) + { + case EVENT_GRAUF_START: { - me->SetControlled(false, UNIT_STATE_ROOT); - if (Creature* cr = GetGrauf()) + if (Creature* grauf = _instance->GetCreature(DATA_GRAUF)) { - me->EnterVehicleUnattackable(cr, 0); - cr->AI()->DoAction(ACTION_START_EVENT); + me->EnterVehicleUnattackable(grauf, 0); + grauf->AI()->DoAction(ACTION_START_ENCOUNTER); } else EnterEvadeMode(); - break; } + case EVENT_SKADI_RESET_CHECK: + { + if (Creature* resetTrigger = me->FindNearestCreature(NPC_TRIGGER_RESET, 200.0f)) + resetTrigger->CastSpell(resetTrigger, SPELL_GAUNTLET_RESET_CHECK, true); + _events.Repeat(6s); + break; + } + } + return; + } + + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (_events.ExecuteEvent()) + { case EVENT_SKADI_CRUSH: - { - me->CastSpell(me->GetVictim(), SPELL_CRUSH, false); - events.Repeat(8s); - break; - } + DoCastVictim(SPELL_CRUSH); + _events.Repeat(8s); + break; case EVENT_SKADI_SPEAR: - { - if (Unit* tgt = SelectTarget(SelectTargetMethod::Random, 0)) - me->CastSpell(tgt, SPELL_POISONED_SPEAR, false); - - events.Repeat(10s); - break; - } + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0)) + DoCast(target, SPELL_POISONED_SPEAR); + _events.Repeat(10s); + break; case EVENT_SKADI_WHIRLWIND: - { - me->CastSpell(me, SPELL_WHIRLWIND, false); - events.Repeat(15s, 20s); - events.DelayEvents(10s); - break; - } + DoCast(me, SPELL_WHIRLWIND); + _events.Repeat(15s, 20s); + _events.DelayEvents(10s); + break; } DoMeleeAttackIfReady(); } - void JustDied(Unit* /*pKiller*/) override + void JustDied(Unit* /*killer*/) override { - summons.DespawnAll(); + _summons.DespawnAll(); Talk(SAY_DEATH); - if (m_pInstance) + if (_instance) { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS, DONE); - m_pInstance->HandleGameObject(m_pInstance->GetGuidData(SKADI_DOOR), true); + _instance->SetData(DATA_SKADI_THE_RUTHLESS, DONE); + _instance->HandleGameObject(_instance->GetGuidData(SKADI_DOOR), true); } } - void KilledUnit(Unit* /*pVictim*/) override + void KilledUnit(Unit* who) override { - if (urand(0, 1)) - return; - - Talk(SAY_KILL); + if (who->IsPlayer()) + Talk(SAY_KILL); } + + void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override + { + _summons.DespawnAll(); + ScriptedAI::EnterEvadeMode(); + } + + private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + CombatPhase _phase; + uint8 _harpoonHit; + uint8 _loveSkadi; + bool _firstWaveSummoned; + bool _encounterStarted; }; }; @@ -266,263 +386,324 @@ class boss_skadi_grauf : public CreatureScript public: boss_skadi_grauf() : CreatureScript("boss_skadi_grauf") { } - CreatureAI* GetAI(Creature* pCreature) const override + CreatureAI* GetAI(Creature* creature) const override { - return GetUtgardePinnacleAI(pCreature); + return GetUtgardePinnacleAI(creature); } struct boss_skadi_graufAI : public VehicleAI { - boss_skadi_graufAI(Creature* pCreature) : VehicleAI(pCreature), summons(me) + boss_skadi_graufAI(Creature* creature) : VehicleAI(creature), _summons(me) { - m_pInstance = pCreature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } - InstanceScript* m_pInstance; - EventMap events; - SummonList summons; - uint8 currentPos; - uint8 AchievementHitCount; - void Reset() override { - events.Reset(); - summons.DespawnAll(); - currentPos = 0; - AchievementHitCount = 0; - me->RemoveAllAuras(); + _events.Reset(); + _summons.DespawnAll(); + me->SetReactState(REACT_PASSIVE); + me->SetSpeedRate(MOVE_RUN, 2.5f); } void DoAction(int32 param) override { - if (param == ACTION_START_EVENT) + if (param == ACTION_START_ENCOUNTER) { - events.RescheduleEvent(EVENT_GRAUF_CHECK, 5s); - events.RescheduleEvent(EVENT_GRAUF_START, 2s); - } - else if (param == ACTION_REMOVE_SKADI) - { - if (Unit* passenger = me->GetVehicleKit()->GetPassenger(0)) - if (Creature* skadi = passenger->ToCreature()) - skadi->AI()->Talk(SAY_DRAKE_DEATH); - me->GetMotionMaster()->MovePoint(10, 480.0f, -513.0f, 108.0f); - events.ScheduleEvent(EVENT_GRAUF_REMOVE_SKADI, 2s); - } - else if (param == ACTION_MYGIRL_ACHIEVEMENT) - { - AchievementHitCount++; - if (AchievementHitCount >= 3 && m_pInstance) - m_pInstance->SetData(DATA_SKADI_ACHIEVEMENT, true); + me->setActive(true); + me->SetCanFly(true); + me->SetDisableGravity(true); + me->GetMotionMaster()->Clear(true); + me->SetAnimTier(AnimTier::Fly); + me->GetMotionMaster()->MovePath(PATH_INITIAL, FORCED_MOVEMENT_RUN); } } - void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override { - if (spellInfo->Id == 47593) // SPELL_FREEZING_CLOUD_VISUAL trigger - target->CastSpell(target, SPELL_FREEZING_CLOUD, true); + if (spellInfo->Id == SPELL_LAUNCH_HARPOON) + if (Creature* skadi = _instance->GetCreature(DATA_SKADI_THE_RUTHLESS)) + skadi->AI()->DoAction(ACTION_HARPOON_HIT); } - void SpawnFlameTriggers(uint8 point) + void MovementInform(uint32 type, uint32 /*id*/) override { - for(uint8 j = 0; j < 50; ++j) + if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized()) { - if (point == 1) - me->SummonCreature(NPC_BREATH_TRIGGER, 480.0f - (j * 3), -518.0f + (j / 16.0f), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); - else - me->SummonCreature(NPC_BREATH_TRIGGER, 480.0f - (j * 3), -510.0f + (j / 16.0f), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); - } - // and out of loop, cover the small room - if (point == 0) - { - Creature* cr; - if ((cr = me->SummonCreature(NPC_BREATH_TRIGGER, 483, -484.9f, 105, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))) - cr->CastSpell(cr, SPELL_FREEZING_CLOUD, true); - if ((cr = me->SummonCreature(NPC_BREATH_TRIGGER, 471.0f, -484.7f, 105, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))) - cr->CastSpell(cr, SPELL_FREEZING_CLOUD, true); - - for (uint8 j = 0; j < 7; j++) - if ((cr = me->SummonCreature(NPC_BREATH_TRIGGER, 477.0f, -507.0f + (j * 3), 105.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))) - cr->CastSpell(cr, SPELL_FREEZING_CLOUD, true); - } - } - - void MovementInform(uint32 /*uiType*/, uint32 Id) override - { - switch (Id) - { - case 0: - case 1: - me->RemoveAurasDueToSpell(SPELL_FREEZING_CLOUD_VISUAL); - me->SetFacingTo(M_PI * 2); - break; - case 2: - case 3: - if (m_pInstance) - m_pInstance->SetData(SKADI_IN_RANGE, 1); - Talk(EMOTE_RANGE); - me->SetFacingTo(M_PI); - break; - } - } - - uint8 SelectNextPos(uint8 Position) - { - switch (Position) - { - case 0: - case 1: - return 2 + urand(0, 1); - default: - if (me->GetPositionY() < -515.0f) - return 1; - else - return 0; - } - } - - void JustEngagedWith(Unit*) override - { - me->SetInCombatWithZone(); - } - - void RemoveSkadi(bool withEvade) - { - if (Unit* skadi = me->GetVehicleKit()->GetPassenger(0)) - { - summons.DespawnAll(); - skadi->ExitVehicle(); - if (withEvade) - { - skadi->ToCreature()->AI()->EnterEvadeMode(); - skadi->UpdatePosition(343.02f, -507.325f, 104.567f, M_PI, true); - } - else - skadi->ToCreature()->AI()->DoAction(ACTION_PHASE2); - - skadi->StopMovingOnCurrentPos(); - } - } - - void CheckPlayers() - { - Map::PlayerList const& pList = me->GetMap()->GetPlayers(); - for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr) - { - if (itr->GetSource()->GetPositionY() > -490.0f || itr->GetSource()->IsGameMaster() || !itr->GetSource()->IsAlive()) - continue; - - return; - } - - RemoveSkadi(true); - } - - void SpawnHelpers(uint8 Spot) - { - if (Creature* Harpooner = me->SummonCreature(NPC_YMIRJAR_HARPOONER, TrashPosition[Spot].GetPositionX() + rand() % 5, TrashPosition[Spot].GetPositionY() + rand() % 5, TrashPosition[Spot].GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - Harpooner->SetInCombatWithZone(); - summons.Summon(Harpooner); - } - if (Creature* Second = me->SummonCreature((urand(0, 1) ? NPC_YMIRJAR_WARRIOR : NPC_YMIRJAR_WITCH_DOCTOR), TrashPosition[Spot].GetPositionX() + rand() % 5, TrashPosition[Spot].GetPositionY() + rand() % 5, TrashPosition[Spot].GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - Second->SetInCombatWithZone(); - summons.Summon(Second); + me->SetFacingTo(BreachFacing); + Talk(EMOTE_ON_RANGE); + _events.ScheduleEvent(EVENT_GRAUF_LEAVE_BREACH, 10s); } } void UpdateAI(uint32 diff) override { - events.Update(diff); - switch (events.ExecuteEvent()) + _events.Update(diff); + switch (_events.ExecuteEvent()) { - case EVENT_GRAUF_CHECK: - { - CheckPlayers(); - events.Repeat(2s); - break; - } - case EVENT_GRAUF_START: - { - me->GetMotionMaster()->Clear(true); - me->GetMotionMaster()->MoveTakeoff(10, SkadiPosition[0].GetPositionX(), SkadiPosition[0].GetPositionY(), SkadiPosition[0].GetPositionZ(), 3.0f); + case EVENT_GRAUF_LEAVE_BREACH: + _lastSide = RAND(POINT_LEFT, POINT_RIGHT); + me->GetMotionMaster()->MovePath(_lastSide == POINT_LEFT ? PATH_LEFT : PATH_RIGHT, FORCED_MOVEMENT_RUN); - SpawnHelpers(0); - SpawnHelpers(0); - events.ScheduleEvent(EVENT_GRAUF_MOVE, 5s); - events.ScheduleEvent(EVENT_GRAUF_SUMMON_HELPERS, 20s); - break; - } - case EVENT_GRAUF_MOVE: - { - AchievementHitCount = 0; - uint8 targetPoint = SelectNextPos(currentPos); - me->GetMotionMaster()->MovePoint(targetPoint, SkadiPosition[targetPoint].GetPositionX(), SkadiPosition[targetPoint].GetPositionY(), SkadiPosition[targetPoint].GetPositionZ()); - if (targetPoint <= 1) - { - Talk(EMOTE_DEEP_BREATH); - SpawnFlameTriggers(targetPoint); - me->CastSpell(me, SPELL_FREEZING_CLOUD_VISUAL, false); - } + if (_lastSide == POINT_LEFT) + DoCast(me, SPELL_FREEZING_CLOUD_LEFT_PERIODIC); + else + DoCast(me, SPELL_FREEZING_CLOUD_RIGHT_PERIODIC); - if (m_pInstance) - m_pInstance->SetData(SKADI_IN_RANGE, 0); + if (Creature* skadi = _instance->GetCreature(DATA_SKADI_THE_RUTHLESS)) + skadi->AI()->DoAction(ACTION_DRAKE_BREATH); - currentPos = targetPoint; - events.Repeat(25s); - break; - } - case EVENT_GRAUF_SUMMON_HELPERS: - { - SpawnHelpers(1); - events.Repeat(15s); - break; - } - case EVENT_GRAUF_REMOVE_SKADI: - { - RemoveSkadi(false); - me->DespawnOrUnsummon(); - break; - } + _events.ScheduleEvent(EVENT_GRAUF_REMOVE_AURA, 10s); + break; + case EVENT_GRAUF_REMOVE_AURA: + me->RemoveAurasDueToSpell(SPELL_FREEZING_CLOUD_LEFT_PERIODIC); + me->RemoveAurasDueToSpell(SPELL_FREEZING_CLOUD_RIGHT_PERIODIC); + break; } } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* skadi = _instance->GetCreature(DATA_SKADI_THE_RUTHLESS)) + { + skadi->ExitVehicle(); + skadi->AI()->DoAction(ACTION_PHASE2); + + if (skadi->AI()->GetData(DATA_LOVE_TO_SKADI) == 1) + _instance->SetData(DATA_SKADI_ACHIEVEMENT, true); + } + me->DespawnOrUnsummon(6s); + } + + private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + uint8 _lastSide = POINT_LEFT; }; }; -class go_harpoon_canon : public GameObjectScript +// 48642 - Launch Harpoon +class spell_skadi_launch_harpoon : public SpellScript { -public: - go_harpoon_canon() : GameObjectScript("go_harpoon_canon") { } + PrepareSpellScript(spell_skadi_launch_harpoon); - bool OnGossipHello(Player* pPlayer, GameObject* go) override + void FilterTargets(std::list& targets) { - InstanceScript* m_pInstance = go->GetInstanceScript(); - if (m_pInstance && m_pInstance->GetData(DATA_SKADI_THE_RUTHLESS) == IN_PROGRESS) - if (m_pInstance->GetData(SKADI_IN_RANGE) == 1) - { - uint8 count = m_pInstance->GetData(SKADI_HITS) + 1; - m_pInstance->SetData(SKADI_HITS, count); + if (targets.size() >= 2) + targets.remove_if([](WorldObject* obj) { return obj->GetEntry() != NPC_GRAUF; }); + } - if (Creature* grauf = ObjectAccessor::GetCreature(*pPlayer, m_pInstance->GetGuidData(DATA_GRAUF))) - { - if (count >= 3) - { - m_pInstance->SetData(SKADI_IN_RANGE, 0); - grauf->AI()->DoAction(ACTION_REMOVE_SKADI); - } + void HandleDamageCalc() + { + if (Unit* target = GetHitUnit()) + SetHitDamage(target->CountPctFromMaxHealth(35)); + } - grauf->AI()->DoAction(ACTION_MYGIRL_ACHIEVEMENT); - } - go->CastSpell((Unit*)nullptr, SPELL_LAUNCH_HARPOON); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skadi_launch_harpoon::FilterTargets, EFFECT_0, TARGET_UNIT_CONE_ENTRY); + OnHit += SpellHitFn(spell_skadi_launch_harpoon::HandleDamageCalc); + } +}; +// 50255 - Poisoned Spear +class spell_skadi_poisoned_spear : public SpellScript +{ + PrepareSpellScript(spell_skadi_poisoned_spear); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_POISONED_SPEAR_PERIODIC }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_POISONED_SPEAR_PERIODIC, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_skadi_poisoned_spear::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } +}; + +// 47594 - Freezing Cloud (right side) +class spell_freezing_cloud_area_right : public SpellScript +{ + PrepareSpellScript(spell_freezing_cloud_area_right); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_FREEZING_CLOUD }); + } + + void FilterTargets(std::list& targets) + { + targets.remove_if([](WorldObject* obj) { return obj->GetPositionY() > -511.0f; }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FREEZING_CLOUD, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_freezing_cloud_area_right::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_freezing_cloud_area_right::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } +}; + +// 47574 - Freezing Cloud (left side) +class spell_freezing_cloud_area_left : public SpellScript +{ + PrepareSpellScript(spell_freezing_cloud_area_left); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_FREEZING_CLOUD }); + } + + void FilterTargets(std::list& targets) + { + targets.remove_if([](WorldObject* obj) { return obj->GetPositionY() < -511.0f; }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_FREEZING_CLOUD, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_freezing_cloud_area_left::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_freezing_cloud_area_left::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } +}; + +// 47579, 60020 - Freezing Cloud (damage aura) +class spell_freezing_cloud_damage : public AuraScript +{ + PrepareAuraScript(spell_freezing_cloud_damage); + + bool CanBeAppliedOn(Unit* target) + { + if (Aura* aur = target->GetAura(GetId())) + if (aur->GetOwner() != GetOwner()) + return false; return true; } + + void Register() override + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_freezing_cloud_damage::CanBeAppliedOn); + } +}; + +// 59275 - Summon Gauntlet Mobs Periodic +class spell_summon_gauntlet_mobs_periodic : public AuraScript +{ + PrepareAuraScript(spell_summon_gauntlet_mobs_periodic); + + void CastTheNextTwoSpells() + { + for (uint8 i = 0; i < 2; ++i) + { + uint32 spellId = _summonSpells.front(); + GetTarget()->CastSpell((Unit*)nullptr, spellId, true); + _summonSpells.push_back(spellId); + _summonSpells.pop_front(); + } + } + + void PushBackTheNextTwoSpells() + { + for (uint8 j = 0; j < 2; ++j) + { + _summonSpells.push_back(_summonSpells.front()); + _summonSpells.pop_front(); + } + } + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + if (RAND(0, 1)) + { + CastTheNextTwoSpells(); + PushBackTheNextTwoSpells(); + } + else + { + PushBackTheNextTwoSpells(); + CastTheNextTwoSpells(); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_gauntlet_mobs_periodic::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + +private: + std::deque _summonSpells = + { + SPELL_SUMMON_YMIRJAR_WARRIOR_E, + SPELL_SUMMON_YMIRJAR_HARPOONER_W, + SPELL_SUMMON_YMIRJAR_WARRIOR_W, + SPELL_SUMMON_YMIRJAR_HARPOONER_E, + SPELL_SUMMON_YMIRJAR_WARRIOR_W, + SPELL_SUMMON_YMIRJAR_WITCH_DOCTOR_E, + SPELL_SUMMON_YMIRJAR_WARRIOR_E, + SPELL_SUMMON_YMIRJAR_WITCH_DOCTOR_W + }; +}; + +// 49308 - Utgarde Pinnacle Gauntlet Reset Check +class spell_skadi_reset_check : public SpellScript +{ + PrepareSpellScript(spell_skadi_reset_check); + + void CountTargets(std::list& targets) + { + targets.remove_if(Acore::UnitAuraCheck(false, SPELL_GAUNTLET_EFFECT)); + _targetCount = targets.size(); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (_targetCount) + return; + + Creature* target = GetHitCreature(); + if (!target) + return; + + if (InstanceScript* instance = target->GetInstanceScript()) + if (instance->GetData(DATA_SKADI_THE_RUTHLESS) == IN_PROGRESS) + if (Creature* skadi = instance->GetCreature(DATA_SKADI_THE_RUTHLESS)) + skadi->AI()->EnterEvadeMode(); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_skadi_reset_check::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_skadi_reset_check::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + } + +private: + uint32 _targetCount = 0; }; void AddSC_boss_skadi() { new boss_skadi(); new boss_skadi_grauf(); - new go_harpoon_canon(); + RegisterSpellScript(spell_skadi_launch_harpoon); + RegisterSpellScript(spell_skadi_poisoned_spear); + RegisterSpellScript(spell_freezing_cloud_area_left); + RegisterSpellScript(spell_freezing_cloud_area_right); + RegisterSpellScript(spell_freezing_cloud_damage); + RegisterSpellScript(spell_summon_gauntlet_mobs_periodic); + RegisterSpellScript(spell_skadi_reset_check); } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp index cddc964ae..c332fccbd 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp @@ -23,9 +23,18 @@ ObjectData const creatureData[] = { { NPC_SKADI_THE_RUTHLESS, DATA_SKADI_THE_RUTHLESS }, + { NPC_GARUF, DATA_GRAUF }, { 0, 0 } }; +ObjectData const summonData[] = +{ + { NPC_YMIRJAR_WARRIOR, DATA_SKADI_THE_RUTHLESS }, + { NPC_YMIRJAR_WITCH_DOCTOR, DATA_SKADI_THE_RUTHLESS }, + { NPC_YMIRJAR_HARPOONER, DATA_SKADI_THE_RUTHLESS }, + { 0, 0 } +}; + class instance_utgarde_pinnacle : public InstanceMapScript { public: @@ -65,6 +74,7 @@ public: { SetHeaders(DataHeader); LoadObjectData(creatureData, nullptr); + LoadSummonData(summonData); SkadiHits = 0; SkadiInRange = 0; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h index f05387598..cb67ff7e3 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h @@ -49,6 +49,7 @@ enum Data DATA_SVALA_ACHIEVEMENT = 50, DATA_SKADI_ACHIEVEMENT = 51, DATA_YMIRON_ACHIEVEMENT = 52, + DATA_LOVE_TO_SKADI = 53, }; enum Objects @@ -71,6 +72,9 @@ enum Objects NPC_MASSIVE_JORMUNGAR = 26685, NPC_FEROCIOUS_RHINO = 26686, NPC_GARUF = 26893, + NPC_YMIRJAR_WARRIOR = 26690, + NPC_YMIRJAR_WITCH_DOCTOR = 26691, + NPC_YMIRJAR_HARPOONER = 26692, }; template @@ -79,4 +83,6 @@ inline AI* GetUtgardePinnacleAI(T* obj) return GetInstanceAI(obj, UtgardePinnacleScriptName); } +#define RegisterUtgardePinnacleCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetUtgardePinnacleAI) + #endif