aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Authentication/AuthCodes.cpp2
-rw-r--r--src/server/authserver/Authentication/AuthCodes.h2
-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/AI/SmartScripts/SmartAI.cpp5
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp23
-rw-r--r--src/server/game/Calendar/CalendarMgr.h3
-rw-r--r--src/server/game/DataStores/DBCStores.cpp2
-rw-r--r--src/server/game/DataStores/DBCStores.h1
-rw-r--r--src/server/game/DataStores/DBCStructure.h12
-rw-r--r--src/server/game/DataStores/DBCfmt.h1
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp8
-rw-r--r--src/server/game/Entities/Player/Player.cpp10
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp15
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp39
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp4
-rw-r--r--src/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Grids/GridStates.cpp12
-rw-r--r--src/server/game/Grids/GridStates.h7
-rw-r--r--src/server/game/Guilds/Guild.cpp8
-rw-r--r--src/server/game/Handlers/ArenaTeamHandler.cpp6
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp21
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp5
-rw-r--r--src/server/game/Instances/InstanceScript.h4
-rw-r--r--src/server/game/Maps/Map.cpp44
-rw-r--r--src/server/game/Maps/MapUpdater.cpp30
-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/Spell.cpp17
-rw-r--r--src/server/game/Spells/SpellMgr.cpp12
-rw-r--r--src/server/game/Spells/SpellScript.h4
-rw-r--r--src/server/game/Tickets/TicketMgr.cpp2
-rw-r--r--src/server/game/Warden/Warden.cpp2
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp7
-rw-r--r--src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp13
-rw-r--r--src/server/scripts/EasternKingdoms/zone_duskwood.cpp56
-rw-r--r--src/server/scripts/Kalimdor/zone_durotar.cpp6
-rw-r--r--src/server/scripts/Kalimdor/zone_silithus.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp3
-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.cpp3333
-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
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp6
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp212
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp2
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp55
-rw-r--r--src/server/scripts/Spells/spell_holiday.cpp2
-rw-r--r--src/server/scripts/Spells/spell_shaman.cpp2
-rw-r--r--src/server/scripts/World/boss_emerald_dragons.cpp2
-rw-r--r--src/server/shared/Database/DatabaseWorkerPool.h6
-rw-r--r--src/server/shared/Logging/Log.cpp15
-rw-r--r--src/server/shared/Logging/Log.h54
-rw-r--r--src/server/shared/Packets/ByteBuffer.h14
-rw-r--r--src/tools/mmaps_generator/TerrainBuilder.cpp2
63 files changed, 3245 insertions, 2655 deletions
diff --git a/src/server/authserver/Authentication/AuthCodes.cpp b/src/server/authserver/Authentication/AuthCodes.cpp
index bb278dd6653..55517884b8e 100644
--- a/src/server/authserver/Authentication/AuthCodes.cpp
+++ b/src/server/authserver/Authentication/AuthCodes.cpp
@@ -79,4 +79,4 @@ namespace AuthHelper
return NULL;
}
-};
+}
diff --git a/src/server/authserver/Authentication/AuthCodes.h b/src/server/authserver/Authentication/AuthCodes.h
index 5e6522f8981..97b4779da0e 100644
--- a/src/server/authserver/Authentication/AuthCodes.h
+++ b/src/server/authserver/Authentication/AuthCodes.h
@@ -92,6 +92,6 @@ namespace AuthHelper
bool IsAcceptedClientBuild(int build);
bool IsPostBCAcceptedClientBuild(int build);
bool IsPreBCAcceptedClientBuild(int build);
-};
+}
#endif
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 36c1d384693..c205dd908c7 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/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 098f3130fed..e769b7c22a5 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -618,10 +618,7 @@ void SmartAI::DamageTaken(Unit* doneBy, uint32& damage)
{
GetScript()->ProcessEventsFor(SMART_EVENT_DAMAGED, doneBy, damage);
if (mInvincibilityHpLevel && (damage >= me->GetHealth() - mInvincibilityHpLevel))
- {
- damage = 0;
- me->SetHealth(mInvincibilityHpLevel);
- }
+ damage = me->GetHealth() - mInvincibilityHpLevel; // damage should not be nullified, because of player damage req.
}
void SmartAI::HealReceived(Unit* doneBy, uint32& addhealth)
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index 52ed50f3948..a4cb972e625 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -17,7 +17,6 @@
#include "CalendarMgr.h"
#include "QueryResult.h"
-#include "DatabaseEnv.h"
#include "Log.h"
#include "Player.h"
#include "GuildMgr.h"
@@ -128,6 +127,12 @@ void CalendarMgr::AddEvent(CalendarEvent* calendarEvent, CalendarSendEventType s
void CalendarMgr::AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite)
{
+ SQLTransaction dummy;
+ AddInvite(calendarEvent, invite, dummy);
+}
+
+void CalendarMgr::AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite, SQLTransaction& trans)
+{
if (!calendarEvent->IsGuildAnnouncement())
SendCalendarEventInvite(*invite);
@@ -137,7 +142,7 @@ void CalendarMgr::AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite
if (!calendarEvent->IsGuildAnnouncement())
{
_invites[invite->GetEventId()].push_back(invite);
- UpdateInvite(invite);
+ UpdateInvite(invite, trans);
}
}
@@ -221,7 +226,6 @@ void CalendarMgr::RemoveInvite(uint64 inviteId, uint64 eventId, uint64 /*remover
void CalendarMgr::UpdateEvent(CalendarEvent* calendarEvent)
{
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CALENDAR_EVENT);
stmt->setUInt64(0, calendarEvent->GetEventId());
stmt->setUInt32(1, GUID_LOPART(calendarEvent->GetCreatorGUID()));
@@ -232,13 +236,17 @@ void CalendarMgr::UpdateEvent(CalendarEvent* calendarEvent)
stmt->setUInt32(6, uint32(calendarEvent->GetEventTime()));
stmt->setUInt32(7, calendarEvent->GetFlags());
stmt->setUInt32(8, calendarEvent->GetTimeZoneTime()); // correct?
- trans->Append(stmt);
- CharacterDatabase.CommitTransaction(trans);
+ CharacterDatabase.Execute(stmt);
}
void CalendarMgr::UpdateInvite(CalendarInvite* invite)
{
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ SQLTransaction dummy;
+ UpdateInvite(invite, dummy);
+}
+
+void CalendarMgr::UpdateInvite(CalendarInvite* invite, SQLTransaction& trans)
+{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CALENDAR_INVITE);
stmt->setUInt64(0, invite->GetInviteId());
stmt->setUInt64(1, invite->GetEventId());
@@ -248,8 +256,7 @@ void CalendarMgr::UpdateInvite(CalendarInvite* invite)
stmt->setUInt32(5, uint32(invite->GetStatusTime()));
stmt->setUInt8(6, invite->GetRank());
stmt->setString(7, invite->GetText());
- trans->Append(stmt);
- CharacterDatabase.CommitTransaction(trans);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
void CalendarMgr::RemoveAllPlayerEventsAndInvites(uint64 guid)
diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h
index da185d519d5..8f44b013e5c 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -20,6 +20,7 @@
#include <ace/Singleton.h>
#include "Common.h"
+#include "DatabaseEnv.h"
#include "WorldPacket.h"
enum CalendarMailAnswers
@@ -305,8 +306,10 @@ class CalendarMgr
void UpdateEvent(CalendarEvent* calendarEvent);
void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite);
+ void AddInvite(CalendarEvent* calendarEvent, CalendarInvite* invite, SQLTransaction& trans);
void RemoveInvite(uint64 inviteId, uint64 eventId, uint64 remover);
void UpdateInvite(CalendarInvite* invite);
+ void UpdateInvite(CalendarInvite* invite, SQLTransaction& trans);
void RemoveAllPlayerEventsAndInvites(uint64 guid);
void RemovePlayerGuildEventsAndSignups(uint64 guid, uint32 guildId);
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 9b0465a4536..44f03b6978d 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -139,6 +139,7 @@ DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDatafmt);
+DBCStorage <PowerDisplayEntry> sPowerDisplayStore(PowerDisplayfmt);
DBCStorage <PvPDifficultyEntry> sPvPDifficultyStore(PvPDifficultyfmt);
DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt);
@@ -391,6 +392,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc");
for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i)
if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i))
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index b77db950541..fe775dfda19 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -141,6 +141,7 @@ extern DBCStorage <MapEntry> sMapStore;
extern MapDifficultyMap sMapDifficultyMap;
extern DBCStorage <MovieEntry> sMovieStore;
extern DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore;
+extern DBCStorage <PowerDisplayEntry> sPowerDisplayStore;
extern DBCStorage <QuestSortEntry> sQuestSortStore;
extern DBCStorage <QuestXPEntry> sQuestXPStore;
extern DBCStorage <QuestFactionRewEntry> sQuestFactionRewardStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index abe7bde4bf5..5d6c8c7aa89 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1398,6 +1398,16 @@ struct OverrideSpellDataEntry
//uint32 unk0; // 11
};
+struct PowerDisplayEntry
+{
+ uint32 Id; // 0
+ uint32 PowerType; // 1
+ //char* Name; // 2
+ //uint32 R; // 3
+ //uint32 G; // 4
+ //uint32 B; // 5
+};
+
struct PvPDifficultyEntry
{
//uint32 id; // 0 m_ID
@@ -1982,7 +1992,7 @@ struct VehicleEntry
uint32 m_uiLocomotionType; // 34
float m_msslTrgtImpactTexRadius; // 35
uint32 m_uiSeatIndicatorType; // 36
- uint32 m_powerType; // 37, new in 3.1
+ uint32 m_powerDisplayId; // 37, new in 3.1
// 38, new in 3.1
// 39, new in 3.1
};
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 35a8eecb708..222353467f4 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -91,6 +91,7 @@ char const OverrideSpellDatafmt[] = "niiiiiiiiiix";
char const QuestFactionRewardfmt[] = "niiiiiiiiii";
char const QuestSortEntryfmt[] = "nxxxxxxxxxxxxxxxxx";
char const QuestXPfmt[] = "niiiiiiiiii";
+char const PowerDisplayfmt[] = "nixxxx";
char const PvPDifficultyfmt[] = "diiiii";
char const RandomPropertiesPointsfmt[] = "niiiiiiiiiiiiiii";
char const ScalingStatDistributionfmt[] = "niiiiiiiiiiiiiiiiiiiii";
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 36997eb884a..01621637985 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -569,7 +569,7 @@ void Creature::Update(uint32 diff)
if (getPowerType() == POWER_ENERGY)
{
- if (!IsVehicle() || GetVehicleKit()->GetVehicleInfo()->m_powerType != POWER_PYRITE)
+ if (!IsVehicle() || GetVehicleKit()->GetVehicleInfo()->m_powerDisplayId != POWER_PYRITE)
Regenerate(POWER_ENERGY);
}
else
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 8051c757bf2..306e4209e4d 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -526,7 +526,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:
@@ -568,10 +568,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)
@@ -1098,7 +1100,7 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f
SwitchDoorOrButton(true, alternative);
SetLootState(GO_ACTIVATED, user);
- m_cooldownTime = time(NULL) + time_to_restore;
+ m_cooldownTime = time_to_restore ? (time(NULL) + time_to_restore) : 0;
}
void GameObject::SetGoArtKit(uint8 kit)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a701e6fc38f..563d7fed107 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -144,6 +144,8 @@ enum CharacterCustomizeFlags
static uint32 copseReclaimDelay[MAX_DEATH_COUNT] = { 30, 60, 120 };
+uint32 const MAX_MONEY_AMOUNT = static_cast<uint32>(std::numeric_limits<int32>::max());
+
// == PlayerTaxi ================================================
PlayerTaxi::PlayerTaxi()
@@ -364,6 +366,12 @@ void TradeData::SetMoney(uint32 money)
if (m_money == money)
return;
+ if (!m_player->HasEnoughMoney(money))
+ {
+ m_player->GetSession()->SendTradeStatus(TRADE_STATUS_BUSY);
+ return;
+ }
+
m_money = money;
SetAccepted(false);
@@ -22639,7 +22647,7 @@ bool Player::ModifyMoney(int32 amount, bool sendError /*= true*/)
SetMoney (GetMoney() > uint32(-amount) ? GetMoney() + amount : 0);
else
{
- if (GetMoney() < uint32(MAX_MONEY_AMOUNT - amount))
+ if (GetMoney() < MAX_MONEY_AMOUNT - static_cast<uint32>(amount))
SetMoney(GetMoney() + amount);
else
{
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 92691c3fd45..0826f533df7 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -29,6 +29,7 @@
#include "SpellMgr.h"
#include "Unit.h"
+#include <limits>
#include <string>
#include <vector>
@@ -824,7 +825,8 @@ enum PlayerDelayedOperations
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
-#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1)
+// Maximum money amount : 2^31 - 1
+extern uint32 const MAX_MONEY_AMOUNT;
struct InstancePlayerBind
{
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index fd45c3fc596..8bc07732bb6 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);
@@ -210,8 +210,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();
}
}
@@ -450,6 +456,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();
@@ -464,7 +471,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/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index fae4f0c6b6a..4c3724a8860 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -76,42 +76,9 @@ Vehicle::~Vehicle()
void Vehicle::Install()
{
- if (Creature* creature = _me->ToCreature())
- {
- switch (_vehicleInfo->m_powerType)
- {
- case POWER_STEAM:
- case POWER_HEAT:
- case POWER_BLOOD:
- case POWER_OOZE:
- case POWER_WRATH:
- _me->setPowerType(POWER_ENERGY);
- _me->SetMaxPower(POWER_ENERGY, 100);
- break;
- case POWER_PYRITE:
- _me->setPowerType(POWER_ENERGY);
- _me->SetMaxPower(POWER_ENERGY, 50);
- break;
- default:
- for (uint32 i = 0; i < MAX_SPELL_VEHICLE; ++i)
- {
- if (!creature->m_spells[i])
- continue;
-
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(creature->m_spells[i]);
- if (!spellInfo)
- continue;
-
- if (spellInfo->PowerType == POWER_ENERGY && spellInfo->CalcPowerCost(_me, spellInfo->GetSchoolMask()) > 0)
- {
- _me->setPowerType(POWER_ENERGY);
- _me->SetMaxPower(POWER_ENERGY, 100);
- break;
- }
- }
- break;
- }
- }
+ if (_me->GetTypeId() == TYPEID_UNIT)
+ if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(_vehicleInfo->m_powerDisplayId))
+ _me->setPowerType(Powers(powerDisplay->PowerType));
_status = STATUS_INSTALLED;
if (GetBase()->GetTypeId() == TYPEID_UNIT)
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 2905b0454c4..207f80eabe7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3822,8 +3822,8 @@ void ObjectMgr::LoadQuests()
"RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, "
// 117 118 119 120 121 122 123 124 125 126 127 128 129
"Unknown0, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, "
- // 130 131 132 133 134 135 136 137 138 139 140
- "EmoteOnIncomplete, EmoteOnComplete, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, WDBVerified"
+ // 130 131 132 133 134 135 136 137 138 139
+ "EmoteOnIncomplete, EmoteOnComplete, 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 48c9e618a1d..ba5940d7e12 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -432,7 +432,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/Grids/GridStates.cpp b/src/server/game/Grids/GridStates.cpp
index 8b57c382cd7..3e085f1f381 100644
--- a/src/server/game/Grids/GridStates.cpp
+++ b/src/server/game/Grids/GridStates.cpp
@@ -20,18 +20,6 @@
#include "GridNotifiers.h"
#include "Log.h"
-#ifdef TRINITY_DEBUG
-bool GridState::checkMagic()
-{
- if (i_Magic != MAGIC_TESTVAL)
- {
- TC_LOG_ERROR("misc", "!!! GridState: Magic value gone !!!");
- return false;
- }
- return true;
-}
-#endif
-
void InvalidState::Update(Map&, NGridType&, GridInfo&, uint32) const
{ }
diff --git a/src/server/game/Grids/GridStates.h b/src/server/game/Grids/GridStates.h
index 016df4dc3d4..af11ab08d5e 100644
--- a/src/server/game/Grids/GridStates.h
+++ b/src/server/game/Grids/GridStates.h
@@ -27,13 +27,6 @@ class Map;
class GridState
{
public:
-#ifdef TRINITY_DEBUG
-#define MAGIC_TESTVAL 0xFBE823BA
- GridState() { i_Magic = MAGIC_TESTVAL; }
- bool checkMagic();
- void setMagic() { i_Magic = MAGIC_TESTVAL; }
- unsigned int i_Magic;
-#endif
virtual ~GridState() { };
virtual void Update(Map &, NGridType&, GridInfo &, uint32 t_diff) const = 0;
};
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index f448fbb9f19..db0a196dec6 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -754,7 +754,7 @@ int32 Guild::Member::GetBankWithdrawValue(uint8 tabId) const
{
// Guild master has unlimited amount.
if (IsRank(GR_GUILDMASTER))
- return tabId == GUILD_BANK_MAX_TABS ? GUILD_WITHDRAW_MONEY_UNLIMITED : GUILD_WITHDRAW_SLOT_UNLIMITED;
+ return static_cast<int32>(tabId == GUILD_BANK_MAX_TABS ? GUILD_WITHDRAW_MONEY_UNLIMITED : GUILD_WITHDRAW_SLOT_UNLIMITED);
return m_bankWithdraw[tabId];
}
@@ -1760,7 +1760,7 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair)
{
//clamp amount to MAX_MONEY_AMOUNT, Players can't hold more than that anyway
- amount = std::min(amount, uint32(MAX_MONEY_AMOUNT));
+ amount = std::min(amount, MAX_MONEY_AMOUNT);
if (m_bankMoney < amount) // Not enough money in bank
return false;
@@ -2581,7 +2581,7 @@ inline int32 Guild::_GetMemberRemainingSlots(Member const* member, uint8 tabId)
{
uint8 rankId = member->GetRankId();
if (rankId == GR_GUILDMASTER)
- return GUILD_WITHDRAW_SLOT_UNLIMITED;
+ return static_cast<int32>(GUILD_WITHDRAW_SLOT_UNLIMITED);
if ((_GetRankBankTabRights(rankId, tabId) & GUILD_BANK_RIGHT_VIEW_TAB) != 0)
{
int32 remaining = _GetRankBankTabSlotsPerDay(rankId, tabId) - member->GetBankWithdrawValue(tabId);
@@ -2598,7 +2598,7 @@ inline int32 Guild::_GetMemberRemainingMoney(Member const* member) const
{
uint8 rankId = member->GetRankId();
if (rankId == GR_GUILDMASTER)
- return GUILD_WITHDRAW_MONEY_UNLIMITED;
+ return static_cast<int32>(GUILD_WITHDRAW_MONEY_UNLIMITED);
if ((_GetRankRights(rankId) & (GR_RIGHT_WITHDRAW_REPAIR | GR_RIGHT_WITHDRAW_GOLD)) != 0)
{
diff --git a/src/server/game/Handlers/ArenaTeamHandler.cpp b/src/server/game/Handlers/ArenaTeamHandler.cpp
index 632bd02def0..3bb3edac500 100644
--- a/src/server/game/Handlers/ArenaTeamHandler.cpp
+++ b/src/server/game/Handlers/ArenaTeamHandler.cpp
@@ -121,6 +121,12 @@ void WorldSession::HandleArenaTeamInviteOpcode(WorldPacket& recvData)
return;
}
+ if (GetPlayer()->GetArenaTeamId(arenaTeam->GetSlot()) != arenaTeamId)
+ {
+ SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
+ return;
+ }
+
// OK result but don't send invite
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
return;
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index 45d4d221d06..278c180c380 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -255,7 +255,14 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
uint32 inviteCount;
recvData >> inviteCount;
- for (uint32 i = 0; i < inviteCount; ++i)
+ SQLTransaction trans;
+ if (inviteCount > 1)
+ trans = CharacterDatabase.BeginTransaction();
+
+ // client limits the amount of players to be invited to 100
+ const uint32 MaxPlayerInvites = 100;
+
+ for (uint32 i = 0; i < inviteCount && i < MaxPlayerInvites; ++i)
{
uint64 invitee = 0;
uint8 status = 0;
@@ -265,8 +272,11 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData)
// 946684800 is 01/01/2000 00:00:00 - default response time
CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent.GetEventId(), invitee, guid, 946684800, CalendarInviteStatus(status), CalendarModerationRank(rank), "");
- sCalendarMgr->AddInvite(&calendarEvent, invite);
+ sCalendarMgr->AddInvite(&calendarEvent, invite, trans);
}
+
+ if (inviteCount > 1)
+ CharacterDatabase.CommitTransaction(trans);
}
sCalendarMgr->AddEvent(new CalendarEvent(calendarEvent, calendarEvent.GetEventId()), CALENDAR_SENDTYPE_ADD);
@@ -350,10 +360,15 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket& recvData)
sCalendarMgr->AddEvent(newEvent, CALENDAR_SENDTYPE_COPY);
CalendarInviteStore invites = sCalendarMgr->GetEventInvites(eventId);
+ SQLTransaction trans;
+ if (invites.size() > 1)
+ trans = CharacterDatabase.BeginTransaction();
for (CalendarInviteStore::const_iterator itr = invites.begin(); itr != invites.end(); ++itr)
- sCalendarMgr->AddInvite(newEvent, new CalendarInvite(**itr, sCalendarMgr->GetFreeInviteId(), newEvent->GetEventId()));
+ sCalendarMgr->AddInvite(newEvent, new CalendarInvite(**itr, sCalendarMgr->GetFreeInviteId(), newEvent->GetEventId()), trans);
+ if (invites.size() > 1)
+ CharacterDatabase.CommitTransaction(trans);
// should we change owner when somebody makes a copy of event owned by another person?
}
else
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 4372de9eafe..884c4a83b15 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -299,14 +299,14 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/)
return;
}
- if (_player->GetMoney() >= uint32(MAX_MONEY_AMOUNT) - his_trade->GetMoney())
+ if (_player->GetMoney() >= MAX_MONEY_AMOUNT - his_trade->GetMoney())
{
_player->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
my_trade->SetAccepted(false, true);
return;
}
- if (trader->GetMoney() >= uint32(MAX_MONEY_AMOUNT) - my_trade->GetMoney())
+ if (trader->GetMoney() >= MAX_MONEY_AMOUNT - my_trade->GetMoney())
{
trader->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
his_trade->SetAccepted(false, true);
@@ -686,7 +686,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/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 3050443edc0..9e11c566c22 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -243,7 +243,7 @@ AI* GetInstanceAI(T* obj, char const* scriptName)
return new AI(obj);
return NULL;
-};
+}
template<class AI, class T>
AI* GetInstanceAI(T* obj)
@@ -253,6 +253,6 @@ AI* GetInstanceAI(T* obj)
return new AI(obj);
return NULL;
-};
+}
#endif // TRINITY_INSTANCE_DATA_H
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index cd391299785..ba271235330 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,24 +2645,27 @@ void Map::RemoveAllObjectsInRemoveList()
RemoveFromMap(corpse, true);
break;
}
- case TYPEID_DYNAMICOBJECT:
- RemoveFromMap((DynamicObject*)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_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/Maps/MapUpdater.cpp b/src/server/game/Maps/MapUpdater.cpp
index f3a5a66bf66..dd697719d54 100644
--- a/src/server/game/Maps/MapUpdater.cpp
+++ b/src/server/game/Maps/MapUpdater.cpp
@@ -6,34 +6,6 @@
#include <ace/Guard_T.h>
#include <ace/Method_Request.h>
-class WDBThreadStartReq1 : public ACE_Method_Request
-{
- public:
-
- WDBThreadStartReq1()
- {
- }
-
- virtual int call()
- {
- return 0;
- }
-};
-
-class WDBThreadEndReq1 : public ACE_Method_Request
-{
- public:
-
- WDBThreadEndReq1()
- {
- }
-
- virtual int call()
- {
- return 0;
- }
-};
-
class MapUpdateRequest : public ACE_Method_Request
{
private:
@@ -67,7 +39,7 @@ MapUpdater::~MapUpdater()
int MapUpdater::activate(size_t num_threads)
{
- return m_executor.start((int)num_threads, new WDBThreadStartReq1, new WDBThreadEndReq1);
+ return m_executor.start((int)num_threads);
}
int MapUpdater::deactivate()
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 9b3732d232b..099275ba8dc 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -137,7 +137,7 @@ Quest::Quest(Field* questRecord)
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
OfferRewardEmoteDelay[i] = questRecord[136+i].GetInt32();
- //int32 WDBVerified = questRecord[140].GetInt32();
+ //int32 VerifiedBuild = questRecord[140].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 8e7edfc5355..3e1763e6c5b 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1343,17 +1343,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/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 7c6f2552b44..768c0b7e818 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1251,8 +1251,12 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
float angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle);
- float ground = z;
- float liquidLevel = m_caster->GetMap()->GetWaterOrGroundLevel(x, y, z, &ground);
+ float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z, true, 50.0f);
+ float liquidLevel = VMAP_INVALID_HEIGHT_VALUE;
+ LiquidData liquidData;
+ if (m_caster->GetMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquidData))
+ liquidLevel = liquidData.level;
+
if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level
{
SendCastResult(SPELL_FAILED_NOT_HERE);
@@ -1288,10 +1292,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
dist = objSize + (dist - objSize) * float(rand_norm());
Position pos = dest._position;
- if (targetType.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP)
- m_caster->MovePositionToFirstCollision(pos, dist, angle);
- else
- m_caster->MovePosition(pos, dist, angle);
+ m_caster->MovePositionToFirstCollision(pos, dist, angle);
dest.Relocate(pos);
break;
@@ -1324,7 +1325,7 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici
dist = objSize + (dist - objSize) * float(rand_norm());
Position pos = dest._position;
- target->MovePosition(pos, dist, angle);
+ target->MovePositionToFirstCollision(pos, dist, angle);
dest.Relocate(pos);
break;
@@ -1363,7 +1364,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT
dist *= float(rand_norm());
Position pos = dest._position;
- m_caster->MovePosition(pos, dist, angle);
+ m_caster->MovePositionToFirstCollision(pos, dist, angle);
dest.Relocate(pos);
break;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index ba5b8856323..501cb1e77f2 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3375,6 +3375,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/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 75a191a9801..32b8781fb89 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -249,7 +249,7 @@ class SpellScript : public _SpellScript
class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) { } }; \
class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) { } }; \
class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) { } }; \
- class DestinationTargetSelectHandlerFunction : public SpellScript::DestinationTargetSelectHandler { public: DestinationTargetSelectHandlerFunction(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::DestinationTargetSelectHandler((SpellScript::SpellDestinationTargetSelectFnType)_DestinationTargetSelectHandlerScript, _effIndex, _targetType) { } };
+ class DestinationTargetSelectHandlerFunction : public SpellScript::DestinationTargetSelectHandler { public: DestinationTargetSelectHandlerFunction(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::DestinationTargetSelectHandler((SpellScript::SpellDestinationTargetSelectFnType)_DestinationTargetSelectHandlerScript, _effIndex, _targetType) { } }
#define PrepareSpellScript(CLASSNAME) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
public:
@@ -623,7 +623,7 @@ class AuraScript : public _SpellScript
class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) { } }; \
class CheckProcHandlerFunction : public AuraScript::CheckProcHandler { public: CheckProcHandlerFunction(AuraCheckProcFnType handlerScript) : AuraScript::CheckProcHandler((AuraScript::AuraCheckProcFnType)handlerScript) { } }; \
class AuraProcHandlerFunction : public AuraScript::AuraProcHandler { public: AuraProcHandlerFunction(AuraProcFnType handlerScript) : AuraScript::AuraProcHandler((AuraScript::AuraProcFnType)handlerScript) { } }; \
- class EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: EffectProcHandlerFunction(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)effectHandlerScript, effIndex, effName) { } }; \
+ class EffectProcHandlerFunction : public AuraScript::EffectProcHandler { public: EffectProcHandlerFunction(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName) : AuraScript::EffectProcHandler((AuraScript::AuraEffectProcFnType)effectHandlerScript, effIndex, effName) { } }
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp
index b9ecfffb8c3..71d51153b4c 100644
--- a/src/server/game/Tickets/TicketMgr.cpp
+++ b/src/server/game/Tickets/TicketMgr.cpp
@@ -233,7 +233,7 @@ void GmTicket::SetChatLog(std::list<uint32> time, std::string const& log)
std::stringstream ss(log);
std::stringstream newss;
std::string line;
- while (std::getline(ss, line))
+ while (std::getline(ss, line) && !time.empty())
{
newss << secsToTimeString(time.front()) << ": " << line << "\n";
time.pop_front();
diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp
index 42872bba22e..0810295c0cc 100644
--- a/src/server/game/Warden/Warden.cpp
+++ b/src/server/game/Warden/Warden.cpp
@@ -223,7 +223,7 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/)
void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData)
{
- if (!_warden)
+ if (!_warden || recvData.empty())
return;
_warden->DecryptData(recvData.contents(), recvData.size());
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index f2f11801229..5dbe95b3e54 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -1020,7 +1020,7 @@ public:
}
else
{
- if (newmoney > MAX_MONEY_AMOUNT)
+ if (newmoney > static_cast<int32>(MAX_MONEY_AMOUNT))
newmoney = MAX_MONEY_AMOUNT;
handler->PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(moneyToAdd), handler->GetNameLink(target).c_str());
@@ -1035,10 +1035,7 @@ public:
if (handler->needReportToTarget(target))
ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, handler->GetNameLink().c_str(), moneyToAdd);
- if (moneyToAdd >= MAX_MONEY_AMOUNT)
- moneyToAdd = MAX_MONEY_AMOUNT;
-
- if (targetMoney >= uint32(MAX_MONEY_AMOUNT) - moneyToAdd)
+ if (targetMoney >= MAX_MONEY_AMOUNT - moneyToAdd)
moneyToAdd -= targetMoney;
target->ModifyMoney(moneyToAdd);
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
index 83b716728ea..354e1204a50 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
+++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
@@ -212,4 +212,4 @@ void AddSC_boss_balinda()
{
new boss_balinda;
new npc_water_elemental;
-};
+}
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
index 010e06d67cb..870ae370366 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
@@ -109,7 +109,7 @@ void SummonCroneIfReady(InstanceScript* instance, Creature* creature)
pCrone->AI()->AttackStart(creature->GetVictim());
}
}
-};
+}
class boss_dorothee : public CreatureScript
{
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
index 5562559786d..28bb24f49a9 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp
@@ -679,13 +679,16 @@ public:
if (!map->IsDungeon())
return;
- Map::PlayerList const &PlayerList = map->GetPlayers();
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ Map::PlayerList const &playerList = map->GetPlayers();
+ Position homePos = me->GetHomePosition();
+ for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
{
- if (i->GetSource()->GetPositionZ() <= DRAGON_REALM_Z-5)
+ Player* player = itr->GetSource();
+ if (player->IsInDist(&homePos, 50.0f) && player->GetPositionZ() <= DEMON_REALM_Z + 10.f)
{
- i->GetSource()->RemoveAura(AURA_SPECTRAL_REALM);
- i->GetSource()->TeleportTo(me->GetMap()->GetId(), i->GetSource()->GetPositionX(), i->GetSource()->GetPositionY(), DRAGON_REALM_Z+5, i->GetSource()->GetOrientation());
+ player->RemoveAura(AURA_SPECTRAL_REALM);
+ player->TeleportTo(me->GetMap()->GetId(), player->GetPositionX(),
+ player->GetPositionY(), DRAGON_REALM_Z + 5, player->GetOrientation());
}
}
}
diff --git a/src/server/scripts/EasternKingdoms/zone_duskwood.cpp b/src/server/scripts/EasternKingdoms/zone_duskwood.cpp
index 236455137dc..4eaf98d0a0e 100644
--- a/src/server/scripts/EasternKingdoms/zone_duskwood.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_duskwood.cpp
@@ -29,18 +29,19 @@ EndScriptData */
enum TwilightCorrupter
{
- ITEM_FRAGMENT = 21149,
NPC_TWILIGHT_CORRUPTER = 15625,
- YELL_TWILIGHTCORRUPTOR_RESPAWN = 0,
- YELL_TWILIGHTCORRUPTOR_AGGRO = 1,
- YELL_TWILIGHTCORRUPTOR_KILL = 2,
+ YELL_TWILIGHT_CORRUPTOR_RESPAWN = 0,
+ YELL_TWILIGHT_CORRUPTOR_AGGRO = 1,
+ YELL_TWILIGHT_CORRUPTOR_KILL = 2,
+
SPELL_SOUL_CORRUPTION = 25805,
SPELL_CREATURE_OF_NIGHTMARE = 25806,
SPELL_LEVEL_UP = 24312,
EVENT_SOUL_CORRUPTION = 1,
EVENT_CREATURE_OF_NIGHTMARE = 2,
- FACTION_HOSTILE = 14
+
+ QUEST_NIGHTMARES_CORRUPTION = 8735
};
/*######
@@ -58,12 +59,13 @@ public:
void Reset() override
{
- KillCount = 0;
+ _events.Reset();
+ KillCount = 0;
}
void EnterCombat(Unit* /*who*/) override
{
- Talk(YELL_TWILIGHTCORRUPTOR_AGGRO);
+ Talk(YELL_TWILIGHT_CORRUPTOR_AGGRO);
_events.ScheduleEvent(EVENT_SOUL_CORRUPTION, 15000);
_events.ScheduleEvent(EVENT_CREATURE_OF_NIGHTMARE, 30000);
}
@@ -73,7 +75,7 @@ public:
if (victim->GetTypeId() == TYPEID_PLAYER)
{
++KillCount;
- Talk(YELL_TWILIGHTCORRUPTOR_KILL, victim);
+ Talk(YELL_TWILIGHT_CORRUPTOR_KILL, victim);
if (KillCount == 3)
{
@@ -90,22 +92,27 @@ public:
_events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SOUL_CORRUPTION:
- DoCastVictim(SPELL_SOUL_CORRUPTION);
- _events.ScheduleEvent(EVENT_SOUL_CORRUPTION, rand()%4000+15000);
+ DoCastAOE(SPELL_SOUL_CORRUPTION);
+ _events.ScheduleEvent(EVENT_SOUL_CORRUPTION, urand(15000, 19000));
break;
case EVENT_CREATURE_OF_NIGHTMARE:
- DoCastVictim(SPELL_CREATURE_OF_NIGHTMARE);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_CREATURE_OF_NIGHTMARE);
_events.ScheduleEvent(EVENT_CREATURE_OF_NIGHTMARE, 45000);
break;
default:
break;
}
}
+
DoMeleeAttackIfReady();
}
@@ -124,27 +131,22 @@ public:
# at_twilight_grove
######*/
+Position const TwillightCorrupter = { -10328.16f, -489.57f, 49.95f, 0.0f };
+
class at_twilight_grove : public AreaTriggerScript
{
-public:
- at_twilight_grove() : AreaTriggerScript("at_twilight_grove") { }
+ public:
+ at_twilight_grove() : AreaTriggerScript("at_twilight_grove") { }
- bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
- {
- if (player->HasQuestForItem(ITEM_FRAGMENT))
+ bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
{
- if (Unit* corrupter = player->SummonCreature(NPC_TWILIGHT_CORRUPTER, -10328.16f, -489.57f, 49.95f, 0, TEMPSUMMON_MANUAL_DESPAWN, 60000))
- corrupter->setFaction(FACTION_HOSTILE);
+ if (player->GetQuestStatus(QUEST_NIGHTMARES_CORRUPTION) == QUEST_STATUS_INCOMPLETE)
+ if (!player->FindNearestCreature(NPC_TWILIGHT_CORRUPTER, 500.0f, true))
+ if (Creature* corrupter = player->SummonCreature(NPC_TWILIGHT_CORRUPTER, TwillightCorrupter, TEMPSUMMON_MANUAL_DESPAWN, 60000))
+ corrupter->AI()->Talk(YELL_TWILIGHT_CORRUPTOR_RESPAWN, player);
- if (Creature* CorrupterSpeaker = player->SummonCreature(1, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()-1, 0, TEMPSUMMON_TIMED_DESPAWN, 15000))
- {
- CorrupterSpeaker->SetName("Twilight Corrupter");
- CorrupterSpeaker->SetVisible(true);
- CorrupterSpeaker->AI()->Talk(YELL_TWILIGHTCORRUPTOR_RESPAWN, player);
- }
- }
- return false;
- };
+ return false;
+ };
};
void AddSC_duskwood()
diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp
index 8d6ae347b85..358814d440a 100644
--- a/src/server/scripts/Kalimdor/zone_durotar.cpp
+++ b/src/server/scripts/Kalimdor/zone_durotar.cpp
@@ -447,7 +447,7 @@ class spell_mount_check : public SpellScriptLoader
class spell_mount_check_AuraScript : public AuraScript
{
- PrepareAuraScript(spell_mount_check_AuraScript)
+ PrepareAuraScript(spell_mount_check_AuraScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
@@ -495,7 +495,7 @@ class spell_voljin_war_drums : public SpellScriptLoader
class spell_voljin_war_drums_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_voljin_war_drums_SpellScript)
+ PrepareSpellScript(spell_voljin_war_drums_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
@@ -552,7 +552,7 @@ class spell_voodoo : public SpellScriptLoader
class spell_voodoo_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_voodoo_SpellScript)
+ PrepareSpellScript(spell_voodoo_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp
index 3f4fb31a11d..42ab3d8d9cf 100644
--- a/src/server/scripts/Kalimdor/zone_silithus.cpp
+++ b/src/server/scripts/Kalimdor/zone_silithus.cpp
@@ -1006,7 +1006,7 @@ void npc_qiraj_war_spawn::npc_qiraj_war_spawnAI::JustDied(Unit* /*slayer*/)
if (npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI* triggerAI = CAST_AI(npc_anachronos_quest_trigger::npc_anachronos_quest_triggerAI, mob->AI()))
triggerAI->LiveCounter();
-};
+}
/*#####
# go_crystalline_tear
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
index abeafe156ad..c0f7b2f1856 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp
@@ -553,7 +553,7 @@ class spell_mistress_kiss_area : public SpellScriptLoader
class spell_mistress_kiss_area_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_mistress_kiss_area_SpellScript)
+ PrepareSpellScript(spell_mistress_kiss_area_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
index 00eb970b57b..5fa52c1eb53 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
@@ -673,8 +673,7 @@ class spell_powering_up : public SpellScriptLoader
class spell_powering_up_SpellScript : public SpellScript
{
- public:
- PrepareSpellScript(spell_powering_up_SpellScript)
+ PrepareSpellScript(spell_powering_up_SpellScript);
uint32 spellId;
uint32 poweringUp;
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..0c5514a1c0a 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,1151 @@ 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();
+ _utherGUID = 0;
+ _lichkingGUID = 0;
}
- }
- 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 +1374,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 +1409,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 +1453,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 +1816,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);
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 3f0fb2f93b1..192249955cf 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -1810,7 +1810,7 @@ public:
class spell_malygos_vortex_dummy_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_malygos_vortex_dummy_SpellScript)
+ PrepareSpellScript(spell_malygos_vortex_dummy_SpellScript);
bool Load() override
{
@@ -2282,7 +2282,7 @@ class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoade
class spell_malygos_surge_of_power_warning_selector_25_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_malygos_surge_of_power_warning_selector_25_SpellScript)
+ PrepareSpellScript(spell_malygos_surge_of_power_warning_selector_25_SpellScript);
bool Load() override
{
@@ -2348,7 +2348,7 @@ class spell_malygos_surge_of_power_25 : public SpellScriptLoader
class spell_malygos_surge_of_power_25_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_malygos_surge_of_power_25_SpellScript)
+ PrepareSpellScript(spell_malygos_surge_of_power_25_SpellScript);
bool Load() override
{
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp
index 0870614ba78..585da8e28d3 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp
@@ -299,7 +299,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader
class spell_varos_energize_core_area_enemySpellScript : public SpellScript
{
- PrepareSpellScript(spell_varos_energize_core_area_enemySpellScript)
+ PrepareSpellScript(spell_varos_energize_core_area_enemySpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
@@ -343,7 +343,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader
class spell_varos_energize_core_area_entrySpellScript : public SpellScript
{
- PrepareSpellScript(spell_varos_energize_core_area_entrySpellScript)
+ PrepareSpellScript(spell_varos_energize_core_area_entrySpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
index c81cd0b0b80..07cdfa3353c 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp
@@ -15,14 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* Script Data Start
-SDName: Boss krystallus
-SDAuthor: LordVanMartin
-SD%Complete:
-SDComment:
-SDCategory:
-Script Data End */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
@@ -30,17 +22,13 @@ Script Data End */
enum Spells
{
- SPELL_BOULDER_TOSS = 50843,
- H_SPELL_BOULDER_TOSS = 59742,
- SPELL_GROUND_SPIKE = 59750,
- SPELL_GROUND_SLAM = 50827,
- SPELL_SHATTER = 50810,
- H_SPELL_SHATTER = 61546,
- SPELL_SHATTER_EFFECT = 50811,
- H_SPELL_SHATTER_EFFECT = 61547,
- SPELL_STONED = 50812,
- SPELL_STOMP = 48131,
- H_SPELL_STOMP = 59744
+ SPELL_BOULDER_TOSS = 50843,
+ SPELL_GROUND_SPIKE = 59750,
+ SPELL_GROUND_SLAM = 50827,
+ SPELL_SHATTER = 50810,
+ SPELL_SHATTER_EFFECT = 50811,
+ SPELL_STONED = 50812,
+ SPELL_STOMP = 48131
};
enum Yells
@@ -51,133 +39,103 @@ enum Yells
SAY_SHATTER = 3
};
-class boss_krystallus : public CreatureScript
+enum Events
{
-public:
- boss_krystallus() : CreatureScript("boss_krystallus") { }
-
- struct boss_krystallusAI : public ScriptedAI
- {
- boss_krystallusAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = creature->GetInstanceScript();
- }
-
- uint32 uiBoulderTossTimer;
- uint32 uiGroundSpikeTimer;
- uint32 uiGroundSlamTimer;
- uint32 uiShatterTimer;
- uint32 uiStompTimer;
-
- bool bIsSlam;
-
- InstanceScript* instance;
-
- void Reset() override
- {
- bIsSlam = false;
-
- uiBoulderTossTimer = urand(3000, 9000);
- uiGroundSpikeTimer = urand(9000, 14000);
- uiGroundSlamTimer = urand(15000, 18000);
- uiStompTimer = urand(20000, 29000);
- uiShatterTimer = 0;
-
- instance->SetBossState(DATA_KRYSTALLUS, NOT_STARTED);
- }
- void EnterCombat(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
+ EVENT_BOULDER_TOSS = 1,
+ EVENT_GROUND_SPIKE,
+ EVENT_GROUND_SLAM,
+ EVENT_STOMP,
+ EVENT_SHATTER
+};
- instance->SetBossState(DATA_KRYSTALLUS, IN_PROGRESS);
- }
+class boss_krystallus : public CreatureScript
+{
+ public:
+ boss_krystallus() : CreatureScript("boss_krystallus") { }
- void UpdateAI(uint32 diff) override
+ struct boss_krystallusAI : public BossAI
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ boss_krystallusAI(Creature* creature) : BossAI(creature, DATA_KRYSTALLUS) { }
- if (uiBoulderTossTimer <= diff)
+ void Reset() override
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_BOULDER_TOSS);
- uiBoulderTossTimer = urand(9000, 15000);
- } else uiBoulderTossTimer -= diff;
-
- if (uiGroundSpikeTimer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_GROUND_SPIKE);
- uiGroundSpikeTimer = urand(12000, 17000);
- } else uiGroundSpikeTimer -= diff;
-
- if (uiStompTimer <= diff)
- {
- DoCast(me, SPELL_STOMP);
- uiStompTimer = urand(20000, 29000);
- } else uiStompTimer -= diff;
-
- if (uiGroundSlamTimer <= diff)
- {
- DoCast(me, SPELL_GROUND_SLAM);
- bIsSlam = true;
- uiShatterTimer = 10000;
- uiGroundSlamTimer = urand(15000, 18000);
- } else uiGroundSlamTimer -= diff;
+ _Reset();
+ }
- if (bIsSlam)
+ void EnterCombat(Unit* /*who*/) override
{
- if (uiShatterTimer <= diff)
- {
- DoCast(me, DUNGEON_MODE(SPELL_SHATTER, H_SPELL_SHATTER));
- } else uiShatterTimer -= diff;
+ Talk(SAY_AGGRO);
+ _EnterCombat();
+
+ events.ScheduleEvent(EVENT_BOULDER_TOSS, urand(3000, 9000));
+ events.ScheduleEvent(EVENT_GROUND_SLAM, urand(15000, 18000));
+ events.ScheduleEvent(EVENT_STOMP, urand(20000, 29000));
+ if (IsHeroic())
+ events.ScheduleEvent(EVENT_GROUND_SPIKE, urand(9000, 14000));
}
- DoMeleeAttackIfReady();
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
-
- instance->SetBossState(DATA_KRYSTALLUS, DONE);
- }
+ void UpdateAI(uint32 diff) override
+ {
+ // Return since we have no target
+ if (!UpdateVictim())
+ return;
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
+ events.Update(diff);
- Talk(SAY_KILL);
- }
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- void SpellHitTarget(Unit* /*target*/, const SpellInfo* pSpell) override
- {
- //this part should be in the core
- if (pSpell->Id == SPELL_SHATTER || pSpell->Id == H_SPELL_SHATTER)
- {
- /// @todo we need eventmap to kill this stuff
- //clear this, if we are still performing
- if (bIsSlam)
+ while (uint32 eventId = events.ExecuteEvent())
{
- bIsSlam = false;
-
- //and correct movement, if not already
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
+ switch (eventId)
{
- if (me->GetVictim())
- me->GetMotionMaster()->MoveChase(me->GetVictim());
+ case EVENT_BOULDER_TOSS:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
+ DoCast(target, SPELL_BOULDER_TOSS);
+ events.ScheduleEvent(EVENT_BOULDER_TOSS, urand(9000, 15000));
+ break;
+ case EVENT_GROUND_SPIKE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_GROUND_SPIKE);
+ events.ScheduleEvent(EVENT_GROUND_SPIKE, urand(12000, 17000));
+ break;
+ case EVENT_GROUND_SLAM:
+ DoCast(me, SPELL_GROUND_SLAM);
+ events.ScheduleEvent(EVENT_SHATTER, 10000);
+ events.ScheduleEvent(EVENT_GROUND_SLAM, urand(15000, 18000));
+ break;
+ case EVENT_STOMP:
+ DoCast(me, SPELL_STOMP);
+ events.ScheduleEvent(EVENT_STOMP, urand(20000, 29000));
+ break;
+ case EVENT_SHATTER:
+ DoCast(me, SPELL_SHATTER);
+ break;
+ default:
+ break;
}
}
+
+ DoMeleeAttackIfReady();
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+ _JustDied();
}
- }
- };
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetHallsOfStoneAI<boss_krystallusAI>(creature);
- }
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetHallsOfStoneAI<boss_krystallusAI>(creature);
+ }
};
class spell_krystallus_shatter : public SpellScriptLoader
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index cfa5429ea79..f284aacf996 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -89,7 +89,7 @@ class spell_ulduar_proximity_mines : public SpellScriptLoader
class spell_ulduar_proximity_minesSpellScript : public SpellScript
{
- PrepareSpellScript(spell_ulduar_proximity_minesSpellScript)
+ PrepareSpellScript(spell_ulduar_proximity_minesSpellScript);
void HandleScript(SpellEffIndex effIndex)
{
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 77a4faa7e8c..4c72d790059 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -509,7 +509,7 @@ class spell_gen_break_shield: public SpellScriptLoader
class spell_gen_break_shield_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_break_shield_SpellScript)
+ PrepareSpellScript(spell_gen_break_shield_SpellScript);
void HandleScriptEffect(SpellEffIndex effIndex)
{
@@ -671,7 +671,7 @@ class spell_gen_chaos_blast : public SpellScriptLoader
class spell_gen_chaos_blast_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_chaos_blast_SpellScript)
+ PrepareSpellScript(spell_gen_chaos_blast_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
@@ -895,7 +895,7 @@ class spell_gen_count_pct_from_max_hp : public SpellScriptLoader
class spell_gen_count_pct_from_max_hp_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_count_pct_from_max_hp_SpellScript)
+ PrepareSpellScript(spell_gen_count_pct_from_max_hp_SpellScript);
public:
spell_gen_count_pct_from_max_hp_SpellScript(int32 damagePct) : SpellScript(), _damagePct(damagePct) { }
@@ -1446,6 +1446,7 @@ class spell_gen_elune_candle : public SpellScriptLoader
class spell_gen_elune_candle_SpellScript : public SpellScript
{
PrepareSpellScript(spell_gen_elune_candle_SpellScript);
+
bool Validate(SpellInfo const* /*spellInfo*/) override
{
if (!sSpellMgr->GetSpellInfo(SPELL_ELUNE_CANDLE_OMEN_HEAD) ||
@@ -1511,7 +1512,7 @@ class spell_gen_gadgetzan_transporter_backfire : public SpellScriptLoader
class spell_gen_gadgetzan_transporter_backfire_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_gadgetzan_transporter_backfire_SpellScript)
+ PrepareSpellScript(spell_gen_gadgetzan_transporter_backfire_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
@@ -1612,7 +1613,7 @@ class spell_gen_gnomish_transporter : public SpellScriptLoader
class spell_gen_gnomish_transporter_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_gnomish_transporter_SpellScript)
+ PrepareSpellScript(spell_gen_gnomish_transporter_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
@@ -2093,7 +2094,7 @@ class spell_gen_mounted_charge: public SpellScriptLoader
class spell_gen_mounted_charge_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_mounted_charge_SpellScript)
+ PrepareSpellScript(spell_gen_mounted_charge_SpellScript);
void HandleScriptEffect(SpellEffIndex effIndex)
{
@@ -2794,7 +2795,7 @@ class spell_gen_parachute_ic : public SpellScriptLoader
class spell_gen_parachute_ic_AuraScript : public AuraScript
{
- PrepareAuraScript(spell_gen_parachute_ic_AuraScript)
+ PrepareAuraScript(spell_gen_parachute_ic_AuraScript);
void HandleTriggerSpell(AuraEffect const* /*aurEff*/)
{
@@ -2842,30 +2843,28 @@ class spell_gen_pet_summoned : public SpellScriptLoader
if (player->GetLastPetNumber())
{
PetType newPetType = (player->getClass() == CLASS_HUNTER) ? HUNTER_PET : SUMMON_PET;
- if (Pet* newPet = new Pet(player, newPetType))
+ Pet* newPet = new Pet(player, newPetType);
+ if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true))
{
- if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true))
- {
- // revive the pet if it is dead
- if (newPet->getDeathState() == DEAD)
- newPet->setDeathState(ALIVE);
+ // revive the pet if it is dead
+ if (newPet->getDeathState() == DEAD)
+ newPet->setDeathState(ALIVE);
- newPet->SetFullHealth();
- newPet->SetPower(newPet->getPowerType(), newPet->GetMaxPower(newPet->getPowerType()));
+ newPet->SetFullHealth();
+ newPet->SetPower(newPet->getPowerType(), newPet->GetMaxPower(newPet->getPowerType()));
- switch (newPet->GetEntry())
- {
- case NPC_DOOMGUARD:
- case NPC_INFERNAL:
- newPet->SetEntry(NPC_IMP);
- break;
- default:
- break;
- }
+ switch (newPet->GetEntry())
+ {
+ case NPC_DOOMGUARD:
+ case NPC_INFERNAL:
+ newPet->SetEntry(NPC_IMP);
+ break;
+ default:
+ break;
}
- else
- delete newPet;
}
+ else
+ delete newPet;
}
}
@@ -3123,7 +3122,7 @@ class spell_gen_spectator_cheer_trigger : public SpellScriptLoader
class spell_gen_spectator_cheer_trigger_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_spectator_cheer_trigger_SpellScript)
+ PrepareSpellScript(spell_gen_spectator_cheer_trigger_SpellScript);
void HandleDummy(SpellEffIndex /*effIndex*/)
{
@@ -3615,7 +3614,7 @@ class spell_gen_vendor_bark_trigger : public SpellScriptLoader
class spell_gen_vendor_bark_trigger_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_gen_vendor_bark_trigger_SpellScript)
+ PrepareSpellScript(spell_gen_vendor_bark_trigger_SpellScript);
void HandleDummy(SpellEffIndex /* effIndex */)
{
diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp
index dc0c70975dd..85bf85fa2d2 100644
--- a/src/server/scripts/Spells/spell_holiday.cpp
+++ b/src/server/scripts/Spells/spell_holiday.cpp
@@ -296,7 +296,7 @@ class spell_pilgrims_bounty_buff_food : public SpellScriptLoader
class spell_pilgrims_bounty_buff_food_AuraScript : public AuraScript
{
- PrepareAuraScript(spell_pilgrims_bounty_buff_food_AuraScript)
+ PrepareAuraScript(spell_pilgrims_bounty_buff_food_AuraScript);
private:
uint32 const _triggeredSpellId;
diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp
index 590cad7007f..61ff79c505e 100644
--- a/src/server/scripts/Spells/spell_shaman.cpp
+++ b/src/server/scripts/Spells/spell_shaman.cpp
@@ -775,7 +775,7 @@ class spell_sha_lava_lash : public SpellScriptLoader
class spell_sha_lava_lash_SpellScript : public SpellScript
{
- PrepareSpellScript(spell_sha_lava_lash_SpellScript)
+ PrepareSpellScript(spell_sha_lava_lash_SpellScript);
bool Load() override
{
diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp
index 362c02e1af5..950b4cd10e9 100644
--- a/src/server/scripts/World/boss_emerald_dragons.cpp
+++ b/src/server/scripts/World/boss_emerald_dragons.cpp
@@ -781,4 +781,4 @@ void AddSC_emerald_dragons()
// dragon spellscripts
new spell_dream_fog_sleep();
new spell_mark_of_nature();
-};
+}
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index c60458323f7..3665a388854 100644
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -49,8 +49,10 @@ class DatabaseWorkerPool
{
public:
/* Activity state */
- DatabaseWorkerPool() : _queue(new ACE_Activation_Queue()), _connectionInfo(NULL)
+ DatabaseWorkerPool() : _connectionInfo(NULL)
{
+ _messageQueue = new ACE_Message_Queue<ACE_SYNCH>(8 * 1024 * 1024, 8 * 1024 * 1024);
+ _queue = new ACE_Activation_Queue(_messageQueue);
memset(_connectionCount, 0, sizeof(_connectionCount));
_connections.resize(IDX_SIZE);
@@ -131,6 +133,7 @@ class DatabaseWorkerPool
//! Deletes the ACE_Activation_Queue object and its underlying ACE_Message_Queue
delete _queue;
+ delete _messageQueue;
TC_LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName());
@@ -520,6 +523,7 @@ class DatabaseWorkerPool
IDX_SIZE
};
+ ACE_Message_Queue<ACE_SYNCH>* _messageQueue; //! Message Queue used by ACE_Activation_Queue
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
std::vector< std::vector<T*> > _connections;
uint32 _connectionCount[2]; //! Counter of MySQL connections;
diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp
index bc002668b3b..dc9bda62bfb 100644
--- a/src/server/shared/Logging/Log.cpp
+++ b/src/server/shared/Logging/Log.cpp
@@ -250,13 +250,13 @@ void Log::ReadLoggersFromConfig()
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE);
appenders[appender->getId()] = appender;
- Logger& rootLogger = loggers[LOGGER_ROOT];
- rootLogger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR);
- rootLogger.addAppender(appender->getId(), appender);
+ Logger& logger = loggers[LOGGER_ROOT];
+ logger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR);
+ logger.addAppender(appender->getId(), appender);
- Logger& serverLogger = loggers["server"];
- serverLogger.Create("server", LOG_LEVEL_INFO);
- serverLogger.addAppender(appender->getId(), appender);
+ logger = loggers["server"];
+ logger.Create("server", LOG_LEVEL_ERROR);
+ logger.addAppender(appender->getId(), appender);
}
}
@@ -267,7 +267,7 @@ void Log::vlog(std::string const& filter, LogLevel level, char const* str, va_li
write(new LogMessage(level, filter, text));
}
-void Log::write(LogMessage* msg)
+void Log::write(LogMessage* msg) const
{
Logger const* logger = GetLoggerByType(msg->type);
msg->text.append("\n");
@@ -376,7 +376,6 @@ void Log::Close()
delete worker;
worker = NULL;
loggers.clear();
- cachedLoggers.clear();
for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
{
delete it->second;
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 5fa638e2f40..a118e6e8773 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -35,7 +35,6 @@ class Log
friend class ACE_Singleton<Log, ACE_Thread_Mutex>;
typedef std::unordered_map<std::string, Logger> LoggerMap;
- typedef std::unordered_map<std::string, Logger const*> CachedLoggerContainer;
private:
Log();
@@ -44,7 +43,7 @@ class Log
public:
void LoadFromConfig();
void Close();
- bool ShouldLog(std::string const& type, LogLevel level);
+ bool ShouldLog(std::string const& type, LogLevel level) const;
bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true);
void outMessage(std::string const& f, LogLevel level, char const* str, ...) ATTR_PRINTF(4, 5);
@@ -57,9 +56,9 @@ class Log
private:
static std::string GetTimestampStr();
void vlog(std::string const& f, LogLevel level, char const* str, va_list argptr);
- void write(LogMessage* msg);
+ void write(LogMessage* msg) const;
- Logger const* GetLoggerByType(std::string const& type);
+ Logger const* GetLoggerByType(std::string const& type) const;
Appender* GetAppenderByName(std::string const& name);
uint8 NextAppenderId();
void CreateAppenderFromConfig(std::string const& name);
@@ -69,7 +68,6 @@ class Log
AppenderMap appenders;
LoggerMap loggers;
- CachedLoggerContainer cachedLoggers;
uint8 AppenderId;
std::string m_logsDir;
@@ -78,37 +76,29 @@ class Log
LogWorker* worker;
};
-inline Logger const* Log::GetLoggerByType(std::string const& originalType)
+inline Logger const* Log::GetLoggerByType(std::string const& type) const
{
- // Check if already cached
- CachedLoggerContainer::const_iterator itCached = cachedLoggers.find(originalType);
- if (itCached != cachedLoggers.end())
- return itCached->second;
-
- Logger const* logger = NULL;
- std::string type(originalType);
-
- do
- {
- // Search for the logger "type.subtype"
- LoggerMap::const_iterator it = loggers.find(type);
- if (it == loggers.end())
- {
- // Search for the logger "type", if our logger contains '.', otherwise search for LOGGER_ROOT
- size_t found = type.find_last_of(".");
- type = found != std::string::npos ? type.substr(0, found) : LOGGER_ROOT;
- }
- else
- logger = &(it->second);
- }
- while (!logger);
-
- cachedLoggers[originalType] = logger;
- return logger;
+ LoggerMap::const_iterator it = loggers.find(type);
+ if (it != loggers.end())
+ return &(it->second);
+
+ if (type == LOGGER_ROOT)
+ return NULL;
+
+ std::string parentLogger = LOGGER_ROOT;
+ size_t found = type.find_last_of(".");
+ if (found != std::string::npos)
+ parentLogger = type.substr(0,found);
+
+ return GetLoggerByType(parentLogger);
}
-inline bool Log::ShouldLog(std::string const& type, LogLevel level)
+inline bool Log::ShouldLog(std::string const& type, LogLevel level) const
{
+ // TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should
+ // Speed up in cases where requesting "Type.sub1.sub2" but only configured
+ // Logger "Type"
+
Logger const* logger = GetLoggerByType(type);
if (!logger)
return false;
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index bc46b87fa27..dd0a9d5fdf4 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -377,9 +377,19 @@ class ByteBuffer
return *this;
}
- uint8 * contents() { return &_storage[0]; }
+ uint8 * contents()
+ {
+ if (_storage.empty())
+ throw ByteBufferException();
+ return &_storage[0];
+ }
- const uint8 *contents() const { return &_storage[0]; }
+ const uint8 *contents() const
+ {
+ if (_storage.empty())
+ throw ByteBufferException();
+ return &_storage[0];
+ }
size_t size() const { return _storage.size(); }
bool empty() const { return _storage.empty(); }
diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp
index 19112d84266..7832cef18de 100644
--- a/src/tools/mmaps_generator/TerrainBuilder.cpp
+++ b/src/tools/mmaps_generator/TerrainBuilder.cpp
@@ -906,7 +906,7 @@ namespace MMAP
float p0[3], p1[3];
uint32 mid, tx, ty;
float size;
- if (sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty,
+ if (sscanf(buf, "%u %u,%u (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty,
&p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size) != 10)
continue;