aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/GroupHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers/GroupHandler.cpp')
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp657
1 files changed, 476 insertions, 181 deletions
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 89f77e784b9..ee28e0c30d5 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -48,11 +48,12 @@ 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);
+ 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);
}
@@ -61,59 +62,91 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE");
- std::string membername;
- recvData >> membername;
- recvData.read_skip<uint32>();
+ 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();
+
+ recvData.ReadByteSeq(crossRealmGuid[4]);
+ recvData.ReadByteSeq(crossRealmGuid[7]);
+ recvData.ReadByteSeq(crossRealmGuid[6]);
+
+ 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))
+ if (!normalizePlayerName(memberName))
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S);
return;
}
- Player* player = sObjectAccessor->FindPlayerByName(membername);
+ Player* player = sObjectAccessor->FindPlayerByName(memberName);
// no player
if (!player)
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, 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, memberName, 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, memberName, 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, memberName, ERR_TARGET_NOT_IN_INSTANCE_S);
return;
}
// just ignore us
if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
return;
}
if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S);
+ SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S);
return;
}
+ ObjectGuid invitedGuid = player->GetGUID();
+
Group* group = GetPlayer()->GetGroup();
if (group && group->isBGGroup())
group = GetPlayer()->GetOriginalGroup();
@@ -124,17 +157,63 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
// 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, memberName, 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_GROUP_INVITE, 10); // guess size
- data << uint8(0); // invited/already in group flag
- data << GetPlayer()->GetName(); // max len 48
- data << uint32(0); // unk
- data << uint8(0); // count
- data << uint32(0); // unk
+ WorldPacket data(SMSG_GROUP_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);
}
@@ -185,90 +264,138 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
}
// ok, we do it
- WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size
- data << uint8(1); // invited/already in group flag
- data << GetPlayer()->GetName(); // max len 48
- data << uint32(0); // unk
- data << uint8(0); // count
- data << uint32(0); // unk
+ WorldPacket data(SMSG_GROUP_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();
+
+ 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, memberName, ERR_PARTY_RESULT_OK);
}
-void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recvData)
+void WorldSession::HandleGroupInviteResponseOpcode(WorldPacket& recvData)
{
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ACCEPT");
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE_RESPONSE");
- recvData.read_skip<uint32>();
- Group* group = GetPlayer()->GetGroupInvite();
+ recvData.ReadBit(); // unk always 0
+ bool accept = recvData.ReadBit();
- if (!group)
- return;
+ // Never actually received?
+ /*if (accept)
+ recvData.read_skip<uint32>(); // unk*/
- // Remove player from invitees in any case
- group->RemoveInvite(GetPlayer());
+ Group* group = GetPlayer()->GetGroupInvite();
- if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
- {
- sLog->outError(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
+ if (!group)
return;
- }
- // Group is full
- if (group->IsFull())
+ if (accept)
{
- SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
- return;
- }
+ // Remove player from invitees in any case
+ group->RemoveInvite(GetPlayer());
- Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
-
- // Forming a new group, create it
- if (!group->IsCreated())
- {
- // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
- if (!leader)
+ if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
{
- group->RemoveAllInvites();
+ sLog->outError(LOG_FILTER_NETWORKIO, "HandleGroupAcceptOpcode: player %s(%d) tried to accept an invite to his own group", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow());
return;
}
- // If we're about to create a group there really should be a leader present
- ASSERT(leader);
- group->RemoveInvite(leader);
- group->Create(leader);
- sGroupMgr->AddGroup(group);
- }
+ // Group is full
+ if (group->IsFull())
+ {
+ SendPartyResult(PARTY_OP_INVITE, "", ERR_GROUP_FULL);
+ return;
+ }
- // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
- if (!group->AddMember(GetPlayer()))
- return;
+ Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
- group->BroadcastGroupUpdate();
-}
+ // Forming a new group, create it
+ if (!group->IsCreated())
+ {
+ // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
+ if (!leader)
+ {
+ group->RemoveAllInvites();
+ return;
+ }
-void WorldSession::HandleGroupDeclineOpcode(WorldPacket & /*recvData*/)
-{
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DECLINE");
+ // If we're about to create a group there really should be a leader present
+ ASSERT(leader);
+ group->RemoveInvite(leader);
+ group->Create(leader);
+ sGroupMgr->AddGroup(group);
+ }
- Group* group = GetPlayer()->GetGroupInvite();
- if (!group)
- return;
+ // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
+ if (!group->AddMember(GetPlayer()))
+ return;
- // Remember leader if online (group pointer will be invalid if group gets disbanded)
- Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
+ group->BroadcastGroupUpdate();
+ }
+ else
+ {
+ // Remember leader if online (group pointer will be invalid if group gets disbanded)
+ Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
- // uninvite, group can be deleted
- GetPlayer()->UninviteFromGroup();
+ // uninvite, group can be deleted
+ GetPlayer()->UninviteFromGroup();
- if (!leader || !leader->GetSession())
- return;
+ if (!leader || !leader->GetSession())
+ return;
- // report
- WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().length());
- data << GetPlayer()->GetName();
- leader->GetSession()->SendPacket(&data);
+ // report
+ WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().size());
+ data << GetPlayer()->GetName();
+ leader->GetSession()->SendPacket(&data);
+ }
}
void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData)
@@ -386,7 +513,81 @@ void WorldSession::HandleGroupSetLeaderOpcode(WorldPacket& recvData)
group->SendUpdate();
}
-void WorldSession::HandleGroupDisbandOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleGroupSetRolesOpcode(WorldPacket& recvData)
+{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SET_ROLES");
+
+ 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_GROUP_SET_ROLE, 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 (GetPlayer()->GetGroup())
+ GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
+ else
+ SendPacket(&data);
+}
+
+void WorldSession::HandleGroupDisbandOpcode(WorldPacket& /*recvData*/)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_DISBAND");
@@ -471,7 +672,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData)
recvData >> x;
recvData >> y;
- //sLog->outDebug("Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
+ //sLog->outDebug(LOG_FILTER_GENERAL, "Received opcode MSG_MINIMAP_PING X: %f, Y: %f", x, y);
/** error handling **/
/********************/
@@ -500,7 +701,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData)
// everything's fine, do it
roll = urand(minimum, maximum);
- //sLog->outDebug("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
+ //sLog->outDebug(LOG_FILTER_GENERAL, "ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8);
data << uint32(minimum);
@@ -521,7 +722,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
if (!group)
return;
- uint8 x;
+ uint8 x;
recvData >> x;
/** error handling **/
@@ -529,9 +730,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
// everything's fine, do it
if (x == 0xFF) // target icon request
- {
group->SendTargetIconList(this);
- }
else // target icon update
{
if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
@@ -543,7 +742,7 @@ void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_RAID_CONVERT");
@@ -554,14 +753,22 @@ void WorldSession::HandleGroupRaidConvertOpcode(WorldPacket & /*recvData*/)
if (_player->InBattleground())
return;
- /** error handling **/
+ // error handling
if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2)
return;
- /********************/
// everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code)
SendPartyResult(PARTY_OP_INVITE, "", ERR_PARTY_RESULT_OK);
- group->ConvertToRaid();
+
+ // 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)
+ group->ConvertToRaid();
+ else
+ group->ConvertToGroup();
}
void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
@@ -590,10 +797,9 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
Player* movedPlayer = sObjectAccessor->FindPlayerByName(name);
uint64 guid;
+
if (movedPlayer)
- {
guid = movedPlayer->GetGUID();
- }
else
{
CharacterDatabase.EscapeString(name);
@@ -603,6 +809,16 @@ void WorldSession::HandleGroupChangeSubGroupOpcode(WorldPacket& recvData)
group->ChangeMembersGroup(guid, groupNr);
}
+void WorldSession::HandleGroupSwapSubGroupOpcode(WorldPacket& recvData)
+{
+ sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_SWAP_SUB_GROUP");
+ std::string unk1;
+ std::string unk2;
+
+ recvData >> unk1;
+ recvData >> unk2;
+}
+
void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_ASSISTANT_LEADER");
@@ -693,7 +909,7 @@ void WorldSession::HandleRaidReadyCheckOpcode(WorldPacket& recvData)
}
}
-void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleRaidReadyCheckFinishedOpcode(WorldPacket& /*recvData*/)
{
//Group* group = GetPlayer()->GetGroup();
//if (!group)
@@ -718,64 +934,82 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER);
- uint32 byteCount = 0;
- for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
- if (mask & (1 << i))
- byteCount += GroupUpdateLength[i];
-
- data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
+ data->Initialize(SMSG_PARTY_MEMBER_STATS, 80); // average value
data->append(player->GetPackGUID());
- *data << (uint32) mask;
+ *data << uint32(mask);
if (mask & GROUP_UPDATE_FLAG_STATUS)
{
if (player)
{
if (player->IsPvP())
- *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP);
+ *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP);
else
- *data << (uint16) MEMBER_STATUS_ONLINE;
+ *data << uint16(MEMBER_STATUS_ONLINE);
}
else
- *data << (uint16) MEMBER_STATUS_OFFLINE;
+ *data << uint16(MEMBER_STATUS_OFFLINE);
}
if (mask & GROUP_UPDATE_FLAG_CUR_HP)
- *data << (uint32) player->GetHealth();
+ *data << uint32(player->GetHealth());
if (mask & GROUP_UPDATE_FLAG_MAX_HP)
- *data << (uint32) player->GetMaxHealth();
+ *data << uint32(player->GetMaxHealth());
Powers powerType = player->getPowerType();
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
- *data << (uint8) powerType;
+ *data << uint8(powerType);
if (mask & GROUP_UPDATE_FLAG_CUR_POWER)
- *data << (uint16) player->GetPower(powerType);
+ *data << uint16(player->GetPower(powerType));
if (mask & GROUP_UPDATE_FLAG_MAX_POWER)
- *data << (uint16) player->GetMaxPower(powerType);
+ *data << uint16(player->GetMaxPower(powerType));
if (mask & GROUP_UPDATE_FLAG_LEVEL)
- *data << (uint16) player->getLevel();
+ *data << uint16(player->getLevel());
if (mask & GROUP_UPDATE_FLAG_ZONE)
- *data << (uint16) player->GetZoneId();
+ *data << uint16(player->GetZoneId());
+
+ if (mask & GROUP_UPDATE_FLAG_UNK100)
+ *data << uint16(0);
if (mask & GROUP_UPDATE_FLAG_POSITION)
- *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY();
+ *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()) << 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);
- *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
- *data << uint8(1);
+ if (!aurApp)
+ {
+ *data << uint32(0);
+ *data << uint16(0);
+ continue;
+ }
+
+ *data << uint32(aurApp->GetBase()->GetId());
+ *data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ 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);
+ }
+ }
}
}
}
@@ -784,9 +1018,9 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (mask & GROUP_UPDATE_FLAG_PET_GUID)
{
if (pet)
- *data << (uint64) pet->GetGUID();
+ *data << uint64(pet->GetGUID());
else
- *data << (uint64) 0;
+ *data << uint64(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_NAME)
@@ -794,97 +1028,129 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke
if (pet)
*data << pet->GetName();
else
- *data << (uint8) 0;
+ *data << uint8(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID)
{
if (pet)
- *data << (uint16) pet->GetDisplayId();
+ *data << uint16(pet->GetDisplayId());
else
- *data << (uint16) 0;
+ *data << uint16(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
{
if (pet)
- *data << (uint32) pet->GetHealth();
+ *data << uint32(pet->GetHealth());
else
- *data << (uint32) 0;
+ *data << uint32(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
{
if (pet)
- *data << (uint32) pet->GetMaxHealth();
+ *data << uint32(pet->GetMaxHealth());
else
- *data << (uint32) 0;
+ *data << uint32(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
{
if (pet)
- *data << (uint8) pet->getPowerType();
+ *data << uint8(pet->getPowerType());
else
- *data << (uint8) 0;
+ *data << uint8(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER)
{
if (pet)
- *data << (uint16) pet->GetPower(pet->getPowerType());
+ *data << uint16(pet->GetPower(pet->getPowerType()));
else
- *data << (uint16) 0;
+ *data << uint16(0);
}
if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER)
{
if (pet)
- *data << (uint16) pet->GetMaxPower(pet->getPowerType());
+ *data << uint16(pet->GetMaxPower(pet->getPowerType()));
else
- *data << (uint16) 0;
+ *data << uint16(0);
}
if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
{
if (Vehicle* veh = player->GetVehicle())
- *data << (uint32) veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat];
+ *data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]);
+ else
+ *data << uint32(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);
- *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
- *data << uint8(1);
+ if (!aurApp)
+ {
+ *data << uint32(0);
+ *data << uint16(0);
+ continue;
+ }
+
+ *data << uint32(aurApp->GetBase()->GetId());
+ *data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ 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 << (uint64) 0;
+ {
+ *data << uint8(0);
+ *data << uint64(0);
+ }
+ }
+
+ if (mask & GROUP_UPDATE_FLAG_PHASE)
+ {
+ *data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT
+ *data << uint32(0); // count
+ // for (count) *data << uint16(phaseId)
}
}
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
-void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
+void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
- uint64 Guid;
- recvData >> Guid;
+ uint64 guid;
+ recvData >> guid;
- Player* player = HashMapHolder<Player>::Find(Guid);
+ Player* player = HashMapHolder<Player>::Find(guid);
if (!player)
{
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
- data.appendPackGUID(Guid);
+ data.appendPackGUID(guid);
data << (uint32) GROUP_UPDATE_FLAG_STATUS;
data << (uint16) MEMBER_STATUS_OFFLINE;
SendPacket(&data);
@@ -897,94 +1163,123 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
data.append(player->GetPackGUID());
- uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF
- if (pet)
- mask1 = 0x7FFFFFFF; // for hunters and other classes with pets
+ uint32 mask1 = GROUP_UPDATE_FULL;
- Powers powerType = player->getPowerType();
- data << (uint32) mask1; // group update mask
- data << (uint16) MEMBER_STATUS_ONLINE; // member's online status
- data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP
- data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP
- data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE
- 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
+ if (!pet)
+ mask1 &= ~GROUP_UPDATE_PET;
+ Powers powerType = player->getPowerType();
+ data << uint32(mask1); // group update mask
+ data << uint16(MEMBER_STATUS_ONLINE); // member's online status, GROUP_UPDATE_FLAG_STATUS
+ data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP
+ data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP
+ data << uint8 (powerType); // GROUP_UPDATE_FLAG_POWER_TYPE
+ 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 << uint64(auramask); // placeholder
+ data << uint32(MAX_AURAS); // count
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
- if (AuraApplication * aurApp = player->GetVisibleAura(i))
+ if (AuraApplication const* aurApp = player->GetVisibleAura(i))
{
auramask |= (uint64(1) << i);
- data << (uint32) aurApp->GetBase()->GetId();
- data << (uint8) 1;
+
+ data << uint32(aurApp->GetBase()->GetId());
+ data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ 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
+ data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS
if (pet)
{
Powers petpowertype = pet->getPowerType();
- data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID
+ data << uint64(pet->GetGUID()); // GROUP_UPDATE_FLAG_PET_GUID
data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME
- data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID
- data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP
- data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP
- data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE
- data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER
- data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER
-
+ data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID
+ data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP
+ data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP
+ data << uint8 (petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE
+ data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER
+ data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER
+
+ // GROUP_UPDATE_FLAG_PET_AURAS
+ data << uint8(1);
uint64 petauramask = 0;
size_t petMaskPos = data.wpos();
- data << (uint64) petauramask; // placeholder
+ data << uint64(petauramask); // placeholder
+ data << uint32(MAX_AURAS); // count
for (uint8 i = 0; i < MAX_AURAS; ++i)
{
- if (AuraApplication * auraApp = pet->GetVisibleAura(i))
+ if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
{
petauramask |= (uint64(1) << i);
- data << (uint32) auraApp->GetBase()->GetId();
- data << (uint8) 1;
+
+ data << uint32(aurApp->GetBase()->GetId());
+ data << uint16(aurApp->GetFlags());
+
+ if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT)
+ {
+ 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>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS
}
- else
- {
- data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME
- data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS
- }
+ // else not needed, flags do not include any PET_ update
+
+ // GROUP_UPDATE_FLAG_PHASE
+ data << uint32(8); // either 0 or 8, same unk found in SMSG_PHASESHIFT
+ data << uint32(0); // count
+ // for (count) *data << uint16(phaseId)
SendPacket(&data);
}
-/*!*/void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket & /*recvData*/)
+void WorldSession::HandleRequestRaidInfoOpcode(WorldPacket& /*recvData*/)
{
// every time the player checks the character screen
_player->SendRaidInfo();
}
-/*void WorldSession::HandleGroupCancelOpcode(WorldPacket& recvData)
-{
- sLog->outDebug("WORLD: got CMSG_GROUP_CANCEL.");
-}*/
-
void WorldSession::HandleOptOutOfLootOpcode(WorldPacket& recvData)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_OPT_OUT_OF_LOOT");
- uint32 passOnLoot;
+ bool passOnLoot;
recvData >> passOnLoot; // 1 always pass, 0 do not pass
// ignore if player not loaded
if (!GetPlayer()) // needed because STATUS_AUTHED
{
- if (passOnLoot != 0)
+ if (passOnLoot)
sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
return;
}