diff options
Diffstat (limited to 'src/server/game/Handlers/GroupHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/GroupHandler.cpp | 657 |
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; } |