aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/bnetserver/Main.cpp93
-rw-r--r--src/server/collision/Management/MMapManager.cpp157
-rw-r--r--src/server/collision/Management/VMapManager2.cpp2
-rw-r--r--src/server/collision/Maps/MapTree.cpp2
-rw-r--r--src/server/collision/Maps/TileAssembler.cpp5
-rw-r--r--src/server/collision/Models/GameObjectModel.cpp10
-rw-r--r--src/server/collision/Models/GameObjectModel.h2
-rw-r--r--src/server/collision/VMapDefinitions.h4
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h2
-rw-r--r--src/server/game/AI/CreatureAISelector.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp32
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h32
-rw-r--r--src/server/game/Accounts/RBAC.h9
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp142
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp4
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp24
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundBFG.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundTP.h2
-rw-r--r--src/server/game/CMakeLists.txt5
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp44
-rw-r--r--src/server/game/Chat/Channels/Channel.h6
-rw-r--r--src/server/game/Chat/Chat.cpp22
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp105
-rw-r--r--src/server/game/DataStores/DB2Stores.h15
-rw-r--r--src/server/game/DataStores/DB2Structure.h160
-rw-r--r--src/server/game/DataStores/DB2fmt.h12
-rw-r--r--src/server/game/DataStores/DBCEnums.h287
-rw-r--r--src/server/game/DataStores/DBCStores.cpp30
-rw-r--r--src/server/game/DataStores/DBCStores.h6
-rw-r--r--src/server/game/DataStores/DBCStructure.h62
-rw-r--r--src/server/game/DataStores/DBCfmt.h8
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp12
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp1
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp15
-rw-r--r--src/server/game/Entities/Creature/Creature.h6
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp14
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h1
-rw-r--r--src/server/game/Entities/Item/Item.cpp30
-rw-r--r--src/server/game/Entities/Item/Item.h10
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.cpp4
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h223
-rw-r--r--src/server/game/Entities/Object/Object.cpp221
-rw-r--r--src/server/game/Entities/Object/Object.h147
-rw-r--r--src/server/game/Entities/Object/Position.cpp184
-rw-r--r--src/server/game/Entities/Object/Position.h225
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp26
-rw-r--r--src/server/game/Entities/Pet/Pet.h8
-rw-r--r--src/server/game/Entities/Player/Player.cpp434
-rw-r--r--src/server/game/Entities/Player/Player.h108
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp83
-rw-r--r--src/server/game/Entities/Transport/Transport.h3
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp50
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp208
-rw-r--r--src/server/game/Entities/Unit/Unit.h140
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.cpp10
-rw-r--r--src/server/game/Events/GameEventMgr.cpp25
-rw-r--r--src/server/game/Events/GameEventMgr.h6
-rw-r--r--src/server/game/Garrison/Garrison.cpp690
-rw-r--r--src/server/game/Garrison/Garrison.h159
-rw-r--r--src/server/game/Garrison/GarrisonMap.cpp142
-rw-r--r--src/server/game/Garrison/GarrisonMap.h43
-rw-r--r--src/server/game/Garrison/GarrisonMgr.cpp353
-rw-r--r--src/server/game/Garrison/GarrisonMgr.h69
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp143
-rw-r--r--src/server/game/Globals/ObjectMgr.h7
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h24
-rw-r--r--src/server/game/Groups/Group.cpp453
-rw-r--r--src/server/game/Groups/Group.h156
-rw-r--r--src/server/game/Groups/GroupMgr.cpp7
-rw-r--r--src/server/game/Groups/GroupMgr.h2
-rw-r--r--src/server/game/Guilds/Guild.cpp29
-rw-r--r--src/server/game/Guilds/Guild.h3
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp45
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp16
-rw-r--r--src/server/game/Handlers/GarrisonHandler.cpp56
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp982
-rw-r--r--src/server/game/Handlers/GuildHandler.cpp6
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp97
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp2
-rw-r--r--src/server/game/Handlers/LootHandler.cpp4
-rw-r--r--src/server/game/Handlers/MailHandler.cpp8
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp133
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp27
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp51
-rw-r--r--src/server/game/Handlers/PetHandler.cpp3
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp19
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp2
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp12
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp8
-rw-r--r--src/server/game/Handlers/VoidStorageHandler.cpp2
-rw-r--r--src/server/game/Loot/LootMgr.cpp22
-rw-r--r--src/server/game/Maps/Map.cpp73
-rw-r--r--src/server/game/Maps/Map.h10
-rw-r--r--src/server/game/Maps/MapInstanced.cpp23
-rw-r--r--src/server/game/Maps/MapInstanced.h3
-rw-r--r--src/server/game/Maps/ZoneScript.h4
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h70
-rw-r--r--src/server/game/Movement/MotionMaster.h2
-rw-r--r--src/server/game/Movement/Spline/MoveSplineFlag.h38
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp18
-rw-r--r--src/server/game/Pools/PoolMgr.cpp16
-rw-r--r--src/server/game/Quests/QuestDef.cpp4
-rw-r--r--src/server/game/Quests/QuestDef.h8
-rw-r--r--src/server/game/Scripting/MapScripts.cpp42
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp2
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp8
-rw-r--r--src/server/game/Server/Packets/ChannelPackets.cpp43
-rw-r--r--src/server/game/Server/Packets/ChannelPackets.h50
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp49
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.h31
-rw-r--r--src/server/game/Server/Packets/ChatPackets.cpp33
-rw-r--r--src/server/game/Server/Packets/ChatPackets.h31
-rw-r--r--src/server/game/Server/Packets/CombatLogPackets.cpp73
-rw-r--r--src/server/game/Server/Packets/CombatLogPackets.h74
-rw-r--r--src/server/game/Server/Packets/CombatPackets.cpp9
-rw-r--r--src/server/game/Server/Packets/CombatPackets.h12
-rw-r--r--src/server/game/Server/Packets/EquipmentSetPackets.cpp3
-rw-r--r--src/server/game/Server/Packets/EquipmentSetPackets.h2
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.cpp247
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.h285
-rw-r--r--src/server/game/Server/Packets/GuildPackets.cpp11
-rw-r--r--src/server/game/Server/Packets/InstancePackets.cpp74
-rw-r--r--src/server/game/Server/Packets/InstancePackets.h113
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp23
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h34
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp81
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h41
-rw-r--r--src/server/game/Server/Packets/MovementPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/MovementPackets.h2
-rw-r--r--src/server/game/Server/Packets/NPCPackets.cpp16
-rw-r--r--src/server/game/Server/Packets/NPCPackets.h24
-rw-r--r--src/server/game/Server/Packets/PartyPackets.cpp715
-rw-r--r--src/server/game/Server/Packets/PartyPackets.h616
-rw-r--r--src/server/game/Server/Packets/QueryPackets.cpp29
-rw-r--r--src/server/game/Server/Packets/QueryPackets.h27
-rw-r--r--src/server/game/Server/Packets/QuestPackets.cpp12
-rw-r--r--src/server/game/Server/Packets/QuestPackets.h3
-rw-r--r--src/server/game/Server/Packets/ReferAFriendPackets.cpp3
-rw-r--r--src/server/game/Server/Packets/SystemPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/TicketPackets.cpp3
-rw-r--r--src/server/game/Server/Packets/WhoPackets.cpp7
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp257
-rw-r--r--src/server/game/Server/WorldSession.cpp24
-rw-r--r--src/server/game/Server/WorldSession.h144
-rw-r--r--src/server/game/Server/WorldSocket.cpp9
-rw-r--r--src/server/game/Server/WorldSocket.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h8
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp71
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h4
-rw-r--r--src/server/game/Spells/Spell.cpp93
-rw-r--r--src/server/game/Spells/Spell.h10
-rw-r--r--src/server/game/Spells/SpellEffects.cpp156
-rw-r--r--src/server/game/Spells/SpellInfo.cpp11
-rw-r--r--src/server/game/Spells/SpellInfo.h1
-rw-r--r--src/server/game/Spells/SpellMgr.cpp4
-rw-r--r--src/server/game/Spells/SpellScript.cpp8
-rw-r--r--src/server/game/Spells/SpellScript.h2
-rw-r--r--src/server/game/Support/SupportMgr.cpp32
-rw-r--r--src/server/game/Support/SupportMgr.h12
-rw-r--r--src/server/game/Texts/ChatTextBuilder.h4
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp4
-rw-r--r--src/server/game/World/World.cpp43
-rw-r--r--src/server/game/World/World.h4
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_go.cpp68
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp28
-rw-r--r--src/server/scripts/Commands/cs_group.cpp2
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp2
-rw-r--r--src/server/scripts/Commands/cs_message.cpp6
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp12
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp10
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp79
-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/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp187
-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/Nexus/EyeOfEternity/boss_malygos.cpp1
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h3
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp6
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp39
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp20
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp48
-rw-r--r--src/server/scripts/OutdoorPvP/OutdoorPvPNA.h8
-rw-r--r--src/server/scripts/Outland/CMakeLists.txt1
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp4
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp5
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp28
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp231
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp255
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h80
-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.cpp73
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp164
-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/Spells/spell_quest.cpp12
-rw-r--r--src/server/shared/Common.h11
-rw-r--r--src/server/shared/Cryptography/SHA1.h4
-rw-r--r--src/server/shared/Cryptography/SHA256.h4
-rw-r--r--src/server/shared/DataStores/DB2Store.h2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp17
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h16
-rw-r--r--src/server/shared/Database/Implementation/HotfixDatabase.cpp62
-rw-r--r--src/server/shared/Database/Implementation/HotfixDatabase.h33
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp4
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp203
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h3
-rw-r--r--src/server/shared/Logging/Log.h5
-rw-r--r--src/server/shared/Networking/MessageBuffer.h4
-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/Main.cpp12
-rw-r--r--src/server/worldserver/worldserver.conf.dist2
-rw-r--r--src/tools/map_extractor/System.cpp4
-rw-r--r--src/tools/mmaps_generator/CMakeLists.txt10
-rw-r--r--src/tools/mmaps_generator/MapBuilder.cpp141
-rw-r--r--src/tools/mmaps_generator/TerrainBuilder.cpp4
-rw-r--r--src/tools/vmap4_extractor/vmapexport.cpp6
233 files changed, 10361 insertions, 3931 deletions
diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp
index 20d1193b8e2..86590bfa3f5 100644
--- a/src/server/bnetserver/Main.cpp
+++ b/src/server/bnetserver/Main.cpp
@@ -51,25 +51,52 @@ using namespace boost::program_options;
# define _TRINITY_BNET_CONFIG "bnetserver.conf"
#endif
+#if PLATFORM == PLATFORM_WINDOWS
+#include "ServiceWin32.h"
+char serviceName[] = "bnetserver";
+char serviceLongName[] = "TrinityCore bnet service";
+char serviceDescription[] = "TrinityCore Battle.net emulator authentication service";
+/*
+* -1 - not in service mode
+* 0 - stopped
+* 1 - running
+* 2 - paused
+*/
+int m_ServiceStatus = -1;
+
+static 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);
-std::unique_ptr<boost::asio::io_service> _ioService;
-std::unique_ptr<boost::asio::deadline_timer> _dbPingTimer;
-uint32 _dbPingInterval;
+static boost::asio::io_service* _ioService;
+static boost::asio::deadline_timer* _dbPingTimer;
+static uint32 _dbPingInterval;
LoginDatabaseWorkerPool LoginDatabase;
int main(int argc, char** argv)
{
std::string configFile = _TRINITY_BNET_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() ? 0 : 1;
+ else if (configService.compare("uninstall") == 0)
+ return WinServiceUninstall() ? 0 : 1;
+ else if (configService.compare("run") == 0)
+ return WinServiceRun() ? 0 : 1;
+#endif
+
std::string configError;
if (!sConfigMgr->LoadInitial(configFile, configError))
{
@@ -109,7 +136,7 @@ int main(int argc, char** argv)
sIpcContext->Initialize();
- _ioService.reset(new boost::asio::io_service());
+ _ioService = new boost::asio::io_service();
// Get the list of realms for the server
sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10), worldListenPort);
@@ -120,6 +147,7 @@ int main(int argc, char** argv)
{
TC_LOG_ERROR("server.bnetserver", "Specified battle.net port (%d) out of allowed range (1-65535)", bnport);
StopDB();
+ delete _ioService;
return 1;
}
@@ -139,13 +167,22 @@ int main(int argc, char** argv)
// Enabled a timed callback for handling the database keep alive ping
_dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30);
- _dbPingTimer.reset(new boost::asio::deadline_timer(*_ioService));
+ _dbPingTimer = new boost::asio::deadline_timer(*_ioService);
_dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval));
_dbPingTimer->async_wait(KeepDatabaseAliveHandler);
sComponentMgr->Load();
sModuleMgr->Load();
+#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();
@@ -162,9 +199,10 @@ int main(int argc, char** argv)
TC_LOG_INFO("server.bnetserver", "Halting process...");
- signals.clear();
+ signals.cancel();
- _ioService.reset();
+ delete _dbPingTimer;
+ delete _ioService;
return 0;
}
@@ -211,24 +249,55 @@ void KeepDatabaseAliveHandler(const boost::system::error_code& error)
}
}
-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)
{
+ (void)configService;
+
options_description all("Allowed options");
all.add_options()
("help,h", "print usage message")
("config,c", value<std::string>(&configFile)->default_value(_TRINITY_BNET_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";
}
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp
index bb752fd9b49..e0b1ed3b161 100644
--- a/src/server/collision/Management/MMapManager.cpp
+++ b/src/server/collision/Management/MMapManager.cpp
@@ -24,6 +24,9 @@
namespace MMAP
{
+ static char const* const MAP_FILE_NAME_FORMAT = "%smmaps/%04i.mmap";
+ static char const* const TILE_FILE_NAME_FORMAT = "%smmaps/%04i%02i%02i.mmtile";
+
// ######################## MMapManager ########################
MMapManager::~MMapManager()
{
@@ -41,15 +44,11 @@ namespace MMAP
return true;
// load and init dtNavMesh - read parameters from file
- uint32 pathLen = uint32(sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1);
- char *fileName = new char[pathLen];
- snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId);
-
- FILE* file = fopen(fileName, "rb");
+ std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId);
+ FILE* file = fopen(fileName.c_str(), "rb");
if (!file)
{
- TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName);
- delete [] fileName;
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName.c_str());
return false;
}
@@ -58,8 +57,7 @@ namespace MMAP
fclose(file);
if (count != 1)
{
- TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName);
- delete [] fileName;
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName.c_str());
return false;
}
@@ -68,14 +66,11 @@ namespace MMAP
if (dtStatusFailed(mesh->init(&params)))
{
dtFreeNavMesh(mesh);
- TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName);
- delete [] fileName;
+ TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %04u from file %s", mapId, fileName.c_str());
return false;
}
- delete [] fileName;
-
- TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %04i.mmap", mapId);
// store inside our map list
MMapData* mmap_data = new MMapData(mesh, mapId);
@@ -104,33 +99,27 @@ namespace MMAP
if (mmap->loadedTileRefs.find(packedGridPos) != mmap->loadedTileRefs.end())
return false;
- // load this tile :: mmaps/MMMXXYY.mmtile
- uint32 pathLen = uint32(sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1);
- char *fileName = new char[pathLen];
-
- snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
-
- FILE* file = fopen(fileName, "rb");
+ // load this tile :: mmaps/MMMMXXYY.mmtile
+ std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId, x, y);
+ FILE* file = fopen(fileName.c_str(), "rb");
if (!file)
{
- TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName);
- delete [] fileName;
+ TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName.c_str());
return false;
}
- delete [] fileName;
// read header
MmapTileHeader fileHeader;
if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC)
{
- TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %04u%02i%02i.mmtile", mapId, x, y);
fclose(file);
return false;
}
if (fileHeader.mmapVersion != MMAP_VERSION)
{
- TC_LOG_ERROR("maps", "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
+ TC_LOG_ERROR("maps", "MMAP:loadMap: %04u%02i%02i.mmtile was built with generator v%i, expected v%i",
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
fclose(file);
return false;
@@ -142,7 +131,7 @@ namespace MMAP
size_t result = fread(data, fileHeader.size, 1, file);
if (!result)
{
- TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %04u%02i%02i.mmtile", mapId, x, y);
fclose(file);
return false;
}
@@ -157,14 +146,14 @@ namespace MMAP
{
mmap->loadedTileRefs.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
++loadedTiles;
- TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y);
+ TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %04i[%02i, %02i] into %04i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y);
LoadPhaseTiles(mapId, x, y);
return true;
}
- TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %04u%02i%02i.mmtile into navmesh", mapId, x, y);
dtFree(data);
return false;
}
@@ -172,37 +161,33 @@ namespace MMAP
PhasedTile* MMapManager::LoadTile(uint32 mapId, int32 x, int32 y)
{
// load this tile :: mmaps/MMMXXYY.mmtile
- uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1;
- char *fileName = new char[pathLen];
-
- snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
-
- FILE* file = fopen(fileName, "rb");
+ std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId, x, y);
+ FILE* file = fopen(fileName.c_str(), "rb");
if (!file)
{
// Not all tiles have phased versions, don't flood this msg
//TC_LOG_DEBUG("phase", "MMAP:LoadTile: Could not open mmtile file '%s'", fileName);
- delete[] fileName;
return NULL;
}
- delete[] fileName;
PhasedTile* pTile = new PhasedTile();
// read header
if (fread(&pTile->fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || pTile->fileHeader.mmapMagic != MMAP_MAGIC)
{
- TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header in mmap %04u%02i%02i.mmtile", mapId, x, y);
fclose(file);
- return NULL;
+ delete pTile;
+ return nullptr;
}
if (pTile->fileHeader.mmapVersion != MMAP_VERSION)
{
- TC_LOG_ERROR("phase", "MMAP:LoadTile: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
+ TC_LOG_ERROR("phase", "MMAP:LoadTile: %04u%02i%02i.mmtile was built with generator v%i, expected v%i",
mapId, x, y, pTile->fileHeader.mmapVersion, MMAP_VERSION);
fclose(file);
- return NULL;
+ delete pTile;
+ return nullptr;
}
pTile->data = (unsigned char*)dtAlloc(pTile->fileHeader.size, DT_ALLOC_PERM);
@@ -211,9 +196,10 @@ namespace MMAP
size_t result = fread(pTile->data, pTile->fileHeader.size, 1, file);
if (!result)
{
- TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_ERROR("phase", "MMAP:LoadTile: Bad header or data in mmap %04u%02i%02i.mmtile", mapId, x, y);
fclose(file);
- return NULL;
+ delete pTile;
+ return nullptr;
}
fclose(file);
@@ -237,7 +223,7 @@ namespace MMAP
// only a few tiles have terrain swaps, do not write error for them
if (data)
{
- TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %03u%02i%02i.mmtile for root phase map %u", map->ID, x, y, mapId);
+ TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %04u%02i%02i.mmtile for root phase map %u", map->ID, x, y, mapId);
_phaseTiles[map->ID][packedGridPos] = data;
}
}
@@ -256,7 +242,7 @@ namespace MMAP
if (_phaseTiles[mapId][packedGridPos])
{
- TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %03u%02i%02i.mmtile for root phase map %u", mapId, x, y, rootMapId);
+ TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %04u%02i%02i.mmtile for root phase map %u", mapId, x, y, rootMapId);
delete _phaseTiles[mapId][packedGridPos]->data;
delete _phaseTiles[mapId][packedGridPos];
_phaseTiles[mapId].erase(packedGridPos);
@@ -269,7 +255,7 @@ namespace MMAP
if (loadedMMaps.find(mapId) == loadedMMaps.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %04u%02i%02i.mmtile", mapId, x, y);
return false;
}
@@ -280,7 +266,7 @@ namespace MMAP
if (mmap->loadedTileRefs.find(packedGridPos) == mmap->loadedTileRefs.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %04u%02i%02i.mmtile", mapId, x, y);
return false;
}
@@ -292,14 +278,14 @@ namespace MMAP
// this is technically a memory leak
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
// we cannot recover from this error - assert out
- TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %04u%02i%02i.mmtile from navmesh", mapId, x, y);
ASSERT(false);
}
else
{
mmap->loadedTileRefs.erase(packedGridPos);
--loadedTiles;
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %04i", mapId, x, y, mapId);
UnloadPhaseTile(mapId, x, y);
return true;
@@ -313,7 +299,7 @@ namespace MMAP
if (loadedMMaps.find(mapId) == loadedMMaps.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %04u", mapId);
return false;
}
@@ -324,18 +310,18 @@ namespace MMAP
uint32 x = (i->first >> 16);
uint32 y = (i->first & 0x0000FFFF);
if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL)))
- TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
+ TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %04u%02i%02i.mmtile from navmesh", mapId, x, y);
else
{
UnloadPhaseTile(mapId, x, y);
--loadedTiles;
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %04i[%02i, %02i] from %04i", mapId, x, y, mapId);
}
}
delete mmap;
loadedMMaps.erase(mapId);
- TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %04i.mmap", mapId);
return true;
}
@@ -346,14 +332,14 @@ namespace MMAP
if (loadedMMaps.find(mapId) == loadedMMaps.end())
{
// file may not exist, therefore not loaded
- TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %04u", mapId);
return false;
}
MMapData* mmap = loadedMMaps[mapId];
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
{
- TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %04u instanceId %u", mapId, instanceId);
return false;
}
@@ -361,7 +347,7 @@ namespace MMAP
dtFreeNavMeshQuery(query);
mmap->navMeshQueries.erase(instanceId);
- TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %04u instanceId %u", mapId, instanceId);
return true;
}
@@ -388,11 +374,11 @@ namespace MMAP
if (dtStatusFailed(query->init(mmap->GetNavMesh(swaps), 1024)))
{
dtFreeNavMeshQuery(query);
- TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %04u instanceId %u", mapId, instanceId);
return NULL;
}
- TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %04u instanceId %u", mapId, instanceId);
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
}
@@ -426,25 +412,25 @@ namespace MMAP
if (loadedPhasedTiles[swap].find(packedXY) == loadedPhasedTiles[swap].end())
{
- TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: mmtile %03u[%02i, %02i] unload skipped, due to not loaded", swap, x, y);
+ TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: mmtile %04u[%02i, %02i] unload skipped, due to not loaded", swap, x, y);
return;
}
dtMeshHeader* header = (dtMeshHeader*)ptile->data;
// remove old tile
if (dtStatusFailed(navMesh->removeTile(loadedTileRefs[packedXY], NULL, NULL)))
- TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not unload phased %03u%02i%02i.mmtile from navmesh", swap, x, y);
+ TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not unload phased %04u%02i%02i.mmtile from navmesh", swap, x, y);
else
{
- TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Unloaded phased %03u%02i%02i.mmtile from navmesh", swap, x, y);
+ TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Unloaded phased %04u%02i%02i.mmtile from navmesh", swap, x, y);
// restore base tile
if (dtStatusSucceed(navMesh->addTile(_baseTiles[packedXY]->data, _baseTiles[packedXY]->dataSize, 0, 0, &loadedTileRefs[packedXY])))
{
- TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Loaded base mmtile %03u[%02i, %02i] into %03i[%02i, %02i]", _mapId, x, y, _mapId, header->x, header->y);
+ TC_LOG_DEBUG("phase", "MMapData::RemoveSwap: Loaded base mmtile %04u[%02i, %02i] into %04i[%02i, %02i]", _mapId, x, y, _mapId, header->x, header->y);
}
else
- TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not load base %03u%02i%02i.mmtile to navmesh", _mapId, x, y);
+ TC_LOG_ERROR("phase", "MMapData::RemoveSwap: Could not load base %04u%02i%02i.mmtile to navmesh", _mapId, x, y);
}
loadedPhasedTiles[swap].erase(packedXY);
@@ -464,12 +450,12 @@ namespace MMAP
if (loadedTileRefs.find(packedXY) == loadedTileRefs.end())
{
- TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %03u[%02i, %02i] load skipped, due to not loaded base tile on map %u", swap, x, y, _mapId);
+ TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %04u[%02i, %02i] load skipped, due to not loaded base tile on map %u", swap, x, y, _mapId);
return;
}
if (loadedPhasedTiles[swap].find(packedXY) != loadedPhasedTiles[swap].end())
{
- TC_LOG_DEBUG("phase", "MMapData::AddSwap: WARNING! phased mmtile %03u[%02i, %02i] load skipped, due to already loaded on map %u", swap, x, y, _mapId);
+ TC_LOG_DEBUG("phase", "MMapData::AddSwap: WARNING! phased mmtile %04u[%02i, %02i] load skipped, due to already loaded on map %u", swap, x, y, _mapId);
return;
}
@@ -480,25 +466,25 @@ namespace MMAP
if (!oldTile)
{
- TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %03u[%02i, %02i] load skipped, due to not loaded base tile ref on map %u", swap, x, y, _mapId);
+ TC_LOG_DEBUG("phase", "MMapData::AddSwap: phased mmtile %04u[%02i, %02i] load skipped, due to not loaded base tile ref on map %u", swap, x, y, _mapId);
return;
}
- uint32 old_x = oldTile->header->x;
- uint32 old_y = oldTile->header->y;
-
// header xy is based on the swap map's tile set, wich doesn't have all the same tiles as root map, so copy the xy from the orignal header
- memcpy(ptile->data + 8, (char*)&old_x, 4);
- memcpy(ptile->data + 12, (char*)&old_y, 4);
+ header->x = oldTile->header->x;
+ header->y = oldTile->header->y;
// the removed tile's data
PhasedTile* pt = new PhasedTile();
// remove old tile
if (dtStatusFailed(navMesh->removeTile(loadedTileRefs[packedXY], &pt->data, &pt->dataSize)))
- TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not unload %03u%02i%02i.mmtile from navmesh", _mapId, x, y);
+ {
+ TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not unload %04u%02i%02i.mmtile from navmesh", _mapId, x, y);
+ delete pt;
+ }
else
{
- TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %03u%02i%02i.mmtile from navmesh", _mapId, x, y);
+ TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %04u%02i%02i.mmtile from navmesh", _mapId, x, y);
// store the removed data first time, this is the origonal, non-phased tile
if (_baseTiles.find(packedXY) == _baseTiles.end())
@@ -510,43 +496,38 @@ namespace MMAP
// add new swapped tile
if (dtStatusSucceed(navMesh->addTile(ptile->data, ptile->fileHeader.size, 0, 0, &loadedTileRefs[packedXY])))
{
- TC_LOG_DEBUG("phase", "MMapData::AddSwap: Loaded phased mmtile %03u[%02i, %02i] into %03i[%02i, %02i]", swap, x, y, _mapId, header->x, header->y);
+ TC_LOG_DEBUG("phase", "MMapData::AddSwap: Loaded phased mmtile %04u[%02i, %02i] into %04i[%02i, %02i]", swap, x, y, _mapId, header->x, header->y);
}
else
- TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not load %03u%02i%02i.mmtile to navmesh", swap, x, y);
+ TC_LOG_ERROR("phase", "MMapData::AddSwap: Could not load %04u%02i%02i.mmtile to navmesh", swap, x, y);
}
}
dtNavMesh* MMapData::GetNavMesh(TerrainSet swaps)
{
- for (uint32 swap : _activeSwaps)
+ std::set<uint32> activeSwaps = _activeSwaps; // _activeSwaps is modified inside RemoveSwap
+ for (uint32 swap : activeSwaps)
{
- if (swaps.find(swap) == swaps.end()) // swap not active
+ if (!swaps.count(swap)) // swap not active
{
PhaseTileContainer ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap);
for (PhaseTileContainer::const_iterator itr = ptc.begin(); itr != ptc.end(); ++itr)
- {
RemoveSwap(itr->second, swap, itr->first); // remove swap
- }
}
}
- if (!swaps.empty())
+ // for each of the calling unit's terrain swaps
+ for (uint32 swap : swaps)
{
- // for each of the calling unit's terrain swaps
- for (uint32 swap : swaps)
+ if (!_activeSwaps.count(swap)) // swap not active
{
// for each of the terrain swap's xy tiles
PhaseTileContainer ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap);
for (PhaseTileContainer::const_iterator itr = ptc.begin(); itr != ptc.end(); ++itr)
- {
- if (_activeSwaps.find(swap) == _activeSwaps.end()) // swap not active
- {
- AddSwap(itr->second, swap, itr->first); // add swap
- }
- }
+ AddSwap(itr->second, swap, itr->first); // add swap
}
}
+
return navMesh;
}
}
diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp
index f9fcff96ad2..0c3ff1a9bfa 100644
--- a/src/server/collision/Management/VMapManager2.cpp
+++ b/src/server/collision/Management/VMapManager2.cpp
@@ -66,7 +66,7 @@ namespace VMAP
std::string VMapManager2::getMapFileName(unsigned int mapId)
{
std::stringstream fname;
- fname.width(3);
+ fname.width(4);
fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2);
return fname.str();
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp
index b493ec18f5f..862f3e1cefe 100644
--- a/src/server/collision/Maps/MapTree.cpp
+++ b/src/server/collision/Maps/MapTree.cpp
@@ -90,7 +90,7 @@ namespace VMAP
{
std::stringstream tilefilename;
tilefilename.fill('0');
- tilefilename << std::setw(3) << mapID << '_';
+ tilefilename << std::setw(4) << mapID << '_';
//tilefilename << std::setw(2) << tileX << '_' << std::setw(2) << tileY << ".vmtile";
tilefilename << std::setw(2) << tileY << '_' << std::setw(2) << tileX << ".vmtile";
return tilefilename.str();
diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp
index 172c556b9a7..ce39dc02da8 100644
--- a/src/server/collision/Maps/TileAssembler.cpp
+++ b/src/server/collision/Maps/TileAssembler.cpp
@@ -24,7 +24,6 @@
#include <set>
#include <iomanip>
#include <sstream>
-#include <iomanip>
using G3D::Vector3;
using G3D::AABox;
@@ -116,7 +115,7 @@ namespace VMAP
// write map tree file
std::stringstream mapfilename;
- mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree";
+ mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(4) << map_iter->first << ".vmtree";
FILE* mapfile = fopen(mapfilename.str().c_str(), "wb");
if (!mapfile)
{
@@ -157,7 +156,7 @@ namespace VMAP
uint32 nSpawns = tileEntries.count(tile->first);
std::stringstream tilefilename;
tilefilename.fill('0');
- tilefilename << iDestDir << '/' << std::setw(3) << map_iter->first << '_';
+ tilefilename << iDestDir << '/' << std::setw(4) << map_iter->first << '_';
uint32 x, y;
StaticMapTree::unpackTileID(tile->first, x, y);
tilefilename << std::setw(2) << x << '_' << std::setw(2) << y << ".vmtile";
diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp
index 6140c266b18..607460a2784 100644
--- a/src/server/collision/Models/GameObjectModel.cpp
+++ b/src/server/collision/Models/GameObjectModel.cpp
@@ -188,12 +188,12 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto
return hit;
}
-bool GameObjectModel::Relocate(const GameObject& go)
+bool GameObjectModel::UpdatePosition()
{
if (!iModel)
return false;
- ModelList::const_iterator it = model_list.find(go.GetDisplayId());
+ ModelList::const_iterator it = model_list.find(owner->GetDisplayId());
if (it == model_list.end())
return false;
@@ -205,9 +205,9 @@ bool GameObjectModel::Relocate(const GameObject& go)
return false;
}
- iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
+ iPos = Vector3(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ());
- G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(go.GetOrientation(), 0, 0);
+ G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(owner->GetOrientation(), 0, 0);
iInvRot = iRotation.inverse();
// transform bounding box:
mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale);
@@ -221,7 +221,7 @@ bool GameObjectModel::Relocate(const GameObject& go)
for (int i = 0; i < 8; ++i)
{
Vector3 pos(iBound.corner(i));
- go.SummonCreature(1, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN);
+ owner->SummonCreature(1, pos.x, pos.y, pos.z, 0, TEMPSUMMON_MANUAL_DESPAWN);
}
#endif
diff --git a/src/server/collision/Models/GameObjectModel.h b/src/server/collision/Models/GameObjectModel.h
index 232ebbee5e9..43d299d6d8f 100644
--- a/src/server/collision/Models/GameObjectModel.h
+++ b/src/server/collision/Models/GameObjectModel.h
@@ -68,7 +68,7 @@ public:
static GameObjectModel* Create(const GameObject& go);
- bool Relocate(GameObject const& go);
+ bool UpdatePosition();
};
#endif // _GAMEOBJECT_MODEL_H
diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h
index 8d18372d2b1..7234256f069 100644
--- a/src/server/collision/VMapDefinitions.h
+++ b/src/server/collision/VMapDefinitions.h
@@ -25,8 +25,8 @@
namespace VMAP
{
- const char VMAP_MAGIC[] = "VMAP_4.2";
- const char RAW_VMAP_MAGIC[] = "VMAP042"; // used in extracted vmap files with raw data
+ const char VMAP_MAGIC[] = "VMAP_4.3";
+ const char RAW_VMAP_MAGIC[] = "VMAP043"; // used in extracted vmap files with raw data
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
// defined in TileAssembler.cpp currently...
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 91eb00f17c5..3ea18f272ae 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/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index f835206aba5..8a37186d0af 100644
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -53,7 +53,7 @@ namespace FactorySelector
ai_factory = ai_registry.GetRegistryItem("VehicleAI");
else if (creature->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Guardian*)creature)->GetOwner()->GetTypeId() == TYPEID_PLAYER)
ai_factory = ai_registry.GetRegistryItem("PetAI");
- else if (creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
+ else if (creature->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
ai_factory = ai_registry.GetRegistryItem("NullCreatureAI");
else if (creature->IsGuard())
ai_factory = ai_registry.GetRegistryItem("GuardAI");
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index bc26fc42df8..66164730219 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -478,7 +478,7 @@ void npc_escortAI::Start(bool isActiveAttacker /* = true*/, bool run /* = false
}
//disable npcflags
- me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ me->SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
{
HasImmuneToNPCFlags = true;
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
index 720847b2f20..ab91b0b5b27 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp
@@ -313,7 +313,7 @@ void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, const Qu
TC_LOG_DEBUG("scripts", "FollowerAI start with WAYPOINT_MOTION_TYPE, set to MoveIdle.");
}
- me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ me->SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
AddFollowState(STATE_FOLLOW_INPROGRESS);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index f3520820f30..f50bf1fe0e1 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1355,7 +1355,31 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
case SMART_ACTION_SET_COUNTER:
{
- StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
+ if (ObjectList* targets = GetTargets(e, unit))
+ {
+ for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
+ {
+ if (IsCreature(*itr))
+ {
+ if (SmartAI* ai = CAST_AI(SmartAI, (*itr)->ToCreature()->AI()))
+ ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
+ else
+ TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartAI, skipping");
+ }
+ else if (IsGameObject(*itr))
+ {
+ if (SmartGameObjectAI* ai = CAST_AI(SmartGameObjectAI, (*itr)->ToGameObject()->AI()))
+ ai->GetScript()->StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
+ else
+ TC_LOG_ERROR("sql.sql", "SmartScript: Action target for SMART_ACTION_SET_COUNTER is not using SmartGameObjectAI, skipping");
+ }
+ }
+
+ delete targets;
+ }
+ else
+ StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
+
break;
}
case SMART_ACTION_WP_START:
@@ -1681,7 +1705,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
if (IsCreature(*itr))
- (*itr)->ToUnit()->SetUInt32Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
+ (*itr)->ToUnit()->SetUInt64Value(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
delete targets;
break;
@@ -1694,7 +1718,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
if (IsCreature(*itr))
- (*itr)->ToUnit()->SetFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
+ (*itr)->ToUnit()->SetFlag64(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
delete targets;
break;
@@ -1707,7 +1731,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr)
if (IsCreature(*itr))
- (*itr)->ToUnit()->RemoveFlag(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
+ (*itr)->ToUnit()->RemoveFlag64(UNIT_NPC_FLAGS, e.action.unitFlag.flag);
delete targets;
break;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index 0233d1aa7d0..c5cc5aedb43 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -177,33 +177,25 @@ class SmartScript
GameObject* FindGameObjectNear(WorldObject* searchObject, ObjectGuid::LowType guid) const
{
- GameObject* gameObject = NULL;
+ auto bounds = searchObject->GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
- Cell cell(p);
-
- Trinity::GameObjectWithDbGUIDCheck goCheck(*searchObject, guid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(searchObject, gameObject, goCheck);
-
- TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > objectChecker(checker);
- cell.Visit(p, objectChecker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
-
- return gameObject;
+ return bounds.first->second;
}
Creature* FindCreatureNear(WorldObject* searchObject, ObjectGuid::LowType guid) const
{
- Creature* creature = NULL;
- CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
- Cell cell(p);
+ auto bounds = searchObject->GetMap()->GetCreatureBySpawnIdStore().equal_range(guid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- Trinity::CreatureWithDbGUIDCheck target_check(searchObject, guid);
- Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(searchObject, creature, target_check);
-
- TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
- cell.Visit(p, unit_checker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
+ auto creatureItr = std::find_if(bounds.first, bounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair)
+ {
+ return pair.second->IsAlive();
+ });
- return creature;
+ return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
}
ObjectListMap* mTargetStorage;
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 2a499db8fdb..6d56774e447 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -61,7 +61,7 @@ enum RBACPermissions
// 9 - reuse
RBAC_PERM_USE_CHARACTER_TEMPLATES = 10,
RBAC_PERM_LOG_GM_TRADE = 11,
- // 12 - reuse
+ // 12 - reuse
RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14,
RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15,
@@ -738,6 +738,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_TICKET_RESET_BUG = 831,
RBAC_PERM_COMMAND_TICKET_RESET_COMPLAINT = 832,
RBAC_PERM_COMMAND_TICKET_RESET_SUGGESTION = 833,
+ RBAC_PERM_COMMAND_GO_QUEST = 834,
// custom permissions 1000+
RBAC_PERM_MAX
@@ -846,6 +847,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)
@@ -869,6 +871,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)
@@ -893,6 +896,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)
@@ -983,9 +987,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/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index cfe93b0cde3..9c347879768 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -28,6 +28,7 @@
#include "DBCEnums.h"
#include "DisableMgr.h"
#include "GameEventMgr.h"
+#include "Garrison.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
#include "Guild.h"
@@ -1161,6 +1162,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
SetCriteriaProgress(achievementCriteria, 1, referencePlayer);
break;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
@@ -1269,6 +1271,39 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR:
+ case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
+ case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
+ case ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON:
+ case ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS:
break; // Not implemented yet :(
}
@@ -1413,6 +1448,7 @@ bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteria const* achieveme
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
return progress->counter >= 1;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
return progress->counter >= (requiredAmount * 75);
@@ -2492,6 +2528,44 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(ModifierTreeNode const*
if (!unit || unit->GetHealthPct() >= reqValue)
return false;
break;
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY: // 145
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->PacketInfo.Quality != reqValue)
+ return false;
+
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL: // 146
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->PacketInfo.FollowerLevel < reqValue)
+ return false;
+
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL: // 184
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->GetItemLevel() < reqValue)
+ return false;
+ break;
+ }
default:
break;
}
@@ -2729,6 +2803,74 @@ char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes
return "GUILD_CHALLENGE_TYPE";
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
return "GUILD_CHALLENGE";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
+ return "LFR_DUNGEONS_COMPLETED";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES:
+ return "LFR_LEAVES";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
+ return "LFR_VOTE_KICKS_INITIATED_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
+ return "LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR:
+ return "BE_KICKED_FROM_LFR";
+ case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
+ return "COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
+ return "COMPLETE_SCENARIO_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
+ return "COMPLETE_SCENARIO";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
+ return "OWN_BATTLE_PET";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ return "OWN_BATTLE_PET_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
+ return "CAPTURE_BATTLE_PET";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
+ return "WIN_PET_BATTLE";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
+ return "LEVEL_BATTLE_PET";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
+ return "CAPTURE_BATTLE_PET_CREDIT";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
+ return "LEVEL_BATTLE_PET_CREDIT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA:
+ return "ENTER_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA:
+ return "LEAVE_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
+ return "COMPLETE_DUNGEON_ENCOUNTER";
+ case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ return "PLACE_GARRISON_BUILDING";
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
+ return "UPGRADE_GARRISON_BUILDING";
+ case ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
+ return "CONSTRUCT_GARRISON_BUILDING";
+ case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON:
+ return "UPGRADE_GARRISON";
+ case ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION:
+ return "START_GARRISON_MISSION";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
+ return "COMPLETE_GARRISON_MISSION_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
+ return "COMPLETE_GARRISON_MISSION";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
+ return "RECRUIT_GARRISON_FOLLOWER_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
+ return "LEARN_GARRISON_BLUEPRINT_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
+ return "COMPLETE_GARRISON_SHIPMENT";
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
+ return "RAISE_GARRISON_FOLLOWER_ITEM_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
+ return "RAISE_GARRISON_FOLLOWER_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY:
+ return "OWN_TOY";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT:
+ return "OWN_TOY_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
+ return "RECRUIT_GARRISON_FOLLOWER";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS:
+ return "OWN_HEIRLOOMS";
}
return "MISSING_TYPE";
}
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
index 2b34d308763..76b2d849a73 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
@@ -320,7 +320,7 @@ bool AuctionBotSeller::Initialize()
continue;
}
- if (prototype->GetFlags() & ITEM_FLAG_UNLOCKED)
+ if (prototype->GetFlags() & ITEM_FIELD_FLAG_UNLOCKED)
{
// skip any not locked lootable items (mostly quest specific or reward cases)
if (!prototype->GetLockID())
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index c6c46c48f50..f37526ae71b 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -71,7 +71,7 @@ namespace Trinity
void do_helper(WorldPacket& data, char const* text)
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgtype, LANG_UNIVERSAL, _source, _source, text);
+ packet.Initialize(_msgtype, LANG_UNIVERSAL, _source, _source, text);
packet.Write();
data = packet.Move();
}
@@ -98,7 +98,7 @@ namespace Trinity
snprintf(str, 2048, text, arg1str, arg2str);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgtype, LANG_UNIVERSAL, _source, _source, str);
+ packet.Initialize(_msgtype, LANG_UNIVERSAL, _source, _source, str);
packet.Write();
data = packet.Move();
}
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index 1bb636078e2..a227dc1a07b 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -471,8 +471,8 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
_battlegroundMapTemplates.clear();
_battlegroundTemplates.clear();
- // 0 1 2 3 4 5 6 7 8 9 10 11
- QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template");
+ // 0 1 2 3 4 5 6 7 8 9
+ QueryResult result = WorldDatabase.Query("SELECT ID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, HordeStartLoc, StartMaxDist, Weight, ScriptName FROM battleground_template");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
@@ -504,22 +504,22 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
bgTemplate.MaxPlayersPerTeam = fields[2].GetUInt16();
bgTemplate.MinLevel = fields[3].GetUInt8();
bgTemplate.MaxLevel = fields[4].GetUInt8();
- float dist = fields[9].GetFloat();
+ float dist = fields[7].GetFloat();
bgTemplate.MaxStartDistSq = dist * dist;
- bgTemplate.Weight = fields[10].GetUInt8();
- bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[11].GetCString());
+ bgTemplate.Weight = fields[8].GetUInt8();
+ bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[9].GetCString());
bgTemplate.BattlemasterEntry = bl;
if (bgTemplate.MaxPlayersPerTeam == 0 || bgTemplate.MinPlayersPerTeam > bgTemplate.MaxPlayersPerTeam)
{
- TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)",
+ TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u has bad values for MinPlayersPerTeam (%u) and MaxPlayersPerTeam(%u)",
bgTemplate.Id, bgTemplate.MinPlayersPerTeam, bgTemplate.MaxPlayersPerTeam);
continue;
}
if (bgTemplate.MinLevel == 0 || bgTemplate.MaxLevel == 0 || bgTemplate.MinLevel > bgTemplate.MaxLevel)
{
- TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has bad values for MinLevel (%u) and MaxLevel (%u)",
+ TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u has bad values for MinLevel (%u) and MaxLevel (%u)",
bgTemplate.Id, bgTemplate.MinLevel, bgTemplate.MaxLevel);
continue;
}
@@ -529,22 +529,22 @@ void BattlegroundMgr::LoadBattlegroundTemplates()
uint32 startId = fields[5].GetUInt32();
if (WorldSafeLocsEntry const* start = sWorldSafeLocsStore.LookupEntry(startId))
{
- bgTemplate.StartLocation[TEAM_ALLIANCE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, fields[6].GetFloat());
+ bgTemplate.StartLocation[TEAM_ALLIANCE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, (start->Facing * M_PI) / 180);
}
else
{
- TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has non-existed WorldSafeLocs.dbc id %u in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId);
+ TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u a non-existant WorldSafeLoc (ID: %u) in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId);
continue;
}
- startId = fields[7].GetUInt32();
+ startId = fields[6].GetUInt32();
if (WorldSafeLocsEntry const* start = sWorldSafeLocsStore.LookupEntry(startId))
{
- bgTemplate.StartLocation[TEAM_HORDE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, fields[8].GetFloat());
+ bgTemplate.StartLocation[TEAM_HORDE].Relocate(start->Loc.X, start->Loc.Y, start->Loc.Z, (start->Facing * M_PI) / 180);
}
else
{
- TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id %u has non-existed WorldSafeLocs.dbc id %u in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId);
+ TC_LOG_ERROR("sql.sql", "Table `battleground_template` for ID %u has a non-existant WorldSafeLoc (ID: %u) in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId);
continue;
}
}
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
index 9a65019a390..eb225250a56 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/BattlegroundBFG.h b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
index 3694c62d663..8b6f16d1ff9 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundBFG.h
@@ -42,7 +42,7 @@ class BattlegroundBFGScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(std::vector<int32>& stats)
+ void BuildObjectivesBlock(std::vector<int32>& stats) override
{
stats.push_back(BasesAssaulted);
stats.push_back(BasesDefended);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundTP.h b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
index b11485d6025..1dfd3801864 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundTP.h
@@ -42,7 +42,7 @@ class BattlegroundTPScore final : public BattlegroundScore
}
}
- void BuildObjectivesBlock(std::vector<int32>& stats)
+ void BuildObjectivesBlock(std::vector<int32>& stats) override
{
stats.push_back(FlagCaptures);
stats.push_back(FlagReturns);
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index caa75c24121..9c3646c39ca 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -24,6 +24,7 @@ file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h)
file(GLOB_RECURSE sources_DungeonFinding DungeonFinding/*.cpp DungeonFinding/*.h)
file(GLOB_RECURSE sources_Entities Entities/*.cpp Entities/*.h)
file(GLOB_RECURSE sources_Events Events/*.cpp Events/*.h)
+file(GLOB_RECURSE sources_Garrison Garrison/*.cpp Garrison/*.h)
file(GLOB_RECURSE sources_Globals Globals/*.cpp Globals/*.h)
file(GLOB_RECURSE sources_Grids Grids/*.cpp Grids/*.h)
file(GLOB_RECURSE sources_Groups Groups/*.cpp Groups/*.h)
@@ -75,6 +76,7 @@ set(game_STAT_SRCS
${sources_DungeonFinding}
${sources_Entities}
${sources_Events}
+ ${sources_Garrison}
${sources_Globals}
${sources_Grids}
${sources_Groups}
@@ -172,6 +174,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Vehicle
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport
${CMAKE_CURRENT_SOURCE_DIR}/Events
+ ${CMAKE_CURRENT_SOURCE_DIR}/Garrison
${CMAKE_CURRENT_SOURCE_DIR}/Globals
${CMAKE_CURRENT_SOURCE_DIR}/Grids/Cells
${CMAKE_CURRENT_SOURCE_DIR}/Grids/Notifiers
@@ -217,8 +220,8 @@ include_directories(
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
add_library(game STATIC
- ${game_STAT_SRCS}
${game_STAT_PCH_SRC}
+ ${game_STAT_SRCS}
)
add_dependencies(game revision.h)
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 04b6eb1b5b1..97fa489d388 100644
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -626,10 +626,10 @@ void Channel::Say(ObjectGuid const& guid, std::string const& what, uint32 lang)
WorldPackets::Chat::Chat packet;
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
- packet.Initalize(CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name);
+ packet.Initialize(CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name);
else
{
- packet.Initalize(CHAT_MSG_CHANNEL, Language(lang), nullptr, nullptr, what, 0, _name);
+ packet.Initialize(CHAT_MSG_CHANNEL, Language(lang), nullptr, nullptr, what, 0, _name);
packet.SenderGUID = guid;
packet.TargetGUID = guid;
}
@@ -990,32 +990,42 @@ void Channel::MakeVoiceOff(WorldPackets::Channel::ChannelNotify& data, ObjectGui
void Channel::JoinNotify(Player const* player)
{
ObjectGuid const& guid = player->GetGUID();
- WorldPacket data(IsConstant() ? SMSG_USERLIST_ADD : SMSG_USERLIST_UPDATE, 8 + 1 + 1 + 4 + GetName().size());
- data << guid;
- data << uint8(GetPlayerFlags(guid));
- data << uint8(GetFlags());
- data << uint32(GetNumPlayers());
- data << GetName();
if (IsConstant())
- SendToAllButOne(&data, guid);
+ {
+ WorldPackets::Channel::UserlistAdd userlistAdd;
+ userlistAdd.AddedUserGUID = guid;
+ userlistAdd._ChannelFlags = GetFlags();
+ userlistAdd.UserFlags = GetPlayerFlags(guid);
+ userlistAdd.ChannelID = GetChannelId();
+ userlistAdd.ChannelName = GetName();
+ SendToAllButOne(userlistAdd.Write(), guid);
+ }
else
- SendToAll(&data);
+ {
+ WorldPackets::Channel::UserlistUpdate userlistUpdate;
+ userlistUpdate.UpdatedUserGUID = guid;
+ userlistUpdate._ChannelFlags = GetFlags();
+ userlistUpdate.UserFlags = GetPlayerFlags(guid);
+ userlistUpdate.ChannelID = GetChannelId();
+ userlistUpdate.ChannelName = GetName();
+ SendToAll(userlistUpdate.Write());
+ }
}
void Channel::LeaveNotify(Player const* player)
{
ObjectGuid const& guid = player->GetGUID();
- WorldPacket data(SMSG_USERLIST_REMOVE, 8 + 1 + 4 + GetName().size());
- data << guid;
- data << uint8(GetFlags());
- data << uint32(GetNumPlayers());
- data << GetName();
+ WorldPackets::Channel::UserlistRemove userlistRemove;
+ userlistRemove.RemovedUserGUID = guid;
+ userlistRemove._ChannelFlags = GetFlags();
+ userlistRemove.ChannelID = GetChannelId();
+ userlistRemove.ChannelName = GetName();
if (IsConstant())
- SendToAllButOne(&data, guid);
+ SendToAllButOne(userlistRemove.Write(), guid);
else
- SendToAll(&data);
+ SendToAll(userlistRemove.Write());
}
void Channel::SetModerator(ObjectGuid const& guid, bool set)
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 2cfe0797bce..23cd4e4cada 100644
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -72,7 +72,9 @@ enum ChatNotify
CHAT_NOT_IN_AREA_NOTICE = 0x20, //+ "[%s] You are not in the correct area for this channel."; -- The user is trying to send a chat to a zone specific channel, and they're not physically in that zone.
CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels.
CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s.";
- CHAT_VOICE_OFF_NOTICE = 0x23 //+ "[%s] Channel voice disabled by %s.";
+ CHAT_VOICE_OFF_NOTICE = 0x23, //+ "[%s] Channel voice disabled by %s.";
+ CHAT_TRIAL_RESTRICTED = 0x24,
+ CHAT_NOT_ALLOWED_IN_CHANNEL = 0x25
};
enum ChannelFlags
@@ -206,7 +208,7 @@ class Channel
void DeVoice(Player const* player);
void JoinNotify(Player const* player);
void LeaveNotify(Player const* player);
- void SetOwnership(bool ownership) { _ownership = ownership; };
+ void SetOwnership(bool ownership) { _ownership = ownership; }
static void CleanOldChannelsInDB();
private:
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 837ff0be60f..52c52726b73 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -201,7 +201,7 @@ void ChatHandler::SendSysMessage(const char *str)
while (char* line = LineFromMessage(pos))
{
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
m_session->SendPacket(packet.Write());
}
@@ -219,7 +219,7 @@ void ChatHandler::SendGlobalSysMessage(const char *str)
while (char* line = LineFromMessage(pos))
{
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
sWorld->SendGlobalMessage(packet.Write());
}
@@ -237,7 +237,7 @@ void ChatHandler::SendGlobalGMSysMessage(const char *str)
while (char* line = LineFromMessage(pos))
{
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
sWorld->SendGlobalGMMessage(packet.Write());
}
@@ -321,9 +321,9 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
std::string zoneName = "Unknown";
if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId))
{
- areaName = area->ZoneName;
+ areaName = area->AreaName_lang;
if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID))
- zoneName = zone->ZoneName;
+ zoneName = zone->AreaName_lang;
}
sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (%s) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected: %s (%s)]",
@@ -796,15 +796,11 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(ObjectGuid::Lo
if (!obj && sObjectMgr->GetGOData(lowguid)) // guid is DB guid of object
{
- // search near player then
- CellCoord p(Trinity::ComputeCellCoord(pl->GetPositionX(), pl->GetPositionY()));
- Cell cell(p);
+ auto bounds = pl->GetMap()->GetGameObjectBySpawnIdStore().equal_range(lowguid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- Trinity::GameObjectWithDbGUIDCheck go_check(*pl, lowguid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(pl, obj, go_check);
-
- TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
- cell.Visit(p, object_checker, *pl->GetMap(), *pl, pl->GetGridActivationRange());
+ return bounds.first->second;
}
return obj;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index bed2cc793f4..01c65315d35 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -28,6 +28,18 @@ DB2Storage<AreaGroupMemberEntry> sAreaGroupMemberStore("AreaGroupMemb
DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.db2", BroadcastTextFormat, HOTFIX_SEL_BROADCAST_TEXT);
DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore("CurrencyTypes.db2", CurrencyTypesFormat, HOTFIX_SEL_CURRENCY_TYPES);
DB2Storage<CurvePointEntry> sCurvePointStore("CurvePoint.db2", CurvePointFormat, HOTFIX_SEL_CURVE_POINT);
+DB2Storage<GameObjectsEntry> sGameObjectsStore("GameObjects.db2", GameObjectsFormat, HOTFIX_SEL_GAMEOBJECTS);
+DB2Storage<GarrAbilityEntry> sGarrAbilityStore("GarrAbility.db2", GarrAbilityFormat, HOTFIX_SEL_GARR_ABILITY);
+DB2Storage<GarrBuildingEntry> sGarrBuildingStore("GarrBuilding.db2", GarrBuildingFormat, HOTFIX_SEL_GARR_BUILDING);
+DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore("GarrBuildingPlotInst.db2", GarrBuildingPlotInstFormat, HOTFIX_SEL_GARR_BUILDING_PLOT_INST);
+DB2Storage<GarrClassSpecEntry> sGarrClassSpecStore("GarrClassSpec.db2", GarrClassSpecFormat, HOTFIX_SEL_GARR_CLASS_SPEC);
+DB2Storage<GarrFollowerEntry> sGarrFollowerStore("GarrFollower.db2", GarrFollowerFormat, HOTFIX_SEL_GARR_FOLLOWER);
+DB2Storage<GarrFollowerXAbilityEntry> sGarrFollowerXAbilityStore("GarrFollowerXAbility.db2", GarrFollowerXAbilityFormat, HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY);
+DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore("GarrPlotBuilding.db2", GarrPlotBuildingFormat, HOTFIX_SEL_GARR_PLOT_BUILDING);
+DB2Storage<GarrPlotEntry> sGarrPlotStore("GarrPlot.db2", GarrPlotFormat, HOTFIX_SEL_GARR_PLOT);
+DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore("GarrPlotInstance.db2", GarrPlotInstanceFormat, HOTFIX_SEL_GARR_PLOT_INSTANCE);
+DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore("GarrSiteLevel.db2", GarrSiteLevelFormat, HOTFIX_SEL_GARR_SITE_LEVEL);
+DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore("GarrSiteLevelPlotInst.db2", GarrSiteLevelPlotInstFormat, HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST);
DB2Storage<HolidaysEntry> sHolidaysStore("Holidays.db2", HolidaysEntryFormat, HOTFIX_SEL_HOLIDAYS);
DB2Storage<ItemAppearanceEntry> sItemAppearanceStore("ItemAppearance.db2", ItemAppearanceFormat, HOTFIX_SEL_ITEM_APPEARANCE);
DB2Storage<ItemBonusEntry> sItemBonusStore("ItemBonus.db2", ItemBonusFormat, HOTFIX_SEL_ITEM_BONUS);
@@ -50,8 +62,8 @@ DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore("Spel
DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore("SpellClassOptions.db2", SpellClassOptionsFormat, HOTFIX_SEL_SPELL_CLASS_OPTIONS);
DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore("SpellLearnSpell.db2", SpellLearnSpellFormat, HOTFIX_SEL_SPELL_LEARN_SPELL);
DB2Storage<SpellMiscEntry> sSpellMiscStore("SpellMisc.db2", SpellMiscFormat, HOTFIX_SEL_SPELL_MISC);
-DB2Storage<SpellPowerEntry> sSpellPowerStore("SpellPower.db2", SpellPowerFormat, HOTFIX_SEL_SPELL_POWER);
DB2Storage<SpellPowerDifficultyEntry> sSpellPowerDifficultyStore("SpellPowerDifficulty.db2", SpellPowerDifficultyFormat, HOTFIX_SEL_SPELL_POWER_DIFFICULTY);
+DB2Storage<SpellPowerEntry> sSpellPowerStore("SpellPower.db2", SpellPowerFormat, HOTFIX_SEL_SPELL_POWER);
DB2Storage<SpellReagentsEntry> sSpellReagentsStore("SpellReagents.db2", SpellReagentsFormat, HOTFIX_SEL_SPELL_REAGENTS);
DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore("SpellRuneCost.db2", SpellRuneCostFormat, HOTFIX_SEL_SPELL_RUNE_COST);
DB2Storage<SpellTotemsEntry> sSpellTotemsStore("SpellTotems.db2", SpellTotemsFormat, HOTFIX_SEL_SPELL_TOTEMS);
@@ -125,41 +137,57 @@ void DB2Manager::LoadStores(std::string const& dataPath)
DB2StoreProblemList bad_db2_files;
uint32 availableDb2Locales = 0xFF;
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sAreaGroupMemberStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sBroadcastTextStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurrencyTypesStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sCurvePointStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sHolidaysStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemAppearanceStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemBonusTreeNodeStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemCurrencyCostStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemEffectStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemExtendedCostStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemModifiedAppearanceStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemSparseStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemXBonusTreeStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sKeyChainStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sMountStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sOverrideSpellDataStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sPhaseXPhaseGroupStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sQuestPackageItemStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSoundEntriesStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellAuraRestrictionsStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellCastingRequirementsStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellClassOptionsStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellLearnSpellStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellMiscStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellPowerStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellPowerDifficultyStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellReagentsStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellRuneCostStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sSpellTotemsStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiNodesStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathNodeStore, db2Path);
- LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sTaxiPathStore, db2Path);
+#define LOAD_DB2(store) LoadDB2(availableDb2Locales, bad_db2_files, _stores, &store, db2Path)
+
+ LOAD_DB2(sAreaGroupMemberStore);
+ LOAD_DB2(sAreaGroupStore);
+ LOAD_DB2(sBroadcastTextStore);
+ LOAD_DB2(sCurrencyTypesStore);
+ LOAD_DB2(sCurvePointStore);
+ LOAD_DB2(sGameObjectsStore);
+ LOAD_DB2(sGarrAbilityStore);
+ LOAD_DB2(sGarrBuildingStore);
+ LOAD_DB2(sGarrBuildingPlotInstStore);
+ LOAD_DB2(sGarrClassSpecStore);
+ LOAD_DB2(sGarrFollowerStore);
+ LOAD_DB2(sGarrFollowerXAbilityStore);
+ LOAD_DB2(sGarrPlotBuildingStore);
+ LOAD_DB2(sGarrPlotInstanceStore);
+ LOAD_DB2(sGarrPlotStore);
+ LOAD_DB2(sGarrSiteLevelPlotInstStore);
+ LOAD_DB2(sGarrSiteLevelStore);
+ LOAD_DB2(sHolidaysStore);
+ LOAD_DB2(sItemAppearanceStore);
+ LOAD_DB2(sItemBonusStore);
+ LOAD_DB2(sItemBonusTreeNodeStore);
+ LOAD_DB2(sItemCurrencyCostStore);
+ LOAD_DB2(sItemEffectStore);
+ LOAD_DB2(sItemExtendedCostStore);
+ LOAD_DB2(sItemModifiedAppearanceStore);
+ LOAD_DB2(sItemSparseStore);
+ LOAD_DB2(sItemStore);
+ LOAD_DB2(sItemXBonusTreeStore);
+ LOAD_DB2(sKeyChainStore);
+ LOAD_DB2(sMountStore);
+ LOAD_DB2(sOverrideSpellDataStore);
+ LOAD_DB2(sPhaseXPhaseGroupStore);
+ LOAD_DB2(sQuestPackageItemStore);
+ LOAD_DB2(sSoundEntriesStore);
+ LOAD_DB2(sSpellAuraRestrictionsStore);
+ LOAD_DB2(sSpellCastingRequirementsStore);
+ LOAD_DB2(sSpellClassOptionsStore);
+ LOAD_DB2(sSpellLearnSpellStore);
+ LOAD_DB2(sSpellMiscStore);
+ LOAD_DB2(sSpellPowerDifficultyStore);
+ LOAD_DB2(sSpellPowerStore);
+ LOAD_DB2(sSpellReagentsStore);
+ LOAD_DB2(sSpellRuneCostStore);
+ LOAD_DB2(sSpellTotemsStore);
+ LOAD_DB2(sTaxiNodesStore);
+ LOAD_DB2(sTaxiPathNodeStore);
+ LOAD_DB2(sTaxiPathStore);
+
+#undef LOAD_DB2
for (AreaGroupMemberEntry const* areaGroupMember : sAreaGroupMemberStore)
_areaGroupMembers[areaGroupMember->AreaGroupID].push_back(areaGroupMember->AreaID);
@@ -493,6 +521,11 @@ MountEntry const* DB2Manager::GetMount(uint32 spellId) const
return nullptr;
}
+MountEntry const* DB2Manager::GetMountById(uint32 id) const
+{
+ return sMountStore.LookupEntry(id);
+}
+
std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItems(uint32 questPackageID) const
{
auto itr = _questPackages.find(questPackageID);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index ece71c7413e..a79b3d1c1fa 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -23,8 +23,20 @@
#include "SharedDefines.h"
extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore;
-extern DB2Storage<HolidaysEntry> sHolidaysStore;
extern DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore;
+extern DB2Storage<GameObjectsEntry> sGameObjectsStore;
+extern DB2Storage<GarrAbilityEntry> sGarrAbilityStore;
+extern DB2Storage<GarrBuildingEntry> sGarrBuildingStore;
+extern DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore;
+extern DB2Storage<GarrClassSpecEntry> sGarrClassSpecStore;
+extern DB2Storage<GarrFollowerEntry> sGarrFollowerStore;
+extern DB2Storage<GarrFollowerXAbilityEntry> sGarrFollowerXAbilityStore;
+extern DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore;
+extern DB2Storage<GarrPlotEntry> sGarrPlotStore;
+extern DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore;
+extern DB2Storage<GarrSiteLevelEntry> sGarrSiteLevelStore;
+extern DB2Storage<GarrSiteLevelPlotInstEntry> sGarrSiteLevelPlotInstStore;
+extern DB2Storage<HolidaysEntry> sHolidaysStore;
extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore;
extern DB2Storage<ItemEffectEntry> sItemEffectStore;
extern DB2Storage<ItemEntry> sItemStore;
@@ -98,6 +110,7 @@ public:
std::set<uint32> GetItemBonusTree(uint32 itemId, uint32 itemBonusTreeMod) const;
uint32 GetItemDisplayId(uint32 itemId, uint32 appearanceModId) const;
MountEntry const* GetMount(uint32 spellId) const;
+ MountEntry const* GetMountById(uint32 id) const;
std::vector<QuestPackageItemEntry const*> const* GetQuestPackageItems(uint32 questPackageID) const;
std::set<uint32> GetPhasesForGroup(uint32 group) const;
std::vector<SpellPowerEntry const*> GetSpellPowers(uint32 spellId, Difficulty difficulty = DIFFICULTY_NONE, bool* hasDifficultyPowers = nullptr) const;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 912ae5d60d5..80c79a94b96 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -81,6 +81,166 @@ struct CurvePointEntry
float Y; // 4
};
+struct GameObjectsEntry
+{
+ uint32 ID; // 0
+ uint32 MapID; // 1
+ uint32 DisplayID; // 2
+ DBCPosition3D Position; // 3-5
+ float RotationX; // 6
+ float RotationY; // 7
+ float RotationZ; // 8
+ float RotationW; // 9
+ float Size; // 10
+ uint32 PhaseUseFlags; // 11
+ uint32 PhaseID; // 12
+ uint32 PhaseGroupID; // 13
+ uint32 Type; // 14
+ uint32 Data[8]; // 15-22
+ LocalizedString* Name; // 23
+};
+
+struct GarrAbilityEntry
+{
+ uint32 ID; // 0
+ uint32 Flags; // 1
+ LocalizedString* Name; // 2
+ LocalizedString* Description; // 3
+ uint32 IconFileDataID; // 4
+ uint32 OtherFactionGarrAbilityID; // 5
+ uint32 GarrAbilityCategoryID; // 6
+};
+
+struct GarrBuildingEntry
+{
+ uint32 ID; // 0
+ uint32 HordeGameObjectID; // 1
+ uint32 AllianceGameObjectID; // 2
+ uint32 Unknown; // 3
+ uint32 Type; // 4
+ uint32 Level; // 5
+ LocalizedString* NameAlliance; // 6
+ LocalizedString* NameHorde; // 7
+ LocalizedString* Description; // 8
+ LocalizedString* Tooltip; // 9
+ uint32 BuildDuration; // 10
+ uint32 CostCurrencyID; // 11
+ int32 CostCurrencyAmount; // 12
+ uint32 HordeTexPrefixKitID; // 13
+ uint32 AllianceTexPrefixKitID; // 14
+ uint32 IconFileDataID; // 15
+ uint32 BonusAmount; // 16
+ uint32 Flags; // 17
+ uint32 AllianceActivationScenePackageID; // 18
+ uint32 HordeActivationScenePackageID; // 19
+ uint32 MaxShipments; // 20
+ uint32 FollowerRequiredGarrAbilityID; // 21
+ uint32 FollowerGarrAbilityEffectID; // 22
+ int32 CostMoney; // 23
+};
+
+struct GarrBuildingPlotInstEntry
+{
+ uint32 ID; // 0
+ uint32 GarrBuildingID; // 1
+ uint32 UiTextureAtlasMemberID; // 2
+ uint32 GarrSiteLevelPlotInstID; // 3
+ DBCPosition2D LandmarkOffset; // 4-5
+};
+
+struct GarrClassSpecEntry
+{
+ uint32 ID; // 0
+ LocalizedString* NameMale; // 1
+ LocalizedString* NameFemale; // 2
+ LocalizedString* NameGenderless; // 3
+ uint32 ClassAtlasID; // 4 UiTextureAtlasMember.db2 ref
+ uint32 GarrFollItemSetID; // 5
+};
+
+struct GarrFollowerEntry
+{
+ uint32 ID; // 0
+ uint32 HordeCreatureID; // 1
+ uint32 AllianceCreatureID; // 2
+ uint32 HordeUiAnimRaceInfoID; // 3
+ uint32 AllianceUiAnimRaceInfoID; // 4
+ uint32 Quality; // 5
+ uint32 HordeGarrClassSpecID; // 6
+ uint32 AllianceGarrClassSpecID; // 7
+ uint32 HordeGarrFollItemSetID; // 8
+ uint32 AllianceGarrFollItemSetID; // 9
+ uint32 Level; // 10
+ uint32 ItemLevelWeapon; // 11
+ uint32 ItemLevelArmor; // 12
+ uint32 Unknown1; // 13
+ uint32 Flags; // 14
+ LocalizedString* HordeSourceText; // 15
+ LocalizedString* AllianceSourceText; // 16
+ int32 Unknown2; // 17
+ int32 Unknown3; // 18
+ uint32 HordePortraitIconID; // 19
+ uint32 AlliancePortraitIconID; // 20
+};
+
+struct GarrFollowerXAbilityEntry
+{
+ uint32 ID; // 0
+ uint32 GarrFollowerID; // 1
+ uint32 GarrAbilityID; // 2
+ uint32 FactionIndex; // 3
+};
+
+struct GarrPlotEntry
+{
+ uint32 ID; // 0
+ uint32 GarrPlotUICategoryID; // 1
+ uint32 PlotType; // 2
+ uint32 Flags; // 3
+ LocalizedString* Name; // 4
+ uint32 MinCount; // 5
+ uint32 MaxCount; // 6
+ uint32 AllianceConstructionGameObjectID; // 7
+ uint32 HordeConstructionGameObjectID; // 8
+};
+
+struct GarrPlotBuildingEntry
+{
+ uint32 ID; // 0
+ uint32 GarrPlotID; // 1
+ uint32 GarrBuildingID; // 2
+};
+
+struct GarrPlotInstanceEntry
+{
+ uint32 ID; // 0
+ uint32 GarrPlotID; // 1
+ LocalizedString* Name; // 2
+};
+
+struct GarrSiteLevelEntry
+{
+ uint32 ID; // 0
+ uint32 Level; // 1
+ uint32 MapID; // 2
+ uint32 SiteID; // 3
+ uint32 UITextureKitID; // 4
+ DBCPosition2D TownHall; // 5-6
+ uint32 MovieID; // 7
+ uint32 Level2; // 8
+ uint32 UpgradeResourceCost; // 9
+ uint32 UpgradeMoneyCost; // 10
+};
+
+struct GarrSiteLevelPlotInstEntry
+{
+ uint32 ID; // 0
+ uint32 GarrSiteLevelID; // 1
+ uint32 GarrPlotInstanceID; // 2
+ DBCPosition2D Landmark; // 3-4
+ uint32 Unknown; // 5
+};
+
struct HolidaysEntry
{
uint32 ID; // 0
diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h
index f59c7b56f56..7c915b37326 100644
--- a/src/server/game/DataStores/DB2fmt.h
+++ b/src/server/game/DataStores/DB2fmt.h
@@ -23,6 +23,18 @@ char const AreaGroupMemberFormat[] = "nii";
char const BroadcastTextFormat[] = "nissiiiiiiiii";
char const CurrencyTypesFormat[] = "nisssiiiiiis";
char const CurvePointFormat[] = "niiff";
+char const GameObjectsFormat[] = "niiffffffffiiiiiiiiiiiis";
+char const GarrAbilityFormat[] = "nissiii";
+char const GarrBuildingFormat[] = "niiiiissssiiiiiiiiiiiiii";
+char const GarrBuildingPlotInstFormat[] = "niiiff";
+char const GarrClassSpecFormat[] = "nsssii";
+char const GarrFollowerFormat[] = "niiiiiiiiiiiiiissiiii";
+char const GarrFollowerXAbilityFormat[] = "niii";
+char const GarrPlotBuildingFormat[] = "nii";
+char const GarrPlotFormat[] = "niiisiiii";
+char const GarrPlotInstanceFormat[] = "nis";
+char const GarrSiteLevelFormat[] = "niiiiffiiii";
+char const GarrSiteLevelPlotInstFormat[] = "niiffi";
char const HolidaysEntryFormat[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisiii";
char const ItemFormat[] = "niiiiiiii";
char const ItemAppearanceFormat[] = "nii";
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index cc310fbdeb5..719e539a9c4 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -21,6 +21,8 @@
#include "Define.h"
+#pragma pack(push, 1)
+
struct DBCPosition2D
{
float X;
@@ -34,6 +36,8 @@ struct DBCPosition3D
float Z;
};
+#pragma pack(pop)
+
enum LevelLimit
{
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
@@ -155,6 +159,12 @@ enum AchievementCriteriaAdditionalCondition
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY = 145,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL = 146,
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_RARE_MISSION = 147, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_LEVEL = 149, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_MISSION_TYPE = 167, // NYI
+ ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL = 184,
};
enum AchievementCriteriaFlags
@@ -184,121 +194,169 @@ enum AchievementCriteriaTimedTypes
enum AchievementCriteriaTypes
{
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
- ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
- ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
- ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH = 17,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19,
- ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20,
- ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23,
- ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24,
- ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27,
- ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28,
- ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29,
- ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32,
- ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40,
- ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42,
- ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47,
- ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48,
- ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, /// @todo itemlevel is mentioned in text but not present in dbc
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51,
- ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52,
- ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53,
- ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54,
- ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55,
- ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, /// @todo in some cases map not present, and in some cases need do without die
- ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57,
- ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60,
- ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61,
- ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67,
- ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68,
- ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69,
- ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
- ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
+ ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
+ ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH = 17,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19,
+ ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20,
+ ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23,
+ ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24,
+ ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27,
+ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28,
+ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29,
+ ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32,
+ ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33,
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39,
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40,
+ ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42,
+ ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47,
+ ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48,
+ ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49,
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, /// @todo itemlevel is mentioned in text but not present in dbc
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51,
+ ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52,
+ ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53,
+ ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54,
+ ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55,
+ ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, /// @todo in some cases map not present, and in some cases need do without die
+ ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57,
+ ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60,
+ ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61,
+ ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67,
+ ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68,
+ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69,
+ ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
+ ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
/// @todo 73: Achievements 1515, 1241, 1103 (Name: Mal'Ganis)
- ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76,
- ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77,
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80,
- ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION = 82,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83,
- ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS = 84,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88,
- ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90,
- ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
- ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104,
- ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106,
- ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107,
- ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109,
- ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, /// @todo target entry is missing
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113,
- ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
- ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
- ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
- ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
- ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139 //struct { uint32 count; } Guild Challenge
-};
-
-#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 188
+ ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74,
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76,
+ ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78,
+ ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80,
+ ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION = 82,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83,
+ ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS = 84,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87,
+ ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88,
+ ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90,
+ ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
+ ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
+ ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104,
+ ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105,
+ ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106,
+ ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107,
+ ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108,
+ ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109,
+ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, /// @todo target entry is missing
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113,
+ ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
+ ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
+ ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
+ ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
+ ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
+ ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
+ ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
+ ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
+ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
+ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139, //struct { uint32 count; } Guild Challenge
+ // 140 unk
+ // 141 unk
+ // 142 unk
+ // 143 unk
+ // 144 unk
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED = 145,
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES = 146,
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER = 147,
+ ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER = 148,
+ ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR = 149,
+ ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK = 150,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT = 151,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO = 152,
+ // ACHIEVEMENT_CRITERIA_TYPE_REACH_SOMETHING_LIKE_AREATRIGGER = 153,
+ // 154
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET = 155,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT = 156,
+ ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET = 157,
+ ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE = 158,
+ // 159
+ ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET = 160,
+ ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT = 161, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT = 162, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA = 163, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA = 164, // triggers a quest credit
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165,
+ ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING = 167,
+ ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING = 168,
+ ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169,
+ ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON = 170,
+ ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION = 171,
+ // 172
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT = 173,
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174,
+ ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT = 175,
+ // 176
+ // 177
+ ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT = 178,
+ // 179
+ // 180
+ // 181
+ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182,
+ ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL = 183,
+ ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL = 184,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY = 185,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT = 186,
+ ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER = 187,
+ ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS = 189
+};
+
+#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 190
enum AchievementCriteriaTreeOperator
{
@@ -427,6 +485,7 @@ enum MapFlags
MAP_FLAG_CAN_TOGGLE_DIFFICULTY = 0x0100,
MAP_FLAG_FLEX_LOCKING = 0x8000, // All difficulties share completed encounters lock, not bound to a single instance id
// heroic difficulty flag overrides it and uses instance id bind
+ MAP_FLAG_GARRISON = 0x4000000
};
enum AbilytyLearnType
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index e1f0c595b5f..fcc6a23ddf3 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -60,6 +60,7 @@ static AreaFlagByMapID sAreaFlagByMapID; // for instances wit
static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt);
+DBCStorage <AnimKitEntry> sAnimKitStore(AnimKitfmt);
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
DBCStorage <ArmorLocationEntry> sArmorLocationStore(ArmorLocationfmt);
DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt);
@@ -131,6 +132,9 @@ GameTable <GtSpellScalingEntry> sGtSpellScalingStore(GtSpellScalingfmt)
GameTable <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore(GtOCTBaseHPByClassfmt);
GameTable <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore(GtOCTBaseMPByClassfmt);
DBCStorage <GuildPerkSpellsEntry> sGuildPerkSpellsStore(GuildPerkSpellsfmt);
+DBCStorage <GuildColorBackgroundEntry> sGuildColorBackgroundStore(GuildColorBackgroundfmt);
+DBCStorage <GuildColorBorderEntry> sGuildColorBorderStore(GuildColorBorderfmt);
+DBCStorage <GuildColorEmblemEntry> sGuildColorEmblemStore(GuildColorEmblemfmt);
DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore(ImportPriceArmorfmt);
DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore(ImportPriceQualityfmt);
@@ -369,6 +373,7 @@ void LoadDBCStores(const std::string& dataPath)
}
LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc"/*, &CustomAchievementfmt, &CustomAchievementIndex*/);//19116
+ LoadDBC(availableDbcLocales, bad_dbc_files, sAnimKitStore, dbcPath, "AnimKit.dbc");//19865
LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sArmorLocationStore, dbcPath, "ArmorLocation.dbc");//19116
@@ -462,6 +467,9 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sGuildPerkSpellsStore, dbcPath, "GuildPerkSpells.dbc");//19116
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGuildColorBackgroundStore, dbcPath, "GuildColorBackground.dbc");//19865
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGuildColorBorderStore, dbcPath, "GuildColorBorder.dbc"); //19865
+ LoadDBC(availableDbcLocales, bad_dbc_files, sGuildColorEmblemStore, dbcPath, "GuildColorEmblem.dbc");//19865
LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceArmorStore, dbcPath, "ImportPriceArmor.dbc"); // 19116
LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceQualityStore, dbcPath, "ImportPriceQuality.dbc"); // 19116
@@ -881,9 +889,9 @@ void Map2ZoneCoordinates(float& x, float& y, uint32 zone)
std::swap(x, y); // client have map coords swapped
}
-MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapID)
+MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty /*= nullptr*/)
{
- auto itr = sMapDifficultyMap.find(mapID);
+ auto itr = sMapDifficultyMap.find(mapId);
if (itr == sMapDifficultyMap.end())
return nullptr;
@@ -892,14 +900,22 @@ MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapID)
for (auto& p : itr->second)
{
- DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(p.first);
- if (!difficulty)
+ DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(p.first);
+ if (!difficultyEntry)
continue;
- if (difficulty->Flags & DIFFICULTY_FLAG_DEFAULT)
+ if (difficultyEntry->Flags & DIFFICULTY_FLAG_DEFAULT)
+ {
+ if (difficulty)
+ *difficulty = Difficulty(p.first);
+
return p.second;
+ }
}
+ if (difficulty)
+ *difficulty = Difficulty(itr->second.begin()->first);
+
return itr->second.begin()->second;
}
@@ -920,7 +936,7 @@ MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficult
{
DifficultyEntry const* diffEntry = sDifficultyStore.LookupEntry(difficulty);
if (!diffEntry)
- return GetDefaultMapDifficulty(mapId);
+ return GetDefaultMapDifficulty(mapId, &difficulty);
uint32 tmpDiff = difficulty;
MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff));
@@ -929,7 +945,7 @@ MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficult
tmpDiff = diffEntry->FallbackDifficultyID;
diffEntry = sDifficultyStore.LookupEntry(tmpDiff);
if (!diffEntry)
- return GetDefaultMapDifficulty(mapId);
+ return GetDefaultMapDifficulty(mapId, &difficulty);
// pull new data
mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // we are 10 normal or 25 normal
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 72c0c35f1cb..03eda581f28 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -66,7 +66,7 @@ void Zone2MapCoordinates(float &x, float &y, uint32 zone);
void Map2ZoneCoordinates(float &x, float &y, uint32 zone);
typedef std::unordered_map<uint32, std::unordered_map<uint32, MapDifficultyEntry const*>> MapDifficultyMap;
-MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapID);
+MapDifficultyEntry const* GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty = nullptr);
MapDifficultyEntry const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
MapDifficultyEntry const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty);
@@ -123,6 +123,7 @@ private:
};
extern DBCStorage <AchievementEntry> sAchievementStore;
+extern DBCStorage <AnimKitEntry> sAnimKitStore;
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
extern DBCStorage <ArmorLocationEntry> sArmorLocationStore;
@@ -184,6 +185,9 @@ extern GameTable <GtSpellScalingEntry> sGtSpellScalingStore;
extern GameTable <GtOCTBaseHPByClassEntry> sGtOCTBaseHPByClassStore;
extern GameTable <GtOCTBaseMPByClassEntry> sGtOCTBaseMPByClassStore;
extern DBCStorage <GuildPerkSpellsEntry> sGuildPerkSpellsStore;
+extern DBCStorage <GuildColorBackgroundEntry> sGuildColorBackgroundStore;
+extern DBCStorage <GuildColorBorderEntry> sGuildColorBorderStore;
+extern DBCStorage <GuildColorEmblemEntry> sGuildColorEmblemStore;
extern DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore;
extern DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore;
extern DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 178ab097d81..aac3cbd2193 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -50,12 +50,12 @@ struct AchievementEntry
uint32 CriteriaTree; // 14
};
-struct AchievementCategoryEntry
+struct AnimKitEntry
{
uint32 ID; // 0
- uint32 Parent; // 1 -1 for main category
- //char* Name_lang; // 2
- //uint32 UIOrder; // 3
+ //uint32 OneShotDuration; // 1
+ //uint32 OneShotStopAnimKitID; // 2
+ //uint32 LowDefAnimKitID; // 3
};
// Temporary define until max depth is found somewhere (adt?)
@@ -72,10 +72,10 @@ struct AreaTableEntry
//uint32 SoundProviderPrefUnderwater; // 7,
//uint32 AmbienceID; // 8,
//uint32 ZoneMusic; // 9,
- char* ZoneName; // 10
+ //char* ZoneName; // 10 - Internal name
//uint32 IntroSound; // 11
uint32 ExplorationLevel; // 12
- //char* AreaName_lang // 13
+ char* AreaName_lang; // 13 - In-game name
uint32 FactionGroupMask; // 14
uint32 LiquidTypeID[4]; // 15-18
//float AmbientMultiplier; // 19
@@ -494,12 +494,15 @@ struct CriteriaEntry
uint32 ObjectiveId;
// ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31
+ // ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA = 163
+ // ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA = 164
uint32 AreaID;
// ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36
// ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42
// ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57
+ // ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY = 185
uint32 ItemID;
// ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38
@@ -544,6 +547,21 @@ struct CriteriaEntry
// ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109
uint32 LootType;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165
+ uint32 DungeonEncounterID;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169
+ uint32 GarrBuildingID;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON = 170
+ uint32 GarrisonLevel;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174
+ uint32 GarrMissionID;
+
+ // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182
+ uint32 CharShipmentContainerID;
} Asset; // 2
uint32 StartEvent; // 3
uint32 StartAsset; // 4
@@ -935,6 +953,33 @@ struct GuildPerkSpellsEntry
uint32 SpellID; // 2
};
+// GuildColorBackground.dbc
+struct GuildColorBackgroundEntry
+{
+ uint32 ID;
+ //uint8 Red;
+ //uint8 Green;
+ //uint8 Blue;
+};
+
+// GuildColorBorder.dbc
+struct GuildColorBorderEntry
+{
+ uint32 ID;
+ //uint8 Red;
+ //uint8 Green;
+ //uint8 Blue;
+};
+
+// GuildColorEmblem.dbc
+struct GuildColorEmblemEntry
+{
+ uint32 ID;
+ //uint8 Red;
+ //uint8 Green;
+ //uint8 Blue;
+};
+
// ImportPriceArmor.dbc
struct ImportPriceArmorEntry
{
@@ -1235,13 +1280,13 @@ struct MapEntry
uint32 RaidOffset; // 17
uint32 MaxPlayers; // 18
int32 ParentMapID; // 19 related to phasing
- //uint32 CosmeticParentMapID // 20
+ int32 CosmeticParentMapID; // 20
//uint32 TimeOffset // 21
// Helpers
uint32 Expansion() const { return ExpansionID; }
- bool IsDungeon() const { return InstanceType == MAP_INSTANCE || InstanceType == MAP_RAID; }
+ bool IsDungeon() const { return (InstanceType == MAP_INSTANCE || InstanceType == MAP_RAID) && !IsGarrison(); }
bool IsNonRaidDungeon() const { return InstanceType == MAP_INSTANCE; }
bool Instanceable() const { return InstanceType == MAP_INSTANCE || InstanceType == MAP_RAID || InstanceType == MAP_BATTLEGROUND || InstanceType == MAP_ARENA; }
bool IsRaid() const { return InstanceType == MAP_RAID; }
@@ -1266,6 +1311,7 @@ struct MapEntry
}
bool IsDynamicDifficultyMap() const { return (Flags & MAP_FLAG_CAN_TOGGLE_DIFFICULTY) != 0; }
+ bool IsGarrison() const { return (Flags & MAP_FLAG_GARRISON) != 0; }
};
struct MapDifficultyEntry
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 8c067dabb27..c7aa00286e1 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -25,7 +25,8 @@
char const Achievementfmt[] = "niixsxiixixxiii";
const std::string CustomAchievementfmt = "pppaaaapapaapp";
const std::string CustomAchievementIndex = "ID";
-char const AreaTableEntryfmt[] = "iiiniixxxxsxixiiiiixxxxxxxxxx";
+char const AnimKitfmt[] = "nxxx";
+char const AreaTableEntryfmt[] = "iiiniixxxxxxisiiiiixxxxxxxxxx";
char const AreaTriggerEntryfmt[] = "nifffxxxfffffxxxx";
char const ArmorLocationfmt[] = "nfffff";
char const AuctionHouseEntryfmt[] = "niiix";
@@ -87,6 +88,9 @@ char const GtSpellScalingfmt[] = "df";
char const GtOCTBaseHPByClassfmt[] = "df";
char const GtOCTBaseMPByClassfmt[] = "df";
char const GuildPerkSpellsfmt[] = "dii";
+char const GuildColorBackgroundfmt[] = "nXXX";
+char const GuildColorBorderfmt[] = "nXXX";
+char const GuildColorEmblemfmt[] = "nXXX";
char const ImportPriceArmorfmt[] = "nffff";
char const ImportPriceQualityfmt[] = "nf";
char const ImportPriceShieldfmt[] = "nf";
@@ -113,7 +117,7 @@ char const LiquidTypefmt[] = "nxxixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
char const LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx";
char const PhaseEntryfmt[] = "ni";
char const MailTemplateEntryfmt[] = "nxs";
-char const MapEntryfmt[] = "nxiixxsixxixiffxiiiixx";
+char const MapEntryfmt[] = "nxiixxsixxixiffxiiiiix";
char const MapDifficultyEntryfmt[] = "diisiiii";
char const MinorTalentEntryfmt[] = "niii";
char const MovieEntryfmt[] = "nxxxx";
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index b077f3e6110..e786c3b9c7c 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -412,7 +412,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
joinData.result = LFG_JOIN_NOT_MEET_REQS;
else if (grp)
{
- if (grp->GetMembersCount() > MAXGROUPSIZE)
+ if (grp->GetMembersCount() > MAX_GROUP_SIZE)
joinData.result = LFG_JOIN_TOO_MUCH_MEMBERS;
else
{
diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp
index 97f87a4d814..30e9a587353 100644
--- a/src/server/game/DungeonFinding/LFGQueue.cpp
+++ b/src/server/game/DungeonFinding/LFGQueue.cpp
@@ -323,7 +323,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
LfgRolesMap proposalRoles;
// Check for correct size
- if (check.size() > MAXGROUPSIZE || check.empty())
+ if (check.size() > MAX_GROUP_SIZE || check.empty())
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", strGuids.c_str());
return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE;
@@ -349,7 +349,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
// Check if more than one LFG group and number of players joining
uint8 numPlayers = 0;
uint8 numLfgGroups = 0;
- for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it)
+ for (GuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAX_GROUP_SIZE; ++it)
{
ObjectGuid guid = *it;
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
@@ -374,8 +374,8 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
}
}
- // Group with less that MAXGROUPSIZE members always compatible
- if (check.size() == 1 && numPlayers != MAXGROUPSIZE)
+ // Group with less that MAX_GROUP_SIZE members always compatible
+ if (check.size() == 1 && numPlayers != MAX_GROUP_SIZE)
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", strGuids.c_str());
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
@@ -396,7 +396,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS;
}
- if (numPlayers > MAXGROUPSIZE)
+ if (numPlayers > MAX_GROUP_SIZE)
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too much players (%u)", strGuids.c_str(), numPlayers);
SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS);
@@ -473,7 +473,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
}
// Enough players?
- if (numPlayers != MAXGROUPSIZE)
+ if (numPlayers != MAX_GROUP_SIZE)
{
TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers);
LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
index 426d47f88d3..b1ce1f0cdbb 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -18,6 +18,7 @@
#include "Unit.h"
#include "SpellInfo.h"
#include "Log.h"
+#include "UpdateData.h"
#include "AreaTrigger.h"
AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0)
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index 4294eb57dbd..15e560a8e7e 100644
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -59,7 +59,7 @@ void Corpse::RemoveFromWorld()
if (IsInWorld())
GetMap()->GetObjectsStore().Remove<Corpse>(GetGUID());
- Object::RemoveFromWorld();
+ WorldObject::RemoveFromWorld();
}
bool Corpse::Create(ObjectGuid::LowType guidlow, Map* map)
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index ce7eadcae2b..70a2ab2307a 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -382,13 +382,14 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
setFaction(cInfo->faction);
- uint32 npcflag, unit_flags, dynamicflags;
+ uint32 unit_flags, dynamicflags;
+ uint64 npcflag;
ObjectMgr::ChooseCreatureFlags(cInfo, npcflag, unit_flags, dynamicflags, data);
if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT)
- SetUInt32Value(UNIT_NPC_FLAGS, npcflag | sGameEventMgr->GetNPCFlag(this));
+ SetUInt64Value(UNIT_NPC_FLAGS, npcflag | sGameEventMgr->GetNPCFlag(this));
else
- SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
+ SetUInt64Value(UNIT_NPC_FLAGS, npcflag);
SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags);
SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2);
@@ -965,7 +966,7 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask)
CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId);
uint32 displayId = GetNativeDisplayId();
- uint32 npcflag = GetUInt32Value(UNIT_NPC_FLAGS);
+ uint64 npcflag = GetUInt64Value(UNIT_NPC_FLAGS);
uint32 unit_flags = GetUInt32Value(UNIT_FIELD_FLAGS);
uint32 dynamicflags = GetUInt32Value(OBJECT_DYNAMIC_FLAGS);
@@ -1053,7 +1054,7 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask)
stmt->setUInt32(index++, GetHealth());
stmt->setUInt32(index++, GetPower(POWER_MANA));
stmt->setUInt8(index++, uint8(GetDefaultMovementType()));
- stmt->setUInt32(index++, npcflag);
+ stmt->setUInt64(index++, npcflag);
stmt->setUInt32(index++, unit_flags);
stmt->setUInt32(index++, dynamicflags);
trans->Append(stmt);
@@ -1511,7 +1512,7 @@ void Creature::setDeathState(DeathState s)
SaveRespawnTime();
SetTarget(ObjectGuid::Empty); // remove target selection in any cases (can be set at aura remove in Unit::setDeathState)
- SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0); // if creature is mounted on a virtual mount, remove it at death
@@ -1543,7 +1544,7 @@ void Creature::setDeathState(DeathState s)
UpdateMovementFlags();
CreatureTemplate const* cinfo = GetCreatureTemplate();
- SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag);
+ SetUInt64Value(UNIT_NPC_FLAGS, cinfo->npcflag);
ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING));
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
LoadCreaturesAddon(true);
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index adab2ea38bb..0e985ff3648 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -93,7 +93,7 @@ struct CreatureTemplate
int32 expansion;
uint32 expansionUnknown; // either 0 or 3, sent to the client / wdb
uint32 faction;
- uint32 npcflag;
+ uint64 npcflag;
float speed_walk;
float speed_run;
float scale;
@@ -304,7 +304,7 @@ struct CreatureData
uint32 curmana;
uint8 movementType;
uint32 spawnMask;
- uint32 npcflag;
+ uint64 npcflag;
uint32 unit_flags; // enum UnitFlags mask values
uint32 dynamicflags;
uint32 phaseid;
@@ -373,7 +373,7 @@ struct VendorItem
uint8 Type;
//helpers
- bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->GetFlags2() & ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD || !ExtendedCost; }
+ bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->GetFlags2() & ITEM_FLAG2_EXT_COST_REQUIRES_GOLD || !ExtendedCost; }
};
typedef std::vector<VendorItem*> VendorItemList;
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 815c98c9710..faa458d45dc 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -505,7 +505,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
packet.Info.SuggestedGroupNum = quest->GetSuggestedPlayers();
packet.Info.RewardNextQuest = quest->GetNextQuestInChain();
packet.Info.RewardXPDifficulty = quest->GetXPDifficulty();
- packet.Info.Float10 = quest->Float10; // Unk
+ packet.Info.RewardXPMultiplier = quest->GetXPMultiplier();
packet.Info.Float13 = quest->Float13; // Unk
if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 852269855df..948579cd419 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -180,7 +180,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
m_stationaryPosition.Relocate(x, y, z, ang);
if (!IsPositionValid())
{
- TC_LOG_ERROR("misc", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, name_id, x, y);
+ TC_LOG_ERROR("misc", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, GetSpawnId(), name_id, x, y);
return false;
}
@@ -195,13 +195,13 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id);
if (!goinfo)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: non-existing entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f)", guidlow, name_id, map->GetId(), x, y, z);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: non-existing entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f)", guidlow, GetSpawnId(), name_id, map->GetId(), x, y, z);
return false;
}
if (goinfo->type == GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, name_id);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, GetSpawnId(), name_id);
return false;
}
@@ -214,7 +214,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
if (goinfo->type >= MAX_GAMEOBJECT_TYPE)
{
- TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Entry: %u) not created: non-existing GO type '%u' in `gameobject_template`. It will crash client if created.", guidlow, name_id, goinfo->type);
+ TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: non-existing GO type '%u' in `gameobject_template`. It will crash client if created.", guidlow, GetSpawnId(), name_id, goinfo->type);
return false;
}
@@ -310,7 +310,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
break;
}
- if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(guidlow))
+ if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(GetSpawnId()))
{
if (addon->InvisibilityValue)
{
@@ -2163,7 +2163,7 @@ void GameObject::SetTransportState(GOState state, uint32 stopFrame /*= 0*/)
m_goValue.Transport.StateUpdateTimer = 0;
m_goValue.Transport.PathProgress = getMSTime();
if (GetGoState() >= GO_STATE_TRANSPORT_STOPPED)
- m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED);
+ m_goValue.Transport.PathProgress += m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED);
SetGoState(GO_STATE_TRANSPORT_ACTIVE);
}
else
@@ -2420,7 +2420,7 @@ void GameObject::UpdateModelPosition()
if (GetMap()->ContainsGameObjectModel(*m_model))
{
GetMap()->RemoveGameObjectModel(*m_model);
- m_model->Relocate(*this);
+ m_model->UpdatePosition();
GetMap()->InsertGameObjectModel(*m_model);
}
}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index ee429c95475..c61f1ba87c4 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -1065,6 +1065,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map
float GetStationaryY() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT) return m_stationaryPosition.GetPositionY(); return GetPositionY(); }
float GetStationaryZ() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT) return m_stationaryPosition.GetPositionZ(); return GetPositionZ(); }
float GetStationaryO() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT) return m_stationaryPosition.GetOrientation(); return GetOrientation(); }
+ void RelocateStationaryPosition(float x, float y, float z, float o) { m_stationaryPosition.Relocate(x, y, z, o); }
float GetInteractionDistance() const;
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 50994df7831..7250c0cff23 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -361,7 +361,7 @@ void Item::SaveToDB(SQLTransaction& trans)
trans->Append(stmt);
- if ((uState == ITEM_CHANGED) && HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
+ if ((uState == ITEM_CHANGED) && HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GIFT_OWNER);
stmt->setUInt64(0, GetOwnerGUID().GetCounter());
@@ -376,7 +376,7 @@ void Item::SaveToDB(SQLTransaction& trans)
stmt->setUInt64(0, GetGUID().GetCounter());
trans->Append(stmt);
- if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
+ if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
stmt->setUInt64(0, GetGUID().GetCounter());
@@ -451,7 +451,7 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
// Remove bind flag for items vs NO_BIND set
if (IsSoulBound() && proto->GetBonding() == NO_BIND)
{
- ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND, false);
+ ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, false);
need_save = true;
}
@@ -760,7 +760,7 @@ bool Item::CanBeTraded(bool mail, bool trade) const
if (m_lootGenerated)
return false;
- if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE) || !trade)))
+ if ((!mail || !IsBoundAccountWide()) && (IsSoulBound() && (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE) || !trade)))
return false;
if (IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()))
@@ -1071,7 +1071,7 @@ Item* Item::CloneItem(uint32 count, Player const* player) const
newItem->SetGuidValue(ITEM_FIELD_CREATOR, GetGuidValue(ITEM_FIELD_CREATOR));
newItem->SetGuidValue(ITEM_FIELD_GIFTCREATOR, GetGuidValue(ITEM_FIELD_GIFTCREATOR));
- newItem->SetUInt32Value(ITEM_FIELD_FLAGS, GetUInt32Value(ITEM_FIELD_FLAGS) & ~(ITEM_FLAG_REFUNDABLE | ITEM_FLAG_BOP_TRADEABLE));
+ newItem->SetUInt32Value(ITEM_FIELD_FLAGS, GetUInt32Value(ITEM_FIELD_FLAGS) & ~(ITEM_FIELD_FLAG_REFUNDABLE | ITEM_FIELD_FLAG_BOP_TRADEABLE));
newItem->SetUInt32Value(ITEM_FIELD_DURATION, GetUInt32Value(ITEM_FIELD_DURATION));
// player CAN be NULL in which case we must not update random properties because that accesses player's item update queue
if (player)
@@ -1089,7 +1089,7 @@ bool Item::IsBindedNotWith(Player const* player) const
if (GetOwnerGUID() == player->GetGUID())
return false;
- if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
+ if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE))
if (allowedGUIDs.find(player->GetGUID()) != allowedGUIDs.end())
return false;
@@ -1211,10 +1211,10 @@ void Item::DeleteRefundDataFromDB(SQLTransaction* trans)
void Item::SetNotRefundable(Player* owner, bool changestate /*=true*/, SQLTransaction* trans /*=NULL*/)
{
- if (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
+ if (!HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE))
return;
- RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
+ RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE);
// Following is not applicable in the trading procedure
if (changestate)
SetState(ITEM_CHANGED, owner);
@@ -1269,13 +1269,13 @@ bool Item::IsRefundExpired()
void Item::SetSoulboundTradeable(GuidSet const& allowedLooters)
{
- SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE);
+ SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE);
allowedGUIDs = allowedLooters;
}
void Item::ClearSoulboundTradeable(Player* currentOwner)
{
- RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE);
+ RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE);
if (allowedGUIDs.empty())
return;
@@ -1315,7 +1315,7 @@ bool Item::CanBeTransmogrified() const
if (proto->GetClass() == ITEM_CLASS_WEAPON && proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
return false;
- if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG)
+ if (proto->GetFlags2() & ITEM_FLAG2_CANNOT_BE_TRANSMOG)
return false;
if (!HasStats())
@@ -1331,7 +1331,7 @@ bool Item::CanTransmogrify() const
if (!proto)
return false;
- if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG)
+ if (proto->GetFlags2() & ITEM_FLAG2_CANNOT_TRANSMOG)
return false;
if (proto->GetQuality() == ITEM_QUALITY_LEGENDARY)
@@ -1344,7 +1344,7 @@ bool Item::CanTransmogrify() const
if (proto->GetClass() == ITEM_CLASS_WEAPON && proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_FISHING_POLE)
return false;
- if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_CAN_TRANSMOG)
+ if (proto->GetFlags2() & ITEM_FLAG2_CAN_TRANSMOG)
return true;
if (!HasStats())
@@ -1405,7 +1405,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice)
{
normalSellPrice = true;
- if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ if (proto->GetFlags2() & ITEM_FLAG2_HAS_NORMAL_PRICE)
{
return proto->GetBuyPrice();
}
@@ -1524,7 +1524,7 @@ uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*=
{
uint32 cost = 0;
- if (proto->GetFlags2() & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ if (proto->GetFlags2() & ITEM_FLAG2_HAS_NORMAL_PRICE)
cost = proto->GetSellPrice();
else
{
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index c204cbb1f17..7d03a0a68eb 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -261,10 +261,10 @@ class Item : public Object
void SetOwnerGUID(ObjectGuid guid) { SetGuidValue(ITEM_FIELD_OWNER, guid); }
Player* GetOwner()const;
- void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND, val); }
- bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND); }
- bool IsBoundAccountWide() const { return (GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT) != 0; }
- bool IsBattlenetAccountBound() const { return (GetTemplate()->GetFlags2() & ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND) != 0; }
+ void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, val); }
+ bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND); }
+ bool IsBoundAccountWide() const { return (GetTemplate()->GetFlags() & ITEM_FLAG_BIND_TO_ACCOUNT) != 0; }
+ bool IsBattlenetAccountBound() const { return (GetTemplate()->GetFlags2() & ITEM_FLAG2_BNET_ACCOUNT_BOUND) != 0; }
bool IsBindedNotWith(Player const* player) const;
bool IsBoundByEnchant() const;
virtual void SaveToDB(SQLTransaction& trans);
@@ -291,7 +291,7 @@ class Item : public Object
Bag* ToBag() { if (IsBag()) return reinterpret_cast<Bag*>(this); else return NULL; }
const Bag* ToBag() const { if (IsBag()) return reinterpret_cast<const Bag*>(this); else return NULL; }
- bool IsLocked() const { return !HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED); }
+ bool IsLocked() const { return !HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED); }
bool IsBag() const { return GetTemplate()->GetInventoryType() == INVTYPE_BAG; }
bool IsCurrencyToken() const { return GetTemplate()->IsCurrencyToken(); }
bool IsNotEmptyBag() const;
diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp
index 34a6ee635a6..f9e2e2d4236 100644
--- a/src/server/game/Entities/Item/ItemTemplate.cpp
+++ b/src/server/game/Entities/Item/ItemTemplate.cpp
@@ -89,7 +89,7 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag
store = &sItemDamageAmmoStore;
break;
case INVTYPE_2HWEAPON:
- if (GetFlags2() & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ if (GetFlags2() & ITEM_FLAG2_CASTER_WEAPON)
store = &sItemDamageTwoHandCasterStore;
else
store = &sItemDamageTwoHandStore;
@@ -117,7 +117,7 @@ void ItemTemplate::GetDamage(uint32 itemLevel, float& minDamage, float& maxDamag
case INVTYPE_WEAPON:
case INVTYPE_WEAPONMAINHAND:
case INVTYPE_WEAPONOFFHAND:
- if (GetFlags2() & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ if (GetFlags2() & ITEM_FLAG2_CASTER_WEAPON)
store = &sItemDamageOneHandCasterStore;
else
store = &sItemDamageOneHandStore;
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index 47523872151..c578b641ad2 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -127,101 +127,140 @@ enum ItemBondingType
#define MAX_BIND_TYPE 6
/* /// @todo: Requiring actual cases in which using (an) item isn't allowed while shapeshifted. Else, this flag would need an implementation.
- ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms */
-
-enum ItemProtoFlags
-{
- ITEM_PROTO_FLAG_UNK1 = 0x00000001, // ?
- ITEM_PROTO_FLAG_CONJURED = 0x00000002, // Conjured item
- ITEM_PROTO_FLAG_OPENABLE = 0x00000004, // Item can be right clicked to open for loot
- ITEM_PROTO_FLAG_HEROIC = 0x00000008, // Makes green "Heroic" text appear on item
- ITEM_PROTO_FLAG_DEPRECATED = 0x00000010, // Cannot equip or use
- ITEM_PROTO_FLAG_INDESTRUCTIBLE = 0x00000020, // Item can not be destroyed, except by using spell (item can be reagent for spell)
- ITEM_PROTO_FLAG_UNK2 = 0x00000040, // ?
- ITEM_PROTO_FLAG_NO_EQUIP_COOLDOWN = 0x00000080, // No default 30 seconds cooldown when equipped
- ITEM_PROTO_FLAG_UNK3 = 0x00000100, // ?
- ITEM_PROTO_FLAG_WRAPPER = 0x00000200, // Item can wrap other items
- ITEM_PROTO_FLAG_UNK4 = 0x00000400, // ?
- ITEM_PROTO_FLAG_PARTY_LOOT = 0x00000800, // Looting this item does not remove it from available loot
- ITEM_PROTO_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost)
- ITEM_PROTO_FLAG_CHARTER = 0x00002000, // Item is guild or arena charter
- ITEM_PROTO_FLAG_UNK5 = 0x00004000, // Only readable items have this (but not all)
- ITEM_PROTO_FLAG_UNK6 = 0x00008000, // ?
- ITEM_PROTO_FLAG_UNK7 = 0x00010000, // ?
- ITEM_PROTO_FLAG_UNK8 = 0x00020000, // ?
- ITEM_PROTO_FLAG_PROSPECTABLE = 0x00040000, // Item can be prospected
- ITEM_PROTO_FLAG_UNIQUE_EQUIPPED = 0x00080000, // You can only equip one of these
- ITEM_PROTO_FLAG_UNK9 = 0x00100000, // ?
- ITEM_PROTO_FLAG_USEABLE_IN_ARENA = 0x00200000, // Item can be used during arena match
- ITEM_PROTO_FLAG_THROWABLE = 0x00400000, // Some Thrown weapons have it (and only Thrown) but not all
- ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms
- ITEM_PROTO_FLAG_UNK10 = 0x01000000, // ?
- ITEM_PROTO_FLAG_SMART_LOOT = 0x02000000, // Profession recipes: can only be looted if you meet requirements and don't already know it
- ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA = 0x04000000, // Item cannot be used in arena
- ITEM_PROTO_FLAG_BIND_TO_ACCOUNT = 0x08000000, // Item binds to account and can be sent only to your own characters
- ITEM_PROTO_FLAG_TRIGGERED_CAST = 0x10000000, // Spell is cast with triggered flag
- ITEM_PROTO_FLAG_MILLABLE = 0x20000000, // Item can be milled
- ITEM_PROTO_FLAG_UNK11 = 0x40000000, // ?
- ITEM_PROTO_FLAG_BOP_TRADEABLE = 0x80000000 // bound item that can be traded
-};
-
-enum ItemFieldFlags
-{
- ITEM_FLAG_SOULBOUND = 0x00000001, // Item is soulbound and cannot be traded <<--
- ITEM_FLAG_UNK1 = 0x00000002, // ?
- ITEM_FLAG_UNLOCKED = 0x00000004, // Item had lock but can be opened now
- ITEM_FLAG_WRAPPED = 0x00000008, // Item is wrapped and contains another item
- ITEM_FLAG_UNK2 = 0x00000010, // ?
- ITEM_FLAG_UNK3 = 0x00000020, // ?
- ITEM_FLAG_UNK4 = 0x00000040, // ?
- ITEM_FLAG_UNK5 = 0x00000080, // ?
- ITEM_FLAG_BOP_TRADEABLE = 0x00000100, // Allows trading soulbound items
- ITEM_FLAG_READABLE = 0x00000200, // Opens text page when right clicked
- ITEM_FLAG_UNK6 = 0x00000400, // ?
- ITEM_FLAG_UNK7 = 0x00000800, // ?
- ITEM_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost)
- ITEM_FLAG_UNK8 = 0x00002000, // ?
- ITEM_FLAG_UNK9 = 0x00004000, // ?
- ITEM_FLAG_UNK10 = 0x00008000, // ?
- ITEM_FLAG_UNK11 = 0x00010000, // ?
- ITEM_FLAG_UNK12 = 0x00020000, // ?
- ITEM_FLAG_UNK13 = 0x00040000, // ?
- ITEM_FLAG_UNK14 = 0x00080000, // ?
- ITEM_FLAG_UNK15 = 0x00100000, // ?
- ITEM_FLAG_UNK16 = 0x00200000, // ?
- ITEM_FLAG_UNK17 = 0x00400000, // ?
- ITEM_FLAG_UNK18 = 0x00800000, // ?
- ITEM_FLAG_UNK19 = 0x01000000, // ?
- ITEM_FLAG_UNK20 = 0x02000000, // ?
- ITEM_FLAG_UNK21 = 0x04000000, // ?
- ITEM_FLAG_UNK22 = 0x08000000, // ?
- ITEM_FLAG_UNK23 = 0x10000000, // ?
- ITEM_FLAG_UNK24 = 0x20000000, // ?
- ITEM_FLAG_UNK25 = 0x40000000, // ?
- ITEM_FLAG_UNK26 = 0x80000000, // ?
-
- ITEM_FLAG_MAIL_TEXT_MASK = ITEM_FLAG_READABLE | ITEM_FLAG_UNK13 | ITEM_FLAG_UNK14
-};
-
-enum ItemFlagsExtra
-{
- ITEM_FLAGS_EXTRA_HORDE_ONLY = 0x00000001,
- ITEM_FLAGS_EXTRA_ALLIANCE_ONLY = 0x00000002,
- ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required
- ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100,
- ITEM_FLAGS_EXTRA_CASTER_WEAPON = 0x00000200,
- ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE = 0x00004000,
- ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND = 0x00020000,
- ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG = 0x00200000,
- ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG = 0x00400000,
- ITEM_FLAGS_EXTRA_CAN_TRANSMOG = 0x00800000,
+ ITEM_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms */
+
+// ITEM_FIELD_FLAGS
+enum ItemFieldFlags : uint32
+{
+ ITEM_FIELD_FLAG_SOULBOUND = 0x00000001, // Item is soulbound and cannot be traded <<--
+ ITEM_FIELD_FLAG_TRANSLATED = 0x00000002, // Item text will not read as garbage when player does not know the language
+ ITEM_FIELD_FLAG_UNLOCKED = 0x00000004, // Item had lock but can be opened now
+ ITEM_FIELD_FLAG_WRAPPED = 0x00000008, // Item is wrapped and contains another item
+ ITEM_FIELD_FLAG_UNK2 = 0x00000010,
+ ITEM_FIELD_FLAG_UNK3 = 0x00000020,
+ ITEM_FIELD_FLAG_UNK4 = 0x00000040,
+ ITEM_FIELD_FLAG_UNK5 = 0x00000080,
+ ITEM_FIELD_FLAG_BOP_TRADEABLE = 0x00000100, // Allows trading soulbound items
+ ITEM_FIELD_FLAG_READABLE = 0x00000200, // Opens text page when right clicked
+ ITEM_FIELD_FLAG_UNK6 = 0x00000400,
+ ITEM_FIELD_FLAG_UNK7 = 0x00000800,
+ ITEM_FIELD_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost)
+ ITEM_FIELD_FLAG_UNK8 = 0x00002000,
+ ITEM_FIELD_FLAG_UNK9 = 0x00004000,
+ ITEM_FIELD_FLAG_UNK10 = 0x00008000,
+ ITEM_FIELD_FLAG_UNK11 = 0x00010000,
+ ITEM_FIELD_FLAG_UNK12 = 0x00020000,
+ ITEM_FIELD_FLAG_UNK13 = 0x00040000,
+ ITEM_FIELD_FLAG_UNK14 = 0x00080000,
+ ITEM_FIELD_FLAG_UNK15 = 0x00100000,
+ ITEM_FIELD_FLAG_UNK16 = 0x00200000,
+ ITEM_FIELD_FLAG_UNK17 = 0x00400000,
+ ITEM_FIELD_FLAG_UNK18 = 0x00800000,
+ ITEM_FIELD_FLAG_UNK19 = 0x01000000,
+ ITEM_FIELD_FLAG_UNK20 = 0x02000000,
+ ITEM_FIELD_FLAG_UNK21 = 0x04000000,
+ ITEM_FIELD_FLAG_UNK22 = 0x08000000,
+ ITEM_FIELD_FLAG_UNK23 = 0x10000000,
+ ITEM_FIELD_FLAG_UNK24 = 0x20000000,
+ ITEM_FIELD_FLAG_UNK25 = 0x40000000,
+ ITEM_FIELD_FLAG_UNK26 = 0x80000000,
+
+ ITEM_FIELD_FLAG_MAIL_TEXT_MASK = ITEM_FIELD_FLAG_READABLE | ITEM_FIELD_FLAG_UNK13 | ITEM_FIELD_FLAG_UNK14
+};
+
+enum ItemFlags : uint32
+{
+ ITEM_FLAG_UNK1 = 0x00000001,
+ ITEM_FLAG_CONJURED = 0x00000002, // Conjured item
+ ITEM_FLAG_OPENABLE = 0x00000004, // Item can be right clicked to open for loot
+ ITEM_FLAG_HEROIC = 0x00000008, // Makes green "Heroic" text appear on item
+ ITEM_FLAG_DEPRECATED = 0x00000010, // Cannot equip or use
+ ITEM_FLAG_INDESTRUCTIBLE = 0x00000020, // Item can not be destroyed, except by using spell (item can be reagent for spell)
+ ITEM_FLAG_UNK2 = 0x00000040,
+ ITEM_FLAG_NO_EQUIP_COOLDOWN = 0x00000080, // No default 30 seconds cooldown when equipped
+ ITEM_FLAG_UNK3 = 0x00000100,
+ ITEM_FLAG_WRAPPER = 0x00000200, // Item can wrap other items
+ ITEM_FLAG_UNK4 = 0x00000400,
+ ITEM_FLAG_PARTY_LOOT = 0x00000800, // Looting this item does not remove it from available loot
+ ITEM_FLAG_REFUNDABLE = 0x00001000, // Item can be returned to vendor for its original cost (extended cost)
+ ITEM_FLAG_CHARTER = 0x00002000, // Item is guild or arena charter
+ ITEM_FLAG_UNK5 = 0x00004000, // Only readable items have this (but not all)
+ ITEM_FLAG_UNK6 = 0x00008000,
+ ITEM_FLAG_UNK7 = 0x00010000,
+ ITEM_FLAG_UNK8 = 0x00020000,
+ ITEM_FLAG_PROSPECTABLE = 0x00040000, // Item can be prospected
+ ITEM_FLAG_UNIQUE_EQUIPPED = 0x00080000, // You can only equip one of these
+ ITEM_FLAG_UNK9 = 0x00100000,
+ ITEM_FLAG_USEABLE_IN_ARENA = 0x00200000, // Item can be used during arena match
+ ITEM_FLAG_THROWABLE = 0x00400000, // Some Thrown weapons have it (and only Thrown) but not all
+ ITEM_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms
+ ITEM_FLAG_UNK10 = 0x01000000,
+ ITEM_FLAG_SMART_LOOT = 0x02000000, // Profession recipes: can only be looted if you meet requirements and don't already know it
+ ITEM_FLAG_NOT_USEABLE_IN_ARENA = 0x04000000, // Item cannot be used in arena
+ ITEM_FLAG_BIND_TO_ACCOUNT = 0x08000000, // Item binds to account and can be sent only to your own characters
+ ITEM_FLAG_TRIGGERED_CAST = 0x10000000, // Spell is cast with triggered flag
+ ITEM_FLAG_MILLABLE = 0x20000000, // Item can be milled
+ ITEM_FLAG_UNK11 = 0x40000000,
+ ITEM_FLAG_BOP_TRADEABLE = 0x80000000 // bound item that can be traded
+};
+
+enum ItemFlags2 : uint32
+{
+ ITEM_FLAG2_HORDE_ONLY = 0x00000001,
+ ITEM_FLAG2_ALLIANCE_ONLY = 0x00000002,
+ ITEM_FLAG2_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required
+ ITEM_FLAG2_UNK1 = 0x00000008,
+ ITEM_FLAG2_UNK2 = 0x00000010,
+ ITEM_FLAG2_UNK3 = 0x00000020,
+ ITEM_FLAG2_UNK4 = 0x00000040,
+ ITEM_FLAG2_UNK5 = 0x00000080,
+ ITEM_FLAG2_NEED_ROLL_DISABLED = 0x00000100,
+ ITEM_FLAG2_CASTER_WEAPON = 0x00000200,
+ ITEM_FLAG2_UNK6 = 0x00000400,
+ ITEM_FLAG2_UNK7 = 0x00000800,
+ ITEM_FLAG2_UNK8 = 0x00001000,
+ ITEM_FLAG2_UNK9 = 0x00002000,
+ ITEM_FLAG2_HAS_NORMAL_PRICE = 0x00004000,
+ ITEM_FLAG2_UNK10 = 0x00008000,
+ ITEM_FLAG2_UNK11 = 0x00010000,
+ ITEM_FLAG2_BNET_ACCOUNT_BOUND = 0x00020000,
+ ITEM_FLAG2_UNK12 = 0x00040000,
+ ITEM_FLAG2_UNK13 = 0x00080000,
+ ITEM_FLAG2_UNK14 = 0x00100000,
+ ITEM_FLAG2_CANNOT_BE_TRANSMOG = 0x00200000,
+ ITEM_FLAG2_CANNOT_TRANSMOG = 0x00400000,
+ ITEM_FLAG2_CAN_TRANSMOG = 0x00800000,
+ ITEM_FLAG2_UNK15 = 0x01000000,
+ ITEM_FLAG2_UNK16 = 0x02000000,
+ ITEM_FLAG2_UNK17 = 0x04000000,
+ ITEM_FLAG2_UNK18 = 0x08000000,
+ ITEM_FLAG2_UNK19 = 0x10000000,
+ ITEM_FLAG2_UNK20 = 0x20000000,
+ ITEM_FLAG2_UNK21 = 0x40000000,
+ ITEM_FLAG2_CRAFTING_MATERIAL = 0x80000000
};
enum ItemFlags3
{
- ITEM_FLAG3_IGNORE_ITEM_LEVEL_DELTAS = 0x080, // Ignore item level adjustments from PLAYER_FIELD_ITEM_LEVEL_DELTA
- ITEM_FLAG3_IGNORE_PVP_ITEM_LEVEL_CAP = 0x100,
- ITEM_FLAG3_HEIRLOOM_QUALITY = 0x200, // Item appears as having heirloom quality ingame regardless of its real quality (does not affect stat calculation)
+ ITEM_FLAG3_UNK1 = 0x00000001,
+ ITEM_FLAG3_UNK2 = 0x00000002,
+ ITEM_FLAG3_UNK3 = 0x00000004,
+ ITEM_FLAG3_UNK4 = 0x00000008,
+ ITEM_FLAG3_UNK5 = 0x00000010,
+ ITEM_FLAG3_UNK6 = 0x00000020,
+ ITEM_FLAG3_UNK7 = 0x00000040,
+ ITEM_FLAG3_IGNORE_ITEM_LEVEL_DELTAS = 0x00000080, // Ignore item level adjustments from PLAYER_FIELD_ITEM_LEVEL_DELTA
+ ITEM_FLAG3_IGNORE_PVP_ITEM_LEVEL_CAP = 0x00000100,
+ ITEM_FLAG3_HEIRLOOM_QUALITY = 0x00000200, // Item appears as having heirloom quality ingame regardless of its real quality (does not affect stat calculation)
+ ITEM_FLAG3_UNK8 = 0x00000400,
+ ITEM_FLAG3_UNK9 = 0x00000800,
+ ITEM_FLAG3_DOESNT_APPEAR_IN_GUILD_NEWS = 0x00001000, // Item is not included in the guild news panel
+ ITEM_FLAG3_UNK10 = 0x00002000,
+ ITEM_FLAG3_UNK11 = 0x00004000,
+ ITEM_FLAG3_UNK12 = 0x00008000,
+ ITEM_FLAG3_UNK13 = 0x00010000,
+ ITEM_FLAG3_UNK14 = 0x00020000,
+ ITEM_FLAG3_UNK15 = 0x00040000
};
enum ItemFlagsCustom
@@ -710,7 +749,7 @@ struct ItemTemplate
bool IsPotion() const { return GetClass() == ITEM_CLASS_CONSUMABLE && GetSubClass() == ITEM_SUBCLASS_POTION; }
bool IsVellum() const { return GetClass() == ITEM_CLASS_TRADE_GOODS && GetSubClass() == ITEM_SUBCLASS_ENCHANTMENT; }
- bool IsConjuredConsumable() const { return GetClass() == ITEM_CLASS_CONSUMABLE && (GetFlags() & ITEM_PROTO_FLAG_CONJURED); }
+ bool IsConjuredConsumable() const { return GetClass() == ITEM_CLASS_CONSUMABLE && (GetFlags() & ITEM_FLAG_CONJURED); }
bool IsRangedWeapon() const
{
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 68650bdff59..655af613220 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -212,11 +212,16 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
break;
}
- if (!(flags & UPDATEFLAG_LIVING))
- if (WorldObject const* worldObject = dynamic_cast<WorldObject const*>(this))
+ if (WorldObject const* worldObject = dynamic_cast<WorldObject const*>(this))
+ {
+ if (!(flags & UPDATEFLAG_LIVING))
if (!worldObject->m_movementInfo.transport.guid.IsEmpty())
flags |= UPDATEFLAG_TRANSPORT_POSITION;
+ if (worldObject->GetAIAnimKitId() || worldObject->GetMovementAnimKitId() || worldObject->GetMeleeAnimKitId())
+ flags |= UPDATEFLAG_ANIMKITS;
+ }
+
if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
@@ -237,14 +242,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
}
if (Unit const* unit = ToUnit())
- {
if (unit->GetVictim())
flags |= UPDATEFLAG_HAS_TARGET;
- if (unit->GetAIAnimKitId() || unit->GetMovementAnimKitId() || unit->GetMeleeAnimKitId())
- flags |= UPDATEFLAG_ANIMKITS;
- }
-
ByteBuffer buf(0x400);
buf << uint8(updateType);
buf << GetPackGUID();
@@ -502,10 +502,10 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint32 flags) const
if (AnimKitCreate)
{
- Unit const* unit = ToUnit();
- *data << uint16(unit->GetAIAnimKitId()); // AiID
- *data << uint16(unit->GetMovementAnimKitId()); // MovementID
- *data << uint16(unit->GetMeleeAnimKitId()); // MeleeID
+ WorldObject const* self = static_cast<WorldObject const*>(this);
+ *data << uint16(self->GetAIAnimKitId()); // AiID
+ *data << uint16(self->GetMovementAnimKitId()); // MovementID
+ *data << uint16(self->GetMeleeAnimKitId()); // MeleeID
}
if (Rotation)
@@ -1408,62 +1408,6 @@ bool Object::PrintIndexError(uint32 index, bool set) const
return false;
}
-bool Position::operator==(Position const &a)
-{
- return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
- G3D::fuzzyEq(a.m_positionY, m_positionY) &&
- G3D::fuzzyEq(a.m_positionZ, m_positionZ) &&
- G3D::fuzzyEq(a._orientation, _orientation));
-}
-
-bool Position::HasInLine(WorldObject const* target, float width) const
-{
- if (!HasInArc(float(M_PI), target))
- return false;
- width += target->GetObjectSize();
- float angle = GetRelativeAngle(target);
- return std::fabs(std::sin(angle)) * GetExactDist2d(target->GetPositionX(), target->GetPositionY()) < width;
-}
-
-std::string Position::ToString() const
-{
- std::stringstream sstr;
- sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << _orientation;
- return sstr.str();
-}
-
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
-{
- float x, y, z, o;
- buf >> x >> y >> z >> o;
- streamer.Pos->Relocate(x, y, z, o);
- return buf;
-}
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
-{
- buf << streamer.Pos->GetPositionX();
- buf << streamer.Pos->GetPositionY();
- buf << streamer.Pos->GetPositionZ();
- return buf;
-}
-
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
-{
- float x, y, z;
- buf >> x >> y >> z;
- streamer.Pos->Relocate(x, y, z);
- return buf;
-}
-
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
-{
- buf << streamer.Pos->GetPositionX();
- buf << streamer.Pos->GetPositionY();
- buf << streamer.Pos->GetPositionZ();
- buf << streamer.Pos->GetOrientation();
- return buf;
-}
-
void MovementInfo::OutDebug()
{
TC_LOG_DEBUG("misc", "MOVEMENT INFO");
@@ -1502,7 +1446,9 @@ void MovementInfo::OutDebug()
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0),
m_name(""), m_isActive(false), m_isWorldObject(isWorldObject), m_zoneScript(NULL),
m_transport(NULL), m_currMap(NULL), m_InstanceId(0),
-m_phaseMask(PHASEMASK_NORMAL), _dbPhase(0), m_notifyflags(0), m_executed_notifies(0)
+m_phaseMask(PHASEMASK_NORMAL), _dbPhase(0), m_notifyflags(0), m_executed_notifies(0),
+m_aiAnimKitId(0), m_movementAnimKitId(0), m_meleeAnimKitId(0)
+
{
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST);
m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
@@ -1823,92 +1769,6 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m
return distsq < maxdist * maxdist;
}
-void Position::RelocateOffset(const Position & offset)
-{
- m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI)));
- m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation()));
- m_positionZ = GetPositionZ() + offset.GetPositionZ();
- SetOrientation(GetOrientation() + offset.GetOrientation());
-}
-
-void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const
-{
- float dx = endPos.GetPositionX() - GetPositionX();
- float dy = endPos.GetPositionY() - GetPositionY();
-
- retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation());
- retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation());
- retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ();
- retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation());
-}
-
-Position Position::GetPositionWithOffset(Position const& offset) const
-{
- Position ret(*this);
- ret.RelocateOffset(offset);
- return ret;
-}
-
-float Position::GetAngle(const Position* obj) const
-{
- if (!obj)
- return 0;
-
- return GetAngle(obj->GetPositionX(), obj->GetPositionY());
-}
-
-// Return angle in range 0..2*pi
-float Position::GetAngle(const float x, const float y) const
-{
- float dx = x - GetPositionX();
- float dy = y - GetPositionY();
-
- float ang = std::atan2(dy, dx);
- ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang;
- return ang;
-}
-
-void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const
-{
- float dx = GetPositionX() - x;
- float dy = GetPositionY() - y;
-
- if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f)
- {
- float angle = (float)rand_norm()*static_cast<float>(2*M_PI);
- vcos = std::cos(angle);
- vsin = std::sin(angle);
- }
- else
- {
- float dist = std::sqrt((dx*dx) + (dy*dy));
- vcos = dx / dist;
- vsin = dy / dist;
- }
-}
-
-bool Position::HasInArc(float arc, const Position* obj, float border) const
-{
- // always have self in arc
- if (obj == this)
- return true;
-
- // move arc to range 0.. 2*pi
- arc = NormalizeOrientation(arc);
-
- float angle = GetAngle(obj);
- angle -= _orientation;
-
- // move angle to range -pi ... +pi
- angle = NormalizeOrientation(angle);
- if (angle > float(M_PI))
- angle -= 2.0f * float(M_PI);
-
- float lborder = -1 * (arc/border); // in range -pi..0
- float rborder = (arc/border); // in range 0..pi
- return ((angle >= lborder) && (angle <= rborder));
-}
-
bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size) const
{
if (!obj1 || !obj2)
@@ -2042,11 +1902,6 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
}
-bool Position::IsPositionValid() const
-{
- return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, _orientation);
-}
-
float WorldObject::GetGridActivationRange() const
{
if (ToPlayer())
@@ -3247,6 +3102,54 @@ ObjectGuid WorldObject::GetTransGUID() const
return ObjectGuid::Empty;
}
+void WorldObject::SetAIAnimKitId(uint16 animKitId)
+{
+ if (m_aiAnimKitId == animKitId)
+ return;
+
+ if (animKitId && !sAnimKitStore.LookupEntry(animKitId))
+ return;
+
+ m_aiAnimKitId = animKitId;
+
+ WorldPacket data(SMSG_SET_AI_ANIM_KIT, 8 + 2);
+ data << GetPackGUID();
+ data << uint16(animKitId);
+ SendMessageToSet(&data, true);
+}
+
+void WorldObject::SetMovementAnimKitId(uint16 animKitId)
+{
+ if (m_movementAnimKitId == animKitId)
+ return;
+
+ if (animKitId && !sAnimKitStore.LookupEntry(animKitId))
+ return;
+
+ m_movementAnimKitId = animKitId;
+
+ WorldPacket data(SMSG_SET_MOVEMENT_ANIM_KIT, 8 + 2);
+ data << GetPackGUID();
+ data << uint16(animKitId);
+ SendMessageToSet(&data, true);
+}
+
+void WorldObject::SetMeleeAnimKitId(uint16 animKitId)
+{
+ if (m_meleeAnimKitId == animKitId)
+ return;
+
+ if (animKitId && !sAnimKitStore.LookupEntry(animKitId))
+ return;
+
+ m_meleeAnimKitId = animKitId;
+
+ WorldPacket data(SMSG_SET_MELEE_ANIM_KIT, 8 + 2);
+ data << GetPackGUID();
+ data << uint16(animKitId);
+ SendMessageToSet(&data, true);
+}
+
void WorldObject::RebuildTerrainSwaps()
{
// Clear all terrain swaps, will be rebuilt below
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 04d5f306076..b9a6320a835 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -20,6 +20,7 @@
#define _OBJECT_H
#include "Common.h"
+#include "Position.h"
#include "UpdateMask.h"
#include "GridReference.h"
#include "ObjectDefines.h"
@@ -263,141 +264,6 @@ class Object
Object& operator=(Object const& right) = delete;
};
-struct Position
-{
- Position(float x = 0, float y = 0, float z = 0, float o = 0)
- : m_positionX(x), m_positionY(y), m_positionZ(z), _orientation(NormalizeOrientation(o)) { }
-
- Position(Position const& loc) { Relocate(loc); }
-
- struct PositionXYZStreamer
- {
- explicit PositionXYZStreamer(Position& pos) : Pos(&pos) { }
- Position* Pos;
- };
-
- struct PositionXYZOStreamer
- {
- explicit PositionXYZOStreamer(Position& pos) : Pos(&pos) { }
- Position* Pos;
- };
-
- float m_positionX;
- float m_positionY;
- float m_positionZ;
-// Better to limit access to _orientation field, to guarantee the value is normalized
-private:
- float _orientation;
-
-public:
- bool operator==(Position const &a);
-
- inline bool operator!=(Position const &a)
- {
- return !(operator==(a));
- }
-
- void Relocate(float x, float y)
- { m_positionX = x; m_positionY = y;}
- void Relocate(float x, float y, float z)
- { m_positionX = x; m_positionY = y; m_positionZ = z; }
- void Relocate(float x, float y, float z, float orientation)
- { m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation); }
- void Relocate(Position const &pos)
- { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos._orientation); }
- void Relocate(Position const* pos)
- { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->_orientation); }
- void RelocateOffset(Position const &offset);
- void SetOrientation(float orientation)
- { _orientation = NormalizeOrientation(orientation); }
-
- float GetPositionX() const { return m_positionX; }
- float GetPositionY() const { return m_positionY; }
- float GetPositionZ() const { return m_positionZ; }
- float GetOrientation() const { return _orientation; }
-
- void GetPosition(float &x, float &y) const
- { x = m_positionX; y = m_positionY; }
- void GetPosition(float &x, float &y, float &z) const
- { x = m_positionX; y = m_positionY; z = m_positionZ; }
- void GetPosition(float &x, float &y, float &z, float &o) const
- { x = m_positionX; y = m_positionY; z = m_positionZ; o = _orientation; }
-
- Position GetPosition() const
- {
- return *this;
- }
-
- Position::PositionXYZStreamer PositionXYZStream()
- {
- return PositionXYZStreamer(*this);
- }
- Position::PositionXYZOStreamer PositionXYZOStream()
- {
- return PositionXYZOStreamer(*this);
- }
-
- bool IsPositionValid() const;
-
- float GetExactDist2dSq(float x, float y) const
- { float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; }
- float GetExactDist2d(const float x, const float y) const
- { return std::sqrt(GetExactDist2dSq(x, y)); }
- float GetExactDist2dSq(Position const* pos) const
- { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; }
- float GetExactDist2d(Position const* pos) const
- { return std::sqrt(GetExactDist2dSq(pos)); }
- float GetExactDistSq(float x, float y, float z) const
- { float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; }
- float GetExactDist(float x, float y, float z) const
- { return std::sqrt(GetExactDistSq(x, y, z)); }
- float GetExactDistSq(Position const* pos) const
- { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; }
- float GetExactDist(Position const* pos) const
- { return std::sqrt(GetExactDistSq(pos)); }
-
- void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const;
- Position GetPositionWithOffset(Position const& offset) const;
-
- float GetAngle(Position const* pos) const;
- float GetAngle(float x, float y) const;
- float GetRelativeAngle(Position const* pos) const
- { return GetAngle(pos) - _orientation; }
- float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - _orientation; }
- void GetSinCos(float x, float y, float &vsin, float &vcos) const;
-
- bool IsInDist2d(float x, float y, float dist) const
- { return GetExactDist2dSq(x, y) < dist * dist; }
- bool IsInDist2d(Position const* pos, float dist) const
- { return GetExactDist2dSq(pos) < dist * dist; }
- bool IsInDist(float x, float y, float z, float dist) const
- { return GetExactDistSq(x, y, z) < dist * dist; }
- bool IsInDist(Position const* pos, float dist) const
- { return GetExactDistSq(pos) < dist * dist; }
- bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
- bool HasInLine(WorldObject const* target, float width) const;
- std::string ToString() const;
-
- // modulos a radian orientation to the range of 0..2PI
- static float NormalizeOrientation(float o)
- {
- // fmod only supports positive numbers. Thus we have
- // to emulate negative numbers
- if (o < 0)
- {
- float mod = o *-1;
- mod = std::fmod(mod, 2.0f * static_cast<float>(M_PI));
- mod = -mod + 2.0f * static_cast<float>(M_PI);
- return mod;
- }
- return std::fmod(o, 2.0f * static_cast<float>(M_PI));
- }
-};
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
-
struct MovementInfo
{
// common
@@ -783,6 +649,13 @@ class WorldObject : public Object, public WorldLocation
virtual float GetStationaryZ() const { return GetPositionZ(); }
virtual float GetStationaryO() const { return GetOrientation(); }
+ uint16 GetAIAnimKitId() const { return m_aiAnimKitId; }
+ void SetAIAnimKitId(uint16 animKitId);
+ uint16 GetMovementAnimKitId() const { return m_movementAnimKitId; }
+ void SetMovementAnimKitId(uint16 animKitId);
+ uint16 GetMeleeAnimKitId() const { return m_meleeAnimKitId; }
+ void SetMeleeAnimKitId(uint16 animKitId);
+
protected:
std::string m_name;
bool m_isActive;
@@ -823,6 +696,10 @@ class WorldObject : public Object, public WorldLocation
bool CanDetect(WorldObject const* obj, bool ignoreStealth) const;
bool CanDetectInvisibilityOf(WorldObject const* obj) const;
bool CanDetectStealthOf(WorldObject const* obj) const;
+
+ uint16 m_aiAnimKitId;
+ uint16 m_movementAnimKitId;
+ uint16 m_meleeAnimKitId;
};
namespace Trinity
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp
new file mode 100644
index 00000000000..530e51cd8f5
--- /dev/null
+++ b/src/server/game/Entities/Object/Position.cpp
@@ -0,0 +1,184 @@
+/*
+ * 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 "Position.h"
+#include "ByteBuffer.h"
+#include "G3D/g3dmath.h"
+#include "GridDefines.h"
+
+bool Position::operator==(Position const &a)
+{
+ return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
+ G3D::fuzzyEq(a.m_positionY, m_positionY) &&
+ G3D::fuzzyEq(a.m_positionZ, m_positionZ) &&
+ G3D::fuzzyEq(a.m_orientation, m_orientation));
+}
+
+void Position::RelocateOffset(const Position & offset)
+{
+ m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI)));
+ m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation()));
+ m_positionZ = GetPositionZ() + offset.GetPositionZ();
+ SetOrientation(GetOrientation() + offset.GetOrientation());
+}
+
+bool Position::IsPositionValid() const
+{
+ return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation);
+}
+
+void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const
+{
+ float dx = endPos.GetPositionX() - GetPositionX();
+ float dy = endPos.GetPositionY() - GetPositionY();
+
+ retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation());
+ retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation());
+ retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ();
+ retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation());
+}
+
+Position Position::GetPositionWithOffset(Position const& offset) const
+{
+ Position ret(*this);
+ ret.RelocateOffset(offset);
+ return ret;
+}
+
+float Position::GetAngle(const Position* obj) const
+{
+ if (!obj)
+ return 0;
+
+ return GetAngle(obj->GetPositionX(), obj->GetPositionY());
+}
+
+// Return angle in range 0..2*pi
+float Position::GetAngle(float x, float y) const
+{
+ float dx = x - GetPositionX();
+ float dy = y - GetPositionY();
+
+ float ang = std::atan2(dy, dx);
+ ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang;
+ return ang;
+}
+
+void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+
+ if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f)
+ {
+ float angle = (float)rand_norm()*static_cast<float>(2 * M_PI);
+ vcos = std::cos(angle);
+ vsin = std::sin(angle);
+ }
+ else
+ {
+ float dist = std::sqrt((dx*dx) + (dy*dy));
+ vcos = dx / dist;
+ vsin = dy / dist;
+ }
+}
+
+bool Position::HasInArc(float arc, const Position* obj, float border) const
+{
+ // always have self in arc
+ if (obj == this)
+ return true;
+
+ // move arc to range 0.. 2*pi
+ arc = NormalizeOrientation(arc);
+
+ float angle = GetAngle(obj);
+ angle -= m_orientation;
+
+ // move angle to range -pi ... +pi
+ angle = NormalizeOrientation(angle);
+ if (angle > float(M_PI))
+ angle -= 2.0f * float(M_PI);
+
+ float lborder = -1 * (arc / border); // in range -pi..0
+ float rborder = (arc / border); // in range 0..pi
+ return ((angle >= lborder) && (angle <= rborder));
+}
+
+bool Position::HasInLine(Position const* pos, float width) const
+{
+ if (!HasInArc(float(M_PI), pos))
+ return false;
+
+ float angle = GetRelativeAngle(pos);
+ return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width;
+}
+
+std::string Position::ToString() const
+{
+ std::stringstream sstr;
+ sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation;
+ return sstr.str();
+}
+
+ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer)
+{
+ buf << streamer.Pos->GetPositionX();
+ buf << streamer.Pos->GetPositionY();
+ return buf;
+}
+
+ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer)
+{
+ float x, y;
+ buf >> x >> y;
+ streamer.Pos->Relocate(x, y);
+ return buf;
+}
+
+ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
+{
+ buf << streamer.Pos->GetPositionX();
+ buf << streamer.Pos->GetPositionY();
+ buf << streamer.Pos->GetPositionZ();
+ return buf;
+}
+
+ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
+{
+ float x, y, z;
+ buf >> x >> y >> z;
+ streamer.Pos->Relocate(x, y, z);
+ return buf;
+}
+
+ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
+{
+ buf << streamer.Pos->GetPositionX();
+ buf << streamer.Pos->GetPositionY();
+ buf << streamer.Pos->GetPositionZ();
+ buf << streamer.Pos->GetOrientation();
+ return buf;
+}
+
+ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
+{
+ float x, y, z, o;
+ buf >> x >> y >> z >> o;
+ streamer.Pos->Relocate(x, y, z, o);
+ return buf;
+}
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
new file mode 100644
index 00000000000..5bd37567811
--- /dev/null
+++ b/src/server/game/Entities/Object/Position.h
@@ -0,0 +1,225 @@
+/*
+ * 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 Trinity_game_Position_h__
+#define Trinity_game_Position_h__
+
+#include "Common.h"
+
+class ByteBuffer;
+
+struct Position
+{
+ Position(float x = 0, float y = 0, float z = 0, float o = 0)
+ : m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { }
+
+ Position(Position const& loc) { Relocate(loc); }
+
+ struct PositionXYStreamer
+ {
+ explicit PositionXYStreamer(Position& pos) : Pos(&pos) { }
+ Position* Pos;
+ };
+
+ struct PositionXYZStreamer
+ {
+ explicit PositionXYZStreamer(Position& pos) : Pos(&pos) { }
+ Position* Pos;
+ };
+
+ struct PositionXYZOStreamer
+ {
+ explicit PositionXYZOStreamer(Position& pos) : Pos(&pos) { }
+ Position* Pos;
+ };
+
+ float m_positionX;
+ float m_positionY;
+ float m_positionZ;
+ // Better to limit access to _orientation field, to guarantee the value is normalized
+private:
+ float m_orientation;
+
+public:
+ bool operator==(Position const &a);
+
+ inline bool operator!=(Position const &a)
+ {
+ return !(operator==(a));
+ }
+
+ void Relocate(float x, float y)
+ {
+ m_positionX = x; m_positionY = y;
+ }
+
+ void Relocate(float x, float y, float z)
+ {
+ m_positionX = x; m_positionY = y; m_positionZ = z;
+ }
+
+ void Relocate(float x, float y, float z, float orientation)
+ {
+ m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation);
+ }
+
+ void Relocate(Position const &pos)
+ {
+ m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos.m_orientation);
+ }
+
+ void Relocate(Position const* pos)
+ {
+ m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->m_orientation);
+ }
+
+ void RelocateOffset(Position const &offset);
+
+ void SetOrientation(float orientation)
+ {
+ m_orientation = NormalizeOrientation(orientation);
+ }
+
+ float GetPositionX() const { return m_positionX; }
+ float GetPositionY() const { return m_positionY; }
+ float GetPositionZ() const { return m_positionZ; }
+ float GetOrientation() const { return m_orientation; }
+
+ void GetPosition(float &x, float &y) const
+ {
+ x = m_positionX; y = m_positionY;
+ }
+
+ void GetPosition(float &x, float &y, float &z) const
+ {
+ x = m_positionX; y = m_positionY; z = m_positionZ;
+ }
+
+ void GetPosition(float &x, float &y, float &z, float &o) const
+ {
+ x = m_positionX; y = m_positionY; z = m_positionZ; o = m_orientation;
+ }
+
+ Position GetPosition() const { return *this; }
+
+ Position::PositionXYStreamer PositionXYStream() { return PositionXYStreamer(*this); }
+ Position::PositionXYZStreamer PositionXYZStream() { return PositionXYZStreamer(*this); }
+ Position::PositionXYZOStreamer PositionXYZOStream() { return PositionXYZOStreamer(*this); }
+
+ bool IsPositionValid() const;
+
+ float GetExactDist2dSq(float x, float y) const
+ {
+ float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy;
+ }
+
+ float GetExactDist2d(const float x, const float y) const
+ {
+ return std::sqrt(GetExactDist2dSq(x, y));
+ }
+
+ float GetExactDist2dSq(Position const* pos) const
+ {
+ float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy;
+ }
+
+ float GetExactDist2d(Position const* pos) const
+ {
+ return std::sqrt(GetExactDist2dSq(pos));
+ }
+
+ float GetExactDistSq(float x, float y, float z) const
+ {
+ float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz;
+ }
+
+ float GetExactDist(float x, float y, float z) const
+ {
+ return std::sqrt(GetExactDistSq(x, y, z));
+ }
+
+ float GetExactDistSq(Position const* pos) const
+ {
+ float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz;
+ }
+
+ float GetExactDist(Position const* pos) const
+ {
+ return std::sqrt(GetExactDistSq(pos));
+ }
+
+ void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const;
+ Position GetPositionWithOffset(Position const& offset) const;
+
+ float GetAngle(Position const* pos) const;
+ float GetAngle(float x, float y) const;
+ float GetRelativeAngle(Position const* pos) const
+ {
+ return GetAngle(pos) - m_orientation;
+ }
+
+ float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; }
+ void GetSinCos(float x, float y, float &vsin, float &vcos) const;
+
+ bool IsInDist2d(float x, float y, float dist) const
+ {
+ return GetExactDist2dSq(x, y) < dist * dist;
+ }
+
+ bool IsInDist2d(Position const* pos, float dist) const
+ {
+ return GetExactDist2dSq(pos) < dist * dist;
+ }
+
+ bool IsInDist(float x, float y, float z, float dist) const
+ {
+ return GetExactDistSq(x, y, z) < dist * dist;
+ }
+
+ bool IsInDist(Position const* pos, float dist) const
+ {
+ return GetExactDistSq(pos) < dist * dist;
+ }
+
+ bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
+ bool HasInLine(Position const* pos, float width) const;
+ std::string ToString() const;
+
+ // modulos a radian orientation to the range of 0..2PI
+ static float NormalizeOrientation(float o)
+ {
+ // fmod only supports positive numbers. Thus we have
+ // to emulate negative numbers
+ if (o < 0)
+ {
+ float mod = o *-1;
+ mod = std::fmod(mod, 2.0f * static_cast<float>(M_PI));
+ mod = -mod + 2.0f * static_cast<float>(M_PI);
+ return mod;
+ }
+ return std::fmod(o, 2.0f * static_cast<float>(M_PI));
+ }
+};
+
+ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
+ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
+ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
+ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
+ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
+ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
+
+#endif // Trinity_game_Position_h__
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index f91986ddbfd..b6430a8dd26 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -39,7 +39,7 @@
Pet::Pet(Player* owner, PetType type) :
Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
- m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
+ m_petType(type), m_duration(0), m_loading(false), m_groupUpdateMask(0),
m_declinedname(NULL)
{
ASSERT(GetOwner());
@@ -208,7 +208,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
SetDisplayId(fields[3].GetUInt32());
SetNativeDisplayId(fields[3].GetUInt32());
uint32 petlevel = fields[4].GetUInt16();
- SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
SetName(fields[8].GetString());
switch (getPetType())
@@ -337,8 +337,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
owner->PetSpellInitialize();
- if (owner->GetGroup())
- owner->SetGroupUpdateFlag(GROUP_UPDATE_PET);
+ SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
// TODO: 6.x remove/update pet talents
//owner->SendTalentsInfoData(true);
@@ -785,7 +784,7 @@ bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map)
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32(sObjectMgr->GetXPForLevel(getLevel()+1)*PET_XP_FACTOR));
- SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ SetUInt64Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
if (cinfo->type == CREATURE_TYPE_BEAST)
{
@@ -1938,6 +1937,21 @@ void Pet::SetDisplayId(uint32 modelId)
if (!isControlled())
return;
+ SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
+}
+
+void Pet::SetGroupUpdateFlag(uint32 flag)
+{
+ if (GetOwner()->GetGroup())
+ {
+ m_groupUpdateMask |= flag;
+ GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
+ }
+}
+
+void Pet::ResetGroupUpdateFlag()
+{
+ m_groupUpdateMask = GROUP_UPDATE_FLAG_PET_NONE;
if (GetOwner()->GetGroup())
- GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
+ GetOwner()->RemoveGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
}
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index 494db54208d..70f14fbd7ca 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -134,9 +134,9 @@ class Pet : public Guardian
uint32 m_usedTalentCount;
- uint64 GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; }
- void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); }
- void ResetAuraUpdateMaskForRaid() { m_auraRaidUpdateMask = 0; }
+ uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
+ void SetGroupUpdateFlag(uint32 flag);
+ void ResetGroupUpdateFlag();
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
@@ -147,9 +147,9 @@ class Pet : public Guardian
protected:
PetType m_petType;
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
- uint64 m_auraRaidUpdateMask;
bool m_loading;
uint32 m_regenTimer;
+ uint32 m_groupUpdateMask;
DeclinedName *m_declinedname;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index d7e48947600..3c0510cf3c5 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -31,20 +31,22 @@
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "CharacterPackets.h"
-#include "TalentPackets.h"
#include "Chat.h"
+#include "ChatPackets.h"
#include "CombatLogPackets.h"
#include "CombatPackets.h"
#include "Common.h"
#include "ConditionMgr.h"
#include "CreatureAI.h"
-#include "DatabaseEnv.h"
#include "DB2Stores.h"
+#include "DatabaseEnv.h"
#include "DisableMgr.h"
+#include "DuelPackets.h"
#include "EquipmentSetPackets.h"
#include "Formulas.h"
#include "GameEventMgr.h"
#include "GameObjectAI.h"
+#include "Garrison.h"
#include "GossipDef.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
@@ -52,14 +54,19 @@
#include "GroupMgr.h"
#include "Guild.h"
#include "GuildMgr.h"
+#include "InstancePackets.h"
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
+#include "ItemPackets.h"
#include "LFGMgr.h"
#include "Language.h"
#include "Log.h"
+#include "LootPackets.h"
#include "MailPackets.h"
#include "MapInstanced.h"
#include "MapManager.h"
+#include "MiscPackets.h"
+#include "MovementPackets.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
@@ -67,6 +74,7 @@
#include "OutdoorPvPMgr.h"
#include "Pet.h"
#include "QuestDef.h"
+#include "QuestPackets.h"
#include "ReputationMgr.h"
#include "revision.h"
#include "SkillDiscovery.h"
@@ -77,27 +85,22 @@
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellPackets.h"
+#include "TalentPackets.h"
+#include "TradePackets.h"
#include "Transport.h"
#include "UpdateData.h"
#include "UpdateFieldFlags.h"
#include "UpdateMask.h"
#include "Util.h"
#include "Vehicle.h"
+#include "VehiclePackets.h"
#include "Weather.h"
#include "WeatherMgr.h"
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
-#include "MiscPackets.h"
-#include "ChatPackets.h"
-#include "DuelPackets.h"
-#include "MovementPackets.h"
-#include "ItemPackets.h"
-#include "QuestPackets.h"
-#include "LootPackets.h"
-#include "TradePackets.h"
-#include "VehiclePackets.h"
+#include "InstancePackets.h"
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
@@ -699,7 +702,6 @@ Player::Player(WorldSession* session): Unit(true)
// group is initialized in the reference constructor
SetGroupInvite(NULL);
m_groupUpdateMask = 0;
- m_auraRaidUpdateMask = 0;
m_bPassOnGroupLoot = false;
duel = NULL;
@@ -800,7 +802,7 @@ Player::Player(WorldSession* session): Unit(true)
m_dungeonDifficulty = DIFFICULTY_NORMAL;
m_raidDifficulty = DIFFICULTY_NORMAL_RAID;
m_legacyRaidDifficulty = DIFFICULTY_10_N;
- m_raidMapDifficulty = DIFFICULTY_NORMAL_RAID;
+ m_prevMapDifficulty = DIFFICULTY_NORMAL_RAID;
m_lastPotionId = 0;
_talentMgr = new PlayerTalentInfo();
@@ -885,7 +887,6 @@ Player::Player(WorldSession* session): Unit(true)
_maxPersonalArenaRate = 0;
memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
- memset(_CUFProfiles, 0, MAX_CUF_PROFILES * sizeof(CUFProfile*));
m_achievementMgr = new AchievementMgr<Player>(this);
m_reputationMgr = new ReputationMgr(this);
@@ -925,9 +926,6 @@ Player::~Player()
for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
delete _voidStorageItems[i];
- for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
- delete _CUFProfiles[i];
-
ClearResurrectRequestData();
sWorld->DecreasePlayerCount();
@@ -1123,10 +1121,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac
UpdateMaxHealth(); // Update max Health (for add bonus from stamina)
SetFullHealth();
if (getPowerType() == POWER_MANA)
- {
- UpdateMaxPower(POWER_MANA); // Update max Mana (for add bonus from intellect)
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
- }
if (getPowerType() == POWER_RUNIC_POWER)
{
@@ -2057,6 +2052,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// this will be used instead of the current location in SaveToDB
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
+ m_teleport_options = options;
SetFallInformation(0, z);
// code for finish transfer called in WorldSession::HandleMovementOpcodes()
@@ -2086,6 +2082,12 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!sMapMgr->CanPlayerEnter(mapid, this, false))
return false;
+ // Seamless teleport can happen only if cosmetic maps match
+ if (!oldmap ||
+ (oldmap->GetEntry()->CosmeticParentMapID != int32(mapid) && int32(GetMapId()) != mEntry->CosmeticParentMapID &&
+ !((oldmap->GetEntry()->CosmeticParentMapID != -1) ^ (oldmap->GetEntry()->CosmeticParentMapID != mEntry->CosmeticParentMapID))))
+ options &= ~TELE_TO_SEAMLESS;
+
//I think this always returns true. Correct me if I am wrong.
// If the map is not created, assume it is possible to enter it.
// It will be created in the WorldPortAck.
@@ -2148,7 +2150,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
//remove auras before removing from map...
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
- if (!GetSession()->PlayerLogout())
+ if (!GetSession()->PlayerLogout() && !(options & TELE_TO_SEAMLESS))
{
// send transfer packets
WorldPackets::Movement::TransferPending transferPending;
@@ -2168,19 +2170,25 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
oldmap->RemovePlayerFromMap(this, false);
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
+ m_teleport_options = options;
SetFallInformation(0, z);
// if the player is saved before worldportack (at logout for example)
// this will be used instead of the current location in SaveToDB
if (!GetSession()->PlayerLogout())
{
+ if (mEntry->IsDungeon())
+ {
+ WorldPackets::Instance::UpdateLastInstance updateLastInstance;
+ updateLastInstance.MapID = mapid;
+ SendDirectMessage(updateLastInstance.Write());
+ }
+
WorldPackets::Movement::NewWorld packet;
packet.MapID = mapid;
packet.Pos = m_teleport_dest;
- packet.Reason = NEW_WORLD_NORMAL;
-
+ packet.Reason = !(options & TELE_TO_SEAMLESS) ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS;
SendDirectMessage(packet.Write());
- SendSavedInstances();
}
// move packet sent by client always after far teleport
@@ -2300,17 +2308,16 @@ void Player::RemoveFromWorld()
sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
}
+ // Remove items from world before self - player must be found in Item::RemoveFromObjectUpdate
+ for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
+ if (m_items[i])
+ m_items[i]->RemoveFromWorld();
+
///- Do not add/remove the player from the object storage
///- It will crash when updating the ObjectAccessor
///- The player should only be removed when logging out
Unit::RemoveFromWorld();
- for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
- {
- if (m_items[i])
- m_items[i]->RemoveFromWorld();
- }
-
for (ItemMap::iterator iter = mMitems.begin(); iter != mMitems.end(); ++iter)
iter->second->RemoveFromWorld();
@@ -2620,7 +2627,7 @@ bool Player::CanInteractWithQuestGiver(Object* questGiver)
return false;
}
-Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
+Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint64 npcflagmask)
{
// unit checks
if (!guid)
@@ -2646,7 +2653,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
return NULL;
// appropriate npc type
- if (npcflagmask && !creature->HasFlag(UNIT_NPC_FLAGS, npcflagmask))
+ if (npcflagmask && !creature->HasFlag64(UNIT_NPC_FLAGS, npcflagmask))
return NULL;
// not allow interaction under control, but allow with own pets
@@ -4136,7 +4143,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
return TRAINER_SPELL_RED;
bool hasSpell = true;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i)
{
if (!trainer_spell->ReqAbility[i])
continue;
@@ -4159,7 +4166,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
if (getLevel() < trainer_spell->ReqLevel)
return TRAINER_SPELL_RED;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i)
{
if (!trainer_spell->ReqAbility[i])
continue;
@@ -4186,7 +4193,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
// check primary prof. limit
// first rank of primary profession spell when there are no proffesions avalible is disabled
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i)
{
if (!trainer_spell->ReqAbility[i])
continue;
@@ -4568,6 +4575,22 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
CharacterDatabase.CommitTransaction(trans);
sWorld->DeleteCharacterInfo(playerguid);
@@ -5206,7 +5229,7 @@ void Player::UpdateLocalChannels(uint32 newZone)
if (channel->Flags & CHANNEL_DBC_FLAG_CITY_ONLY)
currentNameExt = sObjectMgr->GetTrinityStringForDBCLocale(LANG_CHANNEL_CITY);
else
- currentNameExt = current_zone->ZoneName;
+ currentNameExt = current_zone->AreaName_lang;
snprintf(new_channel_name_buf, 100, channel->Name_lang, currentNameExt);
@@ -6182,6 +6205,22 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
return false;
}
break;
+ case ACTION_BUTTON_MOUNT:
+ {
+ auto mount = sDB2Manager.GetMountById(action);
+ if (!mount)
+ {
+ TC_LOG_ERROR("entities.player", "Mount action %u not added into button %u for player %s (%s): mount does not exist", action, button, GetName().c_str(), GetGUID().ToString().c_str());
+ return false;
+ }
+
+ if (!HasSpell(mount->SpellId))
+ {
+ TC_LOG_ERROR("entities.player", "Mount action %u not added into button %u for player %s (%s): Player does not know this mount", action, button, GetName().c_str(), GetGUID().ToString().c_str());
+ return false;
+ }
+ break;
+ }
case ACTION_BUTTON_C:
case ACTION_BUTTON_CMACRO:
case ACTION_BUTTON_MACRO:
@@ -6743,12 +6782,12 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
// victim_rank [1..4] HK: <dishonored rank>
// victim_rank [5..19] HK: <alliance\horde rank>
// victim_rank [0, 20+] HK: <>
- WorldPacket data(SMSG_PVP_CREDIT, 4+8+4);
- data << uint32(honor);
- data << victim_guid;
- data << uint32(victim_rank);
+ WorldPackets::Combat::PvPCredit data;
+ data.Honor = honor;
+ data.Target = victim_guid;
+ data.Rank = victim_rank;
- GetSession()->SendPacket(&data);
+ GetSession()->SendPacket(data.Write());
// add honor points
ModifyCurrency(CURRENCY_TYPE_HONOR_POINTS, int32(honor));
@@ -7345,7 +7384,11 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
// group update
if (GetGroup())
+ {
SetGroupUpdateFlag(GROUP_UPDATE_FULL);
+ if (Pet* pet = GetPet())
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
+ }
m_zoneUpdateId = newZone;
m_zoneUpdateTimer = ZONE_UPDATE_INTERVAL;
@@ -7656,23 +7699,23 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
break;
case ITEM_MOD_AGILITY: // modify agility
HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_AGILITY, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_STRENGTH: //modify strength
HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STRENGTH, float(val), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_INTELLECT: //modify intellect
HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_INTELLECT, float(val), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_SPIRIT: //modify spirit
HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_SPIRIT, float(val), apply);
+ ApplyStatBuffMod(STAT_SPIRIT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_SPIRIT, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_STAMINA: //modify stamina
HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
- ApplyStatBuffMod(STAT_STAMINA, float(val), apply);
+ ApplyStatBuffMod(STAT_STAMINA, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STAMINA, BASE_PCT_EXCLUDE_CREATE)), apply);
break;
case ITEM_MOD_DEFENSE_SKILL_RATING:
ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply);
@@ -7805,6 +7848,32 @@ void Player::_ApplyItemBonuses(Item* item, uint8 slot, bool apply)
case ITEM_MOD_ARCANE_RESISTANCE:
HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
break;
+ case ITEM_MOD_AGI_STR_INT:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
+ case ITEM_MOD_AGI_STR:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
+ case ITEM_MOD_AGI_INT:
+ HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_AGILITY, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_AGILITY, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
+ case ITEM_MOD_STR_INT:
+ HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
+ HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
+ ApplyStatBuffMod(STAT_STRENGTH, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_STRENGTH, BASE_PCT_EXCLUDE_CREATE)), apply);
+ ApplyStatBuffMod(STAT_INTELLECT, CalculatePct(val, GetModifierValue(UNIT_MOD_STAT_INTELLECT, BASE_PCT_EXCLUDE_CREATE)), apply);
+ break;
}
}
@@ -11403,10 +11472,10 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const
if (!proto)
return EQUIP_ERR_ITEM_NOT_FOUND;
- if ((proto->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE)
+ if ((proto->GetFlags2() & ITEM_FLAG2_HORDE_ONLY) && GetTeam() != HORDE)
return EQUIP_ERR_CANT_EQUIP_EVER;
- if ((proto->GetFlags2() & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE)
+ if ((proto->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY) && GetTeam() != ALLIANCE)
return EQUIP_ERR_CANT_EQUIP_EVER;
if ((proto->GetAllowableClass() & getClassMask()) == 0 || (proto->GetAllowableRace() & getRaceMask()) == 0)
@@ -11996,7 +12065,7 @@ void Player::MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool
// in case trade we already have item in other player inventory
pLastItem->SetState(in_characterInventoryDB ? ITEM_CHANGED : ITEM_NEW, this);
- if (pLastItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
+ if (pLastItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE))
AddTradeableItem(pLastItem);
}
}
@@ -12013,7 +12082,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
for (uint8 i = 0; i < MAX_BAG_SIZE; ++i)
DestroyItem(slot, i, update);
- if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
+ if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
@@ -12086,7 +12155,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
// Delete rolled money / loot from db.
// MUST be done before RemoveFromWorld() or GetTemplate() fails
if (ItemTemplate const* pTmp = pItem->GetTemplate())
- if (pTmp->GetFlags() & ITEM_PROTO_FLAG_OPENABLE)
+ if (pTmp->GetFlags() & ITEM_FLAG_OPENABLE)
pItem->ItemContainerDeleteLootMoneyAndLootItemsFromDB();
if (IsInWorld() && update)
@@ -13670,11 +13739,11 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
if (menuItemBounds.first == menuItemBounds.second && menuId == GetDefaultGossipMenuForSource(source))
menuItemBounds = sObjectMgr->GetGossipMenuItemsMapBounds(0);
- uint32 npcflags = 0;
+ uint64 npcflags = 0;
if (source->GetTypeId() == TYPEID_UNIT)
{
- npcflags = source->GetUInt32Value(UNIT_NPC_FLAGS);
+ npcflags = source->GetUInt64Value(UNIT_NPC_FLAGS);
if (showQuests && npcflags & UNIT_NPC_FLAG_QUESTGIVER)
PrepareQuestMenu(source->GetGUID());
}
@@ -14115,7 +14184,7 @@ void Player::SendPreparedQuest(ObjectGuid guid)
return;
}
- if (object->GetTypeId() != TYPEID_UNIT || object->ToCreature()->GetUInt32Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_GOSSIP)
+ if (object->GetTypeId() != TYPEID_UNIT || object->GetUInt64Value(UNIT_NPC_FLAGS) & UNIT_NPC_FLAG_GOSSIP)
{
if (quest->IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
AddQuestAndCheckCompletion(quest, object);
@@ -14636,7 +14705,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
DestroyItemCount(obj.ObjectID, obj.Amount, true);
break;
case QUEST_OBJECTIVE_CURRENCY:
- ModifyCurrency(obj.ObjectID, -int32(obj.Amount));
+ ModifyCurrency(obj.ObjectID, -int32(obj.Amount), false, true);
break;
}
}
@@ -17302,12 +17371,19 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
_LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
- m_achievementMgr->CheckAllAchievementCriteria(this);
-
_LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS));
_LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES));
+ std::unique_ptr<Garrison> garrison = Trinity::make_unique<Garrison>(this);
+ if (garrison->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS),
+ holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES)))
+ _garrison = std::move(garrison);
+
+ m_achievementMgr->CheckAllAchievementCriteria(this);
return true;
}
@@ -17321,19 +17397,19 @@ void Player::_LoadCUFProfiles(PreparedQueryResult result)
// SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?
Field* fields = result->Fetch();
- uint8 id = fields[0].GetUInt8();
- std::string name = fields[1].GetString();
- uint16 frameHeight = fields[2].GetUInt16();
- uint16 frameWidth = fields[3].GetUInt16();
- uint8 sortBy = fields[4].GetUInt8();
- uint8 healthText = fields[5].GetUInt8();
- uint32 boolOptions = fields[6].GetUInt32();
- uint8 unk146 = fields[7].GetUInt8();
- uint8 unk147 = fields[8].GetUInt8();
- uint8 unk148 = fields[9].GetUInt8();
- uint16 unk150 = fields[10].GetUInt16();
- uint16 unk152 = fields[11].GetUInt16();
- uint16 unk154 = fields[12].GetUInt16();
+ uint8 id = fields[0].GetUInt8();
+ std::string name = fields[1].GetString();
+ uint16 frameHeight = fields[2].GetUInt16();
+ uint16 frameWidth = fields[3].GetUInt16();
+ uint8 sortBy = fields[4].GetUInt8();
+ uint8 healthText = fields[5].GetUInt8();
+ uint32 boolOptions = fields[6].GetUInt32();
+ uint8 topPoint = fields[7].GetUInt8();
+ uint8 bottomPoint = fields[8].GetUInt8();
+ uint8 leftPoint = fields[9].GetUInt8();
+ uint16 topOffset = fields[10].GetUInt16();
+ uint16 bottomOffset = fields[11].GetUInt16();
+ uint16 leftOffset = fields[12].GetUInt16();
if (id > MAX_CUF_PROFILES)
{
@@ -17341,7 +17417,7 @@ void Player::_LoadCUFProfiles(PreparedQueryResult result)
continue;
}
- _CUFProfiles[id] = new CUFProfile(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, unk146, unk147, unk148, unk150, unk152, unk154);
+ _CUFProfiles[id] = Trinity::make_unique<CUFProfile>(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, topPoint, bottomPoint, leftPoint, topOffset, bottomOffset, leftOffset);
}
while (result->NextRow());
}
@@ -17759,13 +17835,13 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
remove = true;
}
// "Conjured items disappear if you are logged out for more than 15 minutes"
- else if (timeDiff > 15 * MINUTE && proto->GetFlags() & ITEM_PROTO_FLAG_CONJURED)
+ else if (timeDiff > 15 * MINUTE && proto->GetFlags() & ITEM_FLAG_CONJURED)
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s', diff: %u) has conjured item (%s, entry: %u) with expired lifetime (15 minutes). Deleting item.",
GetGUID().ToString().c_str(), GetName().c_str(), timeDiff, item->GetGUID().ToString().c_str(), item->GetEntry());
remove = true;
}
- else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
+ else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE))
{
if (item->GetPlayedTime() > (2 * HOUR))
{
@@ -17776,7 +17852,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
stmt->setUInt64(0, item->GetGUID().GetCounter());
trans->Append(stmt);
- item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
+ item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE);
}
else
{
@@ -17794,11 +17870,11 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
{
TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s') has item (%s, entry: %u) with refundable flags, but without data in item_refund_instance. Removing flag.",
GetGUID().ToString().c_str(), GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetEntry());
- item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
+ item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE);
}
}
}
- else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
+ else if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE))
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ITEM_BOP_TRADE);
stmt->setUInt64(0, item->GetGUID().GetCounter());
@@ -17820,9 +17896,9 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
}
else
{
- TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s') has item (%s, entry: %u) with ITEM_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.",
+ TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s') has item (%s, entry: %u) with ITEM_FIELD_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.",
GetGUID().ToString().c_str(), GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetEntry());
- item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE);
+ item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE);
}
}
else if (proto->GetHolidayID())
@@ -18509,12 +18585,7 @@ void Player::SetPendingBind(uint32 instanceId, uint32 bindTimer)
void Player::SendRaidInfo()
{
- uint32 counter = 0;
-
- WorldPacket data(SMSG_INSTANCE_INFO, 4);
-
- size_t p_counter = data.wpos();
- data << uint32(counter); // placeholder
+ WorldPackets::Instance::InstanceInfo instanceInfo;
time_t now = time(NULL);
@@ -18525,69 +18596,28 @@ void Player::SendRaidInfo()
if (itr->second.perm)
{
InstanceSave* save = itr->second.save;
- bool isHeroic = save->GetDifficultyID() == DIFFICULTY_10_HC || save->GetDifficultyID() == DIFFICULTY_25_HC;
- uint32 completedEncounters = 0;
- if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId()))
- if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript())
- completedEncounters = instanceScript->GetCompletedEncounterMask();
- data << uint32(save->GetMapId()); // map id
- data << uint32(save->GetDifficultyID()); // difficulty
- data << uint32(isHeroic); // heroic
- data << uint64(save->GetInstanceId()); // instance id
- data << uint8(1); // expired = 0
- data << uint8(0); // extended = 1
- data << uint32(save->GetResetTime() - now); // reset time
- data << uint32(completedEncounters); // completed encounters mask
- ++counter;
- }
- }
- }
+ WorldPackets::Instance::InstanceLockInfos lockInfos;
- data.put<uint32>(p_counter, counter);
- GetSession()->SendPacket(&data);
-}
-
-/*
-- called on every successful teleportation to a map
-*/
-void Player::SendSavedInstances()
-{
- bool hasBeenSaved = false;
- WorldPacket data;
+ lockInfos.InstanceID = save->GetInstanceId();
+ lockInfos.MapID = save->GetMapId();
+ lockInfos.DifficultyID = save->GetDifficultyID();
+ lockInfos.TimeRemaining = save->GetResetTime() - now;
- for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
- {
- for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
- {
- if (itr->second.perm) // only permanent binds are sent
- {
- hasBeenSaved = true;
- break;
- }
- }
- }
-
- //Send opcode SMSG_UPDATE_INSTANCE_OWNERSHIP. true or false means, whether you have current raid/heroic instances
- data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP, 4);
- data << uint32(hasBeenSaved);
- GetSession()->SendPacket(&data);
+ lockInfos.CompletedMask = 0;
+ if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId()))
+ if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript())
+ lockInfos.CompletedMask = instanceScript->GetCompletedEncounterMask();
- if (!hasBeenSaved)
- return;
+ lockInfos.Locked = lockInfos.TimeRemaining <= 0;
+ lockInfos.Extended = false;
- for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
- {
- for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
- {
- if (itr->second.perm)
- {
- data.Initialize(SMSG_UPDATE_LAST_INSTANCE, 4);
- data << uint32(itr->second.save->GetMapId());
- GetSession()->SendPacket(&data);
+ instanceInfo.LockList.push_back(lockInfos);
}
}
}
+
+ GetSession()->SendPacket(instanceInfo.Write());
}
/// convert the player's binds to the group
@@ -19107,6 +19137,8 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveInstanceTimeRestrictions(trans);
_SaveCurrency(trans);
_SaveCUFProfiles(trans);
+ if (_garrison)
+ _garrison->SaveToDB(trans);
// check if stats should only be saved on logout
// save stats can be out of transaction
@@ -19410,13 +19442,13 @@ void Player::_SaveCUFProfiles(SQLTransaction& trans)
stmt->setUInt16(4, _CUFProfiles[i]->FrameWidth);
stmt->setUInt8(5, _CUFProfiles[i]->SortBy);
stmt->setUInt8(6, _CUFProfiles[i]->HealthText);
- stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 27 of 32 fields used, fits in an int
- stmt->setUInt8(8, _CUFProfiles[i]->Unk146);
- stmt->setUInt8(9, _CUFProfiles[i]->Unk147);
- stmt->setUInt8(10, _CUFProfiles[i]->Unk148);
- stmt->setUInt16(11, _CUFProfiles[i]->Unk150);
- stmt->setUInt16(12, _CUFProfiles[i]->Unk152);
- stmt->setUInt16(13, _CUFProfiles[i]->Unk154);
+ stmt->setUInt32(7, _CUFProfiles[i]->BoolOptions.to_ulong()); // 25 of 32 fields used, fits in an int
+ stmt->setUInt8(8, _CUFProfiles[i]->TopPoint);
+ stmt->setUInt8(9, _CUFProfiles[i]->BottomPoint);
+ stmt->setUInt8(10, _CUFProfiles[i]->LeftPoint);
+ stmt->setUInt16(11, _CUFProfiles[i]->TopOffset);
+ stmt->setUInt16(12, _CUFProfiles[i]->BottomOffset);
+ stmt->setUInt16(13, _CUFProfiles[i]->LeftOffset);
}
trans->Append(stmt);
@@ -19958,10 +19990,10 @@ void Player::SendExplorationExperience(uint32 Area, uint32 Experience)
GetSession()->SendPacket(WorldPackets::Misc::ExplorationExperience(Experience, Area).Write());
}
-void Player::SendDungeonDifficulty()
+void Player::SendDungeonDifficulty(int32 forcedDifficulty /*= -1*/)
{
WorldPackets::Misc::DungeonDifficultySet dungeonDifficultySet;
- dungeonDifficultySet.DifficultyID = GetDungeonDifficultyID();
+ dungeonDifficultySet.DifficultyID = forcedDifficulty == -1 ? GetDungeonDifficultyID() : forcedDifficulty;
GetSession()->SendPacket(dungeonDifficultySet.Write());
}
@@ -19975,8 +20007,8 @@ void Player::SendRaidDifficulty(bool legacy, int32 forcedDifficulty /*= -1*/)
void Player::SendResetFailedNotify(uint32 /*mapid*/)
{
- WorldPacket data(SMSG_RESET_FAILED_NOTIFY, 4);
- GetSession()->SendPacket(&data);
+ WorldPackets::Instance::ResetFailedNotify data;
+ GetSession()->SendPacket(data.Write());
}
/// Reset all solo instances and optionally send a message on success for each
@@ -20037,9 +20069,9 @@ void Player::ResetInstances(uint8 method, bool isRaid, bool isLegacy)
void Player::SendResetInstanceSuccess(uint32 MapId)
{
- WorldPacket data(SMSG_INSTANCE_RESET, 4);
- data << uint32(MapId);
- GetSession()->SendPacket(&data);
+ WorldPackets::Instance::InstanceReset data;
+ data.MapID = MapId;
+ GetSession()->SendPacket(data.Write());
}
void Player::SendResetInstanceFailed(uint32 reason, uint32 MapId)
@@ -20049,10 +20081,11 @@ void Player::SendResetInstanceFailed(uint32 reason, uint32 MapId)
// 1: There are players offline in your party.
// 2>: There are players in your party attempting to zone into an instance.
*/
- WorldPacket data(SMSG_INSTANCE_RESET_FAILED, 8);
- data << uint32(reason);
- data << uint32(MapId);
- GetSession()->SendPacket(&data);
+
+ WorldPackets::Instance::InstanceResetFailed data;
+ data.MapID = MapId;
+ data.ResetFailedReason = reason;
+ GetSession()->SendPacket(data.Write());
}
/*********************************************************/
@@ -20212,7 +20245,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
GetSession()->SendPacket(&data);
if (GetGroup())
- SetGroupUpdateFlag(GROUP_UPDATE_PET);
+ SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
}
}
@@ -20251,7 +20284,7 @@ void Player::Say(std::string const& text, Language language, WorldObject const*
sScriptMgr->OnPlayerChat(this, CHAT_MSG_SAY, language, _text);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SAY, language, this, this, _text);
+ packet.Initialize(CHAT_MSG_SAY, language, this, this, _text);
SendMessageToSetInRange(packet.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
}
@@ -20261,7 +20294,7 @@ void Player::Yell(std::string const& text, Language language, WorldObject const*
sScriptMgr->OnPlayerChat(this, CHAT_MSG_YELL, language, _text);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_YELL, language, this, this, _text);
+ packet.Initialize(CHAT_MSG_YELL, language, this, this, _text);
SendMessageToSetInRange(packet.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true);
}
@@ -20271,7 +20304,7 @@ void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/
sScriptMgr->OnPlayerChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
+ packet.Initialize(CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text);
SendMessageToSetInRange(packet.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT));
}
@@ -20284,7 +20317,7 @@ void Player::WhisperAddon(std::string const& text, const std::string& prefix, Pl
return;
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_WHISPER, LANG_ADDON, this, this, text, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(CHAT_MSG_WHISPER, LANG_ADDON, this, this, text, 0, "", DEFAULT_LOCALE, prefix);
receiver->SendDirectMessage(packet.Write());
}
@@ -20301,14 +20334,14 @@ void Player::Whisper(std::string const& text, Language language, Player* target,
sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, language, _text, target);
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_WHISPER, Language(language), this, this, _text);
+ packet.Initialize(CHAT_MSG_WHISPER, Language(language), this, this, _text);
target->SendDirectMessage(packet.Write());
// rest stuff shouldn't happen in case of addon message
if (isAddonMessage)
return;
- packet.Initalize(CHAT_MSG_WHISPER_INFORM, Language(language), target, target, _text);
+ packet.Initialize(CHAT_MSG_WHISPER_INFORM, Language(language), target, target, _text);
SendDirectMessage(packet.Write());
if (!isAcceptWhispers() && !IsGameMaster() && !target->IsGameMaster())
@@ -21235,9 +21268,9 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c
if (!bStore)
AutoUnequipOffhandIfNeed();
- if (pProto->GetFlags() & ITEM_PROTO_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1)
+ if (pProto->GetFlags() & ITEM_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1)
{
- it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE);
+ it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE);
it->SetRefundRecipient(GetGUID());
it->SetPaidMoney(price);
it->SetPaidExtendedCost(crItem->ExtendedCost);
@@ -21427,7 +21460,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin
return false;
}
- if (!IsGameMaster() && ((pProto->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->GetFlags2() == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeam() == HORDE)))
+ if (!IsGameMaster() && ((pProto->GetFlags2() & ITEM_FLAG2_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->GetFlags2() == ITEM_FLAG2_ALLIANCE_ONLY && GetTeam() == HORDE)))
return false;
Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR);
@@ -22276,7 +22309,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi
m_clientGUIDs.erase(target->GetGUID());
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (%s) is out of range for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %s (%u) is out of range for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
#endif
}
}
@@ -22288,7 +22321,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi
UpdateVisibilityOf_helper(m_clientGUIDs, target, visibleNow);
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (%s) is visible now for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %s (%u) is visible now for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
#endif
}
}
@@ -22610,11 +22643,23 @@ void Player::SendInitialPacketsAfterAddToMap()
if (GetMap()->IsRaid())
{
- DifficultyEntry const* difficulty = sDifficultyStore.AssertEntry(GetMap()->GetDifficultyID());
- SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0, GetMap()->GetDifficultyID());
+ m_prevMapDifficulty = GetMap()->GetDifficultyID();
+ DifficultyEntry const* difficulty = sDifficultyStore.AssertEntry(m_prevMapDifficulty);
+ SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0, m_prevMapDifficulty);
}
else if (GetMap()->IsNonRaidDungeon())
- SendDungeonDifficulty();
+ {
+ m_prevMapDifficulty = GetMap()->GetDifficultyID();
+ SendDungeonDifficulty(m_prevMapDifficulty);
+ }
+ else if (!GetMap()->Instanceable())
+ {
+ DifficultyEntry const* difficulty = sDifficultyStore.AssertEntry(m_prevMapDifficulty);
+ SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0);
+ }
+
+ if (_garrison)
+ _garrison->SendRemoteInfo();
}
void Player::SendUpdateToOutOfRangeGroupMembers()
@@ -22625,9 +22670,8 @@ void Player::SendUpdateToOutOfRangeGroupMembers()
group->UpdatePlayerOutOfRange(this);
m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE;
- m_auraRaidUpdateMask = 0;
if (Pet* pet = GetPet())
- pet->ResetAuraUpdateMaskForRaid();
+ pet->ResetGroupUpdateFlag();
}
void Player::SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg)
@@ -22667,7 +22711,7 @@ void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint3
void Player::ApplyEquipCooldown(Item* pItem)
{
- if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_PROTO_FLAG_NO_EQUIP_COOLDOWN))
+ if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_NO_EQUIP_COOLDOWN))
return;
ItemTemplate const* proto = pItem->GetTemplate();
@@ -22686,10 +22730,10 @@ void Player::ApplyEquipCooldown(Item* pItem)
GetSpellHistory()->AddCooldown(effectData->SpellID, pItem->GetEntry(), std::chrono::seconds(30));
- WorldPacket data(SMSG_ITEM_COOLDOWN, 12);
- data << pItem->GetGUID();
- data << uint32(effectData->SpellID);
- GetSession()->SendPacket(&data);
+ WorldPackets::Item::ItemCooldown data;
+ data.ItemGuid = pItem->GetGUID();
+ data.SpellID = effectData->SpellID;
+ GetSession()->SendPacket(data.Write());
}
}
@@ -23057,7 +23101,7 @@ void Player::SetMonthlyQuestStatus(uint32 quest_id)
m_MonthlyQuestChanged = true;
}
-void Player::ResetDailyQuestStatus()
+void Player::DailyReset()
{
for (uint32 questId : GetDynamicValues(PLAYER_DYNAMIC_FIELD_DAILY_QUESTS))
if (uint32 questBit = GetQuestUniqueBitFlag(questId))
@@ -23070,6 +23114,9 @@ void Player::ResetDailyQuestStatus()
// DB data deleted in caller
m_DailyQuestChanged = false;
m_lastDailyQuestTime = 0;
+
+ if (_garrison)
+ _garrison->ResetFollowerActivationLimit();
}
void Player::ResetWeeklyQuestStatus()
@@ -23351,7 +23398,7 @@ void Player::UpdateForQuestWorldObjects()
continue;
// check if this unit requires quest specific flags
- if (!obj->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
+ if (!obj->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
continue;
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(obj->GetEntry());
@@ -24837,7 +24884,7 @@ InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limi
InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8 except_slot, uint32 limit_count) const
{
// check unique-equipped on item
- if (itemProto->GetFlags() & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED)
+ if (itemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPED)
{
// there is an equip limit on this item
if (HasItemOrGemWithIdEquipped(itemProto->GetId(), 1, except_slot))
@@ -25132,7 +25179,7 @@ bool Player::IsPetNeedBeTemporaryUnsummoned() const
bool Player::CanSeeSpellClickOn(Creature const* c) const
{
- if (!c->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
+ if (!c->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK))
return false;
SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(c->GetEntry());
@@ -25696,10 +25743,10 @@ void Player::DeleteRefundReference(ObjectGuid it)
void Player::SendRefundInfo(Item* item)
{
- // This function call unsets ITEM_FLAGS_REFUNDABLE if played time is over 2 hours.
+ // This function call unsets ITEM_FIELD_FLAG_REFUNDABLE if played time is over 2 hours.
item->UpdatePlayedTime(this);
- if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
+ if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE))
{
TC_LOG_DEBUG("entities.player.items", "Item refund: item not refundable!");
return;
@@ -25847,7 +25894,7 @@ void Player::SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece,
void Player::RefundItem(Item* item)
{
- if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
+ if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE))
{
TC_LOG_DEBUG("entities.player.items", "Item refund: item not refundable!");
return;
@@ -25935,7 +25982,7 @@ void Player::RefundItem(Item* item)
uint32 count = iece->RequiredCurrencyCount[i];
uint32 currencyid = iece->RequiredCurrency[i];
if (count && currencyid)
- ModifyCurrency(currencyid, count);
+ ModifyCurrency(currencyid, count, true, true);
}
// Grant back money
@@ -26151,6 +26198,13 @@ void Player::OnCombatExit()
m_holyPowerRegenTimerCount = 20000; // first charge of holy power decays 20 seconds after leaving combat
}
+void Player::CreateGarrison(uint32 garrSiteId)
+{
+ std::unique_ptr<Garrison> garrison(new Garrison(this));
+ if (garrison->Create(garrSiteId))
+ _garrison = std::move(garrison);
+}
+
void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply)
{
WorldPackets::Movement::MoveSetFlag packet(apply ? SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY : SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY);
@@ -26217,9 +26271,9 @@ std::string Player::GetMapAreaAndZoneString()
std::string zoneName = "Unknown";
if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId))
{
- areaName = area->ZoneName;
+ areaName = area->AreaName_lang;
if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID))
- zoneName = zone->ZoneName;
+ zoneName = zone->AreaName_lang;
}
std::ostringstream str;
@@ -26301,7 +26355,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
pet->setPowerType(POWER_MANA);
- pet->SetUInt32Value(UNIT_NPC_FLAGS, 0);
+ pet->SetUInt64Value(UNIT_NPC_FLAGS, 0);
pet->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
pet->InitStatsForLevel(getLevel());
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index d61b7845abf..5bae50edb68 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -47,6 +47,7 @@ class ReputationMgr;
class Channel;
class Creature;
class DynamicObject;
+class Garrison;
class Group;
class Guild;
class OutdoorPvP;
@@ -206,8 +207,9 @@ enum CUFBoolOptions
CUF_DISPLAY_POWER_BAR,
CUF_DISPLAY_BORDER,
CUF_USE_CLASS_COLORS,
- CUF_DISPLAY_NON_BOSS_DEBUFFS,
CUF_DISPLAY_HORIZONTAL_GROUPS,
+ CUF_DISPLAY_NON_BOSS_DEBUFFS,
+ CUF_DYNAMIC_POSITION,
CUF_LOCKED,
CUF_SHOWN,
CUF_AUTO_ACTIVATE_2_PLAYERS,
@@ -221,9 +223,6 @@ enum CUFBoolOptions
CUF_AUTO_ACTIVATE_SPEC_2,
CUF_AUTO_ACTIVATE_PVP,
CUF_AUTO_ACTIVATE_PVE,
- CUF_UNK_145,
- CUF_UNK_156,
- CUF_UNK_157,
// The unks is _LOCKED and _SHOWN and _DYNAMIC, unknown order
@@ -235,32 +234,32 @@ struct CUFProfile
{
CUFProfile() : ProfileName(), BoolOptions() // might want to change default value for options
{
- FrameHeight = 0;
- FrameWidth = 0;
- SortBy = 0;
- HealthText = 0;
- Unk146 = 0;
- Unk147 = 0;
- Unk148 = 0;
- Unk150 = 0;
- Unk152 = 0;
- Unk154 = 0;
+ FrameHeight = 0;
+ FrameWidth = 0;
+ SortBy = 0;
+ HealthText = 0;
+ TopPoint = 0;
+ BottomPoint = 0;
+ LeftPoint = 0;
+ TopOffset = 0;
+ BottomOffset = 0;
+ LeftOffset = 0;
}
CUFProfile(const std::string& name, uint16 frameHeight, uint16 frameWidth, uint8 sortBy, uint8 healthText, uint32 boolOptions,
- uint8 unk146, uint8 unk147, uint8 unk148, uint16 unk150, uint16 unk152, uint16 unk154)
+ uint8 topPoint, uint8 bottomPoint, uint8 leftPoint, uint16 topOffset, uint16 bottomOffset, uint16 leftOffset)
: ProfileName(name), BoolOptions((int)boolOptions)
{
- FrameHeight = frameHeight;
- FrameWidth = frameWidth;
- SortBy = sortBy;
- HealthText = healthText;
- Unk146 = unk146;
- Unk147 = unk147;
- Unk148 = unk148;
- Unk150 = unk150;
- Unk152 = unk152;
- Unk154 = unk154;
+ FrameHeight = frameHeight;
+ FrameWidth = frameWidth;
+ SortBy = sortBy;
+ HealthText = healthText;
+ TopPoint = topPoint;
+ BottomPoint = bottomPoint;
+ LeftPoint = leftPoint;
+ TopOffset = topOffset;
+ BottomOffset = bottomOffset;
+ LeftOffset = leftOffset;
}
std::string ProfileName;
@@ -269,15 +268,15 @@ struct CUFProfile
uint8 SortBy;
uint8 HealthText;
- // LeftAlign, TopAlight, BottomAllign (unk order)
- uint8 Unk146;
- uint8 Unk147;
- uint8 Unk148;
+ // LeftAlign, TopAlight, BottomAlign
+ uint8 TopPoint;
+ uint8 BottomPoint;
+ uint8 LeftPoint;
- // LeftOffset, TopOffset and BottomOffset (unk order)
- uint16 Unk150;
- uint16 Unk152;
- uint16 Unk154;
+ // LeftOffset, TopOffset and BottomOffset
+ uint16 TopOffset;
+ uint16 BottomOffset;
+ uint16 LeftOffset;
std::bitset<CUF_BOOL_OPTIONS_COUNT> BoolOptions;
@@ -310,6 +309,7 @@ enum ActionButtonType
ACTION_BUTTON_DROPDOWN = 0x30,
ACTION_BUTTON_MACRO = 0x40,
ACTION_BUTTON_CMACRO = ACTION_BUTTON_C | ACTION_BUTTON_MACRO,
+ ACTION_BUTTON_MOUNT = 0x60,
ACTION_BUTTON_ITEM = 0x80
};
@@ -484,9 +484,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;
@@ -918,7 +918,8 @@ enum TeleportToOptions
TELE_TO_NOT_LEAVE_TRANSPORT = 0x02,
TELE_TO_NOT_LEAVE_COMBAT = 0x04,
TELE_TO_NOT_UNSUMMON_PET = 0x08,
- TELE_TO_SPELL = 0x10
+ TELE_TO_SPELL = 0x10,
+ TELE_TO_SEAMLESS = 0x20
};
/// Type of environmental damages
@@ -983,6 +984,11 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE,
PLAYER_LOGIN_QUERY_LOAD_CURRENCY,
PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS,
+ PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES,
MAX_PLAYER_LOGIN_QUERY
};
@@ -1319,7 +1325,6 @@ private:
PlayerTalentInfo(PlayerTalentInfo const&);
};
-
class Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
@@ -1364,7 +1369,7 @@ class Player : public Unit, public GridObject<Player>
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
bool CanInteractWithQuestGiver(Object* questGiver);
- Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
+ Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint64 npcflagmask);
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, GameobjectTypes type) const;
void ToggleAFK();
@@ -1676,7 +1681,7 @@ class Player : public Unit, public GridObject<Player>
void SetWeeklyQuestStatus(uint32 quest_id);
void SetMonthlyQuestStatus(uint32 quest_id);
void SetSeasonalQuestStatus(uint32 quest_id);
- void ResetDailyQuestStatus();
+ void DailyReset();
void ResetWeeklyQuestStatus();
void ResetMonthlyQuestStatus();
void ResetSeasonalQuestStatus(uint16 event_id);
@@ -1732,8 +1737,9 @@ class Player : public Unit, public GridObject<Player>
void AddTimedQuest(uint32 questId) { m_timedquests.insert(questId); }
void RemoveTimedQuest(uint32 questId) { m_timedquests.erase(questId); }
- void SaveCUFProfile(uint8 id, CUFProfile* profile) { delete _CUFProfiles[id]; _CUFProfiles[id] = profile; } ///> Replaces a CUF profile at position 0-4
- CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id]; } ///> Retrieves a CUF profile at position 0-4
+ void SaveCUFProfile(uint8 id, std::nullptr_t) { _CUFProfiles[id] = nullptr; } ///> Empties a CUF profile at position 0-4
+ void SaveCUFProfile(uint8 id, std::unique_ptr<CUFProfile> profile) { _CUFProfiles[id] = std::move(profile); } ///> Replaces a CUF profile at position 0-4
+ CUFProfile* GetCUFProfile(uint8 id) const { return _CUFProfiles[id].get(); } ///> Retrieves a CUF profile at position 0-4
uint8 GetCUFProfilesCount() const
{
uint8 count = 0;
@@ -2051,7 +2057,6 @@ class Player : public Unit, public GridObject<Player>
uint32 GetSpellByProto(ItemTemplate* proto);
float GetHealthBonusFromStamina();
- float GetManaBonusFromIntellect();
bool UpdateStats(Stats stat) override;
bool UpdateAllStats() override;
@@ -2127,7 +2132,7 @@ class Player : public Unit, public GridObject<Player>
void SendAutoRepeatCancel(Unit* target);
void SendExplorationExperience(uint32 Area, uint32 Experience);
- void SendDungeonDifficulty();
+ void SendDungeonDifficulty(int32 forcedDifficulty = -1);
void SendRaidDifficulty(bool legacy, int32 forcedDifficulty = -1);
void ResetInstances(uint8 method, bool isRaid, bool isLegacy);
void SendResetInstanceSuccess(uint32 MapId);
@@ -2138,7 +2143,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 const* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); };// overwrite Object::SendMessageToSet
+ void SendMessageToSet(WorldPacket const* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) override; // overwrite Object::SendMessageToSetInRange
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) override;
@@ -2188,6 +2193,7 @@ class Player : public Unit, public GridObject<Player>
bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; }
bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; }
bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; }
+ bool IsBeingTeleportedSeamlessly() const { return IsBeingTeleportedFar() && m_teleport_options & TELE_TO_SEAMLESS; }
void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; }
void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; }
void ProcessDelayedOperations();
@@ -2493,7 +2499,6 @@ class Player : public Unit, public GridObject<Player>
void SetPendingBind(uint32 instanceId, uint32 bindTimer);
bool HasPendingBind() const { return _pendingBindId > 0; }
void SendRaidInfo();
- void SendSavedInstances();
static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader);
bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false);
bool CheckInstanceLoginValid();
@@ -2517,8 +2522,7 @@ class Player : public Unit, public GridObject<Player>
uint8 GetSubGroup() const { return m_group.getSubGroup(); }
uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; }
- uint64 GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; }
- void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); }
+ void RemoveGroupUpdateFlag(uint32 flag) { m_groupUpdateMask &= ~flag; }
Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup(ObjectGuid guidMember = ObjectGuid::Empty) const;
@@ -2624,6 +2628,9 @@ class Player : public Unit, public GridObject<Player>
void OnCombatExit();
+ void CreateGarrison(uint32 garrSiteId);
+ Garrison* GetGarrison() { return _garrison.get(); }
+
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
@@ -2753,7 +2760,7 @@ class Player : public Unit, public GridObject<Player>
Difficulty m_dungeonDifficulty;
Difficulty m_raidDifficulty;
Difficulty m_legacyRaidDifficulty;
- Difficulty m_raidMapDifficulty;
+ Difficulty m_prevMapDifficulty;
uint32 m_atLoginFlags;
@@ -2881,7 +2888,6 @@ class Player : public Unit, public GridObject<Player>
GroupReference m_originalGroup;
Group* m_groupInvite;
uint32 m_groupUpdateMask;
- uint64 m_auraRaidUpdateMask;
bool m_bPassOnGroupLoot;
// last used pet number (for BG's)
@@ -2904,7 +2910,7 @@ class Player : public Unit, public GridObject<Player>
uint8 m_grantableLevels;
- CUFProfile* _CUFProfiles[MAX_CUF_PROFILES];
+ std::array<std::unique_ptr<CUFProfile>, MAX_CUF_PROFILES> _CUFProfiles = {};
private:
// internal common parts for CanStore/StoreItem functions
@@ -2973,6 +2979,8 @@ class Player : public Unit, public GridObject<Player>
uint32 _activeCheats;
uint32 _maxPersonalArenaRate;
+
+ std::unique_ptr<Garrison> _garrison;
};
void AddItemsSetItem(Player* player, Item* item);
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 81497029e55..e61c23c8c37 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -36,7 +36,7 @@
Transport::Transport() : GameObject(),
_transportInfo(NULL), _isMoving(true), _pendingStop(false),
_triggeredArrivalEvent(false), _triggeredDepartureEvent(false),
- _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false)
+ _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false), _delayedTeleport(false)
{
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
}
@@ -231,6 +231,14 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
+void Transport::DelayedUpdate(uint32 /*diff*/)
+{
+ if (GetKeyFrames().size() <= 1)
+ return;
+
+ DelayedTeleportTransport();
+}
+
void Transport::AddPassenger(WorldObject* passenger)
{
if (!IsInWorld())
@@ -607,36 +615,8 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
if (oldMap->GetId() != newMapid)
{
- Map* newMap = sMapMgr->CreateBaseMap(newMapid);
+ _delayedTeleport = true;
UnloadStaticPassengers();
- GetMap()->RemoveFromMap<Transport>(this, false);
- SetMap(newMap);
-
- for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();)
- {
- WorldObject* obj = (*_passengerTeleportItr++);
-
- float destX, destY, destZ, destO;
- obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
- TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
-
- switch (obj->GetTypeId())
- {
- case TYPEID_PLAYER:
- if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
- RemovePassenger(obj);
- break;
- case TYPEID_DYNAMICOBJECT:
- obj->AddObjectToRemoveList();
- break;
- default:
- RemovePassenger(obj);
- break;
- }
- }
-
- Relocate(x, y, z, o);
- GetMap()->AddToMap<Transport>(this);
return true;
}
else
@@ -659,6 +639,48 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
}
}
+void Transport::DelayedTeleportTransport()
+{
+ if (!_delayedTeleport)
+ return;
+
+ _delayedTeleport = false;
+ Map* newMap = sMapMgr->CreateBaseMap(_nextFrame->Node->MapID);
+ GetMap()->RemoveFromMap<Transport>(this, false);
+ SetMap(newMap);
+
+ float x = _nextFrame->Node->Loc.X,
+ y = _nextFrame->Node->Loc.Y,
+ z = _nextFrame->Node->Loc.Z,
+ o =_nextFrame->InitialOrientation;
+
+ for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();)
+ {
+ WorldObject* obj = (*_passengerTeleportItr++);
+
+ float destX, destY, destZ, destO;
+ obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
+ TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
+
+ switch (obj->GetTypeId())
+ {
+ case TYPEID_PLAYER:
+ if (!obj->ToPlayer()->TeleportTo(_nextFrame->Node->MapID, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
+ RemovePassenger(obj);
+ break;
+ case TYPEID_DYNAMICOBJECT:
+ obj->AddObjectToRemoveList();
+ break;
+ default:
+ RemovePassenger(obj);
+ break;
+ }
+ }
+
+ Relocate(x, y, z, o);
+ GetMap()->AddToMap<Transport>(this);
+}
+
void Transport::UpdatePassengerPositions(PassengerSet& passengers)
{
for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr)
@@ -697,6 +719,7 @@ void Transport::UpdatePassengerPositions(PassengerSet& passengers)
break;
case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false);
+ passenger->ToGameObject()->RelocateStationaryPosition(x, y, z, o);
break;
case TYPEID_DYNAMICOBJECT:
GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index 193e32300c0..d6598a0036c 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -39,6 +39,7 @@ class Transport : public GameObject, public TransportBase
void CleanupsBeforeDelete(bool finalCleanup = true) override;
void Update(uint32 diff) override;
+ void DelayedUpdate(uint32 diff);
void BuildUpdate(UpdateDataMapType& data_map) override;
@@ -103,6 +104,7 @@ class Transport : public GameObject, public TransportBase
void MoveToNextWaypoint();
float CalculateSegmentPos(float perc);
bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o);
+ void DelayedTeleportTransport();
void UpdatePassengerPositions(PassengerSet& passengers);
void DoEventIfAny(KeyFrame const& node, bool departure);
@@ -127,6 +129,7 @@ class Transport : public GameObject, public TransportBase
PassengerSet _staticPassengers;
bool _delayedAddModel;
+ bool _delayedTeleport;
};
#endif
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index e9af35ff952..7cc25c5a5a1 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -117,7 +117,6 @@ bool Player::UpdateStats(Stats stat)
UpdateMaxHealth();
break;
case STAT_INTELLECT:
- UpdateMaxPower(POWER_MANA);
UpdateAllSpellCritChances();
UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently
break;
@@ -155,12 +154,18 @@ bool Player::UpdateStats(Stats stat)
void Player::ApplySpellPowerBonus(int32 amount, bool apply)
{
+ if (HasAuraType(SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT))
+ return;
+
apply = _ModifyUInt32(apply, m_baseSpellPower, amount);
// For speed just update for client
ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply);
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, amount, apply);
+
+ if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT))
+ UpdateAttackPowerAndDamage();
}
void Player::UpdateSpellDamageAndHealingBonus()
@@ -172,6 +177,9 @@ void Player::UpdateSpellDamageAndHealingBonus()
// Get damage bonus for all schools
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)));
+
+ if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT))
+ UpdateAttackPowerAndDamage();
}
bool Player::UpdateAllStats()
@@ -266,17 +274,6 @@ float Player::GetHealthBonusFromStamina()
return stamina * ratio;
}
-float Player::GetManaBonusFromIntellect()
-{
- // Taken from PaperDollFrame.lua - 4.3.4.15595
- float intellect = GetStat(STAT_INTELLECT);
-
- float baseInt = std::min(20.0f, intellect);
- float moreInt = intellect - baseInt;
-
- return baseInt + (moreInt * 15.0f);
-}
-
void Player::UpdateMaxHealth()
{
UnitMods unitMod = UNIT_MOD_HEALTH;
@@ -293,11 +290,9 @@ void Player::UpdateMaxPower(Powers power)
{
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power);
- float bonusPower = (power == POWER_MANA && GetCreatePowers(power) > 0) ? GetManaBonusFromIntellect() : 0;
-
float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
value *= GetModifierValue(unitMod, BASE_PCT);
- value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
+ value += GetModifierValue(unitMod, TOTAL_VALUE);
value *= GetModifierValue(unitMod, TOTAL_PCT);
SetMaxPower(power, uint32(value));
@@ -312,13 +307,17 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER;
uint16 index = UNIT_FIELD_ATTACK_POWER;
+ uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MOD_POS;
+ uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER;
if (ranged)
{
index = UNIT_FIELD_RANGED_ATTACK_POWER;
+ index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS;
+ index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
val2 = (level + std::max(GetStat(STAT_AGILITY), 0.0f)) * entry->RangedAttackPowerPerAgility;
}
- else
+ else if (!HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT))
{
float strengthValue = std::max(GetStat(STAT_STRENGTH) * entry->AttackPowerPerStrength, 0.0f);
float agilityValue = std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerAgility, 0.0f);
@@ -330,11 +329,20 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
val2 = strengthValue + agilityValue;
}
+ else
+ {
+ int32 minSpellPower = GetInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS);
+ for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
+ minSpellPower = std::min(minSpellPower, GetInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i));
+
+ val2 = CalculatePct(float(minSpellPower), GetFloatValue(PLAYER_FIELD_OVERRIDE_AP_BY_SPELL_POWER_PERCENT));
+ }
SetModifierValue(unitMod, BASE_VALUE, val2);
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
+ float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
//add dynamic flat mods
if (!ranged)
@@ -346,6 +354,8 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
}
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
+ SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MOD_POS field
+ SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
Pet* pet = GetPet(); //update pet's AP
Guardian* guardian = GetGuardianPet();
@@ -361,7 +371,9 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
UpdateDamagePhysical(BASE_ATTACK);
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
UpdateDamagePhysical(OFF_ATTACK);
- if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness
+ if (HasAuraType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER) ||
+ HasAuraType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER) ||
+ HasAuraType(SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT))
UpdateSpellDamageAndHealingBonus();
if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet
@@ -746,10 +758,6 @@ void Player::UpdateManaRegen()
// Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen
spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA);
- // SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5
- if (GetStat(STAT_INTELLECT) > 0.0f)
- spirit_regen *= std::sqrt(GetStat(STAT_INTELLECT));
-
// CombatRegen = 5% of Base Mana
float base_regen = GetCreateMana() * 0.01f + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 46ef88128cf..4c61f23126f 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -237,6 +237,7 @@ Unit::Unit(bool isWorldObject) :
for (uint8 i = 0; i < UNIT_MOD_END; ++i)
{
m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
+ m_auraModifiersGroup[i][BASE_PCT_EXCLUDE_CREATE] = 100.0f;
m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
@@ -284,10 +285,6 @@ Unit::Unit(bool isWorldObject) :
_oldFactionId = 0;
_isWalkingBeforeCharm = false;
-
- _aiAnimKitId = 0;
- _movementAnimKitId = 0;
- _meleeAnimKitId = 0;
}
////////////////////////////////////////////////////////////
@@ -4822,50 +4819,29 @@ void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVict
victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpell, amount, procAura);
}
-void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* pInfo)
+void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo* info)
{
- AuraEffect const* aura = pInfo->auraEff;
+ AuraEffect const* aura = info->auraEff;
+ WorldPackets::CombatLog::SpellPeriodicAuraLog data;
+ data.TargetGUID = GetGUID();
+ data.CasterGUID = aura->GetCasterGUID();
+ data.SpellID = aura->GetId();
- WorldPacket data(SMSG_SPELL_PERIODIC_AURA_LOG, 30);
- data << GetPackGUID();
- data << aura->GetCasterGUID().WriteAsPacked();
- data << uint32(aura->GetId()); // spellId
- data << uint32(1); // count
- data << uint32(aura->GetAuraType()); // auraId
- switch (aura->GetAuraType())
- {
- case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
- data << uint32(pInfo->damage); // damage
- data << uint32(pInfo->overDamage); // overkill?
- data << uint32(aura->GetSpellInfo()->GetSchoolMask());
- data << uint32(pInfo->absorb); // absorb
- data << uint32(pInfo->resist); // resist
- data << uint8(pInfo->critical); // new 3.1.2 critical tick
- break;
- case SPELL_AURA_PERIODIC_HEAL:
- case SPELL_AURA_OBS_MOD_HEALTH:
- data << uint32(pInfo->damage); // damage
- data << uint32(pInfo->overDamage); // overheal
- data << uint32(pInfo->absorb); // absorb
- data << uint8(pInfo->critical); // new 3.1.2 critical tick
- break;
- case SPELL_AURA_OBS_MOD_POWER:
- case SPELL_AURA_PERIODIC_ENERGIZE:
- data << uint32(aura->GetMiscValue()); // power type
- data << uint32(pInfo->damage); // damage
- break;
- case SPELL_AURA_PERIODIC_MANA_LEECH:
- data << uint32(aura->GetMiscValue()); // power type
- data << uint32(pInfo->damage); // amount
- data << float(pInfo->multiplier); // gain multiplier
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::SendPeriodicAuraLog: unknown aura %u", uint32(aura->GetAuraType()));
- return;
- }
+ /// @todo: should send more logs in one packet when multistrike
+ WorldPackets::CombatLog::SpellPeriodicAuraLog::SpellLogEffect spellLogEffect;
+ spellLogEffect.Effect = aura->GetAuraType();
+ spellLogEffect.Amount = info->damage;
+ spellLogEffect.OverHealOrKill = info->overDamage;
+ spellLogEffect.SchoolMaskOrPower = aura->GetSpellInfo()->GetSchoolMask();
+ spellLogEffect.AbsorbedOrAmplitude = info->absorb;
+ spellLogEffect.Resisted = info->resist;
+ spellLogEffect.Crit = info->critical;
+ spellLogEffect.Multistrike = false; // NYI
+ /// @todo: implement debug info
- SendMessageToSet(&data, true);
+ data.Effects.push_back(spellLogEffect);
+
+ SendMessageToSet(data.Write(), true);
}
void Unit::SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo)
@@ -6957,15 +6933,11 @@ void Unit::setPowerType(Powers new_powertype)
if (ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POWER_TYPE);
}
- else if (Pet* pet = ToCreature()->ToPet())
+ /*else if (Pet* pet = ToCreature()->ToPet()) TODO 6.x
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
+ }*/
float powerMultiplier = 1.0f;
if (!IsPet())
@@ -8157,13 +8129,14 @@ int32 Unit::HealBySpell(Unit* victim, SpellInfo const* spellInfo, uint32 addHeal
void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, Powers powerType)
{
- WorldPacket data(SMSG_SPELL_ENERGIZE_LOG, (8+8+4+4+4+1));
- data << victim->GetPackGUID();
- data << GetPackGUID();
- data << uint32(spellId);
- data << uint32(powerType);
- data << int32(damage);
- SendMessageToSet(&data, true);
+ WorldPackets::CombatLog::SpellEnergizeLog data;
+ data.CasterGUID = GetGUID();
+ data.TargetGUID = victim->GetGUID();
+ data.SpellID = spellId;
+ data.Type = powerType;
+ data.Amount = damage;
+
+ SendMessageToSet(data.Write(), true);
}
void Unit::EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType)
@@ -8547,6 +8520,13 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
{
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ float overrideSP = GetFloatValue(PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT);
+ if (overrideSP > 0.0f)
+ return int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), overrideSP) + 0.5f);
+ }
+
int32 DoneAdvertisedBenefit = 0;
AuraEffectList const& mDamageDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
@@ -9117,6 +9097,13 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u
int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
{
+ if (GetTypeId() == TYPEID_PLAYER)
+ {
+ float overrideSP = GetFloatValue(PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT);
+ if (overrideSP > 0.0f)
+ return int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), overrideSP) + 0.5f);
+ }
+
int32 advertisedBenefit = 0;
AuraEffectList const& mHealingDone = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE);
@@ -9675,9 +9662,9 @@ void Unit::Dismount()
if (Player* thisPlayer = ToPlayer())
thisPlayer->SendMovementSetCollisionHeight(thisPlayer->GetCollisionHeight(false));
- WorldPacket data(SMSG_DISMOUNT, 8);
- data << GetPackGUID();
- SendMessageToSet(&data, true);
+ WorldPackets::Misc::Dismount data;
+ data.Guid = GetGUID();
+ SendMessageToSet(data.Write(), true);
// dismount as a vehicle
if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
@@ -9763,7 +9750,7 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const
bool Unit::IsServiceProvider() const
{
- return HasFlag(UNIT_NPC_FLAGS,
+ return HasFlag64(UNIT_NPC_FLAGS,
UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER |
UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER |
UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_SPIRITHEALER |
@@ -11245,6 +11232,7 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
switch (modifierType)
{
case BASE_VALUE:
+ case BASE_PCT_EXCLUDE_CREATE:
case TOTAL_VALUE:
m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
break;
@@ -11320,7 +11308,8 @@ float Unit::GetTotalStatValue(Stats stat) const
return 0.0f;
// value = ((base_value * base_pct) + total_value) * total_pct
- float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat);
+ float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
+ value += GetCreateStat(stat);
value *= m_auraModifiersGroup[unitMod][BASE_PCT];
value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
@@ -11339,7 +11328,7 @@ float Unit::GetTotalAuraModValue(UnitMods unitMod) const
if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
return 0.0f;
- float value = m_auraModifiersGroup[unitMod][BASE_VALUE];
+ float value = CalculatePct(m_auraModifiersGroup[unitMod][BASE_VALUE], std::max(m_auraModifiersGroup[unitMod][BASE_PCT_EXCLUDE_CREATE], -100.0f));
value *= m_auraModifiersGroup[unitMod][BASE_PCT];
value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
@@ -11470,11 +11459,7 @@ void Unit::SetHealth(uint32 val)
else if (Pet* pet = ToCreature()->ToPet())
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
}
}
@@ -11495,11 +11480,7 @@ void Unit::SetMaxHealth(uint32 val)
else if (Pet* pet = ToCreature()->ToPet())
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
}
if (val < health)
@@ -11551,15 +11532,11 @@ void Unit::SetPower(Powers power, int32 val)
if (player->GetGroup())
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
}
- else if (Pet* pet = ToCreature()->ToPet())
+ /*else if (Pet* pet = ToCreature()->ToPet()) TODO 6.x
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
+ }*/
}
void Unit::SetMaxPower(Powers power, int32 val)
@@ -11577,15 +11554,11 @@ void Unit::SetMaxPower(Powers power, int32 val)
if (ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
}
- else if (Pet* pet = ToCreature()->ToPet())
+ /*else if (Pet* pet = ToCreature()->ToPet()) TODO 6.x
{
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
+ }*/
if (val < cur_power)
SetPower(power, val);
@@ -13007,23 +12980,13 @@ void Unit::UpdateAuraForGroup(uint8 slot)
if (Player* player = ToPlayer())
{
if (player->GetGroup())
- {
player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS);
- player->SetAuraUpdateMaskForRaid(slot);
- }
}
else if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsPet())
{
Pet* pet = ((Pet*)this);
if (pet->isControlled())
- {
- Unit* owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- {
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS);
- pet->SetAuraUpdateMaskForRaid(slot);
- }
- }
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS);
}
}
@@ -13401,45 +13364,6 @@ void Unit::SendDurabilityLoss(Player* receiver, uint32 percent)
receiver->GetSession()->SendPacket(packet.Write());
}
-void Unit::SetAIAnimKitId(uint16 animKitId)
-{
- if (_aiAnimKitId == animKitId)
- return;
-
- _aiAnimKitId = animKitId;
-
- WorldPacket data(SMSG_SET_AI_ANIM_KIT, 8 + 2);
- data << GetPackGUID();
- data << uint16(animKitId);
- SendMessageToSet(&data, true);
-}
-
-void Unit::SetMovementAnimKitId(uint16 animKitId)
-{
- if (_movementAnimKitId == animKitId)
- return;
-
- _movementAnimKitId = animKitId;
-
- WorldPacket data(SMSG_SET_MOVEMENT_ANIM_KIT, 8 + 2);
- data << GetPackGUID();
- data << uint16(animKitId);
- SendMessageToSet(&data, true);
-}
-
-void Unit::SetMeleeAnimKitId(uint16 animKitId)
-{
- if (_meleeAnimKitId == animKitId)
- return;
-
- _meleeAnimKitId = animKitId;
-
- WorldPacket data(SMSG_SET_MELEE_ANIM_KIT, 8 + 2);
- data << GetPackGUID();
- data << uint16(animKitId);
- SendMessageToSet(&data, true);
-}
-
void Unit::PlayOneShotAnimKit(uint16 animKitId)
{
WorldPacket data(SMSG_PLAY_ONE_SHOT_ANIM_KIT, 7+2);
@@ -14276,7 +14200,7 @@ void Unit::RemoveVehicleKit(bool onRemoveFromWorld /*= false*/)
m_updateFlag &= ~UPDATEFLAG_VEHICLE;
m_unitTypeMask &= ~UNIT_MASK_VEHICLE;
- RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK | UNIT_NPC_FLAG_PLAYER_VEHICLE);
+ RemoveFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK | UNIT_NPC_FLAG_PLAYER_VEHICLE);
}
bool Unit::IsOnVehicle(const Unit* vehicle) const
@@ -16401,7 +16325,7 @@ void Unit::Whisper(std::string const& text, Language language, Player* target, b
LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
WorldPackets::Chat::Chat packet;
- packet.Initalize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, language, this, target, text, 0, "", locale);
+ packet.Initialize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, language, this, target, text, 0, "", locale);
target->SendDirectMessage(packet.Write());
}
@@ -16448,7 +16372,7 @@ void Unit::Whisper(uint32 textId, Player* target, bool isBossWhisper /*= false*/
LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
WorldPackets::Chat::Chat packet;
- packet.Initalize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, LANG_UNIVERSAL, this, target, DB2Manager::GetBroadcastTextValue(bct, locale, getGender()), 0, "", locale);
+ packet.Initialize(isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, LANG_UNIVERSAL, this, target, DB2Manager::GetBroadcastTextValue(bct, locale, getGender()), 0, "", locale);
target->SendDirectMessage(packet.Write());
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index f92c2f278f3..538bcea9eba 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -330,13 +330,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
@@ -418,7 +411,7 @@ namespace Movement
}
typedef std::list<Unit*> UnitList;
-typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
+typedef std::list<std::pair<Aura*, uint8>> DispelChargesList;
struct SpellImmune
{
@@ -431,10 +424,11 @@ typedef std::list<SpellImmune> SpellImmuneList;
enum UnitModifierType
{
BASE_VALUE = 0,
- BASE_PCT = 1,
- TOTAL_VALUE = 2,
- TOTAL_PCT = 3,
- MODIFIER_TYPE_END = 4
+ BASE_PCT_EXCLUDE_CREATE = 1, // percent modifier affecting all stat values from auras and gear but not player base for level
+ BASE_PCT = 2,
+ TOTAL_VALUE = 3,
+ TOTAL_PCT = 4,
+ MODIFIER_TYPE_END = 5
};
enum WeaponDamageRange
@@ -443,13 +437,6 @@ enum WeaponDamageRange
MAXDAMAGE
};
-enum DamageTypeToSchool
-{
- RESISTANCE,
- DAMAGE_DEALT,
- DAMAGE_TAKEN
-};
-
enum AuraRemoveMode
{
AURA_REMOVE_NONE = 0,
@@ -729,40 +716,45 @@ enum UnitFlags2
};
/// Non Player Character flags
-enum NPCFlags : uint32
-{
- UNIT_NPC_FLAG_NONE = 0x00000000,
- UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100%
- UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // 100%
- UNIT_NPC_FLAG_UNK1 = 0x00000004,
- UNIT_NPC_FLAG_UNK2 = 0x00000008,
- UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100%
- UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100%
- UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100%
- UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100%
- UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor
- UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100%
- UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed
- UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100%
- UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100%
- UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100%
- UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed
- UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed
- UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100%
- UNIT_NPC_FLAG_BANKER = 0x00020000, // 100%
- UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions
- UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100%
- UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100%
- UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100%
- UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
- UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
- UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click)
- UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set
- UNIT_NPC_FLAG_MAILBOX = 0x04000000, // mailbox
- UNIT_NPC_FLAG_REFORGER = 0x08000000, // reforging
- UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x10000000, // transmogrification
- UNIT_NPC_FLAG_VAULTKEEPER = 0x20000000, // void storage
- UNIT_NPC_FLAG_BLACK_MARKET = 0x80000000 // black market
+enum NPCFlags : uint64
+{
+ UNIT_NPC_FLAG_NONE = 0x0000000000,
+ UNIT_NPC_FLAG_GOSSIP = 0x0000000001, // 100%
+ UNIT_NPC_FLAG_QUESTGIVER = 0x0000000002, // 100%
+ UNIT_NPC_FLAG_UNK1 = 0x0000000004,
+ UNIT_NPC_FLAG_UNK2 = 0x0000000008,
+ UNIT_NPC_FLAG_TRAINER = 0x0000000010, // 100%
+ UNIT_NPC_FLAG_TRAINER_CLASS = 0x0000000020, // 100%
+ UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x0000000040, // 100%
+ UNIT_NPC_FLAG_VENDOR = 0x0000000080, // 100%
+ UNIT_NPC_FLAG_VENDOR_AMMO = 0x0000000100, // 100%, general goods vendor
+ UNIT_NPC_FLAG_VENDOR_FOOD = 0x0000000200, // 100%
+ UNIT_NPC_FLAG_VENDOR_POISON = 0x0000000400, // guessed
+ UNIT_NPC_FLAG_VENDOR_REAGENT = 0x0000000800, // 100%
+ UNIT_NPC_FLAG_REPAIR = 0x0000001000, // 100%
+ UNIT_NPC_FLAG_FLIGHTMASTER = 0x0000002000, // 100%
+ UNIT_NPC_FLAG_SPIRITHEALER = 0x0000004000, // guessed
+ UNIT_NPC_FLAG_SPIRITGUIDE = 0x0000008000, // guessed
+ UNIT_NPC_FLAG_INNKEEPER = 0x0000010000, // 100%
+ UNIT_NPC_FLAG_BANKER = 0x0000020000, // 100%
+ UNIT_NPC_FLAG_PETITIONER = 0x0000040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions
+ UNIT_NPC_FLAG_TABARDDESIGNER = 0x0000080000, // 100%
+ UNIT_NPC_FLAG_BATTLEMASTER = 0x0000100000, // 100%
+ UNIT_NPC_FLAG_AUCTIONEER = 0x0000200000, // 100%
+ UNIT_NPC_FLAG_STABLEMASTER = 0x0000400000, // 100%
+ UNIT_NPC_FLAG_GUILD_BANKER = 0x0000800000, // cause client to send 997 opcode
+ UNIT_NPC_FLAG_SPELLCLICK = 0x0001000000, // cause client to send 1015 opcode (spell click)
+ UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x0002000000, // players with mounts that have vehicle data should have it set
+ UNIT_NPC_FLAG_MAILBOX = 0x0004000000, // mailbox
+ UNIT_NPC_FLAG_REFORGER = 0x0008000000, // reforging
+ UNIT_NPC_FLAG_TRANSMOGRIFIER = 0x0010000000, // transmogrification
+ UNIT_NPC_FLAG_VAULTKEEPER = 0x0020000000, // void storage
+ UNIT_NPC_FLAG_BLACK_MARKET = 0x0080000000, // black market
+ UNIT_NPC_FLAG_ITEM_UPGRADE_MASTER = 0x0100000000,
+ UNIT_NPC_FLAG_GARRISON_ARCHITECT = 0x0200000000,
+ UNIT_NPC_FLAG_SHIPMENT_CRAFTER = 0x2000000000,
+ UNIT_NPC_FLAG_GARRISON_MISSION_NPC = 0x4000000000,
+ UNIT_NPC_FLAG_TRADESKILL_NPC = 0x8000000000
};
enum MovementFlags
@@ -1484,12 +1476,6 @@ class Unit : public WorldObject
MountCapabilityEntry const* GetMountCapability(uint32 mountType) const;
void SendDurabilityLoss(Player* receiver, uint32 percent);
- uint16 GetAIAnimKitId() const { return _aiAnimKitId; }
- void SetAIAnimKitId(uint16 animKitId);
- uint16 GetMovementAnimKitId() const { return _movementAnimKitId; }
- void SetMovementAnimKitId(uint16 animKitId);
- uint16 GetMeleeAnimKitId() const { return _meleeAnimKitId; }
- void SetMeleeAnimKitId(uint16 animKitId);
void PlayOneShotAnimKit(uint16 animKitId);
uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
@@ -1547,22 +1533,22 @@ class Unit : public WorldObject
MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType) const;
MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const;
- bool IsVendor() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); }
- bool IsTrainer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER); }
- bool IsQuestGiver() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); }
- bool IsGossip() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); }
- bool IsTaxi() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER); }
- bool IsGuildMaster() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER); }
- bool IsBattleMaster() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER); }
- bool IsBanker() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER); }
- bool IsInnkeeper() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER); }
- bool IsSpiritHealer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER); }
- bool IsSpiritGuide() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE); }
- bool IsTabardDesigner()const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER); }
- bool IsAuctioner() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER); }
- bool IsArmorer() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR); }
+ bool IsVendor() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); }
+ bool IsTrainer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER); }
+ bool IsQuestGiver() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); }
+ bool IsGossip() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); }
+ bool IsTaxi() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER); }
+ bool IsGuildMaster() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER); }
+ bool IsBattleMaster() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER); }
+ bool IsBanker() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER); }
+ bool IsInnkeeper() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER); }
+ bool IsSpiritHealer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER); }
+ bool IsSpiritGuide() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE); }
+ bool IsTabardDesigner()const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER); }
+ bool IsAuctioner() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER); }
+ bool IsArmorer() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR); }
bool IsServiceProvider() const;
- bool IsSpiritService() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); }
+ bool IsSpiritService() const { return HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); }
bool IsCritter() const { return GetCreatureType() == CREATURE_TYPE_CRITTER; }
bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); }
@@ -1981,7 +1967,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; }
@@ -2341,10 +2327,6 @@ class Unit : public WorldObject
time_t _lastDamagedTime; // Part of Evade mechanics
- uint16 _aiAnimKitId;
- uint16 _movementAnimKitId;
- uint16 _meleeAnimKitId;
-
SpellHistory* _spellHistory;
};
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index c2f298beeb7..08efa9b9cae 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -50,9 +50,9 @@ UsableSeatNum(0), _me(unit), _vehicleInfo(vehInfo), _creatureEntry(creatureEntry
// Set or remove correct flags based on available seats. Will overwrite db data (if wrong).
if (UsableSeatNum)
- _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
+ _me->SetFlag64(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
else
- _me->RemoveFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
+ _me->RemoveFlag64(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
InitMovementInfoForBase();
}
@@ -479,7 +479,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->ID, _me->GetGUID().ToString().c_str(), (int32)seat->first);
if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum)
- _me->SetFlag(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
+ _me->SetFlag64(UNIT_NPC_FLAGS, (_me->GetTypeId() == TYPEID_PLAYER ? UNIT_NPC_FLAG_PLAYER_VEHICLE : UNIT_NPC_FLAG_SPELLCLICK));
// Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle
if (seat->second.SeatInfo->Flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE && !seat->second.Passenger.IsUnselectable)
@@ -768,9 +768,9 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
if (!Target->UsableSeatNum)
{
if (Target->GetBase()->GetTypeId() == TYPEID_PLAYER)
- Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
+ Target->GetBase()->RemoveFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
else
- Target->GetBase()->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ Target->GetBase()->RemoveFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
}
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 00d6afdd6e4..0d6b971ec15 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -715,7 +715,7 @@ void GameEventMgr::LoadFromDB()
ObjectGuid::LowType guid = fields[0].GetUInt64();
uint16 event_id = fields[1].GetUInt8();
- uint32 npcflag = fields[2].GetUInt32();
+ uint64 npcflag = fields[2].GetUInt64();
if (event_id >= mGameEvent.size())
{
@@ -916,9 +916,9 @@ void GameEventMgr::LoadFromDB()
}
}
-uint32 GameEventMgr::GetNPCFlag(Creature* cr)
+uint64 GameEventMgr::GetNPCFlag(Creature* cr)
{
- uint32 mask = 0;
+ uint64 mask = 0;
ObjectGuid::LowType guid = cr->GetSpawnId();
for (ActiveEvents::iterator e_itr = m_ActiveEvents.begin(); e_itr != m_ActiveEvents.end(); ++e_itr)
@@ -1139,7 +1139,7 @@ void GameEventMgr::UpdateEventNPCFlags(uint16 event_id)
if (CreatureTemplate const* creatureTemplate = creature->GetCreatureTemplate())
npcflag |= creatureTemplate->npcflag;
- creature->SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
+ creature->SetUInt64Value(UNIT_NPC_FLAGS, npcflag);
// reset gossip options, since the flag change might have added / removed some
//cr->ResetGossipOptions();
}
@@ -1266,8 +1266,12 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(*itr);
- for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second;)
+ {
+ Creature* creature = itr2->second;
+ ++itr2;
+ creature->AddObjectToRemoveList();
+ }
});
}
}
@@ -1292,11 +1296,16 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
{
auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(*itr);
- for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr2 = gameobjectBounds.first; itr2 != gameobjectBounds.second;)
+ {
+ GameObject* go = itr2->second;
+ ++itr2;
+ go->AddObjectToRemoveList();
+ }
});
}
}
+
if (internal_event_id < 0 || internal_event_id >= int32(mGameEventPoolIds.size()))
{
TC_LOG_ERROR("gameevent", "GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %u (size: %zu)", internal_event_id, mGameEventPoolIds.size());
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index bbddd5698d8..6f3b5c63180 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -98,7 +98,7 @@ class GameEventMgr
{
private:
GameEventMgr();
- ~GameEventMgr() { };
+ ~GameEventMgr() { }
public:
static GameEventMgr* instance()
@@ -124,7 +124,7 @@ class GameEventMgr
void StopEvent(uint16 event_id, bool overwrite = false);
void HandleQuestComplete(uint32 quest_id); // called on world event type quest completions
void HandleWorldEventGossip(Player* player, Creature* c);
- uint32 GetNPCFlag(Creature* cr);
+ uint64 GetNPCFlag(Creature* cr);
uint32 GetNpcTextId(uint32 guid);
uint16 GetEventIdForQuest(Quest const* quest) const;
private:
@@ -162,7 +162,7 @@ class GameEventMgr
typedef std::list<NPCVendorEntry> NPCVendorList;
typedef std::vector<NPCVendorList> GameEventNPCVendorMap;
typedef std::map<uint32 /*quest id*/, GameEventQuestToEventConditionNum> QuestIdToEventConditionMap;
- typedef std::pair<ObjectGuid::LowType /*guid*/, uint32 /*npcflag*/> GuidNPCFlagPair;
+ typedef std::pair<ObjectGuid::LowType /*guid*/, uint64 /*npcflag*/> GuidNPCFlagPair;
typedef std::list<GuidNPCFlagPair> NPCFlagList;
typedef std::vector<NPCFlagList> GameEventNPCFlagMap;
typedef std::vector<uint32> GameEventBitmask;
diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp
new file mode 100644
index 00000000000..749ebb562c5
--- /dev/null
+++ b/src/server/game/Garrison/Garrison.cpp
@@ -0,0 +1,690 @@
+/*
+ * 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 "Garrison.h"
+#include "GameObject.h"
+#include "GarrisonMgr.h"
+#include "MapManager.h"
+#include "ObjectMgr.h"
+
+Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followerActivationsRemainingToday(1)
+{
+}
+
+bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
+ PreparedQueryResult followers, PreparedQueryResult abilities)
+{
+ if (!garrison)
+ return false;
+
+ Field* fields = garrison->Fetch();
+ _siteLevel = sGarrSiteLevelStore.LookupEntry(fields[0].GetUInt32());
+ _followerActivationsRemainingToday = fields[1].GetUInt32();
+ if (!_siteLevel)
+ return false;
+
+ InitializePlots();
+
+ if (blueprints)
+ {
+ do
+ {
+ fields = blueprints->Fetch();
+ if (GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(fields[0].GetUInt32()))
+ _knownBuildings.insert(building->ID);
+
+ } while (blueprints->NextRow());
+ }
+
+ if (buildings)
+ {
+ do
+ {
+ fields = buildings->Fetch();
+ uint32 plotInstanceId = fields[0].GetUInt32();
+ uint32 buildingId = fields[1].GetUInt32();
+ time_t timeBuilt = time_t(fields[2].GetUInt64());
+ bool active = fields[3].GetBool();
+
+
+ Plot* plot = GetPlot(plotInstanceId);
+ if (!plot)
+ continue;
+
+ if (!sGarrBuildingStore.LookupEntry(buildingId))
+ continue;
+
+ plot->BuildingInfo.PacketInfo = boost::in_place();
+ plot->BuildingInfo.PacketInfo->GarrPlotInstanceID = plotInstanceId;
+ plot->BuildingInfo.PacketInfo->GarrBuildingID = buildingId;
+ plot->BuildingInfo.PacketInfo->TimeBuilt = timeBuilt;
+ plot->BuildingInfo.PacketInfo->Active = active;
+
+ } while (buildings->NextRow());
+ }
+
+ // 0 1 2 3 4 5 6 7 8 9
+ // SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?
+ if (followers)
+ {
+ do
+ {
+ Field* fields = followers->Fetch();
+
+ uint64 dbId = fields[0].GetUInt64();
+ uint32 followerId = fields[1].GetUInt32();
+ if (!sGarrFollowerStore.LookupEntry(followerId))
+ continue;
+
+ _followerIds.insert(followerId);
+ Follower& follower = _followers[dbId];
+ follower.PacketInfo.DbID = dbId;
+ follower.PacketInfo.GarrFollowerID = followerId;
+ follower.PacketInfo.Quality = fields[2].GetUInt32();
+ follower.PacketInfo.FollowerLevel = fields[3].GetUInt32();
+ follower.PacketInfo.ItemLevelWeapon = fields[4].GetUInt32();
+ follower.PacketInfo.ItemLevelArmor = fields[5].GetUInt32();
+ follower.PacketInfo.Xp = fields[6].GetUInt32();
+ follower.PacketInfo.CurrentBuildingID = fields[7].GetUInt32();
+ follower.PacketInfo.CurrentMissionID = fields[8].GetUInt32();
+ follower.PacketInfo.FollowerStatus = fields[9].GetUInt32();
+ if (!sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID))
+ follower.PacketInfo.CurrentBuildingID = 0;
+
+ //if (!sGarrMissionStore.LookupEntry(follower.PacketInfo.CurrentMissionID))
+ // follower.PacketInfo.CurrentMissionID = 0;
+
+ } while (followers->NextRow());
+
+ if (abilities)
+ {
+ do
+ {
+ Field* fields = abilities->Fetch();
+ uint64 dbId = fields[0].GetUInt64();
+ GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(fields[1].GetUInt32());
+
+ if (!ability)
+ continue;
+
+ auto itr = _followers.find(dbId);
+ if (itr == _followers.end())
+ continue;
+
+ itr->second.PacketInfo.AbilityID.push_back(ability);
+ } while (abilities->NextRow());
+ }
+ }
+
+ return true;
+}
+
+void Garrison::SaveToDB(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, _siteLevel->ID);
+ stmt->setUInt32(2, _followerActivationsRemainingToday);
+ trans->Append(stmt);
+
+ for (uint32 building : _knownBuildings)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, building);
+ trans->Append(stmt);
+ }
+
+ for (auto const& p : _plots)
+ {
+ Plot const& plot = p.second;
+ if (plot.BuildingInfo.PacketInfo)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, plot.BuildingInfo.PacketInfo->GarrPlotInstanceID);
+ stmt->setUInt32(2, plot.BuildingInfo.PacketInfo->GarrBuildingID);
+ stmt->setUInt64(3, plot.BuildingInfo.PacketInfo->TimeBuilt);
+ stmt->setBool(4, plot.BuildingInfo.PacketInfo->Active);
+ trans->Append(stmt);
+ }
+ }
+
+ for (auto const& p : _followers)
+ {
+ Follower const& follower = p.second;
+ uint8 index = 0;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(index++, follower.PacketInfo.DbID);
+ stmt->setUInt64(index++, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(index++, follower.PacketInfo.GarrFollowerID);
+ stmt->setUInt32(index++, follower.PacketInfo.Quality);
+ stmt->setUInt32(index++, follower.PacketInfo.FollowerLevel);
+ stmt->setUInt32(index++, follower.PacketInfo.ItemLevelWeapon);
+ stmt->setUInt32(index++, follower.PacketInfo.ItemLevelArmor);
+ stmt->setUInt32(index++, follower.PacketInfo.Xp);
+ stmt->setUInt32(index++, follower.PacketInfo.CurrentBuildingID);
+ stmt->setUInt32(index++, follower.PacketInfo.CurrentMissionID);
+ stmt->setUInt32(index++, follower.PacketInfo.FollowerStatus);
+ trans->Append(stmt);
+
+ uint8 slot = 0;
+ for (GarrAbilityEntry const* ability : follower.PacketInfo.AbilityID)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
+ stmt->setUInt64(0, follower.PacketInfo.DbID);
+ stmt->setUInt32(1, ability->ID);
+ stmt->setUInt8(2, slot++);
+ trans->Append(stmt);
+ }
+ }
+}
+
+bool Garrison::Create(uint32 garrSiteId)
+{
+ _siteLevel = sGarrisonMgr.GetGarrSiteLevelEntry(garrSiteId, 1);
+ if (!_siteLevel)
+ return false;
+
+ InitializePlots();
+
+ WorldPackets::Garrison::GarrisonCreateResult garrisonCreateResult;
+ garrisonCreateResult.GarrSiteLevelID = _siteLevel->ID;
+ _owner->SendDirectMessage(garrisonCreateResult.Write());
+ _owner->SendUpdatePhasing();
+ SendRemoteInfo();
+ return true;
+}
+
+void Garrison::InitializePlots()
+{
+ if (std::vector<GarrSiteLevelPlotInstEntry const*> const* plots = sGarrisonMgr.GetGarrPlotInstForSiteLevel(_siteLevel->ID))
+ {
+ for (std::size_t i = 0; i < plots->size(); ++i)
+ {
+ uint32 garrPlotInstanceId = plots->at(i)->GarrPlotInstanceID;
+ GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
+ GameObjectsEntry const* gameObject = sGarrisonMgr.GetPlotGameObject(_siteLevel->MapID, garrPlotInstanceId);
+ if (!plotInstance || !gameObject)
+ continue;
+
+ GarrPlotEntry const* plot = sGarrPlotStore.LookupEntry(plotInstance->GarrPlotID);
+ if (!plot)
+ continue;
+
+ Plot& plotInfo = _plots[garrPlotInstanceId];
+ plotInfo.PacketInfo.GarrPlotInstanceID = garrPlotInstanceId;
+ plotInfo.PacketInfo.PlotPos.Relocate(gameObject->Position.X, gameObject->Position.Y, gameObject->Position.Z, 2 * std::acos(gameObject->RotationW));
+ plotInfo.PacketInfo.PlotType = plot->PlotType;
+ plotInfo.EmptyGameObjectId = gameObject->ID;
+ plotInfo.GarrSiteLevelPlotInstId = plots->at(i)->ID;
+ }
+ }
+}
+
+void Garrison::Upgrade()
+{
+}
+
+void Garrison::Enter() const
+{
+ WorldLocation loc(_siteLevel->MapID);
+ loc.Relocate(_owner);
+ _owner->TeleportTo(loc, TELE_TO_SEAMLESS);
+}
+
+void Garrison::Leave() const
+{
+ if (MapEntry const* map = sMapStore.LookupEntry(_siteLevel->MapID))
+ {
+ WorldLocation loc(map->ParentMapID);
+ loc.Relocate(_owner);
+ _owner->TeleportTo(loc, TELE_TO_SEAMLESS);
+ }
+}
+
+GarrisonFactionIndex Garrison::GetFaction() const
+{
+ return _owner->GetTeam() == HORDE ? GARRISON_FACTION_INDEX_HORDE : GARRISON_FACTION_INDEX_ALLIANCE;
+}
+
+std::vector<Garrison::Plot*> Garrison::GetPlots()
+{
+ std::vector<Plot*> plots;
+ plots.reserve(_plots.size());
+ for (auto& p : _plots)
+ plots.push_back(&p.second);
+
+ return plots;
+}
+
+Garrison::Plot* Garrison::GetPlot(uint32 garrPlotInstanceId)
+{
+ auto itr = _plots.find(garrPlotInstanceId);
+ if (itr != _plots.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
+Garrison::Plot const* Garrison::GetPlot(uint32 garrPlotInstanceId) const
+{
+ auto itr = _plots.find(garrPlotInstanceId);
+ if (itr != _plots.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
+void Garrison::LearnBlueprint(uint32 garrBuildingId)
+{
+ WorldPackets::Garrison::GarrisonLearnBlueprintResult learnBlueprintResult;
+ learnBlueprintResult.BuildingID = garrBuildingId;
+ learnBlueprintResult.Result = GARRISON_SUCCESS;
+
+ if (!sGarrBuildingStore.LookupEntry(garrBuildingId))
+ learnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID;
+ else if (_knownBuildings.count(garrBuildingId))
+ learnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_KNOWN;
+ else
+ _knownBuildings.insert(garrBuildingId);
+
+ _owner->SendDirectMessage(learnBlueprintResult.Write());
+}
+
+void Garrison::UnlearnBlueprint(uint32 garrBuildingId)
+{
+ WorldPackets::Garrison::GarrisonUnlearnBlueprintResult unlearnBlueprintResult;
+ unlearnBlueprintResult.BuildingID = garrBuildingId;
+ unlearnBlueprintResult.Result = GARRISON_SUCCESS;
+
+ if (!sGarrBuildingStore.LookupEntry(garrBuildingId))
+ unlearnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID;
+ else if (!_knownBuildings.count(garrBuildingId))
+ unlearnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_NOT_KNOWN;
+ else
+ _knownBuildings.erase(garrBuildingId);
+
+ _owner->SendDirectMessage(unlearnBlueprintResult.Write());
+}
+
+void Garrison::PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId)
+{
+ WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult;
+ placeBuildingResult.Result = CheckBuildingPlacement(garrPlotInstanceId, garrBuildingId);
+ if (placeBuildingResult.Result == GARRISON_SUCCESS)
+ {
+ placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
+ placeBuildingResult.BuildingInfo.GarrBuildingID = garrBuildingId;
+ placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr);
+
+ Plot* plot = GetPlot(garrPlotInstanceId);
+ uint32 oldBuildingId = 0;
+ Map* map = FindMap();
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(garrBuildingId);
+ if (map)
+ plot->DeleteGameObject(map);
+
+ if (plot->BuildingInfo.PacketInfo)
+ {
+ oldBuildingId = plot->BuildingInfo.PacketInfo->GarrBuildingID;
+ if (sGarrBuildingStore.AssertEntry(oldBuildingId)->Type != building->Type)
+ plot->ClearBuildingInfo(_owner);
+ }
+
+ plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
+ if (map)
+ if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
+ map->AddToMap(go);
+
+ _owner->ModifyCurrency(building->CostCurrencyID, -building->CostCurrencyAmount, false, true);
+ _owner->ModifyMoney(-building->CostMoney * GOLD, false);
+
+ if (oldBuildingId)
+ {
+ WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved;
+ buildingRemoved.Result = GARRISON_SUCCESS;
+ buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
+ buildingRemoved.GarrBuildingID = oldBuildingId;
+ _owner->SendDirectMessage(buildingRemoved.Write());
+ }
+ }
+
+ _owner->SendDirectMessage(placeBuildingResult.Write());
+}
+
+void Garrison::CancelBuildingConstruction(uint32 garrPlotInstanceId)
+{
+ WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved;
+ buildingRemoved.Result = CheckBuildingRemoval(garrPlotInstanceId);
+ if (buildingRemoved.Result == GARRISON_SUCCESS)
+ {
+ Plot* plot = GetPlot(garrPlotInstanceId);
+
+ buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
+ buildingRemoved.GarrBuildingID = plot->BuildingInfo.PacketInfo->GarrBuildingID;
+
+ Map* map = FindMap();
+ if (map)
+ plot->DeleteGameObject(map);
+
+ plot->ClearBuildingInfo(_owner);
+ _owner->SendDirectMessage(buildingRemoved.Write());
+
+ GarrBuildingEntry const* constructing = sGarrBuildingStore.AssertEntry(buildingRemoved.GarrBuildingID);
+ // Refund construction/upgrade cost
+ _owner->ModifyCurrency(constructing->CostCurrencyID, constructing->CostCurrencyAmount, false, true);
+ _owner->ModifyMoney(constructing->CostMoney * GOLD, false);
+
+ if (constructing->Level > 1)
+ {
+ // Restore previous level building
+ GarrBuildingEntry const* restored = sGarrisonMgr.GetPreviousLevelBuilding(constructing->Type, constructing->Level);
+ ASSERT(restored);
+
+ WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult;
+ placeBuildingResult.Result = GARRISON_SUCCESS;
+ placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
+ placeBuildingResult.BuildingInfo.GarrBuildingID = restored->ID;
+ placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr);
+ placeBuildingResult.BuildingInfo.Active = true;
+
+ plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
+ _owner->SendDirectMessage(placeBuildingResult.Write());
+ }
+
+ if (map)
+ if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
+ map->AddToMap(go);
+ }
+ else
+ _owner->SendDirectMessage(buildingRemoved.Write());
+}
+
+void Garrison::AddFollower(uint32 garrFollowerId)
+{
+ WorldPackets::Garrison::GarrisonAddFollowerResult addFollowerResult;
+ GarrFollowerEntry const* followerEntry = sGarrFollowerStore.LookupEntry(garrFollowerId);
+ if (_followerIds.count(garrFollowerId) || !followerEntry)
+ {
+ addFollowerResult.Result = GARRISON_GENERIC_UNKNOWN_ERROR;
+ _owner->SendDirectMessage(addFollowerResult.Write());
+ return;
+ }
+
+ _followerIds.insert(garrFollowerId);
+ uint64 dbId = sGarrisonMgr.GenerateFollowerDbId();
+ Follower& follower = _followers[dbId];
+ follower.PacketInfo.DbID = dbId;
+ follower.PacketInfo.GarrFollowerID = garrFollowerId;
+ follower.PacketInfo.Quality = followerEntry->Quality; // TODO: handle magic upgrades
+ follower.PacketInfo.FollowerLevel = followerEntry->Level;
+ follower.PacketInfo.ItemLevelWeapon = followerEntry->ItemLevelWeapon;
+ follower.PacketInfo.ItemLevelArmor = followerEntry->ItemLevelArmor;
+ follower.PacketInfo.Xp = 0;
+ follower.PacketInfo.CurrentBuildingID = 0;
+ follower.PacketInfo.CurrentMissionID = 0;
+ follower.PacketInfo.AbilityID = sGarrisonMgr.RollFollowerAbilities(followerEntry, follower.PacketInfo.Quality, GetFaction(), true);
+ follower.PacketInfo.FollowerStatus = 0;
+
+ addFollowerResult.Follower = follower.PacketInfo;
+ _owner->SendDirectMessage(addFollowerResult.Write());
+
+ _owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER, follower.PacketInfo.DbID);
+}
+
+Garrison::Follower const* Garrison::GetFollower(uint64 dbId) const
+{
+ auto itr = _followers.find(dbId);
+ if (itr != _followers.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
+void Garrison::SendInfo()
+{
+ WorldPackets::Garrison::GetGarrisonInfoResult garrisonInfo;
+ garrisonInfo.GarrSiteID = _siteLevel->SiteID;
+ garrisonInfo.GarrSiteLevelID = _siteLevel->ID;
+ garrisonInfo.FactionIndex = GetFaction();
+ garrisonInfo.NumFollowerActivationsRemaining = _followerActivationsRemainingToday;
+ for (auto& p : _plots)
+ {
+ Plot& plot = p.second;
+ garrisonInfo.Plots.push_back(&plot.PacketInfo);
+ if (plot.BuildingInfo.PacketInfo)
+ garrisonInfo.Buildings.push_back(plot.BuildingInfo.PacketInfo.get_ptr());
+ }
+
+ for (auto const& p : _followers)
+ garrisonInfo.Followers.push_back(&p.second.PacketInfo);
+
+ _owner->SendDirectMessage(garrisonInfo.Write());
+}
+
+void Garrison::SendRemoteInfo() const
+{
+ MapEntry const* garrisonMap = sMapStore.LookupEntry(_siteLevel->MapID);
+ if (!garrisonMap || int32(_owner->GetMapId()) != garrisonMap->ParentMapID)
+ return;
+
+ WorldPackets::Garrison::GarrisonRemoteInfo remoteInfo;
+ remoteInfo.Sites.resize(1);
+
+ WorldPackets::Garrison::GarrisonRemoteSiteInfo& remoteSiteInfo = remoteInfo.Sites[0];
+ remoteSiteInfo.GarrSiteLevelID = _siteLevel->ID;
+ for (auto const& p : _plots)
+ if (p.second.BuildingInfo.PacketInfo)
+ remoteSiteInfo.Buildings.emplace_back(p.first, p.second.BuildingInfo.PacketInfo->GarrBuildingID);
+
+ _owner->SendDirectMessage(remoteInfo.Write());
+}
+
+void Garrison::SendBlueprintAndSpecializationData()
+{
+ WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationDataResult data;
+ data.BlueprintsKnown = &_knownBuildings;
+ _owner->SendDirectMessage(data.Write());
+}
+
+void Garrison::SendBuildingLandmarks(Player* receiver) const
+{
+ WorldPackets::Garrison::GarrisonBuildingLandmarks buildingLandmarks;
+ buildingLandmarks.Landmarks.reserve(_plots.size());
+
+ for (auto const& p : _plots)
+ {
+ Plot const& plot = p.second;
+ if (plot.BuildingInfo.PacketInfo)
+ if (uint32 garrBuildingPlotInstId = sGarrisonMgr.GetGarrBuildingPlotInst(plot.BuildingInfo.PacketInfo->GarrBuildingID, plot.GarrSiteLevelPlotInstId))
+ buildingLandmarks.Landmarks.emplace_back(garrBuildingPlotInstId, plot.PacketInfo.PlotPos);
+ }
+
+ receiver->SendDirectMessage(buildingLandmarks.Write());
+}
+
+Map* Garrison::FindMap() const
+{
+ return sMapMgr->FindMap(_siteLevel->MapID, _owner->GetGUID().GetCounter());
+}
+
+GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const
+{
+ GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
+ Plot const* plot = GetPlot(garrPlotInstanceId);
+ if (!plotInstance || !plot)
+ return GARRISON_ERROR_INVALID_PLOT;
+
+ GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(garrBuildingId);
+ if (!building)
+ return GARRISON_ERROR_INVALID_BUILDINGID;
+
+ if (!sGarrisonMgr.IsPlotMatchingBuilding(plotInstance->GarrPlotID, garrBuildingId))
+ return GARRISON_ERROR_INVALID_PLOT_BUILDING;
+
+ // Cannot place buldings of higher level than garrison level
+ if (building->Level > _siteLevel->Level)
+ return GARRISON_ERROR_INVALID_BUILDINGID;
+
+ if (building->Flags & GARRISON_BUILDING_FLAG_NEEDS_PLAN)
+ {
+ if (!_knownBuildings.count(garrBuildingId))
+ return GARRISON_ERROR_BLUEPRINT_NOT_KNOWN;
+ }
+ else // Building is built as a quest reward
+ return GARRISON_ERROR_INVALID_BUILDINGID;
+
+ // Check all plots to find if we already have this building
+ GarrBuildingEntry const* existingBuilding;
+ for (auto const& p : _plots)
+ {
+ if (p.second.BuildingInfo.PacketInfo)
+ {
+ existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID);
+ if (existingBuilding->Type == building->Type)
+ if (p.first != garrPlotInstanceId || existingBuilding->Level + 1 != building->Level) // check if its an upgrade in same plot
+ return GARRISON_ERROR_BUILDING_EXISTS;
+ }
+ }
+
+ if (!_owner->HasCurrency(building->CostCurrencyID, building->CostCurrencyAmount))
+ return GARRISON_ERROR_NOT_ENOUGH_CURRENCY;
+
+ if (!_owner->HasEnoughMoney(uint64(building->CostMoney) * GOLD))
+ return GARRISON_ERROR_NOT_ENOUGH_GOLD;
+
+ // New building cannot replace another building currently under construction
+ if (plot->BuildingInfo.PacketInfo)
+ if (!plot->BuildingInfo.PacketInfo->Active)
+ return GARRISON_ERROR_NO_BUILDING;
+
+ return GARRISON_SUCCESS;
+}
+
+GarrisonError Garrison::CheckBuildingRemoval(uint32 garrPlotInstanceId) const
+{
+ Plot const* plot = GetPlot(garrPlotInstanceId);
+ if (!plot)
+ return GARRISON_ERROR_INVALID_PLOT;
+
+ if (!plot->BuildingInfo.PacketInfo)
+ return GARRISON_ERROR_NO_BUILDING;
+
+ if (plot->BuildingInfo.CanActivate())
+ return GARRISON_ERROR_BUILDING_EXISTS;
+
+ return GARRISON_SUCCESS;
+}
+
+GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex faction)
+{
+ uint32 entry = EmptyGameObjectId;
+ if (BuildingInfo.PacketInfo)
+ {
+ GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.AssertEntry(PacketInfo.GarrPlotInstanceID);
+ GarrPlotEntry const* plot = sGarrPlotStore.AssertEntry(plotInstance->GarrPlotID);
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(BuildingInfo.PacketInfo->GarrBuildingID);
+ if (BuildingInfo.PacketInfo->Active)
+ entry = faction == GARRISON_FACTION_INDEX_HORDE ? building->HordeGameObjectID : building->AllianceGameObjectID;
+ else
+ entry = faction == GARRISON_FACTION_INDEX_HORDE ? plot->HordeConstructionGameObjectID : plot->AllianceConstructionGameObjectID;
+ }
+
+ if (!sObjectMgr->GetGameObjectTemplate(entry))
+ {
+ TC_LOG_ERROR("garrison", "Garrison attempted to spawn gameobject whose template doesn't exist (%u)", entry);
+ return nullptr;
+ }
+
+ Position const& pos = PacketInfo.PlotPos;
+ GameObject* go = new GameObject();
+ if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, 0, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(),
+ 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_ACTIVE))
+ {
+ delete go;
+ return nullptr;
+ }
+
+ BuildingInfo.Guid = go->GetGUID();
+ return go;
+}
+
+void Garrison::Plot::DeleteGameObject(Map* map)
+{
+ if (BuildingInfo.Guid.IsEmpty())
+ return;
+
+ if (GameObject* oldBuilding = map->GetGameObject(BuildingInfo.Guid))
+ oldBuilding->Delete();
+
+ BuildingInfo.Guid.Clear();
+}
+
+void Garrison::Plot::ClearBuildingInfo(Player* owner)
+{
+ WorldPackets::Garrison::GarrisonPlotPlaced plotPlaced;
+ plotPlaced.PlotInfo = &PacketInfo;
+ owner->SendDirectMessage(plotPlaced.Write());
+
+ BuildingInfo.PacketInfo = boost::none;
+}
+
+void Garrison::Plot::SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner)
+{
+ if (!BuildingInfo.PacketInfo)
+ {
+ WorldPackets::Garrison::GarrisonPlotRemoved plotRemoved;
+ plotRemoved.GarrPlotInstanceID = PacketInfo.GarrPlotInstanceID;
+ owner->SendDirectMessage(plotRemoved.Write());
+ }
+
+ BuildingInfo.PacketInfo = buildingInfo;
+}
+
+bool Garrison::Building::CanActivate() const
+{
+ if (PacketInfo)
+ {
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(PacketInfo->GarrBuildingID);
+ if (PacketInfo->TimeBuilt + building->BuildDuration <= time(nullptr))
+ return true;
+ }
+
+ return false;
+}
+
+uint32 Garrison::Follower::GetItemLevel() const
+{
+ return (PacketInfo.ItemLevelWeapon + PacketInfo.ItemLevelArmor) / 2;
+}
diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h
new file mode 100644
index 00000000000..71d67a1b6b5
--- /dev/null
+++ b/src/server/game/Garrison/Garrison.h
@@ -0,0 +1,159 @@
+/*
+ * 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 Garrison_h__
+#define Garrison_h__
+
+#include "Player.h"
+#include "GarrisonPackets.h"
+
+enum GarrisonFactionIndex
+{
+ GARRISON_FACTION_INDEX_HORDE = 0,
+ GARRISON_FACTION_INDEX_ALLIANCE = 1
+};
+
+enum GarrisonBuildingFlags
+{
+ GARRISON_BUILDING_FLAG_NEEDS_PLAN = 0x1
+};
+
+enum GarrisonFollowerFlags
+{
+ GARRISON_FOLLOWER_FLAG_UNIQUE = 0x1
+};
+
+enum GarrisonAbilityFlags
+{
+ GARRISON_ABILITY_FLAG_TRAIT = 0x01,
+ GARRISON_ABILITY_CANNOT_ROLL = 0x02,
+ GARRISON_ABILITY_HORDE_ONLY = 0x04,
+ GARRISON_ABILITY_ALLIANCE_ONLY = 0x08,
+ GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x10,
+ GARRISON_ABILITY_FLAG_EXCLUSIVE = 0x20
+};
+
+enum GarrisonError
+{
+ GARRISON_SUCCESS = 0,
+ GARRISON_ERROR_INVALID_PLOT = 1,
+ GARRISON_ERROR_INVALID_BUILDINGID = 2,
+ GARRISON_ERROR_INVALID_PLOT_BUILDING = 7,
+ GARRISON_ERROR_NO_BUILDING = 8,
+ GARRISON_ERROR_SPECIALIZATION_KNOWN = 19,
+ GARRISON_ERROR_BLUEPRINT_KNOWN = 21,
+ GARRISON_ERROR_BLUEPRINT_NOT_KNOWN = 22,
+ GARRISON_ERROR_BUILDING_EXISTS = 24,
+ GARRISON_ERROR_NOT_ENOUGH_CURRENCY = 46,
+ GARRISON_ERROR_NOT_ENOUGH_GOLD = 47,
+
+ GARRISON_GENERIC_UNKNOWN_ERROR = 255 // custom value for packets whose handlers only check if error != 0
+};
+
+enum GarrisonFollowerStatus
+{
+ FOLLOWER_STATUS_FAVORITE = 0x01,
+ FOLLOWER_STATUS_EXHAUSTED = 0x02,
+ FOLLOWER_STATUS_INACTIVE = 0x04
+};
+
+class GameObject;
+class Map;
+
+class Garrison
+{
+public:
+ struct Building
+ {
+ bool CanActivate() const;
+
+ ObjectGuid Guid;
+ Optional<WorldPackets::Garrison::GarrisonBuildingInfo> PacketInfo;
+ };
+
+ struct Plot
+ {
+ GameObject* CreateGameObject(Map* map, GarrisonFactionIndex faction);
+ void DeleteGameObject(Map* map);
+ void ClearBuildingInfo(Player* owner);
+ void SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner);
+
+ WorldPackets::Garrison::GarrisonPlotInfo PacketInfo;
+ uint32 EmptyGameObjectId = 0;
+ uint32 GarrSiteLevelPlotInstId = 0;
+ Building BuildingInfo;
+ };
+
+ struct Follower
+ {
+ uint32 GetItemLevel() const;
+
+ WorldPackets::Garrison::GarrisonFollower PacketInfo;
+ };
+
+ explicit Garrison(Player* owner);
+
+ bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
+ PreparedQueryResult followers, PreparedQueryResult abilities);
+ void SaveToDB(SQLTransaction& trans);
+
+ bool Create(uint32 garrSiteId);
+ void Upgrade();
+
+ void Enter() const;
+ void Leave() const;
+
+ GarrisonFactionIndex GetFaction() const;
+
+ // Plots
+ std::vector<Plot*> GetPlots();
+ Plot* GetPlot(uint32 garrPlotInstanceId);
+ Plot const* GetPlot(uint32 garrPlotInstanceId) const;
+
+ // Buildings
+ void LearnBlueprint(uint32 garrBuildingId);
+ void UnlearnBlueprint(uint32 garrBuildingId);
+ void PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId);
+ void CancelBuildingConstruction(uint32 garrPlotInstanceId);
+
+ // Followers
+ void AddFollower(uint32 garrFollowerId);
+ Follower const* GetFollower(uint64 dbId) const;
+
+ void SendInfo();
+ void SendRemoteInfo() const;
+ void SendBlueprintAndSpecializationData();
+ void SendBuildingLandmarks(Player* receiver) const;
+
+ void ResetFollowerActivationLimit() { _followerActivationsRemainingToday = 1; }
+
+private:
+ Map* FindMap() const;
+ void InitializePlots();
+ GarrisonError CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const;
+ GarrisonError CheckBuildingRemoval(uint32 garrPlotInstanceId) const;
+ Player* _owner;
+ GarrSiteLevelEntry const* _siteLevel;
+ uint32 _followerActivationsRemainingToday;
+
+ std::unordered_map<uint32 /*garrPlotInstanceId*/, Plot> _plots;
+ std::unordered_set<uint32 /*garrBuildingId*/> _knownBuildings;
+ std::unordered_map<uint64 /*dbId*/, Follower> _followers;
+ std::unordered_set<uint32> _followerIds;
+};
+
+#endif // Garrison_h__
diff --git a/src/server/game/Garrison/GarrisonMap.cpp b/src/server/game/Garrison/GarrisonMap.cpp
new file mode 100644
index 00000000000..b9cf63140b4
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMap.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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 "GarrisonMap.h"
+#include "Garrison.h"
+#include "ObjectAccessor.h"
+#include "ObjectGridLoader.h"
+#include "GameObject.h"
+
+class GarrisonGridLoader
+{
+public:
+ GarrisonGridLoader(NGridType* grid, GarrisonMap* map, Cell const& cell)
+ : i_cell(cell), i_grid(grid), i_map(map), i_garrison(map->GetGarrison()), i_gameObjects(0), i_creatures(0)
+ { }
+
+ void Visit(GameObjectMapType& m);
+ void Visit(CreatureMapType& m);
+
+ void LoadN();
+
+ template<class T> static void SetObjectCell(T* obj, CellCoord const& cellCoord);
+ template<class T> void Visit(GridRefManager<T>& /*m*/) { }
+
+private:
+ Cell i_cell;
+ NGridType* i_grid;
+ GarrisonMap* i_map;
+ Garrison* i_garrison;
+ uint32 i_gameObjects;
+ uint32 i_creatures;
+};
+
+void GarrisonGridLoader::LoadN()
+{
+ if (i_garrison)
+ {
+ i_cell.data.Part.cell_y = 0;
+ for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x)
+ {
+ i_cell.data.Part.cell_x = x;
+ for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y)
+ {
+ i_cell.data.Part.cell_y = y;
+
+ //Load creatures and game objects
+ TypeContainerVisitor<GarrisonGridLoader, GridTypeMapContainer> visitor(*this);
+ i_grid->VisitGrid(x, y, visitor);
+ }
+ }
+ }
+
+ TC_LOG_DEBUG("maps", "%u GameObjects and %u Creatures loaded for grid %u on map %u", i_gameObjects, i_creatures, i_grid->GetGridId(), i_map->GetId());
+}
+
+void GarrisonGridLoader::Visit(GameObjectMapType& m)
+{
+ std::vector<Garrison::Plot*> plots = i_garrison->GetPlots();
+ if (!plots.empty())
+ {
+ CellCoord cellCoord = i_cell.GetCellCoord();
+ for (Garrison::Plot* plot : plots)
+ {
+ Position const& spawn = plot->PacketInfo.PlotPos;
+ if (cellCoord != Trinity::ComputeCellCoord(spawn.GetPositionX(), spawn.GetPositionY()))
+ continue;
+
+ GameObject* go = plot->CreateGameObject(i_map, i_garrison->GetFaction());
+ if (!go)
+ continue;
+
+ go->AddToGrid(m);
+ ObjectGridLoader::SetObjectCell(go, cellCoord);
+ go->AddToWorld();
+ ++i_gameObjects;
+ }
+ }
+}
+
+void GarrisonGridLoader::Visit(CreatureMapType& /*m*/)
+{
+
+}
+
+GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, Map* parent, ObjectGuid const& owner)
+ : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner), _loadingPlayer(nullptr)
+{
+ GarrisonMap::InitVisibilityDistance();
+}
+
+void GarrisonMap::LoadGridObjects(NGridType* grid, Cell const& cell)
+{
+ Map::LoadGridObjects(grid, cell);
+
+ GarrisonGridLoader loader(grid, this, cell);
+ loader.LoadN();
+}
+
+Garrison* GarrisonMap::GetGarrison()
+{
+ if (_loadingPlayer)
+ return _loadingPlayer->GetGarrison();
+
+ if (Player* owner = ObjectAccessor::FindConnectedPlayer(_owner))
+ return owner->GetGarrison();
+
+ return nullptr;
+}
+
+void GarrisonMap::InitVisibilityDistance()
+{
+ //init visibility distance for instances
+ m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas();
+ m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas();
+}
+
+bool GarrisonMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
+{
+ if (player->GetGUID() == _owner)
+ _loadingPlayer = player;
+
+ bool result = Map::AddPlayerToMap(player, initPlayer);
+
+ if (player->GetGUID() == _owner)
+ _loadingPlayer = nullptr;
+
+ return result;
+}
diff --git a/src/server/game/Garrison/GarrisonMap.h b/src/server/game/Garrison/GarrisonMap.h
new file mode 100644
index 00000000000..5f5c9b134b7
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMap.h
@@ -0,0 +1,43 @@
+/*
+ * 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 GarrisonMap_h__
+#define GarrisonMap_h__
+
+#include "Map.h"
+
+class Garrison;
+class Player;
+
+class GarrisonMap : public Map
+{
+public:
+ GarrisonMap(uint32 id, time_t, uint32 instanceId, Map* parent, ObjectGuid const& owner);
+
+ void LoadGridObjects(NGridType* grid, Cell const& cell) override;
+ Garrison* GetGarrison();
+
+ void InitVisibilityDistance() override;
+
+ bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
+
+private:
+ ObjectGuid _owner;
+ Player* _loadingPlayer; ///< @workaround Player is not registered in ObjectAccessor during login
+};
+
+#endif // GarrisonMap_h__
diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp
new file mode 100644
index 00000000000..f95acef952c
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMgr.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 "GarrisonMgr.h"
+#include "Containers.h"
+#include "DatabaseEnv.h"
+#include "Garrison.h"
+#include "ObjectDefines.h"
+#include "World.h"
+
+void GarrisonMgr::Initialize()
+{
+ for (GarrSiteLevelPlotInstEntry const* plotInstance : sGarrSiteLevelPlotInstStore)
+ _garrisonPlotInstBySiteLevel[plotInstance->GarrSiteLevelID].push_back(plotInstance);
+
+ for (GameObjectsEntry const* gameObject : sGameObjectsStore)
+ if (gameObject->Type == GAMEOBJECT_TYPE_GARRISON_PLOT)
+ _garrisonPlots[gameObject->MapID][gameObject->Data[0]] = gameObject;
+
+ for (GarrPlotBuildingEntry const* plotBuilding : sGarrPlotBuildingStore)
+ _garrisonBuildingsByPlot[plotBuilding->GarrPlotID].insert(plotBuilding->GarrBuildingID);
+
+ for (GarrBuildingPlotInstEntry const* buildingPlotInst : sGarrBuildingPlotInstStore)
+ _garrisonBuildingPlotInstances[MAKE_PAIR64(buildingPlotInst->GarrBuildingID, buildingPlotInst->GarrSiteLevelPlotInstID)] = buildingPlotInst->ID;
+
+ for (GarrBuildingEntry const* building : sGarrBuildingStore)
+ _garrisonBuildingsByType[building->Type].push_back(building);
+
+ for (GarrFollowerXAbilityEntry const* followerAbility : sGarrFollowerXAbilityStore)
+ {
+ if (GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(followerAbility->GarrAbilityID))
+ {
+ if (!(ability->Flags & GARRISON_ABILITY_CANNOT_ROLL) && ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
+ _garrisonFollowerRandomTraits.insert(ability);
+
+ if (followerAbility->FactionIndex < 2)
+ {
+ if (ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
+ _garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Traits.insert(ability);
+ else
+ _garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Counters.insert(ability);
+ }
+ }
+ }
+
+ InitializeDbIdSequences();
+ LoadFollowerClassSpecAbilities();
+}
+
+GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
+{
+ for (GarrSiteLevelEntry const* garrSiteLevel : sGarrSiteLevelStore)
+ if (garrSiteLevel->SiteID == garrSiteId && garrSiteLevel->Level == level)
+ return garrSiteLevel;
+
+ return nullptr;
+}
+
+std::vector<GarrSiteLevelPlotInstEntry const*> const* GarrisonMgr::GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const
+{
+ auto itr = _garrisonPlotInstBySiteLevel.find(garrSiteLevelId);
+ if (itr != _garrisonPlotInstBySiteLevel.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
+GameObjectsEntry const* GarrisonMgr::GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const
+{
+ auto mapItr = _garrisonPlots.find(mapId);
+ if (mapItr != _garrisonPlots.end())
+ {
+ auto plotItr = mapItr->second.find(garrPlotInstanceId);
+ if (plotItr != mapItr->second.end())
+ return plotItr->second;
+ }
+
+ return nullptr;
+}
+
+bool GarrisonMgr::IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const
+{
+ auto plotItr = _garrisonBuildingsByPlot.find(garrPlotId);
+ if (plotItr != _garrisonBuildingsByPlot.end())
+ return plotItr->second.count(garrBuildingId) > 0;
+
+ return false;
+}
+
+uint32 GarrisonMgr::GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const
+{
+ auto itr = _garrisonBuildingPlotInstances.find(MAKE_PAIR64(garrBuildingId, garrSiteLevelPlotInstId));
+ if (itr != _garrisonBuildingPlotInstances.end())
+ return itr->second;
+
+ return 0;
+}
+
+GarrBuildingEntry const* GarrisonMgr::GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const
+{
+ auto itr = _garrisonBuildingsByType.find(buildingType);
+ if (itr != _garrisonBuildingsByType.end())
+ for (GarrBuildingEntry const* building : itr->second)
+ if (building->Level == currentLevel - 1)
+ return building;
+
+ return nullptr;
+}
+
+uint64 GarrisonMgr::GenerateFollowerDbId()
+{
+ if (_followerDbIdGenerator >= std::numeric_limits<uint64>::max())
+ {
+ TC_LOG_ERROR("misc", "Garrison follower db id overflow! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
+ }
+
+ return _followerDbIdGenerator++;
+}
+
+uint32 const AbilitiesForQuality[][2] =
+{
+ // Counters, Traits
+ { 0, 0 },
+ { 1, 0 },
+ { 1, 1 }, // Uncommon
+ { 1, 2 }, // Rare
+ { 2, 3 }, // Epic
+ { 2, 3 } // Legendary
+};
+
+std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
+{
+ ASSERT(faction < 2);
+
+ bool hasForcedExclusiveTrait = false;
+ std::list<GarrAbilityEntry const*> result;
+ int32 slots[2] = { AbilitiesForQuality[quality][0], AbilitiesForQuality[quality][1] };
+
+ GarrAbilities const* abilities = nullptr;
+ auto itr = _garrisonFollowerAbilities[faction].find(follower->ID);
+ if (itr != _garrisonFollowerAbilities[faction].end())
+ abilities = &itr->second;
+
+ std::list<GarrAbilityEntry const*> abilityList, forcedAbilities, traitList, forcedTraits;
+ if (abilities)
+ {
+ for (GarrAbilityEntry const* ability : abilities->Counters)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
+ forcedAbilities.push_back(ability);
+ else
+ abilityList.push_back(ability);
+ }
+
+ for (GarrAbilityEntry const* ability : abilities->Traits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
+ forcedTraits.push_back(ability);
+ else
+ traitList.push_back(ability);
+ }
+ }
+
+ Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
+ Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
+
+ // Add abilities specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation
+ if (initial)
+ {
+ forcedAbilities.splice(forcedAbilities.end(), abilityList);
+ forcedTraits.splice(forcedTraits.end(), traitList);
+ }
+
+ forcedAbilities.sort();
+ abilityList.sort();
+ forcedTraits.sort();
+ traitList.sort();
+
+ // check if we have a trait from exclusive category
+ for (GarrAbilityEntry const* ability : forcedTraits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ {
+ hasForcedExclusiveTrait = true;
+ break;
+ }
+ }
+
+ if (slots[0] > forcedAbilities.size() + abilityList.size())
+ {
+ std::list<GarrAbilityEntry const*> classSpecAbilities = GetClassSpecAbilities(follower, faction);
+ std::list<GarrAbilityEntry const*> classSpecAbilitiesTemp, classSpecAbilitiesTemp2;
+ classSpecAbilitiesTemp2.swap(abilityList);
+ std::set_difference(classSpecAbilities.begin(), classSpecAbilities.end(), forcedAbilities.begin(), forcedAbilities.end(), std::back_inserter(classSpecAbilitiesTemp));
+ std::set_union(classSpecAbilitiesTemp.begin(), classSpecAbilitiesTemp.end(), classSpecAbilitiesTemp2.begin(), classSpecAbilitiesTemp2.end(), std::back_inserter(abilityList));
+
+ Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
+ }
+
+ if (slots[1] > forcedTraits.size() + traitList.size())
+ {
+ std::list<GarrAbilityEntry const*> genericTraits, genericTraitsTemp;
+ for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ // forced exclusive trait exists, skip other ones entirely
+ if (hasForcedExclusiveTrait && ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ continue;
+
+ genericTraitsTemp.push_back(ability);
+ }
+
+ std::set_difference(genericTraitsTemp.begin(), genericTraitsTemp.end(), forcedTraits.begin(), forcedTraits.end(), std::back_inserter(genericTraits));
+ genericTraits.splice(genericTraits.begin(), traitList);
+ // "split" the list into two parts [nonexclusive, exclusive] to make selection later easier
+ genericTraits.sort([](GarrAbilityEntry const* a1, GarrAbilityEntry const* a2)
+ {
+ uint32 e1 = a1->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
+ uint32 e2 = a2->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
+ if (e1 != e2)
+ return e1 < e2;
+
+ return a1->ID < a2->ID;
+ });
+ genericTraits.unique();
+
+ std::size_t firstExclusive = 0, total = genericTraits.size();
+ for (auto itr = genericTraits.begin(); itr != genericTraits.end(); ++itr, ++firstExclusive)
+ if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ break;
+
+ while (traitList.size() < std::max<int32>(0, slots[1] - forcedTraits.size()) && total)
+ {
+ auto itr = genericTraits.begin();
+ std::advance(itr, urand(0, total-- - 1));
+ if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ total = firstExclusive; // selected exclusive trait - no other can be selected now
+ else
+ --firstExclusive;
+
+ traitList.push_back(*itr);
+ genericTraits.erase(itr);
+ }
+ }
+
+ result.splice(result.end(), forcedAbilities);
+ result.splice(result.end(), abilityList);
+ result.splice(result.end(), forcedTraits);
+ result.splice(result.end(), traitList);
+
+ return result;
+}
+
+std::list<GarrAbilityEntry const*> GarrisonMgr::GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const
+{
+ std::list<GarrAbilityEntry const*> abilities;
+ uint32 classSpecId;
+ switch (faction)
+ {
+ case GARRISON_FACTION_INDEX_HORDE:
+ classSpecId = follower->HordeGarrClassSpecID;
+ break;
+ case GARRISON_FACTION_INDEX_ALLIANCE:
+ classSpecId = follower->AllianceGarrClassSpecID;
+ break;
+ default:
+ return abilities;
+ }
+
+ if (!sGarrClassSpecStore.LookupEntry(classSpecId))
+ return abilities;
+
+ auto itr = _garrisonFollowerClassSpecAbilities.find(classSpecId);
+ if (itr != _garrisonFollowerClassSpecAbilities.end())
+ abilities = itr->second;
+
+ return abilities;
+}
+
+void GarrisonMgr::InitializeDbIdSequences()
+{
+ if (QueryResult result = CharacterDatabase.Query("SELECT MAX(dbId) FROM character_garrison_followers"))
+ _followerDbIdGenerator = (*result)[0].GetUInt64() + 1;
+}
+
+void GarrisonMgr::LoadFollowerClassSpecAbilities()
+{
+ QueryResult result = WorldDatabase.Query("SELECT classSpecId, abilityId FROM garrison_follower_class_spec_abilities");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 garrison follower class spec abilities. DB table `garrison_follower_class_spec_abilities` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 classSpecId = fields[0].GetUInt32();
+ uint32 abilityId = fields[1].GetUInt32();
+
+ if (!sGarrClassSpecStore.LookupEntry(classSpecId))
+ {
+ TC_LOG_ERROR("sql.sql", "Non-existing GarrClassSpec.db2 entry %u was referenced in `garrison_follower_class_spec_abilities` by row (%u, %u).", classSpecId, classSpecId, abilityId);
+ continue;
+ }
+
+ GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(abilityId);
+ if (!ability)
+ {
+ TC_LOG_ERROR("sql.sql", "Non-existing GarrAbility.db2 entry %u was referenced in `garrison_follower_class_spec_abilities` by row (%u, %u).", abilityId, classSpecId, abilityId);
+ continue;
+ }
+
+ _garrisonFollowerClassSpecAbilities[classSpecId].push_back(ability);
+ ++count;
+
+ } while (result->NextRow());
+
+ for (auto& pair : _garrisonFollowerClassSpecAbilities)
+ pair.second.sort();
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u garrison follower class spec abilities.", count);
+}
diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h
new file mode 100644
index 00000000000..63810e3c3ab
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMgr.h
@@ -0,0 +1,69 @@
+/*
+ * 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 GarrisonMgr_h__
+#define GarrisonMgr_h__
+
+#include "DB2Stores.h"
+#include <unordered_set>
+
+struct GarrAbilities
+{
+ std::unordered_set<GarrAbilityEntry const*> Counters;
+ std::unordered_set<GarrAbilityEntry const*> Traits;
+};
+
+class GarrisonMgr
+{
+public:
+ static GarrisonMgr& Instance()
+ {
+ static GarrisonMgr instance;
+ return instance;
+ }
+
+ void Initialize();
+
+ GarrSiteLevelEntry const* GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const;
+ std::vector<GarrSiteLevelPlotInstEntry const*> const* GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const;
+ GameObjectsEntry const* GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const;
+ bool IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const;
+ uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const;
+ GarrBuildingEntry const* GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const;
+ uint64 GenerateFollowerDbId();
+ std::list<GarrAbilityEntry const*> RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const;
+ std::list<GarrAbilityEntry const*> GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const;
+
+private:
+ void InitializeDbIdSequences();
+ void LoadFollowerClassSpecAbilities();
+
+ std::unordered_map<uint32 /*garrSiteId*/, std::vector<GarrSiteLevelPlotInstEntry const*>> _garrisonPlotInstBySiteLevel;
+ std::unordered_map<uint32 /*mapId*/, std::unordered_map<uint32 /*garrPlotId*/, GameObjectsEntry const*>> _garrisonPlots;
+ std::unordered_map<uint32 /*garrPlotId*/, std::unordered_set<uint32/*garrBuildingId*/>> _garrisonBuildingsByPlot;
+ std::unordered_map<uint64 /*garrBuildingId | garrSiteLevelPlotInstId << 32*/, uint32 /*garrBuildingPlotInstId*/> _garrisonBuildingPlotInstances;
+ std::unordered_map<uint32 /*buildingType*/, std::vector<GarrBuildingEntry const*>> _garrisonBuildingsByType;
+ std::unordered_map<uint32 /*garrFollowerId*/, GarrAbilities> _garrisonFollowerAbilities[2];
+ std::unordered_map<uint32 /*classSpecId*/, std::list<GarrAbilityEntry const*>> _garrisonFollowerClassSpecAbilities;
+ std::set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits;
+
+ uint64 _followerDbIdGenerator = UI64LIT(1);
+};
+
+#define sGarrisonMgr GarrisonMgr::Instance()
+
+#endif // GarrisonMgr_h__
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 6beae09bb20..fa52653811f 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -474,7 +474,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields)
creatureTemplate.expansion = fields[17].GetInt16();
creatureTemplate.expansionUnknown = fields[18].GetUInt16();
creatureTemplate.faction = fields[19].GetUInt16();
- creatureTemplate.npcflag = fields[20].GetUInt32();
+ creatureTemplate.npcflag = fields[20].GetUInt64();
creatureTemplate.speed_walk = fields[21].GetFloat();
creatureTemplate.speed_run = fields[22].GetFloat();
creatureTemplate.scale = fields[23].GetFloat();
@@ -678,9 +678,9 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
if (cInfo->npcflag != difficultyInfo->npcflag)
{
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, `npcflag`: %u) has different `npcflag` in difficulty %u mode (Entry: %u, `npcflag`: %u).",
+ TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, `npcflag`: " UI64FMTD ") has different `npcflag` in difficulty %u mode (Entry: %u, `npcflag`: " UI64FMTD ").",
cInfo->Entry, cInfo->npcflag, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->npcflag);
- TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `npcflag`=%u WHERE `entry`=%u;",
+ TC_LOG_ERROR("sql.sql", "Possible FIX: UPDATE `creature_template` SET `npcflag`=" UI64FMTD " WHERE `entry`=%u;",
cInfo->npcflag, cInfo->DifficultyEntry[diff]);
continue;
}
@@ -1171,7 +1171,7 @@ void ObjectMgr::LoadEquipmentTemplates()
uint32 oldMSTime = getMSTime();
// 0 1 2 3 4
- QueryResult result = WorldDatabase.Query("SELECT entry, id, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template");
+ QueryResult result = WorldDatabase.Query("SELECT CreatureID, ID, ItemID1, ItemID2, ItemID3 FROM creature_equip_template");
if (!result)
{
@@ -1188,7 +1188,7 @@ void ObjectMgr::LoadEquipmentTemplates()
if (!sObjectMgr->GetCreatureTemplate(entry))
{
- TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_equip_template`", entry);
+ TC_LOG_ERROR("sql.sql", "Creature template (CreatureID: %u) does not exist but has a record in `creature_equip_template`", entry);
continue;
}
@@ -1214,7 +1214,7 @@ void ObjectMgr::LoadEquipmentTemplates()
if (!dbcItem)
{
- TC_LOG_ERROR("sql.sql", "Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id=%u, forced to 0.",
+ TC_LOG_ERROR("sql.sql", "Unknown item (ID=%u) in creature_equip_template.ItemID%u for CreatureID = %u and ID=%u, forced to 0.",
equipmentInfo.ItemEntry[i], i+1, entry, id);
equipmentInfo.ItemEntry[i] = 0;
continue;
@@ -1230,7 +1230,7 @@ void ObjectMgr::LoadEquipmentTemplates()
dbcItem->InventoryType != INVTYPE_THROWN &&
dbcItem->InventoryType != INVTYPE_RANGEDRIGHT)
{
- TC_LOG_ERROR("sql.sql", "Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u and id = %u is not equipable in a hand, forced to 0.",
+ TC_LOG_ERROR("sql.sql", "Item (ID=%u) in creature_equip_template.ItemID%u for CreatureID = %u and ID = %u is not equipable in a hand, forced to 0.",
equipmentInfo.ItemEntry[i], i+1, entry, id);
equipmentInfo.ItemEntry[i] = 0;
}
@@ -1261,7 +1261,7 @@ uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData co
return cinfo->GetRandomValidModelId();
}
-void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data /*= NULL*/)
+void ObjectMgr::ChooseCreatureFlags(CreatureTemplate const* cinfo, uint64& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data /*= NULL*/)
{
npcflag = cinfo->npcflag;
unit_flags = cinfo->unit_flags;
@@ -1743,11 +1743,11 @@ void ObjectMgr::LoadCreatures()
data.spawnMask = fields[15].GetUInt32();
int16 gameEvent = fields[16].GetInt8();
uint32 PoolId = fields[17].GetUInt32();
- data.npcflag = fields[18].GetUInt32();
+ data.npcflag = fields[18].GetUInt64();
data.unit_flags = fields[19].GetUInt32();
data.dynamicflags = fields[20].GetUInt32();
- data.phaseid = fields[21].GetUInt32();
- data.phaseGroup = fields[22].GetUInt32();
+ data.phaseid = fields[21].GetUInt32();
+ data.phaseGroup = fields[22].GetUInt32();
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid);
if (!mapEntry)
@@ -1825,6 +1825,25 @@ void ObjectMgr::LoadCreatures()
data.phaseGroup = 0;
}
+ if (data.phaseid)
+ {
+ PhaseEntry const* phase = sPhaseStore.LookupEntry(data.phaseid);
+ if (!phase)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: " UI64FMTD " Entry: %u) with `phaseid` %u does not exist, set to 0", guid, data.id, data.phaseid);
+ data.phaseid = 0;
+ }
+ }
+
+ if (data.phaseGroup)
+ {
+ if (sDB2Manager.GetPhasesForGroup(data.phaseGroup).empty())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: " UI64FMTD " Entry: %u) with `phasegroup` %u does not exist, set to 0", guid, data.id, data.phaseGroup);
+ data.phaseGroup = 0;
+ }
+ }
+
if (sWorld->getBoolConfig(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA))
{
uint32 zoneId = 0;
@@ -2084,8 +2103,8 @@ void ObjectMgr::LoadGameobjects()
int16 gameEvent = fields[15].GetInt8();
uint32 PoolId = fields[16].GetUInt32();
- data.phaseid = fields[17].GetUInt32();
- data.phaseGroup = fields[18].GetUInt32();
+ data.phaseid = fields[17].GetUInt32();
+ data.phaseGroup = fields[18].GetUInt32();
if (data.phaseGroup && data.phaseid)
{
@@ -2093,6 +2112,25 @@ void ObjectMgr::LoadGameobjects()
data.phaseGroup = 0;
}
+ if (data.phaseid)
+ {
+ PhaseEntry const* phase = sPhaseStore.LookupEntry(data.phaseid);
+ if (!phase)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) with `phaseid` %u does not exist, set to 0", guid, data.id, data.phaseid);
+ data.phaseid = 0;
+ }
+ }
+
+ if (data.phaseGroup)
+ {
+ if (sDB2Manager.GetPhasesForGroup(data.phaseGroup).empty())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) with `phaseGroup` %u does not exist, set to 0", guid, data.id, data.phaseGroup);
+ data.phaseGroup = 0;
+ }
+ }
+
if (std::abs(data.orientation) > 2 * float(M_PI))
{
TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) with abs(`orientation`) > 2*PI (orientation is expressed in radians), normalized.", guid, data.id);
@@ -2204,6 +2242,25 @@ bool ObjectMgr::GetPlayerNameByGUID(ObjectGuid const& guid, std::string& name)
return false;
}
+bool ObjectMgr::GetPlayerNameAndClassByGUID(ObjectGuid const& guid, std::string& name, uint8& _class)
+{
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
+ {
+ name = player->GetName();
+ _class = player->getClass();
+ return true;
+ }
+
+ if (CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid))
+ {
+ name = characterInfo->Name;
+ _class = characterInfo->Class;
+ return true;
+ }
+
+ return false;
+}
+
uint32 ObjectMgr::GetPlayerTeamByGUID(ObjectGuid const& guid)
{
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
@@ -2328,7 +2385,7 @@ void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill,
{
*disenchantID = 0;
*(int32*)requiredDisenchantSkill = -1;
- if ((itemTemplate.GetFlags() & (ITEM_PROTO_FLAG_CONJURED | ITEM_PROTO_FLAG_UNK6)) ||
+ if ((itemTemplate.GetFlags() & (ITEM_FLAG_CONJURED | ITEM_FLAG_UNK6)) ||
itemTemplate.GetBonding() == BIND_QUEST_ITEM || itemTemplate.GetArea() || itemTemplate.GetMap() ||
itemTemplate.GetMaxStackSize() > 1 ||
itemTemplate.GetQuality() < ITEM_QUALITY_UNCOMMON || itemTemplate.GetQuality() > ITEM_QUALITY_EPIC ||
@@ -3582,10 +3639,10 @@ void ObjectMgr::LoadQuests()
mExclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
- //0 1 2 3 4 5 6 7 8 9 10 11 12
- "ID, QuestType, QuestLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, Float10, RewardMoney, RewardMoneyDifficulty, "
- //13 14 15 16 17 18 19 20 21
- "Float13, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, StartItem, Flags, FlagsEx, "
+ //0 1 2 3 4 5 6 7 8 9 10
+ "ID, QuestType, QuestLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
+ //11 12 13 14 15 16 17 18 19 20 21
+ "RewardMoney, RewardMoneyDifficulty, Float13, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, StartItem, Flags, FlagsEx, "
//22 23 24 25 26 27 28 29
"RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, "
//30 31 32 33 34 35 36 37
@@ -5236,14 +5293,8 @@ void ObjectMgr::LoadNPCText()
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.Query("SELECT ID, "
- "BroadcastTextID0, Probability0, "
- "BroadcastTextID1, Probability1, "
- "BroadcastTextID2, Probability2, "
- "BroadcastTextID3, Probability3, "
- "BroadcastTextID4, Probability4, "
- "BroadcastTextID5, Probability5, "
- "BroadcastTextID6, Probability6, "
- "BroadcastTextID7, Probability7"
+ "Probability0, Probability1, Probability2, Probability3, Probability4, Probability5, Probability6, Probability7, "
+ "BroadcastTextID0, BroadcastTextID1, BroadcastTextID2, BroadcastTextID3, BroadcastTextID4, BroadcastTextID5, BroadcastTextID6, BroadcastTextID7"
" FROM npc_text");
if (!result)
{
@@ -5268,27 +5319,30 @@ void ObjectMgr::LoadNPCText()
for (uint8 i = 0; i < MAX_NPC_TEXT_OPTIONS; ++i)
{
- npcText.Data[i].BroadcastTextID = fields[1 + i].GetUInt32();
- npcText.Data[i].Probability = fields[1 + i * 2].GetFloat();
+ npcText.Data[i].Probability = fields[1 + i].GetFloat();
+ npcText.Data[i].BroadcastTextID = fields[9 + i].GetUInt32();
}
- bool isValid = false;
for (uint8 i = 0; i < MAX_NPC_TEXT_OPTIONS; i++)
{
if (npcText.Data[i].BroadcastTextID)
{
if (!sBroadcastTextStore.LookupEntry(npcText.Data[i].BroadcastTextID))
{
- TC_LOG_ERROR("sql.sql", "NpcText (Id: %u) in table `npc_text` has non-existing or incompatible Index: %u BroadcastTextID %u.", textID, i, npcText.Data[i].BroadcastTextID);
+ TC_LOG_ERROR("sql.sql", "NPCText (ID: %u) has a non-existing or incompatible BroadcastText (ID: %u, Index: %u)", textID, npcText.Data[i].BroadcastTextID, i);
npcText.Data[i].BroadcastTextID = 0;
}
- else
- isValid = true;
}
}
- if (!isValid)
- TC_LOG_ERROR("sql.sql", "NpcText (Id: %u) in table `npc_text` is invalid", textID);
+ for (uint8 i = 0; i < MAX_NPC_TEXT_OPTIONS; i++)
+ {
+ if (npcText.Data[i].Probability > 0 && npcText.Data[i].BroadcastTextID == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "NPCText (ID: %u) has a probability (Index: %u) set, but no BroadcastTextID to go with it", textID, i);
+ npcText.Data[i].Probability = 0;
+ }
+ }
}
while (result->NextRow());
@@ -6421,6 +6475,22 @@ void ObjectMgr::LoadGameObjectTemplate()
{
uint32 oldMSTime = getMSTime();
+ for (GameObjectsEntry const* db2go : sGameObjectsStore)
+ {
+ GameObjectTemplate& go = _gameObjectTemplateStore[db2go->ID];
+ go.entry = db2go->ID;
+ go.type = db2go->Type;
+ go.displayId = db2go->DisplayID;
+ go.name = db2go->Name->Str[sWorld->GetDefaultDbcLocale()];
+ go.faction = 0;
+ go.flags = 0;
+ go.size = db2go->Size;
+ memset(go.raw.data, 0, sizeof(go.raw.data));
+ memcpy(go.raw.data, db2go->Data, std::min(sizeof(db2go->Data), sizeof(go.raw.data)));
+ go.unkInt32 = 0;
+ go.ScriptId = 0;
+ }
+
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, "
// 10 11 12 13 14 15 16 17 18 19 20 21 22
@@ -7075,6 +7145,9 @@ void ObjectMgr::LoadQuestPOI()
int32 PlayerConditionID = fields[12].GetInt32();
int32 WoDUnk1 = fields[13].GetInt32();
+ if (!sObjectMgr->GetQuestTemplate(QuestID))
+ TC_LOG_ERROR("sql.sql", "`quest_poi` quest id (%u) Idx1 (%u) does not exist in `quest_template`", QuestID, Idx1);
+
QuestPOI POI(BlobIndex, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, WorldMapAreaId, Floor, Priority, Flags, WorldEffectID, PlayerConditionID, WoDUnk1);
if (QuestID < int32(POIs.size()) && Idx1 < int32(POIs[QuestID].size()))
{
@@ -8198,7 +8271,7 @@ void ObjectMgr::LoadGossipMenuItems()
gMenuItem.OptionText = fields[3].GetString();
gMenuItem.OptionBroadcastTextId = fields[4].GetUInt32();
gMenuItem.OptionType = fields[5].GetUInt8();
- gMenuItem.OptionNpcflag = fields[6].GetUInt32();
+ gMenuItem.OptionNpcflag = fields[6].GetUInt64();
gMenuItem.ActionMenuId = fields[7].GetUInt32();
gMenuItem.ActionPoiId = fields[8].GetUInt32();
gMenuItem.BoxCoded = fields[9].GetBool();
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index d55492ac0f1..4277ab74048 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -510,7 +510,7 @@ struct GossipMenuItems
std::string OptionText;
uint32 OptionBroadcastTextId;
uint32 OptionType;
- uint32 OptionNpcflag;
+ uint64 OptionNpcflag;
uint32 ActionMenuId;
uint32 ActionPoiId;
bool BoxCoded;
@@ -728,7 +728,7 @@ class ObjectMgr
CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId);
CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID);
static uint32 ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = NULL);
- static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = NULL);
+ static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint64& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = NULL);
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id);
CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid);
GameObjectAddon const* GetGameObjectAddon(ObjectGuid::LowType lowguid);
@@ -780,6 +780,7 @@ class ObjectMgr
* @return true if player was found, false otherwise
*/
static bool GetPlayerNameByGUID(ObjectGuid const& guid, std::string& name);
+ static bool GetPlayerNameAndClassByGUID(ObjectGuid const& guid, std::string& name, uint8& _class);
static uint32 GetPlayerTeamByGUID(ObjectGuid const& guid);
static uint32 GetPlayerAccountIdByGUID(ObjectGuid const& guid);
static uint32 GetPlayerAccountIdByPlayerName(std::string const& name);
@@ -1364,7 +1365,7 @@ class ObjectMgr
{
auto itr = _guidGenerators.find(high);
if (itr == _guidGenerators.end())
- itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first;
+ itr = _guidGenerators.insert(std::make_pair(high, Trinity::make_unique<ObjectGuidGenerator<high>>())).first;
return *itr->second;
}
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 8a5386684bb..aea2d8ec383 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -736,18 +736,6 @@ namespace Trinity
NearestGameObjectTypeInObjectRangeCheck(NearestGameObjectTypeInObjectRangeCheck const&);
};
- class GameObjectWithDbGUIDCheck
- {
- public:
- GameObjectWithDbGUIDCheck(WorldObject const& /*obj*/, ObjectGuid::LowType db_guid) : i_db_guid(db_guid) { }
- bool operator()(GameObject const* go) const
- {
- return go->GetSpawnId() == i_db_guid;
- }
- private:
- ObjectGuid::LowType i_db_guid;
- };
-
// Unit checks
class MostHPMissingInRange
@@ -849,18 +837,6 @@ namespace Trinity
float i_range;
};
- class CreatureWithDbGUIDCheck
- {
- public:
- CreatureWithDbGUIDCheck(WorldObject const* /*obj*/, ObjectGuid::LowType lowguid) : i_lowguid(lowguid) { }
- bool operator()(Creature* u)
- {
- return u->GetSpawnId() == i_lowguid;
- }
- private:
- ObjectGuid::LowType i_lowguid;
- };
-
class AnyFriendlyUnitInObjectRangeCheck
{
public:
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index c73aeb3a719..fadf7e1970e 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -21,6 +21,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Player.h"
+#include "Pet.h"
#include "World.h"
#include "ObjectMgr.h"
#include "GroupMgr.h"
@@ -35,6 +36,7 @@
#include "Util.h"
#include "LFGMgr.h"
#include "UpdateFieldFlags.h"
+#include "PartyPackets.h"
Roll::Roll(ObjectGuid _guid, LootItem const& li) : itemGUID(_guid), itemid(li.itemid),
itemRandomPropId(li.randomPropertyId), itemRandomSuffix(li.randomSuffix), itemCount(li.count),
@@ -55,11 +57,15 @@ Loot* Roll::getLoot()
Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL),
m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(DIFFICULTY_10_N),
-m_bgGroup(NULL), m_bfGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
-m_masterLooterGuid(), m_subGroupsCounts(NULL), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0)
+m_bgGroup(nullptr), m_bfGroup(nullptr), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
+m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0),
+m_readyCheckStarted(false), m_readyCheckTimer(0), m_activeMarkers(0)
{
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].Clear();
+
+ for (uint8 i = 0; i < RAID_MARKERS_COUNT; ++i)
+ m_markers[i] = nullptr;
}
Group::~Group()
@@ -176,7 +182,7 @@ void Group::LoadGroupFromDB(Field* fields)
m_looterGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64());
m_lootThreshold = ItemQualities(fields[3].GetUInt8());
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].SetRawValue(fields[4 + i].GetBinary());
m_groupType = GroupType(fields[12].GetUInt8());
@@ -199,7 +205,7 @@ void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uin
member.guid = ObjectGuid::Create<HighGuid::Player>(guidLow);
// skip non-existed member
- if (!ObjectMgr::GetPlayerNameByGUID(member.guid, member.name))
+ if (!ObjectMgr::GetPlayerNameAndClassByGUID(member.guid, member.name, member._class))
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_MEMBER);
stmt->setUInt64(0, guidLow);
@@ -207,9 +213,10 @@ void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uin
return;
}
- member.group = subgroup;
- member.flags = memberFlags;
- member.roles = roles;
+ member.group = subgroup;
+ member.flags = memberFlags;
+ member.roles = roles;
+ member.readyChecked = false;
m_memberSlots.push_back(member);
@@ -368,7 +375,7 @@ bool Group::AddMember(Player* player)
bool groupFound = false;
for (; subGroup < MAX_RAID_SUBGROUPS; ++subGroup)
{
- if (m_subGroupsCounts[subGroup] < MAXGROUPSIZE)
+ if (m_subGroupsCounts[subGroup] < MAX_GROUP_SIZE)
{
groupFound = true;
break;
@@ -380,11 +387,13 @@ bool Group::AddMember(Player* player)
}
MemberSlot member;
- member.guid = player->GetGUID();
- member.name = player->GetName();
- member.group = subGroup;
- member.flags = 0;
- member.roles = 0;
+ member.guid = player->GetGUID();
+ member.name = player->GetName();
+ member._class = player->getClass();
+ member.group = subGroup;
+ member.flags = 0;
+ member.roles = 0;
+ member.readyChecked = false;
m_memberSlots.push_back(member);
SubGroupCounterIncrease(subGroup);
@@ -407,7 +416,7 @@ bool Group::AddMember(Player* player)
if (!isRaidGroup()) // reset targetIcons for non-raid-groups
{
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].Clear();
}
@@ -455,7 +464,11 @@ bool Group::AddMember(Player* player)
}
}
}
+
player->SetGroupUpdateFlag(GROUP_UPDATE_FULL);
+ if (Pet* pet = player->GetPet())
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
+
UpdatePlayerOutOfRange(player);
// quest related GO state dependent from raid membership
@@ -552,12 +565,6 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
player->GetSession()->SendPacket(&data);
}
- // Do we really need to send this opcode?
- data.Initialize(SMSG_PARTY_UPDATE, 1+1+1+1+8+4+4+8);
- data << uint8(0x10) << uint8(0) << uint8(0) << uint8(0);
- data << m_guid << uint32(m_counter) << uint32(0) << uint64(0);
- player->GetSession()->SendPacket(&data);
-
_homebindIfInstance(player);
}
@@ -644,7 +651,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
}
}
-void Group::ChangeLeader(ObjectGuid newLeaderGuid)
+void Group::ChangeLeader(ObjectGuid newLeaderGuid, int8 partyIndex)
{
member_witerator slot = _getMemberWSlot(newLeaderGuid);
@@ -707,9 +714,10 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)
m_leaderName = newLeader->GetName();
ToggleGroupMemberFlag(slot, MEMBER_FLAG_ASSISTANT, false);
- WorldPacket data(SMSG_GROUP_NEW_LEADER, m_leaderName.size()+1);
- data << slot->name;
- BroadcastPacket(&data, true);
+ WorldPackets::Party::GroupNewLeader groupNewLeader;
+ groupNewLeader.Name = m_leaderName;
+ groupNewLeader.PartyIndex = partyIndex;
+ BroadcastPacket(groupNewLeader.Write(), true);
}
void Group::Disband(bool hideDestroy /* = false */)
@@ -1136,7 +1144,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject)
if (item->DisenchantID && m_maxEnchantingLevel >= item->RequiredDisenchantSkill)
r->rollVoteMask |= ROLL_FLAG_TYPE_DISENCHANT;
- if (item->GetFlags2() & ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED)
+ if (item->GetFlags2() & ITEM_FLAG2_NEED_ROLL_DISABLED)
r->rollVoteMask &= ~ROLL_FLAG_TYPE_NEED;
loot->items[itemSlot].is_blocked = true;
@@ -1491,45 +1499,38 @@ void Group::CountTheRoll(Rolls::iterator rollI)
delete roll;
}
-void Group::SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid)
+void Group::SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy, uint8 partyIndex)
{
- if (id >= TARGETICONCOUNT)
+ if (symbol >= TARGET_ICONS_COUNT)
return;
// clean other icons
- if (!targetGuid.IsEmpty())
- for (int i = 0; i < TARGETICONCOUNT; ++i)
- if (m_targetIcons[i] == targetGuid)
- SetTargetIcon(i, ObjectGuid::Empty, ObjectGuid::Empty);
+ if (!target.IsEmpty())
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
+ if (m_targetIcons[i] == target)
+ SetTargetIcon(i, ObjectGuid::Empty, changedBy, partyIndex);
- m_targetIcons[id] = targetGuid;
+ m_targetIcons[symbol] = target;
- WorldPacket data(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, (1+8+1+8));
- data << uint8(0); // set targets
- data << whoGuid;
- data << uint8(id);
- data << targetGuid;
- BroadcastPacket(&data, true);
+ WorldPackets::Party::SendRaidTargetUpdateSingle updateSingle;
+ updateSingle.PartyIndex = partyIndex;
+ updateSingle.Target = target;
+ updateSingle.ChangedBy = changedBy;
+ updateSingle.Symbol = symbol;
+ BroadcastPacket(updateSingle.Write(), true);
}
-void Group::SendTargetIconList(WorldSession* session)
+void Group::SendTargetIconList(WorldSession* session, int8 partyIndex)
{
if (!session)
return;
- WorldPacket data(SMSG_SEND_RAID_TARGET_UPDATE_ALL, (1+TARGETICONCOUNT*9));
- data << uint8(1); // list targets
+ WorldPackets::Party::SendRaidTargetUpdateAll updateAll;
+ updateAll.PartyIndex = partyIndex;
+ for (uint8 i = 0; i < TARGET_ICONS_COUNT; i++)
+ updateAll.TargetIcons.insert(std::pair<uint8, ObjectGuid>(i, m_targetIcons[i]));
- for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
- {
- if (m_targetIcons[i].IsEmpty())
- continue;
-
- data << uint8(i);
- data << m_targetIcons[i];
- }
-
- session->SendPacket(&data);
+ session->SendPacket(updateAll.Write());
}
void Group::SendUpdate()
@@ -1556,56 +1557,79 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot)
slot = &(*witr);
}
- WorldPacket data(SMSG_PARTY_UPDATE, (1+1+1+1+1+4+8+4+4+(GetMembersCount()-1)*(13+8+1+1+1+1)+8+1+8+1+1+1+1));
- data << uint8(m_groupType); // group type (flags in 3.3)
- data << uint8(slot->group);
- data << uint8(slot->flags);
- data << uint8(slot->roles);
- if (isLFGGroup())
- {
- data << uint8(sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0); // FIXME - Dungeon save status? 2 = done
- data << uint32(sLFGMgr->GetDungeon(m_guid));
- data << uint8(0); // 4.x new
- }
+ WorldPackets::Party::PartyUpdate partyUpdate;
- data << m_guid;
- data << uint32(m_counter++); // 3.3, value increases every time this packet gets sent
- data << uint32(GetMembersCount()-1);
- for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ partyUpdate.PartyType = m_groupType;
+ partyUpdate.PartyIndex = 0;
+ partyUpdate.PartyFlags = uint8(IsCreated());
+
+ partyUpdate.PartyGUID = m_guid;
+ partyUpdate.LeaderGUID = m_leaderGuid;
+
+ partyUpdate.SequenceNum = m_counter++; // 3.3, value increases every time this packet gets sent
+
+ partyUpdate.MyIndex = -1;
+ uint8 index = 0;
+ for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr, ++index)
{
if (slot->guid == citr->guid)
- continue;
+ partyUpdate.MyIndex = index;
Player* member = ObjectAccessor::FindConnectedPlayer(citr->guid);
- uint8 onlineState = (member && !member->GetSession()->PlayerLogout()) ? MEMBER_STATUS_ONLINE : MEMBER_STATUS_OFFLINE;
- onlineState = onlineState | ((isBGGroup() || isBFGroup()) ? MEMBER_STATUS_PVP : 0);
+ WorldPackets::Party::GroupPlayerInfos playerInfos;
- data << citr->name;
- data << citr->guid; // guid
- data << uint8(onlineState); // online-state
- data << uint8(citr->group); // groupid
- data << uint8(citr->flags); // See enum GroupMemberFlags
- data << uint8(citr->roles); // Lfg Roles
+ playerInfos.GUID = citr->guid;
+ playerInfos.Name = citr->name;
+ playerInfos.Class = citr->_class;
+
+ playerInfos.Status = MEMBER_STATUS_OFFLINE;
+ if (member && member->GetSession() && !member->GetSession()->PlayerLogout())
+ playerInfos.Status = MEMBER_STATUS_ONLINE | (isBGGroup() || isBFGroup() ? MEMBER_STATUS_PVP : 0);
+
+ playerInfos.Subgroup = citr->group; // groupid
+ playerInfos.Flags = citr->flags; // See enum GroupMemberFlags
+ playerInfos.RolesAssigned = citr->roles; // Lfg Roles
+
+ partyUpdate.PlayerList.push_back(playerInfos);
}
- data << m_leaderGuid; // leader guid
+ if (GetMembersCount() > 1)
+ {
+ // LootSettings
+ partyUpdate.LootSettings = boost::in_place();
+ partyUpdate.LootSettings->Method = m_lootMethod;
+ partyUpdate.LootSettings->Threshold = m_lootThreshold;
+ partyUpdate.LootSettings->LootMaster = m_lootMethod == MASTER_LOOT ? m_masterLooterGuid : ObjectGuid::Empty;
+
+ // Difficulty Settings
+ partyUpdate.DifficultySettings = boost::in_place();
+ partyUpdate.DifficultySettings->DungeonDifficultyID = m_dungeonDifficulty;
+ partyUpdate.DifficultySettings->RaidDifficultyID = m_raidDifficulty;
+ partyUpdate.DifficultySettings->LegacyRaidDifficultyID = m_legacyRaidDifficulty;
+ }
- if (GetMembersCount() - 1)
+ // LfgInfos
+ if (isLFGGroup())
{
- data << uint8(m_lootMethod); // loot method
+ partyUpdate.LfgInfos = boost::in_place();
- if (m_lootMethod == MASTER_LOOT)
- data << m_masterLooterGuid; // master looter guid
- else
- data << uint64(0);
+ partyUpdate.LfgInfos->Slot = sLFGMgr->GetDungeon(m_guid);
+ partyUpdate.LfgInfos->BootCount = 0; // new 6.x
+ partyUpdate.LfgInfos->Aborted = false; // new 6.x
+
+ partyUpdate.LfgInfos->MyFlags = 0; // new 6.x
+ partyUpdate.LfgInfos->MyRandomSlot = 0; // new 6.x
+
+ partyUpdate.LfgInfos->MyPartialClear = sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0; // FIXME - Dungeon save status? 2 = done
+ partyUpdate.LfgInfos->MyGearDiff = 0.f; // new 6.x
+ partyUpdate.LfgInfos->MyFirstReward = false; // new 6.x
- data << uint8(m_lootThreshold); // loot threshold
- data << uint8(m_dungeonDifficulty); // Dungeon Difficulty
- data << uint8(m_raidDifficulty); // Raid Difficulty
+ partyUpdate.LfgInfos->MyStrangerCount = 0; // new 6.x
+ partyUpdate.LfgInfos->MyKickVoteCount = 0; // new 6.x
}
- player->GetSession()->SendPacket(&data);
+ player->GetSession()->SendPacket(partyUpdate.Write());
}
void Group::UpdatePlayerOutOfRange(Player* player)
@@ -1613,15 +1637,15 @@ void Group::UpdatePlayerOutOfRange(Player* player)
if (!player || !player->IsInWorld())
return;
- WorldPacket data;
- player->GetSession()->BuildPartyMemberStatsChangedPacket(player, &data);
+ WorldPackets::Party::PartyMemberStats packet;
+ packet.Initialize(player);
Player* member;
for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
member = itr->GetSource();
if (member && member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
- member->GetSession()->SendPacket(&data);
+ member->GetSession()->SendPacket(packet.Write());
}
}
@@ -1653,32 +1677,6 @@ void Group::BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRai
}
}
-void Group::BroadcastReadyCheck(WorldPacket const* packet)
-{
- for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next())
- {
- Player* player = itr->GetSource();
- if (player && player->GetSession())
- if (IsLeader(player->GetGUID()) || IsAssistant(player->GetGUID()))
- player->GetSession()->SendPacket(packet);
- }
-}
-
-void Group::OfflineReadyCheck()
-{
- for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
- {
- Player* player = ObjectAccessor::FindConnectedPlayer(citr->guid);
- if (!player || !player->GetSession())
- {
- WorldPacket data(SMSG_READY_CHECK_RESPONSE, 9);
- data << citr->guid;
- data << uint8(0);
- BroadcastReadyCheck(&data);
- }
- }
-}
-
bool Group::_setMembersGroup(ObjectGuid guid, uint8 group)
{
member_witerator slot = _getMemberWSlot(guid);
@@ -1725,8 +1723,8 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group)
if (slot == m_memberSlots.end())
return;
+ uint8 prevSubGroup = slot->group;
// Abort if the player is already in the target sub group
- uint8 prevSubGroup = GetMemberGroup(guid);
if (prevSubGroup == group)
return;
@@ -1758,7 +1756,6 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group)
else
{
// If player is in BG raid, it is possible that he is also in normal raid - and that normal raid is stored in m_originalGroup reference
- prevSubGroup = player->GetOriginalSubGroup();
player->GetOriginalGroupRef().setSubGroup(group);
}
}
@@ -1767,6 +1764,51 @@ void Group::ChangeMembersGroup(ObjectGuid guid, uint8 group)
SendUpdate();
}
+void Group::SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid)
+{
+ if (!isRaidGroup())
+ return;
+
+ member_witerator slots[2];
+ slots[0] = _getMemberWSlot(firstGuid);
+ slots[1] = _getMemberWSlot(secondGuid);
+ if (slots[0] == m_memberSlots.end() || slots[1] == m_memberSlots.end())
+ return;
+
+ if (slots[0]->group == slots[1]->group)
+ return;
+
+ uint8 tmp = slots[0]->group;
+ slots[0]->group = slots[1]->group;
+ slots[1]->group = tmp;
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ for (uint8 i = 0; i < 2; i++)
+ {
+ // Preserve new sub group in database for non-raid groups
+ if (!isBGGroup() && !isBFGroup())
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_MEMBER_SUBGROUP);
+
+ stmt->setUInt8(0, slots[i]->group);
+ stmt->setUInt64(1, slots[i]->guid.GetCounter());
+
+ trans->Append(stmt);
+ }
+
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(slots[i]->guid))
+ {
+ if (player->GetGroup() == this)
+ player->GetGroupRef().setSubGroup(slots[i]->group);
+ else
+ player->GetOriginalGroupRef().setSubGroup(slots[i]->group);
+ }
+ }
+ CharacterDatabase.CommitTransaction(trans);
+
+ SendUpdate();
+}
+
// Retrieve the next Round-Roubin player for the group
//
// No update done if loot method is FFA.
@@ -2262,9 +2304,167 @@ void Group::SetLfgRoles(ObjectGuid guid, uint8 roles)
SendUpdate();
}
+uint8 Group::GetLfgRoles(ObjectGuid guid)
+{
+ member_witerator slot = _getMemberWSlot(guid);
+ if (slot == m_memberSlots.end())
+ return 0;
+
+ return slot->roles;
+}
+
+void Group::Update(uint32 diff)
+{
+ UpdateReadyCheck(diff);
+}
+
+void Group::UpdateReadyCheck(uint32 diff)
+{
+ if (!m_readyCheckStarted)
+ return;
+
+ m_readyCheckTimer -= diff;
+ if (m_readyCheckTimer <= 0)
+ EndReadyCheck();
+}
+
+void Group::StartReadyCheck(ObjectGuid starterGuid, int8 partyIndex, uint32 duration)
+{
+ if (m_readyCheckStarted)
+ return;
+
+ member_witerator slot = _getMemberWSlot(starterGuid);
+ if (slot == m_memberSlots.end())
+ return ;
+
+ m_readyCheckStarted = true;
+ m_readyCheckTimer = duration;
+
+ SetOfflineMembersReadyChecked();
+
+ SetMemberReadyChecked(&(*slot));
+
+ WorldPackets::Party::ReadyCheckStarted readyCheckStarted;
+ readyCheckStarted.PartyGUID = m_guid;
+ readyCheckStarted.PartyIndex = partyIndex;
+ readyCheckStarted.InitiatorGUID = starterGuid;
+ readyCheckStarted.Duration = duration;
+ BroadcastPacket(readyCheckStarted.Write(), false);
+}
+
+void Group::EndReadyCheck(void)
+{
+ if (!m_readyCheckStarted)
+ return;
+
+ m_readyCheckStarted = false;
+ m_readyCheckTimer = 0;
+
+ ResetMemberReadyChecked();
+
+ WorldPackets::Party::ReadyCheckCompleted readyCheckCompleted;
+ readyCheckCompleted.PartyIndex = 0;
+ readyCheckCompleted.PartyGUID = m_guid;
+ BroadcastPacket(readyCheckCompleted.Write(), false);
+}
+
+bool Group::IsReadyCheckCompleted(void) const
+{
+ for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
+ if (!citr->readyChecked)
+ return false;
+ return true;
+}
+
+void Group::SetMemberReadyCheck(ObjectGuid guid, bool ready)
+{
+ if (!m_readyCheckStarted)
+ return;
+
+ member_witerator slot = _getMemberWSlot(guid);
+ if (slot != m_memberSlots.end())
+ SetMemberReadyCheck(&(*slot), ready);
+}
+
+void Group::SetMemberReadyCheck(MemberSlot* slot, bool ready)
+{
+ WorldPackets::Party::ReadyCheckResponse response;
+ response.PartyGUID = m_guid;
+ response.Player = slot->guid;
+ response.IsReady = ready;
+ BroadcastPacket(response.Write(), false);
+
+ SetMemberReadyChecked(slot);
+}
+
+void Group::SetOfflineMembersReadyChecked(void)
+{
+ for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+ {
+ Player* player = ObjectAccessor::FindConnectedPlayer(itr->guid);
+ if (!player || !player->GetSession())
+ SetMemberReadyCheck(&(*itr), false);
+ }
+}
+
+void Group::SetMemberReadyChecked(MemberSlot* slot)
+{
+ slot->readyChecked = true;
+ if (IsReadyCheckCompleted())
+ EndReadyCheck();
+}
+
+void Group::ResetMemberReadyChecked(void)
+{
+ for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+ itr->readyChecked = false;
+}
+
+void Group::AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid)
+{
+ if (markerId >= RAID_MARKERS_COUNT || m_markers[markerId])
+ return;
+
+ m_activeMarkers |= (1 << markerId);
+ m_markers[markerId] = Trinity::make_unique<RaidMarker>(mapId, positionX, positionY, positionZ, transportGuid);
+ SendRaidMarkersChanged();
+}
+
+void Group::DeleteRaidMarker(uint8 markerId)
+{
+ if (markerId > RAID_MARKERS_COUNT)
+ return;
+
+ for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
+ if (m_markers[i] && (markerId == i || markerId == RAID_MARKERS_COUNT))
+ {
+ m_markers[i] = nullptr;
+ m_activeMarkers &= ~(1 << i);
+ }
+
+ SendRaidMarkersChanged();
+}
+
+void Group::SendRaidMarkersChanged(WorldSession* session, int8 partyIndex)
+{
+ WorldPackets::Party::RaidMarkersChanged packet;
+
+ packet.PartyIndex = partyIndex;
+ packet.ActiveMarkers = m_activeMarkers;
+
+ for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
+ if (m_markers[i])
+ packet.RaidMarkers.push_back(m_markers[i].get());
+
+ if (session)
+ session->SendPacket(packet.Write());
+ else
+ BroadcastPacket(packet.Write(), false);
+}
+
bool Group::IsFull() const
{
- return isRaidGroup() ? (m_memberSlots.size() >= MAXRAIDSIZE) : (m_memberSlots.size() >= MAXGROUPSIZE);
+ return isRaidGroup() ? (m_memberSlots.size() >= MAX_RAID_SIZE) : (m_memberSlots.size() >= MAX_GROUP_SIZE);
}
bool Group::isLFGGroup() const
@@ -2371,10 +2571,9 @@ bool Group::SameSubGroup(ObjectGuid guid1, MemberSlot const* slot2) const
bool Group::HasFreeSlotSubGroup(uint8 subgroup) const
{
- return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE);
+ return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAX_GROUP_SIZE);
}
-
uint8 Group::GetMemberGroup(ObjectGuid guid) const
{
member_citerator mslot = _getMemberCSlot(guid);
@@ -2522,3 +2721,15 @@ void Group::ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)
slot->flags &= ~flag;
}
+void Group::SetEveryoneIsAssistant(bool apply)
+{
+ if (apply)
+ m_groupType = GroupType(m_groupType | GROUPTYPE_EVERYONE_ASSISTANT);
+ else
+ m_groupType = GroupType(m_groupType & ~GROUPTYPE_EVERYONE_ASSISTANT);
+
+ for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
+ ToggleGroupMemberFlag(itr, MEMBER_FLAG_ASSISTANT, apply);
+
+ SendUpdate();
+}
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 4154f31a410..634d1f0f37b 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -24,6 +24,7 @@
#include "LootMgr.h"
#include "QueryResult.h"
#include "SharedDefines.h"
+#include "Object.h"
class Battlefield;
class Battleground;
@@ -38,10 +39,14 @@ class WorldSession;
struct MapEntry;
-#define MAXGROUPSIZE 5
-#define MAXRAIDSIZE 40
-#define MAX_RAID_SUBGROUPS MAXRAIDSIZE/MAXGROUPSIZE
-#define TARGETICONCOUNT 8
+#define MAX_GROUP_SIZE 5
+#define MAX_RAID_SIZE 40
+#define MAX_RAID_SUBGROUPS MAX_RAID_SIZE / MAX_GROUP_SIZE
+
+#define TARGET_ICONS_COUNT 8
+#define RAID_MARKERS_COUNT 8
+
+#define READYCHECK_DURATION 35000
enum RollVote
{
@@ -81,50 +86,59 @@ enum GroupMemberAssignment
enum GroupType
{
- GROUPTYPE_NORMAL = 0x00,
- GROUPTYPE_BG = 0x01,
- GROUPTYPE_RAID = 0x02,
- GROUPTYPE_BGRAID = GROUPTYPE_BG | GROUPTYPE_RAID, // mask
- GROUPTYPE_LFG_RESTRICTED = 0x04, // Script_HasLFGRestrictions()
- GROUPTYPE_LFG = 0x08,
+ GROUPTYPE_NORMAL = 0x00,
+ GROUPTYPE_BG = 0x01,
+ GROUPTYPE_RAID = 0x02,
+ GROUPTYPE_BGRAID = GROUPTYPE_BG | GROUPTYPE_RAID, // mask
+ GROUPTYPE_LFG_RESTRICTED = 0x04, // Script_HasLFGRestrictions()
+ GROUPTYPE_LFG = 0x08,
+ GROUPTYPE_EVERYONE_ASSISTANT = 0x40, // Script_IsEveryoneAssistant() (4.x)
// 0x10, leave/change group?, I saw this flag when leaving group and after leaving BG while in group
// GROUPTYPE_ONE_PERSON_PARTY = 0x20, 4.x Script_IsOnePersonParty()
- // GROUPTYPE_EVERYONE_ASSISTANT = 0x40 4.x Script_IsEveryoneAssistant()
};
enum GroupUpdateFlags
{
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
- GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16 (GroupMemberStatusFlag)
- GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32 (HP)
- GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32 (HP)
- GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 (PowerType)
- GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // int16 (power value)
- GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // int16 (power value)
- GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 (level value)
- GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 (zone id)
- GROUP_UPDATE_FLAG_UNK100 = 0x00000100, // int16 (unk)
- GROUP_UPDATE_FLAG_POSITION = 0x00000200, // uint16 (x), uint16 (y), uint16 (z)
- GROUP_UPDATE_FLAG_AURAS = 0x00000400, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
- GROUP_UPDATE_FLAG_PET_GUID = 0x00000800, // uint64 (pet guid)
- GROUP_UPDATE_FLAG_PET_NAME = 0x00001000, // cstring (name, NULL terminated string)
- GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00002000, // uint16 (model id)
- GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00004000, // uint32 (HP)
- GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00008000, // uint32 (HP)
- GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00010000, // uint8 (PowerType)
- GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00020000, // uint16 (power value)
- GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00040000, // uint16 (power value)
- GROUP_UPDATE_FLAG_PET_AURAS = 0x00080000, // [see GROUP_UPDATE_FLAG_AURAS]
- GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00100000, // int32 (vehicle seat id)
- GROUP_UPDATE_FLAG_PHASE = 0x00200000, // int32 (unk), uint32 (phase count), for (count) uint16(phaseId)
-
- GROUP_UPDATE_PET = GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID |
- GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE |
- GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER | GROUP_UPDATE_FLAG_PET_AURAS, // all pet flags
- GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
- GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER |
- GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION |
- GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_PET | GROUP_UPDATE_FLAG_PHASE // all known flags, except UNK100 and VEHICLE_SEAT
+ GROUP_UPDATE_FLAG_UNK704 = 0x00000001, // uint8[2] (unk)
+ GROUP_UPDATE_FLAG_STATUS = 0x00000002, // uint16 (GroupMemberStatusFlag)
+ GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000004, // uint8 (PowerType)
+ GROUP_UPDATE_FLAG_UNK322 = 0x00000008, // uint16 (unk)
+ GROUP_UPDATE_FLAG_CUR_HP = 0x00000010, // uint32 (HP)
+ GROUP_UPDATE_FLAG_MAX_HP = 0x00000020, // uint32 (max HP)
+ GROUP_UPDATE_FLAG_CUR_POWER = 0x00000040, // int16 (power value)
+ GROUP_UPDATE_FLAG_MAX_POWER = 0x00000080, // int16 (max power value)
+ GROUP_UPDATE_FLAG_LEVEL = 0x00000100, // uint16 (level value)
+ GROUP_UPDATE_FLAG_UNK200000 = 0x00000200, // int16 (unk)
+ GROUP_UPDATE_FLAG_ZONE = 0x00000400, // uint16 (zone id)
+ GROUP_UPDATE_FLAG_UNK2000000 = 0x00000800, // int16 (unk)
+ GROUP_UPDATE_FLAG_UNK4000000 = 0x00001000, // int32 (unk)
+ GROUP_UPDATE_FLAG_POSITION = 0x00002000, // uint16 (x), uint16 (y), uint16 (z)
+ GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00104000, // int32 (vehicle seat id)
+ GROUP_UPDATE_FLAG_AURAS = 0x00008000, // uint8 (unk), uint64 (mask), uint32 (count), for each bit set: uint32 (spell id) + uint16 (AuraFlags) (if has flags Scalable -> 3x int32 (bps))
+ GROUP_UPDATE_FLAG_PET = 0x00010000, // complex (pet)
+ GROUP_UPDATE_FLAG_PHASE = 0x00020000, // int32 (unk), uint32 (phase count), for (count) uint16(phaseId)
+
+ GROUP_UPDATE_FULL = GROUP_UPDATE_FLAG_UNK704 | GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_POWER_TYPE |
+ GROUP_UPDATE_FLAG_UNK322 | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP |
+ GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL |
+ GROUP_UPDATE_FLAG_UNK200000 | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_UNK2000000 |
+ GROUP_UPDATE_FLAG_UNK4000000 | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_VEHICLE_SEAT |
+ GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET | GROUP_UPDATE_FLAG_PHASE // all known flags
+};
+
+enum GroupUpdatePetFlags
+{
+ GROUP_UPDATE_FLAG_PET_NONE = 0x00000000, // nothing
+ GROUP_UPDATE_FLAG_PET_GUID = 0x00000001, // ObjectGuid (pet guid)
+ GROUP_UPDATE_FLAG_PET_NAME = 0x00000002, // cstring (name, NULL terminated string)
+ GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00000004, // uint16 (model id)
+ GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00000008, // uint32 (HP)
+ GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00000010, // uint32 (max HP)
+ GROUP_UPDATE_FLAG_PET_AURAS = 0x00000020, // [see GROUP_UPDATE_FLAG_AURAS]
+
+ GROUP_UPDATE_PET_FULL = GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID |
+ GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_AURAS // all pet flags
};
class Roll : public LootValidatorRef
@@ -160,6 +174,18 @@ struct InstanceGroupBind
InstanceGroupBind() : save(NULL), perm(false) { }
};
+struct RaidMarker
+{
+ WorldLocation Location;
+ ObjectGuid TransportGUID;
+
+ RaidMarker(uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid = ObjectGuid::Empty)
+ {
+ Location.WorldRelocate(mapId, positionX, positionY, positionZ);
+ TransportGUID = transportGuid;
+ }
+};
+
/** request member stats checken **/
/// @todo uninvite people that not accepted invite
class Group
@@ -169,9 +195,11 @@ class Group
{
ObjectGuid guid;
std::string name;
+ uint8 _class;
uint8 group;
uint8 flags;
uint8 roles;
+ bool readyChecked;
};
typedef std::list<MemberSlot> MemberSlotList;
typedef MemberSlotList::const_iterator member_citerator;
@@ -197,7 +225,7 @@ class Group
bool AddLeaderInvite(Player* player);
bool AddMember(Player* player);
bool RemoveMember(ObjectGuid guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker = ObjectGuid::Empty, const char* reason = NULL);
- void ChangeLeader(ObjectGuid guid);
+ void ChangeLeader(ObjectGuid guid, int8 partyIndex = 0);
void SetLootMethod(LootMethod method);
void SetLooterGuid(ObjectGuid guid);
void SetMasterLooterGuid(ObjectGuid guid);
@@ -205,6 +233,31 @@ class Group
void SetLootThreshold(ItemQualities threshold);
void Disband(bool hideDestroy = false);
void SetLfgRoles(ObjectGuid guid, uint8 roles);
+ uint8 GetLfgRoles(ObjectGuid guid);
+ void SetEveryoneIsAssistant(bool apply);
+
+ // Update
+ void Update(uint32 diff);
+ void UpdateReadyCheck(uint32 diff);
+
+ // Ready check
+ void StartReadyCheck(ObjectGuid starterGuid, int8 partyIndex, uint32 duration = READYCHECK_DURATION);
+ void EndReadyCheck();
+
+ bool IsReadyCheckStarted(void) const { return m_readyCheckStarted; }
+ bool IsReadyCheckCompleted(void) const;
+
+ void SetOfflineMembersReadyChecked(void);
+ void SetMemberReadyCheck(ObjectGuid guid, bool ready);
+ void SetMemberReadyCheck(MemberSlot* slot, bool ready);
+
+ void SetMemberReadyChecked(MemberSlot* slot);
+ void ResetMemberReadyChecked(void);
+
+ // Raid Markers
+ void AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid = ObjectGuid::Empty);
+ void DeleteRaidMarker(uint8 markerId);
+ void SendRaidMarkersChanged(WorldSession* session = nullptr, int8 partyIndex = 0);
// properties accessories
bool IsFull() const;
@@ -221,7 +274,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;
@@ -254,7 +307,8 @@ class Group
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(Battleground const* bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid& errorGuid);
void ChangeMembersGroup(ObjectGuid guid, uint8 group);
- void SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid);
+ void SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid);
+ void SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy, uint8 partyIndex);
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag);
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag);
@@ -269,7 +323,7 @@ class Group
// -no description-
//void SendInit(WorldSession* session);
- void SendTargetIconList(WorldSession* session);
+ void SendTargetIconList(WorldSession* session, int8 partyIndex = 0);
void SendUpdate();
void SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot* slot = NULL);
void UpdatePlayerOutOfRange(Player* player);
@@ -290,8 +344,6 @@ class Group
void BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignoredPlayer = ObjectGuid::Empty);
void BroadcastAddonMessagePacket(WorldPacket const* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignore = ObjectGuid::Empty);
- void BroadcastReadyCheck(WorldPacket const* packet);
- void OfflineReadyCheck();
/*********************************************************/
/*** LOOT SYSTEM ***/
@@ -351,7 +403,7 @@ class Group
Difficulty m_legacyRaidDifficulty;
Battleground* m_bgGroup;
Battlefield* m_bfGroup;
- ObjectGuid m_targetIcons[TARGETICONCOUNT];
+ ObjectGuid m_targetIcons[TARGET_ICONS_COUNT];
LootMethod m_lootMethod;
ItemQualities m_lootThreshold;
ObjectGuid m_looterGuid;
@@ -363,5 +415,13 @@ class Group
uint32 m_counter; // used only in SMSG_GROUP_LIST
uint32 m_maxEnchantingLevel;
uint32 m_dbStoreId; // Represents the ID used in database (Can be reused by other groups if group was disbanded)
+
+ // Ready Check
+ bool m_readyCheckStarted;
+ int32 m_readyCheckTimer;
+
+ // Raid markers
+ std::array<std::unique_ptr<RaidMarker>, RAID_MARKERS_COUNT> m_markers;
+ uint32 m_activeMarkers;
};
#endif
diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp
index f0c764e7269..7fb239cec48 100644
--- a/src/server/game/Groups/GroupMgr.cpp
+++ b/src/server/game/Groups/GroupMgr.cpp
@@ -233,3 +233,10 @@ void GroupMgr::LoadGroups()
TC_LOG_INFO("server.loading", ">> Loaded %u group-instance saves in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
}
+
+void GroupMgr::Update(uint32 diff)
+{
+ for (GroupContainer::iterator itr = GroupStore.begin(); itr != GroupStore.end(); itr++)
+ if (itr->second)
+ itr->second->Update(diff);
+}
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
index 6aafe77432c..2fdd6d978e9 100644
--- a/src/server/game/Groups/GroupMgr.h
+++ b/src/server/game/Groups/GroupMgr.h
@@ -50,6 +50,8 @@ public:
void AddGroup(Group* group);
void RemoveGroup(Group* group);
+ void Update(uint32 diff);
+
protected:
ObjectGuid::LowType NextGroupId;
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index c5812999490..d4ba420d44d 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -678,13 +678,23 @@ void EmblemInfo::ReadPacket(WorldPackets::Guild::SaveGuildEmblem& packet)
m_backgroundColor = packet.Bg;
}
-void EmblemInfo::LoadFromDB(Field* fields)
+bool EmblemInfo::ValidateEmblemColors()
+{
+ return sGuildColorBackgroundStore.LookupEntry(m_backgroundColor) &&
+ sGuildColorBorderStore.LookupEntry(m_borderColor) &&
+ sGuildColorEmblemStore.LookupEntry(m_color);
+
+}
+
+bool EmblemInfo::LoadFromDB(Field* fields)
{
m_style = fields[3].GetUInt8();
m_color = fields[4].GetUInt8();
m_borderStyle = fields[5].GetUInt8();
m_borderColor = fields[6].GetUInt8();
m_backgroundColor = fields[7].GetUInt8();
+
+ return ValidateEmblemColors();
}
void EmblemInfo::SaveToDB(ObjectGuid::LowType guildId) const
@@ -1602,11 +1612,11 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
}
// Invited player cannot be in another guild
- /*if (pInvitee->GetGuildId())
+ if (pInvitee->GetGuildId())
{
SendCommandResult(session, GUILD_COMMAND_INVITE_PLAYER, ERR_ALREADY_IN_GUILD_S, name);
return;
- }*/
+ }
// Invited player cannot be invited
if (pInvitee->GetGuildIdInvited())
@@ -2244,7 +2254,14 @@ bool Guild::LoadFromDB(Field* fields)
m_id = fields[0].GetUInt64();
m_name = fields[1].GetString();
m_leaderGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64());
- m_emblemInfo.LoadFromDB(fields);
+
+ if (!m_emblemInfo.LoadFromDB(fields))
+ {
+ TC_LOG_ERROR("guild", "Guild " UI64FMTD " has invalid emblem colors (Background: %u, Border: %u, Emblem: %u), skipped.",
+ m_id, m_emblemInfo.GetBackgroundColor(), m_emblemInfo.GetBorderColor(), m_emblemInfo.GetColor());
+ return false;
+ }
+
m_info = fields[8].GetString();
m_motd = fields[9].GetString();
m_createdDate = time_t(fields[10].GetUInt32());
@@ -2466,7 +2483,7 @@ void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::strin
if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), nullptr, msg);
+ packet.Initialize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, Language(language), session->GetPlayer(), nullptr, msg);
WorldPacket const* data = packet.Write();
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindConnectedPlayer())
@@ -2481,7 +2498,7 @@ void Guild::BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::
if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, LANG_ADDON, session->GetPlayer(), nullptr, msg, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, LANG_ADDON, session->GetPlayer(), nullptr, msg, 0, "", DEFAULT_LOCALE, prefix);
WorldPacket const* data = packet.Write();
for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player* player = itr->second->FindPlayer())
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index 42951320885..777147f2595 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -266,9 +266,10 @@ class EmblemInfo
public:
EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { }
- void LoadFromDB(Field* fields);
+ bool LoadFromDB(Field* fields);
void SaveToDB(ObjectGuid::LowType guildId) const;
void ReadPacket(WorldPackets::Guild::SaveGuildEmblem& packet);
+ bool ValidateEmblemColors();
uint32 GetStyle() const { return m_style; }
uint32 GetColor() const { return m_color; }
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index 0d9f292c4c2..88f45056187 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -174,7 +174,7 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell
}
if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() ||
- item->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) ||
+ item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) ||
item->GetCount() < packetItem.UseCount)
{
SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index e7818a841aa..7b22d46d67b 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -236,6 +236,26 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CURRENCY, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES, stmt);
+
return res;
}
@@ -2554,25 +2574,18 @@ void WorldSession::SendCharRename(ResponseCodes result, WorldPackets::Character:
void WorldSession::SendCharCustomize(ResponseCodes result, WorldPackets::Character::CharCustomizeInfo const* customizeInfo)
{
- /// @todo: fix 6.x implementation
- (void)result;
- (void)customizeInfo;
- /*
- WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1 + 8 + customizeInfo.NewName.size() + 1 + 6);
- data << uint8(result);
if (result == RESPONSE_SUCCESS)
{
- data << customizeInfo.Guid;
- data << customizeInfo.NewName;
- data << uint8(customizeInfo.Gender);
- data << uint8(customizeInfo.Skin);
- data << uint8(customizeInfo.Face);
- data << uint8(customizeInfo.HairStyle);
- data << uint8(customizeInfo.HairColor);
- data << uint8(customizeInfo.FacialHair);
+ WorldPackets::Character::CharCustomizeResponse response(customizeInfo);
+ SendPacket(response.Write());
+ }
+ else
+ {
+ WorldPackets::Character::CharCustomizeFailed failed;
+ failed.Result = uint8(result);
+ failed.CharGUID = customizeInfo->CharGUID;
+ SendPacket(failed.Write());
}
- SendPacket(&data);
- */
}
void WorldSession::SendCharFactionChange(ResponseCodes result, WorldPackets::Character::CharRaceOrFactionChangeInfo const* factionChangeInfo)
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index b5550c2c073..b9fd383b19d 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -288,7 +288,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false, group->GetMemberGroup(GetPlayer()->GetGUID()));
break;
}
@@ -320,8 +320,8 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
}
case CHAT_MSG_RAID:
{
- Group* group = GetPlayer()->GetOriginalGroup();
- if (!group)
+ Group* group = GetPlayer()->GetGroup();
+ if (!group || !group->isRaidGroup() || group->isBGGroup())
return;
if (group->IsLeader(GetPlayer()->GetGUID()))
@@ -330,7 +330,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -344,7 +344,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
WorldPackets::Chat::Chat packet;
//in battleground, raid warning is sent only to players in battleground - code is ok
- packet.Initalize(CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
+ packet.Initialize(CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -381,7 +381,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -484,7 +484,7 @@ void WorldSession::HandleChatAddonMessage(ChatMsg type, std::string prefix, std:
}
WorldPackets::Chat::Chat packet;
- packet.Initalize(type, LANG_ADDON, sender, nullptr, text, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(type, LANG_ADDON, sender, nullptr, text, 0, "", DEFAULT_LOCALE, prefix);
group->BroadcastAddonMessagePacket(packet.Write(), prefix, true, subGroup, sender->GetGUID());
break;
}
@@ -666,7 +666,7 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData)
return;
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_IGNORED, LANG_UNIVERSAL, _player, _player, GetPlayer()->GetName());
+ packet.Initialize(CHAT_MSG_IGNORED, LANG_UNIVERSAL, _player, _player, GetPlayer()->GetName());
player->SendDirectMessage(packet.Write());
}
diff --git a/src/server/game/Handlers/GarrisonHandler.cpp b/src/server/game/Handlers/GarrisonHandler.cpp
new file mode 100644
index 00000000000..54c7f4242fd
--- /dev/null
+++ b/src/server/game/Handlers/GarrisonHandler.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 "WorldSession.h"
+#include "Garrison.h"
+#include "GarrisonPackets.h"
+
+void WorldSession::HandleGetGarrisonInfo(WorldPackets::Garrison::GetGarrisonInfo& /*getGarrisonInfo*/)
+{
+ if (Garrison* garrison = _player->GetGarrison())
+ garrison->SendInfo();
+}
+
+void WorldSession::HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::GarrisonPurchaseBuilding& garrisonPurchaseBuilding)
+{
+ if (!_player->GetNPCIfCanInteractWith(garrisonPurchaseBuilding.NpcGUID, UNIT_NPC_FLAG_GARRISON_ARCHITECT))
+ return;
+
+ if (Garrison* garrison = _player->GetGarrison())
+ garrison->PlaceBuilding(garrisonPurchaseBuilding.PlotInstanceID, garrisonPurchaseBuilding.BuildingID);
+}
+
+void WorldSession::HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction)
+{
+ if (!_player->GetNPCIfCanInteractWith(garrisonCancelConstruction.NpcGUID, UNIT_NPC_FLAG_GARRISON_ARCHITECT))
+ return;
+
+ if (Garrison* garrison = _player->GetGarrison())
+ garrison->CancelBuildingConstruction(garrisonCancelConstruction.PlotInstanceID);
+}
+
+void WorldSession::HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& /*garrisonRequestBlueprintAndSpecializationData*/)
+{
+ if (Garrison* garrison = _player->GetGarrison())
+ garrison->SendBlueprintAndSpecializationData();
+}
+
+void WorldSession::HandleGarrisonGetBuildingLandmarks(WorldPackets::Garrison::GarrisonGetBuildingLandmarks& /*garrisonGetBuildingLandmarks*/)
+{
+ if (Garrison* garrison = _player->GetGarrison())
+ garrison->SendBuildingLandmarks(_player);
+}
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 9552c9a0655..eefe89fef74 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -35,6 +35,7 @@
#include "SpellAuraEffects.h"
#include "MiscPackets.h"
#include "LootPackets.h"
+#include "PartyPackets.h"
class Aura;
@@ -51,103 +52,59 @@ class Aura;
void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val /* = 0 */)
{
- WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4 + 8);
- data << uint32(operation);
- data << member;
- data << uint32(res);
- data << uint32(val); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S)
- data << uint64(0); // player who caused error (in some cases).
-
- SendPacket(&data);
-}
-
-void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
-{
- ObjectGuid crossRealmGuid; // unused
-
- recvData.read_skip<uint32>(); // Non-zero in cross realm invites
- recvData.read_skip<uint32>(); // Always 0
-
- crossRealmGuid[2] = recvData.ReadBit();
- crossRealmGuid[7] = recvData.ReadBit();
-
- uint8 realmLen = recvData.ReadBits(9);
-
- crossRealmGuid[3] = recvData.ReadBit();
-
- uint8 nameLen = recvData.ReadBits(10);
-
- crossRealmGuid[5] = recvData.ReadBit();
- crossRealmGuid[4] = recvData.ReadBit();
- crossRealmGuid[6] = recvData.ReadBit();
- crossRealmGuid[0] = recvData.ReadBit();
- crossRealmGuid[1] = recvData.ReadBit();
+ WorldPackets::Party::PartyCommandResult packet;
- recvData.ReadByteSeq(crossRealmGuid[4]);
- recvData.ReadByteSeq(crossRealmGuid[7]);
- recvData.ReadByteSeq(crossRealmGuid[6]);
+ packet.Name = member;
+ packet.Command = uint8(operation);
+ packet.Result = uint8(res);
+ packet.ResultData = val;
+ packet.ResultGUID = ObjectGuid::Empty;
- std::string memberName, realmName;
- memberName = recvData.ReadString(nameLen);
- realmName = recvData.ReadString(realmLen); // unused
-
- recvData.ReadByteSeq(crossRealmGuid[1]);
- recvData.ReadByteSeq(crossRealmGuid[0]);
- recvData.ReadByteSeq(crossRealmGuid[5]);
- recvData.ReadByteSeq(crossRealmGuid[3]);
- recvData.ReadByteSeq(crossRealmGuid[2]);
-
- // attempt add selected player
-
- // cheating
- if (!normalizePlayerName(memberName))
- {
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
- return;
- }
+ SendPacket(packet.Write());
+}
- Player* player = ObjectAccessor::FindPlayerByName(memberName);
+void WorldSession::HandlePartyInviteOpcode(WorldPackets::Party::PartyInviteClient& packet)
+{
+ Player* player = ObjectAccessor::FindPlayerByName(packet.TargetName);
// no player
if (!player)
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, packet.TargetName, ERR_BAD_PLAYER_NAME_S);
return;
}
// restrict invite to GMs
if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->IsGameMaster() && player->IsGameMaster())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_BAD_PLAYER_NAME_S);
return;
}
// can't group with
if (!GetPlayer()->IsGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PLAYER_WRONG_FACTION);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_PLAYER_WRONG_FACTION);
return;
}
if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_TARGET_NOT_IN_INSTANCE_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_TARGET_NOT_IN_INSTANCE_S);
return;
}
// just ignore us
if (player->GetInstanceId() != 0 && player->GetDungeonDifficultyID() != GetPlayer()->GetDungeonDifficultyID())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_IGNORING_YOU_S);
return;
}
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUID()))
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_IGNORING_YOU_S);
return;
}
- ObjectGuid invitedGuid = player->GetGUID();
-
Group* group = GetPlayer()->GetGroup();
if (group && group->isBGGroup())
group = GetPlayer()->GetOriginalGroup();
@@ -155,67 +112,18 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
Group* group2 = player->GetGroup();
if (group2 && group2->isBGGroup())
group2 = player->GetOriginalGroup();
+
// player already in another group or invited
if (group2 || player->GetGroupInvite())
{
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_ALREADY_IN_GROUP_S);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_ALREADY_IN_GROUP_S);
if (group2)
{
// tell the player that they were invited but it failed as they were already in a group
- WorldPacket data(SMSG_PARTY_INVITE, 45);
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[0]);
- data.WriteBit(invitedGuid[3]);
- data.WriteBit(invitedGuid[2]);
-
- data.WriteBit(0); // Inverse already in group
-
- data.WriteBit(invitedGuid[6]);
- data.WriteBit(invitedGuid[5]);
-
- data.WriteBits(0, 9); // Realm name
-
- data.WriteBit(invitedGuid[4]);
-
- data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
-
- data.WriteBits(0, 24); // Count 2
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[1]);
- data.WriteBit(invitedGuid[7]);
-
- data.FlushBits();
-
- data.WriteByteSeq(invitedGuid[1]);
- data.WriteByteSeq(invitedGuid[4]);
-
- data << int32(getMSTime());
- data << int32(0);
- data << int32(0);
-
- data.WriteByteSeq(invitedGuid[6]);
- data.WriteByteSeq(invitedGuid[0]);
- data.WriteByteSeq(invitedGuid[2]);
- data.WriteByteSeq(invitedGuid[3]);
-
- // for count2 { int32(0) }
-
- data.WriteByteSeq(invitedGuid[5]);
-
- // data.append(realm name);
-
- data.WriteByteSeq(invitedGuid[7]);
-
- data.WriteString(GetPlayer()->GetName()); // inviter name
-
- data << int32(0);
-
- player->GetSession()->SendPacket(&data);
+ WorldPackets::Party::PartyInvite partyInvite;
+ partyInvite.Initialize(GetPlayer(), packet.ProposedRoles, false);
+ player->GetSession()->SendPacket(partyInvite.Write());
}
return;
@@ -264,79 +172,21 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
}
}
- // ok, we do it
- WorldPacket data(SMSG_PARTY_INVITE, 45);
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[0]);
- data.WriteBit(invitedGuid[3]);
- data.WriteBit(invitedGuid[2]);
-
- data.WriteBit(1); // Inverse already in group
-
- data.WriteBit(invitedGuid[6]);
- data.WriteBit(invitedGuid[5]);
-
- data.WriteBits(0, 9); // Realm name
-
- data.WriteBit(invitedGuid[4]);
-
- data.WriteBits(GetPlayer()->GetName().size(), 7); // Inviter name length
-
- data.WriteBits(0, 24); // Count 2
-
- data.WriteBit(0);
-
- data.WriteBit(invitedGuid[1]);
- data.WriteBit(invitedGuid[7]);
-
- data.FlushBits();
+ WorldPackets::Party::PartyInvite partyInvite;
+ partyInvite.Initialize(GetPlayer(), packet.ProposedRoles, true);
+ player->GetSession()->SendPacket(partyInvite.Write());
- data.WriteByteSeq(invitedGuid[1]);
- data.WriteByteSeq(invitedGuid[4]);
-
- data << int32(getMSTime());
- data << int32(0);
- data << int32(0);
-
- data.WriteByteSeq(invitedGuid[6]);
- data.WriteByteSeq(invitedGuid[0]);
- data.WriteByteSeq(invitedGuid[2]);
- data.WriteByteSeq(invitedGuid[3]);
-
- // for count2 { int32(0) }
-
- data.WriteByteSeq(invitedGuid[5]);
-
- // data.append(realm name);
-
- data.WriteByteSeq(invitedGuid[7]);
-
- data.WriteString(GetPlayer()->GetName());
-
- data << int32(0);
-
- player->GetSession()->SendPacket(&data);
-
- SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PARTY_RESULT_OK);
+ SendPartyResult(PARTY_OP_INVITE, player->GetName(), ERR_PARTY_RESULT_OK);
}
-void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
+void WorldSession::HandlePartyInviteResponseOpcode(WorldPackets::Party::PartyInviteResponse& packet)
{
- recvData.ReadBit(); // unk always 0
- bool accept = recvData.ReadBit();
-
- // Never actually received?
- /*if (accept)
- recvData.read_skip<uint32>(); // unk*/
-
Group* group = GetPlayer()->GetGroupInvite();
if (!group)
return;
- if (accept)
+ if (packet.Accept)
{
// Remove player from invitees in any case
group->RemoveInvite(GetPlayer());
@@ -391,28 +241,22 @@ void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
return;
// report
- WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().size());
- data << GetPlayer()->GetName();
- leader->GetSession()->SendPacket(&data);
+ WorldPackets::Party::GroupDecline decline(GetPlayer()->GetName());
+ leader->GetSession()->SendPacket(decline.Write());
}
}
-void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
+void WorldSession::HandlePartyUninviteOpcode(WorldPackets::Party::PartyUninvite& packet)
{
- ObjectGuid guid;
- std::string reason;
- recvData >> guid;
- recvData >> reason;
-
- //can't uninvite yourself
- if (guid == GetPlayer()->GetGUID())
+ // can't uninvite yourself
+ if (packet.TargetGUID == GetPlayer()->GetGUID())
{
TC_LOG_ERROR("network", "WorldSession::HandleGroupUninviteGuidOpcode: leader %s (%s) tried to uninvite himself from the group.",
GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str());
return;
}
- PartyResult res = GetPlayer()->CanUninviteFromGroup(guid);
+ PartyResult res = GetPlayer()->CanUninviteFromGroup(packet.TargetGUID);
if (res != ERR_PARTY_RESULT_OK)
{
SendPartyResult(PARTY_OP_UNINVITE, "", res);
@@ -423,13 +267,13 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
// grp is checked already above in CanUninviteFromGroup()
ASSERT(grp);
- if (grp->IsMember(guid))
+ if (grp->IsMember(packet.TargetGUID))
{
- Player::RemoveFromGroup(grp, guid, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID(), reason.c_str());
+ Player::RemoveFromGroup(grp, packet.TargetGUID, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID(), packet.Reason.c_str());
return;
}
- if (Player* player = grp->GetInvited(guid))
+ if (Player* player = grp->GetInvited(packet.TargetGUID))
{
player->UninviteFromGroup();
return;
@@ -438,12 +282,9 @@ void WorldSession::HandleGroupUninviteOpcode(WorldPacket& recvData)
SendPartyResult(PARTY_OP_UNINVITE, "", ERR_TARGET_NOT_IN_GROUP_S);
}
-void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetPartyLeaderOpcode(WorldPackets::Party::SetPartyLeader& packet)
{
- ObjectGuid guid;
- recvData >> guid;
-
- Player* player = ObjectAccessor::FindConnectedPlayer(guid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(packet.TargetGUID);
Group* group = GetPlayer()->GetGroup();
if (!group || !player)
@@ -453,87 +294,35 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
return;
// Everything's fine, accepted.
- group->ChangeLeader(guid);
+ group->ChangeLeader(packet.TargetGUID, packet.PartyIndex);
group->SendUpdate();
}
-void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetRoleOpcode(WorldPackets::Party::SetRole& packet)
{
- uint32 newRole;
- ObjectGuid guid1; // Assigner GUID
- ObjectGuid guid2; // Target GUID
-
- guid1 = GetPlayer()->GetGUID();
-
- recvData >> newRole;
-
- guid2[2] = recvData.ReadBit();
- guid2[6] = recvData.ReadBit();
- guid2[3] = recvData.ReadBit();
- guid2[7] = recvData.ReadBit();
- guid2[5] = recvData.ReadBit();
- guid2[1] = recvData.ReadBit();
- guid2[0] = recvData.ReadBit();
- guid2[4] = recvData.ReadBit();
-
- recvData.ReadByteSeq(guid2[6]);
- recvData.ReadByteSeq(guid2[4]);
- recvData.ReadByteSeq(guid2[1]);
- recvData.ReadByteSeq(guid2[3]);
- recvData.ReadByteSeq(guid2[0]);
- recvData.ReadByteSeq(guid2[5]);
- recvData.ReadByteSeq(guid2[2]);
- recvData.ReadByteSeq(guid2[7]);
-
- WorldPacket data(SMSG_ROLE_CHANGED_INFORM, 24);
-
- data.WriteBit(guid1[1]);
- data.WriteBit(guid2[0]);
- data.WriteBit(guid2[2]);
- data.WriteBit(guid2[4]);
- data.WriteBit(guid2[7]);
- data.WriteBit(guid2[3]);
- data.WriteBit(guid1[7]);
- data.WriteBit(guid2[5]);
- data.WriteBit(guid1[5]);
- data.WriteBit(guid1[4]);
- data.WriteBit(guid1[3]);
- data.WriteBit(guid2[6]);
- data.WriteBit(guid1[2]);
- data.WriteBit(guid1[6]);
- data.WriteBit(guid2[1]);
- data.WriteBit(guid1[0]);
-
- data.WriteByteSeq(guid1[7]);
- data.WriteByteSeq(guid2[3]);
- data.WriteByteSeq(guid1[6]);
- data.WriteByteSeq(guid2[4]);
- data.WriteByteSeq(guid2[0]);
- data << uint32(newRole); // New Role
- data.WriteByteSeq(guid2[6]);
- data.WriteByteSeq(guid2[2]);
- data.WriteByteSeq(guid1[0]);
- data.WriteByteSeq(guid1[4]);
- data.WriteByteSeq(guid2[1]);
- data.WriteByteSeq(guid1[3]);
- data.WriteByteSeq(guid1[5]);
- data.WriteByteSeq(guid1[2]);
- data.WriteByteSeq(guid2[5]);
- data.WriteByteSeq(guid2[7]);
- data.WriteByteSeq(guid1[1]);
- data << uint32(0); // Old Role
-
- if (Group* group = GetPlayer()->GetGroup())
+ WorldPackets::Party::RoleChangedInform roleChangedInform;
+
+ Group* group = GetPlayer()->GetGroup();
+ uint8 oldRole = group ? group->GetLfgRoles(packet.TargetGUID) : 0;
+ if (oldRole == packet.Role)
+ return;
+
+ roleChangedInform.PartyIndex = packet.PartyIndex;
+ roleChangedInform.From = GetPlayer()->GetGUID();
+ roleChangedInform.ChangedUnit = packet.TargetGUID;
+ roleChangedInform.OldRole = oldRole;
+ roleChangedInform.NewRole = packet.Role;
+
+ if (group)
{
- /// @todo probably should be sent only if (oldRole != newRole)
- group->BroadcastPacket(&data, false);
- group->SetLfgRoles(guid2, newRole);
+ group->BroadcastPacket(roleChangedInform.Write(), false);
+ group->SetLfgRoles(packet.TargetGUID, packet.Role);
}
else
- SendPacket(&data);
+ SendPacket(roleChangedInform.Write());
}
-void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleLeaveGroupOpcode(WorldPackets::Party::LeaveGroup& /*packet*/)
{
Group* grp = GetPlayer()->GetGroup();
if (!grp)
@@ -554,13 +343,8 @@ void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
GetPlayer()->RemoveFromGroup(GROUP_REMOVEMETHOD_LEAVE);
}
-void WorldSession::HandleLootMethodOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetLootMethodOpcode(WorldPackets::Party::SetLootMethod& packet)
{
- uint32 lootMethod;
- ObjectGuid lootMaster;
- uint32 lootThreshold;
- recvData >> lootMethod >> lootMaster >> lootThreshold;
-
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
@@ -569,20 +353,20 @@ void WorldSession::HandleLootMethodOpcode(WorldPacket& recvData)
if (!group->IsLeader(GetPlayer()->GetGUID()))
return;
- if (lootMethod > NEED_BEFORE_GREED)
+ if (packet.LootMethod > NEED_BEFORE_GREED)
return;
- if (lootThreshold < ITEM_QUALITY_UNCOMMON || lootThreshold > ITEM_QUALITY_ARTIFACT)
+ if (packet.LootThreshold < ITEM_QUALITY_UNCOMMON || packet.LootThreshold > ITEM_QUALITY_ARTIFACT)
return;
- if (lootMethod == MASTER_LOOT && !group->IsMember(lootMaster))
+ if (packet.LootMethod == MASTER_LOOT && !group->IsMember(packet.LootMasterGUID))
return;
/********************/
// everything's fine, do it
- group->SetLootMethod((LootMethod)lootMethod);
- group->SetMasterLooterGuid(lootMaster);
- group->SetLootThreshold((ItemQualities)lootThreshold);
+ group->SetLootMethod((LootMethod)packet.LootMethod);
+ group->SetMasterLooterGuid(packet.LootMasterGUID);
+ group->SetLootThreshold((ItemQualities)packet.LootThreshold);
group->SendUpdate();
}
@@ -605,28 +389,16 @@ void WorldSession::HandleLootRoll(WorldPackets::Loot::LootRoll& packet)
}
}
-void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData)
+void WorldSession::HandleMinimapPingOpcode(WorldPackets::Party::MinimapPingClient& packet)
{
- TC_LOG_DEBUG("network", "WORLD: Received MSG_MINIMAP_PING");
-
if (!GetPlayer()->GetGroup())
return;
- float x, y;
- recvData >> x;
- recvData >> y;
-
- //TC_LOG_DEBUG("misc", "Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
-
- /** error handling **/
- /********************/
-
- // everything's fine, do it
- WorldPacket data(SMSG_MINIMAP_PING, (8+4+4));
- data << GetPlayer()->GetGUID();
- data << float(x);
- data << float(y);
- GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID());
+ WorldPackets::Party::MinimapPing minimapPing;
+ minimapPing.Sender = GetPlayer()->GetGUID();
+ minimapPing.PositionX = packet.PositionX;
+ minimapPing.PositionY = packet.PositionY;
+ GetPlayer()->GetGroup()->BroadcastPacket(minimapPing.Write(), true, -1, GetPlayer()->GetGUID());
}
void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient& packet)
@@ -643,8 +415,6 @@ void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient&
// everything's fine, do it
roll = urand(minimum, maximum);
- //TC_LOG_DEBUG("misc", "ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
-
WorldPackets::Misc::RandomRoll randomRoll;
randomRoll.Min = minimum;
randomRoll.Max = maximum;
@@ -657,44 +427,31 @@ void WorldSession::HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient&
SendPacket(randomRoll.Write());
}
-void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
+void WorldSession::HandleUpdateRaidTargetOpcode(WorldPackets::Party::UpdateRaidTarget& packet)
{
- TC_LOG_DEBUG("network", "WORLD: Received MSG_RAID_TARGET_UPDATE");
-
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- uint8 x;
- recvData >> x;
-
- /** error handling **/
- /********************/
-
- // everything's fine, do it
- if (x == 0xFF) // target icon request
- group->SendTargetIconList(this);
- else // target icon update
+ if (packet.Symbol == 0xFF) // target icon request
+ group->SendTargetIconList(this, packet.PartyIndex);
+ else // target icon update
{
if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
return;
- ObjectGuid guid;
- recvData >> guid;
-
- if (guid.IsPlayer())
+ if (packet.Target.IsPlayer())
{
- Player* target = ObjectAccessor::FindConnectedPlayer(guid);
-
+ Player* target = ObjectAccessor::FindConnectedPlayer(packet.Target);
if (!target || target->IsHostileTo(GetPlayer()))
return;
}
- group->SetTargetIcon(x, _player->GetGUID(), guid);
+ group->SetTargetIcon(packet.Symbol, packet.Target, GetPlayer()->GetGUID(), packet.PartyIndex);
}
}
-void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
+void WorldSession::HandleConvertRaidOpcode(WorldPackets::Party::ConvertRaid& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
@@ -711,71 +468,56 @@ void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK);
// New 4.x: it is now possible to convert a raid to a group if member count is 5 or less
-
- bool toRaid;
- recvData >> toRaid;
-
- if (toRaid)
+ if (packet.Raid)
group->ConvertToRaid();
else
group->ConvertToGroup();
}
-void WorldSession::HandleGroupRequestJoinUpdates(WorldPacket& /*recvData*/)
+void WorldSession::HandleRequestPartyJoinUpdates(WorldPackets::Party::RequestPartyJoinUpdates& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- // does some stuff. dunno what.
+ group->SendTargetIconList(this, packet.PartyIndex);
+ group->SendRaidMarkersChanged(this, packet.PartyIndex);
}
-void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
+void WorldSession::HandleChangeSubGroupOpcode(WorldPackets::Party::ChangeSubGroup& packet)
{
// we will get correct pointer for group here, so we don't have to check if group is BG raid
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- std::string name;
- uint8 groupNr;
- recvData >> name;
- recvData >> groupNr;
-
- if (groupNr >= MAX_RAID_SUBGROUPS)
+ if (packet.NewSubGroup >= MAX_RAID_SUBGROUPS)
return;
ObjectGuid senderGuid = GetPlayer()->GetGUID();
if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
return;
- if (!group->HasFreeSlotSubGroup(groupNr))
+ if (!group->HasFreeSlotSubGroup(packet.NewSubGroup))
return;
- Player* movedPlayer = ObjectAccessor::FindConnectedPlayerByName(name);
- ObjectGuid guid;
-
- if (movedPlayer)
- guid = movedPlayer->GetGUID();
- else
- {
- CharacterDatabase.EscapeString(name);
- guid = ObjectMgr::GetPlayerGUIDByName(name.c_str());
- }
-
- group->ChangeMembersGroup(guid, groupNr);
+ group->ChangeMembersGroup(packet.TargetGUID, packet.NewSubGroup);
}
-void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData)
+void WorldSession::HandleSwapSubGroupsOpcode(WorldPackets::Party::SwapSubGroups& packet)
{
- std::string unk1;
- std::string unk2;
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
+ return;
- recvData >> unk1;
- recvData >> unk2;
+ ObjectGuid senderGuid = GetPlayer()->GetGUID();
+ if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
+ return;
+
+ group->SwapMembersGroups(packet.FirstTarget, packet.SecondTarget);
}
-void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
+void WorldSession::HandleSetAssistantLeaderOpcode(WorldPackets::Party::SetAssistantLeader& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
@@ -784,12 +526,7 @@ void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
if (!group->IsLeader(GetPlayer()->GetGUID()))
return;
- ObjectGuid guid;
- bool apply;
- recvData >> guid;
- recvData >> apply;
-
- group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT);
+ group->SetGroupMemberFlag(packet.Target, packet.Apply, MEMBER_FLAG_ASSISTANT);
}
void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData)
@@ -826,509 +563,102 @@ void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData)
group->SendUpdate();
}
-void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
+void WorldSession::HandleDoReadyCheckOpcode(WorldPackets::Party::DoReadyCheck& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- if (recvData.empty()) // request
- {
- /** error handling **/
- if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
- return;
- /********************/
-
- // everything's fine, do it
- WorldPacket data(SMSG_READY_CHECK_STARTED, 8);
- data << GetPlayer()->GetGUID();
- group->BroadcastPacket(&data, false, -1);
+ /** error handling **/
+ if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
+ return;
+ /********************/
- group->OfflineReadyCheck();
- }
- else // answer
- {
- uint8 state;
- recvData >> state;
-
- // everything's fine, do it
- WorldPacket data(SMSG_READY_CHECK_RESPONSE, 9);
- data << GetPlayer()->GetGUID();
- data << uint8(state);
- group->BroadcastReadyCheck(&data);
- }
+ // everything's fine, do it
+ group->StartReadyCheck(GetPlayer()->GetGUID(), packet.PartyIndex);
}
-void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data)
+void WorldSession::HandleReadyCheckResponseOpcode(WorldPackets::Party::ReadyCheckResponseClient& packet)
{
- uint32 mask = player->GetGroupUpdateFlag();
-
- if (mask == GROUP_UPDATE_FLAG_NONE)
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
return;
- std::set<uint32> const& phases = player->GetPhases();
-
- if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also
- mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER);
-
- if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
- mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
-
- data->Initialize(SMSG_PARTY_MEMBER_STATE, 80); // average value
- *data << player->GetPackGUID();
- *data << uint32(mask);
-
- if (mask & GROUP_UPDATE_FLAG_STATUS)
- {
- uint16 playerStatus = MEMBER_STATUS_ONLINE;
- if (player->IsPvP())
- playerStatus |= MEMBER_STATUS_PVP;
-
- if (!player->IsAlive())
- {
- if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
- playerStatus |= MEMBER_STATUS_GHOST;
- else
- playerStatus |= MEMBER_STATUS_DEAD;
- }
-
- if (player->IsFFAPvP())
- playerStatus |= MEMBER_STATUS_PVP_FFA;
-
- if (player->isAFK())
- playerStatus |= MEMBER_STATUS_AFK;
-
- if (player->isDND())
- playerStatus |= MEMBER_STATUS_DND;
-
- *data << uint16(playerStatus);
- }
-
- if (mask & GROUP_UPDATE_FLAG_CUR_HP)
- *data << uint32(player->GetHealth());
-
- if (mask & GROUP_UPDATE_FLAG_MAX_HP)
- *data << uint32(player->GetMaxHealth());
-
- Powers powerType = player->getPowerType();
- if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
- *data << uint8(powerType);
-
- if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
- *data << uint16(player->GetPower(powerType));
-
- if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
- *data << uint16(player->GetMaxPower(powerType));
-
- if (mask & GROUP_UPDATE_FLAG_LEVEL)
- *data << uint16(player->getLevel());
-
- if (mask & GROUP_UPDATE_FLAG_ZONE)
- *data << uint16(player->GetZoneId());
-
- if (mask & GROUP_UPDATE_FLAG_UNK100)
- *data << uint16(0);
-
- if (mask & GROUP_UPDATE_FLAG_POSITION)
- {
- *data << uint16(player->GetPositionX());
- *data << uint16(player->GetPositionY());
- *data << uint16(player->GetPositionZ());
- }
-
- if (mask & GROUP_UPDATE_FLAG_AURAS)
- {
- *data << uint8(0);
- uint64 auramask = player->GetAuraUpdateMaskForRaid();
- *data << uint64(auramask);
- *data << uint32(MAX_AURAS); // count
- for (uint32 i = 0; i < MAX_AURAS; ++i)
- {
- if (auramask & (uint64(1) << i))
- {
- AuraApplication const* aurApp = player->GetVisibleAura(i);
- if (!aurApp)
- {
- *data << uint32(0);
- *data << uint16(0);
- continue;
- }
-
- *data << uint32(aurApp->GetBase()->GetId());
- *data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- *data << int32(eff->GetAmount());
- else
- *data << int32(0);
- }
- }
- }
- }
- }
-
- Pet* pet = player->GetPet();
- if (mask & GROUP_UPDATE_FLAG_PET_GUID)
- {
- if (pet)
- *data << pet->GetGUID();
- else
- *data << ObjectGuid::Empty;
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_NAME)
- {
- if (pet)
- *data << pet->GetName();
- else
- *data << uint8(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
- {
- if (pet)
- *data << uint16(pet->GetDisplayId());
- else
- *data << uint16(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
- {
- if (pet)
- *data << uint32(pet->GetHealth());
- else
- *data << uint32(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
- {
- if (pet)
- *data << uint32(pet->GetMaxHealth());
- else
- *data << uint32(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
- {
- if (pet)
- *data << uint8(pet->getPowerType());
- else
- *data << uint8(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
- {
- if (pet)
- *data << uint16(pet->GetPower(pet->getPowerType()));
- else
- *data << uint16(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
- {
- if (pet)
- *data << uint16(pet->GetMaxPower(pet->getPowerType()));
- else
- *data << uint16(0);
- }
-
- if (mask & GROUP_UPDATE_FLAG_PET_AURAS)
- {
- if (pet)
- {
- *data << uint8(0);
- uint64 auramask = pet->GetAuraUpdateMaskForRaid();
- *data << uint64(auramask);
- *data << uint32(MAX_AURAS); // count
- for (uint32 i = 0; i < MAX_AURAS; ++i)
- {
- if (auramask & (uint64(1) << i))
- {
- AuraApplication const* aurApp = pet->GetVisibleAura(i);
- if (!aurApp)
- {
- *data << uint32(0);
- *data << uint16(0);
- continue;
- }
-
- *data << uint32(aurApp->GetBase()->GetId());
- *data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- *data << int32(eff->GetAmount());
- else
- *data << int32(0);
- }
- }
- }
- }
- }
- else
- {
- *data << uint8(0);
- *data << uint64(0);
- }
- }
-
- if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
- {
- if (Vehicle* veh = player->GetVehicle())
- *data << uint32(veh->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
- else
- *data << uint32(0);
-
- }
-
- if (mask & GROUP_UPDATE_FLAG_PHASE)
- {
- *data << uint32(phases.empty() ? 8 : 0);
- *data << uint32(phases.size());
- for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- *data << uint16(*itr);
- }
+ // everything's fine, do it
+ group->SetMemberReadyCheck(GetPlayer()->GetGUID(), packet.IsReady);
}
-/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
-void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
+void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPackets::Party::RequestPartyMemberStats& packet)
{
- ObjectGuid Guid;
- recvData >> Guid;
+ WorldPackets::Party::PartyMemberStats partyMemberStats;
- Player* player = ObjectAccessor::FindConnectedPlayer(Guid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(packet.TargetGUID);
if (!player)
{
- WorldPacket data(SMSG_PARTY_MEMBER_STATE, 3 + 4 + 2);
- data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
- data << Guid.WriteAsPacked();
- data << uint32(GROUP_UPDATE_FLAG_STATUS);
- data << uint16(MEMBER_STATUS_OFFLINE);
- SendPacket(&data);
- return;
- }
-
- Pet* pet = player->GetPet();
- Powers powerType = player->getPowerType();
- std::set<uint32> const& phases = player->GetPhases();
-
- WorldPacket data(SMSG_PARTY_MEMBER_STATE, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8);
- data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
- data << player->GetPackGUID();
-
- uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP
- | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL
- | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS
- | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS;
-
- if (powerType != POWER_MANA)
- updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE;
-
- if (pet)
- updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP
- | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER;
-
- if (player->GetVehicle())
- updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT;
-
- if (!phases.empty())
- updateFlags |= GROUP_UPDATE_FLAG_PHASE;
-
- uint16 playerStatus = MEMBER_STATUS_ONLINE;
- if (player->IsPvP())
- playerStatus |= MEMBER_STATUS_PVP;
-
- if (!player->IsAlive())
- {
- if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
- playerStatus |= MEMBER_STATUS_GHOST;
- else
- playerStatus |= MEMBER_STATUS_DEAD;
- }
-
- if (player->IsFFAPvP())
- playerStatus |= MEMBER_STATUS_PVP_FFA;
-
- if (player->isAFK())
- playerStatus |= MEMBER_STATUS_AFK;
-
- if (player->isDND())
- playerStatus |= MEMBER_STATUS_DND;
-
- data << uint32(updateFlags);
- data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS
- data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP
- data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP
- if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE)
- data << uint8(powerType);
-
- data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER
- data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER
- data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL
- data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE
- data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION
- data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION
- data << uint16(player->GetPositionZ()); // GROUP_UPDATE_FLAG_POSITION
-
- // GROUP_UPDATE_FLAG_AURAS
- data << uint8(1);
- uint64 auramask = 0;
- size_t maskPos = data.wpos();
- data << uint64(auramask); // placeholder
- data << uint32(MAX_AURAS); // count
-
- for (uint8 i = 0; i < MAX_AURAS; ++i)
- {
- if (AuraApplication const* aurApp = player->GetVisibleAura(i))
- {
- auramask |= (uint64(1) << i);
-
- data << uint32(aurApp->GetBase()->GetId());
- data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- data << int32(eff->GetAmount());
- else
- data << int32(0);
- }
- }
- }
- }
-
- data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
- data << pet->GetGUID();
-
- data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME
- data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP)
- data << uint32(pet->GetHealth());
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP)
- data << uint32(pet->GetMaxHealth());
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
- data << (uint8)pet->getPowerType();
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER)
- data << uint16(pet->GetPower(pet->getPowerType()));
-
- if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER)
- data << uint16(pet->GetMaxPower(pet->getPowerType()));
-
- // GROUP_UPDATE_FLAG_PET_AURAS
- uint64 petAuraMask = 0;
- data << uint8(1);
- maskPos = data.wpos();
- data << uint64(petAuraMask); // placeholder
- data << uint32(MAX_AURAS); // count
- if (pet)
- {
- for (uint8 i = 0; i < MAX_AURAS; ++i)
- {
- if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
- {
- petAuraMask |= (uint64(1) << i);
-
- data << uint32(aurApp->GetBase()->GetId());
- data << uint16(aurApp->GetFlags());
-
- if (aurApp->GetFlags() & AFLAG_SCALABLE)
- {
- for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
- data << int32(eff->GetAmount());
- else
- data << int32(0);
- }
- }
- }
- }
- }
-
- data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS
-
- if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
- data << uint32(player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
-
- if (updateFlags & GROUP_UPDATE_FLAG_PHASE)
- {
- data << uint32(phases.empty() ? 8 : 0);
- data << uint32(phases.size());
- for (std::set<uint32>::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
- data << uint16(*itr);
+ partyMemberStats.MemberStats.GUID = packet.TargetGUID;
+ partyMemberStats.MemberStats.Status = MEMBER_STATUS_OFFLINE;
}
+ else
+ partyMemberStats.Initialize(player);
- SendPacket(&data);
+ SendPacket(partyMemberStats.Write());
}
-void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleRequestRaidInfoOpcode(WorldPackets::Party::RequestRaidInfo& /*packet*/)
{
// every time the player checks the character screen
_player->SendRaidInfo();
}
-void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData)
+void WorldSession::HandleOptOutOfLootOpcode(WorldPackets::Party::OptOutOfLoot& packet)
{
- bool passOnLoot;
- recvData >> passOnLoot; // 1 always pass, 0 do not pass
-
// ignore if player not loaded
if (!GetPlayer()) // needed because STATUS_AUTHED
{
- if (passOnLoot)
+ if (packet.PassOnLoot)
TC_LOG_ERROR("network", "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
return;
}
- GetPlayer()->SetPassOnGroupLoot(passOnLoot != 0);
+ GetPlayer()->SetPassOnGroupLoot(packet.PassOnLoot);
}
-void WorldSession::HandleRolePollBeginOpcode(WorldPacket& recvData)
+void WorldSession::HandleInitiateRolePoll(WorldPackets::Party::InitiateRolePoll& packet)
{
Group* group = GetPlayer()->GetGroup();
if (!group)
return;
- if (recvData.empty())
- {
- if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
- return;
+ ObjectGuid guid = GetPlayer()->GetGUID();
+ if (!group->IsLeader(guid) && !group->IsAssistant(guid))
+ return;
- ObjectGuid guid = GetPlayer()->GetGUID();
-
- WorldPacket data(SMSG_ROLE_POLL_INFORM, 8);
- data.WriteBit(guid[1]);
- data.WriteBit(guid[5]);
- data.WriteBit(guid[7]);
- data.WriteBit(guid[3]);
- data.WriteBit(guid[2]);
- data.WriteBit(guid[4]);
- data.WriteBit(guid[0]);
- data.WriteBit(guid[6]);
- data.WriteByteSeq(guid[4]);
- data.WriteByteSeq(guid[7]);
- data.WriteByteSeq(guid[0]);
- data.WriteByteSeq(guid[5]);
- data.WriteByteSeq(guid[1]);
- data.WriteByteSeq(guid[6]);
- data.WriteByteSeq(guid[2]);
- data.WriteByteSeq(guid[3]);
-
- GetPlayer()->GetGroup()->BroadcastPacket(&data, true);
- }
+ WorldPackets::Party::RolePollInform rolePollInform;
+ rolePollInform.From = GetPlayer()->GetGUID();
+ rolePollInform.PartyIndex = packet.PartyIndex;
+ group->BroadcastPacket(rolePollInform.Write(), true);
+}
+
+void WorldSession::HandleSetEveryoneIsAssistant(WorldPackets::Party::SetEveryoneIsAssistant& packet)
+{
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
+ return;
+
+ if (!group->IsLeader(GetPlayer()->GetGUID()))
+ return;
+
+ group->SetEveryoneIsAssistant(packet.EveryoneIsAssistant);
+}
+
+void WorldSession::HandleClearRaidMarker(WorldPackets::Party::ClearRaidMarker& packet)
+{
+ Group* group = GetPlayer()->GetGroup();
+ if (!group)
+ return;
+
+ if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
+ return;
+
+ group->DeleteRaidMarker(packet.MarkerId);
}
diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp
index ad3de84beb5..fbd1d5a7183 100644
--- a/src/server/game/Handlers/GuildHandler.cpp
+++ b/src/server/game/Handlers/GuildHandler.cpp
@@ -191,6 +191,12 @@ void WorldSession::HandleSaveGuildEmblem(WorldPackets::Guild::SaveGuildEmblem& p
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
+ if (!emblemInfo.ValidateEmblemColors())
+ {
+ Guild::SendSaveEmblemResult(this, ERR_GUILDEMBLEM_INVALID_TABARD_COLORS);
+ return;
+ }
+
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetEmblem(this, emblemInfo);
else
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index 9e282582b7d..e6aecff9137 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -295,7 +295,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPackets::Item::DestroyItem& dest
return;
}
- if (item->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_INDESTRUCTIBLE)
+ if (item->GetTemplate()->GetFlags() & ITEM_FLAG_INDESTRUCTIBLE)
{
_player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, NULL, NULL);
return;
@@ -388,7 +388,7 @@ void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet)
// prevent selling item for sellprice when the item is still refundable
// this probably happens when right clicking a refundable item, the client sends both
// CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified)
- if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE))
+ if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE))
return; // Therefore, no feedback to client
// special case at auto sell (sell all)
@@ -494,38 +494,6 @@ void WorldSession::HandleBuybackItem(WorldPackets::Item::BuyBackItem& packet)
_player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, creature, 0, 0);
}
-void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket& recvData)
-{
- ObjectGuid vendorguid, bagguid;
- uint32 item, slot, count;
- uint8 bagslot;
-
- recvData >> vendorguid >> item >> slot >> bagguid >> bagslot >> count;
-
- // client expects count starting at 1, and we send vendorslot+1 to client already
- if (slot > 0)
- --slot;
- else
- return; // cheating
-
- uint8 bag = NULL_BAG; // init for case invalid bagGUID
- Item* bagItem = NULL;
- // find bag slot by bag guid
- if (bagguid == _player->GetGUID())
- bag = INVENTORY_SLOT_BAG_0;
- else
- bagItem = _player->GetItemByGuid(bagguid);
-
- if (bagItem && bagItem->IsBag())
- bag = bagItem->GetSlot();
-
- // bag not found, cheating?
- if (bag == NULL_BAG)
- return;
-
- GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, bag, bagslot);
-}
-
void WorldSession::HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet)
{
// client expects count starting at 1, and we send vendorslot+1 to client already
@@ -623,8 +591,8 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid)
continue;
// Only display items in vendor lists for the team the player is on
- if ((itemTemplate->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) ||
- (itemTemplate->GetFlags2() & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE))
+ if ((itemTemplate->GetFlags2() & ITEM_FLAG2_HORDE_ONLY && _player->GetTeam() == ALLIANCE) ||
+ (itemTemplate->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY && _player->GetTeam() == HORDE))
continue;
// Items sold out are not displayed in list
@@ -748,13 +716,12 @@ void WorldSession::SendEnchantmentLog(ObjectGuid target, ObjectGuid caster, uint
void WorldSession::SendItemEnchantTimeUpdate(ObjectGuid Playerguid, ObjectGuid Itemguid, uint32 slot, uint32 Duration)
{
- // last check 2.0.10
- WorldPacket data(SMSG_ITEM_ENCHANT_TIME_UPDATE, (8+4+4+8));
- data << Itemguid;
- data << uint32(slot);
- data << uint32(Duration);
- data << Playerguid;
- SendPacket(&data);
+ WorldPackets::Item::ItemEnchantTimeUpdate data;
+ data.ItemGuid = Itemguid;
+ data.DurationLeft = Duration;
+ data.Slot = slot;
+ data.OwnerGuid = Playerguid;
+ SendPacket(data.Write());
}
void WorldSession::HandleWrapItem(WorldPackets::Item::WrapItem& packet)
@@ -782,7 +749,7 @@ void WorldSession::HandleWrapItem(WorldPackets::Item::WrapItem& packet)
return;
}
- if (!(gift->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_WRAPPER)) // cheating: non-wrapper wrapper
+ if (!(gift->GetTemplate()->GetFlags() & ITEM_FLAG_WRAPPER)) // cheating: non-wrapper wrapper
{
_player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL);
return;
@@ -872,7 +839,7 @@ void WorldSession::HandleWrapItem(WorldPackets::Item::WrapItem& packet)
}
item->SetGuidValue(ITEM_FIELD_GIFTCREATOR, _player->GetGUID());
- item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED);
+ item->SetUInt32Value(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED);
item->SetState(ITEM_CHANGED, _player);
if (item->GetState() == ITEM_NEW) // save new item, to have alway for `character_gifts` record in `item_instance`
@@ -979,7 +946,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
ItemTemplate const* iGemProto = Gems[i]->GetTemplate();
// unique item (for new and already placed bit removed enchantments
- if (iGemProto->GetFlags() & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED)
+ if (iGemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPED)
{
for (int j = 0; j < MAX_GEM_SOCKETS; ++j)
{
@@ -1094,17 +1061,13 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData)
itemTarget->SendUpdateSockets();
}
-void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recvData)
+void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPackets::Item::CancelTempEnchantment& cancelTempEnchantment)
{
- uint32 slot;
-
- recvData >> slot;
-
// apply only to equipped item
- if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, slot))
+ if (!Player::IsEquipmentPos(INVENTORY_SLOT_BAG_0, cancelTempEnchantment.Slot))
return;
- Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
+ Item* item = GetPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, cancelTempEnchantment.Slot);
if (!item)
return;
@@ -1149,34 +1112,6 @@ void WorldSession::HandleItemRefund(WorldPacket &recvData)
GetPlayer()->RefundItem(item);
}
-/**
- * Handles the packet sent by the client when requesting information about item text.
- *
- * This function is called when player clicks on item which has some flag set
- */
-void WorldSession::HandleItemTextQuery(WorldPacket& recvData )
-{
- ObjectGuid itemGuid;
- recvData >> itemGuid;
-
- TC_LOG_DEBUG("network", "CMSG_ITEM_TEXT_QUERY %s", itemGuid.ToString().c_str());
-
- WorldPacket data(SMSG_QUERY_ITEM_TEXT_RESPONSE, 14); // guess size
-
- if (Item* item = _player->GetItemByGuid(itemGuid))
- {
- data << uint8(0); // has text
- data << itemGuid; // item guid
- data << item->GetText();
- }
- else
- {
- data << uint8(1); // no text
- }
-
- SendPacket(&data);
-}
-
void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
{
Player* player = GetPlayer();
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index c4d3358a333..4a3866cbb1b 100644
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -86,7 +86,7 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData)
{
if (!sLFGMgr->isOptionEnabled(lfg::LFG_OPTION_ENABLE_DUNGEON_FINDER | lfg::LFG_OPTION_ENABLE_RAID_BROWSER) ||
(GetPlayer()->GetGroup() && GetPlayer()->GetGroup()->GetLeaderGUID() != GetPlayer()->GetGUID() &&
- (GetPlayer()->GetGroup()->GetMembersCount() == MAXGROUPSIZE || !GetPlayer()->GetGroup()->isLFGGroup())))
+ (GetPlayer()->GetGroup()->GetMembersCount() == MAX_GROUP_SIZE || !GetPlayer()->GetGroup()->isLFGGroup())))
{
recvData.rfinish();
return;
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 4f7a42c3770..ddd084cbd9d 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -325,7 +325,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
ItemTemplate const* proto = pItem->GetTemplate();
// destroy only 5 items from stack in case prospecting and milling
- if (proto->GetFlags() & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE))
+ if (proto->GetFlags() & (ITEM_FLAG_PROSPECTABLE | ITEM_FLAG_MILLABLE))
{
pItem->m_lootGenerated = false;
pItem->loot.clear();
@@ -341,7 +341,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
else
{
// Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item
- if (pItem->loot.isLooted() || !(proto->GetFlags() & ITEM_PROTO_FLAG_OPENABLE))
+ if (pItem->loot.isLooted() || !(proto->GetFlags() & ITEM_FLAG_OPENABLE))
player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
}
return; // item can be looted only single player
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index b8ac779887b..dd55c6f2f06 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -196,7 +196,7 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet)
if (Item* item = player->GetItemByGuid(att.ItemGUID))
{
ItemTemplate const* itemProto = item->GetTemplate();
- if (!itemProto || !(itemProto->GetFlags() & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT))
+ if (!itemProto || !(itemProto->GetFlags() & ITEM_FLAG_BIND_TO_ACCOUNT))
{
accountBound = false;
break;
@@ -250,13 +250,13 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet)
}
}
- if (item->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION))
+ if (item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
return;
}
- if (packet.Info.Cod && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
+ if (packet.Info.Cod && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))
{
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD);
return;
@@ -636,7 +636,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextIt
if (m->messageType == MAIL_NORMAL)
bodyItem->SetGuidValue(ITEM_FIELD_CREATOR, ObjectGuid::Create<HighGuid::Player>(m->sender));
- bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_MAIL_TEXT_MASK);
+ bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_MAIL_TEXT_MASK);
ItemPosCountVec dest;
uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index b01f0c6c147..0aa941de4e2 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -209,7 +209,7 @@ void WorldSession::HandleWhoOpcode(WorldPackets::Who::WhoRequestPkt& whoRequest)
{
std::string aName;
if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(target->GetZoneId()))
- aName = areaEntry->ZoneName;
+ aName = areaEntry->AreaName_lang;
bool show = false;
for (size_t i = 0; i < wWords.size(); ++i)
@@ -848,12 +848,9 @@ void WorldSession::HandleRealmSplitOpcode(WorldPacket& recvData)
//TC_LOG_DEBUG("response sent %u", unk);
}
-void WorldSession::HandleFarSightOpcode(WorldPacket& recvData)
+void WorldSession::HandleFarSightOpcode(WorldPackets::Misc::FarSight& packet)
{
- bool apply;
- recvData >> apply;
-
- if (apply)
+ if (packet.Enable)
{
TC_LOG_DEBUG("network", "Added FarSight %s to %s", _player->GetGuidValue(PLAYER_FARSIGHT).ToString().c_str(), _player->GetGUID().ToString().c_str());
if (WorldObject* target = _player->GetViewpoint())
@@ -907,7 +904,7 @@ void WorldSession::HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse&
_player->m_timeSyncQueue.pop();
}
-void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/)
+void WorldSession::HandleResetInstancesOpcode(WorldPackets::Instance::ResetInstances& /*packet*/)
{
if (Group* group = _player->GetGroup())
{
@@ -1216,129 +1213,29 @@ void WorldSession::HandleObjectUpdateRescuedOpcode(WorldPackets::Misc::ObjectUpd
_player->m_clientGUIDs.insert(objectUpdateRescued.ObjectGUID);
}
-void WorldSession::HandleSaveCUFProfiles(WorldPacket& recvPacket)
+void WorldSession::HandleSaveCUFProfiles(WorldPackets::Misc::SaveCUFProfiles& packet)
{
- uint8 count = (uint8)recvPacket.ReadBits(20);
-
- if (count > MAX_CUF_PROFILES)
+ if (packet.CUFProfiles.size() > MAX_CUF_PROFILES)
{
TC_LOG_ERROR("entities.player", "HandleSaveCUFProfiles - %s tried to save more than %i CUF profiles. Hacking attempt?", GetPlayerName().c_str(), MAX_CUF_PROFILES);
- recvPacket.rfinish();
return;
}
- CUFProfile* profiles[MAX_CUF_PROFILES];
- uint8 strlens[MAX_CUF_PROFILES];
-
- for (uint8 i = 0; i < count; ++i)
- {
- profiles[i] = new CUFProfile;
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_2 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_10_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_UNK_157 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_HEAL_PREDICTION , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_SPEC_1 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVP , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_POWER_BAR , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_15_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_40_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_PETS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_5_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS, recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_2_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_UNK_156 , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_NON_BOSS_DEBUFFS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_MAIN_TANK_AND_ASSIST , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_AGGRO_HIGHLIGHT , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_3_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_BORDER , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_USE_CLASS_COLORS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_UNK_145 , recvPacket.ReadBit());
- strlens[i] = (uint8)recvPacket.ReadBits(8);
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_PVE , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_DISPLAY_HORIZONTAL_GROUPS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_AUTO_ACTIVATE_25_PLAYERS , recvPacket.ReadBit());
- profiles[i]->BoolOptions.set(CUF_KEEP_GROUPS_TOGETHER , recvPacket.ReadBit());
- }
-
- for (uint8 i = 0; i < count; ++i)
- {
- recvPacket >> profiles[i]->Unk146;
- profiles[i]->ProfileName = recvPacket.ReadString(strlens[i]);
- recvPacket >> profiles[i]->Unk152;
- recvPacket >> profiles[i]->FrameHeight;
- recvPacket >> profiles[i]->FrameWidth;
- recvPacket >> profiles[i]->Unk150;
- recvPacket >> profiles[i]->HealthText;
- recvPacket >> profiles[i]->Unk147;
- recvPacket >> profiles[i]->SortBy;
- recvPacket >> profiles[i]->Unk154;
- recvPacket >> profiles[i]->Unk148;
-
- GetPlayer()->SaveCUFProfile(i, profiles[i]);
- }
+ for (uint8 i = 0; i < packet.CUFProfiles.size(); ++i)
+ GetPlayer()->SaveCUFProfile(i, std::move(packet.CUFProfiles[i]));
- for (uint8 i = count; i < MAX_CUF_PROFILES; ++i)
- GetPlayer()->SaveCUFProfile(i, NULL);
+ for (uint8 i = packet.CUFProfiles.size(); i < MAX_CUF_PROFILES; ++i)
+ GetPlayer()->SaveCUFProfile(i, nullptr);
}
void WorldSession::SendLoadCUFProfiles()
{
Player* player = GetPlayer();
- uint8 count = player->GetCUFProfilesCount();
-
- ByteBuffer byteBuffer(25 * count);
- WorldPacket data(SMSG_LOAD_CUF_PROFILES, 5 * count + 25 * count);
-
- data.WriteBits(count, 20);
- for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
- {
- CUFProfile* profile = player->GetCUFProfile(i);
- if (!profile)
- continue;
-
- data.WriteBit(profile->BoolOptions[CUF_UNK_157]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_10_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_5_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_25_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HEAL_PREDICTION]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVE]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_HORIZONTAL_GROUPS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_40_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_3_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_AGGRO_HIGHLIGHT]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_BORDER]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_2_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_NON_BOSS_DEBUFFS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_MAIN_TANK_AND_ASSIST]);
- data.WriteBit(profile->BoolOptions[CUF_UNK_156]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_2]);
- data.WriteBit(profile->BoolOptions[CUF_USE_CLASS_COLORS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_POWER_BAR]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_SPEC_1]);
- data.WriteBits(profile->ProfileName.size(), 8);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_ONLY_DISPELLABLE_DEBUFFS]);
- data.WriteBit(profile->BoolOptions[CUF_KEEP_GROUPS_TOGETHER]);
- data.WriteBit(profile->BoolOptions[CUF_UNK_145]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_15_PLAYERS]);
- data.WriteBit(profile->BoolOptions[CUF_DISPLAY_PETS]);
- data.WriteBit(profile->BoolOptions[CUF_AUTO_ACTIVATE_PVP]);
-
- byteBuffer << uint16(profile->Unk154);
- byteBuffer << uint16(profile->FrameHeight);
- byteBuffer << uint16(profile->Unk152);
- byteBuffer << uint8(profile->Unk147);
- byteBuffer << uint16(profile->Unk150);
- byteBuffer << uint8(profile->Unk146);
- byteBuffer << uint8(profile->HealthText);
- byteBuffer << uint8(profile->SortBy);
- byteBuffer << uint16(profile->FrameWidth);
- byteBuffer << uint8(profile->Unk148);
- byteBuffer.WriteString(profile->ProfileName);
- }
+ WorldPackets::Misc::LoadCUFProfiles loadCUFProfiles;
- data.FlushBits();
- data.append(byteBuffer);
- SendPacket(&data);
+ for (uint8 i = 0; i < MAX_CUF_PROFILES; i++)
+ if (CUFProfile* cufProfile = player->GetCUFProfile(i))
+ loadCUFProfiles.CUFProfiles.push_back(cufProfile);
+ SendPacket(loadCUFProfiles.Write());
}
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 3835a0642f9..240825faade 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -23,6 +23,7 @@
#include "Log.h"
#include "Corpse.h"
#include "Player.h"
+#include "Garrison.h"
#include "SpellAuras.h"
#include "MapManager.h"
#include "Transport.h"
@@ -46,6 +47,7 @@ void WorldSession::HandleMoveWorldportAckOpcode()
if (!GetPlayer()->IsBeingTeleportedFar())
return;
+ bool seamlessTeleport = GetPlayer()->IsBeingTeleportedSeamlessly();
GetPlayer()->SetSemaphoreTeleportFar(false);
// get the teleport destination
@@ -88,13 +90,16 @@ void WorldSession::HandleMoveWorldportAckOpcode()
float z = loc.GetPositionZ();
if (GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
z += GetPlayer()->GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
+
GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
GetPlayer()->ResetMap();
GetPlayer()->SetMap(newMap);
- GetPlayer()->SendInitialPacketsBeforeAddToMap();
- if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer()))
+ if (!seamlessTeleport)
+ GetPlayer()->SendInitialPacketsBeforeAddToMap();
+
+ if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer(), !seamlessTeleport))
{
TC_LOG_ERROR("network", "WORLD: failed to teleport player %s (%s) to map %d (%s) because of unknown reason!",
GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str(), loc.GetMapId(), newMap ? newMap->GetMapName() : "Unknown");
@@ -124,16 +129,26 @@ void WorldSession::HandleMoveWorldportAckOpcode()
}
}
- GetPlayer()->SendInitialPacketsAfterAddToMap();
+ if (!seamlessTeleport)
+ GetPlayer()->SendInitialPacketsAfterAddToMap();
+ else
+ {
+ GetPlayer()->UpdateVisibilityForPlayer();
+ if (Garrison* garrison = GetPlayer()->GetGarrison())
+ garrison->SendRemoteInfo();
+ }
// flight fast teleport case
if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
{
if (!_player->InBattleground())
{
- // short preparations to continue flight
- FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
- flight->Initialize(GetPlayer());
+ if (!seamlessTeleport)
+ {
+ // short preparations to continue flight
+ FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
+ flight->Initialize(GetPlayer());
+ }
return;
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index a5dc60b8494..2418bb84cac 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -130,7 +130,7 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
bool valid = true;
bool primary_prof_first_rank = false;
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i)
{
if (!tSpell->ReqAbility[i])
continue;
@@ -173,7 +173,7 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
break;
SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->ReqAbility[i]);
- for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2)
+ for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < MAX_TRAINERSPELL_ABILITY_REQS; ++itr2)
{
spell.ReqAbility[maxReq] = itr2->second;
++maxReq;
@@ -189,19 +189,14 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
SendPacket(packet.Write());
}
-void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
+void WorldSession::HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet)
{
- ObjectGuid guid;
- uint32 spellId;
- uint32 trainerId;
-
- recvData >> guid >> trainerId >> spellId;
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL %s, learn spell id is: %u", guid.ToString().c_str(), spellId);
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL %s, learn spell id is: %i", packet.TrainerGUID.ToString().c_str(), packet.SpellID);
- Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER);
+ Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(packet.TrainerGUID, UNIT_NPC_FLAG_TRAINER);
if (!unit)
{
- TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", guid.ToString().c_str());
+ TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", packet.TrainerGUID.ToString().c_str());
return;
}
@@ -213,32 +208,32 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
if (!trainer_spells)
{
- SendTrainerBuyFailed(guid, spellId, 0);
+ SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 0);
return;
}
// not found, cheat?
- TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
- if (!trainer_spell)
+ TrainerSpell const* trainerSpell = trainer_spells->Find(packet.SpellID);
+ if (!trainerSpell)
{
- SendTrainerBuyFailed(guid, spellId, 0);
+ SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 0);
return;
}
// can't be learn, cheat? Or double learn with lags...
- if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
+ if (_player->GetTrainerSpellState(trainerSpell) != TRAINER_SPELL_GREEN)
{
- SendTrainerBuyFailed(guid, spellId, 0);
+ SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 0);
return;
}
// apply reputation discount
- uint32 nSpellCost = uint32(floor(trainer_spell->MoneyCost * _player->GetReputationPriceDiscount(unit)));
+ uint32 nSpellCost = uint32(floor(trainerSpell->MoneyCost * _player->GetReputationPriceDiscount(unit)));
// check money requirement
if (!_player->HasEnoughMoney(uint64(nSpellCost)))
{
- SendTrainerBuyFailed(guid, spellId, 1);
+ SendTrainerBuyFailed(packet.TrainerGUID, packet.SpellID, 1);
return;
}
@@ -248,19 +243,19 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
_player->SendPlaySpellVisualKit(362, 1); // 113 EmoteSalute
// learn explicitly or cast explicitly
- if (trainer_spell->IsCastable())
- _player->CastSpell(_player, trainer_spell->SpellID, true);
+ if (trainerSpell->IsCastable())
+ _player->CastSpell(_player, trainerSpell->SpellID, true);
else
- _player->LearnSpell(spellId, false);
+ _player->LearnSpell(packet.SpellID, false);
}
-void WorldSession::SendTrainerBuyFailed(ObjectGuid guid, uint32 spellId, uint32 reason)
+void WorldSession::SendTrainerBuyFailed(ObjectGuid trainerGUID, uint32 spellID, int32 trainerFailedReason)
{
- WorldPacket data(SMSG_TRAINER_BUY_FAILED, 16);
- data << guid;
- data << uint32(spellId); // should be same as in packet from client
- data << uint32(reason); // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable."
- SendPacket(&data);
+ WorldPackets::NPC::TrainerBuyFailed trainerBuyFailed;
+ trainerBuyFailed.TrainerGUID = trainerGUID;
+ trainerBuyFailed.SpellID = spellID; // should be same as in packet from client
+ trainerBuyFailed.TrainerFailedReason = trainerFailedReason; // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable."
+ SendPacket(trainerBuyFailed.Write());
}
void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet)
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 7f1782ea1f0..429d3565052 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -616,8 +616,7 @@ void WorldSession::HandlePetRename(WorldPacket& recvData)
pet->SetName(name);
- if (pet->GetOwner()->GetGroup())
- pet->GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME);
+ pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME);
pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED);
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index e92fdab9409..eec80888559 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -414,3 +414,22 @@ void WorldSession::HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet)
SendPacket(response.Write());
}
}
+
+/**
+* Handles the packet sent by the client when requesting information about item text.
+*
+* This function is called when player clicks on item which has some flag set
+*/
+void WorldSession::HandleItemTextQuery(WorldPackets::Query::ItemTextQuery& itemTextQuery)
+{
+ WorldPackets::Query::QueryItemTextResponse queryItemTextResponse;
+ queryItemTextResponse.Id = itemTextQuery.Id;
+
+ if (Item* item = _player->GetItemByGuid(itemTextQuery.Id))
+ {
+ queryItemTextResponse.Valid = true;
+ queryItemTextResponse.Item.Text = item->GetText();
+ }
+
+ SendPacket(queryItemTextResponse.Write());
+}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 36296355577..c1d61ca49f4 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -659,7 +659,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPackets::Quest::Ques
Creature* questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(), *itr);
if (!questgiver || questgiver->IsHostileTo(_player))
continue;
- if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER))
+ if (!questgiver->HasFlag64(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER))
continue;
response.QuestGiver.emplace_back(questgiver->GetGUID(), _player->GetQuestDialogStatus(questgiver));
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 2cfa14164fe..2d3090825da 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -81,14 +81,14 @@ void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet)
}
// only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB)
- if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && user->InArena())
+ if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_FLAG_USEABLE_IN_ARENA) && user->InArena())
{
user->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, item, NULL);
return;
}
// don't allow items banned in arena
- if (proto->GetFlags() & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && user->InArena())
+ if (proto->GetFlags() & ITEM_FLAG_NOT_USEABLE_IN_ARENA && user->InArena())
{
user->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, item, NULL);
return;
@@ -153,7 +153,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet)
}
// Verify that the bag is an actual bag or wrapped item that can be used "normally"
- if (!(proto->GetFlags() & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
+ if (!(proto->GetFlags() & ITEM_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))
{
player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL);
TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [%s] tried to open item [%s, entry: %u] which is not openable!",
@@ -182,7 +182,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPackets::Spells::OpenItem& packet)
}
}
- if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))// wrapped?
+ if (item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))// wrapped?
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM);
@@ -281,8 +281,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
caster = _player;
}
- // check known spell
- if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellInfo->Id))
+ // check known spell or raid marker spell (which not requires player to know it)
+ if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellInfo->Id) && !spellInfo->HasEffect(SPELL_EFFECT_CHANGE_RAID_MARKER))
return;
// Check possible spell cast overrides
diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp
index 159876fdebd..ddfc0cef55c 100644
--- a/src/server/game/Handlers/TradeHandler.cpp
+++ b/src/server/game/Handlers/TradeHandler.cpp
@@ -67,7 +67,7 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
tradeItem.EntryID = item->GetEntry();
tradeItem.StackCount = item->GetCount();
tradeItem.GiftCreator = item->GetGuidValue(ITEM_FIELD_GIFTCREATOR);
- if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
+ if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED))
{
tradeItem.Unwrapped = boost::in_place();
@@ -76,7 +76,7 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/)
tradeItem.Unwrapped->OnUseEnchantmentID = item->GetEnchantmentId(USE_ENCHANTMENT_SLOT);
tradeItem.Unwrapped->Creator = item->GetGuidValue(ITEM_FIELD_CREATOR);
tradeItem.Unwrapped->Charges = item->GetSpellCharges();
- tradeItem.Unwrapped->Lock = item->GetTemplate()->GetLockID() && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED);
+ tradeItem.Unwrapped->Lock = item->GetTemplate()->GetLockID() && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED);
tradeItem.Unwrapped->MaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
tradeItem.Unwrapped->Durability = item->GetUInt32Value(ITEM_FIELD_DURABILITY);
@@ -124,7 +124,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
}
// adjust time (depends on /played)
- if (myItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
+ if (myItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE))
myItems[i]->SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, trader->GetTotalPlayedTime()-(_player->GetTotalPlayedTime()-myItems[i]->GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME)));
// store
trader->MoveItemToInventory(traderDst, myItems[i], true, true);
@@ -142,7 +142,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[])
}
// adjust time (depends on /played)
- if (hisItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_BOP_TRADEABLE))
+ if (hisItems[i]->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE))
hisItems[i]->SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, _player->GetTotalPlayedTime()-(trader->GetTotalPlayedTime()-hisItems[i]->GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME)));
// store
_player->MoveItemToInventory(playerDst, hisItems[i], true, true);
diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp
index dcca2f81711..46e2f1270c1 100644
--- a/src/server/game/Handlers/VoidStorageHandler.cpp
+++ b/src/server/game/Handlers/VoidStorageHandler.cpp
@@ -158,7 +158,7 @@ void WorldSession::HandleVoidStorageTransfer(WorldPackets::VoidStorage::VoidStor
Item* item = _player->GetItemByGuid(voidStorageTransfer.Deposits[i]);
if (!item)
{
- TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s wants to deposit an invalid item (%s).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), item->GetGUID().ToString().c_str());
+ TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s wants to deposit an invalid item (%s).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Deposits[i].ToString().c_str());
continue;
}
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index efb3810d00c..189b620b805 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -155,12 +155,6 @@ uint32 LootStore::LoadLootTable()
uint8 mincount = fields[7].GetUInt8();
uint8 maxcount = fields[8].GetUInt8();
- if (maxcount > std::numeric_limits<uint8>::max())
- {
- TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d Item %d: MaxCount value (%u) to large. must be less %u - skipped", GetName(), entry, item, maxcount, std::numeric_limits<uint8>::max());
- continue; // error already printed to log/console.
- }
-
if (groupid >= 1 << 7) // it stored in 7 bit field
{
TC_LOG_ERROR("sql.sql", "Table '%s' Entry %d Item %d: GroupId (%u) must be less %u - skipped", GetName(), entry, item, groupid, 1 << 7);
@@ -365,7 +359,7 @@ LootItem::LootItem(LootStoreItem const& li)
conditions = li.conditions;
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid);
- freeforall = proto && (proto->GetFlags() & ITEM_PROTO_FLAG_PARTY_LOOT);
+ freeforall = proto && (proto->GetFlags() & ITEM_FLAG_PARTY_LOOT);
follow_loot_rules = proto && (proto->FlagsCu & ITEM_FLAGS_CU_FOLLOW_LOOT_RULES);
needs_quest = li.needs_quest;
@@ -392,14 +386,14 @@ bool LootItem::AllowedForPlayer(Player const* player) const
return false;
// not show loot for players without profession or those who already know the recipe
- if ((pProto->GetFlags() & ITEM_PROTO_FLAG_SMART_LOOT) && (!player->HasSkill(pProto->GetRequiredSkill()) || player->HasSpell(pProto->Effects[1]->SpellID)))
+ if ((pProto->GetFlags() & ITEM_FLAG_SMART_LOOT) && (!player->HasSkill(pProto->GetRequiredSkill()) || player->HasSpell(pProto->Effects[1]->SpellID)))
return false;
// not show loot for not own team
- if ((pProto->GetFlags2() & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeam() != HORDE)
+ if ((pProto->GetFlags2() & ITEM_FLAG2_HORDE_ONLY) && player->GetTeam() != HORDE)
return false;
- if ((pProto->GetFlags2() & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE)
+ if ((pProto->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE)
return false;
// check quest requirements
@@ -447,7 +441,7 @@ void Loot::AddItem(LootStoreItem const& item)
// non-conditional one-player only items are counted here,
// free for all items are counted in FillFFALoot(),
// non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot()
- if (!item.needs_quest && item.conditions.empty() && !(proto->GetFlags() & ITEM_PROTO_FLAG_PARTY_LOOT))
+ if (!item.needs_quest && item.conditions.empty() && !(proto->GetFlags() & ITEM_FLAG_PARTY_LOOT))
++unlootedCount;
}
}
@@ -1651,7 +1645,7 @@ void LoadLootTemplates_Item()
// remove real entries and check existence loot
ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore();
for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr)
- if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end() && itr->second.GetFlags() & ITEM_PROTO_FLAG_OPENABLE)
+ if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end() && itr->second.GetFlags() & ITEM_FLAG_OPENABLE)
lootIdSet.erase(itr->second.GetId());
// output error for any still listed (not referenced from appropriate table) ids
@@ -1676,7 +1670,7 @@ void LoadLootTemplates_Milling()
ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore();
for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr)
{
- if (!(itr->second.GetFlags() & ITEM_PROTO_FLAG_MILLABLE))
+ if (!(itr->second.GetFlags() & ITEM_FLAG_MILLABLE))
continue;
if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end())
@@ -1739,7 +1733,7 @@ void LoadLootTemplates_Prospecting()
ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore();
for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr)
{
- if (!(itr->second.GetFlags() & ITEM_PROTO_FLAG_PROSPECTABLE))
+ if (!(itr->second.GetFlags() & ITEM_FLAG_PROSPECTABLE))
continue;
if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end())
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index ebfdaaf3b73..26a3d38635d 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -40,7 +40,7 @@
#include "Weather.h"
u_map_magic MapMagic = { {'M','A','P','S'} };
-u_map_magic MapVersionMagic = { {'v','1','.','4'} };
+u_map_magic MapVersionMagic = { {'v','1','.','5'} };
u_map_magic MapAreaMagic = { {'A','R','E','A'} };
u_map_magic MapHeightMagic = { {'M','H','G','T'} };
u_map_magic MapLiquidMagic = { {'M','L','I','Q'} };
@@ -78,33 +78,29 @@ Map::~Map()
bool Map::ExistMap(uint32 mapid, int gx, int gy)
{
- int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1;
- char* fileName = new char[len];
- snprintf(fileName, len, (char *)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), mapid, gx, gy);
+ std::string fileName = Trinity::StringFormat("%smaps/%04u_%02u_%02u.map", sWorld->GetDataPath().c_str(), mapid, gx, gy);
bool ret = false;
- FILE* pf = fopen(fileName, "rb");
-
- if (!pf)
+ FILE* file = fopen(fileName.c_str(), "rb");
+ if (!file)
{
- TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName);
+ TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName.c_str());
TC_LOG_ERROR("maps", "Please place MAP-files (*.map) in the appropriate directory (%s), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath()+"maps/").c_str());
}
else
{
map_fileheader header;
- if (fread(&header, sizeof(header), 1, pf) == 1)
+ if (fread(&header, sizeof(header), 1, file) == 1)
{
if (header.mapMagic.asUInt != MapMagic.asUInt || header.versionMagic.asUInt != MapVersionMagic.asUInt)
TC_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please recreate using the mapextractor.",
- fileName, 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar);
+ fileName.c_str(), 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar);
else
ret = true;
}
- fclose(pf);
+ fclose(file);
}
- delete[] fileName;
return ret;
}
@@ -191,16 +187,12 @@ void Map::LoadMap(int gx, int gy, bool reload)
}
// map file name
- char* tmp = NULL;
- int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1;
- tmp = new char[len];
- snprintf(tmp, len, (char *)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy);
- TC_LOG_DEBUG("maps", "Loading map %s", tmp);
+ std::string fileName = Trinity::StringFormat("%smaps/%04u_%02u_%02u.map", sWorld->GetDataPath().c_str(), GetId(), gx, gy);
+ TC_LOG_DEBUG("maps", "Loading map %s", fileName.c_str());
// loading data
GridMaps[gx][gy] = new GridMap();
- if (!GridMaps[gx][gy]->loadData(tmp))
- TC_LOG_ERROR("maps", "Error loading map file: \n %s\n", tmp);
- delete[] tmp;
+ if (!GridMaps[gx][gy]->loadData(fileName.c_str()))
+ TC_LOG_ERROR("maps", "Error loading map file: %s", fileName.c_str());
sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy);
}
@@ -456,8 +448,7 @@ bool Map::EnsureGridLoaded(const Cell &cell)
setGridObjectDataLoaded(true, cell.GridX(), cell.GridY());
- ObjectGridLoader loader(*grid, this, cell);
- loader.LoadN();
+ LoadGridObjects(grid, cell);
// Add resurrectable corpses to world object list in grid
sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this);
@@ -468,12 +459,18 @@ bool Map::EnsureGridLoaded(const Cell &cell)
return false;
}
+void Map::LoadGridObjects(NGridType* grid, Cell const& cell)
+{
+ ObjectGridLoader loader(*grid, this, cell);
+ loader.LoadN();
+}
+
void Map::LoadGrid(float x, float y)
{
EnsureGridLoaded(Cell(x, y));
}
-bool Map::AddPlayerToMap(Player* player)
+bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
{
CellCoord cellCoord = Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY());
if (!cellCoord.IsCoordValid())
@@ -491,13 +488,16 @@ bool Map::AddPlayerToMap(Player* player)
player->SetMap(this);
player->AddToWorld();
- SendInitSelf(player);
+ if (initPlayer)
+ SendInitSelf(player);
+
SendInitTransports(player);
SendZoneDynamicInfo(player);
- player->m_clientGUIDs.clear();
- player->UpdateObjectVisibility(false);
+ if (initPlayer)
+ player->m_clientGUIDs.clear();
+ player->UpdateObjectVisibility(false);
player->SendUpdatePhasing();
sScriptMgr->OnPlayerEnterMap(this, player);
@@ -2600,7 +2600,7 @@ void Map::SendObjectUpdates()
while (!_updateObjects.empty())
{
Object* obj = *_updateObjects.begin();
- ASSERT(obj && obj->IsInWorld());
+ ASSERT(obj->IsInWorld());
_updateObjects.erase(_updateObjects.begin());
obj->BuildUpdate(update_players);
}
@@ -2616,6 +2616,17 @@ void Map::SendObjectUpdates()
void Map::DelayedUpdate(const uint32 t_diff)
{
+ for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
+ {
+ Transport* transport = *_transportsUpdateIter;
+ ++_transportsUpdateIter;
+
+ if (!transport->IsInWorld())
+ continue;
+
+ transport->DelayedUpdate(t_diff);
+ }
+
RemoveAllObjectsInRemoveList();
// Don't unload grids if it's battleground, since we may have manually added GOs, creatures, those doesn't load from DB at grid re-load !
@@ -2955,7 +2966,7 @@ bool InstanceMap::CanEnter(Player* player)
/*
Do map specific checks and add the player to the map if successful.
*/
-bool InstanceMap::AddPlayerToMap(Player* player)
+bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
{
/// @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
// GMs still can teleport player in instance.
@@ -3065,7 +3076,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
}
// this will acquire the same mutex so it cannot be in the previous block
- Map::AddPlayerToMap(player);
+ Map::AddPlayerToMap(player, initPlayer);
if (i_data)
i_data->OnPlayerEnter(player);
@@ -3323,7 +3334,7 @@ bool BattlegroundMap::CanEnter(Player* player)
return Map::CanEnter(player);
}
-bool BattlegroundMap::AddPlayerToMap(Player* player)
+bool BattlegroundMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
{
{
std::lock_guard<std::mutex> lock(_mapLock);
@@ -3333,7 +3344,7 @@ bool BattlegroundMap::AddPlayerToMap(Player* player)
// reset instance validity, battleground maps do not homebind
player->m_InstanceValid = true;
}
- return Map::AddPlayerToMap(player);
+ return Map::AddPlayerToMap(player, initPlayer);
}
void BattlegroundMap::RemovePlayerFromMap(Player* player, bool remove)
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 1394808b2cc..fb1ac3cc62d 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -274,7 +274,7 @@ class Map : public GridRefManager<NGridType>
return false;
}
- virtual bool AddPlayerToMap(Player*);
+ virtual bool AddPlayerToMap(Player* player, bool initPlayer = true);
virtual void RemovePlayerFromMap(Player*, bool);
template<class T> bool AddToMap(T *);
template<class T> void RemoveFromMap(T *, bool);
@@ -394,6 +394,7 @@ class Map : public GridRefManager<NGridType>
bool IsBattleground() const { return i_mapEntry && i_mapEntry->IsBattleground(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattlegroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattlegroundOrArena(); }
+ bool IsGarrison() const { return i_mapEntry && i_mapEntry->IsGarrison(); }
bool GetEntrancePos(int32 &mapid, float &x, float &y)
{
if (!i_mapEntry)
@@ -601,6 +602,7 @@ class Map : public GridRefManager<NGridType>
protected:
void SetUnloadReferenceLock(const GridCoord &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
+ virtual void LoadGridObjects(NGridType* grid, Cell const& cell);
std::mutex _mapLock;
std::mutex _gridLock;
@@ -697,7 +699,7 @@ class Map : public GridRefManager<NGridType>
{
auto itr = _guidGenerators.find(high);
if (itr == _guidGenerators.end())
- itr = _guidGenerators.insert(std::make_pair(high, std::unique_ptr<ObjectGuidGenerator<high>>(new ObjectGuidGenerator<high>()))).first;
+ itr = _guidGenerators.insert(std::make_pair(high, Trinity::make_unique<ObjectGuidGenerator<high>>())).first;
return *itr->second;
}
@@ -725,7 +727,7 @@ class InstanceMap : public Map
public:
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
~InstanceMap();
- bool AddPlayerToMap(Player*) override;
+ bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
void RemovePlayerFromMap(Player*, bool) override;
void Update(const uint32) override;
void CreateInstanceData(bool load);
@@ -755,7 +757,7 @@ class BattlegroundMap : public Map
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode);
~BattlegroundMap();
- bool AddPlayerToMap(Player*) override;
+ bool AddPlayerToMap(Player* player, bool initPlayer = true) override;
void RemovePlayerFromMap(Player*, bool) override;
bool CanEnter(Player* player) override;
void SetUnload();
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index c48b616788e..bd69844ae7c 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -26,6 +26,7 @@
#include "World.h"
#include "Group.h"
#include "Player.h"
+#include "GarrisonMap.h"
MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DIFFICULTY_NORMAL)
{
@@ -138,7 +139,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player)
}
}
}
- else
+ else if (!IsGarrison())
{
InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficultyID(GetEntry()));
InstanceSave* pSave = pBind ? pBind->save : NULL;
@@ -180,6 +181,13 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player)
map = CreateInstance(newInstanceId, NULL, diff);
}
}
+ else
+ {
+ newInstanceId = player->GetGUID().GetCounter();
+ map = FindInstanceMap(newInstanceId);
+ if (!map)
+ map = CreateGarrison(newInstanceId, player);
+ }
return map;
}
@@ -206,7 +214,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
// some instances only have one difficulty
GetDownscaledMapDifficultyData(GetId(), difficulty);
- TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal");
+ TC_LOG_DEBUG("maps", "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save ? "" : "new ", InstanceId, GetId(), difficulty ? "heroic" : "normal");
InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
ASSERT(map->IsDungeon());
@@ -237,6 +245,17 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun
return map;
}
+GarrisonMap* MapInstanced::CreateGarrison(uint32 instanceId, Player* owner)
+{
+ std::lock_guard<std::mutex> lock(_mapLock);
+
+ GarrisonMap* map = new GarrisonMap(GetId(), GetGridExpiry(), instanceId, this, owner->GetGUID());
+ ASSERT(map->IsGarrison());
+
+ m_InstancedMaps[instanceId] = map;
+ return map;
+}
+
// increments the iterator after erase
bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr)
{
diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h
index c385215ba76..e487957ed6e 100644
--- a/src/server/game/Maps/MapInstanced.h
+++ b/src/server/game/Maps/MapInstanced.h
@@ -23,6 +23,8 @@
#include "InstanceSaveMgr.h"
#include "DBCEnums.h"
+class GarrisonMap;
+
class MapInstanced : public Map
{
friend class MapManager;
@@ -66,6 +68,7 @@ class MapInstanced : public Map
private:
InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty);
BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg);
+ GarrisonMap* CreateGarrison(uint32 instanceId, Player* owner);
InstancedMaps m_InstancedMaps;
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/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 975d74795fc..86e1c80bbd1 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -1113,7 +1113,7 @@ enum SpellEffectName
SPELL_EFFECT_REPUTATION = 103,
SPELL_EFFECT_SUMMON_OBJECT_SLOT1 = 104,
SPELL_EFFECT_SUMMON_OBJECT_SLOT2 = 105,
- SPELL_EFFECT_SUMMON_OBJECT_SLOT3 = 106,
+ SPELL_EFFECT_CHANGE_RAID_MARKER = 106,
SPELL_EFFECT_SUMMON_OBJECT_SLOT4 = 107,
SPELL_EFFECT_DISPEL_MECHANIC = 108,
SPELL_EFFECT_RESURRECT_PET = 109,
@@ -1174,7 +1174,7 @@ enum SpellEffectName
SPELL_EFFECT_REMOVE_AURA = 164,
SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT = 165,
SPELL_EFFECT_GIVE_CURRENCY = 166,
- SPELL_EFFECT_167 = 167,
+ SPELL_EFFECT_UPDATE_PLAYER_PHASE = 167,
SPELL_EFFECT_ALLOW_CONTROL_PET = 168, // NYI
SPELL_EFFECT_DESTROY_ITEM = 169,
SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES = 170, // NYI
@@ -1199,8 +1199,8 @@ enum SpellEffectName
SPELL_EFFECT_LOOT = 189, // NYI, lootid in MiscValue ?
SPELL_EFFECT_190 = 190,
SPELL_EFFECT_TELEPORT_TO_DIGSITE = 191, // NYI
- SPELL_EFFECT_192 = 192,
- SPELL_EFFECT_193 = 193,
+ SPELL_EFFECT_UNCAGE_BATTLEPET = 192,
+ SPELL_EFFECT_START_PET_BATTLE = 193,
SPELL_EFFECT_194 = 194,
SPELL_EFFECT_195 = 195,
SPELL_EFFECT_196 = 196,
@@ -1211,53 +1211,53 @@ enum SpellEffectName
SPELL_EFFECT_ENABLE_BATTLE_PETS = 201, // NYI
SPELL_EFFECT_202 = 202,
SPELL_EFFECT_203 = 203,
- SPELL_EFFECT_204 = 204,
- SPELL_EFFECT_205 = 205,
+ SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY = 204,
+ SPELL_EFFECT_LAUNCH_QUEST_CHOICE = 205,
SPELL_EFFECT_206 = 206,
- SPELL_EFFECT_207 = 207,
+ SPELL_EFFECT_LAUNCH_QUEST_TASK = 207, // Starts one of the "progress bar" quests
SPELL_EFFECT_208 = 208,
SPELL_EFFECT_209 = 209,
- SPELL_EFFECT_210 = 210,
- SPELL_EFFECT_211 = 211,
+ SPELL_EFFECT_LEARN_GARRISON_BUILDING = 210,
+ SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION = 211,
SPELL_EFFECT_212 = 212,
SPELL_EFFECT_213 = 213,
- SPELL_EFFECT_214 = 214,
- SPELL_EFFECT_215 = 215,
- SPELL_EFFECT_216 = 216,
- SPELL_EFFECT_217 = 217,
+ SPELL_EFFECT_CREATE_GARRISON = 214,
+ SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS = 215, // Unlocks boosted players' spells (ChrUpgrade*.db2)
+ SPELL_EFFECT_CREATE_SHIPMENT = 216,
+ SPELL_EFFECT_UPGRADE_GARRISON = 217,
SPELL_EFFECT_218 = 218,
SPELL_EFFECT_219 = 219,
- SPELL_EFFECT_220 = 220,
+ SPELL_EFFECT_ADD_GARRISON_FOLLOWER = 220,
SPELL_EFFECT_221 = 221,
- SPELL_EFFECT_222 = 222,
- SPELL_EFFECT_223 = 223,
- SPELL_EFFECT_224 = 224,
- SPELL_EFFECT_225 = 225,
+ SPELL_EFFECT_CREATE_HEIRLOOM_ITEM = 222,
+ SPELL_EFFECT_CHANGE_ITEM_BONUSES = 223,
+ SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING = 224,
+ SPELL_EFFECT_GRANT_BATTLEPET_LEVEL = 225,
SPELL_EFFECT_226 = 226,
SPELL_EFFECT_227 = 227,
SPELL_EFFECT_228 = 228,
- SPELL_EFFECT_229 = 229,
- SPELL_EFFECT_230 = 230,
- SPELL_EFFECT_231 = 231,
- SPELL_EFFECT_232 = 232,
- SPELL_EFFECT_233 = 233,
+ SPELL_EFFECT_SET_FOLLOWER_QUALITY = 229,
+ SPELL_EFFECT_INCREASE_FOLLOWER_ITEM_LEVEL = 230,
+ SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE = 231,
+ SPELL_EFFECT_REMOVE_PHASE = 232,
+ SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES = 233,
SPELL_EFFECT_234 = 234,
SPELL_EFFECT_235 = 235,
- SPELL_EFFECT_236 = 236,
- SPELL_EFFECT_237 = 237,
- SPELL_EFFECT_238 = 238,
- SPELL_EFFECT_239 = 239,
+ SPELL_EFFECT_GIVE_EXPERIENCE = 236, // Increases players XP
+ SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS = 237,
+ SPELL_EFFECT_INCREASE_SKILL = 238,
+ SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION = 239, // Instantly finishes building construction
SPELL_EFFECT_240 = 240,
SPELL_EFFECT_241 = 241,
SPELL_EFFECT_242 = 242,
- SPELL_EFFECT_243 = 243,
- SPELL_EFFECT_244 = 244,
- SPELL_EFFECT_245 = 245,
- SPELL_EFFECT_246 = 246,
- SPELL_EFFECT_247 = 247,
- SPELL_EFFECT_248 = 248,
+ SPELL_EFFECT_APPLY_ENCHANT_ILLUSION = 243,
+ SPELL_EFFECT_LEARN_FOLLOWER_ABILITY = 244,
+ SPELL_EFFECT_UPGRADE_HEIRLOOM = 245,
+ SPELL_EFFECT_FINISH_GARRISON_MISSION = 246,
+ SPELL_EFFECT_ADD_GARRISON_MISSION = 247,
+ SPELL_EFFECT_FINISH_SHIPMENT = 248,
SPELL_EFFECT_249 = 249,
- SPELL_EFFECT_250 = 250,
+ SPELL_EFFECT_TAKE_SCREENSHOT = 250, // Serverside marker for selfie screenshot - achievement check
TOTAL_SPELL_EFFECTS = 251,
};
@@ -4882,7 +4882,7 @@ enum PartyResult
};
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
-#define MMAP_VERSION 6
+#define MMAP_VERSION 7
struct MmapTileHeader
{
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/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h
index f50633205aa..acd0c94bbf1 100644
--- a/src/server/game/Movement/Spline/MoveSplineFlag.h
+++ b/src/server/game/Movement/Spline/MoveSplineFlag.h
@@ -32,12 +32,12 @@ namespace Movement
{
None = 0x00000000,
// x00-x07 used as animation Ids storage in pair with Animation flag
- Unknown0 = 0x00000008, // NOT VERIFIED
+ Unknown0 = 0x00000008, // NOT VERIFIED - does someting related to falling/fixed orientation
FallingSlow = 0x00000010,
Done = 0x00000020,
Falling = 0x00000040, // Affects elevation computation, can't be combined with Parabolic flag
No_Spline = 0x00000080,
- Unknown2 = 0x00000100, // NOT VERIFIED
+ Unknown1 = 0x00000100, // NOT VERIFIED
Flying = 0x00000200, // Smooth movement(Catmullrom interpolation mode), flying animation
OrientationFixed = 0x00000400, // Model orientation fixed
Catmullrom = 0x00000800, // Used Catmullrom interpolation mode
@@ -46,21 +46,21 @@ namespace Movement
Frozen = 0x00004000, // Will never arrive
TransportEnter = 0x00008000,
TransportExit = 0x00010000,
- Unknown3 = 0x00020000, // NOT VERIFIED
- Unknown4 = 0x00040000, // NOT VERIFIED
+ Unknown2 = 0x00020000, // NOT VERIFIED
+ Unknown3 = 0x00040000, // NOT VERIFIED
OrientationInversed = 0x00080000,
SmoothGroundPath = 0x00100000,
Walkmode = 0x00200000,
UncompressedPath = 0x00400000,
- Unknown6 = 0x00800000, // NOT VERIFIED
- Animation = 0x01000000, // Plays animation after some time passed
- Parabolic = 0x02000000, // Affects elevation computation, can't be combined with Falling flag
- Final_Point = 0x04000000,
- Final_Target = 0x08000000,
- Final_Angle = 0x10000000,
- Unknown7 = 0x20000000, // NOT VERIFIED
- Unknown8 = 0x40000000, // NOT VERIFIED
- Unknown9 = 0x80000000, // NOT VERIFIED
+ Unknown4 = 0x00800000, // NOT VERIFIED
+ Unknown5 = 0x01000000, // NOT VERIFIED
+ Animation = 0x02000000, // Plays animation after some time passed
+ Parabolic = 0x04000000, // Affects elevation computation, can't be combined with Falling flag
+ Final_Point = 0x08000000,
+ Final_Target = 0x10000000,
+ Final_Angle = 0x20000000,
+ Unknown6 = 0x40000000, // NOT VERIFIED
+ Unknown7 = 0x80000000, // NOT VERIFIED
// Masks
Mask_Final_Facing = Final_Point | Final_Target | Final_Angle,
@@ -69,7 +69,7 @@ namespace Movement
// flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably
Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done,
// Unused, not suported flags
- Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown0|Unknown2|Unknown3|Unknown4|Unknown6|Unknown7|Unknown8|Unknown9
+ Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown0|Unknown1|Unknown2|Unknown3|Unknown4|Unknown5|Unknown6|Unknown7
};
inline uint32& raw() { return (uint32&)*this; }
@@ -114,7 +114,7 @@ namespace Movement
bool done : 1;
bool falling : 1;
bool no_spline : 1;
- bool unknown2 : 1;
+ bool unknown1 : 1;
bool flying : 1;
bool orientationFixed : 1;
bool catmullrom : 1;
@@ -123,21 +123,21 @@ namespace Movement
bool frozen : 1;
bool transportEnter : 1;
bool transportExit : 1;
+ bool unknown2 : 1;
bool unknown3 : 1;
- bool unknown4 : 1;
bool orientationInversed : 1;
bool smoothGroundPath : 1;
bool walkmode : 1;
bool uncompressedPath : 1;
- bool unknown6 : 1;
+ bool unknown4 : 1;
+ bool unknown5 : 1;
bool animation : 1;
bool parabolic : 1;
bool final_point : 1;
bool final_target : 1;
bool final_angle : 1;
+ bool unknown6 : 1;
bool unknown7 : 1;
- bool unknown8 : 1;
- bool unknown9 : 1;
};
#pragma pack(pop)
}
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index 0343e92c506..117891140da 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -162,12 +162,14 @@ bool OPvPCapturePoint::DelCreature(uint32 type)
}
auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(spawnId);
- for (auto itr = bounds.first; itr != bounds.second; ++itr)
+ for (auto itr = bounds.first; itr != bounds.second;)
{
+ Creature* c = itr->second;
+ ++itr;
// Don't save respawn time
- itr->second->SetRespawnTime(0);
- itr->second->RemoveCorpse();
- itr->second->AddObjectToRemoveList();
+ c->SetRespawnTime(0);
+ c->RemoveCorpse();
+ c->AddObjectToRemoveList();
}
TC_LOG_DEBUG("outdoorpvp", "deleting opvp creature type %u", type);
@@ -196,11 +198,13 @@ bool OPvPCapturePoint::DelObject(uint32 type)
ObjectGuid::LowType spawnId = m_Objects[type];
auto bounds = m_PvP->GetMap()->GetGameObjectBySpawnIdStore().equal_range(spawnId);
- for (auto itr = bounds.first; itr != bounds.second; ++itr)
+ for (auto itr = bounds.first; itr != bounds.second;)
{
+ GameObject* go = itr->second;
+ ++itr;
// Don't save respawn time
- itr->second->SetRespawnTime(0);
- itr->second->Delete();
+ go->SetRespawnTime(0);
+ go->Delete();
}
sObjectMgr->DeleteGOData(spawnId);
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 15f378e138a..a82652d2f03 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -225,8 +225,12 @@ void PoolGroup<Creature>::Despawn1Object(uint64 guid)
if (!map->Instanceable())
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid);
- for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr = creatureBounds.first; itr != creatureBounds.second;)
+ {
+ Creature* creature = itr->second;
+ ++itr;
+ creature->AddObjectToRemoveList();
+ }
}
}
}
@@ -243,8 +247,12 @@ void PoolGroup<GameObject>::Despawn1Object(uint64 guid)
if (!map->Instanceable())
{
auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid);
- for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;)
+ {
+ GameObject* go = itr->second;
+ ++itr;
+ go->AddObjectToRemoveList();
+ }
}
}
}
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index c878287b4ac..148cdeab68e 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -34,7 +34,7 @@ Quest::Quest(Field* questRecord)
SuggestedPlayers = questRecord[7].GetUInt8();
NextQuestInChain = questRecord[8].GetUInt32();
RewardXPDifficulty = questRecord[9].GetUInt32();
- Float10 = questRecord[10].GetFloat();
+ RewardXPMultiplier = questRecord[10].GetFloat();
RewardMoney = questRecord[11].GetUInt32();
RewardMoneyDifficulty = questRecord[12].GetUInt32();
Float13 = questRecord[13].GetFloat();
@@ -225,7 +225,7 @@ uint32 Quest::XPValue(uint32 playerLevel) const
else if (diffFactor > 10)
diffFactor = 10;
- uint32 xp = diffFactor * xpentry->Exp[RewardXPDifficulty] / 10;
+ uint32 xp = diffFactor * xpentry->Exp[RewardXPDifficulty] * RewardXPMultiplier / 10;
if (xp <= 100)
xp = 5 * ((xp + 2) / 5);
else if (xp <= 500)
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 8433a549c60..e11794dc64c 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -226,7 +226,8 @@ enum QuestObjectiveType
QUEST_OBJECTIVE_AREATRIGGER = 10,
QUEST_OBJECTIVE_WINPETBATTLEAGAINSTNPC = 11,
QUEST_OBJECTIVE_DEFEATBATTLEPET = 12,
- QUEST_OBJECTIVE_WINPVPPETBATTLES = 13
+ QUEST_OBJECTIVE_WINPVPPETBATTLES = 13,
+ QUEST_OBJECTIVE_CRITERIA_TREE = 14
};
struct QuestTemplateLocale
@@ -318,6 +319,7 @@ class Quest
uint32 GetBonusTalents() const { return RewardTalents; }
int32 GetRewArenaPoints() const {return RewardArenaPoints; }
uint32 GetXPDifficulty() const { return RewardXPDifficulty; }
+ float GetXPMultiplier() const { return RewardXPMultiplier; }
uint32 GetSrcItemId() const { return SourceItemId; }
uint32 GetSrcItemCount() const { return SourceItemIdCount; }
uint32 GetSrcSpell() const { return SourceSpellID; }
@@ -332,7 +334,7 @@ class Quest
std::string const& GetPortraitGiverName() const { return PortraitGiverName; }
std::string const& GetPortraitTurnInText() const { return PortraitTurnInText; }
std::string const& GetPortraitTurnInName() const { return PortraitTurnInName; }
- QuestObjectives const& GetObjectives() const { return Objectives; };
+ QuestObjectives const& GetObjectives() const { return Objectives; }
uint32 GetRewMoney() const;
uint32 GetRewMoneyDifficulty() const { return RewardMoneyDifficulty; }
uint32 GetRewHonor() const { return RewardHonor; }
@@ -401,7 +403,7 @@ class Quest
uint32 SuggestedPlayers;
uint32 NextQuestInChain;
uint32 RewardXPDifficulty;
- float Float10;
+ float RewardXPMultiplier;
int32 RewardMoney;
uint32 RewardMoneyDifficulty;
float Float13;
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index 1db3dbb9f93..ecfc069ca78 100644
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -283,18 +283,11 @@ inline void Map::_ScriptProcessDoor(Object* source, Object* target, const Script
inline GameObject* Map::_FindGameObject(WorldObject* searchObject, ObjectGuid::LowType guid) const
{
- GameObject* gameobject = NULL;
+ auto bounds = searchObject->GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid);
+ if (bounds.first == bounds.second)
+ return nullptr;
- CellCoord p(Trinity::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
- Cell cell(p);
-
- Trinity::GameObjectWithDbGUIDCheck goCheck(*searchObject, guid);
- Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(searchObject, gameobject, goCheck);
-
- TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > objectChecker(checker);
- cell.Visit(p, objectChecker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
-
- return gameobject;
+ return bounds.first->second;
}
/// Process queued scripts
@@ -806,26 +799,17 @@ void Map::ScriptsProcess()
}
Creature* cTarget = NULL;
- WorldObject* wSource = dynamic_cast <WorldObject*> (source);
- if (wSource) //using grid searcher
+ WorldObject* wSource = dynamic_cast<WorldObject*>(source);
+ auto creatureBounds = _creatureBySpawnIdStore.equal_range(step.script->CallScript.CreatureEntry);
+ if (creatureBounds.first != creatureBounds.second)
{
- CellCoord p(Trinity::ComputeCellCoord(wSource->GetPositionX(), wSource->GetPositionY()));
- Cell cell(p);
-
- Trinity::CreatureWithDbGUIDCheck target_check(wSource, uint64(step.script->CallScript.CreatureEntry));
- Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(wSource, cTarget, target_check);
-
- TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
- cell.Visit(p, unit_checker, *wSource->GetMap(), *wSource, wSource->GetGridActivationRange());
- }
- else //check hashmap holders
- {
- if (CreatureData const* data = sObjectMgr->GetCreatureData(step.script->CallScript.CreatureEntry))
+ // Prefer alive (last respawned) creature
+ auto creatureItr = std::find_if(creatureBounds.first, creatureBounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair)
{
- auto creatureBounds = _creatureBySpawnIdStore.equal_range(step.script->CallScript.CreatureEntry);
- if (creatureBounds.first != creatureBounds.second)
- cTarget = creatureBounds.first->second;
- }
+ return pair.second->IsAlive();
+ });
+
+ cTarget = creatureItr != creatureBounds.second ? creatureItr->second : creatureBounds.first->second;
}
if (!cTarget)
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 553c752ccce..aa8be4946e4 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -634,6 +634,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();
@@ -1188,6 +1189,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/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp
index 12161867004..40af397e110 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.cpp
+++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp
@@ -60,6 +60,7 @@ WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
_worldPacket << uint8(Result);
_worldPacket.WriteBit(SuccessInfo.is_initialized());
_worldPacket.WriteBit(WaitInfo.is_initialized());
+ _worldPacket.FlushBits();
if (SuccessInfo)
{
@@ -83,6 +84,8 @@ WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
_worldPacket.WriteBit(realm.IsInternalRealm);
_worldPacket.WriteBits(realm.RealmNameActual.length(), 8);
_worldPacket.WriteBits(realm.RealmNameNormalized.length(), 8);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(realm.RealmNameActual);
_worldPacket.WriteString(realm.RealmNameNormalized);
}
@@ -111,6 +114,8 @@ WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
_worldPacket.WriteBits(templat.Name.length(), 7);
_worldPacket.WriteBits(templat.Description.length(), 10);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(templat.Name);
_worldPacket.WriteString(templat.Description);
}
@@ -120,6 +125,7 @@ WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
_worldPacket.WriteBit(SuccessInfo->NumPlayersHorde.is_initialized());
_worldPacket.WriteBit(SuccessInfo->NumPlayersAlliance.is_initialized());
_worldPacket.WriteBit(SuccessInfo->IsVeteranTrial);
+ _worldPacket.FlushBits();
if (SuccessInfo->NumPlayersHorde)
_worldPacket << uint16(*SuccessInfo->NumPlayersHorde);
@@ -132,9 +138,9 @@ WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
{
_worldPacket << uint32(WaitInfo->WaitCount);
_worldPacket.WriteBit(WaitInfo->HasFCM);
+ _worldPacket.FlushBits();
}
- _worldPacket.FlushBits();
return &_worldPacket;
}
diff --git a/src/server/game/Server/Packets/ChannelPackets.cpp b/src/server/game/Server/Packets/ChannelPackets.cpp
index 5acb018b46f..cc6406b81bc 100644
--- a/src/server/game/Server/Packets/ChannelPackets.cpp
+++ b/src/server/game/Server/Packets/ChannelPackets.cpp
@@ -83,6 +83,49 @@ WorldPacket const* WorldPackets::Channel::ChannelNotifyLeft::Write()
return &_worldPacket;
}
+WorldPacket const* WorldPackets::Channel::UserlistAdd::Write()
+{
+ _worldPacket << AddedUserGUID;
+ _worldPacket << uint8(_ChannelFlags);
+ _worldPacket << uint8(UserFlags);
+
+ _worldPacket << uint32(ChannelID);
+
+ _worldPacket.WriteBits(ChannelName.length(), 7);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(ChannelName);
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Channel::UserlistRemove::Write()
+{
+ _worldPacket << RemovedUserGUID;
+
+ _worldPacket << uint8(_ChannelFlags);
+
+ _worldPacket << uint32(ChannelID);
+
+ _worldPacket.WriteBits(ChannelName.length(), 7);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(ChannelName);
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Channel::UserlistUpdate::Write()
+{
+ _worldPacket << UpdatedUserGUID;
+
+ _worldPacket << uint8(_ChannelFlags);
+ _worldPacket << uint8(UserFlags);
+
+ _worldPacket << uint32(ChannelID);
+
+ _worldPacket.WriteBits(ChannelName.length(), 7);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(ChannelName);
+ return &_worldPacket;
+}
+
void WorldPackets::Channel::ChannelPlayerCommand::Read()
{
switch (GetOpcode())
diff --git a/src/server/game/Server/Packets/ChannelPackets.h b/src/server/game/Server/Packets/ChannelPackets.h
index ca47c76edc9..7464e9bd391 100644
--- a/src/server/game/Server/Packets/ChannelPackets.h
+++ b/src/server/game/Server/Packets/ChannelPackets.h
@@ -95,6 +95,56 @@ namespace WorldPackets
bool Suspended = false; ///< User Leave - false, On Zone Change - true
};
+ class UserlistAdd final : public ServerPacket
+ {
+ public:
+ UserlistAdd() : ServerPacket(SMSG_USERLIST_ADD, 30) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid AddedUserGUID;
+
+ uint8 _ChannelFlags = CHANNEL_FLAG_NONE; ///< @see enum ChannelFlags
+ uint8 UserFlags = MEMBER_FLAG_NONE;
+
+ int32 ChannelID = 0;
+
+ std::string ChannelName;
+ };
+
+ class UserlistRemove final : public ServerPacket
+ {
+ public:
+ UserlistRemove() : ServerPacket(SMSG_USERLIST_REMOVE, 30) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid RemovedUserGUID;
+
+ uint8 _ChannelFlags = CHANNEL_FLAG_NONE; ///< @see enum ChannelFlags
+
+ uint32 ChannelID = 0;
+
+ std::string ChannelName;
+ };
+
+ class UserlistUpdate final : public ServerPacket
+ {
+ public:
+ UserlistUpdate() : ServerPacket(SMSG_USERLIST_UPDATE, 30) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid UpdatedUserGUID;
+
+ uint8 _ChannelFlags = CHANNEL_FLAG_NONE; ///< @see enum ChannelFlags
+ uint8 UserFlags = MEMBER_FLAG_NONE;
+
+ int32 ChannelID = 0;
+
+ std::string ChannelName;
+ };
+
class ChannelPlayerCommand final : public ClientPacket
{
public:
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index d3b3050216c..9c6bb07f56e 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -154,6 +154,8 @@ WorldPacket const* WorldPackets::Character::EnumCharactersResult::Write()
_worldPacket.WriteBit(charInfo.FirstLogin);
_worldPacket.WriteBit(charInfo.BoostInProgress);
_worldPacket.WriteBits(charInfo.unkWod61x, 5);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(charInfo.Name);
}
@@ -215,11 +217,13 @@ WorldPacket const* WorldPackets::Character::CharacterRenameResult::Write()
_worldPacket << uint8(Result);
_worldPacket.WriteBit(Guid.is_initialized());
_worldPacket.WriteBits(Name.length(), 6);
+ _worldPacket.FlushBits();
if (Guid)
_worldPacket << *Guid;
_worldPacket.WriteString(Name);
+
return &_worldPacket;
}
@@ -305,19 +309,21 @@ WorldPacket const* WorldPackets::Character::GenerateRandomCharacterNameResult::W
{
_worldPacket.WriteBit(Success);
_worldPacket.WriteBits(Name.length(), 6);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(Name);
+
return &_worldPacket;
}
void WorldPackets::Character::ReorderCharacters::Read()
{
uint32 count = std::min<uint32>(_worldPacket.ReadBits(9), sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM));
- while (count--)
+ Entries.resize(count);
+ for (ReorderInfo& reorderInfo : Entries)
{
- ReorderInfo reorderInfo;
_worldPacket >> reorderInfo.PlayerGUID;
_worldPacket >> reorderInfo.NewPosition;
- Entries.emplace_back(reorderInfo);
}
}
@@ -492,3 +498,40 @@ WorldPacket const* WorldPackets::Character::SetFactionVisible::Write()
_worldPacket << FactionIndex;
return &_worldPacket;
}
+
+WorldPackets::Character::CharCustomizeResponse::CharCustomizeResponse(WorldPackets::Character::CharCustomizeInfo const* info)
+ : ServerPacket(SMSG_CHAR_CUSTOMIZE, 16 + 1 + 1 + 1 + 1 + 1 + 1 + 1)
+{
+ CharGUID = info->CharGUID;
+ SexID = info->SexID;
+ SkinID = info->SkinID;
+ HairColorID = info->HairColorID;
+ HairStyleID = info->HairStyleID;
+ FacialHairStyleID = info->FacialHairStyleID;
+ FaceID = info->FaceID;
+ CharName = info->CharName;
+}
+
+WorldPacket const* WorldPackets::Character::CharCustomizeResponse::Write()
+{
+ _worldPacket << CharGUID;
+ _worldPacket << uint8(SexID);
+ _worldPacket << uint8(SkinID);
+ _worldPacket << uint8(HairColorID);
+ _worldPacket << uint8(HairStyleID);
+ _worldPacket << uint8(FacialHairStyleID);
+ _worldPacket << uint8(FaceID);
+ _worldPacket.WriteBits(CharName.length(), 6);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(CharName);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Character::CharCustomizeFailed::Write()
+{
+ _worldPacket << uint8(Result);
+ _worldPacket << CharGUID;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h
index cee4f5edb5c..10f1053f8ee 100644
--- a/src/server/game/Server/Packets/CharacterPackets.h
+++ b/src/server/game/Server/Packets/CharacterPackets.h
@@ -608,7 +608,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
- BarberShopResult Result;
+ BarberShopResult Result = BARBER_SHOP_RESULT_SUCCESS;
};
class LogXPGain final : public ServerPacket
@@ -686,6 +686,35 @@ namespace WorldPackets
uint32 FactionIndex = 0;
};
+
+ class CharCustomizeResponse final : public ServerPacket
+ {
+ public:
+ CharCustomizeResponse() : ServerPacket(SMSG_CHAR_CUSTOMIZE, 16 + 1 + 1 + 1 + 1 + 1 + 1 + 1) { }
+ CharCustomizeResponse(CharCustomizeInfo const* customizeInfo);
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid CharGUID;
+ std::string CharName;
+ uint8 SexID = 0;
+ uint8 SkinID = 0;
+ uint8 HairColorID = 0;
+ uint8 HairStyleID = 0;
+ uint8 FacialHairStyleID = 0;
+ uint8 FaceID = 0;
+ };
+
+ class CharCustomizeFailed final : public ServerPacket
+ {
+ public:
+ CharCustomizeFailed() : ServerPacket(SMSG_CHAR_CUSTOMIZE_FAILED, 1 + 16) { }
+
+ WorldPacket const* Write() override;
+
+ uint8 Result = 0;
+ ObjectGuid CharGUID;
+ };
}
}
diff --git a/src/server/game/Server/Packets/ChatPackets.cpp b/src/server/game/Server/Packets/ChatPackets.cpp
index de4194db023..4204278d514 100644
--- a/src/server/game/Server/Packets/ChatPackets.cpp
+++ b/src/server/game/Server/Packets/ChatPackets.cpp
@@ -92,7 +92,7 @@ void WorldPackets::Chat::ChatMessageEmote::Read()
Text = _worldPacket.ReadString(len);
}
-void WorldPackets::Chat::Chat::Initalize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message,
+void WorldPackets::Chat::Chat::Initialize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message,
uint32 achievementId /*= 0*/, std::string channelName /*= ""*/, LocaleConstant locale /*= DEFAULT_LOCALE*/, std::string addonPrefix /*= ""*/)
{
// Clear everything because same packet can be used multiple times
@@ -165,6 +165,8 @@ WorldPacket const* WorldPackets::Chat::Chat::Write()
_worldPacket.WriteBits(_ChatFlags, 11);
_worldPacket.WriteBit(HideChatLog);
_worldPacket.WriteBit(FakeSenderName);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(SenderName);
_worldPacket.WriteString(TargetName);
_worldPacket.WriteString(Prefix);
@@ -203,14 +205,43 @@ WorldPacket const* WorldPackets::Chat::STextEmote::Write()
WorldPacket const* WorldPackets::Chat::PrintNotification::Write()
{
_worldPacket.WriteBits(NotifyText.size(), 12);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(NotifyText);
+
return &_worldPacket;
}
WorldPacket const* WorldPackets::Chat::ChatPlayerNotfound::Write()
{
_worldPacket.WriteBits(Name.length(), 9);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(Name);
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Chat::ChatServerMessage::Write()
+{
+ _worldPacket << MessageID;
+
+ _worldPacket.WriteBits(StringParam.length(), 11);
+ _worldPacket.FlushBits();
+
+ _worldPacket.WriteString(StringParam);
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Chat::ChatRegisterAddonPrefixes::Read()
+{
+ int32 count;
+ _worldPacket >> count;
+
+ for (int32 i = 0; i < count; ++i)
+ {
+ uint32 lenghts = _worldPacket.ReadBits(5);
+ Prefixes.push_back(_worldPacket.ReadString(lenghts));
+ }
+}
diff --git a/src/server/game/Server/Packets/ChatPackets.h b/src/server/game/Server/Packets/ChatPackets.h
index b794d118d88..c8bb038ce19 100644
--- a/src/server/game/Server/Packets/ChatPackets.h
+++ b/src/server/game/Server/Packets/ChatPackets.h
@@ -151,7 +151,7 @@ namespace WorldPackets
public:
Chat() : ServerPacket(SMSG_CHAT, 100) { }
- void Initalize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message, uint32 achievementId = 0, std::string channelName = "", LocaleConstant locale = DEFAULT_LOCALE, std::string addonPrefix = "");
+ void Initialize(ChatMsg chatType, Language language, WorldObject const* sender, WorldObject const* receiver, std::string message, uint32 achievementId = 0, std::string channelName = "", LocaleConstant locale = DEFAULT_LOCALE, std::string addonPrefix = "");
WorldPacket const* Write() override;
uint8 SlashCmd = 0; ///< @see enum ChatMsg
@@ -239,6 +239,35 @@ namespace WorldPackets
std::string Name;
};
+
+ class ChatServerMessage final : public ServerPacket
+ {
+ public:
+ ChatServerMessage() : ServerPacket(SMSG_CHAT_SERVER_MESSAGE, 4 + 2) { }
+
+ WorldPacket const* Write() override;
+
+ int32 MessageID = 0;
+ std::string StringParam;
+ };
+
+ class ChatRegisterAddonPrefixes final : public ClientPacket
+ {
+ public:
+ ChatRegisterAddonPrefixes(WorldPacket&& packet) : ClientPacket(CMSG_CHAT_REGISTER_ADDON_PREFIXES, std::move(packet)) { }
+
+ void Read() override;
+
+ std::vector<std::string> Prefixes;
+ };
+
+ class ChatUnregisterAllAddonPrefixes final : public ClientPacket
+ {
+ public:
+ ChatUnregisterAllAddonPrefixes(WorldPacket&& packet) : ClientPacket(CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES, std::move(packet)) { }
+
+ void Read() override { }
+ };
}
}
diff --git a/src/server/game/Server/Packets/CombatLogPackets.cpp b/src/server/game/Server/Packets/CombatLogPackets.cpp
index 0702ad63f05..295f27375da 100644
--- a/src/server/game/Server/Packets/CombatLogPackets.cpp
+++ b/src/server/game/Server/Packets/CombatLogPackets.cpp
@@ -147,3 +147,76 @@ WorldPacket const* WorldPackets::CombatLog::SpellHealLog::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::CombatLog::SpellPeriodicAuraLog::Write()
+{
+ _worldPacket << TargetGUID;
+ _worldPacket << CasterGUID;
+ _worldPacket << SpellID;
+
+ _worldPacket << uint32(Effects.size());
+
+ for (SpellLogEffect const& effect : Effects)
+ {
+ _worldPacket << effect.Effect;
+ _worldPacket << int32(effect.Amount);
+ _worldPacket << int32(effect.OverHealOrKill);
+ _worldPacket << int32(effect.SchoolMaskOrPower);
+ _worldPacket << int32(effect.AbsorbedOrAmplitude);
+ _worldPacket << int32(effect.Resisted);
+
+ _worldPacket.WriteBit(effect.Crit);
+ _worldPacket.WriteBit(effect.Multistrike);
+
+ if (_worldPacket.WriteBit(effect.DebugInfo.is_initialized()))
+ {
+ _worldPacket << float(effect.DebugInfo->CritRollMade);
+ _worldPacket << float(effect.DebugInfo->CritRollNeeded);
+ }
+
+ _worldPacket.FlushBits();
+ }
+
+ _worldPacket.WriteBit(LogData.is_initialized());
+ _worldPacket.FlushBits();
+ if (LogData)
+ _worldPacket << *LogData;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::CombatLog::SpellInterruptLog::Write()
+{
+ _worldPacket << Caster;
+ _worldPacket << Victim;
+ _worldPacket << int32(InterruptedSpellID);
+ _worldPacket << int32(SpellID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::CombatLog::SpellEnergizeLog::Write()
+{
+ _worldPacket << CasterGUID;
+ _worldPacket << TargetGUID;
+
+ _worldPacket << int32(SpellID);
+ _worldPacket << int32(Type);
+ _worldPacket << int32(Amount);
+
+ _worldPacket.WriteBit(LogData.is_initialized());
+ _worldPacket.FlushBits();
+ if (LogData)
+ _worldPacket << *LogData;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::CombatLog::SpellInstakillLog::Write()
+{
+ _worldPacket << Target;
+ _worldPacket << Caster;
+ _worldPacket << int32(SpellID);
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/CombatLogPackets.h b/src/server/game/Server/Packets/CombatLogPackets.h
index c74e8112698..1962bc2c2fc 100644
--- a/src/server/game/Server/Packets/CombatLogPackets.h
+++ b/src/server/game/Server/Packets/CombatLogPackets.h
@@ -91,7 +91,6 @@ namespace WorldPackets
class SpellHealLog final : public ServerPacket
{
public:
-
SpellHealLog() : ServerPacket(SMSG_SPELL_HEAL_LOG, 16 + 16 + 4 * 4 + 1) { }
WorldPacket const* Write() override;
@@ -108,6 +107,79 @@ namespace WorldPackets
Optional<float> CritRollNeeded;
Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false
};
+
+ class SpellPeriodicAuraLog final : public ServerPacket
+ {
+ public:
+ struct PeriodicalAuraLogEffectDebugInfo
+ {
+ float CritRollMade = 0.0f;
+ float CritRollNeeded = 0.0f;
+ };
+
+ struct SpellLogEffect
+ {
+ int32 Effect = 0;
+ int32 Amount = 0;
+ int32 OverHealOrKill = 0;
+ int32 SchoolMaskOrPower = 0;
+ int32 AbsorbedOrAmplitude = 0;
+ int32 Resisted = 0;
+ bool Crit = false;
+ bool Multistrike = false;
+ Optional<PeriodicalAuraLogEffectDebugInfo> DebugInfo;
+ };
+
+ SpellPeriodicAuraLog() : ServerPacket(SMSG_SPELL_PERIODIC_AURA_LOG, 16 + 16 + 4 + 4 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid TargetGUID;
+ ObjectGuid CasterGUID;
+ int32 SpellID = 0;
+ std::vector<SpellLogEffect> Effects;
+ Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false
+ };
+
+ class SpellInterruptLog final : public ServerPacket
+ {
+ public:
+ SpellInterruptLog() : ServerPacket(SMSG_SPELL_INTERRUPT_LOG, 16 + 16 + 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Caster;
+ ObjectGuid Victim;
+ int32 InterruptedSpellID = 0;
+ int32 SpellID = 0;
+ };
+
+ class SpellEnergizeLog final : public ServerPacket
+ {
+ public:
+ SpellEnergizeLog() : ServerPacket(SMSG_SPELL_ENERGIZE_LOG, 16 + 16 + 4 + 4 + 4 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid CasterGUID;
+ ObjectGuid TargetGUID;
+ int32 SpellID = 0;
+ int32 Type = 0;
+ int32 Amount = 0;
+ Optional<Spells::SpellCastLogData> LogData; /// @todo: find the correct way where to use it, in sniff always false
+ };
+
+ class SpellInstakillLog final : public ServerPacket
+ {
+ public:
+ SpellInstakillLog() : ServerPacket(SMSG_SPELL_INSTAKILL_LOG, 16 + 16 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Target;
+ ObjectGuid Caster;
+ int32 SpellID;
+ };
}
}
diff --git a/src/server/game/Server/Packets/CombatPackets.cpp b/src/server/game/Server/Packets/CombatPackets.cpp
index e095e951e36..d47f2275ee6 100644
--- a/src/server/game/Server/Packets/CombatPackets.cpp
+++ b/src/server/game/Server/Packets/CombatPackets.cpp
@@ -198,3 +198,12 @@ WorldPacket const* WorldPackets::Combat::ThreatClear::Write()
_worldPacket << UnitGUID;
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Combat::PvPCredit::Write()
+{
+ _worldPacket << int32(Honor);
+ _worldPacket << Target;
+ _worldPacket << int32(Rank);
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/CombatPackets.h b/src/server/game/Server/Packets/CombatPackets.h
index 0cab58044eb..deeb98fe335 100644
--- a/src/server/game/Server/Packets/CombatPackets.h
+++ b/src/server/game/Server/Packets/CombatPackets.h
@@ -246,6 +246,18 @@ namespace WorldPackets
ObjectGuid UnitGUID;
};
+
+ class PvPCredit final : public ServerPacket
+ {
+ public:
+ PvPCredit() : ServerPacket(SMSG_PVP_CREDIT, 4 + 16 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Target;
+ int32 Honor = 0;
+ int32 Rank = 0;
+ };
}
}
diff --git a/src/server/game/Server/Packets/EquipmentSetPackets.cpp b/src/server/game/Server/Packets/EquipmentSetPackets.cpp
index 0dc948f5170..3fe30d2b8e7 100644
--- a/src/server/game/Server/Packets/EquipmentSetPackets.cpp
+++ b/src/server/game/Server/Packets/EquipmentSetPackets.cpp
@@ -40,9 +40,10 @@ WorldPacket const* WorldPackets::EquipmentSet::LoadEquipmentSet::Write()
_worldPacket.WriteBits(equipSet->SetName.length(), 8);
_worldPacket.WriteBits(equipSet->SetIcon.length(), 9);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(equipSet->SetName);
_worldPacket.WriteString(equipSet->SetIcon);
- _worldPacket.FlushBits();
}
return &_worldPacket;
diff --git a/src/server/game/Server/Packets/EquipmentSetPackets.h b/src/server/game/Server/Packets/EquipmentSetPackets.h
index a26eee383ae..a7936cc1b79 100644
--- a/src/server/game/Server/Packets/EquipmentSetPackets.h
+++ b/src/server/game/Server/Packets/EquipmentSetPackets.h
@@ -63,7 +63,7 @@ namespace WorldPackets
void Read() override;
- uint64 ID;
+ uint64 ID = 0;
};
class UseEquipmentSet final : public ClientPacket
diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp
new file mode 100644
index 00000000000..88374e7ce62
--- /dev/null
+++ b/src/server/game/Server/Packets/GarrisonPackets.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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 "GarrisonPackets.h"
+
+WorldPacket const* WorldPackets::Garrison::GarrisonCreateResult::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << uint32(GarrSiteLevelID);
+
+ return &_worldPacket;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonPlotInfo& plotInfo)
+{
+ data << uint32(plotInfo.GarrPlotInstanceID);
+ data << plotInfo.PlotPos.PositionXYZOStream();
+ data << uint32(plotInfo.PlotType);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo)
+{
+ data << uint32(buildingInfo.GarrPlotInstanceID);
+ data << uint32(buildingInfo.GarrBuildingID);
+ data << uint32(buildingInfo.TimeBuilt);
+ data << uint32(buildingInfo.CurrentGarSpecID);
+ data << uint32(buildingInfo.TimeSpecCooldown);
+ data.WriteBit(buildingInfo.Active);
+ data.FlushBits();
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonFollower const& follower)
+{
+ data << uint64(follower.DbID);
+ data << uint32(follower.GarrFollowerID);
+ data << uint32(follower.Quality);
+ data << uint32(follower.FollowerLevel);
+ data << uint32(follower.ItemLevelWeapon);
+ data << uint32(follower.ItemLevelArmor);
+ data << uint32(follower.Xp);
+ data << uint32(follower.CurrentBuildingID);
+ data << uint32(follower.CurrentMissionID);
+ data << uint32(follower.AbilityID.size());
+ data << uint32(follower.FollowerStatus);
+ for (GarrAbilityEntry const* ability : follower.AbilityID)
+ data << uint32(ability->ID);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonMission const& mission)
+{
+ data << uint64(mission.DbID);
+ data << uint32(mission.MissionRecID);
+ data << uint32(mission.OfferTime);
+ data << uint32(mission.OfferDuration);
+ data << uint32(mission.StartTime);
+ data << uint32(mission.TravelDuration);
+ data << uint32(mission.MissionDuration);
+ data << uint32(mission.MissionState);
+
+ return data;
+}
+
+WorldPacket const* WorldPackets::Garrison::GetGarrisonInfoResult::Write()
+{
+ _worldPacket.reserve(4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 +
+ Buildings.size() * sizeof(GarrisonBuildingInfo) +
+ Plots.size() * sizeof(GarrisonPlotInfo) +
+ Followers.size() * (sizeof(GarrisonFollower) + 5 * 4) +
+ Missions.size() * sizeof(GarrisonMission) +
+ ArchivedMissions.size() * 4);
+
+ _worldPacket << int32(GarrSiteID);
+ _worldPacket << int32(GarrSiteLevelID);
+ _worldPacket << int32(FactionIndex);
+ _worldPacket << uint32(Buildings.size());
+ _worldPacket << uint32(Plots.size());
+ _worldPacket << uint32(Followers.size());
+ _worldPacket << uint32(Missions.size());
+ _worldPacket << uint32(ArchivedMissions.size());
+ _worldPacket << int32(NumFollowerActivationsRemaining);
+
+ for (GarrisonBuildingInfo const* building : Buildings)
+ _worldPacket << *building;
+
+ for (GarrisonPlotInfo* plot : Plots)
+ _worldPacket << *plot;
+
+ for (GarrisonFollower const* follower : Followers)
+ _worldPacket << *follower;
+
+ for (GarrisonMission const* mission : Missions)
+ _worldPacket << *mission;
+
+ if (!ArchivedMissions.empty())
+ _worldPacket.append(ArchivedMissions.data(), ArchivedMissions.size());
+
+ return &_worldPacket;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonRemoteBuildingInfo const& building)
+{
+ data << uint32(building.GarrPlotInstanceID);
+ data << uint32(building.GarrBuildingID);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonRemoteSiteInfo const& site)
+{
+ data << uint32(site.GarrSiteLevelID);
+ data << uint32(site.Buildings.size());
+ for (WorldPackets::Garrison::GarrisonRemoteBuildingInfo const& building : site.Buildings)
+ data << building;
+
+ return data;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonRemoteInfo::Write()
+{
+ _worldPacket << uint32(Sites.size());
+ for (GarrisonRemoteSiteInfo const& site : Sites)
+ _worldPacket << site;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Garrison::GarrisonPurchaseBuilding::Read()
+{
+ _worldPacket >> NpcGUID;
+ _worldPacket >> PlotInstanceID;
+ _worldPacket >> BuildingID;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonPlaceBuildingResult::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << BuildingInfo;
+ _worldPacket.WriteBit(PlayActivationCinematic);
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Garrison::GarrisonCancelConstruction::Read()
+{
+ _worldPacket >> NpcGUID;
+ _worldPacket >> PlotInstanceID;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonBuildingRemoved::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << uint32(GarrPlotInstanceID);
+ _worldPacket << uint32(GarrBuildingID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonLearnBlueprintResult::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << uint32(BuildingID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonUnlearnBlueprintResult::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << uint32(BuildingID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationDataResult::Write()
+{
+ _worldPacket << uint32(BlueprintsKnown ? BlueprintsKnown->size() : 0);
+ _worldPacket << uint32(SpecializationsKnown ? SpecializationsKnown->size() : 0);
+ if (BlueprintsKnown)
+ for (uint32 blueprint : *BlueprintsKnown)
+ _worldPacket << uint32(blueprint);
+
+ if (SpecializationsKnown)
+ for (uint32 specialization : *SpecializationsKnown)
+ _worldPacket << uint32(specialization);
+
+ return &_worldPacket;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonBuildingLandmark& landmark)
+{
+ data << uint32(landmark.GarrBuildingPlotInstID);
+ data << landmark.Pos.PositionXYZStream();
+
+ return data;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonBuildingLandmarks::Write()
+{
+ _worldPacket << uint32(Landmarks.size());
+ for (GarrisonBuildingLandmark& landmark : Landmarks)
+ _worldPacket << landmark;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonPlotPlaced::Write()
+{
+ _worldPacket << *PlotInfo;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonPlotRemoved::Write()
+{
+ _worldPacket << uint32(GarrPlotInstanceID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonAddFollowerResult::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << Follower;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h
new file mode 100644
index 00000000000..1bb04c7ba95
--- /dev/null
+++ b/src/server/game/Server/Packets/GarrisonPackets.h
@@ -0,0 +1,285 @@
+/*
+ * 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 GarrisonPackets_h__
+#define GarrisonPackets_h__
+
+#include "Packet.h"
+#include "ObjectGuid.h"
+#include "Position.h"
+#include "PacketUtilities.h"
+#include "DB2Structure.h"
+
+namespace WorldPackets
+{
+ namespace Garrison
+ {
+ class GarrisonCreateResult final : public ServerPacket
+ {
+ public:
+ GarrisonCreateResult() : ServerPacket(SMSG_GARRISON_CREATE_RESULT, 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 GarrSiteLevelID = 0;
+ uint32 Result = 0;
+ };
+
+ class GetGarrisonInfo final : public ClientPacket
+ {
+ public:
+ GetGarrisonInfo(WorldPacket&& packet) : ClientPacket(CMSG_GET_GARRISON_INFO, std::move(packet)) { }
+
+ void Read() override { }
+ };
+
+ struct GarrisonPlotInfo
+ {
+ uint32 GarrPlotInstanceID = 0;
+ Position PlotPos;
+ uint32 PlotType = 0;
+ };
+
+ struct GarrisonBuildingInfo
+ {
+ uint32 GarrPlotInstanceID = 0;
+ uint32 GarrBuildingID = 0;
+ time_t TimeBuilt = time_t(0);
+ uint32 CurrentGarSpecID = 0;
+ time_t TimeSpecCooldown = time_t(2288912640); // 06/07/1906 18:35:44 - another in the series of magic blizz dates
+ bool Active = false;
+ };
+
+ struct GarrisonFollower
+ {
+ uint64 DbID = 0;
+ uint32 GarrFollowerID = 0;
+ uint32 Quality = 0;
+ uint32 FollowerLevel = 0;
+ uint32 ItemLevelWeapon = 0;
+ uint32 ItemLevelArmor = 0;
+ uint32 Xp = 0;
+ uint32 CurrentBuildingID = 0;
+ uint32 CurrentMissionID = 0;
+ std::list<GarrAbilityEntry const*> AbilityID;
+ uint32 FollowerStatus;
+ };
+
+ struct GarrisonMission
+ {
+ uint64 DbID = 0;
+ uint32 MissionRecID = 0;
+ time_t OfferTime = time_t(0);
+ uint32 OfferDuration = 0;
+ time_t StartTime = time_t(2288912640);
+ uint32 TravelDuration = 0;
+ uint32 MissionDuration = 0;
+ uint32 MissionState = 0;
+ };
+
+ class GetGarrisonInfoResult final : public ServerPacket
+ {
+ public:
+ GetGarrisonInfoResult() : ServerPacket(SMSG_GET_GARRISON_INFO_RESULT) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 GarrSiteID = 0;
+ uint32 GarrSiteLevelID = 0;
+ uint32 FactionIndex = 0;
+ uint32 NumFollowerActivationsRemaining = 0;
+ std::vector<GarrisonPlotInfo*> Plots;
+ std::vector<GarrisonBuildingInfo const*> Buildings;
+ std::vector<GarrisonFollower const*> Followers;
+ std::vector<GarrisonMission const*> Missions;
+ std::vector<int32> ArchivedMissions;
+ };
+
+ struct GarrisonRemoteBuildingInfo
+ {
+ GarrisonRemoteBuildingInfo() : GarrPlotInstanceID(0), GarrBuildingID(0) { }
+ GarrisonRemoteBuildingInfo(uint32 plotInstanceId, uint32 buildingId) : GarrPlotInstanceID(plotInstanceId), GarrBuildingID(buildingId) { }
+
+ uint32 GarrPlotInstanceID;
+ uint32 GarrBuildingID;
+ };
+
+ struct GarrisonRemoteSiteInfo
+ {
+ uint32 GarrSiteLevelID = 0;
+ std::vector<GarrisonRemoteBuildingInfo> Buildings;
+ };
+
+ class GarrisonRemoteInfo final : public ServerPacket
+ {
+ public:
+ GarrisonRemoteInfo() : ServerPacket(SMSG_GARRISON_REMOTE_INFO) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<GarrisonRemoteSiteInfo> Sites;
+ };
+
+ class GarrisonPurchaseBuilding final : public ClientPacket
+ {
+ public:
+ GarrisonPurchaseBuilding(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_PURCHASE_BUILDING, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid NpcGUID;
+ uint32 BuildingID = 0;
+ uint32 PlotInstanceID = 0;
+ };
+
+ class GarrisonPlaceBuildingResult final : public ServerPacket
+ {
+ public:
+ GarrisonPlaceBuildingResult() : ServerPacket(SMSG_GARRISON_PLACE_BUILDING_RESULT) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 Result = 0;
+ GarrisonBuildingInfo BuildingInfo;
+ bool PlayActivationCinematic = false;
+ };
+
+ class GarrisonCancelConstruction final : public ClientPacket
+ {
+ public:
+ GarrisonCancelConstruction(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_CANCEL_CONSTRUCTION, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid NpcGUID;
+ uint32 PlotInstanceID = 0;
+ };
+
+ class GarrisonBuildingRemoved final : public ServerPacket
+ {
+ public:
+ GarrisonBuildingRemoved() : ServerPacket(SMSG_GARRISON_BUILDING_REMOVED, 4 + 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 Result = 0;
+ uint32 GarrPlotInstanceID = 0;
+ uint32 GarrBuildingID = 0;
+ };
+
+ class GarrisonLearnBlueprintResult final : public ServerPacket
+ {
+ public:
+ GarrisonLearnBlueprintResult() : ServerPacket(SMSG_GARRISON_LEARN_BLUEPRINT_RESULT, 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 BuildingID = 0;
+ uint32 Result = 0;
+ };
+
+ class GarrisonUnlearnBlueprintResult final : public ServerPacket
+ {
+ public:
+ GarrisonUnlearnBlueprintResult() : ServerPacket(SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT, 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 BuildingID = 0;
+ uint32 Result = 0;
+ };
+
+ class GarrisonRequestBlueprintAndSpecializationData final : public ClientPacket
+ {
+ public:
+ GarrisonRequestBlueprintAndSpecializationData(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA, std::move(packet)) { }
+
+ void Read() override { }
+ };
+
+ class GarrisonRequestBlueprintAndSpecializationDataResult final : public ServerPacket
+ {
+ public:
+ GarrisonRequestBlueprintAndSpecializationDataResult() : ServerPacket(SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT, 400) { }
+
+ WorldPacket const* Write() override;
+
+ std::unordered_set<uint32> const* SpecializationsKnown = nullptr;
+ std::unordered_set<uint32> const* BlueprintsKnown = nullptr;
+ };
+
+ class GarrisonGetBuildingLandmarks final : public ClientPacket
+ {
+ public:
+ GarrisonGetBuildingLandmarks(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_GET_BUILDING_LANDMARKS, std::move(packet)) { }
+
+ void Read() override { }
+ };
+
+ struct GarrisonBuildingLandmark
+ {
+ GarrisonBuildingLandmark() : GarrBuildingPlotInstID(0), Pos() { }
+ GarrisonBuildingLandmark(uint32 buildingPlotInstId, Position const& pos) : GarrBuildingPlotInstID(buildingPlotInstId), Pos(pos) { }
+
+ uint32 GarrBuildingPlotInstID;
+ Position Pos;
+ };
+
+ class GarrisonBuildingLandmarks final : public ServerPacket
+ {
+ public:
+ GarrisonBuildingLandmarks() : ServerPacket(SMSG_GARRISON_BUILDING_LANDMARKS) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<GarrisonBuildingLandmark> Landmarks;
+ };
+
+ class GarrisonPlotPlaced final : public ServerPacket
+ {
+ public:
+ GarrisonPlotPlaced() : ServerPacket(SMSG_GARRISON_PLOT_PLACED) { }
+
+ WorldPacket const* Write() override;
+
+ GarrisonPlotInfo* PlotInfo = nullptr;
+ };
+
+ class GarrisonPlotRemoved final : public ServerPacket
+ {
+ public:
+ GarrisonPlotRemoved() : ServerPacket(SMSG_GARRISON_PLOT_REMOVED, 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 GarrPlotInstanceID = 0;
+ };
+
+ class GarrisonAddFollowerResult final : public ServerPacket
+ {
+ public:
+ GarrisonAddFollowerResult() : ServerPacket(SMSG_GARRISON_ADD_FOLLOWER_RESULT, 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 5 * 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ GarrisonFollower Follower;
+ uint32 Result = 0;
+ };
+ }
+}
+
+#endif // GarrisonPackets_h__
diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp
index d0383a82160..34ea92ce27c 100644
--- a/src/server/game/Server/Packets/GuildPackets.cpp
+++ b/src/server/game/Server/Packets/GuildPackets.cpp
@@ -30,6 +30,7 @@ WorldPacket const* WorldPackets::Guild::QueryGuildInfoResponse::Write()
{
_worldPacket << GuildGuid;
_worldPacket.WriteBit(Info.is_initialized());
+ _worldPacket.FlushBits();
if (Info)
{
@@ -48,13 +49,16 @@ WorldPacket const* WorldPackets::Guild::QueryGuildInfoResponse::Write()
_worldPacket << uint32(rank.RankOrder);
_worldPacket.WriteBits(rank.RankName.size(), 7);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(rank.RankName);
}
_worldPacket.WriteBits(Info->GuildName.size(), 7);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(Info->GuildName);
}
- _worldPacket.FlushBits();
return &_worldPacket;
}
@@ -69,7 +73,6 @@ WorldPacket const* WorldPackets::Guild::GuildRoster::Write()
for (GuildRosterMemberData const& member : MemberData)
_worldPacket << member;
- _worldPacket.ResetBitPos();
_worldPacket.WriteBits(WelcomeText.length(), 10);
_worldPacket.WriteBits(InfoText.length(), 10);
_worldPacket.FlushBits();
@@ -798,10 +801,10 @@ WorldPacket const* WorldPackets::Guild::GuildChallengeUpdate::Write()
void WorldPackets::Guild::SaveGuildEmblem::Read()
{
_worldPacket >> Vendor;
- _worldPacket >> BStyle;
_worldPacket >> EStyle;
- _worldPacket >> BColor;
_worldPacket >> EColor;
+ _worldPacket >> BStyle;
+ _worldPacket >> BColor;
_worldPacket >> Bg;
}
diff --git a/src/server/game/Server/Packets/InstancePackets.cpp b/src/server/game/Server/Packets/InstancePackets.cpp
new file mode 100644
index 00000000000..7cf46454533
--- /dev/null
+++ b/src/server/game/Server/Packets/InstancePackets.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 "InstancePackets.h"
+
+WorldPacket const* WorldPackets::Instance::UpdateLastInstance::Write()
+{
+ _worldPacket << uint32(MapID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Instance::UpdateInstanceOwnership::Write()
+{
+ _worldPacket << int32(IOwnInstance);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Instance::InstanceInfo::Write()
+{
+ _worldPacket << int32(LockList.size());
+
+ for (InstanceLockInfos const& lockInfos : LockList)
+ _worldPacket << lockInfos;
+
+ return &_worldPacket;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Instance::InstanceLockInfos const& lockInfos)
+{
+ data << lockInfos.MapID;
+ data << lockInfos.DifficultyID;
+ data << lockInfos.InstanceID;
+ data << lockInfos.TimeRemaining;
+ data << lockInfos.CompletedMask;
+
+ data.WriteBit(lockInfos.Locked);
+ data.WriteBit(lockInfos.Extended);
+
+ data.FlushBits();
+
+ return data;
+}
+
+WorldPacket const* WorldPackets::Instance::InstanceReset::Write()
+{
+ _worldPacket << uint32(MapID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Instance::InstanceResetFailed::Write()
+{
+ _worldPacket << uint32(MapID);
+ _worldPacket.WriteBits(ResetFailedReason, 2);
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/InstancePackets.h b/src/server/game/Server/Packets/InstancePackets.h
new file mode 100644
index 00000000000..bfc14dddc5b
--- /dev/null
+++ b/src/server/game/Server/Packets/InstancePackets.h
@@ -0,0 +1,113 @@
+/*
+ * 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 InstancePackets_h__
+#define InstancePackets_h__
+
+#include "Packet.h"
+#include "ObjectGuid.h"
+
+namespace WorldPackets
+{
+ namespace Instance
+ {
+ class UpdateLastInstance final : public ServerPacket
+ {
+ public:
+ UpdateLastInstance() : ServerPacket(SMSG_UPDATE_LAST_INSTANCE, 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 MapID = 0;
+ };
+
+ // This packet is no longer sent - it is only here for documentation purposes
+ class UpdateInstanceOwnership final : public ServerPacket
+ {
+ public:
+ UpdateInstanceOwnership() : ServerPacket(SMSG_UPDATE_INSTANCE_OWNERSHIP, 4) { }
+
+ WorldPacket const* Write() override;
+
+ int32 IOwnInstance = 0; // Used to control whether "Reset all instances" button appears on the UI - Script_CanShowResetInstances()
+ // but it has been deperecated in favor of simply checking group leader, being inside an instance or using dungeon finder
+ };
+
+ struct InstanceLockInfos
+ {
+ uint64 InstanceID = 0u;
+ uint32 MapID = 0u;
+ uint32 DifficultyID = 0u;
+ int32 TimeRemaining = 0;
+ uint32 CompletedMask = 0u;
+
+ bool Locked = false;
+ bool Extended = false;
+ };
+
+ class InstanceInfo final : public ServerPacket
+ {
+ public:
+ InstanceInfo() : ServerPacket(SMSG_INSTANCE_INFO, 4) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<InstanceLockInfos> LockList;
+ };
+
+ class ResetInstances final : public ClientPacket
+ {
+ public:
+ ResetInstances(WorldPacket&& packet) : ClientPacket(CMSG_RESET_INSTANCES, std::move(packet)) { }
+
+ void Read() override { }
+ };
+
+ class InstanceReset final : public ServerPacket
+ {
+ public:
+ InstanceReset() : ServerPacket(SMSG_INSTANCE_RESET, 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 MapID = 0;
+ };
+
+ class InstanceResetFailed final : public ServerPacket
+ {
+ public:
+ InstanceResetFailed() : ServerPacket(SMSG_INSTANCE_RESET_FAILED, 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 MapID = 0;
+ uint8 ResetFailedReason = 0;
+ };
+
+ class ResetFailedNotify final : public ServerPacket
+ {
+ public:
+ ResetFailedNotify() : ServerPacket(SMSG_RESET_FAILED_NOTIFY, 0) { }
+
+ WorldPacket const* Write() override { return &_worldPacket; }
+ };
+ }
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Instance::InstanceLockInfos const& lockInfos);
+
+#endif // InstancePackets_h__
diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp
index 3feea2cdc98..8b0bec535b3 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -369,3 +369,26 @@ void WorldPackets::Item::WrapItem::Read()
{
_worldPacket >> Inv;
}
+
+void WorldPackets::Item::CancelTempEnchantment::Read()
+{
+ _worldPacket >> Slot;
+}
+
+WorldPacket const* WorldPackets::Item::ItemCooldown::Write()
+{
+ _worldPacket << ItemGuid;
+ _worldPacket << uint32(SpellID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Item::ItemEnchantTimeUpdate::Write()
+{
+ _worldPacket << ItemGuid;
+ _worldPacket << uint32(DurationLeft);
+ _worldPacket << uint32(Slot);
+ _worldPacket << OwnerGuid;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h
index d37df357513..e73f42bcaf2 100644
--- a/src/server/game/Server/Packets/ItemPackets.h
+++ b/src/server/game/Server/Packets/ItemPackets.h
@@ -353,6 +353,40 @@ namespace WorldPackets
InvUpdate Inv;
};
+ class CancelTempEnchantment final : public ClientPacket
+ {
+ public:
+ CancelTempEnchantment(WorldPacket&& packet) : ClientPacket(CMSG_CANCEL_TEMP_ENCHANTMENT, std::move(packet)) { }
+
+ void Read() override;
+
+ int32 Slot = 0;
+ };
+
+ class ItemCooldown final : public ServerPacket
+ {
+ public:
+ ItemCooldown() : ServerPacket(SMSG_ITEM_COOLDOWN, 20) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid ItemGuid;
+ uint32 SpellID = 0;
+ };
+
+ class ItemEnchantTimeUpdate final : public ServerPacket
+ {
+ public:
+ ItemEnchantTimeUpdate() : ServerPacket(SMSG_ITEM_ENCHANT_TIME_UPDATE, 40) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid OwnerGuid;
+ ObjectGuid ItemGuid;
+ uint32 DurationLeft = 0;
+ uint32 Slot = 0;
+ };
+
ByteBuffer& operator>>(ByteBuffer& data, InvUpdate& invUpdate);
}
}
diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp
index 40dde52700b..bbd3fcb2ba7 100644
--- a/src/server/game/Server/Packets/MiscPackets.cpp
+++ b/src/server/game/Server/Packets/MiscPackets.cpp
@@ -439,3 +439,84 @@ WorldPacket const* WorldPackets::Misc::PlaySound::Write()
return &_worldPacket;
}
+
+void WorldPackets::Misc::FarSight::Read()
+{
+ Enable = _worldPacket.ReadBit();
+}
+
+WorldPacket const* WorldPackets::Misc::Dismount::Write()
+{
+ _worldPacket << Guid;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Misc::SaveCUFProfiles::Read()
+{
+ uint32 count;
+ _worldPacket >> count;
+
+ for (uint8 i = 0; i < count && i < MAX_CUF_PROFILES; i++)
+ {
+ std::unique_ptr<CUFProfile> cufProfile = Trinity::make_unique<CUFProfile>();
+
+ uint8 strLen = _worldPacket.ReadBits(7);
+
+ // Bool Options
+ for (uint8 option = 0; option < CUF_BOOL_OPTIONS_COUNT; option++)
+ cufProfile->BoolOptions.set(option, _worldPacket.ReadBit());
+
+ // Other Options
+ _worldPacket >> cufProfile->FrameHeight;
+ _worldPacket >> cufProfile->FrameWidth;
+
+ _worldPacket >> cufProfile->SortBy;
+ _worldPacket >> cufProfile->HealthText;
+
+ _worldPacket >> cufProfile->TopPoint;
+ _worldPacket >> cufProfile->BottomPoint;
+ _worldPacket >> cufProfile->LeftPoint;
+
+ _worldPacket >> cufProfile->TopOffset;
+ _worldPacket >> cufProfile->BottomOffset;
+ _worldPacket >> cufProfile->LeftOffset;
+
+ cufProfile->ProfileName = _worldPacket.ReadString(strLen);
+
+ CUFProfiles.push_back(std::move(cufProfile));
+ }
+}
+
+WorldPacket const* WorldPackets::Misc::LoadCUFProfiles::Write()
+{
+ _worldPacket << uint32(CUFProfiles.size());
+
+ for (CUFProfile const* cufProfile : CUFProfiles)
+ {
+ _worldPacket.WriteBits(cufProfile->ProfileName.size(), 7);
+
+ // Bool Options
+ for (uint8 option = 0; option < CUF_BOOL_OPTIONS_COUNT; option++)
+ _worldPacket.WriteBit(cufProfile->BoolOptions[option]);
+
+ // Other Options
+ _worldPacket << cufProfile->FrameHeight;
+ _worldPacket << cufProfile->FrameWidth;
+
+ _worldPacket << cufProfile->SortBy;
+ _worldPacket << cufProfile->HealthText;
+
+ _worldPacket << cufProfile->TopPoint;
+ _worldPacket << cufProfile->BottomPoint;
+ _worldPacket << cufProfile->LeftPoint;
+
+ _worldPacket << cufProfile->TopOffset;
+ _worldPacket << cufProfile->BottomOffset;
+ _worldPacket << cufProfile->LeftOffset;
+
+ _worldPacket.WriteString(cufProfile->ProfileName);
+ }
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h
index 5673680afe6..93bac0d208b 100644
--- a/src/server/game/Server/Packets/MiscPackets.h
+++ b/src/server/game/Server/Packets/MiscPackets.h
@@ -24,6 +24,7 @@
#include "G3D/Vector3.h"
#include "Object.h"
#include "Unit.h"
+#include "Player.h"
#include "Weather.h"
namespace WorldPackets
@@ -622,6 +623,46 @@ namespace WorldPackets
void Read() override { }
};
+
+ class FarSight final : public ClientPacket
+ {
+ public:
+ FarSight(WorldPacket&& packet) : ClientPacket(CMSG_FAR_SIGHT, std::move(packet)) { }
+
+ void Read() override;
+
+ bool Enable = false;
+ };
+
+ class Dismount final : public ServerPacket
+ {
+ public:
+ Dismount() : ServerPacket(SMSG_DISMOUNT, 16) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Guid;
+ };
+
+ class SaveCUFProfiles final : public ClientPacket
+ {
+ public:
+ SaveCUFProfiles(WorldPacket&& packet) : ClientPacket(CMSG_SAVE_CUF_PROFILES, std::move(packet)) { }
+
+ void Read() override;
+
+ std::vector<std::unique_ptr<CUFProfile>> CUFProfiles;
+ };
+
+ class LoadCUFProfiles final : public ServerPacket
+ {
+ public:
+ LoadCUFProfiles() : ServerPacket(SMSG_LOAD_CUF_PROFILES, 20) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<CUFProfile const*> CUFProfiles;
+ };
}
}
diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp
index f0db56302f6..14fb2ecb33c 100644
--- a/src/server/game/Server/Packets/MovementPackets.cpp
+++ b/src/server/game/Server/Packets/MovementPackets.cpp
@@ -198,9 +198,9 @@ ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MonsterSplineFi
data << monsterSplineFilter.BaseSpeed;
data << monsterSplineFilter.StartOffset;
data << monsterSplineFilter.DistToPrevFilterKey;
+ data << monsterSplineFilter.AddedToStart;
for (WorldPackets::Movement::MonsterSplineFilterKey const& filterKey : monsterSplineFilter.FilterKeys)
data << filterKey;
- data << monsterSplineFilter.AddedToStart;
data.WriteBits(monsterSplineFilter.FilterFlags, 2);
data.FlushBits();
diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h
index 6803bdf3b95..d4fb41cf330 100644
--- a/src/server/game/Server/Packets/MovementPackets.h
+++ b/src/server/game/Server/Packets/MovementPackets.h
@@ -398,7 +398,7 @@ namespace WorldPackets
void Read() override;
ObjectGuid MoverGUID;
- uint32 TimeSkipped;
+ uint32 TimeSkipped = 0;
};
}
diff --git a/src/server/game/Server/Packets/NPCPackets.cpp b/src/server/game/Server/Packets/NPCPackets.cpp
index 4e44f07fd01..a6c74459bf5 100644
--- a/src/server/game/Server/Packets/NPCPackets.cpp
+++ b/src/server/game/Server/Packets/NPCPackets.cpp
@@ -175,3 +175,19 @@ WorldPacket const* WorldPackets::NPC::SpiritHealerConfirm::Write()
return &_worldPacket;
}
+
+void WorldPackets::NPC::TrainerBuySpell::Read()
+{
+ _worldPacket >> TrainerGUID;
+ _worldPacket >> TrainerID;
+ _worldPacket >> SpellID;
+}
+
+WorldPacket const* WorldPackets::NPC::TrainerBuyFailed::Write()
+{
+ _worldPacket << TrainerGUID;
+ _worldPacket << SpellID;
+ _worldPacket << TrainerFailedReason;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/NPCPackets.h b/src/server/game/Server/Packets/NPCPackets.h
index ec23c51a206..990ef897986 100644
--- a/src/server/game/Server/Packets/NPCPackets.h
+++ b/src/server/game/Server/Packets/NPCPackets.h
@@ -216,6 +216,30 @@ namespace WorldPackets
ObjectGuid Unit;
};
+
+ class TrainerBuySpell final : public ClientPacket
+ {
+ public:
+ TrainerBuySpell(WorldPacket&& packet) : ClientPacket(CMSG_TRAINER_BUY_SPELL, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid TrainerGUID;
+ int32 TrainerID = 0;
+ int32 SpellID = 0;
+ };
+
+ class TrainerBuyFailed final : public ServerPacket
+ {
+ public:
+ TrainerBuyFailed() : ServerPacket(SMSG_TRAINER_BUY_FAILED, 16 + 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid TrainerGUID;
+ int32 SpellID = 0;
+ int32 TrainerFailedReason = 0;
+ };
}
}
diff --git a/src/server/game/Server/Packets/PartyPackets.cpp b/src/server/game/Server/Packets/PartyPackets.cpp
new file mode 100644
index 00000000000..f5cbfd7f5c2
--- /dev/null
+++ b/src/server/game/Server/Packets/PartyPackets.cpp
@@ -0,0 +1,715 @@
+/*
+ * 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 "PartyPackets.h"
+
+#include "Player.h"
+#include "Pet.h"
+#include "Vehicle.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
+#include "ObjectMgr.h"
+
+WorldPacket const* WorldPackets::Party::PartyCommandResult::Write()
+{
+ _worldPacket.WriteBits(Name.size(), 9);
+
+ _worldPacket.WriteBits(Command, 4);
+ _worldPacket.WriteBits(Result, 6);
+
+ _worldPacket << ResultData;
+ _worldPacket << ResultGUID;
+ _worldPacket.WriteString(Name);
+
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::PartyInviteClient::Read()
+{
+ uint32 targetNameLen, targetRealmLen;
+
+ _worldPacket >> PartyIndex;
+ _worldPacket >> ProposedRoles;
+ _worldPacket >> TargetGUID;
+ _worldPacket >> TargetCfgRealmID;
+
+ targetNameLen = _worldPacket.ReadBits(9);
+ targetRealmLen = _worldPacket.ReadBits(9);
+
+ TargetName = _worldPacket.ReadString(targetNameLen);
+ TargetRealm = _worldPacket.ReadString(targetRealmLen);
+}
+
+WorldPacket const* WorldPackets::Party::PartyInvite::Write()
+{
+ // Order guessed
+ _worldPacket.WriteBit(CanAccept);
+ _worldPacket.WriteBit(MightCRZYou);
+ _worldPacket.WriteBit(MustBeBNetFriend);
+ _worldPacket.WriteBit(AllowMultipleRoles);
+ _worldPacket.WriteBit(IsXRealm);
+
+ _worldPacket.WriteBits(InviterName.size(), 6);
+
+ _worldPacket << InviterGUID;
+ _worldPacket << InviterBNetAccountId;
+
+ _worldPacket << InviterVirtualRealmAddress;
+ _worldPacket << Unk1;
+
+ _worldPacket.WriteBit(IsLocal);
+ _worldPacket.WriteBit(Unk2);
+
+ _worldPacket.WriteBits(InviterRealmNameActual.size(), 8);
+ _worldPacket.WriteBits(InviterRealmNameNormalized.size(), 8);
+ _worldPacket.WriteString(InviterRealmNameActual);
+ _worldPacket.WriteString(InviterRealmNameNormalized);
+
+ _worldPacket << ProposedRoles;
+ _worldPacket << int32(LfgSlots.size());
+ _worldPacket << LfgCompletedMask;
+
+ _worldPacket.WriteString(InviterName);
+
+ for (int32 LfgSlot : LfgSlots)
+ _worldPacket << LfgSlot;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::PartyInvite::Initialize(Player* const inviter, int32 proposedRoles, bool canAccept)
+{
+ CanAccept = canAccept;
+
+ InviterName = inviter->GetName();
+ InviterGUID = inviter->GetGUID();
+ InviterBNetAccountId = inviter->GetSession()->GetAccountGUID();
+
+ ProposedRoles = proposedRoles;
+
+ std::string realmName = sObjectMgr->GetRealmName(realmHandle.Index);
+
+ InviterVirtualRealmAddress = GetVirtualRealmAddress();
+ InviterRealmNameActual = realmName;
+ InviterRealmNameNormalized = realmName;
+}
+
+void WorldPackets::Party::PartyInviteResponse::Read()
+{
+ _worldPacket >> PartyIndex;
+
+ Accept = _worldPacket.ReadBit();
+
+ bool hasRolesDesired = _worldPacket.ReadBit();
+ if (hasRolesDesired)
+ {
+ RolesDesired = boost::in_place();
+ _worldPacket >> *RolesDesired;
+ }
+}
+
+void WorldPackets::Party::PartyUninvite::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+
+ uint8 reasonLen = _worldPacket.ReadBits(8);
+ Reason = _worldPacket.ReadString(reasonLen);
+}
+
+WorldPacket const* WorldPackets::Party::GroupDecline::Write()
+{
+ _worldPacket.WriteBits(Name.length(), 9);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(Name);
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::RequestPartyMemberStats::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+}
+
+WorldPacket const* WorldPackets::Party::PartyMemberStats::Write()
+{
+ _worldPacket.WriteBit(ForEnemy);
+
+ _worldPacket << MemberStats;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::SetPartyLeader::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+}
+
+void WorldPackets::Party::SetRole::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> TargetGUID;
+ _worldPacket >> Role;
+}
+
+WorldPacket const* WorldPackets::Party::RoleChangedInform::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << From;
+ _worldPacket << ChangedUnit;
+ _worldPacket << OldRole;
+ _worldPacket << NewRole;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::LeaveGroup::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+void WorldPackets::Party::SetLootMethod::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> LootMethod;
+ _worldPacket >> LootMasterGUID;
+ _worldPacket >> LootThreshold;
+}
+
+void WorldPackets::Party::MinimapPingClient::Read()
+{
+ _worldPacket >> PositionX;
+ _worldPacket >> PositionY;
+ _worldPacket >> PartyIndex;
+}
+
+WorldPacket const* WorldPackets::Party::MinimapPing::Write()
+{
+ _worldPacket << Sender;
+ _worldPacket << PositionX;
+ _worldPacket << PositionY;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::UpdateRaidTarget::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> Target;
+ _worldPacket >> Symbol;
+}
+
+WorldPacket const* WorldPackets::Party::SendRaidTargetUpdateSingle::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << Symbol;
+ _worldPacket << Target;
+ _worldPacket << ChangedBy;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::SendRaidTargetUpdateAll::Write()
+{
+ _worldPacket << PartyIndex;
+
+ _worldPacket << int32(TargetIcons.size());
+
+ std::map<uint8, ObjectGuid>::const_iterator itr;
+ for (itr = TargetIcons.begin(); itr != TargetIcons.end(); itr++)
+ {
+ _worldPacket << itr->second;
+ _worldPacket << itr->first;
+ }
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::ConvertRaid::Read()
+{
+ Raid = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::RequestPartyJoinUpdates::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+void WorldPackets::Party::SetAssistantLeader::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> Target;
+ Apply = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::DoReadyCheck::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+WorldPacket const* WorldPackets::Party::ReadyCheckStarted::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << PartyGUID;
+ _worldPacket << InitiatorGUID;
+ _worldPacket << Duration;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::ReadyCheckResponseClient::Read()
+{
+ _worldPacket >> PartyIndex;
+ IsReady = _worldPacket.ReadBit();
+}
+
+WorldPacket const* WorldPackets::Party::ReadyCheckResponse::Write()
+{
+ _worldPacket << PartyGUID;
+ _worldPacket << Player;
+
+ _worldPacket.WriteBit(IsReady);
+
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::ReadyCheckCompleted::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << PartyGUID;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::OptOutOfLoot::Read()
+{
+ PassOnLoot = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::InitiateRolePoll::Read()
+{
+ _worldPacket >> PartyIndex;
+}
+
+WorldPacket const* WorldPackets::Party::RolePollInform::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << From;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::GroupNewLeader::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket.WriteBits(Name.size(), 6);
+ _worldPacket.WriteString(Name);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Party::PartyUpdate::Write()
+{
+ _worldPacket << PartyType;
+ _worldPacket << PartyIndex;
+ _worldPacket << PartyFlags;
+
+ _worldPacket << MyIndex;
+ _worldPacket << PartyGUID;
+ _worldPacket << SequenceNum;
+ _worldPacket << LeaderGUID;
+
+ _worldPacket << PlayerList;
+
+ _worldPacket.WriteBit(LfgInfos.is_initialized());
+ _worldPacket.WriteBit(LootSettings.is_initialized());
+ _worldPacket.WriteBit(DifficultySettings.is_initialized());
+
+ _worldPacket.FlushBits();
+
+ if (LfgInfos.is_initialized())
+ _worldPacket << *LfgInfos;
+
+ if (LootSettings.is_initialized())
+ _worldPacket << *LootSettings;
+
+ if (DifficultySettings.is_initialized())
+ _worldPacket << *DifficultySettings;
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::SetEveryoneIsAssistant::Read()
+{
+ _worldPacket >> PartyIndex;
+ EveryoneIsAssistant = _worldPacket.ReadBit();
+}
+
+void WorldPackets::Party::ChangeSubGroup::Read()
+{
+ _worldPacket >> TargetGUID;
+ _worldPacket >> PartyIndex;
+ _worldPacket >> NewSubGroup;
+}
+
+void WorldPackets::Party::SwapSubGroups::Read()
+{
+ _worldPacket >> PartyIndex;
+ _worldPacket >> FirstTarget;
+ _worldPacket >> SecondTarget;
+}
+
+void WorldPackets::Party::ClearRaidMarker::Read()
+{
+ _worldPacket >> MarkerId;
+}
+
+WorldPacket const* WorldPackets::Party::RaidMarkersChanged::Write()
+{
+ _worldPacket << PartyIndex;
+ _worldPacket << ActiveMarkers;
+
+ _worldPacket.WriteBits(RaidMarkers.size(), 4);
+ _worldPacket.FlushBits();
+
+ for (RaidMarker* raidMarker : RaidMarkers)
+ {
+ _worldPacket << raidMarker->TransportGUID;
+ _worldPacket << raidMarker->Location.GetMapId();
+ _worldPacket << raidMarker->Location.PositionXYZStream();
+ }
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Party::PartyMemberStats::Initialize(Player const* player)
+{
+ ForEnemy = false;
+
+ MemberStats.GUID = player->GetGUID();
+
+ // Status
+ MemberStats.Status = MEMBER_STATUS_ONLINE;
+
+ if (player->IsPvP())
+ MemberStats.Status |= MEMBER_STATUS_PVP;
+
+ if (!player->IsAlive())
+ {
+ if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
+ MemberStats.Status |= MEMBER_STATUS_GHOST;
+ else
+ MemberStats.Status |= MEMBER_STATUS_DEAD;
+ }
+
+ if (player->IsFFAPvP())
+ MemberStats.Status |= MEMBER_STATUS_PVP_FFA;
+
+ if (player->isAFK())
+ MemberStats.Status |= MEMBER_STATUS_AFK;
+
+ if (player->isDND())
+ MemberStats.Status |= MEMBER_STATUS_DND;
+
+ // Level
+ MemberStats.Level = player->getLevel();
+
+ // Health
+ MemberStats.CurrentHealth = player->GetHealth();
+ MemberStats.MaxHealth = player->GetMaxHealth();
+
+ // Power
+ MemberStats.PowerType = player->getPowerType();
+ MemberStats.CurrentPower = player->GetPower(player->getPowerType());
+ MemberStats.MaxPower = player->GetMaxPower(player->getPowerType());
+
+ // Position
+ MemberStats.ZoneID = player->GetZoneId();
+ MemberStats.PositionX = int16(player->GetPositionX());
+ MemberStats.PositionY = int16(player->GetPositionY());
+ MemberStats.PositionZ = int16(player->GetPositionZ());
+
+ // Unk
+ MemberStats.Unk322 = 0; // Always 0
+ MemberStats.Unk704[0] = 1; // Always 1
+ MemberStats.Unk704[1] = 0; // Always 0
+ MemberStats.Unk200000 = 0; // Always 0
+
+ MemberStats.Unk2000000 = 0;
+ MemberStats.Unk4000000 = 0;
+
+ // Vehicle
+ if (player->GetVehicle() && player->GetVehicle()->GetVehicleInfo())
+ MemberStats.VehicleSeat = player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat];
+
+ // Auras
+ for (uint8 i = 0; i < MAX_AURAS; ++i)
+ {
+ if (AuraApplication const* aurApp = player->GetVisibleAura(i))
+ {
+ WorldPackets::Party::GroupAura aura;
+
+ aura.SpellId = aurApp->GetBase()->GetId();
+ aura.EffectMask = aurApp->GetEffectMask();
+ aura.Scalings = aurApp->GetFlags(); // ??
+
+ if (aurApp->GetFlags() & AFLAG_SCALABLE)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ float scale = 0.f;
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ scale = float(eff->GetAmount());
+ aura.EffectScales.push_back(scale);
+ }
+ }
+
+ MemberStats.AuraList.push_back(aura);
+ }
+ }
+
+ // Phases
+ std::set<uint32> const& phases = player->GetPhases();
+ MemberStats.Phases.PhaseShiftFlags = 0x08 | (phases.size() ? 0x10 : 0);
+ MemberStats.Phases.PersonalGUID = ObjectGuid::Empty;
+ for (uint32 phaseId : phases)
+ {
+ WorldPackets::Party::GroupPhase phase;
+ phase.Id = phaseId;
+ phase.Flags = 1;
+ MemberStats.Phases.List.push_back(phase);
+ }
+
+ // Pet
+ if (player->GetPet())
+ {
+ Pet* pet = player->GetPet();
+
+ MemberStats.PetStats = boost::in_place();
+
+ MemberStats.PetStats->GUID = pet->GetGUID();
+ MemberStats.PetStats->Name = pet->GetName();
+ MemberStats.PetStats->ModelId = pet->GetDisplayId();
+
+ MemberStats.PetStats->CurrentHealth = pet->GetHealth();
+ MemberStats.PetStats->MaxHealth = pet->GetMaxHealth();
+
+ for (uint8 i = 0; i < MAX_AURAS; ++i)
+ {
+ if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
+ {
+ WorldPackets::Party::GroupAura aura;
+
+ aura.SpellId = aurApp->GetBase()->GetId();
+ aura.EffectMask = aurApp->GetEffectMask();
+ aura.Scalings = aurApp->GetFlags(); // ??
+
+ if (aurApp->GetFlags() & AFLAG_SCALABLE)
+ {
+ for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ float scale = 0.f;
+ if (AuraEffect const* eff = aurApp->GetBase()->GetEffect(i))
+ scale = float(eff->GetAmount());
+ aura.EffectScales.push_back(scale);
+ }
+ }
+
+ MemberStats.PetStats->AuraList.push_back(aura);
+ }
+ }
+ }
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhase const& phase)
+{
+ data << phase.Flags;
+ data << phase.Id;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhases const& phases)
+{
+ data << phases.PhaseShiftFlags;
+ data << int32(phases.List.size());
+ data << phases.PersonalGUID;
+
+ for (WorldPackets::Party::GroupPhase const& phase : phases.List)
+ data << phase;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupAura const& aura)
+{
+ data << aura.SpellId;
+ data << aura.Scalings;
+ data << aura.EffectMask;
+
+ data << int32(aura.EffectScales.size());
+ for (float scale : aura.EffectScales)
+ data << scale;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupAura> const& auraList)
+{
+ data << int32(auraList.size());
+ for (WorldPackets::Party::GroupAura const& aura : auraList)
+ data << aura;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPetStats const& petStats)
+{
+ data << petStats.GUID;
+
+ data << petStats.ModelId;
+
+ data << petStats.CurrentHealth;
+ data << petStats.MaxHealth;
+
+ data << petStats.AuraList;
+
+ data.WriteBits(petStats.Name.size(), 8);
+ data.FlushBits();
+ data.WriteString(petStats.Name);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupMemberStats const& memberStats)
+{
+ data << memberStats.GUID;
+
+ for (uint8 i = 0; i < 2; i++)
+ data << memberStats.Unk704[i];
+
+ data << memberStats.Status;
+
+ data << memberStats.PowerType;
+
+ data << memberStats.Unk322;
+
+ data << memberStats.CurrentHealth;
+ data << memberStats.MaxHealth;
+
+ data << memberStats.CurrentPower;
+ data << memberStats.MaxPower;
+
+ data << memberStats.Level;
+
+ data << memberStats.Unk200000;
+
+ data << memberStats.ZoneID;
+
+ data << memberStats.Unk2000000;
+ data << memberStats.Unk4000000;
+
+ data << memberStats.PositionX;
+ data << memberStats.PositionY;
+ data << memberStats.PositionZ;
+
+ data << memberStats.VehicleSeat;
+
+ data << int32(memberStats.AuraList.size());
+
+ data << memberStats.Phases;
+
+ for (WorldPackets::Party::GroupAura const& aura : memberStats.AuraList)
+ data << aura;
+
+ data.WriteBit(memberStats.PetStats.is_initialized());
+ data.FlushBits();
+
+ if (memberStats.PetStats.is_initialized())
+ data << *memberStats.PetStats;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupPlayerInfos> const& playerList)
+{
+ data << int32(playerList.size());
+
+ for (WorldPackets::Party::GroupPlayerInfos const& playerInfos : playerList)
+ data << playerInfos;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPlayerInfos const& playerInfos)
+{
+ data.WriteBits(playerInfos.Name.size(), 6);
+ data.FlushBits();
+
+ data << playerInfos.GUID;
+ data << playerInfos.Status;
+ data << playerInfos.Subgroup;
+ data << playerInfos.Flags;
+ data << playerInfos.RolesAssigned;
+ data << playerInfos.Class;
+
+ data.WriteString(playerInfos.Name);
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLfgInfos const& lfgInfos)
+{
+ data << lfgInfos.MyFlags;
+ data << lfgInfos.Slot;
+ data << lfgInfos.MyRandomSlot;
+ data << lfgInfos.MyPartialClear;
+ data << lfgInfos.MyGearDiff;
+ data << lfgInfos.MyStrangerCount;
+ data << lfgInfos.MyKickVoteCount;
+ data << lfgInfos.BootCount;
+
+ data.WriteBit(lfgInfos.Aborted);
+ data.WriteBit(lfgInfos.MyFirstReward);
+ data.FlushBits();
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLootSettings const& lootSettings)
+{
+ data << lootSettings.Method;
+ data << lootSettings.LootMaster;
+ data << lootSettings.Threshold;
+
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupDifficultySettings const& difficultySettings)
+{
+ data << difficultySettings.DungeonDifficultyID;
+ data << difficultySettings.RaidDifficultyID;
+ data << difficultySettings.LegacyRaidDifficultyID;
+
+ return data;
+}
diff --git a/src/server/game/Server/Packets/PartyPackets.h b/src/server/game/Server/Packets/PartyPackets.h
new file mode 100644
index 00000000000..ed3eed60ef4
--- /dev/null
+++ b/src/server/game/Server/Packets/PartyPackets.h
@@ -0,0 +1,616 @@
+/*
+ * 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 PartyPackets_h__
+#define PartyPackets_h__
+
+#include "Packet.h"
+#include "ObjectGuid.h"
+#include "Group.h"
+
+namespace WorldPackets
+{
+ namespace Party
+ {
+ class PartyCommandResult final : public ServerPacket
+ {
+ public:
+ PartyCommandResult() : ServerPacket(SMSG_PARTY_COMMAND_RESULT, 23) { }
+
+ WorldPacket const* Write() override;
+
+ std::string Name;
+ uint8 Command = 0u;
+ uint8 Result = 0u;
+ uint32 ResultData = 0u;
+ ObjectGuid ResultGUID;
+ };
+
+ class PartyInviteClient final : public ClientPacket
+ {
+ public:
+ PartyInviteClient(WorldPacket&& packet) : ClientPacket(CMSG_PARTY_INVITE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ int32 ProposedRoles = 0;
+ int32 TargetCfgRealmID = 0;
+ std::string TargetName;
+ std::string TargetRealm;
+ ObjectGuid TargetGUID;
+ };
+
+ class PartyInvite final : public ServerPacket
+ {
+ public:
+ PartyInvite() : ServerPacket(SMSG_PARTY_INVITE, 55) { }
+
+ WorldPacket const* Write() override;
+ void Initialize(Player* const inviter, int32 proposedRoles, bool canAccept);
+
+ bool MightCRZYou = false;
+ bool MustBeBNetFriend = false;
+ bool AllowMultipleRoles = false;
+ bool Unk2 = false;
+ int16 Unk1 = 0;
+
+ bool CanAccept = false;
+
+ // Inviter
+ ObjectGuid InviterGUID;
+ ObjectGuid InviterBNetAccountId;
+ std::string InviterName;
+
+ // Realm
+ bool IsXRealm = false;
+ bool IsLocal = true;
+ uint32 InviterVirtualRealmAddress = 0u;
+ std::string InviterRealmNameActual;
+ std::string InviterRealmNameNormalized;
+
+ // Lfg
+ int32 ProposedRoles = 0;
+ int32 LfgCompletedMask = 0;
+ std::vector<int32> LfgSlots;
+ };
+
+ class PartyInviteResponse final : public ClientPacket
+ {
+ public:
+ PartyInviteResponse(WorldPacket&& packet) : ClientPacket(CMSG_PARTY_INVITE_RESPONSE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ bool Accept = false;
+ Optional<int32> RolesDesired;
+ };
+
+ class PartyUninvite final : public ClientPacket
+ {
+ public:
+ PartyUninvite(WorldPacket&& packet) : ClientPacket(CMSG_PARTY_UNINVITE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ std::string Reason;
+ };
+
+ class GroupDecline final : public ServerPacket
+ {
+ public:
+ GroupDecline(std::string const& name) : ServerPacket(SMSG_GROUP_DECLINE, 2 + name.size()), Name(name) { }
+
+ WorldPacket const* Write() override;
+
+ std::string Name;
+ };
+
+ class RequestPartyMemberStats final : public ClientPacket
+ {
+ public:
+ RequestPartyMemberStats(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_PARTY_MEMBER_STATS, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ };
+
+ struct GroupPhase
+ {
+ uint16 Flags = 0u;
+ uint16 Id = 0u;
+ };
+
+ struct GroupPhases
+ {
+ int32 PhaseShiftFlags = 0;
+ ObjectGuid PersonalGUID;
+ std::vector<GroupPhase> List;
+ };
+
+ struct GroupAura
+ {
+ uint32 SpellId = 0u;
+ uint8 Scalings = 0;
+ uint32 EffectMask = 0u;
+ std::vector<float> EffectScales;
+ };
+
+ struct GroupPetStats
+ {
+ ObjectGuid GUID;
+ std::string Name;
+ int16 ModelId = 0;
+
+ int32 CurrentHealth = 0;
+ int32 MaxHealth = 0;
+
+ std::vector<GroupAura> AuraList;
+ };
+
+ struct GroupMemberStats
+ {
+ ObjectGuid GUID;
+ int16 Level = 0;
+ int16 Status = 0;
+
+ int32 CurrentHealth = 0;
+ int32 MaxHealth;
+
+ uint8 PowerType = 0u;
+ int16 CurrentPower = 0;
+ int16 MaxPower = 0;
+
+ int16 ZoneID = 0;
+ int16 PositionX = 0;
+ int16 PositionY = 0;
+ int16 PositionZ = 0;
+
+ int32 VehicleSeat = 0;
+
+ GroupPhases Phases;
+ std::vector<GroupAura> AuraList;
+ Optional<GroupPetStats> PetStats;
+
+ int16 Unk322 = 0;
+ int16 Unk200000 = 0;
+ int16 Unk2000000 = 0;
+ int32 Unk4000000 = 0;
+ int8 Unk704[2];
+ };
+
+ class PartyMemberStats final : public ServerPacket
+ {
+ public:
+ PartyMemberStats() : ServerPacket(SMSG_PARTY_MEMBER_STATE, 80) { }
+
+ WorldPacket const* Write() override;
+ void Initialize(Player const* player);
+
+ GroupMemberStats MemberStats;
+ bool ForEnemy = false;
+ };
+
+ class SetPartyLeader final : public ClientPacket
+ {
+ public:
+ SetPartyLeader(WorldPacket&& packet) : ClientPacket(CMSG_SET_PARTY_LEADER, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ };
+
+ class SetRole final : public ClientPacket
+ {
+ public:
+ SetRole(WorldPacket&& packet) : ClientPacket(CMSG_SET_ROLE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid TargetGUID;
+ int32 Role = 0;
+ };
+
+ class RoleChangedInform final : public ServerPacket
+ {
+ public:
+ RoleChangedInform() : ServerPacket(SMSG_ROLE_CHANGED_INFORM, 41) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid From;
+ ObjectGuid ChangedUnit;
+ int32 OldRole = 0;
+ int32 NewRole = 0;
+ };
+
+ class LeaveGroup final : public ClientPacket
+ {
+ public:
+ LeaveGroup(WorldPacket&& packet) : ClientPacket(CMSG_LEAVE_GROUP, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class SetLootMethod final : public ClientPacket
+ {
+ public:
+ SetLootMethod(WorldPacket&& packet) : ClientPacket(CMSG_SET_LOOT_METHOD, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid LootMasterGUID;
+ uint8 LootMethod = 0u;
+ uint32 LootThreshold = 0u;
+ };
+
+ class MinimapPingClient final : public ClientPacket
+ {
+ public:
+ MinimapPingClient(WorldPacket&& packet) : ClientPacket(CMSG_MINIMAP_PING, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ float PositionX = 0.f;
+ float PositionY = 0.f;
+ };
+
+ class MinimapPing final : public ServerPacket
+ {
+ public:
+ MinimapPing() : ServerPacket(SMSG_MINIMAP_PING, 24) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Sender;
+ float PositionX = 0.f;
+ float PositionY = 0.f;
+ };
+
+ class UpdateRaidTarget final : public ClientPacket
+ {
+ public:
+ UpdateRaidTarget(WorldPacket&& packet) : ClientPacket(CMSG_UPDATE_RAID_TARGET, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid Target;
+ int8 Symbol = 0;
+ };
+
+ class SendRaidTargetUpdateSingle final : public ServerPacket
+ {
+ public:
+ SendRaidTargetUpdateSingle() : ServerPacket(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, 34) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid Target;
+ ObjectGuid ChangedBy;
+ int8 Symbol = 0;
+ };
+
+ class SendRaidTargetUpdateAll final : public ServerPacket
+ {
+ public:
+ SendRaidTargetUpdateAll() : ServerPacket(SMSG_SEND_RAID_TARGET_UPDATE_ALL, 1 + TARGET_ICONS_COUNT * (1 + 16)) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ std::map<uint8, ObjectGuid> TargetIcons;
+ };
+
+ class ConvertRaid final : public ClientPacket
+ {
+ public:
+ ConvertRaid(WorldPacket&& packet) : ClientPacket(CMSG_CONVERT_RAID, std::move(packet)) { }
+
+ void Read() override;
+
+ bool Raid = false;
+ };
+
+ class RequestPartyJoinUpdates final : public ClientPacket
+ {
+ public:
+ RequestPartyJoinUpdates(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_PARTY_JOIN_UPDATES, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class SetAssistantLeader final : public ClientPacket
+ {
+ public:
+ SetAssistantLeader(WorldPacket&& packet) : ClientPacket(CMSG_SET_ASSISTANT_LEADER, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Target;
+ int8 PartyIndex = 0;
+ bool Apply = false;
+ };
+
+ class DoReadyCheck final : public ClientPacket
+ {
+ public:
+ DoReadyCheck(WorldPacket&& packet) : ClientPacket(CMSG_DO_READY_CHECK, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class ReadyCheckStarted final : public ServerPacket
+ {
+ public:
+ ReadyCheckStarted() : ServerPacket(SMSG_READY_CHECK_STARTED, 37) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid PartyGUID;
+ ObjectGuid InitiatorGUID;
+ uint32 Duration = 0u;
+ };
+
+ class ReadyCheckResponseClient final : public ClientPacket
+ {
+ public:
+ ReadyCheckResponseClient(WorldPacket&& packet) : ClientPacket(CMSG_READY_CHECK_RESPONSE, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ bool IsReady = false;
+ };
+
+ class ReadyCheckResponse final : public ServerPacket
+ {
+ public:
+ ReadyCheckResponse() : ServerPacket(SMSG_READY_CHECK_RESPONSE, 19) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid PartyGUID;
+ ObjectGuid Player;
+ bool IsReady = false;
+ };
+
+ class ReadyCheckCompleted final : public ServerPacket
+ {
+ public:
+ ReadyCheckCompleted() : ServerPacket(SMSG_READY_CHECK_COMPLETED, 17) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid PartyGUID;
+ };
+
+ class RequestRaidInfo final : public ClientPacket
+ {
+ public:
+ RequestRaidInfo(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_RAID_INFO, std::move(packet)) { }
+
+ void Read() override { }
+ };
+
+ class OptOutOfLoot final : public ClientPacket
+ {
+ public:
+ OptOutOfLoot(WorldPacket&& packet) : ClientPacket(CMSG_OPT_OUT_OF_LOOT, std::move(packet)) { }
+
+ void Read() override;
+
+ bool PassOnLoot = false;
+ };
+
+ class InitiateRolePoll final : public ClientPacket
+ {
+ public:
+ InitiateRolePoll(WorldPacket&& packet) : ClientPacket(CMSG_INITIATE_ROLE_POLL, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ };
+
+ class RolePollInform final : public ServerPacket
+ {
+ public:
+ RolePollInform() : ServerPacket(SMSG_ROLE_POLL_INFORM, 17) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ ObjectGuid From;
+ };
+
+ class GroupNewLeader final : public ServerPacket
+ {
+ public:
+ GroupNewLeader() : ServerPacket(SMSG_GROUP_NEW_LEADER, 14) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ std::string Name;
+ };
+
+ struct GroupPlayerInfos
+ {
+ ObjectGuid GUID;
+ std::string Name;
+ uint8 Class = 0;
+
+ uint8 Status = 0u;
+ uint8 Subgroup = 0u;
+ uint8 Flags = 0u;
+ uint8 RolesAssigned = 0u;
+ };
+
+ struct GroupLfgInfos
+ {
+ int32 Slot = 0u;
+ int8 BootCount = 0;
+
+ bool Aborted = false;
+
+ int32 MyRandomSlot = 0;
+ uint8 MyFlags = 0u;
+ uint8 MyPartialClear = 0u;
+ float MyGearDiff = 0.f;
+
+ int8 MyStrangerCount = 0;
+ int8 MyKickVoteCount = 0;
+
+ bool MyFirstReward = false;
+ };
+
+ struct GroupLootSettings
+ {
+ uint8 Method = 0u;
+ ObjectGuid LootMaster;
+ uint8 Threshold = 0u;
+ };
+
+ struct GroupDifficultySettings
+ {
+ uint32 DungeonDifficultyID = 0u;
+ uint32 RaidDifficultyID = 0u;
+ uint32 LegacyRaidDifficultyID = 0u;
+ };
+
+ class PartyUpdate final : public ServerPacket
+ {
+ public:
+ PartyUpdate() : ServerPacket(SMSG_PARTY_UPDATE, 200) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyFlags = 0;
+ int8 PartyIndex = 0;
+ int8 PartyType = 0;
+
+ ObjectGuid PartyGUID;
+ ObjectGuid LeaderGUID;
+
+ int32 MyIndex = 0;
+ int32 SequenceNum = 0;
+
+ std::vector<GroupPlayerInfos> PlayerList;
+
+ Optional<GroupLfgInfos> LfgInfos;
+ Optional<GroupLootSettings> LootSettings;
+ Optional<GroupDifficultySettings> DifficultySettings;
+ };
+
+ class SetEveryoneIsAssistant final : public ClientPacket
+ {
+ public:
+ SetEveryoneIsAssistant(WorldPacket&& packet) : ClientPacket(CMSG_SET_EVERYONE_IS_ASSISTANT, std::move(packet)) { }
+
+ void Read() override;
+
+ int8 PartyIndex = 0;
+ bool EveryoneIsAssistant = false;
+ };
+
+ class ChangeSubGroup final : public ClientPacket
+ {
+ public:
+ ChangeSubGroup(WorldPacket&& packet) : ClientPacket(CMSG_CHANGE_SUB_GROUP, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid TargetGUID;
+ int8 PartyIndex = 0;
+ uint8 NewSubGroup = 0u;
+ };
+
+ class SwapSubGroups final : public ClientPacket
+ {
+ public:
+ SwapSubGroups(WorldPacket&& packet) : ClientPacket(CMSG_SWAP_SUB_GROUPS, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid FirstTarget;
+ ObjectGuid SecondTarget;
+ int8 PartyIndex = 0;
+ };
+
+ class ClearRaidMarker final : public ClientPacket
+ {
+ public:
+ ClearRaidMarker(WorldPacket&& packet) : ClientPacket(CMSG_CLEAR_RAID_MARKER, std::move(packet)) { }
+
+ void Read() override;
+
+ uint8 MarkerId = 0u;
+ };
+
+ class RaidMarkersChanged final : public ServerPacket
+ {
+ public:
+ RaidMarkersChanged() : ServerPacket(SMSG_RAID_MARKERS_CHANGED, 6) { }
+
+ WorldPacket const* Write() override;
+
+ int8 PartyIndex = 0;
+ uint32 ActiveMarkers = 0u;
+
+ std::vector<RaidMarker*> RaidMarkers;
+ };
+ }
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhase const& phase);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPhases const& phases);
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupAura const& aura);
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupAura> const& auraList);
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPetStats const& petStats);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupMemberStats const& memberStats);
+
+ByteBuffer& operator<<(ByteBuffer& data, std::vector<WorldPackets::Party::GroupPlayerInfos> const& playerList);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupPlayerInfos const& playerInfos);
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLfgInfos const& lfgInfos);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupLootSettings const& lootSettings);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Party::GroupDifficultySettings const& difficultySettings);
+
+#endif // PartyPackets_h__
diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp
index 2325c5efac0..f7806a9e588 100644
--- a/src/server/game/Server/Packets/QueryPackets.cpp
+++ b/src/server/game/Server/Packets/QueryPackets.cpp
@@ -176,8 +176,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupDa
data << uint8(lookupData.Level);
data.WriteString(lookupData.Name);
- data.FlushBits();
-
return data;
}
@@ -210,6 +208,8 @@ WorldPacket const* WorldPackets::Query::QueryPageTextResponse::Write()
_worldPacket << Info.ID;
_worldPacket << Info.NextPageID;
_worldPacket.WriteBits(Info.Text.length(), 12);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(Info.Text);
}
@@ -290,6 +290,7 @@ WorldPacket const* WorldPackets::Query::QueryGameObjectResponse::Write()
{
_worldPacket << GameObjectID;
_worldPacket.WriteBit(Allow);
+ _worldPacket.FlushBits();
if (Allow)
{
@@ -464,3 +465,27 @@ WorldPacket const* WorldPackets::Query::QueryPetNameResponse::Write()
return &_worldPacket;
}
+
+void WorldPackets::Query::ItemTextQuery::Read()
+{
+ _worldPacket >> Id;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::ItemTextCache const& itemTextCache)
+{
+ data.WriteBits(itemTextCache.Text.length(), 13);
+ data.FlushBits();
+
+ data.WriteString(itemTextCache.Text);
+
+ return data;
+}
+
+WorldPacket const* WorldPackets::Query::QueryItemTextResponse::Write()
+{
+ _worldPacket.WriteBit(Valid);
+ _worldPacket << Id;
+ _worldPacket << Item;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h
index a5d7e5de8c4..88bf5a887f6 100644
--- a/src/server/game/Server/Packets/QueryPackets.h
+++ b/src/server/game/Server/Packets/QueryPackets.h
@@ -418,6 +418,33 @@ namespace WorldPackets
uint32 Timestamp = 0;
std::string Name;
};
+
+ class ItemTextQuery final : public ClientPacket
+ {
+ public:
+ ItemTextQuery(WorldPacket&& packet) : ClientPacket(CMSG_ITEM_TEXT_QUERY, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Id;
+ };
+
+ struct ItemTextCache
+ {
+ std::string Text;
+ };
+
+ class QueryItemTextResponse final : public ServerPacket
+ {
+ public:
+ QueryItemTextResponse() : ServerPacket(SMSG_QUERY_ITEM_TEXT_RESPONSE) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid Id;
+ bool Valid = false;
+ ItemTextCache Item;
+ };
}
}
diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp
index 5a5320a4e2f..d792783cf9a 100644
--- a/src/server/game/Server/Packets/QuestPackets.cpp
+++ b/src/server/game/Server/Packets/QuestPackets.cpp
@@ -72,7 +72,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
_worldPacket << Info.SuggestedGroupNum;
_worldPacket << Info.RewardNextQuest;
_worldPacket << Info.RewardXPDifficulty;
- _worldPacket << Info.Float10; // Unk
+ _worldPacket << Info.RewardXPMultiplier;
_worldPacket << Info.RewardMoney;
_worldPacket << Info.RewardMoneyDifficulty;
_worldPacket << Info.Float13; // Unk
@@ -149,10 +149,12 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
_worldPacket << questObjective.UnkFloat;
_worldPacket << int32(questObjective.VisualEffects.size());
- for (auto& visualEffect : questObjective.VisualEffects)
+ for (int32 visualEffect : questObjective.VisualEffects)
_worldPacket << visualEffect;
_worldPacket.WriteBits(questObjective.Description.size(), 8);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(questObjective.Description);
}
@@ -165,6 +167,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
_worldPacket.WriteBits(Info.PortraitTurnInText.size(), 10);
_worldPacket.WriteBits(Info.PortraitTurnInName.size(), 8);
_worldPacket.WriteBits(Info.QuestCompletionLog.size(), 11);
+ _worldPacket.FlushBits();
_worldPacket.WriteString(Info.LogTitle);
_worldPacket.WriteString(Info.LogDescription);
@@ -277,6 +280,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverOfferRewardMessage::Write()
_worldPacket.WriteBits(PortraitGiverName.size(), 8);
_worldPacket.WriteBits(PortraitGiverText.size(), 10);
_worldPacket.WriteBits(PortraitTurnInName.size(), 8);
+ _worldPacket.FlushBits();
_worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(RewardText);
@@ -362,6 +366,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverQuestDetails::Write()
_worldPacket.WriteBit(DisplayPopup);
_worldPacket.WriteBit(StartCheat);
_worldPacket.WriteBit(AutoLaunched);
+ _worldPacket.FlushBits();
_worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(DescriptionText);
@@ -406,6 +411,7 @@ WorldPacket const* WorldPackets::Quest::QuestGiverRequestItems::Write()
_worldPacket.WriteBits(QuestTitle.size(), 9);
_worldPacket.WriteBits(CompletionText.size(), 12);
+ _worldPacket.FlushBits();
_worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(CompletionText);
@@ -477,6 +483,8 @@ WorldPacket const* WorldPackets::Quest::QuestConfirmAcceptResponse::Write()
_worldPacket << InitiatedBy;
_worldPacket.WriteBits(QuestTitle.size(), 10);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(QuestTitle);
return &_worldPacket;
diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h
index a83bcc219be..b2d7269ebb0 100644
--- a/src/server/game/Server/Packets/QuestPackets.h
+++ b/src/server/game/Server/Packets/QuestPackets.h
@@ -116,6 +116,7 @@ namespace WorldPackets
int32 SuggestedGroupNum = 0;
int32 RewardNextQuest = 0; // client will request this quest from NPC, if not 0
int32 RewardXPDifficulty = 0; // used for calculating rewarded experience
+ float RewardXPMultiplier = 1.0f;
int32 RewardMoney = 0; // reward money (below max lvl)
int32 RewardMoneyDifficulty = 0; // used in XP calculation at client
int32 RewardBonusMoney = 0;
@@ -163,8 +164,6 @@ namespace WorldPackets
int32 RewardCurrencyID[QUEST_REWARD_CURRENCY_COUNT] = {};
int32 RewardCurrencyQty[QUEST_REWARD_CURRENCY_COUNT] = {};
- // Non JAM data
- float Float10 = 1.0f;
float Float13 = 1.0f;
int32 AllowableRaces = -1;
};
diff --git a/src/server/game/Server/Packets/ReferAFriendPackets.cpp b/src/server/game/Server/Packets/ReferAFriendPackets.cpp
index 0f3211936f6..8bc017223f8 100644
--- a/src/server/game/Server/Packets/ReferAFriendPackets.cpp
+++ b/src/server/game/Server/Packets/ReferAFriendPackets.cpp
@@ -30,6 +30,7 @@ void WorldPackets::RaF::GrantLevel::Read()
WorldPacket const* WorldPackets::RaF::ProposeLevelGrant::Write()
{
_worldPacket << Sender;
+
return &_worldPacket;
}
@@ -39,6 +40,8 @@ WorldPacket const* WorldPackets::RaF::ReferAFriendFailure::Write()
// Client uses this string only if Reason == ERR_REFER_A_FRIEND_NOT_IN_GROUP || Reason == ERR_REFER_A_FRIEND_SUMMON_OFFLINE_S
// but always reads it from packet
_worldPacket.WriteBits(Str.length(), 6);
+ _worldPacket.FlushBits();
_worldPacket.WriteString(Str);
+
return &_worldPacket;
}
diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp
index 365dc742e85..b03994aebab 100644
--- a/src/server/game/Server/Packets/SystemPackets.cpp
+++ b/src/server/game/Server/Packets/SystemPackets.cpp
@@ -121,6 +121,8 @@ WorldPacket const* WorldPackets::System::SetTimeZoneInformation::Write()
{
_worldPacket.WriteBits(ServerTimeTZ.length(), 7);
_worldPacket.WriteBits(GameTimeTZ.length(), 7);
+ _worldPacket.FlushBits();
+
_worldPacket.WriteString(ServerTimeTZ);
_worldPacket.WriteString(GameTimeTZ);
diff --git a/src/server/game/Server/Packets/TicketPackets.cpp b/src/server/game/Server/Packets/TicketPackets.cpp
index 80a6dad3bd2..cdbeea53e32 100644
--- a/src/server/game/Server/Packets/TicketPackets.cpp
+++ b/src/server/game/Server/Packets/TicketPackets.cpp
@@ -70,6 +70,7 @@ WorldPacket const* WorldPackets::Ticket::GMTicketGetTicketResponse::Write()
{
_worldPacket << Result;
_worldPacket.WriteBit(Info.is_initialized());
+ _worldPacket.FlushBits();
if (Info)
{
@@ -84,12 +85,12 @@ WorldPacket const* WorldPackets::Ticket::GMTicketGetTicketResponse::Write()
_worldPacket.WriteBits(Info->TicketDescription.size(), 11);
_worldPacket.WriteBits(Info->WaitTimeOverrideMessage.size(), 10);
+ _worldPacket.FlushBits();
_worldPacket.WriteString(Info->TicketDescription);
_worldPacket.WriteString(Info->WaitTimeOverrideMessage);
}
- _worldPacket.FlushBits();
return &_worldPacket;
}
diff --git a/src/server/game/Server/Packets/WhoPackets.cpp b/src/server/game/Server/Packets/WhoPackets.cpp
index 99ce0805e8b..632aeba0e12 100644
--- a/src/server/game/Server/Packets/WhoPackets.cpp
+++ b/src/server/game/Server/Packets/WhoPackets.cpp
@@ -25,9 +25,10 @@ void WorldPackets::Who::WhoIsRequest::Read()
WorldPacket const* WorldPackets::Who::WhoIsResponse::Write()
{
_worldPacket.WriteBits(AccountName.length(), 11);
- _worldPacket.WriteString(AccountName);
_worldPacket.FlushBits();
+ _worldPacket.WriteString(AccountName);
+
return &_worldPacket;
}
@@ -102,10 +103,10 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Who::WhoEntry const& entr
data.WriteBits(entry.GuildName.length(), 7);
data.WriteBit(entry.IsGM);
- data.WriteString(entry.GuildName);
-
data.FlushBits();
+ data.WriteString(entry.GuildName);
+
return data;
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 2886b079c93..45071d14cd4 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -23,16 +23,19 @@
#include "Packets/BankPackets.h"
#include "Packets/BattlegroundPackets.h"
#include "Packets/BlackMarketPackets.h"
-#include "Packets/CharacterPackets.h"
#include "Packets/ChannelPackets.h"
+#include "Packets/CharacterPackets.h"
#include "Packets/ChatPackets.h"
#include "Packets/ClientConfigPackets.h"
#include "Packets/CombatPackets.h"
#include "Packets/DuelPackets.h"
#include "Packets/EquipmentSetPackets.h"
#include "Packets/GameObjectPackets.h"
+#include "Packets/GarrisonPackets.h"
#include "Packets/GuildPackets.h"
+#include "Packets/PartyPackets.h"
#include "Packets/InspectPackets.h"
+#include "Packets/InstancePackets.h"
#include "Packets/ItemPackets.h"
#include "Packets/LootPackets.h"
#include "Packets/MailPackets.h"
@@ -47,9 +50,9 @@
#include "Packets/ScenePackets.h"
#include "Packets/SocialPackets.h"
#include "Packets/TalentPackets.h"
+#include "Packets/TicketPackets.h"
#include "Packets/TokenPackets.h"
#include "Packets/TradePackets.h"
-#include "Packets/TicketPackets.h"
#include "Packets/VehiclePackets.h"
#include "Packets/VoidStoragePackets.h"
#include "Packets/WhoPackets.h"
@@ -249,7 +252,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_CANCEL_MOD_SPEED_NO_CONTROL_AURAS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CANCEL_MOUNT_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::CancelMountAura, &WorldSession::HandleCancelMountAuraOpcode);
DEFINE_HANDLER(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode);
+ DEFINE_HANDLER(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::CancelTempEnchantment, &WorldSession::HandleCancelTempEnchantmentOpcode);
DEFINE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, WorldPackets::Trade::CancelTrade, &WorldSession::HandleCancelTradeOpcode);
DEFINE_HANDLER(CMSG_CAN_DUEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Duel::CanDuel, &WorldSession::HandleCanDuel);
DEFINE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Spells::CastSpell, &WorldSession::HandleCastSpellOpcode);
@@ -257,7 +260,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_CHALLENGE_MODE_REQUEST_MAP_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHANGE_BAG_SLOT_FLAG, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHANGE_MONUMENT_APPEARANCE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGE_SUB_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupChangeSubGroupOpcode );
+ DEFINE_HANDLER(CMSG_CHANGE_SUB_GROUP, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::ChangeSubGroup, &WorldSession::HandleChangeSubGroupOpcode);
DEFINE_HANDLER(CMSG_CHARACTER_RENAME_REQUEST, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharacterRenameRequest, &WorldSession::HandleCharRenameOpcode);
DEFINE_HANDLER(CMSG_CHAR_CUSTOMIZE, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharCustomize, &WorldSession::HandleCharCustomizeOpcode);
DEFINE_HANDLER(CMSG_CHAR_DELETE, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CharDelete, &WorldSession::HandleCharDeleteOpcode);
@@ -306,14 +309,14 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_CHAT_MESSAGE_SAY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatMessage, &WorldSession::HandleChatMessageOpcode);
DEFINE_HANDLER(CMSG_CHAT_MESSAGE_WHISPER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatMessageWhisper, &WorldSession::HandleChatMessageWhisperOpcode);
DEFINE_HANDLER(CMSG_CHAT_MESSAGE_YELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatMessage, &WorldSession::HandleChatMessageOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_REGISTER_ADDON_PREFIXES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonRegisteredPrefixesOpcode);
+ DEFINE_HANDLER(CMSG_CHAT_REGISTER_ADDON_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatRegisterAddonPrefixes, &WorldSession::HandleAddonRegisteredPrefixesOpcode);
DEFINE_HANDLER(CMSG_CHAT_REPORT_FILTERED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_REPORT_IGNORED, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChatIgnoredOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUnregisterAddonPrefixesOpcode);
+ DEFINE_HANDLER(CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::ChatUnregisterAllAddonPrefixes, &WorldSession::HandleUnregisterAllAddonPrefixesOpcode);
DEFINE_HANDLER(CMSG_CHECK_RAF_EMAIL_ENABLED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHECK_WOW_TOKEN_VETERAN_ELIGIBILITY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_CHOICE_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_CLEAR_RAID_MARKER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_CLEAR_RAID_MARKER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::ClearRaidMarker, &WorldSession::HandleClearRaidMarker);
DEFINE_HANDLER(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::ClearTradeItem, &WorldSession::HandleClearTradeItemOpcode);
DEFINE_HANDLER(CMSG_CLIENT_PORT_GRAVEYARD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::PortGraveyard, &WorldSession::HandlePortGraveyard);
DEFINE_HANDLER(CMSG_CLOSE_INTERACTION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -329,7 +332,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_COMPLETE_MOVIE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_CONFIRM_RESPEC_WIPE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleConfirmRespecWipeOpcode );
DEFINE_HANDLER(CMSG_CONNECT_TO_FAILED, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_CONVERT_RAID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupRaidConvertOpcode );
+ DEFINE_HANDLER(CMSG_CONVERT_RAID, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::ConvertRaid, &WorldSession::HandleConvertRaidOpcode);
DEFINE_HANDLER(CMSG_CREATE_CHARACTER, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::CreateCharacter, &WorldSession::HandleCharCreateOpcode);
DEFINE_HANDLER(CMSG_CREATE_SHIPMENT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_DB_QUERY_BULK, STATUS_AUTHED, PROCESS_INPLACE, WorldPackets::Query::DBQueryBulk, &WorldSession::HandleDBQueryBulk);
@@ -355,7 +358,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_DISCARDED_TIME_SYNC_ACKS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_DISMISS_CRITTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissCritter );
DEFINE_HANDLER(CMSG_DO_MASTER_LOOT_ROLL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_DO_READY_CHECK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckOpcode );
+ DEFINE_HANDLER(CMSG_DO_READY_CHECK, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::DoReadyCheck, &WorldSession::HandleDoReadyCheckOpcode);
DEFINE_HANDLER(CMSG_DUEL_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Duel::DuelResponse, &WorldSession::HandleDuelResponseOpcode);
DEFINE_HANDLER(CMSG_EJECT_PASSENGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::EjectPassenger, &WorldSession::HandleEjectPassenger);
DEFINE_HANDLER(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::EmoteClient, &WorldSession::HandleEmoteOpcode);
@@ -364,21 +367,21 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_ENGINE_SURVEY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_ENUM_CHARACTERS, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::EnumCharacters, &WorldSession::HandleCharEnumOpcode);
DEFINE_HANDLER(CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::EnumCharacters, &WorldSession::HandleCharUndeleteEnumOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_FAR_SIGHT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleFarSightOpcode );
+ DEFINE_HANDLER(CMSG_FAR_SIGHT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::FarSight, &WorldSession::HandleFarSightOpcode);
DEFINE_HANDLER(CMSG_GAME_OBJ_REPORT_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::GameObject::GameObjReportUse, &WorldSession::HandleGameobjectReportUse);
DEFINE_HANDLER(CMSG_GAME_OBJ_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::GameObject::GameObjUse, &WorldSession::HandleGameObjectUseOpcode);
DEFINE_HANDLER(CMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_GARRISON_CANCEL_CONSTRUCTION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_GARRISON_CANCEL_CONSTRUCTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonCancelConstruction, &WorldSession::HandleGarrisonCancelConstruction);
DEFINE_HANDLER(CMSG_GARRISON_CHECK_UPGRADEABLE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_COMPLETE_MISSION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_GENERATE_RECRUITS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_GARRISON_GET_BUILDING_LANDMARKS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_GARRISON_GET_BUILDING_LANDMARKS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonGetBuildingLandmarks, &WorldSession::HandleGarrisonGetBuildingLandmarks);
DEFINE_HANDLER(CMSG_GARRISON_MISSION_BONUS_ROLL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_GARRISON_PURCHASE_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_GARRISON_PURCHASE_BUILDING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonPurchaseBuilding, &WorldSession::HandleGarrisonPurchaseBuilding);
DEFINE_HANDLER(CMSG_GARRISON_RECRUIT_FOLLOWER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_REMOVE_FOLLOWER, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData, &WorldSession::HandleGarrisonRequestBlueprintAndSpecializationData);
DEFINE_HANDLER(CMSG_GARRISON_REQUEST_LANDING_PAGE_SHIPMENT_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_REQUEST_SHIPMENT_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_SET_BUILDING_ACTIVE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -389,7 +392,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_GARRISON_SWAP_BUILDINGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GENERATE_RANDOM_CHARACTER_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::GenerateRandomCharacterName, &WorldSession::HandleRandomizeCharNameOpcode);
DEFINE_HANDLER(CMSG_GET_CHALLENGE_MODE_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_GET_GARRISON_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_GET_GARRISON_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GetGarrisonInfo, &WorldSession::HandleGetGarrisonInfo);
DEFINE_HANDLER(CMSG_GET_ITEM_PURCHASE_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::GetItemPurchaseData, &WorldSession::HandleGetItemPurchaseData);
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_MIRROR_IMAGE_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest );
DEFINE_HANDLER(CMSG_GET_PVP_OPTIONS_ENABLED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Battleground::GetPVPOptionsEnabled, &WorldSession::HandleGetPVPOptionsEnabled);
@@ -456,20 +459,20 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_HEARTH_AND_RESURRECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Battleground::HearthAndResurrect, &WorldSession::HandleHearthAndResurrect);
DEFINE_HANDLER(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::IgnoreTrade, &WorldSession::HandleIgnoreTradeOpcode);
DEFINE_HANDLER(CMSG_INCREASE_CAST_TIME_FOR_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_INITIATE_ROLE_POLL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRolePollBeginOpcode);
+ DEFINE_HANDLER(CMSG_INITIATE_ROLE_POLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::InitiateRolePoll, &WorldSession::HandleInitiateRolePoll);
DEFINE_HANDLER(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::InitiateTrade, &WorldSession::HandleInitiateTradeOpcode);
DEFINE_HANDLER(CMSG_INSPECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::Inspect, &WorldSession::HandleInspectOpcode);
DEFINE_HANDLER(CMSG_INSPECT_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::InspectPVPRequest, &WorldSession::HandleInspectPVP);
DEFINE_OPCODE_HANDLER_OLD(CMSG_INSTANCE_LOCK_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleInstanceLockResponse);
DEFINE_OPCODE_HANDLER_OLD(CMSG_ITEM_PURCHASE_REFUND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleItemRefund );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_ITEM_TEXT_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleItemTextQuery );
+ DEFINE_HANDLER(CMSG_ITEM_TEXT_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::ItemTextQuery, &WorldSession::HandleItemTextQuery);
DEFINE_HANDLER(CMSG_JOIN_PET_BATTLE_QUEUE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_JOIN_RATED_BATTLEGROUND, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_KEEP_ALIVE, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess);
DEFINE_HANDLER(CMSG_KEYBOUND_OVERRIDE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LEARN_PET_SPECIALIZATION_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LEARN_TALENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Talent::LearnTalents, &WorldSession::HandleLearnTalentsOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_LEAVE_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupDisbandOpcode );
+ DEFINE_HANDLER(CMSG_LEAVE_GROUP, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::LeaveGroup, &WorldSession::HandleLeaveGroupOpcode);
DEFINE_HANDLER(CMSG_LEAVE_PET_BATTLE_QUEUE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LFG_LIST_APPLY_TO_GROUP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_LFG_LIST_CANCEL_APPLICATION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -512,7 +515,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_MAIL_TAKE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeItem, &WorldSession::HandleMailTakeItem);
DEFINE_HANDLER(CMSG_MAIL_TAKE_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeMoney, &WorldSession::HandleMailTakeMoney);
DEFINE_OPCODE_HANDLER_OLD(CMSG_MASTER_LOOT_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_MINIMAP_PING, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode );
+ DEFINE_HANDLER(CMSG_MINIMAP_PING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::MinimapPingClient, &WorldSession::HandleMinimapPingOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition );
DEFINE_HANDLER(CMSG_MOUNT_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_MOUNT_SPECIAL_ANIM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode );
@@ -588,10 +591,10 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_OPEN_MISSION_NPC, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_OPEN_SHIPMENT_NPC, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_OPT_OUT_OF_LOOT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleOptOutOfLootOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_PARTY_INVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_PARTY_INVITE_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteResponseOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_PARTY_UNINVITE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupUninviteOpcode );
+ DEFINE_HANDLER(CMSG_OPT_OUT_OF_LOOT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::OptOutOfLoot, &WorldSession::HandleOptOutOfLootOpcode);
+ DEFINE_HANDLER(CMSG_PARTY_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::PartyInviteClient, &WorldSession::HandlePartyInviteOpcode);
+ DEFINE_HANDLER(CMSG_PARTY_INVITE_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::PartyInviteResponse, &WorldSession::HandlePartyInviteResponseOpcode);
+ DEFINE_HANDLER(CMSG_PARTY_UNINVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::PartyUninvite, &WorldSession::HandlePartyUninviteOpcode);
DEFINE_HANDLER(CMSG_PETITION_BUY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::PetitionBuy, &WorldSession::HandlePetitionBuy);
DEFINE_HANDLER(CMSG_PETITION_RENAME_GUILD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::PetitionRenameGuild, &WorldSession::HandlePetitionRenameGuild);
DEFINE_HANDLER(CMSG_PETITION_SHOW_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::PetitionShowList, &WorldSession::HandlePetitionShowList);
@@ -653,7 +656,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_PUSH_RESULT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPushResult );
DEFINE_HANDLER(CMSG_QUEUED_MESSAGES_END, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_RANDOM_ROLL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::RandomRollClient, &WorldSession::HandleRandomRollOpcode);
- DEFINE_HANDLER(CMSG_READY_CHECK_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_READY_CHECK_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::ReadyCheckResponseClient, &WorldSession::HandleReadyCheckResponseOpcode);
DEFINE_HANDLER(CMSG_READ_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::ReadItem, &WorldSession::HandleReadItem);
DEFINE_HANDLER(CMSG_RECLAIM_CORPSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::ReclaimCorpse, &WorldSession::HandleReclaimCorpse);
DEFINE_HANDLER(CMSG_RECRUIT_A_FRIEND, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -674,12 +677,12 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_REQUEST_GUILD_REWARDS_LIST, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Guild::RequestGuildRewardsList, &WorldSession::HandleRequestGuildRewardsList);
DEFINE_HANDLER(CMSG_REQUEST_HONOR_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::RequestHonorStats, &WorldSession::HandleRequestHonorStatsOpcode);
DEFINE_HANDLER(CMSG_REQUEST_LFG_LIST_BLACKLIST, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PARTY_JOIN_UPDATES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRequestJoinUpdates);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode);
+ DEFINE_HANDLER(CMSG_REQUEST_PARTY_JOIN_UPDATES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::RequestPartyJoinUpdates, &WorldSession::HandleRequestPartyJoinUpdates);
+ DEFINE_HANDLER(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::RequestPartyMemberStats, &WorldSession::HandleRequestPartyMemberStatsOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PET_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode );
DEFINE_HANDLER(CMSG_REQUEST_PLAYED_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::RequestPlayedTime, &WorldSession::HandlePlayedTime);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_PVP_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleRequestPvpReward );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_RAID_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRaidInfoOpcode );
+ DEFINE_HANDLER(CMSG_REQUEST_RAID_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::RequestRaidInfo, &WorldSession::HandleRequestRaidInfoOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_RATED_BATTLEFIELD_INFO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestRatedBattlefieldInfo);
DEFINE_HANDLER(CMSG_REQUEST_RESEARCH_HISTORY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REQUEST_STABLED_PETS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode );
@@ -689,11 +692,11 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_REQUEST_VEHICLE_SWITCH_SEAT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RequestVehicleSwitchSeat, &WorldSession::HandleRequestVehicleSwitchSeat);
DEFINE_HANDLER(CMSG_REQUEST_WOW_TOKEN_MARKET_PRICE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Token::RequestWowTokenMarketPrice, &WorldSession::HandleRequestWowTokenMarketPrice);
DEFINE_HANDLER(CMSG_RESET_CHALLENGE_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_RESET_INSTANCES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleResetInstancesOpcode );
+ DEFINE_HANDLER(CMSG_RESET_INSTANCES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Instance::ResetInstances, &WorldSession::HandleResetInstancesOpcode);
DEFINE_HANDLER(CMSG_RESURRECT_RESPONSE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::ResurrectResponse, &WorldSession::HandleResurrectResponse);
DEFINE_HANDLER(CMSG_REVERT_MONUMENT_APPEARANCE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_RIDE_VEHICLE_INTERACT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::RideVehicleInteract, &WorldSession::HandleRideVehicleInteract);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SAVE_CUF_PROFILES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleSaveCUFProfiles );
+ DEFINE_HANDLER(CMSG_SAVE_CUF_PROFILES, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::SaveCUFProfiles, &WorldSession::HandleSaveCUFProfiles);
DEFINE_HANDLER(CMSG_SAVE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::SaveEquipmentSet, &WorldSession::HandleEquipmentSetSave);
DEFINE_HANDLER(CMSG_SAVE_GUILD_EMBLEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::SaveGuildEmblem, &WorldSession::HandleSaveGuildEmblem);
DEFINE_HANDLER(CMSG_SCENE_PLAYBACK_CANCELED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Scenes::ScenePlaybackCanceled, &WorldSession::HandleScenePlaybackCanceled);
@@ -714,7 +717,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Movement::SetActiveMover, &WorldSession::HandleSetActiveMoverOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ACTIVE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel );
DEFINE_HANDLER(CMSG_SET_ADVANCED_COMBAT_LOGGING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ASSISTANT_LEADER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupAssistantLeaderOpcode);
+ DEFINE_HANDLER(CMSG_SET_ASSISTANT_LEADER, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetAssistantLeader, &WorldSession::HandleSetAssistantLeaderOpcode);
DEFINE_HANDLER(CMSG_SET_BACKPACK_AUTOSORT_DISABLED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_BANK_AUTOSORT_DISABLED, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_BANK_BAG_SLOT_FLAG, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -722,22 +725,22 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SET_CURRENCY_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_DIFFICULTY_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetDungeonDifficulty, &WorldSession::HandleSetDungeonDifficultyOpcode);
- DEFINE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetEveryoneIsAssistant, &WorldSession::HandleSetEveryoneIsAssistant);
DEFINE_HANDLER(CMSG_SET_FACTION_AT_WAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionAtWar, &WorldSession::HandleSetFactionAtWar);
DEFINE_HANDLER(CMSG_SET_FACTION_INACTIVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionInactive, &WorldSession::HandleSetFactionInactiveOpcode);
DEFINE_HANDLER(CMSG_SET_FACTION_NOT_AT_WAR, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetFactionNotAtWar, &WorldSession::HandleSetFactionNotAtWar);
DEFINE_HANDLER(CMSG_SET_INSERT_ITEMS_LEFT_TO_RIGHT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_LFG_BONUS_FACTION_ID, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_LOOT_METHOD, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMethodOpcode );
+ DEFINE_HANDLER(CMSG_SET_LOOT_METHOD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::SetLootMethod, &WorldSession::HandleSetLootMethodOpcode);
DEFINE_HANDLER(CMSG_SET_LOOT_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PARTY_ASSIGNMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PARTY_LEADER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSetLeaderOpcode );
+ DEFINE_HANDLER(CMSG_SET_PARTY_LEADER, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetPartyLeader, &WorldSession::HandleSetPartyLeaderOpcode);
DEFINE_HANDLER(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames );
DEFINE_HANDLER(CMSG_SET_PREFERRED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_PVP, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SET_RAID_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetRaidDifficulty, &WorldSession::HandleSetRaidDifficultyOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ROLE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSetRolesOpcode );
+ DEFINE_HANDLER(CMSG_SET_ROLE, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetRole, &WorldSession::HandleSetRoleOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend );
DEFINE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetSelection, &WorldSession::HandleSetSelectionOpcode);
DEFINE_HANDLER(CMSG_SET_SHEATHED, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Combat::SetSheathed, &WorldSession::HandleSetSheathedOpcode);
@@ -773,7 +776,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_SWAP_INV_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SwapInvItem, &WorldSession::HandleSwapInvItemOpcode);
DEFINE_HANDLER(CMSG_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SwapItem, &WorldSession::HandleSwapItem);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SWAP_SUB_GROUPS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGroupSwapSubGroupOpcode );
+ DEFINE_HANDLER(CMSG_SWAP_SUB_GROUPS, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SwapSubGroups, &WorldSession::HandleSwapSubGroupsOpcode);
DEFINE_HANDLER(CMSG_SWAP_VOID_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::VoidStorage::SwapVoidItem, &WorldSession::HandleVoidSwapItem);
DEFINE_HANDLER(CMSG_TABARD_VENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleTabardVendorActivateOpcode);
DEFINE_HANDLER(CMSG_TALK_TO_GOSSIP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleGossipHelloOpcode);
@@ -789,7 +792,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_TOGGLE_PVP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTogglePvP );
DEFINE_OPCODE_HANDLER_OLD(CMSG_TOTEM_DESTROYED, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTotemDestroyed );
DEFINE_HANDLER(CMSG_TOY_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_TRAINER_BUY_SPELL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTrainerBuySpellOpcode );
+ DEFINE_HANDLER(CMSG_TRAINER_BUY_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::TrainerBuySpell, &WorldSession::HandleTrainerBuySpellOpcode);
DEFINE_HANDLER(CMSG_TRAINER_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleTrainerListOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_TRANSMOGRIFY_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems );
DEFINE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Petition::TurnInPetition, &WorldSession::HandleTurnInPetition);
@@ -807,7 +810,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::ClientConfig::UserClientUpdateAccountData, &WorldSession::HandleUpdateAccountData);
DEFINE_HANDLER(CMSG_UPDATE_CLIENT_SETTINGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_OPCODE_HANDLER_OLD(CMSG_UPDATE_MISSILE_TRAJECTORY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_UPDATE_RAID_TARGET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode );
+ DEFINE_HANDLER(CMSG_UPDATE_RAID_TARGET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::UpdateRaidTarget, &WorldSession::HandleUpdateRaidTargetOpcode);
DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Token::UpdateListedAuctionableTokens, &WorldSession::HandleUpdateListedAuctionableTokens);
DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_COUNT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_UPGRADE_GARRISON, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -988,7 +991,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHALLENGE_MODE_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANGE_PLAYER_DIFFICULTY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY_JOINED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY_LEFT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -998,8 +1001,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_COMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_SPELL_TIER_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_UPGRADE_STARTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_FACTION_CHANGE_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_AUTO_RESPONDED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1011,7 +1014,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_PLAYER_NOTFOUND, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_RECONNECT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_RESTRICTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_SERVER_MESSAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAT_SERVER_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHEAT_IGNORE_DIMISHING_RETURNS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHECK_WARGAME_ENTRY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHUNKED_PACKET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1058,7 +1061,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DIFFERENT_INSTANCE_FROM_PARTY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISENCHANT_CREDIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISMOUNT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPEL_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DISPLAY_GAME_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1081,7 +1084,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENCOUNTER_END, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENCOUNTER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENUM_CHARACTERS_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENVIRONMENTAL_DAMAGE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENVIRONMENTAL_DAMAGE_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_ID, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EXPECTED_SPAM_RECORDS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EXPLORATION_EXPERIENCE, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1107,51 +1110,51 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_SPEED_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_TIME_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_ACTIVATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_LANDMARKS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_REMOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_COMPLETE_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_CREATE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_DELETE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL2, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_XP, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_IS_UPGRADEABLE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LANDINGPAGE_SHIPMENTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_BLUEPRINT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_FOLLOWERS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_MISSIONS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_NUM_FOLLOWER_ACTIVATIONS_REMAINING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_ARCHITECT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_MISSION_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLACE_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_USED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUIT_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOTE_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_START_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UPGRADE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_FOLLOWER_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_ACTIVATED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_LANDMARKS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_COMPLETE_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_CREATE_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_DELETE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_ITEM_LEVEL2, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_FOLLOWER_CHANGED_XP, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_IS_UPGRADEABLE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LANDINGPAGE_SHIPMENTS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_BLUEPRINT_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LEARN_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_FOLLOWERS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_LIST_MISSIONS_CHEAT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_NUM_FOLLOWER_ACTIVATIONS_REMAINING, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_ARCHITECT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_MISSION_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLACE_BUILDING_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_USED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUIT_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOTE_INFO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_FROM_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REMOVE_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_REQUEST_BLUEPRINT_AND_SPECIALIZATION_DATA_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_START_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UNLEARN_BLUEPRINT_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_UPGRADE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GENERATE_RANDOM_CHARACTER_NAME_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_ACCOUNT_CHARACTER_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_DISPLAYED_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_GARRISON_INFO_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENTS_OF_TYPE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENT_INFO_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_DISPLAYED_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_GARRISON_INFO_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENTS_OF_TYPE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_SHIPMENT_INFO_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GET_TROPHY_LIST_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_REQUEST_PLAYER_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GM_TICKET_CASE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1167,10 +1170,10 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GOSSIP_MESSAGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GOSSIP_POI, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_ACTION_THROTTLED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DECLINE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DESTROYED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_NEW_LEADER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_UNINVITE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DECLINE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_DESTROYED, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_NEW_LEADER, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GROUP_UNINVITE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_DELETED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_EARNED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_ACHIEVEMENT_MEMBERS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1246,21 +1249,21 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_ENCOUNTER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_ENCOUNTER_TIMER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_GROUP_SIZE_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_SAVE_CREATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVALIDATE_PLAYER, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVALID_PROMOTION_CODE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVENTORY_CHANGE_FAILURE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_IS_QUEST_COMPLETE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_COOLDOWN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_ENCHANT_TIME_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_EXPIRE_PURCHASE_REFUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PURCHASE_REFUND_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PUSH_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_TALENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1296,7 +1299,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_ACCOUNT_RESTORE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_CHARACTER_COPY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LIVE_REGION_GET_ACCOUNT_CHARACTER_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_EQUIPMENT_SET, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_SELECTED_TROPHY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGIN_SET_TIME_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -1325,7 +1328,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAP_OBJ_EVENTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MASTER_LOOT_CANDIDATE_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MESSAGE_BOX, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_MINIMAP_PING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MINIMAP_PING, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_COMPONENTED_DATA, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_CREATURE_DATA, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MISSILE_CANCEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1420,7 +1423,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MONEY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_RECEIVED_MAIL, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ON_MONSTER_MOVE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_OPEN_CONTAINER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1429,14 +1432,14 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_OPEN_SHIPMENT_NPC_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_OVERRIDE_LIGHT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PAGE_TEXT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_INVITE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_COMMAND_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_INVITE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_KILL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_MEMBER_STATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PARTY_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PAUSE_MIRROR_TIMER, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PENDING_RAID_LOCK, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETITION_ALREADY_SIGNED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETITION_ALREADY_SIGNED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETITION_RENAME_GUILD_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETITION_SHOW_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PETITION_SHOW_SIGNATURES, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1495,7 +1498,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PRINT_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PROC_RESIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PROPOSE_LEVEL_GRANT, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_LOG_DATA, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_SEASON, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1504,7 +1507,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_GAME_OBJECT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_GARRISON_CREATURE_NAME_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_GUILD_INFO_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_ITEM_TEXT_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_ITEM_TEXT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_NPC_TEXT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PAGE_TEXT_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_PETITION_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1537,12 +1540,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_DIFFICULTY_SET, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_GROUP_ONLY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_INSTANCE_MESSAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RANDOM_ROLL, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RATED_BATTLEFIELD_INFO, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_COMPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_STARTED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_COMPLETED, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_READY_CHECK_STARTED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_RESULT_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_RESULT_OK, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_QUERY_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1561,7 +1564,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_WOW_TOKEN_MARKET_PRICE_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESEARCH_COMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_COMPRESSION_CONTEXT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_RANGED_COMBAT_TIMER, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_WEEKLY_CURRENCY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPEC_WIPE_CONFIRM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1571,9 +1574,9 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RUNE_REGEN_DEBUG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_BOOT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_COMPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1592,8 +1595,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SELL_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ITEM_PASSIVES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_KNOWN_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_ALL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_ALL, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_SPELL_CHARGES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_SPELL_HISTORY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_UNLEARN_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -1625,7 +1628,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_SPELL_CHARGES, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_SPELL_CHARGES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_TASK_COMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_TIME_ZONE_INFORMATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_VEHICLE_REC_ID, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -1643,19 +1646,19 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DAMAGE_SHIELD, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DISPELL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_ENERGIZE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_ENERGIZE_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_EXECUTE_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_HEAL_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INSTAKILL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INTERRUPT_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INSTAKILL_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INTERRUPT_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_MISS_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_MULTISTRIKE_EFFECT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_NON_MELEE_DAMAGE_LOG, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_OR_DAMAGE_IMMUNE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PERIODIC_AURA_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PERIODIC_AURA_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1691,8 +1694,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TOTEM_MOVED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_STATUS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_UPDATED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_PENDING, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1709,17 +1712,17 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_CHARACTER_FLAGS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_EXPANSION_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_TALENT_DATA, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_TASK_PROGRESS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WEEKLY_SPELL_USAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_USE_EQUIPMENT_SET_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_VENDOR_INVENTORY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_VIGNETTE_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index db4ec66ea00..650e100f514 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -322,6 +322,10 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (IsConnectionIdle())
m_Socket[CONNECTION_TYPE_REALM]->CloseSocket();
+ if (updater.ProcessUnsafe())
+ while (_player && _player->IsBeingTeleportedSeamlessly())
+ HandleMoveWorldportAckOpcode();
+
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
WorldPacket* packet = NULL;
@@ -453,7 +457,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
//check if we are safe to proceed with logout
//logout procedure should happen only in World::UpdateSessions() method!!!
- if (updater.ProcessLogout())
+ if (updater.ProcessUnsafe())
{
time_t currTime = time(NULL);
///- If necessary, log the player out
@@ -909,31 +913,23 @@ bool WorldSession::IsAddonRegistered(const std::string& prefix) const
return itr != _registeredAddonPrefixes.end();
}
-void WorldSession::HandleUnregisterAddonPrefixesOpcode(WorldPacket& /*recvPacket*/) // empty packet
+void WorldSession::HandleUnregisterAllAddonPrefixesOpcode(WorldPackets::Chat::ChatUnregisterAllAddonPrefixes& /*packet*/) // empty packet
{
_registeredAddonPrefixes.clear();
}
-void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket)
+void WorldSession::HandleAddonRegisteredPrefixesOpcode(WorldPackets::Chat::ChatRegisterAddonPrefixes& packet)
{
- // This is always sent after CMSG_UNREGISTER_ALL_ADDON_PREFIXES
+ // This is always sent after CMSG_CHAT_UNREGISTER_ALL_ADDON_PREFIXES
- uint32 count = recvPacket.ReadBits(25);
-
- if (count > REGISTERED_ADDON_PREFIX_SOFTCAP)
+ if (packet.Prefixes.size() > REGISTERED_ADDON_PREFIX_SOFTCAP)
{
// if we have hit the softcap (64) nothing should be filtered
_filterAddonMessages = false;
- recvPacket.rfinish();
return;
}
- std::vector<uint8> lengths(count);
- for (uint32 i = 0; i < count; ++i)
- lengths[i] = recvPacket.ReadBits(5);
-
- for (uint32 i = 0; i < count; ++i)
- _registeredAddonPrefixes.push_back(recvPacket.ReadString(lengths[i]));
+ _registeredAddonPrefixes.insert(_registeredAddonPrefixes.end(), packet.Prefixes.begin(), packet.Prefixes.end());
if (_registeredAddonPrefixes.size() > REGISTERED_ADDON_PREFIX_SOFTCAP) // shouldn't happen
{
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 631f87aeb11..d0242b86440 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -186,6 +186,8 @@ namespace WorldPackets
class ChatMessageEmote;
class CTextEmote;
class EmoteClient;
+ class ChatRegisterAddonPrefixes;
+ class ChatUnregisterAllAddonPrefixes;
}
namespace Combat
@@ -214,6 +216,15 @@ namespace WorldPackets
class GameObjUse;
}
+ namespace Garrison
+ {
+ class GetGarrisonInfo;
+ class GarrisonPurchaseBuilding;
+ class GarrisonCancelConstruction;
+ class GarrisonRequestBlueprintAndSpecializationData;
+ class GarrisonGetBuildingLandmarks;
+ }
+
namespace Guild
{
class QueryGuildInfo;
@@ -266,6 +277,12 @@ namespace WorldPackets
class RequestHonorStats;
}
+ namespace Instance
+ {
+ class InstanceInfo;
+ class ResetInstances;
+ }
+
namespace Item
{
class AutoEquipItem;
@@ -282,6 +299,7 @@ namespace WorldPackets
class SwapInvItem;
class SwapItem;
class WrapItem;
+ class CancelTempEnchantment;
}
namespace Loot
@@ -327,6 +345,9 @@ namespace WorldPackets
class ObjectUpdateRescued;
class CompleteCinematic;
class NextCinematicCamera;
+ class FarSight;
+ class LoadCUFProfiles;
+ class SaveCUFProfiles;
}
namespace Movement
@@ -346,6 +367,48 @@ namespace WorldPackets
class Hello;
class GossipSelectOption;
class SpiritHealerActivate;
+ class TrainerBuySpell;
+ }
+
+ namespace Party
+ {
+ class PartyCommandResult;
+ class PartyInviteClient;
+ class PartyInvite;
+ class PartyInviteResponse;
+ class PartyUninvite;
+ class GroupDecline;
+ class RequestPartyMemberStats;
+ class PartyMemberStats;
+ class SetPartyLeader;
+ class SetRole;
+ class RoleChangedInform;
+ class SetLootMethod;
+ class LeaveGroup;
+ class MinimapPingClient;
+ class MinimapPing;
+ class UpdateRaidTarget;
+ class SendRaidTargetUpdateSingle;
+ class SendRaidTargetUpdateAll;
+ class ConvertRaid;
+ class RequestPartyJoinUpdates;
+ class SetAssistantLeader;
+ class DoReadyCheck;
+ class ReadyCheckStarted;
+ class ReadyCheckResponseClient;
+ class ReadyCheckResponse;
+ class ReadyCheckCompleted;
+ class RequestRaidInfo;
+ class OptOutOfLoot;
+ class InitiateRolePoll;
+ class RolePollInform;
+ class GroupNewLeader;
+ class PartyUpdate;
+ class SetEveryoneIsAssistant;
+ class ChangeSubGroup;
+ class SwapSubGroups;
+ class RaidMarkersChanged;
+ class ClearRaidMarker;
}
namespace Petition
@@ -375,6 +438,7 @@ namespace WorldPackets
class QueryPetName;
class QuestPOIQuery;
class QueryQuestCompletionNPCs;
+ class ItemTextQuery;
}
namespace Quest
@@ -635,8 +699,8 @@ public:
explicit PacketFilter(WorldSession* pSession) : m_pSession(pSession) { }
virtual ~PacketFilter() { }
- virtual bool Process(WorldPacket* /*packet*/) { return true; }
- virtual bool ProcessLogout() const { return true; }
+ virtual bool Process(WorldPacket* /*packet*/) = 0;
+ virtual bool ProcessUnsafe() const { return false; }
protected:
WorldSession* const m_pSession;
@@ -653,9 +717,7 @@ public:
explicit MapSessionFilter(WorldSession* pSession) : PacketFilter(pSession) { }
~MapSessionFilter() { }
- virtual bool Process(WorldPacket* packet) override;
- //in Map::Update() we do not process player logout!
- virtual bool ProcessLogout() const override { return false; }
+ bool Process(WorldPacket* packet) override;
};
//class used to filer only thread-unsafe packets from queue
@@ -666,7 +728,8 @@ public:
explicit WorldSessionFilter(WorldSession* pSession) : PacketFilter(pSession) { }
~WorldSessionFilter() { }
- virtual bool Process(WorldPacket* packet) override;
+ bool Process(WorldPacket* packet) override;
+ bool ProcessUnsafe() const override { return true; }
};
struct PacketCounter
@@ -843,8 +906,6 @@ class WorldSession
void SendNotInArenaTeamPacket(uint8 type);
void SendPetitionShowList(ObjectGuid guid);
- void BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data);
-
void DoLootRelease(ObjectGuid lguid);
// Account mute time
@@ -1039,28 +1100,31 @@ class WorldSession
void HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped& moveTimeSkipped);
void HandleMovementAckMessage(WorldPackets::Movement::MovementAckMessage& movementAck);
- void HandleRequestRaidInfoOpcode(WorldPacket& recvData);
+ void HandleRequestRaidInfoOpcode(WorldPackets::Party::RequestRaidInfo& packet);
- void HandleGroupInviteOpcode(WorldPacket& recvPacket);
+ void HandlePartyInviteOpcode(WorldPackets::Party::PartyInviteClient& packet);
//void HandleGroupCancelOpcode(WorldPacket& recvPacket);
- void HandleGroupInviteResponseOpcode(WorldPacket& recvPacket);
- void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
- void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket);
- void HandleGroupSetRolesOpcode(WorldPacket& recvData);
- void HandleGroupDisbandOpcode(WorldPacket& recvPacket);
- void HandleOptOutOfLootOpcode(WorldPacket& recvData);
- void HandleLootMethodOpcode(WorldPacket& recvPacket);
+ void HandlePartyInviteResponseOpcode(WorldPackets::Party::PartyInviteResponse& packet);
+ void HandlePartyUninviteOpcode(WorldPackets::Party::PartyUninvite& packet);
+ void HandleSetPartyLeaderOpcode(WorldPackets::Party::SetPartyLeader& packet);
+ void HandleSetRoleOpcode(WorldPackets::Party::SetRole& packet);
+ void HandleLeaveGroupOpcode(WorldPackets::Party::LeaveGroup& packet);
+ void HandleOptOutOfLootOpcode(WorldPackets::Party::OptOutOfLoot& packet);
+ void HandleSetLootMethodOpcode(WorldPackets::Party::SetLootMethod& packet);
void HandleLootRoll(WorldPackets::Loot::LootRoll& packet);
- void HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData);
- void HandleRaidTargetUpdateOpcode(WorldPacket& recvData);
- void HandleRaidReadyCheckOpcode(WorldPacket& recvData);
- void HandleGroupRaidConvertOpcode(WorldPacket& recvData);
- void HandleGroupRequestJoinUpdates(WorldPacket& recvData);
- void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData);
- void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData);
- void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData);
+ void HandleRequestPartyMemberStatsOpcode(WorldPackets::Party::RequestPartyMemberStats& packet);
+ void HandleUpdateRaidTargetOpcode(WorldPackets::Party::UpdateRaidTarget& packet);
+ void HandleDoReadyCheckOpcode(WorldPackets::Party::DoReadyCheck& packet);
+ void HandleReadyCheckResponseOpcode(WorldPackets::Party::ReadyCheckResponseClient& packet);
+ void HandleConvertRaidOpcode(WorldPackets::Party::ConvertRaid& packet);
+ void HandleRequestPartyJoinUpdates(WorldPackets::Party::RequestPartyJoinUpdates& packet);
+ void HandleChangeSubGroupOpcode(WorldPackets::Party::ChangeSubGroup& packet);
+ void HandleSwapSubGroupsOpcode(WorldPackets::Party::SwapSubGroups& packet);
+ void HandleSetAssistantLeaderOpcode(WorldPackets::Party::SetAssistantLeader& packet);
void HandlePartyAssignmentOpcode(WorldPacket& recvData);
- void HandleRolePollBeginOpcode(WorldPacket& recvData);
+ void HandleInitiateRolePoll(WorldPackets::Party::InitiateRolePoll& packet);
+ void HandleSetEveryoneIsAssistant(WorldPackets::Party::SetEveryoneIsAssistant& packet);
+ void HandleClearRaidMarker(WorldPackets::Party::ClearRaidMarker& packet);
void HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet);
void HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet);
@@ -1119,7 +1183,7 @@ class WorldSession
void HandleTabardVendorActivateOpcode(WorldPackets::NPC::Hello& packet);
void HandleBankerActivateOpcode(WorldPackets::NPC::Hello& packet);
void HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet);
- void HandleTrainerBuySpellOpcode(WorldPacket& recvPacket);
+ void HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet);
void HandlePetitionShowList(WorldPackets::Petition::PetitionShowList& packet);
void HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet);
void HandleGossipSelectOptionOpcode(WorldPackets::NPC::GossipSelectOption& packet);
@@ -1135,7 +1199,7 @@ class WorldSession
void HandleStableRevivePet(WorldPacket& recvPacket);
void HandleStableSwapPet(WorldPacket& recvPacket);
void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId);
- void SendTrainerBuyFailed(ObjectGuid guid, uint32 spellId, uint32 reason);
+ void SendTrainerBuyFailed(ObjectGuid trainerGUID, uint32 spellID, int32 trainerFailedReason);
void HandleCanDuel(WorldPackets::Duel::CanDuel& packet);
void HandleDuelResponseOpcode(WorldPackets::Duel::DuelResponse& duelResponse);
@@ -1179,7 +1243,7 @@ class WorldSession
void HandleMailMarkAsRead(WorldPackets::Mail::MailMarkAsRead& packet);
void HandleMailReturnToSender(WorldPackets::Mail::MailReturnToSender& packet);
void HandleMailDelete(WorldPackets::Mail::MailDelete& packet);
- void HandleItemTextQuery(WorldPacket& recvData);
+ void HandleItemTextQuery(WorldPackets::Query::ItemTextQuery& itemTextQuery);
void HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextItem& packet);
void HandleQueryNextMailTime(WorldPackets::Mail::MailQueryNextMailTime& packet);
void HandleCancelChanneling(WorldPacket& recvData);
@@ -1190,7 +1254,6 @@ class WorldSession
void HandleDestroyItemOpcode(WorldPackets::Item::DestroyItem& destroyItem);
void HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem& autoEquipItem);
void HandleSellItemOpcode(WorldPackets::Item::SellItem& packet);
- void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket);
void HandleBuyItemOpcode(WorldPackets::Item::BuyItem& packet);
void HandleListInventoryOpcode(WorldPackets::NPC::Hello& packet);
void HandleAutoStoreBagItemOpcode(WorldPackets::Item::AutoStoreBagItem& packet);
@@ -1252,8 +1315,8 @@ class WorldSession
void HandleTextEmoteOpcode(WorldPackets::Chat::CTextEmote& packet);
void HandleChatIgnoredOpcode(WorldPacket& recvPacket);
- void HandleUnregisterAddonPrefixesOpcode(WorldPacket& recvPacket);
- void HandleAddonRegisteredPrefixesOpcode(WorldPacket& recvPacket);
+ void HandleUnregisterAllAddonPrefixesOpcode(WorldPackets::Chat::ChatUnregisterAllAddonPrefixes& packet);
+ void HandleAddonRegisteredPrefixesOpcode(WorldPackets::Chat::ChatRegisterAddonPrefixes& packet);
void HandleReclaimCorpse(WorldPackets::Misc::ReclaimCorpse& packet);
void HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient& packet);
@@ -1326,9 +1389,9 @@ class WorldSession
void HandleWardenDataOpcode(WorldPacket& recvData);
void HandleWorldTeleportOpcode(WorldPacket& recvData);
- void HandleMinimapPingOpcode(WorldPacket& recvData);
+ void HandleMinimapPingOpcode(WorldPackets::Party::MinimapPingClient& packet);
void HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient& packet);
- void HandleFarSightOpcode(WorldPacket& recvData);
+ void HandleFarSightOpcode(WorldPackets::Misc::FarSight& packet);
void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty);
void HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDifficulty& setRaidDifficulty);
void HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData);
@@ -1336,7 +1399,7 @@ class WorldSession
void HandleRealmSplitOpcode(WorldPacket& recvData);
void HandleTimeSyncResponse(WorldPackets::Misc::TimeSyncResponse& packet);
void HandleWhoIsOpcode(WorldPackets::Who::WhoIsRequest& packet);
- void HandleResetInstancesOpcode(WorldPacket& recvData);
+ void HandleResetInstancesOpcode(WorldPackets::Instance::ResetInstances& packet);
void HandleInstanceLockResponse(WorldPacket& recvPacket);
// Looking for Dungeon/Raid
@@ -1374,7 +1437,7 @@ class WorldSession
// Socket gem
void HandleSocketOpcode(WorldPacket& recvData);
- void HandleCancelTempEnchantmentOpcode(WorldPacket& recvData);
+ void HandleCancelTempEnchantmentOpcode(WorldPackets::Item::CancelTempEnchantment& cancelTempEnchantment);
void HandleGetItemPurchaseData(WorldPackets::Item::GetItemPurchaseData& packet);
void HandleItemRefund(WorldPacket& recvData);
@@ -1459,9 +1522,16 @@ class WorldSession
void HandleRequestWowTokenMarketPrice(WorldPackets::Token::RequestWowTokenMarketPrice& requestWowTokenMarketPrice);
// Compact Unit Frames (4.x)
- void HandleSaveCUFProfiles(WorldPacket& recvPacket);
+ void HandleSaveCUFProfiles(WorldPackets::Misc::SaveCUFProfiles& packet);
void SendLoadCUFProfiles();
+ // Garrison
+ void HandleGetGarrisonInfo(WorldPackets::Garrison::GetGarrisonInfo& getGarrisonInfo);
+ void HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::GarrisonPurchaseBuilding& garrisonPurchaseBuilding);
+ void HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction);
+ void HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& garrisonRequestBlueprintAndSpecializationData);
+ void HandleGarrisonGetBuildingLandmarks(WorldPackets::Garrison::GarrisonGetBuildingLandmarks& garrisonGetBuildingLandmarks);
+
private:
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index e4b98f1c54b..bc1306d73e1 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -44,8 +44,8 @@ struct CompressedWorldPacket
using boost::asio::ip::tcp;
std::string const WorldSocket::ServerConnectionInitialize("WORLD OF WARCRAFT CONNECTION - SERVER TO CLIENT");
-
std::string const WorldSocket::ClientConnectionInitialize("WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER");
+uint32 const WorldSocket::MinSizeForCompression = 0x400;
uint32 const SizeOfClientHeader[2][2] =
{
@@ -54,7 +54,6 @@ uint32 const SizeOfClientHeader[2][2] =
};
uint32 const SizeOfServerHeader[2] = { sizeof(uint16) + sizeof(uint32), sizeof(uint32) };
-
WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)),
_type(CONNECTION_TYPE_REALM), _authSeed(rand32()), _OverSpeedPings(0),
_worldSession(nullptr), _authed(false), _compressionStream(nullptr), _initialized(false)
@@ -375,7 +374,7 @@ void WorldSocket::SendPacket(WorldPacket const& packet)
uint32 packetSize = packet.size();
uint32 sizeOfHeader = SizeOfServerHeader[_authCrypt.IsInitialized()];
- if (packetSize > 0x400)
+ if (packetSize > MinSizeForCompression && _authCrypt.IsInitialized())
packetSize = compressBound(packetSize) + sizeof(CompressedWorldPacket);
std::unique_lock<std::mutex> guard(_writeLock);
@@ -403,7 +402,7 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer&
uint8* headerPos = buffer.GetWritePointer();
buffer.WriteCompleted(sizeOfHeader);
- if (packetSize > 0x400)
+ if (packetSize > MinSizeForCompression && _authCrypt.IsInitialized())
{
CompressedWorldPacket cmp;
cmp.UncompressedSize = packetSize + 4;
@@ -451,7 +450,7 @@ uint32 WorldSocket::CompressPacket(uint8* buffer, WorldPacket const& packet)
_compressionStream->next_in = (Bytef*)&opcode;
_compressionStream->avail_in = sizeof(uint32);
- int32 z_res = deflate(_compressionStream, Z_BLOCK);
+ int32 z_res = deflate(_compressionStream, Z_NO_FLUSH);
if (z_res != Z_OK)
{
TC_LOG_ERROR("network", "Can't compress packet opcode (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index e42a310f470..b82029f88d5 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -69,8 +69,8 @@ union ClientPktHeader
class WorldSocket : public Socket<WorldSocket>
{
static std::string const ServerConnectionInitialize;
-
static std::string const ClientConnectionInitialize;
+ static uint32 const MinSizeForCompression;
public:
WorldSocket(tcp::socket&& socket);
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index 7e60ac9b5da..497b416ded1 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -461,7 +461,7 @@ enum AuraType
SPELL_AURA_401 = 401,
SPELL_AURA_402 = 402,
SPELL_AURA_403 = 403,
- SPELL_AURA_404 = 404,
+ SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT = 404,
SPELL_AURA_405 = 405,
SPELL_AURA_406 = 406,
SPELL_AURA_MOD_FEAR_2 = 407, // NYI
@@ -476,7 +476,7 @@ enum AuraType
SPELL_AURA_416 = 416,
SPELL_AURA_417 = 417,
SPELL_AURA_418 = 418,
- SPELL_AURA_419 = 419,
+ SPELL_AURA_MOD_BASE_MANA_PCT = 419,
SPELL_AURA_MOD_BATTLE_PET_XP_PCT = 420, // NYI
SPELL_AURA_421 = 421,
SPELL_AURA_422 = 422,
@@ -523,8 +523,8 @@ enum AuraType
SPELL_AURA_CONVER_CRIT_RATING_PCT_TO_PARRY_RATING = 463, // NYI
SPELL_AURA_464 = 464,
SPELL_AURA_465 = 465,
- SPELL_AURA_466 = 466,
- SPELL_AURA_467 = 467,
+ SPELL_AURA_MOD_BONUS_ARMOR_PCT = 466, // Affects bonus armor gain from all sources except base stats
+ SPELL_AURA_MOD_STAT_BONUS_PCT = 467, // Affects stat gain from all sources except base stats
SPELL_AURA_468 = 468,
SPELL_AURA_469 = 469,
SPELL_AURA_471 = 471,
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index a3b0c4788e7..b5f154e6fe1 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -426,7 +426,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //363 SPELL_AURA_MOD_NEXT_SPELL
&AuraEffect::HandleUnused, //364 unused (4.3.4)
&AuraEffect::HandleNULL, //365 SPELL_AURA_MAX_FAR_CLIP_PLANE
- &AuraEffect::HandleNULL, //366 SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT
+ &AuraEffect::HandleOverrideSpellPowerByAttackPower, //366 SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT
&AuraEffect::HandleNULL, //367 SPELL_AURA_367
&AuraEffect::HandleUnused, //368 unused (4.3.4)
&AuraEffect::HandleNULL, //369 SPELL_AURA_ENABLE_POWER_BAR_TIMER
@@ -464,7 +464,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //401
&AuraEffect::HandleNULL, //402
&AuraEffect::HandleNULL, //403
- &AuraEffect::HandleNULL, //404
+ &AuraEffect::HandleOverrideAttackPowerBySpellPower, //404 SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT
&AuraEffect::HandleNULL, //405
&AuraEffect::HandleNULL, //406
&AuraEffect::HandleNULL, //407 SPELL_AURA_MOD_FEAR_2
@@ -479,7 +479,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //416
&AuraEffect::HandleNULL, //417
&AuraEffect::HandleNULL, //418
- &AuraEffect::HandleNULL, //419
+ &AuraEffect::HandleAuraModIncreaseBaseManaPercent, //419 SPELL_AURA_MOD_BASE_MANA_PCT
&AuraEffect::HandleNULL, //420 SPELL_AURA_MOD_BATTLE_PET_XP_PCT
&AuraEffect::HandleNULL, //421
&AuraEffect::HandleNULL, //422
@@ -526,8 +526,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //463 SPELL_AURA_CRIT_RATING_AFFECTS_PARRY used by Riposte
&AuraEffect::HandleNULL, //464
&AuraEffect::HandleNULL, //465
- &AuraEffect::HandleNULL, //466
- &AuraEffect::HandleNULL, //467
+ &AuraEffect::HandleNULL, //466 SPELL_AURA_MOD_BONUS_ARMOR_PCT
+ &AuraEffect::HandleModStatBonusPercent, //467 SPELL_AURA_MOD_STAT_BONUS_PCT
&AuraEffect::HandleNULL, //468
&AuraEffect::HandleNULL, //469
&AuraEffect::HandleNULL, //470
@@ -3982,6 +3982,59 @@ void AuraEffect::HandleAuraModExpertise(AuraApplication const* aurApp, uint8 mod
target->ToPlayer()->UpdateExpertise(OFF_ATTACK);
}
+void AuraEffect::HandleModStatBonusPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ Unit* target = aurApp->GetTarget();
+
+ if (GetMiscValue() < -1 || GetMiscValue() > 4)
+ {
+ TC_LOG_ERROR("spells", "WARNING: Misc Value for SPELL_AURA_MOD_STAT_BONUS_PCT not valid");
+ return;
+ }
+
+ // only players have base stats
+ if (target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ {
+ if (GetMiscValue() == i || GetMiscValue() == -1)
+ {
+ target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT_EXCLUDE_CREATE, float(m_amount), apply);
+ target->ApplyStatPercentBuffMod(Stats(i), float(m_amount), apply);
+ }
+ }
+}
+
+void AuraEffect::HandleOverrideSpellPowerByAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
+
+ target->ApplyModSignedFloatValue(PLAYER_FIELD_OVERRIDE_SPELL_POWER_BY_AP_PCT, float(m_amount), apply);
+ target->UpdateSpellDamageAndHealingBonus();
+}
+
+void AuraEffect::HandleOverrideAttackPowerBySpellPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ Player* target = aurApp->GetTarget()->ToPlayer();
+ if (!target)
+ return;
+
+ target->ApplyModSignedFloatValue(PLAYER_FIELD_OVERRIDE_AP_BY_SPELL_POWER_PERCENT, float(m_amount), apply);
+ target->UpdateAttackPowerAndDamage();
+}
+
/********************************/
/*** HEAL & ENERGIZE ***/
/********************************/
@@ -4141,6 +4194,14 @@ void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurA
target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply);
}
+void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
+{
+ if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
+ return;
+
+ aurApp->GetTarget()->HandleStatModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()), apply);
+}
+
/********************************/
/*** FIGHT ***/
/********************************/
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index e8431e202ba..91cf75dbe87 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -234,6 +234,9 @@ class AuraEffect
void HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModResistenceOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModExpertise(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleModStatBonusPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleOverrideSpellPowerByAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleOverrideAttackPowerBySpellPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// heal and energize
void HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModPowerRegenPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -244,6 +247,7 @@ class AuraEffect
void HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModIncreaseHealthPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
+ void HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// fight
void HandleAuraModParryPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModDodgePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index e8da248160b..cb0f34c162b 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -857,12 +857,14 @@ void Spell::SelectSpellTargets()
// Do not check for selfcast
if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID())
{
- m_UniqueTargetInfo.erase(ihit++);
- continue;
+ ihit = m_UniqueTargetInfo.erase(ihit);
+ continue;
}
}
+
++ihit;
}
+
if (checkLvl && m_UniqueTargetInfo.empty())
{
SendCastResult(SPELL_FAILED_LOWLEVEL);
@@ -2298,7 +2300,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
target->processed = true; // Target checked in apply effects procedure
// Get mask of effects for target
- uint8 mask = target->effectMask;
+ uint32 mask = target->effectMask;
Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID);
if (!unit && target->targetGUID.IsPlayer()) // only players may be targeted across maps
@@ -2326,6 +2328,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
return;
}
+ if (!unit)
+ return;
+
if (unit->IsAlive() != target->alive)
return;
@@ -2850,8 +2855,8 @@ bool Spell::UpdateChanneledTargetList()
if (m_channelTargetEffectMask == 0)
return true;
- uint8 channelTargetEffectMask = m_channelTargetEffectMask;
- uint8 channelAuraMask = 0;
+ uint32 channelTargetEffectMask = m_channelTargetEffectMask;
+ uint32 channelAuraMask = 0;
for (SpellEffectInfo const* effect : GetEffects())
if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA)
channelAuraMask |= 1 << effect->EffectIndex;
@@ -2866,7 +2871,7 @@ bool Spell::UpdateChanneledTargetList()
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
}
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
if (ihit->missCondition == SPELL_MISS_NONE && (channelTargetEffectMask & ihit->effectMask))
{
@@ -3359,10 +3364,10 @@ void Spell::handle_immediate()
// process immediate effects (items, ground, etc.) also initialize some variables
_handle_immediate_phase();
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
- for (std::vector<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
+ for (std::vector<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
FinishTargetProcessing();
@@ -3402,7 +3407,7 @@ uint64 Spell::handle_delayed(uint64 t_offset)
bool single_missile = (m_targets.HasDst());
// now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases)
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
if (ihit->processed == false)
{
@@ -3417,7 +3422,7 @@ uint64 Spell::handle_delayed(uint64 t_offset)
}
// now recheck gameobject targeting correctness
- for (std::vector<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
+ for (std::vector<GOTargetInfo>::iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
{
if (ighit->processed == false)
{
@@ -3475,7 +3480,7 @@ void Spell::_handle_immediate_phase()
}
// process items
- for (std::vector<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
+ for (std::vector<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
if (!m_originalCaster)
@@ -4145,47 +4150,13 @@ void Spell::ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 nu
void Spell::ExecuteLogEffectInterruptCast(uint8 /*effIndex*/, Unit* victim, uint32 spellId)
{
- ObjectGuid casterGuid = m_caster->GetGUID();
- ObjectGuid targetGuid = victim->GetGUID();
-
- WorldPacket data(SMSG_SPELL_INTERRUPT_LOG, 8 + 8 + 4 + 4);
- data.WriteBit(targetGuid[4]);
- data.WriteBit(casterGuid[5]);
- data.WriteBit(casterGuid[6]);
- data.WriteBit(casterGuid[1]);
- data.WriteBit(casterGuid[3]);
- data.WriteBit(casterGuid[0]);
- data.WriteBit(targetGuid[3]);
- data.WriteBit(targetGuid[5]);
- data.WriteBit(targetGuid[1]);
- data.WriteBit(casterGuid[4]);
- data.WriteBit(casterGuid[7]);
- data.WriteBit(targetGuid[7]);
- data.WriteBit(targetGuid[6]);
- data.WriteBit(targetGuid[2]);
- data.WriteBit(casterGuid[2]);
- data.WriteBit(targetGuid[0]);
-
- data.WriteByteSeq(casterGuid[7]);
- data.WriteByteSeq(casterGuid[6]);
- data.WriteByteSeq(casterGuid[3]);
- data.WriteByteSeq(casterGuid[2]);
- data.WriteByteSeq(targetGuid[3]);
- data.WriteByteSeq(targetGuid[6]);
- data.WriteByteSeq(targetGuid[2]);
- data.WriteByteSeq(targetGuid[4]);
- data.WriteByteSeq(targetGuid[7]);
- data.WriteByteSeq(targetGuid[0]);
- data.WriteByteSeq(casterGuid[4]);
- data << uint32(m_spellInfo->Id);
- data.WriteByteSeq(targetGuid[1]);
- data.WriteByteSeq(casterGuid[0]);
- data.WriteByteSeq(casterGuid[5]);
- data.WriteByteSeq(casterGuid[1]);
- data << uint32(spellId);
- data.WriteByteSeq(targetGuid[5]);
+ WorldPackets::CombatLog::SpellInterruptLog data;
+ data.Caster = m_caster->GetGUID();
+ data.Victim = victim->GetGUID();
+ data.InterruptedSpellID = m_spellInfo->Id;
+ data.SpellID = spellId;
- m_caster->SendMessageToSet(&data, true);
+ m_caster->SendMessageToSet(data.Write(), true);
}
void Spell::ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* victim, int32 itemId, int32 amount)
@@ -4313,7 +4284,7 @@ void Spell::SendResurrectRequest(Player* target)
// for player resurrections the name is looked up by guid
std::string const sentName(m_caster->GetTypeId() == TYPEID_PLAYER
? "" : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex()));
-
+
WorldPackets::Spells::ResurrectRequest resurrectRequest;
resurrectRequest.ResurrectOffererGUID = m_caster->GetGUID();
resurrectRequest.ResurrectOffererVirtualRealmAddress = GetVirtualRealmAddress();
@@ -4585,7 +4556,7 @@ void Spell::TakeReagents()
ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : NULL;
// do not take reagents for these item casts
- if (castItemTemplate && castItemTemplate->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST)
+ if (castItemTemplate && castItemTemplate->GetFlags() & ITEM_FLAG_TRIGGERED_CAST)
return;
Player* p_caster = m_caster->ToPlayer();
@@ -5815,7 +5786,7 @@ bool Spell::CanAutoCast(Unit* target)
{
SelectSpellTargets();
//check if among target units, our WANTED target is as well (->only self cast spells return false)
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->targetGUID == targetguid)
return true;
}
@@ -6016,7 +5987,7 @@ SpellCastResult Spell::CheckItems()
}
// do not take reagents for these item casts
- if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST))
+ if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_TRIGGERED_CAST))
{
bool checkReagents = !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST) && !player->CanNoReagentCast(m_spellInfo);
// Not own traded item (in trader trade slot) requires reagents even if triggered spell
@@ -6143,7 +6114,7 @@ SpellCastResult Spell::CheckItems()
if (m_targets.GetItemTarget()->GetOwner() != m_caster)
return SPELL_FAILED_NOT_TRADEABLE;
// do not allow to enchant vellum from scroll made by vellum-prevent exploit
- if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST)
+ if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_TRIGGERED_CAST)
return SPELL_FAILED_TOTEM_CATEGORY;
ItemPosCountVec dest;
InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1);
@@ -6266,7 +6237,7 @@ SpellCastResult Spell::CheckItems()
if (!m_targets.GetItemTarget())
return SPELL_FAILED_CANT_BE_PROSPECTED;
//ensure item is a prospectable ore
- if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_PROSPECTABLE))
+ if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_FLAG_PROSPECTABLE))
return SPELL_FAILED_CANT_BE_PROSPECTED;
//prevent prospecting in trade slot
if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
@@ -6289,7 +6260,7 @@ SpellCastResult Spell::CheckItems()
if (!m_targets.GetItemTarget())
return SPELL_FAILED_CANT_BE_MILLED;
//ensure item is a millable herb
- if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_MILLABLE))
+ if (!(m_targets.GetItemTarget()->GetTemplate()->GetFlags() & ITEM_FLAG_MILLABLE))
return SPELL_FAILED_CANT_BE_MILLED;
//prevent milling in trade slot
if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
@@ -6832,7 +6803,7 @@ void Spell::HandleLaunchPhase()
if (effect && (m_applyMultiplierMask & (1 << effect->EffectIndex)))
multiplier[effect->EffectIndex] = effect->CalcDamageMultiplier(m_originalCaster, this);
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
{
TargetInfo& target = *ihit;
@@ -7502,7 +7473,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
}
else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE))
{
- if (!_caster->HasInLine(target, _caster->GetObjectSize()))
+ if (!_caster->HasInLine(target, _caster->GetObjectSize() + target->GetObjectSize()))
return false;
}
else
@@ -7519,7 +7490,7 @@ WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Po
bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target)
{
// return all targets on missile trajectory (0 - size of a missile)
- if (!_caster->HasInLine(target, 0))
+ if (!_caster->HasInLine(target, target->GetObjectSize()))
return false;
return WorldObjectSpellAreaTargetCheck::operator ()(target);
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index ddf6cb055ae..ec716a0e03d 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -338,6 +338,7 @@ class Spell
void EffectApplyGlyph(SpellEffIndex effIndex);
void EffectEnchantHeldItem(SpellEffIndex effIndex);
void EffectSummonObject(SpellEffIndex effIndex);
+ void EffectChangeRaidMarker(SpellEffIndex effIndex);
void EffectResurrect(SpellEffIndex effIndex);
void EffectParry(SpellEffIndex effIndex);
void EffectBlock(SpellEffIndex effIndex);
@@ -405,6 +406,9 @@ class Spell
void EffectCreateAreaTrigger(SpellEffIndex effIndex);
void EffectRemoveTalent(SpellEffIndex effIndex);
void EffectDestroyItem(SpellEffIndex effIndex);
+ void EffectLearnGarrisonBuilding(SpellEffIndex effIndex);
+ void EffectCreateGarrison(SpellEffIndex effIndex);
+ void EffectAddGarrisonFollower(SpellEffIndex effIndex);
typedef std::set<Aura*> UsedSpellMods;
@@ -669,7 +673,7 @@ class Spell
uint64 timeDelay;
SpellMissInfo missCondition:8;
SpellMissInfo reflectResult:8;
- uint32 effectMask:32;
+ uint32 effectMask;
bool processed:1;
bool alive:1;
bool crit:1;
@@ -683,8 +687,8 @@ class Spell
{
ObjectGuid targetGUID;
uint64 timeDelay;
- uint32 effectMask:32;
- bool processed:1;
+ uint32 effectMask;
+ bool processed;
};
std::vector<GOTargetInfo> m_UniqueGOTargetInfo;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 372ff5faba8..36e544de3bd 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -67,6 +67,8 @@
#include "GuildMgr.h"
#include "ReputationMgr.h"
#include "AreaTrigger.h"
+#include "Garrison.h"
+#include "CombatLogPackets.h"
#include "DuelPackets.h"
#include "MiscPackets.h"
#include "SpellPackets.h"
@@ -179,7 +181,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectReputation, //103 SPELL_EFFECT_REPUTATION
&Spell::EffectSummonObject, //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
&Spell::EffectSummonObject, //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
- &Spell::EffectSummonObject, //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
+ &Spell::EffectChangeRaidMarker, //106 SPELL_EFFECT_CHANGE_RAID_MARKER
&Spell::EffectSummonObject, //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
&Spell::EffectDispelMechanic, //108 SPELL_EFFECT_DISPEL_MECHANIC
&Spell::EffectResurrectPet, //109 SPELL_EFFECT_RESURRECT_PET
@@ -240,7 +242,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectRemoveAura, //164 SPELL_EFFECT_REMOVE_AURA
&Spell::EffectDamageFromMaxHealthPCT, //165 SPELL_EFFECT_DAMAGE_FROM_MAX_HEALTH_PCT
&Spell::EffectGiveCurrency, //166 SPELL_EFFECT_GIVE_CURRENCY
- &Spell::EffectNULL, //167 SPELL_EFFECT_167
+ &Spell::EffectNULL, //167 SPELL_EFFECT_UPDATE_PLAYER_PHASE
&Spell::EffectNULL, //168 SPELL_EFFECT_ALLOW_CONTROL_PET
&Spell::EffectDestroyItem, //169 SPELL_EFFECT_DESTROY_ITEM
&Spell::EffectNULL, //170 SPELL_EFFECT_UPDATE_ZONE_AURAS_AND_PHASES
@@ -265,8 +267,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //189 SPELL_EFFECT_LOOT
&Spell::EffectNULL, //190 SPELL_EFFECT_190
&Spell::EffectNULL, //191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
- &Spell::EffectNULL, //192 SPELL_EFFECT_192
- &Spell::EffectNULL, //193 SPELL_EFFECT_193
+ &Spell::EffectNULL, //192 SPELL_EFFECT_UNCAGE_BATTLEPET
+ &Spell::EffectNULL, //193 SPELL_EFFECT_START_PET_BATTLE
&Spell::EffectNULL, //194 SPELL_EFFECT_194
&Spell::EffectNULL, //195 SPELL_EFFECT_195
&Spell::EffectNULL, //196 SPELL_EFFECT_196
@@ -277,53 +279,53 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //201 SPELL_EFFECT_ENABLE_BATTLE_PETS
&Spell::EffectNULL, //202 SPELL_EFFECT_202
&Spell::EffectNULL, //203 SPELL_EFFECT_203
- &Spell::EffectNULL, //204 SPELL_EFFECT_204
- &Spell::EffectNULL, //205 SPELL_EFFECT_205
+ &Spell::EffectNULL, //204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY
+ &Spell::EffectNULL, //205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE
&Spell::EffectNULL, //206 SPELL_EFFECT_206
- &Spell::EffectNULL, //207 SPELL_EFFECT_207
+ &Spell::EffectNULL, //207 SPELL_EFFECT_LAUNCH_QUEST_TASK
&Spell::EffectNULL, //208 SPELL_EFFECT_208
&Spell::EffectNULL, //209 SPELL_EFFECT_209
- &Spell::EffectNULL, //210 SPELL_EFFECT_210
- &Spell::EffectNULL, //211 SPELL_EFFECT_211
+ &Spell::EffectLearnGarrisonBuilding, //210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
+ &Spell::EffectNULL, //211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION
&Spell::EffectNULL, //212 SPELL_EFFECT_212
&Spell::EffectNULL, //213 SPELL_EFFECT_213
- &Spell::EffectNULL, //214 SPELL_EFFECT_214
- &Spell::EffectNULL, //215 SPELL_EFFECT_215
- &Spell::EffectNULL, //216 SPELL_EFFECT_216
- &Spell::EffectNULL, //217 SPELL_EFFECT_217
+ &Spell::EffectCreateGarrison, //214 SPELL_EFFECT_CREATE_GARRISON
+ &Spell::EffectNULL, //215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS
+ &Spell::EffectNULL, //216 SPELL_EFFECT_CREATE_SHIPMENT
+ &Spell::EffectNULL, //217 SPELL_EFFECT_UPGRADE_GARRISON
&Spell::EffectNULL, //218 SPELL_EFFECT_218
&Spell::EffectNULL, //219 SPELL_EFFECT_219
- &Spell::EffectNULL, //220 SPELL_EFFECT_220
+ &Spell::EffectAddGarrisonFollower, //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
&Spell::EffectNULL, //221 SPELL_EFFECT_221
- &Spell::EffectNULL, //222 SPELL_EFFECT_222
- &Spell::EffectNULL, //223 SPELL_EFFECT_223
- &Spell::EffectNULL, //224 SPELL_EFFECT_224
- &Spell::EffectNULL, //225 SPELL_EFFECT_225
+ &Spell::EffectNULL, //222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
+ &Spell::EffectNULL, //223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
+ &Spell::EffectNULL, //224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
+ &Spell::EffectNULL, //225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL
&Spell::EffectNULL, //226 SPELL_EFFECT_226
&Spell::EffectNULL, //227 SPELL_EFFECT_227
&Spell::EffectNULL, //228 SPELL_EFFECT_228
- &Spell::EffectNULL, //229 SPELL_EFFECT_229
- &Spell::EffectNULL, //230 SPELL_EFFECT_230
- &Spell::EffectNULL, //231 SPELL_EFFECT_231
- &Spell::EffectNULL, //232 SPELL_EFFECT_232
- &Spell::EffectNULL, //233 SPELL_EFFECT_233
+ &Spell::EffectNULL, //229 SPELL_EFFECT_SET_FOLLOWER_QUALITY
+ &Spell::EffectNULL, //230 SPELL_EFFECT_INCREASE_FOLLOWER_ITEM_LEVEL
+ &Spell::EffectNULL, //231 SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE
+ &Spell::EffectNULL, //232 SPELL_EFFECT_REMOVE_PHASE
+ &Spell::EffectNULL, //233 SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES
&Spell::EffectNULL, //234 SPELL_EFFECT_234
&Spell::EffectNULL, //235 SPELL_EFFECT_235
- &Spell::EffectNULL, //236 SPELL_EFFECT_236
- &Spell::EffectNULL, //237 SPELL_EFFECT_237
- &Spell::EffectNULL, //238 SPELL_EFFECT_238
- &Spell::EffectNULL, //239 SPELL_EFFECT_239
+ &Spell::EffectNULL, //236 SPELL_EFFECT_GIVE_EXPERIENCE
+ &Spell::EffectNULL, //237 SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS
+ &Spell::EffectNULL, //238 SPELL_EFFECT_INCREASE_SKILL
+ &Spell::EffectNULL, //239 SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION
&Spell::EffectNULL, //240 SPELL_EFFECT_240
&Spell::EffectNULL, //241 SPELL_EFFECT_241
&Spell::EffectNULL, //242 SPELL_EFFECT_242
- &Spell::EffectNULL, //243 SPELL_EFFECT_243
- &Spell::EffectNULL, //244 SPELL_EFFECT_244
- &Spell::EffectNULL, //244 SPELL_EFFECT_245
- &Spell::EffectNULL, //244 SPELL_EFFECT_246
- &Spell::EffectNULL, //244 SPELL_EFFECT_247
- &Spell::EffectNULL, //244 SPELL_EFFECT_248
- &Spell::EffectNULL, //244 SPELL_EFFECT_249
- &Spell::EffectNULL, //244 SPELL_EFFECT_250
+ &Spell::EffectNULL, //243 SPELL_EFFECT_APPLY_ENCHANT_ILLUSION
+ &Spell::EffectNULL, //244 SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
+ &Spell::EffectNULL, //245 SPELL_EFFECT_UPGRADE_HEIRLOOM
+ &Spell::EffectNULL, //246 SPELL_EFFECT_FINISH_GARRISON_MISSION
+ &Spell::EffectNULL, //247 SPELL_EFFECT_ADD_GARRISON_MISSION
+ &Spell::EffectNULL, //248 SPELL_EFFECT_FINISH_SHIPMENT
+ &Spell::EffectNULL, //249 SPELL_EFFECT_249
+ &Spell::EffectNULL, //250 SPELL_EFFECT_TAKE_SCREENSHOT
};
void Spell::EffectNULL(SpellEffIndex /*effIndex*/)
@@ -377,11 +379,12 @@ void Spell::EffectInstaKill(SpellEffIndex /*effIndex*/)
if (m_caster == unitTarget) // prevent interrupt message
finish();
- WorldPacket data(SMSG_SPELL_INSTAKILL_LOG, 8+8+4);
- data << m_caster->GetGUID();
- data << unitTarget->GetGUID();
- data << uint32(m_spellInfo->Id);
- m_caster->SendMessageToSet(&data, true);
+ WorldPackets::CombatLog::SpellInstakillLog data;
+ data.Target = unitTarget->GetGUID();
+ data.Caster = m_caster->GetGUID();
+ data.SpellID = m_spellInfo->Id;
+
+ m_caster->SendMessageToSet(data.Write(), true);
m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, NODAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
@@ -420,7 +423,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
{
uint32 count = 0;
- for (std::vector<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
if (ihit->effectMask & (1<<effIndex))
++count;
@@ -431,7 +434,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
{
// Consumption
case 28865:
- damage = (((InstanceMap*)m_caster->GetMap())->GetDifficultyID() == DIFFICULTY_NONE ? 2750 : 4250);
+ damage = (m_caster->GetMap()->GetDifficultyID() == DIFFICULTY_NONE ? 2750 : 4250);
break;
// percent from health with min
case 25599: // Thundercrash
@@ -1907,7 +1910,7 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex)
if (gameObjTarget)
SendLoot(guid, LOOT_SKINNING);
else if (itemTarget)
- itemTarget->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED);
+ itemTarget->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED);
// not allow use skill grow at item base open
if (!m_CastItem && skillId != SKILL_NONE)
@@ -2166,7 +2169,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
return;
summon->SelectLevel(); // some summoned creaters have different from 1 DB data for level/hp
- summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag);
+ summon->SetUInt64Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag);
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
@@ -2544,7 +2547,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
else
{
// do not increase skill if vellum used
- if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_TRIGGERED_CAST))
+ if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_TRIGGERED_CAST))
player->UpdateCraftSkill(m_spellInfo->Id);
uint32 enchant_id = effectInfo->MiscValue;
@@ -2922,7 +2925,7 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
unitTarget->ToCreature()->AI()->AttackStart(m_caster);
}
-void Spell::EffectWeaponDmg(SpellEffIndex /*effIndex*/)
+void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
return;
@@ -2933,8 +2936,9 @@ void Spell::EffectWeaponDmg(SpellEffIndex /*effIndex*/)
// multiple weapon dmg effect workaround
// execute only the last weapon damage
// and handle all effects at once
- for (SpellEffectInfo const* effect : GetEffects())
+ for (uint8 index = effIndex + 1; index < MAX_SPELL_EFFECTS; ++index)
{
+ SpellEffectInfo const* effect = GetEffect(index);
if (!effect)
continue;
switch (effect->Effect)
@@ -4646,6 +4650,25 @@ void Spell::EffectPullTowards(SpellEffIndex /*effIndex*/)
unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ);
}
+void Spell::EffectChangeRaidMarker(SpellEffIndex /*effIndex*/)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ Player* player = m_caster->ToPlayer();
+ if (!player || !m_targets.HasDst())
+ return;
+
+ Group* group = player->GetGroup();
+ if (!group || (group->isRaidGroup() && !group->IsLeader(player->GetGUID()) && !group->IsAssistant(player->GetGUID())))
+ return;
+
+ float x, y, z;
+ destTarget->GetPosition(x, y, z);
+
+ group->AddRaidMarker(damage, player->GetMapId(), x, y, z);
+}
+
void Spell::EffectDispelMechanic(SpellEffIndex /*effIndex*/)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
@@ -4981,7 +5004,7 @@ void Spell::EffectProspecting(SpellEffIndex /*effIndex*/)
if (!player)
return;
- if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_PROSPECTABLE))
+ if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_FLAG_PROSPECTABLE))
return;
if (itemTarget->GetCount() < 5)
@@ -5006,7 +5029,7 @@ void Spell::EffectMilling(SpellEffIndex /*effIndex*/)
if (!player)
return;
- if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_PROTO_FLAG_MILLABLE))
+ if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_FLAG_MILLABLE))
return;
if (itemTarget->GetCount() < 5)
@@ -5801,3 +5824,38 @@ void Spell::EffectDestroyItem(SpellEffIndex effIndex)
if (Item* item = player->GetItemByEntry(itemId))
player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
}
+
+void Spell::EffectLearnGarrisonBuilding(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
+ garrison->LearnBlueprint(GetEffect(effIndex)->MiscValue);
+}
+
+void Spell::EffectCreateGarrison(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ unitTarget->ToPlayer()->CreateGarrison(GetEffect(effIndex)->MiscValue);
+}
+
+void Spell::EffectAddGarrisonFollower(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
+ garrison->AddFollower(GetEffect(effIndex)->MiscValue);
+}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 4db7091f971..6560309527c 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -806,7 +806,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 103 SPELL_EFFECT_REPUTATION
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
- {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 106 SPELL_EFFECT_CHANGE_RAID_MARKER
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 108 SPELL_EFFECT_DISPEL_MECHANIC
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_DEST}, // 109 SPELL_EFFECT_SUMMON_DEAD_PET
@@ -1822,6 +1822,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
if (!player->CanFlyInZone(map_id, zone_id))
return SPELL_FAILED_INCORRECT_AREA;
}
+ break;
}
case SPELL_AURA_MOUNTED:
{
@@ -1958,7 +1959,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
@@ -2577,6 +2578,8 @@ std::vector<SpellInfo::CostData> SpellInfo::CalcPowerCost(Unit const* caster, Sp
powerCost += int32(CalculatePct(caster->GetMaxHealth(), power->ManaCostPercentage));
break;
case POWER_MANA:
+ powerCost += int32(CalculatePct(caster->GetCreateMana(), power->ManaCostPercentage));
+ break;
case POWER_RAGE:
case POWER_FOCUS:
case POWER_ENERGY:
@@ -2635,7 +2638,7 @@ std::vector<SpellInfo::CostData> SpellInfo::CalcPowerCost(Unit const* caster, Sp
modOwner->ApplySpellMod(Id, SPELLMOD_SPELL_COST2, powerCost);
}
- if (!caster->IsControlledByPlayer())
+ if (!caster->IsControlledByPlayer() && G3D::fuzzyEq(power->ManaCostPercentage, 0.0f))
{
if (Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION)
{
@@ -2693,7 +2696,7 @@ std::vector<SpellInfo::CostData> SpellInfo::CalcPowerCost(Unit const* caster, Sp
}
};
- if (_hasPowerDifficultyData) // optimization - use static data for 99.5% cases (4753 of 4772 in build 6.1.0.19702)
+ if (!_hasPowerDifficultyData) // optimization - use static data for 99.5% cases (4753 of 4772 in build 6.1.0.19702)
collector(PowerCosts);
else
collector(sDB2Manager.GetSpellPowers(Id, caster->GetMap()->GetDifficultyID()));
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 62381372657..6d1d787e303 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -197,6 +197,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 2f74218ba7b..4f73eee601f 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3030,6 +3030,10 @@ void SpellMgr::LoadSpellInfoCorrections()
switch (spellInfo->Id)
{
+ case 63026: // Summon Aspirant Test NPC (HACK: Target shouldn't be changed)
+ case 63137: // Summon Valiant Test (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
+ const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
+ break;
case 42436: // Drink! (Brewfest)
const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
break;
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 33773a57631..4fd8b5d8bf6 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -64,9 +64,9 @@ _SpellScript::EffectHook::EffectHook(uint8 _effIndex)
effIndex = _effIndex;
}
-uint8 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEntry)
+uint32 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEntry)
{
- uint8 mask = 0;
+ uint32 mask = 0;
if ((effIndex == EFFECT_ALL) || (effIndex == EFFECT_FIRST_FOUND))
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -74,13 +74,13 @@ uint8 _SpellScript::EffectHook::GetAffectedEffectsMask(SpellInfo const* spellEnt
if ((effIndex == EFFECT_FIRST_FOUND) && mask)
return mask;
if (CheckEffect(spellEntry, i))
- mask |= (uint8)1<<i;
+ mask |= 1 << i;
}
}
else
{
if (CheckEffect(spellEntry, effIndex))
- mask |= (uint8)1<<effIndex;
+ mask |= 1 << effIndex;
}
return mask;
}
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index fb9e1ed3937..f9a2f1ec847 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -74,7 +74,7 @@ class _SpellScript
EffectHook(uint8 _effIndex);
virtual ~EffectHook() { }
- uint8 GetAffectedEffectsMask(SpellInfo const* spellInfo);
+ uint32 GetAffectedEffectsMask(SpellInfo const* spellInfo);
bool IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex);
virtual bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) = 0;
std::string EffIndexToString();
diff --git a/src/server/game/Support/SupportMgr.cpp b/src/server/game/Support/SupportMgr.cpp
index 90afcfd1511..5afd6fc1d81 100644
--- a/src/server/game/Support/SupportMgr.cpp
+++ b/src/server/game/Support/SupportMgr.cpp
@@ -38,7 +38,7 @@ std::string Ticket::FormatViewMessageString(ChatHandler& handler, char const* cl
{
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayer()->GetName().c_str());
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayerName().c_str());
if (closedName)
ss << handler.PGetParseString(LANG_COMMAND_TICKETCLOSED, closedName);
if (assignedToName)
@@ -173,13 +173,12 @@ std::string GmTicket::FormatViewMessageString(ChatHandler& handler, bool detaile
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayer()->GetName().c_str());
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayerName().c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(curTime - _createTime, true, false)).c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGE, (secsToTimeString(curTime - _lastModifiedTime, true, false)).c_str());
- std::string name;
- if (ObjectMgr::GetPlayerNameByGUID(_assignedTo, name))
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, name.c_str());
+ if (!_assignedTo.IsEmpty())
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, GetAssignedToName().c_str());
if (detailed)
{
@@ -196,7 +195,7 @@ std::string GmTicket::FormatViewMessageString(ChatHandler& handler, const char*
{
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayer()->GetName().c_str());
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayerName().c_str());
if (szClosedName)
ss << handler.PGetParseString(LANG_COMMAND_TICKETCLOSED, szClosedName);
if (szAssignedToName)
@@ -281,12 +280,11 @@ std::string BugTicket::FormatViewMessageString(ChatHandler& handler, bool detail
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayer()->GetName().c_str());
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayerName().c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(curTime - _createTime, true, false)).c_str());
- std::string name;
- if (ObjectMgr::GetPlayerNameByGUID(_assignedTo, name))
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, name.c_str());
+ if (!_assignedTo.IsEmpty())
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, GetAssignedToName().c_str());
if (detailed)
{
@@ -408,12 +406,11 @@ std::string ComplaintTicket::FormatViewMessageString(ChatHandler& handler, bool
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayer()->GetName().c_str());
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayerName().c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(curTime - _createTime, true, false)).c_str());
- std::string name;
- if (ObjectMgr::GetPlayerNameByGUID(_assignedTo, name))
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, name.c_str());
+ if (!_assignedTo.IsEmpty())
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, GetAssignedToName().c_str());
if (detailed)
{
@@ -495,12 +492,11 @@ std::string SuggestionTicket::FormatViewMessageString(ChatHandler& handler, bool
std::stringstream ss;
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTGUID, _id);
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayer()->GetName().c_str());
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTNAME, GetPlayerName().c_str());
ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTAGECREATE, (secsToTimeString(curTime - _createTime, true, false)).c_str());
- std::string name;
- if (ObjectMgr::GetPlayerNameByGUID(_assignedTo, name))
- ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, name.c_str());
+ if (!_assignedTo.IsEmpty())
+ ss << handler.PGetParseString(LANG_COMMAND_TICKETLISTASSIGNEDTO, GetAssignedToName().c_str());
if (detailed)
{
diff --git a/src/server/game/Support/SupportMgr.h b/src/server/game/Support/SupportMgr.h
index e0adb411aa0..10bd90d4f80 100644
--- a/src/server/game/Support/SupportMgr.h
+++ b/src/server/game/Support/SupportMgr.h
@@ -93,8 +93,16 @@ public:
uint32 GetId() const { return _id; }
ObjectGuid GetPlayerGuid() const { return _playerGuid; }
- Player* GetPlayer() const { return ObjectAccessor::FindPlayer(_playerGuid); }
- Player* GetAssignedPlayer() const { return ObjectAccessor::FindPlayer(_assignedTo); }
+ Player* GetPlayer() const { return ObjectAccessor::FindConnectedPlayer(_playerGuid); }
+ std::string GetPlayerName() const
+ {
+ std::string name;
+ if (!_playerGuid.IsEmpty())
+ ObjectMgr::GetPlayerNameByGUID(_playerGuid, name);
+
+ return name;
+ }
+ Player* GetAssignedPlayer() const { return ObjectAccessor::FindConnectedPlayer(_assignedTo); }
ObjectGuid GetAssignedToGUID() const { return _assignedTo; }
std::string GetAssignedToName() const
{
diff --git a/src/server/game/Texts/ChatTextBuilder.h b/src/server/game/Texts/ChatTextBuilder.h
index dcee6f08ac3..167680f1cd2 100644
--- a/src/server/game/Texts/ChatTextBuilder.h
+++ b/src/server/game/Texts/ChatTextBuilder.h
@@ -34,7 +34,7 @@ namespace Trinity
{
BroadcastTextEntry const* bct = sBroadcastTextStore.LookupEntry(_textId);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, bct ? Language(bct->Language) : LANG_UNIVERSAL, _source, _target, bct ? DB2Manager::GetBroadcastTextValue(bct, locale, _source->getGender()) : "", _achievementId, "", locale);
+ packet.Initialize(_msgType, bct ? Language(bct->Language) : LANG_UNIVERSAL, _source, _target, bct ? DB2Manager::GetBroadcastTextValue(bct, locale, _source->getGender()) : "", _achievementId, "", locale);
packet.Write();
data = packet.Move();
}
@@ -56,7 +56,7 @@ namespace Trinity
void operator()(WorldPacket& data, LocaleConstant locale)
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, _language, _source, _target, _text, 0, "", locale);
+ packet.Initialize(_msgType, _language, _source, _target, _text, 0, "", locale);
packet.Write();
data = packet.Move();
}
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 281504b9aaf..c1ea235a3e2 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -37,7 +37,7 @@ class CreatureTextBuilder
{
std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _gender, _textGroup, _textId, locale);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, Language(_language), _source, _target, text, 0, "", locale);
+ packet.Initialize(_msgType, Language(_language), _source, _target, text, 0, "", locale);
packet.Write();
data = packet.Move();
}
@@ -62,7 +62,7 @@ class PlayerTextBuilder
{
std::string const& text = sCreatureTextMgr->GetLocalizedChatString(_source->GetEntry(), _gender, _textGroup, _textId, locale);
WorldPackets::Chat::Chat packet;
- packet.Initalize(_msgType, Language(_language), _talker, _target, text, 0, "", locale);
+ packet.Initialize(_msgType, Language(_language), _talker, _target, text, 0, "", locale);
packet.Write();
data = packet.Move();
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 94f13abfb6c..d68da8fbc63 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -38,6 +38,7 @@
#include "DatabaseEnv.h"
#include "DisableMgr.h"
#include "GameEventMgr.h"
+#include "GarrisonMgr.h"
#include "GridNotifiersImpl.h"
#include "GroupMgr.h"
#include "GuildFinderMgr.h"
@@ -1520,7 +1521,6 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadGameObjectLocales();
sObjectMgr->LoadQuestTemplateLocale();
sObjectMgr->LoadQuestObjectivesLocale();
- sObjectMgr->LoadQuestGreetings();
sObjectMgr->LoadPageTextLocales();
sObjectMgr->LoadGossipMenuItemsLocales();
sObjectMgr->LoadPointOfInterestLocales();
@@ -1660,6 +1660,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Quests Starters and Enders...");
sObjectMgr->LoadQuestStartersAndEnders(); // must be after quest load
+ TC_LOG_INFO("server.loading", "Loading Quest Greetings...");
+ sObjectMgr->LoadQuestGreetings();
+
TC_LOG_INFO("server.loading", "Loading Objects Pooling Data...");
sPoolMgr->LoadFromDB();
@@ -1869,6 +1872,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading client addons...");
AddonMgr::LoadFromDB();
+ TC_LOG_INFO("server.loading", "Loading garrison info...");
+ sGarrisonMgr.Initialize();
+
///- Handle outdated emails (delete/return)
TC_LOG_INFO("server.loading", "Returning old mails...");
sObjectMgr->ReturnOrDeleteOldMails(false);
@@ -2121,7 +2127,7 @@ void World::Update(uint32 diff)
/// Handle daily quests reset time
if (m_gameTime > m_NextDailyQuestReset)
{
- ResetDailyQuests();
+ DailyReset();
m_NextDailyQuestReset += DAY;
}
@@ -2246,6 +2252,9 @@ void World::Update(uint32 diff)
sLFGMgr->Update(diff);
RecordTimeDiff("UpdateLFGMgr");
+ sGroupMgr->Update(diff);
+ RecordTimeDiff("GroupMgr");
+
// execute callbacks from sql queries that were queued recently
ProcessQueryCallbacks();
RecordTimeDiff("ProcessQueryCallbacks");
@@ -2375,7 +2384,7 @@ namespace Trinity
while (char* line = ChatHandler::LineFromMessage(text))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
packet.Write();
dataList.emplace_back(new WorldPacket(packet.Move()));
}
@@ -2441,7 +2450,7 @@ void World::SendGlobalText(const char* text, WorldSession* self)
while (char* line = ChatHandler::LineFromMessage(pos))
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, line);
SendGlobalMessage(packet.Write(), self);
}
@@ -2475,7 +2484,7 @@ bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession
void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, uint32 team)
{
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text);
+ packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text);
SendZoneMessage(zone, packet.Write(), self, team);
}
@@ -2747,7 +2756,7 @@ void World::ShutdownMsg(bool show, Player* player, const std::string& reason)
ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME;
- SendServerMessage(msgid, str.c_str(), player);
+ SendServerMessage(msgid, str, player);
TC_LOG_DEBUG("misc", "Server is %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"), str.c_str());
}
}
@@ -2772,17 +2781,17 @@ void World::ShutdownCancel()
}
/// Send a server message to the user(s)
-void World::SendServerMessage(ServerMessageType type, const char *text, Player* player)
+void World::SendServerMessage(ServerMessageType messageID, std::string stringParam /*= ""*/, Player* player /*= NULL*/)
{
- WorldPacket data(SMSG_CHAT_SERVER_MESSAGE, 50); // guess size
- data << uint32(type);
- if (type <= SERVER_MSG_STRING)
- data << text;
+ WorldPackets::Chat::ChatServerMessage chatServerMessage;
+ chatServerMessage.MessageID = int32(messageID);
+ if (messageID <= SERVER_MSG_STRING)
+ chatServerMessage.StringParam = stringParam;
if (player)
- player->GetSession()->SendPacket(&data);
+ player->GetSession()->SendPacket(chatServerMessage.Write());
else
- SendGlobalMessage(&data);
+ SendGlobalMessage(chatServerMessage.Write());
}
void World::UpdateSessions(uint32 diff)
@@ -3050,16 +3059,20 @@ void World::InitCurrencyResetTime()
sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
}
-void World::ResetDailyQuests()
+void World::DailyReset()
{
TC_LOG_INFO("misc", "Daily quests reset for all characters.");
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY);
CharacterDatabase.Execute(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS);
+ stmt->setUInt32(0, 1);
+ CharacterDatabase.Execute(stmt);
+
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
if (itr->second->GetPlayer())
- itr->second->GetPlayer()->ResetDailyQuestStatus();
+ itr->second->GetPlayer()->DailyReset();
// change available dailies
sPoolMgr->ChangeDailyQuests();
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index b3bebca08e3..b169431f2fd 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -671,7 +671,7 @@ class World
void SendWorldText(uint32 string_id, ...);
void SendGlobalText(const char* text, WorldSession* self);
void SendGMText(uint32 string_id, ...);
- void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL);
+ void SendServerMessage(ServerMessageType messageID, std::string stringParam = "", Player* player = NULL);
void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0);
void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0);
bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0);
@@ -805,7 +805,7 @@ class World
void InitRandomBGResetTime();
void InitGuildResetTime();
void InitCurrencyResetTime();
- void ResetDailyQuests();
+ void DailyReset();
void ResetWeeklyQuests();
void ResetMonthlyQuests();
void ResetRandomBG();
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index ecd98595723..7f1a364fd57 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -485,7 +485,7 @@ public:
char const* msg = "testtest";
uint8 type = atoi(args);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), LANG_UNIVERSAL, handler->GetSession()->GetPlayer(), handler->GetSession()->GetPlayer(), msg, 0, "chan");
+ packet.Initialize(ChatMsg(type), LANG_UNIVERSAL, handler->GetSession()->GetPlayer(), handler->GetSession()->GetPlayer(), msg, 0, "chan");
handler->GetSession()->SendPacket(packet.Write());
return true;
}
diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp
index c12c9b5d43e..53522736718 100644
--- a/src/server/scripts/Commands/cs_go.cpp
+++ b/src/server/scripts/Commands/cs_go.cpp
@@ -44,6 +44,7 @@ public:
{ "graveyard", rbac::RBAC_PERM_COMMAND_GO_GRAVEYARD, false, &HandleGoGraveyardCommand, "", NULL },
{ "grid", rbac::RBAC_PERM_COMMAND_GO_GRID, false, &HandleGoGridCommand, "", NULL },
{ "object", rbac::RBAC_PERM_COMMAND_GO_OBJECT, false, &HandleGoObjectCommand, "", NULL },
+ { "quest", rbac::RBAC_PERM_COMMAND_GO_QUEST, false, &HandleGoQuestCommand, "", NULL },
{ "taxinode", rbac::RBAC_PERM_COMMAND_GO_TAXINODE, false, &HandleGoTaxinodeCommand, "", NULL },
{ "trigger", rbac::RBAC_PERM_COMMAND_GO_TRIGGER, false, &HandleGoTriggerCommand, "", NULL },
{ "zonexy", rbac::RBAC_PERM_COMMAND_GO_ZONEXY, false, &HandleGoZoneXYCommand, "", NULL },
@@ -315,6 +316,71 @@ public:
return true;
}
+ static bool HandleGoQuestCommand(ChatHandler* handler, char const* args)
+ {
+ if (!*args)
+ return false;
+
+ Player* player = handler->GetSession()->GetPlayer();
+
+ char* id = handler->extractKeyFromLink((char*)args, "Hquest");
+ if (!id)
+ return false;
+
+ uint32 questID = atoi(id);
+ if (!questID)
+ return false;
+
+ if (!sObjectMgr->GetQuestTemplate(questID))
+ {
+ handler->PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, questID);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ float x, y, z;
+ uint32 mapId;
+
+ if (QuestPOIVector const* poiData = sObjectMgr->GetQuestPOIVector(questID))
+ {
+ auto data = poiData->front();
+
+ mapId = data.MapID;
+
+ x = data.points.front().X;
+ y = data.points.front().Y;
+ }
+ else
+ {
+ handler->PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, questID);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ if (!MapManager::IsValidMapCoord(mapId, x, y) || sObjectMgr->IsTransportMap(mapId))
+ {
+ handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId);
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+
+ // stop flight if need
+ if (player->IsInFlight())
+ {
+ player->GetMotionMaster()->MovementExpired();
+ player->CleanupAfterTaxiFlight();
+ }
+ // save only in non-flight case
+ else
+ player->SaveRecallPosition();
+
+ Map const* map = sMapMgr->CreateBaseMap(mapId);
+ z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y));
+
+ player->TeleportTo(mapId, x, y, z, 0.0f);
+ return true;
+ }
+
static bool HandleGoTaxinodeCommand(ChatHandler* handler, char const* args)
{
Player* player = handler->GetSession()->GetPlayer();
@@ -448,7 +514,7 @@ public:
if (map->Instanceable())
{
- handler->PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->ZoneName, map->GetId(), map->GetMapName());
+ handler->PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->AreaName_lang, map->GetId(), map->GetMapName());
handler->SetSentErrorMessage(true);
return false;
}
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index ef52f6ebd95..ad877bdefb4 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -168,6 +168,8 @@ public:
// fill the gameobject data and save to the db
object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMask());
+ guidLow = object->GetSpawnId();
+
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
// this is required to avoid weird behavior and memory leaks
delete object;
@@ -431,14 +433,14 @@ public:
}
object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), o);
+ object->RelocateStationaryPosition(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), o);
object->UpdateRotationFields();
object->DestroyForNearbyPlayers();
object->UpdateObjectVisibility();
object->SaveToDB();
- object->Refresh();
- handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetGUID().GetCounter(), object->GetGOInfo()->name.c_str(), object->GetGUID().ToString().c_str(), o);
+ handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetGUID().ToString().c_str(), o);
return true;
}
@@ -472,21 +474,20 @@ public:
char* toY = strtok(NULL, " ");
char* toZ = strtok(NULL, " ");
+ float x, y, z;
if (!toX)
{
Player* player = handler->GetSession()->GetPlayer();
- object->Relocate(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), object->GetOrientation());
- object->DestroyForNearbyPlayers();
- object->UpdateObjectVisibility();
+ player->GetPosition(x, y, z);
}
else
{
if (!toY || !toZ)
return false;
- float x = (float)atof(toX);
- float y = (float)atof(toY);
- float z = (float)atof(toZ);
+ x = (float)atof(toX);
+ y = (float)atof(toY);
+ z = (float)atof(toZ);
if (!MapManager::IsValidMapCoord(object->GetMapId(), x, y, z))
{
@@ -494,16 +495,15 @@ public:
handler->SetSentErrorMessage(true);
return false;
}
-
- object->Relocate(x, y, z, object->GetOrientation());
- object->DestroyForNearbyPlayers();
- object->UpdateObjectVisibility();
}
+ object->DestroyForNearbyPlayers();
+ object->RelocateStationaryPosition(x, y, z, object->GetOrientation());
+ object->GetMap()->GameObjectRelocation(object, x, y, z, object->GetOrientation());
+
object->SaveToDB();
- object->Refresh();
- handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetGUID().GetCounter(), object->GetGOInfo()->name.c_str(), object->GetGUID().ToString().c_str());
+ handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetGUID().ToString().c_str());
return true;
}
diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp
index ae7b2039e81..5e5694ba23a 100644
--- a/src/server/scripts/Commands/cs_group.cpp
+++ b/src/server/scripts/Commands/cs_group.cpp
@@ -354,7 +354,7 @@ public:
{
AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID);
if (zone)
- zoneName = zone->ZoneName;
+ zoneName = zone->AreaName_lang;
}
}
else
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index d8f98e90275..4d1d484cb2f 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -106,7 +106,7 @@ public:
AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaflag);
if (areaEntry)
{
- std::string name = areaEntry->ZoneName;
+ std::string name = areaEntry->AreaName_lang;
if (name.empty())
continue;
diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp
index 519ae1e1f97..be3a027277c 100644
--- a/src/server/scripts/Commands/cs_message.cpp
+++ b/src/server/scripts/Commands/cs_message.cpp
@@ -134,9 +134,9 @@ public:
if (!*args)
return false;
- char buff[2048];
- sprintf(buff, handler->GetTrinityString(LANG_SYSTEMMESSAGE), args);
- sWorld->SendServerMessage(SERVER_MSG_STRING, buff);
+ std::string str = handler->PGetParseString(LANG_SYSTEMMESSAGE, args);
+
+ sWorld->SendServerMessage(SERVER_MSG_STRING, str);
return true;
}
// announce to logged in GMs
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 9e537e42d20..b9765223add 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -236,8 +236,8 @@ public:
handler->PSendSysMessage(LANG_MAP_POSITION,
mapId, (mapEntry ? mapEntry->MapName_lang : unknown),
- zoneId, (zoneEntry ? zoneEntry->ZoneName : unknown),
- areaId, (areaEntry ? areaEntry->ZoneName : unknown),
+ zoneId, (zoneEntry ? zoneEntry->AreaName_lang : unknown),
+ areaId, (areaEntry ? areaEntry->AreaName_lang : unknown),
object->GetPhaseMask(),
object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation());
handler->PSendSysMessage(LANG_GRID_POSITION,
@@ -1465,7 +1465,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
@@ -1716,7 +1716,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);
@@ -1762,11 +1762,11 @@ public:
AreaTableEntry const* area = GetAreaEntryByAreaID(areaId);
if (area)
{
- areaName = area->ZoneName;
+ areaName = area->AreaName_lang;
AreaTableEntry const* zone = GetAreaEntryByAreaID(area->ParentAreaID);
if (zone)
- zoneName = zone->ZoneName;
+ zoneName = zone->AreaName_lang;
}
if (target)
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index 48a514fd0db..3bcb6862b7f 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -313,7 +313,7 @@ public:
{
uint32 factionid = target->getFaction();
uint32 flag = target->GetUInt32Value(UNIT_FIELD_FLAGS);
- uint32 npcflag = target->GetUInt32Value(UNIT_NPC_FLAGS);
+ uint64 npcflag = target->GetUInt64Value(UNIT_NPC_FLAGS);
uint32 dyflag = target->GetUInt32Value(OBJECT_DYNAMIC_FLAGS);
handler->PSendSysMessage(LANG_CURRENT_FACTION, target->GetGUID().ToString().c_str(), factionid, flag, npcflag, dyflag);
return true;
@@ -330,11 +330,11 @@ public:
char* pnpcflag = strtok(NULL, " ");
- uint32 npcflag;
+ uint64 npcflag;
if (!pnpcflag)
- npcflag = target->GetUInt32Value(UNIT_NPC_FLAGS);
+ npcflag = target->GetUInt64Value(UNIT_NPC_FLAGS);
else
- npcflag = atoi(pnpcflag);
+ npcflag = std::strtoull(pnpcflag, nullptr, 10);
char* pdyflag = strtok(NULL, " ");
@@ -355,7 +355,7 @@ public:
target->setFaction(factionid);
target->SetUInt32Value(UNIT_FIELD_FLAGS, flag);
- target->SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
+ target->SetUInt64Value(UNIT_NPC_FLAGS, npcflag);
target->SetUInt32Value(OBJECT_DYNAMIC_FLAGS, dyflag);
return true;
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 5dc1696057e..2c91a9e6e3e 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -374,28 +374,13 @@ public:
ObjectGuid::LowType lowGuid = strtoull(guidStr, nullptr, 10);
- 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->GetSpawnId();
+ handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
+ handler->SetSentErrorMessage(true);
+ return false;
}
int wait = waitStr ? atoi(waitStr) : 0;
@@ -411,18 +396,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;
@@ -634,7 +607,7 @@ public:
if (!*args)
return false;
- uint32 npcFlags = (uint32) atoi((char*)args);
+ uint64 npcFlags = std::strtoull(args, nullptr, 10);
Creature* creature = handler->getSelectedCreature();
@@ -645,11 +618,11 @@ public:
return false;
}
- creature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
+ creature->SetUInt64Value(UNIT_NPC_FLAGS, npcFlags);
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_NPCFLAG);
- stmt->setUInt32(0, npcFlags);
+ stmt->setUInt64(0, npcFlags);
stmt->setUInt32(1, creature->GetEntry());
WorldDatabase.Execute(stmt);
@@ -726,7 +699,7 @@ public:
CreatureTemplate const* cInfo = target->GetCreatureTemplate();
uint32 faction = target->getFaction();
- uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS);
+ uint64 npcflags = target->GetUInt64Value(UNIT_NPC_FLAGS);
uint32 mechanicImmuneMask = cInfo->MechanicImmuneMask;
uint32 displayid = target->GetDisplayId();
uint32 nativeid = target->GetNativeDisplayId();
@@ -836,34 +809,22 @@ public:
lowguid = strtoull(cId, nullptr, 10);
- /* 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->GetSpawnId();
+ 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 ec2f41cc625..15280bc7848 100644
--- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
+++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp
@@ -197,7 +197,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/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index f1c4c22527b..d261b7a623a 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -25,14 +25,6 @@
#include "ruby_sanctum.h"
#include "Player.h"
-/* ScriptData
-SDName: ruby_sanctum
-SDAuthors: Kaelima, Warpten
-SD%Complete: 90%
-SDComment: Based on Kaelima's initial work (half of it). Corporeality handling is a pure guess, we lack info.
-SDCategory: Chamber of Aspects
-EndScriptData */
-
enum Texts
{
// Shared
@@ -86,6 +78,8 @@ enum Spells
// Living Inferno
SPELL_BLAZING_AURA = 75885,
+ SPELL_SPAWN_LIVING_EMBERS = 75880,
+ SPELL_SUMMON_LIVING_EMBER = 75881,
// Halion Controller
SPELL_COSMETIC_FIRE_PILLAR = 76006,
@@ -142,7 +136,7 @@ enum Events
EVENT_CHECK_CORPOREALITY = 14,
EVENT_SHADOW_PULSARS_SHOOT = 15,
EVENT_TRIGGER_BERSERK = 16,
- EVENT_TWILIGHT_MENDING = 17
+ EVENT_TWILIGHT_MENDING = 17,
};
enum Actions
@@ -155,7 +149,13 @@ enum Actions
ACTION_MONITOR_CORPOREALITY = 3,
// Orb Carrier
- ACTION_SHOOT = 4
+ ACTION_SHOOT = 4,
+
+ // Living Inferno
+ ACTION_SUMMON_LIVING_EMBERS = 5,
+
+ // Meteor Flame
+ ACTION_SUMMON_FLAME = 6
};
enum Phases
@@ -173,7 +173,8 @@ enum Misc
DATA_MATERIAL_DAMAGE_TAKEN = 2,
DATA_STACKS_DISPELLED = 3,
DATA_FIGHT_PHASE = 4,
- DATA_EVADE_METHOD = 5
+ DATA_EVADE_METHOD = 5,
+ DATA_SPAWNED_FLAMES = 6,
};
enum OrbCarrierSeats
@@ -702,7 +703,7 @@ class npc_halion_controller : public CreatureScript
// The IsInCombat() check is needed because that check should be false when Halion is
// not engaged, while it would return true without as UpdateVictim() checks for
// combat state.
- if (!(_events.IsInPhase(PHASE_INTRO)) && me->IsInCombat() && !UpdateVictim())
+ if (!_events.IsInPhase(PHASE_INTRO) && me->IsInCombat() && !UpdateVictim())
{
EnterEvadeMode();
return;
@@ -893,8 +894,6 @@ class npc_halion_controller : public CreatureScript
}
};
-typedef npc_halion_controller::npc_halion_controllerAI controllerAI;
-
class npc_orb_carrier : public CreatureScript
{
public:
@@ -996,7 +995,7 @@ class npc_meteor_strike_initial : public CreatureScript
if (!owner)
return;
- // Let Halion Controller count as summoner
+ // Let Controller count as summoner
if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->JustSummoned(me);
@@ -1006,11 +1005,13 @@ class npc_meteor_strike_initial : public CreatureScript
if (HalionAI* halionAI = CAST_AI(HalionAI, owner->AI()))
{
Position const* ownerPos = halionAI->GetMeteorStrikePosition();
+ // Adjust randomness between 0 and pi.
+ float randomAdjustment = frand(static_cast<float>(M_PI / 14), static_cast<float>(13 * M_PI / 14));
float angle[4];
angle[0] = me->GetAngle(ownerPos);
- angle[1] = me->GetAngle(ownerPos) - static_cast<float>(M_PI/2);
- angle[2] = me->GetAngle(ownerPos) - static_cast<float>(-M_PI/2);
- angle[3] = me->GetAngle(ownerPos) - static_cast<float>(M_PI);
+ angle[1] = angle[0] + randomAdjustment;
+ angle[2] = angle[0] + static_cast<float>(M_PI);
+ angle[3] = angle[2] + randomAdjustment;
_meteorList.clear();
for (uint8 i = 0; i < 4; i++)
@@ -1019,7 +1020,10 @@ class npc_meteor_strike_initial : public CreatureScript
me->SetOrientation(angle[i]);
Position newPos = me->GetNearPosition(10.0f, 0.0f); // Exact distance
if (Creature* meteor = me->SummonCreature(NPC_METEOR_STRIKE_NORTH + i, newPos, TEMPSUMMON_TIMED_DESPAWN, 30000))
+ {
+ meteor->SetOrientation(angle[i]);
_meteorList.push_back(meteor);
+ }
}
}
}
@@ -1045,11 +1049,8 @@ class npc_meteor_strike : public CreatureScript
struct npc_meteor_strikeAI : public ScriptedAI
{
npc_meteor_strikeAI(Creature* creature) : ScriptedAI(creature),
- _instance(creature->GetInstanceScript())
+ _instance(creature->GetInstanceScript()), _spawnCount(0)
{
- _range = 5.0f;
- _spawnCount = 0;
-
SetCombatMovement(false);
}
@@ -1070,34 +1071,38 @@ class npc_meteor_strike : public CreatureScript
controller->AI()->JustSummoned(me);
}
- void UpdateAI(uint32 diff) override
+ void SetData(uint32 dataType, uint32 dataCount) override
{
- if (_spawnCount > 5)
- return;
+ if (dataType == DATA_SPAWNED_FLAMES)
+ _spawnCount += dataCount;
+ }
- _events.Update(diff);
+ uint32 GetData(uint32 dataType) const override
+ {
+ if (dataType == DATA_SPAWNED_FLAMES)
+ return _spawnCount;
+ return 0;
+ }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
if (_events.ExecuteEvent() == EVENT_SPAWN_METEOR_FLAME)
{
- Position pos = me->GetNearPosition( _range, 0.0f);
-
+ Position pos = me->GetNearPosition(5.0f, 0.0f);
if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000))
{
- if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
- controller->AI()->JustSummoned(flame);
+ flame->SetOrientation(me->GetOrientation());
- flame->CastSpell(flame, SPELL_METEOR_STRIKE_FIRE_AURA_2, true);
- ++_spawnCount;
+ flame->AI()->SetGUID(GetGUID());
+ flame->AI()->DoAction(ACTION_SUMMON_FLAME);
}
- _range += 5.0f;
- _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, 800);
}
}
private:
InstanceScript* _instance;
EventMap _events;
- float _range;
uint8 _spawnCount;
};
@@ -1107,6 +1112,67 @@ class npc_meteor_strike : public CreatureScript
}
};
+class npc_meteor_strike_flame : public CreatureScript
+{
+ public:
+ npc_meteor_strike_flame() : CreatureScript("npc_meteor_strike_flame") { }
+
+ struct npc_meteor_strike_flameAI : public ScriptedAI
+ {
+ npc_meteor_strike_flameAI(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript())
+ {
+ SetCombatMovement(false);
+ }
+
+ void SetGUID(ObjectGuid guid, int32 /*id = 0 */)
+ {
+ _rootOwnerGuid = guid;
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action != ACTION_SUMMON_FLAME || _rootOwnerGuid.IsEmpty())
+ return;
+
+ me->CastSpell(me, SPELL_METEOR_STRIKE_FIRE_AURA_2, true);
+
+ Creature* meteorStrike = ObjectAccessor::GetCreature(*me, _rootOwnerGuid);
+ if (!meteorStrike || meteorStrike->AI()->GetData(DATA_SPAWNED_FLAMES) > 5)
+ return;
+
+ me->SetOrientation(me->GetOrientation() + frand(static_cast<float>(-M_PI / 16), static_cast<float>(M_PI / 16)));
+ Position pos = me->GetNearPosition(5.0f, 0.0f);
+
+ if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000))
+ {
+ flame->AI()->SetGUID(_rootOwnerGuid);
+ meteorStrike->AI()->SetData(DATA_SPAWNED_FLAMES, 1);
+ }
+ }
+
+ void IsSummonedBy(Unit* /*summoner*/) override
+ {
+ // Let Halion Controller count as summoner.
+ if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
+ controller->AI()->JustSummoned(me);
+ }
+
+ void UpdateAI(uint32 /*diff*/) override { }
+ void EnterEvadeMode() override { }
+
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ ObjectGuid _rootOwnerGuid = ObjectGuid::Empty;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetRubySanctumAI<npc_meteor_strike_flameAI>(creature);
+ }
+};
+
class npc_combustion_consumption : public CreatureScript
{
public:
@@ -1119,26 +1185,23 @@ class npc_combustion_consumption : public CreatureScript
{
SetCombatMovement(false);
- switch (me->GetEntry())
+ switch (creature->GetEntry())
{
case NPC_COMBUSTION:
_explosionSpell = SPELL_FIERY_COMBUSTION_EXPLOSION;
_damageSpell = SPELL_COMBUSTION_DAMAGE_AURA;
- me->SetPhaseMask(0x01, true);
+ creature->SetPhaseMask(IsHeroic() ? 0x21 : 0x01, true);
break;
case NPC_CONSUMPTION:
_explosionSpell = SPELL_SOUL_CONSUMPTION_EXPLOSION;
_damageSpell = SPELL_CONSUMPTION_DAMAGE_AURA;
- me->SetPhaseMask(0x20, true);
+ creature->SetPhaseMask(IsHeroic() ? 0x21 : 0x20, true);
break;
default: // Should never happen
_explosionSpell = 0;
_damageSpell = 0;
break;
}
-
- if (IsHeroic())
- me->SetPhaseMask(0x01 | 0x20, true);
}
void IsSummonedBy(Unit* summoner) override
@@ -1160,7 +1223,7 @@ class npc_combustion_consumption : public CreatureScript
me->CastCustomSpell(SPELL_SCALE_AURA, SPELLVALUE_AURA_STACK, stackAmount, me);
DoCast(me, _damageSpell);
- int32 damage = 1200 + (stackAmount * 1290); // Needs more researches.
+ int32 damage = 1200 + (stackAmount * 1290); // Needs more research.
summoner->CastCustomSpell(_explosionSpell, SPELLVALUE_BASE_POINT0, damage, summoner);
}
@@ -1193,6 +1256,10 @@ class npc_living_inferno : public CreatureScript
me->SetInCombatWithZone();
me->CastSpell(me, SPELL_BLAZING_AURA, true);
+ // SMSG_SPELL_GO for the living ember stuff isn't even sent to the client - Blizzard on drugs.
+ if (me->GetMap()->GetDifficultyID() == DIFFICULTY_25_HC)
+ me->CastSpell(me, SPELL_SPAWN_LIVING_EMBERS, true);
+
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->JustSummoned(me);
@@ -1210,7 +1277,6 @@ class npc_living_inferno : public CreatureScript
}
};
-//! Need sniff data
class npc_living_ember : public CreatureScript
{
public:
@@ -1738,12 +1804,46 @@ class spell_halion_summon_exit_portals : public SpellScriptLoader
}
};
+class spell_halion_spawn_living_embers : public SpellScriptLoader
+{
+ public:
+ spell_halion_spawn_living_embers() : SpellScriptLoader("spell_halion_spawn_living_embers") { }
+
+ class spell_halion_spawn_living_embers_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_halion_spawn_living_embers_SpellScript);
+
+ void SelectMeteorFlames(std::list<WorldObject*>& unitList)
+ {
+ if (!unitList.empty())
+ Trinity::Containers::RandomResizeList(unitList, 10);
+ }
+
+ void HandleScript(SpellEffIndex /* effIndex */)
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_LIVING_EMBER, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_halion_spawn_living_embers_SpellScript::SelectMeteorFlames, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_halion_spawn_living_embers_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_halion_spawn_living_embers_SpellScript();
+ }
+};
+
void AddSC_boss_halion()
{
new boss_halion();
new boss_twilight_halion();
new npc_halion_controller();
+ new npc_meteor_strike_flame();
new npc_meteor_strike_initial();
new npc_meteor_strike();
new npc_combustion_consumption();
@@ -1765,4 +1865,5 @@ void AddSC_boss_halion()
new spell_halion_twilight_phasing();
new spell_halion_twilight_cutter();
new spell_halion_clear_debuffs();
+ new spell_halion_spawn_living_embers();
}
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 0fc4f1a4a8b..7f88a56f22c 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 faa448ef539..51756834e77 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -1059,8 +1059,8 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
{
if (GetHitUnit()->HasAura(SPELL_VOLATILE_OOZE_ADHESIVE))
{
- GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
GetHitUnit()->RemoveAurasDueToSpell(SPELL_VOLATILE_OOZE_ADHESIVE, 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 7bd1dee15ca..423c1049452 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);
@@ -490,7 +490,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;
@@ -1630,7 +1630,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 aee14edd0c3..d38d630f775 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/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 0c79b42f20c..b939c40cabb 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -128,7 +128,6 @@ enum Spells
SPELL_ARCANE_BARRAGE_DAMAGE = 63934, // the actual damage - cast by affected player by script spell
// Transition /II-III/
- SPELL_SUMMOM_RED_DRAGON_BUDYY = 56070,
SPELL_RIDE_RED_DRAGON_BUDDY = 56071,
SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST = 58846, // After implicitly hit player targets they will force cast 56070 on self
SPELL_DESTROY_PLATFORM_CHANNEL = 58842,
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h
index b6a0d3f9b62..d9b921b38a1 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h
@@ -80,7 +80,8 @@ enum InstanceSpells
SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle
SPELL_PORTAL_OPENED = 61236,
SPELL_RIDE_RED_DRAGON_TRIGGERED = 56072,
- SPELL_IRIS_OPENED = 61012 // visual when starting encounter
+ SPELL_IRIS_OPENED = 61012, // visual when starting encounter
+ SPELL_SUMMOM_RED_DRAGON_BUDDY = 56070
};
#endif
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp
index 79a7c5cb772..11d19d76d80 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp
@@ -39,6 +39,12 @@ public:
SetBossNumber(MAX_ENCOUNTER);
}
+ void OnPlayerEnter(Player* player) override
+ {
+ if (GetBossState(DATA_MALYGOS_EVENT) == DONE)
+ player->CastSpell(player, SPELL_SUMMOM_RED_DRAGON_BUDDY, true);
+ }
+
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
index 9ca88f4fdfa..525ecacd39a 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -482,40 +482,47 @@ class boss_flame_leviathan : public CreatureScript
if (action && action <= 4) // Tower destruction, debuff leviathan loot and reduce active tower count
{
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3 | LOOT_MODE_HARD_MODE_4) && ActiveTowersCount == 4)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_4);
- --ActiveTowersCount;
- }
+
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3) && ActiveTowersCount == 3)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
- --ActiveTowersCount;
- }
+
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2) && ActiveTowersCount == 2)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
- --ActiveTowersCount;
- }
+
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1) && ActiveTowersCount == 1)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
- --ActiveTowersCount;
- }
}
switch (action)
{
case ACTION_TOWER_OF_STORM_DESTROYED:
- towerOfStorms = false;
+ if (towerOfStorms)
+ {
+ towerOfStorms = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_TOWER_OF_FROST_DESTROYED:
- towerOfFrost = false;
+ if (towerOfFrost)
+ {
+ towerOfFrost = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_TOWER_OF_FLAMES_DESTROYED:
- towerOfFlames = false;
+ if (towerOfFlames)
+ {
+ towerOfFlames = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_TOWER_OF_LIFE_DESTROYED:
- towerOfLife = false;
+ if (towerOfLife)
+ {
+ towerOfLife = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_START_HARD_MODE: // Activate hard-mode enable all towers, apply buffs on leviathan
ActiveTowers = true;
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 134783ccf07..6a1ff6d4eea 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/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index 7f29a6621bd..2e426fd77cf 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -25,53 +25,6 @@
#include "CombatAI.h"
/*######
-## npc_squire_david
-######*/
-
-enum SquireDavid
-{
- QUEST_THE_ASPIRANT_S_CHALLENGE_H = 13680,
- QUEST_THE_ASPIRANT_S_CHALLENGE_A = 13679,
-
- NPC_ARGENT_VALIANT = 33448,
-
- GOSSIP_TEXTID_SQUIRE = 14407
-};
-
-#define GOSSIP_SQUIRE_ITEM_1 "I am ready to fight!"
-#define GOSSIP_SQUIRE_ITEM_2 "How do the Argent Crusader raiders fight?"
-
-class npc_squire_david : public CreatureScript
-{
-public:
- npc_squire_david() : CreatureScript("npc_squire_david") { }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (player->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_H) == QUEST_STATUS_INCOMPLETE ||
- player->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_A) == QUEST_STATUS_INCOMPLETE)//We need more info about it.
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
- }
-
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SQUIRE, creature->GetGUID());
- return true;
- }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- {
- player->CLOSE_GOSSIP_MENU();
- creature->SummonCreature(NPC_ARGENT_VALIANT, 8575.451f, 952.472f, 547.554f, 0.38f);
- }
- return true;
- }
-};
-
-/*######
## npc_argent_valiant
######*/
@@ -837,7 +790,6 @@ class npc_frostbrood_skytalon : public CreatureScript
void AddSC_icecrown()
{
- new npc_squire_david;
new npc_argent_valiant;
new npc_guardian_pavilion;
new npc_tournament_training_dummy;
diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h
index c2dd71ce7cf..77a7c338118 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(WorldPackets::WorldState::InitWorldStates& packet);
+ void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override;
- bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
+ bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override;
int32 HandleOpenGo(Player* player, GameObject* go) override;
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_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
index fb44a403d86..dfc5f5992a6 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
@@ -108,6 +108,7 @@ class boss_grand_warlock_nethekurse : public CreatureScript
void Reset() override
{
+ _Reset();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Initialize();
@@ -115,9 +116,8 @@ class boss_grand_warlock_nethekurse : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
+ _JustDied();
Talk(SAY_DIE);
-
- instance->SetBossState(DATA_NETHEKURSE, DONE);
}
void SetData(uint32 data, uint32 value) override
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
index 7d00cd97126..a950882eddd 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
@@ -160,6 +160,7 @@ class boss_warbringer_omrogg : public CreatureScript
void Reset() override
{
+ _Reset();
if (Unit* LeftHead = ObjectAccessor::GetUnit(*me, LeftHeadGUID))
{
LeftHead->setDeathState(JUST_DIED);
@@ -257,14 +258,14 @@ class boss_warbringer_omrogg : public CreatureScript
Creature* LeftHead = ObjectAccessor::GetCreature(*me, LeftHeadGUID);
Creature* RightHead = ObjectAccessor::GetCreature(*me, RightHeadGUID);
+ _JustDied();
+
if (!LeftHead || !RightHead)
return;
LeftHead->AI()->Talk(YELL_DIE_L);
RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL);
-
- instance->SetBossState(DATA_OMROGG, DONE);
}
void UpdateAI(uint32 diff) override
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 b44ae46c78c..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
@@ -35,7 +35,10 @@ enum Says
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
- SAY_DEATH = 2
+ SAY_DEATH = 2,
+
+ SAY_CALL_EXECUTIONER_A = 3,
+ SAY_CALL_EXECUTIONER_H = 4
};
enum Spells
@@ -84,10 +87,28 @@ class boss_warchief_kargath_bladefist : public CreatureScript
resetcheck_timer = 5000;
}
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_EXECUTIONER_TAUNT)
+ {
+ switch (instance->GetData(DATA_TEAM_IN_INSTANCE))
+ {
+ case ALLIANCE:
+ Talk(SAY_CALL_EXECUTIONER_A);
+ break;
+ case HORDE:
+ Talk(SAY_CALL_EXECUTIONER_H);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
void Reset() override
{
removeAdds();
-
+ _Reset();
me->SetSpeed(MOVE_RUN, 2);
me->SetWalk(false);
@@ -96,10 +117,9 @@ class boss_warchief_kargath_bladefist : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
+ _JustDied();
Talk(SAY_DEATH);
removeAdds();
-
- instance->SetBossState(DATA_KARGATH, DONE);
}
void EnterCombat(Unit* /*who*/) override
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 c6b08bdada1..a781861d47f 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
@@ -26,6 +26,18 @@ EndScriptData */
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "shattered_halls.h"
+#include "Player.h"
+#include "SpellAuras.h"
+#include "CreatureAI.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+
+DoorData const doorData[] =
+{
+ { 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
{
@@ -43,6 +55,41 @@ class instance_shattered_halls : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
+ LoadDoorData(doorData);
+ executionTimer = 0;
+ executed = 0;
+ _team = 0;
+ }
+
+ void OnPlayerEnter(Player* player) override
+ {
+ Aura* ex = nullptr;
+
+ if (!_team)
+ _team = player->GetTeam();
+
+ player->CastSpell(player, SPELL_REMOVE_KARGATH_EXECUTIONER, true);
+
+ if (!executionTimer || executionerGUID.IsEmpty())
+ return;
+
+ switch (executed)
+ {
+ case 0:
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_1, player);
+ break;
+ case 1:
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_2, player);
+ break;
+ case 2:
+ ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_3, player);
+ break;
+ default:
+ break;
+ }
+
+ if (ex)
+ ex->SetDuration(executionTimer);
}
void OnGameObjectCreate(GameObject* go) override
@@ -50,21 +97,65 @@ class instance_shattered_halls : public InstanceMapScript
switch (go->GetEntry())
{
case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
- nethekurseDoor1GUID = go->GetGUID();
+ case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
+ AddDoor(go, true);
+ default:
break;
+ }
+ }
+
+ void OnGameObjectRemove(GameObject* go) override
+ {
+ switch (go->GetEntry())
+ {
+ case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
- nethekurseDoor2GUID = go->GetGUID();
+ AddDoor(go, false);
+ default:
break;
}
}
void OnCreatureCreate(Creature* creature) override
{
+ if (!_team)
+ {
+ Map::PlayerList const &players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->GetSource())
+ _team = player->GetTeam();
+ }
+
switch (creature->GetEntry())
{
case NPC_GRAND_WARLOCK_NETHEKURSE:
nethekurseGUID = creature->GetGUID();
break;
+ case NPC_KARGATH_BLADEFIST:
+ kargathGUID = creature->GetGUID();
+ break;
+ case NPC_RANDY_WHIZZLESPROCKET:
+ if (_team == HORDE)
+ creature->UpdateEntry(NPC_DRISELLA);
+ break;
+ case NPC_SHATTERED_EXECUTIONER:
+ executionTimer = 55 * MINUTE * IN_MILLISECONDS;
+ 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;
}
}
@@ -75,18 +166,18 @@ class instance_shattered_halls : public InstanceMapScript
switch (type)
{
- case DATA_NETHEKURSE:
- if (state == IN_PROGRESS)
- {
- HandleGameObject(nethekurseDoor1GUID, false);
- HandleGameObject(nethekurseDoor2GUID, false);
- }
- else
+ case DATA_SHATTERED_EXECUTIONER:
+ if (state == DONE)
{
- HandleGameObject(nethekurseDoor1GUID, true);
- HandleGameObject(nethekurseDoor2GUID, true);
+ DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
+ executionTimer = 0;
+ SaveToDB();
}
break;
+ case DATA_KARGATH:
+ if (Creature* executioner = instance->GetCreature(executionerGUID))
+ executioner->AI()->Reset(); // trigger removal of IMMUNE_TO_PC flag
+ break;
case DATA_OMROGG:
break;
}
@@ -99,24 +190,120 @@ class instance_shattered_halls : public InstanceMapScript
{
case NPC_GRAND_WARLOCK_NETHEKURSE:
return nethekurseGUID;
- break;
- case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
- return nethekurseDoor1GUID;
- break;
- case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
- return nethekurseDoor2GUID;
- break;
+ case NPC_KARGATH_BLADEFIST:
+ return kargathGUID;
+ case NPC_SHATTERED_EXECUTIONER:
+ return executionerGUID;
+ case DATA_FIRST_PRISONER:
+ case DATA_SECOND_PRISONER:
+ case DATA_THIRD_PRISONER:
+ return victimsGUID[data - DATA_FIRST_PRISONER];
+ default:
+ return ObjectGuid::Empty;
}
- return ObjectGuid::Empty;
}
- protected:
+ void WriteSaveDataMore(std::ostringstream& data) override
+ {
+ if (!instance->IsHeroic())
+ return;
+
+ data << uint32(executed) << ' '
+ << executionTimer << ' ';
+ }
+
+ void ReadSaveDataMore(std::istringstream& data) override
+ {
+ if (!instance->IsHeroic())
+ return;
+
+ uint32 readbuff;
+ data >> readbuff;
+ executed = uint8(readbuff);
+ data >> readbuff;
+
+ if (executed > VictimCount)
+ {
+ executed = VictimCount;
+ executionTimer = 0;
+ return;
+ }
+
+ if (!readbuff)
+ return;
+
+ Creature* executioner = nullptr;
+
+ instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
+ if (Creature* kargath = instance->GetCreature(kargathGUID))
+ if (executionerGUID.IsEmpty())
+ executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
+
+ if (executioner)
+ for (uint8 i = executed; i < VictimCount; ++i)
+ executioner->SummonCreature(executionerVictims[i](GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
+
+ executionTimer = readbuff;
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_PRISONERS_EXECUTED:
+ return executed;
+ case DATA_TEAM_IN_INSTANCE:
+ return _team;
+ default:
+ return 0;
+ }
+ }
+
+ void Update(uint32 diff) override
+ {
+ if (!executionTimer)
+ return;
+
+ if (executionTimer <= diff)
+ {
+ DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
+ switch (++executed)
+ {
+ case 1:
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_2);
+ executionTimer = 10 * MINUTE * IN_MILLISECONDS;
+ break;
+ case 2:
+ DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_3);
+ executionTimer = 15 * MINUTE * IN_MILLISECONDS;
+ break;
+ default:
+ executionTimer = 0;
+ break;
+ }
+
+ if (Creature* executioner = instance->GetCreature(executionerGUID))
+ executioner->AI()->SetData(DATA_PRISONERS_EXECUTED, executed);
+
+ SaveToDB();
+ }
+ else
+ executionTimer -= diff;
+ }
+
+ private:
ObjectGuid nethekurseGUID;
- ObjectGuid nethekurseDoor1GUID;
- ObjectGuid nethekurseDoor2GUID;
+ ObjectGuid kargathGUID;
+ ObjectGuid executionerGUID;
+ ObjectGuid victimsGUID[3];
+
+ uint8 executed;
+ uint32 executionTimer;
+ uint32 _team;
};
};
+
void AddSC_instance_shattered_halls()
{
new instance_shattered_halls();
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..d31fa4c4f09
--- /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*, bool /*entered*/) 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 90cbbe2a438..894cc9c40a6 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
@@ -21,18 +21,45 @@
#define DataHeader "SH"
-uint32 const EncounterCount = 3;
+uint32 const EncounterCount = 4;
+uint32 const VictimCount = 3;
enum DataTypes
{
- DATA_NETHEKURSE = 1,
- DATA_OMROGG = 2,
- DATA_KARGATH = 3
+ DATA_NETHEKURSE = 0,
+ DATA_OMROGG = 1,
+ DATA_KARGATH = 2,
+
+ DATA_SHATTERED_EXECUTIONER = 3,
+ DATA_PRISONERS_EXECUTED = 4,
+
+ DATA_TEAM_IN_INSTANCE = 5,
+
+ DATA_FIRST_PRISONER,
+ DATA_SECOND_PRISONER,
+ DATA_THIRD_PRISONER
};
enum CreatureIds
{
- NPC_GRAND_WARLOCK_NETHEKURSE = 16807
+ NPC_GRAND_WARLOCK_NETHEKURSE = 16807,
+ NPC_KARGATH_BLADEFIST = 16808,
+
+ NPC_SHATTERED_EXECUTIONER = 17301,
+
+ // Alliance Ids
+ NPC_RANDY_WHIZZLESPROCKET = 17288,
+
+ NPC_CAPTAIN_ALINA = 17290,
+ NPC_ALLIANCE_VICTIM_1 = 17289,
+ NPC_ALLIANCE_VICTIM_2 = 17292,
+
+ // Horde Ids
+ NPC_DRISELLA = 17294,
+
+ NPC_CAPTAIN_BONESHATTER = 17296,
+ NPC_HORDE_VICTIM_1 = 17295,
+ NPC_HORDE_VICTIM_2 = 17297
};
enum GameobjectIds
@@ -41,4 +68,47 @@ enum GameobjectIds
GO_GRAND_WARLOCK_CHAMBER_DOOR_2 = 182540
};
+enum QuestIds
+{
+ QUEST_IMPRISONED_A = 9524,
+ 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
+{
+ 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 Position const& GetPos() const { return _spawnPos; }
+
+private:
+ const uint32 _allianceNPC;
+ const uint32 _hordeNPC;
+ const Position _spawnPos;
+};
+
+const FactionSpawnerHelper executionerVictims[VictimCount] =
+{
+ { NPC_CAPTAIN_ALINA, NPC_CAPTAIN_BONESHATTER, { 138.8807f, -84.22707f, 1.992269f, 0.06981317f } },
+ { NPC_ALLIANCE_VICTIM_1, NPC_HORDE_VICTIM_1, { 151.2411f, -91.02930f, 2.019741f, 1.57079600f } },
+ { NPC_ALLIANCE_VICTIM_2, NPC_HORDE_VICTIM_2, { 151.0459f, -77.51981f, 2.021008f, 4.74729500f } }
+};
+
+
#endif
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 b3324980bd4..c8e3e57ac3b 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 38ccf33a612..3eae867b86c 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
@@ -352,7 +344,7 @@ 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..29504166846 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* 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
@@ -16,13 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Void_Reaver
-SD%Complete: 90
-SDComment: Should reset if raid are out of room.
-SDCategory: Tempest Keep, The Eye
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "the_eye.h"
@@ -43,48 +35,35 @@ enum Spells
SPELL_BERSERK = 27680
};
+enum Events
+{
+ EVENT_POUNDING = 1,
+ EVENT_ARCANE_ORB,
+ EVENT_KNOCK_AWAY,
+ EVENT_BERSERK
+};
+
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()
{
- Pounding_Timer = 15000;
- ArcaneOrb_Timer = 3000;
- KnockAway_Timer = 30000;
- Berserk_Timer = 600000;
-
Enraged = false;
}
- InstanceScript* instance;
-
- uint32 Pounding_Timer;
- uint32 ArcaneOrb_Timer;
- uint32 KnockAway_Timer;
- uint32 Berserk_Timer;
-
- bool Enraged;
-
void Reset() override
{
Initialize();
-
- if (me->IsAlive())
- instance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED);
+ _Reset();
}
void KilledUnit(Unit* /*victim*/) override
@@ -96,82 +75,91 @@ class boss_void_reaver : public CreatureScript
{
Talk(SAY_DEATH);
DoZoneInCombat();
-
- instance->SetData(DATA_VOIDREAVEREVENT, DONE);
+ _JustDied();
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
+ _EnterCombat();
- instance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS);
+ events.ScheduleEvent(EVENT_POUNDING, 15000);
+ events.ScheduleEvent(EVENT_ARCANE_ORB, 3000);
+ events.ScheduleEvent(EVENT_KNOCK_AWAY, 30000);
+ events.ScheduleEvent(EVENT_BERSERK, 600000);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
- // Pounding
- if (Pounding_Timer <= diff)
- {
- DoCastVictim(SPELL_POUNDING);
- Talk(SAY_POUNDING);
- Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000)
- }
- else
- Pounding_Timer -= diff;
- // Arcane Orb
- if (ArcaneOrb_Timer <= diff)
- {
- Unit* target = NULL;
- std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
- std::vector<Unit*> target_list;
- for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
- {
- target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
- if (!target)
- continue;
- // exclude pets & totems, 18 yard radius minimum
- if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false))
- target_list.push_back(target);
- target = NULL;
- }
- if (!target_list.empty())
- target = *(target_list.begin() + rand32() % target_list.size());
- else
- target = me->GetVictim();
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (target)
- me->CastSpell(target, SPELL_ARCANE_ORB, false, NULL, NULL);
- ArcaneOrb_Timer = 3000;
- }
- else
- ArcaneOrb_Timer -= diff;
- // Single Target knock back, reduces aggro
- if (KnockAway_Timer <= diff)
+ while (uint32 eventId = events.ExecuteEvent())
{
- DoCastVictim(SPELL_KNOCK_AWAY);
- //Drop 25% aggro
- if (DoGetThreat(me->GetVictim()))
- DoModifyThreatPercent(me->GetVictim(), -25);
- KnockAway_Timer = 30000;
- }
- else
- KnockAway_Timer -= diff;
- //Berserk
- if (Berserk_Timer < diff && !Enraged)
- {
- DoCast(me, SPELL_BERSERK);
- Enraged = true;
+ switch (eventId)
+ {
+ case EVENT_POUNDING:
+ DoCastVictim(SPELL_POUNDING);
+ Talk(SAY_POUNDING);
+ events.ScheduleEvent(EVENT_POUNDING, 15000);
+ break;
+ case EVENT_ARCANE_ORB:
+ {
+ Unit* target = NULL;
+ std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
+ std::vector<Unit*> target_list;
+ for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr)
+ {
+ target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
+ if (!target)
+ continue;
+ // exclude pets & totems, 18 yard radius minimum
+ if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false))
+ target_list.push_back(target);
+ target = NULL;
+ }
+
+ if (!target_list.empty())
+ target = *(target_list.begin() + rand32() % target_list.size());
+ else
+ target = me->GetVictim();
+
+ if (target)
+ me->CastSpell(target, SPELL_ARCANE_ORB, false, NULL, NULL);
+
+ events.ScheduleEvent(EVENT_ARCANE_ORB, 3000);
+ break;
+ }
+ case EVENT_KNOCK_AWAY:
+ DoCastVictim(SPELL_KNOCK_AWAY);
+ // Drop 25% aggro
+ if (DoGetThreat(me->GetVictim()))
+ DoModifyThreatPercent(me->GetVictim(), -25);
+
+ events.ScheduleEvent(EVENT_KNOCK_AWAY, 30000);
+ break;
+ case EVENT_BERSERK:
+ if (!Enraged)
+ {
+ DoCast(me, SPELL_BERSERK);
+ Enraged = true;
+ }
+ break;
+ default:
+ break;
+ }
}
- else
- Berserk_Timer -= diff;
DoMeleeAttackIfReady();
EnterEvadeIfOutOfCombatArea(diff);
}
+
+ private:
+ bool Enraged;
};
CreatureAI* GetAI(Creature* creature) const 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/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index f3c8396832c..87bd5923c8f 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -338,7 +338,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 +374,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 +855,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 +898,7 @@ class spell_q12659_ahunaes_knife : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q12659_ahunaes_knife_SpellScript();
- };
+ }
};
enum StoppingTheSpread
@@ -944,7 +944,7 @@ class spell_q9874_liquid_fire : public SpellScriptLoader
SpellScript* GetSpellScript() const override
{
return new spell_q9874_liquid_fire_SpellScript();
- };
+ }
};
enum SalvagingLifesStength
@@ -988,7 +988,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/Common.h b/src/server/shared/Common.h
index dc9e948966d..e83340bdd84 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -38,6 +38,7 @@
#include <queue>
#include <sstream>
#include <algorithm>
+#include <memory>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
@@ -164,4 +165,14 @@ struct LocalizedString
template <typename T>
using Optional = boost::optional<T>;
+namespace Trinity
+{
+ //! std::make_unique implementation (TODO: remove this once C++14 is supported)
+ template<typename T, typename ...Args>
+ std::unique_ptr<T> make_unique(Args&& ...args)
+ {
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ }
+}
+
#endif
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/Cryptography/SHA256.h b/src/server/shared/Cryptography/SHA256.h
index 659236f9495..1d85545b2e0 100644
--- a/src/server/shared/Cryptography/SHA256.h
+++ b/src/server/shared/Cryptography/SHA256.h
@@ -38,8 +38,8 @@ class SHA256Hash
void Initialize();
void Finalize();
- uint8 *GetDigest(void) { return mDigest; };
- int GetLength(void) const { return SHA256_DIGEST_LENGTH; };
+ uint8 *GetDigest(void) { return mDigest; }
+ int GetLength(void) const { return SHA256_DIGEST_LENGTH; }
private:
SHA256_CTX mC;
diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h
index 4ce77c1cd28..c541a6651a3 100644
--- a/src/server/shared/DataStores/DB2Store.h
+++ b/src/server/shared/DataStores/DB2Store.h
@@ -112,6 +112,8 @@ public:
void EraseRecord(uint32 id) override { if (id < _indexTableSize) _indexTable.AsT[id] = nullptr; }
T const* LookupEntry(uint32 id) const { return (id >= _indexTableSize) ? nullptr : _indexTable.AsT[id]; }
+ T const* AssertEntry(uint32 id) const { return ASSERT_NOTNULL(LookupEntry(id)); }
+
std::string const& GetFileName() const { return _fileName; }
uint32 GetNumRows() const { return _indexTableSize; }
char const* GetFormat() const { return _format; }
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 6c18a0e76ee..277ccd4569a 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -681,4 +681,21 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE, "UPDATE quest_tracker SET completed_by_gm = 1 WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_QUEST_TRACK_COMPLETE_TIME, "UPDATE quest_tracker SET quest_complete_time = NOW() WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_QUEST_TRACK_ABANDON_TIME, "UPDATE quest_tracker SET quest_abandon_time = NOW() WHERE id = ? AND character_guid = ? ORDER BY quest_accept_time DESC LIMIT 1", CONNECTION_ASYNC);
+
+ // Garrison
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON, "SELECT siteLevelId, followerActivationsRemainingToday FROM character_garrison WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON, "INSERT INTO character_garrison (guid, siteLevelId, followerActivationsRemainingToday) VALUES (?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_GARRISON, "DELETE FROM character_garrison WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS, "UPDATE character_garrison SET followerActivationsRemainingToday = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, "SELECT buildingId FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, "INSERT INTO character_garrison_blueprints (guid, buildingId) VALUES (?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, "DELETE FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS, "INSERT INTO character_garrison_buildings (guid, plotInstanceId, buildingId, timeBuilt, active) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, "DELETE FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS, "SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS, "INSERT INTO character_garrison_followers (dbId, guid, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS, "DELETE gfab, gf FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE gf.guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "SELECT gfab.dbId, gfab.abilityId FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE guid = ? ORDER BY gfab.slot", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "INSERT INTO character_garrison_follower_abilities (dbId, abilityId, slot) VALUES (?, ?, ?)", CONNECTION_ASYNC);
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index ed3b6dd8098..fc9c930e6b1 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -598,6 +598,22 @@ enum CharacterDatabaseStatements
CHAR_UPD_QUEST_TRACK_COMPLETE_TIME,
CHAR_UPD_QUEST_TRACK_ABANDON_TIME,
+ CHAR_SEL_CHARACTER_GARRISON,
+ CHAR_INS_CHARACTER_GARRISON,
+ CHAR_DEL_CHARACTER_GARRISON,
+ CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS,
+ CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS,
+ CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS,
+ CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS,
+ CHAR_SEL_CHARACTER_GARRISON_BUILDINGS,
+ CHAR_INS_CHARACTER_GARRISON_BUILDINGS,
+ CHAR_DEL_CHARACTER_GARRISON_BUILDINGS,
+ CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS,
+ CHAR_INS_CHARACTER_GARRISON_FOLLOWERS,
+ CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS,
+ CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
+ CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
+
MAX_CHARACTERDATABASE_STATEMENTS
};
diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.cpp b/src/server/shared/Database/Implementation/HotfixDatabase.cpp
index e13863d9326..a7043b1d5ff 100644
--- a/src/server/shared/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/shared/Database/Implementation/HotfixDatabase.cpp
@@ -39,12 +39,70 @@ void HotfixDatabaseConnection::DoPrepareStatements()
PREPARE_LOCALE_STMT(HOTFIX_SEL_BROADCAST_TEXT, "SELECT ID, MaleText_lang, FemaleText_lang FROM broadcast_text_locale WHERE locale = ?", CONNECTION_SYNCH);
// CurrencyTypes.db2
- PrepareStatement(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, CategoryID, Name, InventoryIcon1, InventoryIcon2, SpellWeight, SpellCategory, MaxQty, MaxEarnablePerWeek, Flags, Quality, Description FROM currency_types ORDER BY ID DESC", CONNECTION_SYNCH);
- PREPARE_LOCALE_STMT(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, Name_lang, InventoryIcon1_lang, InventoryIcon2_lang, Description_lang FROM currency_types_locale WHERE locale = ?", CONNECTION_SYNCH);
+ PrepareStatement(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, CategoryID, Name, InventoryIcon1, InventoryIcon2, SpellWeight, SpellCategory, "
+ "MaxQty, MaxEarnablePerWeek, Flags, Quality, Description FROM currency_types ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, Name_lang, InventoryIcon1_lang, InventoryIcon2_lang, "
+ "Description_lang FROM currency_types_locale WHERE locale = ?", CONNECTION_SYNCH);
// CurvePoint.db2
PrepareStatement(HOTFIX_SEL_CURVE_POINT, "SELECT ID, CurveID, `Index`, X, Y FROM curve_point ORDER BY ID DESC", CONNECTION_SYNCH);
+ // GameObjects.db2
+ PrepareStatement(HOTFIX_SEL_GAMEOBJECTS, "SELECT ID, MapID, DisplayID, PositionX, PositionY, PositionZ, RotationX, RotationY, RotationZ, RotationW, Size, "
+ "PhaseUseFlags, PhaseID, PhaseGroupID, Type, Data0, Data1, Data2, Data3, Data4, Data5, Data6, Data7, Name FROM gameobjects ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GAMEOBJECTS, "SELECT ID, Name_lang FROM gameobjects_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrAbility.db2
+ PrepareStatement(HOTFIX_SEL_GARR_ABILITY, "SELECT ID, Flags, Name, Description, IconFileDataID, OtherFactionGarrAbilityID, "
+ "GarrAbilityCategoryID FROM garr_ability ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_ABILITY, "SELECT ID, Name_lang, Description_lang FROM garr_ability_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrBuilding.db2
+ PrepareStatement(HOTFIX_SEL_GARR_BUILDING, "SELECT ID, HordeGameObjectID, AllianceGameObjectID, Unknown, Type, Level, NameAlliance, NameHorde, Description, "
+ "Tooltip, BuildDuration, CostCurrencyID, CostCurrencyAmount, HordeTexPrefixKitID, AllianceTexPrefixKitID, IconFileDataID, BonusAmount, Flags, "
+ "AllianceActivationScenePackageID, HordeActivationScenePackageID, MaxShipments, FollowerRequiredGarrAbilityID, FollowerGarrAbilityEffectID, CostMoney "
+ "FROM garr_building ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_BUILDING, "SELECT ID, NameAlliance_lang, NameHorde_lang, Description_lang, Tooltip_lang "
+ "FROM garr_building_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrBuildingPlotInst.db2
+ PrepareStatement(HOTFIX_SEL_GARR_BUILDING_PLOT_INST, "SELECT ID, GarrBuildingID, UiTextureAtlasMemberID, GarrSiteLevelPlotInstID, "
+ "LandmarkOffsetX, LandmarkOffsetY FROM garr_building_plot_inst ORDER BY ID DESC", CONNECTION_SYNCH);
+
+ // GarrClassSpec.db2
+ PrepareStatement(HOTFIX_SEL_GARR_CLASS_SPEC, "SELECT ID, NameMale, NameFemale, NameGenderless, ClassAtlasID, GarrFollItemSetID "
+ "FROM garr_class_spec ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_CLASS_SPEC, "SELECT ID, NameMale_lang, NameFemale_lang, NameGenderless_lang FROM garr_class_spec_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrFollower.db2
+ PrepareStatement(HOTFIX_SEL_GARR_FOLLOWER, "SELECT ID, HordeCreatureID, AllianceCreatureID, HordeUiAnimRaceInfoID, AllianceUiAnimRaceInfoID, Quality, "
+ "HordeGarrClassSpecID, AllianceGarrClassSpecID, HordeGarrFollItemSetID, AllianceGarrFollItemSetID, Level, ItemLevelWeapon, ItemLevelArmor, Unknown1, Flags, "
+ "HordeSourceText, AllianceSourceText, Unknown2, Unknown3, HordePortraitIconID, AlliancePortraitIconID FROM garr_follower ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_FOLLOWER, "SELECT ID, HordeSourceText_lang, AllianceSourceText_lang FROM garr_follower_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrFollowerXAbility.db2
+ PrepareStatement(HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY, "SELECT ID, GarrFollowerID, GarrAbilityID, FactionIndex FROM garr_follower_x_ability ORDER BY ID DESC", CONNECTION_SYNCH);
+
+ // GarrPlot.db2
+ PrepareStatement(HOTFIX_SEL_GARR_PLOT, "SELECT ID, GarrPlotUICategoryID, PlotType, Flags, Name, MinCount, MaxCount, "
+ "AllianceConstructionGameObjectID, HordeConstructionGameObjectID FROM garr_plot ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_PLOT, "SELECT ID, Name_lang FROM garr_plot_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrPlotBuilding.db2
+ PrepareStatement(HOTFIX_SEL_GARR_PLOT_BUILDING, "SELECT ID, GarrPlotID, GarrBuildingID FROM garr_plot_building ORDER BY ID DESC", CONNECTION_SYNCH);
+
+ // GarrPlotInstance.db2
+ PrepareStatement(HOTFIX_SEL_GARR_PLOT_INSTANCE, "SELECT ID, GarrPlotID, Name FROM garr_plot_instance ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_PLOT_INSTANCE, "SELECT ID, Name_lang FROM garr_plot_instance_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrSiteLevel.db2
+ PrepareStatement(HOTFIX_SEL_GARR_SITE_LEVEL, "SELECT ID, Level, MapID, SiteID, UITextureKitID, TownHallX, TownHallY, MovieID, Level2, "
+ "UpgradeResourceCost, UpgradeMoneyCost FROM garr_site_level ORDER BY ID DESC", CONNECTION_SYNCH);
+
+ // GarrSiteLevelPlotInst.db2
+ PrepareStatement(HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST, "SELECT ID, GarrSiteLevelID, GarrPlotInstanceID, LandmarkX, LandmarkY, "
+ "Unknown FROM garr_site_level_plot_inst ORDER BY ID DESC", CONNECTION_SYNCH);
+
// Holidays.db2
PrepareStatement(HOTFIX_SEL_HOLIDAYS, "SELECT ID, Duration1, Duration2, Duration3, Duration4, Duration5, Duration6, Duration7, Duration8, Duration9, Duration10, "
"Date1, Date2, Date3, Date4, Date5, Date6, Date7, Date8, Date9, Date10, Date11, Date12, Date13, Date14, Date15, Date16, Region, Looping, "
diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.h b/src/server/shared/Database/Implementation/HotfixDatabase.h
index 3d8e528cd98..4adf555dc2f 100644
--- a/src/server/shared/Database/Implementation/HotfixDatabase.h
+++ b/src/server/shared/Database/Implementation/HotfixDatabase.h
@@ -54,6 +54,37 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_CURVE_POINT,
+ HOTFIX_SEL_GAMEOBJECTS,
+ HOTFIX_SEL_GAMEOBJECTS_LOCALE,
+
+ HOTFIX_SEL_GARR_ABILITY,
+ HOTFIX_SEL_GARR_ABILITY_LOCALE,
+
+ HOTFIX_SEL_GARR_BUILDING,
+ HOTFIX_SEL_GARR_BUILDING_LOCALE,
+
+ HOTFIX_SEL_GARR_BUILDING_PLOT_INST,
+
+ HOTFIX_SEL_GARR_CLASS_SPEC,
+ HOTFIX_SEL_GARR_CLASS_SPEC_LOCALE,
+
+ HOTFIX_SEL_GARR_FOLLOWER,
+ HOTFIX_SEL_GARR_FOLLOWER_LOCALE,
+
+ HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY,
+
+ HOTFIX_SEL_GARR_PLOT,
+ HOTFIX_SEL_GARR_PLOT_LOCALE,
+
+ HOTFIX_SEL_GARR_PLOT_BUILDING,
+
+ HOTFIX_SEL_GARR_PLOT_INSTANCE,
+ HOTFIX_SEL_GARR_PLOT_INSTANCE_LOCALE,
+
+ HOTFIX_SEL_GARR_SITE_LEVEL,
+
+ HOTFIX_SEL_GARR_SITE_LEVEL_PLOT_INST,
+
HOTFIX_SEL_HOLIDAYS,
HOTFIX_SEL_HOLIDAYS_LOCALE,
@@ -86,7 +117,7 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_OVERRIDE_SPELL_DATA,
HOTFIX_SEL_PHASE_GROUP,
-
+
HOTFIX_SEL_QUEST_PACKAGE_ITEM,
HOTFIX_SEL_SOUND_ENTRIES,
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index 70350f3136c..0b2967f8922 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -46,7 +46,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_INS_IP_BANNED, "INSERT INTO ip_banned (ip, bandate, unbandate, bannedby, banreason) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_IP_NOT_BANNED, "DELETE FROM ip_banned WHERE ip = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_ACCOUNT_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?, 1)", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED, "UPDATE account_banned SET active = 0 WHERE id = ? AND active != 0", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED, "UPDATE account_banned SET unbandate = UNIX_TIMESTAMP(), active = 0 WHERE id = ? AND active != 0", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM, "DELETE FROM realmcharacters WHERE acctid = ? AND realmid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC);
@@ -124,7 +124,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_EMAIL_BY_ID, "SELECT email FROM battlenet_accounts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL, "SELECT id FROM battlenet_accounts WHERE email = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_PASSWORD, "UPDATE battlenet_accounts SET v = '', s = '', sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_BNET_CHECK_PASSWORD, "SELECT 1 FROM battlenet_accounts WHERE id = ? AND sha_pass_hash = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_SEL_BNET_CHECK_PASSWORD, "SELECT 1 FROM battlenet_accounts WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK, "UPDATE battlenet_accounts SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY, "UPDATE battlenet_accounts SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT, "SELECT battlenet_account FROM account WHERE id = ?", CONNECTION_SYNCH);
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index f8f641a9ea7..e50cf42e439 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -61,6 +61,7 @@ HANDLE WheatyExceptionReport::m_hDumpFile;
HANDLE WheatyExceptionReport::m_hProcess;
SymbolPairs WheatyExceptionReport::symbols;
std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails;
+bool WheatyExceptionReport::stackOverflowException;
// Declare global instance of class
WheatyExceptionReport g_WheatyExceptionReport;
@@ -72,6 +73,7 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor
// Install the unhandled exception filter function
m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter);
m_hProcess = GetCurrentProcess();
+ stackOverflowException = false;
if (!IsDebuggerPresent())
{
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
@@ -97,6 +99,9 @@ WheatyExceptionReport::~WheatyExceptionReport()
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo)
{
+ 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 +424,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 +1325,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..101b6187f2b 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,7 @@ class WheatyExceptionReport
static HANDLE m_hProcess;
static SymbolPairs symbols;
static std::stack<SymbolDetail> symbolDetails;
+ static bool stackOverflowException;
static char* PushSymbolDetail(char* pszCurrBuffer);
static char* PopSymbolDetail(char* pszCurrBuffer);
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index e22a06e635e..5b3782fce55 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -23,6 +23,7 @@
#include "Appender.h"
#include "Logger.h"
#include "StringFormat.h"
+#include "Common.h"
#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
@@ -64,7 +65,7 @@ class Log
template<typename... Args>
inline void outMessage(std::string const& filter, LogLevel const level, const char* fmt, Args const&... args)
{
- write(std::unique_ptr<LogMessage>(new LogMessage(level, filter, Trinity::StringFormat(fmt, args...))));
+ write(Trinity::make_unique<LogMessage>(level, filter, Trinity::StringFormat(fmt, args...)));
}
template<typename... Args>
@@ -73,7 +74,7 @@ class Log
if (!ShouldLog("commands.gm", LOG_LEVEL_INFO))
return;
- std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, "commands.gm", std::move(Trinity::StringFormat(fmt, args...))));
+ std::unique_ptr<LogMessage> msg = Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm", std::move(Trinity::StringFormat(fmt, args...)));
msg->param1 = std::to_string(account);
diff --git a/src/server/shared/Networking/MessageBuffer.h b/src/server/shared/Networking/MessageBuffer.h
index 802442b5c31..d0c65f05c3d 100644
--- a/src/server/shared/Networking/MessageBuffer.h
+++ b/src/server/shared/Networking/MessageBuffer.h
@@ -55,9 +55,9 @@ public:
uint8* GetBasePointer() { return _storage.data(); }
- uint8* GetReadPointer() { return &_storage[_rpos]; }
+ uint8* GetReadPointer() { return GetBasePointer() + _rpos; }
- uint8* GetWritePointer() { return &_storage[_wpos]; }
+ uint8* GetWritePointer() { return GetBasePointer() + _wpos; }
void ReadCompleted(size_type bytes) { _rpos += bytes; }
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 9806151b4c4..10c8c163ec4 100644
--- a/src/server/shared/Updater/DBUpdater.cpp
+++ b/src/server/shared/Updater/DBUpdater.cpp
@@ -381,8 +381,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/Main.cpp b/src/server/worldserver/Main.cpp
index d4a6915894d..e39ccb3c98f 100644
--- a/src/server/worldserver/Main.cpp
+++ b/src/server/worldserver/Main.cpp
@@ -111,11 +111,11 @@ extern int main(int argc, char** argv)
#ifdef _WIN32
if (configService.compare("install") == 0)
- return WinServiceInstall() == true ? 0 : 1;
+ return WinServiceInstall() ? 0 : 1;
else if (configService.compare("uninstall") == 0)
- return WinServiceUninstall() == true ? 0 : 1;
+ return WinServiceUninstall() ? 0 : 1;
else if (configService.compare("run") == 0)
- WinServiceRun();
+ return WinServiceRun() ? 0 : 0;
#endif
std::string configError;
@@ -613,11 +613,13 @@ variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile
store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), vm);
notify(vm);
}
- catch (std::exception& e) {
+ catch (std::exception& e)
+ {
std::cerr << e.what() << "\n";
}
- if (vm.count("help")) {
+ if (vm.count("help"))
+ {
std::cout << all << "\n";
}
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index c59b845e454..668cec43aca 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1018,7 +1018,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/System.cpp b/src/tools/map_extractor/System.cpp
index ab9774a3038..9059867dce4 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -402,7 +402,7 @@ void ReadLiquidTypeTableDBC()
// Map file format data
static char const* MAP_MAGIC = "MAPS";
-static char const* MAP_VERSION_MAGIC = "v1.4";
+static char const* MAP_VERSION_MAGIC = "v1.5";
static char const* MAP_AREA_MAGIC = "AREA";
static char const* MAP_HEIGHT_MAGIC = "MHGT";
static char const* MAP_LIQUID_MAGIC = "MLIQ";
@@ -1091,7 +1091,7 @@ void ExtractMaps(uint32 build)
continue;
sprintf(storagePath, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
- sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
+ sprintf(output_filename, "%s/maps/%04u_%02u_%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(storagePath, output_filename, y, x, build);
sprintf(storagePath, "World\\Maps\\%s\\%s_%u_%u_obj0.adt", map_ids[z].name, map_ids[z].name, x, y);
diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt
index 48e30b1c3cf..4dfe106bd3e 100644
--- a/src/tools/mmaps_generator/CMakeLists.txt
+++ b/src/tools/mmaps_generator/CMakeLists.txt
@@ -12,7 +12,7 @@ file(GLOB_RECURSE mmap_gen_sources *.cpp *.h)
set(mmap_gen_Includes
${CMAKE_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/dep/libmpq
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
${CMAKE_SOURCE_DIR}/dep/zlib
${CMAKE_SOURCE_DIR}/dep/bzip2
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
@@ -30,13 +30,6 @@ set(mmap_gen_Includes
${CMAKE_SOURCE_DIR}/src/server/collision/Models
)
-if( WIN32 )
- set(mmap_gen_Includes
- ${mmap_gen_Includes}
- ${CMAKE_SOURCE_DIR}/dep/libmpq/win
- )
-endif()
-
include_directories(${mmap_gen_Includes})
add_executable(mmaps_generator ${mmap_gen_sources})
@@ -46,6 +39,7 @@ target_link_libraries(mmaps_generator
g3dlib
Recast
Detour
+ format
${BZIP2_LIBRARIES}
${ZLIB_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
index 412ba7a0055..b3d495f8a7e 100644
--- a/src/tools/mmaps_generator/MapBuilder.cpp
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
@@ -19,6 +19,7 @@
#include "PathCommon.h"
#include "MapBuilder.h"
+#include "StringFormat.h"
#include "MapTree.h"
#include "ModelInstance.h"
@@ -28,7 +29,7 @@
#include "DetourCommon.h"
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
-#define MMAP_VERSION 6
+#define MMAP_VERSION 7
struct MmapTileHeader
{
@@ -83,13 +84,12 @@ namespace MMAP
{
std::vector<std::string> files;
uint32 mapID, tileX, tileY, tileID, count = 0;
- char filter[12];
printf("Discovering maps... ");
getDirContents(files, "maps");
for (uint32 i = 0; i < files.size(); ++i)
{
- mapID = uint32(atoi(files[i].substr(0,3).c_str()));
+ mapID = uint32(atoi(files[i].substr(0, 4).c_str()));
if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end())
{
m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>));
@@ -101,7 +101,7 @@ namespace MMAP
getDirContents(files, "vmaps", "*.vmtree");
for (uint32 i = 0; i < files.size(); ++i)
{
- mapID = uint32(atoi(files[i].substr(0,3).c_str()));
+ mapID = uint32(atoi(files[i].substr(0, 4).c_str()));
if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end())
{
m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>));
@@ -117,26 +117,24 @@ namespace MMAP
std::set<uint32>* tiles = (*itr).m_tiles;
mapID = (*itr).m_mapId;
- sprintf(filter, "%03u*.vmtile", mapID);
files.clear();
- getDirContents(files, "vmaps", filter);
+ getDirContents(files, "vmaps", Trinity::StringFormat("%04u*.vmtile", mapID));
for (uint32 i = 0; i < files.size(); ++i)
{
- tileX = uint32(atoi(files[i].substr(7,2).c_str()));
- tileY = uint32(atoi(files[i].substr(4,2).c_str()));
+ tileX = uint32(atoi(files[i].substr(8, 2).c_str()));
+ tileY = uint32(atoi(files[i].substr(5, 2).c_str()));
tileID = StaticMapTree::packTileID(tileY, tileX);
tiles->insert(tileID);
count++;
}
- sprintf(filter, "%03u*", mapID);
files.clear();
- getDirContents(files, "maps", filter);
+ getDirContents(files, "maps", Trinity::StringFormat("%04u*", mapID));
for (uint32 i = 0; i < files.size(); ++i)
{
- tileY = uint32(atoi(files[i].substr(3,2).c_str()));
- tileX = uint32(atoi(files[i].substr(5,2).c_str()));
+ tileY = uint32(atoi(files[i].substr(5, 2).c_str()));
+ tileX = uint32(atoi(files[i].substr(8, 2).c_str()));
tileID = StaticMapTree::packTileID(tileX, tileY);
if (tiles->insert(tileID).second)
@@ -386,12 +384,12 @@ namespace MMAP
buildNavMesh(mapID, navMesh);
if (!navMesh)
{
- printf("[Map %03i] Failed creating navmesh!\n", mapID);
+ printf("[Map %04i] Failed creating navmesh!\n", mapID);
return;
}
// now start building mmtiles for each tile
- printf("[Map %03i] We have %u tiles. \n", mapID, (unsigned int)tiles->size());
+ printf("[Map %04i] We have %u tiles. \n", mapID, (unsigned int)tiles->size());
for (std::set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
{
uint32 tileX, tileY;
@@ -408,13 +406,13 @@ namespace MMAP
dtFreeNavMesh(navMesh);
}
- printf("[Map %03i] Complete!\n", mapID);
+ printf("[Map %04u] Complete!\n", mapID);
}
/**************************************************************************/
void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh)
{
- printf("[Map %03i] Building tile [%02u,%02u]\n", mapID, tileX, tileY);
+ printf("[Map %04i] Building tile [%02u,%02u]\n", mapID, tileX, tileY);
MeshData meshData;
@@ -500,22 +498,22 @@ namespace MMAP
navMeshParams.maxPolys = maxPolysPerTile;
navMesh = dtAllocNavMesh();
- printf("[Map %03i] Creating navMesh...\n", mapID);
+ printf("[Map %04u] Creating navMesh...\n", mapID);
if (!navMesh->init(&navMeshParams))
{
- printf("[Map %03i] Failed creating navmesh! \n", mapID);
+ printf("[Map %04u] Failed creating navmesh! \n", mapID);
return;
}
char fileName[25];
- sprintf(fileName, "mmaps/%03u.mmap", mapID);
+ sprintf(fileName, "mmaps/%04u.mmap", mapID);
FILE* file = fopen(fileName, "wb");
if (!file)
{
dtFreeNavMesh(navMesh);
char message[1024];
- sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName);
+ sprintf(message, "[Map %04u] Failed to open %s for writing!\n", mapID, fileName);
perror(message);
return;
}
@@ -531,9 +529,8 @@ namespace MMAP
dtNavMesh* navMesh)
{
// console output
- char tileString[20];
- sprintf(tileString, "[Map %03i] [%02i,%02i]: ", mapID, tileX, tileY);
- printf("%s Building movemap tiles...\n", tileString);
+ std::string tileString = Trinity::StringFormat("[Map %04u] [%02i,%02i]: ", mapID, tileX, tileY);
+ printf("%s Building movemap tiles...\n", tileString.c_str());
IntermediateValues iv;
@@ -614,7 +611,7 @@ namespace MMAP
tile.solid = rcAllocHeightfield();
if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
{
- printf("%s Failed building heightfield! \n", tileString);
+ printf("%s Failed building heightfield! \n", tileString.c_str());
continue;
}
@@ -635,33 +632,33 @@ namespace MMAP
tile.chf = rcAllocCompactHeightfield();
if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf))
{
- printf("%s Failed compacting heightfield! \n", tileString);
+ printf("%s Failed compacting heightfield! \n", tileString.c_str());
continue;
}
// build polymesh intermediates
if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf))
{
- printf("%s Failed eroding area! \n", tileString);
+ printf("%s Failed eroding area! \n", tileString.c_str());
continue;
}
if (!rcBuildDistanceField(m_rcContext, *tile.chf))
{
- printf("%s Failed building distance field! \n", tileString);
+ printf("%s Failed building distance field! \n", tileString.c_str());
continue;
}
if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea))
{
- printf("%s Failed building regions! \n", tileString);
+ printf("%s Failed building regions! \n", tileString.c_str());
continue;
}
tile.cset = rcAllocContourSet();
if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset))
{
- printf("%s Failed building contours! \n", tileString);
+ printf("%s Failed building contours! \n", tileString.c_str());
continue;
}
@@ -669,14 +666,14 @@ namespace MMAP
tile.pmesh = rcAllocPolyMesh();
if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh))
{
- printf("%s Failed building polymesh! \n", tileString);
+ printf("%s Failed building polymesh! \n", tileString.c_str());
continue;
}
tile.dmesh = rcAllocPolyMeshDetail();
if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *tile.dmesh))
{
- printf("%s Failed building polymesh detail! \n", tileString);
+ printf("%s Failed building polymesh detail! \n", tileString.c_str());
continue;
}
@@ -699,7 +696,7 @@ namespace MMAP
iv.polyMesh = rcAllocPolyMesh();
if (!iv.polyMesh)
{
- printf("%s alloc iv.polyMesh FIALED!\n", tileString);
+ printf("%s alloc iv.polyMesh FAILED!\n", tileString.c_str());
delete[] pmmerge;
delete[] dmmerge;
delete[] tiles;
@@ -710,7 +707,7 @@ namespace MMAP
iv.polyMeshDetail = rcAllocPolyMeshDetail();
if (!iv.polyMeshDetail)
{
- printf("%s alloc m_dmesh FIALED!\n", tileString);
+ printf("%s alloc m_dmesh FAILED!\n", tileString.c_str());
delete[] pmmerge;
delete[] dmmerge;
delete[] tiles;
@@ -774,12 +771,12 @@ namespace MMAP
// so we have a clear error message
if (params.nvp > DT_VERTS_PER_POLYGON)
{
- printf("%s Invalid verts-per-polygon value! \n", tileString);
+ printf("%s Invalid verts-per-polygon value! \n", tileString.c_str());
break;
}
if (params.vertCount >= 0xffff)
{
- printf("%s Too many vertices! \n", tileString);
+ printf("%s Too many vertices! \n", tileString.c_str());
break;
}
if (!params.vertCount || !params.verts)
@@ -788,7 +785,7 @@ namespace MMAP
// loaded but those models don't span into this tile
// message is an annoyance
- //printf("%sNo vertices to build tile! \n", tileString);
+ //printf("%sNo vertices to build tile! \n", tileString.c_str());
break;
}
if (!params.polyCount || !params.polys ||
@@ -797,47 +794,47 @@ namespace MMAP
// we have flat tiles with no actual geometry - don't build those, its useless
// keep in mind that we do output those into debug info
// drop tiles with only exact count - some tiles may have geometry while having less tiles
- printf("%s No polygons to build on tile! \n", tileString);
+ printf("%s No polygons to build on tile! \n", tileString.c_str());
break;
}
if (!params.detailMeshes || !params.detailVerts || !params.detailTris)
{
- printf("%s No detail mesh to build tile! \n", tileString);
+ printf("%s No detail mesh to build tile! \n", tileString.c_str());
break;
}
- printf("%s Building navmesh tile...\n", tileString);
+ printf("%s Building navmesh tile...\n", tileString.c_str());
if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
{
- printf("%s Failed building navmesh tile! \n", tileString);
+ printf("%s Failed building navmesh tile! \n", tileString.c_str());
break;
}
dtTileRef tileRef = 0;
- printf("%s Adding tile to navmesh...\n", tileString);
+ printf("%s Adding tile to navmesh...\n", tileString.c_str());
// DT_TILE_FREE_DATA tells detour to unallocate memory when the tile
// is removed via removeTile()
dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef);
if (!tileRef || dtResult != DT_SUCCESS)
{
- printf("%s Failed adding tile to navmesh! \n", tileString);
+ printf("%s Failed adding tile to navmesh! \n", tileString.c_str());
break;
}
// file output
char fileName[255];
- sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
+ sprintf(fileName, "mmaps/%04u%02i%02i.mmtile", mapID, tileY, tileX);
FILE* file = fopen(fileName, "wb");
if (!file)
{
char message[1024];
- sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName);
+ sprintf(message, "[Map %04u] Failed to open %s for writing!\n", mapID, fileName);
perror(message);
navMesh->removeTile(tileRef, NULL, NULL);
break;
}
- printf("%s Writing to file...\n", tileString);
+ printf("%s Writing to file...\n", tileString.c_str());
// write header
MmapTileHeader header;
@@ -898,6 +895,8 @@ namespace MMAP
case 1:
case 530:
case 571:
+ case 870:
+ case 1116:
return true;
default:
break;
@@ -916,6 +915,12 @@ namespace MMAP
case 597: // CraigTest.wdt
case 605: // development_nonweighted.wdt
case 606: // QA_DVD.wdt
+ case 651: // ElevatorSpawnTest.wdt
+ case 1060: // LevelDesignLand-DevOnly.wdt
+ case 1181: // PattyMackTestGarrisonBldgMap.wdt
+ case 1264: // Propland-DevOnly.wdt
+ case 1270: // devland3.wdt
+ case 1427: // PattyMackTestGarrisonBldgMap2.wdt
return true;
default:
if (isTransportMap(mapID))
@@ -926,13 +931,21 @@ namespace MMAP
if (m_skipBattlegrounds)
switch (mapID)
{
- case 30: // AV
+ case 30: // Alterac Valley
case 37: // ?
- case 489: // WSG
- case 529: // AB
- case 566: // EotS
- case 607: // SotA
- case 628: // IoC
+ case 489: // Warsong Gulch
+ case 529: // Arathi Basin
+ case 566: // Eye of the Storm
+ case 607: // Strand of the Ancients
+ case 628: // Isle of Conquest
+ case 726: // Twin Peaks
+ case 727: // Silvershard Mines
+ case 761: // The Battle for Gilneas
+ case 968: // Rated Eye of the Storm
+ case 998: // Temple of Kotmogu
+ case 1010: // CTF3
+ case 1105: // Deepwind Gorge
+ case 1280: // Southshore vs. Tarren Mill
return true;
default:
break;
@@ -970,11 +983,35 @@ namespace MMAP
case 641:
case 642:
case 647:
+ case 662:
case 672:
case 673:
+ case 674:
case 712:
case 713:
case 718:
+ case 738:
+ case 739:
+ case 740:
+ case 741:
+ case 742:
+ case 743:
+ case 747:
+ case 748:
+ case 749:
+ case 750:
+ case 762:
+ case 763:
+ case 765:
+ case 766:
+ case 767:
+ case 1113:
+ case 1132:
+ case 1133:
+ case 1172:
+ case 1173:
+ case 1192:
+ case 1231:
return true;
default:
return false;
@@ -985,7 +1022,7 @@ namespace MMAP
bool MapBuilder::shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY)
{
char fileName[255];
- sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX);
+ sprintf(fileName, "mmaps/%04u%02i%02i.mmtile", mapID, tileY, tileX);
FILE* file = fopen(fileName, "rb");
if (!file)
return false;
diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp
index 8f85cfdbe83..125f630bb13 100644
--- a/src/tools/mmaps_generator/TerrainBuilder.cpp
+++ b/src/tools/mmaps_generator/TerrainBuilder.cpp
@@ -80,7 +80,7 @@ struct map_liquidHeader
namespace MMAP
{
- char const* MAP_VERSION_MAGIC = "v1.4";
+ char const* MAP_VERSION_MAGIC = "v1.5";
TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ }
TerrainBuilder::~TerrainBuilder() { }
@@ -134,7 +134,7 @@ namespace MMAP
bool TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion)
{
char mapFileName[255];
- sprintf(mapFileName, "maps/%03u%02u%02u.map", mapID, tileY, tileX);
+ sprintf(mapFileName, "maps/%04u_%02u_%02u.map", mapID, tileY, tileX);
FILE* mapFile = fopen(mapFileName, "rb");
if (!mapFile)
diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp
index fb2cc0a20d0..9b01ecfb1df 100644
--- a/src/tools/vmap4_extractor/vmapexport.cpp
+++ b/src/tools/vmap4_extractor/vmapexport.cpp
@@ -72,7 +72,7 @@ bool preciseVectorData = false;
//static const char * szWorkDirMaps = ".\\Maps";
const char* szWorkDirWmo = "./Buildings";
-const char* szRawVMAPMagic = "VMAP042";
+const char* szRawVMAPMagic = "VMAP043";
bool OpenCascStorage()
{
@@ -249,7 +249,7 @@ void ParsMapFiles()
char id[10];
for (unsigned int i=0; i<map_count; ++i)
{
- sprintf(id,"%03u",map_ids[i].id);
+ sprintf(id, "%04u", map_ids[i].id);
sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
WDTFile WDT(fn,map_ids[i].name);
if(WDT.init(id, map_ids[i].id))
@@ -355,7 +355,7 @@ bool processArgv(int argc, char ** argv, const char *versionString)
int main(int argc, char ** argv)
{
bool success = true;
- const char *versionString = "V4.00 2012_02";
+ const char *versionString = "V4.03 2015_05";
// Use command line arguments, when some
if (!processArgv(argc, argv, versionString))