aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Main.cpp112
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp4
-rw-r--r--src/server/game/Accounts/RBAC.h6
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp7
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp122
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.h6
-rw-r--r--src/server/game/Chat/Channels/Channel.h2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp5
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp6
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp31
-rw-r--r--src/server/game/Entities/Creature/Creature.h12
-rw-r--r--src/server/game/Entities/Object/Position.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp4
-rw-r--r--src/server/game/Entities/Player/Player.h10
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp42
-rw-r--r--src/server/game/Entities/Unit/Unit.h20
-rw-r--r--src/server/game/Events/GameEventMgr.h2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp8
-rw-r--r--src/server/game/Groups/Group.cpp3
-rw-r--r--src/server/game/Groups/Group.h2
-rw-r--r--src/server/game/Handlers/BattleGroundHandler.cpp8
-rw-r--r--src/server/game/Maps/ZoneScript.h4
-rw-r--r--src/server/game/Movement/MotionMaster.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp2
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp35
-rw-r--r--src/server/game/Spells/SpellHistory.cpp2
-rw-r--r--src/server/game/Spells/SpellInfo.cpp2
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp3
-rw-r--r--src/server/game/Spells/SpellScript.cpp4
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp26
-rw-r--r--src/server/game/Texts/CreatureTextMgr.h6
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp4
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp71
-rw-r--r--src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_moonglade.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp6
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h12
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp20
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp43
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_erekem.cpp45
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp70
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp56
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_moragg.cpp34
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp75
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp40
-rw-r--r--src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp467
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.cpp190
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.h71
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPNA.h8
-rw-r--r--src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp2
-rw-r--r--src/server/scripts/Outland/CMakeLists.txt1
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp6
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp253
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp255
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h22
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp21
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp35
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp75
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp22
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp123
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/the_eye.h30
-rw-r--r--src/server/scripts/Outland/zone_hellfire_peninsula.cpp7
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp23
-rw-r--r--src/server/shared/Cryptography/SHA1.h4
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp213
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h5
-rw-r--r--src/server/shared/PrecompiledHeaders/sharedPCH.h1
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp19
-rw-r--r--src/server/shared/Utilities/TaskScheduler.cpp208
-rw-r--r--src/server/shared/Utilities/TaskScheduler.h627
-rw-r--r--src/server/worldserver/worldserver.conf.dist2
-rw-r--r--src/tools/map_extractor/mpq_libmpq.cpp2
-rw-r--r--src/tools/map_extractor/mpq_libmpq04.h2
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq.cpp2
-rw-r--r--src/tools/vmap4_extractor/mpq_libmpq04.h2
84 files changed, 2263 insertions, 1434 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index c748e9d28a8..15ab1c38925 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -46,25 +46,52 @@ using namespace boost::program_options;
# define _TRINITY_REALM_CONFIG "authserver.conf"
#endif
+#if PLATFORM == PLATFORM_WINDOWS
+#include "ServiceWin32.h"
+char serviceName[] = "authserver";
+char serviceLongName[] = "TrinityCore auth service";
+char serviceDescription[] = "TrinityCore World of Warcraft emulator auth service";
+/*
+* -1 - not in service mode
+* 0 - stopped
+* 1 - running
+* 2 - paused
+*/
+int m_ServiceStatus = -1;
+
+boost::asio::deadline_timer* _serviceStatusWatchTimer;
+void ServiceStatusWatcher(boost::system::error_code const& error);
+#endif
+
bool StartDB();
void StopDB();
void SignalHandler(const boost::system::error_code& error, int signalNumber);
void KeepDatabaseAliveHandler(const boost::system::error_code& error);
-variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile);
+variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService);
-boost::asio::io_service _ioService;
-boost::asio::deadline_timer _dbPingTimer(_ioService);
+boost::asio::io_service* _ioService;
+boost::asio::deadline_timer* _dbPingTimer;
uint32 _dbPingInterval;
LoginDatabaseWorkerPool LoginDatabase;
int main(int argc, char** argv)
{
std::string configFile = _TRINITY_REALM_CONFIG;
- auto vm = GetConsoleArguments(argc, argv, configFile);
+ std::string configService;
+ auto vm = GetConsoleArguments(argc, argv, configFile, configService);
// exit if help is enabled
if (vm.count("help"))
return 0;
+#if PLATFORM == PLATFORM_WINDOWS
+ if (configService.compare("install") == 0)
+ return WinServiceInstall() == true ? 0 : 1;
+ else if (configService.compare("uninstall") == 0)
+ return WinServiceUninstall() == true ? 0 : 1;
+ else if (configService.compare("run") == 0)
+ return WinServiceRun() ? 0 : 1;
+#endif
+
std::string configError;
if (!sConfigMgr->LoadInitial(configFile, configError))
{
@@ -95,13 +122,16 @@ int main(int argc, char** argv)
if (!StartDB())
return 1;
+ _ioService = new boost::asio::io_service();
+
// Get the list of realms for the server
- sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
+ sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
if (sRealmList->size() == 0)
{
TC_LOG_ERROR("server.authserver", "No valid realms specified.");
StopDB();
+ delete _ioService;
return 1;
}
@@ -111,15 +141,16 @@ int main(int argc, char** argv)
{
TC_LOG_ERROR("server.authserver", "Specified port out of allowed range (1-65535)");
StopDB();
+ delete _ioService;
return 1;
}
std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");
- sAuthSocketMgr.StartNetwork(_ioService, bindIp, port);
+ sAuthSocketMgr.StartNetwork(*_ioService, bindIp, port);
// Set signal handlers
- boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM);
+ boost::asio::signal_set signals(*_ioService, SIGINT, SIGTERM);
#if PLATFORM == PLATFORM_WINDOWS
signals.add(SIGBREAK);
#endif
@@ -130,20 +161,38 @@ int main(int argc, char** argv)
// Enabled a timed callback for handling the database keep alive ping
_dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30);
- _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval));
- _dbPingTimer.async_wait(KeepDatabaseAliveHandler);
+ _dbPingTimer = new boost::asio::deadline_timer(*_ioService);
+ _dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval));
+ _dbPingTimer->async_wait(KeepDatabaseAliveHandler);
+
+#if PLATFORM == PLATFORM_WINDOWS
+ if (m_ServiceStatus != -1)
+ {
+ _serviceStatusWatchTimer = new boost::asio::deadline_timer(*_ioService);
+ _serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1));
+ _serviceStatusWatchTimer->async_wait(ServiceStatusWatcher);
+ }
+#endif
// Start the io service worker loop
- _ioService.run();
+ _ioService->run();
+
+ _dbPingTimer->cancel();
+
+ sAuthSocketMgr.StopNetwork();
// Close the Database Pool and library
StopDB();
TC_LOG_INFO("server.authserver", "Halting process...");
+
+ signals.cancel();
+
+ delete _dbPingTimer;
+ delete _ioService;
return 0;
}
-
/// Initialize connection to the database
bool StartDB()
{
@@ -174,7 +223,7 @@ void StopDB()
void SignalHandler(const boost::system::error_code& error, int /*signalNumber*/)
{
if (!error)
- _ioService.stop();
+ _ioService->stop();
}
void KeepDatabaseAliveHandler(const boost::system::error_code& error)
@@ -184,31 +233,58 @@ void KeepDatabaseAliveHandler(const boost::system::error_code& error)
TC_LOG_INFO("server.authserver", "Ping MySQL to keep connection alive");
LoginDatabase.KeepAlive();
- _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval));
- _dbPingTimer.async_wait(KeepDatabaseAliveHandler);
+ _dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval));
+ _dbPingTimer->async_wait(KeepDatabaseAliveHandler);
}
}
-variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile)
+#if PLATFORM == PLATFORM_WINDOWS
+void ServiceStatusWatcher(boost::system::error_code const& error)
+{
+ if (!error)
+ {
+ if (m_ServiceStatus == 0)
+ {
+ _ioService->stop();
+ delete _serviceStatusWatchTimer;
+ }
+ else
+ {
+ _serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1));
+ _serviceStatusWatchTimer->async_wait(ServiceStatusWatcher);
+ }
+ }
+}
+#endif
+
+variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService)
{
options_description all("Allowed options");
all.add_options()
("help,h", "print usage message")
("config,c", value<std::string>(&configFile)->default_value(_TRINITY_REALM_CONFIG), "use <arg> as configuration file")
;
+#if PLATFORM == PLATFORM_WINDOWS
+ options_description win("Windows platform specific options");
+ win.add_options()
+ ("service,s", value<std::string>(&configService)->default_value(""), "Windows service options: [install | uninstall]")
+ ;
+
+ all.add(win);
+#endif
variables_map variablesMap;
try
{
store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap);
notify(variablesMap);
}
- catch (std::exception& e) {
+ catch (std::exception& e)
+ {
std::cerr << e.what() << "\n";
}
- if (variablesMap.count("help")) {
+ if (variablesMap.count("help"))
std::cout << all << "\n";
- }
return variablesMap;
}
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 9eafcc30c81..efe55830b1b 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -128,7 +128,7 @@ class UnitAI
virtual void InitializeAI() { if (!me->isDead()) Reset(); }
- virtual void Reset() { };
+ virtual void Reset() { }
// Called when unit is charmed
virtual void OnCharmed(bool apply) = 0;
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 20a7ca05d93..21a15fa4f99 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -581,7 +581,11 @@ void SmartAI::JustDied(Unit* killer)
{
GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, killer);
if (HasEscortState(SMART_ESCORT_ESCORTING))
+ {
EndPath(true);
+ me->StopMoving();//force stop
+ me->GetMotionMaster()->MoveIdle();
+ }
}
void SmartAI::KilledUnit(Unit* victim)
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 8f9db8d5a27..339788dee01 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -802,6 +802,7 @@ class RBACData
* @return Success or failure (with reason) to grant the permission
*
* Example Usage:
+ * @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST)
@@ -825,6 +826,7 @@ class RBACData
* @return Success or failure (with reason) to deny the permission
*
* Example Usage:
+ * @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS)
@@ -849,6 +851,7 @@ class RBACData
* @return Success or failure (with reason) to remove the permission
*
* Example Usage:
+ * @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->RevokeRole(permissionId) == RBAC_OK)
@@ -939,9 +942,6 @@ class RBACData
*
* Given a list of permissions, gets all the inherited permissions
* @param permissions The list of permissions to expand
- *
- * @return new list of permissions containing original permissions and
- * all other pemissions that are linked to the original ones
*/
void ExpandPermissions(RBACPermissionContainer& permissions);
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index d9db2a9b5d1..43b7acde925 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -889,7 +889,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
// (after what time the ratings aren't taken into account when making teams) then
// the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
// else leave the discard time on 0, this way all ratings will be discarded
- uint32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer();
+ // this has to be signed value - when the server starts, this value would be negative and thus overflow
+ int32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer();
// we need to find 2 teams which will play next game
GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT];
@@ -905,7 +906,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
// if group match conditions, then add it to pool
if (!(*itr2)->IsInvitedToBGInstanceGUID
&& (((*itr2)->ArenaMatchmakerRating >= arenaMinRating && (*itr2)->ArenaMatchmakerRating <= arenaMaxRating)
- || (*itr2)->JoinTime < discardTime))
+ || (int32)(*itr2)->JoinTime < discardTime))
{
itr_teams[found++] = itr2;
team = i;
@@ -923,7 +924,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
{
if (!(*itr3)->IsInvitedToBGInstanceGUID
&& (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating)
- || (*itr3)->JoinTime < discardTime)
+ || (int32)(*itr3)->JoinTime < discardTime)
&& (*itr_teams[0])->ArenaTeamId != (*itr3)->ArenaTeamId)
{
itr_teams[found++] = itr3;
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
index b0adaa4078d..7e8debfd24d 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.h
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.h
@@ -106,7 +106,7 @@ class BattlegroundQueue
class SelectionPool
{
public:
- SelectionPool(): PlayerCount(0) { };
+ SelectionPool(): PlayerCount(0) { }
void Init();
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
bool KickGroup(uint32 size);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index e14e9fadafc..f267bf7c6c6 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -99,7 +99,7 @@ bool BattlegroundSA::ResetObjs()
for (uint8 i = BG_SA_MAXNPC; i < BG_SA_MAXNPC + BG_SA_MAX_GY; i++)
DelCreature(i);
- for (uint8 i = 0; i < 6; i++)
+ for (uint8 i = 0; i < MAX_GATES; ++i)
GateStatus[i] = BG_SA_GATE_OK;
if (!AddCreature(BG_SA_NpcEntries[BG_SA_NPC_KANRETHAD], BG_SA_NPC_KANRETHAD, BG_SA_NpcSpawnlocs[BG_SA_NPC_KANRETHAD]))
@@ -179,9 +179,6 @@ bool BattlegroundSA::ResetObjs()
GetBGObject(BG_SA_TITAN_RELIC)->SetFaction(atF);
GetBGObject(BG_SA_TITAN_RELIC)->Refresh();
- for (uint8 i = 0; i <= 5; i++)
- GateStatus[i] = BG_SA_GATE_OK;
-
TotalTime = 0;
ShipsStarted = false;
@@ -221,6 +218,8 @@ bool BattlegroundSA::ResetObjs()
GetBGObject(i)->SetFaction(atF);
}
+ UpdateObjectInteractionFlags();
+
for (uint8 i = BG_SA_BOMB; i < BG_SA_MAXOBJ; i++)
{
if (!AddObject(i, BG_SA_ObjEntries[BG_SA_BOMB], BG_SA_ObjSpawnlocs[i], 0, 0, 0, 0, RESPAWN_ONE_DAY))
@@ -481,28 +480,7 @@ void BattlegroundSA::AddPlayer(Player* player)
SendTransportInit(player);
- if (!ShipsStarted)
- {
- if (player->GetTeamId() == Attackers)
- {
- player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
-
- if (urand(0, 1))
- player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
- else
- player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
-
- }
- else
- player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
- }
- else
- {
- if (player->GetTeamId() == Attackers)
- player->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
- else
- player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
- }
+ TeleportToEntrancePosition(player);
}
void BattlegroundSA::RemovePlayer(Player* /*player*/, ObjectGuid /*guid*/, uint32 /*team*/) { }
@@ -533,23 +511,31 @@ void BattlegroundSA::TeleportPlayers()
player->ResetAllPowers();
player->CombatStopWithPets(true);
- for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
- if (Player* p = ObjectAccessor::FindPlayer(itr->first))
- p->CastSpell(p, SPELL_PREPARATION, true);
+ player->CastSpell(player, SPELL_PREPARATION, true);
- if (player->GetTeamId() == Attackers)
- {
- player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+ TeleportToEntrancePosition(player);
+ }
+ }
+}
- if (urand(0, 1))
- player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
- else
- player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
- }
+void BattlegroundSA::TeleportToEntrancePosition(Player* player)
+{
+ if (player->GetTeamId() == Attackers)
+ {
+ if (!ShipsStarted)
+ {
+ player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
+
+ if (urand(0, 1))
+ player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else
- player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
+ player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
}
+ else
+ player->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
}
+ else
+ player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
}
void BattlegroundSA::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker /*= NULL*/)
@@ -628,6 +614,8 @@ void BattlegroundSA::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject*
}
}
}
+
+ UpdateObjectInteractionFlags();
}
else
break;
@@ -711,7 +699,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player)
safeloc = BG_SA_GYEntries[BG_SA_DEFENDER_LAST_GY];
closest = sWorldSafeLocsStore.LookupEntry(safeloc);
- nearest = std::sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y) + (closest->z - z)*(closest->z - z));
+ nearest = player->GetExactDistSq(closest->x, closest->y, closest->z);
for (uint8 i = BG_SA_RIGHT_CAPTURABLE_GY; i < BG_SA_MAX_GY; i++)
{
@@ -719,7 +707,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player)
continue;
ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
- dist = std::sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y) + (ret->z - z)*(ret->z - z));
+ dist = player->GetExactDistSq(ret->x, ret->y, ret->z);
if (dist < nearest)
{
closest = ret;
@@ -738,23 +726,66 @@ void BattlegroundSA::SendTime()
UpdateWorldState(BG_SA_TIMER_SEC_DECS, ((end_of_round%60000)%10000)/1000);
}
+bool BattlegroundSA::CanInteractWithObject(uint32 objectId)
+{
+ switch (objectId)
+ {
+ case BG_SA_TITAN_RELIC:
+ if (GateStatus[BG_SA_ANCIENT_GATE] != BG_SA_GATE_DESTROYED || GateStatus[BG_SA_YELLOW_GATE] != BG_SA_GATE_DESTROYED)
+ return false;
+ // no break
+ case BG_SA_CENTRAL_FLAG:
+ if (GateStatus[BG_SA_RED_GATE] != BG_SA_GATE_DESTROYED && GateStatus[BG_SA_PURPLE_GATE] != BG_SA_GATE_DESTROYED)
+ return false;
+ // no break
+ case BG_SA_LEFT_FLAG:
+ case BG_SA_RIGHT_FLAG:
+ if (GateStatus[BG_SA_GREEN_GATE] != BG_SA_GATE_DESTROYED && GateStatus[BG_SA_BLUE_GATE] != BG_SA_GATE_DESTROYED)
+ return false;
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+
+ return true;
+}
+
+void BattlegroundSA::UpdateObjectInteractionFlags(uint32 objectId)
+{
+ if (GameObject* go = GetBGObject(objectId))
+ {
+ if (CanInteractWithObject(objectId))
+ go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ else
+ go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ }
+}
+
+void BattlegroundSA::UpdateObjectInteractionFlags()
+{
+ for (uint8 i = BG_SA_CENTRAL_FLAG; i <= BG_SA_LEFT_FLAG; ++i)
+ UpdateObjectInteractionFlags(i);
+ UpdateObjectInteractionFlags(BG_SA_TITAN_RELIC);
+}
+
void BattlegroundSA::EventPlayerClickedOnFlag(Player* source, GameObject* go)
{
switch (go->GetEntry())
{
case 191307:
case 191308:
- if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)
+ if (CanInteractWithObject(BG_SA_LEFT_FLAG))
CaptureGraveyard(BG_SA_LEFT_CAPTURABLE_GY, source);
break;
case 191305:
case 191306:
- if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)
+ if (CanInteractWithObject(BG_SA_RIGHT_FLAG))
CaptureGraveyard(BG_SA_RIGHT_CAPTURABLE_GY, source);
break;
case 191310:
case 191309:
- if ((GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) && (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED))
+ if (CanInteractWithObject(BG_SA_CENTRAL_FLAG))
CaptureGraveyard(BG_SA_CENTRAL_CAPTURABLE_GY, source);
break;
default:
@@ -856,10 +887,7 @@ void BattlegroundSA::TitanRelicActivated(Player* clicker)
if (!clicker)
return;
- if (GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED &&
- GateStatus[BG_SA_YELLOW_GATE] == BG_SA_GATE_DESTROYED &&
- (GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) &&
- (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED))
+ if (CanInteractWithObject(BG_SA_TITAN_RELIC))
{
if (clicker->GetTeamId() == Attackers)
{
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
index 7f9a656c979..118cea41a7b 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h
@@ -620,6 +620,7 @@ class BattlegroundSA : public Battleground
* -Teleport all players to good location
*/
void TeleportPlayers();
+ void TeleportToEntrancePosition(Player* player);
/**
* \brief Called on start and between the two round
* -Update faction of all vehicle
@@ -627,6 +628,11 @@ class BattlegroundSA : public Battleground
void OverrideGunFaction();
/// Set selectable or not demolisher, called on battle start, when boats arrive to dock
void DemolisherStartState(bool start);
+ /// Checks if a player can interact with the given object
+ bool CanInteractWithObject(uint32 objectId);
+ /// Updates interaction flags of specific objects
+ void UpdateObjectInteractionFlags(uint32 objectId);
+ void UpdateObjectInteractionFlags();
/**
* \brief Called when a gate is destroy
* -Give honor to player witch destroy it
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 9b9c2f1e514..0f2a940e3b4 100644
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -184,7 +184,7 @@ class Channel
void DeVoice(ObjectGuid guid1, ObjectGuid guid2);
void JoinNotify(ObjectGuid guid); // invisible notify
void LeaveNotify(ObjectGuid guid); // invisible notify
- void SetOwnership(bool ownership) { _ownership = ownership; };
+ void SetOwnership(bool ownership) { _ownership = ownership; }
static void CleanOldChannelsInDB();
private:
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 25fbef2ca86..b05f9ac2a0d 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1535,6 +1535,9 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
if (!((1 << i) & cond->SourceGroup))
continue;
+ if (spellInfo->Effects[i].ChainTarget > 0)
+ continue;
+
switch (spellInfo->Effects[i].TargetA.GetSelectionCategory())
{
case TARGET_SELECT_CATEGORY_NEARBY:
@@ -1555,7 +1558,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
break;
}
- TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
+ TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
cond->SourceGroup &= ~(1 << i);
}
// all effects were removed, no need to add the condition at all
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index f07e4e7113f..5ad94948cd0 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -410,6 +410,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
joinData.result = LFG_JOIN_RANDOM_COOLDOWN;
else if (dungeons.empty())
joinData.result = LFG_JOIN_NOT_MEET_REQS;
+ else if (player->HasAura(9454)) // check Freeze debuff
+ joinData.result = LFG_JOIN_NOT_MEET_REQS;
else if (grp)
{
if (grp->GetMembersCount() > MAXGROUPSIZE)
@@ -429,6 +431,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
joinData.result = LFG_JOIN_PARTY_RANDOM_COOLDOWN;
else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue())
joinData.result = LFG_JOIN_USING_BG_SYSTEM;
+ else if (plrg->HasAura(9454)) // check Freeze debuff
+ joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS;
++memberCount;
players.insert(plrg->GetGUID());
}
@@ -1281,6 +1285,8 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*
error = LFG_TELEPORTERROR_IN_VEHICLE;
else if (player->GetCharmGUID())
error = LFG_TELEPORTERROR_CHARMING;
+ else if (player->HasAura(9454)) // check Freeze debuff
+ error = LFG_TELEPORTERROR_INVALID_LOCATION;
else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance
{
uint32 mapid = dungeon->map;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 7f00fc7f9d8..809c76c260a 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1370,9 +1370,6 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const
if (IsCivilian())
return false;
- if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
- return false;
-
// Do not attack non-combat pets
if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
@@ -2415,7 +2412,7 @@ bool Creature::SetSwim(bool enable)
return true;
}
-bool Creature::SetCanFly(bool enable)
+bool Creature::SetCanFly(bool enable, bool /*packetOnly = false */)
{
if (!Unit::SetCanFly(enable))
return false;
@@ -2638,3 +2635,29 @@ void Creature::StartPickPocketRefillTimer()
_pickpocketLootRestore = time(NULL) + sWorld->getIntConfig(CONFIG_CREATURE_PICKPOCKET_REFILL);
}
+void Creature::SetTextRepeatId(uint8 textGroup, uint8 id)
+{
+ CreatureTextRepeatIds& repeats = m_textRepeat[textGroup];
+ if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
+ repeats.push_back(id);
+ else
+ TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), GetName().c_str(), GetGUIDLow(), GetEntry(), uint32(id));
+}
+
+CreatureTextRepeatIds Creature::GetTextRepeatGroup(uint8 textGroup)
+{
+ CreatureTextRepeatIds ids;
+
+ CreatureTextRepeatGroup::const_iterator groupItr = m_textRepeat.find(textGroup);
+ if (groupItr != m_textRepeat.end())
+ ids = groupItr->second;
+
+ return ids;
+}
+
+void Creature::ClearTextRepeatGroup(uint8 textGroup)
+{
+ CreatureTextRepeatGroup::iterator groupItr = m_textRepeat.find(textGroup);
+ if (groupItr != m_textRepeat.end())
+ groupItr->second.clear();
+}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 6f82d5dda4a..585bc137e0b 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -409,6 +409,10 @@ struct TrainerSpellData
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
+//used for handling non-repeatable random texts
+typedef std::vector<uint8> CreatureTextRepeatIds;
+typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
+
class Creature : public Unit, public GridObject<Creature>, public MapObject
{
public:
@@ -472,7 +476,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
bool SetWalk(bool enable) override;
bool SetDisableGravity(bool disable, bool packetOnly = false) override;
bool SetSwim(bool enable) override;
- bool SetCanFly(bool enable) override;
+ bool SetCanFly(bool enable, bool packetOnly = false) override;
bool SetWaterWalking(bool enable, bool packetOnly = false) override;
bool SetFeatherFall(bool enable, bool packetOnly = false) override;
bool SetHover(bool enable, bool packetOnly = false) override;
@@ -656,6 +660,10 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
void FocusTarget(Spell const* focusSpell, WorldObject const* target);
void ReleaseFocus(Spell const* focusSpell);
+ CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup);
+ void SetTextRepeatId(uint8 textGroup, uint8 id);
+ void ClearTextRepeatGroup(uint8 textGroup);
+
protected:
bool CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0);
bool InitEntry(uint32 entry, CreatureData const* data = nullptr);
@@ -720,6 +728,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
bool TriggerJustRespawned;
Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
+
+ CreatureTextRepeatGroup m_textRepeat;
};
class AssistDelayEvent : public BasicEvent
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp
index e31b913a25a..530e51cd8f5 100644
--- a/src/server/game/Entities/Object/Position.cpp
+++ b/src/server/game/Entities/Object/Position.cpp
@@ -17,6 +17,8 @@
#include "Position.h"
#include "ByteBuffer.h"
+#include "G3D/g3dmath.h"
+#include "GridDefines.h"
bool Position::operator==(Position const &a)
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 030c2a25110..275dbf92dca 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -26251,9 +26251,9 @@ bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/)
return true;
}
-bool Player::SetCanFly(bool apply)
+bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/)
{
- if (!Unit::SetCanFly(apply))
+ if (!packetOnly && !Unit::SetCanFly(apply))
return false;
WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index af640e4c73c..98b9d8a3d07 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -346,9 +346,9 @@ struct Runes
struct EnchantDuration
{
- EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { };
+ EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { }
EnchantDuration(Item* _item, EnchantmentSlot _slot, uint32 _leftduration) : item(_item), slot(_slot),
- leftduration(_leftduration){ ASSERT(item); };
+ leftduration(_leftduration){ ASSERT(item); }
Item* item;
EnchantmentSlot slot;
@@ -1664,7 +1664,7 @@ class Player : public Unit, public GridObject<Player>
void setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana);
void clearResurrectRequestData() { setResurrectRequestData(ObjectGuid::Empty, 0, 0.0f, 0.0f, 0.0f, 0, 0); }
- bool isResurrectRequestedBy(ObjectGuid guid) const { return m_resurrectGUID == guid; }
+ bool isResurrectRequestedBy(ObjectGuid guid) const { return !m_resurrectGUID.IsEmpty() && m_resurrectGUID == guid; }
bool isResurrectRequested() const { return !m_resurrectGUID.IsEmpty(); }
void ResurrectUsingRequestData();
@@ -1839,7 +1839,7 @@ class Player : public Unit, public GridObject<Player>
bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
void UpdateUnderwaterState(Map* m, float x, float y, float z) override;
- void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); };// overwrite Object::SendMessageToSet
+ void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet
void SendMessageToSetInRange(WorldPacket* data, float fist, bool self) override;// overwrite Object::SendMessageToSetInRange
void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr) override;
@@ -2301,7 +2301,7 @@ class Player : public Unit, public GridObject<Player>
void RemoveFromWhisperWhiteList(ObjectGuid guid) { WhisperList.remove(guid); }
bool SetDisableGravity(bool disable, bool packetOnly /* = false */) override;
- bool SetCanFly(bool apply) override;
+ bool SetCanFly(bool apply, bool packetOnly = false) override;
bool SetWaterWalking(bool apply, bool packetOnly = false) override;
bool SetFeatherFall(bool apply, bool packetOnly = false) override;
bool SetHover(bool enable, bool packetOnly = false) override;
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 85dccddf186..6d98a4c78b2 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -226,7 +226,7 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
-void Transport::DelayedUpdate(uint32 diff)
+void Transport::DelayedUpdate(uint32 /*diff*/)
{
if (GetKeyFrames().size() <= 1)
return;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 219ee8b1002..9b0da57fa31 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -9949,11 +9949,15 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
- // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
- float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype));
- // apply spellmod to Done damage (flat and pct)
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
+ float tmpDamage = float(int32(pdamage) + DoneTotal);
+ // SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicDamageAurasTick.
+ if (damagetype != DOT)
+ {
+ tmpDamage *= SpellDamagePctDone(victim, spellProto, damagetype);
+ // apply spellmod to Done damage (flat and pct)
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
+ }
return uint32(std::max(tmpDamage, 0.0f));
}
@@ -10793,11 +10797,15 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
DoneTotal = 0;
}
- // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
- float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto));
- // apply spellmod to Done amount
- if (Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
+ float heal = float(int32(healamount) + DoneTotal);
+ // SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicHealAurasTick.
+ if (damagetype != DOT)
+ {
+ heal *= SpellHealingPctDone(victim, spellProto);
+ // apply spellmod to Done amount
+ if (Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, heal);
+ }
return uint32(std::max(heal, 0.0f));
}
@@ -12286,6 +12294,13 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
/// @todo possible affect only on MOVE_RUN
if (int32 normalization = GetMaxPositiveAuraModifier(SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED))
{
+ if (Creature* creature = ToCreature())
+ {
+ uint32 immuneMask = creature->GetCreatureTemplate()->MechanicImmuneMask;
+ if (immuneMask & (1 << MECHANIC_SNARE) || immuneMask & (1 << MECHANIC_DAZE))
+ break;
+ }
+
// Use speed from aura
float max_speed = normalization / (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]);
if (speed > max_speed)
@@ -16440,7 +16455,7 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
float vcos, vsin;
GetSinCos(x, y, vsin, vcos);
- WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
+ WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8 + 4 + 4 + 4 + 4 + 4));
data << GetPackGUID();
data << uint32(0); // counter
data << float(vcos); // x direction
@@ -16449,6 +16464,9 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
data << float(-speedZ); // Z Movement speed (vertical)
player->GetSession()->SendPacket(&data);
+
+ if (player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_FLY))
+ player->SetCanFly(true, true);
}
}
@@ -17507,7 +17525,7 @@ bool Unit::SetSwim(bool enable)
return true;
}
-bool Unit::SetCanFly(bool enable)
+bool Unit::SetCanFly(bool enable, bool /*packetOnly = false */)
{
if (enable == HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
return false;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 088a0bbdf73..2593ca2c728 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -273,13 +273,6 @@ enum UnitRename
#define MAX_AGGRO_RESET_TIME 10 // in seconds
#define MAX_AGGRO_RADIUS 45.0f // yards
-enum Swing
-{
- NOSWING = 0,
- SINGLEHANDEDSWING = 1,
- TWOHANDEDSWING = 2
-};
-
enum VictimState
{
VICTIMSTATE_INTACT = 0, // set when attacker misses
@@ -356,7 +349,7 @@ class TransportBase;
class SpellCastTargets;
typedef std::list<Unit*> UnitList;
-typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
+typedef std::list<std::pair<Aura*, uint8>> DispelChargesList;
struct SpellImmune
{
@@ -381,13 +374,6 @@ enum WeaponDamageRange
MAXDAMAGE
};
-enum DamageTypeToSchool
-{
- RESISTANCE,
- DAMAGE_DEALT,
- DAMAGE_TAKEN
-};
-
enum AuraRemoveMode
{
AURA_REMOVE_NONE = 0,
@@ -1583,7 +1569,7 @@ class Unit : public WorldObject
virtual bool SetWalk(bool enable);
virtual bool SetDisableGravity(bool disable, bool packetOnly = false);
virtual bool SetSwim(bool enable);
- virtual bool SetCanFly(bool enable);
+ virtual bool SetCanFly(bool enable, bool packetOnly = false);
virtual bool SetWaterWalking(bool enable, bool packetOnly = false);
virtual bool SetFeatherFall(bool enable, bool packetOnly = false);
virtual bool SetHover(bool enable, bool packetOnly = false);
@@ -1896,7 +1882,7 @@ class Unit : public WorldObject
void TauntApply(Unit* victim);
void TauntFadeOut(Unit* taunter);
ThreatManager& getThreatManager() { return m_ThreatManager; }
- void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); };
+ void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }
void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ }
HostileRefManager& getHostileRefManager() { return m_HostileRefManager; }
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index a47b6f29e80..eb29e463a4d 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -96,7 +96,7 @@ class GameEventMgr
{
private:
GameEventMgr();
- ~GameEventMgr() { };
+ ~GameEventMgr() { }
public:
static GameEventMgr* instance()
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index a3414c72613..e540824e71c 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -1057,12 +1057,12 @@ void ObjectMgr::LoadGameObjectAddons()
{
Field* fields = result->Fetch();
- ObjectGuid::LowType guid = fields[0].GetUInt64();
+ ObjectGuid::LowType guid = fields[0].GetUInt32();
const GameObjectData* goData = GetGOData(guid);
if (!goData)
{
- TC_LOG_ERROR("sql.sql", "GameObject (GUID: " UI64FMTD ") does not exist but has a record in `gameobject_addon`", guid);
+ TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) does not exist but has a record in `gameobject_addon`", guid);
continue;
}
@@ -1072,14 +1072,14 @@ void ObjectMgr::LoadGameObjectAddons()
if (gameObjectAddon.invisibilityType >= TOTAL_INVISIBILITY_TYPES)
{
- TC_LOG_ERROR("sql.sql", "GameObject (GUID: " UI64FMTD ") has invalid InvisibilityType in `gameobject_addon`", guid);
+ TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) has invalid InvisibilityType in `gameobject_addon`", guid);
gameObjectAddon.invisibilityType = INVISIBILITY_GENERAL;
gameObjectAddon.InvisibilityValue = 0;
}
if (gameObjectAddon.invisibilityType && !gameObjectAddon.InvisibilityValue)
{
- TC_LOG_ERROR("sql.sql", "GameObject (GUID: " UI64FMTD ") has InvisibilityType set but has no InvisibilityValue in `gameobject_addon`, set to 1", guid);
+ TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) has InvisibilityType set but has no InvisibilityValue in `gameobject_addon`, set to 1", guid);
gameObjectAddon.InvisibilityValue = 1;
}
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index ae8712510c9..2e81bdd1af8 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -1857,6 +1857,9 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
// check if someone in party is using dungeon system
if (member->isUsingLfg())
return ERR_LFG_CANT_USE_BATTLEGROUND;
+ // check Freeze debuff
+ if (member->HasAura(9454))
+ return ERR_BATTLEGROUND_JOIN_FAILED;
}
// only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 28e933bd08c..732afce9517 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -218,7 +218,7 @@ class Group
ObjectGuid GetMasterLooterGuid() const;
ItemQualities GetLootThreshold() const;
- uint32 GetDbStoreId() const { return m_dbStoreId; };
+ uint32 GetDbStoreId() const { return m_dbStoreId; }
// member manipulation methods
bool IsMember(ObjectGuid guid) const;
diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp
index de23626eb25..2ec89ac2a26 100644
--- a/src/server/game/Handlers/BattleGroundHandler.cpp
+++ b/src/server/game/Handlers/BattleGroundHandler.cpp
@@ -178,6 +178,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
return;
}
+ // check Freeze debuff
+ if (_player->HasAura(9454))
+ return;
+
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
@@ -434,6 +438,10 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
WorldPacket data;
if (action)
{
+ // check Freeze debuff
+ if (_player->HasAura(9454))
+ return;
+
if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
return; // cheating?
diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h
index d8dba57d438..fd52bdd4c14 100644
--- a/src/server/game/Maps/ZoneScript.h
+++ b/src/server/game/Maps/ZoneScript.h
@@ -29,8 +29,8 @@ class ZoneScript
ZoneScript() { }
virtual ~ZoneScript() { }
- virtual uint32 GetCreatureEntry(uint32 /*guidlow*/, CreatureData const* data) { return data->id; }
- virtual uint32 GetGameObjectEntry(uint32 /*guidlow*/, uint32 entry) { return entry; }
+ virtual uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) { return data->id; }
+ virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) { return entry; }
virtual void OnCreatureCreate(Creature* ) { }
virtual void OnCreatureRemove(Creature* ) { }
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 0b547d96e7f..c8da50364ba 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -182,7 +182,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
void MoveJumpTo(float angle, float speedXY, float speedZ);
void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP)
- { MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); };
+ { MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); }
void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP);
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
void MoveFall(uint32 id = 0);
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 97e3880161a..f91fc1985d5 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -367,7 +367,7 @@ void FlightPathMovementGenerator::InitEndGridInfo()
_endMapId = (*i_path)[nodeCount - 1].MapID; //! MapId of last node
_preloadTargetNode = nodeCount - 3;
_endGridX = (*i_path)[nodeCount - 1].LocX;
- _endGridY = (*i_path)[nodeCount - 1].LocZ;
+ _endGridY = (*i_path)[nodeCount - 1].LocY;
}
void FlightPathMovementGenerator::PreloadEndGrid()
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 8be5da91c32..f0ee013bcc2 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -622,6 +622,7 @@ void AddSC_instance_magtheridons_lair();
void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
void AddSC_boss_warbringer_omrogg();
void AddSC_boss_warchief_kargath_bladefist();
+void AddSC_shattered_halls();
void AddSC_instance_shattered_halls();
void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
void AddSC_boss_omor_the_unscarred();
@@ -1152,6 +1153,7 @@ void AddOutlandScripts()
AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
AddSC_boss_warbringer_omrogg();
AddSC_boss_warchief_kargath_bladefist();
+ AddSC_shattered_halls();
AddSC_instance_shattered_halls();
AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
AddSC_boss_omor_the_unscarred();
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index fa40d4c97a1..918b000a557 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -3851,10 +3851,11 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
}
else
{
- if (int32(target->GetHealth()) > GetAmount())
- target->ModifyHealth(-GetAmount());
- else
- target->SetHealth(1);
+ if (target->GetHealth() > 0)
+ {
+ int32 value = std::min<int32>(target->GetHealth() - 1, GetAmount());
+ target->ModifyHealth(-value);
+ }
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
}
}
@@ -3866,19 +3867,15 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u
Unit* target = aurApp->GetTarget();
- uint32 oldhealth = target->GetHealth();
- double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth();
+ float percent = target->GetHealthPct();
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
// refresh percentage
- if (oldhealth > 0)
+ if (target->GetHealth() > 0)
{
- uint32 newhealth = uint32(ceil((double)target->GetMaxHealth() * healthPercentage));
- if (newhealth == 0)
- newhealth = 1;
-
- target->SetHealth(newhealth);
+ uint32 newHealth = std::max<uint32>(target->CountPctFromMaxHealth(int32(percent)), 1);
+ target->SetHealth(newHealth);
}
}
@@ -3942,8 +3939,12 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp
// Unit will keep hp% after MaxHealth being modified if unit is alive.
float percent = target->GetHealthPct();
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
- if (target->IsAlive())
- target->SetHealth(target->CountPctFromMaxHealth(int32(percent)));
+
+ if (target->GetHealth() > 0)
+ {
+ uint32 newHealth = std::max<uint32>(target->CountPctFromMaxHealth(int32(percent)), 1);
+ target->SetHealth(newHealth);
+ }
}
void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -5844,6 +5845,9 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
else
damage = std::max(int32(damage * GetDonePct()), 0);
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
+
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
// Calculate armor mitigation
@@ -6147,6 +6151,9 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
else
damage = std::max(int32(damage * GetDonePct()), 0);
+ if (Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
+
damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
}
diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp
index b16993f28a3..09e3be690b1 100644
--- a/src/server/game/Spells/SpellHistory.cpp
+++ b/src/server/game/Spells/SpellHistory.cpp
@@ -22,6 +22,7 @@
#include "SpellInfo.h"
#include "Spell.h"
#include "World.h"
+#include "Opcodes.h"
SpellHistory::Clock::duration const SpellHistory::InfinityCooldownDelay = std::chrono::duration_cast<SpellHistory::Clock::duration>(std::chrono::seconds(MONTH));
SpellHistory::Clock::duration const SpellHistory::InfinityCooldownDelayCheck = std::chrono::duration_cast<SpellHistory::Clock::duration>(std::chrono::seconds(MONTH / 2));
@@ -627,6 +628,7 @@ void SpellHistory::BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 sp
void SpellHistory::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) const
{
data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + (4 + 4) * cooldowns.size());
+ data << uint64(_owner->GetGUID());
data << uint8(flags);
for (auto const& cooldown : cooldowns)
{
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 75a48e36ded..789b95e3e14 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -1614,7 +1614,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
}
// not allow casting on flying player
- if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT))
+ if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT) && !(AttributesCu & SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET))
return SPELL_FAILED_BAD_TARGETS;
/* TARGET_UNIT_MASTER gets blocked here for passengers, because the whole idea of this check is to
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index f2808a089e1..cfa9877405d 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -186,6 +186,7 @@ enum SpellCustomAttributes
SPELL_ATTR0_CU_IGNORE_ARMOR = 0x00008000,
SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER = 0x00010000,
SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET = 0x00020000,
+ SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET = 0x00040000,
SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2
};
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 191850516d4..13290320084 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2955,7 +2955,7 @@ void SpellMgr::LoadSpellInfoCorrections()
switch (spellInfo->Id)
{
case 63026: // Force Cast (HACK: Target shouldn't be changed)
- case 63171: // Force Cast (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
+ case 63137: // Force Cast (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
spellInfo->Effects[0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
case 53096: // Quetz'lun's Judgment
@@ -3134,6 +3134,7 @@ void SpellMgr::LoadSpellInfoCorrections()
case 64823: // Item - Druid T8 Balance 4P Bonus
case 34477: // Misdirection
case 44401: // Missile Barrage
+ case 18820: // Insight
spellInfo->ProcCharges = 1;
break;
case 44544: // Fingers of Frost
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index b347a982132..09f557dc63b 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -641,8 +641,8 @@ SpellValue const* SpellScript::GetSpellValue()
bool AuraScript::_Validate(SpellInfo const* entry)
{
for (std::list<CheckAreaTargetHandler>::iterator itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr)
- if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
- TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have area aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+ if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && !entry->HasEffect(SPELL_EFFECT_APPLY_AURA))
+ TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr)
if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 5fbc4b8ae1e..f9ccd2efd16 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -77,7 +77,7 @@ void CreatureTextMgr::LoadCreatureTexts()
uint32 oldMSTime = getMSTime();
mTextMap.clear(); // for reload case
- mTextRepeatMap.clear(); //reset all currently used temp texts
+ //all currently used temp texts are NOT reset
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEXT);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -224,13 +224,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject
if (tempGroup.empty())
{
- CreatureTextRepeatMap::iterator mapItr = mTextRepeatMap.find(source->GetGUID());
- if (mapItr != mTextRepeatMap.end())
- {
- CreatureTextRepeatGroup::iterator groupItr = mapItr->second.find(textGroup);
- groupItr->second.clear();
- }
-
+ source->ClearTextRepeatGroup(textGroup);
tempGroup = textGroupContainer;
}
@@ -426,26 +420,14 @@ void CreatureTextMgr::SetRepeatId(Creature* source, uint8 textGroup, uint8 id)
if (!source)
return;
- CreatureTextRepeatIds& repeats = mTextRepeatMap[source->GetGUID()][textGroup];
- if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
- repeats.push_back(id);
- else
- TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), source->GetName().c_str(), source->GetGUIDLow(), source->GetEntry(), uint32(id));
+ source->SetTextRepeatId(textGroup, id);
}
CreatureTextRepeatIds CreatureTextMgr::GetRepeatGroup(Creature* source, uint8 textGroup)
{
ASSERT(source);//should never happen
- CreatureTextRepeatIds ids;
- CreatureTextRepeatMap::const_iterator mapItr = mTextRepeatMap.find(source->GetGUID());
- if (mapItr != mTextRepeatMap.end())
- {
- CreatureTextRepeatGroup::const_iterator groupItr = (*mapItr).second.find(textGroup);
- if (groupItr != mapItr->second.end())
- ids = groupItr->second;
- }
- return ids;
+ return source->GetTextRepeatGroup(textGroup);
}
bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup)
diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h
index 6ee1e82ce66..237aedd49d0 100644
--- a/src/server/game/Texts/CreatureTextMgr.h
+++ b/src/server/game/Texts/CreatureTextMgr.h
@@ -75,11 +75,6 @@ typedef std::unordered_map<uint32, CreatureTextHolder> CreatureTextMap; // a
typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap;
-//used for handling non-repeatable random texts
-typedef std::vector<uint8> CreatureTextRepeatIds;
-typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
-typedef std::unordered_map<ObjectGuid, CreatureTextRepeatGroup> CreatureTextRepeatMap;//guid based
-
class CreatureTextMgr
{
private:
@@ -115,7 +110,6 @@ class CreatureTextMgr
float GetRangeForChatType(ChatMsg msgType) const;
CreatureTextMap mTextMap;
- CreatureTextRepeatMap mTextRepeatMap;
LocaleCreatureTextMap mLocaleTextMap;
};
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index a43416dc67d..c8a908f6930 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -1440,7 +1440,7 @@ public:
* Player %s %s (guid: %u) - I. LANG_PINFO_PLAYER
* ** GM Mode active, Phase: -1 - II. LANG_PINFO_GM_ACTIVE (if GM)
* ** Banned: (Type, Reason, Time, By) - III. LANG_PINFO_BANNED (if banned)
- * ** Muted: (Time, Reason, By) - IV. LANG_PINFO_MUTED (if muted)
+ * ** Muted: (Reason, Time, By) - IV. LANG_PINFO_MUTED (if muted)
* * Account: %s (id: %u), GM Level: %u - V. LANG_PINFO_ACC_ACCOUNT
* * Last Login: %u (Failed Logins: %u) - VI. LANG_PINFO_ACC_LASTLOGIN
* * Uses OS: %s - Latency: %u ms - VII. LANG_PINFO_ACC_OS
@@ -1693,7 +1693,7 @@ public:
// Output IV. LANG_PINFO_MUTED if mute is applied
if (muteTime > 0)
- handler->PSendSysMessage(LANG_PINFO_MUTED, secsToTimeString(muteTime - time(NULL), true).c_str(), muteReason.c_str(), muteBy.c_str());
+ handler->PSendSysMessage(LANG_PINFO_MUTED, muteReason.c_str(), secsToTimeString(muteTime - time(nullptr), true).c_str(), muteBy.c_str());
// Output V. LANG_PINFO_ACC_ACCOUNT
handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName.c_str(), accId, security);
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 390be999d9d..09a41fd82b5 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -370,28 +370,13 @@ public:
uint32 lowGuid = atoi((char*)guidStr);
- Creature* creature = NULL;
-
- /* FIXME: impossible without entry
- if (lowguid)
- creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
- */
-
// attempt check creature existence by DB data
- if (!creature)
- {
- CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
- if (!data)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
- handler->SetSentErrorMessage(true);
- return false;
- }
- }
- else
+ CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
+ if (!data)
{
- // obtain real GUID for DB operations
- lowGuid = creature->GetDBTableGUIDLow();
+ handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
int wait = waitStr ? atoi(waitStr) : 0;
@@ -407,18 +392,6 @@ public:
WorldDatabase.Execute(stmt);
- if (creature && creature->GetWaypointPath())
- {
- creature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- creature->GetMotionMaster()->Initialize();
- if (creature->IsAlive()) // dead creature will reset movement generator at respawn
- {
- creature->setDeathState(JUST_DIED);
- creature->Respawn(true);
- }
- creature->SaveToDB();
- }
-
handler->SendSysMessage(LANG_WAYPOINT_ADDED);
return true;
@@ -830,34 +803,22 @@ public:
lowguid = atoi(cId);
- /* FIXME: impossible without entry
- if (lowguid)
- creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
- */
-
// Attempting creature load from DB data
- if (!creature)
+ CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
+ if (!data)
{
- CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
- if (!data)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
- handler->SetSentErrorMessage(true);
- return false;
- }
+ handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
- uint32 map_id = data->mapid;
+ uint32 map_id = data->mapid;
- if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
- {
- handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
- handler->SetSentErrorMessage(true);
- return false;
- }
- }
- else
+ if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
{
- lowguid = creature->GetDBTableGUIDLow();
+ handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
}
else
diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
index 1d7e1594d05..ca944f7037b 100644
--- a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
+++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp
@@ -102,7 +102,7 @@ public:
}
}
- virtual void Update(uint32 /*diff*/) // correct order goes form 1-6
+ virtual void Update(uint32 /*diff*/) override // correct order goes form 1-6
{
switch (State)
{
diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
index cae26735568..29002460b2a 100644
--- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
+++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
@@ -202,7 +202,7 @@ class boss_archaedas : public CreatureScript
DoMeleeAttackIfReady();
}
- void JustDied (Unit* /*killer*/)
+ void JustDied (Unit* /*killer*/) override
{
instance->SetData(DATA_ANCIENT_DOOR, DONE); // open the vault door
instance->SetData(DATA_MINIONS, SPECIAL); // deactivate his minions
diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp
index 704fefe2678..163620230ef 100644
--- a/src/server/scripts/Kalimdor/zone_moonglade.cpp
+++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp
@@ -384,6 +384,8 @@ public:
}
PlayerGUID = player->GetGUID();
Start(true, false, PlayerGUID);
+ me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
return;
}
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 660a639487f..fabe54303b8 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
@@ -196,7 +196,7 @@ class instance_halls_of_reflection : public InstanceMapScript
}
}
- uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
+ uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{
if (!_teamInInstance)
{
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 63082808e03..d7a580800bc 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -1060,8 +1060,8 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
uint32 adhesiveId = sSpellMgr->GetSpellIdForDifficulty(SPELL_VOLATILE_OOZE_ADHESIVE, GetCaster());
if (GetHitUnit()->HasAura(adhesiveId))
{
- GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
GetHitUnit()->RemoveAurasDueToSpell(adhesiveId, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL);
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index 60268fc8d87..e908d088554 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -348,7 +348,7 @@ class boss_sindragosa : public CreatureScript
events.ScheduleEvent(EVENT_AIR_MOVEMENT, 1);
break;
case POINT_AIR_PHASE:
- me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL);
+ me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL, TRIGGERED_FULL_MASK);
me->SetFacingTo(float(M_PI));
events.ScheduleEvent(EVENT_AIR_MOVEMENT_FAR, 1);
events.ScheduleEvent(EVENT_FROST_BOMB, 9000);
@@ -491,7 +491,7 @@ class boss_sindragosa : public CreatureScript
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, FrostBeaconSelector(me)))
{
Talk(EMOTE_WARN_FROZEN_ORB, target);
- DoCast(target, SPELL_ICE_TOMB_DUMMY, true);
+ me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, 1, nullptr, TRIGGERED_FULL_MASK);
}
events.ScheduleEvent(EVENT_ICE_TOMB, urand(16000, 23000));
break;
@@ -1631,7 +1631,7 @@ void AddSC_boss_sindragosa()
new spell_rimefang_icy_blast();
new spell_frostwarden_handler_order_whelp();
new spell_frostwarden_handler_focus_fire();
- new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY);
+ new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY, TRIGGERED_IGNORE_SET_FACING);
new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON);
new at_sindragosa_lair();
new achievement_all_you_can_eat();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index 8bf8e5ee6fb..091190b6b4e 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -524,14 +524,16 @@ enum AreaIds
class spell_trigger_spell_from_caster : public SpellScriptLoader
{
public:
- spell_trigger_spell_from_caster(char const* scriptName, uint32 triggerId) : SpellScriptLoader(scriptName), _triggerId(triggerId) { }
+ spell_trigger_spell_from_caster(char const* scriptName, uint32 triggerId, TriggerCastFlags triggerFlags = TRIGGERED_FULL_MASK)
+ : SpellScriptLoader(scriptName), _triggerId(triggerId), _triggerFlags(triggerFlags) { }
class spell_trigger_spell_from_caster_SpellScript : public SpellScript
{
PrepareSpellScript(spell_trigger_spell_from_caster_SpellScript);
public:
- spell_trigger_spell_from_caster_SpellScript(uint32 triggerId) : SpellScript(), _triggerId(triggerId) { }
+ spell_trigger_spell_from_caster_SpellScript(uint32 triggerId, TriggerCastFlags triggerFlags)
+ : SpellScript(), _triggerId(triggerId), _triggerFlags(triggerFlags) { }
bool Validate(SpellInfo const* /*spell*/) override
{
@@ -542,7 +544,7 @@ class spell_trigger_spell_from_caster : public SpellScriptLoader
void HandleTrigger()
{
- GetCaster()->CastSpell(GetHitUnit(), _triggerId, true);
+ GetCaster()->CastSpell(GetHitUnit(), _triggerId, _triggerFlags);
}
void Register() override
@@ -551,15 +553,17 @@ class spell_trigger_spell_from_caster : public SpellScriptLoader
}
uint32 _triggerId;
+ TriggerCastFlags _triggerFlags;
};
SpellScript* GetSpellScript() const override
{
- return new spell_trigger_spell_from_caster_SpellScript(_triggerId);
+ return new spell_trigger_spell_from_caster_SpellScript(_triggerId, _triggerFlags);
}
private:
uint32 _triggerId;
+ TriggerCastFlags _triggerFlags;
};
template<class AI>
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index 61848070170..1b823b4a452 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -317,7 +317,7 @@ class instance_icecrown_citadel : public InstanceMapScript
}
// Weekly quest spawn prevention
- uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) override
+ uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{
uint32 entry = data->id;
switch (entry)
@@ -372,7 +372,7 @@ class instance_icecrown_citadel : public InstanceMapScript
return entry;
}
- uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
+ uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{
switch (entry)
{
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index 181fb49ba2e..d0e4b7be63b 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -903,17 +903,15 @@ class boss_yogg_saron : public CreatureScript
DoCast(me, SPELL_KNOCK_AWAY);
me->ResetLootMode();
- switch (_instance->GetData(DATA_KEEPERS_COUNT))
- {
- case 0:
- me->AddLootMode(LOOT_MODE_HARD_MODE_4);
- case 1:
- me->AddLootMode(LOOT_MODE_HARD_MODE_3);
- case 2:
- me->AddLootMode(LOOT_MODE_HARD_MODE_2);
- case 3:
- me->AddLootMode(LOOT_MODE_HARD_MODE_1);
- }
+ uint32 keepersCount = _instance->GetData(DATA_KEEPERS_COUNT);
+ if (keepersCount == 0)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_4);
+ if (keepersCount <= 1)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_3);
+ if (keepersCount <= 2)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_2);
+ if (keepersCount <= 3)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_1);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp
index 36d2c5f8ed3..dc923e534b0 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp
@@ -23,12 +23,9 @@ enum Spells
{
SPELL_ARCANE_VACUUM = 58694,
SPELL_BLIZZARD = 58693,
- H_SPELL_BLIZZARD = 59369,
SPELL_MANA_DESTRUCTION = 59374,
SPELL_TAIL_SWEEP = 58690,
- H_SPELL_TAIL_SWEEP = 59283,
SPELL_UNCONTROLLABLE_ENERGY = 58688,
- H_SPELL_UNCONTROLLABLE_ENERGY = 59281,
SPELL_TRANSFORM = 58668
};
@@ -48,17 +45,11 @@ class boss_cyanigosa : public CreatureScript
public:
boss_cyanigosa() : CreatureScript("boss_cyanigosa") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_cyanigosaAI>(creature);
- }
-
- struct boss_cyanigosaAI : public ScriptedAI
+ struct boss_cyanigosaAI : public BossAI
{
- boss_cyanigosaAI(Creature* creature) : ScriptedAI(creature)
+ boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA)
{
Initialize();
- instance = creature->GetInstanceScript();
}
void Initialize()
@@ -76,24 +67,20 @@ public:
uint32 uiTailSweepTimer;
uint32 uiUncontrollableEnergyTimer;
- InstanceScript* instance;
-
void Reset() override
{
Initialize();
- instance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED);
+ BossAI::Reset();
}
- void EnterCombat(Unit* /*who*/) override
+ void EnterCombat(Unit* who) override
{
+ BossAI::EnterCombat(who);
Talk(SAY_AGGRO);
-
- instance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS);
}
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
if (instance->GetData(DATA_REMOVE_NPC) == 1)
@@ -102,13 +89,12 @@ public:
instance->SetData(DATA_REMOVE_NPC, 0);
}
- //Return since we have no target
if (!UpdateVictim())
return;
if (uiArcaneVacuumTimer <= diff)
{
- DoCast(SPELL_ARCANE_VACUUM);
+ DoCastAOE(SPELL_ARCANE_VACUUM);
uiArcaneVacuumTimer = 10000;
} else uiArcaneVacuumTimer -= diff;
@@ -121,7 +107,7 @@ public:
if (uiTailSweepTimer <= diff)
{
- DoCast(SPELL_TAIL_SWEEP);
+ DoCastVictim(SPELL_TAIL_SWEEP);
uiTailSweepTimer = 20000;
} else uiTailSweepTimer -= diff;
@@ -144,22 +130,23 @@ public:
DoMeleeAttackIfReady();
}
- void JustDied(Unit* /*killer*/) override
+ void JustDied(Unit* killer) override
{
+ BossAI::JustDied(killer);
Talk(SAY_DEATH);
-
- instance->SetData(DATA_CYANIGOSA_EVENT, DONE);
}
void KilledUnit(Unit* victim) override
{
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- Talk(SAY_SLAY);
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_cyanigosaAI>(creature);
+ }
};
class achievement_defenseless : public AchievementCriteriaScript
diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp
index e990b8796de..5c8d4b8691a 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp
@@ -24,9 +24,7 @@ enum Spells
SPELL_BLOODLUST = 54516,
SPELL_BREAK_BONDS = 59463,
SPELL_CHAIN_HEAL = 54481,
- H_SPELL_CHAIN_HEAL = 59473,
SPELL_EARTH_SHIELD = 54479,
- H_SPELL_EARTH_SHIELD = 59471,
SPELL_EARTH_SHOCK = 54511,
SPELL_LIGHTNING_BOLT = 53044,
SPELL_STORMSTRIKE = 51876
@@ -47,11 +45,6 @@ class boss_erekem : public CreatureScript
public:
boss_erekem() : CreatureScript("boss_erekem") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_erekemAI>(creature);
- }
-
struct boss_erekemAI : public ScriptedAI
{
boss_erekemAI(Creature* creature) : ScriptedAI(creature)
@@ -81,9 +74,9 @@ public:
{
Initialize();
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)))
{
@@ -129,25 +122,23 @@ public:
Talk(SAY_AGGRO);
DoCast(me, SPELL_EARTH_SHIELD);
- if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_EREKEM_CELL)))
- if (pDoor->GetGoState() == GO_STATE_READY)
+ if (GameObject* door = instance->GetGameObject(DATA_EREKEM_CELL))
+ if (door->GetGoState() == GO_STATE_READY)
{
EnterEvadeMode();
return;
}
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
}
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
- //Return since we have no target
if (!UpdateVictim())
return;
@@ -212,22 +203,20 @@ public:
if (instance->GetData(DATA_WAVE_COUNT) == 6)
{
- instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 7);
}
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
{
- instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 13);
}
}
void KilledUnit(Unit* victim) override
{
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- Talk(SAY_SLAY);
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
}
ObjectGuid GetChainHealTargetGUID()
@@ -247,6 +236,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_erekemAI>(creature);
+ }
};
enum GuardSpells
@@ -261,11 +254,6 @@ class npc_erekem_guard : public CreatureScript
public:
npc_erekem_guard() : CreatureScript("npc_erekem_guard") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_erekem_guardAI>(creature);
- }
-
struct npc_erekem_guardAI : public ScriptedAI
{
npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature)
@@ -308,7 +296,6 @@ public:
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -336,6 +323,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_erekem_guardAI>(creature);
+ }
};
void AddSC_boss_erekem()
diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp
index 48fe8049d19..9be73febd52 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp
@@ -23,19 +23,16 @@ enum Spells
{
SPELL_DRAINED = 59820,
SPELL_FRENZY = 54312,
- SPELL_FRENZY_H = 59522,
SPELL_PROTECTIVE_BUBBLE = 54306,
SPELL_WATER_BLAST = 54237,
- SPELL_WATER_BLAST_H = 59520,
SPELL_WATER_BOLT_VOLLEY = 54241,
- SPELL_WATER_BOLT_VOLLEY_H = 59521,
SPELL_SPLASH = 59516,
SPELL_WATER_GLOBULE = 54268
};
enum IchoronCreatures
{
- NPC_ICHOR_GLOBULE = 29321,
+ NPC_ICHOR_GLOBULE = 29321
};
enum Yells
@@ -52,18 +49,18 @@ enum Yells
enum Actions
{
ACTION_WATER_ELEMENT_HIT = 1,
- ACTION_WATER_ELEMENT_KILLED = 2,
+ ACTION_WATER_ELEMENT_KILLED = 2
};
/// @todo get those positions from spawn of creature 29326
#define MAX_SPAWN_LOC 5
-static Position SpawnLoc[MAX_SPAWN_LOC]=
+static Position const SpawnLoc[MAX_SPAWN_LOC]=
{
{1840.64f, 795.407f, 44.079f, 1.676f},
{1886.24f, 757.733f, 47.750f, 5.201f},
{1877.91f, 845.915f, 43.417f, 3.560f},
{1918.97f, 850.645f, 47.225f, 4.136f},
- {1935.50f, 796.224f, 52.492f, 4.224f},
+ {1935.50f, 796.224f, 52.492f, 4.224f}
};
enum Misc
@@ -76,11 +73,6 @@ class boss_ichoron : public CreatureScript
public:
boss_ichoron() : CreatureScript("boss_ichoron") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_ichoronAI>(creature);
- }
-
struct boss_ichoronAI : public ScriptedAI
{
boss_ichoronAI(Creature* creature) : ScriptedAI(creature), m_waterElements(creature)
@@ -117,9 +109,9 @@ public:
DespawnWaterElements();
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
@@ -128,16 +120,17 @@ public:
DoCast(me, SPELL_PROTECTIVE_BUBBLE);
- if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ICHORON_CELL)))
- if (pDoor->GetGoState() == GO_STATE_READY)
+ if (GameObject* door = instance->GetGameObject(DATA_ICHORON_CELL))
+ if (door->GetGoState() == GO_STATE_READY)
{
EnterEvadeMode();
return;
}
+
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
}
void AttackStart(Unit* who) override
@@ -208,7 +201,6 @@ public:
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 uiDiff) override
{
if (!UpdateVictim())
@@ -230,7 +222,7 @@ public:
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
{
Talk(SAY_SHATTER);
- DoCast(me, SPELL_WATER_BLAST);
+ DoCast(me, SPELL_WATER_BLAST); // wrong target
DoCast(me, SPELL_DRAINED);
bIsExploded = true;
me->AttackStop();
@@ -291,12 +283,12 @@ public:
if (instance->GetData(DATA_WAVE_COUNT) == 6)
{
- instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 7);
}
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
{
- instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 13);
}
}
@@ -323,13 +315,15 @@ public:
void KilledUnit(Unit* victim) override
{
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- Talk(SAY_SLAY);
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_ichoronAI>(creature);
+ }
};
class npc_ichor_globule : public CreatureScript
@@ -337,11 +331,6 @@ class npc_ichor_globule : public CreatureScript
public:
npc_ichor_globule() : CreatureScript("npc_ichor_globule") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_ichor_globuleAI>(creature);
- }
-
struct npc_ichor_globuleAI : public ScriptedAI
{
npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature)
@@ -367,19 +356,18 @@ public:
void AttackStart(Unit* /*who*/) override
{
- return;
}
void UpdateAI(uint32 uiDiff) override
{
if (uiRangeCheck_Timer < uiDiff)
{
- if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON)))
+ if (Creature* ichoron = instance->GetCreature(DATA_ICHORON))
{
- if (me->IsWithinDist(pIchoron, 2.0f, false))
+ if (me->IsWithinDist(ichoron, 2.0f, false))
{
- if (pIchoron->AI())
- pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
+ if (ichoron->AI())
+ ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT);
me->DespawnOrUnsummon();
}
}
@@ -391,12 +379,16 @@ public:
void JustDied(Unit* /*killer*/) override
{
DoCast(me, SPELL_SPLASH);
- if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON)))
- if (pIchoron->AI())
- pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
+ if (Creature* ichoron = instance->GetCreature(DATA_ICHORON))
+ if (ichoron->AI())
+ ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED);
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_ichor_globuleAI>(creature);
+ }
};
class achievement_dehydration : public AchievementCriteriaScript
diff --git a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp
index c3df7b71b83..5040dccfa36 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp
@@ -21,13 +21,10 @@
enum Spells
{
- SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic
- SPELL_FIREBOLT = 54235,
- H_SPELL_FIREBOLT = 59468,
- SPELL_FLAME_BREATH = 54282,
- H_SPELL_FLAME_BREATH = 59469,
- SPELL_LAVA_BURN = 54249,
- H_SPELL_LAVA_BURN = 59594
+ SPELL_CAUTERIZING_FLAMES = 59466, // Only in heroic
+ SPELL_FIREBOLT = 54235,
+ SPELL_FLAME_BREATH = 54282,
+ SPELL_LAVA_BURN = 54249
};
class boss_lavanthor : public CreatureScript
@@ -35,11 +32,6 @@ class boss_lavanthor : public CreatureScript
public:
boss_lavanthor() : CreatureScript("boss_lavanthor") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_lavanthorAI>(creature);
- }
-
struct boss_lavanthorAI : public ScriptedAI
{
boss_lavanthorAI(Creature* creature) : ScriptedAI(creature)
@@ -67,23 +59,24 @@ public:
{
Initialize();
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
- if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_LAVANTHOR_CELL)))
- if (pDoor->GetGoState() == GO_STATE_READY)
- {
- EnterEvadeMode();
- return;
- }
- if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
- else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
+ if (GameObject* door = instance->GetGameObject(DATA_LAVANTHOR_CELL))
+ if (door->GetGoState() == GO_STATE_READY)
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ if (instance->GetData(DATA_WAVE_COUNT) == 6)
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
+ else if (instance->GetData(DATA_WAVE_COUNT) == 12)
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
}
void AttackStart(Unit* who) override
@@ -102,10 +95,8 @@ public:
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
- //Return since we have no target
if (!UpdateVictim())
return;
@@ -123,9 +114,10 @@ public:
if (uiLavaBurnTimer <= diff)
{
- DoCastVictim(SPELL_LAVA_BURN);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
+ DoCast(target, SPELL_LAVA_BURN);
uiLavaBurnTimer = urand(15000, 23000);
- }
+ } else uiLavaBurnTimer -= diff;
if (IsHeroic())
{
@@ -143,17 +135,21 @@ public:
{
if (instance->GetData(DATA_WAVE_COUNT) == 6)
{
- instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 7);
}
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
{
- instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 13);
}
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_lavanthorAI>(creature);
+ }
};
void AddSC_boss_lavanthor()
diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
index 9a6422dec32..1c98806b127 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
@@ -19,11 +19,12 @@
#include "ScriptedCreature.h"
#include "violet_hold.h"
-//Spells
enum Spells
{
SPELL_CORROSIVE_SALIVA = 54527,
- SPELL_OPTIC_LINK = 54396
+ SPELL_OPTIC_LINK = 54396,
+ SPELL_RAY_OF_PAIN = 54438, // NYI missing spelldifficulty
+ SPELL_RAY_OF_SUFFERING = 54442 // NYI missing spelldifficulty
};
class boss_moragg : public CreatureScript
@@ -31,11 +32,6 @@ class boss_moragg : public CreatureScript
public:
boss_moragg() : CreatureScript("boss_moragg") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_moraggAI>(creature);
- }
-
struct boss_moraggAI : public ScriptedAI
{
boss_moraggAI(Creature* creature) : ScriptedAI(creature)
@@ -60,23 +56,24 @@ public:
Initialize();
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
- if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_MORAGG_CELL)))
- if (pDoor->GetGoState() == GO_STATE_READY)
+ if (GameObject* door = instance->GetGameObject(DATA_MORAGG_CELL))
+ if (door->GetGoState() == GO_STATE_READY)
{
EnterEvadeMode();
return;
}
+
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
}
void AttackStart(Unit* who) override
@@ -95,10 +92,8 @@ public:
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
- //Return since we have no target
if (!UpdateVictim())
return;
@@ -117,21 +112,26 @@ public:
DoMeleeAttackIfReady();
}
+
void JustDied(Unit* /*killer*/) override
{
if (instance->GetData(DATA_WAVE_COUNT) == 6)
{
- instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 7);
}
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
{
- instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 13);
}
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_moraggAI>(creature);
+ }
};
void AddSC_boss_moragg()
diff --git a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp
index 833b06cfbff..d1efcb8ca7a 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp
@@ -23,9 +23,7 @@
enum Spells
{
SPELL_ARCANE_BARRAGE_VOLLEY = 54202,
- SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483,
SPELL_ARCANE_BUFFET = 54226,
- SPELL_ARCANE_BUFFET_H = 59485,
SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102,
SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137,
SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138
@@ -40,7 +38,6 @@ enum NPCs
enum CreatureSpells
{
SPELL_ARCANE_POWER = 54160,
- H_SPELL_ARCANE_POWER = 59474,
SPELL_SUMMON_PLAYERS = 54164,
SPELL_POWER_BALL_VISUAL = 54141
};
@@ -61,11 +58,6 @@ class boss_xevozz : public CreatureScript
public:
boss_xevozz() : CreatureScript("boss_xevozz") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_xevozzAI>(creature);
- }
-
struct boss_xevozzAI : public ScriptedAI
{
boss_xevozzAI(Creature* creature) : ScriptedAI(creature)
@@ -90,9 +82,9 @@ public:
void Reset() override
{
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
Initialize();
DespawnSphere();
@@ -139,46 +131,46 @@ public:
void EnterCombat(Unit* /*who*/) override
{
- Talk(SAY_AGGRO);
- if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_XEVOZZ_CELL)))
- if (pDoor->GetGoState() == GO_STATE_READY)
+ if (GameObject* door = instance->GetGameObject(DATA_XEVOZZ_CELL))
+ if (door->GetGoState() == GO_STATE_READY)
{
EnterEvadeMode();
return;
}
+
+ Talk(SAY_AGGRO);
+
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
}
void MoveInLineOfSight(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 uiDiff) override
+ void UpdateAI(uint32 diff) override
{
- //Return since we have no target
if (!UpdateVictim())
return;
- if (uiArcaneBarrageVolley_Timer < uiDiff)
+ if (uiArcaneBarrageVolley_Timer < diff)
{
DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY);
uiArcaneBarrageVolley_Timer = urand(20000, 22000);
}
- else uiArcaneBarrageVolley_Timer -= uiDiff;
+ else uiArcaneBarrageVolley_Timer -= diff;
if (uiArcaneBuffet_Timer)
{
- if (uiArcaneBuffet_Timer < uiDiff)
+ if (uiArcaneBuffet_Timer < diff)
{
DoCastVictim(SPELL_ARCANE_BUFFET);
uiArcaneBuffet_Timer = 0;
}
- else uiArcaneBuffet_Timer -= uiDiff;
+ else uiArcaneBuffet_Timer -= diff;
}
- if (uiSummonEtherealSphere_Timer < uiDiff)
+ if (uiSummonEtherealSphere_Timer < diff)
{
Talk(SAY_SPAWN);
DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1);
@@ -188,7 +180,7 @@ public:
uiSummonEtherealSphere_Timer = urand(45000, 47000);
uiArcaneBuffet_Timer = urand(5000, 6000);
}
- else uiSummonEtherealSphere_Timer -= uiDiff;
+ else uiSummonEtherealSphere_Timer -= diff;
DoMeleeAttackIfReady();
}
@@ -201,24 +193,27 @@ public:
if (instance->GetData(DATA_WAVE_COUNT) == 6)
{
- instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 7);
}
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
{
- instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED);
instance->SetData(DATA_WAVE_COUNT, 13);
}
}
+
void KilledUnit(Unit* victim) override
{
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- Talk(SAY_SLAY);
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_xevozzAI>(creature);
+ }
};
class npc_ethereal_sphere : public CreatureScript
@@ -226,11 +221,6 @@ class npc_ethereal_sphere : public CreatureScript
public:
npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_ethereal_sphereAI>(creature);
- }
-
struct npc_ethereal_sphereAI : public ScriptedAI
{
npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature)
@@ -255,16 +245,15 @@ public:
Initialize();
}
- void UpdateAI(uint32 uiDiff) override
+ void UpdateAI(uint32 diff) override
{
- //Return since we have no target
if (!UpdateVictim())
return;
if (!me->HasAura(SPELL_POWER_BALL_VISUAL))
DoCast(me, SPELL_POWER_BALL_VISUAL);
- if (uiRangeCheck_Timer < uiDiff)
+ if (uiRangeCheck_Timer < diff)
{
if (Creature* pXevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ)))
{
@@ -276,9 +265,9 @@ public:
}
uiRangeCheck_Timer = 1000;
}
- else uiRangeCheck_Timer -= uiDiff;
+ else uiRangeCheck_Timer -= diff;
- if (uiSummonPlayers_Timer < uiDiff)
+ if (uiSummonPlayers_Timer < diff)
{
DoCast(me, SPELL_SUMMON_PLAYERS); // not working right
@@ -295,10 +284,14 @@ public:
uiSummonPlayers_Timer = urand(33000, 35000);
}
- else uiSummonPlayers_Timer -= uiDiff;
+ else uiSummonPlayers_Timer -= diff;
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_ethereal_sphereAI>(creature);
+ }
};
void AddSC_boss_xevozz()
diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp
index 90fd936e853..c29861f08a4 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp
@@ -22,15 +22,13 @@
enum Spells
{
SPELL_SHROUD_OF_DARKNESS = 54524,
- H_SPELL_SHROUD_OF_DARKNESS = 59745,
SPELL_SUMMON_VOID_SENTRY = 54369,
- SPELL_VOID_SHIFT = 54361,
- H_SPELL_VOID_SHIFT = 59743,
+ SPELL_VOID_SHIFT = 54361
};
enum Creatures
{
- NPC_VOID_SENTRY = 29364
+ NPC_VOID_SENTRY = 29364
};
enum Yells
@@ -53,11 +51,6 @@ class boss_zuramat : public CreatureScript
public:
boss_zuramat() : CreatureScript("boss_zuramat") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_zuramatAI>(creature);
- }
-
struct boss_zuramatAI : public ScriptedAI
{
boss_zuramatAI(Creature* creature) : ScriptedAI(creature)
@@ -107,25 +100,25 @@ public:
void EnterCombat(Unit* /*who*/) override
{
- Talk(SAY_AGGRO);
- if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ZURAMAT_CELL)))
- if (pDoor->GetGoState() == GO_STATE_READY)
+ if (GameObject* door = instance->GetGameObject(DATA_ZURAMAT_CELL))
+ if (door->GetGoState() == GO_STATE_READY)
{
EnterEvadeMode();
return;
}
+
+ Talk(SAY_AGGRO);
+
if (instance->GetData(DATA_WAVE_COUNT) == 6)
- instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS);
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
- instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS);
}
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
- //Return since we have no target
if (!UpdateVictim())
return;
@@ -171,26 +164,27 @@ public:
if (instance->GetData(DATA_WAVE_COUNT) == 6)
{
- instance->SetData(DATA_1ST_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 7);
}
else if (instance->GetData(DATA_WAVE_COUNT) == 12)
{
- instance->SetData(DATA_2ND_BOSS_EVENT, DONE);
+ instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE);
instance->SetData(DATA_WAVE_COUNT, 13);
}
}
void KilledUnit(Unit* victim) override
{
- if (victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- Talk(SAY_SLAY);
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
}
-
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_zuramatAI>(creature);
+ }
};
class achievement_void_dance : public AchievementCriteriaScript
diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
index ef9ad806c89..28c56a02255 100644
--- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
@@ -22,8 +22,6 @@
#include "Player.h"
#include "TemporarySummon.h"
-#define MAX_ENCOUNTER 3
-
/* Violet Hold encounters:
0 - First boss
1 - Second boss
@@ -38,21 +36,6 @@
6 - Zuramat
7 - Cyanigosa */
-enum GameObjects
-{
- GO_MAIN_DOOR = 191723,
- GO_XEVOZZ_DOOR = 191556,
- GO_LAVANTHOR_DOOR = 191566,
- GO_ICHORON_DOOR = 191722,
- GO_ZURAMAT_DOOR = 191565,
- GO_EREKEM_DOOR = 191564,
- GO_EREKEM_GUARD_1_DOOR = 191563,
- GO_EREKEM_GUARD_2_DOOR = 191562,
- GO_MORAGG_DOOR = 191606,
- GO_INTRO_ACTIVATION_CRYSTAL = 193615,
- GO_ACTIVATION_CRYSTAL = 193611
-};
-
enum AzureSaboteurSpells
{
SABOTEUR_SHIELD_DISRUPTION = 58291,
@@ -64,7 +47,7 @@ enum CrystalSpells
SPELL_ARCANE_LIGHTNING = 57930
};
-const Position PortalLocation[] =
+Position const PortalLocation[] =
{
{1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1
{1918.37f, 853.437f, 47.1624f, 4.12294f}, // WP 2
@@ -74,21 +57,21 @@ const Position PortalLocation[] =
{1908.31f, 809.657f, 38.7037f, 3.08701f} // WP 6
};
-const Position ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f};
-const Position BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f};
-const Position BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f};
-const Position BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f};
-const Position BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f};
-const Position BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f};
-const Position BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f};
-const Position BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f};
-const Position BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f};
-
-const Position CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f};
-const Position MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f};
-const Position MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f};
-
-//Cyanigosa's prefight event data
+Position const ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f};
+Position const BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f};
+Position const BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f};
+Position const BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f};
+Position const BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f};
+Position const BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f};
+Position const BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f};
+Position const BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f};
+Position const BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f};
+
+Position const CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f};
+Position const MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f};
+Position const MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f};
+
+// Cyanigosa's prefight event data
enum Yells
{
CYANIGOSA_SAY_SPAWN = 0
@@ -100,21 +83,45 @@ enum Spells
CYANIGOSA_BLUE_AURA = 47759,
};
+ObjectData const creatureData[] =
+{
+ { NPC_XEVOZZ, DATA_XEVOZZ },
+ { NPC_LAVANTHOR, DATA_LAVANTHOR },
+ { NPC_ICHORON, DATA_ICHORON },
+ { NPC_ZURAMAT, DATA_ZURAMAT },
+ { NPC_EREKEM, DATA_EREKEM },
+ { NPC_MORAGG, DATA_MORAGG },
+ { NPC_CYANIGOSA, DATA_CYANIGOSA },
+ { NPC_SINCLARI, DATA_SINCLARI },
+ { 0, 0 } // END
+};
+
+ObjectData const gameObjectData[] =
+{
+ { GO_EREKEM_GUARD_1_DOOR, DATA_EREKEM_LEFT_GUARD_CELL },
+ { GO_EREKEM_GUARD_2_DOOR, DATA_EREKEM_RIGHT_GUARD_CELL },
+ { GO_EREKEM_DOOR, DATA_EREKEM_CELL },
+ { GO_ZURAMAT_DOOR, DATA_ZURAMAT_CELL },
+ { GO_LAVANTHOR_DOOR, DATA_LAVANTHOR_CELL },
+ { GO_MORAGG_DOOR, DATA_MORAGG_CELL },
+ { GO_ICHORON_DOOR, DATA_ICHORON_CELL },
+ { GO_XEVOZZ_DOOR, DATA_XEVOZZ_CELL },
+ { GO_MAIN_DOOR, DATA_MAIN_DOOR },
+ { 0, 0 } // END
+};
+
class instance_violet_hold : public InstanceMapScript
{
public:
instance_violet_hold() : InstanceMapScript("instance_violet_hold", 608) { }
- InstanceScript* GetInstanceScript(InstanceMap* map) const override
- {
- return new instance_violet_hold_InstanceMapScript(map);
- }
-
struct instance_violet_hold_InstanceMapScript : public InstanceScript
{
instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
+ SetBossNumber(EncounterCount);
+ LoadObjectData(creatureData, gameObjectData);
uiRemoveNpc = 0;
@@ -138,29 +145,10 @@ public:
bCrystalActivated = false;
defenseless = true;
uiMainEventPhase = NOT_STARTED;
-
- memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
- ObjectGuid uiMoragg;
- ObjectGuid uiErekem;
ObjectGuid uiErekemGuard[2];
- ObjectGuid uiIchoron;
- ObjectGuid uiLavanthor;
- ObjectGuid uiXevozz;
- ObjectGuid uiZuramat;
- ObjectGuid uiCyanigosa;
- ObjectGuid uiSinclari;
-
- ObjectGuid uiMoraggCell;
- ObjectGuid uiErekemCell;
- ObjectGuid uiErekemLeftGuardCell;
- ObjectGuid uiErekemRightGuardCell;
- ObjectGuid uiIchoronCell;
- ObjectGuid uiLavanthorCell;
- ObjectGuid uiXevozzCell;
- ObjectGuid uiZuramatCell;
- ObjectGuid uiMainDoor;
+
ObjectGuid uiTeleportationPortal;
ObjectGuid uiSaboteurPortal;
@@ -180,7 +168,6 @@ public:
uint8 uiDoorIntegrity;
- uint16 m_auiEncounter[MAX_ENCOUNTER];
uint8 uiCountErekemGuards;
uint8 uiCountActivationCrystals;
uint8 uiCyanigosaEventPhase;
@@ -194,52 +181,23 @@ public:
std::list<uint8> NpcAtDoorCastingList;
- std::string str_data;
-
- bool IsEncounterInProgress() const override
- {
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (m_auiEncounter[i] == IN_PROGRESS)
- return true;
-
- return false;
- }
-
void OnCreatureCreate(Creature* creature) override
{
+ InstanceScript::OnCreatureCreate(creature);
+
switch (creature->GetEntry())
{
- case CREATURE_XEVOZZ:
- uiXevozz = creature->GetGUID();
- break;
- case CREATURE_LAVANTHOR:
- uiLavanthor = creature->GetGUID();
- break;
- case CREATURE_ICHORON:
- uiIchoron = creature->GetGUID();
- break;
- case CREATURE_ZURAMAT:
- uiZuramat = creature->GetGUID();
- break;
- case CREATURE_EREKEM:
- uiErekem = creature->GetGUID();
- break;
- case CREATURE_EREKEM_GUARD:
+ case NPC_EREKEM_GUARD:
if (uiCountErekemGuards < 2)
{
uiErekemGuard[uiCountErekemGuards++] = creature->GetGUID();
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
}
break;
- case CREATURE_MORAGG:
- uiMoragg = creature->GetGUID();
+ case NPC_CYANIGOSA:
+ creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
break;
- case CREATURE_CYANIGOSA:
- uiCyanigosa = creature->GetGUID();
- creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
- break;
- case CREATURE_SINCLARI:
- uiSinclari = creature->GetGUID();
+ default:
break;
}
@@ -255,68 +213,53 @@ public:
void OnGameObjectCreate(GameObject* go) override
{
+ InstanceScript::OnGameObjectCreate(go);
+
switch (go->GetEntry())
{
- case GO_EREKEM_GUARD_1_DOOR:
- uiErekemLeftGuardCell = go->GetGUID();
- break;
- case GO_EREKEM_GUARD_2_DOOR:
- uiErekemRightGuardCell = go->GetGUID();
- break;
- case GO_EREKEM_DOOR:
- uiErekemCell = go->GetGUID();
- break;
- case GO_ZURAMAT_DOOR:
- uiZuramatCell = go->GetGUID();
- break;
- case GO_LAVANTHOR_DOOR:
- uiLavanthorCell = go->GetGUID();
- break;
- case GO_MORAGG_DOOR:
- uiMoraggCell = go->GetGUID();
- break;
- case GO_ICHORON_DOOR:
- uiIchoronCell = go->GetGUID();
- break;
- case GO_XEVOZZ_DOOR:
- uiXevozzCell = go->GetGUID();
- break;
- case GO_MAIN_DOOR:
- uiMainDoor = go->GetGUID();
- break;
case GO_ACTIVATION_CRYSTAL:
if (uiCountActivationCrystals < 4)
uiActivationCrystal[uiCountActivationCrystals++] = go->GetGUID();
break;
+ default:
+ break;
}
}
- void SetData(uint32 type, uint32 data) override
+ bool SetBossState(uint32 type, EncounterState state) override
{
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
switch (type)
{
case DATA_1ST_BOSS_EVENT:
- UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_EREKEM, NULL);
- m_auiEncounter[0] = data;
- if (data == DONE)
- SaveToDB();
+ if (state == DONE)
+ UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_EREKEM, nullptr);
break;
case DATA_2ND_BOSS_EVENT:
- UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_MORAGG, NULL);
- m_auiEncounter[1] = data;
- if (data == DONE)
- SaveToDB();
- break;
- case DATA_CYANIGOSA_EVENT:
- m_auiEncounter[2] = data;
- if (data == DONE)
+ if (state == DONE)
+ UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_MORAGG, nullptr);
+ break;
+ case DATA_CYANIGOSA:
+ if (state == DONE)
{
- SaveToDB();
uiMainEventPhase = DONE;
- if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
- pMainDoor->SetGoState(GO_STATE_ACTIVE);
+ if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR))
+ mainDoor->SetGoState(GO_STATE_ACTIVE);
}
break;
+ default:
+ break;
+ }
+
+ return true;
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ switch (type)
+ {
case DATA_WAVE_COUNT:
uiWaveCount = data;
bActive = true;
@@ -340,21 +283,8 @@ public:
NpcAtDoorCastingList.pop_back();
break;
case DATA_MAIN_DOOR:
- if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
- {
- switch (data)
- {
- case GO_STATE_ACTIVE:
- pMainDoor->SetGoState(GO_STATE_ACTIVE);
- break;
- case GO_STATE_READY:
- pMainDoor->SetGoState(GO_STATE_READY);
- break;
- case GO_STATE_ACTIVE_ALTERNATIVE:
- pMainDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
- break;
- }
- }
+ if (GameObject* mainDoor = GetGameObject(type))
+ mainDoor->SetGoState(GOState(data));
break;
case DATA_START_BOSS_ENCOUNTER:
switch (uiWaveCount)
@@ -374,7 +304,7 @@ public:
uiMainEventPhase = data;
if (data == IN_PROGRESS) // Start event
{
- if (GameObject* mainDoor = instance->GetGameObject(uiMainDoor))
+ if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR))
mainDoor->SetGoState(GO_STATE_READY);
uiWaveCount = 1;
bActive = true;
@@ -404,9 +334,6 @@ public:
{
switch (type)
{
- case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0];
- case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1];
- case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2];
case DATA_WAVE_COUNT: return uiWaveCount;
case DATA_REMOVE_NPC: return uiRemoveNpc;
case DATA_PORTAL_LOCATION: return uiLocation;
@@ -421,125 +348,107 @@ public:
return 0;
}
- ObjectGuid GetGuidData(uint32 identifier) const override
+ ObjectGuid GetGuidData(uint32 type) const override
{
- switch (identifier)
+ switch (type)
{
- case DATA_MORAGG: return uiMoragg;
- case DATA_EREKEM: return uiErekem;
case DATA_EREKEM_GUARD_1: return uiErekemGuard[0];
case DATA_EREKEM_GUARD_2: return uiErekemGuard[1];
- case DATA_ICHORON: return uiIchoron;
- case DATA_LAVANTHOR: return uiLavanthor;
- case DATA_XEVOZZ: return uiXevozz;
- case DATA_ZURAMAT: return uiZuramat;
- case DATA_CYANIGOSA: return uiCyanigosa;
- case DATA_MORAGG_CELL: return uiMoraggCell;
- case DATA_EREKEM_CELL: return uiErekemCell;
- case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell;
- case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell;
- case DATA_ICHORON_CELL: return uiIchoronCell;
- case DATA_LAVANTHOR_CELL: return uiLavanthorCell;
- case DATA_XEVOZZ_CELL: return uiXevozzCell;
- case DATA_ZURAMAT_CELL: return uiZuramatCell;
- case DATA_MAIN_DOOR: return uiMainDoor;
- case DATA_SINCLARI: return uiSinclari;
case DATA_TELEPORTATION_PORTAL: return uiTeleportationPortal;
case DATA_SABOTEUR_PORTAL: return uiSaboteurPortal;
}
- return ObjectGuid::Empty;
+ return InstanceScript::GetGuidData(type);
}
void SpawnPortal()
{
SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5))%6);
- if (Creature* pSinclari = instance->GetCreature(uiSinclari))
- if (Creature* portal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN))
+ if (Creature* sinclari = GetCreature(DATA_SINCLARI))
+ if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN))
uiTeleportationPortal = portal->GetGUID();
}
void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true)
{
- Creature* pBoss = NULL;
+ Creature* boss = nullptr;
switch (uiBoss)
{
case BOSS_MORAGG:
- HandleGameObject(uiMoraggCell, bForceRespawn);
- pBoss = instance->GetCreature(uiMoragg);
- if (pBoss)
- pBoss->GetMotionMaster()->MovePoint(0, BossStartMove1);
+ HandleGameObject(GetObjectGuid(DATA_MORAGG_CELL), bForceRespawn);
+ boss = GetCreature(DATA_MORAGG);
+ if (boss)
+ boss->GetMotionMaster()->MovePoint(0, BossStartMove1);
break;
case BOSS_EREKEM:
- HandleGameObject(uiErekemCell, bForceRespawn);
- HandleGameObject(uiErekemRightGuardCell, bForceRespawn);
- HandleGameObject(uiErekemLeftGuardCell, bForceRespawn);
-
- pBoss = instance->GetCreature(uiErekem);
+ HandleGameObject(GetObjectGuid(DATA_EREKEM_CELL), bForceRespawn);
+ HandleGameObject(GetObjectGuid(DATA_EREKEM_LEFT_GUARD_CELL), bForceRespawn);
+ HandleGameObject(GetObjectGuid(DATA_EREKEM_RIGHT_GUARD_CELL), bForceRespawn);
- if (pBoss)
- pBoss->GetMotionMaster()->MovePoint(0, BossStartMove2);
+ boss = GetCreature(DATA_EREKEM);
+ if (boss)
+ boss->GetMotionMaster()->MovePoint(0, BossStartMove2);
if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0]))
{
if (bForceRespawn)
- pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
else
- pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21);
}
if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1]))
{
if (bForceRespawn)
- pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
else
- pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22);
}
break;
case BOSS_ICHORON:
- HandleGameObject(uiIchoronCell, bForceRespawn);
- pBoss = instance->GetCreature(uiIchoron);
- if (pBoss)
- pBoss->GetMotionMaster()->MovePoint(0, BossStartMove3);
+ HandleGameObject(GetObjectGuid(DATA_ICHORON_CELL), bForceRespawn);
+ boss = GetCreature(DATA_ICHORON);
+ if (boss)
+ boss->GetMotionMaster()->MovePoint(0, BossStartMove3);
break;
case BOSS_LAVANTHOR:
- HandleGameObject(uiLavanthorCell, bForceRespawn);
- pBoss = instance->GetCreature(uiLavanthor);
- if (pBoss)
- pBoss->GetMotionMaster()->MovePoint(0, BossStartMove4);
+ HandleGameObject(GetObjectGuid(DATA_LAVANTHOR_CELL), bForceRespawn);
+ boss = GetCreature(DATA_LAVANTHOR);
+ if (boss)
+ boss->GetMotionMaster()->MovePoint(0, BossStartMove4);
break;
case BOSS_XEVOZZ:
- HandleGameObject(uiXevozzCell, bForceRespawn);
- pBoss = instance->GetCreature(uiXevozz);
- if (pBoss)
- pBoss->GetMotionMaster()->MovePoint(0, BossStartMove5);
+ HandleGameObject(GetObjectGuid(DATA_XEVOZZ_CELL), bForceRespawn);
+ boss = GetCreature(DATA_XEVOZZ);
+ if (boss)
+ boss->GetMotionMaster()->MovePoint(0, BossStartMove5);
break;
case BOSS_ZURAMAT:
- HandleGameObject(uiZuramatCell, bForceRespawn);
- pBoss = instance->GetCreature(uiZuramat);
- if (pBoss)
- pBoss->GetMotionMaster()->MovePoint(0, BossStartMove6);
+ HandleGameObject(GetObjectGuid(DATA_ZURAMAT_CELL), bForceRespawn);
+ boss = GetCreature(DATA_ZURAMAT);
+ if (boss)
+ boss->GetMotionMaster()->MovePoint(0, BossStartMove6);
break;
}
// generic boss state changes
- if (pBoss)
+ if (boss)
{
- pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
- pBoss->SetReactState(REACT_AGGRESSIVE);
+ boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ boss->SetReactState(REACT_AGGRESSIVE);
if (!bForceRespawn)
{
- if (pBoss->isDead())
+ if (boss->isDead())
{
// respawn but avoid to be looted again
- pBoss->Respawn();
- pBoss->RemoveLootMode(1);
+ boss->Respawn();
+ boss->RemoveLootMode(1);
}
- pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ boss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
uiWaveCount = 0;
}
}
@@ -555,12 +464,12 @@ public:
case 6:
if (uiFirstBoss == 0)
uiFirstBoss = urand(1, 6);
- if (Creature* pSinclari = instance->GetCreature(uiSinclari))
+ if (Creature* sinclari = GetCreature(DATA_SINCLARI))
{
- if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
- uiSaboteurPortal = pPortal->GetGUID();
- if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
- pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false);
+ if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
+ uiSaboteurPortal = portal->GetGUID();
+ if (Creature* azureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
+ azureSaboteur->CastSpell(azureSaboteur, SABOTEUR_SHIELD_EFFECT, false);
}
break;
case 12:
@@ -569,25 +478,22 @@ public:
{
uiSecondBoss = urand(1, 6);
} while (uiSecondBoss == uiFirstBoss);
- if (Creature* pSinclari = instance->GetCreature(uiSinclari))
+ if (Creature* sinclari = GetCreature(DATA_SINCLARI))
{
- if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
+ if (Creature* pPortal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN))
uiSaboteurPortal = pPortal->GetGUID();
- if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
+ if (Creature* pAzureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN))
pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false);
}
break;
case 18:
- {
- Creature* pSinclari = instance->GetCreature(uiSinclari);
- if (pSinclari)
- pSinclari->SummonCreature(CREATURE_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN);
+ if (Creature* sinclari = GetCreature(DATA_SINCLARI))
+ sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN);
break;
- }
case 1:
{
- if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor))
- pMainDoor->SetGoState(GO_STATE_READY);
+ if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR))
+ mainDoor->SetGoState(GO_STATE_READY);
DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100);
// no break
}
@@ -597,54 +503,15 @@ public:
}
}
- std::string GetSaveData() override
+ void WriteSaveDataMore(std::ostringstream& data) override
{
- OUT_SAVE_INST_DATA;
-
- std::ostringstream saveStream;
- saveStream << "V H " << (uint16)m_auiEncounter[0]
- << ' ' << (uint16)m_auiEncounter[1]
- << ' ' << (uint16)m_auiEncounter[2]
- << ' ' << (uint16)uiFirstBoss
- << ' ' << (uint16)uiSecondBoss;
-
- str_data = saveStream.str();
-
- OUT_SAVE_INST_DATA_COMPLETE;
- return str_data;
+ data << uiFirstBoss << ' ' << uiSecondBoss;
}
- void Load(const char* in) override
+ void ReadSaveDataMore(std::istringstream& data) override
{
- if (!in)
- {
- OUT_LOAD_INST_DATA_FAIL;
- return;
- }
-
- OUT_LOAD_INST_DATA(in);
-
- char dataHead1, dataHead2;
- uint16 data0, data1, data2, data3, data4;
-
- std::istringstream loadStream(in);
- loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4;
-
- if (dataHead1 == 'V' && dataHead2 == 'H')
- {
- m_auiEncounter[0] = data0;
- m_auiEncounter[1] = data1;
- m_auiEncounter[2] = data2;
-
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (m_auiEncounter[i] == IN_PROGRESS)
- m_auiEncounter[i] = NOT_STARTED;
-
- uiFirstBoss = uint8(data3);
- uiSecondBoss = uint8(data4);
- } else OUT_LOAD_INST_DATA_FAIL;
-
- OUT_LOAD_INST_DATA_COMPLETE;
+ data >> uiFirstBoss;
+ data >> uiSecondBoss;
}
bool CheckWipe()
@@ -695,54 +562,51 @@ public:
if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i]))
crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- if (Creature* pSinclari = instance->GetCreature(uiSinclari))
+ if (Creature* sinclari = GetCreature(DATA_SINCLARI))
{
- pSinclari->SetVisible(true);
+ sinclari->SetVisible(true);
std::list<Creature*> GuardList;
- pSinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
+ sinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f);
if (!GuardList.empty())
{
- for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr)
+ for (Creature* guard : GuardList)
{
- if (Creature* pGuard = *itr)
- {
- pGuard->SetVisible(true);
- pGuard->SetReactState(REACT_AGGRESSIVE);
- pGuard->GetMotionMaster()->MovePoint(1, pGuard->GetHomePosition());
- }
+ guard->SetVisible(true);
+ guard->SetReactState(REACT_AGGRESSIVE);
+ guard->GetMotionMaster()->MovePoint(1, guard->GetHomePosition());
}
}
- pSinclari->GetMotionMaster()->MovePoint(1, pSinclari->GetHomePosition());
- pSinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ sinclari->GetMotionMaster()->MovePoint(1, sinclari->GetHomePosition());
+ sinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
}
// Cyanigosa is spawned but not tranformed, prefight event
- Creature* pCyanigosa = instance->GetCreature(uiCyanigosa);
- if (pCyanigosa && !pCyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM))
+ Creature* cyanigosa = GetCreature(DATA_CYANIGOSA);
+ if (cyanigosa && !cyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM))
{
if (uiCyanigosaEventTimer <= diff)
{
switch (uiCyanigosaEventPhase)
{
case 1:
- pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false);
- pCyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN);
+ cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false);
+ cyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN);
uiCyanigosaEventTimer = 7*IN_MILLISECONDS;
++uiCyanigosaEventPhase;
break;
case 2:
- pCyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f);
- pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false);
+ cyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f);
+ cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false);
uiCyanigosaEventTimer = 7*IN_MILLISECONDS;
++uiCyanigosaEventPhase;
break;
case 3:
- pCyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA);
- pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0);
- pCyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
- pCyanigosa->SetReactState(REACT_AGGRESSIVE);
+ cyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA);
+ cyanigosa->CastSpell(cyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0);
+ cyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE);
+ cyanigosa->SetReactState(REACT_AGGRESSIVE);
uiCyanigosaEventTimer = 2*IN_MILLISECONDS;
++uiCyanigosaEventPhase;
break;
@@ -815,6 +679,11 @@ public:
}
}
};
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
+ {
+ return new instance_violet_hold_InstanceMapScript(map);
+ }
};
void AddSC_instance_violet_hold()
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
index 645a9da4764..8bcc80b5a84 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@@ -32,18 +32,18 @@
enum PortalCreatures
{
- CREATURE_AZURE_INVADER_1 = 30661,
- CREATURE_AZURE_INVADER_2 = 30961,
- CREATURE_AZURE_SPELLBREAKER_1 = 30662,
- CREATURE_AZURE_SPELLBREAKER_2 = 30962,
- CREATURE_AZURE_BINDER_1 = 30663,
- CREATURE_AZURE_BINDER_2 = 30918,
- CREATURE_AZURE_MAGE_SLAYER_1 = 30664,
- CREATURE_AZURE_MAGE_SLAYER_2 = 30963,
- CREATURE_AZURE_CAPTAIN = 30666,
- CREATURE_AZURE_SORCEROR = 30667,
- CREATURE_AZURE_RAIDER = 30668,
- CREATURE_AZURE_STALKER = 32191
+ NPC_AZURE_INVADER_1 = 30661,
+ NPC_AZURE_INVADER_2 = 30961,
+ NPC_AZURE_SPELLBREAKER_1 = 30662,
+ NPC_AZURE_SPELLBREAKER_2 = 30962,
+ NPC_AZURE_BINDER_1 = 30663,
+ NPC_AZURE_BINDER_2 = 30918,
+ NPC_AZURE_MAGE_SLAYER_1 = 30664,
+ NPC_AZURE_MAGE_SLAYER_2 = 30963,
+ NPC_AZURE_CAPTAIN = 30666,
+ NPC_AZURE_SORCEROR = 30667,
+ NPC_AZURE_RAIDER = 30668,
+ NPC_AZURE_STALKER = 32191
};
enum AzureInvaderSpells
@@ -258,7 +258,7 @@ public:
{
case GOSSIP_ACTION_INFO_DEF+1:
player->CLOSE_GOSSIP_MENU();
- ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, (creature->AI()))->uiPhase = 1;
+ ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, creature->AI())->uiPhase = 1;
if (InstanceScript* instance = creature->GetInstanceScript())
instance->SetData(DATA_MAIN_EVENT_PHASE, SPECIAL);
break;
@@ -296,17 +296,12 @@ public:
return true;
}
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_sinclariAI>(creature);
- }
-
struct npc_sinclariAI : public ScriptedAI
{
npc_sinclariAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
- instance = creature->GetInstanceScript();
+ instance = creature->GetInstanceScript();
}
void Initialize()
@@ -345,8 +340,6 @@ public:
void UpdateAI(uint32 uiDiff) override
{
- ScriptedAI::UpdateAI(uiDiff);
-
if (uiPhase)
{
if (uiTimer <= uiDiff)
@@ -415,6 +408,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_sinclariAI>(creature);
+ }
};
class npc_azure_saboteur : public CreatureScript
@@ -422,14 +419,9 @@ class npc_azure_saboteur : public CreatureScript
public:
npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_saboteurAI>(creature);
- }
-
struct npc_azure_saboteurAI : public npc_escortAI
{
- npc_azure_saboteurAI(Creature* creature):npc_escortAI(creature)
+ npc_azure_saboteurAI(Creature* creature) : npc_escortAI(creature)
{
instance = creature->GetInstanceScript();
bHasGotMovingPoints = false;
@@ -532,13 +524,16 @@ public:
{
me->CastSpell(me, SABOTEUR_SHIELD_DISRUPTION, false);
me->DisappearAndDie();
- Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL));
- if (pSaboPort)
+ if (Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL)))
pSaboPort->DisappearAndDie();
instance->SetData(DATA_START_BOSS_ENCOUNTER, 1);
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_saboteurAI>(creature);
+ }
};
class npc_teleportation_portal_vh : public CreatureScript
@@ -546,11 +541,6 @@ class npc_teleportation_portal_vh : public CreatureScript
public:
npc_teleportation_portal_vh() : CreatureScript("npc_teleportation_portal_vh") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_teleportation_portalAI>(creature);
- }
-
struct npc_teleportation_portalAI : public ScriptedAI
{
npc_teleportation_portalAI(Creature* creature) : ScriptedAI(creature), listOfMobs(me)
@@ -583,7 +573,6 @@ public:
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void UpdateAI(uint32 diff) override
{
if (instance->GetData(DATA_REMOVE_NPC) == 1)
@@ -608,7 +597,7 @@ public:
uint8 k = uiWaveCount < 12 ? 2 : 3;
for (uint8 i = 0; i < k; ++i)
{
- uint32 entry = RAND(CREATURE_AZURE_CAPTAIN, CREATURE_AZURE_RAIDER, CREATURE_AZURE_STALKER, CREATURE_AZURE_SORCEROR);
+ uint32 entry = RAND(NPC_AZURE_CAPTAIN, NPC_AZURE_RAIDER, NPC_AZURE_STALKER, NPC_AZURE_SORCEROR);
DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
}
me->SetVisible(false);
@@ -633,14 +622,14 @@ public:
uint8 k = instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4;
for (uint8 i = 0; i < k; ++i)
{
- uint32 entry = RAND(CREATURE_AZURE_INVADER_1, CREATURE_AZURE_INVADER_2, CREATURE_AZURE_SPELLBREAKER_1, CREATURE_AZURE_SPELLBREAKER_2, CREATURE_AZURE_MAGE_SLAYER_1, CREATURE_AZURE_MAGE_SLAYER_2, CREATURE_AZURE_BINDER_1, CREATURE_AZURE_BINDER_2);
+ uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_INVADER_2, NPC_AZURE_SPELLBREAKER_1, NPC_AZURE_SPELLBREAKER_2, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_MAGE_SLAYER_2, NPC_AZURE_BINDER_1, NPC_AZURE_BINDER_2);
DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN);
}
}
else
{
bPortalGuardianOrKeeperOrEliteSpawn = true;
- uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER);
+ uint32 entry = RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER);
if (Creature* pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN))
me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false);
}
@@ -674,11 +663,15 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_teleportation_portalAI>(creature);
+ }
};
struct violet_hold_trashAI : public npc_escortAI
{
- violet_hold_trashAI(Creature* creature):npc_escortAI(creature)
+ violet_hold_trashAI(Creature* creature) : npc_escortAI(creature)
{
instance = creature->GetInstanceScript();
bHasGotMovingPoints = false;
@@ -723,7 +716,7 @@ struct violet_hold_trashAI : public npc_escortAI
}
}
- void UpdateAI(uint32) override
+ void UpdateAI(uint32 diff) override
{
if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS)
me->CastStop();
@@ -778,6 +771,8 @@ struct violet_hold_trashAI : public npc_escortAI
SetDespawnAtEnd(false);
Start(true, true);
}
+
+ npc_escortAI::UpdateAI(diff);
}
void JustDied(Unit* /*killer*/) override
@@ -791,7 +786,6 @@ struct violet_hold_trashAI : public npc_escortAI
DoCast(SPELL_DESTROY_DOOR_SEAL);
instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_ADD, 1);
}
-
};
class npc_azure_invader : public CreatureScript
@@ -799,11 +793,6 @@ class npc_azure_invader : public CreatureScript
public:
npc_azure_invader() : CreatureScript("npc_azure_invader") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_invaderAI>(creature);
- }
-
struct npc_azure_invaderAI : public violet_hold_trashAI
{
npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature)
@@ -833,12 +822,11 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
- if (me->GetEntry() == CREATURE_AZURE_INVADER_1)
+ if (me->GetEntry() == NPC_AZURE_INVADER_1)
{
if (uiCleaveTimer <= diff)
{
@@ -848,14 +836,13 @@ public:
if (uiImpaleTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_IMPALE);
uiImpaleTimer = 4000;
} else uiImpaleTimer -= diff;
}
- if (me->GetEntry() == CREATURE_AZURE_INVADER_2)
+ if (me->GetEntry() == NPC_AZURE_INVADER_2)
{
if (uiBrutalStrikeTimer <= diff)
{
@@ -876,6 +863,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_invaderAI>(creature);
+ }
};
class npc_azure_binder : public CreatureScript
@@ -883,11 +874,6 @@ class npc_azure_binder : public CreatureScript
public:
npc_azure_binder() : CreatureScript("npc_azure_binder") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_binderAI>(creature);
- }
-
struct npc_azure_binderAI : public violet_hold_trashAI
{
npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature)
@@ -917,12 +903,11 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
- if (me->GetEntry() == CREATURE_AZURE_BINDER_1)
+ if (me->GetEntry() == NPC_AZURE_BINDER_1)
{
if (uiArcaneExplosionTimer <= diff)
{
@@ -930,16 +915,15 @@ public:
uiArcaneExplosionTimer = 5000;
} else uiArcaneExplosionTimer -= diff;
- if (uiArcainBarrageTimer <= diff)
+ if (uiArcainBarrageTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
- DoCast(target, SPELL_ARCANE_BARRAGE);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_ARCANE_BARRAGE);
uiArcainBarrageTimer = 6000;
} else uiArcainBarrageTimer -= diff;
}
- if (me->GetEntry() == CREATURE_AZURE_BINDER_2)
+ if (me->GetEntry() == NPC_AZURE_BINDER_2)
{
if (uiFrostNovaTimer <= diff)
{
@@ -949,8 +933,7 @@ public:
if (uiFrostboltTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_FROSTBOLT);
uiFrostboltTimer = 6000;
} else uiFrostboltTimer -= diff;
@@ -960,6 +943,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_binderAI>(creature);
+ }
};
class npc_azure_mage_slayer : public CreatureScript
@@ -967,11 +954,6 @@ class npc_azure_mage_slayer : public CreatureScript
public:
npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_mage_slayerAI>(creature);
- }
-
struct npc_azure_mage_slayerAI : public violet_hold_trashAI
{
npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature)
@@ -997,12 +979,11 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
- if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_1)
+ if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_1)
{
if (uiArcaneEmpowermentTimer <= diff)
{
@@ -1011,12 +992,11 @@ public:
} else uiArcaneEmpowermentTimer -= diff;
}
- if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_2)
+ if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2)
{
if (uiSpellLockTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_SPELL_LOCK);
uiSpellLockTimer = 9000;
} else uiSpellLockTimer -= diff;
@@ -1026,6 +1006,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_mage_slayerAI>(creature);
+ }
};
class npc_azure_raider : public CreatureScript
@@ -1033,11 +1017,6 @@ class npc_azure_raider : public CreatureScript
public:
npc_azure_raider() : CreatureScript("npc_azure_raider") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_raiderAI>(creature);
- }
-
struct npc_azure_raiderAI : public violet_hold_trashAI
{
npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature)
@@ -1063,7 +1042,6 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -1084,6 +1062,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_raiderAI>(creature);
+ }
};
class npc_azure_stalker : public CreatureScript
@@ -1114,7 +1096,6 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -1123,8 +1104,7 @@ public:
{
if (_tacticalBlinkTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true))
DoCast(target, SPELL_TACTICAL_BLINK);
_tacticalBlinkTimer = 6000;
_tacticalBlinkCast = true;
@@ -1135,8 +1115,8 @@ public:
{
if (_backstabTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true);
- DoCast(target, SPELL_BACKSTAB);
+ if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true))
+ DoCast(target, SPELL_BACKSTAB);
_tacticalBlinkCast = false;
_backstabTimer =1300;
} else _backstabTimer -= diff;
@@ -1191,36 +1171,32 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
- if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_1)
+ if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_1)
{
if (uiArcaneBlastTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_ARCANE_BLAST);
uiArcaneBlastTimer = 6000;
} else uiArcaneBlastTimer -= diff;
if (uiSlowTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_SLOW);
uiSlowTimer = 5000;
} else uiSlowTimer -= diff;
}
- if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_2)
+ if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2)
{
if (uiChainsOfIceTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_CHAINS_OF_ICE);
uiChainsOfIceTimer = 7000;
} else uiChainsOfIceTimer -= diff;
@@ -1247,11 +1223,6 @@ class npc_azure_captain : public CreatureScript
public:
npc_azure_captain() : CreatureScript("npc_azure_captain") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_captainAI>(creature);
- }
-
struct npc_azure_captainAI : public violet_hold_trashAI
{
npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature)
@@ -1277,7 +1248,6 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
@@ -1298,6 +1268,10 @@ public:
}
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_captainAI>(creature);
+ }
};
class npc_azure_sorceror : public CreatureScript
@@ -1305,11 +1279,6 @@ class npc_azure_sorceror : public CreatureScript
public:
npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<npc_azure_sorcerorAI>(creature);
- }
-
struct npc_azure_sorcerorAI : public violet_hold_trashAI
{
npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature)
@@ -1337,15 +1306,13 @@ public:
void UpdateAI(uint32 diff) override
{
violet_hold_trashAI::UpdateAI(diff);
- npc_escortAI::UpdateAI(diff);
if (!UpdateVictim())
return;
if (uiArcaneStreamTimer <= diff)
{
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true);
- if (target)
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_ARCANE_STREAM);
uiArcaneStreamTimer = urand(0, 5000)+5000;
uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer;
@@ -1360,6 +1327,11 @@ public:
DoMeleeAttackIfReady();
}
};
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_azure_sorcerorAI>(creature);
+ }
};
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.h b/src/server/scripts/Northrend/VioletHold/violet_hold.h
index 404d1f493e6..275a7467d83 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.h
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.h
@@ -18,13 +18,18 @@
#ifndef DEF_VIOLET_HOLD_H
#define DEF_VIOLET_HOLD_H
-#define DataHeader "VIO"
+#define DataHeader "VH"
+
+uint32 const EncounterCount = 3;
enum Data
{
+ // Main encounters
DATA_1ST_BOSS_EVENT,
DATA_2ND_BOSS_EVENT,
- DATA_CYANIGOSA_EVENT,
+ DATA_CYANIGOSA,
+
+ // Misc
DATA_WAVE_COUNT,
DATA_REMOVE_NPC,
DATA_PORTAL_LOCATION,
@@ -38,10 +43,8 @@ enum Data
DATA_ACTIVATE_CRYSTAL,
DATA_MAIN_EVENT_PHASE,
DATA_DEFENSELESS,
-};
-enum Data64
-{
+ // Bosses
DATA_MORAGG,
DATA_EREKEM,
DATA_EREKEM_GUARD_1,
@@ -50,7 +53,8 @@ enum Data64
DATA_LAVANTHOR,
DATA_XEVOZZ,
DATA_ZURAMAT,
- DATA_CYANIGOSA,
+
+ // Cells
DATA_MORAGG_CELL,
DATA_EREKEM_CELL,
DATA_EREKEM_LEFT_GUARD_CELL,
@@ -59,6 +63,8 @@ enum Data64
DATA_LAVANTHOR_CELL,
DATA_XEVOZZ_CELL,
DATA_ZURAMAT_CELL,
+
+ // Misc
DATA_MAIN_DOOR,
DATA_SINCLARI,
DATA_TELEPORTATION_PORTAL,
@@ -81,33 +87,48 @@ enum Bosses
enum CreaturesIds
{
- CREATURE_TELEPORTATION_PORTAL = 31011,
- CREATURE_PORTAL_GUARDIAN = 30660,
- CREATURE_PORTAL_KEEPER = 30695,
- CREATURE_XEVOZZ = 29266,
- CREATURE_LAVANTHOR = 29312,
- CREATURE_ICHORON = 29313,
- CREATURE_ZURAMAT = 29314,
- CREATURE_EREKEM = 29315,
- CREATURE_EREKEM_GUARD = 29395,
- CREATURE_MORAGG = 29316,
- CREATURE_CYANIGOSA = 31134,
- CREATURE_SINCLARI = 30658,
- CREATURE_SABOTEOUR = 31079,
- NPC_VIOLET_HOLD_GUARD = 30659,
- NPC_DEFENSE_SYSTEM = 30837
+ NPC_TELEPORTATION_PORTAL = 31011,
+ NPC_PORTAL_GUARDIAN = 30660,
+ NPC_PORTAL_KEEPER = 30695,
+ NPC_XEVOZZ = 29266,
+ NPC_LAVANTHOR = 29312,
+ NPC_ICHORON = 29313,
+ NPC_ZURAMAT = 29314,
+ NPC_EREKEM = 29315,
+ NPC_EREKEM_GUARD = 29395,
+ NPC_MORAGG = 29316,
+ NPC_CYANIGOSA = 31134,
+ NPC_SINCLARI = 30658,
+ NPC_SABOTEOUR = 31079,
+ NPC_VIOLET_HOLD_GUARD = 30659,
+ NPC_DEFENSE_SYSTEM = 30837
+};
+
+enum GameObjectIds
+{
+ GO_MAIN_DOOR = 191723,
+ GO_XEVOZZ_DOOR = 191556,
+ GO_LAVANTHOR_DOOR = 191566,
+ GO_ICHORON_DOOR = 191722,
+ GO_ZURAMAT_DOOR = 191565,
+ GO_EREKEM_DOOR = 191564,
+ GO_EREKEM_GUARD_1_DOOR = 191563,
+ GO_EREKEM_GUARD_2_DOOR = 191562,
+ GO_MORAGG_DOOR = 191606,
+ GO_INTRO_ACTIVATION_CRYSTAL = 193615,
+ GO_ACTIVATION_CRYSTAL = 193611
};
enum WorldStateIds
{
- WORLD_STATE_VH = 3816,
- WORLD_STATE_VH_PRISON_STATE = 3815,
- WORLD_STATE_VH_WAVE_COUNT = 3810,
+ WORLD_STATE_VH = 3816,
+ WORLD_STATE_VH_PRISON_STATE = 3815,
+ WORLD_STATE_VH_WAVE_COUNT = 3810,
};
enum Events
{
- EVENT_ACTIVATE_CRYSTAL = 20001
+ EVENT_ACTIVATE_CRYSTAL = 20001
};
#endif
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
index 80c8041bc6d..fac9d8fa357 100644
--- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
+++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
@@ -261,13 +261,13 @@ class OPvPCapturePointNA : public OPvPCapturePoint
public:
OPvPCapturePointNA(OutdoorPvP* pvp);
- bool Update(uint32 diff);
+ bool Update(uint32 diff) override;
- void ChangeState();
+ void ChangeState() override;
- void FillInitialWorldStates(WorldPacket & data);
+ void FillInitialWorldStates(WorldPacket & data) override;
- bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
+ bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override;
int32 HandleOpenGo(Player* player, ObjectGuid guid) override;
diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp
index 662bad46162..263fd8340b9 100644
--- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp
+++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp
@@ -113,7 +113,7 @@ public:
Map::PlayerList const &PlayerList = map->GetPlayers();
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* i_pl = i->GetSource())
- if (i_pl->IsAlive() && (dist = i_pl->IsWithinDist(me, 45)))
+ if (i_pl->IsAlive() && (dist = i_pl->GetDistance(me)) < 45)
{
i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC);
me->AddAura(SPELL_INHIBITMAGIC, i_pl);
diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt
index 24658dbc21f..42621b76941 100644
--- a/src/server/scripts/Outland/CMakeLists.txt
+++ b/src/server/scripts/Outland/CMakeLists.txt
@@ -27,6 +27,7 @@ set(scripts_STAT_SRCS
Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
+ Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
index 21ed710f4d8..7f2e08b39ca 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
@@ -87,11 +87,11 @@ class boss_warchief_kargath_bladefist : public CreatureScript
resetcheck_timer = 5000;
}
- void SetData(uint32 type, uint32 data) override
+ void DoAction(int32 action) override
{
- if (type == 1)
+ if (action == ACTION_EXECUTIONER_TAUNT)
{
- switch (data)
+ switch (instance->GetData(DATA_TEAM_IN_INSTANCE))
{
case ALLIANCE:
Talk(SAY_CALL_EXECUTIONER_A);
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
index 6939b15585a..5cfae286f9b 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
@@ -32,20 +32,11 @@ EndScriptData */
#include "SpellAuras.h"
#include "shattered_halls.h"
-enum Spells
-{
- SPELL_CLEAVE = 15284,
-
- SPELL_EXECUTE_1 = 39288,
- SPELL_EXECUTE_2,
- SPELL_EXECUTE_3
-};
-
DoorData const doorData[] =
{
- {GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_S },
- {GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_N },
- {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE}
+ { GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
+ { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
};
class instance_shattered_halls : public InstanceMapScript
@@ -77,9 +68,7 @@ class instance_shattered_halls : public InstanceMapScript
if (!_team)
_team = player->GetTeam();
- player->RemoveAurasDueToSpell(SPELL_EXECUTE_1);
- player->RemoveAurasDueToSpell(SPELL_EXECUTE_2);
- player->RemoveAurasDueToSpell(SPELL_EXECUTE_3);
+ player->CastSpell(player, SPELL_REMOVE_KARGATH_EXECUTIONER, true);
if (!executionTimer || executionerGUID.IsEmpty())
return;
@@ -87,13 +76,13 @@ class instance_shattered_halls : public InstanceMapScript
switch (executed)
{
case 0:
- ex = player->AddAura(SPELL_EXECUTE_1, player);
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_1, player);
break;
case 1:
- ex = player->AddAura(SPELL_EXECUTE_2, player);
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_2, player);
break;
case 2:
- ex = player->AddAura(SPELL_EXECUTE_3, player);
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_3, player);
break;
default:
break;
@@ -151,10 +140,22 @@ class instance_shattered_halls : public InstanceMapScript
break;
case NPC_SHATTERED_EXECUTIONER:
executionTimer = 55 * MINUTE * IN_MILLISECONDS;
- DoCastSpellOnPlayers(SPELL_EXECUTE_1);
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_1);
executionerGUID = creature->GetGUID();
SaveToDB();
break;
+ case NPC_CAPTAIN_ALINA:
+ case NPC_CAPTAIN_BONESHATTER:
+ victimsGUID[0] = creature->GetGUID();
+ break;
+ case NPC_ALLIANCE_VICTIM_1:
+ case NPC_HORDE_VICTIM_1:
+ victimsGUID[1] = creature->GetGUID();
+ break;
+ case NPC_ALLIANCE_VICTIM_2:
+ case NPC_HORDE_VICTIM_2:
+ victimsGUID[2] = creature->GetGUID();
+ break;
}
}
@@ -168,16 +169,14 @@ class instance_shattered_halls : public InstanceMapScript
case DATA_SHATTERED_EXECUTIONER:
if (state == DONE)
{
- DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1);
- DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2);
- DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3);
+ DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
executionTimer = 0;
SaveToDB();
}
break;
case DATA_KARGATH:
if (Creature* executioner = instance->GetCreature(executionerGUID))
- executioner->AI()->Reset();
+ executioner->AI()->Reset(); // trigger removal of IMMUNE_TO_PC flag
break;
case DATA_OMROGG:
break;
@@ -191,16 +190,16 @@ class instance_shattered_halls : public InstanceMapScript
{
case NPC_GRAND_WARLOCK_NETHEKURSE:
return nethekurseGUID;
- break;
case NPC_KARGATH_BLADEFIST:
return kargathGUID;
- break;
case NPC_SHATTERED_EXECUTIONER:
return executionerGUID;
- break;
+ case DATA_FIRST_PRISONER:
+ case DATA_SECOND_PRISONER:
+ case DATA_THIRD_PRISONER:
+ return victimsGUID[data - DATA_FIRST_PRISONER];
default:
return ObjectGuid::Empty;
- break;
}
}
@@ -253,13 +252,10 @@ class instance_shattered_halls : public InstanceMapScript
{
case DATA_PRISONERS_EXECUTED:
return executed;
- break;
case DATA_TEAM_IN_INSTANCE:
return _team;
- break;
default:
return 0;
- break;
}
}
@@ -269,27 +265,25 @@ class instance_shattered_halls : public InstanceMapScript
return;
if (executionTimer <= diff)
- {
+ {
+ DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
switch (++executed)
{
case 1:
- DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1);
- DoCastSpellOnPlayers(SPELL_EXECUTE_2);
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_2);
executionTimer = 10 * MINUTE * IN_MILLISECONDS;
break;
case 2:
- DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2);
- DoCastSpellOnPlayers(SPELL_EXECUTE_3);
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_3);
executionTimer = 15 * MINUTE * IN_MILLISECONDS;
break;
default:
- DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3);
executionTimer = 0;
break;
}
if (Creature* executioner = instance->GetCreature(executionerGUID))
- executioner->AI()->SetData(1, executed);
+ executioner->AI()->SetData(DATA_PRISONERS_EXECUTED, executed);
SaveToDB();
}
@@ -297,10 +291,11 @@ class instance_shattered_halls : public InstanceMapScript
executionTimer -= diff;
}
- protected:
+ private:
ObjectGuid nethekurseGUID;
ObjectGuid kargathGUID;
ObjectGuid executionerGUID;
+ ObjectGuid victimsGUID[3];
uint8 executed;
uint32 executionTimer;
@@ -308,189 +303,7 @@ class instance_shattered_halls : public InstanceMapScript
};
};
-class at_nethekurse_exit : public AreaTriggerScript
-{
- public:
- at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { };
-
- bool OnTrigger(Player* player, AreaTriggerEntry const*) override
- {
- if (InstanceScript* is = player->GetInstanceScript())
- {
- if (is->instance->IsHeroic())
- {
- Creature* executioner = nullptr;
-
- is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
- if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST)))
- {
- if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty())
- {
- executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
- kargath->AI()->SetData(1, is->GetData(DATA_TEAM_IN_INSTANCE));
- }
- }
-
- if (executioner)
- for (uint8 i = 0; i < VictimCount; ++i)
- executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
- }
- }
-
- return false;
- }
-};
-
-class boss_shattered_executioner : public CreatureScript
-{
- public:
- boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { }
-
- struct boss_shattered_executionerAI : public BossAI
- {
- boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER)
- {
- Initialize();
- };
-
- void Initialize()
- {
- cleaveTimer = 500;
- me->ResetLootMode();
- switch (instance->GetData(DATA_PRISONERS_EXECUTED))
- {
- case 0:
- me->AddLootMode(LOOT_MODE_HARD_MODE_3);
- case 1:
- me->AddLootMode(LOOT_MODE_HARD_MODE_2);
- case 2:
- me->AddLootMode(LOOT_MODE_HARD_MODE_1);
- }
- }
-
- void Reset() override
- {
- _Reset();
- if (instance->GetBossState(DATA_KARGATH) == DONE)
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- else
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
-
- Initialize();
- }
-
- void JustSummoned(Creature*) override { }
-
- void JustDied(Unit*) override
- {
- _JustDied();
- Map::PlayerList const &players = instance->instance->GetPlayers();
- for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- {
- Player* pl = itr->GetSource();
- uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
- if (pl->GetQuestStatus(qId) != QUEST_STATUS_NONE && pl->GetQuestStatus(qId) != QUEST_STATUS_FAILED)
- pl->CompleteQuest(qId);
- }
- }
-
- void SetData(uint32 type, uint32 data) override
- {
- if (type == 1)
- {
- uint32 entry = executionerVictims[data - 1](instance->GetData(DATA_TEAM_IN_INSTANCE));
- if (Creature* victim = me->FindNearestCreature(entry, 30.0f, true))
- me->Kill(victim);
-
- if (data == 1)
- {
- Map::PlayerList const &players = instance->instance->GetPlayers();
- for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
- {
- Player* pl = itr->GetSource();
- uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
- if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
- pl->FailQuest(qId);
- }
- }
-
- switch (data)
- {
- case 3:
- me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
- case 2:
- me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
- case 1:
- me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
- default:
- break;
- }
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
-
- if (cleaveTimer <= diff)
- {
- DoCast(SPELL_CLEAVE);
- cleaveTimer = urand(5000, 7000);
- }
- else
- cleaveTimer -= diff;
-
- DoMeleeAttackIfReady();
- }
- private:
- uint32 cleaveTimer;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_shattered_executionerAI>(creature);
- }
-};
-
-class spell_kargath_executioner : public SpellScriptLoader
-{
- public:
- spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { }
-
- class spell_kargath_executioner_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_kargath_executioner_AuraScript);
-
- bool AreaCheck(Unit* target)
- {
- if (target->GetMap()->GetId() != 540)
- return false;
-
- return true;
- }
-
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_PLAYER;
- }
-
- void Register() override
- {
- DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_kargath_executioner_AuraScript();
- }
-};
-
void AddSC_instance_shattered_halls()
{
new instance_shattered_halls();
- new at_nethekurse_exit();
- new boss_shattered_executioner();
- new spell_kargath_executioner();
}
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
new file mode 100644
index 00000000000..500b0ae4bcb
--- /dev/null
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "InstanceScript.h"
+#include "Player.h"
+#include "SpellAuras.h"
+#include "shattered_halls.h"
+
+class at_nethekurse_exit : public AreaTriggerScript
+{
+ public:
+ at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { };
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const*) override
+ {
+ if (InstanceScript* is = player->GetInstanceScript())
+ {
+ if (is->instance->IsHeroic())
+ {
+ Creature* executioner = nullptr;
+
+ is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
+ if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST)))
+ {
+ if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty())
+ {
+ executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
+ kargath->AI()->DoAction(ACTION_EXECUTIONER_TAUNT);
+ }
+ }
+
+ if (executioner)
+ for (uint8 i = 0; i < VictimCount; ++i)
+ executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
+ }
+ }
+
+ return false;
+ }
+};
+
+enum Spells
+{
+ SPELL_CLEAVE = 15284
+};
+
+class boss_shattered_executioner : public CreatureScript
+{
+ public:
+ boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { }
+
+ struct boss_shattered_executionerAI : public BossAI
+ {
+ boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER)
+ {
+ Initialize();
+ };
+
+ void Initialize()
+ {
+ cleaveTimer = 500;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+
+ // _Reset() resets the loot mode, so we add them again, if any
+ uint32 prisonersExecuted = instance->GetData(DATA_PRISONERS_EXECUTED);
+ if (prisonersExecuted == 0)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_3);
+ if (prisonersExecuted <= 1)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_2);
+ if (prisonersExecuted <= 2)
+ me->AddLootMode(LOOT_MODE_HARD_MODE_1);
+
+ if (instance->GetBossState(DATA_KARGATH) == DONE)
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ else
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+
+ Initialize();
+ }
+
+ void JustSummoned(Creature*) override { } // avoid despawn of prisoners on death/reset
+
+ void JustDied(Unit*) override
+ {
+ _JustDied();
+
+ if (instance->GetData(DATA_PRISONERS_EXECUTED) > 0)
+ return;
+
+ Map::PlayerList const &players = instance->instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ Player* pl = itr->GetSource();
+ uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
+ if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
+ pl->CompleteQuest(qId);
+ }
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ if (type == DATA_PRISONERS_EXECUTED && data <= 3)
+ {
+ if (Creature* victim = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FIRST_PRISONER + data - 1)))
+ me->Kill(victim);
+
+ if (data == 1)
+ {
+ Map::PlayerList const &players = instance->instance->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ Player* pl = itr->GetSource();
+ uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
+ if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
+ pl->FailQuest(qId);
+ }
+ }
+
+ switch (data)
+ {
+ case 3:
+ me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
+ case 2:
+ me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
+ case 1:
+ me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
+ default:
+ break;
+ }
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (cleaveTimer <= diff)
+ {
+ DoCast(SPELL_CLEAVE);
+ cleaveTimer = urand(5000, 7000);
+ }
+ else
+ cleaveTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ private:
+ uint32 cleaveTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_shattered_executionerAI>(creature);
+ }
+};
+
+class spell_kargath_executioner : public SpellScriptLoader
+{
+ public:
+ spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { }
+
+ class spell_kargath_executioner_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_kargath_executioner_AuraScript);
+
+ bool AreaCheck(Unit* target)
+ {
+ if (target->GetMap()->GetId() != 540)
+ return false;
+
+ return true;
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void Register() override
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_kargath_executioner_AuraScript();
+ }
+};
+
+class spell_remove_kargath_executioner : public SpellScriptLoader
+{
+ public:
+ spell_remove_kargath_executioner() : SpellScriptLoader("spell_remove_kargath_executioner") { }
+
+ class spell_remove_kargath_executioner_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_remove_kargath_executioner_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetCaster();
+
+ target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_1);
+ target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_2);
+ target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_3);
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_remove_kargath_executioner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_remove_kargath_executioner_SpellScript();
+ }
+};
+
+void AddSC_shattered_halls()
+{
+ new at_nethekurse_exit();
+ new boss_shattered_executioner();
+ new spell_kargath_executioner();
+ new spell_remove_kargath_executioner();
+}
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
index adc07bec2ff..894cc9c40a6 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
@@ -33,7 +33,11 @@ enum DataTypes
DATA_SHATTERED_EXECUTIONER = 3,
DATA_PRISONERS_EXECUTED = 4,
- DATA_TEAM_IN_INSTANCE = 5
+ DATA_TEAM_IN_INSTANCE = 5,
+
+ DATA_FIRST_PRISONER,
+ DATA_SECOND_PRISONER,
+ DATA_THIRD_PRISONER
};
enum CreatureIds
@@ -70,6 +74,20 @@ enum QuestIds
QUEST_IMPRISONED_H = 9525
};
+enum InstanceSpells
+{
+ SPELL_KARGATH_EXECUTIONER_1 = 39288,
+ SPELL_KARGATH_EXECUTIONER_2 = 39289,
+ SPELL_KARGATH_EXECUTIONER_3 = 39290,
+
+ SPELL_REMOVE_KARGATH_EXECUTIONER = 39291
+};
+
+enum Actions
+{
+ ACTION_EXECUTIONER_TAUNT = 1
+};
+
const Position Executioner = { 152.8524f, -83.63912f, 2.021005f, 0.06981317f };
struct FactionSpawnerHelper
@@ -77,7 +95,7 @@ struct FactionSpawnerHelper
FactionSpawnerHelper(uint32 allianceEntry, uint32 hordeEntry, const Position& pos) : _allianceNPC(allianceEntry), _hordeNPC(hordeEntry), _spawnPos(pos) { }
inline uint32 operator()(uint32 teamID) const { return teamID == ALLIANCE ? _allianceNPC : _hordeNPC; }
- inline const Position GetPos() const { return _spawnPos; }
+ inline Position const& GetPos() const { return _spawnPos; }
private:
const uint32 _allianceNPC;
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
index cc825afd3a0..48508aa4790 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
@@ -77,12 +77,11 @@ class boss_alar : public CreatureScript
public:
boss_alar() : CreatureScript("boss_alar") { }
- struct boss_alarAI : public ScriptedAI
+ struct boss_alarAI : public BossAI
{
- boss_alarAI(Creature* creature) : ScriptedAI(creature)
+ boss_alarAI(Creature* creature) : BossAI(creature, DATA_ALAR)
{
Initialize();
- instance = creature->GetInstanceScript();
DefaultMoveSpeedRate = creature->GetSpeedRate(MOVE_RUN);
DiveBomb_Timer = 0;
MeltArmor_Timer = 0;
@@ -105,8 +104,6 @@ class boss_alar : public CreatureScript
cur_wp = 4;
}
- InstanceScript* instance;
-
WaitEventType WaitEvent;
uint32 WaitTimer;
@@ -129,9 +126,8 @@ class boss_alar : public CreatureScript
void Reset() override
{
- instance->SetData(DATA_ALAREVENT, NOT_STARTED);
-
Initialize();
+ _Reset();
me->SetDisplayId(me->GetNativeDisplayId());
me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
@@ -145,18 +141,11 @@ class boss_alar : public CreatureScript
void EnterCombat(Unit* /*who*/) override
{
- instance->SetData(DATA_ALAREVENT, IN_PROGRESS);
-
+ _EnterCombat();
me->SetDisableGravity(true); // after enterevademode will be set walk movement
- DoZoneInCombat();
me->setActive(true);
}
- void JustDied(Unit* /*killer*/) override
- {
- instance->SetData(DATA_ALAREVENT, DONE);
- }
-
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR)
@@ -508,7 +497,7 @@ class npc_ember_of_alar : public CreatureScript
DoCast(me, SPELL_EMBER_BLAST, true);
me->SetDisplayId(11686);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- if (instance->GetData(DATA_ALAREVENT) == 2)
+ if (instance->GetBossState(DATA_ALAR) == IN_PROGRESS)
{
if (Unit* Alar = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_ALAR)))
{
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp
index 6021e38d3cf..ff9bdf15276 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp
@@ -92,17 +92,13 @@ class boss_high_astromancer_solarian : public CreatureScript
{
public:
- boss_high_astromancer_solarian()
- : CreatureScript("boss_high_astromancer_solarian")
- {
- }
+ boss_high_astromancer_solarian() : CreatureScript("boss_high_astromancer_solarian") { }
- struct boss_high_astromancer_solarianAI : public ScriptedAI
+ struct boss_high_astromancer_solarianAI : public BossAI
{
- boss_high_astromancer_solarianAI(Creature* creature) : ScriptedAI(creature), Summons(me)
+ boss_high_astromancer_solarianAI(Creature* creature) : BossAI(creature, DATA_HIGH_ASTROMANCER_SOLARIAN)
{
Initialize();
- instance = creature->GetInstanceScript();
defaultarmor = creature->GetArmor();
defaultsize = creature->GetObjectScale();
@@ -126,9 +122,6 @@ class boss_high_astromancer_solarian : public CreatureScript
Phase = 1;
}
- InstanceScript* instance;
- SummonList Summons;
-
uint8 Phase;
uint32 ArcaneMissiles_Timer;
@@ -152,16 +145,13 @@ class boss_high_astromancer_solarian : public CreatureScript
void Reset() override
{
Initialize();
-
- instance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED);
-
+ _Reset();
me->SetArmor(defaultarmor);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetVisible(true);
me->SetObjectScale(defaultsize);
me->SetDisplayId(MODEL_HUMAN);
- Summons.DespawnAll();
}
void KilledUnit(Unit* /*victim*/) override
@@ -174,15 +164,13 @@ class boss_high_astromancer_solarian : public CreatureScript
me->SetObjectScale(defaultsize);
me->SetDisplayId(MODEL_HUMAN);
Talk(SAY_DEATH);
- instance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE);
+ _JustDied();
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
- DoZoneInCombat();
-
- instance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS);
+ _EnterCombat();
}
void SummonMinion(uint32 entry, float x, float y, float z)
@@ -193,7 +181,7 @@ class boss_high_astromancer_solarian : public CreatureScript
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
Summoned->AI()->AttackStart(target);
- Summons.Summon(Summoned);
+ summons.Summon(Summoned);
}
}
@@ -431,10 +419,7 @@ class npc_solarium_priest : public CreatureScript
{
public:
- npc_solarium_priest()
- : CreatureScript("npc_solarium_priest")
- {
- }
+ npc_solarium_priest() : CreatureScript("npc_solarium_priest") { }
struct npc_solarium_priestAI : public ScriptedAI
{
@@ -462,9 +447,7 @@ class npc_solarium_priest : public CreatureScript
Initialize();
}
- void EnterCombat(Unit* /*who*/) override
- {
- }
+ void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
index 9aa1981eabb..f5583c0bc53 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp
@@ -286,17 +286,13 @@ class boss_kaelthas : public CreatureScript
{
public:
- boss_kaelthas()
- : CreatureScript("boss_kaelthas")
- {
- }
- //Kael'thas AI
- struct boss_kaelthasAI : public ScriptedAI
+ boss_kaelthas() : CreatureScript("boss_kaelthas") { }
+
+ struct boss_kaelthasAI : public BossAI
{
- boss_kaelthasAI(Creature* creature) : ScriptedAI(creature), summons(me)
+ boss_kaelthasAI(Creature* creature) : BossAI(creature, DATA_KAELTHAS)
{
Initialize();
- instance = creature->GetInstanceScript();
PhaseSubphase = 0;
Phase_Timer = 0;
}
@@ -320,8 +316,6 @@ class boss_kaelthas : public CreatureScript
ChainPyros = false;
}
- InstanceScript* instance;
-
uint32 Fireball_Timer;
uint32 ArcaneDisruption_Timer;
uint32 Phoenix_Timer;
@@ -341,8 +335,6 @@ class boss_kaelthas : public CreatureScript
bool IsCastingFireball;
bool ChainPyros;
- SummonList summons;
-
ObjectGuid m_auiAdvisorGuid[MAX_ADVISORS];
void Reset() override
@@ -351,8 +343,8 @@ class boss_kaelthas : public CreatureScript
if (me->IsInCombat())
PrepareAdvisors();
-
- summons.DespawnAll();
+
+ _Reset();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
@@ -413,7 +405,6 @@ class boss_kaelthas : public CreatureScript
}
void MoveInLineOfSight(Unit* who) override
-
{
if (!me->HasUnitState(UNIT_STATE_STUNNED) && me->CanCreatureAttack(who))
{
@@ -444,6 +435,8 @@ class boss_kaelthas : public CreatureScript
{
if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase)
StartEvent();
+
+ instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS);
}
void KilledUnit(Unit* /*victim*/) override
@@ -463,11 +456,6 @@ class boss_kaelthas : public CreatureScript
}
}
- void SummonedCreatureDespawn(Creature* summon) override
- {
- summons.Despawn(summon);
- }
-
void JustDied(Unit* /*killer*/) override
{
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
@@ -475,8 +463,6 @@ class boss_kaelthas : public CreatureScript
Talk(SAY_DEATH);
- summons.DespawnAll();
-
instance->SetData(DATA_KAELTHASEVENT, 0);
for (uint8 i = 0; i < MAX_ADVISORS; ++i)
@@ -484,6 +470,7 @@ class boss_kaelthas : public CreatureScript
if (Unit* pAdvisor = ObjectAccessor::GetUnit(*me, m_auiAdvisorGuid[i]))
pAdvisor->Kill(pAdvisor);
}
+ _JustDied();
}
void UpdateAI(uint32 diff) override
@@ -1024,10 +1011,8 @@ class boss_thaladred_the_darkener : public CreatureScript
{
public:
- boss_thaladred_the_darkener()
- : CreatureScript("boss_thaladred_the_darkener")
- {
- }
+ boss_thaladred_the_darkener() : CreatureScript("boss_thaladred_the_darkener") { }
+
struct boss_thaladred_the_darkenerAI : public advisorbase_ai
{
boss_thaladred_the_darkenerAI(Creature* creature) : advisorbase_ai(creature)
@@ -1130,10 +1115,8 @@ class boss_lord_sanguinar : public CreatureScript
{
public:
- boss_lord_sanguinar()
- : CreatureScript("boss_lord_sanguinar")
- {
- }
+ boss_lord_sanguinar() : CreatureScript("boss_lord_sanguinar") { }
+
struct boss_lord_sanguinarAI : public advisorbase_ai
{
boss_lord_sanguinarAI(Creature* creature) : advisorbase_ai(creature)
@@ -1205,10 +1188,8 @@ class boss_grand_astromancer_capernian : public CreatureScript
{
public:
- boss_grand_astromancer_capernian()
- : CreatureScript("boss_grand_astromancer_capernian")
- {
- }
+ boss_grand_astromancer_capernian() : CreatureScript("boss_grand_astromancer_capernian") { }
+
struct boss_grand_astromancer_capernianAI : public advisorbase_ai
{
boss_grand_astromancer_capernianAI(Creature* creature) : advisorbase_ai(creature)
@@ -1358,10 +1339,8 @@ class boss_master_engineer_telonicus : public CreatureScript
{
public:
- boss_master_engineer_telonicus()
- : CreatureScript("boss_master_engineer_telonicus")
- {
- }
+ boss_master_engineer_telonicus() : CreatureScript("boss_master_engineer_telonicus") { }
+
struct boss_master_engineer_telonicusAI : public advisorbase_ai
{
boss_master_engineer_telonicusAI(Creature* creature) : advisorbase_ai(creature)
@@ -1449,10 +1428,8 @@ class npc_kael_flamestrike : public CreatureScript
{
public:
- npc_kael_flamestrike()
- : CreatureScript("npc_kael_flamestrike")
- {
- }
+ npc_kael_flamestrike() : CreatureScript("npc_kael_flamestrike") { }
+
struct npc_kael_flamestrikeAI : public ScriptedAI
{
npc_kael_flamestrikeAI(Creature* creature) : ScriptedAI(creature)
@@ -1482,7 +1459,6 @@ class npc_kael_flamestrike : public CreatureScript
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void EnterCombat(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
@@ -1523,10 +1499,8 @@ class npc_phoenix_tk : public CreatureScript
{
public:
- npc_phoenix_tk()
- : CreatureScript("npc_phoenix_tk")
- {
- }
+ npc_phoenix_tk() : CreatureScript("npc_phoenix_tk") { }
+
struct npc_phoenix_tkAI : public ScriptedAI
{
npc_phoenix_tkAI(Creature* creature) : ScriptedAI(creature)
@@ -1585,10 +1559,8 @@ class npc_phoenix_egg_tk : public CreatureScript
{
public:
- npc_phoenix_egg_tk()
- : CreatureScript("npc_phoenix_egg_tk")
- {
- }
+ npc_phoenix_egg_tk() : CreatureScript("npc_phoenix_egg_tk") { }
+
struct npc_phoenix_egg_tkAI : public ScriptedAI
{
npc_phoenix_egg_tkAI(Creature* creature) : ScriptedAI(creature)
@@ -1611,7 +1583,6 @@ class npc_phoenix_egg_tk : public CreatureScript
//ignore any
void MoveInLineOfSight(Unit* /*who*/) override { }
-
void AttackStart(Unit* who) override
{
if (me->Attack(who, false))
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp
index 9186b491fa4..1aa7d5298e5 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp
@@ -47,17 +47,13 @@ class boss_void_reaver : public CreatureScript
{
public:
- boss_void_reaver()
- : CreatureScript("boss_void_reaver")
- {
- }
+ boss_void_reaver() : CreatureScript("boss_void_reaver") { }
- struct boss_void_reaverAI : public ScriptedAI
+ struct boss_void_reaverAI : public BossAI
{
- boss_void_reaverAI(Creature* creature) : ScriptedAI(creature)
+ boss_void_reaverAI(Creature* creature) : BossAI(creature, DATA_VOID_REAVER)
{
Initialize();
- instance = creature->GetInstanceScript();
}
void Initialize()
@@ -70,8 +66,6 @@ class boss_void_reaver : public CreatureScript
Enraged = false;
}
- InstanceScript* instance;
-
uint32 Pounding_Timer;
uint32 ArcaneOrb_Timer;
uint32 KnockAway_Timer;
@@ -82,9 +76,7 @@ class boss_void_reaver : public CreatureScript
void Reset() override
{
Initialize();
-
- if (me->IsAlive())
- instance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED);
+ _Reset();
}
void KilledUnit(Unit* /*victim*/) override
@@ -96,15 +88,13 @@ class boss_void_reaver : public CreatureScript
{
Talk(SAY_DEATH);
DoZoneInCombat();
-
- instance->SetData(DATA_VOIDREAVEREVENT, DONE);
+ _JustDied();
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
-
- instance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS);
+ _EnterCombat();
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp
index 38c9cdd487c..c421b9974ce 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp
@@ -27,8 +27,6 @@ EndScriptData */
#include "InstanceScript.h"
#include "the_eye.h"
-#define MAX_ENCOUNTER 5
-
/* The Eye encounters:
0 - Kael'thas event
1 - Al' ar event
@@ -39,20 +37,16 @@ EndScriptData */
class instance_the_eye : public InstanceMapScript
{
public:
- instance_the_eye()
- : InstanceMapScript("instance_the_eye", 550)
- {
- }
+ instance_the_eye() : InstanceMapScript("instance_the_eye", 550) { }
struct instance_the_eye_InstanceMapScript : public InstanceScript
{
instance_the_eye_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
- memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ SetBossNumber(EncounterCount);
KaelthasEventPhase = 0;
- AlarEventPhase = 0;
}
ObjectGuid ThaladredTheDarkener;
@@ -63,44 +57,34 @@ class instance_the_eye : public InstanceMapScript
ObjectGuid Astromancer;
ObjectGuid Alar;
uint8 KaelthasEventPhase;
- uint8 AlarEventPhase;
-
- uint32 m_auiEncounter[MAX_ENCOUNTER];
-
- bool IsEncounterInProgress() const override
- {
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (m_auiEncounter[i] == IN_PROGRESS)
- return true;
-
- return false;
- }
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
- case 20064:
- ThaladredTheDarkener = creature->GetGUID();
- break;
- case 20063:
- MasterEngineerTelonicus = creature->GetGUID();
- break;
- case 20062:
- GrandAstromancerCapernian = creature->GetGUID();
- break;
- case 20060:
- LordSanguinar = creature->GetGUID();
- break;
- case 19622:
- Kaelthas = creature->GetGUID();
- break;
- case 18805:
- Astromancer = creature->GetGUID();
- break;
- case 19514:
- Alar = creature->GetGUID();
- break;
+ case NPC_SANGUINAR:
+ LordSanguinar = creature->GetGUID();
+ break;
+ case NPC_CAPERNIAN:
+ GrandAstromancerCapernian = creature->GetGUID();
+ break;
+ case NPC_TELONICUS:
+ MasterEngineerTelonicus = creature->GetGUID();
+ break;
+ case NPC_THALADRED:
+ ThaladredTheDarkener = creature->GetGUID();
+ break;
+ case NPC_KAELTHAS:
+ Kaelthas = creature->GetGUID();
+ break;
+ case NPC_HIGH_ASTROMANCER_SOLARIAN:
+ Astromancer = creature->GetGUID();
+ break;
+ case NPC_ALAR:
+ Alar = creature->GetGUID();
+ break;
+ default:
+ break;
}
}
@@ -113,7 +97,7 @@ class instance_the_eye : public InstanceMapScript
case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian;
case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus;
case DATA_KAELTHAS: return Kaelthas;
- case DATA_ASTROMANCER: return Astromancer;
+ case DATA_HIGH_ASTROMANCER_SOLARIAN: return Astromancer;
case DATA_ALAR: return Alar;
}
return ObjectGuid::Empty;
@@ -123,64 +107,23 @@ class instance_the_eye : public InstanceMapScript
{
switch (type)
{
- case DATA_ALAREVENT:
- AlarEventPhase = data;
- m_auiEncounter[0] = data;
- break;
- case DATA_HIGHASTROMANCERSOLARIANEVENT:
- m_auiEncounter[1] = data;
- break;
- case DATA_VOIDREAVEREVENT:
- m_auiEncounter[2] = data;
- break;
- case DATA_KAELTHASEVENT:
- KaelthasEventPhase = data;
- m_auiEncounter[3] = data;
- break;
+ case DATA_KAELTHASEVENT:
+ KaelthasEventPhase = data;
+ break;
+ default:
+ break;
}
- if (data == DONE)
- SaveToDB();
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
- case DATA_ALAREVENT: return AlarEventPhase;
- case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1];
- case DATA_VOIDREAVEREVENT: return m_auiEncounter[2];
- case DATA_KAELTHASEVENT: return KaelthasEventPhase;
+ case DATA_KAELTHASEVENT:
+ return KaelthasEventPhase;
}
return 0;
}
-
- std::string GetSaveData() override
- {
- OUT_SAVE_INST_DATA;
-
- std::ostringstream stream;
- stream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3];
-
- OUT_SAVE_INST_DATA_COMPLETE;
- return stream.str();
- }
-
- void Load(const char* in) override
- {
- if (!in)
- {
- OUT_LOAD_INST_DATA_FAIL;
- return;
- }
- OUT_LOAD_INST_DATA(in);
-
- std::istringstream stream(in);
- stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3];
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
- m_auiEncounter[i] = NOT_STARTED;
- OUT_LOAD_INST_DATA_COMPLETE;
- }
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h
index 718f37861d9..c46fe408274 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h
+++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h
@@ -21,19 +21,33 @@
#define DataHeader "TE"
+uint32 const EncounterCount = 4;
+
enum DataTypes
{
- DATA_ALAREVENT = 1,
- DATA_ASTROMANCER = 2,
- DATA_GRANDASTROMANCERCAPERNIAN = 3,
- DATA_HIGHASTROMANCERSOLARIANEVENT = 4,
- DATA_KAELTHAS = 5,
+ // Encounter States/Boss GUIDs
+ DATA_KAELTHAS = 0,
+ DATA_ALAR = 1,
+ DATA_HIGH_ASTROMANCER_SOLARIAN = 2,
+ DATA_VOID_REAVER = 3,
+
+ DATA_ASTROMANCER = 4,
+ DATA_GRANDASTROMANCERCAPERNIAN = 5,
DATA_KAELTHASEVENT = 6,
DATA_LORDSANGUINAR = 7,
DATA_MASTERENGINEERTELONICUS = 8,
- DATA_THALADREDTHEDARKENER = 10,
- DATA_VOIDREAVEREVENT = 11,
- DATA_ALAR = 12
+ DATA_THALADREDTHEDARKENER = 9
+};
+
+enum CreatureIds
+{
+ NPC_SANGUINAR = 20060,
+ NPC_CAPERNIAN = 20062,
+ NPC_TELONICUS = 20063,
+ NPC_THALADRED = 20064,
+ NPC_KAELTHAS = 19622,
+ NPC_HIGH_ASTROMANCER_SOLARIAN = 18805,
+ NPC_ALAR = 19514
};
#endif
diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
index 471c776d54b..d1a31906d58 100644
--- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
+++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
@@ -770,7 +770,8 @@ public:
void Initialize()
{
circleRounds = 0;
- point = 0;
+ point = 3;
+ wpreached = false;
}
void Reset() override
@@ -778,9 +779,7 @@ public:
events.Reset();
summons.DespawnAll();
- circleRounds = 0;
- point = 3;
- wpreached = false;
+ Initialize();
}
void DoAction(int32 action) override
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index d98ef2ec799..60ff67d74c0 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -208,22 +208,23 @@ class spell_q6124_6129_apply_salve : public SpellScriptLoader
if (GetCastItem())
if (Creature* creatureTarget = GetHitCreature())
{
- uint32 uiNewEntry = 0;
+ uint32 newEntry = 0;
switch (caster->GetTeam())
{
case HORDE:
if (creatureTarget->GetEntry() == NPC_SICKLY_GAZELLE)
- uiNewEntry = NPC_CURED_GAZELLE;
+ newEntry = NPC_CURED_GAZELLE;
break;
case ALLIANCE:
if (creatureTarget->GetEntry() == NPC_SICKLY_DEER)
- uiNewEntry = NPC_CURED_DEER;
+ newEntry = NPC_CURED_DEER;
break;
}
- if (uiNewEntry)
+ if (newEntry)
{
- creatureTarget->UpdateEntry(uiNewEntry);
+ creatureTarget->UpdateEntry(newEntry);
creatureTarget->DespawnOrUnsummon(DESPAWN_TIME);
+ caster->KilledMonsterCredit(newEntry);
}
}
}
@@ -338,7 +339,7 @@ class spell_q11396_11399_scourging_crystal_controller : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q11396_11399_scourging_crystal_controller_SpellScript();
- };
+ }
};
// 43882 Scourging Crystal Controller Dummy
@@ -374,7 +375,7 @@ class spell_q11396_11399_scourging_crystal_controller_dummy : public SpellScript
SpellScript* GetSpellScript() const override
{
return new spell_q11396_11399_scourging_crystal_controller_dummy_SpellScript();
- };
+ }
};
// http://www.wowhead.com/quest=11515 Blood for Blood
@@ -855,7 +856,7 @@ class spell_symbol_of_life_dummy : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_symbol_of_life_dummy_SpellScript();
- };
+ }
};
// http://www.wowhead.com/quest=12659 Scalps!
@@ -898,7 +899,7 @@ class spell_q12659_ahunaes_knife : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q12659_ahunaes_knife_SpellScript();
- };
+ }
};
enum StoppingTheSpread
@@ -944,7 +945,7 @@ class spell_q9874_liquid_fire : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q9874_liquid_fire_SpellScript();
- };
+ }
};
enum SalvagingLifesStength
@@ -988,7 +989,7 @@ class spell_q12805_lifeblood_dummy : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q12805_lifeblood_dummy_SpellScript();
- };
+ }
};
/*
diff --git a/src/server/shared/Cryptography/SHA1.h b/src/server/shared/Cryptography/SHA1.h
index ebd9f721d4a..f59bdc25556 100644
--- a/src/server/shared/Cryptography/SHA1.h
+++ b/src/server/shared/Cryptography/SHA1.h
@@ -39,8 +39,8 @@ class SHA1Hash
void Initialize();
void Finalize();
- uint8 *GetDigest(void) { return mDigest; };
- int GetLength(void) const { return SHA_DIGEST_LENGTH; };
+ uint8 *GetDigest(void) { return mDigest; }
+ int GetLength(void) const { return SHA_DIGEST_LENGTH; }
private:
SHA_CTX mC;
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index f8f641a9ea7..e9f888f280d 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -61,6 +61,9 @@ HANDLE WheatyExceptionReport::m_hDumpFile;
HANDLE WheatyExceptionReport::m_hProcess;
SymbolPairs WheatyExceptionReport::symbols;
std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails;
+bool WheatyExceptionReport::stackOverflowException;
+bool WheatyExceptionReport::alreadyCrashed;
+std::mutex WheatyExceptionReport::alreadyCrashedLock;
// Declare global instance of class
WheatyExceptionReport g_WheatyExceptionReport;
@@ -72,6 +75,8 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor
// Install the unhandled exception filter function
m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter);
m_hProcess = GetCurrentProcess();
+ stackOverflowException = false;
+ alreadyCrashed = false;
if (!IsDebuggerPresent())
{
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
@@ -97,6 +102,16 @@ WheatyExceptionReport::~WheatyExceptionReport()
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo)
{
+ std::unique_lock<std::mutex> guard(alreadyCrashedLock);
+ // Handle only 1 exception in the whole process lifetime
+ if (alreadyCrashed)
+ return EXCEPTION_EXECUTE_HANDLER;
+
+ alreadyCrashed = true;
+
+ if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
+ stackOverflowException = true;
+
TCHAR module_folder_name[MAX_PATH];
GetModuleFileName(0, module_folder_name, MAX_PATH);
TCHAR* pos = _tcsrchr(module_folder_name, '\\');
@@ -419,107 +434,114 @@ void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
void WheatyExceptionReport::GenerateExceptionReport(
PEXCEPTION_POINTERS pExceptionInfo)
{
- SYSTEMTIME systime;
- GetLocalTime(&systime);
-
- // Start out with a banner
- _tprintf(_T("Revision: %s\r\n"), _FULLVERSION);
- _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
- PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
-
- PrintSystemInfo();
- // First print information about the type of fault
- _tprintf(_T("\r\n//=====================================================\r\n"));
- _tprintf(_T("Exception code: %08X %s\r\n"),
- pExceptionRecord->ExceptionCode,
- GetExceptionString(pExceptionRecord->ExceptionCode));
-
- // Now print information about where the fault occured
- TCHAR szFaultingModule[MAX_PATH];
- DWORD section;
- DWORD_PTR offset;
- GetLogicalAddress(pExceptionRecord->ExceptionAddress,
- szFaultingModule,
- sizeof(szFaultingModule),
- section, offset);
+ __try
+ {
+ SYSTEMTIME systime;
+ GetLocalTime(&systime);
+
+ // Start out with a banner
+ _tprintf(_T("Revision: %s\r\n"), _FULLVERSION);
+ _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
+ PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+
+ PrintSystemInfo();
+ // First print information about the type of fault
+ _tprintf(_T("\r\n//=====================================================\r\n"));
+ _tprintf(_T("Exception code: %08X %s\r\n"),
+ pExceptionRecord->ExceptionCode,
+ GetExceptionString(pExceptionRecord->ExceptionCode));
+
+ // Now print information about where the fault occured
+ TCHAR szFaultingModule[MAX_PATH];
+ DWORD section;
+ DWORD_PTR offset;
+ GetLogicalAddress(pExceptionRecord->ExceptionAddress,
+ szFaultingModule,
+ sizeof(szFaultingModule),
+ section, offset);
#ifdef _M_IX86
- _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"),
- pExceptionRecord->ExceptionAddress,
- section, offset, szFaultingModule);
+ _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"),
+ pExceptionRecord->ExceptionAddress,
+ section, offset, szFaultingModule);
#endif
#ifdef _M_X64
- _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
- pExceptionRecord->ExceptionAddress,
- section, offset, szFaultingModule);
+ _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
+ pExceptionRecord->ExceptionAddress,
+ section, offset, szFaultingModule);
#endif
- PCONTEXT pCtx = pExceptionInfo->ContextRecord;
+ PCONTEXT pCtx = pExceptionInfo->ContextRecord;
- // Show the registers
- #ifdef _M_IX86 // X86 Only!
- _tprintf(_T("\r\nRegisters:\r\n"));
+ // Show the registers
+#ifdef _M_IX86 // X86 Only!
+ _tprintf(_T("\r\nRegisters:\r\n"));
- _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
- , pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
- pCtx->Esi, pCtx->Edi);
+ _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
+ , pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
+ pCtx->Esi, pCtx->Edi);
- _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
- _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
- pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
- _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
- pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
- _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
- #endif
+ _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
+ _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
+ pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
+ _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
+ _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+#endif
- #ifdef _M_X64
- _tprintf(_T("\r\nRegisters:\r\n"));
- _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
- _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
- , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
- pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);
- _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
- _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
- pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
- _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
- pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
- _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
- #endif
+#ifdef _M_X64
+ _tprintf(_T("\r\nRegisters:\r\n"));
+ _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
+ _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
+ , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
+ pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);
+ _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
+ _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
+ pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
+ _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
+ _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+#endif
- SymSetOptions(SYMOPT_DEFERRED_LOADS);
+ SymSetOptions(SYMOPT_DEFERRED_LOADS);
- // Initialize DbgHelp
- if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
- {
- _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
- ErrorMessage(GetLastError()));
- }
+ // Initialize DbgHelp
+ if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
+ {
+ _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
+ ErrorMessage(GetLastError()));
+ }
- CONTEXT trashableContext = *pCtx;
+ CONTEXT trashableContext = *pCtx;
- WriteStackDetails(&trashableContext, false, NULL);
- printTracesForAllThreads(false);
+ WriteStackDetails(&trashableContext, false, NULL);
+ printTracesForAllThreads(false);
-// #ifdef _M_IX86 // X86 Only!
+ // #ifdef _M_IX86 // X86 Only!
- _tprintf(_T("========================\r\n"));
- _tprintf(_T("Local Variables And Parameters\r\n"));
+ _tprintf(_T("========================\r\n"));
+ _tprintf(_T("Local Variables And Parameters\r\n"));
- trashableContext = *pCtx;
- WriteStackDetails(&trashableContext, true, NULL);
- printTracesForAllThreads(true);
+ trashableContext = *pCtx;
+ WriteStackDetails(&trashableContext, true, NULL);
+ printTracesForAllThreads(true);
- /*_tprintf(_T("========================\r\n"));
- _tprintf(_T("Global Variables\r\n"));
+ /*_tprintf(_T("========================\r\n"));
+ _tprintf(_T("Global Variables\r\n"));
- SymEnumSymbols(GetCurrentProcess(),
+ SymEnumSymbols(GetCurrentProcess(),
(UINT_PTR)GetModuleHandle(szFaultingModule),
0, EnumerateSymbolsCallback, 0);*/
- // #endif // X86 Only!
+ // #endif // X86 Only!
- SymCleanup(GetCurrentProcess());
+ SymCleanup(GetCurrentProcess());
- _tprintf(_T("\r\n"));
+ _tprintf(_T("\r\n"));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ _tprintf(_T("Error writing the crash log\r\n"));
+ }
}
//======================================================================
@@ -1313,16 +1335,43 @@ DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address)
//============================================================================
int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
{
- TCHAR szBuff[WER_LARGE_BUFFER_SIZE];
int retValue;
- DWORD cbWritten;
va_list argptr;
-
va_start(argptr, format);
+ if (stackOverflowException)
+ {
+ retValue = heapprintf(format, argptr);
+ va_end(argptr);
+ }
+ else
+ {
+ retValue = stackprintf(format, argptr);
+ va_end(argptr);
+ }
+
+ return retValue;
+}
+
+int __cdecl WheatyExceptionReport::stackprintf(const TCHAR * format, va_list argptr)
+{
+ int retValue;
+ DWORD cbWritten;
+
+ TCHAR szBuff[WER_LARGE_BUFFER_SIZE];
retValue = vsprintf(szBuff, format, argptr);
- va_end(argptr);
+ WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0);
+ return retValue;
+}
+
+int __cdecl WheatyExceptionReport::heapprintf(const TCHAR * format, va_list argptr)
+{
+ int retValue;
+ DWORD cbWritten;
+ TCHAR* szBuff = (TCHAR*)malloc(sizeof(TCHAR) * WER_LARGE_BUFFER_SIZE);
+ retValue = vsprintf(szBuff, format, argptr);
WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0);
+ free(szBuff);
return retValue;
}
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h
index b7731daaa2b..ef6334add16 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.h
+++ b/src/server/shared/Debugging/WheatyExceptionReport.h
@@ -178,6 +178,8 @@ class WheatyExceptionReport
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
static int __cdecl _tprintf(const TCHAR * format, ...);
+ static int __cdecl stackprintf(const TCHAR * format, va_list argptr);
+ static int __cdecl heapprintf(const TCHAR * format, va_list argptr);
static bool StoreSymbol(DWORD type , DWORD_PTR offset);
static void ClearSymbols();
@@ -191,6 +193,9 @@ class WheatyExceptionReport
static HANDLE m_hProcess;
static SymbolPairs symbols;
static std::stack<SymbolDetail> symbolDetails;
+ static bool stackOverflowException;
+ static bool alreadyCrashed;
+ static std::mutex alreadyCrashedLock;
static char* PushSymbolDetail(char* pszCurrBuffer);
static char* PopSymbolDetail(char* pszCurrBuffer);
diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h
index d0c15b17f0c..87af9f44eb7 100644
--- a/src/server/shared/PrecompiledHeaders/sharedPCH.h
+++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h
@@ -6,3 +6,4 @@
#include "SQLOperation.h"
#include "Errors.h"
#include "TypeList.h"
+#include "TaskScheduler.h"
diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp
index e5c571e4517..20ded669cec 100644
--- a/src/server/shared/Updater/DBUpdater.cpp
+++ b/src/server/shared/Updater/DBUpdater.cpp
@@ -349,8 +349,27 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
args.push_back("-h" + host);
args.push_back("-u" + user);
args.push_back("-p" + password);
+
+ // Check if we want to connect through ip or socket (Unix only)
+#ifdef _WIN32
+
args.push_back("-P" + port_or_socket);
+#else
+
+ if (!std::isdigit(port_or_socket[0]))
+ {
+ // We can't check here if host == "." because is named localhost if socket option is enabled
+ args.push_back("-P0");
+ args.push_back("--protocol=SOCKET");
+ args.push_back("-S" + port_or_socket);
+ }
+ else
+ // generic case
+ args.push_back("-P" + port_or_socket);
+
+#endif
+
// Set the default charset to utf8
args.push_back("--default-character-set=utf8");
diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/server/shared/Utilities/TaskScheduler.cpp
new file mode 100644
index 00000000000..4b261413fd9
--- /dev/null
+++ b/src/server/shared/Utilities/TaskScheduler.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "TaskScheduler.h"
+
+TaskScheduler& TaskScheduler::Update()
+{
+ _now = clock_t::now();
+ Dispatch();
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::Update(size_t const milliseconds)
+{
+ return Update(std::chrono::milliseconds(milliseconds));
+}
+
+TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
+{
+ _asyncHolder.push(callable);
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::CancelAll()
+{
+ /// Clear the task holder
+ _task_holder.Clear();
+ _asyncHolder = AsyncHolder();
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::CancelGroup(group_t const group)
+{
+ _task_holder.RemoveIf([group](TaskContainer const& task) -> bool
+ {
+ return task->IsInGroup(group);
+ });
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups)
+{
+ std::for_each(groups.begin(), groups.end(),
+ std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1));
+
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
+{
+ _task_holder.Push(std::move(task));
+ return *this;
+}
+
+void TaskScheduler::Dispatch()
+{
+ // Process all asyncs
+ while (!_asyncHolder.empty())
+ {
+ _asyncHolder.front()();
+ _asyncHolder.pop();
+ }
+
+ while (!_task_holder.IsEmpty())
+ {
+ if (_task_holder.First()->_end > _now)
+ break;
+
+ // Perfect forward the context to the handler
+ // Use weak references to catch destruction before callbacks.
+ TaskContext context(_task_holder.Pop(), std::weak_ptr<TaskScheduler>(self_reference));
+
+ // Invoke the context
+ context.Invoke();
+ }
+}
+
+void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
+{
+ container.insert(task);
+}
+
+auto TaskScheduler::TaskQueue::Pop() -> TaskContainer
+{
+ TaskContainer result = *container.begin();
+ container.erase(container.begin());
+ return result;
+}
+
+auto TaskScheduler::TaskQueue::First() const -> TaskContainer const&
+{
+ return *container.begin();
+}
+
+void TaskScheduler::TaskQueue::Clear()
+{
+ container.clear();
+}
+
+void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter)
+{
+ for (auto itr = container.begin(); itr != container.end();)
+ if (filter(*itr))
+ itr = container.erase(itr);
+ else
+ ++itr;
+}
+
+void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
+{
+ std::vector<TaskContainer> cache;
+ for (auto itr = container.begin(); itr != container.end();)
+ if (filter(*itr))
+ {
+ cache.push_back(*itr);
+ itr = container.erase(itr);
+ }
+ else
+ ++itr;
+
+ container.insert(cache.begin(), cache.end());
+}
+
+bool TaskScheduler::TaskQueue::IsEmpty() const
+{
+ return container.empty();
+}
+
+TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply)
+{
+ if (auto const owner = _owner.lock())
+ apply(*owner);
+
+ return *this;
+}
+
+bool TaskContext::IsExpired() const
+{
+ return _owner.expired();
+}
+
+bool TaskContext::IsInGroup(TaskScheduler::group_t const group) const
+{
+ return _task->IsInGroup(group);
+}
+
+TaskContext& TaskContext::SetGroup(TaskScheduler::group_t const group)
+{
+ _task->_group = group;
+ return *this;
+}
+
+TaskContext& TaskContext::ClearGroup()
+{
+ _task->_group = boost::none;
+ return *this;
+}
+
+TaskScheduler::repeated_t TaskContext::GetRepeatCounter() const
+{
+ return _task->_repeated;
+}
+
+TaskContext& TaskContext::Async(std::function<void()> const& callable)
+{
+ return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable));
+}
+
+TaskContext& TaskContext::CancelAll()
+{
+ return Dispatch(std::mem_fn(&TaskScheduler::CancelAll));
+}
+
+TaskContext& TaskContext::CancelGroup(TaskScheduler::group_t const group)
+{
+ return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group));
+}
+
+TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
+{
+ return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, std::cref(groups)));
+}
+
+void TaskContext::AssertOnConsumed() const
+{
+ // This was adapted to TC to prevent static analysis tools from complaining.
+ // If you encounter this assertion check if you repeat a TaskContext more then 1 time!
+ ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!");
+}
+
+void TaskContext::Invoke()
+{
+ _task->_task(*this);
+}
diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h
new file mode 100644
index 00000000000..98e210e55b1
--- /dev/null
+++ b/src/server/shared/Utilities/TaskScheduler.h
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _TASK_SCHEDULER_H_
+#define _TASK_SCHEDULER_H_
+
+#include <algorithm>
+#include <chrono>
+#include <vector>
+#include <queue>
+#include <memory>
+#include <utility>
+#include <set>
+
+#include <boost/optional.hpp>
+
+#include "Util.h"
+
+class TaskContext;
+
+/// The TaskScheduler class provides the ability to schedule std::function's in the near future.
+/// Use TaskScheduler::Update to update the scheduler.
+/// Popular methods are:
+/// * Schedule (Schedules a std::function which will be executed in the near future).
+/// * Schedules an asynchronous function which will be executed at the next update tick.
+/// * Cancel, Delay & Reschedule (Methods to manipulate already scheduled tasks).
+/// Tasks are organized in groups (uint), multiple tasks can have the same group id,
+/// you can provide a group or not, but keep in mind that you can only manipulate specific tasks through its group id!
+/// Tasks callbacks use the function signature void(TaskContext) where TaskContext provides
+/// access to the function schedule plan which makes it possible to repeat the task
+/// with the same duration or a new one.
+/// It also provides access to the repeat counter which is useful for task that repeat itself often
+/// but behave different every time (spoken event dialogs for example).
+class TaskScheduler
+{
+ friend class TaskContext;
+
+ // Time definitions (use steady clock)
+ typedef std::chrono::steady_clock clock_t;
+ typedef clock_t::time_point timepoint_t;
+ typedef clock_t::duration duration_t;
+
+ // Task group type
+ typedef uint32 group_t;
+ // Task repeated type
+ typedef uint32 repeated_t;
+ // Task handle type
+ typedef std::function<void(TaskContext)> task_handler_t;
+
+ class Task
+ {
+ friend class TaskContext;
+ friend class TaskScheduler;
+
+ timepoint_t _end;
+ duration_t _duration;
+ boost::optional<group_t> _group;
+ repeated_t _repeated;
+ task_handler_t _task;
+
+ public:
+ // All Argument construct
+ Task(timepoint_t const& end, duration_t const& duration, boost::optional<group_t> const& group,
+ repeated_t const repeated, task_handler_t const& task)
+ : _end(end), _duration(duration), _group(group), _repeated(repeated), _task(task) { }
+
+ // Minimal Argument construct
+ Task(timepoint_t const& end, duration_t const& duration, task_handler_t const& task)
+ : _end(end), _duration(duration), _group(boost::none), _repeated(0), _task(task) { }
+
+ // Copy construct
+ Task(Task const&) = delete;
+ // Move construct
+ Task(Task&&) = delete;
+ // Copy Assign
+ Task& operator= (Task const&) = default;
+ // Move Assign
+ Task& operator= (Task&& right) = delete;
+
+ // Order tasks by its end
+ inline bool operator< (Task const& other) const
+ {
+ return _end < other._end;
+ }
+
+ inline bool operator> (Task const& other) const
+ {
+ return _end > other._end;
+ }
+
+ // Compare tasks with its end
+ inline bool operator== (Task const& other)
+ {
+ return _end == other._end;
+ }
+
+ // Returns true if the task is in the given group
+ inline bool IsInGroup(group_t const group) const
+ {
+ return _group == group;
+ }
+ };
+
+ typedef std::shared_ptr<Task> TaskContainer;
+
+ /// Container which provides Task order, insert and reschedule operations.
+ struct Compare
+ {
+ bool operator() (TaskContainer const& left, TaskContainer const& right)
+ {
+ return (*left.get()) < (*right.get());
+ };
+ };
+
+ class TaskQueue
+ {
+ std::multiset<TaskContainer, Compare> container;
+
+ public:
+ // Pushes the task in the container
+ void Push(TaskContainer&& task);
+
+ /// Pops the task out of the container
+ TaskContainer Pop();
+
+ TaskContainer const& First() const;
+
+ void Clear();
+
+ void RemoveIf(std::function<bool(TaskContainer const&)> const& filter);
+
+ void ModifyIf(std::function<bool(TaskContainer const&)> const& filter);
+
+ bool IsEmpty() const;
+ };
+
+ /// Contains a self reference to track if this object was deleted or not.
+ std::shared_ptr<TaskScheduler> self_reference;
+
+ /// The current time point (now)
+ timepoint_t _now;
+
+ /// The Task Queue which contains all task objects.
+ TaskQueue _task_holder;
+
+ typedef std::queue<std::function<void()>> AsyncHolder;
+
+ /// Contains all asynchronous tasks which will be invoked at
+ /// the next update tick.
+ AsyncHolder _asyncHolder;
+
+public:
+ TaskScheduler() : self_reference(this, [](TaskScheduler const*) { }),
+ _now(clock_t::now()) { }
+
+ TaskScheduler(TaskScheduler const&) = delete;
+ TaskScheduler(TaskScheduler&&) = delete;
+ TaskScheduler& operator= (TaskScheduler const&) = delete;
+ TaskScheduler& operator= (TaskScheduler&&) = delete;
+
+ /// Update the scheduler to the current time.
+ TaskScheduler& Update();
+
+ /// Update the scheduler with a difftime in ms.
+ TaskScheduler& Update(size_t const milliseconds);
+
+ /// Update the scheduler with a difftime.
+ template<class _Rep, class _Period>
+ TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime)
+ {
+ _now += difftime;
+ Dispatch();
+ return *this;
+ }
+
+ /// Schedule an callable function that is executed at the next update tick.
+ /// Its safe to modify the TaskScheduler from within the callable.
+ TaskScheduler& Async(std::function<void()> const& callable);
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _Rep, class _Period>
+ TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ task_handler_t const& task)
+ {
+ return ScheduleAt(_now, time, task);
+ }
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _Rep, class _Period>
+ TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ group_t const group, task_handler_t const& task)
+ {
+ return ScheduleAt(_now, time, group, task);
+ }
+
+ /// Schedule an event with a randomized rate between min and max rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, task_handler_t const& task)
+ {
+ return Schedule(RandomDurationBetween(min, max), task);
+ }
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::Schedule instead!
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, group_t const group,
+ task_handler_t const& task)
+ {
+ return Schedule(RandomDurationBetween(min, max), group, task);
+ }
+
+ /// Cancels all tasks.
+ /// Never call this from within a task context! Use TaskContext::CancelAll instead!
+ TaskScheduler& CancelAll();
+
+ /// Cancel all tasks of a single group.
+ /// Never call this from within a task context! Use TaskContext::CancelGroup instead!
+ TaskScheduler& CancelGroup(group_t const group);
+
+ /// Cancels all groups in the given std::vector.
+ /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}"
+ TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups);
+
+ /// Delays all tasks with the given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ _task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool
+ {
+ task->_end += duration;
+ return true;
+ });
+ return *this;
+ }
+
+ /// Delays all tasks with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayAll(RandomDurationBetween(min, max));
+ }
+
+ /// Delays all tasks of a group with the given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ _task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool
+ {
+ if (task->IsInGroup(group))
+ {
+ task->_end += duration;
+ return true;
+ }
+ else
+ return false;
+ });
+ return *this;
+ }
+
+ /// Delays all tasks of a group with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& DelayGroup(group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayGroup(group, RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks with a given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ auto const end = _now + duration;
+ _task_holder.ModifyIf([end](TaskContainer const& task) -> bool
+ {
+ task->_end = end;
+ return true;
+ });
+ return *this;
+ }
+
+ /// Reschedule all tasks with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleAll(RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks of a group with the given duration.
+ template<class _Rep, class _Period>
+ TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ auto const end = _now + duration;
+ _task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool
+ {
+ if (task->IsInGroup(group))
+ {
+ task->_end = end;
+ return true;
+ }
+ else
+ return false;
+ });
+ return *this;
+ }
+
+ /// Reschedule all tasks of a group with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskScheduler& RescheduleGroup(group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleGroup(group, RandomDurationBetween(min, max));
+ }
+
+private:
+ /// Insert a new task to the enqueued tasks.
+ TaskScheduler& InsertTask(TaskContainer task);
+
+ template<class _Rep, class _Period>
+ TaskScheduler& ScheduleAt(timepoint_t const& end,
+ std::chrono::duration<_Rep, _Period> const& time, task_handler_t const& task)
+ {
+ return InsertTask(TaskContainer(new Task(end + time, time, task)));
+ }
+
+ /// Schedule an event with a fixed rate.
+ /// Never call this from within a task context! Use TaskContext::schedule instead!
+ template<class _Rep, class _Period>
+ TaskScheduler& ScheduleAt(timepoint_t const& end,
+ std::chrono::duration<_Rep, _Period> const& time,
+ group_t const group, task_handler_t const& task)
+ {
+ static repeated_t const DEFAULT_REPEATED = 0;
+ return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, task)));
+ }
+
+ // Returns a random duration between min and max
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ static std::chrono::milliseconds
+ RandomDurationBetween(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ auto const milli_min = std::chrono::duration_cast<std::chrono::milliseconds>(min);
+ auto const milli_max = std::chrono::duration_cast<std::chrono::milliseconds>(max);
+
+ // TC specific: use SFMT URandom
+ return std::chrono::milliseconds(urand(milli_min.count(), milli_max.count()));
+ }
+
+ /// Dispatch remaining tasks
+ void Dispatch();
+};
+
+class TaskContext
+{
+ friend class TaskScheduler;
+
+ /// Associated task
+ TaskScheduler::TaskContainer _task;
+
+ /// Owner
+ std::weak_ptr<TaskScheduler> _owner;
+
+ /// Marks the task as consumed
+ std::shared_ptr<bool> _consumed;
+
+ /// Dispatches an action safe on the TaskScheduler
+ TaskContext& Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply);
+
+public:
+ // Empty constructor
+ TaskContext()
+ : _task(), _owner(), _consumed(std::make_shared<bool>(true)) { }
+
+ // Construct from task and owner
+ explicit TaskContext(TaskScheduler::TaskContainer&& task, std::weak_ptr<TaskScheduler>&& owner)
+ : _task(task), _owner(owner), _consumed(std::make_shared<bool>(false)) { }
+
+ // Copy construct
+ TaskContext(TaskContext const& right)
+ : _task(right._task), _owner(right._owner), _consumed(right._consumed) { }
+
+ // Move construct
+ TaskContext(TaskContext&& right)
+ : _task(std::move(right._task)), _owner(std::move(right._owner)), _consumed(std::move(right._consumed)) { }
+
+ // Copy assign
+ TaskContext& operator= (TaskContext const& right)
+ {
+ _task = right._task;
+ _owner = right._owner;
+ _consumed = right._consumed;
+ return *this;
+ }
+
+ // Move assign
+ TaskContext& operator= (TaskContext&& right)
+ {
+ _task = std::move(right._task);
+ _owner = std::move(right._owner);
+ _consumed = std::move(right._consumed);
+ return *this;
+ }
+
+ /// Returns true if the owner was deallocated and this context has expired.
+ bool IsExpired() const;
+
+ /// Returns true if the event is in the given group
+ bool IsInGroup(TaskScheduler::group_t const group) const;
+
+ /// Sets the event in the given group
+ TaskContext& SetGroup(TaskScheduler::group_t const group);
+
+ /// Removes the group from the event
+ TaskContext& ClearGroup();
+
+ /// Returns the repeat counter which increases every time the task is repeated.
+ TaskScheduler::repeated_t GetRepeatCounter() const;
+
+ /// Repeats the event and sets a new duration.
+ /// std::chrono::seconds(5) for example.
+ /// This will consume the task context, its not possible to repeat the task again
+ /// from the same task context!
+ template<class _Rep, class _Period>
+ TaskContext& Repeat(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ AssertOnConsumed();
+
+ // Set new duration, in-context timing and increment repeat counter
+ _task->_duration = duration;
+ _task->_end += duration;
+ _task->_repeated += 1;
+ (*_consumed) = true;
+ return Dispatch(std::bind(&TaskScheduler::InsertTask, std::placeholders::_1, _task));
+ }
+
+ /// Repeats the event with the same duration.
+ /// This will consume the task context, its not possible to repeat the task again
+ /// from the same task context!
+ TaskContext& Repeat()
+ {
+ return Repeat(_task->_duration);
+ }
+
+ /// Repeats the event and set a new duration that is randomized between min and max.
+ /// std::chrono::seconds(5) for example.
+ /// This will consume the task context, its not possible to repeat the task again
+ /// from the same task context!
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& Repeat(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return Repeat(TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Schedule a callable function that is executed at the next update tick from within the context.
+ /// Its safe to modify the TaskScheduler from within the callable.
+ TaskContext& Async(std::function<void()> const& callable);
+
+ /// Schedule an event with a fixed rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _Rep, class _Period>
+ TaskContext& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ TaskScheduler::task_handler_t const& task)
+ {
+ auto const end = _task->_end;
+ return Dispatch([end, time, task](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.ScheduleAt<_Rep, _Period>(end, time, task);
+ });
+ }
+
+ /// Schedule an event with a fixed rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _Rep, class _Period>
+ TaskContext& Schedule(std::chrono::duration<_Rep, _Period> const& time,
+ TaskScheduler::group_t const group, TaskScheduler::task_handler_t const& task)
+ {
+ auto const end = _task->_end;
+ return Dispatch([end, time, group, task](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.ScheduleAt<_Rep, _Period>(end, time, group, task);
+ });
+ }
+
+ /// Schedule an event with a randomized rate between min and max rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::task_handler_t const& task)
+ {
+ return Schedule(TaskScheduler::RandomDurationBetween(min, max), task);
+ }
+
+ /// Schedule an event with a randomized rate between min and max rate from within the context.
+ /// Its possible that the new event is executed immediately!
+ /// Use TaskScheduler::Async to create a task
+ /// which will be called at the next update tick.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::group_t const group,
+ TaskScheduler::task_handler_t const& task)
+ {
+ return Schedule(TaskScheduler::RandomDurationBetween(min, max), group, task);
+ }
+
+ /// Cancels all tasks from within the context.
+ TaskContext& CancelAll();
+
+ /// Cancel all tasks of a single group from within the context.
+ TaskContext& CancelGroup(TaskScheduler::group_t const group);
+
+ /// Cancels all groups in the given std::vector from within the context.
+ /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}"
+ TaskContext& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups);
+
+ /// Delays all tasks with the given duration from within the context.
+ template<class _Rep, class _Period>
+ TaskContext& DelayAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::DelayAll<_Rep, _Period>, std::placeholders::_1, duration));
+ }
+
+ /// Delays all tasks with a random duration between min and max from within the context.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayAll(TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Delays all tasks of a group with the given duration from within the context.
+ template<class _Rep, class _Period>
+ TaskContext& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::DelayGroup<_Rep, _Period>, std::placeholders::_1, group, duration));
+ }
+
+ /// Delays all tasks of a group with a random duration between min and max from within the context.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& DelayGroup(TaskScheduler::group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return DelayGroup(group, TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks with the given duration.
+ template<class _Rep, class _Period>
+ TaskContext& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::RescheduleAll, std::placeholders::_1, duration));
+ }
+
+ /// Reschedule all tasks with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleAll(TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+ /// Reschedule all tasks of a group with the given duration.
+ template<class _Rep, class _Period>
+ TaskContext& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration)
+ {
+ return Dispatch(std::bind(&TaskScheduler::RescheduleGroup<_Rep, _Period>, std::placeholders::_1, group, duration));
+ }
+
+ /// Reschedule all tasks of a group with a random duration between min and max.
+ template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ TaskContext& RescheduleGroup(TaskScheduler::group_t const group,
+ std::chrono::duration<_RepLeft, _PeriodLeft> const& min,
+ std::chrono::duration<_RepRight, _PeriodRight> const& max)
+ {
+ return RescheduleGroup(group, TaskScheduler::RandomDurationBetween(min, max));
+ }
+
+private:
+ /// Asserts if the task was consumed already.
+ void AssertOnConsumed() const;
+
+ /// Invokes the associated hook of the task.
+ void Invoke();
+};
+
+/// Milliseconds shorthand typedef.
+typedef std::chrono::milliseconds Milliseconds;
+
+/// Seconds shorthand typedef.
+typedef std::chrono::seconds Seconds;
+
+/// Minutes shorthand typedef.
+typedef std::chrono::minutes Minutes;
+
+/// Hours shorthand typedef.
+typedef std::chrono::hours Hours;
+
+#endif /// _TASK_SCHEDULER_H_
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 2758c8e39cd..447ef9a45a8 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1021,7 +1021,7 @@ OffhandCheckAtSpellUnlearn = 1
# ClientCacheVersion
# Description: Client cache version for client cache data reset. Use any value different
# from DB and not recently been used to trigger client side cache reset.
-# Default: 0 - (Use DB value from world DB db_version.cache_id field)
+# Default: 0 - (Use DB value from world DB version.cache_id field)
ClientCacheVersion = 0
diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp
index 3e12747e9c5..482e3a3abbd 100644
--- a/src/tools/map_extractor/mpq_libmpq.cpp
+++ b/src/tools/map_extractor/mpq_libmpq.cpp
@@ -71,7 +71,7 @@ MPQFile::MPQFile(const char* filename):
uint32_t filenum;
if(libmpq__file_number(mpq_a, filename, &filenum)) continue;
libmpq__off_t transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
+ libmpq__file_size_unpacked(mpq_a, filenum, &size);
// HACK: in patch.mpq some files don't want to open and give 1 for filesize
if (size<=1) {
diff --git a/src/tools/map_extractor/mpq_libmpq04.h b/src/tools/map_extractor/mpq_libmpq04.h
index 470e7bd0c50..c6fe36a8221 100644
--- a/src/tools/map_extractor/mpq_libmpq04.h
+++ b/src/tools/map_extractor/mpq_libmpq04.h
@@ -43,7 +43,7 @@ public:
uint32_t filenum;
if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return;
libmpq__off_t size, transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
+ libmpq__file_size_unpacked(mpq_a, filenum, &size);
char *buffer = new char[size+1];
buffer[size] = '\0';
diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp
index 5e0effc1a77..f3eb3da96b6 100644
--- a/src/tools/vmap4_extractor/mpq_libmpq.cpp
+++ b/src/tools/vmap4_extractor/mpq_libmpq.cpp
@@ -71,7 +71,7 @@ MPQFile::MPQFile(const char* filename):
uint32 filenum;
if(libmpq__file_number(mpq_a, filename, &filenum)) continue;
libmpq__off_t transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
+ libmpq__file_size_unpacked(mpq_a, filenum, &size);
// HACK: in patch.mpq some files don't want to open and give 1 for filesize
if (size<=1) {
diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h
index bb842daf258..6196285627d 100644
--- a/src/tools/vmap4_extractor/mpq_libmpq04.h
+++ b/src/tools/vmap4_extractor/mpq_libmpq04.h
@@ -42,7 +42,7 @@ public:
uint32_t filenum;
if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return;
libmpq__off_t size, transferred;
- libmpq__file_unpacked_size(mpq_a, filenum, &size);
+ libmpq__file_size_unpacked(mpq_a, filenum, &size);
char *buffer = new char[size + 1];
buffer[size] = '\0';