aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/bnetserver/Main.cpp6
-rw-r--r--src/server/collision/Management/MMapManager.cpp12
-rw-r--r--src/server/collision/Maps/TileAssembler.cpp1
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h2
-rw-r--r--src/server/game/Accounts/RBAC.h6
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp142
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp4
-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/Chat/Channels/Channel.cpp44
-rw-r--r--src/server/game/Chat/Channels/Channel.h6
-rw-r--r--src/server/game/Chat/Chat.cpp6
-rw-r--r--src/server/game/DataStores/DBCEnums.h282
-rw-r--r--src/server/game/DataStores/DBCStores.cpp24
-rw-r--r--src/server/game/DataStores/DBCStores.h3
-rw-r--r--src/server/game/DataStores/DBCStructure.h26
-rw-r--r--src/server/game/DataStores/DBCfmt.h1
-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/Creature/GossipDef.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp12
-rw-r--r--src/server/game/Entities/Object/Object.cpp74
-rw-r--r--src/server/game/Entities/Object/Object.h11
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp24
-rw-r--r--src/server/game/Entities/Pet/Pet.h8
-rw-r--r--src/server/game/Entities/Player/Player.cpp186
-rw-r--r--src/server/game/Entities/Player/Player.h88
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp2
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp20
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp169
-rw-r--r--src/server/game/Entities/Unit/Unit.h37
-rw-r--r--src/server/game/Events/GameEventMgr.h2
-rw-r--r--src/server/game/Garrison/Garrison.cpp115
-rw-r--r--src/server/game/Garrison/Garrison.h10
-rw-r--r--src/server/game/Garrison/GarrisonMap.cpp18
-rw-r--r--src/server/game/Garrison/GarrisonMap.h4
-rw-r--r--src/server/game/Garrison/GarrisonMgr.cpp160
-rw-r--r--src/server/game/Garrison/GarrisonMgr.h11
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp27
-rw-r--r--src/server/game/Globals/ObjectMgr.h3
-rw-r--r--src/server/game/Groups/Group.cpp451
-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.cpp8
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp33
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp16
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp982
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp13
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp122
-rw-r--r--src/server/game/Handlers/PetHandler.cpp3
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp4
-rw-r--r--src/server/game/Loot/LootMgr.cpp6
-rw-r--r--src/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Maps/MapInstanced.cpp2
-rw-r--r--src/server/game/Maps/ZoneScript.h4
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h4
-rw-r--r--src/server/game/Movement/MotionMaster.h2
-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/ScriptLoader.cpp2
-rw-r--r--src/server/game/Server/Packets/ChannelPackets.h10
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp37
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.h31
-rw-r--r--src/server/game/Server/Packets/ChatPackets.cpp14
-rw-r--r--src/server/game/Server/Packets/ChatPackets.h20
-rw-r--r--src/server/game/Server/Packets/CombatLogPackets.cpp37
-rw-r--r--src/server/game/Server/Packets/CombatLogPackets.h34
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.cpp4
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.h3
-rw-r--r--src/server/game/Server/Packets/InstancePackets.cpp26
-rw-r--r--src/server/game/Server/Packets/InstancePackets.h24
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp18
-rw-r--r--src/server/game/Server/Packets/ItemPackets.h24
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp69
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h21
-rw-r--r--src/server/game/Server/Packets/MovementPackets.h2
-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/QuestPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/QuestPackets.h3
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp103
-rw-r--r--src/server/game/Server/WorldSession.cpp18
-rw-r--r--src/server/game/Server/WorldSession.h102
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp30
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h1
-rw-r--r--src/server/game/Spells/Spell.cpp25
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellEffects.cpp25
-rw-r--r--src/server/game/Spells/SpellInfo.cpp3
-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/Texts/ChatTextBuilder.h4
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp4
-rw-r--r--src/server/game/World/World.cpp9
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp4
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp71
-rw-r--r--src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp12
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp6
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h12
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp20
-rw-r--r--src/server/scripts/Northrend/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/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/Database/Implementation/CharacterDatabase.cpp7
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h5
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp2
-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/PrecompiledHeaders/sharedPCH.h1
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp19
-rw-r--r--src/server/shared/Utilities/TaskScheduler.cpp204
-rw-r--r--src/server/shared/Utilities/TaskScheduler.h591
-rw-r--r--src/server/worldserver/worldserver.conf.dist2
135 files changed, 5214 insertions, 2110 deletions
diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp
index 20d1193b8e2..e1c0b187c46 100644
--- a/src/server/bnetserver/Main.cpp
+++ b/src/server/bnetserver/Main.cpp
@@ -57,9 +57,9 @@ 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);
-std::unique_ptr<boost::asio::io_service> _ioService;
-std::unique_ptr<boost::asio::deadline_timer> _dbPingTimer;
-uint32 _dbPingInterval;
+static std::unique_ptr<boost::asio::io_service> _ioService;
+static std::unique_ptr<boost::asio::deadline_timer> _dbPingTimer;
+static uint32 _dbPingInterval;
LoginDatabaseWorkerPool LoginDatabase;
int main(int argc, char** argv)
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp
index 25a9a86bc1b..e0b1ed3b161 100644
--- a/src/server/collision/Management/MMapManager.cpp
+++ b/src/server/collision/Management/MMapManager.cpp
@@ -177,7 +177,8 @@ namespace MMAP
{
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)
@@ -185,7 +186,8 @@ namespace MMAP
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);
@@ -196,7 +198,8 @@ namespace MMAP
{
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);
@@ -475,7 +478,10 @@ namespace MMAP
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 %04u%02i%02i.mmtile from navmesh", _mapId, x, y);
+ delete pt;
+ }
else
{
TC_LOG_DEBUG("phase", "MMapData::AddSwap: Unloaded %04u%02i%02i.mmtile from navmesh", _mapId, x, y);
diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp
index 86391d5488a..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;
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/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 40ab7ebc52e..6d56774e447 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -847,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)
@@ -870,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)
@@ -894,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)
@@ -984,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/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/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/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 04b6eb1b5b1..90c44aa501b 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 c7952d7758c..ed6aa52da5a 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());
}
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index fc05f0fdc6a..719e539a9c4 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -159,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
@@ -188,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
{
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index e1f0c595b5f..540d4cf6d9e 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);
@@ -369,6 +370,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
@@ -881,9 +883,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 +894,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 +930,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 +939,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..5ad47549351 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;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 2893ea3df83..f8f140ff02b 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?)
@@ -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
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index e3b474bc27b..a67ec26ed7c 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -25,6 +25,7 @@
char const Achievementfmt[] = "niixsxiixixxiii";
const std::string CustomAchievementfmt = "pppaaaapapaapp";
const std::string CustomAchievementIndex = "ID";
+char const AnimKitfmt[] = "nxxx";
char const AreaTableEntryfmt[] = "iiiniixxxxxxisiiiiixxxxxxxxxx";
char const AreaTriggerEntryfmt[] = "nifffxxxfffffxxxx";
char const ArmorLocationfmt[] = "nfffff";
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/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..da2257641d5 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
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index c2f7718438e..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)
@@ -1446,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);
@@ -3100,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 b4b66bd5121..b9a6320a835 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -649,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;
@@ -689,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/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 05d649fe632..c8152e3ac36 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -39,8 +39,8 @@
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_declinedname(NULL)
+ m_petType(type), m_duration(0), m_loading(false), m_declinedname(NULL),
+ m_groupUpdateMask(0)
{
ASSERT(GetOwner());
@@ -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);
@@ -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 a3a602d2f4a..96e58f41fc6 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -100,6 +100,7 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "WorldStatePackets.h"
+#include "InstancePackets.h"
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
@@ -701,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;
@@ -802,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();
@@ -887,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);
@@ -927,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();
@@ -1125,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)
{
@@ -4594,6 +4587,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
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);
@@ -7387,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;
@@ -7698,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);
@@ -7847,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;
}
}
@@ -17344,18 +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(new Garrison(this));
+ 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_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;
}
@@ -17369,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)
{
@@ -17389,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());
}
@@ -18557,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);
@@ -18573,27 +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;
+
+ WorldPackets::Instance::InstanceLockInfos lockInfos;
+
+ lockInfos.InstanceID = save->GetInstanceId();
+ lockInfos.MapID = save->GetMapId();
+ lockInfos.DifficultyID = save->GetDifficultyID();
+ lockInfos.TimeRemaining = save->GetResetTime() - now;
+
+ lockInfos.CompletedMask = 0;
if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId()))
if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript())
- completedEncounters = instanceScript->GetCompletedEncounterMask();
+ lockInfos.CompletedMask = instanceScript->GetCompletedEncounterMask();
+
+ lockInfos.Locked = lockInfos.TimeRemaining <= 0;
+ lockInfos.Extended = false;
- 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;
+ instanceInfo.LockList.push_back(lockInfos);
}
}
}
- data.put<uint32>(p_counter, counter);
- GetSession()->SendPacket(&data);
+ GetSession()->SendPacket(instanceInfo.Write());
}
/// convert the player's binds to the group
@@ -19418,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);
@@ -19966,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());
}
@@ -20220,7 +20244,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
GetSession()->SendPacket(&data);
if (GetGroup())
- SetGroupUpdateFlag(GROUP_UPDATE_PET);
+ SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
}
}
@@ -20259,7 +20283,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);
}
@@ -20269,7 +20293,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);
}
@@ -20279,7 +20303,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));
}
@@ -20292,7 +20316,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());
}
@@ -20309,14 +20333,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())
@@ -22618,11 +22642,20 @@ 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();
@@ -22636,9 +22669,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)
@@ -22697,10 +22729,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());
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index df08a1b30d4..5bae50edb68 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -207,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,
@@ -222,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
@@ -236,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;
@@ -270,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;
@@ -486,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;
@@ -989,6 +987,8 @@ enum PlayerLoginQueryIndex
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
};
@@ -1737,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;
@@ -2056,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;
@@ -2132,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);
@@ -2143,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;
@@ -2522,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;
@@ -2761,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;
@@ -2889,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)
@@ -2912,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
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 7034f7fbdc5..f449cec1eef 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -231,7 +231,7 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
-void Transport::DelayedUpdate(uint32 diff)
+void Transport::DelayedUpdate(uint32 /*diff*/)
{
if (GetKeyFrames().size() <= 1)
return;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index e9af35ff952..526d2b020e1 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;
@@ -266,17 +265,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 +281,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));
@@ -746,10 +732,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 7ae20779fa7..490c31e683c 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())
@@ -11245,6 +11217,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 +11293,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 +11313,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 +11444,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 +11465,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 +11517,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 +11539,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 +12965,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 +13349,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);
@@ -16401,7 +16310,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 +16357,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 252f044b4ef..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,
@@ -1489,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; }
@@ -1986,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; }
@@ -2346,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/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index 5edd6f3da2d..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()
diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp
index 3087de37472..749ebb562c5 100644
--- a/src/server/game/Garrison/Garrison.cpp
+++ b/src/server/game/Garrison/Garrison.cpp
@@ -25,7 +25,8 @@ Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followe
{
}
-bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings)
+bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
+ PreparedQueryResult followers, PreparedQueryResult abilities)
{
if (!garrison)
return false;
@@ -76,6 +77,59 @@ bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blue
} 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;
}
@@ -93,6 +147,10 @@ void Garrison::SaveToDB(SQLTransaction& trans)
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);
@@ -121,6 +179,35 @@ void Garrison::SaveToDB(SQLTransaction& trans)
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)
@@ -348,15 +435,17 @@ void Garrison::AddFollower(uint32 garrFollowerId)
{
WorldPackets::Garrison::GarrisonAddFollowerResult addFollowerResult;
GarrFollowerEntry const* followerEntry = sGarrFollowerStore.LookupEntry(garrFollowerId);
- if (_followers.count(garrFollowerId) || !followerEntry)
+ if (_followerIds.count(garrFollowerId) || !followerEntry)
{
addFollowerResult.Result = GARRISON_GENERIC_UNKNOWN_ERROR;
_owner->SendDirectMessage(addFollowerResult.Write());
return;
}
- Follower& follower = _followers[garrFollowerId];
- follower.PacketInfo.DbID = sGarrisonMgr.GenerateFollowerDbId();
+ _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;
@@ -370,6 +459,17 @@ void Garrison::AddFollower(uint32 garrFollowerId)
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()
@@ -481,7 +581,7 @@ GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32
if (!_owner->HasCurrency(building->CostCurrencyID, building->CostCurrencyAmount))
return GARRISON_ERROR_NOT_ENOUGH_CURRENCY;
- if (!_owner->HasEnoughMoney(uint64(building->CostMoney * GOLD)))
+ if (!_owner->HasEnoughMoney(uint64(building->CostMoney) * GOLD))
return GARRISON_ERROR_NOT_ENOUGH_GOLD;
// New building cannot replace another building currently under construction
@@ -583,3 +683,8 @@ bool Garrison::Building::CanActivate() const
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
index 348998b276c..71d67a1b6b5 100644
--- a/src/server/game/Garrison/Garrison.h
+++ b/src/server/game/Garrison/Garrison.h
@@ -43,7 +43,8 @@ enum GarrisonAbilityFlags
GARRISON_ABILITY_CANNOT_ROLL = 0x02,
GARRISON_ABILITY_HORDE_ONLY = 0x04,
GARRISON_ABILITY_ALLIANCE_ONLY = 0x08,
- GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x10
+ GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x10,
+ GARRISON_ABILITY_FLAG_EXCLUSIVE = 0x20
};
enum GarrisonError
@@ -99,12 +100,15 @@ public:
struct Follower
{
+ uint32 GetItemLevel() const;
+
WorldPackets::Garrison::GarrisonFollower PacketInfo;
};
explicit Garrison(Player* owner);
- bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings);
+ bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings,
+ PreparedQueryResult followers, PreparedQueryResult abilities);
void SaveToDB(SQLTransaction& trans);
bool Create(uint32 garrSiteId);
@@ -128,6 +132,7 @@ public:
// Followers
void AddFollower(uint32 garrFollowerId);
+ Follower const* GetFollower(uint64 dbId) const;
void SendInfo();
void SendRemoteInfo() const;
@@ -148,6 +153,7 @@ private:
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
index 7316504d185..b9cf63140b4 100644
--- a/src/server/game/Garrison/GarrisonMap.cpp
+++ b/src/server/game/Garrison/GarrisonMap.cpp
@@ -97,7 +97,7 @@ 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)
+ : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner), _loadingPlayer(nullptr)
{
GarrisonMap::InitVisibilityDistance();
}
@@ -112,6 +112,9 @@ void GarrisonMap::LoadGridObjects(NGridType* grid, Cell const& cell)
Garrison* GarrisonMap::GetGarrison()
{
+ if (_loadingPlayer)
+ return _loadingPlayer->GetGarrison();
+
if (Player* owner = ObjectAccessor::FindConnectedPlayer(_owner))
return owner->GetGarrison();
@@ -124,3 +127,16 @@ void GarrisonMap::InitVisibilityDistance()
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
index 0ccc77b05fa..5f5c9b134b7 100644
--- a/src/server/game/Garrison/GarrisonMap.h
+++ b/src/server/game/Garrison/GarrisonMap.h
@@ -21,6 +21,7 @@
#include "Map.h"
class Garrison;
+class Player;
class GarrisonMap : public Map
{
@@ -32,8 +33,11 @@ public:
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
index 3229ee7d02a..f95acef952c 100644
--- a/src/server/game/Garrison/GarrisonMgr.cpp
+++ b/src/server/game/Garrison/GarrisonMgr.cpp
@@ -17,6 +17,7 @@
#include "GarrisonMgr.h"
#include "Containers.h"
+#include "DatabaseEnv.h"
#include "Garrison.h"
#include "ObjectDefines.h"
#include "World.h"
@@ -55,6 +56,9 @@ void GarrisonMgr::Initialize()
}
}
}
+
+ InitializeDbIdSequences();
+ LoadFollowerClassSpecAbilities();
}
GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
@@ -139,11 +143,12 @@ uint32 const AbilitiesForQuality[][2] =
{ 2, 3 } // Legendary
};
-std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
+std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
{
ASSERT(faction < 2);
- std::list<uint32> result;
+ bool hasForcedExclusiveTrait = false;
+ std::list<GarrAbilityEntry const*> result;
int32 slots[2] = { AbilitiesForQuality[quality][0], AbilitiesForQuality[quality][1] };
GarrAbilities const* abilities = nullptr;
@@ -151,7 +156,7 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
if (itr != _garrisonFollowerAbilities[faction].end())
abilities = &itr->second;
- std::list<uint32> abilityList, forcedAbilities, traitList, forcedTraits;
+ std::list<GarrAbilityEntry const*> abilityList, forcedAbilities, traitList, forcedTraits;
if (abilities)
{
for (GarrAbilityEntry const* ability : abilities->Counters)
@@ -162,9 +167,9 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
continue;
if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
- forcedAbilities.push_back(ability->ID);
+ forcedAbilities.push_back(ability);
else
- abilityList.push_back(ability->ID);
+ abilityList.push_back(ability);
}
for (GarrAbilityEntry const* ability : abilities->Traits)
@@ -175,36 +180,51 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
continue;
if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
- forcedTraits.push_back(ability->ID);
+ forcedTraits.push_back(ability);
else
- traitList.push_back(ability->ID);
+ 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 counters specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation
+ // 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);
}
- if (slots[0] > forcedAbilities.size() + abilityList.size())
+ forcedAbilities.sort();
+ abilityList.sort();
+ forcedTraits.sort();
+ traitList.sort();
+
+ // check if we have a trait from exclusive category
+ for (GarrAbilityEntry const* ability : forcedTraits)
{
- std::list<uint32> classSpecAbilities; // = GetDefaultClassSpecAbilities(follower, faction)
+ if (ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ {
+ hasForcedExclusiveTrait = true;
+ break;
+ }
+ }
- abilityList.splice(abilityList.end(), classSpecAbilities);
- abilityList.sort();
- abilityList.unique();
+ 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<uint32> genericTraits;
+ std::list<GarrAbilityEntry const*> genericTraits, genericTraitsTemp;
for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits)
{
if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
@@ -212,14 +232,44 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
continue;
- genericTraits.push_back(ability->ID);
+ // forced exclusive trait exists, skip other ones entirely
+ if (hasForcedExclusiveTrait && ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ continue;
+
+ genericTraitsTemp.push_back(ability);
}
- traitList.splice(traitList.end(), genericTraits);
- traitList.sort();
- traitList.unique();
+ 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();
- Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
+ 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);
@@ -229,3 +279,75 @@ std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* fo
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
index f037c0867a0..63810e3c3ab 100644
--- a/src/server/game/Garrison/GarrisonMgr.h
+++ b/src/server/game/Garrison/GarrisonMgr.h
@@ -45,18 +45,23 @@ public:
uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const;
GarrBuildingEntry const* GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const;
uint64 GenerateFollowerDbId();
- std::list<uint32> RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const;
+ 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_set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits;
+ std::unordered_map<uint32 /*classSpecId*/, std::list<GarrAbilityEntry const*>> _garrisonFollowerClassSpecAbilities;
+ std::set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits;
- uint64 _followerDbIdGenerator;
+ uint64 _followerDbIdGenerator = UI64LIT(1);
};
#define sGarrisonMgr GarrisonMgr::Instance()
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index ac87f58af5c..cdd550a98f2 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2242,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))
@@ -3620,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
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index dc26e30773c..4277ab74048 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -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/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index f359e1eff57..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 */)
@@ -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..d4c6a0a680d 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1602,11 +1602,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())
@@ -2466,7 +2466,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 +2481,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/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 56d865e5d06..7b22d46d67b 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -248,6 +248,14 @@ bool LoginQueryHolder::Initialize()
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;
}
@@ -2566,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/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/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index c938751e162..e6aecff9137 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -716,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)
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/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 025bb45b42b..c87bff8511e 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1213,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();
+ WorldPackets::Misc::LoadCUFProfiles loadCUFProfiles;
- 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);
- }
-
- 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/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/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 3d2f60929fb..2d3090825da 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -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/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index a63ed66446e..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);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index a2faa8cc0a0..fb1ac3cc62d 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -699,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;
}
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index 473e3163216..bd69844ae7c 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -214,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());
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 ed004c6174d..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
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/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/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/ChannelPackets.h b/src/server/game/Server/Packets/ChannelPackets.h
index 6c43588e86a..8dba1e84677 100644
--- a/src/server/game/Server/Packets/ChannelPackets.h
+++ b/src/server/game/Server/Packets/ChannelPackets.h
@@ -104,8 +104,8 @@ namespace WorldPackets
ObjectGuid AddedUserGUID;
- ChannelFlags ChannelFlags = CHANNEL_FLAG_NONE;
- ChannelMemberFlags UserFlags = MEMBER_FLAG_NONE;
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 UserFlags = MEMBER_FLAG_NONE;
int32 ChannelID = 0;
@@ -121,7 +121,7 @@ namespace WorldPackets
ObjectGuid RemovedUserGUID;
- ChannelFlags ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
uint32 ChannelID = 0;
@@ -137,8 +137,8 @@ namespace WorldPackets
ObjectGuid UpdatedUserGUID;
- ChannelFlags ChannelFlags = CHANNEL_FLAG_NONE;
- ChannelMemberFlags UserFlags = MEMBER_FLAG_NONE;
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 UserFlags = MEMBER_FLAG_NONE;
int32 ChannelID = 0;
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index a48639f1b03..9c6bb07f56e 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -498,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 260770e65fe..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
@@ -233,3 +233,15 @@ WorldPacket const* WorldPackets::Chat::ChatServerMessage::Write()
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 5bc55952168..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
@@ -250,6 +250,24 @@ namespace WorldPackets
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..6742e797c54 100644
--- a/src/server/game/Server/Packets/CombatLogPackets.cpp
+++ b/src/server/game/Server/Packets/CombatLogPackets.cpp
@@ -147,3 +147,40 @@ 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;
+}
diff --git a/src/server/game/Server/Packets/CombatLogPackets.h b/src/server/game/Server/Packets/CombatLogPackets.h
index c74e8112698..a931166ef80 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,39 @@ 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
+ };
}
}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp
index 456149bbdbb..88374e7ce62 100644
--- a/src/server/game/Server/Packets/GarrisonPackets.cpp
+++ b/src/server/game/Server/Packets/GarrisonPackets.cpp
@@ -60,8 +60,8 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Garrison::GarrisonFollowe
data << uint32(follower.CurrentMissionID);
data << uint32(follower.AbilityID.size());
data << uint32(follower.FollowerStatus);
- for (uint32 abilityId : follower.AbilityID)
- data << uint32(abilityId);
+ for (GarrAbilityEntry const* ability : follower.AbilityID)
+ data << uint32(ability->ID);
return data;
}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h
index 5fc386ab72b..1bb04c7ba95 100644
--- a/src/server/game/Server/Packets/GarrisonPackets.h
+++ b/src/server/game/Server/Packets/GarrisonPackets.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
#include "Position.h"
#include "PacketUtilities.h"
+#include "DB2Structure.h"
namespace WorldPackets
{
@@ -74,7 +75,7 @@ namespace WorldPackets
uint32 Xp = 0;
uint32 CurrentBuildingID = 0;
uint32 CurrentMissionID = 0;
- std::list<uint32> AbilityID;
+ std::list<GarrAbilityEntry const*> AbilityID;
uint32 FollowerStatus;
};
diff --git a/src/server/game/Server/Packets/InstancePackets.cpp b/src/server/game/Server/Packets/InstancePackets.cpp
index 50b2a66a8b8..db5bdcbd9e8 100644
--- a/src/server/game/Server/Packets/InstancePackets.cpp
+++ b/src/server/game/Server/Packets/InstancePackets.cpp
@@ -30,3 +30,29 @@ WorldPacket const* WorldPackets::Instance::UpdateInstanceOwnership::Write()
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;
+}
diff --git a/src/server/game/Server/Packets/InstancePackets.h b/src/server/game/Server/Packets/InstancePackets.h
index 09f6c1efdcb..e38bcb97462 100644
--- a/src/server/game/Server/Packets/InstancePackets.h
+++ b/src/server/game/Server/Packets/InstancePackets.h
@@ -46,7 +46,31 @@ namespace WorldPackets
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;
+ };
}
}
+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 a4da605ca08..8b0bec535b3 100644
--- a/src/server/game/Server/Packets/ItemPackets.cpp
+++ b/src/server/game/Server/Packets/ItemPackets.cpp
@@ -374,3 +374,21 @@ 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 7b0b9e41e4b..e73f42bcaf2 100644
--- a/src/server/game/Server/Packets/ItemPackets.h
+++ b/src/server/game/Server/Packets/ItemPackets.h
@@ -363,6 +363,30 @@ namespace WorldPackets
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 a12ff537050..bbd3fcb2ba7 100644
--- a/src/server/game/Server/Packets/MiscPackets.cpp
+++ b/src/server/game/Server/Packets/MiscPackets.cpp
@@ -451,3 +451,72 @@ WorldPacket const* WorldPackets::Misc::Dismount::Write()
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 fda0e44990e..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
@@ -642,6 +643,26 @@ namespace WorldPackets
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.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/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/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp
index ad4001899fe..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
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/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 4c87e00fc91..70a22f0b1bb 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -33,6 +33,7 @@
#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"
@@ -259,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);
@@ -308,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);
@@ -331,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);
@@ -357,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);
@@ -458,7 +459,7 @@ 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);
@@ -471,7 +472,7 @@ void OpcodeTable::Initialize()
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);
@@ -514,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 );
@@ -590,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);
@@ -655,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);
@@ -676,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 );
@@ -695,7 +696,7 @@ void OpcodeTable::Initialize()
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);
@@ -716,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);
@@ -724,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);
@@ -775,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);
@@ -809,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);
@@ -990,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);
@@ -1000,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);
@@ -1169,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);
@@ -1248,7 +1249,7 @@ 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_INFO, STATUS_NEVER, 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_SAVE_CREATED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1257,12 +1258,12 @@ void OpcodeTable::Initialize()
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);
@@ -1298,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);
@@ -1327,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);
@@ -1431,11 +1432,11 @@ 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);
@@ -1539,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);
@@ -1573,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);
@@ -1594,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);
@@ -1657,7 +1658,7 @@ void OpcodeTable::Initialize()
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);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index fa557616450..650e100f514 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -913,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 6cfa8202af4..8f74a8900b0 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -171,9 +171,6 @@ namespace WorldPackets
class ChannelPlayerCommand;
class JoinChannel;
class LeaveChannel;
- class UserlistAdd;
- class UserlistRemove;
- class UserlistUpdate;
}
namespace Chat
@@ -189,6 +186,8 @@ namespace WorldPackets
class ChatMessageEmote;
class CTextEmote;
class EmoteClient;
+ class ChatRegisterAddonPrefixes;
+ class ChatUnregisterAllAddonPrefixes;
}
namespace Combat
@@ -278,6 +277,11 @@ namespace WorldPackets
class RequestHonorStats;
}
+ namespace Instance
+ {
+ class InstanceInfo;
+ }
+
namespace Item
{
class AutoEquipItem;
@@ -341,6 +345,8 @@ namespace WorldPackets
class CompleteCinematic;
class NextCinematicCamera;
class FarSight;
+ class LoadCUFProfiles;
+ class SaveCUFProfiles;
}
namespace Movement
@@ -363,6 +369,47 @@ namespace WorldPackets
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
{
class DeclinePetition;
@@ -858,8 +905,6 @@ class WorldSession
void SendNotInArenaTeamPacket(uint8 type);
void SendPetitionShowList(ObjectGuid guid);
- void BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data);
-
void DoLootRelease(ObjectGuid lguid);
// Account mute time
@@ -1054,28 +1099,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);
@@ -1266,8 +1314,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);
@@ -1340,7 +1388,7 @@ 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(WorldPackets::Misc::FarSight& packet);
void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty);
@@ -1473,7 +1521,7 @@ 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
diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h
index 7e60ac9b5da..669b90e6392 100644
--- a/src/server/game/Spells/Auras/SpellAuraDefines.h
+++ b/src/server/game/Spells/Auras/SpellAuraDefines.h
@@ -524,7 +524,7 @@ enum AuraType
SPELL_AURA_464 = 464,
SPELL_AURA_465 = 465,
SPELL_AURA_466 = 466,
- SPELL_AURA_467 = 467,
+ 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..5abf9d10375 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -527,7 +527,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
&AuraEffect::HandleNULL, //464
&AuraEffect::HandleNULL, //465
&AuraEffect::HandleNULL, //466
- &AuraEffect::HandleNULL, //467
+ &AuraEffect::HandleModStatBonusPercent, //467 SPELL_AURA_MOD_STAT_BONUS_PCT
&AuraEffect::HandleNULL, //468
&AuraEffect::HandleNULL, //469
&AuraEffect::HandleNULL, //470
@@ -3982,6 +3982,34 @@ 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);
+ if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet())
+ target->ApplyStatPercentBuffMod(Stats(i), float(m_amount), apply);
+ }
+ }
+}
+
/********************************/
/*** HEAL & ENERGIZE ***/
/********************************/
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index e8431e202ba..b2519b4b78a 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -234,6 +234,7 @@ 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;
// heal and energize
void HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModPowerRegenPCT(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 fb40de60048..6f2f761868e 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);
@@ -2326,6 +2328,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
return;
}
+ if (!unit)
+ return;
+
if (unit->IsAlive() != target->alive)
return;
@@ -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)
@@ -5815,7 +5820,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;
}
@@ -6832,7 +6837,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;
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 3ca8550b3ce..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);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 9e4f0608a38..c640134f6e4 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -180,7 +180,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
@@ -241,7 +241,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
@@ -421,7 +421,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;
@@ -4648,6 +4648,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)
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 4db7091f971..7b012d8a0f6 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:
{
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 2f74218ba7b..70b820aed96 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: // Force Cast (HACK: Target shouldn't be changed)
+ case 63171: // Force Cast (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
+ 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/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 9b8c63000fc..d68da8fbc63 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2252,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");
@@ -2381,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()));
}
@@ -2447,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);
}
@@ -2481,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);
}
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_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 61df922452f..b9765223add 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -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);
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index 81cad2db188..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;
@@ -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 f027a98da9d..d261b7a623a 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -1064,7 +1064,7 @@ class npc_meteor_strike : public CreatureScript
}
}
- void IsSummonedBy(Unit* summoner) override
+ void IsSummonedBy(Unit* /*summoner*/) override
{
// Let Halion Controller count as summoner.
if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
@@ -1092,9 +1092,6 @@ class npc_meteor_strike : public CreatureScript
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->AI()->SetGUID(GetGUID());
@@ -1128,7 +1125,7 @@ class npc_meteor_strike_flame : public CreatureScript
SetCombatMovement(false);
}
- void SetGUID(ObjectGuid guid, int32 id /* = 0 */)
+ void SetGUID(ObjectGuid guid, int32 /*id = 0 */)
{
_rootOwnerGuid = guid;
}
@@ -1149,9 +1146,6 @@ class npc_meteor_strike_flame : public CreatureScript
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->AI()->SetGUID(_rootOwnerGuid);
meteorStrike->AI()->SetData(DATA_SPAWNED_FLAMES, 1);
}
@@ -1164,7 +1158,7 @@ class npc_meteor_strike_flame : public CreatureScript
controller->AI()->JustSummoned(me);
}
- void UpdateAI(uint32 diff) override { }
+ void UpdateAI(uint32 /*diff*/) override { }
void EnterEvadeMode() override { }
private:
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/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/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/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index e9ce253d1cf..277ccd4569a 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -690,7 +690,12 @@ void CharacterDatabaseConnection::DoPrepareStatements()
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_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 53c42a0b852..fc9c930e6b1 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -608,6 +608,11 @@ enum CharacterDatabaseStatements
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/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index 70350f3136c..99d6cb7af50 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);
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/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..c945ad4dab0
--- /dev/null
+++ b/src/server/shared/Utilities/TaskScheduler.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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::forward<TaskContainer>(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(new TaskContextInstance(_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();
+}
+
+TaskContextInstance& TaskContextInstance::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply)
+{
+ if (auto const owner = _owner.lock())
+ apply(*owner);
+
+ return *this;
+}
+
+bool TaskContextInstance::IsInGroup(TaskScheduler::group_t const group) const
+{
+ return _task->IsInGroup(group);
+}
+
+TaskContextInstance& TaskContextInstance::SetGroup(TaskScheduler::group_t const group)
+{
+ _task->_group = group;
+ return *this;
+}
+
+TaskContextInstance& TaskContextInstance::ClearGroup()
+{
+ _task->_group = boost::none;
+ return *this;
+}
+
+TaskScheduler::repeated_t TaskContextInstance::GetRepeatCounter() const
+{
+ return _task->_repeated;
+}
+
+TaskContextInstance& TaskContextInstance::Async(std::function<void()> const& callable)
+{
+ return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable));
+}
+
+TaskContextInstance& TaskContextInstance::CancelAll()
+{
+ return Dispatch(std::mem_fn(&TaskScheduler::CancelAll));
+}
+
+TaskContextInstance& TaskContextInstance::CancelGroup(TaskScheduler::group_t const group)
+{
+ return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group));
+}
+
+TaskContextInstance& TaskContextInstance::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
+{
+ return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, groups));
+}
+
+void TaskContextInstance::AssertOnConsumed()
+{
+ // 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(_task && "Bad task logic, task context was consumed already!");
+}
+
+void TaskContextInstance::Invoke()
+{
+ _task->_task(shared_from_this());
+}
diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h
new file mode 100644
index 00000000000..3498a9bcf6c
--- /dev/null
+++ b/src/server/shared/Utilities/TaskScheduler.h
@@ -0,0 +1,591 @@
+/*
+ * 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 TaskContextInstance;
+
+typedef std::shared_ptr<TaskContextInstance> 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 TaskContextInstance;
+
+ // 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 TaskContextInstance;
+ 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>
+ std::chrono::milliseconds
+ static 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 TaskContextInstance
+ : public std::enable_shared_from_this<TaskContextInstance>
+{
+ friend class TaskScheduler;
+
+ /// Associated task
+ TaskScheduler::TaskContainer _task;
+
+ /// Owner
+ std::weak_ptr<TaskScheduler> const _owner;
+
+ /// Dispatches an action safe on the TaskScheduler
+ TaskContextInstance& Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply);
+
+public:
+ explicit TaskContextInstance(TaskScheduler::TaskContainer task, std::weak_ptr<TaskScheduler>&& owner)
+ : _task(task), _owner(owner) { }
+
+ /// 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
+ TaskContextInstance& SetGroup(TaskScheduler::group_t const group);
+
+ /// Removes the group from the event
+ TaskContextInstance& 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>
+ TaskContextInstance& 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;
+ 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!
+ TaskContextInstance& 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>
+ TaskContextInstance& 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.
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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.
+ TaskContextInstance& CancelAll();
+
+ /// Cancel all tasks of a single group from within the context.
+ TaskContextInstance& 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}"
+ TaskContextInstance& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups);
+
+ /// Delays all tasks with the given duration from within the context.
+ template<class _Rep, class _Period>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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>
+ TaskContextInstance& 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:
+ void AssertOnConsumed();
+
+ /// Invokes the associated hook of the task.
+ void Invoke();
+};
+
+/// Milliseconds shorthand typedef.
+typedef std::chrono::milliseconds Milliseconds;
+
+/// Seconds shorthand typedef.
+typedef std::chrono::seconds Seconds;
+
+/// Minutes shorthand typedef.
+typedef std::chrono::minutes Minutes;
+
+/// Hours shorthand typedef.
+typedef std::chrono::hours Hours;
+
+#endif /// _TASK_SCHEDULER_H_
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 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