aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp1
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp3
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp6
-rw-r--r--src/server/game/Entities/Player/Player.cpp6
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp15
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp4
-rw-r--r--src/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp1
-rw-r--r--src/server/game/Maps/Map.cpp50
-rw-r--r--src/server/game/Quests/QuestDef.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp12
-rw-r--r--src/server/game/Spells/SpellMgr.cpp12
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp162
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp164
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp3331
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h275
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp1168
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp2
18 files changed, 2938 insertions, 2278 deletions
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 8bf34527769..9631b75fe06 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -28,7 +28,6 @@
void UnitAI::AttackStart(Unit* victim)
{
-
if (victim && me->Attack(victim, true))
me->GetMotionMaster()->MoveChase(victim);
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index ea9d6c2b9fd..48870a12a25 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -478,10 +478,7 @@ void BossAI::_JustDied()
events.Reset();
summons.DespawnAll();
if (instance)
- {
instance->SetBossState(_bossId, DONE);
- instance->SaveToDB();
- }
}
void BossAI::_EnterCombat()
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 5f91755d527..acfc8da9bc8 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -527,7 +527,7 @@ void GameObject::Update(uint32 diff)
{
case GAMEOBJECT_TYPE_DOOR:
case GAMEOBJECT_TYPE_BUTTON:
- if (GetGOInfo()->GetAutoCloseTime() && (m_cooldownTime < time(NULL)))
+ if (m_cooldownTime && (m_cooldownTime < time(NULL)))
ResetDoorOrButton();
break;
case GAMEOBJECT_TYPE_GOOBER:
@@ -569,10 +569,12 @@ void GameObject::Update(uint32 diff)
CastSpell(target, goInfo->trap.spellId);
// Template value or 4 seconds
- m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4));
+ m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4));
if (goInfo->trap.type == 1)
SetLootState(GO_JUST_DEACTIVATED);
+ else if (!goInfo->trap.type)
+ SetLootState(GO_READY);
// Battleground gameobjects have data2 == 0 && data5 == 3
if (!goInfo->trap.diameter && goInfo->trap.cooldown == 3)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 7a7f931e68f..2a8217d2028 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -371,6 +371,12 @@ void TradeData::SetMoney(uint64 money)
if (m_money == money)
return;
+ if (!m_player->HasEnoughMoney(money))
+ {
+ m_player->GetSession()->SendTradeStatus(TRADE_STATUS_BUSY);
+ return;
+ }
+
m_money = money;
SetAccepted(false);
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index d7af98b47d1..5f0ae6ecdea 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -85,8 +85,8 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa
_triggeredDepartureEvent = false;
m_goValue.Transport.PathProgress = 0;
- SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
- SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
+ SetObjectScale(goinfo->size);
+ SetFaction(goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetPeriod(tInfo->pathTime);
SetEntry(goinfo->entry);
@@ -209,8 +209,14 @@ void Transport::Update(uint32 diff)
3. transport moves from active to inactive grid
4. the grid that transport is currently in unloads
*/
- if (_staticPassengers.empty() && GetMap()->IsGridLoaded(GetPositionX(), GetPositionY())) // 2.
+ bool gridActive = GetMap()->IsGridLoaded(GetPositionX(), GetPositionY());
+
+ if (_staticPassengers.empty() && gridActive) // 2.
LoadStaticPassengers();
+ else if (!_staticPassengers.empty() && !gridActive)
+ // 4. - if transports stopped on grid edge, some passengers can remain in active grids
+ // unload all static passengers otherwise passengers won't load correctly when the grid that transport is currently in becomes active
+ UnloadStaticPassengers();
}
}
@@ -447,6 +453,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
void Transport::UpdatePosition(float x, float y, float z, float o)
{
bool newActive = GetMap()->IsGridLoaded(x, y);
+ Cell oldCell(GetPositionX(), GetPositionY());
Relocate(x, y, z, o);
UpdateModelPosition();
@@ -461,7 +468,7 @@ void Transport::UpdatePosition(float x, float y, float z, float o)
*/
if (_staticPassengers.empty() && newActive) // 1.
LoadStaticPassengers();
- else if (!_staticPassengers.empty() && !newActive && Cell(x, y).DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3.
+ else if (!_staticPassengers.empty() && !newActive && oldCell.DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3.
UnloadStaticPassengers();
else
UpdatePassengerPositions(_staticPassengers);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index adf321b1ef3..454d79a0ee1 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3657,8 +3657,8 @@ void ObjectMgr::LoadQuests()
"QuestGiverTextWindow, QuestGiverTargetName, QuestTurnTextWindow, QuestTurnTargetName, SoundAccept, SoundTurnIn, "
// 150 151 152 153 154 155 156 157 158 159
"DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, "
- // 160 161 162 163 164 165 166 167 168
- "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, WDBVerified"
+ // 160 161 162 163 164 165 166 167
+ "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4"
" FROM quest_template");
if (!result)
{
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index e9e48e9e0dd..9008e7415da 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -433,7 +433,7 @@ struct BroadcastText
uint32 SoundId;
uint32 Unk1;
uint32 Unk2;
- // uint32 WDBVerified;
+ // uint32 VerifiedBuild;
std::string const& GetText(LocaleConstant locale = DEFAULT_LOCALE, uint8 gender = GENDER_MALE, bool forceGender = false) const
{
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 298ae29bfcd..fc6062773a1 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -785,7 +785,6 @@ void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
if (!my_trade)
return;
- // gold can be incorrect, but this is checked at trade finished.
my_trade->SetMoney(gold);
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index cac40ff4961..22c0b332f33 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1544,11 +1544,8 @@ void Map::UnloadAll()
Transport* transport = *itr;
++itr;
- transport->RemoveFromWorld();
- delete transport;
+ RemoveFromMap<Transport>(transport, true);
}
-
- _transports.clear();
}
// *****************************
@@ -2648,27 +2645,30 @@ void Map::RemoveAllObjectsInRemoveList()
RemoveFromMap(corpse, true);
break;
}
- case TYPEID_DYNAMICOBJECT:
- RemoveFromMap((DynamicObject*)obj, true);
- break;
- case TYPEID_AREATRIGGER:
- RemoveFromMap((AreaTrigger*)obj, true);
- break;
- case TYPEID_GAMEOBJECT:
- if (Transport* transport = obj->ToGameObject()->ToTransport())
- RemoveFromMap(transport, true);
- else
- RemoveFromMap(obj->ToGameObject(), true);
- break;
- case TYPEID_UNIT:
- // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
- // make sure that like sources auras/etc removed before destructor start
- obj->ToCreature()->CleanupsBeforeDelete();
- RemoveFromMap(obj->ToCreature(), true);
- break;
- default:
- TC_LOG_ERROR("maps", "Non-grid object (TypeId: %u) is in grid object remove list, ignored.", obj->GetTypeId());
- break;
+ case TYPEID_DYNAMICOBJECT:
+ RemoveFromMap(obj->ToDynObject(), true);
+ break;
+ case TYPEID_AREATRIGGER:
+ RemoveFromMap((AreaTrigger*)obj, true);
+ break;
+ case TYPEID_GAMEOBJECT:
+ {
+ GameObject* go = obj->ToGameObject();
+ if (Transport* transport = go->ToTransport())
+ RemoveFromMap(transport, true);
+ else
+ RemoveFromMap(go, true);
+ break;
+ }
+ case TYPEID_UNIT:
+ // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
+ // make sure that like sources auras/etc removed before destructor start
+ obj->ToCreature()->CleanupsBeforeDelete();
+ RemoveFromMap(obj->ToCreature(), true);
+ break;
+ default:
+ TC_LOG_ERROR("maps", "Non-grid object (TypeId: %u) is in grid object remove list, ignored.", obj->GetTypeId());
+ break;
}
i_objectsToRemove.erase(itr);
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 0f54e0af6c1..9a17175b1a8 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -162,7 +162,7 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
OfferRewardEmoteDelay[i] = questRecord[164+i].GetInt32();
- // int32 WDBVerified = questRecord[168].GetInt32();
+ //int32 VerifiedBuild = questRecord[168].GetInt32();
if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
Flags |= QUEST_FLAGS_AUTO_ACCEPT;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 44b2be40fec..05b4ebfc258 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1305,17 +1305,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (target->HasAura(61988) && !target->HasAura(25771))
target->RemoveAura(61988);
break;
- case 72368: // Shared Suffering
- case 72369:
- if (caster)
- {
- if (AuraEffect* aurEff = GetEffect(0))
- {
- int32 remainingDamage = aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber());
- if (remainingDamage > 0)
- caster->CastCustomSpell(caster, 72373, NULL, &remainingDamage, NULL, true);
- }
- }
+ default:
break;
}
break;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 23228accd21..33a2bd2d41a 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3385,6 +3385,18 @@ void SpellMgr::LoadSpellInfoCorrections()
break;
// ENDOF TRIAL OF THE CRUSADER SPELLS
//
+ // HALLS OF REFLECTION SPELLS
+ //
+ case 72435: // Defiling Horror
+ case 72452: // Defiling Horror
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd
+ spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd
+ break;
+ case 72900: // Start Halls of Reflection Quest AE
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
+ break;
+ // ENDOF HALLS OF REFLECTION SPELLS
+ //
// ICECROWN CITADEL SPELLS
//
// THESE SPELLS ARE WORKING CORRECTLY EVEN WITHOUT THIS HACK
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp
index 9cf61058bd9..a5577b6a0ea 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp
@@ -25,7 +25,7 @@ enum Texts
SAY_SLAY = 1,
SAY_DEATH = 2,
SAY_IMPENDING_DESPAIR = 3,
- SAY_DEFILING_HORROR = 4,
+ SAY_DEFILING_HORROR = 4
};
enum Spells
@@ -33,8 +33,9 @@ enum Spells
SPELL_QUIVERING_STRIKE = 72422,
SPELL_IMPENDING_DESPAIR = 72426,
SPELL_DEFILING_HORROR = 72435,
- SPELL_HOPELESSNESS = 72395,
- H_SPELL_HOPELESSNESS = 72390, /// @todo not in dbc. Add in DB.
+ SPELL_HOPELESSNESS_1 = 72395,
+ SPELL_HOPELESSNESS_2 = 72396,
+ SPELL_HOPELESSNESS_3 = 72397
};
enum Events
@@ -42,99 +43,106 @@ enum Events
EVENT_NONE,
EVENT_QUIVERING_STRIKE,
EVENT_IMPENDING_DESPAIR,
- EVENT_DEFILING_HORROR,
+ EVENT_DEFILING_HORROR
};
+uint32 const HopelessnessHelper[3] = { SPELL_HOPELESSNESS_1, SPELL_HOPELESSNESS_2, SPELL_HOPELESSNESS_3 };
+
class boss_falric : public CreatureScript
{
-public:
- boss_falric() : CreatureScript("boss_falric") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_falricAI>(creature);
- }
-
- struct boss_falricAI : public boss_horAI
- {
- boss_falricAI(Creature* creature) : boss_horAI(creature) { }
-
- uint8 uiHopelessnessCount;
-
- void Reset() override
- {
- boss_horAI::Reset();
-
- uiHopelessnessCount = 0;
+ public:
+ boss_falric() : CreatureScript("boss_falric") { }
- instance->SetBossState(DATA_FALRIC_EVENT, NOT_STARTED);
- }
-
- void EnterCombat(Unit* /*who*/) override
+ struct boss_falricAI : public boss_horAI
{
- Talk(SAY_AGGRO);
- instance->SetBossState(DATA_FALRIC_EVENT, IN_PROGRESS);
-
- events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000);
- events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000);
- events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000, 45000)); /// @todo adjust timer.
- }
+ boss_falricAI(Creature* creature) : boss_horAI(creature, DATA_FALRIC) { }
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
-
- instance->SetBossState(DATA_FALRIC_EVENT, DONE);
- }
+ void Reset() override
+ {
+ boss_horAI::Reset();
+ _hopelessnessCount = 0;
+ }
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ DoZoneInCombat();
+ instance->SetBossState(DATA_FALRIC, IN_PROGRESS);
- void UpdateAI(uint32 diff) override
- {
- // Return since we have no target
- if (!UpdateVictim())
- return;
+ events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000);
+ events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000);
+ events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(21000, 39000));
+ }
- events.Update(diff);
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if ((_hopelessnessCount < 1 && me->HealthBelowPctDamaged(66, damage))
+ || (_hopelessnessCount < 2 && me->HealthBelowPctDamaged(33, damage))
+ || (_hopelessnessCount < 3 && me->HealthBelowPctDamaged(10, damage)))
+ {
+ if (_hopelessnessCount)
+ me->RemoveOwnedAura(sSpellMgr->GetSpellIdForDifficulty(HopelessnessHelper[_hopelessnessCount - 1], me));
+ DoCast(me, HopelessnessHelper[_hopelessnessCount]);
+ ++_hopelessnessCount;
+ }
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ events.Reset();
+ instance->SetBossState(DATA_FALRIC, DONE);
+ }
- switch (events.ExecuteEvent())
+ void KilledUnit(Unit* who) override
{
- case EVENT_QUIVERING_STRIKE:
- DoCast(SPELL_QUIVERING_STRIKE);
- events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000);
- break;
- case EVENT_IMPENDING_DESPAIR:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- {
- Talk(SAY_IMPENDING_DESPAIR);
- DoCast(target, SPELL_IMPENDING_DESPAIR);
- }
- events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000);
- break;
- case EVENT_DEFILING_HORROR:
- DoCast(SPELL_DEFILING_HORROR);
- events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000, 45000)); /// @todo adjust timer.
- break;
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
}
- if ((uiHopelessnessCount < 1 && HealthBelowPct(66))
- || (uiHopelessnessCount < 2 && HealthBelowPct(33))
- || (uiHopelessnessCount < 3 && HealthBelowPct(10)))
+ void UpdateAI(uint32 diff) override
{
- uiHopelessnessCount++;
- DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS, H_SPELL_HOPELESSNESS));
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (events.ExecuteEvent())
+ {
+ case EVENT_QUIVERING_STRIKE:
+ DoCastVictim(SPELL_QUIVERING_STRIKE);
+ events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000);
+ break;
+ case EVENT_IMPENDING_DESPAIR:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
+ {
+ Talk(SAY_IMPENDING_DESPAIR);
+ DoCast(target, SPELL_IMPENDING_DESPAIR);
+ }
+ events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000);
+ break;
+ case EVENT_DEFILING_HORROR:
+ DoCastAOE(SPELL_DEFILING_HORROR);
+ events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(21000, 39000));
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
- }
- };
+ private:
+ uint8 _hopelessnessCount;
+ };
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<boss_falricAI>(creature);
+ }
};
void AddSC_boss_falric()
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp
index cf267ff1079..902a917c594 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp
@@ -17,6 +17,8 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
#include "halls_of_reflection.h"
enum Texts
@@ -33,6 +35,7 @@ enum Spells
SPELL_WELL_OF_CORRUPTION = 72362,
SPELL_CORRUPTED_FLESH = 72363,
SPELL_SHARED_SUFFERING = 72368,
+ SPELL_SHARED_SUFFERING_DISPEL = 72373
};
enum Events
@@ -41,93 +44,130 @@ enum Events
EVENT_OBLITERATE,
EVENT_WELL_OF_CORRUPTION,
EVENT_CORRUPTED_FLESH,
- EVENT_SHARED_SUFFERING,
+ EVENT_SHARED_SUFFERING
};
class boss_marwyn : public CreatureScript
{
-public:
- boss_marwyn() : CreatureScript("boss_marwyn") { }
+ public:
+ boss_marwyn() : CreatureScript("boss_marwyn") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_marwynAI>(creature);
- }
-
- struct boss_marwynAI : public boss_horAI
- {
- boss_marwynAI(Creature* creature) : boss_horAI(creature) { }
-
- void Reset() override
+ struct boss_marwynAI : public boss_horAI
{
- boss_horAI::Reset();
+ boss_marwynAI(Creature* creature) : boss_horAI(creature, DATA_MARWYN) { }
- instance->SetBossState(DATA_MARWYN_EVENT, NOT_STARTED);
- }
+ void Reset() override
+ {
+ boss_horAI::Reset();
+ }
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
- instance->SetBossState(DATA_MARWYN_EVENT, IN_PROGRESS);
+ void EnterCombat(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+ DoZoneInCombat();
+ instance->SetBossState(DATA_MARWYN, IN_PROGRESS);
+
+ events.ScheduleEvent(EVENT_OBLITERATE, urand(8000, 13000));
+ events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
+ events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000);
+ events.ScheduleEvent(EVENT_SHARED_SUFFERING, urand(14000, 15000));
+ }
- events.ScheduleEvent(EVENT_OBLITERATE, 30000); /// @todo Check timer
- events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
- events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000);
- events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); /// @todo Check timer
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ events.Reset();
+ instance->SetBossState(DATA_MARWYN, DONE);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- instance->SetBossState(DATA_MARWYN_EVENT, DONE);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (events.ExecuteEvent())
+ {
+ case EVENT_OBLITERATE:
+ DoCastVictim(SPELL_OBLITERATE);
+ events.ScheduleEvent(EVENT_OBLITERATE, urand(8000, 13000));
+ break;
+ case EVENT_WELL_OF_CORRUPTION:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_WELL_OF_CORRUPTION);
+ events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
+ break;
+ case EVENT_CORRUPTED_FLESH:
+ Talk(SAY_CORRUPTED_FLESH);
+ DoCastAOE(SPELL_CORRUPTED_FLESH);
+ events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000);
+ break;
+ case EVENT_SHARED_SUFFERING:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_SHARED_SUFFERING);
+ events.ScheduleEvent(EVENT_SHARED_SUFFERING, urand(14000, 15000));
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
- void KilledUnit(Unit* /*victim*/) override
+ CreatureAI* GetAI(Creature* creature) const override
{
- Talk(SAY_SLAY);
+ return GetHallsOfReflectionAI<boss_marwynAI>(creature);
}
+};
- void UpdateAI(uint32 diff) override
- {
- // Return since we have no target
- if (!UpdateVictim())
- return;
+// 72368, 72369 - Shared Suffering
+class spell_marwyn_shared_suffering : public SpellScriptLoader
+{
+ public:
+ spell_marwyn_shared_suffering() : SpellScriptLoader("spell_marwyn_shared_suffering") { }
- events.Update(diff);
+ class spell_marwyn_shared_suffering_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_marwyn_shared_suffering_AuraScript);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ void HandleEffectRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
+ return;
+
+ if (Unit* caster = GetCaster())
+ {
+ int32 remainingDamage = aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber());
+ if (remainingDamage > 0)
+ caster->CastCustomSpell(SPELL_SHARED_SUFFERING_DISPEL, SPELLVALUE_BASE_POINT1, remainingDamage, GetTarget(), TRIGGERED_FULL_MASK);
+ }
+ }
- switch (events.ExecuteEvent())
+ void Register() override
{
- case EVENT_OBLITERATE:
- DoCast(SPELL_OBLITERATE);
- events.ScheduleEvent(EVENT_OBLITERATE, 30000);
- break;
- case EVENT_WELL_OF_CORRUPTION:
- DoCast(SPELL_WELL_OF_CORRUPTION);
- events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000);
- break;
- case EVENT_CORRUPTED_FLESH:
- Talk(SAY_CORRUPTED_FLESH);
- DoCast(SPELL_CORRUPTED_FLESH);
- events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000);
- break;
- case EVENT_SHARED_SUFFERING:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_SHARED_SUFFERING);
- events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000);
- break;
+ AfterEffectRemove += AuraEffectRemoveFn(spell_marwyn_shared_suffering_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
}
+ };
- DoMeleeAttackIfReady();
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_marwyn_shared_suffering_AuraScript();
}
- };
-
};
void AddSC_boss_marwyn()
{
new boss_marwyn();
+ new spell_marwyn_shared_suffering();
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index ca2a181a48a..7366ba32bdf 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -18,6 +18,8 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
+#include "SpellScript.h"
+#include "Transport.h"
#include "Player.h"
#include "halls_of_reflection.h"
@@ -36,17 +38,6 @@ enum Text
SAY_JAINA_INTRO_11 = 10,
SAY_JAINA_INTRO_END = 11,
- SAY_JAINA_ESCAPE_1 = 0,
- SAY_JAINA_ESCAPE_2 = 1,
- SAY_JAINA_ESCAPE_3 = 2,
- SAY_JAINA_ESCAPE_4 = 3,
- SAY_JAINA_ESCAPE_5 = 4,
- SAY_JAINA_ESCAPE_6 = 5,
- SAY_JAINA_ESCAPE_7 = 6,
- SAY_JAINA_ESCAPE_8 = 7,
- SAY_JAINA_ESCAPE_9 = 8,
- SAY_JAINA_ESCAPE_10 = 9,
-
SAY_SYLVANAS_INTRO_1 = 0,
SAY_SYLVANAS_INTRO_2 = 1,
SAY_SYLVANAS_INTRO_3 = 2,
@@ -57,16 +48,6 @@ enum Text
SAY_SYLVANAS_INTRO_8 = 7,
SAY_SYLVANAS_INTRO_END = 8,
- SAY_SYLVANAS_ESCAPE_1 = 0,
- SAY_SYLVANAS_ESCAPE_2 = 1,
- SAY_SYLVANAS_ESCAPE_3 = 2,
- SAY_SYLVANAS_ESCAPE_4 = 3,
- SAY_SYLVANAS_ESCAPE_5 = 4,
- SAY_SYLVANAS_ESCAPE_6 = 5,
- SAY_SYLVANAS_ESCAPE_7 = 6,
- SAY_SYLVANAS_ESCAPE_8 = 7,
- SAY_SYLVANAS_ESCAPE_9 = 8,
-
SAY_UTHER_INTRO_A2_1 = 0,
SAY_UTHER_INTRO_A2_2 = 1,
SAY_UTHER_INTRO_A2_3 = 2,
@@ -90,27 +71,40 @@ enum Text
SAY_LK_JAINA_INTRO_END = 3,
SAY_LK_SYLVANAS_INTRO_END = 4,
+ SAY_JAINA_SYLVANAS_ESCAPE_1 = 0,
+ SAY_JAINA_SYLVANAS_ESCAPE_2 = 1,
+ SAY_JAINA_SYLVANAS_ESCAPE_3 = 2,
+ SAY_JAINA_SYLVANAS_ESCAPE_4 = 3,
+ SAY_JAINA_SYLVANAS_ESCAPE_5 = 4,
+ SAY_JAINA_SYLVANAS_ESCAPE_6 = 5,
+ SAY_JAINA_SYLVANAS_ESCAPE_7 = 6, // unused
+ SAY_JAINA_SYLVANAS_ESCAPE_8 = 7,
+
+ SAY_JAINA_ESCAPE_9 = 8,
+ SAY_JAINA_ESCAPE_10 = 9,
+
+ SAY_SYLVANAS_ESCAPE_9 = 8,
+
SAY_LK_ESCAPE_1 = 0,
SAY_LK_ESCAPE_2 = 1,
- SAY_LK_ESCAPE_3 = 2,
- SAY_LK_ESCAPE_4 = 3,
- SAY_LK_ESCAPE_5 = 4,
- SAY_LK_ESCAPE_6 = 5,
- SAY_LK_ESCAPE_7 = 6,
- SAY_LK_ESCAPE_8 = 7,
- SAY_LK_ESCAPE_9 = 8,
- SAY_LK_ESCAPE_10 = 9,
- SAY_LK_ESCAPE_11 = 10,
+ SAY_LK_ESCAPE_ICEWALL_SUMMONED_1 = 2,
+ SAY_LK_ESCAPE_ICEWALL_SUMMONED_2 = 3,
+ SAY_LK_ESCAPE_ICEWALL_SUMMONED_3 = 4,
+ SAY_LK_ESCAPE_ICEWALL_SUMMONED_4 = 5,
+ SAY_LK_ESCAPE_GHOULS = 6,
+ SAY_LK_ESCAPE_ABOMINATION = 7,
+ SAY_LK_ESCAPE_WINTER = 8,
+ SAY_LK_ESCAPE_HARVEST_SOUL = 9,
SAY_FALRIC_INTRO_1 = 5,
SAY_FALRIC_INTRO_2 = 6,
- SAY_MARWYN_INTRO_1 = 4,
+ SAY_MARWYN_INTRO_1 = 4
};
enum Events
{
- EVENT_WALK_INTRO1 = 1,
+ EVENT_WALK_INTRO1 = 1,
EVENT_WALK_INTRO2,
EVENT_START_INTRO,
EVENT_SKIP_INTRO,
@@ -181,21 +175,17 @@ enum Events
EVENT_ESCAPE_13,
EVENT_ESCAPE_14,
EVENT_ESCAPE_15,
- //EVENT_ESCAPE_16,
+ EVENT_ESCAPE_16,
EVENT_ESCAPE_17,
- EVENT_ESCAPE_18,
- EVENT_ESCAPE_19,
- EVENT_ESCAPE_20,
- EVENT_ESCAPE_21,
- EVENT_ESCAPE_22,
- EVENT_ESCAPE_23,
- EVENT_ESCAPE_24,
- EVENT_ESCAPE_25,
- EVENT_ESCAPE_26,
- EVENT_ESCAPE_27,
-
- EVENT_OPEN_FROSTWORN_DOOR,
- EVENT_CLOSE_FROSTWORN_DOOR,
+
+ EVENT_REMORSELESS_WINTER,
+ EVENT_ESCAPE_SUMMON_GHOULS,
+ EVENT_ESCAPE_SUMMON_WITCH_DOCTOR,
+ EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION,
+
+ EVENT_OPEN_IMPENETRABLE_DOOR,
+ EVENT_CLOSE_IMPENETRABLE_DOOR,
+ EVENT_KORELN_LORALEN_DEATH
};
enum Misc
@@ -203,907 +193,1149 @@ enum Misc
ACTION_START_INTRO,
ACTION_SKIP_INTRO,
- QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710,
- QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712,
- QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500,
- QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802,
+ JAINA_SYLVANAS_MAX_HEALTH = 252000,
+
+ POINT_SHADOW_THRONE_DOOR = 1,
+ POINT_ATTACK_ICEWALL = 2,
+ POINT_TRAP = 3,
+
+ SOUND_LK_SLAY_1 = 17214,
+ SOUND_LK_SLAY_2 = 17215,
+ SOUND_LK_FURY_OF_FROSTMOURNE = 17224
};
enum Spells
{
- SPELL_CAST_VISUAL = 65633, // Jaina/Sylavana
- SPELL_BOSS_SPAWN_AURA = 72712, // Falric and Marwyn
- SPELL_UTHER_DESPAWN = 70693,
+ // Misc
SPELL_TAKE_FROSTMOURNE = 72729,
SPELL_FROSTMOURNE_DESPAWN = 72726,
SPELL_FROSTMOURNE_VISUAL = 73220,
SPELL_FROSTMOURNE_SOUNDS = 70667,
- SPELL_JAINA_ICEBARRIER = 69787, // Jaina Ice Barrier
- SPELL_JAINA_ICEPRISON = 69708, // Jaina Ice Prison
- SPELL_SYLVANAS_CLOAKOFDARKNESS = 70188, // Sylvanas Cloak of Darkness
- SPELL_SYLVANAS_DARKBINDING = 70194, // Sylvanas Dark Binding
- SPELL_REMORSELESS_WINTER = 69780, // Lich King Remorseless Winter
- SPELL_SOUL_REAPER = 69409, // Lich King Soul Reaper
- SPELL_FURY_OF_FROSTMOURNE = 70063, // Lich King Fury of FrostMourne
+ SPELL_BOSS_SPAWN_AURA = 72712, // Falric and Marwyn
+ SPELL_UTHER_DESPAWN = 70693,
+
+ // Jaina, Sylvanas
+ SPELL_CAST_VISUAL = 65633, // wrong
+ SPELL_SUMMON_SOULS = 72711,
+ SPELL_TAUNT_ARTHAS = 69857,
+ SPELL_JAINA_ICE_BARRIER = 69787, // Jaina Ice Barrier
+ SPELL_JAINA_ICE_PRISON = 69708, // Jaina Ice Prison
SPELL_JAINA_DESTROY_ICE_WALL = 69784, // Jaina
+ SPELL_SYLVANAS_CLOAK_OF_DARKNESS = 70188, // Sylvanas Cloak of Darkness
+ SPELL_SYLVANAS_DARK_BINDING = 70194, // Sylvanas Dark Binding
SPELL_SYLVANAS_DESTROY_ICE_WALL = 70224, // Sylvanas
- SPELL_SYLVANAS_JUMP = 68339, // Sylvanas Jump
+ SPELL_SYLVANAS_BLINDING_RETREAT = 70199, // Sylvanas Blinding Retreat
+
+ // Lich King
+ SPELL_REMORSELESS_WINTER = 69780, // Lich King Remorseless Winter
+ SPELL_SOUL_REAPER = 69409, // Lich King Soul Reaper
+ SPELL_FURY_OF_FROSTMOURNE = 70063, // Lich King Fury of Frostmourne
SPELL_RAISE_DEAD = 69818,
- SPELL_HARVEST_SOUL = 70070,
- SPELL_SUMMON_RISE_WITCH_DOCTOR = 69836,
+ SPELL_SUMMON_RISEN_WITCH_DOCTOR = 69836,
SPELL_SUMMON_LUMBERING_ABOMINATION = 69835,
SPELL_SUMMON_ICE_WALL = 69768, // Visual effect and icewall summoning
+ SPELL_PAIN_AND_SUFFERING = 74115, // Lich King Pain and Suffering
+ SPELL_STUN_BREAK_JAINA = 69764, // Lich King visual spell, another Stun Break is 69763, should remove the stun effect
+ SPELL_STUN_BREAK_SYLVANAS = 70200,
+ SPELL_HARVEST_SOUL = 69866, // Lich King Harvest Soul
+
+ // Koreln, Loralen
+ SPELL_FEIGN_DEATH = 29266,
// Raging Ghoul
- SPELL_EMERGE_VISUAL = 50142,
SPELL_GHOUL_JUMP = 70150,
+ SPELL_RAGING_GHOUL_SPAWN = 69636,
- // Witch Doctor
- SPELL_COURSE_OF_DOOM = 70144,
+ // Risen Witch Doctor
+ SPELL_CURSE_OF_DOOM = 70144,
SPELL_SHADOW_BOLT_VOLLEY = 70145,
SPELL_SHADOW_BOLT = 70080,
+ SPELL_RISEN_WITCH_DOCTOR_SPAWN = 69639,
// Lumbering Abomination
- SPELL_ABON_STRIKE = 40505,
- SPELL_VOMIT_SPRAY = 70176,
+ SPELL_CLEAVE = 40505,
+ SPELL_VOMIT_SPRAY = 70176
};
-const Position HallsofReflectionLocs[] =
+enum HorGossipMenu
{
- {5283.234863f, 1990.946777f, 707.695679f, 0.929097f}, // 2 Loralen Follows
- {5408.031250f, 2102.918213f, 707.695251f, 0.792756f}, // 9 Sylvanas Follows
- {5401.866699f, 2110.837402f, 707.695251f, 0.800610f}, // 10 Loralen follows
+ GOSSIP_MENU_JAINA_FINAL = 10930,
+ GOSSIP_MENU_SYLVANAS_FINAL = 10931
};
-const Position NpcJainaOrSylvanasEscapeRoute[] =
+Position const NpcJainaOrSylvanasEscapeRoute[] =
{
- {5601.217285f, 2207.652832f, 731.541931f, 5.223304f}, // leave the throne room
- {5607.224375f, 2173.913330f, 731.126038f, 2.608723f}, // adjust route
- {5583.427246f, 2138.784180f, 731.150391f, 4.260901f}, // stop for talking
- {5560.281738f, 2104.025635f, 731.410889f, 4.058383f}, // attack the first icewall
- {5510.990723f, 2000.772217f, 734.716064f, 3.973213f}, // attack the second icewall
- {5452.641113f, 1905.762329f, 746.530579f, 4.118834f}, // attack the third icewall
- {5338.126953f, 1768.429810f, 767.237244f, 3.855189f}, // attack the fourth icewall
- {5257.712402f, 1669.379395f, 784.300110f, 0.908373f}, // face the Lich king
- {5261.191895f, 1681.901611f, 784.285278f, 4.410465f}, // final position
+ { 5601.217285f, 2207.652832f, 731.541931f, 5.223304f }, // leave the throne room
+ { 5607.224375f, 2173.913330f, 731.126038f, 2.608723f }, // adjust route
+ { 5583.427246f, 2138.784180f, 731.150391f, 4.260901f }, // stop for talking
+ { 5560.281738f, 2104.025635f, 731.410889f, 4.058383f }, // attack the first icewall
+ { 5510.990723f, 2000.772217f, 734.716064f, 3.973213f }, // attack the second icewall
+ { 5452.641113f, 1905.762329f, 746.530579f, 4.118834f }, // attack the third icewall
+ { 5338.126953f, 1768.429810f, 767.237244f, 3.855189f }, // attack the fourth icewall
+ { 5259.06f, 1669.27f, 784.3008f, 0.0f }, // trap (sniffed)
+ { 5265.53f, 1681.6f, 784.2947f, 4.13643f } // final position (sniffed)
};
-const Position IceWalls[] =
+Position const LichKingMoveAwayPos = { 5400.069824f, 2102.7131689f, 707.69525f, 0.843803f }; // Lich King walks away
+Position const LichKingFirstSummon = { 5600.076172f, 2192.270996f, 731.750488f, 4.330935f }; // Lich King First summons
+Position const JainaSylvanasShadowThroneDoor = { 5577.243f, 2235.852f, 733.0128f, 2.209562f }; // Jaina/Sylvanas move to door
+Position const LichKingFinalPos = { 5283.742188f, 1706.335693f, 783.293518f, 4.138510f }; // Lich King Final Pos
+
+// sniffed
+Position const KorelnOrLoralenPos[] =
{
- {5547.833f, 2083.701f,731.4332f,4.24115f}, // first icewall
- {5503.213f, 1969.547f,737.0245f,4.293779f},// second icewall
- {5439.976f, 1879.005f,752.7048f,4.207591f},// third icewall
- {5318.289f, 1749.184f,771.9423f,4.054276f},// fourth icewall
+ { 5253.061f, 1953.616f, 707.6948f, 0.8377581f },
+ { 5283.226f, 1992.300f, 707.7445f, 0.8377581f },
+ { 5360.711f, 2064.797f, 707.6948f, 0.0f }
};
-const Position IntroPos = {5265.89f, 1952.98f, 707.6978f, 0.0f}; // Jaina/Sylvanas Intro Start Position
-const Position MoveThronePos = {5306.952148f, 1998.499023f, 709.341431f, 1.277278f}; // Jaina/Sylvanas walks to throne
-const Position UtherSpawnPos = {5308.310059f, 2003.857178f, 709.341431f, 4.650315f};
-const Position LichKingSpawnPos = {5362.917480f, 2062.307129f, 707.695374f, 3.945812f};
-const Position LichKingMoveThronePos = {5312.080566f, 2009.172119f, 709.341431f, 3.973301f}; // Lich King walks to throne
-const Position LichKingMoveAwayPos = {5400.069824f, 2102.7131689f, 707.69525f, 0.843803f}; // Lich King walks away
-const Position LichKingSpawnPos2 = {5552.733398f, 2262.718506f, 733.011047f, 4.009696f}; // Lich King Spawn Position 2
-const Position LichKingFirstSummon = {5600.076172f, 2192.270996f, 731.750488f, 4.330935f}; // Lich King First summons
-const Position JainaShadowThroneDoor = {5577.243f, 2235.852f, 733.0128f, 2.209562f}; // Jaina Spawn Position 2
-const Position SylvanasShadowThroneDoor = {5577.243f, 2235.852f, 733.0128f, 2.209562f}; // Sylvanas Spawn Position 2
-const Position FalricStartPos = {5283.878906f, 2030.459595f, 709.319641f, 5.506670f}; // Falric start position
-const Position MarwynStartPos = {5334.979980f, 1982.399536f, 709.320129f, 2.347014f}; // Marwyn start position
-const Position LichKingFinalPos = {5283.742188f, 1706.335693f, 783.293518f, 4.138510f}; // Lich King Final Pos
-const Position ChestPos = {5246.187500f, 1649.079468f, 784.301758f, 0.901268f}; // Chest position
-const Position FinalPortalPos = {5270.634277f ,1639.101196f, 784.303040f, 1.682743f}; // Final portal position
-
-class npc_jaina_or_sylvanas_hor : public CreatureScript
+Position const SylvanasIntroPosition[] =
{
- public:
- npc_jaina_or_sylvanas_hor() : CreatureScript("npc_jaina_or_sylvanas_hor") { }
-
- // AI of Part1
- struct npc_jaina_or_sylvanas_horAI : public ScriptedAI
- {
- npc_jaina_or_sylvanas_horAI(Creature* creature) : ScriptedAI(creature)
- {
- _instance = me->GetInstanceScript();
- }
-
- InstanceScript* _instance;
- uint64 _utherGUID;
- uint64 _lichkingGUID;
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // 0 - Spawn
+ { 5263.2f, 1950.96f, 707.6948f, 0.8028514f }, // 1 - Move to Door
+ { 5306.82f, 1998.17f, 709.341f, 1.239184f }, // 2 - Move to Frostmourne
+};
- EventMap _events;
+Position const JainaIntroPosition[] =
+{
+ { 0.0f, 0.0f, 0.0f, 0.0f }, // 0 - Spawn
+ { 5265.89f, 1952.98f, 707.6978f, 0.0f }, // 1 - Move to Door
+ { 5306.95f, 1998.49f, 709.3414f, 1.277278f } // 2 - Move to Frostmourne
+};
- void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
- {
- case 0:
- player->CLOSE_GOSSIP_MENU();
- _events.ScheduleEvent(EVENT_START_INTRO, 1000);
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
- break;
- case 1:
- player->CLOSE_GOSSIP_MENU();
- _events.ScheduleEvent(EVENT_SKIP_INTRO, 1000);
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
- break;
- }
- }
+Position const UtherSpawnPos = { 5307.814f, 2003.168f, 709.4244f, 4.537856f };
- void Reset() override
- {
- _events.Reset();
+Position const LichKingIntroPosition[] =
+{
+ { 5362.463f, 2062.693f, 707.7781f, 3.944444f }, // 0 - Spawn
+ { 5332.83f, 2031.24f, 707.6948f, 0.0f }, // 1 - Door
+ { 5312.93f, 2010.24f, 709.34f, 0.0f }, // 2 - Move to Frostmourne
+ { 5319.028f, 2016.662f, 707.6948f, 0.0f }, // 3 - Move back
+ { 5332.285f, 2030.832f, 707.6948f, 0.0f }, // 4 - Move back 2
+ { 5355.488f, 2055.149f, 707.6907f, 0.0f } // 5 - Move back 3
+};
- _utherGUID = 0;
- _lichkingGUID = 0;
+Position const FalricPosition[] =
+{
+ { 5276.583f, 2037.45f, 709.4025f, 5.532694f }, // 0 - Spawn
+ { 5283.95f, 2030.53f, 709.3191f, 0.0f } // 1 - Intro
+};
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
- me->SetStandState(UNIT_STAND_STATE_STAND);
- _events.ScheduleEvent(EVENT_WALK_INTRO1, 3000);
- }
+Position const MarwynPosition[] =
+{
+ { 5342.232f, 1975.696f, 709.4025f, 2.391101f }, // 0 - Spawn
+ { 5335.01f, 1982.37f, 709.3191f, 0.0f } // 1 - Intro
+};
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
+Position const SylvanasShadowThroneDoorPosition = { 5576.79f, 2235.73f, 733.0029f, 2.687807f };
- switch (_events.ExecuteEvent())
- {
- case EVENT_WALK_INTRO1:
- me->GetMotionMaster()->MovePoint(0, IntroPos);
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- {
- Talk(SAY_JAINA_INTRO_1);
- _events.ScheduleEvent(EVENT_WALK_INTRO2, 7000);
- }
- else
- {
- Talk(SAY_SYLVANAS_INTRO_1);
- _events.ScheduleEvent(EVENT_WALK_INTRO2, 9000);
- }
- break;
- case EVENT_WALK_INTRO2:
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_INTRO_2);
- else
- Talk(SAY_SYLVANAS_INTRO_2);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
- break;
- case EVENT_START_INTRO:
- me->GetMotionMaster()->MovePoint(0, MoveThronePos);
- // Begining of intro is differents between fActions as the speech sequence and timers are differents.
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- _events.ScheduleEvent(EVENT_INTRO_A2_1, 0);
- else
- _events.ScheduleEvent(EVENT_INTRO_H2_1, 0);
- break;
- // A2 Intro Events
- case EVENT_INTRO_A2_1:
- Talk(SAY_JAINA_INTRO_3);
- _events.ScheduleEvent(EVENT_INTRO_A2_2, 7000);
- break;
- case EVENT_INTRO_A2_2:
- Talk(SAY_JAINA_INTRO_4);
- _events.ScheduleEvent(EVENT_INTRO_A2_3, 10000);
- break;
- case EVENT_INTRO_A2_3:
- me->CastSpell(me, SPELL_CAST_VISUAL, false);
- me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true);
- _instance->HandleGameObject(_instance->GetData64(DATA_FROSTMOURNE), true);
- _events.ScheduleEvent(EVENT_INTRO_A2_4, 10000);
- break;
- case EVENT_INTRO_A2_4:
- if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
- {
- uther->GetMotionMaster()->MoveIdle();
- _utherGUID = uther->GetGUID();
- }
- _events.ScheduleEvent(EVENT_INTRO_A2_5, 2000);
- break;
- case EVENT_INTRO_A2_5:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_1);
- _events.ScheduleEvent(EVENT_INTRO_A2_6, 3000);
- break;
- case EVENT_INTRO_A2_6:
- Talk(SAY_JAINA_INTRO_5);
- _events.ScheduleEvent(EVENT_INTRO_A2_7, 7000);
- break;
- case EVENT_INTRO_A2_7:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_2);
- _events.ScheduleEvent(EVENT_INTRO_A2_8, 7000);
- break;
- case EVENT_INTRO_A2_8:
- Talk(SAY_JAINA_INTRO_6);
- _events.ScheduleEvent(EVENT_INTRO_A2_9, 1200);
- break;
- case EVENT_INTRO_A2_9:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_3);
- _events.ScheduleEvent(EVENT_INTRO_A2_10, 11000);
- break;
- case EVENT_INTRO_A2_10:
- Talk(SAY_JAINA_INTRO_7);
- _events.ScheduleEvent(EVENT_INTRO_A2_11, 6000);
- break;
- case EVENT_INTRO_A2_11:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_4);
- _events.ScheduleEvent(EVENT_INTRO_A2_12, 12000);
- break;
- case EVENT_INTRO_A2_12:
- Talk(SAY_JAINA_INTRO_8);
- _events.ScheduleEvent(EVENT_INTRO_A2_13, 6000);
- break;
- case EVENT_INTRO_A2_13:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_5);
- _events.ScheduleEvent(EVENT_INTRO_A2_14, 13000);
- break;
- case EVENT_INTRO_A2_14:
- Talk(SAY_JAINA_INTRO_9);
- _events.ScheduleEvent(EVENT_INTRO_A2_15, 12000);
- break;
- case EVENT_INTRO_A2_15:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_6);
- _events.ScheduleEvent(EVENT_INTRO_A2_16, 25000);
- break;
- case EVENT_INTRO_A2_16:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_7);
- _events.ScheduleEvent(EVENT_INTRO_A2_17, 6000);
- break;
- case EVENT_INTRO_A2_17:
- Talk(SAY_JAINA_INTRO_10);
- _events.ScheduleEvent(EVENT_INTRO_A2_18, 5000);
- break;
- case EVENT_INTRO_A2_18:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- {
- uther->HandleEmoteCommand(EMOTE_ONESHOT_NO);
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_8);
- }
- _events.ScheduleEvent(EVENT_INTRO_A2_19, 12000);
- break;
- case EVENT_INTRO_A2_19:
- Talk(SAY_JAINA_INTRO_11);
- _events.ScheduleEvent(EVENT_INTRO_LK_1, 3000);
- break;
- // H2 Intro Events
- case EVENT_INTRO_H2_1:
- Talk(SAY_SYLVANAS_INTRO_1);
- _events.ScheduleEvent(EVENT_INTRO_H2_2, 8000);
- break;
- case EVENT_INTRO_H2_2:
- Talk(SAY_SYLVANAS_INTRO_2);
- _events.ScheduleEvent(EVENT_INTRO_H2_3, 6000);
- break;
- case EVENT_INTRO_H2_3:
- Talk(SAY_SYLVANAS_INTRO_3);
- me->CastSpell(me, SPELL_CAST_VISUAL, false);
- me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true);
- _instance->HandleGameObject(_instance->GetData64(DATA_FROSTMOURNE), true);
- _events.ScheduleEvent(EVENT_INTRO_H2_4, 6000);
- break;
- case EVENT_INTRO_H2_4:
- // spawn UTHER during speach 2
- if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
- {
- uther->GetMotionMaster()->MoveIdle();
- _utherGUID = uther->GetGUID();
- }
- _events.ScheduleEvent(EVENT_INTRO_H2_5, 2000);
- break;
- case EVENT_INTRO_H2_5:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_1);
- _events.ScheduleEvent(EVENT_INTRO_H2_6, 11000);
- break;
- case EVENT_INTRO_H2_6:
- Talk(SAY_SYLVANAS_INTRO_4);
- _events.ScheduleEvent(EVENT_INTRO_H2_7, 3000);
- break;
- case EVENT_INTRO_H2_7:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_2);
- _events.ScheduleEvent(EVENT_INTRO_H2_8, 6000);
- break;
- case EVENT_INTRO_H2_8:
- Talk(SAY_SYLVANAS_INTRO_5);
- _events.ScheduleEvent(EVENT_INTRO_H2_9, 5000);
- break;
- case EVENT_INTRO_H2_9:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_3);
- _events.ScheduleEvent(EVENT_INTRO_H2_10, 19000);
- break;
- case EVENT_INTRO_H2_10:
- Talk(SAY_SYLVANAS_INTRO_6);
- _events.ScheduleEvent(EVENT_INTRO_H2_11, 1500);
- break;
- case EVENT_INTRO_H2_11:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_4);
- _events.ScheduleEvent(EVENT_INTRO_H2_12, 19500);
- break;
- case EVENT_INTRO_H2_12:
- Talk(SAY_SYLVANAS_INTRO_7);
- _events.ScheduleEvent(EVENT_INTRO_H2_13, 2000);
- break;
- case EVENT_INTRO_H2_13:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- {
- uther->HandleEmoteCommand(EMOTE_ONESHOT_NO);
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_5);
- }
- _events.ScheduleEvent(EVENT_INTRO_H2_14, 12000);
- break;
- case EVENT_INTRO_H2_14:
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_6);
- _events.ScheduleEvent(EVENT_INTRO_H2_15, 8000);
- break;
- case EVENT_INTRO_H2_15:
- Talk(SAY_SYLVANAS_INTRO_8);
- _events.ScheduleEvent(EVENT_INTRO_LK_1, 2000);
- break;
- // Remaining Intro Events common for both faction
- case EVENT_INTRO_LK_1:
- // Spawn LK in front of door, and make him move to the sword.
- if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART1, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
- {
- lichking->SetWalk(true);
- lichking->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos);
- _lichkingGUID = lichking->GetGUID();
- _events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 0);
- _events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 4000);
- }
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- {
- uther->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER);
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- uther->AI()->Talk(SAY_UTHER_INTRO_A2_9);
- else
- uther->AI()->Talk(SAY_UTHER_INTRO_H2_7);
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_2, 10000);
- break;
- case EVENT_INTRO_LK_2:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->AI()->Talk(SAY_LK_INTRO_1);
- _events.ScheduleEvent(EVENT_INTRO_LK_3, 1000);
- break;
- case EVENT_INTRO_LK_3:
- // The Lich King banishes Uther to the abyss.
- if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
- {
- uther->CastSpell(uther, SPELL_UTHER_DESPAWN, true);
- uther->DespawnOrUnsummon(5000);
- _utherGUID = 0;
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_4, 9000);
- break;
- case EVENT_INTRO_LK_4:
- // He steps forward and removes the runeblade from the heap of skulls.
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- {
- if (GameObject* frostmourne = ObjectAccessor::GetGameObject(*me, _instance->GetData64(DATA_FROSTMOURNE)))
- frostmourne->SetPhaseMask(2, true);
- lichking->CastSpell(lichking, SPELL_TAKE_FROSTMOURNE, true);
- lichking->CastSpell(lichking, SPELL_FROSTMOURNE_VISUAL, true);
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_5, 8000);
- break;
- case EVENT_INTRO_LK_5:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->AI()->Talk(SAY_LK_INTRO_2);
- _events.ScheduleEvent(EVENT_INTRO_LK_6, 10000);
- break;
- case EVENT_INTRO_LK_6:
- // summon Falric and Marwyn. then go back to the door
- if (Creature* falric = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_FALRIC_EVENT)))
- {
- falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true);
- falric->SetVisible(true);
- }
- if (Creature* marwyn = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MARWYN_EVENT)))
- {
- marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true);
- marwyn->SetVisible(true);
- }
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- {
- lichking->AI()->Talk(SAY_LK_INTRO_3);
- lichking->SetWalk(true);
- lichking->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos);
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_7, 10000);
- _events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 5000);
- break;
- case EVENT_INTRO_LK_7:
- if (Creature* marwyn = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MARWYN_EVENT)))
- {
- marwyn->AI()->Talk(SAY_MARWYN_INTRO_1);
- marwyn->SetWalk(true);
- marwyn->GetMotionMaster()->MovePoint(0, MarwynStartPos);
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_8, 1000);
- break;
- case EVENT_INTRO_LK_8:
- if (Creature* falric = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_FALRIC_EVENT)))
- {
- falric->AI()->Talk(SAY_FALRIC_INTRO_1);
- falric->SetWalk(true);
- falric->GetMotionMaster()->MovePoint(0, FalricStartPos);
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_9, 5000);
- break;
- case EVENT_INTRO_LK_9:
- if (Creature* falric = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_FALRIC_EVENT)))
- falric->AI()->Talk(SAY_FALRIC_INTRO_2);
- _instance->ProcessEvent(0, EVENT_SPAWN_WAVES);
- _events.ScheduleEvent(EVENT_INTRO_LK_10, 4000);
- break;
- case EVENT_INTRO_LK_10:
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_INTRO_END);
- else
- Talk(SAY_SYLVANAS_INTRO_END);
- me->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos);
- /// @todo Loralen/Koreln shall run also
- _events.ScheduleEvent(EVENT_INTRO_LK_11, 5000);
- break;
- case EVENT_INTRO_LK_11:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- {
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- lichking->AI()->Talk(SAY_LK_JAINA_INTRO_END);
- else
- lichking->AI()->Talk(SAY_LK_SYLVANAS_INTRO_END);
- }
- _events.ScheduleEvent(EVENT_INTRO_END, 5000);
- break;
- case EVENT_INTRO_END:
- _instance->SetData(DATA_INTRO_EVENT, DONE);
- // Loralen or Koreln disappearAndDie()
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- {
- lichking->DespawnOrUnsummon(5000);
- _lichkingGUID = 0;
- }
- me->DespawnOrUnsummon(10000);
- _events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 7000);
- break;
- case EVENT_SKIP_INTRO:
- me->GetMotionMaster()->MovePoint(0, MoveThronePos);
- /// @todo Loralen/Koreln shall run also
- if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART1, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
- {
- lichking->SetWalk(true);
- lichking->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos);
- lichking->SetReactState(REACT_PASSIVE);
- _lichkingGUID = lichking->GetGUID();
- _events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 0);
- _events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 4000);
- }
- _events.ScheduleEvent(EVENT_INTRO_LK_4, 15000);
- break;
- case EVENT_OPEN_FROSTWORN_DOOR:
- if (GameObject* gate = ObjectAccessor::GetGameObject(*me, _instance->GetData64(DATA_FROSTWORN_DOOR)))
- _instance->HandleGameObject(0, true, gate);
- break;
- case EVENT_CLOSE_FROSTWORN_DOOR:
- if (GameObject* gate = ObjectAccessor::GetGameObject(*me, _instance->GetData64(DATA_FROSTWORN_DOOR)))
- _instance->HandleGameObject(0, false, gate);
- break;
- }
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetHallsOfReflectionAI<npc_jaina_or_sylvanas_horAI>(creature);
- }
+Position const IceWallTargetPosition[] =
+{
+ { 5547.833f, 2083.701f, 731.4332f, 1.029744f }, // 1st Icewall
+ { 5503.213f, 1969.547f, 737.0245f, 1.27409f }, // 2nd Icewall
+ { 5439.976f, 1879.005f, 752.7048f, 1.064651f }, // 3rd Icewall
+ { 5318.289f, 1749.184f, 771.9423f, 0.8726646f } // 4th Icewall
};
-class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
+class npc_jaina_or_sylvanas_intro_hor : public CreatureScript
{
public:
- npc_jaina_or_sylvanas_escape_hor() : CreatureScript("npc_jaina_or_sylvanas_escape_hor") { }
-
- // AI of Part2
- struct npc_jaina_or_sylvanas_escape_horAI : public ScriptedAI
- {
- npc_jaina_or_sylvanas_escape_horAI(Creature* creature) : ScriptedAI(creature),
- _instance(creature->GetInstanceScript()), _lichkingGUID(0), _walltargetGUID(0),
- _icewallGUID(0), _icewall(0)
- {
- }
-
- InstanceScript* _instance;
- uint64 _lichkingGUID;
- uint64 _walltargetGUID; // dummy
- uint64 _icewallGUID; // object
- uint32 _icewall; // icewall number
-
- EventMap _events;
+ npc_jaina_or_sylvanas_intro_hor() : CreatureScript("npc_jaina_or_sylvanas_intro_hor") { }
- void Reset() override
+ struct npc_jaina_or_sylvanas_intro_horAI : public ScriptedAI
{
- _events.Reset();
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->DespawnOrUnsummon(1);
- _lichkingGUID = 0;
- _walltargetGUID = 0;
- _icewallGUID = 0;
- _icewall = 0;
- _events.ScheduleEvent(EVENT_ESCAPE, 0);
- }
-
- void JustDied(Unit* /*Killer*/) override
- {
- _instance->SetData(DATA_ESCAPE_EVENT, FAIL);
- }
-
- void DoAction(int32 actionId) override
- {
- switch (actionId)
- {
- case ACTION_START_ESCAPING: // called by InstanceScript when we need to start the escaping event
- _events.ScheduleEvent(EVENT_ESCAPE_1, 1000);
- break;
- case ACTION_WALL_BROKEN:
- _icewall++;
- if (_icewall != 4)
- _events.ScheduleEvent(EVENT_ESCAPE_17, 3000);
- else
- _events.ScheduleEvent(EVENT_ESCAPE_23, 3000);
- break;
+ npc_jaina_or_sylvanas_intro_horAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
}
- }
- void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
+ void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
- case 0:
- player->CLOSE_GOSSIP_MENU();
- me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
- _events.ScheduleEvent(EVENT_ESCAPE_7, 0);
- break;
- }
- }
+ player->PlayerTalkClass->ClearMenus();
- void DestroyIceWall()
- {
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- me->RemoveAurasDueToSpell(SPELL_JAINA_DESTROY_ICE_WALL);
- else
- me->RemoveAurasDueToSpell(SPELL_SYLVANAS_DESTROY_ICE_WALL);
+ switch (gossipListId)
+ {
+ case 0:
+ player->PlayerTalkClass->SendCloseGossip();
+ _events.ScheduleEvent(EVENT_START_INTRO, 1000);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ case 1:
+ player->PlayerTalkClass->SendCloseGossip();
+ _events.ScheduleEvent(EVENT_SKIP_INTRO, 1000);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ default:
+ break;
+ }
+ }
- _instance->HandleGameObject(_icewallGUID, true);
+ void Reset() override
+ {
+ _events.Reset();
- if (Creature* wallTarget = ObjectAccessor::GetCreature(*me, _walltargetGUID))
- wallTarget->DespawnOrUnsummon();
- }
+ _utherGUID = 0;
+ _lichkingGUID = 0;
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ _events.ScheduleEvent(EVENT_WALK_INTRO1, 3000);
+ }
- while (uint32 event = _events.ExecuteEvent())
+ void UpdateAI(uint32 diff) override
{
- switch (event)
+ _events.Update(diff);
+
+ switch (_events.ExecuteEvent())
{
- case EVENT_ESCAPE:
- if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART2, LichKingSpawnPos2, TEMPSUMMON_MANUAL_DESPAWN))
+ case EVENT_WALK_INTRO1:
+ if (Creature* korelnOrLoralen = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KORELN_LORALEN)))
+ korelnOrLoralen->GetMotionMaster()->MovePoint(0, KorelnOrLoralenPos[0]);
+
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
{
- me->Attack(lichking, true);
- lichking->Attack(me, true);
- me->SetReactState(REACT_PASSIVE);
- lichking->SetReactState(REACT_PASSIVE);
- _lichkingGUID = lichking->GetGUID();
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- DoCast(me, SPELL_JAINA_ICEBARRIER);
- else
- DoCast(me, SPELL_SYLVANAS_CLOAKOFDARKNESS);
+ me->GetMotionMaster()->MovePoint(0, JainaIntroPosition[1]);
+ Talk(SAY_JAINA_INTRO_1);
+ _events.ScheduleEvent(EVENT_WALK_INTRO2, 7000);
}
- me->SetHealth(252000);
- break;
- case EVENT_ESCAPE_1:
- _instance->SetData(DATA_ESCAPE_EVENT, IN_PROGRESS);
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ else
{
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- lichking->AI()->Talk(SAY_LK_ESCAPE_1);
- else
- lichking->AI()->Talk(SAY_LK_ESCAPE_2);
- _events.ScheduleEvent(EVENT_ESCAPE_2, 8000);
+ me->GetMotionMaster()->MovePoint(0, SylvanasIntroPosition[1]);
+ Talk(SAY_SYLVANAS_INTRO_1);
+ _events.ScheduleEvent(EVENT_WALK_INTRO2, 9000);
}
break;
- case EVENT_ESCAPE_2:
+ case EVENT_WALK_INTRO2:
if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- DoCast(me, SPELL_CAST_VISUAL, true);
+ Talk(SAY_JAINA_INTRO_2);
else
- DoCast(me, SPELL_SYLVANAS_JUMP, true);
- _events.ScheduleEvent(EVENT_ESCAPE_3, 1000);
+ Talk(SAY_SYLVANAS_INTRO_2);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
break;
- case EVENT_ESCAPE_3:
+ case EVENT_START_INTRO:
+ if (Creature* korelnOrLoralen = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KORELN_LORALEN)))
+ korelnOrLoralen->GetMotionMaster()->MovePoint(0, KorelnOrLoralenPos[1]);
+ // Begining of intro is differents between factions as the speech sequence and timers are differents.
if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- DoCastAOE(SPELL_JAINA_ICEPRISON, true);
+ {
+ me->GetMotionMaster()->MovePoint(0, JainaIntroPosition[2]);
+ _events.ScheduleEvent(EVENT_INTRO_A2_1, 0);
+ }
else
- DoCastAOE(SPELL_SYLVANAS_DARKBINDING, true);
- _events.ScheduleEvent(EVENT_ESCAPE_4, 2000);
+ {
+ me->GetMotionMaster()->MovePoint(0, SylvanasIntroPosition[2]);
+ _events.ScheduleEvent(EVENT_INTRO_H2_1, 0);
+ }
break;
- case EVENT_ESCAPE_4:
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_ESCAPE_1);
- else
- Talk(SAY_SYLVANAS_ESCAPE_1);
- _events.ScheduleEvent(EVENT_ESCAPE_5, 2000);
+ // A2 Intro Events
+ case EVENT_INTRO_A2_1:
+ Talk(SAY_JAINA_INTRO_3);
+ _events.ScheduleEvent(EVENT_INTRO_A2_2, 7000);
break;
- case EVENT_ESCAPE_5:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->CombatStop();
- me->GetMotionMaster()->MovePoint(0, JainaShadowThroneDoor);
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- me->RemoveAurasDueToSpell(SPELL_JAINA_ICEBARRIER);
- else
- me->RemoveAurasDueToSpell(SPELL_SYLVANAS_CLOAKOFDARKNESS);
- _events.ScheduleEvent(EVENT_ESCAPE_6, 5000);
+ case EVENT_INTRO_A2_2:
+ Talk(SAY_JAINA_INTRO_4);
+ _events.ScheduleEvent(EVENT_INTRO_A2_3, 10000);
break;
- case EVENT_ESCAPE_6:
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER);
+ case EVENT_INTRO_A2_3:
+ me->CastSpell(me, SPELL_CAST_VISUAL, false);
+ me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true);
+ _instance->HandleGameObject(_instance->GetData64(DATA_FROSTMOURNE), true);
+ _events.ScheduleEvent(EVENT_INTRO_A2_4, 10000);
break;
- case EVENT_ESCAPE_7:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- {
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- lichking->RemoveAurasDueToSpell(SPELL_JAINA_ICEPRISON);
- else
- lichking->RemoveAurasDueToSpell(SPELL_SYLVANAS_DARKBINDING);
- }
- _events.ScheduleEvent(EVENT_ESCAPE_8, 1000);
+ case EVENT_INTRO_A2_4:
+ if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
+ _utherGUID = uther->GetGUID();
+ _events.ScheduleEvent(EVENT_INTRO_A2_5, 2000);
break;
- case EVENT_ESCAPE_8:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->HandleEmoteCommand(TEXT_EMOTE_ROAR);
- me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[0]);
- _events.ScheduleEvent(EVENT_ESCAPE_9, 3000);
+ case EVENT_INTRO_A2_5:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_1);
+ _events.ScheduleEvent(EVENT_INTRO_A2_6, 3000);
break;
- case EVENT_ESCAPE_9:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[0]);
- _events.ScheduleEvent(EVENT_ESCAPE_10, 1000);
+ case EVENT_INTRO_A2_6:
+ Talk(SAY_JAINA_INTRO_5);
+ _events.ScheduleEvent(EVENT_INTRO_A2_7, 7000);
break;
- case EVENT_ESCAPE_10:
- me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[1]);
- _events.ScheduleEvent(EVENT_ESCAPE_11, 5000);
+ case EVENT_INTRO_A2_7:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_2);
+ _events.ScheduleEvent(EVENT_INTRO_A2_8, 7000);
break;
- case EVENT_ESCAPE_11:
- me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[2]);
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->GetMotionMaster()->MovePoint(0, LichKingFirstSummon);
- _events.ScheduleEvent(EVENT_ESCAPE_12, 6000);
+ case EVENT_INTRO_A2_8:
+ Talk(SAY_JAINA_INTRO_6);
+ _events.ScheduleEvent(EVENT_INTRO_A2_9, 1200);
break;
- case EVENT_ESCAPE_12:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ case EVENT_INTRO_A2_9:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_3);
+ _events.ScheduleEvent(EVENT_INTRO_A2_10, 11000);
+ break;
+ case EVENT_INTRO_A2_10:
+ Talk(SAY_JAINA_INTRO_7);
+ _events.ScheduleEvent(EVENT_INTRO_A2_11, 6000);
+ break;
+ case EVENT_INTRO_A2_11:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_4);
+ _events.ScheduleEvent(EVENT_INTRO_A2_12, 12000);
+ break;
+ case EVENT_INTRO_A2_12:
+ Talk(SAY_JAINA_INTRO_8);
+ _events.ScheduleEvent(EVENT_INTRO_A2_13, 6000);
+ break;
+ case EVENT_INTRO_A2_13:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_5);
+ _events.ScheduleEvent(EVENT_INTRO_A2_14, 13000);
+ break;
+ case EVENT_INTRO_A2_14:
+ Talk(SAY_JAINA_INTRO_9);
+ _events.ScheduleEvent(EVENT_INTRO_A2_15, 12000);
+ break;
+ case EVENT_INTRO_A2_15:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_6);
+ _events.ScheduleEvent(EVENT_INTRO_A2_16, 25000);
+ break;
+ case EVENT_INTRO_A2_16:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_7);
+ _events.ScheduleEvent(EVENT_INTRO_A2_17, 6000);
+ break;
+ case EVENT_INTRO_A2_17:
+ Talk(SAY_JAINA_INTRO_10);
+ _events.ScheduleEvent(EVENT_INTRO_A2_18, 5000);
+ break;
+ case EVENT_INTRO_A2_18:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
{
- lichking->AI()->Talk(SAY_LK_ESCAPE_3);
- lichking->CastSpell(me, SPELL_RAISE_DEAD);
- lichking->Attack(me, true);
+ uther->HandleEmoteCommand(EMOTE_ONESHOT_NO);
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_8);
}
- _events.ScheduleEvent(EVENT_ESCAPE_13, 4000);
+ _events.ScheduleEvent(EVENT_INTRO_A2_19, 12000);
break;
- case EVENT_ESCAPE_13:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ case EVENT_INTRO_A2_19:
+ Talk(SAY_JAINA_INTRO_11);
+ _events.ScheduleEvent(EVENT_INTRO_LK_1, 3000);
+ break;
+ // H2 Intro Events
+ case EVENT_INTRO_H2_1:
+ Talk(SAY_SYLVANAS_INTRO_1);
+ _events.ScheduleEvent(EVENT_INTRO_H2_2, 8000);
+ break;
+ case EVENT_INTRO_H2_2:
+ Talk(SAY_SYLVANAS_INTRO_2);
+ _events.ScheduleEvent(EVENT_INTRO_H2_3, 6000);
+ break;
+ case EVENT_INTRO_H2_3:
+ Talk(SAY_SYLVANAS_INTRO_3);
+ me->CastSpell(me, SPELL_CAST_VISUAL, false);
+ me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true);
+ _instance->HandleGameObject(_instance->GetData64(DATA_FROSTMOURNE), true);
+ _events.ScheduleEvent(EVENT_INTRO_H2_4, 6000);
+ break;
+ case EVENT_INTRO_H2_4:
+ // spawn UTHER during speach 2
+ if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN))
+ _utherGUID = uther->GetGUID();
+ _events.ScheduleEvent(EVENT_INTRO_H2_5, 2000);
+ break;
+ case EVENT_INTRO_H2_5:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_1);
+ _events.ScheduleEvent(EVENT_INTRO_H2_6, 11000);
+ break;
+ case EVENT_INTRO_H2_6:
+ Talk(SAY_SYLVANAS_INTRO_4);
+ _events.ScheduleEvent(EVENT_INTRO_H2_7, 3000);
+ break;
+ case EVENT_INTRO_H2_7:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_2);
+ _events.ScheduleEvent(EVENT_INTRO_H2_8, 6000);
+ break;
+ case EVENT_INTRO_H2_8:
+ Talk(SAY_SYLVANAS_INTRO_5);
+ _events.ScheduleEvent(EVENT_INTRO_H2_9, 5000);
+ break;
+ case EVENT_INTRO_H2_9:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_3);
+ _events.ScheduleEvent(EVENT_INTRO_H2_10, 19000);
+ break;
+ case EVENT_INTRO_H2_10:
+ Talk(SAY_SYLVANAS_INTRO_6);
+ _events.ScheduleEvent(EVENT_INTRO_H2_11, 1500);
+ break;
+ case EVENT_INTRO_H2_11:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_4);
+ _events.ScheduleEvent(EVENT_INTRO_H2_12, 19500);
+ break;
+ case EVENT_INTRO_H2_12:
+ Talk(SAY_SYLVANAS_INTRO_7);
+ _events.ScheduleEvent(EVENT_INTRO_H2_13, 2000);
+ break;
+ case EVENT_INTRO_H2_13:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
{
- lichking->CastSpell(lichking, SPELL_REMORSELESS_WINTER, true);
- lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR);
- lichking->GetMotionMaster()->MoveIdle();
- lichking->GetMotionMaster()->MoveChase(me);
+ uther->HandleEmoteCommand(EMOTE_ONESHOT_NO);
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_5);
}
- if (Creature* walltarget = me->SummonCreature(NPC_ICE_WALL, IceWalls[0], TEMPSUMMON_MANUAL_DESPAWN, 720000))
+ _events.ScheduleEvent(EVENT_INTRO_H2_14, 12000);
+ break;
+ case EVENT_INTRO_H2_14:
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_6);
+ _events.ScheduleEvent(EVENT_INTRO_H2_15, 8000);
+ break;
+ case EVENT_INTRO_H2_15:
+ Talk(SAY_SYLVANAS_INTRO_8);
+ _events.ScheduleEvent(EVENT_INTRO_LK_1, 2000);
+ break;
+ // Remaining Intro Events common for both faction
+ case EVENT_INTRO_LK_1:
+ // Spawn LK in front of door, and make him move to the sword.
+ if (Creature* lichking = me->SummonCreature(NPC_THE_LICH_KING_INTRO, LichKingIntroPosition[0], TEMPSUMMON_MANUAL_DESPAWN))
{
- _walltargetGUID = walltarget->GetGUID();
- walltarget->CastSpell(walltarget, SPELL_SUMMON_ICE_WALL);
- walltarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
- me->Attack(walltarget, false);
+ lichking->SetWalk(true);
+ lichking->GetMotionMaster()->MovePoint(0, LichKingIntroPosition[2]);
+ _lichkingGUID = lichking->GetGUID();
+ _events.ScheduleEvent(EVENT_OPEN_IMPENETRABLE_DOOR, 0);
+ _events.ScheduleEvent(EVENT_CLOSE_IMPENETRABLE_DOOR, 4000);
}
- me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[3]);
- _events.ScheduleEvent(EVENT_ESCAPE_14, 8000);
- break;
- case EVENT_ESCAPE_14:
- if (Creature* walltarget = ObjectAccessor::GetCreature(*me, _walltargetGUID))
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
{
- if (GameObject* icewall = walltarget->FindNearestGameObject(GO_ICE_WALL, 50.00f))
- {
- _icewallGUID = icewall->GetGUID();
- icewall->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- _instance->HandleGameObject(0, false, icewall);
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_ESCAPE_2);
- else
- Talk(SAY_SYLVANAS_ESCAPE_2);
- }
+ uther->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER);
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ uther->AI()->Talk(SAY_UTHER_INTRO_A2_9);
+ else
+ uther->AI()->Talk(SAY_UTHER_INTRO_H2_7);
}
- _events.ScheduleEvent(EVENT_ESCAPE_15, 1000);
+ _events.ScheduleEvent(EVENT_INTRO_LK_2, 10000);
break;
- case EVENT_ESCAPE_15:
+ case EVENT_INTRO_LK_2:
if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ lichking->AI()->Talk(SAY_LK_INTRO_1);
+ _events.ScheduleEvent(EVENT_INTRO_LK_3, 1000);
+ break;
+ case EVENT_INTRO_LK_3:
+ // The Lich King banishes Uther to the abyss.
+ if (Creature* uther = ObjectAccessor::GetCreature(*me, _utherGUID))
{
- lichking->GetMotionMaster()->MoveIdle();
- lichking->GetMotionMaster()->MoveChase(me);
- lichking->SetReactState(REACT_PASSIVE);
+ uther->CastSpell(uther, SPELL_UTHER_DESPAWN, true);
+ uther->DespawnOrUnsummon(5000);
+ _utherGUID = 0;
}
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- DoCast(me, SPELL_JAINA_DESTROY_ICE_WALL, true);
- else
- DoCast(me, SPELL_SYLVANAS_DESTROY_ICE_WALL, true);
+ _events.ScheduleEvent(EVENT_INTRO_LK_4, 9000);
break;
- case EVENT_ESCAPE_17:// ICEWALL BROKEN
- me->GetMotionMaster()->MoveIdle();
+ case EVENT_INTRO_LK_4:
+ // He steps forward and removes the runeblade from the heap of skulls.
if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
{
- lichking->StopMoving();
- lichking->AI()->Talk(SAY_LK_ESCAPE_3);
- lichking->CastSpell(me, SPELL_RAISE_DEAD);
+ if (GameObject* frostmourne = ObjectAccessor::GetGameObject(*me, _instance->GetData64(DATA_FROSTMOURNE)))
+ frostmourne->SetPhaseMask(2, true);
+ lichking->CastSpell(lichking, SPELL_TAKE_FROSTMOURNE, true);
+ lichking->CastSpell(lichking, SPELL_FROSTMOURNE_VISUAL, true);
}
-
- DestroyIceWall();
-
- if (_icewall && _icewall < 4)
- me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[_icewall + 3]);
- _events.ScheduleEvent(EVENT_ESCAPE_18, 2000);
+ _events.ScheduleEvent(EVENT_INTRO_LK_5, 8000);
break;
- case EVENT_ESCAPE_18:
+ case EVENT_INTRO_LK_5:
if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ lichking->AI()->Talk(SAY_LK_INTRO_2);
+ _events.ScheduleEvent(EVENT_INTRO_LK_6, 10000);
+ break;
+ case EVENT_INTRO_LK_6:
+ // summon Falric and Marwyn. then go back to the door
+ if (Creature* falric = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_FALRIC)))
{
- lichking->GetMotionMaster()->MoveIdle();
- lichking->GetMotionMaster()->MoveChase(me);
+ falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true);
+ falric->SetVisible(true);
}
- _events.ScheduleEvent(EVENT_ESCAPE_19, 6000);
- break;
- case EVENT_ESCAPE_19:
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ if (Creature* marwyn = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MARWYN)))
{
- if (_icewall && _icewall < 4)
- lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR);
- lichking->GetMotionMaster()->MoveIdle();
- lichking->GetMotionMaster()->MoveChase(me);
- lichking->SetReactState(REACT_PASSIVE);
- lichking->Attack(me, true);
+ marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true);
+ marwyn->SetVisible(true);
}
- if (_icewall < 4)
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
{
- if (Creature* walltarget = me->SummonCreature(NPC_ICE_WALL, IceWalls[_icewall], TEMPSUMMON_MANUAL_DESPAWN, 720000))
- {
- _walltargetGUID = walltarget->GetGUID();
- walltarget->CastSpell(walltarget, SPELL_SUMMON_ICE_WALL);
- walltarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
- me->Attack(walltarget, false);
- }
+ lichking->AI()->Talk(SAY_LK_INTRO_3);
+ lichking->SetWalk(true);
+ lichking->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos);
}
- _events.ScheduleEvent(EVENT_ESCAPE_20, 3000);
+ _events.ScheduleEvent(EVENT_INTRO_LK_7, 10000);
+ _events.ScheduleEvent(EVENT_OPEN_IMPENETRABLE_DOOR, 5000);
break;
- case EVENT_ESCAPE_20:
- if (Creature* walltarget = ObjectAccessor::GetCreature(*me, _walltargetGUID))
+ case EVENT_INTRO_LK_7:
+ if (Creature* marwyn = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MARWYN)))
{
- if (GameObject* icewall = walltarget->FindNearestGameObject(GO_ICE_WALL, 50.00f))
- {
- _icewallGUID = icewall->GetGUID();
- _instance->HandleGameObject(0, false, icewall);
- icewall->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- {
- if (_icewall == 1)
- Talk(SAY_JAINA_ESCAPE_3);
- else if (_icewall == 2)
- Talk(SAY_JAINA_ESCAPE_4);
- else if (_icewall == 3)
- Talk(SAY_JAINA_ESCAPE_5);
- }
- else if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE)
- {
- if (_icewall == 1)
- Talk(SAY_SYLVANAS_ESCAPE_3);
- else if (_icewall == 2)
- Talk(SAY_SYLVANAS_ESCAPE_4);
- else if (_icewall == 3)
- Talk(SAY_SYLVANAS_ESCAPE_5);
- }
- }
+ marwyn->AI()->Talk(SAY_MARWYN_INTRO_1);
+ marwyn->SetWalk(true);
+ marwyn->GetMotionMaster()->MovePoint(0, MarwynPosition[1]);
}
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ _events.ScheduleEvent(EVENT_INTRO_LK_8, 1000);
+ break;
+ case EVENT_INTRO_LK_8:
+ if (Creature* falric = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_FALRIC)))
{
- if (_icewall && _icewall < 3)
- lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR);
- else
- lichking->CastSpell(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION);
+ falric->AI()->Talk(SAY_FALRIC_INTRO_1);
+ falric->SetWalk(true);
+ falric->GetMotionMaster()->MovePoint(0, FalricPosition[1]);
}
- if (_icewall == 3)
- _events.ScheduleEvent(EVENT_ESCAPE_21, 16000); // last wall, really far
- else
- _events.ScheduleEvent(EVENT_ESCAPE_21, 9000);
+ _events.ScheduleEvent(EVENT_INTRO_LK_9, 5000);
+ break;
+ case EVENT_INTRO_LK_9:
+ if (Creature* falric = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_FALRIC)))
+ falric->AI()->Talk(SAY_FALRIC_INTRO_2);
+ _instance->ProcessEvent(0, EVENT_SPAWN_WAVES);
+ _events.ScheduleEvent(EVENT_INTRO_LK_10, 4000);
break;
- case EVENT_ESCAPE_21:
+ case EVENT_INTRO_LK_10:
if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- DoCast(me, SPELL_JAINA_DESTROY_ICE_WALL, true);
+ Talk(SAY_JAINA_INTRO_END);
else
- DoCast(me, SPELL_SYLVANAS_DESTROY_ICE_WALL, true);
-
+ Talk(SAY_SYLVANAS_INTRO_END);
+ me->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos);
+ /// @todo: needs some improvements
+ if (Creature* korelnOrLoralen = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KORELN_LORALEN)))
+ korelnOrLoralen->GetMotionMaster()->MovePoint(1, KorelnOrLoralenPos[2]);
+ _events.ScheduleEvent(EVENT_INTRO_LK_11, 5000);
+ break;
+ case EVENT_INTRO_LK_11:
if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
{
- if (_icewall == 1)
- lichking->CastSpell(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION);
- else if (_icewall > 1 && _icewall < 4)
- {
- lichking->CastSpell(lichking, SPELL_SUMMON_RISE_WITCH_DOCTOR);
- _events.ScheduleEvent(EVENT_ESCAPE_22, 1000);
- }
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ lichking->AI()->Talk(SAY_LK_JAINA_INTRO_END);
+ else
+ lichking->AI()->Talk(SAY_LK_SYLVANAS_INTRO_END);
}
+ _events.ScheduleEvent(EVENT_INTRO_END, 5000);
break;
- case EVENT_ESCAPE_22:
+ case EVENT_INTRO_END:
+ _instance->SetData(DATA_INTRO_EVENT, DONE);
+ _events.ScheduleEvent(EVENT_KORELN_LORALEN_DEATH, 8000);
if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
{
- if (_icewall >= 2 && _icewall < 4)
- lichking->CastSpell(lichking, SPELL_SUMMON_LUMBERING_ABOMINATION);
+ lichking->DespawnOrUnsummon(5000);
+ _lichkingGUID = 0;
}
+ me->DespawnOrUnsummon(10000);
+ _events.ScheduleEvent(EVENT_CLOSE_IMPENETRABLE_DOOR, 7000);
break;
- case EVENT_ESCAPE_23: // FINAL PART
- DestroyIceWall();
-
+ case EVENT_SKIP_INTRO:
if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_ESCAPE_6);
+ me->GetMotionMaster()->MovePoint(0, JainaIntroPosition[2]);
else
- Talk(SAY_SYLVANAS_ESCAPE_6);
+ me->GetMotionMaster()->MovePoint(0, SylvanasIntroPosition[2]);
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
+ if (Creature* korelnOrLoralen = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KORELN_LORALEN)))
+ korelnOrLoralen->GetMotionMaster()->MovePoint(0, KorelnOrLoralenPos[1]);
+
+ if (Creature* lichking = me->SummonCreature(NPC_THE_LICH_KING_INTRO, LichKingIntroPosition[0], TEMPSUMMON_MANUAL_DESPAWN))
{
- lichking->GetMotionMaster()->MovePoint(0, LichKingFinalPos);
- lichking->AI()->Talk(SAY_LK_ESCAPE_11);
+ lichking->SetWalk(true);
+ lichking->GetMotionMaster()->MovePoint(0, LichKingIntroPosition[2]);
+ lichking->SetReactState(REACT_PASSIVE);
+ _lichkingGUID = lichking->GetGUID();
+ _events.ScheduleEvent(EVENT_OPEN_IMPENETRABLE_DOOR, 0);
+ _events.ScheduleEvent(EVENT_CLOSE_IMPENETRABLE_DOOR, 4000);
}
- me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[8]);
- _events.ScheduleEvent(EVENT_ESCAPE_24, 10000);
+ _events.ScheduleEvent(EVENT_INTRO_LK_4, 15000);
break;
- case EVENT_ESCAPE_24:
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_ESCAPE_8);
- else
- Talk(SAY_SYLVANAS_ESCAPE_8);
- _events.ScheduleEvent(EVENT_ESCAPE_25, 5000);
+ case EVENT_OPEN_IMPENETRABLE_DOOR:
+ _instance->HandleGameObject(_instance->GetData64(DATA_IMPENETRABLE_DOOR), true);
break;
- case EVENT_ESCAPE_25:
- if (GameObject* cave = ObjectAccessor::GetGameObject(*me, _instance->GetData64(DATA_CAVE_IN)))
- cave->SetGoState(GO_STATE_READY);
- _events.ScheduleEvent(EVENT_ESCAPE_26, 4000);
+ case EVENT_CLOSE_IMPENETRABLE_DOOR:
+ _instance->HandleGameObject(_instance->GetData64(DATA_IMPENETRABLE_DOOR), false);
break;
- case EVENT_ESCAPE_26:
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- Talk(SAY_JAINA_ESCAPE_10);
+ case EVENT_KORELN_LORALEN_DEATH:
+ if (Creature* korelnOrLoralen = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_KORELN_LORALEN)))
+ korelnOrLoralen->CastSpell(korelnOrLoralen, SPELL_FEIGN_DEATH);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ uint64 _utherGUID;
+ uint64 _lichkingGUID;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_jaina_or_sylvanas_intro_horAI>(creature);
+ }
+};
+
+class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
+{
+ public:
+ npc_jaina_or_sylvanas_escape_hor() : CreatureScript("npc_jaina_or_sylvanas_escape_hor") { }
+
+ bool OnGossipHello(Player* player, Creature* creature) override
+ {
+ // override default gossip
+ if (InstanceScript* instance = creature->GetInstanceScript())
+ if (instance->GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE)
+ {
+ player->PrepareGossipMenu(creature, creature->GetEntry() == NPC_JAINA_ESCAPE ? GOSSIP_MENU_JAINA_FINAL : GOSSIP_MENU_SYLVANAS_FINAL, true);
+ player->SendPreparedGossip(creature);
+ return true;
+ }
+
+ // load default gossip
+ return false;
+ }
+
+ struct npc_jaina_or_sylvanas_escape_horAI : public ScriptedAI
+ {
+ npc_jaina_or_sylvanas_escape_horAI(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript()), _icewall(0), _prefight(false), _invincibility(true) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ _icewall = 0;
+ _events.ScheduleEvent(EVENT_ESCAPE, 1000);
+ _instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ lichking->AI()->EnterEvadeMode(); // event failed
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (damage >= me->GetHealth() && _invincibility)
+ damage = me->GetHealth() - 1;
+ }
+
+ void DoAction(int32 actionId) override
+ {
+ switch (actionId)
+ {
+ case ACTION_START_PREFIGHT:
+ if (_prefight)
+ return;
+ _prefight = true;
+ _events.ScheduleEvent(EVENT_ESCAPE_1, 1000);
+ break;
+ case ACTION_WALL_BROKEN:
+ ++_icewall;
+ if (_icewall < 4)
+ _events.ScheduleEvent(EVENT_ESCAPE_13, 3000);
else
- Talk(SAY_SYLVANAS_ESCAPE_9);
- _events.ScheduleEvent(EVENT_ESCAPE_27, 4000);
+ _events.ScheduleEvent(EVENT_ESCAPE_15, 3000);
break;
- case EVENT_ESCAPE_27:
- if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
- me->SummonGameObject(IsHeroic() ? GO_CAPTAIN_CHEST_ALLIANCE_HEROIC : GO_CAPTAIN_CHEST_ALLIANCE_NORMAL, ChestPos.GetPositionX(), ChestPos.GetPositionY(), ChestPos.GetPositionZ(), ChestPos.GetOrientation(), 0, 0, 0, 0, 720000);
+ case ACTION_GUNSHIP_ARRIVAL:
+ _events.ScheduleEvent(EVENT_ESCAPE_16, 5000);
+ break;
+ case ACTION_GUNSHIP_ARRIVAL_2:
+ _events.ScheduleEvent(EVENT_ESCAPE_17, 5000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ {
+ player->PlayerTalkClass->ClearMenus();
+
+ switch (gossipListId)
+ {
+ case 0:
+ player->PlayerTalkClass->SendCloseGossip();
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ _events.ScheduleEvent(EVENT_ESCAPE_6, 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DestroyIceWall()
+ {
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ me->RemoveAurasDueToSpell(SPELL_JAINA_DESTROY_ICE_WALL);
+ else
+ me->RemoveAurasDueToSpell(SPELL_SYLVANAS_DESTROY_ICE_WALL);
+
+ _instance->HandleGameObject(_instance->GetData64(DATA_ICEWALL), true);
+ me->m_Events.AddEvent(new GameObjectDeleteDelayEvent(me, _instance->GetData64(DATA_ICEWALL)), me->m_Events.CalculateTime(5000));
+
+ if (Creature* wallTarget = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ICEWALL_TARGET)))
+ wallTarget->DespawnOrUnsummon();
+ }
+
+ void SummonIceWall()
+ {
+ if (_icewall < 4)
+ {
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ lichking->StopMoving();
+ if (Creature* wallTarget = me->SummonCreature(NPC_ICE_WALL_TARGET, IceWallTargetPosition[_icewall], TEMPSUMMON_MANUAL_DESPAWN, 720000))
+ lichking->CastSpell(wallTarget, SPELL_SUMMON_ICE_WALL);
+
+ lichking->AI()->SetData(DATA_ICEWALL, _icewall);
+ }
+ }
+ }
+
+ void AttackIceWall()
+ {
+ if (_icewall < 4)
+ Talk(SAY_JAINA_SYLVANAS_ESCAPE_2 + _icewall);
+
+ if (Creature* wallTarget = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ICEWALL_TARGET)))
+ me->SetFacingToObject(wallTarget);
+
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ DoCast(me, SPELL_JAINA_DESTROY_ICE_WALL, true);
+ else
+ DoCast(me, SPELL_SYLVANAS_DESTROY_ICE_WALL, true);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ switch (pointId)
+ {
+ case POINT_SHADOW_THRONE_DOOR:
+ if (me->GetEntry() == NPC_JAINA_ESCAPE)
+ me->RemoveAurasDueToSpell(SPELL_JAINA_ICE_BARRIER);
else
- me->SummonGameObject(IsHeroic() ? GO_CAPTAIN_CHEST_HORDE_HEROIC : GO_CAPTAIN_CHEST_HORDE_NORMAL, ChestPos.GetPositionX(), ChestPos.GetPositionY(), ChestPos.GetPositionZ(), ChestPos.GetOrientation(), 0, 0, 0, 0, 720000);
- me->SummonGameObject(GO_PORTAL, FinalPortalPos.GetPositionX(), FinalPortalPos.GetPositionY(), FinalPortalPos.GetPositionZ(), FinalPortalPos.GetOrientation(), 0, 0, 0, 0, 720000);
- if (Creature* lichking = ObjectAccessor::GetCreature(*me, _lichkingGUID))
- lichking->DespawnOrUnsummon(1);
+ me->RemoveAurasDueToSpell(SPELL_SYLVANAS_CLOAK_OF_DARKNESS);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ me->SetHealth(JAINA_SYLVANAS_MAX_HEALTH);
+ me->SetFacingTo(SylvanasShadowThroneDoorPosition.GetOrientation());
+ break;
+ case POINT_ATTACK_ICEWALL:
+ AttackIceWall();
+ break;
+ case POINT_TRAP:
+ Talk(SAY_JAINA_SYLVANAS_ESCAPE_8);
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ me->SetFacingToObject(lichking);
break;
+ default:
+ break;
+ }
+ }
+
+ void DeleteAllFromThreatList(Unit* target, uint64 except)
+ {
+ ThreatContainer::StorageType threatlist = target->getThreatManager().getThreatList();
+ for (auto i : threatlist)
+ {
+ if (i->getUnitGuid() == except)
+ continue;
+
+ i->removeReference();
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 event = _events.ExecuteEvent())
+ {
+ switch (event)
+ {
+ case EVENT_ESCAPE:
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ DoCast(me, SPELL_JAINA_ICE_BARRIER);
+ else
+ DoCast(me, SPELL_SYLVANAS_CLOAK_OF_DARKNESS);
+
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ AttackStart(lichking);
+ lichking->AI()->AttackStart(me);
+ me->CastSpell(lichking, SPELL_TAUNT_ARTHAS, true);
+ }
+ me->SetHealth(JAINA_SYLVANAS_MAX_HEALTH);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ case EVENT_ESCAPE_1:
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ lichking->AI()->Talk(SAY_LK_ESCAPE_1);
+ else
+ lichking->AI()->Talk(SAY_LK_ESCAPE_2);
+ _events.ScheduleEvent(EVENT_ESCAPE_2, 8000);
+ }
+ break;
+ case EVENT_ESCAPE_2:
+ me->AttackStop();
+ me->StopMoving();
+ me->SetReactState(REACT_PASSIVE);
+
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ DoCast(me, SPELL_JAINA_ICE_PRISON, false);
+ else
+ DoCast(me, SPELL_SYLVANAS_BLINDING_RETREAT, true);
+
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ lichking->SetReactState(REACT_PASSIVE);
+ lichking->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
+ }
+
+ _events.ScheduleEvent(EVENT_ESCAPE_3, 1500);
+ break;
+ case EVENT_ESCAPE_3:
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE)
+ DoCastAOE(SPELL_SYLVANAS_DARK_BINDING, true);
+ _events.ScheduleEvent(EVENT_ESCAPE_4, 1000);
+ break;
+ case EVENT_ESCAPE_4:
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ DoCast(me, SPELL_CREDIT_FINDING_JAINA);
+ else
+ DoCast(me, SPELL_CREDIT_FINDING_SYLVANAS);
+ Talk(SAY_JAINA_SYLVANAS_ESCAPE_1);
+
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ lichking->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ lichking->RemoveAllAttackers();
+
+ DeleteAllFromThreatList(lichking, me->GetGUID());
+ }
+
+ _events.ScheduleEvent(EVENT_ESCAPE_5, 2000);
+ break;
+ case EVENT_ESCAPE_5:
+ me->GetMotionMaster()->MovePoint(POINT_SHADOW_THRONE_DOOR, SylvanasShadowThroneDoorPosition);
+ break;
+ case EVENT_ESCAPE_6:
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ lichking->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_PACIFIED);
+
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ {
+ lichking->CastSpell(lichking, SPELL_STUN_BREAK_JAINA);
+ lichking->RemoveAurasDueToSpell(SPELL_JAINA_ICE_PRISON);
+ }
+ else
+ {
+ lichking->CastSpell(lichking, SPELL_STUN_BREAK_SYLVANAS);
+ lichking->RemoveAurasDueToSpell(SPELL_SYLVANAS_DARK_BINDING);
+ }
+ }
+ _invincibility = false;
+ _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
+ _events.ScheduleEvent(EVENT_ESCAPE_7, 1000);
+ break;
+ case EVENT_ESCAPE_7:
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ lichking->HandleEmoteCommand(TEXT_EMOTE_ROAR);
+ me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[0]);
+ _events.ScheduleEvent(EVENT_ESCAPE_8, 3000);
+ break;
+ case EVENT_ESCAPE_8:
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ lichking->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[0]);
+ _events.ScheduleEvent(EVENT_ESCAPE_9, 1000);
+ break;
+ case EVENT_ESCAPE_9:
+ me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[1]);
+ _events.ScheduleEvent(EVENT_ESCAPE_10, 5000);
+ break;
+ case EVENT_ESCAPE_10:
+ me->GetMotionMaster()->MovePoint(0, NpcJainaOrSylvanasEscapeRoute[2]);
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ lichking->GetMotionMaster()->MovePoint(1, LichKingFirstSummon);
+ _events.ScheduleEvent(EVENT_ESCAPE_11, 6000);
+ break;
+ case EVENT_ESCAPE_11:
+ SummonIceWall();
+ _events.ScheduleEvent(EVENT_ESCAPE_12, 4000);
+ break;
+ case EVENT_ESCAPE_12:
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ lichking->CastSpell(lichking, SPELL_PAIN_AND_SUFFERING, true);
+
+ me->GetMotionMaster()->MovePoint(POINT_ATTACK_ICEWALL, NpcJainaOrSylvanasEscapeRoute[3]);
+ break;
+ case EVENT_ESCAPE_13: // ICEWALL BROKEN
+ DestroyIceWall();
+
+ if (_icewall && _icewall < 4)
+ me->GetMotionMaster()->MovePoint(POINT_ATTACK_ICEWALL, NpcJainaOrSylvanasEscapeRoute[_icewall + 3]);
+ _events.ScheduleEvent(EVENT_ESCAPE_14, 8000);
+ break;
+ case EVENT_ESCAPE_14:
+ SummonIceWall();
+ break;
+ case EVENT_ESCAPE_15: // FINAL PART
+ DestroyIceWall();
+
+ Talk(SAY_JAINA_SYLVANAS_ESCAPE_6);
+
+ if (Creature* lichking = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING_ESCAPE)))
+ {
+ lichking->GetMotionMaster()->MovePoint(2, LichKingFinalPos);
+ lichking->RemoveAurasDueToSpell(SPELL_REMORSELESS_WINTER);
+ }
+ me->GetMotionMaster()->MovePoint(POINT_TRAP, NpcJainaOrSylvanasEscapeRoute[7]);
+ break;
+ case EVENT_ESCAPE_16:
+ me->RemoveAurasDueToSpell(SPELL_HARVEST_SOUL);
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ Talk(SAY_JAINA_ESCAPE_9);
+ if (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetData64(DATA_GUNSHIP)))
+ gunship->EnableMovement(true);
+ _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE);
+ break;
+ case EVENT_ESCAPE_17:
+ if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
+ Talk(SAY_JAINA_ESCAPE_10);
+ else
+ Talk(SAY_SYLVANAS_ESCAPE_9);
+ DoCast(me, SPELL_CREDIT_ESCAPING_ARTHAS);
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ default:
+ break;
}
}
+
+ DoMeleeAttackIfReady();
}
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetHallsOfReflectionAI<npc_jaina_or_sylvanas_escape_horAI>(creature);
- }
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ uint32 _icewall; // icewall number
+ bool _prefight;
+ bool _invincibility;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_jaina_or_sylvanas_escape_horAI>(creature);
+ }
+};
+
+class npc_the_lich_king_escape_hor : public CreatureScript
+{
+ public:
+ npc_the_lich_king_escape_hor() : CreatureScript("npc_the_lich_king_escape_hor") { }
+
+ struct npc_the_lich_king_escape_horAI : public ScriptedAI
+ {
+ npc_the_lich_king_escape_horAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, NOT_STARTED);
+ _summonsCount = 0;
+ _icewall = 0;
+ _despawn = false;
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type == POINT_MOTION_TYPE)
+ {
+ switch (pointId)
+ {
+ case 1:
+ if (Creature* target = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER)))
+ me->GetMotionMaster()->MoveChase(target);
+ break;
+ case 2:
+ Talk(SAY_LK_ESCAPE_HARVEST_SOUL);
+
+ if (Creature* target = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER)))
+ DoCast(target, SPELL_HARVEST_SOUL);
+
+ if (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetData64(DATA_GUNSHIP)))
+ gunship->EnableMovement(true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void JustSummoned(Creature* /*summon*/) override
+ {
+ ++_summonsCount;
+ }
+
+ void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) override
+ {
+ // should never happen
+ if (!_summonsCount)
+ return;
+
+ --_summonsCount;
+
+ // All summons dead and no summon events scheduled
+ if (!_summonsCount && _events.Empty())
+ {
+ if (Creature* jainaOrSylvanas = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER)))
+ jainaOrSylvanas->AI()->DoAction(ACTION_WALL_BROKEN);
+ }
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ DoPlaySoundToSet(me, RAND(SOUND_LK_SLAY_1, SOUND_LK_SLAY_2));
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ if (type != DATA_ICEWALL)
+ return;
+
+ _icewall = data;
+
+ switch (_icewall)
+ {
+ case 0: // 6 Ghouls, 1 Witch Doctor
+ DoZoneInCombat();
+ _events.ScheduleEvent(EVENT_REMORSELESS_WINTER, 0);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_GHOULS, 8000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 14000);
+ Talk(SAY_LK_ESCAPE_ICEWALL_SUMMONED_1);
+ break;
+ case 1: // 6 Ghouls, 2 Witch Doctor, 1 Lumbering Abomination
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_GHOULS, 8000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 13000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 16000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 18000);
+ Talk(SAY_LK_ESCAPE_ICEWALL_SUMMONED_2);
+ break;
+ case 2: // 6 Ghouls, 2 Witch Doctor, 2 Lumbering Abomination
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_GHOULS, 9000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 14000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 17000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 19000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 39000);
+ Talk(SAY_LK_ESCAPE_ICEWALL_SUMMONED_3);
+ break;
+ case 3: // 12 Ghouls, 4 Witch Doctor, 3 Lumbering Abomination
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_GHOULS, 9000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 17000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 19000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 40000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 46000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_GHOULS, 55000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 62000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 66000);
+ _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 14000);
+ Talk(SAY_LK_ESCAPE_ICEWALL_SUMMONED_4);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void EnterEvadeMode() override
+ {
+ if (_despawn)
+ return;
+
+ _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, FAIL);
+ me->StopMoving();
+ DoPlaySoundToSet(me, SOUND_LK_FURY_OF_FROSTMOURNE);
+ DoCastAOE(SPELL_FURY_OF_FROSTMOURNE);
+ me->DespawnOrUnsummon(12000);
+ _despawn = true;
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!SelectVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 event = _events.ExecuteEvent())
+ {
+ switch (event)
+ {
+ case EVENT_REMORSELESS_WINTER:
+ me->StopMoving();
+ Talk(SAY_LK_ESCAPE_WINTER);
+ DoCast(me, SPELL_REMORSELESS_WINTER);
+ break;
+ case EVENT_ESCAPE_SUMMON_GHOULS:
+ me->StopMoving();
+ Talk(SAY_LK_ESCAPE_GHOULS);
+ DoCast(me, SPELL_RAISE_DEAD);
+ break;
+ case EVENT_ESCAPE_SUMMON_WITCH_DOCTOR:
+ DoCast(me, SPELL_SUMMON_RISEN_WITCH_DOCTOR);
+ break;
+ case EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION:
+ Talk(SAY_LK_ESCAPE_ABOMINATION);
+ DoCast(me, SPELL_SUMMON_LUMBERING_ABOMINATION);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ bool SelectVictim()
+ {
+ if (!me->IsInCombat())
+ return false;
+
+ if (!me->HasReactState(REACT_PASSIVE))
+ {
+ if (Unit* victim = me->SelectVictim())
+ AttackStart(victim);
+ return me->GetVictim();
+ }
+ else if (me->getThreatManager().getThreatList().size() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER))
+ {
+ EnterEvadeMode();
+ return false;
+ }
+
+ return true;
+ }
+
+ InstanceScript* _instance;
+ EventMap _events;
+ uint8 _icewall;
+ uint32 _summonsCount;
+ bool _despawn;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_the_lich_king_escape_horAI>(creature);
+ }
};
enum TrashSpells
@@ -1140,7 +1372,7 @@ enum TrashSpells
SPELL_SHOOT = 72208,
SPELL_CURSED_ARROW = 72222,
SPELL_FROST_TRAP = 72215,
- SPELL_ICE_SHOT = 72268,
+ SPELL_ICE_SHOT = 72268
};
enum TrashEvents
@@ -1175,19 +1407,16 @@ enum TrashEvents
EVENT_SHOOT,
EVENT_CURSED_ARROW,
EVENT_FROST_TRAP,
- EVENT_ICE_SHOT,
+ EVENT_ICE_SHOT
};
struct npc_gauntlet_trash : public ScriptedAI
{
- npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
- {
- InternalWaveId = 0;
- }
+ npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript()), InternalWaveId(0) { }
void Reset() override
{
- InternalWaveId = 0;
me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
_events.Reset();
}
@@ -1222,352 +1451,362 @@ protected:
class npc_ghostly_priest : public CreatureScript
{
-public:
- npc_ghostly_priest() : CreatureScript("npc_ghostly_priest") { }
-
- struct npc_ghostly_priestAI : public npc_gauntlet_trash
- {
- npc_ghostly_priestAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+ public:
+ npc_ghostly_priest() : CreatureScript("npc_ghostly_priest") { }
- void EnterCombat(Unit* /*who*/) override
+ struct npc_ghostly_priestAI : public npc_gauntlet_trash
{
- _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); /// @todo adjust timers
- _events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
- _events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
- _events.ScheduleEvent(EVENT_DARK_MENDING, 20000);
- }
+ npc_ghostly_priestAI(Creature* creature) : npc_gauntlet_trash(creature) { }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- _events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- switch (_events.ExecuteEvent())
- {
- case EVENT_SHADOW_WORD_PAIN:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_SHADOW_WORD_PAIN);
- _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000);
- break;
- case EVENT_CIRCLE_OF_DESTRUCTION:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION);
- _events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
- break;
- case EVENT_COWER_IN_FEAR:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_COWER_IN_FEAR);
- _events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
- break;
- case EVENT_DARK_MENDING:
- // find an ally with missing HP
- if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000)))
- {
- DoCast(target, SPELL_DARK_MENDING);
- _events.ScheduleEvent(EVENT_DARK_MENDING, 20000);
- }
- else
- {
- // no friendly unit with missing hp. re-check in just 5 sec.
- _events.ScheduleEvent(EVENT_DARK_MENDING, 5000);
- }
- break;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(6000, 15000));
+ _events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
+ _events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
+ _events.ScheduleEvent(EVENT_DARK_MENDING, 20000);
}
- DoMeleeAttackIfReady();
- }
- };
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_ghostly_priestAI>(creature);
- }
-};
+ _events.Update(diff);
-class npc_phantom_mage : public CreatureScript
-{
-public:
- npc_phantom_mage() : CreatureScript("npc_phantom_mage") { }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- struct npc_phantom_mageAI : public npc_gauntlet_trash
- {
- npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_SHADOW_WORD_PAIN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_SHADOW_WORD_PAIN);
+ _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(6000, 15000));
+ break;
+ case EVENT_CIRCLE_OF_DESTRUCTION:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 10.0f, true))
+ DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION);
+ _events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000);
+ break;
+ case EVENT_COWER_IN_FEAR:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true))
+ DoCast(target, SPELL_COWER_IN_FEAR);
+ _events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000);
+ break;
+ case EVENT_DARK_MENDING:
+ // find an ally with missing HP
+ if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000)))
+ {
+ DoCast(target, SPELL_DARK_MENDING);
+ _events.ScheduleEvent(EVENT_DARK_MENDING, 20000);
+ }
+ else
+ {
+ // no friendly unit with missing hp. re-check in just 5 sec.
+ _events.ScheduleEvent(EVENT_DARK_MENDING, 5000);
+ }
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
- void EnterEvadeMode() override
+ CreatureAI* GetAI(Creature* creature) const override
{
- if (!me->HasAura(AURA_HALLUCINATION))
- npc_gauntlet_trash::EnterEvadeMode();
+ return GetHallsOfReflectionAI<npc_ghostly_priestAI>(creature);
}
+};
- void EnterCombat(Unit* /*who*/) override
+class npc_phantom_mage : public CreatureScript
+{
+ public:
+ npc_phantom_mage() : CreatureScript("npc_phantom_mage") { }
+
+ struct npc_phantom_mageAI : public npc_gauntlet_trash
{
- _events.ScheduleEvent(EVENT_FIREBALL, 3000); /// @todo adjust timers
- _events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000);
- _events.ScheduleEvent(EVENT_FROSTBOLT, 9000);
- _events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000);
- _events.ScheduleEvent(EVENT_HALLUCINATION, 40000);
- }
+ npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+
+ void EnterEvadeMode() override
+ {
+ if (!me->HasAura(AURA_HALLUCINATION))
+ npc_gauntlet_trash::EnterEvadeMode();
+ }
- void UpdateAI(uint32 diff) override
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_FIREBALL, 3000);
+ _events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000);
+ _events.ScheduleEvent(EVENT_FROSTBOLT, 9000);
+ _events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000);
+ _events.ScheduleEvent(EVENT_HALLUCINATION, 40000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_FIREBALL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_FIREBALL);
+ _events.ScheduleEvent(EVENT_FIREBALL, 15000);
+ break;
+ case EVENT_FLAMESTRIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_FLAMESTRIKE);
+ _events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000);
+ break;
+ case EVENT_FROSTBOLT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_FROSTBOLT);
+ _events.ScheduleEvent(EVENT_FROSTBOLT, 15000);
+ break;
+ case EVENT_CHAINS_OF_ICE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
+ DoCast(target, SPELL_CHAINS_OF_ICE);
+ _events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000);
+ break;
+ case EVENT_HALLUCINATION:
+ // removing any dots on mage or else the invisibility spell will break duration
+ me->RemoveAllAuras();
+ DoCast(me, SPELL_HALLUCINATION);
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
{
- if (!UpdateVictim())
- return;
-
- _events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- switch (_events.ExecuteEvent())
- {
- case EVENT_FIREBALL:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_FIREBALL);
- _events.ScheduleEvent(EVENT_FIREBALL, 15000);
- break;
- case EVENT_FLAMESTRIKE:
- DoCast(SPELL_FLAMESTRIKE);
- _events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000);
- break;
- case EVENT_FROSTBOLT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_FROSTBOLT);
- _events.ScheduleEvent(EVENT_FROSTBOLT, 15000);
- break;
- case EVENT_CHAINS_OF_ICE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_CHAINS_OF_ICE);
- _events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000);
- break;
- case EVENT_HALLUCINATION:
- // removing any dots on mage or else the invisibility spell will break duration
- me->RemoveAllAuras();
- DoCast(SPELL_HALLUCINATION);
- break;
- }
-
- DoMeleeAttackIfReady();
+ return GetHallsOfReflectionAI<npc_phantom_mageAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_phantom_mageAI>(creature);
- }
};
class npc_phantom_hallucination : public CreatureScript
{
-public:
- npc_phantom_hallucination() : CreatureScript("npc_phantom_hallucination") { }
-
- struct npc_phantom_hallucinationAI : public npc_phantom_mage::npc_phantom_mageAI
- {
- npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature) { }
+ public:
+ npc_phantom_hallucination() : CreatureScript("npc_phantom_hallucination") { }
- void Reset() override
+ struct npc_phantom_hallucinationAI : public npc_phantom_mage::npc_phantom_mageAI
{
- if (Unit* unit = me->SelectNearestTarget())
- AttackStart(unit);
- DoZoneInCombat();
- }
+ npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature) { }
- void EnterEvadeMode() override
- {
- if (me->GetOwner() && !me->GetOwner()->HasAura(AURA_HALLUCINATION))
- npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode();
- }
+ void Reset() override
+ {
+ DoZoneInCombat(me, 150.0f);
+ }
+
+ void EnterEvadeMode() override
+ {
+ if (me->GetOwner() && !me->GetOwner()->HasAura(AURA_HALLUCINATION))
+ npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode();
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ DoCastAOE(SPELL_HALLUCINATION_2);
+ }
+ };
- void JustDied(Unit* /*killer*/) override
+ CreatureAI* GetAI(Creature* creature) const override
{
- DoCast(SPELL_HALLUCINATION_2);
+ return new npc_phantom_hallucinationAI(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_phantom_hallucinationAI(creature);
- }
};
class npc_shadowy_mercenary : public CreatureScript
{
-public:
- npc_shadowy_mercenary() : CreatureScript("npc_shadowy_mercenary") { }
-
- struct npc_shadowy_mercenaryAI : public npc_gauntlet_trash
- {
- npc_shadowy_mercenaryAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+ public:
+ npc_shadowy_mercenary() : CreatureScript("npc_shadowy_mercenary") { }
- void EnterCombat(Unit* /*who*/) override
+ struct npc_shadowy_mercenaryAI : public npc_gauntlet_trash
{
- _events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); /// @todo adjust timers
- _events.ScheduleEvent(EVENT_DEADLY_POISON, 5000);
- _events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000);
- _events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000);
- }
+ npc_shadowy_mercenaryAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_SHADOW_STEP, 23000);
+ _events.ScheduleEvent(EVENT_DEADLY_POISON, 5000);
+ _events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000);
+ _events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
- void UpdateAI(uint32 diff) override
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_SHADOW_STEP:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_SHADOW_STEP);
+ _events.ScheduleEvent(EVENT_SHADOW_STEP, 8000);
+ break;
+ case EVENT_DEADLY_POISON:
+ DoCastVictim(SPELL_DEADLY_POISON);
+ _events.ScheduleEvent(EVENT_DEADLY_POISON, 10000);
+ break;
+ case EVENT_ENVENOMED_DAGGER_THROW:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_ENVENOMED_DAGGER_THROW);
+ _events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000);
+ break;
+ case EVENT_KIDNEY_SHOT:
+ DoCastVictim(SPELL_KIDNEY_SHOT);
+ _events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000);
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
{
- if (!UpdateVictim())
- return;
-
- _events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- switch (_events.ExecuteEvent())
- {
- case EVENT_SHADOW_STEP:
- DoCast(SPELL_SHADOW_STEP);
- _events.ScheduleEvent(EVENT_SHADOW_STEP, 8000);
- break;
- case EVENT_DEADLY_POISON:
- DoCastVictim(SPELL_DEADLY_POISON);
- _events.ScheduleEvent(EVENT_DEADLY_POISON, 10000);
- break;
- case EVENT_ENVENOMED_DAGGER_THROW:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_ENVENOMED_DAGGER_THROW);
- _events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000);
- break;
- case EVENT_KIDNEY_SHOT:
- DoCastVictim(SPELL_KIDNEY_SHOT);
- _events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000);
- break;
- }
-
- DoMeleeAttackIfReady();
+ return GetHallsOfReflectionAI<npc_shadowy_mercenaryAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_shadowy_mercenaryAI>(creature);
- }
};
class npc_spectral_footman : public CreatureScript
{
-public:
- npc_spectral_footman() : CreatureScript("npc_spectral_footman") { }
-
- struct npc_spectral_footmanAI : public npc_gauntlet_trash
- {
- npc_spectral_footmanAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+ public:
+ npc_spectral_footman() : CreatureScript("npc_spectral_footman") { }
- void EnterCombat(Unit* /*who*/) override
+ struct npc_spectral_footmanAI : public npc_gauntlet_trash
{
- _events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); /// @todo adjust timers
- _events.ScheduleEvent(EVENT_SHIELD_BASH, 10000);
- _events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000);
- }
+ npc_spectral_footmanAI(Creature* creature) : npc_gauntlet_trash(creature) { }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 14000);
+ _events.ScheduleEvent(EVENT_SHIELD_BASH, 10000);
+ _events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- _events.Update(diff);
+ _events.Update(diff);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- switch (_events.ExecuteEvent())
- {
- case EVENT_SPECTRAL_STRIKE:
- DoCastVictim(SPELL_SPECTRAL_STRIKE);
- _events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000);
- break;
- case EVENT_SHIELD_BASH:
- DoCastVictim(SPELL_SHIELD_BASH);
- _events.ScheduleEvent(EVENT_SHIELD_BASH, 5000);
- break;
- case EVENT_TORTURED_ENRAGE:
- DoCast(SPELL_TORTURED_ENRAGE);
- _events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000);
- break;
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_SPECTRAL_STRIKE:
+ DoCastVictim(SPELL_SPECTRAL_STRIKE);
+ _events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000);
+ break;
+ case EVENT_SHIELD_BASH:
+ DoCastVictim(SPELL_SHIELD_BASH);
+ _events.ScheduleEvent(EVENT_SHIELD_BASH, 5000);
+ break;
+ case EVENT_TORTURED_ENRAGE:
+ DoCast(me, SPELL_TORTURED_ENRAGE);
+ _events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000);
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
}
+ };
- DoMeleeAttackIfReady();
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_spectral_footmanAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_spectral_footmanAI>(creature);
- }
};
class npc_tortured_rifleman : public CreatureScript
{
-public:
- npc_tortured_rifleman() : CreatureScript("npc_tortured_rifleman") { }
-
- struct npc_tortured_riflemanAI : public npc_gauntlet_trash
- {
- npc_tortured_riflemanAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+ public:
+ npc_tortured_rifleman() : CreatureScript("npc_tortured_rifleman") { }
- void EnterCombat(Unit* /*who*/) override
+ struct npc_tortured_riflemanAI : public npc_gauntlet_trash
{
- _events.ScheduleEvent(EVENT_SHOOT, 1); /// @todo adjust timers
- _events.ScheduleEvent(EVENT_CURSED_ARROW, 7000);
- _events.ScheduleEvent(EVENT_FROST_TRAP, 10000);
- _events.ScheduleEvent(EVENT_ICE_SHOT, 15000);
- }
+ npc_tortured_riflemanAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_SHOOT, 1);
+ _events.ScheduleEvent(EVENT_CURSED_ARROW, 7000);
+ _events.ScheduleEvent(EVENT_FROST_TRAP, 10000);
+ _events.ScheduleEvent(EVENT_ICE_SHOT, 15000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_SHOOT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_SHOOT);
+ _events.ScheduleEvent(EVENT_SHOOT, 2000);
+ break;
+ case EVENT_CURSED_ARROW:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_CURSED_ARROW);
+ _events.ScheduleEvent(EVENT_CURSED_ARROW, 10000);
+ break;
+ case EVENT_FROST_TRAP:
+ DoCast(me, SPELL_FROST_TRAP);
+ _events.ScheduleEvent(EVENT_FROST_TRAP, 30000);
+ break;
+ case EVENT_ICE_SHOT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true))
+ DoCast(target, SPELL_ICE_SHOT);
+ _events.ScheduleEvent(EVENT_ICE_SHOT, 15000);
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
{
- if (!UpdateVictim())
- return;
-
- _events.Update(diff);
-
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
-
- switch (_events.ExecuteEvent())
- {
- case EVENT_SHOOT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_SHOOT);
- _events.ScheduleEvent(EVENT_SHOOT, 2000);
- break;
- case EVENT_CURSED_ARROW:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_CURSED_ARROW);
- _events.ScheduleEvent(EVENT_CURSED_ARROW, 10000);
- break;
- case EVENT_FROST_TRAP:
- DoCast(SPELL_FROST_TRAP);
- _events.ScheduleEvent(EVENT_FROST_TRAP, 30000);
- break;
- case EVENT_ICE_SHOT:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_ICE_SHOT);
- _events.ScheduleEvent(EVENT_ICE_SHOT, 15000);
- break;
- }
- DoMeleeAttackIfReady();
+ return GetHallsOfReflectionAI<npc_tortured_riflemanAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_tortured_riflemanAI>(creature);
- }
};
-
-enum GeneralEvents
+enum FrostswornGeneral
{
- //General
+ // General
EVENT_SHIELD = 1,
EVENT_SPIKE = 2,
EVENT_CLONE = 3,
@@ -1575,554 +1814,652 @@ enum GeneralEvents
SAY_AGGRO = 0,
SAY_DEATH = 1,
- SPELL_SHIELD_THROWN = 69222, // 73076 on hc
- SPELL_SPIKE = 69184, // 70399 on hc
- SPELL_CLONE_NAME = 57507,
- SPELL_CLONE_MODEL = 45204,
+ SPELL_SHIELD_THROWN = 69222,
+ SPELL_SPIKE = 69184,
+ SPELL_CLONE = 69828,
+ SPELL_GHOST_VISUAL = 69861,
// Reflection
EVENT_BALEFUL_STRIKE = 1,
- SPELL_BALEFUL_STRIKE = 69933, // 70400 on hc
- SPELL_SPIRIT_BURST = 69900, // 73046 on hc
+ SPELL_BALEFUL_STRIKE = 69933,
+ SPELL_SPIRIT_BURST = 69900
};
-class npc_frostworn_general : public CreatureScript
+class npc_frostsworn_general : public CreatureScript
{
-public:
- npc_frostworn_general() : CreatureScript("npc_frostworn_general") { }
+ public:
+ npc_frostsworn_general() : CreatureScript("npc_frostsworn_general") { }
- struct npc_frostworn_generalAI : public ScriptedAI
- {
- npc_frostworn_generalAI(Creature* creature) : ScriptedAI(creature)
+ struct npc_frostsworn_generalAI : public ScriptedAI
{
- _instance = me->GetInstanceScript();
- Reset();
- }
+ npc_frostsworn_generalAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = creature->GetInstanceScript();
+ }
- InstanceScript* _instance;
- EventMap _events;
+ void Reset() override
+ {
+ _events.Reset();
+ _instance->SetData(DATA_FROSTSWORN_GENERAL, NOT_STARTED);
+ }
- void Reset() override
- {
- _events.Reset();
- _instance->SetData(DATA_FROSWORN_EVENT, NOT_STARTED);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ _events.Reset();
+ _instance->SetData(DATA_FROSTSWORN_GENERAL, DONE);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
- _instance->SetData(DATA_FROSWORN_EVENT, DONE);
- }
+ void EnterCombat(Unit* /*victim*/) override
+ {
+ Talk(SAY_AGGRO);
+ DoZoneInCombat();
+ _events.ScheduleEvent(EVENT_SHIELD, 5000);
+ _events.ScheduleEvent(EVENT_SPIKE, 14000);
+ _events.ScheduleEvent(EVENT_CLONE, 22000);
+ _instance->SetData(DATA_FROSTSWORN_GENERAL, IN_PROGRESS);
+ }
- void EnterCombat(Unit* /*victim*/) override
- {
- Talk(SAY_AGGRO);
- _events.ScheduleEvent(EVENT_SHIELD, 5000);
- _events.ScheduleEvent(EVENT_SPIKE, 14000);
- _events.ScheduleEvent(EVENT_CLONE, 22000);
- _instance->SetData(DATA_FROSWORN_EVENT, IN_PROGRESS);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ _events.Update(diff);
- _events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ while (uint32 event = _events.ExecuteEvent())
+ {
+ switch (event)
+ {
+ case EVENT_SHIELD:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
+ DoCast(target, SPELL_SHIELD_THROWN);
+ _events.ScheduleEvent(EVENT_SHIELD, urand(8000, 12000));
+ break;
+ case EVENT_SPIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
+ DoCast(target, SPELL_SPIKE);
+ _events.ScheduleEvent(EVENT_SPIKE, urand(15000, 20000));
+ break;
+ case EVENT_CLONE:
+ SummonClones();
+ _events.ScheduleEvent(EVENT_CLONE, 60000);
+ break;
+ default:
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
- while (uint32 event = _events.ExecuteEvent())
+ void SummonClones()
{
- switch (event)
+ std::list<Unit*> playerList;
+ SelectTargetList(playerList, 5, SELECT_TARGET_TOPAGGRO, 0.0f, true);
+ for (Unit* target : playerList)
{
- case EVENT_SHIELD:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_SHIELD_THROWN);
- _events.ScheduleEvent(EVENT_SHIELD, urand(8000, 12000));
- break;
- case EVENT_SPIKE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_SPIKE);
- _events.ScheduleEvent(EVENT_SPIKE, urand(15000, 20000));
- break;
- case EVENT_CLONE:
- SummonClones();
- _events.ScheduleEvent(EVENT_CLONE, 60000);
- break;
+ if (Creature* reflection = me->SummonCreature(NPC_REFLECTION, *target, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000))
+ {
+ target->CastSpell(reflection, SPELL_CLONE, true);
+ target->CastSpell(reflection, SPELL_GHOST_VISUAL, true);
+ reflection->AI()->AttackStart(target);
+ }
}
}
- DoMeleeAttackIfReady();
- }
- void SummonClones()
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
{
- std::list<Unit *> playerList;
- SelectTargetList(playerList, 5, SELECT_TARGET_TOPAGGRO, 0, true);
- for (std::list<Unit*>::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
- {
- Unit* temp = (*itr);
- Creature* reflection = me->SummonCreature(NPC_REFLECTION, temp->GetPositionX(), temp->GetPositionY(), temp->GetPositionZ(), temp->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000);
- reflection->SetName(temp->GetName());
- temp->CastSpell(reflection, SPELL_CLONE_NAME, true);
- temp->CastSpell(reflection, SPELL_CLONE_MODEL, true);
- reflection->setFaction(me->getFaction());
- reflection->AI()->AttackStart(temp);
- }
+ return GetHallsOfReflectionAI<npc_frostsworn_generalAI>(creature);
}
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_frostworn_generalAI>(creature);
- }
};
class npc_spiritual_reflection : public CreatureScript
{
-public:
- npc_spiritual_reflection() : CreatureScript("npc_spiritual_reflection") { }
+ public:
+ npc_spiritual_reflection() : CreatureScript("npc_spiritual_reflection") { }
- struct npc_spiritual_reflectionAI : public ScriptedAI
- {
- npc_spiritual_reflectionAI(Creature *creature) : ScriptedAI(creature)
+ struct npc_spiritual_reflectionAI : public ScriptedAI
{
- Reset();
- }
+ npc_spiritual_reflectionAI(Creature *creature) : ScriptedAI(creature) { }
- EventMap _events;
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void Reset() override
- {
- _events.Reset();
- }
+ void EnterCombat(Unit* /*victim*/) override
+ {
+ _events.ScheduleEvent(EVENT_BALEFUL_STRIKE, 3000);
+ }
- void EnterCombat(Unit* /*victim*/) override
- {
- _events.ScheduleEvent(EVENT_BALEFUL_STRIKE, 3000);
- }
+ void JustDied(Unit* /*killer*/) override
+ {
+ DoCastAOE(SPELL_SPIRIT_BURST);
+ }
- void JustDied(Unit* killer) override
- {
- DoCast(killer, SPELL_SPIRIT_BURST);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ _events.Update(diff);
- _events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_BALEFUL_STRIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 8.0f, true))
+ DoCast(target, SPELL_BALEFUL_STRIKE);
+ _events.ScheduleEvent(EVENT_BALEFUL_STRIKE, urand(3000, 8000));
+ break;
+ default:
+ break;
+ }
- switch (_events.ExecuteEvent())
- {
- case EVENT_BALEFUL_STRIKE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_BALEFUL_STRIKE);
- _events.ScheduleEvent(EVENT_BALEFUL_STRIKE, urand(3000, 8000));
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
- }
- };
+ private:
+ EventMap _events;
+ };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_spiritual_reflectionAI(creature);
- }
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_spiritual_reflectionAI(creature);
+ }
};
+// 5689
class at_hor_intro_start : public AreaTriggerScript
{
-public:
- at_hor_intro_start() : AreaTriggerScript("at_hor_intro_start") { }
+ public:
+ at_hor_intro_start() : AreaTriggerScript("at_hor_intro_start") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
- {
- InstanceScript* _instance = player->GetInstanceScript();
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
+ {
+ if (player->IsGameMaster())
+ return true;
- if (player->IsGameMaster())
- return true;
+ InstanceScript* _instance = player->GetInstanceScript();
- if (_instance->GetData(DATA_INTRO_EVENT) == NOT_STARTED)
- _instance->SetData(DATA_INTRO_EVENT, IN_PROGRESS);
+ if (_instance->GetData(DATA_INTRO_EVENT) == NOT_STARTED)
+ _instance->SetData(DATA_INTRO_EVENT, IN_PROGRESS);
- return true;
- }
+ return true;
+ }
};
class at_hor_waves_restarter : public AreaTriggerScript
{
-public:
- at_hor_waves_restarter() : AreaTriggerScript("at_hor_waves_restarter") { }
+ public:
+ at_hor_waves_restarter() : AreaTriggerScript("at_hor_waves_restarter") { }
- bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
- {
- InstanceScript* _instance = player->GetInstanceScript();
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
+ {
+ if (player->IsGameMaster())
+ return true;
- if (player->IsGameMaster())
- return true;
+ InstanceScript* _instance = player->GetInstanceScript();
+
+ if (_instance->GetData(DATA_WAVE_COUNT))
+ return true;
- if (_instance->GetData(DATA_WAVE_COUNT))
+ if (_instance->GetData(DATA_INTRO_EVENT) == DONE && _instance->GetBossState(DATA_MARWYN) != DONE)
+ {
+ _instance->ProcessEvent(0, EVENT_SPAWN_WAVES);
+
+ if (Creature* falric = player->GetCreature(*player, _instance->GetData64(DATA_FALRIC)))
+ {
+ falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true);
+ falric->SetVisible(true);
+ }
+ if (Creature* marwyn = player->GetCreature(*player, _instance->GetData64(DATA_MARWYN)))
+ {
+ marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true);
+ marwyn->SetVisible(true);
+ }
+ }
return true;
+ }
+};
- if (_instance->GetData(DATA_INTRO_EVENT) == DONE && _instance->GetBossState(DATA_MARWYN_EVENT) != DONE)
+// 5740
+class at_hor_impenetrable_door : public AreaTriggerScript
+{
+ public:
+ at_hor_impenetrable_door() : AreaTriggerScript("at_hor_impenetrable_door") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*at*/) override
{
- _instance->ProcessEvent(0, EVENT_SPAWN_WAVES);
+ if (player->IsGameMaster())
+ return true;
- if (Creature* falric = player->GetCreature(*player, _instance->GetData64(DATA_FALRIC_EVENT)))
- {
- falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true);
- falric->SetVisible(true);
- }
- if (Creature* marwyn = player->GetCreature(*player, _instance->GetData64(DATA_MARWYN_EVENT)))
- {
- marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true);
- marwyn->SetVisible(true);
- }
+ InstanceScript* _instance = player->GetInstanceScript();
+ if (_instance->GetBossState(DATA_MARWYN) == DONE)
+ return true;
+
+ /// return false to handle teleport by db
+ return false;
}
- return true;
- }
};
-class at_shadow_throne : public AreaTriggerScript
+// 5605
+class at_hor_shadow_throne : public AreaTriggerScript
{
-public:
- at_shadow_throne() : AreaTriggerScript("at_shadow_throne") { }
+ public:
+ at_hor_shadow_throne() : AreaTriggerScript("at_hor_shadow_throne") { }
- bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
- {
- InstanceScript* _instance = player->GetInstanceScript();
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*at*/) override
+ {
+ if (player->IsGameMaster())
+ return true;
+
+ InstanceScript* _instance = player->GetInstanceScript();
+
+ if (_instance->GetBossState(DATA_THE_LICH_KING_ESCAPE) == NOT_STARTED)
+ _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, IN_PROGRESS);
- if (player->IsGameMaster())
return true;
+ }
+};
- if (_instance->GetData(DATA_ESCAPE_EVENT) == NOT_STARTED)
- _instance->SetData(DATA_ESCAPE_EVENT, IN_PROGRESS);
+enum EscapeEvents
+{
+ // Raging Ghoul
+ EVENT_RAGING_GHOUL_JUMP = 1,
- return true;
- }
+ // Risen Witch Doctor
+ EVENT_RISEN_WITCH_DOCTOR_CURSE,
+ EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT,
+ EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT_VOLLEY,
+
+ // Lumbering Abomination
+ EVENT_LUMBERING_ABOMINATION_VOMIT_SPRAY,
+ EVENT_LUMBERING_ABOMINATION_CLEAVE
};
-class npc_raging_ghoul : public CreatureScript
+namespace hor
{
-public:
- npc_raging_ghoul() : CreatureScript("npc_raging_ghoul") { }
- struct npc_raging_ghoulAI : public ScriptedAI
- {
- npc_raging_ghoulAI(Creature* creature) : ScriptedAI(creature)
+class StartMovementEvent : public BasicEvent
+{
+ public:
+ StartMovementEvent(Creature* owner) : _owner(owner) { }
+
+ bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
{
- _instance = me->GetInstanceScript();
+ _owner->SetReactState(REACT_AGGRESSIVE);
+ if (Unit* target = _owner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ _owner->AI()->AttackStart(target);
+ return true;
}
- InstanceScript* _instance;
- uint32 _emergeTimer;
- bool _doEmerge;
- bool _doJump;
- uint64 _leaderGUID;
+ private:
+ Creature* _owner;
+};
- void Reset() override
- {
- _emergeTimer = 4000;
- _doEmerge = false;
- _doJump = false;
- if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS)
- _instance->SetData(DATA_SUMMONS, 1);
+} // namespace hor
- }
+struct npc_escape_event_trash : public ScriptedAI
+{
+ npc_escape_event_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
- void IsSummonedBy(Unit*) override
- {
- DoCast(me, SPELL_EMERGE_VISUAL);
- }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void JustDied(Unit* /*killer*/) override
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (_instance->GetBossState(DATA_THE_LICH_KING_ESCAPE) == FAIL || _instance->GetBossState(DATA_THE_LICH_KING_ESCAPE) == NOT_STARTED)
+ me->DespawnOrUnsummon();
+ }
+
+ void IsSummonedBy(Unit* /*summoner*/) override
+ {
+ DoZoneInCombat(me, 0.0f);
+ if (Creature* leader = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER)))
{
- _instance->SetData(DATA_SUMMONS, 0);
+ me->SetInCombatWith(leader);
+ leader->SetInCombatWith(me);
+ me->AddThreat(leader, 0.0f);
}
+ }
- void AttackStart(Unit* who) override
+protected:
+ EventMap _events;
+ InstanceScript* _instance;
+};
+
+class npc_raging_ghoul : public CreatureScript
+{
+ public:
+ npc_raging_ghoul() : CreatureScript("npc_raging_ghoul") { }
+
+ struct npc_raging_ghoulAI : public npc_escape_event_trash
{
- if (!who)
- return;
+ npc_raging_ghoulAI(Creature* creature) : npc_escape_event_trash(creature) { }
- if (!_doEmerge)
- return;
+ void Reset() override
+ {
+ npc_escape_event_trash::Reset();
+ _events.ScheduleEvent(EVENT_RAGING_GHOUL_JUMP, 5000);
+ }
- ScriptedAI::AttackStart(who);
- }
+ void IsSummonedBy(Unit* summoner) override
+ {
+ me->CastSpell(me, SPELL_RAGING_GHOUL_SPAWN, true);
+ me->SetReactState(REACT_PASSIVE);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
+ me->m_Events.AddEvent(new hor::StartMovementEvent(me), me->m_Events.CalculateTime(5000));
- void UpdateAI(uint32 diff) override
- {
- if (!_instance)
- return;
+ npc_escape_event_trash::IsSummonedBy(summoner);
+ }
- if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS)
+ void UpdateAI(uint32 diff) override
{
- _leaderGUID = _instance->GetData64(DATA_ESCAPE_LEADER);
- Creature* leader = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER));
+ npc_escape_event_trash::UpdateAI(diff);
+
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
- if (_doEmerge != true)
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (_events.ExecuteEvent())
{
- if (_emergeTimer < diff)
- {
- _doEmerge = true;
- if (leader)
+ case EVENT_RAGING_GHOUL_JUMP:
+ if (Unit* victim = me->GetVictim())
{
- DoResetThreat();
- me->GetMotionMaster()->MoveIdle();
- me->GetMotionMaster()->MoveChase(leader);
+ if (me->IsInRange(victim, 5.0f, 30.0f))
+ {
+ DoCast(victim, SPELL_GHOUL_JUMP);
+ return;
+ }
}
- }
- else
- _emergeTimer -= diff;
+ _events.ScheduleEvent(EVENT_RAGING_GHOUL_JUMP, 500);
+ break;
+ default:
+ break;
}
- if (me->Attack(leader,true))/*(Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 150.0f))*/
- {
- if (!_doJump && me->IsWithinDistInMap(leader, 30.0f) && !me->IsWithinDistInMap(leader, 5.0f))
- {
- _doJump = true;
- DoCast(leader, SPELL_GHOUL_JUMP);
- }
- }
+ DoMeleeAttackIfReady();
}
- else if (_instance->GetData(DATA_ESCAPE_EVENT) == FAIL || _instance->GetData(DATA_ESCAPE_EVENT) == NOT_STARTED)
- me->DespawnOrUnsummon();
- DoMeleeAttackIfReady();
- }
- };
+ };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_raging_ghoulAI>(creature);
- }
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_raging_ghoulAI>(creature);
+ }
};
class npc_risen_witch_doctor : public CreatureScript
{
-public:
- npc_risen_witch_doctor() : CreatureScript("npc_risen_witch_doctor") { }
+ public:
+ npc_risen_witch_doctor() : CreatureScript("npc_risen_witch_doctor") { }
- struct npc_risen_witch_doctorAI : public ScriptedAI
- {
- npc_risen_witch_doctorAI(Creature* creature) : ScriptedAI(creature)
+ struct npc_risen_witch_doctorAI : public npc_escape_event_trash
{
- _instance = me->GetInstanceScript();
- }
+ npc_risen_witch_doctorAI(Creature* creature) : npc_escape_event_trash(creature) { }
- InstanceScript* _instance;
- uint32 _emergeTimer;
- bool _doEmerge;
- uint64 _leaderGUID;
- uint32 _boltTimer;
- uint32 _boltVolleyTimer;
- uint32 _curseTimer;
+ void Reset() override
+ {
+ npc_escape_event_trash::Reset();
+ _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT, 6000);
+ _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT_VOLLEY, 15000);
+ _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_CURSE, 7000);
+ }
- void Reset() override
- {
- _emergeTimer = 5000;
- _boltTimer = 6000;
- _boltVolleyTimer = 15000;
- _curseTimer = 7000;
- _doEmerge = false;
- if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS)
- _instance->SetData(DATA_SUMMONS, 1);
- }
+ void IsSummonedBy(Unit* summoner) override
+ {
+ me->CastSpell(me, SPELL_RISEN_WITCH_DOCTOR_SPAWN, true);
+ me->SetReactState(REACT_PASSIVE);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
+ me->m_Events.AddEvent(new hor::StartMovementEvent(me), me->m_Events.CalculateTime(5000));
- void IsSummonedBy(Unit*) override
- {
- DoCast(me, SPELL_EMERGE_VISUAL);
- DoZoneInCombat(me, 100.00f);
- }
+ npc_escape_event_trash::IsSummonedBy(summoner);
+ }
- void JustDied(Unit* /*killer*/) override
- {
- _instance->SetData(DATA_SUMMONS, 0);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ npc_escape_event_trash::UpdateAI(diff);
- void AttackStart(Unit* who) override
- {
- if (!who)
- return;
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
- if (_doEmerge == false)
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- ScriptedAI::AttackStart(who);
+ switch (_events.ExecuteEvent())
+ {
+ case EVENT_RISEN_WITCH_DOCTOR_CURSE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true))
+ DoCast(target, SPELL_CURSE_OF_DOOM);
+ _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_CURSE, urand(10000, 15000));
+ break;
+ case EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 20.0f, true))
+ DoCast(target, SPELL_SHADOW_BOLT);
+ _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT, urand(2000, 3000));
+ break;
+ case EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT_VOLLEY:
+ if (SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, true))
+ DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY);
+ _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT_VOLLEY, urand(15000, 22000));
+ break;
+ default:
+ break;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_risen_witch_doctorAI>(creature);
}
+};
+
+class npc_lumbering_abomination : public CreatureScript
+{
+ public:
+ npc_lumbering_abomination() : CreatureScript("npc_lumbering_abomination") { }
- void UpdateAI(uint32 diff) override
+ struct npc_lumbering_abominationAI : public npc_escape_event_trash
{
- if (!_instance)
- return;
+ npc_lumbering_abominationAI(Creature* creature) : npc_escape_event_trash(creature) { }
- if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS)
+ void Reset() override
{
- if (_doEmerge != true)
- {
- if (_emergeTimer < diff)
- {
- _doEmerge = true;
- _leaderGUID = _instance->GetData64(DATA_ESCAPE_LEADER);
+ npc_escape_event_trash::Reset();
+ _events.ScheduleEvent(EVENT_LUMBERING_ABOMINATION_VOMIT_SPRAY, 15000);
+ _events.ScheduleEvent(EVENT_LUMBERING_ABOMINATION_CLEAVE, 6000);
+ }
- if (Creature* leader = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER)))
- {
- DoResetThreat();
- me->GetMotionMaster()->MoveIdle();
- me->GetMotionMaster()->MoveChase(leader);
- }
- }
- else
- _emergeTimer -= diff;
- }
+ void UpdateAI(uint32 diff) override
+ {
+ npc_escape_event_trash::UpdateAI(diff);
- if (_curseTimer < diff)
- {
- if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM))
- DoCast(target, SPELL_COURSE_OF_DOOM);
- _curseTimer = urand(10000, 15000);
- }
- else
- _curseTimer -= diff;
+ if (!UpdateVictim())
+ return;
- if (_boltTimer < diff)
- {
- if (Unit *target = SelectTarget(SELECT_TARGET_TOPAGGRO))
- DoCast(target, SPELL_SHADOW_BOLT);
- _boltTimer = urand(2000, 3000);
- }
- else
- _boltTimer -= diff;
+ _events.Update(diff);
- if (_boltVolleyTimer < diff)
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ switch (_events.ExecuteEvent())
{
- if (Unit *target = SelectTarget(SELECT_TARGET_TOPAGGRO))
- DoCast(target, SPELL_SHADOW_BOLT_VOLLEY);
- _boltVolleyTimer = urand(15000, 22000);
+ case EVENT_LUMBERING_ABOMINATION_VOMIT_SPRAY:
+ DoCastVictim(SPELL_VOMIT_SPRAY);
+ _events.ScheduleEvent(EVENT_LUMBERING_ABOMINATION_VOMIT_SPRAY, urand(15000, 20000));
+ break;
+ case EVENT_LUMBERING_ABOMINATION_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ _events.ScheduleEvent(EVENT_LUMBERING_ABOMINATION_CLEAVE, urand(7000, 9000));
+ break;
+ default:
+ break;
}
- else
- _boltVolleyTimer -= diff;
+
+ DoMeleeAttackIfReady();
}
- else if (_instance->GetData(DATA_ESCAPE_EVENT) == FAIL || _instance->GetData(DATA_ESCAPE_EVENT) == NOT_STARTED)
- me->DespawnOrUnsummon();
- DoMeleeAttackIfReady();
- }
- };
+ };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_risen_witch_doctorAI>(creature);
- }
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfReflectionAI<npc_lumbering_abominationAI>(creature);
+ }
};
-
-class npc_lumbering_abomination : public CreatureScript
+// 72900 - Start Halls of Reflection Quest AE
+class spell_hor_start_halls_of_reflection_quest_ae : public SpellScriptLoader
{
-public:
- npc_lumbering_abomination() : CreatureScript("npc_lumbering_abomination") { }
+ public:
+ spell_hor_start_halls_of_reflection_quest_ae() : SpellScriptLoader("spell_hor_start_halls_of_reflection_quest_ae") { }
- struct npc_lumbering_abominationAI : public ScriptedAI
- {
- npc_lumbering_abominationAI(Creature* creature) : ScriptedAI(creature)
+ class spell_hor_start_halls_of_reflection_quest_ae_SpellScript : public SpellScript
{
- _instance = me->GetInstanceScript();
- }
+ PrepareSpellScript(spell_hor_start_halls_of_reflection_quest_ae_SpellScript);
+
+ void StartQuests(SpellEffIndex /*effIndex*/)
+ {
+ if (Player* target = GetHitPlayer())
+ {
+ // CanTakeQuest and CanAddQuest checks done in spell effect execution
+ if (target->GetTeam() == ALLIANCE)
+ target->CastSpell(target, SPELL_START_HALLS_OF_REFLECTION_QUEST_A, true);
+ else
+ target->CastSpell(target, SPELL_START_HALLS_OF_REFLECTION_QUEST_H, true);
+ }
+ }
- InstanceScript* _instance;
- uint64 _leaderGUID;
- bool _doWalk;
- uint32 _strikeTimer;
- uint32 _vomitTimer;
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_hor_start_halls_of_reflection_quest_ae_SpellScript::StartQuests, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
- void Reset() override
+ SpellScript* GetSpellScript() const override
{
- _doWalk = false;
- _vomitTimer = 15000;
- _strikeTimer = 6000;
- if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS)
- _instance->SetData(DATA_SUMMONS, 1);
+ return new spell_hor_start_halls_of_reflection_quest_ae_SpellScript();
}
+};
+
+// 70190 - Evasion
+class spell_hor_evasion : public SpellScriptLoader
+{
+ public:
+ spell_hor_evasion() : SpellScriptLoader("spell_hor_evasion") { }
+
+ class spell_hor_evasion_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_hor_evasion_SpellScript);
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void SetDest(SpellDestination& dest)
+ {
+ WorldObject* target = GetExplTargetWorldObject();
+ Position pos(*target);
+ Position home = GetCaster()->ToCreature()->GetHomePosition();
+
+ // prevent evasion outside the room
+ if (pos.IsInDist2d(&home, 15.0f))
+ return;
+
+ float angle = pos.GetAngle(&home);
+ float dist = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster());
+ target->MovePosition(pos, dist, angle);
+
+ dest.Relocate(pos);
+ }
+
+ void Register() override
+ {
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_hor_evasion_SpellScript::SetDest, EFFECT_0, TARGET_DEST_TARGET_RADIUS);
+ }
+ };
- void IsSummonedBy(Unit*) override
+ SpellScript* GetSpellScript() const override
{
- DoCast(me, SPELL_EMERGE_VISUAL);
- DoZoneInCombat(me, 100.00f);
+ return new spell_hor_evasion_SpellScript();
}
+};
+
+// 70017 - Gunship Cannon Fire
+class spell_hor_gunship_cannon_fire : public SpellScriptLoader
+{
+ public:
+ spell_hor_gunship_cannon_fire() : SpellScriptLoader("spell_hor_gunship_cannon_fire") { }
- void UpdateAI(uint32 diff) override
+ class spell_hor_gunship_cannon_fire_AuraScript : public AuraScript
{
- if (_instance->GetData(DATA_ESCAPE_EVENT) == IN_PROGRESS)
+ PrepareAuraScript(spell_hor_gunship_cannon_fire_AuraScript);
+
+ void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
- if (_doWalk != true)
+ if (!urand(0, 2))
{
- _doWalk = true;
- _leaderGUID = _instance->GetData64(DATA_ESCAPE_LEADER);
- if (Creature* leader = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_ESCAPE_LEADER)))
- {
- DoResetThreat();
- me->GetMotionMaster()->MoveIdle();
- me->GetMotionMaster()->MoveChase(leader);
- }
- }
- if (_strikeTimer < diff)
- {
- if (Unit *target = SelectTarget(SELECT_TARGET_TOPAGGRO))
- DoCast(target, SPELL_ABON_STRIKE);
- _strikeTimer = urand(7000, 9000);
+ if (GetTarget()->GetEntry() == NPC_GUNSHIP_CANNON_HORDE)
+ GetTarget()->CastSpell((Unit*)NULL, SPELL_GUNSHIP_CANNON_FIRE_MISSILE_HORDE, true);
+ else
+ GetTarget()->CastSpell((Unit*)NULL, SPELL_GUNSHIP_CANNON_FIRE_MISSILE_ALLIANCE, true);
}
- else
- _strikeTimer -= diff;
+ }
- if (_vomitTimer < diff)
- {
- if (Unit *target = SelectTarget(SELECT_TARGET_TOPAGGRO))
- DoCast(target, SPELL_VOMIT_SPRAY);
- _vomitTimer = urand(15000, 20000);
- }
- else
- _vomitTimer -= diff;
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_hor_gunship_cannon_fire_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
- else if (_instance->GetData(DATA_ESCAPE_EVENT) == FAIL || _instance->GetData(DATA_ESCAPE_EVENT) == NOT_STARTED)
- me->DespawnOrUnsummon();
- DoMeleeAttackIfReady();
- }
+ };
- void JustDied(Unit* /*killer*/) override
+ AuraScript* GetAuraScript() const override
{
- _instance->SetData(DATA_SUMMONS, 0);
+ return new spell_hor_gunship_cannon_fire_AuraScript();
}
-
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_lumbering_abominationAI>(creature);
- }
};
void AddSC_halls_of_reflection()
{
new at_hor_intro_start();
new at_hor_waves_restarter();
- new at_shadow_throne();
- new npc_jaina_or_sylvanas_hor();
+ new at_hor_impenetrable_door();
+ new at_hor_shadow_throne();
+ new npc_jaina_or_sylvanas_intro_hor();
new npc_jaina_or_sylvanas_escape_hor();
+ new npc_the_lich_king_escape_hor();
new npc_ghostly_priest();
new npc_phantom_mage();
new npc_phantom_hallucination();
new npc_shadowy_mercenary();
new npc_spectral_footman();
new npc_tortured_rifleman();
+ new npc_frostsworn_general();
+ new npc_spiritual_reflection();
new npc_raging_ghoul();
new npc_risen_witch_doctor();
new npc_lumbering_abomination();
- new npc_frostworn_general();
- new npc_spiritual_reflection();
+ new spell_hor_start_halls_of_reflection_quest_ae();
+ new spell_hor_evasion();
+ new spell_hor_gunship_cannon_fire();
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
index c4776c3cfcd..a05035f7b44 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h
@@ -15,170 +15,231 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DEF_HALLS_OF_REFLECTION_H
-#define DEF_HALLS_OF_REFLECTION_H
+#ifndef HALLS_OF_REFLECTION_H_
+#define HALLS_OF_REFLECTION_H_
#define HoRScriptName "instance_halls_of_reflection"
-#define MAX_ENCOUNTER 3
+
+uint32 const EncounterCount = 3;
/* Halls of Reflection encounters:
-0- Falric
-1- Marwyn
-2- The Lich King
+ 0 - Falric
+ 1 - Marwyn
+ 2 - The Lich King
*/
-enum Data
+enum DataTypes
{
- DATA_FALRIC_EVENT = 0,
- DATA_MARWYN_EVENT = 1,
- DATA_LICHKING_EVENT = 2,
+ DATA_FALRIC = 0,
+ DATA_MARWYN = 1,
+ DATA_THE_LICH_KING_ESCAPE = 2,
+
DATA_INTRO_EVENT = 3,
- DATA_FROSWORN_EVENT = 4,
+ DATA_FROSTSWORN_GENERAL = 4,
- DATA_WAVE_COUNT = 5,
- DATA_TEAM_IN_INSTANCE = 6,
- DATA_FROSTMOURNE = 7,
- DATA_FROSTWORN_DOOR = 8,
- DATA_ESCAPE_EVENT = 9,
+ DATA_KORELN_LORALEN = 5,
+ DATA_WAVE_COUNT = 6,
+ DATA_TEAM_IN_INSTANCE = 7,
+ DATA_FROSTMOURNE = 8,
+ DATA_IMPENETRABLE_DOOR = 9,
DATA_ESCAPE_LEADER = 10,
- DATA_SUMMONS = 11,
- DATA_ICEWALL = 12,
- DATA_CAVE_IN = 13
+ DATA_ICEWALL = 11,
+ DATA_ICEWALL_TARGET = 12,
+ DATA_GUNSHIP = 13
};
-enum Creatures
+enum CreatureIds
{
- NPC_JAINA_PART1 = 37221,
- NPC_SYLVANAS_PART1 = 37223,
- NPC_UTHER = 37225,
- NPC_LICH_KING_PART1 = 37226,
- NPC_LORALEN = 37779,
- NPC_KORELN = 37582,
-
- NPC_FALRIC = 38112,
- NPC_MARWYN = 38113,
- NPC_WAVE_MERCENARY = 38177,
- NPC_WAVE_FOOTMAN = 38173,
- NPC_WAVE_RIFLEMAN = 38176,
- NPC_WAVE_PRIEST = 38175,
- NPC_WAVE_MAGE = 38172,
-
- NPC_FROSTWORN_GENERAL = 36723,
- NPC_REFLECTION = 37068, // 37107 for tank only?
-
- NPC_JAINA_PART2 = 36955,
- NPC_SYLVANAS_PART2 = 37554,
- NPC_LICH_KING_PART2 = 36954,
- NPC_BARTLETT = 37182, // High Captain Justin Bartlett
- NPC_KORM = 37833, // Sky-Reaver Korm Blackscar
- NPC_ICE_WALL = 37014, // Ice Wall Target
-
- NPC_RAGING_GNOUL = 36940,
- NPC_RISEN_WITCH_DOCTOR = 36941,
- NPC_ABON = 37069
+ NPC_JAINA_INTRO = 37221,
+ NPC_SYLVANAS_INTRO = 37223,
+ NPC_UTHER = 37225,
+ NPC_THE_LICH_KING_INTRO = 37226,
+ NPC_KORELN = 37582,
+ NPC_LORALEN = 37779,
+ NPC_FROSTMOUNRE_ALTAR_BUNNY = 37704,
+
+ NPC_FALRIC = 38112,
+ NPC_MARWYN = 38113,
+ NPC_WAVE_MERCENARY = 38177,
+ NPC_WAVE_FOOTMAN = 38173,
+ NPC_WAVE_RIFLEMAN = 38176,
+ NPC_WAVE_PRIEST = 38175,
+ NPC_WAVE_MAGE = 38172,
+
+ NPC_FROSTSWORN_GENERAL = 36723,
+ NPC_REFLECTION = 37068, // 37107 for tank only?
+
+ NPC_JAINA_ESCAPE = 36955,
+ NPC_SYLVANAS_ESCAPE = 37554,
+ NPC_THE_LICH_KING_ESCAPE = 36954,
+ NPC_ICE_WALL_TARGET = 37014,
+
+ NPC_RAGING_GHOUL = 36940,
+ NPC_RISEN_WITCH_DOCTOR = 36941,
+ NPC_LUMBERING_ABOMINATION = 37069,
+
+ NPC_GUNSHIP_CANNON_HORDE = 37593,
+ NPC_JUSTIN_BARTLETT = 30344,
+ NPC_KORM_BLACKSCAR = 30824,
+
+ NPC_WORLD_TRIGGER = 22515
};
-enum GameObjects
+enum GameObjectIds
{
- GO_FROSTMOURNE = 202302,
- GO_ENTRANCE_DOOR = 201976,
- GO_FROSTWORN_DOOR = 197341,
- GO_ARTHAS_DOOR = 197342,
- //GO_ESCAPE_DOOR = 197343, // always open ?
-
- GO_ICE_WALL = 201385,
- GO_CAVE = 201596,
-
- GO_STAIRS_SKYBREAKER = 201709,
- GO_SKYBREAKER = 201598,
- GO_STAIRS_ORGRIM_HAMMER = 202211,
- GO_ORGRIM_HAMMER = 201599,
- GO_PORTAL = 202079,
-
- GO_CAPTAIN_CHEST_HORDE_NORMAL = 202212, //3145
- GO_CAPTAIN_CHEST_ALLIANCE_NORMAL = 201710, //30357
- GO_CAPTAIN_CHEST_HORDE_HEROIC = 202337, //3246
- GO_CAPTAIN_CHEST_ALLIANCE_HEROIC = 202336, //3333
+ GO_FROSTMOURNE = 202302,
+ GO_ENTRANCE_DOOR = 201976,
+ GO_IMPENETRABLE_DOOR = 197341,
+ GO_SHADOW_THRONE_DOOR = 197342,
+ GO_ESCAPE_DOOR = 197343, // always open ?
+
+ GO_ICE_WALL = 201385,
+ GO_CAVE_IN = 201596,
+
+ GO_THE_SKYBREAKER = 201598,
+ GO_ORGRIMS_HAMMER = 201599,
+ GO_THE_SKYBREAKER_STAIRS = 201709,
+ GO_ORGRIMS_HAMMER_STAIRS = 202211,
+ GO_PORTAL_TO_DALARAN = 195682,
+
+ GO_THE_CAPTAIN_CHEST_ALLIANCE_NORMAL = 201710,
+ GO_THE_CAPTAIN_CHEST_HORDE_NORMAL = 202212,
+ GO_THE_CAPTAIN_CHEST_ALLIANCE_HEROIC = 202336,
+ GO_THE_CAPTAIN_CHEST_HORDE_HEROIC = 202337
};
-enum HorWorldStates
+enum Achievements
{
- WORLD_STATE_HOR_WAVES_ENABLED = 4884,
- WORLD_STATE_HOR_WAVE_COUNT = 4882,
+ ACHIEV_NOT_RETREATING_EVENT = 22615,
+ SPELL_ACHIEV_CHECK = 72830
};
// Common actions from Instance Script to Boss Script
enum Actions
{
- ACTION_ENTER_COMBAT,
- ACTION_START_ESCAPING,
- ACTION_WALL_BROKEN
+ ACTION_ENTER_COMBAT = -668001,
+ ACTION_START_PREFIGHT = -668002,
+ ACTION_WALL_BROKEN = -668003,
+ ACTION_GUNSHIP_ARRIVAL = -668004,
+ ACTION_GUNSHIP_ARRIVAL_2 = -668005
};
-enum TrashGeneralSpells
+enum InstanceEvents
{
- // General spells
- SPELL_WELL_OF_SOULS = 72630, // cast when spawn(become visible)
- SPELL_SPIRIT_ACTIVATE = 72130, // cast when unit activates
+ EVENT_SPAWN_WAVES = 1,
+ EVENT_NEXT_WAVE = 2,
+ EVENT_DO_WIPE = 3,
+ EVENT_ADD_WAVE = 4,
+ EVENT_SPAWN_ESCAPE_EVENT = 5
};
-enum InstanceEvents
+enum InstanceEventIds
{
- EVENT_SPAWN_WAVES = 1,
- EVENT_NEXT_WAVE = 2,
- EVENT_DO_WIPE = 3,
- EVENT_ADD_WAVE = 4,
+ EVENT_GUNSHIP_ARRIVAL = 22709,
+ EVENT_GUNSHIP_ARRIVAL_2 = 22714,
+ EVENT_ICE_WALL_SUMMONED = 22795
};
-// Base class for FALRIC and MARWYN
-// handled the summonList and the notification events to/from the InstanceScript
-struct boss_horAI : ScriptedAI
+enum InstanceSpells
{
- boss_horAI(Creature* creature) : ScriptedAI(creature), summons(creature)
- {
- instance = me->GetInstanceScript();
- }
+ // Trash
+ SPELL_WELL_OF_SOULS = 72630, // cast when spawn (become visible)
+ SPELL_SPIRIT_ACTIVATE = 72130, // cast when unit activates
+
+ // Start Quests
+ SPELL_START_HALLS_OF_REFLECTION_QUEST_A = 71351,
+ SPELL_START_HALLS_OF_REFLECTION_QUEST_H = 71542,
+ SPELL_START_HALLS_OF_REFLECTION_QUEST_AE = 72900,
+
+ // Quest Credits
+ SPELL_CREDIT_FINDING_SYLVANAS = 71536,
+ SPELL_CREDIT_FINDING_JAINA = 71538,
+ SPELL_CREDIT_ESCAPING_ARTHAS = 71352,
+
+ // Gunship
+ SPELL_GUNSHIP_CANNON_FIRE = 70017,
+ SPELL_GUNSHIP_CANNON_FIRE_MISSILE_ALLIANCE = 70021,
+ SPELL_GUNSHIP_CANNON_FIRE_MISSILE_HORDE = 70246
+};
- InstanceScript* instance;
- EventMap events;
- SummonList summons;
+enum InstanceWorldStates
+{
+ WORLD_STATE_HOR_WAVES_ENABLED = 4884,
+ WORLD_STATE_HOR_WAVE_COUNT = 4882
+};
+
+enum InstanceYells
+{
+ SAY_CAPTAIN_FIRE = 0,
+ SAY_CAPTAIN_FINAL = 1
+};
+
+// Base class for FALRIC and MARWYN
+struct boss_horAI : BossAI
+{
+ boss_horAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId) { }
- void Reset()
+ void Reset() override
{
- events.Reset();
+ _Reset();
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_PASSIVE);
if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED)
- instance->ProcessEvent(0, EVENT_DO_WIPE);
+ instance->ProcessEvent(NULL, EVENT_DO_WIPE);
}
- void DoAction(int32 actionID)
+ void DoAction(int32 actionId) override
{
- switch (actionID)
+ switch (actionId)
{
- case ACTION_ENTER_COMBAT: // called by InstanceScript when boss shall enter in combat.
+ case ACTION_ENTER_COMBAT: // called by InstanceScript when boss shall enter in combat.
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->SetReactState(REACT_AGGRESSIVE);
-
- if (Unit* unit = me->SelectNearestTarget())
- AttackStart(unit);
-
- DoZoneInCombat();
+ DoZoneInCombat(me, 150.0f);
+ break;
+ default:
break;
}
}
- void JustSummoned(Creature* summoned)
+ void JustSummoned(Creature* summon) override
{
- summons.Summon(summoned);
+ summons.Summon(summon);
}
};
+class GameObjectDeleteDelayEvent : public BasicEvent
+{
+ public:
+ GameObjectDeleteDelayEvent(Unit* owner, uint64 gameObjectGUID) : _owner(owner), _gameObjectGUID(gameObjectGUID) { }
+
+ void DeleteGameObject()
+ {
+ if (GameObject* go = ObjectAccessor::GetGameObject(*_owner, _gameObjectGUID))
+ go->Delete();
+ }
+
+ bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
+ {
+ DeleteGameObject();
+ return true;
+ }
+
+ void Abort(uint64 /*execTime*/) override
+ {
+ DeleteGameObject();
+ }
+
+ private:
+ Unit* _owner;
+ uint64 _gameObjectGUID;
+};
+
template<class AI>
AI* GetHallsOfReflectionAI(Creature* creature)
{
return GetInstanceAI<AI>(creature, HoRScriptName);
}
-#endif
+#endif // HALLS_OF_REFLECTION_H_
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
index ab5168dd34a..6f33e80b92b 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
@@ -19,590 +19,792 @@
#include "ScriptedCreature.h"
#include "InstanceScript.h"
#include "Player.h"
+#include "Transport.h"
#include "WorldPacket.h"
#include "halls_of_reflection.h"
-Position const JainaSpawnPos = {5236.659f, 1929.894f, 707.7781f, 0.8726646f}; // Jaina Spawn Position
-Position const SylvanasSpawnPos = {5236.667f, 1929.906f, 707.7781f, 0.8377581f}; // Sylvanas Spawn Position
-Position const GeneralSpawnPos = {5415.538f, 2117.842f, 707.7781f, 3.944444f}; // Frostsworn General
-Position const JainaSpawnPos2 = {5549.011f, 2257.041f, 733.0120f, 1.153993f}; // Jaina Spawn Position 2
-Position const SylvanasSpawnPos2 = {5549.011f, 2257.041f, 733.0120f, 1.153993f}; // Sylvanas Spawn Position 2
+Position const JainaSpawnPos = { 5236.659f, 1929.894f, 707.7781f, 0.8726646f }; // Jaina Spawn Position
+Position const SylvanasSpawnPos = { 5236.667f, 1929.906f, 707.7781f, 0.8377581f }; // Sylvanas Spawn Position (sniffed)
+Position const JainaSpawnPos2 = { 5549.011f, 2257.041f, 733.0120f, 1.153993f }; // Jaina Spawn Position 2
+Position const SylvanasSpawnPos2 = { 5549.29f, 2257.353f, 733.0943f, 0.8901179f }; // Sylvanas Spawn Position 2 (sniffed)
+Position const KorelnOrLoralenSpawnPos = { 5232.68f, 1931.46f, 707.7781f, 0.8377581f };
+
+Position const TheLichKingEscapePosition[] =
+{
+ { 5557.017f, 2266.103f, 733.0943f, 3.892084f }, // 0 - Spawn (Horde)
+ { 5552.733f, 2262.718f, 733.0110f, 4.009696f } // 1 - Spawn (Alliance)
+};
Position const SpawnPos[] =
{
- {5309.577f, 2042.668f, 707.7781f, 4.694936f},
- {5295.885f, 2040.342f, 707.7781f, 5.078908f},
- {5340.836f, 1992.458f, 707.7781f, 2.757620f},
- {5325.072f, 1977.597f, 707.7781f, 2.076942f},
- {5277.365f, 1993.229f, 707.7781f, 0.401426f},
- {5275.479f, 2001.135f, 707.7781f, 0.174533f},
- {5302.448f, 2042.222f, 707.7781f, 4.904375f},
- {5343.293f, 1999.384f, 707.7781f, 2.914700f},
- {5295.635f, 1973.757f, 707.7781f, 1.186824f},
- {5311.031f, 1972.229f, 707.7781f, 1.640610f},
- {5275.076f, 2008.724f, 707.7781f, 6.213372f},
- {5316.701f, 2041.550f, 707.7781f, 4.502949f},
- {5344.150f, 2007.168f, 707.7781f, 3.159046f},
- {5319.158f, 1973.998f, 707.7781f, 1.919862f},
- {5302.247f, 1972.415f, 707.7781f, 1.378810f},
- {5277.739f, 2016.882f, 707.7781f, 5.969026f},
- {5322.964f, 2040.288f, 707.7781f, 4.345870f},
- {5343.467f, 2015.951f, 707.7781f, 3.490659f},
- {5313.820f, 1978.146f, 707.7781f, 1.745329f},
- {5279.649f, 2004.656f, 707.7781f, 0.069814f},
- {5306.057f, 2037.002f, 707.7781f, 4.817109f},
- {5337.865f, 2003.403f, 707.7781f, 2.984513f},
- {5299.434f, 1979.009f, 707.7781f, 1.239184f},
- {5312.752f, 2037.122f, 707.7781f, 4.590216f},
- {5335.724f, 1996.859f, 707.7781f, 2.740167f},
- {5280.632f, 2012.156f, 707.7781f, 6.056293f},
- {5320.369f, 1980.125f, 707.7781f, 2.007129f},
- {5306.572f, 1977.474f, 707.7781f, 1.500983f},
- {5336.599f, 2017.278f, 707.7781f, 3.473205f},
- {5282.897f, 2019.597f, 707.7781f, 5.881760f},
- {5318.704f, 2036.108f, 707.7781f, 4.223697f},
- {5280.513f, 1997.842f, 707.7781f, 0.296706f},
- {5337.833f, 2010.057f, 707.7781f, 3.228859f},
- {5299.250f, 2035.998f, 707.7781f, 5.026548f},
+ { 5309.577f, 2042.668f, 707.7781f, 4.694936f },
+ { 5295.885f, 2040.342f, 707.7781f, 5.078908f },
+ { 5340.836f, 1992.458f, 707.7781f, 2.757620f },
+ { 5325.072f, 1977.597f, 707.7781f, 2.076942f },
+ { 5277.365f, 1993.229f, 707.7781f, 0.401426f },
+ { 5275.479f, 2001.135f, 707.7781f, 0.174533f },
+ { 5302.448f, 2042.222f, 707.7781f, 4.904375f },
+ { 5343.293f, 1999.384f, 707.7781f, 2.914700f },
+ { 5295.635f, 1973.757f, 707.7781f, 1.186824f },
+ { 5311.031f, 1972.229f, 707.7781f, 1.640610f },
+ { 5275.076f, 2008.724f, 707.7781f, 6.213372f },
+ { 5316.701f, 2041.550f, 707.7781f, 4.502949f },
+ { 5344.150f, 2007.168f, 707.7781f, 3.159046f },
+ { 5319.158f, 1973.998f, 707.7781f, 1.919862f },
+ { 5302.247f, 1972.415f, 707.7781f, 1.378810f },
+ { 5277.739f, 2016.882f, 707.7781f, 5.969026f },
+ { 5322.964f, 2040.288f, 707.7781f, 4.345870f },
+ { 5343.467f, 2015.951f, 707.7781f, 3.490659f },
+ { 5313.820f, 1978.146f, 707.7781f, 1.745329f },
+ { 5279.649f, 2004.656f, 707.7781f, 0.069814f },
+ { 5306.057f, 2037.002f, 707.7781f, 4.817109f },
+ { 5337.865f, 2003.403f, 707.7781f, 2.984513f },
+ { 5299.434f, 1979.009f, 707.7781f, 1.239184f },
+ { 5312.752f, 2037.122f, 707.7781f, 4.590216f },
+ { 5335.724f, 1996.859f, 707.7781f, 2.740167f },
+ { 5280.632f, 2012.156f, 707.7781f, 6.056293f },
+ { 5320.369f, 1980.125f, 707.7781f, 2.007129f },
+ { 5306.572f, 1977.474f, 707.7781f, 1.500983f },
+ { 5336.599f, 2017.278f, 707.7781f, 3.473205f },
+ { 5282.897f, 2019.597f, 707.7781f, 5.881760f },
+ { 5318.704f, 2036.108f, 707.7781f, 4.223697f },
+ { 5280.513f, 1997.842f, 707.7781f, 0.296706f },
+ { 5337.833f, 2010.057f, 707.7781f, 3.228859f },
+ { 5299.250f, 2035.998f, 707.7781f, 5.026548f }
};
class instance_halls_of_reflection : public InstanceMapScript
{
-public:
- instance_halls_of_reflection() : InstanceMapScript("instance_halls_of_reflection", 668) { }
-
- struct instance_halls_of_reflection_InstanceMapScript : public InstanceScript
- {
- instance_halls_of_reflection_InstanceMapScript(Map* map) : InstanceScript(map) { }
+ public:
+ instance_halls_of_reflection() : InstanceMapScript(HoRScriptName, 668) { }
- void Initialize() override
+ struct instance_halls_of_reflection_InstanceMapScript : public InstanceScript
{
- SetBossNumber(MAX_ENCOUNTER);
- events.Reset();
-
- _falricGUID = 0;
- _marwynGUID = 0;
- _jainaOrSylvanasPart1GUID = 0;
- _jainaOrSylvanasPart2GUID = 0;
- _lichkingPart1GUID = 0;
- _frostwornGeneralGUID = 0;
-
- _frostmourneGUID = 0;
- _entranceDoorGUID = 0;
- _frostwornDoorGUID = 0;
- _arthasDoorGUID = 0;
- _escapeDoorGUID = 0;
- _caveGUID = 0;
-
- _teamInInstance = 0;
- _waveCount = 0;
- _introEvent = NOT_STARTED;
- _frostwornGeneral = NOT_STARTED;
- _escapeevent = NOT_STARTED;
- _mobsaticewall = 0;
- }
+ instance_halls_of_reflection_InstanceMapScript(Map* map) : InstanceScript(map)
+ {
+ SetBossNumber(EncounterCount);
+
+ JainaOrSylvanasIntroGUID = 0;
+ KorelnOrLoralenGUID = 0;
+ TheLichkingIntroGUID = 0;
+ FalricGUID = 0;
+ MarwynGUID = 0;
+ FrostmourneAltarBunnyGUID = 0;
+ FrostswornGeneralGUID = 0;
+ JainaOrSylvanasEscapeGUID = 0;
+ TheLichKingEscapeGUID = 0;
+
+ FrostmourneGUID = 0;
+ EntranceDoorGUID = 0;
+ ImpenetrableDoorGUID = 0;
+ ShadowThroneDoorGUID = 0;
+ CaveInGUID = 0;
+ GunshipGUID = 0;
+ CaptainsChestGUID = 0;
+ CaptainGUID = 0;
+ IcewallGUID = 0;
+ IcewallTargetGUID = 0;
+
+ _teamInInstance = 0;
+ _waveCount = 0;
+ _introState = NOT_STARTED;
+ _frostswornGeneralState = NOT_STARTED;
+
+ events.Reset();
+ }
- void OnPlayerEnter(Player* player) override
- {
- if (!_teamInInstance)
- _teamInInstance = player->GetTeam();
- }
+ void OnPlayerEnter(Player* player) override
+ {
+ if (!_teamInInstance)
+ _teamInInstance = player->GetTeam();
- void OnCreatureCreate(Creature* creature) override
- {
- if (!_teamInInstance)
+ if (GetBossState(DATA_MARWYN) == DONE)
+ {
+ SpawnGunship();
+
+ if (!JainaOrSylvanasEscapeGUID && GetBossState(DATA_THE_LICH_KING_ESCAPE) != DONE)
+ SpawnEscapeEvent();
+ }
+ }
+
+ void OnCreatureCreate(Creature* creature) override
{
- Map::PlayerList const& players = instance->GetPlayers();
- if (!players.isEmpty())
- if (Player* player = players.begin()->GetSource())
- _teamInInstance = player->GetTeam();
+ switch (creature->GetEntry())
+ {
+ case NPC_JAINA_INTRO:
+ case NPC_SYLVANAS_INTRO:
+ JainaOrSylvanasIntroGUID = creature->GetGUID();
+ break;
+ case NPC_KORELN:
+ case NPC_LORALEN:
+ if (GetBossState(DATA_MARWYN) != DONE)
+ creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ KorelnOrLoralenGUID = creature->GetGUID();
+ break;
+ case NPC_THE_LICH_KING_INTRO:
+ TheLichkingIntroGUID = creature->GetGUID();
+ break;
+ case NPC_FALRIC:
+ FalricGUID = creature->GetGUID();
+ break;
+ case NPC_MARWYN:
+ MarwynGUID = creature->GetGUID();
+ break;
+ case NPC_FROSTMOUNRE_ALTAR_BUNNY:
+ FrostmourneAltarBunnyGUID = creature->GetGUID();
+ break;
+ case NPC_FROSTSWORN_GENERAL:
+ FrostswornGeneralGUID = creature->GetGUID();
+ if (GetBossState(DATA_MARWYN) == DONE)
+ creature->SetPhaseMask(1, true);
+ break;
+ case NPC_JAINA_ESCAPE:
+ case NPC_SYLVANAS_ESCAPE:
+ JainaOrSylvanasEscapeGUID = creature->GetGUID();
+ break;
+ case NPC_THE_LICH_KING_ESCAPE:
+ TheLichKingEscapeGUID = creature->GetGUID();
+ break;
+ case NPC_JUSTIN_BARTLETT:
+ case NPC_KORM_BLACKSCAR:
+ CaptainGUID = creature->GetGUID();
+ break;
+ case NPC_WORLD_TRIGGER:
+ if (!creature->GetTransport())
+ break;
+ // no break
+ case NPC_GUNSHIP_CANNON_HORDE:
+ GunshipCannonGUIDs.insert(creature->GetGUID());
+ break;
+ case NPC_ICE_WALL_TARGET:
+ IcewallTargetGUID = creature->GetGUID();
+ break;
+ default:
+ break;
+ }
}
- switch (creature->GetEntry())
+ void OnCreatureRemove(Creature* creature) override
{
- case NPC_JAINA_PART1:
- case NPC_SYLVANAS_PART1:
- _jainaOrSylvanasPart1GUID = creature->GetGUID();
- break;
- case NPC_FALRIC:
- _falricGUID = creature->GetGUID();
- break;
- case NPC_MARWYN:
- _marwynGUID = creature->GetGUID();
- break;
- case NPC_FROSTWORN_GENERAL:
- _frostwornGeneralGUID = creature->GetGUID();
- if (GetBossState(DATA_MARWYN_EVENT) == DONE)
- if (Creature* general = instance->GetCreature(_frostwornGeneralGUID))
- general->SetPhaseMask(1, true);
- break;
- case NPC_JAINA_PART2:
- case NPC_SYLVANAS_PART2:
- _jainaOrSylvanasPart2GUID = creature->GetGUID();
- break;
+ switch (creature->GetEntry())
+ {
+ case NPC_WAVE_MERCENARY:
+ case NPC_WAVE_FOOTMAN:
+ case NPC_WAVE_RIFLEMAN:
+ case NPC_WAVE_PRIEST:
+ case NPC_WAVE_MAGE:
+ {
+ uint32 internalWaveId = creature->AI()->GetData(0);
+ waveGuidList[internalWaveId].erase(creature->GetGUID());
+ break;
+ }
+ case NPC_ICE_WALL_TARGET:
+ IcewallTargetGUID = 0;
+ break;
+ case NPC_WORLD_TRIGGER:
+ case NPC_GUNSHIP_CANNON_HORDE:
+ GunshipCannonGUIDs.erase(creature->GetGUID());
+ break;
+ default:
+ break;
+ }
}
- }
- void OnCreatureRemove(Creature* creature) override
- {
- switch (creature->GetEntry())
+ uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
{
- case NPC_WAVE_MERCENARY:
- case NPC_WAVE_FOOTMAN:
- case NPC_WAVE_RIFLEMAN:
- case NPC_WAVE_PRIEST:
- case NPC_WAVE_MAGE:
+ if (!_teamInInstance)
+ {
+ Map::PlayerList const& players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->GetSource())
+ _teamInInstance = player->GetTeam();
+ }
+
+ switch (entry)
{
- uint32 internalWaveId = creature->AI()->GetData(0);
- waveGuidList[internalWaveId].erase(creature->GetGUID());
- break;
+ case GO_THE_CAPTAIN_CHEST_ALLIANCE_NORMAL:
+ case GO_THE_CAPTAIN_CHEST_ALLIANCE_HEROIC:
+ case GO_THE_SKYBREAKER_STAIRS:
+ if (_teamInInstance == HORDE)
+ return 0;
+ break;
+ case GO_THE_CAPTAIN_CHEST_HORDE_NORMAL:
+ case GO_THE_CAPTAIN_CHEST_HORDE_HEROIC:
+ case GO_ORGRIMS_HAMMER_STAIRS:
+ if (_teamInInstance == ALLIANCE)
+ return 0;
+ break;
+ default:
+ break;
}
+
+ return entry;
}
- }
- void OnGameObjectCreate(GameObject* go) override
- {
- switch (go->GetEntry())
+ void OnGameObjectCreate(GameObject* go) override
{
- case GO_FROSTMOURNE:
- _frostmourneGUID = go->GetGUID();
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- HandleGameObject(0, false, go);
- if (GetData(DATA_INTRO_EVENT) == DONE)
- go->SetPhaseMask(2, true);
- break;
- case GO_ENTRANCE_DOOR:
- _entranceDoorGUID = go->GetGUID();
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- HandleGameObject(0, true, go);
- break;
- case GO_FROSTWORN_DOOR:
- _frostwornDoorGUID = go->GetGUID();
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- if (GetBossState(DATA_MARWYN_EVENT) == DONE)
- HandleGameObject(0, true, go);
- else
- HandleGameObject(0, false, go);
- break;
- case GO_ARTHAS_DOOR:
- _arthasDoorGUID = go->GetGUID();
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- if (GetData(DATA_FROSWORN_EVENT) == DONE)
- HandleGameObject(0, true, go);
- else
+ switch (go->GetEntry())
+ {
+ case GO_FROSTMOURNE:
+ FrostmourneGUID = go->GetGUID();
+ if (GetData(DATA_INTRO_EVENT) == DONE)
+ go->SetPhaseMask(2, true);
+ break;
+ case GO_ENTRANCE_DOOR:
+ EntranceDoorGUID = go->GetGUID();
+ break;
+ case GO_IMPENETRABLE_DOOR:
+ ImpenetrableDoorGUID = go->GetGUID();
+ HandleGameObject(0, GetBossState(DATA_MARWYN) == DONE, go);
+ break;
+ case GO_SHADOW_THRONE_DOOR:
+ ShadowThroneDoorGUID = go->GetGUID();
+ HandleGameObject(0, GetData(DATA_FROSTSWORN_GENERAL) == DONE, go);
+ break;
+ case GO_CAVE_IN:
+ CaveInGUID = go->GetGUID();
+ break;
+ case GO_THE_SKYBREAKER:
+ case GO_ORGRIMS_HAMMER:
+ GunshipGUID = go->GetGUID();
+ break;
+ case GO_THE_SKYBREAKER_STAIRS:
+ case GO_ORGRIMS_HAMMER_STAIRS:
+ if (GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE)
+ go->SetRespawnTime(DAY);
+ GunshipStairGUIDs.insert(go->GetGUID());
+ break;
+ case GO_THE_CAPTAIN_CHEST_ALLIANCE_NORMAL:
+ case GO_THE_CAPTAIN_CHEST_HORDE_NORMAL:
+ case GO_THE_CAPTAIN_CHEST_ALLIANCE_HEROIC:
+ case GO_THE_CAPTAIN_CHEST_HORDE_HEROIC:
+ CaptainsChestGUID = go->GetGUID();
+ break;
+ case GO_ICE_WALL:
HandleGameObject(0, false, go);
- break;
- case GO_CAVE:
- _caveGUID = go->GetGUID();
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- break;
+ IcewallGUID = go->GetGUID();
+ break;
+ default:
+ break;
+ }
}
- }
- void FillInitialWorldStates(WorldPacket& data) override
- {
- data << uint32(WORLD_STATE_HOR_WAVES_ENABLED) << uint32(0);
- data << uint32(WORLD_STATE_HOR_WAVE_COUNT) << uint32(0);
- }
-
- bool SetBossState(uint32 type, EncounterState state) override
- {
- if (!InstanceScript::SetBossState(type, state))
- return false;
-
- switch (type)
+ void OnGameObjectRemove(GameObject* go) override
{
- case DATA_FALRIC_EVENT:
- if (state == DONE)
- {
- ++_waveCount;
- events.ScheduleEvent(EVENT_NEXT_WAVE, 60000);
- }
- break;
- case DATA_MARWYN_EVENT:
- if (state == DONE)
- {
- HandleGameObject(_entranceDoorGUID, true);
- HandleGameObject(_frostwornDoorGUID, true);
- DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 0);
- if (Creature* general = instance->GetCreature(_frostwornGeneralGUID))
- general->SetPhaseMask(1, true);
- }
- break;
- case DATA_LICHKING_EVENT:
- default:
- break;
+ switch (go->GetEntry())
+ {
+ case GO_THE_SKYBREAKER_STAIRS:
+ case GO_ORGRIMS_HAMMER_STAIRS:
+ GunshipStairGUIDs.erase(go->GetGUID());
+ break;
+ default:
+ break;
+ }
}
- return true;
- }
+ void FillInitialWorldStates(WorldPacket& data) override
+ {
+ data << uint32(WORLD_STATE_HOR_WAVES_ENABLED) << uint32(_introState == DONE && GetBossState(DATA_MARWYN) != DONE);
+ data << uint32(WORLD_STATE_HOR_WAVE_COUNT) << uint32(_waveCount);
+ }
- void SetData(uint32 type, uint32 data) override
- {
- switch (type)
+ bool SetBossState(uint32 type, EncounterState state) override
{
- case DATA_INTRO_EVENT:
- if (data == IN_PROGRESS)
- {
- if (!_introEvent)
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ switch (type)
+ {
+ case DATA_FALRIC:
+ if (state == DONE)
{
- if (_teamInInstance == ALLIANCE)
- instance->SummonCreature(NPC_JAINA_PART1, JainaSpawnPos);
- else
- instance->SummonCreature(NPC_SYLVANAS_PART1, SylvanasSpawnPos);
+ ++_waveCount;
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 60000);
}
- }
- _introEvent = data;
- break;
- case DATA_WAVE_COUNT:
- if (_waveCount && data == NOT_STARTED)
- ProcessEvent(NULL, EVENT_DO_WIPE);
- break;
- case DATA_FROSWORN_EVENT:
- if (data == DONE)
- {
- HandleGameObject(_arthasDoorGUID, true);
- if (_teamInInstance == ALLIANCE)
- instance->SummonCreature(NPC_JAINA_PART2, JainaSpawnPos2);
- else
- instance->SummonCreature(NPC_SYLVANAS_PART2, SylvanasSpawnPos2);
- }
- _frostwornGeneral = data;
- break;
- case DATA_ESCAPE_EVENT:
- if (data == IN_PROGRESS)
- {
- if (!_escapeevent)
- if (Creature* jaina_or_sylvanas = instance->GetCreature(_jainaOrSylvanasPart2GUID))
- jaina_or_sylvanas->AI()->DoAction(ACTION_START_ESCAPING);
- }
- else if (data == NOT_STARTED)
- {
- if (Creature* jaina_or_sylvanas = instance->GetCreature(_jainaOrSylvanasPart2GUID))
- jaina_or_sylvanas->DespawnOrUnsummon(1);
- if (_teamInInstance == ALLIANCE)
- instance->SummonCreature(NPC_JAINA_PART2, JainaSpawnPos2);
- else
- instance->SummonCreature(NPC_SYLVANAS_PART2, SylvanasSpawnPos2);
- SetData(DATA_ESCAPE_EVENT,IN_PROGRESS);
- }
- _escapeevent = data;
- break;
- case DATA_SUMMONS:
- if (data == 0)
- {
- _mobsaticewall--;
- if (_mobsaticewall == 0)
+ break;
+ case DATA_MARWYN:
+ if (state == DONE)
{
- if (Creature* jaina_or_sylvanas = instance->GetCreature(_jainaOrSylvanasPart2GUID))
- jaina_or_sylvanas->AI()->DoAction(ACTION_WALL_BROKEN);
+ if (Creature* bunny = instance->GetCreature(FrostmourneAltarBunnyGUID))
+ bunny->CastSpell(bunny, SPELL_START_HALLS_OF_REFLECTION_QUEST_AE, true);
+
+ if (Creature* korelnOrLoralen = instance->GetCreature(KorelnOrLoralenGUID))
+ korelnOrLoralen->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+
+ HandleGameObject(EntranceDoorGUID, true);
+ HandleGameObject(ImpenetrableDoorGUID, true);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 0);
+ if (Creature* general = instance->GetCreature(FrostswornGeneralGUID))
+ general->SetPhaseMask(1, true);
+
+ SpawnGunship();
+ SpawnEscapeEvent();
}
- }
- else if (data == 1)
- _mobsaticewall++;
- break;
+ break;
+ case DATA_THE_LICH_KING_ESCAPE:
+ switch (state)
+ {
+ case NOT_STARTED:
+ break;
+ case IN_PROGRESS:
+ if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
+ jainaOrSylvanas->AI()->DoAction(ACTION_START_PREFIGHT);
+ break;
+ case DONE:
+ if (GameObject* chest = instance->GetGameObject(CaptainsChestGUID))
+ chest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE | GO_FLAG_NODESPAWN);
+
+ DoUseDoorOrButton(CaveInGUID, 15);
+
+ if (Creature* lichking = instance->GetCreature(TheLichKingEscapeGUID))
+ {
+ lichking->CastSpell((Unit*)NULL, SPELL_ACHIEV_CHECK, true);
+ lichking->DespawnOrUnsummon(1);
+ }
+ break;
+ case FAIL:
+ DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
+
+ if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
+ jainaOrSylvanas->DespawnOrUnsummon(10000);
+
+ if (Creature* icewallTarget = instance->GetCreature(IcewallTargetGUID))
+ icewallTarget->DespawnOrUnsummon();
+
+ if (GameObject* icewall = instance->GetGameObject(IcewallGUID))
+ icewall->Delete();
+
+ events.ScheduleEvent(EVENT_SPAWN_ESCAPE_EVENT, 30000);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return true;
}
- SaveToDB();
- }
+ void SpawnGunship()
+ {
+ // don't spawn gunship twice
+ if (GunshipGUID)
+ return;
+ if (!_teamInInstance)
+ {
+ Map::PlayerList const& players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->GetSource())
+ _teamInInstance = player->GetTeam();
+ }
- // wave scheduling,checked when wave npcs die
- void OnUnitDeath(Unit* unit) override
- {
- Creature* creature = unit->ToCreature();
- if (!creature)
- return;
+ if (Transport* gunship = sTransportMgr->CreateTransport(_teamInInstance == HORDE ? GO_ORGRIMS_HAMMER : GO_THE_SKYBREAKER, 0, instance))
+ gunship->EnableMovement(GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE);
+ }
- switch (creature->GetEntry())
+ void SpawnEscapeEvent()
{
- case NPC_WAVE_MERCENARY:
- case NPC_WAVE_FOOTMAN:
- case NPC_WAVE_RIFLEMAN:
- case NPC_WAVE_PRIEST:
- case NPC_WAVE_MAGE:
+ if (!_teamInInstance)
{
- uint32 deadNpcs = 0;
- uint32 waveId = creature->AI()->GetData(0);
- for (std::set<uint64>::const_iterator itr = waveGuidList[waveId].begin(); itr != waveGuidList[waveId].end(); ++itr)
- {
- Creature* npc = instance->GetCreature(*itr);
- if (!npc || !npc->IsAlive())
- ++deadNpcs;
- }
- // because the current npc returns IsAlive when OnUnitDeath happens
- // we check if the number of dead npcs is equal to the list-1
- if (deadNpcs == waveGuidList[waveId].size() - 1)
+ Map::PlayerList const& players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->GetSource())
+ _teamInInstance = player->GetTeam();
+ }
+
+ if (_teamInInstance == ALLIANCE)
+ {
+ instance->SummonCreature(NPC_JAINA_ESCAPE, JainaSpawnPos2);
+ instance->SummonCreature(NPC_THE_LICH_KING_ESCAPE, TheLichKingEscapePosition[1]);
+ }
+ else
+ {
+ instance->SummonCreature(NPC_SYLVANAS_ESCAPE, SylvanasSpawnPos2);
+ instance->SummonCreature(NPC_THE_LICH_KING_ESCAPE, TheLichKingEscapePosition[0]);
+ }
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ switch (type)
+ {
+ case DATA_INTRO_EVENT:
+ if (data == IN_PROGRESS)
+ {
+ if (_introState == NOT_STARTED)
+ {
+ if (_teamInInstance == ALLIANCE)
+ {
+ instance->SummonCreature(NPC_JAINA_INTRO, JainaSpawnPos);
+ instance->SummonCreature(NPC_KORELN, KorelnOrLoralenSpawnPos);
+ }
+ else
+ {
+ instance->SummonCreature(NPC_SYLVANAS_INTRO, SylvanasSpawnPos);
+ instance->SummonCreature(NPC_LORALEN, KorelnOrLoralenSpawnPos);
+ }
+ }
+ }
+ _introState = data;
+ break;
+ case DATA_WAVE_COUNT:
+ if (_waveCount && data == NOT_STARTED)
+ ProcessEvent(NULL, EVENT_DO_WIPE);
+ break;
+ case DATA_FROSTSWORN_GENERAL:
+ if (data == DONE)
+ HandleGameObject(ShadowThroneDoorGUID, true);
+ _frostswornGeneralState = data;
+ break;
+ default:
+ break;
+ }
+
+ SaveToDB();
+ }
+
+ // wave scheduling, checked when wave npcs die
+ void OnUnitDeath(Unit* unit) override
+ {
+ Creature* creature = unit->ToCreature();
+ if (!creature)
+ return;
+
+ switch (creature->GetEntry())
+ {
+ case NPC_WAVE_MERCENARY:
+ case NPC_WAVE_FOOTMAN:
+ case NPC_WAVE_RIFLEMAN:
+ case NPC_WAVE_PRIEST:
+ case NPC_WAVE_MAGE:
{
+ uint32 waveId = creature->AI()->GetData(0);
+ for (uint64 guid : waveGuidList[waveId])
+ {
+ if (Creature* npc = instance->GetCreature(guid))
+ if (npc->IsAlive())
+ return;
+ }
+
++_waveCount;
events.ScheduleEvent(EVENT_NEXT_WAVE, 3000);
+ break;
}
- break;
}
}
- }
- void Update(uint32 diff) override
- {
- if (!instance->HavePlayers())
- return;
+ void Update(uint32 diff) override
+ {
+ if (!instance->HavePlayers())
+ return;
- events.Update(diff);
+ events.Update(diff);
- switch (events.ExecuteEvent())
- {
- case EVENT_NEXT_WAVE:
- ProcessEvent(NULL, EVENT_ADD_WAVE);
- break;
+ switch (events.ExecuteEvent())
+ {
+ case EVENT_NEXT_WAVE:
+ ProcessEvent(NULL, EVENT_ADD_WAVE);
+ break;
+ case EVENT_SPAWN_ESCAPE_EVENT:
+ SpawnEscapeEvent();
+ break;
+ }
}
- }
- void ProcessEvent(WorldObject* /*go*/, uint32 eventId) override
- {
- switch (eventId)
+ void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) override
{
- // spawning all wave npcs at once
- case EVENT_SPAWN_WAVES:
- _waveCount = 1;
- DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1);
- DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
- {
- std::list<uint32> possibilityList, tempList;
- uint32 posIndex = 0;
+ switch (eventId)
+ {
+ // spawning all wave npcs at once
+ case EVENT_SPAWN_WAVES:
+ _waveCount = 1;
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
+ {
+ std::list<uint32> possibilityList, tempList;
+ uint32 posIndex = 0;
- possibilityList.push_back(NPC_WAVE_MERCENARY);
- possibilityList.push_back(NPC_WAVE_FOOTMAN);
- possibilityList.push_back(NPC_WAVE_RIFLEMAN);
- possibilityList.push_back(NPC_WAVE_PRIEST);
- possibilityList.push_back(NPC_WAVE_MAGE);
+ possibilityList.push_back(NPC_WAVE_MERCENARY);
+ possibilityList.push_back(NPC_WAVE_FOOTMAN);
+ possibilityList.push_back(NPC_WAVE_RIFLEMAN);
+ possibilityList.push_back(NPC_WAVE_PRIEST);
+ possibilityList.push_back(NPC_WAVE_MAGE);
- // iterate each wave
- for (uint8 i = 0; i < 8; ++i)
- {
- tempList = possibilityList;
+ // iterate each wave
+ for (uint8 i = 0; i < 8; ++i)
+ {
+ tempList = possibilityList;
- uint64 bossGuid = i <= 3 ? _falricGUID : _marwynGUID;
+ uint64 bossGuid = i <= 3 ? FalricGUID : MarwynGUID;
- if (!i)
- Trinity::Containers::RandomResizeList(tempList, 3);
- else if (i < 6 && i != 3)
- Trinity::Containers::RandomResizeList(tempList, 4);
+ if (!i)
+ Trinity::Containers::RandomResizeList(tempList, 3);
+ else if (i < 6 && i != 3)
+ Trinity::Containers::RandomResizeList(tempList, 4);
- for (std::list<uint32>::const_iterator itr = tempList.begin(); itr != tempList.end(); ++itr)
- {
- if (Creature* boss = instance->GetCreature(bossGuid))
+ for (uint32 entry : tempList)
{
- if (Creature* temp = boss->SummonCreature(*itr, SpawnPos[posIndex], TEMPSUMMON_DEAD_DESPAWN))
+ if (Creature* boss = instance->GetCreature(bossGuid))
{
- temp->AI()->SetData(0, i);
- waveGuidList[i].insert(temp->GetGUID());
+ if (Creature* temp = boss->SummonCreature(entry, SpawnPos[posIndex], TEMPSUMMON_DEAD_DESPAWN))
+ {
+ temp->AI()->SetData(0, i);
+ waveGuidList[i].insert(temp->GetGUID());
+ }
}
- }
- ++posIndex;
+ ++posIndex;
+ }
}
}
- }
- events.ScheduleEvent(EVENT_NEXT_WAVE, 5000);
- break;
- case EVENT_ADD_WAVE:
- DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1);
- DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
- HandleGameObject(_entranceDoorGUID, false);
-
- if (_waveCount % 5)
- {
- uint32 internalWaveId = _waveCount - ((_waveCount < 5) ? 1 : 2);
- for (std::set<uint64>::const_iterator itr = waveGuidList[internalWaveId].begin(); itr != waveGuidList[internalWaveId].end(); ++itr)
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 5000);
+ break;
+ case EVENT_ADD_WAVE:
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
+ HandleGameObject(EntranceDoorGUID, false);
+
+ if (_waveCount % 5)
{
- if (Creature* temp = instance->GetCreature(*itr))
+ uint32 internalWaveId = _waveCount - ((_waveCount < 5) ? 1 : 2);
+ for (uint64 guid : waveGuidList[internalWaveId])
{
- temp->CastSpell(temp, SPELL_SPIRIT_ACTIVATE, true);
- temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC|UNIT_FLAG_NOT_SELECTABLE);
- temp->AI()->DoZoneInCombat(temp, 100.00f);
+ if (Creature* temp = instance->GetCreature(guid))
+ {
+ temp->CastSpell(temp, SPELL_SPIRIT_ACTIVATE, false);
+ temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE);
+ temp->AI()->DoZoneInCombat(temp, 100.00f);
+ }
}
}
- }
- else
- {
- uint32 bossIndex = (_waveCount / 5) - 1;
- if (GetBossState(DATA_FALRIC_EVENT + bossIndex) != DONE)
+ else
+ {
+ uint32 bossIndex = (_waveCount / 5) - 1;
+ if (GetBossState(DATA_FALRIC + bossIndex) != DONE)
+ {
+ if (Creature* boss = instance->GetCreature(bossIndex ? MarwynGUID : FalricGUID))
+ boss->AI()->DoAction(ACTION_ENTER_COMBAT);
+ }
+ else if (_waveCount != 10)
+ {
+ ++_waveCount;
+ events.ScheduleEvent(EVENT_NEXT_WAVE, 5000);
+ }
+ }
+ break;
+ case EVENT_DO_WIPE:
+ _waveCount = 0;
+ events.Reset();
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1);
+ DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
+ HandleGameObject(EntranceDoorGUID, true);
+
+ if (Creature* falric = instance->GetCreature(FalricGUID))
+ falric->SetVisible(false);
+ if (Creature* marwyn = instance->GetCreature(MarwynGUID))
+ marwyn->SetVisible(false);
+ // despawn wave npcs
+ for (uint8 i = 0; i < 8; ++i)
{
- if (Creature* boss = instance->GetCreature(bossIndex ? _marwynGUID : _falricGUID))
- boss->AI()->DoAction(ACTION_ENTER_COMBAT);
+ for (uint64 guid : waveGuidList[i])
+ if (Creature* creature = instance->GetCreature(guid))
+ creature->DespawnOrUnsummon(1);
+ waveGuidList[i].clear();
}
- else if (_waveCount != 10)
+ break;
+ // Gunship Outro
+ case EVENT_GUNSHIP_ARRIVAL:
+ if (GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE)
+ break;
+
+ if (Transport* gunship = instance->GetTransport(GunshipGUID))
+ gunship->EnableMovement(false);
+
+ if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
+ jainaOrSylvanas->AI()->DoAction(ACTION_GUNSHIP_ARRIVAL);
+
+ if (Creature* captain = instance->GetCreature(CaptainGUID))
+ captain->AI()->Talk(SAY_CAPTAIN_FIRE);
+
+ for (uint64 guid : GunshipCannonGUIDs)
{
- ++_waveCount;
- events.ScheduleEvent(EVENT_NEXT_WAVE, 5000);
+ uint32 entry = GUID_ENPART(guid);
+ if ((entry == NPC_WORLD_TRIGGER && _teamInInstance == ALLIANCE) || (entry == NPC_GUNSHIP_CANNON_HORDE && _teamInInstance == HORDE))
+ if (Creature* cannon = instance->GetCreature(guid))
+ cannon->CastSpell(cannon, SPELL_GUNSHIP_CANNON_FIRE, true);
}
- }
- break;
- case EVENT_DO_WIPE:
- _waveCount = 0;
- events.Reset();
- DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1);
- DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount);
- HandleGameObject(_entranceDoorGUID, true);
-
- if (Creature* falric = instance->GetCreature(_falricGUID))
- falric->SetVisible(false);
- if (Creature* marwyn = instance->GetCreature(_marwynGUID))
- marwyn->SetVisible(false);
- //despawn wave npcs
- for (uint8 i = 0; i < 8; ++i)
- {
- for (std::set<uint64>::const_iterator itr = waveGuidList[i].begin(); itr != waveGuidList[i].end(); ++itr)
- if (Creature* creature = instance->GetCreature(*itr))
- creature->DespawnOrUnsummon(1);
- waveGuidList[i].clear();
- }
- break;
+ break;
+ case EVENT_GUNSHIP_ARRIVAL_2:
+ if (Transport* gunship = instance->GetTransport(GunshipGUID))
+ gunship->EnableMovement(false);
+
+ for (uint64 guid : GunshipStairGUIDs)
+ if (GameObject* stairs = instance->GetGameObject(guid))
+ stairs->SetRespawnTime(DAY);
+
+ if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
+ jainaOrSylvanas->AI()->DoAction(ACTION_GUNSHIP_ARRIVAL_2);
+
+ if (Creature* captain = instance->GetCreature(CaptainGUID))
+ captain->AI()->Talk(SAY_CAPTAIN_FINAL);
+
+ break;
+ default:
+ break;
+ }
}
- }
- uint32 GetData(uint32 type) const override
- {
- switch (type)
+ uint32 GetData(uint32 type) const override
{
- case DATA_WAVE_COUNT:
- return _waveCount;
- case DATA_TEAM_IN_INSTANCE:
- return _teamInInstance;
- case DATA_INTRO_EVENT:
- return _introEvent;
- case DATA_FROSWORN_EVENT:
- return _frostwornGeneral;
- case DATA_ESCAPE_EVENT:
- return _escapeevent;
- case DATA_SUMMONS:
- return _mobsaticewall;
- default:
- break;
- }
+ switch (type)
+ {
+ case DATA_WAVE_COUNT:
+ return _waveCount;
+ case DATA_TEAM_IN_INSTANCE:
+ return _teamInInstance;
+ case DATA_INTRO_EVENT:
+ return _introState;
+ case DATA_FROSTSWORN_GENERAL:
+ return _frostswornGeneralState;
+ default:
+ break;
+ }
- return 0;
- }
+ return 0;
+ }
- uint64 GetData64(uint32 type) const override
- {
- switch (type)
+ uint64 GetData64(uint32 type) const override
{
- case DATA_FALRIC_EVENT:
- return _falricGUID;
- case DATA_MARWYN_EVENT:
- return _marwynGUID;
- case DATA_FROSWORN_EVENT:
- return _frostwornGeneralGUID;
- case DATA_FROSTWORN_DOOR:
- return _frostwornDoorGUID;
- case DATA_FROSTMOURNE:
- return _frostmourneGUID;
- case DATA_ESCAPE_LEADER:
- return _jainaOrSylvanasPart2GUID;
- case DATA_CAVE_IN:
- return _caveGUID;
- default:
- break;
- }
+ switch (type)
+ {
+ case DATA_FALRIC:
+ return FalricGUID;
+ case DATA_MARWYN:
+ return MarwynGUID;
+ case DATA_FROSTSWORN_GENERAL:
+ return FrostswornGeneralGUID;
+ case DATA_IMPENETRABLE_DOOR:
+ return ImpenetrableDoorGUID;
+ case DATA_FROSTMOURNE:
+ return FrostmourneGUID;
+ case DATA_ESCAPE_LEADER:
+ return JainaOrSylvanasEscapeGUID;
+ case DATA_KORELN_LORALEN:
+ return KorelnOrLoralenGUID;
+ case DATA_THE_LICH_KING_ESCAPE:
+ return TheLichKingEscapeGUID;
+ case DATA_GUNSHIP:
+ return GunshipGUID;
+ case DATA_ICEWALL:
+ return IcewallGUID;
+ case DATA_ICEWALL_TARGET:
+ return IcewallTargetGUID;
+ default:
+ break;
+ }
- return 0;
- }
+ return 0;
+ }
- std::string GetSaveData() override
- {
- OUT_SAVE_INST_DATA;
+ std::string GetSaveData() override
+ {
+ OUT_SAVE_INST_DATA;
- std::ostringstream saveStream;
- saveStream << "H R " << GetBossSaveData() << _introEvent << ' ' << _frostwornGeneral << ' ' << _escapeevent;
+ std::ostringstream saveStream;
+ saveStream << "H R " << GetBossSaveData() << _introState << ' ' << _frostswornGeneralState;
- OUT_SAVE_INST_DATA_COMPLETE;
- return saveStream.str();
- }
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
+ }
- void Load(char const* in) override
- {
- if (!in)
+ void Load(char const* in) override
{
- OUT_LOAD_INST_DATA_FAIL;
- return;
- }
+ if (!in)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
- OUT_LOAD_INST_DATA(in);
+ OUT_LOAD_INST_DATA(in);
- char dataHead1, dataHead2;
+ char dataHead1, dataHead2;
- std::istringstream loadStream(in);
- loadStream >> dataHead1 >> dataHead2;
+ std::istringstream loadStream(in);
+ loadStream >> dataHead1 >> dataHead2;
- if (dataHead1 == 'H' && dataHead2 == 'R')
- {
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (dataHead1 == 'H' && dataHead2 == 'R')
{
- uint32 tmpState;
- loadStream >> tmpState;
- if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
- tmpState = NOT_STARTED;
+ for (uint8 i = 0; i < EncounterCount; ++i)
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
- SetBossState(i, EncounterState(tmpState));
- }
+ SetBossState(i, EncounterState(tmpState));
+ }
- uint32 temp = 0;
- loadStream >> temp;
- if (temp == DONE)
- SetData(DATA_INTRO_EVENT, DONE);
- else
- SetData(DATA_INTRO_EVENT, NOT_STARTED);
+ uint32 temp = 0;
+ loadStream >> temp;
+ if (temp == DONE)
+ SetData(DATA_INTRO_EVENT, DONE);
+ else
+ SetData(DATA_INTRO_EVENT, NOT_STARTED);
- loadStream >> temp;
- if (temp == DONE)
- SetData(DATA_FROSWORN_EVENT, DONE);
+ loadStream >> temp;
+ if (temp == DONE)
+ SetData(DATA_FROSTSWORN_GENERAL, DONE);
+ else
+ SetData(DATA_FROSTSWORN_GENERAL, NOT_STARTED);
+ }
else
- SetData(DATA_FROSWORN_EVENT, NOT_STARTED);
+ OUT_LOAD_INST_DATA_FAIL;
- loadStream >> temp;
- if (temp == DONE)
- SetData(DATA_ESCAPE_EVENT, DONE);
- else
- SetData(DATA_ESCAPE_EVENT, NOT_STARTED);
+ OUT_LOAD_INST_DATA_COMPLETE;
}
- else
- OUT_LOAD_INST_DATA_FAIL;
- OUT_LOAD_INST_DATA_COMPLETE;
+ private:
+ uint64 JainaOrSylvanasIntroGUID; // unused
+ uint64 KorelnOrLoralenGUID;
+ uint64 TheLichkingIntroGUID; // unused
+ uint64 FalricGUID;
+ uint64 MarwynGUID;
+ uint64 FrostmourneAltarBunnyGUID;
+ uint64 FrostswornGeneralGUID;
+ uint64 JainaOrSylvanasEscapeGUID;
+ uint64 TheLichKingEscapeGUID;
+
+ uint64 FrostmourneGUID;
+ uint64 EntranceDoorGUID;
+ uint64 ImpenetrableDoorGUID;
+ uint64 ShadowThroneDoorGUID;
+ uint64 CaveInGUID;
+
+ uint32 _teamInInstance;
+ uint32 _waveCount;
+ uint32 _introState;
+ uint32 _frostswornGeneralState;
+
+ EventMap events;
+ std::set<uint64> waveGuidList[8];
+
+ uint64 GunshipGUID;
+ uint64 CaptainsChestGUID;
+ uint64 CaptainGUID;
+ uint64 IcewallGUID;
+ uint64 IcewallTargetGUID;
+
+ std::set<uint64> GunshipCannonGUIDs;
+ std::set<uint64> GunshipStairGUIDs;
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
+ {
+ return new instance_halls_of_reflection_InstanceMapScript(map);
}
-
- private:
- uint64 _falricGUID;
- uint64 _marwynGUID;
- uint64 _jainaOrSylvanasPart1GUID;
- uint64 _jainaOrSylvanasPart2GUID;
- uint64 _lichkingPart1GUID;
- uint64 _frostwornGeneralGUID;
-
- uint64 _frostmourneGUID;
- uint64 _entranceDoorGUID;
- uint64 _frostwornDoorGUID;
- uint64 _arthasDoorGUID;
- uint64 _escapeDoorGUID;
- uint64 _caveGUID;
-
- uint32 _teamInInstance;
- uint32 _waveCount;
- uint32 _introEvent;
- uint32 _frostwornGeneral;
- uint32 _escapeevent;
- uint32 _mobsaticewall;
-
- EventMap events;
-
- std::set<uint64> waveGuidList[8];
- };
-
- InstanceScript* GetInstanceScript(InstanceMap* map) const override
- {
- return new instance_halls_of_reflection_InstanceMapScript(map);
- }
};
void AddSC_instance_halls_of_reflection()
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
index 25cc47b358c..592c44940a4 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
@@ -1800,7 +1800,7 @@ class spell_icc_sprit_alarm : public SpellScriptLoader
}
if (GameObject* trap = GetCaster()->FindNearestGameObject(trapId, 5.0f))
- trap->SetRespawnTime(trap->GetGOInfo()->trap.autoCloseTime);
+ trap->SetRespawnTime(trap->GetGOInfo()->GetAutoCloseTime());
std::list<Creature*> wards;
GetCaster()->GetCreatureListWithEntryInGrid(wards, NPC_DEATHBOUND_WARD, 150.0f);