TrinityCore
Loading...
Searching...
No Matches
GroupHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "CharacterCache.h"
20#include "Common.h"
21#include "DatabaseEnv.h"
22#include "Group.h"
23#include "GroupMgr.h"
24#include "Log.h"
25#include "MiscPackets.h"
26#include "ObjectAccessor.h"
27#include "ObjectMgr.h"
28#include "PartyPackets.h"
29#include "Pet.h"
30#include "Player.h"
31#include "SocialMgr.h"
32#include "SpellAuras.h"
33#include "Util.h"
34#include "Vehicle.h"
35#include "World.h"
36#include "WorldPacket.h"
37
38class Aura;
39
40/* differeces from off:
41 -you can uninvite yourself - is is useful
42 -you can accept invitation even if leader went offline
43*/
44/* todo:
45 -group_destroyed msg is sent but not shown
46 -reduce xp gaining when in raid group
47 -quest sharing has to be corrected
48 -FIX sending PartyMemberStats
49*/
50
51void WorldSession::SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res, uint32 val /* = 0 */)
52{
53 WorldPacket data(SMSG_PARTY_COMMAND_RESULT, 4 + member.size() + 1 + 4 + 4);
54 data << uint32(operation);
55 data << member;
56 data << uint32(res);
57 data << uint32(val); // LFD cooldown related (used with ERR_PARTY_LFG_BOOT_COOLDOWN_S and ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S)
58
59 SendPacket(&data);
60}
61
63{
64 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_INVITE");
65
66 // attempt add selected player
67
68 // cheating
70 {
72 return;
73 }
74
75 Player* invitingPlayer = GetPlayer();
76 Player* invitedPlayer = ObjectAccessor::FindPlayerByName(packet.TargetName);
77
78 // no player
79 if (!invitedPlayer)
80 {
82 return;
83 }
84
85 // player trying to invite himself (most likely cheating)
86 if (invitedPlayer == invitingPlayer)
87 {
89 return;
90 }
91
92 // restrict invite to GMs
93 if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !invitingPlayer->IsGameMaster() && invitedPlayer->IsGameMaster())
94 {
96 return;
97 }
98
99 // can't group with
100 if (!invitingPlayer->IsGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && invitingPlayer->GetTeam() != invitedPlayer->GetTeam())
101 {
103 return;
104 }
105 if (invitingPlayer->GetInstanceId() != 0 && invitedPlayer->GetInstanceId() != 0 && invitingPlayer->GetInstanceId() != invitedPlayer->GetInstanceId() && invitingPlayer->GetMapId() == invitedPlayer->GetMapId())
106 {
108 return;
109 }
110 // just ignore us
111 if (invitedPlayer->GetInstanceId() != 0 && invitedPlayer->GetDungeonDifficulty() != invitingPlayer->GetDungeonDifficulty())
112 {
114 return;
115 }
116
117 if (invitedPlayer->GetSocial()->HasIgnore(invitingPlayer->GetGUID()))
118 {
120 return;
121 }
122
123 if (!invitedPlayer->GetSocial()->HasFriend(invitingPlayer->GetGUID()) && invitingPlayer->GetLevel() < sWorld->getIntConfig(CONFIG_PARTY_LEVEL_REQ))
124 {
126 return;
127 }
128
129 Group* group = invitingPlayer->GetGroup();
130 if (group && group->isBGGroup())
131 group = invitingPlayer->GetOriginalGroup();
132 if (!group)
133 group = invitingPlayer->GetGroupInvite();
134
135 Group* group2 = invitedPlayer->GetGroup();
136 if (group2 && group2->isBGGroup())
137 group2 = invitedPlayer->GetOriginalGroup();
138 // player already in another group or invited
139 if (group2 || invitedPlayer->GetGroupInvite())
140 {
142
143 if (group2)
144 {
145 // tell the player that they were invited but it failed as they were already in a group
147 partyInvite.Initialize(invitingPlayer, packet.ProposedRoles, false);
148 invitedPlayer->SendDirectMessage(partyInvite.Write());
149 }
150
151 return;
152 }
153
154 if (group)
155 {
156 // not have permissions for invite
157 if (!group->IsLeader(invitingPlayer->GetGUID()) && !group->IsAssistant(invitingPlayer->GetGUID()))
158 {
159 if (group->IsCreated())
161 return;
162 }
163 // not have place
164 if (group->IsFull())
165 {
167 return;
168 }
169 }
170
171 // ok, but group not exist, start a new group
172 // but don't create and save the group to the DB until
173 // at least one person joins
174 if (!group)
175 {
176 group = new Group();
177 // new group: if can't add then delete
178 if (!group->AddLeaderInvite(invitingPlayer))
179 {
180 delete group;
181 return;
182 }
183 if (!group->AddInvite(invitedPlayer))
184 {
185 group->RemoveAllInvites();
186 delete group;
187 return;
188 }
189 }
190 else
191 {
192 // already existed group: if can't add then just leave
193 if (!group->AddInvite(invitedPlayer))
194 {
195 return;
196 }
197 }
198
200 partyInvite.Initialize(invitingPlayer, packet.ProposedRoles, true);
201 invitedPlayer->SendDirectMessage(partyInvite.Write());
202
204}
205
207{
208 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_ACCEPT");
209
210 recvData.read_skip<uint32>();
211 Group* group = GetPlayer()->GetGroupInvite();
212
213 if (!group)
214 return;
215
216 // Remove player from invitees in any case
217 group->RemoveInvite(GetPlayer());
218
219 if (group->GetLeaderGUID() == GetPlayer()->GetGUID())
220 {
221 TC_LOG_ERROR("network", "HandleGroupAcceptOpcode: player {} {} tried to accept an invite to his own group", GetPlayer()->GetName(), GetPlayer()->GetGUID().ToString());
222 return;
223 }
224
225 // Group is full
226 if (group->IsFull())
227 {
229 return;
230 }
231
232 Player* leader = ObjectAccessor::FindPlayer(group->GetLeaderGUID());
233
234 // Forming a new group, create it
235 if (!group->IsCreated())
236 {
237 // This can happen if the leader is zoning. To be removed once delayed actions for zoning are implemented
238 if (!leader)
239 {
240 group->RemoveAllInvites();
241 return;
242 }
243
244 // If we're about to create a group there really should be a leader present
245 ASSERT(leader);
246 group->RemoveInvite(leader);
247 group->Create(leader);
248 sGroupMgr->AddGroup(group);
249 }
250
251 // Everything is fine, do it, PLAYER'S GROUP IS SET IN ADDMEMBER!!!
252 if (!group->AddMember(GetPlayer()))
253 return;
254
255 group->BroadcastGroupUpdate();
256}
257
259{
260 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_DECLINE");
261
262 Group* group = GetPlayer()->GetGroupInvite();
263 if (!group)
264 return;
265
266 // Remember leader if online (group pointer will be invalid if group gets disbanded)
268
269 // uninvite, group can be deleted
271
272 if (!leader || !leader->GetSession())
273 return;
274
275 // report
276 WorldPacket data(SMSG_GROUP_DECLINE, GetPlayer()->GetName().length());
277 data << GetPlayer()->GetName();
278 leader->SendDirectMessage(&data);
279}
280
282{
283 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_UNINVITE_GUID");
284
285 ObjectGuid guid;
286 std::string reason;
287 recvData >> guid;
288 recvData >> reason;
289
290 //can't uninvite yourself
291 if (guid == GetPlayer()->GetGUID())
292 {
293 TC_LOG_ERROR("network", "WorldSession::HandleGroupUninviteGuidOpcode: leader {} {} tried to uninvite himself from the group.",
294 GetPlayer()->GetName(), GetPlayer()->GetGUID().ToString());
295 return;
296 }
297
299 if (res != ERR_PARTY_RESULT_OK)
300 {
302 return;
303 }
304
305 Group* grp = GetPlayer()->GetGroup();
306 // grp is checked already above in CanUninviteFromGroup()
307 ASSERT(grp);
308
309 if (grp->IsMember(guid))
310 {
311 Player::RemoveFromGroup(grp, guid, GROUP_REMOVEMETHOD_KICK, GetPlayer()->GetGUID(), reason.c_str());
312 return;
313 }
314
315 if (Player* player = grp->GetInvited(guid))
316 {
317 player->UninviteFromGroup();
318 return;
319 }
320
322}
323
325{
326 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_UNINVITE");
327
328 std::string membername;
329 recvData >> membername;
330
331 // player not found
332 if (!normalizePlayerName(membername))
333 return;
334
335 // can't uninvite yourself
336 if (GetPlayer()->GetName() == membername)
337 {
338 TC_LOG_ERROR("network", "WorldSession::HandleGroupUninviteOpcode: leader {} {} tried to uninvite himself from the group.",
339 GetPlayer()->GetName(), GetPlayer()->GetGUID().ToString());
340 return;
341 }
342
344 if (res != ERR_PARTY_RESULT_OK)
345 {
347 return;
348 }
349
350 Group* grp = GetPlayer()->GetGroup();
351 if (!grp)
352 return;
353
354 ObjectGuid guid = grp->GetMemberGUID(membername);
355 if (!guid.IsEmpty())
356 {
358 return;
359 }
360
361 if (Player* player = grp->GetInvited(guid))
362 {
363 player->UninviteFromGroup();
364 return;
365 }
366
368}
369
371{
372 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_SET_LEADER");
373
374 ObjectGuid guid;
375 recvData >> guid;
376
378 Group* group = GetPlayer()->GetGroup();
379
380 if (!group || !player)
381 return;
382
383 if (!group->IsLeader(GetPlayer()->GetGUID()) || player->GetGroup() != group)
384 return;
385
386 // Everything's fine, accepted.
387 group->ChangeLeader(guid);
388 group->SendUpdate();
389}
390
392{
393 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_DISBAND");
394
395 Group* grp = GetPlayer()->GetGroup();
396 Group* grpInvite = GetPlayer()->GetGroupInvite();
397 if (!grp && !grpInvite)
398 return;
399
400 if (_player->InBattleground())
401 return;
402
404 /********************/
405
406 // everything's fine, do it
407 if (grp)
408 {
411 }
412 else if (grpInvite && grpInvite->GetLeaderGUID() == GetPlayer()->GetGUID())
413 { // pending group creation being cancelled
415 grpInvite->Disband();
416 }
417}
418
420{
421 TC_LOG_DEBUG("network", "WORLD: Received CMSG_LOOT_METHOD");
422
423 uint32 lootMethod;
424 ObjectGuid lootMaster;
425 uint32 lootThreshold;
426 recvData >> lootMethod >> lootMaster >> lootThreshold;
427
428 Group* group = GetPlayer()->GetGroup();
429 if (!group)
430 return;
431
433 if (!group->IsLeader(GetPlayer()->GetGUID()))
434 return;
435
436 if (group->isLFGGroup())
437 return;
438
439 if (lootMethod > NEED_BEFORE_GREED)
440 return;
441
442 if (lootThreshold < ITEM_QUALITY_UNCOMMON || lootThreshold > ITEM_QUALITY_ARTIFACT)
443 return;
444
445 if (lootMethod == MASTER_LOOT && !group->IsMember(lootMaster))
446 return;
447 /********************/
448
449 // everything's fine, do it
450 group->SetLootMethod((LootMethod)lootMethod);
451 group->SetMasterLooterGuid(lootMaster);
452 group->SetLootThreshold((ItemQualities)lootThreshold);
453 group->SendUpdate();
454}
455
457{
458 ObjectGuid guid;
459 uint32 itemSlot;
460 uint8 rollType;
461 recvData >> guid; // guid of the item rolled
462 recvData >> itemSlot;
463 recvData >> rollType; // 0: pass, 1: need, 2: greed
464
465 Group* group = GetPlayer()->GetGroup();
466 if (!group)
467 return;
468
469 if (!group->CountRollVote(GetPlayer()->GetGUID(), guid, rollType))
470 return;
471
472 switch (rollType)
473 {
474 case ROLL_NEED:
476 break;
477 case ROLL_GREED:
479 break;
480 }
481}
482
484{
485 TC_LOG_DEBUG("network", "WORLD: Received MSG_MINIMAP_PING");
486
487 if (!GetPlayer()->GetGroup())
488 return;
489
490 float x, y;
491 recvData >> x;
492 recvData >> y;
493
494 //TC_LOG_DEBUG("Received opcode MSG_MINIMAP_PING X: {}, Y: {}", x, y);
495
497 /********************/
498
499 // everything's fine, do it
500 WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
501 data << GetPlayer()->GetGUID();
502 data << float(x);
503 data << float(y);
504 GetPlayer()->GetGroup()->BroadcastPacket(&data, true, -1, GetPlayer()->GetGUID());
505}
506
508{
509 uint32 minimum, maximum;
510 minimum = packet.Min;
511 maximum = packet.Max;
512
514 if (minimum > maximum || maximum > 10000) // < 32768 for urand call
515 return;
516 /********************/
517
518 GetPlayer()->DoRandomRoll(minimum, maximum);
519}
520
522{
523 TC_LOG_DEBUG("network", "WORLD: Received MSG_RAID_TARGET_UPDATE");
524
525 Group* group = GetPlayer()->GetGroup();
526 if (!group)
527 return;
528
529 uint8 x;
530 recvData >> x;
531
533 /********************/
534
535 // everything's fine, do it
536 if (x == 0xFF) // target icon request
537 group->SendTargetIconList(this);
538 else // target icon update
539 {
540 if (group->isRaidGroup() && !group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
541 return;
542
543 ObjectGuid guid;
544 recvData >> guid;
545
546 if (guid.IsPlayer())
547 {
549
550 if (!target || target->IsHostileTo(GetPlayer()))
551 return;
552 }
553
554 group->SetTargetIcon(x, _player->GetGUID(), guid);
555 }
556}
557
559{
560 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_RAID_CONVERT");
561
562 Group* group = GetPlayer()->GetGroup();
563 if (!group)
564 return;
565
566 if (_player->InBattleground())
567 return;
568
569 // error handling
570 if (!group->IsLeader(GetPlayer()->GetGUID()) || group->GetMembersCount() < 2)
571 return;
572
573 // everything's fine, do it (is it 0 (PARTY_OP_INVITE) correct code)
575 group->ConvertToRaid();
576}
577
579{
580 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_CHANGE_SUB_GROUP");
581
582 // we will get correct pointer for group here, so we don't have to check if group is BG raid
583 Group* group = GetPlayer()->GetGroup();
584 if (!group)
585 return;
586
587 std::string name;
588 uint8 groupNr;
589 recvData >> name;
590 recvData >> groupNr;
591
592 if (!normalizePlayerName(name))
593 return;
594
595 if (groupNr >= MAX_RAID_SUBGROUPS)
596 return;
597
598 ObjectGuid senderGuid = GetPlayer()->GetGUID();
599 if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
600 return;
601
602 if (!group->HasFreeSlotSubGroup(groupNr))
603 return;
604
605 ObjectGuid guid;
606 if (Player* movedPlayer = ObjectAccessor::FindConnectedPlayerByName(name))
607 guid = movedPlayer->GetGUID();
608 else
609 guid = sCharacterCache->GetCharacterGuidByName(name);
610
611 if (guid.IsEmpty())
612 return;
613
614 group->ChangeMembersGroup(guid, groupNr);
615}
616
618{
619 TC_LOG_DEBUG("network", "WORLD: Received CMSG_GROUP_ASSISTANT_LEADER");
620
621 Group* group = GetPlayer()->GetGroup();
622 if (!group)
623 return;
624
625 if (!group->IsLeader(GetPlayer()->GetGUID()))
626 return;
627
628 ObjectGuid guid;
629 bool apply;
630 recvData >> guid;
631 recvData >> apply;
632
633 group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT);
634}
635
637{
638 TC_LOG_DEBUG("network", "WORLD: Received MSG_PARTY_ASSIGNMENT");
639
640 Group* group = GetPlayer()->GetGroup();
641 if (!group)
642 return;
643
644 ObjectGuid senderGuid = GetPlayer()->GetGUID();
645 if (!group->IsLeader(senderGuid) && !group->IsAssistant(senderGuid))
646 return;
647
648 uint8 assignment;
649 bool apply;
650 ObjectGuid guid;
651 recvData >> assignment >> apply;
652 recvData >> guid;
653
654 switch (assignment)
655 {
658 group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_MAINASSIST);
659 break;
661 group->RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINTANK); // Remove main assist flag from current if any.
662 group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_MAINTANK);
663 break;
664 default:
665 break;
666 }
667
668 group->SendUpdate();
669}
670
672{
673 TC_LOG_DEBUG("network", "WORLD: Received MSG_RAID_READY_CHECK");
674
675 Group* group = GetPlayer()->GetGroup();
676 if (!group)
677 return;
678
679 if (recvData.empty()) // request
680 {
682 if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
683 return;
684 /********************/
685
686 // everything's fine, do it
688 data << GetPlayer()->GetGUID();
689 group->BroadcastPacket(&data, false, -1);
690
691 group->OfflineReadyCheck();
692 }
693 else // answer
694 {
695 uint8 state;
696 recvData >> state;
697
698 // everything's fine, do it
700 data << GetPlayer()->GetGUID();
701 data << uint8(state);
702 group->BroadcastReadyCheck(&data);
703 }
704}
705
707{
708 Group* group = GetPlayer()->GetGroup();
709 if (!group)
710 return;
711
712 if (!group->IsLeader(GetPlayer()->GetGUID()) && !group->IsAssistant(GetPlayer()->GetGUID()))
713 return;
714
716 group->BroadcastPacket(&data, true, -1);
717}
718
720{
721 uint32 mask = player->GetGroupUpdateFlag();
722
723 if (mask == GROUP_UPDATE_FLAG_NONE)
724 return;
725
726 if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also
728
729 if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets
731
732 uint32 byteCount = 0;
733 for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i)
734 if (mask & (1 << i))
735 byteCount += GroupUpdateLength[i];
736
737 data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount);
738 *data << player->GetPackGUID();
739 *data << uint32(mask);
740
741 if (mask & GROUP_UPDATE_FLAG_STATUS)
742 {
743 uint16 playerStatus = MEMBER_STATUS_ONLINE;
744 if (player->IsPvP())
745 playerStatus |= MEMBER_STATUS_PVP;
746
747 if (!player->IsAlive())
748 {
750 playerStatus |= MEMBER_STATUS_GHOST;
751 else
752 playerStatus |= MEMBER_STATUS_DEAD;
753 }
754
755 if (player->IsFFAPvP())
756 playerStatus |= MEMBER_STATUS_PVP_FFA;
757
758 if (player->isAFK())
759 playerStatus |= MEMBER_STATUS_AFK;
760
761 if (player->isDND())
762 playerStatus |= MEMBER_STATUS_DND;
763
764 *data << uint16(playerStatus);
765 }
766
767 if (mask & GROUP_UPDATE_FLAG_CUR_HP)
768 *data << uint32(player->GetHealth());
769
770 if (mask & GROUP_UPDATE_FLAG_MAX_HP)
771 *data << uint32(player->GetMaxHealth());
772
773 Powers powerType = player->GetPowerType();
775 *data << uint8(powerType);
776
778 *data << uint16(player->GetPower(powerType));
779
781 *data << uint16(player->GetMaxPower(powerType));
782
783 if (mask & GROUP_UPDATE_FLAG_LEVEL)
784 *data << uint16(player->GetLevel());
785
786 if (mask & GROUP_UPDATE_FLAG_ZONE)
787 *data << uint16(player->GetZoneId());
788
790 {
791 *data << uint16(player->GetPositionX());
792 *data << uint16(player->GetPositionY());
793 }
794
795 if (mask & GROUP_UPDATE_FLAG_AURAS)
796 {
797 uint64 auramask = player->GetAuraUpdateMaskForRaid();
798 *data << uint64(auramask);
799 for (uint32 i = 0; i < MAX_AURAS_GROUP_UPDATE; ++i)
800 {
801 if (auramask & (uint64(1) << i))
802 {
803 AuraApplication const* aurApp = player->GetVisibleAura(i);
804 *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
805 *data << uint8(aurApp ? aurApp->GetFlags() : 0);
806 }
807 }
808 }
809
810 Pet* pet = player->GetPet();
812 {
813 if (pet)
814 *data << pet->GetGUID();
815 else
816 *data << ObjectGuid::Empty;
817 }
818
820 {
821 if (pet)
822 *data << pet->GetName();
823 else
824 *data << uint8(0);
825 }
826
828 {
829 if (pet)
830 *data << uint16(pet->GetDisplayId());
831 else
832 *data << uint16(0);
833 }
834
836 {
837 if (pet)
838 *data << uint32(pet->GetHealth());
839 else
840 *data << uint32(0);
841 }
842
844 {
845 if (pet)
846 *data << uint32(pet->GetMaxHealth());
847 else
848 *data << uint32(0);
849 }
850
852 {
853 if (pet)
854 *data << uint8(pet->GetPowerType());
855 else
856 *data << uint8(0);
857 }
858
860 {
861 if (pet)
862 *data << uint16(pet->GetPower(pet->GetPowerType()));
863 else
864 *data << uint16(0);
865 }
866
868 {
869 if (pet)
870 *data << uint16(pet->GetMaxPower(pet->GetPowerType()));
871 else
872 *data << uint16(0);
873 }
874
876 {
877 if (pet)
878 {
879 uint64 auramask = pet->GetAuraUpdateMaskForRaid();
880 *data << uint64(auramask);
881 for (uint32 i = 0; i < MAX_AURAS_GROUP_UPDATE; ++i)
882 {
883 if (auramask & (uint64(1) << i))
884 {
885 AuraApplication const* aurApp = pet->GetVisibleAura(i);
886 *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0);
887 *data << uint8(aurApp ? aurApp->GetFlags() : 0);
888 }
889 }
890 }
891 else
892 *data << uint64(0);
893 }
894
896 {
897 if (Vehicle* veh = player->GetVehicle())
898 *data << uint32(veh->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
899 else
900 *data << uint32(0);
901 }
902}
903
904/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/
906{
907 TC_LOG_DEBUG("network", "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS");
908 ObjectGuid guid;
909 recvData >> guid;
910
912 if (!player || !GetPlayer()->IsInSameRaidWith(player))
913 {
915 data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
916 data << guid.WriteAsPacked();
919 SendPacket(&data);
920 return;
921 }
922
923 Pet* pet = player->GetPet();
924 Powers powerType = player->GetPowerType();
925
926 WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
927 data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
928 data << player->GetPackGUID();
929
934
935 if (powerType != POWER_MANA)
936 updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE;
937
938 if (pet)
941
942 if (player->GetVehicle())
943 updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT;
944
945 uint16 playerStatus = MEMBER_STATUS_ONLINE;
946 if (player->IsPvP())
947 playerStatus |= MEMBER_STATUS_PVP;
948
949 if (!player->IsAlive())
950 {
952 playerStatus |= MEMBER_STATUS_GHOST;
953 else
954 playerStatus |= MEMBER_STATUS_DEAD;
955 }
956
957 if (player->IsFFAPvP())
958 playerStatus |= MEMBER_STATUS_PVP_FFA;
959
960 if (player->isAFK())
961 playerStatus |= MEMBER_STATUS_AFK;
962
963 if (player->isDND())
964 playerStatus |= MEMBER_STATUS_DND;
965
966 data << uint32(updateFlags);
967 data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS
968 data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP
969 data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP
970 if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE)
971 data << uint8(powerType);
972
973 data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER
974 data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER
975 data << uint16(player->GetLevel()); // GROUP_UPDATE_FLAG_LEVEL
976 data << uint16(player->GetZoneId()); // GROUP_UPDATE_FLAG_ZONE
977 data << uint16(player->GetPositionX()); // GROUP_UPDATE_FLAG_POSITION
978 data << uint16(player->GetPositionY()); // GROUP_UPDATE_FLAG_POSITION
979
980 uint64 auraMask = 0;
981 size_t maskPos = data.wpos();
982 data << uint64(auraMask); // placeholder
983 for (uint8 i = 0; i < MAX_AURAS_GROUP_UPDATE; ++i)
984 {
985 if (AuraApplication const* aurApp = player->GetVisibleAura(i))
986 {
987 auraMask |= uint64(1) << i;
988 data << uint32(aurApp->GetBase()->GetId());
989 data << uint8(aurApp->GetFlags());
990 }
991 }
992
993 data.put<uint64>(maskPos, auraMask); // GROUP_UPDATE_FLAG_AURAS
994
995 if (updateFlags & GROUP_UPDATE_FLAG_PET_GUID)
996 data << ASSERT_NOTNULL(pet)->GetGUID();
997
998 data << std::string(pet ? pet->GetName() : ""); // GROUP_UPDATE_FLAG_PET_NAME
999 data << uint16(pet ? pet->GetDisplayId() : 0); // GROUP_UPDATE_FLAG_PET_MODEL_ID
1000
1001 if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_HP)
1002 data << uint32(pet->GetHealth());
1003
1004 if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_HP)
1005 data << uint32(pet->GetMaxHealth());
1006
1007 if (updateFlags & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
1008 data << uint8(pet->GetPowerType());
1009
1010 if (updateFlags & GROUP_UPDATE_FLAG_PET_CUR_POWER)
1011 data << uint16(pet->GetPower(pet->GetPowerType()));
1012
1013 if (updateFlags & GROUP_UPDATE_FLAG_PET_MAX_POWER)
1014 data << uint16(pet->GetMaxPower(pet->GetPowerType()));
1015
1016 uint64 petAuraMask = 0;
1017 maskPos = data.wpos();
1018 data << uint64(petAuraMask); // placeholder
1019 if (pet)
1020 {
1021 for (uint8 i = 0; i < MAX_AURAS_GROUP_UPDATE; ++i)
1022 {
1023 if (AuraApplication const* aurApp = pet->GetVisibleAura(i))
1024 {
1025 petAuraMask |= uint64(1) << i;
1026 data << uint32(aurApp->GetBase()->GetId());
1027 data << uint8(aurApp->GetFlags());
1028 }
1029 }
1030 }
1031
1032 data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS
1033
1034 if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT)
1035 data << uint32(player->GetVehicle()->GetVehicleInfo()->SeatID[player->m_movementInfo.transport.seat]);
1036
1037 SendPacket(&data);
1038}
1039
1041{
1042 // every time the player checks the character screen
1044}
1045
1047{
1048 TC_LOG_DEBUG("network", "WORLD: Received CMSG_OPT_OUT_OF_LOOT");
1049
1050 uint32 passOnLoot;
1051 recvData >> passOnLoot; // 1 always pass, 0 do not pass
1052
1053 // ignore if player not loaded
1054 if (!GetPlayer()) // needed because STATUS_AUTHED
1055 {
1056 if (passOnLoot != 0)
1057 TC_LOG_ERROR("network", "CMSG_OPT_OUT_OF_LOOT value<>0 for not-loaded character!");
1058 return;
1059 }
1060
1061 GetPlayer()->SetPassOnGroupLoot(passOnLoot != 0);
1062}
#define sCharacterCache
@ ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED
Definition DBCEnums.h:214
@ ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED
Definition DBCEnums.h:213
uint8_t uint8
Definition Define.h:135
uint64_t uint64
Definition Define.h:132
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:84
#define ASSERT
Definition Errors.h:68
#define sGroupMgr
Definition GroupMgr.h:58
@ GROUP_ASSIGN_MAINASSIST
Definition Group.h:82
@ GROUP_ASSIGN_MAINTANK
Definition Group.h:81
@ MEMBER_STATUS_AFK
Definition Group.h:68
@ MEMBER_STATUS_OFFLINE
Definition Group.h:61
@ MEMBER_STATUS_PVP
Definition Group.h:63
@ MEMBER_STATUS_ONLINE
Definition Group.h:62
@ MEMBER_STATUS_DEAD
Definition Group.h:64
@ MEMBER_STATUS_GHOST
Definition Group.h:65
@ MEMBER_STATUS_DND
Definition Group.h:69
@ MEMBER_STATUS_PVP_FFA
Definition Group.h:66
static const uint8 GroupUpdateLength[GROUP_UPDATE_FLAGS_COUNT]
Definition Group.h:127
@ MEMBER_FLAG_ASSISTANT
Definition Group.h:74
@ MEMBER_FLAG_MAINASSIST
Definition Group.h:76
@ MEMBER_FLAG_MAINTANK
Definition Group.h:75
@ GROUP_UPDATE_FLAG_CUR_HP
Definition Group.h:102
@ GROUP_UPDATE_FLAG_PET_CUR_HP
Definition Group.h:114
@ GROUP_UPDATE_FLAG_POWER_TYPE
Definition Group.h:104
@ GROUP_UPDATE_FLAG_PET_CUR_POWER
Definition Group.h:117
@ GROUP_UPDATE_FLAG_PET_MAX_POWER
Definition Group.h:118
@ GROUP_UPDATE_FLAG_MAX_HP
Definition Group.h:103
@ GROUP_UPDATE_FLAG_VEHICLE_SEAT
Definition Group.h:120
@ GROUP_UPDATE_FLAG_STATUS
Definition Group.h:101
@ GROUP_UPDATE_FLAG_PET_POWER_TYPE
Definition Group.h:116
@ GROUP_UPDATE_FLAG_MAX_POWER
Definition Group.h:106
@ GROUP_UPDATE_FLAG_ZONE
Definition Group.h:108
@ GROUP_UPDATE_FLAG_NONE
Definition Group.h:100
@ GROUP_UPDATE_FLAG_POSITION
Definition Group.h:109
@ GROUP_UPDATE_FLAG_PET_MODEL_ID
Definition Group.h:113
@ GROUP_UPDATE_FLAG_PET_NAME
Definition Group.h:112
@ GROUP_UPDATE_FLAG_PET_AURAS
Definition Group.h:119
@ GROUP_UPDATE_FLAG_AURAS
Definition Group.h:110
@ GROUP_UPDATE_FLAG_LEVEL
Definition Group.h:107
@ GROUP_UPDATE_FLAG_PET_GUID
Definition Group.h:111
@ GROUP_UPDATE_FLAG_PET_MAX_HP
Definition Group.h:115
@ GROUP_UPDATE_FLAG_CUR_POWER
Definition Group.h:105
#define GROUP_UPDATE_FLAGS_COUNT
Definition Group.h:125
#define MAX_RAID_SUBGROUPS
Definition Group.h:45
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
LootMethod
Definition Loot.h:61
@ NEED_BEFORE_GREED
Definition Loot.h:66
@ MASTER_LOOT
Definition Loot.h:64
@ ROLL_GREED
Definition Loot.h:39
@ ROLL_NEED
Definition Loot.h:38
bool normalizePlayerName(std::string &name)
@ PLAYER_FLAGS_GHOST
Definition Player.h:348
ItemQualities
@ ITEM_QUALITY_ARTIFACT
Powers
@ POWER_MANA
@ GROUP_REMOVEMETHOD_KICK
@ GROUP_REMOVEMETHOD_LEAVE
PartyResult
@ ERR_ALREADY_IN_GROUP_S
@ ERR_TARGET_NOT_IN_INSTANCE_S
@ ERR_IGNORING_YOU_S
@ ERR_NOT_LEADER
@ ERR_TARGET_NOT_IN_GROUP_S
@ ERR_PLAYER_WRONG_FACTION
@ ERR_INVITE_RESTRICTED
@ ERR_PARTY_RESULT_OK
@ ERR_GROUP_FULL
@ ERR_BAD_PLAYER_NAME_S
#define MAX_AURAS_GROUP_UPDATE
@ PLAYER_FLAGS
uint8 GetFlags() const
Definition SpellAuras.h:70
Aura * GetBase() const
Definition SpellAuras.h:67
uint32 GetId() const
Definition SpellAuras.h:116
void read_skip()
Definition ByteBuffer.h:330
size_t wpos() const
Definition ByteBuffer.h:321
void put(std::size_t pos, T value)
Definition ByteBuffer.h:137
bool empty() const
Definition ByteBuffer.h:410
Definition Group.h:165
bool isLFGGroup() const
Definition Group.cpp:2443
bool AddLeaderInvite(Player *player)
Definition Group.cpp:347
void SendTargetIconList(WorldSession *session)
Definition Group.cpp:1677
bool IsCreated() const
Definition Group.cpp:2463
void SetLootMethod(LootMethod method)
Definition Group.cpp:2408
void ChangeMembersGroup(ObjectGuid guid, uint8 group)
Definition Group.cpp:1882
void RemoveAllInvites()
Definition Group.cpp:366
bool IsAssistant(ObjectGuid guid) const
Definition Group.h:233
void SetLootThreshold(ItemQualities threshold)
Definition Group.cpp:2423
void Disband(bool hideDestroy=false)
Definition Group.cpp:809
void SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid)
Definition Group.cpp:1656
bool IsLeader(ObjectGuid guid) const
Definition Group.cpp:2510
void SendUpdate()
Definition Group.cpp:1697
void SetMasterLooterGuid(ObjectGuid guid)
Definition Group.cpp:2418
void RemoveInvite(Player *player)
Definition Group.cpp:357
bool isBGGroup() const
Definition Group.cpp:2453
void ConvertToRaid()
Definition Group.cpp:302
uint32 GetMembersCount() const
Definition Group.h:249
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag)
Definition Group.cpp:2570
void ChangeLeader(ObjectGuid guid)
Definition Group.cpp:704
ObjectGuid GetMemberGUID(const std::string &name)
Definition Group.cpp:2515
void BroadcastPacket(WorldPacket const *packet, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignoredPlayer=ObjectGuid::Empty)
Definition Group.cpp:1808
Player * GetInvited(ObjectGuid guid) const
Definition Group.cpp:375
bool HasFreeSlotSubGroup(uint8 subgroup) const
Definition Group.cpp:2547
bool IsMember(ObjectGuid guid) const
Definition Group.cpp:2505
bool CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise)
Definition Group.cpp:1416
bool AddInvite(Player *player)
Definition Group.cpp:326
void BroadcastReadyCheck(WorldPacket const *packet)
Definition Group.cpp:1821
bool IsFull() const
Definition Group.cpp:2438
ObjectGuid GetLeaderGUID() const
Definition Group.cpp:2468
bool isRaidGroup() const
Definition Group.cpp:2448
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag)
Definition Group.cpp:2705
void OfflineReadyCheck()
Definition Group.cpp:1832
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
bool IsPlayer() const
Definition ObjectGuid.h:179
PackedGuidWriter WriteAsPacked() const
Definition ObjectGuid.h:152
PackedGuid const & GetPackGUID() const
Definition Object.h:80
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:799
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
Definition Pet.h:40
uint64 GetAuraUpdateMaskForRaid() const
Definition Pet.h:143
bool HasIgnore(ObjectGuid const &ignoreGuid)
bool HasFriend(ObjectGuid const &friendGuid)
uint32 GetTeam() const
Definition Player.h:1832
uint64 GetAuraUpdateMaskForRaid() const
Definition Player.h:2178
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
uint32 DoRandomRoll(uint32 minimum, uint32 maximum)
Definition Player.cpp:26479
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24940
bool InBattleground() const
Definition Player.h:1982
Group * GetOriginalGroup() const
Definition Player.h:2186
Pet * GetPet() const
Definition Player.cpp:20286
void SendRaidInfo()
Definition Player.cpp:18706
WorldSession * GetSession() const
Definition Player.h:1719
void SetPassOnGroupLoot(bool bPassOnGroupLoot)
Definition Player.h:2191
Group * GetGroup()
Definition Player.h:2171
bool IsGameMaster() const
Definition Player.h:998
PartyResult CanUninviteFromGroup(ObjectGuid guidMember=ObjectGuid::Empty) const
Definition Player.cpp:23924
bool isDND() const
Definition Player.h:976
static void RemoveFromGroup(Group *group, ObjectGuid guid, RemoveMethod method=GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker=ObjectGuid::Empty, char const *reason=nullptr)
Definition Player.cpp:2326
PlayerSocial * GetSocial()
Definition Player.h:982
uint32 GetGroupUpdateFlag() const
Definition Player.h:2176
void UninviteFromGroup()
Definition Player.cpp:2303
bool isAFK() const
Definition Player.h:975
Difficulty GetDungeonDifficulty() const
Definition Player.h:1635
Group * GetGroupInvite() const
Definition Player.h:2169
Vehicle * GetVehicle() const
Definition Unit.h:1737
AuraApplication * GetVisibleAura(uint8 slot) const
Definition Unit.cpp:640
bool IsPvP() const
Definition Unit.h:988
Powers GetPowerType() const
Definition Unit.h:931
uint32 GetMaxHealth() const
Definition Unit.h:914
bool IsAlive() const
Definition Unit.h:1234
uint32 GetDisplayId() const
Definition Unit.h:1582
uint32 GetMaxPower(Powers power) const
Definition Unit.h:936
uint32 GetHealth() const
Definition Unit.h:913
bool IsFFAPvP() const
Definition Unit.h:989
uint32 GetPower(Powers power) const
Definition Unit.h:934
uint8 GetLevel() const
Definition Unit.h:889
VehicleEntry const * GetVehicleInfo() const
Definition Vehicle.h:46
uint32 GetMapId() const
Definition Position.h:193
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2796
uint32 GetInstanceId() const
Definition Object.h:365
std::string const & GetName() const
Definition Object.h:382
uint32 GetZoneId() const
Definition Object.h:373
MovementInfo m_movementInfo
Definition Object.h:575
void Initialize(uint16 opcode, size_t newres=200)
Definition WorldPacket.h:73
WorldPacket const * Write() override
void Initialize(Player const *inviter, uint32 proposedRoles, bool canAccept)
void HandleGroupAcceptOpcode(WorldPacket &recvPacket)
void HandleGroupUninviteGuidOpcode(WorldPacket &recvPacket)
void HandleMinimapPingOpcode(WorldPacket &recvData)
void HandleGroupAssistantLeaderOpcode(WorldPacket &recvData)
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
void HandleGroupRaidConvertOpcode(WorldPacket &recvData)
void HandleRaidTargetUpdateOpcode(WorldPacket &recvData)
void HandlePartyAssignmentOpcode(WorldPacket &recvData)
void HandleLootMethodOpcode(WorldPacket &recvPacket)
Player * GetPlayer() const
void HandleLootRoll(WorldPacket &recvData)
void HandleGroupDisbandOpcode(WorldPacket &recvPacket)
void HandleOptOutOfLootOpcode(WorldPacket &recvData)
void HandleGroupChangeSubGroupOpcode(WorldPacket &recvData)
void HandleRandomRollOpcode(WorldPackets::Misc::RandomRollClient &packet)
void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data)
void HandleGroupSetLeaderOpcode(WorldPacket &recvPacket)
void HandleRequestPartyMemberStatsOpcode(WorldPacket &recvData)
Player * _player
void HandleGroupUninviteOpcode(WorldPacket &recvPacket)
void SendPartyResult(PartyOperation operation, std::string const &member, PartyResult res, uint32 val=0)
void HandleRaidReadyCheckOpcode(WorldPacket &recvData)
void HandleGroupDeclineOpcode(WorldPacket &recvPacket)
void HandleGroupInviteOpcode(WorldPackets::Party::PartyInviteClient &packet)
void HandleRaidReadyCheckFinishedOpcode(WorldPacket &recvData)
void HandleRequestRaidInfoOpcode(WorldPacket &recvData)
PartyOperation
@ SMSG_PARTY_COMMAND_RESULT
Definition Opcodes.h:156
@ MSG_RAID_READY_CHECK
Definition Opcodes.h:831
@ MSG_RAID_READY_CHECK_CONFIRM
Definition Opcodes.h:971
@ SMSG_PARTY_MEMBER_STATS_FULL
Definition Opcodes.h:783
@ MSG_RAID_READY_CHECK_FINISHED
Definition Opcodes.h:995
@ MSG_MINIMAP_PING
Definition Opcodes.h:498
@ SMSG_GROUP_DECLINE
Definition Opcodes.h:145
@ SMSG_PARTY_MEMBER_STATS
Definition Opcodes.h:155
@ PARTY_OP_INVITE
@ PARTY_OP_UNINVITE
@ PARTY_OP_LEAVE
#define sWorld
Definition World.h:900
@ CONFIG_PARTY_LEVEL_REQ
Definition World.h:300
@ CONFIG_ALLOW_GM_GROUP
Definition World.h:107
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP
Definition World.h:98
TC_GAME_API Player * FindPlayerByName(std::string_view name)
TC_GAME_API Player * FindConnectedPlayerByName(std::string_view name)
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
struct MovementInfo::TransportInfo transport
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
uint32 SeatID[MAX_VEHICLE_SEATS]