diff options
author | Aqua Deus <95978183+aquadeus@users.noreply.github.com> | 2024-09-21 06:29:15 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-21 06:29:15 +0200 |
commit | 52d4e0f9ef054a01680647176dfa20c39ea80b11 (patch) | |
tree | 7b872d6733a216fd50ac246af2d8966a2f535da5 | |
parent | 35b8868763cc46a16511b11a5c735dc534e887dc (diff) |
Scripts/ShrineOfTheStorm: Implement Aqu'sirr encounter (#30122)
Co-authored-by: ModoX <moardox@gmail.com>
6 files changed, 1027 insertions, 0 deletions
diff --git a/sql/updates/world/master/2024_09_21_00_world.sql b/sql/updates/world/master/2024_09_21_00_world.sql new file mode 100644 index 00000000000..1e6ee1f3b11 --- /dev/null +++ b/sql/updates/world/master/2024_09_21_00_world.sql @@ -0,0 +1,120 @@ +SET @ATID := 95; +SEt @ATCP := 83; +SET @ATIDSPAWN := 97; +SET @CGUID := 7001525; +SET @SPAWNGROUP := 1258; + +-- Instance +DELETE FROM `instance_template` WHERE `map`=1864; +INSERT INTO `instance_template` (`map`, `parent`, `script`) VALUES +(1864, 0, 'instance_shrine_of_the_storm'); + +-- Creature +DELETE FROM `creature` WHERE `guid`= @CGUID+0; +DELETE FROM `creature_addon` WHERE `guid`= @CGUID+0; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnDifficulties`, `PhaseId`, `PhaseGroup`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curHealthPct`, `MovementType`, `npcflag`, `unit_flags`, `unit_flags2`, `unit_flags3`, `VerifiedBuild`) VALUES +(@CGUID+0, 134056, 1864, 9525, 9964, '1,2,23,8', 0, 0, 0, 0, 3931.7275390625, -1244.4896240234375, 128.450714111328125, 0.069714099168777465, 7200, 0, 0, 100, 0, NULL, NULL, NULL, NULL, 55664); -- Aqu'sirr (Area: Tidewater Sanctum - Difficulty: Normal) CreateObject2 (Auras: ) + +UPDATE `creature_template_difficulty` SET `ContentTuningID`=500, `StaticFlags1`=805306624, `VerifiedBuild`=55664 WHERE (`Entry`=134828 AND `DifficultyID`=1); -- 134828 (Aqualing) - Sessile, CanSwim, Floating +UPDATE `creature_template_difficulty` SET `ContentTuningID`=500, `StaticFlags1`=805306624, `VerifiedBuild`=55664 WHERE (`Entry`=134056 AND `DifficultyID`=1); -- 134056 (Aqu'sirr) - Sessile, CanSwim, Floating +UPDATE `creature_template_difficulty` SET `HealthScalingExpansion`=7 WHERE (`Entry`=134056 AND `DifficultyID`=1); -- Aqu'sirr +UPDATE `creature_template_difficulty` SET `HealthScalingExpansion`=7 WHERE (`Entry`=139737 AND `DifficultyID`=1); -- Lord Stormsong +UPDATE `creature_template_difficulty` SET `HealthScalingExpansion`=7 WHERE (`Entry`=134828 AND `DifficultyID`=1); -- Aqualing + +UPDATE `creature_template_addon` SET `auras`='274341' WHERE `entry`=139737; -- 139737 (Lord Stormsong) - Water Ritual +UPDATE `creature_template` SET `ScriptName`='npc_aqusirr_intro_lord_stormsong' WHERE `entry`=139737; -- 139737 (Lord Stormsong) +UPDATE `creature_template` SET `ScriptName`='boss_aqusirr' WHERE `entry`=134056; -- 134056 (Aqu'sirr) +UPDATE `creature_template` SET `ScriptName`='boss_aqusirr_aqualing' WHERE `entry`=134828; -- 134828 (Aqualing) +UPDATE `creature_template` SET `faction`=16, `speed_run`=1.285714268684387207, `BaseAttackTime`=2000, `unit_flags`=64, `unit_flags2`=2048, `unit_flags3`=524288 WHERE `entry`=134828; -- Aqualing + +DELETE FROM `creature_template_addon` WHERE `entry` IN (134828, 134612); +INSERT INTO `creature_template_addon` (`entry`, `PathId`, `mount`, `StandState`, `AnimTier`, `VisFlags`, `SheathState`, `PvpFlags`, `emote`, `aiAnimKit`, `movementAnimKit`, `meleeAnimKit`, `visibilityDistanceType`, `auras`) VALUES +(134828, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, '264899'), -- 134828 (Aqualing) - Diminish +(134612, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, ''); -- 134612 (Grasping Tentacles) + +-- Conversations +DELETE FROM `conversation_actors` WHERE (`Idx`=0 AND `ConversationId` IN (8762, 8761)); +INSERT INTO `conversation_actors` (`ConversationId`, `ConversationActorId`, `Idx`, `CreatureId`, `CreatureDisplayInfoId`, `NoActorObject`, `ActivePlayerObject`, `VerifiedBuild`) VALUES +(8762, 65085, 0, 139971, 60766, 0, 0, 34601), +(8761, 0, 0, 139970, 81302, 0, 0, 27843); + +DELETE FROM `conversation_template` WHERE `Id` IN (8762, 8761); +INSERT INTO `conversation_template` (`Id`, `FirstLineID`, `TextureKitId`, `VerifiedBuild`) VALUES +(8762, 19643, 0, 34601), +(8761, 19642, 0, 27843); + +DELETE FROM `conversation_line_template` WHERE `Id` IN (19643, 19642); +INSERT INTO `conversation_line_template` (`Id`, `UiCameraID`, `ActorIdx`, `Flags`, `ChatType`, `VerifiedBuild`) VALUES +(19643, 1060, 0, 0, 0, 34601), +(19642, 82, 0, 0, 0, 27843); + +-- Spawngroup +DELETE FROM `spawn_group_template` WHERE `groupId`= @SPAWNGROUP+0; +INSERT INTO `spawn_group_template` (`groupId`, `groupName`, `groupFlags`) VALUES +(@SPAWNGROUP+0, 'Shrine of the Storm - Aqu\'sirr spawn', 4); + +DELETE FROM `spawn_group` WHERE `groupId`= @SPAWNGROUP+0; +INSERT INTO `spawn_group` (`groupId`, `spawnType`, `spawnId`) VALUES +(@SPAWNGROUP+0, 0, @CGUID+0); + +-- Areatrigger +DELETE FROM `areatrigger_template` WHERE (`Id` = @ATID+0 AND `IsCustom` = 1); +INSERT INTO `areatrigger_template` (`Id`, `IsCustom`, `Flags`, `VerifiedBuild`) VALUES +(@ATID+0, 1, 1, 0); + +DELETE FROM `areatrigger` WHERE `SpawnId`= @ATIDSPAWN+0; +INSERT INTO `areatrigger` (`SpawnId`, `AreaTriggerCreatePropertiesId`, `IsCustom`, `MapId`, `SpawnDifficulties`, `PosX`, `PosY`, `PosZ`, `Orientation`, `PhaseUseFlags`, `PhaseId`, `PhaseGroup`, `ScriptName`, `Comment`, `VerifiedBuild`) VALUES +(@ATIDSPAWN+0, @ATCP+0, 1, 1864, '1,2,23,8', 3925.384, -1245.656, 128.339, 3.31631, 1, 0, 0, 'at_aqusirr_intro', 'Shrine of the Storm - Trigger Aqu\'sirr intro', 0); + +DELETE FROM `areatrigger_create_properties` WHERE `Id`= @ATCP+0 AND `IsCustom`=1; +INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `SpellForVisuals`, `TimeToTarget`, `TimeToTargetScale`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES +(@ATCP+0, 1, @ATID+0, 1, 0, 0, 0, 0, 0, -1, 0, 0, NULL, 0, 0, 1, 18, 30, 5, 18, 30, 5, 0, 0, '', 0); + +DELETE FROM `areatrigger_template` WHERE (`IsCustom`=0 AND `Id` IN (17428, 17427)); +INSERT INTO `areatrigger_template` (`Id`, `IsCustom`, `Flags`, `VerifiedBuild`) VALUES +(17428, 0, 0, 55664), +(17427, 0, 0, 55664); + +DELETE FROM `areatrigger_create_properties` WHERE (`IsCustom`=0 AND `Id` IN (12773, 12775)); +INSERT INTO `areatrigger_create_properties` (`Id`, `IsCustom`, `AreaTriggerId`, `IsAreatriggerCustom`, `Flags`, `MoveCurveId`, `ScaleCurveId`, `MorphCurveId`, `FacingCurveId`, `AnimId`, `AnimKitId`, `DecalPropertiesId`, `TimeToTarget`, `TimeToTargetScale`, `Shape`, `ShapeData0`, `ShapeData1`, `ShapeData2`, `ShapeData3`, `ShapeData4`, `ShapeData5`, `ShapeData6`, `ShapeData7`, `ScriptName`, `VerifiedBuild`) VALUES +(12773, 0, 17427, 0, 4, 0, 0, 0, 0, -1, 0, 0, 0, 6000, 0, 100, 100, 0, 0, 0, 0, 0, 0, 'at_aqusirr_undertow', 55664), -- Spell: 264144 (Undertow) +(12775, 0, 17428, 0, 4, 0, 0, 0, 0, -1, 0, 0, 0, 4000, 0, 6, 6, 0, 0, 0, 0, 0, 0, 'at_aqusirr_surging_rush', 55664); -- Spell: 264101 (Surging Rush) + +-- Spells +DELETE FROM `spell_script_names` WHERE `spell_id` IN (274365, 274367, 274364, 264903, 264911, 264912, 264913, 274260, 264102, 264560, 264941, 264477, 264526); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(274365, 'spell_aqusirr_requiem_of_the_abyss'), +(274367, 'spell_aqusirr_requiem_of_the_abyss'), +(274364, 'spell_aqusirr_requiem_of_the_abyss_periodic'), +(264903, 'spell_aqusirr_erupting_waters_aura'), +(264911, 'spell_aqusirr_erupting_waters_split_1'), +(264912, 'spell_aqusirr_erupting_waters_split_2'), +(264913, 'spell_aqusirr_erupting_waters_split_3'), +(264560, 'spell_aqusirr_choking_brine'), +(274260, 'spell_aqusirr_surging_rush'), +(264102, 'spell_aqusirr_surging_rush_selector'), +(264941, 'spell_aqusirr_erupting_waters'), +(264477, 'spell_aqusirr_grasp_from_the_depths_selector'), +(264526, 'spell_aqusirr_grasp_from_the_depths_damage'); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=265030; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `ConditionStringValue1`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 265030, 0, 0, 51, 0, 5, 134056, 0, '', 0, 0, 0, '', 'Spell \'Erupting Waters\' can only hit \'Aqu\'sirr\''); + +-- Texts +DELETE FROM `creature_text` WHERE `CreatureID` = 139737; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(139737, 0, 0, 'How dare you sully this holy place with your presence!', 14, 0, 100, 25, 0, 108219, 150520, 0, 'Lord Stormsong to Player'), +(139737, 1, 0, 'I call upon the surging waters! Arise, and wipe out these intruders!', 14, 0, 100, 5, 0, 108220, 150521, 0, 'Lord Stormsong to Player'); + +-- SAI +UPDATE `creature_template` SET `faction`=14, `BaseAttackTime`=2000, `unit_flags`=0, `unit_flags2`=32800, `unit_flags3`=524288, `AIName`='SmartAI' WHERE `entry`=134612; -- Grasping Tentacles +DELETE FROM `smart_scripts` WHERE `entryorguid`=134612 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `Difficulties`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param_string`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `action_param7`, `action_param_string`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_param_string`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(134612, 0, 0, 0, '', 63, 0, 100, 0, 0, 0, 0, 0, 0, '', 85, 264526, 2, 128, 0, 0, 0, 0, NULL, 1, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 'Grasping Tentacles - On Just Created - Self: Cast Spell 264526'); + +UPDATE `creature_template_difficulty` SET `LevelScalingDeltaMin`=1, `LevelScalingDeltaMax`=1, `ContentTuningID`=501, `StaticFlags1`=805306624, `VerifiedBuild`=56647 WHERE (`Entry`=134828 AND `DifficultyID`=2); -- 134828 (Aqualing) - Sessile, CanSwim, Floating +UPDATE `creature_template_difficulty` SET `ContentTuningID`=501, `StaticFlags1`=805306624, `VerifiedBuild`=56647 WHERE (`Entry`=134612 AND `DifficultyID`=2); -- 134612 (Grasping Tentacles) - Sessile, CanSwim, Floating +UPDATE `creature_template_difficulty` SET `LevelScalingDeltaMin`=1, `LevelScalingDeltaMax`=1, `ContentTuningID`=502, `StaticFlags1`=805306624, `VerifiedBuild`=56647 WHERE (`Entry`=134828 AND `DifficultyID`=23); -- 134828 (Aqualing) - Sessile, CanSwim, Floating +UPDATE `creature_template_difficulty` SET `ContentTuningID`=502, `StaticFlags1`=805306624, `VerifiedBuild`=56647 WHERE (`Entry`=134612 AND `DifficultyID`=23); -- 134612 (Grasping Tentacles) - Sessile, CanSwim, Floating diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index e93fc7b6a27..7e6d0947a99 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4892,6 +4892,37 @@ void SpellMgr::LoadSpellInfoCorrections() // // + // SHRINE OF THE STORM SPELLS + // + + // These spells have TARGET_DEST_NEARBY_ENTRY for serverside unit + ApplySpellFix({ + 274365, // Requiem of the Abyss + 274367, // Requiem of the Abyss + 264911, // Erupting Waters + 264912, // Erupting Waters + 264913, // Erupting Waters + }, [](SpellInfo* spellInfo) + { + ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) + { + spellEffectInfo->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DEST); + }); + }); + + // Conversation + ApplySpellFix({ 274668, 274669 }, [](SpellInfo* spellInfo) + { + ApplySpellEffectFix(spellInfo, EFFECT_0, [](SpellEffectInfo* spellEffectInfo) + { + spellEffectInfo->Effect = SPELL_EFFECT_CREATE_CONVERSATION; + }); + }); + + // ENDOF SHRINE OF THE STORM SPELLS + // + + // // WAYCREST MANOR SPELLS // diff --git a/src/server/scripts/KulTiras/ShrineOfTheStorm/boss_aqusirr.cpp b/src/server/scripts/KulTiras/ShrineOfTheStorm/boss_aqusirr.cpp new file mode 100644 index 00000000000..39b0db1dea6 --- /dev/null +++ b/src/server/scripts/KulTiras/ShrineOfTheStorm/boss_aqusirr.cpp @@ -0,0 +1,733 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "AreaTrigger.h" +#include "AreaTriggerAI.h" +#include "Creature.h" +#include "GridNotifiers.h" +#include "InstanceScript.h" +#include "Map.h" +#include "ObjectAccessor.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" +#include "TaskScheduler.h" +#include "shrine_of_the_storm.h" + +enum AqusirrSpells +{ + // Lord Stormsong + SPELL_WATER_RITUAL = 274341, + SPELL_REQUIEM_OF_THE_ABYSS_PERIODIC = 274364, + SPELL_REQUIEM_OF_THE_ABYSS = 274359, + SPELL_REQUIEM_OF_THE_ABYSS_KNOCKBACK = 274367, + SPELL_SPLASHING_WATERS = 241680, + + // Aqu'sirr + SPELL_EMERGE_VISUAL = 274948, + SPELL_UNDERTOW = 264144, + SPELL_SEA_BLAST = 265001, + SPELL_SURGING_RUSH_SELECTOR = 264102, + SPELL_SURGING_RUSH_DAMAGE = 264155, + SPELL_SURGING_RUSH = 264101, + SPELL_ERUPTING_WATERS_SPLIT = 264903, + SPELL_ERUPTING_WATERS_DAMAGE = 264941, + SPELL_ERUPTING_WATERS_AQUALING = 265030, + SPELL_CHOKING_BRINE = 264560, + SPELL_CHOKING_BRINE_MISSILE = 264714, + SPELL_CHOKING_BRINE_MISSILE_2 = 264703, + SPELL_GRASP_FROM_THE_DEPTHS_SELECTOR = 264477, + SPELL_GRASP_FROM_THE_DEPTHS_SUMMON = 264522, + SPELL_GRASP_FROM_THE_DEPTHS_DAMAGE = 264526, + + SPELL_CONVERSATION_HORDE = 274669, + SPELL_CONVERSATION_ALLIANCE = 274668 +}; + +enum AqusirrEvents +{ + EVENT_SURGING_RUSH = 1, + EVENT_CHOKING_BRINE, + EVENT_SEA_BLAST, + EVENT_UNDERTOW, + EVENT_GRASP_FROM_THE_DEPTHS +}; + +enum AqusirrActions +{ + ACTION_START_INTRO = 1 +}; + +enum AqusirrTexts +{ + SAY_AQUSIRR_INTRO_1 = 0, + SAY_AQUSIRR_INTRO_2 = 1 +}; + +enum AqusirrMisc +{ + SPAWN_GROUP_ID_AQUSIRR = 1258, + ANIM_KIT_SURGING_RUSH = 11428 +}; + +constexpr Position RequiemOfTheAbyssPosition = { 3932.82f, -1243.81f, 128.368f }; +constexpr Position EruptingWatersSummonPosition1 = { 3917.31f, -1234.08f, 128.130f }; +constexpr Position EruptingWatersSummonPosition2 = { 3924.02f, -1259.52f, 128.141f }; +constexpr Position EruptingWatersSummonPosition3 = { 3950.80f, -1238.47f, 127.831f }; + +namespace AqusirrEventHandler +{ + void Schedule(Creature* me, EventMap& events) + { + events.ScheduleEvent(EVENT_SURGING_RUSH, 17s); + if (me->GetMap()->GetPlayersCountExceptGMs() > 1) + events.ScheduleEvent(EVENT_CHOKING_BRINE, 8900ms); + events.ScheduleEvent(EVENT_UNDERTOW, 36800ms); + events.ScheduleEvent(EVENT_SEA_BLAST, 1s); + + if (me->GetMap()->IsHeroicOrHigher()) + events.ScheduleEvent(EVENT_GRASP_FROM_THE_DEPTHS, 14300ms); + } + + void Execute(Creature* me, EventMap& events, uint32 eventId) + { + switch (eventId) + { + case EVENT_SEA_BLAST: + { + if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL) && !me->IsWithinMeleeRange(me->GetVictim())) + { + if (Unit* target = me->GetAI()->SelectTarget(SelectTargetMethod::Random)) + me->CastSpell(target, SPELL_SEA_BLAST); + events.Repeat(2400ms); + } + events.Repeat(1s); + break; + } + case EVENT_CHOKING_BRINE: + { + if (Unit* target = me->GetAI()->SelectTarget(SelectTargetMethod::Random)) + me->CastSpell(target, SPELL_CHOKING_BRINE); + events.Repeat(34s, 39s); + break; + } + case EVENT_SURGING_RUSH: + { + me->CastSpell(nullptr, SPELL_SURGING_RUSH_SELECTOR); + events.RescheduleEvent(EVENT_SEA_BLAST, 10s); + events.Repeat(31500ms, 39300ms); + break; + } + case EVENT_UNDERTOW: + { + if (Unit* target = me->GetAI()->SelectTarget(SelectTargetMethod::Random)) + me->CastSpell(target, SPELL_UNDERTOW); + events.Repeat(32400ms, 34s); + break; + } + case EVENT_GRASP_FROM_THE_DEPTHS: + { + me->CastSpell(nullptr, SPELL_GRASP_FROM_THE_DEPTHS_SELECTOR); + events.Repeat(38s); + break; + } + default: + break; + } + } +} + +// 134056 - Aqu'sirr +struct boss_aqusirr : public BossAI +{ + boss_aqusirr(Creature* creature) : BossAI(creature, DATA_AQUSIRR), _triggeredSplit(false), _aqualingDefeatedCount(0) { } + + void JustAppeared() override + { + DoCastSelf(SPELL_EMERGE_VISUAL); + } + + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); + AqusirrEventHandler::Schedule(me, events); + } + + void Reset() override + { + events.Reset(); + _triggeredSplit = false; + _aqualingDefeatedCount = 0; + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (me->IsInEvadeMode()) + return; + + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + instance->SetBossState(DATA_AQUSIRR, FAIL); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GRASP_FROM_THE_DEPTHS_DAMAGE); + + summons.DespawnAll(); + _EnterEvadeMode(); + _DespawnAtEvade(); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + instance->SetBossState(DATA_AQUSIRR, DONE); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_GRASP_FROM_THE_DEPTHS_DAMAGE); + + if (Creature* shrineDummy = GetClosestCreatureWithOptions(me, 50.0f, { .CreatureId = NPC_SHRINE_OF_THE_STORM_DUMMY, .IgnorePhases = true })) + shrineDummy->CastSpell(shrineDummy, instance->instance->GetTeamInInstance() == HORDE ? SPELL_CONVERSATION_HORDE : SPELL_CONVERSATION_ALLIANCE, true); + } + + void ToggleSplit(bool toggle) + { + if (toggle) + { + me->InterruptNonMeleeSpells(true); + DoCastSelf(SPELL_ERUPTING_WATERS_SPLIT); + events.Reset(); + me->SetReactState(REACT_PASSIVE); + } + else + { + DoCastSelf(SPELL_ERUPTING_WATERS_DAMAGE); + me->RemoveAurasDueToSpell(SPELL_ERUPTING_WATERS_SPLIT); + AqusirrEventHandler::Schedule(me, events); + me->SetReactState(REACT_AGGRESSIVE); + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override + { + if (me->HealthBelowPctDamaged(50, damage) && !_triggeredSplit) + { + _triggeredSplit = true; + ToggleSplit(true); + } + } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_ERUPTING_WATERS_AQUALING) + { + DoCastSelf(SPELL_ERUPTING_WATERS_DAMAGE); + + _aqualingDefeatedCount++; + + if (_aqualingDefeatedCount == 3) + ToggleSplit(false); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + AqusirrEventHandler::Execute(me, events, eventId); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + } + +private: + bool _triggeredSplit; + uint8 _aqualingDefeatedCount; +}; + +// 134828 - Aqualing +struct boss_aqusirr_aqualing : public ScriptedAI +{ + boss_aqusirr_aqualing(Creature* creature) : ScriptedAI(creature) + { + SetBoundary(me->GetInstanceScript()->GetBossBoundary(DATA_AQUSIRR)); + } + + void JustAppeared() override + { + DoZoneInCombat(); + } + + void JustDied(Unit* /*killer*/) override + { + me->GetInstanceScript()->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + DoCast(SPELL_ERUPTING_WATERS_AQUALING); + + me->DespawnOrUnsummon(3s); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (Creature* aqusirr = me->GetInstanceScript()->GetCreature(DATA_AQUSIRR)) + aqusirr->AI()->EnterEvadeMode(why); + } + + void JustEngagedWith(Unit* /*who*/) override + { + me->GetInstanceScript()->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 2); + AqusirrEventHandler::Schedule(me, events); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + AqusirrEventHandler::Execute(me, events, eventId); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + } + +private: + EventMap events; +}; + +// 139737 - Lord Stormsong +struct npc_aqusirr_intro_lord_stormsong : public CreatureAI +{ + npc_aqusirr_intro_lord_stormsong(Creature* creature) : CreatureAI(creature) { } + + void DoAction(int32 action) override + { + if (action == ACTION_START_INTRO) + { + me->RemoveAurasDueToSpell(SPELL_WATER_RITUAL); + + Milliseconds delay = 1s; + + _scheduler.Schedule(delay, [this](TaskContext) + { + me->SetFacingTo(0.1939797f); + }); + + delay += 3s; + + _scheduler.Schedule(delay, [this](TaskContext) + { + Talk(SAY_AQUSIRR_INTRO_1); + }); + + delay += 6s; + + _scheduler.Schedule(delay, [this](TaskContext) + { + Talk(SAY_AQUSIRR_INTRO_2); + }); + + delay += 6s; + + _scheduler.Schedule(delay, [this](TaskContext) + { + DoCastSelf(SPELL_REQUIEM_OF_THE_ABYSS); + }); + + delay += 1s; + + _scheduler.Schedule(delay, [this](TaskContext) + { + DoCastSelf(SPELL_REQUIEM_OF_THE_ABYSS_PERIODIC, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + }); + + delay += 6s; + + _scheduler.Schedule(delay, [this](TaskContext) + { + me->GetMap()->SpawnGroupSpawn(SPAWN_GROUP_ID_AQUSIRR); + }); + + delay += 3800ms; + + _scheduler.Schedule(delay, [this](TaskContext) + { + DoCastSelf(SPELL_SPLASHING_WATERS); + }); + } + } + + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_SPLASHING_WATERS) + me->DespawnOrUnsummon(); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + +private: + TaskScheduler _scheduler; +}; + +// 274365 - Requiem of the Abyss (Visual) +// 274367 - Requiem of the Abyss (Knockback) +class spell_aqusirr_requiem_of_the_abyss : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(RequiemOfTheAbyssPosition); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_aqusirr_requiem_of_the_abyss::SetDest, EFFECT_0, TARGET_DEST_DEST); + } +}; + +// 274364 - Requiem of the Abyss +class spell_aqusirr_requiem_of_the_abyss_periodic : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_REQUIEM_OF_THE_ABYSS_KNOCKBACK }); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* creature = GetTarget()->ToCreature(); + if (!creature) + return; + + creature->CastSpell(nullptr, SPELL_REQUIEM_OF_THE_ABYSS_KNOCKBACK, false); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_aqusirr_requiem_of_the_abyss_periodic::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 264903 - Erupting Waters +class spell_aqusirr_erupting_waters_aura : public AuraScript +{ + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* target = GetTarget()->ToCreature(); + if (!target) + return; + + target->SetUnkillable(true); + target->SetImmuneToPC(true); + target->SetUninteractible(true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* target = GetTarget()->ToCreature(); + if (!target) + return; + + target->SetUnkillable(false); + target->SetImmuneToPC(false); + target->SetUninteractible(false); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_aqusirr_erupting_waters_aura::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_aqusirr_erupting_waters_aura::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 264911 - Erupting Waters +class spell_aqusirr_erupting_waters_split_1 : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(EruptingWatersSummonPosition1); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_aqusirr_erupting_waters_split_1::SetDest, EFFECT_0, TARGET_DEST_DEST); + } +}; + +// 264912 - Erupting Waters +class spell_aqusirr_erupting_waters_split_2 : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(EruptingWatersSummonPosition2); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_aqusirr_erupting_waters_split_2::SetDest, EFFECT_0, TARGET_DEST_DEST); + } +}; + +// 264913 - Erupting Waters +class spell_aqusirr_erupting_waters_split_3 : public SpellScript +{ + void SetDest(SpellDestination& dest) + { + dest.Relocate(EruptingWatersSummonPosition3); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_aqusirr_erupting_waters_split_3::SetDest, EFFECT_0, TARGET_DEST_DEST); + } +}; + +// 264941 - Erupting Waters +class spell_aqusirr_erupting_waters : public SpellScript +{ + void HandleDamage(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + caster->SetHealth(caster->GetHealth() - caster->CountPctFromMaxHealth(GetEffectValue())); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_aqusirr_erupting_waters::HandleDamage, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 264560 - Choking Brine +class spell_aqusirr_choking_brine : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_CHOKING_BRINE_MISSILE, SPELL_CHOKING_BRINE_MISSILE_2 }); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + Unit* target = GetTarget(); + target->CastSpell(target, SPELL_CHOKING_BRINE_MISSILE, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + + for (uint8 i = 0; i < 5; ++i) + target->CastSpell(target, SPELL_CHOKING_BRINE_MISSILE_2, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_aqusirr_choking_brine::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 274260 - Surging Rush +class spell_aqusirr_surging_rush : public SpellScript +{ + void HandleScript(SpellEffIndex /*effIndex*/) + { + Creature* creatureTarget = GetHitCreature(); + if (!creatureTarget) + return; + + creatureTarget->RemoveAurasDueToSpell(SPELL_SURGING_RUSH); + creatureTarget->SetDisableGravity(true); + creatureTarget->AddUnitState(UNIT_STATE_ROOT); + creatureTarget->PlayOneShotAnimKitId(ANIM_KIT_SURGING_RUSH); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_aqusirr_surging_rush::HandleScript, EFFECT_0, SPELL_EFFECT_TRIGGER_ACTION_SET); + } +}; + +// 264102 - Surging Rush +class spell_aqusirr_surging_rush_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SURGING_RUSH }); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + static constexpr float MAX_DISTANCE = 40.0f; + constexpr Position CenterPosition = { 3935.63f, -1243.41f, 128.40f }; + + float angle = GetCaster()->GetEntry() == NPC_AQUALING ? GetCaster()->GetAbsoluteAngle(CenterPosition) + frand(-float(M_PI) / 3, float(M_PI) / 3) : GetCaster()->GetAbsoluteAngle(GetHitUnit()); + Position dest = GetCaster()->GetPosition(); + + GetCaster()->MovePosition(dest, MAX_DISTANCE, angle - GetCaster()->GetOrientation(), 2.5f); + + GetCaster()->CastSpell(dest, SPELL_SURGING_RUSH, false); + } + + void HandleActionSet(SpellEffIndex /*effIndex*/) + { + Creature* creatureTarget = GetHitCreature(); + if (!creatureTarget) + return; + + creatureTarget->SetDisableGravity(false); + creatureTarget->ClearUnitState(UNIT_STATE_ROOT); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_aqusirr_surging_rush_selector::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + OnEffectHitTarget += SpellEffectFn(spell_aqusirr_surging_rush_selector::HandleActionSet, EFFECT_2, SPELL_EFFECT_TRIGGER_ACTION_SET); + } +}; + +// 264477 - Grasp from the Depths +class spell_aqusirr_grasp_from_the_depths_selector : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_GRASP_FROM_THE_DEPTHS_SUMMON }); + } + + void HandleHitTarget(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GRASP_FROM_THE_DEPTHS_SUMMON, TRIGGERED_IGNORE_CAST_IN_PROGRESS); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_aqusirr_grasp_from_the_depths_selector::HandleHitTarget, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 264526 - Grasp from the Depths +class spell_aqusirr_grasp_from_the_depths_damage : public AuraScript +{ + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Creature* caster = Object::ToCreature(GetCaster()); + if (!caster) + return; + + caster->DespawnOrUnsummon(); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_aqusirr_grasp_from_the_depths_damage::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 95 - Areatrigger +struct at_aqusirr_intro : AreaTriggerAI +{ + at_aqusirr_intro(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + Player* player = unit->ToPlayer(); + if (!player) + return; + + if (player->IsGameMaster()) + return; + + Creature* lordSongstorm = unit->FindNearestCreature(NPC_LORD_SONGSTORM_AQUSIRR, 50.0f); + if (!lordSongstorm) + return; + + lordSongstorm->AI()->DoAction(ACTION_START_INTRO); + at->Remove(); + } +}; + +// 264144 - Undertow +struct at_aqusirr_undertow : AreaTriggerAI +{ + at_aqusirr_undertow(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + if (!unit->IsPlayer()) + return; + + unit->ApplyMovementForce(at->GetGUID(), at->GetPosition(), -5.0f, MovementForceType::Gravity); + } + + void OnUnitExit(Unit* unit) override + { + if (!unit->IsPlayer()) + return; + + unit->RemoveMovementForce(at->GetGUID()); + } +}; + +// 264101 - Surging Rush +struct at_aqusirr_surging_rush : AreaTriggerAI +{ + at_aqusirr_surging_rush(AreaTrigger* areatrigger) : AreaTriggerAI(areatrigger) { } + + void OnUnitEnter(Unit* unit) override + { + if (!unit->IsPlayer()) + return; + + Unit* caster = at->GetCaster(); + if (!caster) + return; + + caster->CastSpell(unit, SPELL_SURGING_RUSH_DAMAGE, false); + } +}; + +void AddSC_boss_aqusirr() +{ + RegisterShrineOfTheStormCreatureAI(boss_aqusirr); + RegisterShrineOfTheStormCreatureAI(boss_aqusirr_aqualing); + RegisterShrineOfTheStormCreatureAI(npc_aqusirr_intro_lord_stormsong); + + RegisterSpellScript(spell_aqusirr_requiem_of_the_abyss); + RegisterSpellScript(spell_aqusirr_requiem_of_the_abyss_periodic); + RegisterSpellScript(spell_aqusirr_erupting_waters_aura); + RegisterSpellScript(spell_aqusirr_erupting_waters_split_1); + RegisterSpellScript(spell_aqusirr_erupting_waters_split_2); + RegisterSpellScript(spell_aqusirr_erupting_waters_split_3); + RegisterSpellScript(spell_aqusirr_erupting_waters); + RegisterSpellScript(spell_aqusirr_choking_brine); + RegisterSpellScript(spell_aqusirr_surging_rush); + RegisterSpellScript(spell_aqusirr_surging_rush_selector); + RegisterSpellScript(spell_aqusirr_grasp_from_the_depths_selector); + + RegisterAreaTriggerAI(at_aqusirr_intro); + RegisterAreaTriggerAI(at_aqusirr_undertow); + RegisterAreaTriggerAI(at_aqusirr_surging_rush); +} diff --git a/src/server/scripts/KulTiras/ShrineOfTheStorm/instance_shrine_of_the_storm.cpp b/src/server/scripts/KulTiras/ShrineOfTheStorm/instance_shrine_of_the_storm.cpp new file mode 100644 index 00000000000..211cfb51292 --- /dev/null +++ b/src/server/scripts/KulTiras/ShrineOfTheStorm/instance_shrine_of_the_storm.cpp @@ -0,0 +1,72 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "AreaBoundary.h" +#include "InstanceScript.h" +#include "ScriptMgr.h" +#include "shrine_of_the_storm.h" + +static BossBoundaryData const boundaries = +{ + { DATA_AQUSIRR, new ZRangeBoundary(119.89f, 132.9f) } +}; + +ObjectData const creatureData[] = +{ + { BOSS_AQUSIRR, DATA_AQUSIRR }, + { BOSS_BROTHER_IRONHULL, DATA_BROTHER_IRONHULL }, + { BOSS_GALECALLER_FAYE, DATA_GALECALLER_FAYE }, + { BOSS_LORD_STORMSONG, DATA_LORD_STORMSONG }, + { BOSS_VOLZITH_THE_WHISPERER, DATA_VOLZITH_THE_WHISPERER }, + { 0, 0 } // END +}; + +DungeonEncounterData const encounters[] = +{ + { DATA_AQUSIRR, {{ 2130 }} }, + { DATA_TIDESAGE_COUNCIL, {{ 2131 }} }, + { DATA_LORD_STORMSONG, {{ 2132 }} }, + { DATA_VOLZITH_THE_WHISPERER, {{ 2133 }} } +}; + +class instance_shrine_of_the_storm : public InstanceMapScript +{ +public: + instance_shrine_of_the_storm() : InstanceMapScript("instance_shrine_of_the_storm", 1864) { } + + struct instance_shrine_of_the_storm_InstanceMapScript : public InstanceScript + { + instance_shrine_of_the_storm_InstanceMapScript(InstanceMap* map) : InstanceScript(map) + { + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadBossBoundaries(boundaries); + LoadObjectData(creatureData, nullptr); + LoadDungeonEncounterData(encounters); + } + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_shrine_of_the_storm_InstanceMapScript(map); + } +}; + +void AddSC_instance_shrine_of_the_storm() +{ + new instance_shrine_of_the_storm(); +} diff --git a/src/server/scripts/KulTiras/ShrineOfTheStorm/shrine_of_the_storm.h b/src/server/scripts/KulTiras/ShrineOfTheStorm/shrine_of_the_storm.h new file mode 100644 index 00000000000..e8d9b7f4e73 --- /dev/null +++ b/src/server/scripts/KulTiras/ShrineOfTheStorm/shrine_of_the_storm.h @@ -0,0 +1,63 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _Shrine_Of_The_Storm_h__ +#define _Shrine_Of_The_Storm_h__ + +#include "CreatureAIImpl.h" + +constexpr char const* DataHeader = "SOTS"; +constexpr char const* ShrineOfTheStormScriptName = "instance_shrine_of_the_storm"; + +constexpr uint32 const EncounterCount = 4; + +enum ShrineOfTheStormDataTypes +{ + // Encounters + DATA_AQUSIRR = 0, + DATA_TIDESAGE_COUNCIL = 1, + DATA_LORD_STORMSONG = 2, + DATA_VOLZITH_THE_WHISPERER = 3, + + DATA_BROTHER_IRONHULL, + DATA_GALECALLER_FAYE +}; + +enum ShrineOfTheStormCreatureIds +{ + // Bosses + BOSS_AQUSIRR = 134056, + BOSS_BROTHER_IRONHULL = 134063, + BOSS_GALECALLER_FAYE = 134058, + BOSS_LORD_STORMSONG = 134060, + BOSS_VOLZITH_THE_WHISPERER = 134069, + + NPC_LORD_SONGSTORM_AQUSIRR = 139737, + NPC_SHRINE_OF_THE_STORM_DUMMY = 139986, + NPC_GRASPING_TENTACLE = 134612, + NPC_AQUALING = 134828, +}; + +template <class AI, class T> +inline AI* GetShrineOfTheStormAI(T* obj) +{ + return GetInstanceAI<AI>(obj, ShrineOfTheStormScriptName); +} + +#define RegisterShrineOfTheStormCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetShrineOfTheStormAI) + +#endif // _Shrine_Of_The_Storm_h__ diff --git a/src/server/scripts/KulTiras/kultiras_script_loader.cpp b/src/server/scripts/KulTiras/kultiras_script_loader.cpp index 78f622da060..4bcbc4d68c0 100644 --- a/src/server/scripts/KulTiras/kultiras_script_loader.cpp +++ b/src/server/scripts/KulTiras/kultiras_script_loader.cpp @@ -19,6 +19,10 @@ void AddSC_zone_boralus(); +// Shrine of the Storm +void AddSC_boss_aqusirr(); +void AddSC_instance_shrine_of_the_storm(); + // Waycrest Manor void AddSC_boss_heartsbane_triad(); void AddSC_boss_soulbound_goliath(); @@ -32,6 +36,10 @@ void AddKulTirasScripts() { AddSC_zone_boralus(); + // Shrine of the Storm + AddSC_boss_aqusirr(); + AddSC_instance_shrine_of_the_storm(); + // Waycrest Manor AddSC_boss_heartsbane_triad(); AddSC_boss_soulbound_goliath(); |