aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp4
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp44
-rw-r--r--src/server/game/Chat/Chat.cpp6
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp15
-rw-r--r--src/server/game/DataStores/DB2Stores.h5
-rw-r--r--src/server/game/DataStores/DB2Structure.h54
-rw-r--r--src/server/game/DataStores/DB2fmt.h8
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp12
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp2
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp22
-rw-r--r--src/server/game/Entities/Pet/Pet.h8
-rw-r--r--src/server/game/Entities/Player/Player.cpp138
-rw-r--r--src/server/game/Entities/Player/Player.h77
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp82
-rw-r--r--src/server/game/Entities/Transport/Transport.h3
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp58
-rw-r--r--src/server/game/Events/GameEventMgr.cpp17
-rw-r--r--src/server/game/Garrison/Garrison.cpp206
-rw-r--r--src/server/game/Garrison/Garrison.h39
-rw-r--r--src/server/game/Garrison/GarrisonMgr.cpp187
-rw-r--r--src/server/game/Garrison/GarrisonMgr.h15
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp19
-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.h153
-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.cpp4
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp16
-rw-r--r--src/server/game/Handlers/GarrisonHandler.cpp9
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp983
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp121
-rw-r--r--src/server/game/Handlers/PetHandler.cpp3
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp4
-rw-r--r--src/server/game/Maps/Map.cpp13
-rw-r--r--src/server/game/Maps/Map.h2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp18
-rw-r--r--src/server/game/Pools/PoolMgr.cpp16
-rw-r--r--src/server/game/Server/Packets/ChannelPackets.cpp43
-rw-r--r--src/server/game/Server/Packets/ChannelPackets.h50
-rw-r--r--src/server/game/Server/Packets/ChatPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/ChatPackets.h2
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.cpp43
-rw-r--r--src/server/game/Server/Packets/GarrisonPackets.h65
-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/MiscPackets.cpp69
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h21
-rw-r--r--src/server/game/Server/Packets/PartyPackets.cpp716
-rw-r--r--src/server/game/Server/Packets/PartyPackets.h616
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp101
-rw-r--r--src/server/game/Server/WorldSession.h98
-rw-r--r--src/server/game/Spells/Spell.h2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp40
-rw-r--r--src/server/game/Spells/SpellInfo.cpp2
-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_gobject.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp189
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp39
-rw-r--r--src/server/shared/Common.h11
-rw-r--r--src/server/shared/Database/Implementation/HotfixDatabase.cpp19
-rw-r--r--src/server/shared/Database/Implementation/HotfixDatabase.h11
-rw-r--r--src/server/shared/Logging/Log.h5
-rw-r--r--src/tools/mmaps_generator/TerrainBuilder.cpp4
70 files changed, 3515 insertions, 1536 deletions
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/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/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/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index c050caa8094..01c65315d35 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -29,8 +29,12 @@ DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.d
DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore("CurrencyTypes.db2", CurrencyTypesFormat, HOTFIX_SEL_CURRENCY_TYPES);
DB2Storage<CurvePointEntry> sCurvePointStore("CurvePoint.db2", CurvePointFormat, HOTFIX_SEL_CURVE_POINT);
DB2Storage<GameObjectsEntry> sGameObjectsStore("GameObjects.db2", GameObjectsFormat, HOTFIX_SEL_GAMEOBJECTS);
+DB2Storage<GarrAbilityEntry> sGarrAbilityStore("GarrAbility.db2", GarrAbilityFormat, HOTFIX_SEL_GARR_ABILITY);
DB2Storage<GarrBuildingEntry> sGarrBuildingStore("GarrBuilding.db2", GarrBuildingFormat, HOTFIX_SEL_GARR_BUILDING);
DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore("GarrBuildingPlotInst.db2", GarrBuildingPlotInstFormat, HOTFIX_SEL_GARR_BUILDING_PLOT_INST);
+DB2Storage<GarrClassSpecEntry> sGarrClassSpecStore("GarrClassSpec.db2", GarrClassSpecFormat, HOTFIX_SEL_GARR_CLASS_SPEC);
+DB2Storage<GarrFollowerEntry> sGarrFollowerStore("GarrFollower.db2", GarrFollowerFormat, HOTFIX_SEL_GARR_FOLLOWER);
+DB2Storage<GarrFollowerXAbilityEntry> sGarrFollowerXAbilityStore("GarrFollowerXAbility.db2", GarrFollowerXAbilityFormat, HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY);
DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore("GarrPlotBuilding.db2", GarrPlotBuildingFormat, HOTFIX_SEL_GARR_PLOT_BUILDING);
DB2Storage<GarrPlotEntry> sGarrPlotStore("GarrPlot.db2", GarrPlotFormat, HOTFIX_SEL_GARR_PLOT);
DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore("GarrPlotInstance.db2", GarrPlotInstanceFormat, HOTFIX_SEL_GARR_PLOT_INSTANCE);
@@ -141,8 +145,12 @@ void DB2Manager::LoadStores(std::string const& dataPath)
LOAD_DB2(sCurrencyTypesStore);
LOAD_DB2(sCurvePointStore);
LOAD_DB2(sGameObjectsStore);
- LOAD_DB2(sGarrBuildingPlotInstStore);
+ LOAD_DB2(sGarrAbilityStore);
LOAD_DB2(sGarrBuildingStore);
+ LOAD_DB2(sGarrBuildingPlotInstStore);
+ LOAD_DB2(sGarrClassSpecStore);
+ LOAD_DB2(sGarrFollowerStore);
+ LOAD_DB2(sGarrFollowerXAbilityStore);
LOAD_DB2(sGarrPlotBuildingStore);
LOAD_DB2(sGarrPlotInstanceStore);
LOAD_DB2(sGarrPlotStore);
@@ -513,6 +521,11 @@ MountEntry const* DB2Manager::GetMount(uint32 spellId) const
return nullptr;
}
+MountEntry const* DB2Manager::GetMountById(uint32 id) const
+{
+ return sMountStore.LookupEntry(id);
+}
+
std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItems(uint32 questPackageID) const
{
auto itr = _questPackages.find(questPackageID);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 6e3818e8f41..a79b3d1c1fa 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -25,8 +25,12 @@
extern DB2Storage<BroadcastTextEntry> sBroadcastTextStore;
extern DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore;
extern DB2Storage<GameObjectsEntry> sGameObjectsStore;
+extern DB2Storage<GarrAbilityEntry> sGarrAbilityStore;
extern DB2Storage<GarrBuildingEntry> sGarrBuildingStore;
extern DB2Storage<GarrBuildingPlotInstEntry> sGarrBuildingPlotInstStore;
+extern DB2Storage<GarrClassSpecEntry> sGarrClassSpecStore;
+extern DB2Storage<GarrFollowerEntry> sGarrFollowerStore;
+extern DB2Storage<GarrFollowerXAbilityEntry> sGarrFollowerXAbilityStore;
extern DB2Storage<GarrPlotBuildingEntry> sGarrPlotBuildingStore;
extern DB2Storage<GarrPlotEntry> sGarrPlotStore;
extern DB2Storage<GarrPlotInstanceEntry> sGarrPlotInstanceStore;
@@ -106,6 +110,7 @@ public:
std::set<uint32> GetItemBonusTree(uint32 itemId, uint32 itemBonusTreeMod) const;
uint32 GetItemDisplayId(uint32 itemId, uint32 appearanceModId) const;
MountEntry const* GetMount(uint32 spellId) const;
+ MountEntry const* GetMountById(uint32 id) const;
std::vector<QuestPackageItemEntry const*> const* GetQuestPackageItems(uint32 questPackageID) const;
std::set<uint32> GetPhasesForGroup(uint32 group) const;
std::vector<SpellPowerEntry const*> GetSpellPowers(uint32 spellId, Difficulty difficulty = DIFFICULTY_NONE, bool* hasDifficultyPowers = nullptr) const;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index cad9ca32e69..80c79a94b96 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -100,6 +100,17 @@ struct GameObjectsEntry
LocalizedString* Name; // 23
};
+struct GarrAbilityEntry
+{
+ uint32 ID; // 0
+ uint32 Flags; // 1
+ LocalizedString* Name; // 2
+ LocalizedString* Description; // 3
+ uint32 IconFileDataID; // 4
+ uint32 OtherFactionGarrAbilityID; // 5
+ uint32 GarrAbilityCategoryID; // 6
+};
+
struct GarrBuildingEntry
{
uint32 ID; // 0
@@ -137,6 +148,49 @@ struct GarrBuildingPlotInstEntry
DBCPosition2D LandmarkOffset; // 4-5
};
+struct GarrClassSpecEntry
+{
+ uint32 ID; // 0
+ LocalizedString* NameMale; // 1
+ LocalizedString* NameFemale; // 2
+ LocalizedString* NameGenderless; // 3
+ uint32 ClassAtlasID; // 4 UiTextureAtlasMember.db2 ref
+ uint32 GarrFollItemSetID; // 5
+};
+
+struct GarrFollowerEntry
+{
+ uint32 ID; // 0
+ uint32 HordeCreatureID; // 1
+ uint32 AllianceCreatureID; // 2
+ uint32 HordeUiAnimRaceInfoID; // 3
+ uint32 AllianceUiAnimRaceInfoID; // 4
+ uint32 Quality; // 5
+ uint32 HordeGarrClassSpecID; // 6
+ uint32 AllianceGarrClassSpecID; // 7
+ uint32 HordeGarrFollItemSetID; // 8
+ uint32 AllianceGarrFollItemSetID; // 9
+ uint32 Level; // 10
+ uint32 ItemLevelWeapon; // 11
+ uint32 ItemLevelArmor; // 12
+ uint32 Unknown1; // 13
+ uint32 Flags; // 14
+ LocalizedString* HordeSourceText; // 15
+ LocalizedString* AllianceSourceText; // 16
+ int32 Unknown2; // 17
+ int32 Unknown3; // 18
+ uint32 HordePortraitIconID; // 19
+ uint32 AlliancePortraitIconID; // 20
+};
+
+struct GarrFollowerXAbilityEntry
+{
+ uint32 ID; // 0
+ uint32 GarrFollowerID; // 1
+ uint32 GarrAbilityID; // 2
+ uint32 FactionIndex; // 3
+};
+
struct GarrPlotEntry
{
uint32 ID; // 0
diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h
index 19622dcc3d2..7c915b37326 100644
--- a/src/server/game/DataStores/DB2fmt.h
+++ b/src/server/game/DataStores/DB2fmt.h
@@ -24,10 +24,14 @@ char const BroadcastTextFormat[] = "nissiiiiiiiii";
char const CurrencyTypesFormat[] = "nisssiiiiiis";
char const CurvePointFormat[] = "niiff";
char const GameObjectsFormat[] = "niiffffffffiiiiiiiiiiiis";
+char const GarrAbilityFormat[] = "nissiii";
char const GarrBuildingFormat[] = "niiiiissssiiiiiiiiiiiiii";
-char const GarrPlotFormat[] = "niiisiiii";
-char const GarrPlotBuildingFormat[] = "nii";
char const GarrBuildingPlotInstFormat[] = "niiiff";
+char const GarrClassSpecFormat[] = "nsssii";
+char const GarrFollowerFormat[] = "niiiiiiiiiiiiiissiiii";
+char const GarrFollowerXAbilityFormat[] = "niii";
+char const GarrPlotBuildingFormat[] = "nii";
+char const GarrPlotFormat[] = "niiisiiii";
char const GarrPlotInstanceFormat[] = "nis";
char const GarrSiteLevelFormat[] = "niiiiffiiii";
char const GarrSiteLevelPlotInstFormat[] = "niiffi";
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/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index 4294eb57dbd..15e560a8e7e 100644
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -59,7 +59,7 @@ void Corpse::RemoveFromWorld()
if (IsInWorld())
GetMap()->GetObjectsStore().Remove<Corpse>(GetGUID());
- Object::RemoveFromWorld();
+ WorldObject::RemoveFromWorld();
}
bool Corpse::Create(ObjectGuid::LowType guidlow, Map* map)
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 05d649fe632..82b55e23349 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -39,7 +39,7 @@
Pet::Pet(Player* owner, PetType type) :
Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false),
- m_petType(type), m_duration(0), m_auraRaidUpdateMask(0), m_loading(false),
+ m_petType(type), m_duration(0), m_groupUpdateMask(0), m_loading(false),
m_declinedname(NULL)
{
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 16ae4f7e09f..419992f3408 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;
@@ -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();
@@ -2315,17 +2311,16 @@ void Player::RemoveFromWorld()
sBattlefieldMgr->HandlePlayerLeaveZone(this, m_zoneUpdateId);
}
+ // Remove items from world before self - player must be found in Item::RemoveFromObjectUpdate
+ for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
+ if (m_items[i])
+ m_items[i]->RemoveFromWorld();
+
///- Do not add/remove the player from the object storage
///- It will crash when updating the ObjectAccessor
///- The player should only be removed when logging out
Unit::RemoveFromWorld();
- for (uint8 i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; ++i)
- {
- if (m_items[i])
- m_items[i]->RemoveFromWorld();
- }
-
for (ItemMap::iterator iter = mMitems.begin(); iter != mMitems.end(); ++iter)
iter->second->RemoveFromWorld();
@@ -6209,6 +6204,22 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
return false;
}
break;
+ case ACTION_BUTTON_MOUNT:
+ {
+ auto mount = sDB2Manager.GetMountById(action);
+ if (!mount)
+ {
+ TC_LOG_ERROR("entities.player", "Mount action %u not added into button %u for player %s (%s): mount does not exist", action, button, GetName().c_str(), GetGUID().ToString().c_str());
+ return false;
+ }
+
+ if (!HasSpell(mount->SpellId))
+ {
+ TC_LOG_ERROR("entities.player", "Mount action %u not added into button %u for player %s (%s): Player does not know this mount", action, button, GetName().c_str(), GetGUID().ToString().c_str());
+ return false;
+ }
+ break;
+ }
case ACTION_BUTTON_C:
case ACTION_BUTTON_CMACRO:
case ACTION_BUTTON_MACRO:
@@ -7372,7 +7383,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;
@@ -17335,7 +17350,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
_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)))
@@ -17354,19 +17369,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)
{
@@ -17374,7 +17389,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());
}
@@ -18542,12 +18557,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);
@@ -18558,27 +18568,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();
- 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;
+ lockInfos.Locked = lockInfos.TimeRemaining <= 0;
+ lockInfos.Extended = false;
+
+ 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
@@ -19403,13 +19414,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);
@@ -20205,7 +20216,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
GetSession()->SendPacket(&data);
if (GetGroup())
- SetGroupUpdateFlag(GROUP_UPDATE_PET);
+ SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET);
}
}
@@ -20244,7 +20255,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);
}
@@ -20254,7 +20265,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);
}
@@ -20264,7 +20275,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));
}
@@ -20277,7 +20288,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());
}
@@ -20294,14 +20305,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())
@@ -22269,7 +22280,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi
m_clientGUIDs.erase(target->GetGUID());
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (%s) is out of range for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %s (%u) is out of range for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
#endif
}
}
@@ -22281,7 +22292,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi
UpdateVisibilityOf_helper(m_clientGUIDs, target, visibleNow);
#ifdef TRINITY_DEBUG
- TC_LOG_DEBUG("maps", "Object %u (%s) is visible now for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
+ TC_LOG_DEBUG("maps", "Object %s (%u) is visible now for %s. Distance = %f", target->GetGUID().ToString().c_str(), target->GetEntry(), GetGUID().ToString().c_str(), GetDistance(target));
#endif
}
}
@@ -22621,9 +22632,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)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7de2b09a5cb..c7af9426623 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;
@@ -311,6 +309,7 @@ enum ActionButtonType
ACTION_BUTTON_DROPDOWN = 0x30,
ACTION_BUTTON_MACRO = 0x40,
ACTION_BUTTON_CMACRO = ACTION_BUTTON_C | ACTION_BUTTON_MACRO,
+ ACTION_BUTTON_MOUNT = 0x60,
ACTION_BUTTON_ITEM = 0x80
};
@@ -1324,7 +1323,6 @@ private:
PlayerTalentInfo(PlayerTalentInfo const&);
};
-
class Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
@@ -1737,8 +1735,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;
@@ -2522,8 +2521,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;
@@ -2889,7 +2887,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 +2909,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 81497029e55..7034f7fbdc5 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -36,7 +36,7 @@
Transport::Transport() : GameObject(),
_transportInfo(NULL), _isMoving(true), _pendingStop(false),
_triggeredArrivalEvent(false), _triggeredDepartureEvent(false),
- _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false)
+ _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false), _delayedTeleport(false)
{
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
}
@@ -231,6 +231,14 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
+void Transport::DelayedUpdate(uint32 diff)
+{
+ if (GetKeyFrames().size() <= 1)
+ return;
+
+ DelayedTeleportTransport();
+}
+
void Transport::AddPassenger(WorldObject* passenger)
{
if (!IsInWorld())
@@ -607,36 +615,8 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
if (oldMap->GetId() != newMapid)
{
- Map* newMap = sMapMgr->CreateBaseMap(newMapid);
+ _delayedTeleport = true;
UnloadStaticPassengers();
- GetMap()->RemoveFromMap<Transport>(this, false);
- SetMap(newMap);
-
- for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();)
- {
- WorldObject* obj = (*_passengerTeleportItr++);
-
- float destX, destY, destZ, destO;
- obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
- TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
-
- switch (obj->GetTypeId())
- {
- case TYPEID_PLAYER:
- if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
- RemovePassenger(obj);
- break;
- case TYPEID_DYNAMICOBJECT:
- obj->AddObjectToRemoveList();
- break;
- default:
- RemovePassenger(obj);
- break;
- }
- }
-
- Relocate(x, y, z, o);
- GetMap()->AddToMap<Transport>(this);
return true;
}
else
@@ -659,6 +639,48 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
}
}
+void Transport::DelayedTeleportTransport()
+{
+ if (!_delayedTeleport)
+ return;
+
+ _delayedTeleport = false;
+ Map* newMap = sMapMgr->CreateBaseMap(_nextFrame->Node->MapID);
+ GetMap()->RemoveFromMap<Transport>(this, false);
+ SetMap(newMap);
+
+ float x = _nextFrame->Node->Loc.X,
+ y = _nextFrame->Node->Loc.Y,
+ z = _nextFrame->Node->Loc.Z,
+ o =_nextFrame->InitialOrientation;
+
+ for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();)
+ {
+ WorldObject* obj = (*_passengerTeleportItr++);
+
+ float destX, destY, destZ, destO;
+ obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
+ TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
+
+ switch (obj->GetTypeId())
+ {
+ case TYPEID_PLAYER:
+ if (!obj->ToPlayer()->TeleportTo(_nextFrame->Node->MapID, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
+ RemovePassenger(obj);
+ break;
+ case TYPEID_DYNAMICOBJECT:
+ obj->AddObjectToRemoveList();
+ break;
+ default:
+ RemovePassenger(obj);
+ break;
+ }
+ }
+
+ Relocate(x, y, z, o);
+ GetMap()->AddToMap<Transport>(this);
+}
+
void Transport::UpdatePassengerPositions(PassengerSet& passengers)
{
for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr)
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index 193e32300c0..d6598a0036c 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -39,6 +39,7 @@ class Transport : public GameObject, public TransportBase
void CleanupsBeforeDelete(bool finalCleanup = true) override;
void Update(uint32 diff) override;
+ void DelayedUpdate(uint32 diff);
void BuildUpdate(UpdateDataMapType& data_map) override;
@@ -103,6 +104,7 @@ class Transport : public GameObject, public TransportBase
void MoveToNextWaypoint();
float CalculateSegmentPos(float perc);
bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o);
+ void DelayedTeleportTransport();
void UpdatePassengerPositions(PassengerSet& passengers);
void DoEventIfAny(KeyFrame const& node, bool departure);
@@ -127,6 +129,7 @@ class Transport : public GameObject, public TransportBase
PassengerSet _staticPassengers;
bool _delayedAddModel;
+ bool _delayedTeleport;
};
#endif
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 7ae20779fa7..a581e612980 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -6957,15 +6957,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())
@@ -11470,11 +11466,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 +11487,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 +11539,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 +11561,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 +12987,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);
}
}
@@ -16401,7 +16371,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 +16418,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/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index ba247dbd19e..0d6b971ec15 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -1266,8 +1266,12 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(*itr);
- for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr2 = creatureBounds.first; itr2 != creatureBounds.second;)
+ {
+ Creature* creature = itr2->second;
+ ++itr2;
+ creature->AddObjectToRemoveList();
+ }
});
}
}
@@ -1292,11 +1296,16 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
sMapMgr->DoForAllMapsWithMapId(data->mapid, [&itr](Map* map)
{
auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(*itr);
- for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr2 = gameobjectBounds.first; itr2 != gameobjectBounds.second;)
+ {
+ GameObject* go = itr2->second;
+ ++itr2;
+ go->AddObjectToRemoveList();
+ }
});
}
}
+
if (internal_event_id < 0 || internal_event_id >= int32(mGameEventPoolIds.size()))
{
TC_LOG_ERROR("gameevent", "GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %u (size: %zu)", internal_event_id, mGameEventPoolIds.size());
diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp
index 15387d9a9b6..3087de37472 100644
--- a/src/server/game/Garrison/Garrison.cpp
+++ b/src/server/game/Garrison/Garrison.cpp
@@ -210,6 +210,15 @@ Garrison::Plot* Garrison::GetPlot(uint32 garrPlotInstanceId)
return nullptr;
}
+Garrison::Plot const* Garrison::GetPlot(uint32 garrPlotInstanceId) const
+{
+ auto itr = _plots.find(garrPlotInstanceId);
+ if (itr != _plots.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
void Garrison::LearnBlueprint(uint32 garrBuildingId)
{
WorldPackets::Garrison::GarrisonLearnBlueprintResult learnBlueprintResult;
@@ -253,33 +262,116 @@ void Garrison::PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId)
placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr);
Plot* plot = GetPlot(garrPlotInstanceId);
+ uint32 oldBuildingId = 0;
+ Map* map = FindMap();
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(garrBuildingId);
+ if (map)
+ plot->DeleteGameObject(map);
- if (Map* map = FindMap())
+ if (plot->BuildingInfo.PacketInfo)
{
- if (!plot->BuildingInfo.Guid.IsEmpty())
- {
- if (GameObject* oldBuilding = map->GetGameObject(plot->BuildingInfo.Guid))
- oldBuilding->AddObjectToRemoveList();
-
- plot->BuildingInfo.Guid.Clear();
- }
+ oldBuildingId = plot->BuildingInfo.PacketInfo->GarrBuildingID;
+ if (sGarrBuildingStore.AssertEntry(oldBuildingId)->Type != building->Type)
+ plot->ClearBuildingInfo(_owner);
+ }
- plot->BuildingInfo.PacketInfo = placeBuildingResult.BuildingInfo;
+ plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
+ if (map)
if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
- {
map->AddToMap(go);
- GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(garrBuildingId);
- _owner->ModifyCurrency(building->CostCurrencyID, -building->CostCurrencyAmount, false, true);
- _owner->ModifyMoney(-building->CostMoney, false);
- }
- else
- plot->BuildingInfo.PacketInfo = boost::none;
+
+ _owner->ModifyCurrency(building->CostCurrencyID, -building->CostCurrencyAmount, false, true);
+ _owner->ModifyMoney(-building->CostMoney * GOLD, false);
+
+ if (oldBuildingId)
+ {
+ WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved;
+ buildingRemoved.Result = GARRISON_SUCCESS;
+ buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
+ buildingRemoved.GarrBuildingID = oldBuildingId;
+ _owner->SendDirectMessage(buildingRemoved.Write());
}
}
_owner->SendDirectMessage(placeBuildingResult.Write());
}
+void Garrison::CancelBuildingConstruction(uint32 garrPlotInstanceId)
+{
+ WorldPackets::Garrison::GarrisonBuildingRemoved buildingRemoved;
+ buildingRemoved.Result = CheckBuildingRemoval(garrPlotInstanceId);
+ if (buildingRemoved.Result == GARRISON_SUCCESS)
+ {
+ Plot* plot = GetPlot(garrPlotInstanceId);
+
+ buildingRemoved.GarrPlotInstanceID = garrPlotInstanceId;
+ buildingRemoved.GarrBuildingID = plot->BuildingInfo.PacketInfo->GarrBuildingID;
+
+ Map* map = FindMap();
+ if (map)
+ plot->DeleteGameObject(map);
+
+ plot->ClearBuildingInfo(_owner);
+ _owner->SendDirectMessage(buildingRemoved.Write());
+
+ GarrBuildingEntry const* constructing = sGarrBuildingStore.AssertEntry(buildingRemoved.GarrBuildingID);
+ // Refund construction/upgrade cost
+ _owner->ModifyCurrency(constructing->CostCurrencyID, constructing->CostCurrencyAmount, false, true);
+ _owner->ModifyMoney(constructing->CostMoney * GOLD, false);
+
+ if (constructing->Level > 1)
+ {
+ // Restore previous level building
+ GarrBuildingEntry const* restored = sGarrisonMgr.GetPreviousLevelBuilding(constructing->Type, constructing->Level);
+ ASSERT(restored);
+
+ WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult;
+ placeBuildingResult.Result = GARRISON_SUCCESS;
+ placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
+ placeBuildingResult.BuildingInfo.GarrBuildingID = restored->ID;
+ placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr);
+ placeBuildingResult.BuildingInfo.Active = true;
+
+ plot->SetBuildingInfo(placeBuildingResult.BuildingInfo, _owner);
+ _owner->SendDirectMessage(placeBuildingResult.Write());
+ }
+
+ if (map)
+ if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
+ map->AddToMap(go);
+ }
+ else
+ _owner->SendDirectMessage(buildingRemoved.Write());
+}
+
+void Garrison::AddFollower(uint32 garrFollowerId)
+{
+ WorldPackets::Garrison::GarrisonAddFollowerResult addFollowerResult;
+ GarrFollowerEntry const* followerEntry = sGarrFollowerStore.LookupEntry(garrFollowerId);
+ if (_followers.count(garrFollowerId) || !followerEntry)
+ {
+ addFollowerResult.Result = GARRISON_GENERIC_UNKNOWN_ERROR;
+ _owner->SendDirectMessage(addFollowerResult.Write());
+ return;
+ }
+
+ Follower& follower = _followers[garrFollowerId];
+ follower.PacketInfo.DbID = sGarrisonMgr.GenerateFollowerDbId();
+ follower.PacketInfo.GarrFollowerID = garrFollowerId;
+ follower.PacketInfo.Quality = followerEntry->Quality; // TODO: handle magic upgrades
+ follower.PacketInfo.FollowerLevel = followerEntry->Level;
+ follower.PacketInfo.ItemLevelWeapon = followerEntry->ItemLevelWeapon;
+ follower.PacketInfo.ItemLevelArmor = followerEntry->ItemLevelArmor;
+ follower.PacketInfo.Xp = 0;
+ follower.PacketInfo.CurrentBuildingID = 0;
+ follower.PacketInfo.CurrentMissionID = 0;
+ follower.PacketInfo.AbilityID = sGarrisonMgr.RollFollowerAbilities(followerEntry, follower.PacketInfo.Quality, GetFaction(), true);
+ follower.PacketInfo.FollowerStatus = 0;
+
+ addFollowerResult.Follower = follower.PacketInfo;
+ _owner->SendDirectMessage(addFollowerResult.Write());
+}
+
void Garrison::SendInfo()
{
WorldPackets::Garrison::GetGarrisonInfoResult garrisonInfo;
@@ -295,6 +387,9 @@ void Garrison::SendInfo()
garrisonInfo.Buildings.push_back(plot.BuildingInfo.PacketInfo.get_ptr());
}
+ for (auto const& p : _followers)
+ garrisonInfo.Followers.push_back(&p.second.PacketInfo);
+
_owner->SendDirectMessage(garrisonInfo.Write());
}
@@ -347,7 +442,8 @@ Map* Garrison::FindMap() const
GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const
{
GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
- if (!plotInstance || !_plots.count(garrPlotInstanceId))
+ Plot const* plot = GetPlot(garrPlotInstanceId);
+ if (!plotInstance || !plot)
return GARRISON_ERROR_INVALID_PLOT;
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(garrBuildingId);
@@ -357,9 +453,13 @@ GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32
if (!sGarrisonMgr.IsPlotMatchingBuilding(plotInstance->GarrPlotID, garrBuildingId))
return GARRISON_ERROR_INVALID_PLOT_BUILDING;
+ // Cannot place buldings of higher level than garrison level
+ if (building->Level > _siteLevel->Level)
+ return GARRISON_ERROR_INVALID_BUILDINGID;
+
if (building->Flags & GARRISON_BUILDING_FLAG_NEEDS_PLAN)
{
- if (_knownBuildings.count(garrBuildingId))
+ if (!_knownBuildings.count(garrBuildingId))
return GARRISON_ERROR_BLUEPRINT_NOT_KNOWN;
}
else // Building is built as a quest reward
@@ -373,7 +473,7 @@ GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32
{
existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID);
if (existingBuilding->Type == building->Type)
- if (p.first != garrPlotInstanceId || existingBuilding->Level != building->Level + 1) // check if its an upgrade in same plot
+ if (p.first != garrPlotInstanceId || existingBuilding->Level + 1 != building->Level) // check if its an upgrade in same plot
return GARRISON_ERROR_BUILDING_EXISTS;
}
}
@@ -381,9 +481,29 @@ 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)))
+ if (!_owner->HasEnoughMoney(uint64(building->CostMoney * GOLD)))
return GARRISON_ERROR_NOT_ENOUGH_GOLD;
+ // New building cannot replace another building currently under construction
+ if (plot->BuildingInfo.PacketInfo)
+ if (!plot->BuildingInfo.PacketInfo->Active)
+ return GARRISON_ERROR_NO_BUILDING;
+
+ return GARRISON_SUCCESS;
+}
+
+GarrisonError Garrison::CheckBuildingRemoval(uint32 garrPlotInstanceId) const
+{
+ Plot const* plot = GetPlot(garrPlotInstanceId);
+ if (!plot)
+ return GARRISON_ERROR_INVALID_PLOT;
+
+ if (!plot->BuildingInfo.PacketInfo)
+ return GARRISON_ERROR_NO_BUILDING;
+
+ if (plot->BuildingInfo.CanActivate())
+ return GARRISON_ERROR_BUILDING_EXISTS;
+
return GARRISON_SUCCESS;
}
@@ -395,7 +515,7 @@ GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex fact
GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.AssertEntry(PacketInfo.GarrPlotInstanceID);
GarrPlotEntry const* plot = sGarrPlotStore.AssertEntry(plotInstance->GarrPlotID);
GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(BuildingInfo.PacketInfo->GarrBuildingID);
- if (BuildingInfo.PacketInfo->TimeBuilt + building->BuildDuration <= time(nullptr) && BuildingInfo.PacketInfo->Active)
+ if (BuildingInfo.PacketInfo->Active)
entry = faction == GARRISON_FACTION_INDEX_HORDE ? building->HordeGameObjectID : building->AllianceGameObjectID;
else
entry = faction == GARRISON_FACTION_INDEX_HORDE ? plot->HordeConstructionGameObjectID : plot->AllianceConstructionGameObjectID;
@@ -419,3 +539,47 @@ GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex fact
BuildingInfo.Guid = go->GetGUID();
return go;
}
+
+void Garrison::Plot::DeleteGameObject(Map* map)
+{
+ if (BuildingInfo.Guid.IsEmpty())
+ return;
+
+ if (GameObject* oldBuilding = map->GetGameObject(BuildingInfo.Guid))
+ oldBuilding->Delete();
+
+ BuildingInfo.Guid.Clear();
+}
+
+void Garrison::Plot::ClearBuildingInfo(Player* owner)
+{
+ WorldPackets::Garrison::GarrisonPlotPlaced plotPlaced;
+ plotPlaced.PlotInfo = &PacketInfo;
+ owner->SendDirectMessage(plotPlaced.Write());
+
+ BuildingInfo.PacketInfo = boost::none;
+}
+
+void Garrison::Plot::SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner)
+{
+ if (!BuildingInfo.PacketInfo)
+ {
+ WorldPackets::Garrison::GarrisonPlotRemoved plotRemoved;
+ plotRemoved.GarrPlotInstanceID = PacketInfo.GarrPlotInstanceID;
+ owner->SendDirectMessage(plotRemoved.Write());
+ }
+
+ BuildingInfo.PacketInfo = buildingInfo;
+}
+
+bool Garrison::Building::CanActivate() const
+{
+ if (PacketInfo)
+ {
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(PacketInfo->GarrBuildingID);
+ if (PacketInfo->TimeBuilt + building->BuildDuration <= time(nullptr))
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h
index 37712386d0b..be92b9e14f3 100644
--- a/src/server/game/Garrison/Garrison.h
+++ b/src/server/game/Garrison/Garrison.h
@@ -32,6 +32,21 @@ enum GarrisonBuildingFlags
GARRISON_BUILDING_FLAG_NEEDS_PLAN = 0x1
};
+enum GarrisonFollowerFlags
+{
+ GARRISON_FOLLOWER_FLAG_UNIQUE = 0x1
+};
+
+enum GarrisonAbilityFlags
+{
+ GARRISON_ABILITY_FLAG_TRAIT = 0x01,
+ GARRISON_ABILITY_CANNOT_ROLL = 0x02,
+ GARRISON_ABILITY_HORDE_ONLY = 0x04,
+ GARRISON_ABILITY_ALLIANCE_ONLY = 0x08,
+ GARRISON_ABILITY_FLAG_CANNOT_REMOVE = 0x10,
+ GARRISON_ABILITY_FLAG_EXCLUSIVE = 0x20
+};
+
enum GarrisonError
{
GARRISON_SUCCESS = 0,
@@ -44,7 +59,9 @@ enum GarrisonError
GARRISON_ERROR_BLUEPRINT_NOT_KNOWN = 22,
GARRISON_ERROR_BUILDING_EXISTS = 24,
GARRISON_ERROR_NOT_ENOUGH_CURRENCY = 46,
- GARRISON_ERROR_NOT_ENOUGH_GOLD = 47
+ GARRISON_ERROR_NOT_ENOUGH_GOLD = 47,
+
+ GARRISON_GENERIC_UNKNOWN_ERROR = 255 // custom value for packets whose handlers only check if error != 0
};
enum GarrisonFollowerStatus
@@ -62,6 +79,8 @@ class Garrison
public:
struct Building
{
+ bool CanActivate() const;
+
ObjectGuid Guid;
Optional<WorldPackets::Garrison::GarrisonBuildingInfo> PacketInfo;
};
@@ -69,6 +88,9 @@ public:
struct Plot
{
GameObject* CreateGameObject(Map* map, GarrisonFactionIndex faction);
+ void DeleteGameObject(Map* map);
+ void ClearBuildingInfo(Player* owner);
+ void SetBuildingInfo(WorldPackets::Garrison::GarrisonBuildingInfo const& buildingInfo, Player* owner);
WorldPackets::Garrison::GarrisonPlotInfo PacketInfo;
uint32 EmptyGameObjectId = 0;
@@ -76,6 +98,11 @@ public:
Building BuildingInfo;
};
+ struct Follower
+ {
+ WorldPackets::Garrison::GarrisonFollower PacketInfo;
+ };
+
explicit Garrison(Player* owner);
bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings);
@@ -88,12 +115,20 @@ public:
void Leave() const;
GarrisonFactionIndex GetFaction() const;
+
+ // Plots
std::vector<Plot*> GetPlots();
Plot* GetPlot(uint32 garrPlotInstanceId);
+ Plot const* GetPlot(uint32 garrPlotInstanceId) const;
+ // Buildings
void LearnBlueprint(uint32 garrBuildingId);
void UnlearnBlueprint(uint32 garrBuildingId);
void PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId);
+ void CancelBuildingConstruction(uint32 garrPlotInstanceId);
+
+ // Followers
+ void AddFollower(uint32 garrFollowerId);
void SendInfo();
void SendRemoteInfo() const;
@@ -106,12 +141,14 @@ private:
Map* FindMap() const;
void InitializePlots();
GarrisonError CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const;
+ GarrisonError CheckBuildingRemoval(uint32 garrPlotInstanceId) const;
Player* _owner;
GarrSiteLevelEntry const* _siteLevel;
uint32 _followerActivationsRemainingToday;
std::unordered_map<uint32 /*garrPlotInstanceId*/, Plot> _plots;
std::unordered_set<uint32 /*garrBuildingId*/> _knownBuildings;
+ std::unordered_map<uint64 /*dbId*/, Follower> _followers;
};
#endif // Garrison_h__
diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp
index 4e7266c0855..75f4289c385 100644
--- a/src/server/game/Garrison/GarrisonMgr.cpp
+++ b/src/server/game/Garrison/GarrisonMgr.cpp
@@ -16,7 +16,10 @@
*/
#include "GarrisonMgr.h"
+#include "Containers.h"
+#include "Garrison.h"
#include "ObjectDefines.h"
+#include "World.h"
void GarrisonMgr::Initialize()
{
@@ -32,6 +35,26 @@ void GarrisonMgr::Initialize()
for (GarrBuildingPlotInstEntry const* buildingPlotInst : sGarrBuildingPlotInstStore)
_garrisonBuildingPlotInstances[MAKE_PAIR64(buildingPlotInst->GarrBuildingID, buildingPlotInst->GarrSiteLevelPlotInstID)] = buildingPlotInst->ID;
+
+ for (GarrBuildingEntry const* building : sGarrBuildingStore)
+ _garrisonBuildingsByType[building->Type].push_back(building);
+
+ for (GarrFollowerXAbilityEntry const* followerAbility : sGarrFollowerXAbilityStore)
+ {
+ if (GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(followerAbility->GarrAbilityID))
+ {
+ if (!(ability->Flags & GARRISON_ABILITY_CANNOT_ROLL) && ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
+ _garrisonFollowerRandomTraits.insert(ability);
+
+ if (followerAbility->FactionIndex < 2)
+ {
+ if (ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
+ _garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Traits.insert(ability);
+ else
+ _garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Counters.insert(ability);
+ }
+ }
+ }
}
GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
@@ -82,3 +105,167 @@ uint32 GarrisonMgr::GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSi
return 0;
}
+
+GarrBuildingEntry const* GarrisonMgr::GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const
+{
+ auto itr = _garrisonBuildingsByType.find(buildingType);
+ if (itr != _garrisonBuildingsByType.end())
+ for (GarrBuildingEntry const* building : itr->second)
+ if (building->Level == currentLevel - 1)
+ return building;
+
+ return nullptr;
+}
+
+uint64 GarrisonMgr::GenerateFollowerDbId()
+{
+ if (_followerDbIdGenerator >= std::numeric_limits<uint64>::max())
+ {
+ TC_LOG_ERROR("misc", "Garrison follower db id overflow! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
+ }
+
+ return _followerDbIdGenerator++;
+}
+
+uint32 const AbilitiesForQuality[][2] =
+{
+ // Counters, Traits
+ { 0, 0 },
+ { 1, 0 },
+ { 1, 1 }, // Uncommon
+ { 1, 2 }, // Rare
+ { 2, 3 }, // Epic
+ { 2, 3 } // Legendary
+};
+
+std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
+{
+ ASSERT(faction < 2);
+
+ bool hasForcedExclusiveTrait = false;
+ std::list<GarrAbilityEntry const*> result;
+ int32 slots[2] = { AbilitiesForQuality[quality][0], AbilitiesForQuality[quality][1] };
+
+ GarrAbilities const* abilities = nullptr;
+ auto itr = _garrisonFollowerAbilities[faction].find(follower->ID);
+ if (itr != _garrisonFollowerAbilities[faction].end())
+ abilities = &itr->second;
+
+ std::list<GarrAbilityEntry const*> abilityList, forcedAbilities, traitList, forcedTraits;
+ if (abilities)
+ {
+ for (GarrAbilityEntry const* ability : abilities->Counters)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
+ forcedAbilities.push_back(ability);
+ else
+ abilityList.push_back(ability);
+ }
+
+ for (GarrAbilityEntry const* ability : abilities->Traits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
+ forcedTraits.push_back(ability);
+ else
+ traitList.push_back(ability);
+ }
+ }
+
+ Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
+ Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
+
+ // Add counters specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation
+ if (initial)
+ {
+ forcedAbilities.splice(forcedAbilities.end(), abilityList);
+ forcedTraits.splice(forcedTraits.end(), traitList);
+ }
+
+ // check if we have a trait from exclusive category
+ for (GarrAbilityEntry const* ability : forcedTraits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ {
+ hasForcedExclusiveTrait = true;
+ break;
+ }
+ }
+
+ if (slots[0] > forcedAbilities.size() + abilityList.size())
+ {
+ std::list<GarrAbilityEntry const*> classSpecAbilities; // = GetDefaultClassSpecAbilities(follower, faction)
+
+ abilityList.splice(abilityList.end(), classSpecAbilities);
+ abilityList.sort();
+ abilityList.unique();
+
+ Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
+ }
+
+ if (slots[1] > forcedTraits.size() + traitList.size())
+ {
+ std::list<GarrAbilityEntry const*> genericTraits;
+ for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ // forced exclusive trait exists, skip other ones entirely
+ if (hasForcedExclusiveTrait && ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ continue;
+
+ genericTraits.push_back(ability);
+ }
+
+ genericTraits.splice(genericTraits.begin(), traitList);
+ // "split" the list into two parts [nonexclusive, exclusive] to make selection later easier
+ genericTraits.sort([](GarrAbilityEntry const* a1, GarrAbilityEntry const* a2)
+ {
+ uint32 e1 = a1->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
+ uint32 e2 = a2->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE;
+ if (e1 != e2)
+ return e1 < e2;
+
+ return a1->ID < a2->ID;
+ });
+ genericTraits.unique();
+
+ std::size_t firstExclusive = 0, total = genericTraits.size();
+ for (auto itr = genericTraits.begin(); itr != genericTraits.end(); ++itr, ++firstExclusive)
+ if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ break;
+
+ while (traitList.size() < std::max<int32>(0, slots[1] - forcedTraits.size()) && !genericTraits.empty())
+ {
+ auto itr = genericTraits.begin();
+ std::advance(itr, urand(0, total-- - 1));
+ if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE)
+ total = firstExclusive; // selected exclusive trait - no other can be selected now
+ else
+ --firstExclusive;
+
+ traitList.push_back(*itr);
+ genericTraits.erase(itr);
+ }
+ }
+
+ result.splice(result.end(), forcedAbilities);
+ result.splice(result.end(), abilityList);
+ result.splice(result.end(), forcedTraits);
+ result.splice(result.end(), traitList);
+
+ return result;
+}
diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h
index 1b96f9ca27e..a54606dd9b1 100644
--- a/src/server/game/Garrison/GarrisonMgr.h
+++ b/src/server/game/Garrison/GarrisonMgr.h
@@ -18,9 +18,14 @@
#ifndef GarrisonMgr_h__
#define GarrisonMgr_h__
+#include "DB2Stores.h"
#include <unordered_set>
-#include "DB2Stores.h"
+struct GarrAbilities
+{
+ std::unordered_set<GarrAbilityEntry const*> Counters;
+ std::unordered_set<GarrAbilityEntry const*> Traits;
+};
class GarrisonMgr
{
@@ -38,12 +43,20 @@ public:
GameObjectsEntry const* GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const;
bool IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const;
uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const;
+ GarrBuildingEntry const* GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const;
+ uint64 GenerateFollowerDbId();
+ std::list<GarrAbilityEntry const*> RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const;
private:
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;
+
+ uint64 _followerDbIdGenerator;
};
#define sGarrisonMgr GarrisonMgr::Instance()
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index ac87f58af5c..10288cff927 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))
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..e14ca6c976b 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -38,10 +38,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 +85,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 +173,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 +194,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 +224,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 +232,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;
@@ -254,7 +306,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 +322,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 +343,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 +402,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 +414,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..0225c9405ce 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -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/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index b5550c2c073..b9fd383b19d 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -288,7 +288,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false, group->GetMemberGroup(GetPlayer()->GetGUID()));
break;
}
@@ -320,8 +320,8 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
}
case CHAT_MSG_RAID:
{
- Group* group = GetPlayer()->GetOriginalGroup();
- if (!group)
+ Group* group = GetPlayer()->GetGroup();
+ if (!group || !group->isRaidGroup() || group->isBGGroup())
return;
if (group->IsLeader(GetPlayer()->GetGUID()))
@@ -330,7 +330,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -344,7 +344,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
WorldPackets::Chat::Chat packet;
//in battleground, raid warning is sent only to players in battleground - code is ok
- packet.Initalize(CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
+ packet.Initialize(CHAT_MSG_RAID_WARNING, Language(lang), sender, NULL, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -381,7 +381,7 @@ void WorldSession::HandleChatMessage(ChatMsg type, uint32 lang, std::string msg,
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
WorldPackets::Chat::Chat packet;
- packet.Initalize(ChatMsg(type), Language(lang), sender, nullptr, msg);
+ packet.Initialize(ChatMsg(type), Language(lang), sender, nullptr, msg);
group->BroadcastPacket(packet.Write(), false);
break;
}
@@ -484,7 +484,7 @@ void WorldSession::HandleChatAddonMessage(ChatMsg type, std::string prefix, std:
}
WorldPackets::Chat::Chat packet;
- packet.Initalize(type, LANG_ADDON, sender, nullptr, text, 0, "", DEFAULT_LOCALE, prefix);
+ packet.Initialize(type, LANG_ADDON, sender, nullptr, text, 0, "", DEFAULT_LOCALE, prefix);
group->BroadcastAddonMessagePacket(packet.Write(), prefix, true, subGroup, sender->GetGUID());
break;
}
@@ -666,7 +666,7 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recvData)
return;
WorldPackets::Chat::Chat packet;
- packet.Initalize(CHAT_MSG_IGNORED, LANG_UNIVERSAL, _player, _player, GetPlayer()->GetName());
+ packet.Initialize(CHAT_MSG_IGNORED, LANG_UNIVERSAL, _player, _player, GetPlayer()->GetName());
player->SendDirectMessage(packet.Write());
}
diff --git a/src/server/game/Handlers/GarrisonHandler.cpp b/src/server/game/Handlers/GarrisonHandler.cpp
index 0b45fb0ab57..54c7f4242fd 100644
--- a/src/server/game/Handlers/GarrisonHandler.cpp
+++ b/src/server/game/Handlers/GarrisonHandler.cpp
@@ -34,6 +34,15 @@ void WorldSession::HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::Garris
garrison->PlaceBuilding(garrisonPurchaseBuilding.PlotInstanceID, garrisonPurchaseBuilding.BuildingID);
}
+void WorldSession::HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction)
+{
+ if (!_player->GetNPCIfCanInteractWith(garrisonCancelConstruction.NpcGUID, UNIT_NPC_FLAG_GARRISON_ARCHITECT))
+ return;
+
+ if (Garrison* garrison = _player->GetGarrison())
+ garrison->CancelBuildingConstruction(garrisonCancelConstruction.PlotInstanceID);
+}
+
void WorldSession::HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& /*garrisonRequestBlueprintAndSpecializationData*/)
{
if (Garrison* garrison = _player->GetGarrison())
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 9552c9a0655..4aef42fed8d 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,103 @@ 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;
+ if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
+ 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);
- }
+ ObjectGuid guid = GetPlayer()->GetGUID();
+
+ 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/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..1715e1643ea 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1213,129 +1213,28 @@ 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++)
+ loadCUFProfiles.CUFProfiles.push_back(player->GetCUFProfile(i));
+ 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/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 7398da99a06..26a3d38635d 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2600,7 +2600,7 @@ void Map::SendObjectUpdates()
while (!_updateObjects.empty())
{
Object* obj = *_updateObjects.begin();
- ASSERT(obj && obj->IsInWorld());
+ ASSERT(obj->IsInWorld());
_updateObjects.erase(_updateObjects.begin());
obj->BuildUpdate(update_players);
}
@@ -2616,6 +2616,17 @@ void Map::SendObjectUpdates()
void Map::DelayedUpdate(const uint32 t_diff)
{
+ for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
+ {
+ Transport* transport = *_transportsUpdateIter;
+ ++_transportsUpdateIter;
+
+ if (!transport->IsInWorld())
+ continue;
+
+ transport->DelayedUpdate(t_diff);
+ }
+
RemoveAllObjectsInRemoveList();
// Don't unload grids if it's battleground, since we may have manually added GOs, creatures, those doesn't load from DB at grid re-load !
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/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index ed004c6174d..03cde264734 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,
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index 0343e92c506..117891140da 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -162,12 +162,14 @@ bool OPvPCapturePoint::DelCreature(uint32 type)
}
auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(spawnId);
- for (auto itr = bounds.first; itr != bounds.second; ++itr)
+ for (auto itr = bounds.first; itr != bounds.second;)
{
+ Creature* c = itr->second;
+ ++itr;
// Don't save respawn time
- itr->second->SetRespawnTime(0);
- itr->second->RemoveCorpse();
- itr->second->AddObjectToRemoveList();
+ c->SetRespawnTime(0);
+ c->RemoveCorpse();
+ c->AddObjectToRemoveList();
}
TC_LOG_DEBUG("outdoorpvp", "deleting opvp creature type %u", type);
@@ -196,11 +198,13 @@ bool OPvPCapturePoint::DelObject(uint32 type)
ObjectGuid::LowType spawnId = m_Objects[type];
auto bounds = m_PvP->GetMap()->GetGameObjectBySpawnIdStore().equal_range(spawnId);
- for (auto itr = bounds.first; itr != bounds.second; ++itr)
+ for (auto itr = bounds.first; itr != bounds.second;)
{
+ GameObject* go = itr->second;
+ ++itr;
// Don't save respawn time
- itr->second->SetRespawnTime(0);
- itr->second->Delete();
+ go->SetRespawnTime(0);
+ go->Delete();
}
sObjectMgr->DeleteGOData(spawnId);
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 15f378e138a..a82652d2f03 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -225,8 +225,12 @@ void PoolGroup<Creature>::Despawn1Object(uint64 guid)
if (!map->Instanceable())
{
auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid);
- for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr = creatureBounds.first; itr != creatureBounds.second;)
+ {
+ Creature* creature = itr->second;
+ ++itr;
+ creature->AddObjectToRemoveList();
+ }
}
}
}
@@ -243,8 +247,12 @@ void PoolGroup<GameObject>::Despawn1Object(uint64 guid)
if (!map->Instanceable())
{
auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid);
- for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second; ++itr)
- itr->second->AddObjectToRemoveList();
+ for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;)
+ {
+ GameObject* go = itr->second;
+ ++itr;
+ go->AddObjectToRemoveList();
+ }
}
}
}
diff --git a/src/server/game/Server/Packets/ChannelPackets.cpp b/src/server/game/Server/Packets/ChannelPackets.cpp
index 5acb018b46f..c8779052c95 100644
--- a/src/server/game/Server/Packets/ChannelPackets.cpp
+++ b/src/server/game/Server/Packets/ChannelPackets.cpp
@@ -83,6 +83,49 @@ WorldPacket const* WorldPackets::Channel::ChannelNotifyLeft::Write()
return &_worldPacket;
}
+WorldPacket const* WorldPackets::Channel::UserlistAdd::Write()
+{
+ _worldPacket << AddedUserGUID;
+ _worldPacket << uint8(ChannelFlags);
+ _worldPacket << uint8(UserFlags);
+
+ _worldPacket << uint32(ChannelID);
+
+ _worldPacket.WriteBits(ChannelName.length(), 7);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(ChannelName);
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Channel::UserlistRemove::Write()
+{
+ _worldPacket << RemovedUserGUID;
+
+ _worldPacket << uint8(ChannelFlags);
+
+ _worldPacket << uint32(ChannelID);
+
+ _worldPacket.WriteBits(ChannelName.length(), 7);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(ChannelName);
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Channel::UserlistUpdate::Write()
+{
+ _worldPacket << UpdatedUserGUID;
+
+ _worldPacket << uint8(ChannelFlags);
+ _worldPacket << uint8(UserFlags);
+
+ _worldPacket << uint32(ChannelID);
+
+ _worldPacket.WriteBits(ChannelName.length(), 7);
+ _worldPacket.FlushBits();
+ _worldPacket.WriteString(ChannelName);
+ return &_worldPacket;
+}
+
void WorldPackets::Channel::ChannelPlayerCommand::Read()
{
switch (GetOpcode())
diff --git a/src/server/game/Server/Packets/ChannelPackets.h b/src/server/game/Server/Packets/ChannelPackets.h
index ca47c76edc9..8dba1e84677 100644
--- a/src/server/game/Server/Packets/ChannelPackets.h
+++ b/src/server/game/Server/Packets/ChannelPackets.h
@@ -95,6 +95,56 @@ namespace WorldPackets
bool Suspended = false; ///< User Leave - false, On Zone Change - true
};
+ class UserlistAdd final : public ServerPacket
+ {
+ public:
+ UserlistAdd() : ServerPacket(SMSG_USERLIST_ADD, 30) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid AddedUserGUID;
+
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 UserFlags = MEMBER_FLAG_NONE;
+
+ int32 ChannelID = 0;
+
+ std::string ChannelName;
+ };
+
+ class UserlistRemove final : public ServerPacket
+ {
+ public:
+ UserlistRemove() : ServerPacket(SMSG_USERLIST_REMOVE, 30) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid RemovedUserGUID;
+
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+
+ uint32 ChannelID = 0;
+
+ std::string ChannelName;
+ };
+
+ class UserlistUpdate final : public ServerPacket
+ {
+ public:
+ UserlistUpdate() : ServerPacket(SMSG_USERLIST_UPDATE, 30) { }
+
+ WorldPacket const* Write() override;
+
+ ObjectGuid UpdatedUserGUID;
+
+ uint8 ChannelFlags = CHANNEL_FLAG_NONE;
+ uint8 UserFlags = MEMBER_FLAG_NONE;
+
+ int32 ChannelID = 0;
+
+ std::string ChannelName;
+ };
+
class ChannelPlayerCommand final : public ClientPacket
{
public:
diff --git a/src/server/game/Server/Packets/ChatPackets.cpp b/src/server/game/Server/Packets/ChatPackets.cpp
index 260770e65fe..e3df4f5a15d 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
diff --git a/src/server/game/Server/Packets/ChatPackets.h b/src/server/game/Server/Packets/ChatPackets.h
index 5bc55952168..3bfac840ecc 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
diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp
index 09097450486..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);
- if (!follower.AbilityID.empty())
- data.append(follower.AbilityID.data(), follower.AbilityID.size());
+ for (GarrAbilityEntry const* ability : follower.AbilityID)
+ data << uint32(ability->ID);
return data;
}
@@ -155,12 +155,27 @@ WorldPacket const* WorldPackets::Garrison::GarrisonPlaceBuildingResult::Write()
{
_worldPacket << uint32(Result);
_worldPacket << BuildingInfo;
- _worldPacket.WriteBit(Active);
+ _worldPacket.WriteBit(PlayActivationCinematic);
_worldPacket.FlushBits();
return &_worldPacket;
}
+void WorldPackets::Garrison::GarrisonCancelConstruction::Read()
+{
+ _worldPacket >> NpcGUID;
+ _worldPacket >> PlotInstanceID;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonBuildingRemoved::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << uint32(GarrPlotInstanceID);
+ _worldPacket << uint32(GarrBuildingID);
+
+ return &_worldPacket;
+}
+
WorldPacket const* WorldPackets::Garrison::GarrisonLearnBlueprintResult::Write()
{
_worldPacket << uint32(Result);
@@ -208,3 +223,25 @@ WorldPacket const* WorldPackets::Garrison::GarrisonBuildingLandmarks::Write()
return &_worldPacket;
}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonPlotPlaced::Write()
+{
+ _worldPacket << *PlotInfo;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonPlotRemoved::Write()
+{
+ _worldPacket << uint32(GarrPlotInstanceID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Garrison::GarrisonAddFollowerResult::Write()
+{
+ _worldPacket << uint32(Result);
+ _worldPacket << Follower;
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h
index c632a5d6103..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::vector<uint32> AbilityID;
+ std::list<GarrAbilityEntry const*> AbilityID;
uint32 FollowerStatus;
};
@@ -102,9 +103,9 @@ namespace WorldPackets
uint32 FactionIndex = 0;
uint32 NumFollowerActivationsRemaining = 0;
std::vector<GarrisonPlotInfo*> Plots;
- std::vector<GarrisonBuildingInfo*> Buildings;
- std::vector<GarrisonFollower*> Followers;
- std::vector<GarrisonMission*> Missions;
+ std::vector<GarrisonBuildingInfo const*> Buildings;
+ std::vector<GarrisonFollower const*> Followers;
+ std::vector<GarrisonMission const*> Missions;
std::vector<int32> ArchivedMissions;
};
@@ -154,7 +155,30 @@ namespace WorldPackets
uint32 Result = 0;
GarrisonBuildingInfo BuildingInfo;
- bool Active = false;
+ bool PlayActivationCinematic = false;
+ };
+
+ class GarrisonCancelConstruction final : public ClientPacket
+ {
+ public:
+ GarrisonCancelConstruction(WorldPacket&& packet) : ClientPacket(CMSG_GARRISON_CANCEL_CONSTRUCTION, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid NpcGUID;
+ uint32 PlotInstanceID = 0;
+ };
+
+ class GarrisonBuildingRemoved final : public ServerPacket
+ {
+ public:
+ GarrisonBuildingRemoved() : ServerPacket(SMSG_GARRISON_BUILDING_REMOVED, 4 + 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 Result = 0;
+ uint32 GarrPlotInstanceID = 0;
+ uint32 GarrBuildingID = 0;
};
class GarrisonLearnBlueprintResult final : public ServerPacket
@@ -224,6 +248,37 @@ namespace WorldPackets
std::vector<GarrisonBuildingLandmark> Landmarks;
};
+
+ class GarrisonPlotPlaced final : public ServerPacket
+ {
+ public:
+ GarrisonPlotPlaced() : ServerPacket(SMSG_GARRISON_PLOT_PLACED) { }
+
+ WorldPacket const* Write() override;
+
+ GarrisonPlotInfo* PlotInfo = nullptr;
+ };
+
+ class GarrisonPlotRemoved final : public ServerPacket
+ {
+ public:
+ GarrisonPlotRemoved() : ServerPacket(SMSG_GARRISON_PLOT_REMOVED, 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 GarrPlotInstanceID = 0;
+ };
+
+ class GarrisonAddFollowerResult final : public ServerPacket
+ {
+ public:
+ GarrisonAddFollowerResult() : ServerPacket(SMSG_GARRISON_ADD_FOLLOWER_RESULT, 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 5 * 4 + 4) { }
+
+ WorldPacket const* Write() override;
+
+ GarrisonFollower Follower;
+ uint32 Result = 0;
+ };
}
}
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/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/PartyPackets.cpp b/src/server/game/Server/Packets/PartyPackets.cpp
new file mode 100644
index 00000000000..9696cb6a3fc
--- /dev/null
+++ b/src/server/game/Server/Packets/PartyPackets.cpp
@@ -0,0 +1,716 @@
+/*
+ * 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"
+
+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.FlushBits();
+
+ _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/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 6efac892cf9..9b30be91ee3 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);
@@ -315,7 +316,7 @@ void OpcodeTable::Initialize()
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);
@@ -370,7 +371,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_GAME_OBJ_REPORT_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::GameObject::GameObjReportUse, &WorldSession::HandleGameobjectReportUse);
DEFINE_HANDLER(CMSG_GAME_OBJ_USE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::GameObject::GameObjUse, &WorldSession::HandleGameObjectUseOpcode);
DEFINE_HANDLER(CMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_GARRISON_CANCEL_CONSTRUCTION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_GARRISON_CANCEL_CONSTRUCTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Garrison::GarrisonCancelConstruction, &WorldSession::HandleGarrisonCancelConstruction);
DEFINE_HANDLER(CMSG_GARRISON_CHECK_UPGRADEABLE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_COMPLETE_MISSION, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_GARRISON_GENERATE_RECRUITS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
@@ -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);
@@ -1109,12 +1110,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_SPEED_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_TIME_SET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GAME_TIME_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_FOLLOWER_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_FOLLOWER_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ADD_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_ASSIGN_FOLLOWER_TO_BUILDING_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_ACTIVATED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_LANDMARKS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_REMOVED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_BUILDING_SET_ACTIVE_SPECIALIZATION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_COMPLETE_MISSION_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_CREATE_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
@@ -1134,8 +1135,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_MISSION_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_OPEN_TRADESKILL_NPC, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLACE_BUILDING_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_PLACED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_PLOT_REMOVED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_LAST_USED_TIME, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECALL_PORTAL_USED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_GARRISON_RECRUITMENT_FOLLOWERS_GENERATED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
@@ -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);
@@ -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);
@@ -1719,9 +1720,9 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WEEKLY_SPELL_USAGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_USE_EQUIPMENT_SET_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_VENDOR_INVENTORY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_VIGNETTE_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index da7cbbe8020..d8bad3d4933 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -171,6 +171,9 @@ namespace WorldPackets
class ChannelPlayerCommand;
class JoinChannel;
class LeaveChannel;
+ class UserlistAdd;
+ class UserlistRemove;
+ class UserlistUpdate;
}
namespace Chat
@@ -218,6 +221,7 @@ namespace WorldPackets
{
class GetGarrisonInfo;
class GarrisonPurchaseBuilding;
+ class GarrisonCancelConstruction;
class GarrisonRequestBlueprintAndSpecializationData;
class GarrisonGetBuildingLandmarks;
}
@@ -274,6 +278,11 @@ namespace WorldPackets
class RequestHonorStats;
}
+ namespace Instance
+ {
+ class InstanceInfo;
+ }
+
namespace Item
{
class AutoEquipItem;
@@ -337,6 +346,8 @@ namespace WorldPackets
class CompleteCinematic;
class NextCinematicCamera;
class FarSight;
+ class LoadCUFProfiles;
+ class SaveCUFProfiles;
}
namespace Movement
@@ -359,6 +370,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;
@@ -854,8 +906,6 @@ class WorldSession
void SendNotInArenaTeamPacket(uint8 type);
void SendPetitionShowList(ObjectGuid guid);
- void BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data);
-
void DoLootRelease(ObjectGuid lguid);
// Account mute time
@@ -1050,28 +1100,31 @@ class WorldSession
void HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped& moveTimeSkipped);
void HandleMovementAckMessage(WorldPackets::Movement::MovementAckMessage& movementAck);
- void HandleRequestRaidInfoOpcode(WorldPacket& recvData);
+ void HandleRequestRaidInfoOpcode(WorldPackets::Party::RequestRaidInfo& packet);
- void HandleGroupInviteOpcode(WorldPacket& recvPacket);
+ void HandlePartyInviteOpcode(WorldPackets::Party::PartyInviteClient& packet);
//void HandleGroupCancelOpcode(WorldPacket& recvPacket);
- void HandleGroupInviteResponseOpcode(WorldPacket& recvPacket);
- void HandleGroupUninviteOpcode(WorldPacket& recvPacket);
- void HandleGroupSetLeaderOpcode(WorldPacket& recvPacket);
- void HandleGroupSetRolesOpcode(WorldPacket& recvData);
- void HandleGroupDisbandOpcode(WorldPacket& recvPacket);
- void HandleOptOutOfLootOpcode(WorldPacket& recvData);
- void HandleLootMethodOpcode(WorldPacket& recvPacket);
+ void HandlePartyInviteResponseOpcode(WorldPackets::Party::PartyInviteResponse& packet);
+ void HandlePartyUninviteOpcode(WorldPackets::Party::PartyUninvite& packet);
+ void HandleSetPartyLeaderOpcode(WorldPackets::Party::SetPartyLeader& packet);
+ void HandleSetRoleOpcode(WorldPackets::Party::SetRole& packet);
+ void HandleLeaveGroupOpcode(WorldPackets::Party::LeaveGroup& packet);
+ void HandleOptOutOfLootOpcode(WorldPackets::Party::OptOutOfLoot& packet);
+ void HandleSetLootMethodOpcode(WorldPackets::Party::SetLootMethod& packet);
void HandleLootRoll(WorldPackets::Loot::LootRoll& packet);
- void HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData);
- void HandleRaidTargetUpdateOpcode(WorldPacket& recvData);
- void HandleRaidReadyCheckOpcode(WorldPacket& recvData);
- void HandleGroupRaidConvertOpcode(WorldPacket& recvData);
- void HandleGroupRequestJoinUpdates(WorldPacket& recvData);
- void HandleGroupChangeSubGroupOpcode(WorldPacket& recvData);
- void HandleGroupSwapSubGroupOpcode(WorldPacket& recvData);
- void HandleGroupAssistantLeaderOpcode(WorldPacket& recvData);
+ void HandleRequestPartyMemberStatsOpcode(WorldPackets::Party::RequestPartyMemberStats& packet);
+ void HandleUpdateRaidTargetOpcode(WorldPackets::Party::UpdateRaidTarget& packet);
+ void HandleDoReadyCheckOpcode(WorldPackets::Party::DoReadyCheck& packet);
+ void HandleReadyCheckResponseOpcode(WorldPackets::Party::ReadyCheckResponseClient& packet);
+ void HandleConvertRaidOpcode(WorldPackets::Party::ConvertRaid& packet);
+ void HandleRequestPartyJoinUpdates(WorldPackets::Party::RequestPartyJoinUpdates& packet);
+ void HandleChangeSubGroupOpcode(WorldPackets::Party::ChangeSubGroup& packet);
+ void HandleSwapSubGroupsOpcode(WorldPackets::Party::SwapSubGroups& packet);
+ void HandleSetAssistantLeaderOpcode(WorldPackets::Party::SetAssistantLeader& packet);
void HandlePartyAssignmentOpcode(WorldPacket& recvData);
- void HandleRolePollBeginOpcode(WorldPacket& recvData);
+ void HandleInitiateRolePoll(WorldPackets::Party::InitiateRolePoll& packet);
+ void HandleSetEveryoneIsAssistant(WorldPackets::Party::SetEveryoneIsAssistant& packet);
+ void HandleClearRaidMarker(WorldPackets::Party::ClearRaidMarker& packet);
void HandleDeclinePetition(WorldPackets::Petition::DeclinePetition& packet);
void HandleOfferPetition(WorldPackets::Petition::OfferPetition& packet);
@@ -1336,7 +1389,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);
@@ -1469,12 +1522,13 @@ class WorldSession
void HandleRequestWowTokenMarketPrice(WorldPackets::Token::RequestWowTokenMarketPrice& requestWowTokenMarketPrice);
// Compact Unit Frames (4.x)
- void HandleSaveCUFProfiles(WorldPacket& recvPacket);
+ void HandleSaveCUFProfiles(WorldPackets::Misc::SaveCUFProfiles& packet);
void SendLoadCUFProfiles();
// Garrison
void HandleGetGarrisonInfo(WorldPackets::Garrison::GetGarrisonInfo& getGarrisonInfo);
void HandleGarrisonPurchaseBuilding(WorldPackets::Garrison::GarrisonPurchaseBuilding& garrisonPurchaseBuilding);
+ void HandleGarrisonCancelConstruction(WorldPackets::Garrison::GarrisonCancelConstruction& garrisonCancelConstruction);
void HandleGarrisonRequestBlueprintAndSpecializationData(WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationData& garrisonRequestBlueprintAndSpecializationData);
void HandleGarrisonGetBuildingLandmarks(WorldPackets::Garrison::GarrisonGetBuildingLandmarks& garrisonGetBuildingLandmarks);
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 7af7644d924..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);
@@ -407,6 +408,7 @@ class Spell
void EffectDestroyItem(SpellEffIndex effIndex);
void EffectLearnGarrisonBuilding(SpellEffIndex effIndex);
void EffectCreateGarrison(SpellEffIndex effIndex);
+ void EffectAddGarrisonFollower(SpellEffIndex effIndex);
typedef std::set<Aura*> UsedSpellMods;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 97e82426e9d..faa897d866f 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
@@ -294,7 +294,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectNULL, //217 SPELL_EFFECT_UPGRADE_GARRISON
&Spell::EffectNULL, //218 SPELL_EFFECT_218
&Spell::EffectNULL, //219 SPELL_EFFECT_219
- &Spell::EffectNULL, //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
+ &Spell::EffectAddGarrisonFollower, //220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
&Spell::EffectNULL, //221 SPELL_EFFECT_221
&Spell::EffectNULL, //222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
&Spell::EffectNULL, //223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
@@ -2923,7 +2923,7 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
unitTarget->ToCreature()->AI()->AttackStart(m_caster);
}
-void Spell::EffectWeaponDmg(SpellEffIndex /*effIndex*/)
+void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH_TARGET)
return;
@@ -2934,8 +2934,9 @@ void Spell::EffectWeaponDmg(SpellEffIndex /*effIndex*/)
// multiple weapon dmg effect workaround
// execute only the last weapon damage
// and handle all effects at once
- for (SpellEffectInfo const* effect : GetEffects())
+ for (uint8 index = effIndex + 1; index < MAX_SPELL_EFFECTS; ++index)
{
+ SpellEffectInfo const* effect = GetEffect(index);
if (!effect)
continue;
switch (effect->Effect)
@@ -4647,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)
@@ -5825,3 +5845,15 @@ void Spell::EffectCreateGarrison(SpellEffIndex effIndex)
unitTarget->ToPlayer()->CreateGarrison(GetEffect(effIndex)->MiscValue);
}
+
+void Spell::EffectAddGarrisonFollower(SpellEffIndex effIndex)
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
+ return;
+
+ if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (Garrison* garrison = unitTarget->ToPlayer()->GetGarrison())
+ garrison->AddFollower(GetEffect(effIndex)->MiscValue);
+}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 4db7091f971..0bdb36b988f 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
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_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index ef52f6ebd95..1af687aef08 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -168,6 +168,8 @@ public:
// fill the gameobject data and save to the db
object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMask());
+ guidLow = object->GetSpawnId();
+
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
// this is required to avoid weird behavior and memory leaks
delete object;
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index f1c4c22527b..38eae92c917 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -25,14 +25,6 @@
#include "ruby_sanctum.h"
#include "Player.h"
-/* ScriptData
-SDName: ruby_sanctum
-SDAuthors: Kaelima, Warpten
-SD%Complete: 90%
-SDComment: Based on Kaelima's initial work (half of it). Corporeality handling is a pure guess, we lack info.
-SDCategory: Chamber of Aspects
-EndScriptData */
-
enum Texts
{
// Shared
@@ -86,6 +78,8 @@ enum Spells
// Living Inferno
SPELL_BLAZING_AURA = 75885,
+ SPELL_SPAWN_LIVING_EMBERS = 75880,
+ SPELL_SUMMON_LIVING_EMBER = 75881,
// Halion Controller
SPELL_COSMETIC_FIRE_PILLAR = 76006,
@@ -142,7 +136,7 @@ enum Events
EVENT_CHECK_CORPOREALITY = 14,
EVENT_SHADOW_PULSARS_SHOOT = 15,
EVENT_TRIGGER_BERSERK = 16,
- EVENT_TWILIGHT_MENDING = 17
+ EVENT_TWILIGHT_MENDING = 17,
};
enum Actions
@@ -155,7 +149,13 @@ enum Actions
ACTION_MONITOR_CORPOREALITY = 3,
// Orb Carrier
- ACTION_SHOOT = 4
+ ACTION_SHOOT = 4,
+
+ // Living Inferno
+ ACTION_SUMMON_LIVING_EMBERS = 5,
+
+ // Meteor Flame
+ ACTION_SUMMON_FLAME = 6
};
enum Phases
@@ -173,7 +173,8 @@ enum Misc
DATA_MATERIAL_DAMAGE_TAKEN = 2,
DATA_STACKS_DISPELLED = 3,
DATA_FIGHT_PHASE = 4,
- DATA_EVADE_METHOD = 5
+ DATA_EVADE_METHOD = 5,
+ DATA_SPAWNED_FLAMES = 6,
};
enum OrbCarrierSeats
@@ -702,7 +703,7 @@ class npc_halion_controller : public CreatureScript
// The IsInCombat() check is needed because that check should be false when Halion is
// not engaged, while it would return true without as UpdateVictim() checks for
// combat state.
- if (!(_events.IsInPhase(PHASE_INTRO)) && me->IsInCombat() && !UpdateVictim())
+ if (!_events.IsInPhase(PHASE_INTRO) && me->IsInCombat() && !UpdateVictim())
{
EnterEvadeMode();
return;
@@ -893,8 +894,6 @@ class npc_halion_controller : public CreatureScript
}
};
-typedef npc_halion_controller::npc_halion_controllerAI controllerAI;
-
class npc_orb_carrier : public CreatureScript
{
public:
@@ -996,7 +995,7 @@ class npc_meteor_strike_initial : public CreatureScript
if (!owner)
return;
- // Let Halion Controller count as summoner
+ // Let Controller count as summoner
if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->JustSummoned(me);
@@ -1006,11 +1005,13 @@ class npc_meteor_strike_initial : public CreatureScript
if (HalionAI* halionAI = CAST_AI(HalionAI, owner->AI()))
{
Position const* ownerPos = halionAI->GetMeteorStrikePosition();
+ // Adjust randomness between 0 and pi.
+ float randomAdjustment = frand(static_cast<float>(M_PI / 14), static_cast<float>(13 * M_PI / 14));
float angle[4];
angle[0] = me->GetAngle(ownerPos);
- angle[1] = me->GetAngle(ownerPos) - static_cast<float>(M_PI/2);
- angle[2] = me->GetAngle(ownerPos) - static_cast<float>(-M_PI/2);
- angle[3] = me->GetAngle(ownerPos) - static_cast<float>(M_PI);
+ angle[1] = angle[0] + randomAdjustment;
+ angle[2] = angle[0] + static_cast<float>(M_PI);
+ angle[3] = angle[2] + randomAdjustment;
_meteorList.clear();
for (uint8 i = 0; i < 4; i++)
@@ -1019,7 +1020,10 @@ class npc_meteor_strike_initial : public CreatureScript
me->SetOrientation(angle[i]);
Position newPos = me->GetNearPosition(10.0f, 0.0f); // Exact distance
if (Creature* meteor = me->SummonCreature(NPC_METEOR_STRIKE_NORTH + i, newPos, TEMPSUMMON_TIMED_DESPAWN, 30000))
+ {
+ meteor->SetOrientation(angle[i]);
_meteorList.push_back(meteor);
+ }
}
}
}
@@ -1045,11 +1049,8 @@ class npc_meteor_strike : public CreatureScript
struct npc_meteor_strikeAI : public ScriptedAI
{
npc_meteor_strikeAI(Creature* creature) : ScriptedAI(creature),
- _instance(creature->GetInstanceScript())
+ _instance(creature->GetInstanceScript()), _spawnCount(0)
{
- _range = 5.0f;
- _spawnCount = 0;
-
SetCombatMovement(false);
}
@@ -1070,34 +1071,41 @@ class npc_meteor_strike : public CreatureScript
controller->AI()->JustSummoned(me);
}
- void UpdateAI(uint32 diff) override
+ void SetData(uint32 dataType, uint32 dataCount) override
{
- if (_spawnCount > 5)
- return;
+ if (dataType == DATA_SPAWNED_FLAMES)
+ _spawnCount += dataCount;
+ }
- _events.Update(diff);
+ uint32 GetData(uint32 dataType) const override
+ {
+ if (dataType == DATA_SPAWNED_FLAMES)
+ return _spawnCount;
+ return 0;
+ }
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
if (_events.ExecuteEvent() == EVENT_SPAWN_METEOR_FLAME)
{
- Position pos = me->GetNearPosition( _range, 0.0f);
-
+ Position pos = me->GetNearPosition(5.0f, 0.0f);
if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000))
{
if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->JustSummoned(flame);
- flame->CastSpell(flame, SPELL_METEOR_STRIKE_FIRE_AURA_2, true);
- ++_spawnCount;
+ flame->SetOrientation(me->GetOrientation());
+
+ flame->AI()->SetGUID(GetGUID());
+ flame->AI()->DoAction(ACTION_SUMMON_FLAME);
}
- _range += 5.0f;
- _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, 800);
}
}
private:
InstanceScript* _instance;
EventMap _events;
- float _range;
uint8 _spawnCount;
};
@@ -1107,6 +1115,70 @@ class npc_meteor_strike : public CreatureScript
}
};
+class npc_meteor_strike_flame : public CreatureScript
+{
+ public:
+ npc_meteor_strike_flame() : CreatureScript("npc_meteor_strike_flame") { }
+
+ struct npc_meteor_strike_flameAI : public ScriptedAI
+ {
+ npc_meteor_strike_flameAI(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript())
+ {
+ SetCombatMovement(false);
+ }
+
+ void SetGUID(ObjectGuid guid, int32 /*id = 0 */)
+ {
+ _rootOwnerGuid = guid;
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action != ACTION_SUMMON_FLAME || _rootOwnerGuid.IsEmpty())
+ return;
+
+ me->CastSpell(me, SPELL_METEOR_STRIKE_FIRE_AURA_2, true);
+
+ Creature* meteorStrike = ObjectAccessor::GetCreature(*me, _rootOwnerGuid);
+ if (!meteorStrike || meteorStrike->AI()->GetData(DATA_SPAWNED_FLAMES) > 5)
+ return;
+
+ me->SetOrientation(me->GetOrientation() + frand(static_cast<float>(-M_PI / 16), static_cast<float>(M_PI / 16)));
+ Position pos = me->GetNearPosition(5.0f, 0.0f);
+
+ if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000))
+ {
+ 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);
+ }
+ }
+
+ void IsSummonedBy(Unit* /*summoner*/) override
+ {
+ // Let Halion Controller count as summoner.
+ if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER)))
+ controller->AI()->JustSummoned(me);
+ }
+
+ void UpdateAI(uint32 /*diff*/) override { }
+ void EnterEvadeMode() override { }
+
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ ObjectGuid _rootOwnerGuid = ObjectGuid::Empty;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetRubySanctumAI<npc_meteor_strike_flameAI>(creature);
+ }
+};
+
class npc_combustion_consumption : public CreatureScript
{
public:
@@ -1119,26 +1191,23 @@ class npc_combustion_consumption : public CreatureScript
{
SetCombatMovement(false);
- switch (me->GetEntry())
+ switch (creature->GetEntry())
{
case NPC_COMBUSTION:
_explosionSpell = SPELL_FIERY_COMBUSTION_EXPLOSION;
_damageSpell = SPELL_COMBUSTION_DAMAGE_AURA;
- me->SetPhaseMask(0x01, true);
+ creature->SetPhaseMask(IsHeroic() ? 0x21 : 0x01, true);
break;
case NPC_CONSUMPTION:
_explosionSpell = SPELL_SOUL_CONSUMPTION_EXPLOSION;
_damageSpell = SPELL_CONSUMPTION_DAMAGE_AURA;
- me->SetPhaseMask(0x20, true);
+ creature->SetPhaseMask(IsHeroic() ? 0x21 : 0x20, true);
break;
default: // Should never happen
_explosionSpell = 0;
_damageSpell = 0;
break;
}
-
- if (IsHeroic())
- me->SetPhaseMask(0x01 | 0x20, true);
}
void IsSummonedBy(Unit* summoner) override
@@ -1160,7 +1229,7 @@ class npc_combustion_consumption : public CreatureScript
me->CastCustomSpell(SPELL_SCALE_AURA, SPELLVALUE_AURA_STACK, stackAmount, me);
DoCast(me, _damageSpell);
- int32 damage = 1200 + (stackAmount * 1290); // Needs more researches.
+ int32 damage = 1200 + (stackAmount * 1290); // Needs more research.
summoner->CastCustomSpell(_explosionSpell, SPELLVALUE_BASE_POINT0, damage, summoner);
}
@@ -1193,6 +1262,10 @@ class npc_living_inferno : public CreatureScript
me->SetInCombatWithZone();
me->CastSpell(me, SPELL_BLAZING_AURA, true);
+ // SMSG_SPELL_GO for the living ember stuff isn't even sent to the client - Blizzard on drugs.
+ if (me->GetMap()->GetDifficultyID() == DIFFICULTY_25_HC)
+ me->CastSpell(me, SPELL_SPAWN_LIVING_EMBERS, true);
+
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER)))
controller->AI()->JustSummoned(me);
@@ -1210,7 +1283,6 @@ class npc_living_inferno : public CreatureScript
}
};
-//! Need sniff data
class npc_living_ember : public CreatureScript
{
public:
@@ -1738,12 +1810,46 @@ class spell_halion_summon_exit_portals : public SpellScriptLoader
}
};
+class spell_halion_spawn_living_embers : public SpellScriptLoader
+{
+ public:
+ spell_halion_spawn_living_embers() : SpellScriptLoader("spell_halion_spawn_living_embers") { }
+
+ class spell_halion_spawn_living_embers_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_halion_spawn_living_embers_SpellScript);
+
+ void SelectMeteorFlames(std::list<WorldObject*>& unitList)
+ {
+ if (!unitList.empty())
+ Trinity::Containers::RandomResizeList(unitList, 10);
+ }
+
+ void HandleScript(SpellEffIndex /* effIndex */)
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_LIVING_EMBER, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_halion_spawn_living_embers_SpellScript::SelectMeteorFlames, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_halion_spawn_living_embers_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_halion_spawn_living_embers_SpellScript();
+ }
+};
+
void AddSC_boss_halion()
{
new boss_halion();
new boss_twilight_halion();
new npc_halion_controller();
+ new npc_meteor_strike_flame();
new npc_meteor_strike_initial();
new npc_meteor_strike();
new npc_combustion_consumption();
@@ -1765,4 +1871,5 @@ void AddSC_boss_halion()
new spell_halion_twilight_phasing();
new spell_halion_twilight_cutter();
new spell_halion_clear_debuffs();
+ new spell_halion_spawn_living_embers();
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
index 9ca88f4fdfa..525ecacd39a 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp
@@ -482,40 +482,47 @@ class boss_flame_leviathan : public CreatureScript
if (action && action <= 4) // Tower destruction, debuff leviathan loot and reduce active tower count
{
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3 | LOOT_MODE_HARD_MODE_4) && ActiveTowersCount == 4)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_4);
- --ActiveTowersCount;
- }
+
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3) && ActiveTowersCount == 3)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
- --ActiveTowersCount;
- }
+
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2) && ActiveTowersCount == 2)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
- --ActiveTowersCount;
- }
+
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1) && ActiveTowersCount == 1)
- {
me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
- --ActiveTowersCount;
- }
}
switch (action)
{
case ACTION_TOWER_OF_STORM_DESTROYED:
- towerOfStorms = false;
+ if (towerOfStorms)
+ {
+ towerOfStorms = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_TOWER_OF_FROST_DESTROYED:
- towerOfFrost = false;
+ if (towerOfFrost)
+ {
+ towerOfFrost = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_TOWER_OF_FLAMES_DESTROYED:
- towerOfFlames = false;
+ if (towerOfFlames)
+ {
+ towerOfFlames = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_TOWER_OF_LIFE_DESTROYED:
- towerOfLife = false;
+ if (towerOfLife)
+ {
+ towerOfLife = false;
+ --ActiveTowersCount;
+ }
break;
case ACTION_START_HARD_MODE: // Activate hard-mode enable all towers, apply buffs on leviathan
ActiveTowers = true;
diff --git a/src/server/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/Database/Implementation/HotfixDatabase.cpp b/src/server/shared/Database/Implementation/HotfixDatabase.cpp
index 1afb118a06e..a7043b1d5ff 100644
--- a/src/server/shared/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/shared/Database/Implementation/HotfixDatabase.cpp
@@ -52,6 +52,11 @@ void HotfixDatabaseConnection::DoPrepareStatements()
"PhaseUseFlags, PhaseID, PhaseGroupID, Type, Data0, Data1, Data2, Data3, Data4, Data5, Data6, Data7, Name FROM gameobjects ORDER BY ID DESC", CONNECTION_SYNCH);
PREPARE_LOCALE_STMT(HOTFIX_SEL_GAMEOBJECTS, "SELECT ID, Name_lang FROM gameobjects_locale WHERE locale = ?", CONNECTION_SYNCH);
+ // GarrAbility.db2
+ PrepareStatement(HOTFIX_SEL_GARR_ABILITY, "SELECT ID, Flags, Name, Description, IconFileDataID, OtherFactionGarrAbilityID, "
+ "GarrAbilityCategoryID FROM garr_ability ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_ABILITY, "SELECT ID, Name_lang, Description_lang FROM garr_ability_locale WHERE locale = ?", CONNECTION_SYNCH);
+
// GarrBuilding.db2
PrepareStatement(HOTFIX_SEL_GARR_BUILDING, "SELECT ID, HordeGameObjectID, AllianceGameObjectID, Unknown, Type, Level, NameAlliance, NameHorde, Description, "
"Tooltip, BuildDuration, CostCurrencyID, CostCurrencyAmount, HordeTexPrefixKitID, AllianceTexPrefixKitID, IconFileDataID, BonusAmount, Flags, "
@@ -64,6 +69,20 @@ void HotfixDatabaseConnection::DoPrepareStatements()
PrepareStatement(HOTFIX_SEL_GARR_BUILDING_PLOT_INST, "SELECT ID, GarrBuildingID, UiTextureAtlasMemberID, GarrSiteLevelPlotInstID, "
"LandmarkOffsetX, LandmarkOffsetY FROM garr_building_plot_inst ORDER BY ID DESC", CONNECTION_SYNCH);
+ // GarrClassSpec.db2
+ PrepareStatement(HOTFIX_SEL_GARR_CLASS_SPEC, "SELECT ID, NameMale, NameFemale, NameGenderless, ClassAtlasID, GarrFollItemSetID "
+ "FROM garr_class_spec ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_CLASS_SPEC, "SELECT ID, NameMale_lang, NameFemale_lang, NameGenderless_lang FROM garr_class_spec_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrFollower.db2
+ PrepareStatement(HOTFIX_SEL_GARR_FOLLOWER, "SELECT ID, HordeCreatureID, AllianceCreatureID, HordeUiAnimRaceInfoID, AllianceUiAnimRaceInfoID, Quality, "
+ "HordeGarrClassSpecID, AllianceGarrClassSpecID, HordeGarrFollItemSetID, AllianceGarrFollItemSetID, Level, ItemLevelWeapon, ItemLevelArmor, Unknown1, Flags, "
+ "HordeSourceText, AllianceSourceText, Unknown2, Unknown3, HordePortraitIconID, AlliancePortraitIconID FROM garr_follower ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_GARR_FOLLOWER, "SELECT ID, HordeSourceText_lang, AllianceSourceText_lang FROM garr_follower_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // GarrFollowerXAbility.db2
+ PrepareStatement(HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY, "SELECT ID, GarrFollowerID, GarrAbilityID, FactionIndex FROM garr_follower_x_ability ORDER BY ID DESC", CONNECTION_SYNCH);
+
// GarrPlot.db2
PrepareStatement(HOTFIX_SEL_GARR_PLOT, "SELECT ID, GarrPlotUICategoryID, PlotType, Flags, Name, MinCount, MaxCount, "
"AllianceConstructionGameObjectID, HordeConstructionGameObjectID FROM garr_plot ORDER BY ID DESC", CONNECTION_SYNCH);
diff --git a/src/server/shared/Database/Implementation/HotfixDatabase.h b/src/server/shared/Database/Implementation/HotfixDatabase.h
index 5d5f00dbf9e..4adf555dc2f 100644
--- a/src/server/shared/Database/Implementation/HotfixDatabase.h
+++ b/src/server/shared/Database/Implementation/HotfixDatabase.h
@@ -57,11 +57,22 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_GAMEOBJECTS,
HOTFIX_SEL_GAMEOBJECTS_LOCALE,
+ HOTFIX_SEL_GARR_ABILITY,
+ HOTFIX_SEL_GARR_ABILITY_LOCALE,
+
HOTFIX_SEL_GARR_BUILDING,
HOTFIX_SEL_GARR_BUILDING_LOCALE,
HOTFIX_SEL_GARR_BUILDING_PLOT_INST,
+ HOTFIX_SEL_GARR_CLASS_SPEC,
+ HOTFIX_SEL_GARR_CLASS_SPEC_LOCALE,
+
+ HOTFIX_SEL_GARR_FOLLOWER,
+ HOTFIX_SEL_GARR_FOLLOWER_LOCALE,
+
+ HOTFIX_SEL_GARR_FOLLOWER_X_ABILITY,
+
HOTFIX_SEL_GARR_PLOT,
HOTFIX_SEL_GARR_PLOT_LOCALE,
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/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp
index 8f85cfdbe83..125f630bb13 100644
--- a/src/tools/mmaps_generator/TerrainBuilder.cpp
+++ b/src/tools/mmaps_generator/TerrainBuilder.cpp
@@ -80,7 +80,7 @@ struct map_liquidHeader
namespace MMAP
{
- char const* MAP_VERSION_MAGIC = "v1.4";
+ char const* MAP_VERSION_MAGIC = "v1.5";
TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ }
TerrainBuilder::~TerrainBuilder() { }
@@ -134,7 +134,7 @@ namespace MMAP
bool TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion)
{
char mapFileName[255];
- sprintf(mapFileName, "maps/%03u%02u%02u.map", mapID, tileY, tileX);
+ sprintf(mapFileName, "maps/%04u_%02u_%02u.map", mapID, tileY, tileX);
FILE* mapFile = fopen(mapFileName, "rb");
if (!mapFile)