aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp1
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Spells/Spell.cpp3
-rw-r--r--src/server/game/Spells/SpellMgr.cpp11
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp3227
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp55
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp389
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h96
9 files changed, 3633 insertions, 153 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index f8add7e8691..3872f9154b9 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -7773,6 +7773,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
Aura* charge = GetAura(50241);
if (charge && charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL))
RemoveAurasDueToSpell(50240);
+ break;
}
}
break;
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index edabc7b4284..5f5024729ca 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -445,6 +445,7 @@ void AddSC_ulduar_teleporter();
void AddSC_boss_mimiron();
void AddSC_boss_hodir();
void AddSC_boss_freya();
+void AddSC_boss_yogg_saron();
void AddSC_boss_algalon_the_observer();
void AddSC_instance_ulduar();
void AddSC_boss_keleseth(); //Utgarde Keep
@@ -1184,6 +1185,7 @@ void AddNorthrendScripts()
AddSC_boss_mimiron();
AddSC_boss_hodir();
AddSC_boss_freya();
+ AddSC_boss_yogg_saron();
AddSC_boss_algalon_the_observer();
AddSC_instance_ulduar();
AddSC_boss_keleseth(); //Utgarde Keep
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 8f887cebe38..dfec24f3996 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2633,7 +2633,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
{
// for delayed spells ignore negative spells (after duel end) for friendly targets
/// @todo this cause soul transfer bugged
- if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->IsPositive())
+ // 63881 - Malady of the Mind jump spell (Yogg-Saron)
+ if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->IsPositive() && m_spellInfo->Id != 63881)
return SPELL_MISS_EVADE;
// assisting case, healing and resurrection
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 66f7121adf3..026c61d4965 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -84,6 +84,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto,
// ToC Icehowl Arctic Breath
else if (spellproto->SpellVisual[0] == 14153)
return DIMINISHING_NONE;
+ // Black Plague
+ else if (spellproto->Id == 64155)
+ return DIMINISHING_NONE;
break;
}
// Event spells
@@ -3327,6 +3330,14 @@ void SpellMgr::LoadDbcDataCorrections()
// that will be clear if we get more spells with problem like this
spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY;
break;
+ case 61791: // Ride Vehicle (Yogg-Saron)
+ // TODO: remove this when basepoints of all Ride Vehicle auras are calculated correctly
+ spellInfo->EffectBasePoints[0] = 1;
+ break;
+ case 64468: // Empowering Shadows (Yogg-Saron)
+ case 64486: // Empowering Shadows (Yogg-Saron)
+ spellInfo->MaxAffectedTargets = 3; // same for both modes?
+ break;
case 62301: // Cosmic Smash (Algalon the Observer)
spellInfo->MaxAffectedTargets = 1;
break;
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index 1da1e4ab178..674c35836a2 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -26,7 +26,7 @@ set(scripts_STAT_SRCS
Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
Northrend/Ulduar/Ulduar/instance_ulduar.cpp
Northrend/Ulduar/Ulduar/boss_auriaya.cpp
- Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp
+ Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
Northrend/Ulduar/Ulduar/boss_hodir.cpp
Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp
Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
new file mode 100644
index 00000000000..57f50e7ad39
--- /dev/null
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -0,0 +1,3227 @@
+/*
+ * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "PassiveAI.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "MoveSplineInit.h"
+#include "CreatureTextMgr.h"
+#include "ulduar.h"
+
+enum Yells
+{
+ // Sara
+ SAY_SARA_ULDUAR_SCREAM_1 = 0, // screams randomly in a whole instance, unused on retail
+ SAY_SARA_ULDUAR_SCREAM_2 = 1, // screams randomly in a whole instance, unused on retail
+ SAY_SARA_AGGRO = 2,
+ SAY_SARA_FERVOR_HIT = 3,
+ SAY_SARA_BLESSING_HIT = 4,
+ SAY_SARA_KILL = 5,
+ SAY_SARA_TRANSFORM_1 = 6,
+ SAY_SARA_TRANSFORM_2 = 7,
+ SAY_SARA_TRANSFORM_3 = 8,
+ SAY_SARA_TRANSFORM_4 = 9,
+ SAY_SARA_DEATH_RAY = 10,
+ SAY_SARA_PSYCHOSIS_HIT = 11,
+
+ // Yogg-Saron
+ SAY_YOGG_SARON_SPAWN = 0,
+ SAY_YOGG_SARON_MADNESS = 1,
+ EMOTE_YOGG_SARON_MADNESS = 2,
+ SAY_YOGG_SARON_PHASE_3 = 3,
+ SAY_YOGG_SARON_DEAFENING_ROAR = 4,
+ EMOTE_YOGG_SARON_DEAFENING_ROAR = 5,
+ SAY_YOGG_SARON_DEATH = 6,
+ EMOTE_YOGG_SARON_EMPOWERING_SHADOWS = 7,
+ EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE = 8,
+
+ // Voice of Yogg-Saron
+ WHISPER_VOICE_PHASE_1_WIPE = 0,
+ WHISPER_VOICE_INSANE = 1,
+
+ // Brain of Yogg-Saron
+ EMOTE_BRAIN_ILLUSION_SHATTERED = 0,
+
+ // Ominous Cloud
+ EMOTE_OMINOUS_CLOUD_PLAYER_TOUCH = 0,
+
+ // Keepers
+ SAY_KEEPER_CHOSEN_1 = 0,
+ SAY_KEEPER_CHOSEN_2 = 1,
+
+ // Yogg-Saron illusions
+ SAY_STORMWIND_ROLEPLAY_4 = 0,
+ SAY_STORMWIND_ROLEPLAY_7 = 1,
+ SAY_ICECROWN_ROLEPLAY_5 = 2,
+ SAY_ICECROWN_ROLEPLAY_6 = 3,
+ SAY_CHAMBER_ROLEPLAY_5 = 4,
+
+ // Neltharion
+ SAY_CHAMBER_ROLEPLAY_1 = 0,
+ SAY_CHAMBER_ROLEPLAY_3 = 1,
+
+ // Ysera
+ SAY_CHAMBER_ROLEPLAY_2 = 0,
+
+ // Malygos
+ SAY_CHAMBER_ROLEPLAY_4 = 0,
+
+ // Immolated Champion
+ SAY_ICECROWN_ROLEPLAY_1 = 0,
+ SAY_ICECROWN_ROLEPLAY_3 = 1,
+
+ // The Lich King
+ SAY_ICECROWN_ROLEPLAY_2 = 0,
+ SAY_ICECROWN_ROLEPLAY_4 = 1,
+
+ // Garona
+ SAY_STORMWIND_ROLEPLAY_1 = 0,
+ SAY_STORMWIND_ROLEPLAY_2 = 1,
+ SAY_STORMWIND_ROLEPLAY_3 = 2,
+ SAY_STORMWIND_ROLEPLAY_6 = 3,
+
+ // King Llane
+ SAY_STORMWIND_ROLEPLAY_5 = 0,
+};
+
+enum Spells
+{
+ // Voice of Yogg-Saron
+ SPELL_SUMMON_GUARDIAN_2 = 62978,
+ SPELL_SANITY_PERIODIC = 63786,
+ SPELL_SANITY = 63050,
+ SPELL_INSANE_PERIODIC = 64554,
+ SPELL_INSANE = 63120,
+ //SPELL_CLEAR_INSANE = 63122, // when it should be casted?
+ SPELL_CONSTRICTOR_TENTACLE = 64132,
+ SPELL_CRUSHER_TENTACLE_SUMMON = 64139,
+ SPELL_CORRUPTOR_TENTACLE_SUMMON = 64143,
+ SPELL_IMMORTAL_GUARDIAN = 64158,
+
+ // Sara
+ SPELL_SARAS_FERVOR = 63138,
+ SPELL_SARAS_FERVOR_TARGET_SELECTOR = 63747,
+ SPELL_SARAS_BLESSING = 63134,
+ SPELL_SARAS_BLESSING_TARGET_SELECTOR = 63745,
+ SPELL_SARAS_ANGER = 63147,
+ SPELL_SARAS_ANGER_TARGET_SELECTOR = 63744,
+ SPELL_FULL_HEAL = 43978,
+ SPELL_PHASE_2_TRANSFORM = 65157,
+ SPELL_SHADOWY_BARRIER_SARA = 64775,
+ SPELL_RIDE_YOGG_SARON_VEHICLE = 61791,
+ SPELL_PSYCHOSIS = 63795,
+ SPELL_MALADY_OF_THE_MIND = 63830,
+ SPELL_BRAIN_LINK = 63802,
+ SPELL_BRAIN_LINK_DAMAGE = 63803, // red beam
+ SPELL_BRAIN_LINK_NO_DAMAGE = 63804, // yellow beam
+ SPELL_DEATH_RAY = 63891,
+
+ // Ominous Cloud
+ SPELL_OMINOUS_CLOUD_VISUAL = 63084,
+ SPELL_SUMMON_GUARDIAN_1 = 63031,
+
+ // Guardian of Yogg-Saron
+ SPELL_DARK_VOLLEY = 63038,
+ SPELL_SHADOW_NOVA = 62714,
+ SPELL_SHADOW_NOVA_2 = 65719,
+
+ // Yogg-Saron
+ SPELL_EXTINGUISH_ALL_LIFE = 64166,
+ SPELL_SHADOWY_BARRIER_YOGG = 63894,
+ SPELL_KNOCK_AWAY = 64022,
+ SPELL_PHASE_3_TRANSFORM = 63895,
+ SPELL_DEAFENING_ROAR = 64189,
+ SPELL_LUNATIC_GAZE = 64163,
+ SPELL_LUNATIC_GAZE_DAMAGE = 64164,
+ SPELL_SHADOW_BEACON = 64465,
+
+ // Brain of Yogg-Saron
+ SPELL_MATCH_HEALTH = 64066,
+ SPELL_MATCH_HEALTH_2 = 64069,
+ SPELL_INDUCE_MADNESS = 64059,
+ SPELL_BRAIN_HURT_VISUAL = 64361,
+ SPELL_SHATTERED_ILLUSION = 64173,
+ SPELL_SHATTERED_ILLUSION_REMOVE = 65238,
+
+ // Tentacles
+ SPELL_ERUPT = 64144,
+ SPELL_TENTACLE_VOID_ZONE = 64017, // used by Corruptor Tentacle and Crusher Tentacle only
+
+ // Crusher Tentacle
+ SPELL_DIMINISH_POWER = 64145,
+ SPELL_DIMINSH_POWER = 64148,
+ SPELL_FOCUSED_ANGER = 57688,
+ SPELL_CRUSH = 64146,
+ //SPELL_CRUSH_2 = 65201, // triggered by SPELL_CRUSH, basepoints of SPELL_MALADY_OF_THE_MIND
+
+ // Constrictor Tentacle
+ SPELL_TENTACLE_VOID_ZONE_2 = 64384,
+ SPELL_LUNGE = 64131,
+
+ // Corruptor Tentacle
+ SPELL_APATHY = 64156,
+ SPELL_BLACK_PLAGUE = 64153,
+ SPELL_CURSE_OF_DOOM = 64157,
+ SPELL_DRAINING_POISON = 64152,
+
+ // Immortal Guardian
+ SPELL_EMPOWERING_SHADOWS = 64468,
+ SPELL_EMPOWERED = 64161,
+ SPELL_EMPOWERED_BUFF = 65294,
+ SPELL_WEAKENED = 64162,
+ SPELL_DRAIN_LIFE = 64159,
+ SPELL_RECENTLY_SPAWNED = 64497,
+ SPELL_SIMPLE_TELEPORT = 64195,
+
+ // Keepers at Observation Ring
+ SPELL_TELEPORT = 62940,
+
+ // Keepers
+ SPELL_SIMPLE_TELEPORT_KEEPERS = 12980,
+ SPELL_KEEPER_ACTIVE = 62647,
+
+ // Mimiron
+ SPELL_SPEED_OF_INVENTION = 62671,
+ SPELL_DESTABILIZATION_MATRIX = 65206,
+
+ // Freya
+ SPELL_RESILIENCE_OF_NATURE = 62670,
+ SPELL_SANITY_WELL_SUMMON = 64170,
+
+ // Sanity Well
+ SPELL_SANITY_WELL_VISUAL = 63288,
+ SPELL_SANITY_WELL = 64169,
+
+ // Thorim
+ SPELL_FURY_OF_THE_STORM = 62702,
+ SPELL_TITANIC_STORM = 64171,
+
+ // Hodir
+ SPELL_FORTITUDE_OF_FROST = 62650,
+ SPELL_HODIRS_PROTECTIVE_GAZE = 64174,
+ SPELL_FLASH_FREEZE_VISUAL = 64176,
+
+ // Death Orb
+ SPELL_DEATH_RAY_ORIGIN_VISUAL = 63893,
+
+ // Death Ray
+ SPELL_DEATH_RAY_WARNING_VISUAL = 63882,
+ SPELL_DEATH_RAY_PERIODIC = 63883,
+ SPELL_DEATH_RAY_DAMAGE_VISUAL = 63886,
+
+ // Laughing Skull
+ SPELL_LUNATIC_GAZE_SKULL = 64167,
+
+ // Descend Into Madness
+ SPELL_TELEPORT_PORTAL_VISUAL = 64416,
+
+ // Illusions
+ SPELL_GRIM_REPRISAL = 63305,
+ SPELL_GRIM_REPRISAL_DAMAGE = 64039,
+
+ // Suit of Armor
+ SPELL_NONDESCRIPT_1 = 64013,
+
+ // Dragon Consorts & Deathsworn Zealot
+ SPELL_NONDESCRIPT_2 = 64010,
+
+ // Garona
+ SPELL_ASSASSINATE = 64063,
+
+ // King Llane
+ SPELL_PERMANENT_FEIGN_DEATH = 29266,
+
+ // The Lich King
+ SPELL_DEATHGRASP = 63037,
+
+ // Turned Champion
+ SPELL_VERTEX_COLOR_BLACK = 39662,
+
+ // Player self cast spells
+ SPELL_MALADY_OF_THE_MIND_JUMP = 63881,
+ SPELL_ILLUSION_ROOM = 63988,
+ SPELL_HATE_TO_ZERO = 63984,
+ SPELL_TELEPORT_BACK_TO_MAIN_ROOM = 63992,
+ SPELL_INSANE_VISUAL = 64464,
+ SPELL_CONSTRICTOR_TENTACLE_SUMMON = 64133,
+ SPELL_SQUEEZE = 64125,
+ SPELL_FLASH_FREEZE = 64175,
+ SPELL_LOW_SANITY_SCREEN_EFFECT = 63752,
+
+ SPELL_IN_THE_MAWS_OF_THE_OLD_GOD = 64184,
+};
+
+enum Phases
+{
+ PHASE_ONE = 1,
+ PHASE_TRANSFORM = 2,
+ PHASE_TWO = 3,
+ PHASE_THREE = 4,
+};
+
+enum Events
+{
+ // Voice of Yogg-Saron
+ EVENT_LOCK_DOOR = 1,
+ EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON = 2,
+ EVENT_SUMMON_CORRUPTOR_TENTACLE = 3,
+ EVENT_SUMMON_CONSTRICTOR_TENTACLE = 4,
+ EVENT_SUMMON_CRUSHER_TENTACLE = 5,
+ EVENT_ILLUSION = 6,
+ EVENT_SUMMON_IMMORTAL_GUARDIAN = 7,
+ EVENT_EXTINGUISH_ALL_LIFE = 8, // handled by Voice, timer starts at the beginning of the fight (Yogg-Saron is not spawned at this moment)
+
+ // Sara
+ EVENT_SARAS_FERVOR = 9,
+ EVENT_SARAS_BLESSING = 10,
+ EVENT_SARAS_ANGER = 11,
+ EVENT_TRANSFORM_1 = 12,
+ EVENT_TRANSFORM_2 = 13,
+ EVENT_TRANSFORM_3 = 14,
+ EVENT_TRANSFORM_4 = 15,
+ EVENT_PSYCHOSIS = 16,
+ EVENT_MALADY_OF_THE_MIND = 17,
+ EVENT_BRAIN_LINK = 18,
+ EVENT_DEATH_RAY = 19,
+
+ // Tentacles
+ EVENT_DIMINISH_POWER = 20,
+ EVENT_CAST_RANDOM_SPELL = 21,
+
+ // Yogg-Saron
+ EVENT_YELL_BOW_DOWN = 22,
+ EVENT_SHADOW_BEACON = 23,
+ EVENT_LUNATIC_GAZE = 24,
+ EVENT_DEAFENING_ROAR = 25, // only on 25-man with 0-3 keepers active (Hard Mode)
+
+ // Guardian of Yogg-Saron
+ EVENT_DARK_VOLLEY = 26,
+
+ // Immortal Guardian
+ EVENT_DRAIN_LIFE = 27,
+
+ // Keepers
+ EVENT_DESTABILIZATION_MATRIX = 28,
+ EVENT_HODIRS_PROTECTIVE_GAZE = 29,
+
+ // Chamber Illusion
+ EVENT_CHAMBER_ROLEPLAY_1 = 30,
+ EVENT_CHAMBER_ROLEPLAY_2 = 31,
+ EVENT_CHAMBER_ROLEPLAY_3 = 32,
+ EVENT_CHAMBER_ROLEPLAY_4 = 33,
+ EVENT_CHAMBER_ROLEPLAY_5 = 34,
+
+ // Icecrown Illusion
+ EVENT_ICECROWN_ROLEPLAY_1 = 35,
+ EVENT_ICECROWN_ROLEPLAY_2 = 36,
+ EVENT_ICECROWN_ROLEPLAY_3 = 37,
+ EVENT_ICECROWN_ROLEPLAY_4 = 38,
+ EVENT_ICECROWN_ROLEPLAY_5 = 39,
+ EVENT_ICECROWN_ROLEPLAY_6 = 40,
+
+ // Stormwind Illusion
+ EVENT_STORMWIND_ROLEPLAY_1 = 41,
+ EVENT_STORMWIND_ROLEPLAY_2 = 42,
+ EVENT_STORMWIND_ROLEPLAY_3 = 43,
+ EVENT_STORMWIND_ROLEPLAY_4 = 44,
+ EVENT_STORMWIND_ROLEPLAY_5 = 45,
+ EVENT_STORMWIND_ROLEPLAY_6 = 46,
+ EVENT_STORMWIND_ROLEPLAY_7 = 47,
+};
+
+enum EventGroups
+{
+ EVENT_GROUP_SUMMON_TENTACLES = 1,
+};
+
+enum Actions
+{
+ ACTION_PHASE_TRANSFORM = 0,
+ ACTION_PHASE_TWO = 1,
+ ACTION_PHASE_THREE = 2,
+ ACTION_INDUCE_MADNESS = 3,
+ ACTION_SANITY_WELLS = 4,
+ ACTION_FLASH_FREEZE = 5,
+ ACTION_TENTACLE_KILLED = 6,
+ ACTION_START_ROLEPLAY = 8,
+ ACTION_TOGGLE_SHATTERED_ILLUSION = 9,
+};
+
+enum CreatureGroups
+{
+ CREATURE_GROUP_CLOUDS = 0,
+ CREATURE_GROUP_PORTALS_10 = 1,
+ CREATURE_GROUP_PORTALS_25 = 2,
+};
+
+Position const YoggSaronSpawnPos = {1980.43f, -25.7708f, 324.9724f, 3.141593f};
+Position const ObservationRingKeepersPos[4] =
+{
+ {1945.682f, 33.34201f, 411.4408f, 5.270895f}, // Freya
+ {1945.761f, -81.52171f, 411.4407f, 1.029744f}, // Hodir
+ {2028.822f, -65.73573f, 411.4426f, 2.460914f}, // Thorim
+ {2028.766f, 17.42014f, 411.4446f, 3.857178f}, // Mimiron
+};
+Position const YSKeepersPos[4] =
+{
+ {2036.873f, 25.42513f, 338.4984f, 3.909538f}, // Freya
+ {1939.045f, -90.87457f, 338.5426f, 0.994837f}, // Hodir
+ {1939.148f, 42.49035f, 338.5427f, 5.235988f}, // Thorim
+ {2036.658f, -73.58822f, 338.4985f, 2.460914f}, // Mimiron
+};
+Position const IllusionsMiscPos[2] =
+{
+ {1928.793f, 65.03109f, 242.3763f, 0.0f}, // Garona end position
+ {1912.324f, -155.7967f, 239.9896f, 0.0f}, // Saurfang end position
+};
+
+enum MiscData
+{
+ ACHIEV_TIMED_START_EVENT = 21001,
+ SOUND_LUNATIC_GAZE = 15757,
+};
+
+class StartAttackEvent : public BasicEvent
+{
+ public:
+ StartAttackEvent(Creature* summoner, Creature* owner)
+ : _summoner(summoner), _owner(owner)
+ {
+ }
+
+ bool Execute(uint64 /*time*/, uint32 /*diff*/)
+ {
+ _owner->SetReactState(REACT_AGGRESSIVE);
+ if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f))
+ _owner->AI()->AttackStart(target);
+ return true;
+ }
+
+ private:
+ Creature* _summoner;
+ Creature* _owner;
+};
+
+class boss_voice_of_yogg_saron : public CreatureScript
+{
+ public:
+ boss_voice_of_yogg_saron() : CreatureScript("boss_voice_of_yogg_saron") { }
+
+ struct boss_voice_of_yogg_saronAI : public BossAI
+ {
+ boss_voice_of_yogg_saronAI(Creature* creature) : BossAI(creature, BOSS_YOGG_SARON)
+ {
+ SetCombatMovement(false);
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ // TODO: MoveInLineOfSight doesn't work for such a big distance
+ if (who->GetTypeId() == TYPEID_PLAYER && me->GetDistance2d(who) < 99.0f && !me->isInCombat())
+ me->SetInCombatWithZone();
+ }
+
+ void EnterEvadeMode()
+ {
+ BossAI::EnterEvadeMode();
+
+ for (uint8 i = DATA_SARA; i <= DATA_MIMIRON_YS; ++i)
+ if (Creature* creature = ObjectAccessor::GetCreature(*me, instance->GetData64(i)))
+ creature->AI()->EnterEvadeMode();
+
+ // not sure, spoken by Sara (sound), regarding to wowwiki Voice whispers it
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player *player = itr->getSource())
+ {
+ if (events.IsInPhase(PHASE_ONE))
+ Talk(WHISPER_VOICE_PHASE_1_WIPE, player->GetGUID());
+
+ player->RemoveAurasDueToSpell(SPELL_SANITY);
+ player->RemoveAurasDueToSpell(SPELL_INSANE);
+ }
+ }
+
+ void Reset()
+ {
+ _Reset();
+ events.SetPhase(PHASE_ONE);
+
+ instance->SetData(DATA_DRIVE_ME_CRAZY, uint32(true));
+ instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+
+ _guardiansCount = 0;
+ _guardianTimer = 20000;
+ _illusionShattered = false;
+
+ bool clockwise = false;
+ std::list<TempSummon*> clouds;
+ me->SummonCreatureGroup(CREATURE_GROUP_CLOUDS, &clouds);
+ clouds.sort(Trinity::ObjectDistanceOrderPred(me, true));
+ for (std::list<TempSummon*>::const_iterator itr = clouds.begin(); itr != clouds.end(); ++itr)
+ {
+ (*itr)->AI()->DoAction(int32(clockwise));
+ clockwise = !clockwise;
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ if (Creature* sara = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SARA)))
+ sara->SetInCombatWith(me);
+
+ for (uint8 i = DATA_FREYA_YS; i <= DATA_MIMIRON_YS; ++i)
+ if (Creature* keeper = ObjectAccessor::GetCreature(*me, instance->GetData64(i)))
+ keeper->SetInCombatWith(me);
+
+ instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+
+ me->CastCustomSpell(SPELL_SUMMON_GUARDIAN_2, SPELLVALUE_MAX_TARGETS, 1);
+ DoCast(me, SPELL_SANITY_PERIODIC);
+
+ events.ScheduleEvent(EVENT_LOCK_DOOR, 15000);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON, _guardianTimer, 0, PHASE_ONE);
+ events.ScheduleEvent(EVENT_EXTINGUISH_ALL_LIFE, 900000); // 15 minutes
+ }
+
+ void JustDied(Unit* killer)
+ {
+ // don't despawn Yogg-Saron's corpse, remove him from SummonList!
+ if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_YOGG_SARON)))
+ summons.Despawn(yogg);
+
+ BossAI::JustDied(killer);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+ // don't summon tentacles when illusion is shattered, delay them
+ if (_illusionShattered)
+ events.DelayEvents(diff, EVENT_GROUP_SUMMON_TENTACLES);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_LOCK_DOOR:
+ DoCast(me, SPELL_INSANE_PERIODIC);
+ instance->SetBossState(BOSS_YOGG_SARON, IN_PROGRESS);
+ break;
+ case EVENT_EXTINGUISH_ALL_LIFE:
+ if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_YOGG_SARON)))
+ {
+ yogg->AI()->Talk(EMOTE_YOGG_SARON_EXTINGUISH_ALL_LIFE, me->GetGUID());
+ yogg->CastSpell((Unit*)NULL, SPELL_EXTINGUISH_ALL_LIFE, true);
+ }
+ events.ScheduleEvent(EVENT_EXTINGUISH_ALL_LIFE, 10000); // cast it again after a short while, players can survive
+ break;
+ case EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON:
+ me->CastCustomSpell(SPELL_SUMMON_GUARDIAN_2, SPELLVALUE_MAX_TARGETS, 1);
+ ++_guardiansCount;
+ if (_guardiansCount <= 6 && _guardiansCount % 3 == 0)
+ _guardianTimer -= 5000;
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN_OF_YOGG_SARON, _guardianTimer, 0, PHASE_ONE);
+ break;
+ case EVENT_SUMMON_CORRUPTOR_TENTACLE:
+ DoCastAOE(SPELL_CORRUPTOR_TENTACLE_SUMMON);
+ events.ScheduleEvent(EVENT_SUMMON_CORRUPTOR_TENTACLE, 30000, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
+ break;
+ case EVENT_SUMMON_CONSTRICTOR_TENTACLE:
+ me->CastCustomSpell(SPELL_CONSTRICTOR_TENTACLE, SPELLVALUE_MAX_TARGETS, 1);
+ events.ScheduleEvent(EVENT_SUMMON_CONSTRICTOR_TENTACLE, 25000, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
+ break;
+ case EVENT_SUMMON_CRUSHER_TENTACLE:
+ DoCastAOE(SPELL_CRUSHER_TENTACLE_SUMMON);
+ events.ScheduleEvent(EVENT_SUMMON_CRUSHER_TENTACLE, 60000, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
+ break;
+ case EVENT_ILLUSION:
+ {
+ if (Creature* yogg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_YOGG_SARON)))
+ {
+ yogg->AI()->Talk(EMOTE_YOGG_SARON_MADNESS);
+ yogg->AI()->Talk(SAY_YOGG_SARON_MADNESS);
+ }
+
+ me->SummonCreatureGroup(CREATURE_GROUP_PORTALS_10);
+ if (me->GetMap()->Is25ManRaid())
+ me->SummonCreatureGroup(CREATURE_GROUP_PORTALS_25);
+
+ uint8 illusion = urand(CHAMBER_ILLUSION, STORMWIND_ILLUSION);
+ instance->SetData(DATA_ILLUSION, illusion);
+
+ if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRAIN_OF_YOGG_SARON)))
+ brain->AI()->DoAction(ACTION_INDUCE_MADNESS);
+ events.ScheduleEvent(EVENT_ILLUSION, 80000, 0, PHASE_TWO); // wowwiki says 80 secs, wowhead says something about 90 secs
+ break;
+ }
+ case EVENT_SUMMON_IMMORTAL_GUARDIAN:
+ DoCastAOE(SPELL_IMMORTAL_GUARDIAN);
+ events.ScheduleEvent(EVENT_SUMMON_IMMORTAL_GUARDIAN, 15000, 0, PHASE_THREE);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_PHASE_TRANSFORM:
+ events.SetPhase(PHASE_TRANSFORM);
+ summons.DespawnEntry(NPC_OMINOUS_CLOUD);
+ break;
+ case ACTION_PHASE_TWO:
+ events.SetPhase(PHASE_TWO);
+ me->SummonCreature(NPC_YOGG_SARON, YoggSaronSpawnPos);
+ if (Creature* brain = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BRAIN_OF_YOGG_SARON)))
+ brain->SetInCombatWithZone();
+ events.ScheduleEvent(EVENT_SUMMON_CORRUPTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
+ events.ScheduleEvent(EVENT_SUMMON_CONSTRICTOR_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
+ events.ScheduleEvent(EVENT_SUMMON_CRUSHER_TENTACLE, 1, EVENT_GROUP_SUMMON_TENTACLES, PHASE_TWO);
+ events.ScheduleEvent(EVENT_ILLUSION, 60000, 0, PHASE_TWO);
+ break;
+ case ACTION_TOGGLE_SHATTERED_ILLUSION:
+ _illusionShattered = !_illusionShattered;
+ break;
+ case ACTION_PHASE_THREE:
+ events.SetPhase(PHASE_THREE);
+ events.ScheduleEvent(EVENT_SUMMON_IMMORTAL_GUARDIAN, 1000, 0, PHASE_THREE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ switch (summon->GetEntry())
+ {
+ case NPC_GUARDIAN_OF_YOGG_SARON:
+ summon->m_Events.AddEvent(new StartAttackEvent(me, summon), summon->m_Events.CalculateTime(1000));
+ break;
+ case NPC_YOGG_SARON:
+ summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
+ break;
+ case NPC_CONSTRICTOR_TENTACLE:
+ summon->CastSpell(summon, SPELL_LUNGE, true);
+ break;
+ case NPC_CRUSHER_TENTACLE:
+ case NPC_CORRUPTOR_TENTACLE:
+ summon->SetReactState(REACT_PASSIVE);
+ summon->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
+ summon->m_Events.AddEvent(new StartAttackEvent(me, summon), summon->m_Events.CalculateTime(5000));
+ break;
+ case NPC_DESCEND_INTO_MADNESS:
+ summon->CastSpell(summon, SPELL_TELEPORT_PORTAL_VISUAL, true);
+ break;
+ case NPC_IMMORTAL_GUARDIAN:
+ summon->CastSpell(summon, SPELL_SIMPLE_TELEPORT, true);
+ break;
+ }
+
+ BossAI::JustSummoned(summon);
+ }
+
+ private:
+ uint8 _guardiansCount;
+ uint32 _guardianTimer;
+ bool _illusionShattered;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<boss_voice_of_yogg_saronAI>(creature);
+ }
+};
+
+class boss_sara : public CreatureScript
+{
+ public:
+ boss_sara() : CreatureScript("boss_sara") { }
+
+ struct boss_saraAI : public ScriptedAI
+ {
+ boss_saraAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ uint64 GetLinkedPlayerGUID(uint64 guid) const
+ {
+ std::map<uint64, uint64>::const_iterator itr = _linkData.find(guid);
+ if (itr != _linkData.end())
+ return itr->second;
+
+ return 0;
+ }
+
+ void SetLinkBetween(uint64 player1, uint64 player2)
+ {
+ _linkData[player1] = player2;
+ _linkData[player2] = player1;
+ }
+
+ // called once for each target on aura remove
+ void RemoveLinkFrom(uint64 player1)
+ {
+ _linkData.erase(player1);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (_events.IsInPhase(PHASE_ONE) && damage >= me->GetHealth())
+ {
+ damage = 0;
+
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->DoAction(ACTION_PHASE_TRANSFORM);
+
+ Talk(SAY_SARA_TRANSFORM_1);
+ _events.SetPhase(PHASE_TRANSFORM);
+ _events.ScheduleEvent(EVENT_TRANSFORM_1, 4700, 0, PHASE_TRANSFORM);
+ _events.ScheduleEvent(EVENT_TRANSFORM_2, 9500, 0, PHASE_TRANSFORM);
+ _events.ScheduleEvent(EVENT_TRANSFORM_3, 14300, 0, PHASE_TRANSFORM);
+ _events.ScheduleEvent(EVENT_TRANSFORM_4, 14500, 0, PHASE_TRANSFORM);
+ }
+ }
+
+ void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell)
+ {
+ if (!roll_chance_i(30) || _events.IsInPhase(PHASE_TRANSFORM))
+ return;
+
+ switch (spell->Id)
+ {
+ case SPELL_SARAS_FERVOR:
+ Talk(SAY_SARA_FERVOR_HIT);
+ break;
+ case SPELL_SARAS_BLESSING:
+ Talk(SAY_SARA_BLESSING_HIT);
+ break;
+ case SPELL_PSYCHOSIS:
+ Talk(SAY_SARA_PSYCHOSIS_HIT);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER && !me->IsInEvadeMode())
+ Talk(SAY_SARA_KILL);
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ Talk(SAY_SARA_AGGRO);
+ _events.ScheduleEvent(EVENT_SARAS_FERVOR, 5000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SARAS_BLESSING, urand(10000, 30000), 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SARAS_ANGER, urand(15000, 25000), 0, PHASE_ONE);
+ }
+
+ void Reset()
+ {
+ me->RemoveAllAuras();
+ me->SetReactState(REACT_PASSIVE);
+ me->setFaction(35);
+ _events.Reset();
+ _events.SetPhase(PHASE_ONE);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!me->isInCombat())
+ return;
+
+ if (me->HasAura(SPELL_SHATTERED_ILLUSION))
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SARAS_FERVOR:
+ me->CastCustomSpell(SPELL_SARAS_FERVOR_TARGET_SELECTOR, SPELLVALUE_MAX_TARGETS, 1);
+ _events.ScheduleEvent(EVENT_SARAS_FERVOR, 6000, 0, PHASE_ONE);
+ break;
+ case EVENT_SARAS_ANGER:
+ me->CastCustomSpell(SPELL_SARAS_ANGER_TARGET_SELECTOR, SPELLVALUE_MAX_TARGETS, 1);
+ _events.ScheduleEvent(EVENT_SARAS_ANGER, urand(6000, 8000), 0, PHASE_ONE);
+ break;
+ case EVENT_SARAS_BLESSING:
+ me->CastCustomSpell(SPELL_SARAS_BLESSING_TARGET_SELECTOR, SPELLVALUE_MAX_TARGETS, 1);
+ _events.ScheduleEvent(EVENT_SARAS_BLESSING, urand(6000, 30000), 0, PHASE_ONE);
+ break;
+ case EVENT_TRANSFORM_1:
+ Talk(SAY_SARA_TRANSFORM_2);
+ break;
+ case EVENT_TRANSFORM_2:
+ Talk(SAY_SARA_TRANSFORM_3);
+ break;
+ case EVENT_TRANSFORM_3:
+ Talk(SAY_SARA_TRANSFORM_4);
+ DoCast(me, SPELL_FULL_HEAL);
+ me->setFaction(16);
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->DoAction(ACTION_PHASE_TWO);
+ if (Creature* mimiron = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MIMIRON_YS)))
+ mimiron->AI()->DoAction(ACTION_PHASE_TWO);
+ break;
+ case EVENT_TRANSFORM_4:
+ DoCast(me, SPELL_PHASE_2_TRANSFORM);
+ if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetData64(BOSS_YOGG_SARON)))
+ DoCast(yogg, SPELL_RIDE_YOGG_SARON_VEHICLE);
+ DoCast(me, SPELL_SHADOWY_BARRIER_SARA);
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_DEATH_RAY, 20000, 0, PHASE_TWO); // almost never casted at scheduled time, why?
+ _events.ScheduleEvent(EVENT_MALADY_OF_THE_MIND, 18000, 0, PHASE_TWO);
+ _events.ScheduleEvent(EVENT_PSYCHOSIS, 1, 0, PHASE_TWO);
+ _events.ScheduleEvent(EVENT_BRAIN_LINK, 23000, 0, PHASE_TWO);
+ break;
+ case EVENT_DEATH_RAY:
+ DoCast(me, SPELL_DEATH_RAY);
+ _events.ScheduleEvent(EVENT_DEATH_RAY, 21000, 0, PHASE_TWO);
+ break;
+ case EVENT_MALADY_OF_THE_MIND:
+ me->CastCustomSpell(SPELL_MALADY_OF_THE_MIND, SPELLVALUE_MAX_TARGETS, 1);
+ _events.ScheduleEvent(EVENT_MALADY_OF_THE_MIND, urand(18000, 25000), 0, PHASE_TWO);
+ break;
+ case EVENT_PSYCHOSIS:
+ me->CastCustomSpell(SPELL_PSYCHOSIS, SPELLVALUE_MAX_TARGETS, 1);
+ _events.ScheduleEvent(EVENT_PSYCHOSIS, 4000, 0, PHASE_TWO);
+ break;
+ case EVENT_BRAIN_LINK:
+ me->CastCustomSpell(SPELL_BRAIN_LINK, SPELLVALUE_MAX_TARGETS, 2);
+ _events.ScheduleEvent(EVENT_BRAIN_LINK, urand(23000, 26000), 0, PHASE_TWO);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ summon->SetReactState(REACT_PASSIVE);
+
+ switch (summon->GetEntry())
+ {
+ case NPC_DEATH_ORB:
+ Talk(SAY_SARA_DEATH_RAY);
+ summon->CastSpell(summon, SPELL_DEATH_RAY_ORIGIN_VISUAL);
+ for (uint8 i = 0; i < 4; ++i)
+ {
+ Position pos;
+ float radius = frand(25.0f, 50.0f);
+ float angle = frand(0.0f, 2.0f * M_PI);
+ pos.m_positionX = YoggSaronSpawnPos.GetPositionX() + radius * cosf(angle);
+ pos.m_positionY = YoggSaronSpawnPos.GetPositionY() + radius * sinf(angle);
+ pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), YoggSaronSpawnPos.GetPositionZ() + 5.0f);
+ me->SummonCreature(NPC_DEATH_RAY, pos, TEMPSUMMON_TIMED_DESPAWN, 20000);
+ }
+ break;
+ case NPC_DEATH_RAY:
+ summon->CastSpell(summon, SPELL_DEATH_RAY_WARNING_VISUAL);
+ break;
+ }
+
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->JustSummoned(summon);
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_PHASE_THREE: // Sara does nothing in phase 3
+ _events.SetPhase(PHASE_THREE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ std::map<uint64, uint64> _linkData;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<boss_saraAI>(creature);
+ }
+};
+
+class boss_yogg_saron : public CreatureScript
+{
+ public:
+ boss_yogg_saron() : CreatureScript("boss_yogg_saron") { }
+
+ struct boss_yogg_saronAI : public PassiveAI
+ {
+ boss_yogg_saronAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void Reset()
+ {
+ _events.Reset();
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_YELL_BOW_DOWN, 3000, 0, PHASE_TWO);
+ DoCast(me, SPELL_SHADOWY_BARRIER_YOGG);
+ DoCast(me, SPELL_KNOCK_AWAY);
+
+ me->ResetLootMode();
+ switch (_instance->GetData(DATA_KEEPERS_COUNT))
+ {
+ case 0:
+ me->AddLootMode(LOOT_MODE_HARD_MODE_4);
+ case 1:
+ me->AddLootMode(LOOT_MODE_HARD_MODE_3);
+ case 2:
+ me->AddLootMode(LOOT_MODE_HARD_MODE_2);
+ case 3:
+ me->AddLootMode(LOOT_MODE_HARD_MODE_1);
+ }
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell)
+ {
+ if (spell->Id == SPELL_IN_THE_MAWS_OF_THE_OLD_GOD)
+ me->AddLootMode(32);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ Talk(SAY_YOGG_SARON_DEATH);
+
+ if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ me->Kill(creature);
+
+ for (uint8 i = DATA_SARA; i <= DATA_BRAIN_OF_YOGG_SARON; ++i)
+ if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetData64(i)))
+ creature->DisappearAndDie();
+
+ for (uint8 i = DATA_FREYA_YS; i <= DATA_MIMIRON_YS; ++i)
+ if (Creature* creature = ObjectAccessor::GetCreature(*me, _instance->GetData64(i)))
+ creature->AI()->EnterEvadeMode();
+
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player *player = itr->getSource())
+ {
+ player->RemoveAurasDueToSpell(SPELL_SANITY);
+ player->RemoveAurasDueToSpell(SPELL_INSANE);
+ }
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_YELL_BOW_DOWN:
+ Talk(SAY_YOGG_SARON_SPAWN);
+ break;
+ case EVENT_SHADOW_BEACON:
+ DoCastAOE(SPELL_SHADOW_BEACON);
+ Talk(EMOTE_YOGG_SARON_EMPOWERING_SHADOWS);
+ _events.ScheduleEvent(EVENT_SHADOW_BEACON, 45000, 0, PHASE_THREE);
+ break;
+ case EVENT_LUNATIC_GAZE:
+ DoCast(me, SPELL_LUNATIC_GAZE);
+ sCreatureTextMgr->SendSound(me, SOUND_LUNATIC_GAZE, CHAT_MSG_MONSTER_YELL, 0, TEXT_RANGE_NORMAL, TEAM_OTHER, false);
+ _events.ScheduleEvent(EVENT_LUNATIC_GAZE, 12000, 0, PHASE_THREE);
+ break;
+ case EVENT_DEAFENING_ROAR:
+ DoCastAOE(SPELL_DEAFENING_ROAR);
+ Talk(SAY_YOGG_SARON_DEAFENING_ROAR);
+ Talk(EMOTE_YOGG_SARON_DEAFENING_ROAR);
+ _events.ScheduleEvent(EVENT_DEAFENING_ROAR, urand(20000, 25000), 0, PHASE_THREE); // timer guessed
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_PHASE_THREE:
+ _events.SetPhase(PHASE_THREE);
+ _events.ScheduleEvent(EVENT_SHADOW_BEACON, 45000, 0, PHASE_THREE);
+ _events.ScheduleEvent(EVENT_LUNATIC_GAZE, 12000, 0, PHASE_THREE);
+ if (me->GetMap()->Is25ManRaid() && _instance->GetData(DATA_KEEPERS_COUNT) < 4)
+ _events.ScheduleEvent(EVENT_DEAFENING_ROAR, urand(20000, 25000), 0, PHASE_THREE); // timer guessed
+ Talk(SAY_YOGG_SARON_PHASE_3);
+ DoCast(me, SPELL_PHASE_3_TRANSFORM);
+ me->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER_YOGG);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<boss_yogg_saronAI>(creature);
+ }
+};
+
+class boss_brain_of_yogg_saron : public CreatureScript
+{
+ public:
+ boss_brain_of_yogg_saron() : CreatureScript("boss_brain_of_yogg_saron") { }
+
+ struct boss_brain_of_yogg_saronAI : public PassiveAI
+ {
+ boss_brain_of_yogg_saronAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()), _summons(creature) { }
+
+ void Reset()
+ {
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_MATCH_HEALTH);
+ _summons.DespawnAll();
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (me->HealthBelowPctDamaged(30, damage) && !me->HasAura(SPELL_BRAIN_HURT_VISUAL))
+ {
+ me->RemoveAllAuras();
+ me->InterruptNonMeleeSpells(true);
+ DoCastAOE(SPELL_SHATTERED_ILLUSION_REMOVE, true);
+ DoCast(me, SPELL_MATCH_HEALTH_2, true); // it doesn't seem to hit Yogg-Saron here
+ DoCast(me, SPELL_BRAIN_HURT_VISUAL, true);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
+
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->DoAction(ACTION_PHASE_THREE);
+ if (Creature* sara = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_SARA)))
+ sara->AI()->DoAction(ACTION_PHASE_THREE);
+ if (Creature* yogg = ObjectAccessor::GetCreature(*me, _instance->GetData64(BOSS_YOGG_SARON)))
+ yogg->AI()->DoAction(ACTION_PHASE_THREE);
+
+ for (uint8 i = DATA_THORIM_YS; i <= DATA_MIMIRON_YS; ++i)
+ if (Creature* keeper = ObjectAccessor::GetCreature(*me, _instance->GetData64(i)))
+ keeper->AI()->DoAction(ACTION_PHASE_THREE);
+ }
+ }
+
+ void UpdateAI(uint32 /*diff*/) { }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ case ACTION_INDUCE_MADNESS:
+ {
+ _tentaclesKilled = 0;
+
+ me->SummonCreatureGroup(_instance->GetData(DATA_ILLUSION));
+
+ // make sure doors won't be opened
+ for (uint32 i = GO_BRAIN_ROOM_DOOR_1; i <= GO_BRAIN_ROOM_DOOR_3; ++i)
+ _instance->HandleGameObject(_instance->GetData64(i), false);
+
+ DoCastAOE(SPELL_INDUCE_MADNESS);
+ break;
+ }
+ case ACTION_TENTACLE_KILLED:
+ {
+ uint8 illusion = _instance->GetData(DATA_ILLUSION);
+ if (++_tentaclesKilled >= (illusion == ICECROWN_ILLUSION ? 9 : 8))
+ {
+ sCreatureTextMgr->SendChat(me, EMOTE_BRAIN_ILLUSION_SHATTERED, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_AREA);
+ _summons.DespawnAll();
+ DoCastAOE(SPELL_SHATTERED_ILLUSION, true);
+ _instance->HandleGameObject(_instance->GetData64(GO_BRAIN_ROOM_DOOR_1 + illusion), true);
+
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* summon)
+ {
+ _summons.Summon(summon);
+ }
+
+ private:
+ InstanceScript* _instance;
+ SummonList _summons;
+ uint8 _tentaclesKilled;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<boss_brain_of_yogg_saronAI>(creature);
+ }
+};
+
+class npc_ominous_cloud : public CreatureScript
+{
+ public:
+ npc_ominous_cloud() : CreatureScript("npc_ominous_cloud") { }
+
+ struct npc_ominous_cloudAI : public PassiveAI
+ {
+ npc_ominous_cloudAI(Creature* creature) : PassiveAI(creature) { }
+
+ void Reset()
+ {
+ DoCast(me, SPELL_OMINOUS_CLOUD_VISUAL);
+ }
+
+ void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
+ {
+ float step = clockwise ? -M_PI / 8.0f : M_PI / 8.0f;
+ float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
+
+ for (uint8 i = 0; i < 16; angle += step, ++i)
+ {
+ G3D::Vector3 point;
+ point.x = centerPos.GetPositionX() + radius * cosf(angle);
+ point.y = centerPos.GetPositionY() + radius * sinf(angle);
+ point.z = me->GetMap()->GetHeight(me->GetPhaseMask(), point.x, point.y, z + 5.0f);
+ path.push_back(point);
+ }
+ }
+
+ void UpdateAI(uint32 /*diff*/) { }
+
+ void DoAction(int32 action)
+ {
+ Movement::MoveSplineInit init(me);
+ FillCirclePath(YoggSaronSpawnPos, me->GetDistance2d(YoggSaronSpawnPos.GetPositionX(), YoggSaronSpawnPos.GetPositionY()), me->GetPositionZ(), init.Path(), action);
+ init.SetWalk(true);
+ init.SetCyclic();
+ init.Launch();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_ominous_cloudAI>(creature);
+ }
+};
+
+class npc_guardian_of_yogg_saron : public CreatureScript
+{
+ public:
+ npc_guardian_of_yogg_saron() : CreatureScript("npc_guardian_of_yogg_saron") { }
+
+ struct npc_guardian_of_yogg_saronAI : public ScriptedAI
+ {
+ npc_guardian_of_yogg_saronAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ DoCastAOE(SPELL_SHADOW_NOVA);
+ DoCastAOE(SPELL_SHADOW_NOVA_2);
+ }
+
+ void Reset()
+ {
+ _events.ScheduleEvent(EVENT_DARK_VOLLEY, urand(10000, 15000));
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DARK_VOLLEY:
+ DoCastAOE(SPELL_DARK_VOLLEY);
+ _events.ScheduleEvent(EVENT_DARK_VOLLEY, urand(10000, 15000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void IsSummonedBy(Unit* summoner)
+ {
+ if (summoner->GetEntry() != NPC_OMINOUS_CLOUD)
+ return;
+
+ // Guardian can be summoned both by Voice of Yogg-Saron and by Ominous Cloud
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->JustSummoned(me);
+ }
+
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_guardian_of_yogg_saronAI>(creature);
+ }
+};
+
+class npc_corruptor_tentacle : public CreatureScript
+{
+ public:
+ npc_corruptor_tentacle() : CreatureScript("npc_corruptor_tentacle") { }
+
+ struct npc_corruptor_tentacleAI : public ScriptedAI
+ {
+ npc_corruptor_tentacleAI(Creature* creature) : ScriptedAI(creature)
+ {
+ SetCombatMovement(false);
+ }
+
+ void Reset()
+ {
+ DoCast(me, SPELL_TENTACLE_VOID_ZONE);
+ DoCastAOE(SPELL_ERUPT);
+ _events.ScheduleEvent(EVENT_CAST_RANDOM_SPELL, 1);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (me->HasAura(SPELL_SHATTERED_ILLUSION))
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CAST_RANDOM_SPELL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, RAND(SPELL_BLACK_PLAGUE, SPELL_CURSE_OF_DOOM, SPELL_APATHY, SPELL_DRAINING_POISON));
+ _events.ScheduleEvent(EVENT_CAST_RANDOM_SPELL, 3000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_corruptor_tentacleAI>(creature);
+ }
+};
+
+class npc_constrictor_tentacle : public CreatureScript
+{
+ public:
+ npc_constrictor_tentacle() : CreatureScript("npc_constrictor_tentacle") { }
+
+ struct npc_constrictor_tentacleAI : public ScriptedAI
+ {
+ npc_constrictor_tentacleAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
+ {
+ SetCombatMovement(false);
+ }
+
+ void Reset()
+ {
+ DoCast(me, SPELL_TENTACLE_VOID_ZONE_2);
+ DoCastAOE(SPELL_ERUPT);
+ }
+
+ void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply)
+ {
+ if (!apply)
+ passenger->RemoveAurasDueToSpell(SPELL_SQUEEZE);
+ }
+
+ void UpdateAI(uint32 /*diff*/)
+ {
+ UpdateVictim();
+ }
+
+ void IsSummonedBy(Unit* summoner)
+ {
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->JustSummoned(me);
+ }
+
+ private:
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_constrictor_tentacleAI>(creature);
+ }
+};
+
+class npc_crusher_tentacle : public CreatureScript
+{
+ public:
+ npc_crusher_tentacle() : CreatureScript("npc_crusher_tentacle") { }
+
+ struct npc_crusher_tentacleAI : public ScriptedAI
+ {
+ npc_crusher_tentacleAI(Creature* creature) : ScriptedAI(creature)
+ {
+ SetCombatMovement(false);
+ }
+
+ void Reset()
+ {
+ DoCast(me, SPELL_CRUSH);
+ DoCast(me, SPELL_TENTACLE_VOID_ZONE);
+ DoCast(me, SPELL_DIMINSH_POWER);
+ DoCast(me, SPELL_FOCUSED_ANGER);
+ DoCastAOE(SPELL_ERUPT);
+
+ _events.ScheduleEvent(EVENT_DIMINISH_POWER, urand(6000, 8000));
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (me->HasAura(SPELL_SHATTERED_ILLUSION) || me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ // update timers when the Diminish Power is not being channeled so the next one
+ // is not cast immediately after interrupt
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DIMINISH_POWER:
+ DoCast(SPELL_DIMINISH_POWER);
+ _events.ScheduleEvent(EVENT_DIMINISH_POWER, urand(20000, 30000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_crusher_tentacleAI>(creature);
+ }
+};
+
+class npc_influence_tentacle : public CreatureScript
+{
+ public:
+ npc_influence_tentacle() : CreatureScript("npc_influence_tentacle") { }
+
+ struct npc_influence_tentacleAI : public PassiveAI
+ {
+ npc_influence_tentacleAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void Reset()
+ {
+ DoCast(me, me->GetEntry() == NPC_SUIT_OF_ARMOR ? SPELL_NONDESCRIPT_1 : SPELL_NONDESCRIPT_2);
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ if (Creature* brain = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_BRAIN_OF_YOGG_SARON)))
+ brain->AI()->DoAction(ACTION_TENTACLE_KILLED);
+ }
+
+ void UpdateAI(uint32 diff) { }
+
+ private:
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_influence_tentacleAI>(creature);
+ }
+};
+
+typedef boss_sara::boss_saraAI SaraAI;
+
+class npc_descend_into_madness : public CreatureScript
+{
+ public:
+ npc_descend_into_madness() : CreatureScript("npc_descend_into_madness") { }
+
+ struct npc_descend_into_madnessAI : public PassiveAI
+ {
+ npc_descend_into_madnessAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void OnSpellClick(Unit* clicker)
+ {
+ clicker->RemoveAurasDueToSpell(SPELL_BRAIN_LINK);
+ me->DespawnOrUnsummon();
+ }
+
+ void UpdateAI(uint32 /*diff*/) { }
+
+ private:
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_descend_into_madnessAI>(creature);
+ }
+};
+
+class npc_immortal_guardian : public CreatureScript
+{
+ public:
+ npc_immortal_guardian() : CreatureScript("npc_immortal_guardian") { }
+
+ struct npc_immortal_guardianAI : public ScriptedAI
+ {
+ npc_immortal_guardianAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset()
+ {
+ DoCast(me, SPELL_EMPOWERED);
+ DoCast(me, SPELL_RECENTLY_SPAWNED);
+ _events.ScheduleEvent(EVENT_DRAIN_LIFE, urand(3000, 13000));
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ if (me->HealthBelowPctDamaged(1, damage))
+ damage = me->GetHealth() - me->CountPctFromMaxHealth(1); // or set immune to damage? should be done here or in SPELL_WEAKENED spell script?
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DRAIN_LIFE:
+ DoCast(SPELL_DRAIN_LIFE);
+ _events.ScheduleEvent(EVENT_DRAIN_LIFE, urand(20000, 30000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_immortal_guardianAI>(creature);
+ }
+};
+
+class npc_observation_ring_keeper : public CreatureScript
+{
+ public:
+ npc_observation_ring_keeper() : CreatureScript("npc_observation_ring_keeper") { }
+
+ struct npc_observation_ring_keeperAI : public ScriptedAI
+ {
+ npc_observation_ring_keeperAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset()
+ {
+ DoCast(SPELL_SIMPLE_TELEPORT_KEEPERS); // not visible here
+ DoCast(SPELL_KEEPER_ACTIVE);
+ }
+
+ void sGossipSelect(Player* player, uint32 sender, uint32 /*action*/)
+ {
+ if (sender != 10333)
+ return;
+
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->DespawnOrUnsummon(2000);
+ DoCast(SPELL_TELEPORT);
+ Talk(SAY_KEEPER_CHOSEN_1, player->GetGUID());
+ Talk(SAY_KEEPER_CHOSEN_2, player->GetGUID());
+
+ switch (me->GetEntry())
+ {
+ case NPC_FREYA_OBSERVATION_RING:
+ me->SummonCreature(NPC_FREYA_YS, YSKeepersPos[0]);
+ break;
+ case NPC_HODIR_OBSERVATION_RING:
+ me->SummonCreature(NPC_HODIR_YS, YSKeepersPos[1]);
+ break;
+ case NPC_THORIM_OBSERVATION_RING:
+ me->SummonCreature(NPC_THORIM_YS, YSKeepersPos[2]);
+ break;
+ case NPC_MIMIRON_OBSERVATION_RING:
+ me->SummonCreature(NPC_MIMIRON_YS, YSKeepersPos[3]);
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) { }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_observation_ring_keeperAI>(creature);
+ }
+};
+
+class npc_yogg_saron_keeper : public CreatureScript
+{
+ public:
+ npc_yogg_saron_keeper() : CreatureScript("npc_yogg_saron_keeper") { }
+
+ struct npc_yogg_saron_keeperAI : public ScriptedAI
+ {
+ npc_yogg_saron_keeperAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void IsSummonedBy(Unit* /*summoner*/)
+ {
+ DoCast(SPELL_SIMPLE_TELEPORT_KEEPERS);
+ }
+
+ void Reset()
+ {
+ _events.Reset();
+ _events.SetPhase(PHASE_ONE);
+ me->SetReactState(REACT_PASSIVE);
+ me->RemoveAllAuras();
+
+ DoCast(SPELL_KEEPER_ACTIVE); // can we skip removing this aura somehow?
+
+ if (me->GetEntry() == NPC_FREYA_YS)
+ {
+ std::list<Creature*> wells;
+ GetCreatureListWithEntryInGrid(wells, me, NPC_SANITY_WELL, 200.0f);
+ for (std::list<Creature*>::const_iterator itr = wells.begin(); itr != wells.end(); ++itr)
+ {
+ (*itr)->RemoveAurasDueToSpell(SPELL_SANITY_WELL);
+ (*itr)->RemoveAurasDueToSpell(SPELL_SANITY_WELL_VISUAL);
+ }
+ }
+ }
+
+ void EnterCombat(Unit* /*who*/)
+ {
+ switch (me->GetEntry())
+ {
+ case NPC_FREYA_YS:
+ DoCast(SPELL_RESILIENCE_OF_NATURE);
+ DoCast(SPELL_SANITY_WELL_SUMMON);
+ break;
+ case NPC_HODIR_YS:
+ DoCast(SPELL_FORTITUDE_OF_FROST);
+ DoCast(SPELL_HODIRS_PROTECTIVE_GAZE);
+ break;
+ case NPC_THORIM_YS:
+ DoCast(SPELL_FURY_OF_THE_STORM);
+ break;
+ case NPC_MIMIRON_YS:
+ DoCast(SPELL_SPEED_OF_INVENTION);
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ if (!me->isInCombat())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_DESTABILIZATION_MATRIX:
+ me->CastCustomSpell(SPELL_DESTABILIZATION_MATRIX, SPELLVALUE_MAX_TARGETS, 1);
+ _events.ScheduleEvent(EVENT_DESTABILIZATION_MATRIX, urand(15000, 25000), 0, PHASE_TWO);
+ break;
+ case EVENT_HODIRS_PROTECTIVE_GAZE:
+ DoCast(SPELL_HODIRS_PROTECTIVE_GAZE);
+ break;
+ }
+ }
+ }
+
+ void DoAction(int32 action)
+ {
+ switch (action)
+ {
+ // setting the phases is only for Thorim and Mimiron
+ case ACTION_PHASE_TWO:
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_DESTABILIZATION_MATRIX, urand(5000, 15000), 0, PHASE_TWO);
+ break;
+ case ACTION_PHASE_THREE:
+ _events.SetPhase(PHASE_THREE);
+ if (me->GetEntry() == NPC_THORIM_YS)
+ DoCast(SPELL_TITANIC_STORM);
+ break;
+ case ACTION_SANITY_WELLS:
+ {
+ std::list<Creature*> wells;
+ GetCreatureListWithEntryInGrid(wells, me, NPC_SANITY_WELL, 200.0f);
+ for (std::list<Creature*>::const_iterator itr = wells.begin(); itr != wells.end(); ++itr)
+ {
+ (*itr)->CastSpell(*itr, SPELL_SANITY_WELL);
+ (*itr)->CastSpell(*itr, SPELL_SANITY_WELL_VISUAL);
+ }
+ break;
+ }
+ case ACTION_FLASH_FREEZE:
+ DoCast(SPELL_FLASH_FREEZE_VISUAL);
+ _events.ScheduleEvent(EVENT_HODIRS_PROTECTIVE_GAZE, urand(25000, 30000));
+ break;
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_yogg_saron_keeperAI>(creature);
+ }
+};
+
+class npc_yogg_saron_illusions : public CreatureScript
+{
+ public:
+ npc_yogg_saron_illusions() : CreatureScript("npc_yogg_saron_illusions") { }
+
+ struct npc_yogg_saron_illusionsAI : public ScriptedAI
+ {
+ npc_yogg_saron_illusionsAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
+
+ void IsSummonedBy(Unit* /*summoner*/)
+ {
+ switch (_instance->GetData(DATA_ILLUSION))
+ {
+ case CHAMBER_ILLUSION:
+ // i think the first Talk should be delayed as in this moment
+ // players are too far away to be able to see it
+ if (Creature* neltharion = me->FindNearestCreature(NPC_NELTHARION, 50.0f))
+ neltharion->AI()->Talk(SAY_CHAMBER_ROLEPLAY_1);
+
+ _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_1, 16000);
+ _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_2, 22000);
+ _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_3, 28000);
+ _events.ScheduleEvent(EVENT_CHAMBER_ROLEPLAY_4, 36000);
+ break;
+ case ICECROWN_ILLUSION:
+ // same here
+ _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_1, 1000);
+ _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_2, 7500);
+ _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_3, 19500);
+ _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_4, 25500);
+ _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_5, 33000);
+ _events.ScheduleEvent(EVENT_ICECROWN_ROLEPLAY_6, 41300);
+ break;
+ case STORMWIND_ILLUSION:
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_4, 33800); // "A thousand deaths..."
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_5, 38850);
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_7, 58750);
+ // TODO: use "or one murder." sound and split the text in DB
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CHAMBER_ROLEPLAY_1:
+ if (Creature* ysera = me->FindNearestCreature(NPC_YSERA, 50.0f))
+ ysera->AI()->Talk(SAY_CHAMBER_ROLEPLAY_2);
+ break;
+ case EVENT_CHAMBER_ROLEPLAY_2:
+ if (Creature* neltharion = me->FindNearestCreature(NPC_NELTHARION, 50.0f))
+ neltharion->AI()->Talk(SAY_CHAMBER_ROLEPLAY_3);
+ break;
+ case EVENT_CHAMBER_ROLEPLAY_3:
+ if (Creature* malygos = me->FindNearestCreature(NPC_MALYGOS, 50.0f))
+ malygos->AI()->Talk(SAY_CHAMBER_ROLEPLAY_4);
+ break;
+ case EVENT_CHAMBER_ROLEPLAY_4:
+ Talk(SAY_CHAMBER_ROLEPLAY_5);
+ break;
+ case EVENT_ICECROWN_ROLEPLAY_1:
+ if (Creature* bolvar = me->FindNearestCreature(NPC_IMMOLATED_CHAMPION, 50.0f))
+ {
+ bolvar->AI()->Talk(SAY_ICECROWN_ROLEPLAY_1);
+
+ if (Creature* lichKing = me->FindNearestCreature(NPC_THE_LICH_KING, 50.0f))
+ lichKing->CastSpell(bolvar, SPELL_DEATHGRASP);
+ }
+ break;
+ case EVENT_ICECROWN_ROLEPLAY_2:
+ if (Creature* lichKing = me->FindNearestCreature(NPC_THE_LICH_KING, 50.0f))
+ lichKing->AI()->Talk(SAY_ICECROWN_ROLEPLAY_2);
+ break;
+ case EVENT_ICECROWN_ROLEPLAY_3:
+ if (Creature* bolvar = me->FindNearestCreature(NPC_IMMOLATED_CHAMPION, 50.0f))
+ bolvar->AI()->Talk(SAY_ICECROWN_ROLEPLAY_3);
+ if (Creature* saurfang = me->FindNearestCreature(NPC_TURNED_CHAMPION, 50.0f))
+ saurfang->AI()->DoAction(ACTION_START_ROLEPLAY);
+ break;
+ case EVENT_ICECROWN_ROLEPLAY_4:
+ if (Creature* lichKing = me->FindNearestCreature(NPC_THE_LICH_KING, 50.0f))
+ lichKing->AI()->Talk(SAY_ICECROWN_ROLEPLAY_4);
+ break;
+ case EVENT_ICECROWN_ROLEPLAY_5:
+ Talk(SAY_ICECROWN_ROLEPLAY_5);
+ break;
+ case EVENT_ICECROWN_ROLEPLAY_6:
+ Talk(SAY_ICECROWN_ROLEPLAY_6);
+ break;
+ case EVENT_STORMWIND_ROLEPLAY_4:
+ Talk(SAY_STORMWIND_ROLEPLAY_4);
+ break;
+ case EVENT_STORMWIND_ROLEPLAY_5:
+ if (Creature* llane = me->FindNearestCreature(NPC_KING_LLANE, 50.0f))
+ llane->AI()->Talk(SAY_STORMWIND_ROLEPLAY_5);
+ break;
+ case EVENT_STORMWIND_ROLEPLAY_7:
+ Talk(SAY_STORMWIND_ROLEPLAY_7);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_yogg_saron_illusionsAI>(creature);
+ }
+};
+
+class npc_garona : public CreatureScript
+{
+ public:
+ npc_garona() : CreatureScript("npc_garona") { }
+
+ struct npc_garonaAI : public ScriptedAI
+ {
+ npc_garonaAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset()
+ {
+ _events.Reset();
+
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(0, IllusionsMiscPos[0]);
+
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_1, 9250);
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_2, 16700);
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_3, 24150);
+ _events.ScheduleEvent(EVENT_STORMWIND_ROLEPLAY_6, 52700);
+ }
+
+ void UpdateAI(uint32 diff)
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_STORMWIND_ROLEPLAY_1:
+ Talk(SAY_STORMWIND_ROLEPLAY_1);
+ break;
+ case EVENT_STORMWIND_ROLEPLAY_2:
+ Talk(SAY_STORMWIND_ROLEPLAY_2);
+ break;
+ case EVENT_STORMWIND_ROLEPLAY_3:
+ Talk(SAY_STORMWIND_ROLEPLAY_3);
+ break;
+ case EVENT_STORMWIND_ROLEPLAY_6:
+ Talk(SAY_STORMWIND_ROLEPLAY_6);
+ if (Creature* llane = me->FindNearestCreature(NPC_KING_LLANE, 50.0f))
+ {
+ DoCast(SPELL_ASSASSINATE);
+ llane->CastSpell(llane, SPELL_PERMANENT_FEIGN_DEATH);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_garonaAI>(creature);
+ }
+};
+
+class npc_turned_champion : public CreatureScript
+{
+ public:
+ npc_turned_champion() : CreatureScript("npc_turned_champion") { }
+
+ struct npc_turned_championAI : public ScriptedAI
+ {
+ npc_turned_championAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset()
+ {
+ DoCast(SPELL_VERTEX_COLOR_BLACK);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId)
+ {
+ if (type != POINT_MOTION_TYPE || pointId != 0)
+ return;
+
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+ }
+
+ void DoAction(int32 action)
+ {
+ if (action != ACTION_START_ROLEPLAY)
+ return;
+
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(0, IllusionsMiscPos[1]);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_turned_championAI>(creature);
+ }
+};
+
+class npc_laughing_skull : public CreatureScript
+{
+ public:
+ npc_laughing_skull() : CreatureScript("npc_laughing_skull") { }
+
+ struct npc_laughing_skullAI : public ScriptedAI
+ {
+ npc_laughing_skullAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset()
+ {
+ me->SetReactState(REACT_PASSIVE);
+ DoCast(me, SPELL_LUNATIC_GAZE_SKULL);
+ }
+
+ // don't evade, otherwise the Lunatic Gaze aura is removed
+ void UpdateAI(uint32 diff) { }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetUlduarAI<npc_laughing_skullAI>(creature);
+ }
+};
+
+class spell_yogg_saron_target_selectors : public SpellScriptLoader // 63744, 63745, 63747, 65206
+{
+ public:
+ spell_yogg_saron_target_selectors() : SpellScriptLoader("spell_yogg_saron_target_selectors") { }
+
+ class spell_yogg_saron_target_selectors_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_target_selectors_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ GetCaster()->CastSpell(target, uint32(GetEffectValue()));
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_target_selectors_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_target_selectors_SpellScript();
+ }
+};
+
+class SanityReduction : public SpellScript
+{
+ public:
+ SanityReduction() : SpellScript() { }
+ SanityReduction(uint8 stacks) : SpellScript(), _stacks(stacks) { }
+
+ void RemoveSanity(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ if (Aura* sanity = target->GetAura(SPELL_SANITY))
+ sanity->ModStackAmount(-int32(_stacks), AURA_REMOVE_BY_ENEMY_SPELL);
+ }
+
+ protected:
+ uint8 _stacks;
+};
+
+class HighSanityTargetSelector
+{
+ public:
+ HighSanityTargetSelector() { }
+
+ bool operator()(WorldObject* object)
+ {
+ if (Unit* unit = object->ToUnit())
+ if (Aura* sanity = unit->GetAura(SPELL_SANITY))
+ return sanity->GetStackAmount() <= 40;
+ return true;
+ }
+};
+
+class spell_yogg_saron_psychosis : public SpellScriptLoader // 63795, 65301
+{
+ public:
+ spell_yogg_saron_psychosis() : SpellScriptLoader("spell_yogg_saron_psychosis") { }
+
+ class spell_yogg_saron_psychosis_SpellScript : public SanityReduction
+ {
+ PrepareSpellScript(spell_yogg_saron_psychosis_SpellScript);
+
+ bool Load()
+ {
+ _stacks = GetSpellInfo()->Id == SPELL_PSYCHOSIS ? 9 : 12;
+ return true;
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(HighSanityTargetSelector());
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ILLUSION_ROOM));
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_psychosis_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_psychosis_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_psychosis_SpellScript::RemoveSanity, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_psychosis_SpellScript();
+ }
+};
+
+class spell_yogg_saron_malady_of_the_mind : public SpellScriptLoader // 63830, 63881
+{
+ public:
+ spell_yogg_saron_malady_of_the_mind() : SpellScriptLoader("spell_yogg_saron_malady_of_the_mind") { }
+
+ class spell_yogg_saron_malady_of_the_mind_SpellScript : public SanityReduction
+ {
+ public:
+ spell_yogg_saron_malady_of_the_mind_SpellScript() : SanityReduction(3) { }
+
+ PrepareSpellScript(spell_yogg_saron_malady_of_the_mind_SpellScript);
+
+ bool Load()
+ {
+ _applyHandlers = GetSpellInfo()->Id == SPELL_MALADY_OF_THE_MIND;
+ return true;
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(HighSanityTargetSelector());
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ILLUSION_ROOM));
+ }
+
+ void Register()
+ {
+ if (_applyHandlers)
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_malady_of_the_mind_SpellScript::RemoveSanity, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+
+ bool _applyHandlers;
+ };
+
+ class spell_yogg_saron_malady_of_the_mind_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_malady_of_the_mind_AuraScript);
+
+ bool Validate(SpellInfo const* /*spell*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_MALADY_OF_THE_MIND_JUMP))
+ return false;
+ return true;
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ switch (GetTargetApplication()->GetRemoveMode())
+ {
+ case AURA_REMOVE_BY_ENEMY_SPELL:
+ case AURA_REMOVE_BY_EXPIRE:
+ case AURA_REMOVE_BY_DEATH:
+ break;
+ default:
+ return;
+ }
+
+ GetTarget()->CastSpell(GetTarget(), SPELL_MALADY_OF_THE_MIND_JUMP);
+ }
+
+ void Register()
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_malady_of_the_mind_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_MOD_FEAR, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_malady_of_the_mind_SpellScript();
+ }
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_malady_of_the_mind_AuraScript();
+ }
+};
+
+class spell_yogg_saron_brain_link : public SpellScriptLoader // 63802
+{
+ public:
+ spell_yogg_saron_brain_link() : SpellScriptLoader("spell_yogg_saron_brain_link") { }
+
+ class spell_yogg_saron_brain_link_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_brain_link_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_ILLUSION_ROOM));
+
+ if (targets.size() != 2)
+ {
+ targets.clear();
+ return;
+ }
+
+ if (SaraAI* ai = CAST_AI(SaraAI, GetCaster()->GetAI()))
+ ai->SetLinkBetween(targets.front()->GetGUID(), targets.back()->GetGUID());
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_brain_link_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ class spell_yogg_saron_brain_link_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_brain_link_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_BRAIN_LINK_DAMAGE))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_BRAIN_LINK_NO_DAMAGE))
+ return false;
+ return true;
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ if (SaraAI* ai = CAST_AI(SaraAI, caster->GetAI()))
+ {
+ if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
+ ai->RemoveLinkFrom(GetTarget()->GetGUID());
+ else
+ {
+ if (Player* player = ObjectAccessor::GetPlayer(*GetTarget(), ai->GetLinkedPlayerGUID(GetTarget()->GetGUID())))
+ {
+ ai->RemoveLinkFrom(GetTarget()->GetGUID());
+ player->RemoveAurasDueToSpell(SPELL_BRAIN_LINK);
+ }
+ }
+ }
+ }
+
+ void DummyTick(AuraEffect const* aurEff)
+ {
+ Unit* caster = GetCaster();
+ if (!caster)
+ return;
+
+ SaraAI* ai = CAST_AI(SaraAI, caster->GetAI());
+ if (!ai)
+ return;
+
+ Player* linked = ObjectAccessor::GetPlayer(*GetTarget(), ai->GetLinkedPlayerGUID(GetTarget()->GetGUID()));
+ if (!linked)
+ return;
+
+ GetTarget()->CastSpell(linked, (GetTarget()->GetDistance(linked) > (float)aurEff->GetAmount()) ? SPELL_BRAIN_LINK_DAMAGE : SPELL_BRAIN_LINK_NO_DAMAGE, true);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_brain_link_AuraScript::DummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ OnEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_brain_link_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_brain_link_SpellScript();
+ }
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_brain_link_AuraScript();
+ }
+};
+
+class spell_yogg_saron_brain_link_damage : public SpellScriptLoader // 63803
+{
+ public:
+ spell_yogg_saron_brain_link_damage() : SpellScriptLoader("spell_yogg_saron_brain_link_damage") { }
+
+ class spell_yogg_saron_brain_link_damage_SpellScript : public SanityReduction
+ {
+ public:
+ spell_yogg_saron_brain_link_damage_SpellScript() : SanityReduction(2) { }
+
+ PrepareSpellScript(spell_yogg_saron_brain_link_damage_SpellScript);
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_brain_link_damage_SpellScript::RemoveSanity, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_brain_link_damage_SpellScript();
+ }
+};
+
+class spell_yogg_saron_boil_ominously : public SpellScriptLoader // 63030
+{
+ public:
+ spell_yogg_saron_boil_ominously() : SpellScriptLoader("spell_yogg_saron_boil_ominously") { }
+
+ class spell_yogg_saron_boil_ominously_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_boil_ominously_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_GUARDIAN_1))
+ return false;
+ return true;
+ }
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ if (!target->HasAura(SPELL_FLASH_FREEZE) && !GetCaster()->HasAura(SPELL_SUMMON_GUARDIAN_1) && !GetCaster()->HasAura(SPELL_SUMMON_GUARDIAN_2))
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
+ caster->AI()->Talk(EMOTE_OMINOUS_CLOUD_PLAYER_TOUCH, target->GetGUID());
+
+ GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_GUARDIAN_1, true);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_boil_ominously_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_boil_ominously_SpellScript();
+ }
+};
+
+class spell_yogg_saron_shadow_beacon : public SpellScriptLoader // 64465
+{
+ public:
+ spell_yogg_saron_shadow_beacon() : SpellScriptLoader("spell_yogg_saron_shadow_beacon") { }
+
+ class spell_yogg_saron_shadow_beacon_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_shadow_beacon_AuraScript);
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* target = GetTarget()->ToCreature())
+ target->SetEntry(NPC_MARKED_IMMORTAL_GUARDIAN);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Creature* target = GetTarget()->ToCreature())
+ target->SetEntry(NPC_IMMORTAL_GUARDIAN);
+ }
+
+ void Register()
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_shadow_beacon_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_shadow_beacon_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_shadow_beacon_AuraScript();
+ }
+};
+
+class spell_yogg_saron_empowering_shadows_range_check : public SpellScriptLoader // 64466
+{
+ public:
+ spell_yogg_saron_empowering_shadows_range_check() : SpellScriptLoader("spell_yogg_saron_empowering_shadows_range_check") { }
+
+ class spell_yogg_saron_empowering_shadows_range_check_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_empowering_shadows_range_check_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ target->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_empowering_shadows_range_check_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_empowering_shadows_range_check_SpellScript();
+ }
+};
+
+class spell_yogg_saron_empowering_shadows_missile : public SpellScriptLoader // 64467
+{
+ public:
+ spell_yogg_saron_empowering_shadows_missile() : SpellScriptLoader("spell_yogg_saron_empowering_shadows_missile") { }
+
+ class spell_yogg_saron_empowering_shadows_missile_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_empowering_shadows_missile_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_EMPOWERING_SHADOWS))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ target->CastSpell((Unit*)NULL, SPELL_EMPOWERING_SHADOWS, true);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_empowering_shadows_missile_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_empowering_shadows_missile_SpellScript();
+ }
+};
+
+// it works, but is it scripted correctly? why is it aura with 2500ms duration?
+class spell_yogg_saron_constrictor_tentacle : public SpellScriptLoader // 64132
+{
+ public:
+ spell_yogg_saron_constrictor_tentacle() : SpellScriptLoader("spell_yogg_saron_constrictor_tentacle") { }
+
+ class spell_yogg_saron_constrictor_tentacle_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_constrictor_tentacle_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_CONSTRICTOR_TENTACLE_SUMMON))
+ return false;
+ return true;
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), SPELL_CONSTRICTOR_TENTACLE_SUMMON);
+ }
+
+ void Register()
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_constrictor_tentacle_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_constrictor_tentacle_AuraScript();
+ }
+};
+
+class spell_yogg_saron_lunge : public SpellScriptLoader // 64131
+{
+ public:
+ spell_yogg_saron_lunge() : SpellScriptLoader("spell_yogg_saron_lunge") { }
+
+ class spell_yogg_saron_lunge_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_lunge_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SQUEEZE))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ target->CastSpell(target, SPELL_SQUEEZE, true);
+ target->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_lunge_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_lunge_SpellScript();
+ }
+};
+
+class spell_yogg_saron_squeeze : public SpellScriptLoader // 64125
+{
+ public:
+ spell_yogg_saron_squeeze() : SpellScriptLoader("spell_yogg_saron_squeeze") { }
+
+ class spell_yogg_saron_squeeze_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_squeeze_AuraScript);
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* vehicle = GetTarget()->GetVehicleBase())
+ if (vehicle->isAlive())
+ vehicle->Kill(vehicle); // should tentacle die or just release its target?
+ }
+
+ void Register()
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_squeeze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_squeeze_AuraScript();
+ }
+};
+
+class spell_yogg_saron_diminsh_power : public SpellScriptLoader // 64148
+{
+ public:
+ spell_yogg_saron_diminsh_power() : SpellScriptLoader("spell_yogg_saron_diminsh_power") { }
+
+ class spell_yogg_saron_diminsh_power_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_diminsh_power_AuraScript);
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ if (Spell* spell = GetTarget()->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
+ if (spell->getState() == SPELL_STATE_CASTING)
+ GetTarget()->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ }
+
+ void Register()
+ {
+ OnEffectProc += AuraEffectProcFn(spell_yogg_saron_diminsh_power_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_diminsh_power_AuraScript();
+ }
+};
+
+// not sure about SPELL_WEAKENED part, where should it be handled?
+class spell_yogg_saron_empowered : public SpellScriptLoader // 64161
+{
+ public:
+ spell_yogg_saron_empowered() : SpellScriptLoader("spell_yogg_saron_empowered") { }
+
+ class spell_yogg_saron_empowered_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_empowered_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_EMPOWERED_BUFF))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_WEAKENED))
+ return false;
+ return true;
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastCustomSpell(SPELL_EMPOWERED_BUFF, SPELLVALUE_AURA_STACK, 9, GetTarget(), TRIGGERED_FULL_MASK);
+ }
+
+ void OnPeriodic(AuraEffect const* /*aurEff*/)
+ {
+ Unit* target = GetTarget();
+ float stack = ceil((target->GetHealthPct() / 10) - 1);
+ target->RemoveAurasDueToSpell(SPELL_EMPOWERED_BUFF);
+
+ if (stack)
+ {
+ target->RemoveAurasDueToSpell(SPELL_WEAKENED);
+ target->CastCustomSpell(SPELL_EMPOWERED_BUFF, SPELLVALUE_AURA_STACK, stack, target, TRIGGERED_FULL_MASK);
+ }
+ else if (!target->HealthAbovePct(1) && !target->HasAura(SPELL_WEAKENED))
+ target->CastSpell(target, SPELL_WEAKENED, true);
+ }
+
+ void Register()
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_empowered_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_empowered_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_empowered_AuraScript();
+ }
+};
+
+class spell_yogg_saron_match_health : public SpellScriptLoader // 64069
+{
+ public:
+ spell_yogg_saron_match_health() : SpellScriptLoader("spell_yogg_saron_match_health") { }
+
+ class spell_yogg_saron_match_health_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_match_health_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ target->SetHealth(target->CountPctFromMaxHealth((int32)GetCaster()->GetHealthPct()));
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_match_health_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_match_health_SpellScript();
+ }
+};
+
+class spell_yogg_saron_shattered_illusion : public SpellScriptLoader // 65238
+{
+ public:
+ spell_yogg_saron_shattered_illusion() : SpellScriptLoader("spell_yogg_saron_shattered_illusion") { }
+
+ class spell_yogg_saron_shattered_illusion_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_shattered_illusion_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ target->RemoveAurasDueToSpell(uint32(GetEffectValue()));
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_shattered_illusion_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_shattered_illusion_SpellScript();
+ }
+};
+
+class spell_yogg_saron_death_ray_warning_visual : public SpellScriptLoader // 63882
+{
+ public:
+ spell_yogg_saron_death_ray_warning_visual() : SpellScriptLoader("spell_yogg_saron_death_ray_warning_visual") { }
+
+ class spell_yogg_saron_death_ray_warning_visual_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_death_ray_warning_visual_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_RAY_PERIODIC))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_RAY_DAMAGE_VISUAL))
+ return false;
+ return true;
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ {
+ caster->CastSpell(caster, SPELL_DEATH_RAY_PERIODIC, true);
+ caster->CastSpell((Unit*)NULL, SPELL_DEATH_RAY_DAMAGE_VISUAL, true);
+ // TODO: set better movement
+ caster->GetMotionMaster()->MoveConfused();
+ }
+ }
+
+ void Register()
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_death_ray_warning_visual_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_death_ray_warning_visual_AuraScript();
+ }
+};
+
+class spell_yogg_saron_cancel_illusion_room_aura : public SpellScriptLoader // 63993
+{
+ public:
+ spell_yogg_saron_cancel_illusion_room_aura() : SpellScriptLoader("spell_yogg_saron_cancel_illusion_room_aura") { }
+
+ class spell_yogg_saron_cancel_illusion_room_aura_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_cancel_illusion_room_aura_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_TELEPORT_BACK_TO_MAIN_ROOM))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ target->CastSpell(target, SPELL_TELEPORT_BACK_TO_MAIN_ROOM);
+ target->RemoveAurasDueToSpell(uint32(GetEffectValue()));
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_cancel_illusion_room_aura_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_cancel_illusion_room_aura_SpellScript();
+ }
+};
+
+class spell_yogg_saron_nondescript : public SpellScriptLoader // 64010, 64013
+{
+ public:
+ spell_yogg_saron_nondescript() : SpellScriptLoader("spell_yogg_saron_nondescript") { }
+
+ class spell_yogg_saron_nondescript_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_nondescript_AuraScript);
+
+ void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), uint32(aurEff->GetAmount()), true);
+ }
+
+ void Register()
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_nondescript_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_nondescript_AuraScript();
+ }
+};
+
+class spell_yogg_saron_revealed_tentacle : public SpellScriptLoader // 64012
+{
+ public:
+ spell_yogg_saron_revealed_tentacle() : SpellScriptLoader("spell_yogg_saron_revealed_tentacle") { }
+
+ class spell_yogg_saron_revealed_tentacle_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_revealed_tentacle_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_TENTACLE_VOID_ZONE))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_GRIM_REPRISAL))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
+ {
+ caster->CastSpell(caster, SPELL_TENTACLE_VOID_ZONE, true);
+ caster->CastSpell(caster, SPELL_GRIM_REPRISAL, true);
+ caster->UpdateEntry(NPC_INFLUENCE_TENTACLE, 0, caster->GetCreatureData());
+ }
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_revealed_tentacle_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_revealed_tentacle_SpellScript();
+ }
+};
+
+class spell_yogg_saron_grim_reprisal : public SpellScriptLoader // 63305
+{
+ public:
+ spell_yogg_saron_grim_reprisal() : SpellScriptLoader("spell_yogg_saron_grim_reprisal") { }
+
+ class spell_yogg_saron_grim_reprisal_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_grim_reprisal_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_GRIM_REPRISAL_DAMAGE))
+ return false;
+ return true;
+ }
+
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ int32 damage = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), 60);
+ GetTarget()->CastCustomSpell(SPELL_GRIM_REPRISAL_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetDamageInfo()->GetAttacker(), true, NULL, aurEff);
+ }
+
+ void Register()
+ {
+ OnEffectProc += AuraEffectProcFn(spell_yogg_saron_grim_reprisal_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_grim_reprisal_AuraScript();
+ }
+};
+
+class spell_yogg_saron_induce_madness : public SpellScriptLoader // 64059
+{
+ public:
+ spell_yogg_saron_induce_madness() : SpellScriptLoader("spell_yogg_saron_induce_madness") { }
+
+ class spell_yogg_saron_induce_madness_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_induce_madness_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_TELEPORT_BACK_TO_MAIN_ROOM))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_SHATTERED_ILLUSION_REMOVE))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ target->CastSpell(target, SPELL_TELEPORT_BACK_TO_MAIN_ROOM);
+ target->RemoveAurasDueToSpell(SPELL_SANITY, 0, 0, AURA_REMOVE_BY_ENEMY_SPELL);
+ target->RemoveAurasDueToSpell(uint32(GetEffectValue()));
+ }
+ }
+
+ void ClearShatteredIllusion()
+ {
+ GetCaster()->CastSpell((Unit*)NULL, SPELL_SHATTERED_ILLUSION_REMOVE);
+
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ if (Creature* voice = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_VOICE_OF_YOGG_SARON)))
+ voice->AI()->DoAction(ACTION_TOGGLE_SHATTERED_ILLUSION);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_induce_madness_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ AfterCast += SpellCastFn(spell_yogg_saron_induce_madness_SpellScript::ClearShatteredIllusion);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_induce_madness_SpellScript();
+ }
+};
+
+class spell_yogg_saron_sanity : public SpellScriptLoader // 63050
+{
+ public:
+ spell_yogg_saron_sanity() : SpellScriptLoader("spell_yogg_saron_sanity") { }
+
+ class spell_yogg_saron_sanity_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_sanity_SpellScript);
+
+ // don't target players outside of room or handle it in SPELL_INSANE_PERIODIC?
+
+ void ModSanityStacks()
+ {
+ GetSpell()->SetSpellValue(SPELLVALUE_AURA_STACK, 100);
+ }
+
+ void Register()
+ {
+ BeforeCast += SpellCastFn(spell_yogg_saron_sanity_SpellScript::ModSanityStacks);
+ }
+ };
+
+ class spell_yogg_saron_sanity_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_sanity_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_LOW_SANITY_SCREEN_EFFECT))
+ return false;
+ if (!sSpellMgr->GetSpellInfo(SPELL_INSANE))
+ return false;
+ return true;
+ }
+
+ void DummyTick(AuraEffect const* aurEff)
+ {
+ if (GetTarget()->HasAura(SPELL_SANITY_WELL))
+ ModStackAmount(20);
+
+ if (GetStackAmount() <= 40 && !GetTarget()->HasAura(SPELL_LOW_SANITY_SCREEN_EFFECT))
+ GetTarget()->CastSpell(GetTarget(), SPELL_LOW_SANITY_SCREEN_EFFECT, true);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
+ return;
+
+ if (InstanceScript* instance = GetTarget()->GetInstanceScript())
+ instance->SetData(DATA_DRIVE_ME_CRAZY, uint32(false));
+
+ GetTarget()->RemoveAurasDueToSpell(SPELL_BRAIN_LINK);
+
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), SPELL_INSANE, true);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_yogg_saron_sanity_AuraScript::DummyTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_sanity_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_sanity_SpellScript();
+ }
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_sanity_AuraScript();
+ }
+};
+
+class spell_yogg_saron_insane : public SpellScriptLoader // 63120
+{
+ public:
+ spell_yogg_saron_insane() : SpellScriptLoader("spell_yogg_saron_insane") { }
+
+ class spell_yogg_saron_insane_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_insane_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_INSANE_VISUAL))
+ return false;
+ return true;
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (Creature* yogg = caster->ToCreature())
+ yogg->AI()->Talk(WHISPER_VOICE_INSANE, GetTarget()->GetGUID());
+
+ GetTarget()->CastSpell(GetTarget(), SPELL_INSANE_VISUAL, true);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTarget()->isAlive())
+ GetTarget()->Kill(GetTarget());
+ }
+
+ void Register()
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_yogg_saron_insane_AuraScript::OnApply, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_yogg_saron_insane_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_AOE_CHARM, AURA_EFFECT_HANDLE_REAL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_insane_AuraScript();
+ }
+};
+
+class spell_yogg_saron_insane_periodic : public SpellScriptLoader // 64555
+{
+ public:
+ spell_yogg_saron_insane_periodic() : SpellScriptLoader("spell_yogg_saron_insane_periodic") { }
+
+ class spell_yogg_saron_insane_periodic_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_insane_periodic_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ GetCaster()->CastSpell(target, uint32(GetEffectValue()), true);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_insane_periodic_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_insane_periodic_SpellScript();
+ }
+};
+
+class LunaticGazeTargetSelector
+{
+ public:
+ LunaticGazeTargetSelector(Unit* caster) : _caster(caster) { }
+
+ bool operator()(WorldObject* object)
+ {
+ return !object->HasInArc(static_cast<float>(M_PI), _caster);
+ }
+
+ private:
+ Unit* _caster;
+};
+
+class spell_yogg_saron_lunatic_gaze : public SpellScriptLoader // 64164, 64168
+{
+ public:
+ spell_yogg_saron_lunatic_gaze() : SpellScriptLoader("spell_yogg_saron_lunatic_gaze") { }
+
+ class spell_yogg_saron_lunatic_gaze_SpellScript : public SanityReduction
+ {
+ PrepareSpellScript(spell_yogg_saron_lunatic_gaze_SpellScript);
+
+ bool Load()
+ {
+ _stacks = GetSpellInfo()->Id == SPELL_LUNATIC_GAZE_DAMAGE ? 4 : 2;
+ return true;
+ }
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(LunaticGazeTargetSelector(GetCaster()));
+ }
+
+ void Register()
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_lunatic_gaze_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_yogg_saron_lunatic_gaze_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_lunatic_gaze_SpellScript::RemoveSanity, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_lunatic_gaze_SpellScript();
+ }
+};
+
+class spell_yogg_saron_keeper_aura : public SpellScriptLoader // 62650, 62670, 62671, 62702
+{
+ public:
+ spell_yogg_saron_keeper_aura() : SpellScriptLoader("spell_yogg_saron_keeper_aura") { }
+
+ class spell_yogg_saron_keeper_aura_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_keeper_aura_AuraScript);
+
+ bool CanApply(Unit* target)
+ {
+ if (target->GetTypeId() != TYPEID_PLAYER && target != GetCaster())
+ return false;
+ return true;
+ }
+
+ void Register()
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_yogg_saron_keeper_aura_AuraScript::CanApply);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_keeper_aura_AuraScript();
+ }
+};
+
+class spell_yogg_saron_hate_to_zero : public SpellScriptLoader // 63984
+{
+ public:
+ spell_yogg_saron_hate_to_zero() : SpellScriptLoader("spell_yogg_saron_hate_to_zero") { }
+
+ class spell_yogg_saron_hate_to_zero_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_hate_to_zero_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ if (target->CanHaveThreatList())
+ target->getThreatManager().modifyThreatPercent(GetCaster(), -100);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_hate_to_zero_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_hate_to_zero_SpellScript();
+ }
+};
+
+class spell_yogg_saron_in_the_maws_of_the_old_god : public SpellScriptLoader // 64184
+{
+ public:
+ spell_yogg_saron_in_the_maws_of_the_old_god() : SpellScriptLoader("spell_yogg_saron_in_the_maws_of_the_old_god") { }
+
+ class spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript);
+
+ SpellCastResult CheckRequirement()
+ {
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ if (Creature* yogg = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(BOSS_YOGG_SARON)))
+ if (yogg->FindCurrentSpellBySpellId(SPELL_DEAFENING_ROAR))
+ if (GetCaster()->GetDistance(yogg) > 20.0f)
+ return SPELL_FAILED_OUT_OF_RANGE;
+ else
+ return SPELL_CAST_OK;
+
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+ }
+
+ void Register()
+ {
+ OnCheckCast += SpellCheckCastFn(spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript::CheckRequirement);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_in_the_maws_of_the_old_god_SpellScript();
+ }
+};
+
+class spell_yogg_saron_titanic_storm : public SpellScriptLoader // 64172
+{
+ public:
+ spell_yogg_saron_titanic_storm() : SpellScriptLoader("spell_yogg_saron_titanic_storm") { }
+
+ class spell_yogg_saron_titanic_storm_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_yogg_saron_titanic_storm_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ GetCaster()->Kill(target);
+ }
+
+ void Register()
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_yogg_saron_titanic_storm_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_yogg_saron_titanic_storm_SpellScript();
+ }
+};
+
+class spell_yogg_saron_hodirs_protective_gaze : public SpellScriptLoader // 64174
+{
+ public:
+ spell_yogg_saron_hodirs_protective_gaze() : SpellScriptLoader("spell_yogg_saron_hodirs_protective_gaze") { }
+
+ class spell_yogg_saron_hodirs_protective_gaze_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_yogg_saron_hodirs_protective_gaze_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/)
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_FLASH_FREEZE))
+ return false;
+ return true;
+ }
+
+ bool CanApply(Unit* target)
+ {
+ if (target->GetTypeId() != TYPEID_PLAYER && target != GetCaster())
+ return false;
+ return true;
+ }
+
+ void OnAbsorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount)
+ {
+ if (dmgInfo.GetDamage() >= GetTarget()->GetHealth())
+ {
+ absorbAmount = dmgInfo.GetDamage();
+ // or absorbAmount = dmgInfo.GetDamage() - GetTarget()->GetHealth() + 1
+ GetTarget()->CastSpell(GetTarget(), SPELL_FLASH_FREEZE, true);
+ }
+ else
+ PreventDefaultAction();
+ }
+
+ void Register()
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_yogg_saron_hodirs_protective_gaze_AuraScript::CanApply);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_yogg_saron_hodirs_protective_gaze_AuraScript::OnAbsorb, EFFECT_0);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_yogg_saron_hodirs_protective_gaze_AuraScript();
+ }
+};
+
+void AddSC_boss_yogg_saron()
+{
+ new boss_voice_of_yogg_saron();
+ new boss_sara();
+ new boss_yogg_saron();
+ new boss_brain_of_yogg_saron();
+ new npc_ominous_cloud();
+ new npc_guardian_of_yogg_saron();
+ new npc_corruptor_tentacle();
+ new npc_constrictor_tentacle();
+ new npc_crusher_tentacle();
+ new npc_influence_tentacle();
+ new npc_descend_into_madness();
+ new npc_immortal_guardian();
+ new npc_observation_ring_keeper();
+ new npc_yogg_saron_keeper();
+ new npc_yogg_saron_illusions();
+ new npc_garona();
+ new npc_turned_champion();
+ new npc_laughing_skull();
+ new spell_yogg_saron_target_selectors();
+ new spell_yogg_saron_psychosis();
+ new spell_yogg_saron_malady_of_the_mind();
+ new spell_yogg_saron_brain_link();
+ new spell_yogg_saron_brain_link_damage();
+ new spell_yogg_saron_boil_ominously();
+ new spell_yogg_saron_shadow_beacon();
+ new spell_yogg_saron_empowering_shadows_range_check();
+ new spell_yogg_saron_empowering_shadows_missile();
+ new spell_yogg_saron_constrictor_tentacle();
+ new spell_yogg_saron_lunge();
+ new spell_yogg_saron_squeeze();
+ new spell_yogg_saron_diminsh_power();
+ new spell_yogg_saron_empowered();
+ new spell_yogg_saron_match_health();
+ new spell_yogg_saron_shattered_illusion();
+ new spell_yogg_saron_death_ray_warning_visual();
+ new spell_yogg_saron_cancel_illusion_room_aura();
+ new spell_yogg_saron_nondescript();
+ new spell_yogg_saron_revealed_tentacle();
+ new spell_yogg_saron_grim_reprisal();
+ new spell_yogg_saron_induce_madness();
+ new spell_yogg_saron_sanity();
+ new spell_yogg_saron_insane();
+ new spell_yogg_saron_insane_periodic();
+ new spell_yogg_saron_lunatic_gaze();
+ new spell_yogg_saron_keeper_aura();
+ new spell_yogg_saron_hate_to_zero();
+ new spell_yogg_saron_in_the_maws_of_the_old_god();
+ new spell_yogg_saron_titanic_storm();
+ new spell_yogg_saron_hodirs_protective_gaze();
+}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp
deleted file mode 100644
index 4bcb1b9e584..00000000000
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yoggsaron.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- *
- * 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 "ScriptMgr.h"
-#include "ulduar.h"
-
-enum Sara
-{
- // text
- YELL_SARA_PREFIGHT = 0,
- YELL_COMBAT_PHASE_1 = 1,
- YELL_COMBAT_PHASE_2 = 2,
- YELL_SLAY = 3,
-
- // Phase 1 spells
- SPELL_SARAS_ANGER_1 = 63147, // Target Entry 33136
- SPELL_SARAS_ANGER_2 = 63744, // Target Entry 33136
- SPELL_SARAS_FEVOR_1 = 63138, // Target Player
- SPELL_SARAS_FEVOR_2 = 63747, // Target Player
- SPELL_SARAS_BLESSING_1 = 63134, // Target Player
- SPELL_SARAS_BLESSING_2 = 63745, // Target Self
-
- // Phase 2 spells
- SPELL_PHYCHOSIS = 63795, // Target Self
- SPELL_MALADY_OF_THE_MIND = 63830, // Target Self
- SPELL_DEATH_RAY = 63891, // Target Self
- SPELL_BRAIN_LINK = 63802, // Target Self
-};
-
-enum YoggSaron_Yells
-{
-};
-
-enum
-{
- ACHIEV_TIMED_START_EVENT = 21001,
-};
-//not in scriptloader yet just to remove warning boss_yoggsaron.obj : warning LNK4221: no public symbols found; archive member will be inaccessible
-void AddSC_boss_yoggsaron()
-{
-}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index 125f66497bf..421d0ecf3c9 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -24,14 +24,15 @@
static DoorData const doorData[] =
{
- {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
- {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S },
- {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W },
- {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE },
- {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
- {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
- {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
- {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S },
+ {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S },
+ {GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S },
+ {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W },
+ {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE },
+ {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
+ {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
+ {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE },
+ {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE },
};
MinionData const minionData[] =
@@ -56,7 +57,6 @@ class instance_ulduar : public InstanceMapScript
uint64 IgnisGUID;
uint64 RazorscaleGUID;
uint64 RazorscaleController;
- uint64 RazorHarpoonGUIDs[4];
uint64 ExpeditionCommanderGUID;
uint64 XT002GUID;
uint64 XTToyPileGUIDs[4];
@@ -67,14 +67,18 @@ class instance_ulduar : public InstanceMapScript
uint64 HodirGUID;
uint64 ThorimGUID;
uint64 FreyaGUID;
- uint64 KeeperGUIDs[3];
+ uint64 ElderGUIDs[3];
uint64 VezaxGUID;
uint64 YoggSaronGUID;
+ uint64 VoiceOfYoggSaronGUID;
+ uint64 SaraGUID;
+ uint64 BrainOfYoggSaronGUID;
uint64 AlgalonGUID;
- uint64 LeviathanGateGUID;
- uint64 VezaxDoorGUID;
+ uint64 BrannBronzebeardAlgGUID;
// GameObjects
+ uint64 LeviathanGateGUID;
+ uint64 RazorHarpoonGUIDs[4];
uint64 KologarnChestGUID;
uint64 KologarnBridgeGUID;
uint64 KologarnDoorGUID;
@@ -84,11 +88,13 @@ class instance_ulduar : public InstanceMapScript
uint64 HodirDoorGUID;
uint64 HodirIceDoorGUID;
uint64 ArchivumDoorGUID;
+ uint64 VezaxDoorGUID;
+ uint64 BrainRoomDoorGUIDs[3];
+ uint64 KeeperGUIDs[4];
uint64 AlgalonSigilDoorGUID[3];
uint64 AlgalonFloorGUID[2];
uint64 AlgalonUniverseGUID;
uint64 AlgalonTrapdoorGUID;
- uint64 BrannBronzebeardAlgGUID;
uint64 GiftOfTheObserverGUID;
// Miscellaneous
@@ -96,8 +102,11 @@ class instance_ulduar : public InstanceMapScript
uint32 HodirRareCacheData;
uint32 ColossusData;
uint8 elderCount;
+ uint8 illusion;
+ uint8 keepersCount;
bool conSpeedAtory;
bool Unbroken;
+ bool IsDriveMeCrazyEligible;
std::set<uint64> mRubbleSpawns;
@@ -119,6 +128,9 @@ class instance_ulduar : public InstanceMapScript
FreyaGUID = 0;
VezaxGUID = 0;
YoggSaronGUID = 0;
+ VoiceOfYoggSaronGUID = 0;
+ SaraGUID = 0;
+ BrainOfYoggSaronGUID = 0;
AlgalonGUID = 0;
KologarnChestGUID = 0;
KologarnBridgeGUID = 0;
@@ -141,6 +153,8 @@ class instance_ulduar : public InstanceMapScript
HodirRareCacheData = 0;
ColossusData = 0;
elderCount = 0;
+ illusion = 0;
+ keepersCount = 0;
conSpeedAtory = false;
Unbroken = true;
_algalonSummoned = false;
@@ -151,7 +165,11 @@ class instance_ulduar : public InstanceMapScript
memset(XTToyPileGUIDs, 0, sizeof(XTToyPileGUIDs));
memset(AssemblyGUIDs, 0, sizeof(AssemblyGUIDs));
memset(RazorHarpoonGUIDs, 0, sizeof(RazorHarpoonGUIDs));
+ memset(ElderGUIDs, 0, sizeof(ElderGUIDs));
+ memset(BrainRoomDoorGUIDs, 0, sizeof(BrainRoomDoorGUIDs));
memset(KeeperGUIDs, 0, sizeof(KeeperGUIDs));
+ memset(_summonObservationRingKeeper, false, sizeof(_summonObservationRingKeeper));
+ memset(_summonYSKeeper, false, sizeof(_summonYSKeeper));
}
void FillInitialWorldStates(WorldPacket& packet)
@@ -174,6 +192,38 @@ class instance_ulduar : public InstanceMapScript
else
algalon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
}
+
+ // Keepers at Observation Ring
+ if (GetBossState(BOSS_FREYA) == DONE && _summonObservationRingKeeper[0] && !KeeperGUIDs[0])
+ {
+ _summonObservationRingKeeper[0] = false;
+ instance->SummonCreature(NPC_FREYA_OBSERVATION_RING, ObservationRingKeepersPos[0]);
+ }
+ if (GetBossState(BOSS_HODIR) == DONE && _summonObservationRingKeeper[1] && !KeeperGUIDs[1])
+ {
+ _summonObservationRingKeeper[1] = false;
+ instance->SummonCreature(NPC_HODIR_OBSERVATION_RING, ObservationRingKeepersPos[1]);
+ }
+ if (GetBossState(BOSS_THORIM) == DONE && _summonObservationRingKeeper[2] && !KeeperGUIDs[2])
+ {
+ _summonObservationRingKeeper[2] = false;
+ instance->SummonCreature(NPC_THORIM_OBSERVATION_RING, ObservationRingKeepersPos[2]);
+ }
+ if (GetBossState(BOSS_MIMIRON) == DONE && _summonObservationRingKeeper[3] && !KeeperGUIDs[3])
+ {
+ _summonObservationRingKeeper[3] = false;
+ instance->SummonCreature(NPC_MIMIRON_OBSERVATION_RING, ObservationRingKeepersPos[3]);
+ }
+
+ // Keepers in Yogg-Saron's room
+ if (_summonYSKeeper[0])
+ instance->SummonCreature(NPC_FREYA_YS, YSKeepersPos[0]);
+ if (_summonYSKeeper[1])
+ instance->SummonCreature(NPC_HODIR_YS, YSKeepersPos[1]);
+ if (_summonYSKeeper[2])
+ instance->SummonCreature(NPC_THORIM_YS, YSKeepersPos[2]);
+ if (_summonYSKeeper[3])
+ instance->SummonCreature(NPC_MIMIRON_YS, YSKeepersPos[3]);
}
void OnCreatureCreate(Creature* creature)
@@ -194,6 +244,8 @@ class instance_ulduar : public InstanceMapScript
case NPC_IGNIS:
IgnisGUID = creature->GetGUID();
break;
+
+ // Razorscale
case NPC_RAZORSCALE:
RazorscaleGUID = creature->GetGUID();
break;
@@ -203,6 +255,8 @@ class instance_ulduar : public InstanceMapScript
case NPC_EXPEDITION_COMMANDER:
ExpeditionCommanderGUID = creature->GetGUID();
break;
+
+ // XT-002 Deconstructor
case NPC_XT002:
XT002GUID = creature->GetGUID();
break;
@@ -229,24 +283,6 @@ class instance_ulduar : public InstanceMapScript
AddMinion(creature, true);
break;
- // Freya's Keeper
- case NPC_IRONBRANCH:
- KeeperGUIDs[0] = creature->GetGUID();
- if (GetBossState(BOSS_FREYA) == DONE)
- creature->DespawnOrUnsummon();
- break;
- case NPC_BRIGHTLEAF:
- KeeperGUIDs[1] = creature->GetGUID();
- if (GetBossState(BOSS_FREYA) == DONE)
- creature->DespawnOrUnsummon();
- break;
- case NPC_STONEBARK:
- KeeperGUIDs[2] = creature->GetGUID();
- if (GetBossState(BOSS_FREYA) == DONE)
- creature->DespawnOrUnsummon();
- break;
-
- // Kologarn
case NPC_KOLOGARN:
KologarnGUID = creature->GetGUID();
break;
@@ -256,25 +292,11 @@ class instance_ulduar : public InstanceMapScript
case NPC_MIMIRON:
MimironGUID = creature->GetGUID();
break;
+
+ // Hodir
case NPC_HODIR:
HodirGUID = creature->GetGUID();
break;
- case NPC_THORIM:
- ThorimGUID = creature->GetGUID();
- break;
- case NPC_FREYA:
- FreyaGUID = creature->GetGUID();
- break;
- case NPC_VEZAX:
- VezaxGUID = creature->GetGUID();
- break;
- case NPC_YOGGSARON:
- YoggSaronGUID = creature->GetGUID();
- break;
- case NPC_ALGALON:
- AlgalonGUID = creature->GetGUID();
- break;
- // Hodir's Helper NPCs
case NPC_EIVI_NIGHTFEATHER:
if (TeamInInstance == HORDE)
creature->UpdateEntry(NPC_TOR_GREYCLOUD, HORDE);
@@ -307,6 +329,80 @@ class instance_ulduar : public InstanceMapScript
if (TeamInInstance == HORDE)
creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA, HORDE);
break;
+
+ case NPC_THORIM:
+ ThorimGUID = creature->GetGUID();
+ break;
+
+ // Freya
+ case NPC_FREYA:
+ FreyaGUID = creature->GetGUID();
+ break;
+ case NPC_IRONBRANCH:
+ ElderGUIDs[0] = creature->GetGUID();
+ if (GetBossState(BOSS_FREYA) == DONE)
+ creature->DespawnOrUnsummon();
+ break;
+ case NPC_BRIGHTLEAF:
+ ElderGUIDs[1] = creature->GetGUID();
+ if (GetBossState(BOSS_FREYA) == DONE)
+ creature->DespawnOrUnsummon();
+ break;
+ case NPC_STONEBARK:
+ ElderGUIDs[2] = creature->GetGUID();
+ if (GetBossState(BOSS_FREYA) == DONE)
+ creature->DespawnOrUnsummon();
+ break;
+
+ case NPC_VEZAX:
+ VezaxGUID = creature->GetGUID();
+ break;
+
+ // Yogg-Saron
+ case NPC_YOGG_SARON:
+ YoggSaronGUID = creature->GetGUID();
+ break;
+ case NPC_VOICE_OF_YOGG_SARON:
+ VoiceOfYoggSaronGUID = creature->GetGUID();
+ break;
+ case NPC_BRAIN_OF_YOGG_SARON:
+ BrainOfYoggSaronGUID = creature->GetGUID();
+ break;
+ case NPC_SARA:
+ SaraGUID = creature->GetGUID();
+ break;
+ case NPC_FREYA_YS:
+ KeeperGUIDs[0] = creature->GetGUID();
+ _summonYSKeeper[0] = false;
+ SaveToDB();
+ ++keepersCount;
+ break;
+ case NPC_HODIR_YS:
+ KeeperGUIDs[1] = creature->GetGUID();
+ _summonYSKeeper[1] = false;
+ SaveToDB();
+ ++keepersCount;
+ break;
+ case NPC_THORIM_YS:
+ KeeperGUIDs[2] = creature->GetGUID();
+ _summonYSKeeper[2] = false;
+ SaveToDB();
+ ++keepersCount;
+ break;
+ case NPC_MIMIRON_YS:
+ KeeperGUIDs[3] = creature->GetGUID();
+ _summonYSKeeper[3] = false;
+ SaveToDB();
+ ++keepersCount;
+ break;
+ case NPC_SANITY_WELL:
+ creature->SetReactState(REACT_PASSIVE);
+ break;
+
+ // Algalon
+ case NPC_ALGALON:
+ AlgalonGUID = creature->GetGUID();
+ break;
case NPC_BRANN_BRONZBEARD_ALG:
BrannBronzebeardAlgGUID = creature->GetGUID();
break;
@@ -418,6 +514,18 @@ class instance_ulduar : public InstanceMapScript
if (GetBossState(BOSS_ASSEMBLY_OF_IRON) != DONE)
HandleGameObject(ArchivumDoorGUID, false);
break;
+ case GO_YOGG_SARON_DOOR:
+ AddDoor(gameObject, true);
+ break;
+ case GO_BRAIN_ROOM_DOOR_1:
+ BrainRoomDoorGUIDs[0] = gameObject->GetGUID();
+ break;
+ case GO_BRAIN_ROOM_DOOR_2:
+ BrainRoomDoorGUIDs[1] = gameObject->GetGUID();
+ break;
+ case GO_BRAIN_ROOM_DOOR_3:
+ BrainRoomDoorGUIDs[2] = gameObject->GetGUID();
+ break;
case GO_CELESTIAL_PLANETARIUM_ACCESS_10:
case GO_CELESTIAL_PLANETARIUM_ACCESS_25:
if (_algalonSummoned)
@@ -509,27 +617,36 @@ class instance_ulduar : public InstanceMapScript
{
// Flame Leviathan's Tower Event triggers
Creature* FlameLeviathan = instance->GetCreature(LeviathanGUID);
- if (FlameLeviathan && FlameLeviathan->isAlive()) // No leviathan, no event triggering ;)
+
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_TOWER_OF_STORM_DESTROYED:
+ case EVENT_TOWER_OF_STORM_DESTROYED:
+ if (FlameLeviathan && FlameLeviathan->isAlive())
FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_STORM_DESTROYED);
- break;
- case EVENT_TOWER_OF_FROST_DESTROYED:
+ break;
+ case EVENT_TOWER_OF_FROST_DESTROYED:
+ if (FlameLeviathan && FlameLeviathan->isAlive())
FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FROST_DESTROYED);
- break;
- case EVENT_TOWER_OF_FLAMES_DESTROYED:
+ break;
+ case EVENT_TOWER_OF_FLAMES_DESTROYED:
+ if (FlameLeviathan && FlameLeviathan->isAlive())
FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_FLAMES_DESTROYED);
- break;
- case EVENT_TOWER_OF_LIFE_DESTROYED:
+ break;
+ case EVENT_TOWER_OF_LIFE_DESTROYED:
+ if (FlameLeviathan && FlameLeviathan->isAlive())
FlameLeviathan->AI()->DoAction(ACTION_TOWER_OF_LIFE_DESTROYED);
- break;
- }
+ break;
+ case EVENT_ACTIVATE_SANITY_WELL:
+ if (Creature* freya = instance->GetCreature(KeeperGUIDs[0]))
+ freya->AI()->DoAction(4/*ACTION_SANITY_WELLS*/);
+ break;
+ case EVENT_HODIRS_PROTECTIVE_GAZE_PROC:
+ if (Creature* hodir = instance->GetCreature(KeeperGUIDs[1]))
+ hodir->AI()->DoAction(5/*ACTION_FLASH_FREEZE*/);
+ break;
}
}
-
bool SetBossState(uint32 type, EncounterState state)
{
if (!InstanceScript::SetBossState(type, state))
@@ -542,8 +659,14 @@ class instance_ulduar : public InstanceMapScript
case BOSS_RAZORSCALE:
case BOSS_XT002:
case BOSS_AURIAYA:
+ break;
case BOSS_MIMIRON:
+ if (state == DONE)
+ instance->SummonCreature(NPC_MIMIRON_OBSERVATION_RING, ObservationRingKeepersPos[3]);
+ break;
case BOSS_FREYA:
+ if (state == DONE)
+ instance->SummonCreature(NPC_FREYA_OBSERVATION_RING, ObservationRingKeepersPos[0]);
break;
case BOSS_ASSEMBLY_OF_IRON:
if (state == DONE)
@@ -553,7 +676,7 @@ class instance_ulduar : public InstanceMapScript
if (state == DONE)
HandleGameObject(VezaxDoorGUID, true);
break;
- case BOSS_YOGGSARON:
+ case BOSS_YOGG_SARON:
break;
case BOSS_KOLOGARN:
if (state == DONE)
@@ -576,12 +699,18 @@ class instance_ulduar : public InstanceMapScript
HodirChest->SetRespawnTime(HodirChest->GetRespawnDelay());
HandleGameObject(HodirDoorGUID, true);
HandleGameObject(HodirIceDoorGUID, true);
+
+ instance->SummonCreature(NPC_HODIR_OBSERVATION_RING, ObservationRingKeepersPos[1]);
}
break;
case BOSS_THORIM:
if (state == DONE)
+ {
if (GameObject* gameObject = instance->GetGameObject(ThorimChestGUID))
gameObject->SetRespawnTime(gameObject->GetRespawnDelay());
+
+ instance->SummonCreature(NPC_THORIM_OBSERVATION_RING, ObservationRingKeepersPos[2]);
+ }
break;
case BOSS_ALGALON:
if (state == DONE)
@@ -661,6 +790,12 @@ class instance_ulduar : public InstanceMapScript
case DATA_UNBROKEN:
Unbroken = bool(data);
break;
+ case DATA_ILLUSION:
+ illusion = data;
+ break;
+ case DATA_DRIVE_ME_CRAZY:
+ IsDriveMeCrazyEligible = data ? true : false;
+ break;
case EVENT_DESPAWN_ALGALON:
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, 60);
@@ -688,10 +823,24 @@ class instance_ulduar : public InstanceMapScript
return LeviathanGUID;
case BOSS_IGNIS:
return IgnisGUID;
+
+ // Razorscale
case BOSS_RAZORSCALE:
return RazorscaleGUID;
case DATA_RAZORSCALE_CONTROL:
return RazorscaleController;
+ case DATA_EXPEDITION_COMMANDER:
+ return ExpeditionCommanderGUID;
+ case GO_RAZOR_HARPOON_1:
+ return RazorHarpoonGUIDs[0];
+ case GO_RAZOR_HARPOON_2:
+ return RazorHarpoonGUIDs[1];
+ case GO_RAZOR_HARPOON_3:
+ return RazorHarpoonGUIDs[2];
+ case GO_RAZOR_HARPOON_4:
+ return RazorHarpoonGUIDs[3];
+
+ // XT-002 Deconstructor
case BOSS_XT002:
return XT002GUID;
case DATA_TOY_PILE_0:
@@ -699,6 +848,15 @@ class instance_ulduar : public InstanceMapScript
case DATA_TOY_PILE_2:
case DATA_TOY_PILE_3:
return XTToyPileGUIDs[data - DATA_TOY_PILE_0];
+
+ // Assembly of Iron
+ case DATA_STEELBREAKER:
+ return AssemblyGUIDs[0];
+ case DATA_MOLGEIM:
+ return AssemblyGUIDs[1];
+ case DATA_BRUNDIR:
+ return AssemblyGUIDs[2];
+
case BOSS_KOLOGARN:
return KologarnGUID;
case BOSS_AURIAYA:
@@ -709,42 +867,47 @@ class instance_ulduar : public InstanceMapScript
return HodirGUID;
case BOSS_THORIM:
return ThorimGUID;
+
+ // Freya
case BOSS_FREYA:
return FreyaGUID;
+ case BOSS_BRIGHTLEAF:
+ return ElderGUIDs[0];
+ case BOSS_IRONBRANCH:
+ return ElderGUIDs[1];
+ case BOSS_STONEBARK:
+ return ElderGUIDs[2];
+
case BOSS_VEZAX:
return VezaxGUID;
- case BOSS_YOGGSARON:
- return YoggSaronGUID;
- case BOSS_ALGALON:
- return AlgalonGUID;
- // Razorscale expedition commander
- case DATA_EXPEDITION_COMMANDER:
- return ExpeditionCommanderGUID;
- case GO_RAZOR_HARPOON_1:
- return RazorHarpoonGUIDs[0];
- case GO_RAZOR_HARPOON_2:
- return RazorHarpoonGUIDs[1];
- case GO_RAZOR_HARPOON_3:
- return RazorHarpoonGUIDs[2];
- case GO_RAZOR_HARPOON_4:
- return RazorHarpoonGUIDs[3];
-
- // Assembly of Iron
- case DATA_STEELBREAKER:
- return AssemblyGUIDs[0];
- case DATA_MOLGEIM:
- return AssemblyGUIDs[1];
- case DATA_BRUNDIR:
- return AssemblyGUIDs[2];
-
- // Freya's Keepers
- case BOSS_BRIGHTLEAF:
+ // Yogg-Saron
+ case BOSS_YOGG_SARON:
+ return YoggSaronGUID;
+ case DATA_VOICE_OF_YOGG_SARON:
+ return VoiceOfYoggSaronGUID;
+ case DATA_BRAIN_OF_YOGG_SARON:
+ return BrainOfYoggSaronGUID;
+ case DATA_SARA:
+ return SaraGUID;
+ case GO_BRAIN_ROOM_DOOR_1:
+ return BrainRoomDoorGUIDs[0];
+ case GO_BRAIN_ROOM_DOOR_2:
+ return BrainRoomDoorGUIDs[1];
+ case GO_BRAIN_ROOM_DOOR_3:
+ return BrainRoomDoorGUIDs[2];
+ case DATA_FREYA_YS:
return KeeperGUIDs[0];
- case BOSS_IRONBRANCH:
+ case DATA_HODIR_YS:
return KeeperGUIDs[1];
- case BOSS_STONEBARK:
+ case DATA_THORIM_YS:
return KeeperGUIDs[2];
+ case DATA_MIMIRON_YS:
+ return KeeperGUIDs[3];
+
+ // Algalon
+ case BOSS_ALGALON:
+ return AlgalonGUID;
case DATA_SIGILDOOR_01:
return AlgalonSigilDoorGUID[0];
case DATA_SIGILDOOR_02:
@@ -776,6 +939,10 @@ class instance_ulduar : public InstanceMapScript
return HodirRareCacheData;
case DATA_UNBROKEN:
return uint32(Unbroken);
+ case DATA_ILLUSION:
+ return illusion;
+ case DATA_KEEPERS_COUNT:
+ return keepersCount;
default:
break;
}
@@ -789,6 +956,30 @@ class instance_ulduar : public InstanceMapScript
{
case CRITERIA_HERALD_OF_TITANS:
return _maxArmorItemLevel <= MAX_HERALD_ARMOR_ITEMLEVEL && _maxWeaponItemLevel <= MAX_HERALD_WEAPON_ITEMLEVEL;
+ case CRITERIA_WAITS_DREAMING_STORMWIND_25:
+ case CRITERIA_WAITS_DREAMING_STORMWIND_10:
+ return illusion == STORMWIND_ILLUSION;
+ case CRITERIA_WAITS_DREAMING_CHAMBER_25:
+ case CRITERIA_WAITS_DREAMING_CHAMBER_10:
+ return illusion == CHAMBER_ILLUSION;
+ case CRITERIA_WAITS_DREAMING_ICECROWN_25:
+ case CRITERIA_WAITS_DREAMING_ICECROWN_10:
+ return illusion == ICECROWN_ILLUSION;
+ case CRITERIA_DRIVE_ME_CRAZY_10:
+ case CRITERIA_DRIVE_ME_CRAZY_25:
+ return IsDriveMeCrazyEligible;
+ case CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_10:
+ case CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_25:
+ return keepersCount <= 3;
+ case CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_10:
+ case CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_25:
+ return keepersCount <= 2;
+ case CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_10:
+ case CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_25:
+ return keepersCount <= 1;
+ case CRITERIA_ALONE_IN_THE_DARKNESS_10:
+ case CRITERIA_ALONE_IN_THE_DARKNESS_25:
+ return keepersCount == 0;
}
return false;
@@ -801,6 +992,9 @@ class instance_ulduar : public InstanceMapScript
std::ostringstream saveStream;
saveStream << "U U " << GetBossSaveData() << GetData(DATA_COLOSSUS) << ' ' << _algalonTimer << ' ' << (_algalonSummoned ? 1 : 0);
+ for (uint8 i = 0; i < 4; ++i)
+ saveStream << ' ' << (KeeperGUIDs[i] ? 1 : 0);
+
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
@@ -851,6 +1045,21 @@ class instance_ulduar : public InstanceMapScript
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, _algalonTimer);
}
}
+
+ for (uint8 i = 0; i < 4; ++i)
+ {
+ loadStream >> tempState;
+ _summonYSKeeper[i] = tempState != 0;
+ }
+
+ if (GetBossState(BOSS_FREYA) == DONE && !_summonYSKeeper[0])
+ _summonObservationRingKeeper[0] = true;
+ if (GetBossState(BOSS_HODIR) == DONE && !_summonYSKeeper[1])
+ _summonObservationRingKeeper[1] = true;
+ if (GetBossState(BOSS_THORIM) == DONE && !_summonYSKeeper[2])
+ _summonObservationRingKeeper[2] = true;
+ if (GetBossState(BOSS_MIMIRON) == DONE && !_summonYSKeeper[3])
+ _summonObservationRingKeeper[3] = true;
}
OUT_LOAD_INST_DATA_COMPLETE;
@@ -889,6 +1098,8 @@ class instance_ulduar : public InstanceMapScript
uint32 _algalonTimer;
bool _summonAlgalon;
bool _algalonSummoned;
+ bool _summonObservationRingKeeper[4];
+ bool _summonYSKeeper[4];
uint32 _maxArmorItemLevel;
uint32 _maxWeaponItemLevel;
};
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index 08fd95d0e26..86c0c4888ed 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -21,6 +21,8 @@
#include "ObjectMgr.h"
#define UlduarScriptName "instance_ulduar"
+extern Position const ObservationRingKeepersPos[4];
+extern Position const YSKeepersPos[4];
extern Position const AlgalonLandPos;
enum UlduarBosses
@@ -42,7 +44,7 @@ enum UlduarBosses
BOSS_IRONBRANCH = 12,
BOSS_STONEBARK = 13,
BOSS_VEZAX = 14,
- BOSS_YOGGSARON = 15,
+ BOSS_YOGG_SARON = 15,
BOSS_ALGALON = 16,
};
@@ -74,7 +76,7 @@ enum UlduarNPCs
NPC_THORIM = 32865,
NPC_FREYA = 32906,
NPC_VEZAX = 33271,
- NPC_YOGGSARON = 33288,
+ NPC_YOGG_SARON = 33288,
NPC_ALGALON = 32871,
// Mimiron
@@ -115,6 +117,39 @@ enum UlduarNPCs
NPC_NATURES_BLADE = 33527,
NPC_GUARDIAN_OF_LIFE = 33528,
+ // Yogg-Saron
+ NPC_SARA = 33134,
+ NPC_GUARDIAN_OF_YOGG_SARON = 33136,
+ NPC_HODIR_OBSERVATION_RING = 33213,
+ NPC_FREYA_OBSERVATION_RING = 33241,
+ NPC_THORIM_OBSERVATION_RING = 33242,
+ NPC_MIMIRON_OBSERVATION_RING = 33244,
+ NPC_VOICE_OF_YOGG_SARON = 33280,
+ NPC_OMINOUS_CLOUD = 33292,
+ NPC_FREYA_YS = 33410,
+ NPC_HODIR_YS = 33411,
+ NPC_MIMIRON_YS = 33412,
+ NPC_THORIM_YS = 33413,
+ NPC_SUIT_OF_ARMOR = 33433,
+ NPC_KING_LLANE = 33437,
+ NPC_THE_LICH_KING = 33441,
+ NPC_IMMOLATED_CHAMPION = 33442,
+ NPC_YSERA = 33495,
+ NPC_NELTHARION = 33523,
+ NPC_MALYGOS = 33535,
+ NPC_DEATH_RAY = 33881,
+ NPC_DEATH_ORB = 33882,
+ NPC_BRAIN_OF_YOGG_SARON = 33890,
+ NPC_INFLUENCE_TENTACLE = 33943,
+ NPC_TURNED_CHAMPION = 33962,
+ NPC_CRUSHER_TENTACLE = 33966,
+ NPC_CONSTRICTOR_TENTACLE = 33983,
+ NPC_CORRUPTOR_TENTACLE = 33985,
+ NPC_IMMORTAL_GUARDIAN = 33988,
+ NPC_SANITY_WELL = 33991,
+ NPC_DESCEND_INTO_MADNESS = 34072,
+ NPC_MARKED_IMMORTAL_GUARDIAN = 36064,
+
// Algalon the Observer
NPC_BRANN_BRONZBEARD_ALG = 34064,
NPC_AZEROTH = 34246,
@@ -155,6 +190,12 @@ enum UlduarGameObjects
GO_HODIR_ICE_DOOR = 194441,
GO_ARCHIVUM_DOOR = 194556,
+ // Yogg-Saron
+ GO_YOGG_SARON_DOOR = 194773,
+ GO_BRAIN_ROOM_DOOR_1 = 194635,
+ GO_BRAIN_ROOM_DOOR_2 = 194636,
+ GO_BRAIN_ROOM_DOOR_3 = 194637,
+
// Algalon the Observer
GO_CELESTIAL_PLANETARIUM_ACCESS_10 = 194628,
GO_CELESTIAL_PLANETARIUM_ACCESS_25 = 194752,
@@ -169,12 +210,18 @@ enum UlduarGameObjects
GO_GIFT_OF_THE_OBSERVER_25 = 194822,
};
-enum LeviathanData
+enum EventIds
{
EVENT_TOWER_OF_STORM_DESTROYED = 21031,
EVENT_TOWER_OF_FROST_DESTROYED = 21032,
EVENT_TOWER_OF_FLAMES_DESTROYED = 21033,
EVENT_TOWER_OF_LIFE_DESTROYED = 21030,
+ EVENT_ACTIVATE_SANITY_WELL = 21432,
+ EVENT_HODIRS_PROTECTIVE_GAZE_PROC = 21437,
+};
+
+enum LeviathanActions
+{
ACTION_TOWER_OF_STORM_DESTROYED = 1,
ACTION_TOWER_OF_FROST_DESTROYED = 2,
ACTION_TOWER_OF_FLAMES_DESTROYED = 3,
@@ -184,14 +231,30 @@ enum LeviathanData
enum UlduarAchievementCriteriaIds
{
- CRITERIA_CON_SPEED_ATORY = 21597,
- CRITERIA_DISARMED = 21687,
- CRITERIA_HERALD_OF_TITANS = 10678,
+ CRITERIA_CON_SPEED_ATORY = 21597,
+ CRITERIA_DISARMED = 21687,
+ CRITERIA_WAITS_DREAMING_STORMWIND_25 = 10321,
+ CRITERIA_WAITS_DREAMING_CHAMBER_25 = 10322,
+ CRITERIA_WAITS_DREAMING_ICECROWN_25 = 10323,
+ CRITERIA_WAITS_DREAMING_STORMWIND_10 = 10324,
+ CRITERIA_WAITS_DREAMING_CHAMBER_10 = 10325,
+ CRITERIA_WAITS_DREAMING_ICECROWN_10 = 10326,
+ CRITERIA_DRIVE_ME_CRAZY_10 = 10185,
+ CRITERIA_DRIVE_ME_CRAZY_25 = 10296,
+ CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_10 = 10410,
+ CRITERIA_THREE_LIGHTS_IN_THE_DARKNESS_25 = 10414,
+ CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_10 = 10388,
+ CRITERIA_TWO_LIGHTS_IN_THE_DARKNESS_25 = 10415,
+ CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_10 = 10409,
+ CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_25 = 10416,
+ CRITERIA_ALONE_IN_THE_DARKNESS_10 = 10412,
+ CRITERIA_ALONE_IN_THE_DARKNESS_25 = 10417,
+ CRITERIA_HERALD_OF_TITANS = 10678,
};
enum UlduarData
{
- // Collosus (Leviathan)
+ // Colossus (Leviathan)
DATA_COLOSSUS = 20,
// Razorscale
@@ -212,6 +275,18 @@ enum UlduarData
// Hodir
DATA_HODIR_RARE_CACHE,
+ // Yogg-Saron
+ DATA_VOICE_OF_YOGG_SARON,
+ DATA_SARA,
+ DATA_BRAIN_OF_YOGG_SARON,
+ DATA_FREYA_YS,
+ DATA_HODIR_YS,
+ DATA_THORIM_YS,
+ DATA_MIMIRON_YS,
+ DATA_ILLUSION,
+ DATA_DRIVE_ME_CRAZY,
+ DATA_KEEPERS_COUNT,
+
// Algalon the Observer
DATA_ALGALON_SUMMON_STATE,
DATA_SIGILDOOR_01,
@@ -245,6 +320,13 @@ enum UlduarEvents
ACTION_INIT_ALGALON = 6,
};
+enum YoggSaronIllusions
+{
+ CHAMBER_ILLUSION = 0,
+ ICECROWN_ILLUSION = 1,
+ STORMWIND_ILLUSION = 2,
+};
+
template<class AI>
CreatureAI* GetUlduarAI(Creature* creature)
{