aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2021_10_23_07_world_2018_09_01_00_world.sql165
-rw-r--r--src/server/game/Spells/SpellInfo.cpp1
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2001
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp160
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h2
5 files changed, 1173 insertions, 1156 deletions
diff --git a/sql/updates/world/master/2021_10_23_07_world_2018_09_01_00_world.sql b/sql/updates/world/master/2021_10_23_07_world_2018_09_01_00_world.sql
new file mode 100644
index 00000000000..94e1a15a3d3
--- /dev/null
+++ b/sql/updates/world/master/2021_10_23_07_world_2018_09_01_00_world.sql
@@ -0,0 +1,165 @@
+-- Algalon
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN
+('spell_algalon_arcane_barrage',
+'spell_algalon_phase_constellation',
+'spell_algalon_black_hole_phase_shifts');
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(65508,'spell_algalon_phase_constellation'),
+(62168,'spell_algalon_black_hole_phase_shifts'),
+(65250,'spell_algalon_black_hole_phase_shifts'),
+(64417,'spell_algalon_black_hole_phase_shifts');
+
+UPDATE `creature_template` SET `ScriptName`='npc_black_hole' WHERE `entry`=32953;
+UPDATE `creature` SET `spawntimesecs`=15 WHERE `id`=33089; -- Dark Matters should respawn faster (is always full present in each black hole travel)
+
+DELETE FROM `creature_template_movement` WHERE `CreatureId`=34131; -- Stalker Asteroid Target 2 (25 man)
+INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`) VALUES
+(34131,0,0,1,0);
+
+-- Living Constellation immune mask
+UPDATE `creature_template` SET `mechanic_immune_mask` =
+1| -- charm
+2| -- disorient
+4| -- disarm
+16| -- fear
+512| -- sleep
+2048| -- stun
+4096| -- freeze
+8192| -- knockout
+65536| -- polymorph
+131072| -- banish
+524288| -- shackle
+1048576| -- mount
+4194304| -- turn
+8388608| -- horror
+536870912 -- sapped
+WHERE `entry` IN (33052,33116);
+
+-- Brann Bronzebeard
+UPDATE `creature_text` SET `Emote`=19 WHERE `CreatureID`=34064 AND `GroupID`=1 AND `ID`=0;
+
+-- Movement stuffs
+
+-- Before Door (Intro)
+DELETE FROM `script_spline_chain_meta` WHERE `entry`=34064 AND `chainId`=1;
+INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES
+(34064, 1, 0, 4584, 3641),
+(34064, 1, 1, 1881, 1234),
+(34064, 1, 2, 1279, 0);
+DELETE FROM `script_spline_chain_waypoints` WHERE `entry`=34064 AND `chainId`=1;
+INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES
+(34064, 1, 0, 0, 1677.3630, -162.35140, 427.33200),
+(34064, 1, 0, 1, 1680.0880, -162.26590, 427.33260),
+(34064, 1, 0, 2, 1679.0880, -162.26590, 427.33260),
+(34064, 1, 0, 3, 1663.3630, -163.04570, 427.32710),
+(34064, 1, 0, 4, 1660.9440, -163.16570, 427.27290),
+(34064, 1, 0, 5, 1656.7000, -163.37610, 427.27290),
+(34064, 1, 0, 6, 1653.5710, -163.53130, 427.34070),
+(34064, 1, 0, 7, 1642.4820, -164.08120, 427.26020),
+(34064, 1, 0, 8, 1642.4820, -164.08120, 427.26020),
+(34064, 1, 1, 0, 1648.2720, -163.79410, 427.30220),
+(34064, 1, 1, 1, 1642.3860, -164.15430, 427.52730),
+(34064, 1, 1, 2, 1635.0000, -169.51450, 427.25230),
+(34064, 1, 2, 0, 1639.2800, -166.40650, 427.25680),
+(34064, 1, 2, 1, 1635.2970, -169.42000, 427.50950),
+(34064, 1, 2, 2, 1633.2970, -172.92000, 427.50950),
+(34064, 1, 2, 3, 1632.8140, -173.93340, 427.26210);
+
+-- Algalon Room (Intro)
+DELETE FROM `script_spline_chain_meta` WHERE `entry`=34064 AND `chainId`=2;
+INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES
+(34064, 2, 0, 21837, 20656),
+(34064, 2, 1, 20274, 0);
+DELETE FROM `script_spline_chain_waypoints` WHERE `entry`=34064 AND `chainId`=2;
+INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES
+(34064, 2, 0, 0, 1632.8140, -173.93340, 427.26210),
+(34064, 2, 0, 1, 1632.8260, -175.36180, 427.54690),
+(34064, 2, 0, 2, 1632.8260, -176.36180, 427.54690),
+(34064, 2, 0, 3, 1632.5760, -178.11180, 427.54690),
+(34064, 2, 0, 4, 1632.5760, -186.86180, 427.54690),
+(34064, 2, 0, 5, 1632.3260, -191.11180, 427.54690),
+(34064, 2, 0, 6, 1632.0760, -211.36180, 419.79690),
+(34064, 2, 0, 7, 1632.0760, -213.61180, 418.79690),
+(34064, 2, 0, 8, 1631.8260, -219.86180, 418.79690),
+(34064, 2, 0, 9, 1631.5760, -222.86180, 418.79690),
+(34064, 2, 0, 10, 1631.5760, -226.11180, 418.79690),
+(34064, 2, 0, 11, 1631.3390, -226.79030, 418.33180),
+(34064, 2, 1, 0, 1631.4220, -223.79560, 418.40920),
+(34064, 2, 1, 1, 1631.4580, -226.29390, 418.61520),
+(34064, 2, 1, 2, 1631.4580, -226.79390, 418.61520),
+(34064, 2, 1, 3, 1631.9580, -227.79390, 418.36520),
+(34064, 2, 1, 4, 1631.9580, -229.79390, 417.86520),
+(34064, 2, 1, 5, 1631.7080, -232.04390, 417.86520),
+(34064, 2, 1, 6, 1631.7080, -234.04390, 417.86520),
+(34064, 2, 1, 7, 1637.2080, -266.79390, 417.61520),
+(34064, 2, 1, 8, 1630.4940, -267.29210, 417.32110);
+
+-- Outro 1
+DELETE FROM `script_spline_chain_meta` WHERE `entry`=34064 AND `chainId`=3;
+INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES
+(34064, 3, 0, 13940, 0);
+DELETE FROM `script_spline_chain_waypoints` WHERE `entry`=34064 AND `chainId`=3;
+INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES
+(34064, 3, 0, 0, 1631.9890, -221.54390, 418.40910),
+(34064, 3, 0, 1, 1631.9910, -222.44830, 418.40910),
+(34064, 3, 0, 2, 1632.0610, -269.03790, 417.32100),
+(34064, 3, 0, 3, 1631.9860, -297.78310, 417.32100),
+(34064, 3, 0, 4, 1631.9860, -297.78310, 417.32100);
+
+-- Outro 2
+DELETE FROM `script_spline_chain_meta` WHERE `entry`=34064 AND `chainId`=4;
+INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES
+(34064, 4, 0, 26675, 0);
+DELETE FROM `script_spline_chain_waypoints` WHERE `entry`=34064 AND `chainId`=4;
+INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES
+(34064, 4, 0, 0, 1631.9860, -297.78310, 417.32100),
+(34064, 4, 0, 1, 1632.5820, -289.54480, 417.79630),
+(34064, 4, 0, 2, 1633.0820, -267.29480, 417.79630),
+(34064, 4, 0, 3, 1631.8320, -227.29480, 418.54630),
+(34064, 4, 0, 4, 1632.5820, -217.79480, 418.79630),
+(34064, 4, 0, 5, 1632.3320, -203.04480, 423.04630),
+(34064, 4, 0, 6, 1633.0820, -188.79480, 427.54630),
+(34064, 4, 0, 7, 1631.5820, -164.04480, 427.29630),
+(34064, 4, 0, 8, 1656.8320, -164.79480, 427.54630),
+(34064, 4, 0, 9, 1681.3320, -164.29480, 427.54630),
+(34064, 4, 0, 10, 1682.3320, -154.54480, 427.54630),
+(34064, 4, 0, 11, 1683.1770, -136.30650, 427.27150);
+
+-- Despawn Point Intro
+DELETE FROM `script_spline_chain_meta` WHERE `entry`=34064 AND `chainId`=5;
+INSERT INTO `script_spline_chain_meta` (`entry`,`chainId`,`splineId`,`expectedDuration`,`msUntilNext`) VALUES
+(34064, 5, 0, 29711, 28875),
+(34064, 5, 1, 12977, 12141),
+(34064, 5, 2, 7479, 6437),
+(34064, 5, 3, 5117, 0);
+DELETE FROM `script_spline_chain_waypoints` WHERE `entry`=34064 AND `chainId`=5;
+INSERT INTO `script_spline_chain_waypoints` (`entry`,`chainId`,`splineId`,`wpId`,`x`,`y`,`z`) VALUES
+(34064, 5, 0, 0, 1630.4940, -267.29210, 417.32110),
+(34064, 5, 0, 1, 1637.0400, -266.68800, 417.84810),
+(34064, 5, 0, 2, 1634.5400, -233.93800, 417.84810),
+(34064, 5, 0, 3, 1634.2900, -231.68800, 417.84810),
+(34064, 5, 0, 4, 1634.2900, -229.93800, 417.84810),
+(34064, 5, 0, 5, 1632.0400, -227.68800, 418.59810),
+(34064, 5, 0, 6, 1632.0400, -226.18800, 418.84810),
+(34064, 5, 0, 7, 1632.0400, -223.18800, 418.84810),
+(34064, 5, 0, 8, 1632.0400, -220.18800, 418.84810),
+(34064, 5, 0, 9, 1632.0400, -213.68800, 418.84810),
+(34064, 5, 0, 10, 1632.0400, -211.68800, 419.84810),
+(34064, 5, 0, 11, 1632.0850, -201.58390, 423.37500),
+(34064, 5, 1, 0, 1632.0770, -203.61940, 422.59170),
+(34064, 5, 1, 1, 1632.1190, -201.36540, 423.66990),
+(34064, 5, 1, 2, 1631.6190, -190.86540, 427.66990),
+(34064, 5, 1, 3, 1631.3690, -186.86540, 427.41990),
+(34064, 5, 1, 4, 1631.1190, -178.11540, 427.41990),
+(34064, 5, 1, 5, 1631.1190, -176.36540, 427.41990),
+(34064, 5, 1, 6, 1631.1190, -175.36540, 427.41990),
+(34064, 5, 1, 7, 1630.8690, -173.11540, 427.41990),
+(34064, 5, 1, 8, 1630.6600, -172.11150, 427.24800),
+(34064, 5, 2, 0, 1630.7620, -174.22000, 427.26550),
+(34064, 5, 2, 1, 1630.8760, -173.00420, 427.51350),
+(34064, 5, 2, 2, 1630.8760, -171.75420, 427.51350),
+(34064, 5, 2, 3, 1645.9900, -165.78850, 427.26160),
+(34064, 5, 3, 0, 1642.4200, -167.26120, 427.25840),
+(34064, 5, 3, 1, 1646.1510, -165.89170, 427.54380),
+(34064, 5, 3, 2, 1654.4010, -165.14170, 427.54380),
+(34064, 5, 3, 3, 1654.8810, -165.02210, 427.32920);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 3ae31465448..455ab86e36e 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -4351,6 +4351,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, SpellEffectInfo const& ef
case 40268: // Spiritual Vengeance, Teron Gorefiend, Black Temple
case 61987: // Avenging Wrath Marker
case 61988: // Divine Shield exclude aura
+ case 64412: // Phase Punch, Algalon the Observer, Ulduar
case 72410: // Rune of Blood, Saurfang, Icecrown Citadel
case 71204: // Touch of Insignificance, Lady Deathwhisper, Icecrown Citadel
return false;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index b9aafbedd2d..977d211b1f7 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -23,7 +23,6 @@
#include "MapManager.h"
#include "MotionMaster.h"
#include "MoveSplineInit.h"
-#include "ObjectAccessor.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
@@ -60,6 +59,9 @@ enum Texts
SAY_ALGALON_DESPAWN_2 = 18,
SAY_ALGALON_DESPAWN_3 = 19,
SAY_ALGALON_KILL = 20,
+
+ // Direct Sound
+ ENGAGE_MUSIC_ID = 15878
};
enum Spells
@@ -86,6 +88,7 @@ enum Spells
// Living Constellation
SPELL_ARCANE_BARRAGE = 64599,
+ SPELL_DESPAWN_BLACK_HOLE = 64391,
// Collapsing Star
SPELL_COLLAPSE = 62018,
@@ -100,10 +103,11 @@ enum Spells
SPELL_SUMMON_VOID_ZONE_VISUAL = 64470,
SPELL_VOID_ZONE_VISUAL = 64469,
SPELL_BLACK_HOLE_CREDIT = 65312,
+ SPELL_BLACK_HOLE_DOT = 62169,
// Worm Hole
SPELL_WORM_HOLE_TRIGGER = 65251,
- SPELL_SUMMON_UNLEASHED_DARK_MATTER = 64450,
+ SPELL_SUMMON_UNLEASHED_DARK_MATTER = 64450
};
uint32 const PhasePunchAlphaId[5] = {64435, 64434, 64428, 64421, 64417};
@@ -111,104 +115,91 @@ uint32 const PhasePunchAlphaId[5] = {64435, 64434, 64428, 64421, 64417};
enum Events
{
// Celestial Planetarium Access
- EVENT_DESPAWN_CONSOLE = 1,
+ EVENT_DESPAWN_CONSOLE = 1,
// Brann Bronzebeard
- EVENT_BRANN_MOVE_INTRO = 2,
- EVENT_SUMMON_ALGALON = 3,
- EVENT_BRANN_OUTRO_1 = 4,
- EVENT_BRANN_OUTRO_2 = 5,
+ EVENT_BRANN_MOVE_INTRO,
+ EVENT_BRANN_SAY_INTRO_1,
+ EVENT_SUMMON_ALGALON,
+ EVENT_BRANN_OUTRO_1,
+ EVENT_BRANN_OUTRO_2,
// Algalon the Observer
- EVENT_INTRO_1 = 6,
- EVENT_INTRO_2 = 7,
- EVENT_INTRO_3 = 8,
- EVENT_INTRO_FINISH = 9,
- EVENT_START_COMBAT = 10,
- EVENT_INTRO_TIMER_DONE = 11,
- EVENT_QUANTUM_STRIKE = 12,
- EVENT_PHASE_PUNCH = 13,
- EVENT_SUMMON_COLLAPSING_STAR = 14,
- EVENT_BIG_BANG = 15,
- EVENT_RESUME_UPDATING = 16,
- EVENT_ASCEND_TO_THE_HEAVENS = 17,
- EVENT_EVADE = 18,
- EVENT_COSMIC_SMASH = 19,
- EVENT_UNLOCK_YELL = 20,
- EVENT_OUTRO_START = 21,
- EVENT_OUTRO_1 = 22,
- EVENT_OUTRO_2 = 23,
- EVENT_OUTRO_3 = 24,
- EVENT_OUTRO_4 = 25,
- EVENT_OUTRO_5 = 26,
- EVENT_OUTRO_6 = 27,
- EVENT_OUTRO_7 = 28,
- EVENT_OUTRO_8 = 29,
- EVENT_OUTRO_9 = 30,
- EVENT_OUTRO_10 = 31,
- EVENT_OUTRO_11 = 32,
- EVENT_OUTRO_12 = 33,
- EVENT_OUTRO_13 = 34,
- EVENT_OUTRO_14 = 35,
- EVENT_DESPAWN_ALGALON_1 = 36,
- EVENT_DESPAWN_ALGALON_2 = 37,
- EVENT_DESPAWN_ALGALON_3 = 38,
+ EVENT_INTRO_1,
+ EVENT_INTRO_2,
+ EVENT_SUMMON_AZEROTH,
+ EVENT_INTRO_3,
+ EVENT_INTRO_FINISH,
+ EVENT_START_COMBAT,
+ EVENT_INTRO_TIMER_DONE,
+ EVENT_QUANTUM_STRIKE,
+ EVENT_PHASE_PUNCH,
+ EVENT_SUMMON_COLLAPSING_STAR,
+ EVENT_BIG_BANG,
+ EVENT_RESUME_UPDATING,
+ EVENT_ASCEND_TO_THE_HEAVENS,
+ EVENT_EVADE,
+ EVENT_COSMIC_SMASH,
+ EVENT_UNLOCK_YELL,
+ EVENT_OUTRO_START,
+ EVENT_OUTRO_1,
+ EVENT_OUTRO_2,
+ EVENT_OUTRO_3,
+ EVENT_OUTRO_4,
+ EVENT_OUTRO_5,
+ EVENT_OUTRO_6,
+ EVENT_OUTRO_7,
+ EVENT_OUTRO_8,
+ EVENT_OUTRO_9,
+ EVENT_OUTRO_10,
+ EVENT_OUTRO_11,
+ EVENT_DESPAWN_ALGALON_1,
+ EVENT_DESPAWN_ALGALON_2,
+ EVENT_DESPAWN_ALGALON_3,
// Living Constellation
- EVENT_ARCANE_BARRAGE = 39,
+ EVENT_ARCANE_BARRAGE
};
enum Actions
{
- ACTION_START_INTRO = 0,
- ACTION_FINISH_INTRO = 1,
- ACTION_ACTIVATE_STAR = 2,
- ACTION_BIG_BANG = 3,
- ACTION_ASCEND = 4,
- ACTION_OUTRO = 5,
-};
-
-enum Points
-{
- POINT_BRANN_INTRO = 0,
- MAX_BRANN_WAYPOINTS_INTRO = 10,
- POINT_BRANN_OUTRO = 10,
- POINT_BRANN_OUTRO_END = 11,
-
- POINT_ALGALON_LAND = 1,
- POINT_ALGALON_OUTRO = 2,
+ ACTION_START_INTRO = 0,
+ ACTION_ACTIVATE_STAR,
+ ACTION_BIG_BANG,
+ ACTION_ASCEND,
+ ACTION_OUTRO,
+ ACTION_INTRO_2,
};
enum EncounterPhases
{
- PHASE_NORMAL = 0,
- PHASE_ROLE_PLAY = 1,
- PHASE_BIG_BANG = 2
+ PHASE_NORMAL = 0,
+ PHASE_ROLE_PLAY,
+ PHASE_BIG_BANG
};
enum AchievmentInfo
{
EVENT_ID_SUPERMASSIVE_START = 21697,
- DATA_HAS_FED_ON_TEARS = 30043005,
+ DATA_HAS_FED_ON_TEARS = 30043005
};
+enum AlgalonSplineMovements
+{
+ SPLINE_INITIAL_MOVE = 1,
+ SPLINE_ALGALON_ROOM = 2,
+ SPLINE_OUTRO_1 = 3,
+ SPLINE_OUTRO_2 = 4,
+ SPLINE_DESPAWN_INTRO_1 = 5
+};
-Position const BrannIntroSpawnPos = {1676.277f, -162.5308f, 427.3326f, 3.235537f};
-Position const BrannIntroWaypoint[MAX_BRANN_WAYPOINTS_INTRO] =
+enum AlgalonMovePoints
{
- {1642.482f, -164.0812f, 427.2602f, 0.0f},
- {1635.000f, -169.5145f, 427.2523f, 0.0f},
- {1632.814f, -173.9334f, 427.2621f, 0.0f},
- {1632.676f, -190.5927f, 425.8831f, 0.0f},
- {1631.497f, -214.2221f, 418.1152f, 0.0f},
- {1624.717f, -224.6876f, 418.1152f, 0.0f},
- {1631.497f, -214.2221f, 418.1152f, 0.0f},
- {1632.676f, -190.5927f, 425.8831f, 0.0f},
- {1632.814f, -173.9334f, 427.2621f, 0.0f},
- {1635.000f, -169.5145f, 427.2523f, 0.0f},
+ POINT_INITIAL_MOVE = 1,
+ POINT_ALGALON_ROOM,
+ POINT_DESPAWN,
+ POINT_ALGALON_OUTRO
};
-Position const AlgalonSummonPos = {1632.531f, -304.8516f, 450.1123f, 1.530165f};
-Position const AlgalonLandPos = {1632.668f, -302.7656f, 417.3211f, 1.530165f};
#define LIVING_CONSTELLATION_COUNT 11
Position const ConstellationPos[LIVING_CONSTELLATION_COUNT] =
@@ -223,7 +214,7 @@ Position const ConstellationPos[LIVING_CONSTELLATION_COUNT] =
{1592.242f, -325.5323f, 446.9508f, 0.226893f},
{1635.821f, -363.3442f, 424.3459f, 1.466077f},
{1672.188f, -357.2484f, 436.7337f, 2.338741f},
- {1615.800f, -348.0065f, 442.9586f, 1.134464f},
+ {1615.800f, -348.0065f, 442.9586f, 1.134464f}
};
#define COLLAPSING_STAR_COUNT 4
@@ -232,22 +223,19 @@ Position const CollapsingStarPos[COLLAPSING_STAR_COUNT] =
{1649.438f, -319.8127f, 418.3941f, 1.082104f},
{1647.005f, -288.6790f, 417.3955f, 3.490659f},
{1622.451f, -321.1563f, 417.6188f, 4.677482f},
- {1615.060f, -291.6816f, 417.7796f, 3.490659f},
+ {1615.060f, -291.6816f, 417.7796f, 3.490659f}
};
+
+Position const BrannIntroSpawnPos = { 1677.363f, -162.3514f, 427.332f, 3.191144f };
+Position const AlgalonSummonPos = { 1632.531f, -304.8516f, 450.1123f, 1.530165f };
+Position const AlgalonLandPos = { 1632.668f, -302.7656f, 417.3211f, 1.530165f };
Position const AlgalonOutroPos = {1633.64f, -317.78f, 417.3211f, 0.0f};
-Position const BrannOutroPos[3] =
-{
- {1632.023f, -243.7434f, 417.9118f, 0.0f},
- {1631.986f, -297.7831f, 417.3210f, 0.0f},
- {1633.832f, -216.2948f, 417.0463f, 0.0f},
-};
+Position const BrannOutroPos = { 1631.989f, -221.5439f, 418.4091f, 4.714909f };
class ActivateLivingConstellation : public BasicEvent
{
public:
- ActivateLivingConstellation(Unit* owner) : _owner(owner), _instance(owner->GetInstanceScript())
- {
- }
+ ActivateLivingConstellation(Unit* owner) : _owner(owner), _instance(owner->GetInstanceScript()) { }
bool Execute(uint64 execTime, uint32 /*diff*/) override
{
@@ -267,9 +255,7 @@ class ActivateLivingConstellation : public BasicEvent
class CosmicSmashDamageEvent : public BasicEvent
{
public:
- CosmicSmashDamageEvent(Unit* caster) : _caster(caster)
- {
- }
+ CosmicSmashDamageEvent(Unit* caster) : _caster(caster) { }
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
{
@@ -284,9 +270,7 @@ class CosmicSmashDamageEvent : public BasicEvent
class SummonUnleashedDarkMatter : public BasicEvent
{
public:
- SummonUnleashedDarkMatter(Unit* caster) : _caster(caster)
- {
- }
+ SummonUnleashedDarkMatter(Unit* caster) : _caster(caster) { }
bool Execute(uint64 execTime, uint32 /*diff*/) override
{
@@ -299,1097 +283,1002 @@ class SummonUnleashedDarkMatter : public BasicEvent
Unit* _caster;
};
-class boss_algalon_the_observer : public CreatureScript
+struct boss_algalon_the_observer : public BossAI
{
- public:
- boss_algalon_the_observer() : CreatureScript("boss_algalon_the_observer") { }
-
- struct boss_algalon_the_observerAI : public BossAI
+ boss_algalon_the_observer(Creature* creature) : BossAI(creature, BOSS_ALGALON)
+ {
+ Initialize();
+ _firstPull = true;
+ _fedOnTears = false;
+ }
+
+ void Initialize()
+ {
+ _phaseTwo = false;
+ _fightWon = false;
+ _hasYelled = false;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ me->SetReactState(REACT_PASSIVE);
+ Initialize();
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- boss_algalon_the_observerAI(Creature* creature) : BossAI(creature, BOSS_ALGALON)
+ case ACTION_START_INTRO:
{
- Initialize();
- _firstPull = true;
- _fedOnTears = false;
- }
+ me->AddUnitFlag2(UNIT_FLAG2_INSTANTLY_APPEAR_MODEL);
+ me->SetDisableGravity(true);
+ DoCastSelf(SPELL_ARRIVAL, true);
+ DoCastSelf(SPELL_RIDE_THE_LIGHTNING, true);
+ me->SetHomePosition(AlgalonLandPos);
- void Initialize()
- {
- _phaseTwo = false;
- _fightWon = false;
- _hasYelled = false;
- }
+ Movement::MoveSplineInit init(me);
+ init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ(), false);
+ init.SetOrientationFixed(true);
+ me->GetMotionMaster()->LaunchMoveSpline(std::move(init), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE);
- void Reset() override
- {
- _Reset();
- me->SetReactState(REACT_PASSIVE);
- Initialize();
- }
-
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- {
- _fedOnTears = true;
- if (!_hasYelled)
- {
- _hasYelled = true;
- events.ScheduleEvent(EVENT_UNLOCK_YELL, 1000);
- Talk(SAY_ALGALON_KILL);
- }
- }
- }
-
- void DoAction(int32 action) override
- {
- switch (action)
- {
- case ACTION_START_INTRO:
- {
- me->AddUnitFlag2(UNIT_FLAG2_INSTANTLY_APPEAR_MODEL);
- me->SetDisableGravity(true);
- DoCast(me, SPELL_ARRIVAL, true);
- DoCast(me, SPELL_RIDE_THE_LIGHTNING, true);
-
- me->SetHomePosition(AlgalonLandPos);
-
- Movement::MoveSplineInit init(me);
- init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ(), false);
- init.SetOrientationFixed(true);
- me->GetMotionMaster()->LaunchMoveSpline(std::move(init), POINT_ALGALON_LAND, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE);
-
- events.Reset();
- events.SetPhase(PHASE_ROLE_PLAY);
- events.ScheduleEvent(EVENT_INTRO_1, 5000, 0, PHASE_ROLE_PLAY);
- events.ScheduleEvent(EVENT_INTRO_2, 15000, 0, PHASE_ROLE_PLAY);
- events.ScheduleEvent(EVENT_INTRO_3, 23000, 0, PHASE_ROLE_PLAY);
- events.ScheduleEvent(EVENT_INTRO_FINISH, 36000, 0, PHASE_ROLE_PLAY);
- break;
- }
- case ACTION_ASCEND:
- events.SetPhase(PHASE_BIG_BANG);
- events.CancelEvent(EVENT_RESUME_UPDATING);
- events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1500);
- break;
- case EVENT_DESPAWN_ALGALON:
- events.Reset();
- events.SetPhase(PHASE_ROLE_PLAY);
- if (me->IsInCombat())
- events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1);
- events.ScheduleEvent(EVENT_DESPAWN_ALGALON_1, 5000);
- events.ScheduleEvent(EVENT_DESPAWN_ALGALON_2, 17000);
- events.ScheduleEvent(EVENT_DESPAWN_ALGALON_3, 26000);
- me->DespawnOrUnsummon(34000);
- me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- me->SetImmuneToNPC(true);
- break;
- case ACTION_INIT_ALGALON:
- _firstPull = false;
- me->SetImmuneToPC(false);
- break;
- }
- }
-
- uint32 GetData(uint32 type) const override
- {
- return type == DATA_HAS_FED_ON_TEARS ? _fedOnTears : 1;
- }
-
- void JustEngagedWith(Unit* /*target*/) override
- {
- uint32 introDelay = 0;
- me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- me->SetImmuneToNPC(true);
events.Reset();
events.SetPhase(PHASE_ROLE_PLAY);
-
- if (!_firstPull)
- {
- Talk(SAY_ALGALON_AGGRO);
- _JustEngagedWith();
- introDelay = 8000;
- }
- else
- {
- _firstPull = false;
- Talk(SAY_ALGALON_START_TIMER);
- if (Creature* brann = instance->GetCreature(DATA_BRANN_BRONZEBEARD_ALG))
- brann->AI()->DoAction(ACTION_FINISH_INTRO);
-
- me->setActive(true);
- me->SetFarVisible(true);
- DoZoneInCombat();
- introDelay = 26000;
- summons.DespawnEntry(NPC_AZEROTH);
- instance->SetData(EVENT_DESPAWN_ALGALON, 0);
- events.ScheduleEvent(EVENT_START_COMBAT, 18000);
- }
-
- events.ScheduleEvent(EVENT_INTRO_TIMER_DONE, introDelay);
- events.ScheduleEvent(EVENT_QUANTUM_STRIKE, 3500 + introDelay);
- events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500 + introDelay);
- events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 18000 + introDelay);
- events.ScheduleEvent(EVENT_BIG_BANG, 90000 + introDelay);
- events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 360000 + introDelay);
- events.ScheduleEvent(EVENT_COSMIC_SMASH, 25000 + introDelay);
-
- std::list<Creature*> stalkers;
- me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
- for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
- (*itr)->m_Events.KillAllEvents(true);
- }
-
- void MovementInform(uint32 movementType, uint32 pointId) override
- {
- if (movementType != POINT_MOTION_TYPE)
- return;
-
- if (pointId == POINT_ALGALON_LAND)
- me->SetDisableGravity(false);
- else if (pointId == POINT_ALGALON_OUTRO)
- {
- me->SetFacingTo(1.605703f);
- events.ScheduleEvent(EVENT_OUTRO_3, 1200);
- events.ScheduleEvent(EVENT_OUTRO_4, 2400);
- events.ScheduleEvent(EVENT_OUTRO_5, 8500);
- events.ScheduleEvent(EVENT_OUTRO_6, 15500);
- events.ScheduleEvent(EVENT_OUTRO_7, 55500);
- events.ScheduleEvent(EVENT_OUTRO_8, 73500);
- events.ScheduleEvent(EVENT_OUTRO_9, 85500);
- events.ScheduleEvent(EVENT_OUTRO_10, 108500);
- events.ScheduleEvent(EVENT_OUTRO_11, 123500);
- }
- }
-
- void JustSummoned(Creature* summon) override
- {
- summons.Summon(summon);
- switch (summon->GetEntry())
- {
- case NPC_AZEROTH:
- DoCastAOE(SPELL_REORIGINATION, true);
- break;
- case NPC_COLLAPSING_STAR:
- summon->SetReactState(REACT_PASSIVE);
- summon->GetMotionMaster()->MoveRandom(20.0f);
- summon->CastSpell(summon, SPELL_COLLAPSE, TRIGGERED_FULL_MASK);
- break;
- case NPC_BLACK_HOLE:
- summon->SetReactState(REACT_PASSIVE);
- summon->CastSpell(nullptr, SPELL_BLACK_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
- summon->CastSpell(summon, SPELL_CONSTELLATION_PHASE_TRIGGER, TRIGGERED_FULL_MASK);
- summon->CastSpell(nullptr, SPELL_BLACK_HOLE_EXPLOSION);
- summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
- break;
- case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER:
- summon->CastSpell(summon, SPELL_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
- break;
- case NPC_ALGALON_STALKER_ASTEROID_TARGET_01:
- summon->CastSpell(summon, SPELL_COSMIC_SMASH_VISUAL_STATE, TRIGGERED_FULL_MASK);
- break;
- case NPC_ALGALON_STALKER_ASTEROID_TARGET_02:
- summon->m_Events.AddEvent(new CosmicSmashDamageEvent(summon), summon->m_Events.CalculateTime(3250));
- break;
- case NPC_WORM_HOLE:
- summon->SetReactState(REACT_PASSIVE);
- summon->CastSpell(summon, SPELL_WORM_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
- summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
- break;
- case NPC_UNLEASHED_DARK_MATTER:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
- if (summon->Attack(target, true))
- summon->GetMotionMaster()->MoveChase(target);
- break;
- }
+ events.ScheduleEvent(EVENT_INTRO_1, 3s + 500ms, 0, PHASE_ROLE_PLAY);
+ break;
}
-
- void EnterEvadeMode(EvadeReason why) override
- {
- instance->SetBossState(BOSS_ALGALON, FAIL);
- BossAI::EnterEvadeMode(why);
+ case ACTION_ASCEND:
+ events.SetPhase(PHASE_BIG_BANG);
+ events.CancelEvent(EVENT_RESUME_UPDATING);
+ events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1s + 500ms);
+ break;
+ case EVENT_DESPAWN_ALGALON:
+ events.Reset();
+ events.SetPhase(PHASE_ROLE_PLAY);
+ if (me->IsInCombat())
+ events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1);
+ events.ScheduleEvent(EVENT_DESPAWN_ALGALON_1, 5s);
+ events.ScheduleEvent(EVENT_DESPAWN_ALGALON_2, 17s);
+ events.ScheduleEvent(EVENT_DESPAWN_ALGALON_3, 26s);
+ me->DespawnOrUnsummon(34s);
+ me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ me->SetImmuneToNPC(true);
+ break;
+ case ACTION_INIT_ALGALON:
+ _firstPull = false;
me->SetImmuneToPC(false);
- me->SetSheath(SHEATH_STATE_UNARMED);
- }
-
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (_fightWon)
- {
- damage = 0;
- return;
- }
-
- if (!_phaseTwo && me->HealthBelowPctDamaged(20, damage))
- {
- _phaseTwo = true;
- Talk(SAY_ALGALON_PHASE_TWO);
- summons.DespawnEntry(NPC_LIVING_CONSTELLATION);
- summons.DespawnEntry(NPC_COLLAPSING_STAR);
- summons.DespawnEntry(NPC_BLACK_HOLE);
- summons.DespawnEntry(NPC_ALGALON_VOID_ZONE_VISUAL_STALKER);
- events.CancelEvent(EVENT_SUMMON_COLLAPSING_STAR);
- std::list<Creature*> stalkers;
- me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
- for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
- (*itr)->m_Events.KillAllEvents(true);
- for (uint32 i = 0; i < COLLAPSING_STAR_COUNT; ++i)
- if (Creature* wormHole = DoSummon(NPC_WORM_HOLE, CollapsingStarPos[i], TEMPSUMMON_MANUAL_DESPAWN))
- wormHole->m_Events.AddEvent(new SummonUnleashedDarkMatter(wormHole), wormHole->m_Events.CalculateTime(i >= 2 ? 8000 : 6000));
- }
- else if ((int32(me->GetHealth()) - int32(damage)) < CalculatePct<int32>(int32(me->GetMaxHealth()), 2.5f) && !_fightWon)
- {
- _fightWon = true;
- damage = 0;
- me->SetReactState(REACT_PASSIVE);
- me->AttackStop();
- me->SetFaction(FACTION_FRIENDLY);
- me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- DoCast(me, SPELL_SELF_STUN);
- events.Reset();
- summons.DespawnAll();
- events.SetPhase(PHASE_ROLE_PLAY);
- events.ScheduleEvent(EVENT_OUTRO_START, 1500);
- events.ScheduleEvent(EVENT_OUTRO_1, 7200);
- events.ScheduleEvent(EVENT_OUTRO_2, 8700);
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!(events.IsInPhase(PHASE_ROLE_PLAY) || events.IsInPhase(PHASE_BIG_BANG)) && !UpdateVictim())
- return;
-
- events.Update(diff);
-
- if (!events.IsInPhase(PHASE_ROLE_PLAY))
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_INTRO_1:
- me->RemoveAurasDueToSpell(SPELL_RIDE_THE_LIGHTNING);
- Talk(SAY_ALGALON_INTRO_1);
- break;
- case EVENT_INTRO_2:
- DoCastAOE(SPELL_SUMMON_AZEROTH, true);
- Talk(SAY_ALGALON_INTRO_2);
- break;
- case EVENT_INTRO_3:
- Talk(SAY_ALGALON_INTRO_3);
- break;
- case EVENT_INTRO_FINISH:
- events.Reset();
- me->SetImmuneToPC(false);
- break;
- case EVENT_START_COMBAT:
- instance->SetBossState(BOSS_ALGALON, IN_PROGRESS);
- break;
- case EVENT_INTRO_TIMER_DONE:
- {
- events.SetPhase(PHASE_NORMAL);
- me->SetSheath(SHEATH_STATE_MELEE);
- me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- me->SetImmuneToNPC(false);
- me->SetReactState(REACT_DEFENSIVE);
- DoCastAOE(SPELL_SUPERMASSIVE_FAIL, true);
- //! Workaround for Creature::_IsTargetAcceptable returning false
- //! for creatures that start combat in REACT_PASSIVE and UNIT_FLAG_NOT_SELECTABLE
- //! causing them to immediately evade
- if (!me->GetThreatManager().IsThreatListEmpty())
- AttackStart(me->GetThreatManager().GetCurrentVictim());
- for (uint32 i = 0; i < LIVING_CONSTELLATION_COUNT; ++i)
- if (Creature* summon = DoSummon(NPC_LIVING_CONSTELLATION, ConstellationPos[i], 0, TEMPSUMMON_DEAD_DESPAWN))
- summon->SetReactState(REACT_PASSIVE);
-
- std::list<Creature*> stalkers;
- me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
- if (!stalkers.empty())
- {
- Unit* stalker = Trinity::Containers::SelectRandomContainerElement(stalkers);
- stalker->m_Events.AddEvent(new ActivateLivingConstellation(stalker), stalker->m_Events.CalculateTime(urand(45000, 50000)));
- }
- break;
- }
- case EVENT_QUANTUM_STRIKE:
- DoCastVictim(SPELL_QUANTUM_STRIKE);
- events.ScheduleEvent(EVENT_QUANTUM_STRIKE, urand(3000, 5000));
- break;
- case EVENT_PHASE_PUNCH:
- DoCastVictim(SPELL_PHASE_PUNCH);
- events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500);
- break;
- case EVENT_SUMMON_COLLAPSING_STAR:
- Talk(SAY_ALGALON_COLLAPSING_STAR);
- Talk(EMOTE_ALGALON_COLLAPSING_STAR);
- for (uint32 i = 0; i < COLLAPSING_STAR_COUNT; ++i)
- me->SummonCreature(NPC_COLLAPSING_STAR, CollapsingStarPos[i], TEMPSUMMON_CORPSE_DESPAWN);
- events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 60000);
- break;
- case EVENT_BIG_BANG:
- {
- Talk(SAY_ALGALON_BIG_BANG);
- Talk(EMOTE_ALGALON_BIG_BANG);
- events.SetPhase(PHASE_BIG_BANG);
- std::list<Creature*> constellations;
- me->GetCreatureListWithEntryInGrid(constellations, NPC_LIVING_CONSTELLATION, 200.0f);
- for (std::list<Creature*>::iterator itr = constellations.begin(); itr != constellations.end(); ++itr)
- (*itr)->AI()->DoAction(ACTION_BIG_BANG);
- DoCastAOE(SPELL_BIG_BANG);
- events.ScheduleEvent(EVENT_BIG_BANG, 90500);
- events.ScheduleEvent(EVENT_RESUME_UPDATING, 9500);
- break;
- }
- case EVENT_RESUME_UPDATING:
- events.SetPhase(0);
- break;
- case EVENT_ASCEND_TO_THE_HEAVENS:
- Talk(SAY_ALGALON_ASCEND);
- DoCastAOE(SPELL_ASCEND_TO_THE_HEAVENS);
- events.ScheduleEvent(EVENT_EVADE, 2500);
- break;
- case EVENT_EVADE:
- EnterEvadeMode(EVADE_REASON_OTHER);
- break;
- case EVENT_COSMIC_SMASH:
- Talk(EMOTE_ALGALON_COSMIC_SMASH);
- DoCastAOE(SPELL_COSMIC_SMASH);
- events.ScheduleEvent(EVENT_COSMIC_SMASH, 25500);
- break;
- case EVENT_UNLOCK_YELL:
- _hasYelled = false;
- break;
- case EVENT_OUTRO_START:
- instance->SetBossState(BOSS_ALGALON, DONE);
- break;
- case EVENT_OUTRO_1:
- me->RemoveAllAuras();
- me->AddUnitFlag(UNIT_FLAG_RENAME);
- break;
- case EVENT_OUTRO_2:
- _EnterEvadeMode();
- me->GetMotionMaster()->MovePoint(POINT_ALGALON_OUTRO, AlgalonOutroPos);
- break;
- case EVENT_OUTRO_3:
- DoCastAOE(SPELL_KILL_CREDIT);
- break;
- case EVENT_OUTRO_4:
- DoCastAOE(SPELL_SUPERMASSIVE_FAIL);
- me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- break;
- case EVENT_OUTRO_5:
- if (Creature* brann = DoSummon(NPC_BRANN_BRONZBEARD_ALG, BrannOutroPos[0], 131500, TEMPSUMMON_TIMED_DESPAWN))
- brann->AI()->DoAction(ACTION_OUTRO);
- break;
- case EVENT_OUTRO_6:
- Talk(SAY_ALGALON_OUTRO_1);
- me->SetStandState(UNIT_STAND_STATE_KNEEL);
- break;
- case EVENT_OUTRO_7:
- Talk(SAY_ALGALON_OUTRO_2);
- break;
- case EVENT_OUTRO_8:
- Talk(SAY_ALGALON_OUTRO_3);
- break;
- case EVENT_OUTRO_9:
- Talk(SAY_ALGALON_OUTRO_4);
- break;
- case EVENT_OUTRO_10:
- Talk(SAY_ALGALON_OUTRO_5);
- break;
- case EVENT_OUTRO_11:
- me->SetStandState(UNIT_STAND_STATE_STAND);
- DoCast(me, SPELL_TELEPORT);
- me->DespawnOrUnsummon(1500);
- break;
- }
-
- if (me->HasUnitState(UNIT_STATE_CASTING) && !events.IsInPhase(PHASE_ROLE_PLAY))
- return;
- }
-
- DoMeleeAttackIfReady();
- }
-
- private:
- bool _firstPull;
- bool _fedOnTears;
- bool _phaseTwo;
- bool _fightWon;
- bool _hasYelled;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+ break;
+ default:
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ return type == DATA_HAS_FED_ON_TEARS ? _fedOnTears : 1;
+ }
+
+ void JustEngagedWith(Unit* /*target*/) override
+ {
+ uint32 introDelay = 0;
+ me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ me->SetImmuneToNPC(true);
+ events.Reset();
+ events.SetPhase(PHASE_ROLE_PLAY);
+
+ if (!_firstPull)
{
- return GetUlduarAI<boss_algalon_the_observerAI>(creature);
+ Talk(SAY_ALGALON_AGGRO);
+ me->PlayDirectMusic(ENGAGE_MUSIC_ID);
+ _JustEngagedWith();
+ introDelay = 8000;
}
-};
-
-class npc_living_constellation : public CreatureScript
-{
- public:
- npc_living_constellation() : CreatureScript("npc_living_constellation") { }
-
- struct npc_living_constellationAI : public CreatureAI
+ else
{
- npc_living_constellationAI(Creature* creature) : CreatureAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- _isActive = false;
- }
-
- void Reset() override
- {
- _events.Reset();
- _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2500);
- Initialize();
- }
-
- uint32 GetData(uint32 /*type*/) const override
- {
- return _isActive ? 1 : 0;
- }
-
- void DoAction(int32 action) override
- {
- switch (action)
- {
- case ACTION_ACTIVATE_STAR:
- if (Creature* algalon = me->FindNearestCreature(NPC_ALGALON, 200.0f))
- {
- if (Unit* target = algalon->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(algalon)))
- {
- me->SetReactState(REACT_AGGRESSIVE);
- me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
- AttackStart(target);
- DoZoneInCombat();
- _isActive = true;
- }
- }
- break;
- case ACTION_BIG_BANG:
- _events.SetPhase(PHASE_BIG_BANG);
- _events.DelayEvents(9500);
- _events.ScheduleEvent(EVENT_RESUME_UPDATING, 9500);
- break;
- }
- }
-
- void SpellHit(Unit* caster, SpellInfo const* spell) override
- {
- if (spell->Id != SPELL_CONSTELLATION_PHASE_EFFECT || caster->GetTypeId() != TYPEID_UNIT)
- return;
-
- me->DespawnOrUnsummon(1);
- if (InstanceScript* instance = me->GetInstanceScript())
- instance->DoStartCriteriaTimer(CriteriaStartEvent::SendEvent, EVENT_ID_SUPERMASSIVE_START);
- caster->CastSpell(nullptr, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
- caster->ToCreature()->DespawnOrUnsummon(1);
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!(_events.IsInPhase(PHASE_ROLE_PLAY) || _events.IsInPhase(PHASE_BIG_BANG)) && !UpdateVictim())
- return;
-
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_ARCANE_BARRAGE:
- DoCastAOE(SPELL_ARCANE_BARRAGE);
- _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2500);
- break;
- case EVENT_RESUME_UPDATING:
- _events.SetPhase(0);
- break;
- }
- }
- }
-
- private:
- EventMap _events;
- bool _isActive;
- };
+ _firstPull = false;
+ Talk(SAY_ALGALON_START_TIMER);
+ me->InterruptNonMeleeSpells(false);
+ me->setActive(true);
+ me->SetFarVisible(true);
+ DoZoneInCombat();
+ introDelay = 26500;
+ summons.DespawnEntry(NPC_AZEROTH);
+ instance->SetData(EVENT_DESPAWN_ALGALON, 0);
+ events.ScheduleEvent(EVENT_START_COMBAT, 16s);
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ events.ScheduleEvent(EVENT_INTRO_TIMER_DONE, introDelay);
+ events.ScheduleEvent(EVENT_QUANTUM_STRIKE, 3500 + introDelay);
+ events.ScheduleEvent(EVENT_PHASE_PUNCH, 15500 + introDelay);
+ events.ScheduleEvent(EVENT_SUMMON_COLLAPSING_STAR, 18000 + introDelay);
+ events.ScheduleEvent(EVENT_BIG_BANG, 90000 + introDelay);
+ events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 360000 + introDelay);
+ events.ScheduleEvent(EVENT_COSMIC_SMASH, 25000 + introDelay);
+
+ std::list<Creature*> stalkers;
+ me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ (*itr)->m_Events.KillAllEvents(true);
+ }
+
+ void MovementInform(uint32 movementType, uint32 pointId) override
+ {
+ if (movementType != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId == POINT_ALGALON_OUTRO)
{
- return GetUlduarAI<npc_living_constellationAI>(creature);
+ me->SetFacingTo(1.605703f);
+ events.ScheduleEvent(EVENT_OUTRO_3, 1s);
}
-};
+ }
-class npc_collapsing_star : public CreatureScript
-{
- public:
- npc_collapsing_star() : CreatureScript("npc_collapsing_star") { }
-
- struct npc_collapsing_starAI : public PassiveAI
+ void JustSummoned(Creature* summon) override
+ {
+ summons.Summon(summon);
+ switch (summon->GetEntry())
{
- npc_collapsing_starAI(Creature* creature) : PassiveAI(creature)
- {
- _dying = false;
- }
-
- void JustSummoned(Creature* summon) override
- {
- if (summon->GetEntry() != NPC_BLACK_HOLE)
- return;
-
- if (TempSummon* summ = me->ToTempSummon())
- if (Creature* algalon = ObjectAccessor::GetCreature(*me, summ->GetSummonerGUID()))
- algalon->AI()->JustSummoned(summon);
-
- me->DespawnOrUnsummon(1);
- }
-
- void DamageTaken(Unit* /*attacker*/, uint32& damage) override
- {
- if (_dying)
- {
- damage = 0;
- return;
- }
-
- if (damage >= me->GetHealth())
- {
- _dying = true;
- damage = 0;
- DoCast(me, SPELL_BLACK_HOLE_SPAWN_VISUAL, true);
- DoCast(me, SPELL_SUMMON_BLACK_HOLE, true);
- }
- }
-
- bool _dying;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
+ case NPC_COLLAPSING_STAR:
+ summon->SetReactState(REACT_PASSIVE);
+ summon->GetMotionMaster()->MoveRandom(20.0f);
+ summon->CastSpell(summon, SPELL_COLLAPSE, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_ALGALON_VOID_ZONE_VISUAL_STALKER:
+ summon->CastSpell(summon, SPELL_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_ALGALON_STALKER_ASTEROID_TARGET_01:
+ summon->CastSpell(summon, SPELL_COSMIC_SMASH_VISUAL_STATE, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_ALGALON_STALKER_ASTEROID_TARGET_02:
+ summon->m_Events.AddEventAtOffset(new CosmicSmashDamageEvent(summon), 3s + 250ms);
+ break;
+ case NPC_WORM_HOLE:
+ summon->SetReactState(REACT_PASSIVE);
+ summon->CastSpell(summon, SPELL_WORM_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
+ summon->CastSpell(summon, SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
+ break;
+ case NPC_UNLEASHED_DARK_MATTER:
+ DoZoneInCombat(summon);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode(EvadeReason why) override
+ {
+ instance->SetBossState(BOSS_ALGALON, FAIL);
+ BossAI::EnterEvadeMode(why);
+ me->SetImmuneToPC(false);
+ me->SetSheath(SHEATH_STATE_UNARMED);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (_fightWon)
{
- return GetUlduarAI<npc_collapsing_starAI>(creature);
+ damage = 0;
+ return;
}
-};
-class npc_brann_bronzebeard_algalon : public CreatureScript
-{
- public:
- npc_brann_bronzebeard_algalon() : CreatureScript("npc_brann_bronzebeard_algalon") { }
-
- struct npc_brann_bronzebeard_algalonAI : public CreatureAI
+ if (!_phaseTwo && me->HealthBelowPctDamaged(20, damage))
{
- npc_brann_bronzebeard_algalonAI(Creature* creature) : CreatureAI(creature)
- {
- _currentPoint = 0;
- }
+ _phaseTwo = true;
+ Talk(SAY_ALGALON_PHASE_TWO);
+ summons.DespawnEntry(NPC_LIVING_CONSTELLATION);
+ summons.DespawnEntry(NPC_COLLAPSING_STAR);
+ summons.DespawnEntry(NPC_BLACK_HOLE);
+ summons.DespawnEntry(NPC_ALGALON_VOID_ZONE_VISUAL_STALKER);
+ events.CancelEvent(EVENT_SUMMON_COLLAPSING_STAR);
+ std::list<Creature*> stalkers;
+ me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
+ for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
+ (*itr)->m_Events.KillAllEvents(true);
+ for (uint8 i = 0; i < COLLAPSING_STAR_COUNT; ++i)
+ if (Creature* wormHole = DoSummon(NPC_WORM_HOLE, CollapsingStarPos[i], TEMPSUMMON_MANUAL_DESPAWN))
+ wormHole->m_Events.AddEventAtOffset(new SummonUnleashedDarkMatter(wormHole), i >= 2 ? 8s : 6s);
+ }
+ else if ((int32(me->GetHealth()) - int32(damage)) < CalculatePct<int32>(int32(me->GetMaxHealth()), 2.5f) && !_fightWon)
+ {
+ _fightWon = true;
+ damage = 0;
+ events.SetPhase(PHASE_ROLE_PLAY);
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->AddUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ DoCastSelf(SPELL_SELF_STUN);
+ events.Reset();
+ summons.DespawnAll();
+ events.ScheduleEvent(EVENT_OUTRO_START, 1s + 500ms);
+ events.ScheduleEvent(EVENT_OUTRO_1, 7s);
+ }
+ }
- void DoAction(int32 action) override
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ {
+ _fedOnTears = true;
+ if (!_hasYelled)
{
- switch (action)
- {
- case ACTION_START_INTRO:
- _currentPoint = 0;
- _events.Reset();
- me->SetWalk(false);
- _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1);
- break;
- case ACTION_FINISH_INTRO:
- Talk(SAY_BRANN_ALGALON_INTRO_2);
- _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 1);
- break;
- case ACTION_OUTRO:
- me->GetMotionMaster()->MovePoint(POINT_BRANN_OUTRO, BrannOutroPos[1]);
- _events.ScheduleEvent(EVENT_BRANN_OUTRO_1, 89500);
- _events.ScheduleEvent(EVENT_BRANN_OUTRO_2, 116500);
- break;
- }
+ _hasYelled = true;
+ events.ScheduleEvent(EVENT_UNLOCK_YELL, 1s);
+ Talk(SAY_ALGALON_KILL);
}
+ }
+ }
- void MovementInform(uint32 movementType, uint32 pointId) override
- {
- if (movementType != POINT_MOTION_TYPE)
- return;
+ void UpdateAI(uint32 diff) override
+ {
+ if (!(events.IsInPhase(PHASE_ROLE_PLAY) || events.IsInPhase(PHASE_BIG_BANG) || _fightWon) && !UpdateVictim())
+ return;
- uint32 delay = 1;
- _currentPoint = pointId + 1;
- switch (pointId)
- {
- case 2:
- delay = 8000;
- me->SetWalk(true);
- break;
- case 5:
- me->SetWalk(false);
- Talk(SAY_BRANN_ALGALON_INTRO_1);
- _events.ScheduleEvent(EVENT_SUMMON_ALGALON, 7500);
- return;
- case 9:
- me->DespawnOrUnsummon(1);
- return;
- case POINT_BRANN_OUTRO:
- case POINT_BRANN_OUTRO_END:
- return;
- }
+ events.Update(diff);
- _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, delay);
- }
+ if (!events.IsInPhase(PHASE_ROLE_PLAY))
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- UpdateVictim();
-
- if (_events.Empty())
- return;
-
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
+ case EVENT_INTRO_1:
+ me->RemoveAurasDueToSpell(SPELL_RIDE_THE_LIGHTNING);
+ Talk(SAY_ALGALON_INTRO_1);
+ events.ScheduleEvent(EVENT_SUMMON_AZEROTH, 6s, 0, PHASE_ROLE_PLAY);
+ break;
+ case EVENT_SUMMON_AZEROTH:
+ DoCastAOE(SPELL_SUMMON_AZEROTH, true);
+ if (Creature* azeroth = instance->GetCreature(DATA_AZEROTH))
+ if (TempSummon* summon = azeroth->ToTempSummon())
+ summon->SetTempSummonType(TEMPSUMMON_MANUAL_DESPAWN);
+ events.ScheduleEvent(EVENT_INTRO_2, 4s, 0, PHASE_ROLE_PLAY);
+ break;
+ case EVENT_INTRO_2:
+ me->SetDisableGravity(false);
+ Talk(SAY_ALGALON_INTRO_2);
+ DoCastAOE(SPELL_REORIGINATION, true);
+ events.ScheduleEvent(EVENT_INTRO_3, 8s + 500ms, 0, PHASE_ROLE_PLAY);
+ break;
+ case EVENT_INTRO_3:
+ Talk(SAY_ALGALON_INTRO_3);
+ events.ScheduleEvent(EVENT_INTRO_FINISH, 11s + 500ms, 0, PHASE_ROLE_PLAY);
+ break;
+ case EVENT_INTRO_FINISH:
+ events.Reset();
+ me->SetImmuneToPC(false);
+ if (Creature* brann = instance->GetCreature(DATA_BRANN_BRONZEBEARD_ALG))
+ brann->AI()->DoAction(ACTION_INTRO_2);
+ break;
+ case EVENT_START_COMBAT:
+ Talk(SAY_ALGALON_AGGRO);
+ me->PlayDirectMusic(ENGAGE_MUSIC_ID);
+ instance->SetBossState(BOSS_ALGALON, IN_PROGRESS);
+ break;
+ case EVENT_INTRO_TIMER_DONE:
{
- switch (eventId)
+ events.SetPhase(PHASE_NORMAL);
+ me->SetSheath(SHEATH_STATE_MELEE);
+ me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ me->SetImmuneToNPC(false);
+ me->SetReactState(REACT_DEFENSIVE);
+ DoCastAOE(SPELL_SUPERMASSIVE_FAIL, true);
+ //! Workaround for Creature::_IsTargetAcceptable returning false
+ //! for creatures that start combat in REACT_PASSIVE and UNIT_FLAG_NOT_SELECTABLE
+ //! causing them to immediately evade
+ if (!me->GetThreatManager().IsThreatListEmpty())
+ AttackStart(me->GetThreatManager().GetCurrentVictim());
+ for (uint8 i = 0; i < LIVING_CONSTELLATION_COUNT; ++i)
+ if (Creature* summon = DoSummon(NPC_LIVING_CONSTELLATION, ConstellationPos[i], 0, TEMPSUMMON_DEAD_DESPAWN))
+ summon->SetReactState(REACT_PASSIVE);
+
+ std::list<Creature*> stalkers;
+ me->GetCreatureListWithEntryInGrid(stalkers, NPC_ALGALON_STALKER, 200.0f);
+ if (!stalkers.empty())
{
- case EVENT_BRANN_MOVE_INTRO:
- if (_currentPoint < MAX_BRANN_WAYPOINTS_INTRO)
- me->GetMotionMaster()->MovePoint(_currentPoint, BrannIntroWaypoint[_currentPoint]);
- break;
- case EVENT_SUMMON_ALGALON:
- if (Creature* algalon = me->GetMap()->SummonCreature(NPC_ALGALON, AlgalonSummonPos))
- algalon->AI()->DoAction(ACTION_START_INTRO);
- break;
- case EVENT_BRANN_OUTRO_1:
- Talk(SAY_BRANN_ALGALON_OUTRO);
- break;
- case EVENT_BRANN_OUTRO_2:
- me->GetMotionMaster()->MovePoint(POINT_BRANN_OUTRO_END, BrannOutroPos[2]);
- break;
+ Unit* stalker = Trinity::Containers::SelectRandomContainerElement(stalkers);
+ stalker->m_Events.AddEventAtOffset(new ActivateLivingConstellation(stalker), 45s, 50s);
}
+ break;
}
+ case EVENT_QUANTUM_STRIKE:
+ DoCastVictim(SPELL_QUANTUM_STRIKE);
+ events.Repeat(3s, 5s);
+ break;
+ case EVENT_PHASE_PUNCH:
+ DoCastVictim(SPELL_PHASE_PUNCH);
+ events.Repeat(15s + 500ms);
+ break;
+ case EVENT_SUMMON_COLLAPSING_STAR:
+ Talk(SAY_ALGALON_COLLAPSING_STAR);
+ Talk(EMOTE_ALGALON_COLLAPSING_STAR);
+ for (uint8 i = 0; i < COLLAPSING_STAR_COUNT; ++i)
+ me->SummonCreature(NPC_COLLAPSING_STAR, CollapsingStarPos[i], TEMPSUMMON_CORPSE_DESPAWN);
+ events.Repeat(60s);
+ break;
+ case EVENT_BIG_BANG:
+ {
+ Talk(SAY_ALGALON_BIG_BANG);
+ Talk(EMOTE_ALGALON_BIG_BANG);
+ events.SetPhase(PHASE_BIG_BANG);
+ std::list<Creature*> constellations;
+ me->GetCreatureListWithEntryInGrid(constellations, NPC_LIVING_CONSTELLATION, 200.0f);
+ for (std::list<Creature*>::iterator itr = constellations.begin(); itr != constellations.end(); ++itr)
+ (*itr)->AI()->DoAction(ACTION_BIG_BANG);
+ DoCastAOE(SPELL_BIG_BANG);
+ events.Repeat(1min + 30s + 500ms);
+ events.ScheduleEvent(EVENT_RESUME_UPDATING, 9s + 500ms);
+ break;
+ }
+ case EVENT_RESUME_UPDATING:
+ events.SetPhase(PHASE_NORMAL);
+ break;
+ case EVENT_ASCEND_TO_THE_HEAVENS:
+ Talk(SAY_ALGALON_ASCEND);
+ DoCastAOE(SPELL_ASCEND_TO_THE_HEAVENS);
+ events.ScheduleEvent(EVENT_EVADE, 2s + 500ms);
+ break;
+ case EVENT_EVADE:
+ EnterEvadeMode(EVADE_REASON_OTHER);
+ break;
+ case EVENT_COSMIC_SMASH:
+ Talk(EMOTE_ALGALON_COSMIC_SMASH);
+ DoCastAOE(SPELL_COSMIC_SMASH);
+ events.Repeat(25s + 500ms);
+ break;
+ case EVENT_UNLOCK_YELL:
+ _hasYelled = false;
+ break;
+ case EVENT_OUTRO_START:
+ instance->SetBossState(BOSS_ALGALON, DONE);
+ break;
+ case EVENT_OUTRO_1:
+ me->RemoveAllAuras();
+ ResetThreatList();
+ me->SetFaction(FACTION_FRIENDLY);
+ me->AddUnitFlag(UNIT_FLAG_RENAME);
+ events.ScheduleEvent(EVENT_OUTRO_2, 2s);
+ break;
+ case EVENT_OUTRO_2:
+ me->SetRegenerateHealth(false);
+ me->CombatStop();
+ me->GetMotionMaster()->MovePoint(POINT_ALGALON_OUTRO, AlgalonOutroPos);
+ break;
+ case EVENT_OUTRO_3:
+ DoCastAOE(SPELL_KILL_CREDIT);
+ events.ScheduleEvent(EVENT_OUTRO_4, 1s + 400ms);
+ events.ScheduleEvent(EVENT_OUTRO_5, 4s + 500ms);
+ break;
+ case EVENT_OUTRO_4:
+ DoCastAOE(SPELL_SUPERMASSIVE_FAIL);
+ me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ break;
+ case EVENT_OUTRO_5:
+ if (Creature* brann = me->SummonCreature(NPC_BRANN_BRONZBEARD_ALG, BrannOutroPos))
+ brann->AI()->DoAction(ACTION_OUTRO);
+ events.ScheduleEvent(EVENT_OUTRO_6, 10s);
+ break;
+ case EVENT_OUTRO_6:
+ Talk(SAY_ALGALON_OUTRO_1);
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ events.ScheduleEvent(EVENT_OUTRO_7, 39s);
+ break;
+ case EVENT_OUTRO_7:
+ Talk(SAY_ALGALON_OUTRO_2);
+ events.ScheduleEvent(EVENT_OUTRO_8, 18s);
+ break;
+ case EVENT_OUTRO_8:
+ Talk(SAY_ALGALON_OUTRO_3);
+ events.ScheduleEvent(EVENT_OUTRO_9, 12s);
+ break;
+ case EVENT_OUTRO_9:
+ Talk(SAY_ALGALON_OUTRO_4);
+ events.ScheduleEvent(EVENT_OUTRO_10, 24s);
+ break;
+ case EVENT_OUTRO_10:
+ Talk(SAY_ALGALON_OUTRO_5);
+ events.ScheduleEvent(EVENT_OUTRO_11, 15s);
+ break;
+ case EVENT_OUTRO_11:
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ DoCastSelf(SPELL_TELEPORT);
+ me->DespawnOrUnsummon(1s + 200ms);
+ break;
+ case EVENT_DESPAWN_ALGALON_1:
+ Talk(SAY_ALGALON_DESPAWN_1);
+ break;
+ case EVENT_DESPAWN_ALGALON_2:
+ Talk(SAY_ALGALON_DESPAWN_2);
+ break;
+ case EVENT_DESPAWN_ALGALON_3:
+ Talk(SAY_ALGALON_DESPAWN_3);
+ break;
+ default:
+ break;
}
- private:
- EventMap _events;
- uint32 _currentPoint;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetUlduarAI<npc_brann_bronzebeard_algalonAI>(creature);
+ if (me->HasUnitState(UNIT_STATE_CASTING) && !events.IsInPhase(PHASE_ROLE_PLAY))
+ return;
}
+
+ DoMeleeAttackIfReady();
+ }
+
+private:
+ bool _firstPull;
+ bool _fedOnTears;
+ bool _phaseTwo;
+ bool _fightWon;
+ bool _hasYelled;
};
-class go_celestial_planetarium_access : public GameObjectScript
+struct npc_living_constellation : public CreatureAI
{
- public:
- go_celestial_planetarium_access() : GameObjectScript("go_celestial_planetarium_access") { }
-
- struct go_celestial_planetarium_accessAI : public GameObjectAI
+ npc_living_constellation(Creature* creature) : CreatureAI(creature), _instance(creature->GetInstanceScript())
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ _isActive = false;
+ }
+
+ void Reset() override
+ {
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, 2s + 500ms);
+ Initialize();
+ }
+
+ uint32 GetData(uint32 /*type*/) const override
+ {
+ return _isActive ? 1 : 0;
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- go_celestial_planetarium_accessAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { }
-
- InstanceScript* instance;
-
- bool OnReportUse(Player* player) override
- {
- if (me->HasFlag(GO_FLAG_IN_USE))
- return true;
-
- bool hasKey = true;
- if (LockEntry const* lock = sLockStore.LookupEntry(me->GetGOInfo()->GetLockId()))
+ case ACTION_ACTIVATE_STAR:
+ if (Creature* algalon = _instance->GetCreature(BOSS_ALGALON))
{
- hasKey = false;
- for (uint32 i = 0; i < MAX_LOCK_CASE; ++i)
+ if (Unit* target = algalon->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(algalon)))
{
- if (!lock->Index[i])
- continue;
-
- if (player->HasItemCount(lock->Index[i]))
- {
- hasKey = true;
- break;
- }
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
+ AttackStart(target);
+ DoZoneInCombat();
+ _isActive = true;
}
}
+ break;
+ case ACTION_BIG_BANG:
+ _events.SetPhase(PHASE_BIG_BANG);
+ _events.DelayEvents(9s + 500ms);
+ _events.ScheduleEvent(EVENT_RESUME_UPDATING, 9s + 500ms);
+ break;
+ default:
+ break;
+ }
+ }
- if (!hasKey)
- return false;
+ void SpellHit(Unit* caster, SpellInfo const* spell) override
+ {
+ if (spell->Id != SPELL_CONSTELLATION_PHASE_EFFECT || caster->GetTypeId() != TYPEID_UNIT)
+ return;
- // Start Algalon event
- me->AddFlag(GO_FLAG_IN_USE);
- _events.ScheduleEvent(EVENT_DESPAWN_CONSOLE, 5000);
- if (Creature* brann = me->SummonCreature(NPC_BRANN_BRONZBEARD_ALG, BrannIntroSpawnPos))
- brann->AI()->DoAction(ACTION_START_INTRO);
+ _instance->DoStartCriteriaTimer(CriteriaStartEvent::SendEvent, EVENT_ID_SUPERMASSIVE_START);
+ caster->CastSpell(nullptr, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
+ DoCast(caster, SPELL_DESPAWN_BLACK_HOLE, TRIGGERED_FULL_MASK);
+ me->DespawnOrUnsummon(500ms);
+ }
- instance->SetData(DATA_ALGALON_SUMMON_STATE, 1);
- if (GameObject* sigil = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SIGILDOOR_01)))
- sigil->SetGoState(GO_STATE_ACTIVE);
+ void UpdateAI(uint32 diff) override
+ {
+ if (!(_events.IsInPhase(PHASE_ROLE_PLAY) || _events.IsInPhase(PHASE_BIG_BANG)) && !UpdateVictim())
+ return;
- if (GameObject* sigil = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SIGILDOOR_02)))
- sigil->SetGoState(GO_STATE_ACTIVE);
+ _events.Update(diff);
- return false;
- }
-
- void UpdateAI(uint32 diff) override
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- if (_events.Empty())
- return;
-
- _events.Update(diff);
-
- while (uint32 eventId = _events.ExecuteEvent())
+ case EVENT_ARCANE_BARRAGE:
{
- switch (eventId)
- {
- case EVENT_DESPAWN_CONSOLE:
- me->Delete();
- break;
- }
+ DoCastAOE(SPELL_ARCANE_BARRAGE, { SPELLVALUE_MAX_TARGETS, 1 });
+ me->ClearUnitState(UNIT_STATE_CASTING);
+ _events.Repeat(4s, 5s);
+ break;
}
+ case EVENT_RESUME_UPDATING:
+ _events.SetPhase(PHASE_NORMAL);
+ break;
}
-
- EventMap _events;
- };
-
- GameObjectAI* GetAI(GameObject* go) const override
- {
- return GetUlduarAI<go_celestial_planetarium_accessAI>(go);
}
-};
+ }
-class spell_algalon_phase_punch : public SpellScriptLoader
-{
- public:
- spell_algalon_phase_punch() : SpellScriptLoader("spell_algalon_phase_punch") { }
-
- class spell_algalon_phase_punch_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_algalon_phase_punch_AuraScript);
-
- void HandlePeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- if (GetStackAmount() != 1)
- GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]);
- GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK);
- if (GetStackAmount() == 5)
- Remove(AURA_REMOVE_BY_DEFAULT);
- }
-
- void OnRemove(AuraEffect const*, AuraEffectHandleModes)
- {
- if (GetStackAmount() != 5)
- GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]);
- }
-
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_algalon_phase_punch_AuraScript();
- }
+private:
+ EventMap _events;
+ bool _isActive;
+ InstanceScript* _instance;
};
-class NotVictimFilter
+struct npc_black_hole : public ScriptedAI
{
- public:
- NotVictimFilter(Unit* caster) : _victim(caster->GetVictim())
+ npc_black_hole(Creature* creature) : ScriptedAI(creature), _summons(creature) { }
+
+ void Reset() override
+ {
+ me->SetReactState(REACT_PASSIVE);
+ DoCastAOE(SPELL_BLACK_HOLE_TRIGGER, TRIGGERED_FULL_MASK);
+ DoCastSelf(SPELL_CONSTELLATION_PHASE_TRIGGER, TRIGGERED_FULL_MASK);
+ DoCastAOE(SPELL_BLACK_HOLE_EXPLOSION, TRIGGERED_FULL_MASK);
+ DoCastSelf(SPELL_SUMMON_VOID_ZONE_VISUAL, TRIGGERED_FULL_MASK);
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ _summons.Summon(summon);
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
+ {
+ if (spell->Id == SPELL_DESPAWN_BLACK_HOLE)
{
+ _summons.DespawnAll();
+ me->DespawnOrUnsummon(1);
}
+ }
- bool operator()(WorldObject* target)
- {
- return target != _victim;
- }
+ void EnterEvadeMode(EvadeReason /*why*/) override { }
- private:
- Unit* _victim;
+private:
+ SummonList _summons;
};
-class spell_algalon_arcane_barrage : public SpellScriptLoader
+struct npc_collapsing_star : public PassiveAI
{
- public:
- spell_algalon_arcane_barrage() : SpellScriptLoader("spell_algalon_arcane_barrage") { }
+ npc_collapsing_star(Creature* creature) : PassiveAI(creature), _dying(false), _instance(creature->GetInstanceScript()) { }
- class spell_algalon_arcane_barrage_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_algalon_arcane_barrage_SpellScript);
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() != NPC_BLACK_HOLE)
+ return;
- void SelectTarget(std::list<WorldObject*>& targets)
- {
- targets.remove_if(NotVictimFilter(GetCaster()));
- }
+ if (Creature* algalon = _instance->GetCreature(BOSS_ALGALON))
+ algalon->AI()->JustSummoned(summon);
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_arcane_barrage_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- }
- };
+ me->DespawnOrUnsummon(1);
+ }
- SpellScript* GetSpellScript() const override
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (_dying)
{
- return new spell_algalon_arcane_barrage_SpellScript();
+ damage = 0;
+ return;
}
-};
-class ActiveConstellationFilter
-{
- public:
- bool operator()(WorldObject* target) const
+ if (damage >= me->GetHealth())
{
- return target->ToUnit() && target->ToUnit()->GetAI() && target->ToUnit()->GetAI()->GetData(0);
+ _dying = true;
+ damage = 0;
+ DoCastSelf(SPELL_BLACK_HOLE_SPAWN_VISUAL, true);
+ DoCastSelf(SPELL_SUMMON_BLACK_HOLE, true);
}
+ }
+
+private:
+ bool _dying;
+ InstanceScript* _instance;
};
-class spell_algalon_trigger_3_adds : public SpellScriptLoader
+struct npc_brann_bronzebeard_algalon : public CreatureAI
{
- public:
- spell_algalon_trigger_3_adds() : SpellScriptLoader("spell_algalon_trigger_3_adds") { }
+ npc_brann_bronzebeard_algalon(Creature* creature) : CreatureAI(creature) { }
- class spell_algalon_trigger_3_adds_SpellScript : public SpellScript
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- PrepareSpellScript(spell_algalon_trigger_3_adds_SpellScript);
-
- void SelectTarget(std::list<WorldObject*>& targets)
- {
- targets.remove_if(ActiveConstellationFilter());
- }
-
- void HandleDummy(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- Creature* target = GetHitCreature();
- if (!target)
- return;
-
- target->AI()->DoAction(ACTION_ACTIVATE_STAR);
- }
+ case ACTION_START_INTRO:
+ _events.Reset();
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_INITIAL_MOVE, SPLINE_INITIAL_MOVE, false);
+ break;
+ case ACTION_OUTRO:
+ me->GetMotionMaster()->MoveAlongSplineChain(0, SPLINE_OUTRO_1, false);
+ _events.ScheduleEvent(EVENT_BRANN_OUTRO_1, 1min + 32s + 200ms);
+ _events.ScheduleEvent(EVENT_BRANN_OUTRO_2, 2min);
+ break;
+ case ACTION_INTRO_2:
+ Talk(SAY_BRANN_ALGALON_INTRO_2);
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_DESPAWN, SPLINE_DESPAWN_INTRO_1, true);
+ break;
+ default:
+ break;
+ }
+ }
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
- OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE && type != SPLINE_CHAIN_MOTION_TYPE)
+ return;
- SpellScript* GetSpellScript() const override
+ switch (pointId)
{
- return new spell_algalon_trigger_3_adds_SpellScript();
+ case POINT_INITIAL_MOVE:
+ _events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 4s);
+ break;
+ case POINT_ALGALON_ROOM:
+ me->SetFacingTo(4.714909f);
+ _events.ScheduleEvent(EVENT_BRANN_SAY_INTRO_1, 500ms);
+ break;
+ case POINT_DESPAWN:
+ me->DespawnOrUnsummon();
+ break;
+ default:
+ break;
}
-};
+ }
-class spell_algalon_collapse : public SpellScriptLoader
-{
- public:
- spell_algalon_collapse() : SpellScriptLoader("spell_algalon_collapse") { }
-
- class spell_algalon_collapse_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_algalon_collapse_AuraScript);
+ void UpdateAI(uint32 diff) override
+ {
+ if (_events.Empty())
+ return;
- void HandlePeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE);
- }
+ _events.Update(diff);
- void Register() override
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ case EVENT_BRANN_MOVE_INTRO:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_ALGALON_ROOM, SPLINE_ALGALON_ROOM, true);
+ break;
+ case EVENT_BRANN_SAY_INTRO_1:
+ Talk(SAY_BRANN_ALGALON_INTRO_1);
+ _events.ScheduleEvent(EVENT_SUMMON_ALGALON, 8s + 300ms);
+ break;
+ case EVENT_SUMMON_ALGALON:
+ if (Creature* algalon = me->GetMap()->SummonCreature(NPC_ALGALON, AlgalonSummonPos))
+ algalon->AI()->DoAction(ACTION_START_INTRO);
+ break;
+ case EVENT_BRANN_OUTRO_1:
+ Talk(SAY_BRANN_ALGALON_OUTRO);
+ break;
+ case EVENT_BRANN_OUTRO_2:
+ me->GetMotionMaster()->MoveAlongSplineChain(POINT_DESPAWN, SPLINE_OUTRO_2, false);
+ break;
+ default:
+ break;
}
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_algalon_collapse_AuraScript();
}
+ }
+
+private:
+ EventMap _events;
};
-class spell_algalon_big_bang : public SpellScriptLoader
+struct go_celestial_planetarium_access : public GameObjectAI
{
- public:
- spell_algalon_big_bang() : SpellScriptLoader("spell_algalon_big_bang") { }
+ go_celestial_planetarium_access(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
- class spell_algalon_big_bang_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_algalon_big_bang_SpellScript);
+ bool OnReportUse(Player* player) override
+ {
+ if (me->HasFlag(GO_FLAG_IN_USE))
+ return true;
- public:
- spell_algalon_big_bang_SpellScript()
+ bool hasKey = true;
+ if (LockEntry const* lock = sLockStore.LookupEntry(me->GetGOInfo()->GetLockId()))
+ {
+ hasKey = false;
+ for (uint8 i = 0; i < MAX_LOCK_CASE; ++i)
{
- _targetCount = 0;
- }
+ if (!lock->Index[i])
+ continue;
- private:
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_UNIT;
- }
-
- void CountTargets(std::list<WorldObject*>& targets)
- {
- _targetCount = targets.size();
+ if (player->HasItemCount(lock->Index[i]))
+ {
+ hasKey = true;
+ break;
+ }
}
+ }
- void CheckTargets()
- {
- if (!_targetCount)
- GetCaster()->GetAI()->DoAction(ACTION_ASCEND);
- }
+ if (!hasKey)
+ return false;
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- AfterCast += SpellCastFn(spell_algalon_big_bang_SpellScript::CheckTargets);
- }
+ // Start Algalon event
+ me->AddFlag(GO_FLAG_IN_USE);
+ _events.ScheduleEvent(EVENT_DESPAWN_CONSOLE, 5000);
+ if (Creature* brann = me->SummonCreature(NPC_BRANN_BRONZBEARD_ALG, BrannIntroSpawnPos))
+ brann->AI()->DoAction(ACTION_START_INTRO);
- uint32 _targetCount;
- };
+ _instance->SetData(DATA_ALGALON_SUMMON_STATE, 1);
+ if (GameObject* sigil = _instance->GetGameObject(DATA_SIGILDOOR_01))
+ sigil->SetGoState(GO_STATE_ACTIVE);
- SpellScript* GetSpellScript() const override
- {
- return new spell_algalon_big_bang_SpellScript();
- }
-};
+ if (GameObject* sigil = _instance->GetGameObject(DATA_SIGILDOOR_02))
+ sigil->SetGoState(GO_STATE_ACTIVE);
-class spell_algalon_remove_phase : public SpellScriptLoader
-{
- public:
- spell_algalon_remove_phase() : SpellScriptLoader("spell_algalon_remove_phase") { }
+ return false;
+ }
- class spell_algalon_remove_phase_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_algalon_remove_phase_AuraScript);
+ void UpdateAI(uint32 diff) override
+ {
+ if (_events.Empty())
+ return;
- void HandlePeriodic(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE);
- }
+ _events.Update(diff);
- void Register() override
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
{
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ case EVENT_DESPAWN_CONSOLE:
+ me->Delete();
+ break;
+ default:
+ break;
}
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_algalon_remove_phase_AuraScript();
}
+ }
+
+private:
+ EventMap _events;
+ InstanceScript* _instance;
};
-// 62295 - Cosmic Smash
-class spell_algalon_cosmic_smash : public SpellScriptLoader
+// 64412 - Phase Punch
+class spell_algalon_phase_punch : public AuraScript
{
- public:
- spell_algalon_cosmic_smash() : SpellScriptLoader("spell_algalon_cosmic_smash") { }
-
- class spell_algalon_cosmic_smash_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_algalon_cosmic_smash_SpellScript);
-
- void ModDestHeight(SpellDestination& dest)
- {
- Position const offset = { 0.0f, 0.0f, 65.0f, 0.0f };
- dest.RelocateOffset(offset);
- }
-
- void Register() override
- {
- OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_algalon_cosmic_smash_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_SUMMON);
- }
- };
+ PrepareAuraScript(spell_algalon_phase_punch);
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ if (GetStackAmount() != 1)
+ GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]);
+ GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK);
+ if (GetStackAmount() == 5)
+ Remove(AURA_REMOVE_BY_DEFAULT);
+ }
+
+ void OnRemove(AuraEffect const*, AuraEffectHandleModes)
+ {
+ if (GetStackAmount() != 5)
+ GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+};
- SpellScript* GetSpellScript() const override
- {
- return new spell_algalon_cosmic_smash_SpellScript();
- }
+// 65508 - Constellation Phase Trigger
+class spell_algalon_phase_constellation : public AuraScript
+{
+ PrepareAuraScript(spell_algalon_phase_constellation);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return !spellInfo->GetEffects().empty() && ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell });
+ }
+
+ void HandlePeriodic(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+ CastSpellExtraArgs args(aurEff);
+ args.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1);
+ // Phase Effect should only 1 target. Avoid 1 black hole despawn multiple Living Constellation
+ GetTarget()->CastSpell(nullptr, GetSpellInfo()->GetEffect(EFFECT_0).TriggerSpell, args);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_constellation::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
};
-class spell_algalon_cosmic_smash_damage : public SpellScriptLoader
+// 62266 - Trigger 3 Adds
+class spell_algalon_trigger_3_adds : public SpellScript
{
- public:
- spell_algalon_cosmic_smash_damage() : SpellScriptLoader("spell_algalon_cosmic_smash_damage") { }
+ PrepareSpellScript(spell_algalon_trigger_3_adds);
- class spell_algalon_cosmic_smash_damage_SpellScript : public SpellScript
+ void SelectTarget(std::list<WorldObject*>& targets)
+ {
+ // Remove Living Constellation already actived
+ targets.remove_if([](WorldObject* target) -> bool
{
- PrepareSpellScript(spell_algalon_cosmic_smash_damage_SpellScript);
-
- void RecalculateDamage()
- {
- if (!GetExplTargetDest() || !GetHitUnit())
- return;
-
- float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY());
- if (distance > 6.0f)
- SetHitDamage(int32(float(GetHitDamage()) / distance) * 2);
- }
-
- void Register() override
- {
- OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage_SpellScript::RecalculateDamage);
- }
- };
+ return target->ToUnit() && target->ToUnit()->GetAI() && target->ToUnit()->GetAI()->GetData(0);
+ });
+ }
+
+ void HandleDummy(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Creature* target = GetHitCreature())
+ target->AI()->DoAction(ACTION_ACTIVATE_STAR);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+};
- SpellScript* GetSpellScript() const override
- {
- return new spell_algalon_cosmic_smash_damage_SpellScript();
- }
+// 62018 - Collapse
+class spell_algalon_collapse : public AuraScript
+{
+ PrepareAuraScript(spell_algalon_collapse);
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
};
-class spell_algalon_supermassive_fail : public SpellScriptLoader
+// 64443, 64584 - Big Bang
+class spell_algalon_big_bang : public SpellScript
{
- public:
- spell_algalon_supermassive_fail() : SpellScriptLoader("spell_algalon_supermassive_fail") { }
+ PrepareSpellScript(spell_algalon_big_bang);
+
+ bool Load() override
+ {
+ _targetCount = 0;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void CountTargets(std::list<WorldObject*>& targets)
+ {
+ _targetCount = targets.size();
+ }
+
+ void CheckTargets()
+ {
+ if (!_targetCount)
+ GetCaster()->GetAI()->DoAction(ACTION_ASCEND);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ AfterCast += SpellCastFn(spell_algalon_big_bang::CheckTargets);
+ }
+private:
+ uint32 _targetCount;
+};
- class spell_algalon_supermassive_fail_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_algalon_supermassive_fail_SpellScript);
+// 64445 - Remove Player from Phase
+class spell_algalon_remove_phase : public AuraScript
+{
+ PrepareAuraScript(spell_algalon_remove_phase);
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+};
- void RecalculateDamage()
- {
- if (!GetHitPlayer())
- return;
+// 62295 - Cosmic Smash
+class spell_algalon_cosmic_smash : public SpellScript
+{
+ PrepareSpellScript(spell_algalon_cosmic_smash);
+
+ void ModDestHeight(SpellDestination& dest)
+ {
+ // Meteor should spawn below the platform
+ Position const offset = { 0.0f, 0.0f, -36.1325f, 0.0f };
+ dest.RelocateOffset(offset);
+ }
+
+ void Register() override
+ {
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_algalon_cosmic_smash::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_SUMMON);
+ }
+};
- GetHitPlayer()->ResetCriteria(CriteriaFailEvent::BeSpellTarget, GetSpellInfo()->Id, true);
- }
+// 62311, 64596 - Cosmic Smash
+class spell_algalon_cosmic_smash_damage : public SpellScript
+{
+ PrepareSpellScript(spell_algalon_cosmic_smash_damage);
+
+ void RecalculateDamage()
+ {
+ if (!GetExplTargetDest() || !GetHitUnit())
+ return;
+
+ float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY());
+ if (distance > 6.0f)
+ SetHitDamage(int32(float(GetHitDamage()) / distance) * 2);
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage::RecalculateDamage);
+ }
+};
- void Register() override
- {
- OnHit += SpellHitFn(spell_algalon_supermassive_fail_SpellScript::RecalculateDamage);
- }
- };
+// 65311 - Supermassive Fail
+class spell_algalon_supermassive_fail : public SpellScript
+{
+ PrepareSpellScript(spell_algalon_supermassive_fail);
+
+ void RecalculateDamage()
+ {
+ if (Player* player = GetHitPlayer())
+ player->ResetCriteria(CriteriaFailEvent::BeSpellTarget, GetSpellInfo()->Id, true);
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_algalon_supermassive_fail::RecalculateDamage);
+ }
+};
- SpellScript* GetSpellScript() const override
- {
- return new spell_algalon_supermassive_fail_SpellScript();
- }
+// 62168 - Black Hole (Phase Shifts)
+// 65250 - Worm Hole (Phase Shifts)
+// 64417 - Phase Punch (Phase Shifts)
+class spell_algalon_black_hole_phase_shifts : public AuraScript
+{
+ PrepareAuraScript(spell_algalon_black_hole_phase_shifts);
+
+ bool Load() override
+ {
+ return GetUnitOwner()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_BLACK_HOLE_DOT });
+ }
+
+ void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_BLACK_HOLE_DOT, true);
+ }
+
+ void Register() override
+ {
+ OnEffectApply += AuraEffectApplyFn(spell_algalon_black_hole_phase_shifts::HandleEffectApply, EFFECT_0, SPELL_AURA_PHASE, AURA_EFFECT_HANDLE_REAL);
+ }
};
void AddSC_boss_algalon_the_observer()
{
- new boss_algalon_the_observer();
- new npc_living_constellation();
- new npc_collapsing_star();
- new npc_brann_bronzebeard_algalon();
- new go_celestial_planetarium_access();
- new spell_algalon_phase_punch();
- new spell_algalon_arcane_barrage();
- new spell_algalon_trigger_3_adds();
- new spell_algalon_collapse();
- new spell_algalon_big_bang();
- new spell_algalon_remove_phase();
- new spell_algalon_cosmic_smash();
- new spell_algalon_cosmic_smash_damage();
- new spell_algalon_supermassive_fail();
+ RegisterUlduarCreatureAI(boss_algalon_the_observer);
+ RegisterUlduarCreatureAI(npc_living_constellation);
+ RegisterUlduarCreatureAI(npc_black_hole);
+ RegisterUlduarCreatureAI(npc_collapsing_star);
+ RegisterUlduarCreatureAI(npc_brann_bronzebeard_algalon);
+ RegisterGameObjectAI(go_celestial_planetarium_access);
+ RegisterAuraScript(spell_algalon_phase_punch);
+ RegisterAuraScript(spell_algalon_phase_constellation);
+ RegisterSpellScript(spell_algalon_trigger_3_adds);
+ RegisterAuraScript(spell_algalon_collapse);
+ RegisterSpellScript(spell_algalon_big_bang);
+ RegisterAuraScript(spell_algalon_remove_phase);
+ RegisterSpellScript(spell_algalon_cosmic_smash);
+ RegisterSpellScript(spell_algalon_cosmic_smash_damage);
+ RegisterSpellScript(spell_algalon_supermassive_fail);
+ RegisterAuraScript(spell_algalon_black_hole_phase_shifts);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index c34a889f1d4..5d064f9b2ed 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -116,23 +116,31 @@ ObjectData const creatureData[] =
{ NPC_HIGH_EXPLORER_DELLORAH, DATA_DELLORAH },
{ NPC_BRONZEBEARD_RADIO, DATA_BRONZEBEARD_RADIO },
{ NPC_HEART_OF_DECONSTRUCTOR, DATA_XT002_HEART },
+ { NPC_AZEROTH, DATA_AZEROTH },
{ 0, 0, }
};
ObjectData const objectData[] =
{
- { GO_MIMIRON_ELEVATOR, DATA_MIMIRON_ELEVATOR },
- { GO_MIMIRON_BUTTON, DATA_MIMIRON_BUTTON },
- { GO_DOODAD_UL_UNIVERSEGLOBE01, DATA_UNIVERSE_GLOBE },
- { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, DATA_ALGALON_TRAPDOOR },
- { GO_RAZOR_HARPOON_1, GO_RAZOR_HARPOON_1 },
- { GO_RAZOR_HARPOON_2, GO_RAZOR_HARPOON_2 },
- { GO_RAZOR_HARPOON_3, GO_RAZOR_HARPOON_3 },
- { GO_RAZOR_HARPOON_4, GO_RAZOR_HARPOON_4 },
- { GO_THORIM_LEVER, DATA_THORIM_LEVER },
- { GO_THORIM_STONE_DOOR, DATA_STONE_DOOR },
- { GO_THORIM_RUNIC_DOOR, DATA_RUNIC_DOOR },
- { 0, 0 }
+ { GO_MIMIRON_ELEVATOR, DATA_MIMIRON_ELEVATOR },
+ { GO_MIMIRON_BUTTON, DATA_MIMIRON_BUTTON },
+ { GO_DOODAD_UL_UNIVERSEGLOBE01, DATA_UNIVERSE_GLOBE },
+ { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, DATA_ALGALON_TRAPDOOR },
+ { GO_RAZOR_HARPOON_1, GO_RAZOR_HARPOON_1 },
+ { GO_RAZOR_HARPOON_2, GO_RAZOR_HARPOON_2 },
+ { GO_RAZOR_HARPOON_3, GO_RAZOR_HARPOON_3 },
+ { GO_RAZOR_HARPOON_4, GO_RAZOR_HARPOON_4 },
+ { GO_THORIM_LEVER, DATA_THORIM_LEVER },
+ { GO_THORIM_STONE_DOOR, DATA_STONE_DOOR },
+ { GO_THORIM_RUNIC_DOOR, DATA_RUNIC_DOOR },
+ { GO_DOODAD_UL_SIGILDOOR_01, DATA_SIGILDOOR_01 },
+ { GO_DOODAD_UL_SIGILDOOR_02, DATA_SIGILDOOR_02 },
+ { GO_DOODAD_UL_SIGILDOOR_03, DATA_SIGILDOOR_03 },
+ { GO_DOODAD_UL_UNIVERSEFLOOR_01, DATA_UNIVERSE_FLOOR_01 },
+ { GO_DOODAD_UL_UNIVERSEFLOOR_02, DATA_UNIVERSE_FLOOR_02 },
+ { GO_GIFT_OF_THE_OBSERVER_10, DATA_GIFT_OF_THE_OBSERVER },
+ { GO_GIFT_OF_THE_OBSERVER_25, DATA_GIFT_OF_THE_OBSERVER },
+ { 0, 0 }
};
class instance_ulduar : public InstanceMapScript
@@ -195,10 +203,6 @@ class instance_ulduar : public InstanceMapScript
ObjectGuid MimironTramGUID;
ObjectGuid BrainRoomDoorGUIDs[3];
- ObjectGuid AlgalonSigilDoorGUID[3];
- ObjectGuid AlgalonFloorGUID[2];
-
- ObjectGuid GiftOfTheObserverGUID;
// Miscellaneous
uint32 TeamInInstance;
@@ -270,14 +274,6 @@ class instance_ulduar : public InstanceMapScript
{
InstanceScript::OnCreatureCreate(creature);
- if (!TeamInInstance)
- {
- Map::PlayerList const& Players = instance->GetPlayers();
- if (!Players.isEmpty())
- if (Player* player = Players.begin()->GetSource())
- TeamInInstance = player->GetTeam();
- }
-
switch (creature->GetEntry())
{
case NPC_SALVAGED_DEMOLISHER:
@@ -315,50 +311,6 @@ class instance_ulduar : public InstanceMapScript
AddMinion(creature, true);
break;
- // Hodir
- case NPC_EIVI_NIGHTFEATHER:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_TOR_GREYCLOUD);
- break;
- case NPC_ELLIE_NIGHTFEATHER:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_KAR_GREYCLOUD);
- break;
- case NPC_ELEMENTALIST_MAHFUUN:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_SPIRITWALKER_TARA);
- break;
- case NPC_ELEMENTALIST_AVUUN:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_SPIRITWALKER_YONA);
- break;
- case NPC_MISSY_FLAMECUFFS:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_AMIRA_BLAZEWEAVER);
- break;
- case NPC_SISSY_FLAMECUFFS:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_VEESHA_BLAZEWEAVER);
- break;
- case NPC_FIELD_MEDIC_PENNY:
- if (TeamInInstance == HORDE)
- creature->UpdateEntry(NPC_BATTLE_PRIEST_ELIZA);
- break;
- case NPC_FIELD_MEDIC_JESSI:
- if (TeamInInstance == HORDE)
- 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();
@@ -435,6 +387,44 @@ class instance_ulduar : public InstanceMapScript
InstanceScript::OnCreatureCreate(creature);
}
+ uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
+ {
+ if (!TeamInInstance)
+ {
+ Map::PlayerList const& Players = instance->GetPlayers();
+ if (!Players.isEmpty())
+ if (Player* player = Players.begin()->GetSource())
+ TeamInInstance = player->GetTeam();
+ }
+
+ uint32 entry = data->id;
+ switch (entry)
+ {
+ case NPC_EIVI_NIGHTFEATHER:
+ return TeamInInstance == HORDE ? NPC_TOR_GREYCLOUD : NPC_EIVI_NIGHTFEATHER;
+ case NPC_ELLIE_NIGHTFEATHER:
+ return TeamInInstance == HORDE ? NPC_KAR_GREYCLOUD : NPC_ELLIE_NIGHTFEATHER;
+ case NPC_ELEMENTALIST_MAHFUUN:
+ return TeamInInstance == HORDE ? NPC_SPIRITWALKER_TARA : NPC_ELEMENTALIST_MAHFUUN;
+ case NPC_ELEMENTALIST_AVUUN:
+ return TeamInInstance == HORDE ? NPC_SPIRITWALKER_YONA : NPC_ELEMENTALIST_AVUUN;
+ case NPC_MISSY_FLAMECUFFS:
+ return TeamInInstance == HORDE ? NPC_AMIRA_BLAZEWEAVER : NPC_MISSY_FLAMECUFFS;
+ case NPC_SISSY_FLAMECUFFS:
+ return TeamInInstance == HORDE ? NPC_VEESHA_BLAZEWEAVER : NPC_SISSY_FLAMECUFFS;
+ case NPC_FIELD_MEDIC_PENNY:
+ return TeamInInstance == HORDE ? NPC_BATTLE_PRIEST_ELIZA : NPC_FIELD_MEDIC_PENNY;
+ case NPC_FIELD_MEDIC_JESSI:
+ return TeamInInstance == HORDE ? NPC_BATTLE_PRIEST_GINA : NPC_FIELD_MEDIC_JESSI;
+ case NPC_MERCENARY_CAPTAIN_H:
+ return TeamInInstance == HORDE ? NPC_MERCENARY_CAPTAIN_A : NPC_MERCENARY_CAPTAIN_H;
+ case NPC_MERCENARY_SOLDIER_H:
+ return TeamInInstance == HORDE ? NPC_MERCENARY_SOLDIER_A : NPC_MERCENARY_SOLDIER_H;
+ default:
+ return entry;
+ }
+ }
+
void OnCreatureRemove(Creature* creature) override
{
InstanceScript::OnCreatureRemove(creature);
@@ -518,28 +508,10 @@ class instance_ulduar : public InstanceMapScript
gameObject->AddFlag(GO_FLAG_IN_USE);
break;
case GO_DOODAD_UL_SIGILDOOR_01:
- AlgalonSigilDoorGUID[0] = gameObject->GetGUID();
- if (_algalonSummoned)
- gameObject->SetGoState(GO_STATE_ACTIVE);
- break;
case GO_DOODAD_UL_SIGILDOOR_02:
- AlgalonSigilDoorGUID[1] = gameObject->GetGUID();
if (_algalonSummoned)
gameObject->SetGoState(GO_STATE_ACTIVE);
break;
- case GO_DOODAD_UL_SIGILDOOR_03:
- AlgalonSigilDoorGUID[2] = gameObject->GetGUID();
- break;
- case GO_DOODAD_UL_UNIVERSEFLOOR_01:
- AlgalonFloorGUID[0] = gameObject->GetGUID();
- break;
- case GO_DOODAD_UL_UNIVERSEFLOOR_02:
- AlgalonFloorGUID[1] = gameObject->GetGUID();
- break;
- case GO_GIFT_OF_THE_OBSERVER_10:
- case GO_GIFT_OF_THE_OBSERVER_25:
- GiftOfTheObserverGUID = gameObject->GetGUID();
- break;
default:
break;
}
@@ -715,8 +687,8 @@ class instance_ulduar : public InstanceMapScript
_events.CancelEvent(EVENT_DESPAWN_ALGALON);
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
_algalonTimer = 61;
- if (GameObject* gameObject = instance->GetGameObject(GiftOfTheObserverGUID))
- gameObject->SetRespawnTime(gameObject->GetRespawnDelay());
+ if (GameObject* gift = GetGameObject(DATA_GIFT_OF_THE_OBSERVER))
+ gift->SetRespawnTime(gift->GetRespawnDelay());
// get item level (recheck weapons)
Map::PlayerList const& players = instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
@@ -858,18 +830,6 @@ class instance_ulduar : public InstanceMapScript
return KeeperGUIDs[2];
case DATA_MIMIRON_YS:
return KeeperGUIDs[3];
-
- // Algalon
- case DATA_SIGILDOOR_01:
- return AlgalonSigilDoorGUID[0];
- case DATA_SIGILDOOR_02:
- return AlgalonSigilDoorGUID[1];
- case DATA_SIGILDOOR_03:
- return AlgalonSigilDoorGUID[2];
- case DATA_UNIVERSE_FLOOR_01:
- return AlgalonFloorGUID[0];
- case DATA_UNIVERSE_FLOOR_02:
- return AlgalonFloorGUID[1];
}
return InstanceScript::GetGuidData(data);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index 1e6e77b6c71..d332dad74a4 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -452,6 +452,8 @@ enum UlduarData
DATA_UNIVERSE_GLOBE,
DATA_ALGALON_TRAPDOOR,
DATA_BRANN_BRONZEBEARD_ALG,
+ DATA_GIFT_OF_THE_OBSERVER,
+ DATA_AZEROTH,
// Thorim
DATA_SIF,