TrinityCore
Loading...
Searching...
No Matches
Group.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 "Group.h"
19#include "Battleground.h"
20#include "BattlegroundMgr.h"
21#include "CharacterCache.h"
22#include "DatabaseEnv.h"
23#include "DB2Stores.h"
24#include "Formulas.h"
25#include "GameObject.h"
26#include "GameTime.h"
27#include "GroupMgr.h"
28#include "Item.h"
29#include "LFGMgr.h"
30#include "Log.h"
31#include "Loot.h"
32#include "MapManager.h"
33#include "MiscPackets.h"
34#include "ObjectAccessor.h"
35#include "ObjectMgr.h"
36#include "PartyPackets.h"
37#include "Pet.h"
38#include "Player.h"
39#include "UpdateData.h"
40#include "WorldSession.h"
41
43{
44 return Seconds(std::max<time_t>(_endTime - GameTime::GetGameTime(), 0));
45}
46
48{
49 _startTime = startTime ? *startTime : GameTime::GetGameTime();
50 _endTime = _startTime + duration.count();
51}
52
54{
55 return _endTime > GameTime::GetGameTime();
56}
57
72
74{
75 if (m_bgGroup)
76 {
77 TC_LOG_DEBUG("bg.battleground", "Group::~Group: battleground group being deleted.");
78 if (m_bgGroup->GetBgRaid(ALLIANCE) == this)
79 m_bgGroup->SetBgRaid(ALLIANCE, nullptr);
80 else if (m_bgGroup->GetBgRaid(HORDE) == this)
81 m_bgGroup->SetBgRaid(HORDE, nullptr);
82 else
83 TC_LOG_ERROR("misc", "Group::~Group: battleground group is not linked to the correct battleground.");
84 }
85
86 // Sub group counters clean up
87 delete[] m_subGroupsCounts;
88}
89
91{
93 {
96 {
98 m_isLeaderOffline = false;
99 }
100 }
101
102 UpdateReadyCheck(diff);
103}
104
106{
107 Player* newLeader = nullptr;
108
109 // Attempt to give leadership to main assistant first
110 if (isRaidGroup())
111 {
112 for (Group::MemberSlot const& memberSlot : m_memberSlots)
113 {
114 if ((memberSlot.flags & MEMBER_FLAG_ASSISTANT) == MEMBER_FLAG_ASSISTANT)
115 if (Player* player = ObjectAccessor::FindPlayer(memberSlot.guid))
116 {
117 newLeader = player;
118 break;
119 }
120 }
121 }
122
123 // If there aren't assistants in raid, or if the group is not a raid, pick the first available member
124 if (!newLeader)
125 {
126 for (Group::MemberSlot const& memberSlot : m_memberSlots)
127 if (Player* player = ObjectAccessor::FindPlayer(memberSlot.guid))
128 {
129 newLeader = player;
130 break;
131 }
132 }
133
134 if (newLeader)
135 {
136 ChangeLeader(newLeader->GetGUID());
137 SendUpdate();
138 }
139}
140
142{
143 ObjectGuid leaderGuid = leader->GetGUID();
144
145 m_guid = ObjectGuid::Create<HighGuid::Party>(sGroupMgr->GenerateGroupId());
146 m_leaderGuid = leaderGuid;
148 m_leaderName = leader->GetName();
150
151 if (isBGGroup() || isBFGroup())
152 {
155 }
156
159
161 m_looterGuid = leaderGuid;
163
167
168 if (!isBGGroup() && !isBFGroup())
169 {
173
174 m_dbStoreId = sGroupMgr->GenerateNewGroupDbStoreId();
175
176 sGroupMgr->RegisterGroupDbStoreId(m_dbStoreId, this);
177
178 // Store group in database
180
181 uint8 index = 0;
182
183 stmt->setUInt32(index++, m_dbStoreId);
184 stmt->setUInt64(index++, m_leaderGuid.GetCounter());
185 stmt->setUInt8(index++, uint8(m_lootMethod));
186 stmt->setUInt64(index++, m_looterGuid.GetCounter());
187 stmt->setUInt8(index++, uint8(m_lootThreshold));
188 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
189 stmt->setBinary(index++, m_targetIcons[i].GetRawValue());
190 stmt->setUInt16(index++, m_groupFlags);
191 stmt->setUInt32(index++, uint8(m_dungeonDifficulty));
192 stmt->setUInt32(index++, uint8(m_raidDifficulty));
193 stmt->setUInt32(index++, uint8(m_legacyRaidDifficulty));
194 stmt->setUInt64(index++, m_masterLooterGuid.GetCounter());
195 stmt->setInt8(index++, int8(m_pingRestriction));
196
197 CharacterDatabase.Execute(stmt);
198
199 if (InstanceMap* leaderInstance = leader->GetMap()->ToInstanceMap())
200 leaderInstance->TrySetOwningGroup(this);
201
202 bool addMemberResult = AddMember(leader);
203 ASSERT(addMemberResult); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
204 }
205 else if (!AddMember(leader))
206 return false;
207
208 return true;
209}
210
212{
213 m_dbStoreId = fields[17].GetUInt32();
214 m_guid = ObjectGuid::Create<HighGuid::Party>(sGroupMgr->GenerateGroupId());
215 m_leaderGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
216
217 // group leader not exist
218 CharacterCacheEntry const* leader = sCharacterCache->GetCharacterCacheByGuid(m_leaderGuid);
219 if (!leader)
220 return;
221
223 m_leaderName = leader->Name;
224 m_lootMethod = LootMethod(fields[1].GetUInt8());
225 m_looterGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64());
226 m_lootThreshold = ItemQualities(fields[3].GetUInt8());
227
228 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
229 if (std::span<uint8 const> rawGuidBytes = fields[4 + i].GetBinaryView(); rawGuidBytes.size() == ObjectGuid::BytesSize)
230 m_targetIcons[i].SetRawValue(rawGuidBytes);
231
232 m_groupFlags = GroupFlags(fields[12].GetUInt16());
235
239
240 m_masterLooterGuid = fields[16].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[16].GetUInt64()) : ObjectGuid::Empty;
241
242 m_pingRestriction = RestrictPingsTo(fields[18].GetInt8());
243
245 sLFGMgr->_LoadFromDB(fields, GetGUID());
246}
247
248void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
249{
250 MemberSlot member;
251 member.guid = ObjectGuid::Create<HighGuid::Player>(guidLow);
252
253 // skip non-existed member
254 CharacterCacheEntry const* character = sCharacterCache->GetCharacterCacheByGuid(member.guid);
255 if (!character)
256 {
258 stmt->setUInt64(0, guidLow);
259 CharacterDatabase.Execute(stmt);
260 return;
261 }
262
264 memberFlags |= MEMBER_FLAG_ASSISTANT;
265
266 member.name = character->Name;
267 member.race = Races(character->Race);
268 member._class = character->Class;
269 member.group = subgroup;
270 member.flags = memberFlags;
271 member.roles = roles;
272 member.readyChecked = false;
273
274 m_memberSlots.push_back(member);
275
276 SubGroupCounterIncrease(subgroup);
277
278 sLFGMgr->SetupGroupMember(member.guid, GetGUID());
279}
280
298
300{
302
304
305 if (!isBGGroup() && !isBFGroup())
306 {
308
309 stmt->setUInt16(0, m_groupFlags);
310 stmt->setUInt32(1, m_dbStoreId);
311
312 CharacterDatabase.Execute(stmt);
313 }
314
315 SendUpdate();
316
317 // update quest related GO states (quest activity dependent from raid membership)
318 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
319 if (Player* player = ObjectAccessor::FindPlayer(citr->guid))
320 player->UpdateVisibleObjectInteractions(false, true, false, true);
321}
322
324{
325 if (m_memberSlots.size() > 5)
326 return; // What message error should we send?
327
329
331 {
332 delete[] m_subGroupsCounts;
333 m_subGroupsCounts = nullptr;
334 }
335
336 if (!isBGGroup() && !isBFGroup())
337 {
339
340 stmt->setUInt16(0, m_groupFlags);
341 stmt->setUInt32(1, m_dbStoreId);
342
343 CharacterDatabase.Execute(stmt);
344 }
345
346 SendUpdate();
347
348 // update quest related GO states (quest activity dependent from raid membership)
349 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
350 if (Player* player = ObjectAccessor::FindPlayer(citr->guid))
351 player->UpdateVisibleObjectInteractions(false, true, false, true);
352}
353
355{
356 if (!player || player->GetGroupInvite())
357 return false;
358 Group* group = player->GetGroup();
359 if (group && (group->isBGGroup() || group->isBFGroup()))
360 group = player->GetOriginalGroup();
361 if (group)
362 return false;
363
364 RemoveInvite(player);
365
366 m_invitees.insert(player);
367
368 player->SetGroupInvite(this);
369
370 sScriptMgr->OnGroupInviteMember(this, player->GetGUID());
371
372 return true;
373}
374
376{
377 if (!AddInvite(player))
378 return false;
379
380 m_leaderGuid = player->GetGUID();
382 m_leaderName = player->GetName();
383 return true;
384}
385
387{
388 if (player)
389 {
390 m_invitees.erase(player);
391 player->SetGroupInvite(nullptr);
392 }
393}
394
396{
397 for (InvitesList::iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
398 if (*itr)
399 (*itr)->SetGroupInvite(nullptr);
400
401 m_invitees.clear();
402}
403
405{
406 for (InvitesList::const_iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
407 {
408 if ((*itr) && (*itr)->GetGUID() == guid)
409 return (*itr);
410 }
411 return nullptr;
412}
413
414Player* Group::GetInvited(const std::string& name) const
415{
416 for (InvitesList::const_iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
417 {
418 if ((*itr) && (*itr)->GetName() == name)
419 return (*itr);
420 }
421 return nullptr;
422}
423
425{
426 // Get first not-full group
427 uint8 subGroup = 0;
429 {
430 bool groupFound = false;
431 for (; subGroup < MAX_RAID_SUBGROUPS; ++subGroup)
432 {
433 if (m_subGroupsCounts[subGroup] < MAX_GROUP_SIZE)
434 {
435 groupFound = true;
436 break;
437 }
438 }
439 // We are raid group and no one slot is free
440 if (!groupFound)
441 return false;
442 }
443
444 MemberSlot member;
445 member.guid = player->GetGUID();
446 member.name = player->GetName();
447 member.race = Races(player->GetRace());
448 member._class = player->GetClass();
449 member.group = subGroup;
450 member.flags = 0;
451 member.roles = 0;
452 member.readyChecked = false;
453 m_memberSlots.push_back(member);
454
455 SubGroupCounterIncrease(subGroup);
456
457 player->SetGroupInvite(nullptr);
458 if (player->GetGroup())
459 {
460 if (isBGGroup() || isBFGroup()) // if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
461 player->SetBattlegroundOrBattlefieldRaid(this, subGroup);
462 else //if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
463 player->SetOriginalGroup(this, subGroup);
464 }
465 else //if player is not in group, then call set group
466 player->SetGroup(this, subGroup);
467
470
471 // if the same group invites the player back, cancel the homebind timer
472 player->m_InstanceValid = player->CheckInstanceValidity(false);
473
474 if (!isRaidGroup()) // reset targetIcons for non-raid-groups
475 {
476 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
477 m_targetIcons[i].Clear();
478 }
479
480 // insert into the table if we're not a battleground group
481 if (!isBGGroup() && !isBFGroup())
482 {
484
485 stmt->setUInt32(0, m_dbStoreId);
486 stmt->setUInt64(1, member.guid.GetCounter());
487 stmt->setUInt8(2, member.flags);
488 stmt->setUInt8(3, member.group);
489 stmt->setUInt8(4, member.roles);
490
491 CharacterDatabase.Execute(stmt);
492 }
493
494 SendUpdate();
495 sScriptMgr->OnGroupAddMember(this, player->GetGUID());
496
498 if (Pet* pet = player->GetPet())
499 pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
500
502
503 // quest related GO state dependent from raid membership
504 if (isRaidGroup())
505 player->UpdateVisibleObjectInteractions(false, true, false, true);
506
508
509 {
510 // Broadcast new player group member fields to rest of the group
511 UpdateData groupData(player->GetMapId());
512 WorldPacket groupDataPacket;
513
514 // Broadcast group members' fields to player
515 for (GroupReference const& itr : GetMembers())
516 {
517 Player* existingMember = itr.GetSource();
518 if (existingMember == player)
519 continue;
520
521 if (player->HaveAtClient(existingMember))
523
524 if (existingMember->HaveAtClient(player))
525 {
526 UpdateData newData(player->GetMapId());
527 WorldPacket newDataPacket;
529 if (newData.HasData())
530 {
531 newData.BuildPacket(&newDataPacket);
532 existingMember->SendDirectMessage(&newDataPacket);
533 }
534 }
535 }
536
537 if (groupData.HasData())
538 {
539 groupData.BuildPacket(&groupDataPacket);
540 player->SendDirectMessage(&groupDataPacket);
541 }
542 }
543
544 return true;
545}
546
547bool Group::RemoveMember(ObjectGuid guid, RemoveMethod method /*= GROUP_REMOVEMETHOD_DEFAULT*/, ObjectGuid kicker /*= 0*/, const char* reason /*= nullptr*/)
548{
550
551 sScriptMgr->OnGroupRemoveMember(this, guid, method, kicker, reason);
552
554 if (player)
555 {
556 for (GroupReference const& itr : GetMembers())
557 {
558 Player* groupMember = itr.GetSource();
559 if (groupMember->GetGUID() == guid)
560 continue;
561
562 groupMember->RemoveAllGroupBuffsFromCaster(guid);
563 player->RemoveAllGroupBuffsFromCaster(groupMember->GetGUID());
564 }
565 }
566
567 // LFG group vote kick handled in scripts
568 if (isLFGGroup() && method == GROUP_REMOVEMETHOD_KICK)
569 return !m_memberSlots.empty();
570
571 if (player)
573
574 // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group)
575 if (GetMembersCount() > ((isBGGroup() || isLFGGroup() || isBFGroup()) ? 1u : 2u))
576 {
577 if (player)
578 {
579 // Battleground group handling
580 if (isBGGroup() || isBFGroup())
582 else
583 // Regular group
584 {
585 if (player->GetOriginalGroup() == this)
586 player->SetOriginalGroup(nullptr);
587 else
588 player->SetGroup(nullptr);
589
590 // quest related GO state dependent from raid membership
591 player->UpdateVisibleObjectInteractions(false, true, false, true);
592 }
593
595
596 if (method == GROUP_REMOVEMETHOD_KICK || method == GROUP_REMOVEMETHOD_KICK_LFG)
598
599 _homebindIfInstance(player);
600 }
601
602 // Remove player from group in DB
603 if (!isBGGroup() && !isBFGroup())
604 {
606 stmt->setUInt64(0, guid.GetCounter());
607 CharacterDatabase.Execute(stmt);
608 DelinkMember(guid);
609 }
610
611 // Update subgroups
613 if (slot != m_memberSlots.end())
614 {
615 SubGroupCounterDecrease(slot->group);
616 m_memberSlots.erase(slot);
617 }
618
619 // Pick new leader if necessary
620 if (m_leaderGuid == guid)
621 {
622 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
623 {
625 {
626 ChangeLeader(itr->guid);
627 break;
628 }
629 }
630 }
631
632 SendUpdate();
633
634 if (isLFGGroup() && GetMembersCount() == 1)
635 {
637 uint32 mapId = sLFGMgr->GetDungeonMapId(GetGUID());
638 if (!mapId || !leader || (leader->IsAlive() && leader->GetMapId() != mapId))
639 {
640 Disband();
641 return false;
642 }
643 }
644
645 if (m_memberMgr.size() < ((isLFGGroup() || isBGGroup()) ? 1u : 2u))
646 Disband();
647 else if (player)
648 {
649 // send update to removed player too so party frames are destroyed clientside
651 }
652
653 return true;
654 }
655 // If group size before player removal <= 2 then disband it
656 else
657 {
658 Disband();
659 return false;
660 }
661}
662
664{
665 member_witerator slot = _getMemberWSlot(newLeaderGuid);
666
667 if (slot == m_memberSlots.end())
668 return;
669
670 Player* newLeader = ObjectAccessor::FindConnectedPlayer(slot->guid);
671
672 // Don't allow switching leader to offline players
673 if (!newLeader)
674 return;
675
676 sScriptMgr->OnGroupChangeLeader(this, newLeaderGuid, m_leaderGuid);
677
678 if (!isBGGroup() && !isBFGroup())
679 {
680 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
681
682 // Update the group leader
684
685 stmt->setUInt64(0, newLeader->GetGUID().GetCounter());
686 stmt->setUInt32(1, m_dbStoreId);
687
688 trans->Append(stmt);
689
690 CharacterDatabase.CommitTransaction(trans);
691 }
692
694 oldLeader->RemovePlayerFlag(PLAYER_FLAGS_GROUP_LEADER);
695
697 m_leaderGuid = newLeader->GetGUID();
699 m_leaderName = newLeader->GetName();
701
703 groupNewLeader.Name = m_leaderName;
704 groupNewLeader.PartyIndex = GetGroupCategory();
705 BroadcastPacket(groupNewLeader.Write(), true);
706}
707
708void Group::Disband(bool hideDestroy /* = false */)
709{
710 sScriptMgr->OnGroupDisband(this);
711
712 Player* player;
713 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
714 {
715 player = ObjectAccessor::FindConnectedPlayer(citr->guid);
716 if (!player)
717 continue;
718
719 //we cannot call _removeMember because it would invalidate member iterator
720 //if we are removing player from battleground raid
721 if (isBGGroup() || isBFGroup())
723 else
724 {
725 //we can remove player who is in battleground from his original group
726 if (player->GetOriginalGroup() == this)
727 player->SetOriginalGroup(nullptr);
728 else
729 player->SetGroup(nullptr);
730 }
731
733
734 // quest related GO state dependent from raid membership
735 if (isRaidGroup())
736 player->UpdateVisibleObjectInteractions(false, true, false, true);
737
738 if (!hideDestroy)
740
742
743 _homebindIfInstance(player);
744 }
745
746 m_memberSlots.clear();
747
749
750 if (!isBGGroup() && !isBFGroup())
751 {
752 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
753
755 stmt->setUInt32(0, m_dbStoreId);
756 trans->Append(stmt);
757
758 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_MEMBER_ALL);
759 stmt->setUInt32(0, m_dbStoreId);
760 trans->Append(stmt);
761
762 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
763 stmt->setUInt32(0, m_dbStoreId);
764 trans->Append(stmt);
765
766 CharacterDatabase.CommitTransaction(trans);
767
768 sGroupMgr->FreeGroupDbStoreId(this);
769 }
770
771 sGroupMgr->RemoveGroup(this);
772 delete this;
773}
774
775void Group::SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy)
776{
777 if (symbol >= TARGET_ICONS_COUNT)
778 return;
779
780 // clean other icons
781 if (!target.IsEmpty())
782 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
783 if (m_targetIcons[i] == target)
784 SetTargetIcon(i, ObjectGuid::Empty, changedBy);
785
786 m_targetIcons[symbol] = target;
787
789 updateSingle.PartyIndex = GetGroupCategory();
790 updateSingle.Target = target;
791 updateSingle.ChangedBy = changedBy;
792 updateSingle.Symbol = symbol;
793 BroadcastPacket(updateSingle.Write(), true);
794}
795
797{
798 if (!session)
799 return;
800
802 updateAll.PartyIndex = GetGroupCategory();
803 for (uint8 i = 0; i < TARGET_ICONS_COUNT; i++)
804 updateAll.TargetIcons.emplace_back(i, m_targetIcons[i]);
805
806 session->SendPacket(updateAll.Write());
807}
808
810{
811 for (MemberSlot const& memberSlot : m_memberSlots)
812 {
813 Player* player = ObjectAccessor::FindConnectedPlayer(memberSlot.guid);
814 if (!player)
815 continue;
816
817 SendUpdateToPlayer(player, &memberSlot);
818 }
819}
820
821void Group::SendUpdateToPlayer(Player* player, MemberSlot const* slot /*= nullptr*/) const
822{
823 if (player->GetGroup() != this)
824 return;
825
826 // if MemberSlot wasn't provided
827 if (!slot)
828 {
829 member_citerator citr = _getMemberCSlot(player->GetGUID());
830
831 if (citr == m_memberSlots.end()) // if there is no MemberSlot for such a player
832 return;
833
834 slot = &(*citr);
835 }
836
838
839 partyUpdate.PartyFlags = m_groupFlags;
840 partyUpdate.PartyIndex = m_groupCategory;
842
843 partyUpdate.PartyGUID = m_guid;
844 partyUpdate.LeaderGUID = m_leaderGuid;
846
848
850
851 partyUpdate.MyIndex = -1;
852 uint8 index = 0;
853 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr, ++index)
854 {
855 if (slot->guid == citr->guid)
856 partyUpdate.MyIndex = index;
857
858 Player* member = ObjectAccessor::FindConnectedPlayer(citr->guid);
859
860 WorldPackets::Party::PartyPlayerInfo& playerInfos = partyUpdate.PlayerList.emplace_back();
861
862 playerInfos.GUID = citr->guid;
863 playerInfos.Name = citr->name;
864 playerInfos.Class = citr->_class;
865
866 playerInfos.FactionGroup = Player::GetFactionGroupForRace(citr->race);
867
868 playerInfos.Connected = member && member->GetSession() && !member->GetSession()->PlayerLogout();
869
870 playerInfos.Subgroup = citr->group; // groupid
871 playerInfos.Flags = citr->flags; // See enum GroupMemberFlags
872 playerInfos.RolesAssigned = citr->roles; // Lfg Roles
873 }
874
875 if (GetMembersCount() > 1)
876 {
877 // LootSettings
878 partyUpdate.LootSettings.emplace();
879 partyUpdate.LootSettings->Method = m_lootMethod;
880 partyUpdate.LootSettings->Threshold = m_lootThreshold;
882
883 // Difficulty Settings
884 partyUpdate.DifficultySettings.emplace();
885 partyUpdate.DifficultySettings->DungeonDifficultyID = m_dungeonDifficulty;
886 partyUpdate.DifficultySettings->RaidDifficultyID = m_raidDifficulty;
887 partyUpdate.DifficultySettings->LegacyRaidDifficultyID = m_legacyRaidDifficulty;
888 }
889
890 // LfgInfos
891 if (isLFGGroup())
892 {
893 partyUpdate.LfgInfos.emplace();
894
895 partyUpdate.LfgInfos->Slot = sLFGMgr->GetLFGDungeonEntry(sLFGMgr->GetDungeon(m_guid));
896 partyUpdate.LfgInfos->BootCount = 0;
897 partyUpdate.LfgInfos->Aborted = false;
898
899 partyUpdate.LfgInfos->MyFlags = sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0;
900 partyUpdate.LfgInfos->MyRandomSlot = sLFGMgr->GetSelectedRandomDungeon(player->GetGUID());
901
902 partyUpdate.LfgInfos->MyPartialClear = 0;
903 partyUpdate.LfgInfos->MyGearDiff = 0.0f;
904 partyUpdate.LfgInfos->MyFirstReward = false;
905 if (lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(partyUpdate.LfgInfos->MyRandomSlot, player->GetLevel()))
906 if (Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest))
907 partyUpdate.LfgInfos->MyFirstReward = player->CanRewardQuest(quest, false);
908
909 partyUpdate.LfgInfos->MyStrangerCount = 0;
910 partyUpdate.LfgInfos->MyKickVoteCount = 0;
911 }
912
913 player->SendDirectMessage(partyUpdate.Write());
914}
915
917{
919 partyUpdate.PartyFlags = GROUP_FLAG_DESTROYED;
920 partyUpdate.PartyIndex = m_groupCategory;
921 partyUpdate.PartyType = GROUP_TYPE_NONE;
922 partyUpdate.PartyGUID = m_guid;
923 partyUpdate.MyIndex = -1;
925 player->SendDirectMessage(partyUpdate.Write());
926}
927
928void Group::UpdatePlayerOutOfRange(Player const* player) const
929{
930 if (!player || !player->IsInWorld())
931 return;
932
934 packet.Initialize(player);
935 packet.Write();
936
937 for (GroupReference const& itr : GetMembers())
938 {
939 Player const* member = itr.GetSource();
940 if (member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
941 member->SendDirectMessage(packet.GetRawPacket());
942 }
943}
944
945void Group::BroadcastAddonMessagePacket(WorldPacket const* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group /*= -1*/, ObjectGuid ignore /*= ObjectGuid::Empty*/) const
946{
947 for (GroupReference const& itr : GetMembers())
948 {
949 Player* player = itr.GetSource();
950 if ((!ignore.IsEmpty() && player->GetGUID() == ignore) || (ignorePlayersInBGRaid && player->GetGroup() != this))
951 continue;
952
953 if (player->GetSession()->IsAddonRegistered(prefix) && (group == -1 || itr.getSubGroup() == group))
954 player->SendDirectMessage(packet);
955 }
956}
957
958void Group::BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRaid, int group, ObjectGuid ignoredPlayer) const
959{
960 for (GroupReference const& itr : GetMembers())
961 {
962 Player const* player = itr.GetSource();
963 if ((!ignoredPlayer.IsEmpty() && player->GetGUID() == ignoredPlayer) || (ignorePlayersInBGRaid && player->GetGroup() != this))
964 continue;
965
966 if (group == -1 || itr.getSubGroup() == group)
967 player->SendDirectMessage(packet);
968 }
969}
970
972{
974 if (slot == m_memberSlots.end())
975 return false;
976
977 slot->group = group;
978
980
981 if (!isBGGroup() && !isBFGroup())
982 {
984
985 stmt->setUInt8(0, group);
986 stmt->setUInt64(1, guid.GetCounter());
987
988 CharacterDatabase.Execute(stmt);
989 }
990
991 return true;
992}
993
994bool Group::SameSubGroup(Player const* member1, Player const* member2) const
995{
996 if (!member1 || !member2)
997 return false;
998
999 if (member1->GetGroup() != this || member2->GetGroup() != this)
1000 return false;
1001 else
1002 return member1->GetSubGroup() == member2->GetSubGroup();
1003}
1004
1005// Allows setting sub groups both for online or offline members
1007{
1008 // Only raid groups have sub groups
1009 if (!isRaidGroup())
1010 return;
1011
1012 // Check if player is really in the raid
1013 member_witerator slot = _getMemberWSlot(guid);
1014 if (slot == m_memberSlots.end())
1015 return;
1016
1017 uint8 prevSubGroup = slot->group;
1018 // Abort if the player is already in the target sub group
1019 if (prevSubGroup == group)
1020 return;
1021
1022 // Update the player slot with the new sub group setting
1023 slot->group = group;
1024
1025 // Increase the counter of the new sub group..
1027
1028 // ..and decrease the counter of the previous one
1029 SubGroupCounterDecrease(prevSubGroup);
1030
1031 // Preserve new sub group in database for non-raid groups
1032 if (!isBGGroup() && !isBFGroup())
1033 {
1035
1036 stmt->setUInt8(0, group);
1037 stmt->setUInt64(1, guid.GetCounter());
1038
1039 CharacterDatabase.Execute(stmt);
1040 }
1041
1042 // In case the moved player is online, update the player object with the new sub group references
1043 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1044 {
1045 if (player->GetGroup() == this)
1046 player->GetGroupRef().setSubGroup(group);
1047 else
1048 {
1049 // If player is in BG raid, it is possible that he is also in normal raid - and that normal raid is stored in m_originalGroup reference
1050 player->GetOriginalGroupRef().setSubGroup(group);
1051 }
1052 }
1053
1054 // Broadcast the changes to the group
1055 SendUpdate();
1056}
1057
1059{
1060 if (!isRaidGroup())
1061 return;
1062
1063 member_witerator slots[2];
1064 slots[0] = _getMemberWSlot(firstGuid);
1065 slots[1] = _getMemberWSlot(secondGuid);
1066 if (slots[0] == m_memberSlots.end() || slots[1] == m_memberSlots.end())
1067 return;
1068
1069 if (slots[0]->group == slots[1]->group)
1070 return;
1071
1072 uint8 tmp = slots[0]->group;
1073 slots[0]->group = slots[1]->group;
1074 slots[1]->group = tmp;
1075
1076 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1077 for (uint8 i = 0; i < 2; i++)
1078 {
1079 // Preserve new sub group in database for non-raid groups
1080 if (!isBGGroup() && !isBFGroup())
1081 {
1083
1084 stmt->setUInt8(0, slots[i]->group);
1085 stmt->setUInt64(1, slots[i]->guid.GetCounter());
1086
1087 trans->Append(stmt);
1088 }
1089
1090 if (Player* player = ObjectAccessor::FindConnectedPlayer(slots[i]->guid))
1091 {
1092 if (player->GetGroup() == this)
1093 player->GetGroupRef().setSubGroup(slots[i]->group);
1094 else
1095 player->GetOriginalGroupRef().setSubGroup(slots[i]->group);
1096 }
1097 }
1098 CharacterDatabase.CommitTransaction(trans);
1099
1100 SendUpdate();
1101}
1102
1103// Retrieve the next Round-Roubin player for the group
1104//
1105// No update done if loot method is FFA.
1106//
1107// If the RR player is not yet set for the group, the first group member becomes the round-robin player.
1108// If the RR player is set, the next player in group becomes the round-robin player.
1109//
1110// If ifneed is true,
1111// the current RR player is checked to be near the looted object.
1112// if yes, no update done.
1113// if not, he loses his turn.
1114void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed)
1115{
1116 // round robin style looting applies for all low
1117 // quality items in each loot method except free for all
1118 if (GetLootMethod() == FREE_FOR_ALL)
1119 return;
1120
1121 ObjectGuid oldLooterGUID = GetLooterGuid();
1122 member_citerator guid_itr = _getMemberCSlot(oldLooterGUID);
1123 if (guid_itr != m_memberSlots.end())
1124 {
1125 if (ifneed)
1126 {
1127 // not update if only update if need and ok
1128 Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
1129 if (looter && looter->IsAtGroupRewardDistance(pLootedObject))
1130 return;
1131 }
1132 ++guid_itr;
1133 }
1134
1135 // search next after current
1136 Player* pNewLooter = nullptr;
1137 for (member_citerator itr = guid_itr; itr != m_memberSlots.end(); ++itr)
1138 {
1139 if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1140 if (player->IsAtGroupRewardDistance(pLootedObject))
1141 {
1142 pNewLooter = player;
1143 break;
1144 }
1145 }
1146
1147 if (!pNewLooter)
1148 {
1149 // search from start
1150 for (member_citerator itr = m_memberSlots.begin(); itr != guid_itr; ++itr)
1151 {
1152 if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1153 if (player->IsAtGroupRewardDistance(pLootedObject))
1154 {
1155 pNewLooter = player;
1156 break;
1157 }
1158 }
1159 }
1160
1161 if (pNewLooter)
1162 {
1163 if (oldLooterGUID != pNewLooter->GetGUID())
1164 {
1165 SetLooterGuid(pNewLooter->GetGUID());
1166 SendUpdate();
1167 }
1168 }
1169 else
1170 {
1172 SendUpdate();
1173 }
1174}
1175
1176GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(BattlegroundTemplate const* bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 /*MaxPlayerCount*/, bool isRated, uint32 arenaSlot, ObjectGuid& errorGuid) const
1177{
1178 errorGuid = ObjectGuid::Empty;
1179
1180 // check if this group is LFG group
1181 if (isLFGGroup())
1183
1184 BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->Id);
1185 if (!bgEntry)
1186 return ERR_BATTLEGROUND_JOIN_FAILED; // shouldn't happen
1187
1188 // check for min / max count
1189 uint32 memberscount = GetMembersCount();
1190
1191 if (int32(memberscount) > bgEntry->MaxGroupSize) // no MinPlayerCount for battlegrounds
1192 return ERR_BATTLEGROUND_NONE; // ERR_GROUP_JOIN_BATTLEGROUND_TOO_MANY handled on client side
1193
1194 // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
1195 auto membersIterator = GetMembers().begin();
1196 auto membersEnd = GetMembers().end();
1197 // no reference found, can't join this way
1198 if (membersIterator == membersEnd)
1200
1201 Player* reference = membersIterator->GetSource();
1202 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgOrTemplate->MapIDs.front(), reference->GetLevel());
1203 if (!bracketEntry)
1205
1206 uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
1207 Team team = reference->GetTeam();
1208 bool isMercenary = reference->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || reference->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE);
1209
1210 // check every member of the group to be able to join
1211 memberscount = 0;
1212 for (; membersIterator != membersEnd; ++membersIterator)
1213 {
1214 Player* member = membersIterator->GetSource();
1215 // offline member? don't let join
1216 if (!member)
1218 errorGuid = member->GetGUID();
1219 // rbac permissions
1220 if (!member->CanJoinToBattleground(bgOrTemplate))
1222 // don't allow cross-faction join as group
1223 if (member->GetTeam() != team)
1225 // not in the same battleground level braket, don't let join
1226 PVPDifficultyEntry const* memberBracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bracketEntry->MapID, member->GetLevel());
1227 if (memberBracketEntry != bracketEntry)
1229 // don't let join rated matches if the arena team id doesn't match
1230 if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
1232 // don't let join if someone from the group is already in that bg queue
1233 if (member->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId))
1234 return ERR_BATTLEGROUND_JOIN_FAILED; // not blizz-like
1235 // don't let join if someone from the group is in bg queue random
1238 if (bgOrTemplate->Id != BATTLEGROUND_AA && isInRandomBgQueue)
1239 return ERR_IN_RANDOM_BG;
1240 // don't let join to bg queue random if someone from the group is already in bg queue
1241 if (BattlegroundMgr::IsRandomBattleground(bgOrTemplate->Id) && member->InBattlegroundQueue(true) && !isInRandomBgQueue)
1242 return ERR_IN_NON_RANDOM_BG;
1243 // check for deserter debuff in case not arena queue
1244 if (bgOrTemplate->Id != BATTLEGROUND_AA && member->IsDeserter())
1246 // check if member can join any more battleground queues
1247 if (!member->HasFreeBattlegroundQueueId())
1248 return ERR_BATTLEGROUND_TOO_MANY_QUEUES; // not blizz-like
1249 // check if someone in party is using dungeon system
1250 if (member->isUsingLfg())
1252 // check Freeze debuff
1253 if (member->HasAura(9454))
1255 if (isMercenary != (member->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || member->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE)))
1257
1258 memberscount++;
1259 }
1260
1261 errorGuid = ObjectGuid::Empty;
1262
1263 // only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
1264 if (bgOrTemplate->IsArena() && memberscount != MinPlayerCount)
1266
1267 return ERR_BATTLEGROUND_NONE;
1268}
1269
1271{
1272 m_dungeonDifficulty = difficulty;
1273 if (!isBGGroup() && !isBFGroup())
1274 {
1276
1278 stmt->setUInt32(1, m_dbStoreId);
1279
1280 CharacterDatabase.Execute(stmt);
1281 }
1282
1283 SendUpdate();
1284}
1285
1287{
1288 m_raidDifficulty = difficulty;
1289 if (!isBGGroup() && !isBFGroup())
1290 {
1292
1293 stmt->setUInt8(0, uint8(m_raidDifficulty));
1294 stmt->setUInt32(1, m_dbStoreId);
1295
1296 CharacterDatabase.Execute(stmt);
1297 }
1298
1299 SendUpdate();
1300}
1301
1303{
1304 m_legacyRaidDifficulty = difficulty;
1305 if (!isBGGroup() && !isBFGroup())
1306 {
1308
1310 stmt->setUInt32(1, m_dbStoreId);
1311
1312 CharacterDatabase.Execute(stmt);
1313 }
1314
1315 SendUpdate();
1316}
1317
1319{
1320 if (!mapEntry->IsRaid())
1321 return m_dungeonDifficulty;
1322
1323 MapDifficultyEntry const* defaultDifficulty = sDB2Manager.GetDefaultMapDifficulty(mapEntry->ID);
1324 if (!defaultDifficulty)
1326
1327 DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(defaultDifficulty->DifficultyID);
1328 if (!difficulty || difficulty->Flags & DIFFICULTY_FLAG_LEGACY)
1330
1331 return m_raidDifficulty;
1332}
1333
1335{
1337 {
1338 InstanceMap* map = ref.GetSource();
1339 switch (map->Reset(method))
1340 {
1342 notifyPlayer->SendResetInstanceSuccess(map->GetId());
1343 m_recentInstances.erase(map->GetId());
1344 break;
1346 if (method == InstanceResetMethod::Manual)
1348 else if (method == InstanceResetMethod::OnChangeDifficulty)
1349 m_recentInstances.erase(map->GetId()); // map might not have been reset on difficulty change but we still don't want to zone in there again
1350 break;
1352 m_recentInstances.erase(map->GetId()); // forget the instance, allows retrying different lockout with a new leader
1353 break;
1354 default:
1355 break;
1356 }
1357 }
1358}
1359
1364
1366{
1367 if (player && !player->IsGameMaster() && sMapStore.LookupEntry(player->GetMapId())->IsDungeon())
1368 player->m_InstanceValid = false;
1369}
1370
1372{
1373 // FG: HACK: force flags update on group leave - for values update hack
1374 // -- not very efficient but safe
1375 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1376 {
1377 if (Player * pp = ObjectAccessor::FindPlayer(citr->guid))
1378 {
1379 pp->ForceUpdateFieldChange(pp->m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PvpFlags));
1380 pp->ForceUpdateFieldChange(pp->m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::FactionTemplate));
1381 TC_LOG_DEBUG("misc", "-- Forced group value update for '{}'", pp->GetName());
1382 }
1383 }
1384}
1385
1387{
1388 if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(m_countdowns))
1389 return;
1390
1391 if (!m_countdowns[AsUnderlyingType(timerType)])
1392 m_countdowns[AsUnderlyingType(timerType)] = std::make_unique<CountdownInfo>();
1393
1394 m_countdowns[AsUnderlyingType(timerType)]->StartCountdown(duration, startTime);
1395}
1396
1398{
1399 if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(m_countdowns))
1400 return nullptr;
1401
1402 return m_countdowns[AsUnderlyingType(timerType)].get();
1403}
1404
1406{
1407 m_lootMethod = method;
1408}
1409
1411{
1412 m_looterGuid = guid;
1413}
1414
1419
1421{
1422 m_lootThreshold = threshold;
1423}
1424
1426{
1427 member_witerator slot = _getMemberWSlot(guid);
1428 if (slot == m_memberSlots.end())
1429 return;
1430
1431 slot->roles = roles;
1432 SendUpdate();
1433}
1434
1436{
1437 member_citerator slot = _getMemberCSlot(guid);
1438 if (slot == m_memberSlots.end())
1439 return 0;
1440
1441 return slot->roles;
1442}
1443
1445{
1447 return;
1448
1450 if (m_readyCheckTimer <= Milliseconds::zero())
1451 EndReadyCheck();
1452}
1453
1455{
1457 return;
1458
1459 member_witerator slot = _getMemberWSlot(starterGuid);
1460 if (slot == m_memberSlots.end())
1461 return ;
1462
1463 m_readyCheckStarted = true;
1464 m_readyCheckTimer = duration;
1465
1467
1468 SetMemberReadyChecked(&(*slot));
1469
1471 readyCheckStarted.PartyGUID = m_guid;
1472 readyCheckStarted.PartyIndex = GetGroupCategory();
1473 readyCheckStarted.InitiatorGUID = starterGuid;
1474 readyCheckStarted.Duration = duration;
1475 BroadcastPacket(readyCheckStarted.Write(), false);
1476}
1477
1479{
1481 return;
1482
1483 m_readyCheckStarted = false;
1484 m_readyCheckTimer = Milliseconds::zero();
1485
1487
1488 WorldPackets::Party::ReadyCheckCompleted readyCheckCompleted;
1489 readyCheckCompleted.PartyIndex = 0;
1490 readyCheckCompleted.PartyGUID = m_guid;
1491 BroadcastPacket(readyCheckCompleted.Write(), false);
1492}
1493
1495{
1496 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1497 if (!citr->readyChecked)
1498 return false;
1499 return true;
1500}
1501
1503{
1505 return;
1506
1507 member_witerator slot = _getMemberWSlot(guid);
1508 if (slot != m_memberSlots.end())
1509 SetMemberReadyCheck(&(*slot), ready);
1510}
1511
1513{
1515 response.PartyGUID = m_guid;
1516 response.Player = slot->guid;
1517 response.IsReady = ready;
1518 BroadcastPacket(response.Write(), false);
1519
1521}
1522
1524{
1525 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1526 {
1527 Player* player = ObjectAccessor::FindConnectedPlayer(itr->guid);
1528 if (!player || !player->GetSession())
1529 SetMemberReadyCheck(&(*itr), false);
1530 }
1531}
1532
1534{
1535 slot->readyChecked = true;
1537 EndReadyCheck();
1538}
1539
1541{
1542 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1543 itr->readyChecked = false;
1544}
1545
1546void Group::AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid)
1547{
1548 if (markerId >= RAID_MARKERS_COUNT || m_markers[markerId])
1549 return;
1550
1551 m_activeMarkers |= (1 << markerId);
1552 m_markers[markerId] = std::make_unique<RaidMarker>(mapId, positionX, positionY, positionZ, transportGuid);
1554}
1555
1557{
1558 if (markerId > RAID_MARKERS_COUNT)
1559 return;
1560
1561 for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
1562 if (m_markers[i] && (markerId == i || markerId == RAID_MARKERS_COUNT))
1563 {
1564 m_markers[i] = nullptr;
1565 m_activeMarkers &= ~(1 << i);
1566 }
1567
1569}
1570
1572{
1574
1575 packet.PartyIndex = GetGroupCategory();
1577
1578 for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
1579 if (m_markers[i])
1580 packet.RaidMarkers.push_back(m_markers[i].get());
1581
1582 if (session)
1583 session->SendPacket(packet.Write());
1584 else
1585 BroadcastPacket(packet.Write(), false);
1586}
1587
1588bool Group::IsFull() const
1589{
1590 return isRaidGroup() ? (m_memberSlots.size() >= MAX_RAID_SIZE) : (m_memberSlots.size() >= MAX_GROUP_SIZE);
1591}
1592
1594{
1595 return (m_groupFlags & GROUP_FLAG_LFG) != 0;
1596}
1597
1599{
1600 return (m_groupFlags & GROUP_FLAG_RAID) != 0;
1601}
1602
1604{
1605 return m_bgGroup != nullptr;
1606}
1607
1609{
1610 return m_bfGroup != nullptr;
1611}
1612
1614{
1615 return GetMembersCount() > 0;
1616}
1617
1619{
1620 return m_leaderGuid;
1621}
1622
1624{
1625 return m_guid;
1626}
1627
1628char const* Group::GetLeaderName() const
1629{
1630 return m_leaderName.c_str();
1631}
1632
1634{
1635 return m_lootMethod;
1636}
1637
1639{
1640 if (GetLootMethod() == FREE_FOR_ALL)
1641 return ObjectGuid::Empty;
1642 return m_looterGuid;
1643}
1644
1649
1654
1656{
1657 return _getMemberCSlot(guid) != m_memberSlots.end();
1658}
1659
1661{
1662 return (GetLeaderGUID() == guid);
1663}
1664
1665ObjectGuid Group::GetMemberGUID(std::string const& name) const
1666{
1667 auto itr = std::ranges::find(m_memberSlots, name, &MemberSlot::name);
1668 if (itr != m_memberSlots.end())
1669 return itr->guid;
1670
1671 return ObjectGuid::Empty;
1672}
1673
1675{
1676 member_citerator mslot = _getMemberCSlot(guid);
1677 if (mslot == m_memberSlots.end())
1678 return 0u;
1679 return mslot->flags;
1680}
1681
1683{
1684 member_citerator mslot2 = _getMemberCSlot(guid2);
1685 if (mslot2 == m_memberSlots.end())
1686 return false;
1687 return SameSubGroup(guid1, &*mslot2);
1688}
1689
1690bool Group::SameSubGroup(ObjectGuid guid1, MemberSlot const* slot2) const
1691{
1692 member_citerator mslot1 = _getMemberCSlot(guid1);
1693 if (mslot1 == m_memberSlots.end() || !slot2)
1694 return false;
1695 return (mslot1->group == slot2->group);
1696}
1697
1699{
1700 return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAX_GROUP_SIZE);
1701}
1702
1704{
1705 member_citerator mslot = _getMemberCSlot(guid);
1706 if (mslot == m_memberSlots.end())
1707 return (MAX_RAID_SUBGROUPS+1);
1708 return mslot->group;
1709}
1710
1712{
1713 m_bgGroup = bg;
1714}
1715
1717{
1718 m_bfGroup = bf;
1719}
1720
1722{
1723 // Assistants, main assistants and main tanks are only available in raid groups
1724 if (!isRaidGroup())
1725 return;
1726
1727 // Check if player is really in the raid
1728 member_witerator slot = _getMemberWSlot(guid);
1729 if (slot == m_memberSlots.end())
1730 return;
1731
1732 // Do flag specific actions, e.g ensure uniqueness
1733 switch (flag)
1734 {
1736 RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINASSIST); // Remove main assist flag from current if any.
1737 break;
1739 RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINTANK); // Remove main tank flag from current if any.
1740 break;
1742 break;
1743 default:
1744 return; // This should never happen
1745 }
1746
1747 // Switch the actual flag
1748 ToggleGroupMemberFlag(slot, flag, apply);
1749
1750 // Preserve the new setting in the db
1752
1753 stmt->setUInt8(0, slot->flags);
1754 stmt->setUInt64(1, guid.GetCounter());
1755
1756 CharacterDatabase.Execute(stmt);
1757
1758 // Broadcast the changes to the group
1759 SendUpdate();
1760}
1761
1763{
1764 m_memberMgr.push_front(pRef);
1765}
1766
1768{
1769 auto itr = std::ranges::find(m_memberMgr, guid, [](GroupReference const& ref) { return ref.GetSource()->GetGUID(); });
1770 if (itr != m_memberMgr.end())
1771 itr->unlink();
1772}
1773
1775{
1776 // Sub group counters initialization
1777 if (!m_subGroupsCounts)
1779
1780 memset((void*)m_subGroupsCounts, 0, (MAX_RAID_SUBGROUPS)*sizeof(uint8));
1781
1782 for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1783 ++m_subGroupsCounts[itr->group];
1784}
1785
1787{
1788 return std::ranges::find(m_memberSlots, Guid, &MemberSlot::guid);
1789}
1790
1792{
1793 return std::ranges::find(m_memberSlots, Guid, &MemberSlot::guid);
1794}
1795
1797{
1799 ++m_subGroupsCounts[subgroup];
1800}
1801
1803{
1805 --m_subGroupsCounts[subgroup];
1806}
1807
1809{
1810 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1811 if (itr->flags & flag)
1812 itr->flags &= ~flag;
1813}
1814
1816{
1817 if (apply)
1818 slot->flags |= flag;
1819 else
1820 slot->flags &= ~flag;
1821}
1822
1828
1830{
1831 m_isLeaderOffline = false;
1832}
1833
1835{
1836 if (apply)
1838 else
1840
1841 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1843
1844 if (!isBGGroup() && !isBFGroup())
1845 {
1847
1848 stmt->setUInt16(0, m_groupFlags);
1849 stmt->setUInt32(1, m_dbStoreId);
1850
1851 CharacterDatabase.Execute(stmt);
1852 }
1853
1854 SendUpdate();
1855}
1856
1861
1863{
1864 m_pingRestriction = restrictTo;
1865
1866 if (!isBGGroup() && !isBFGroup())
1867 {
1869
1870 stmt->setInt8(0, int8(m_pingRestriction));
1871 stmt->setUInt32(1, m_dbStoreId);
1872
1873 CharacterDatabase.Execute(stmt);
1874 }
1875
1876 SendUpdate();
1877}
@ SPELL_MERCENARY_CONTRACT_ALLIANCE
@ SPELL_MERCENARY_CONTRACT_HORDE
#define sCharacterCache
@ CHAR_INS_GROUP_MEMBER
@ CHAR_DEL_GROUP_MEMBER_ALL
@ CHAR_DEL_GROUP
@ CHAR_INS_GROUP
@ CHAR_UPD_GROUP_DIFFICULTY
@ CHAR_UPD_GROUP_TYPE
@ CHAR_UPD_GROUP_RAID_DIFFICULTY
@ CHAR_UPD_GROUP_MEMBER_FLAG
@ CHAR_UPD_GROUP_LEADER
@ CHAR_UPD_GROUP_PING_RESTRICTION
@ CHAR_UPD_GROUP_MEMBER_SUBGROUP
@ CHAR_UPD_GROUP_LEGACY_RAID_DIFFICULTY
@ CHAR_DEL_GROUP_MEMBER
@ CHAR_DEL_LFG_DATA
@ IN_MILLISECONDS
Definition Common.h:38
@ MINUTE
Definition Common.h:32
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< BattlemasterListEntry > sBattlemasterListStore("BattlemasterList.db2", &BattlemasterListLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
#define sDB2Manager
Definition DB2Stores.h:579
@ DIFFICULTY_FLAG_LEGACY
Definition DBCEnums.h:983
Difficulty
Definition DBCEnums.h:935
@ DIFFICULTY_NORMAL_RAID
Definition DBCEnums.h:948
@ DIFFICULTY_NORMAL
Definition DBCEnums.h:937
@ DIFFICULTY_10_N
Definition DBCEnums.h:939
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:156
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
#define ASSERT
Definition Errors.h:72
#define sGroupMgr
Definition GroupMgr.h:66
RestrictPingsTo
Definition Group.h:199
@ GROUP_TYPE_NORMAL
Definition Group.h:90
@ GROUP_TYPE_NONE
Definition Group.h:89
#define RAID_MARKERS_COUNT
Definition Group.h:55
GroupFlags
Definition Group.h:95
@ GROUP_FLAG_LFG_RESTRICTED
Definition Group.h:99
@ GROUP_FLAG_RAID
Definition Group.h:98
@ GROUP_MASK_BGRAID
Definition Group.h:108
@ GROUP_FLAG_NONE
Definition Group.h:96
@ GROUP_FLAG_EVERYONE_ASSISTANT
Definition Group.h:103
@ GROUP_FLAG_LFG
Definition Group.h:100
@ GROUP_FLAG_DESTROYED
Definition Group.h:101
#define MAX_GROUP_SIZE
Definition Group.h:50
GroupMemberFlags
Definition Group.h:75
@ MEMBER_FLAG_ASSISTANT
Definition Group.h:76
@ MEMBER_FLAG_MAINASSIST
Definition Group.h:78
@ MEMBER_FLAG_MAINTANK
Definition Group.h:77
#define MAX_RAID_SIZE
Definition Group.h:51
@ GROUP_UPDATE_FULL
Definition Group.h:141
#define TARGET_ICONS_COUNT
Definition Group.h:54
CountdownTimerType
Definition Group.h:176
@ GROUP_UPDATE_PET_FULL
Definition Group.h:159
@ GROUP_CATEGORY_HOME
Definition Group.h:113
@ GROUP_CATEGORY_INSTANCE
Definition Group.h:114
#define MAX_RAID_SUBGROUPS
Definition Group.h:52
#define sLFGMgr
Definition LFGMgr.h:515
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
LootMethod
Definition Loot.h:89
@ PERSONAL_LOOT
Definition Loot.h:95
@ MASTER_LOOT
Definition Loot.h:92
@ FREE_FOR_ALL
Definition Loot.h:90
InstanceResetMethod
Definition Map.h:869
#define sObjectMgr
Definition ObjectMgr.h:1873
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ PLAYER_FLAGS_GROUP_LEADER
Definition Player.h:512
Races
Definition RaceMask.h:28
#define sScriptMgr
Definition ScriptMgr.h:1449
GroupJoinBattlegroundResult
@ ERR_BATTLEGROUND_JOIN_TIMED_OUT
@ ERR_BATTLEGROUND_JOIN_FAILED
@ ERR_LFG_CANT_USE_BATTLEGROUND
@ ERR_IN_NON_RANDOM_BG
@ ERR_BATTLEGROUND_NONE
@ ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS
@ ERR_ARENA_TEAM_PARTY_SIZE
@ ERR_BATTLEGROUND_TOO_MANY_QUEUES
@ ERR_BATTLEGROUND_JOIN_MERCENARY
@ ERR_BATTLEGROUND_JOIN_RANGE_INDEX
@ ERR_IN_RANDOM_BG
@ INSTANCE_RESET_FAILED
ItemQualities
@ ITEM_QUALITY_UNCOMMON
@ ALLIANCE
@ HORDE
@ BATTLEGROUND_AA
@ BATTLEGROUND_RANDOM_EPIC
@ BATTLEGROUND_RB
RemoveMethod
@ GROUP_REMOVEMETHOD_KICK_LFG
@ GROUP_REMOVEMETHOD_KICK
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsInWorld() const
Definition BaseEntity.h:158
static BattlegroundQueueTypeId BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize)
static bool IsRandomBattleground(uint32 battlemasterListId)
Group * GetBgRaid(Team team) const
void SetBgRaid(Team team, Group *bg_raid)
static PVPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
Class used to access individual fields of database query result.
Definition Field.h:94
uint64 GetUInt64() const noexcept
Definition Field.cpp:71
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
Seconds GetTimeLeft() const
Definition Group.cpp:42
void StartCountdown(Seconds duration, Optional< time_t > startTime={ })
Definition Group.cpp:47
bool IsRunning() const
Definition Group.cpp:53
Definition Group.h:209
ObjectGuid m_targetIcons[TARGET_ICONS_COUNT]
Definition Group.h:443
member_citerator _getMemberCSlot(ObjectGuid Guid) const
Definition Group.cpp:1786
bool IsReadyCheckCompleted(void) const
Definition Group.cpp:1494
void BroadcastGroupUpdate(void)
Definition Group.cpp:1371
bool isLFGGroup() const
Definition Group.cpp:1593
bool m_isLeaderOffline
Definition Group.h:453
void StartLeaderOfflineTimer()
Definition Group.cpp:1823
uint8 GetMemberGroup(ObjectGuid guid) const
Definition Group.cpp:1703
void SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid)
Definition Group.cpp:1058
ObjectGuid GetMasterLooterGuid() const
Definition Group.cpp:1645
Battlefield * m_bfGroup
Definition Group.h:442
uint8 m_leaderFactionGroup
Definition Group.h:434
ObjectGuid GetMemberGUID(std::string const &name) const
Definition Group.cpp:1665
bool AddLeaderInvite(Player *player)
Definition Group.cpp:375
void SetBattlefieldGroup(Battlefield *bf)
Definition Group.cpp:1716
InvitesList m_invitees
Definition Group.h:432
void ResetInstances(InstanceResetMethod method, Player *notifyPlayer)
Definition Group.cpp:1334
void DeleteRaidMarker(uint8 markerId)
Definition Group.cpp:1556
GroupCategory GetGroupCategory() const
Definition Group.h:307
RestrictPingsTo m_pingRestriction
Definition Group.h:466
Difficulty m_legacyRaidDifficulty
Definition Group.h:440
bool IsCreated() const
Definition Group.cpp:1613
void SendUpdate() const
Definition Group.cpp:809
bool _setMembersGroup(ObjectGuid guid, uint8 group)
Definition Group.cpp:971
void SubGroupCounterDecrease(uint8 subgroup)
Definition Group.cpp:1802
void SetLootMethod(LootMethod method)
Definition Group.cpp:1405
void ChangeMembersGroup(ObjectGuid guid, uint8 group)
Definition Group.cpp:1006
void SendTargetIconList(WorldSession *session) const
Definition Group.cpp:796
void SetEveryoneIsAssistant(bool apply)
Definition Group.cpp:1834
GroupCategory m_groupCategory
Definition Group.h:437
ObjectGuid m_leaderGuid
Definition Group.h:433
void RemoveAllInvites()
Definition Group.cpp:395
std::string m_leaderName
Definition Group.h:435
void AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid=ObjectGuid::Empty)
Definition Group.cpp:1546
void _initRaidSubGroupsCounter()
Definition Group.cpp:1774
void EndReadyCheck()
Definition Group.cpp:1478
ObjectGuid m_looterGuid
Definition Group.h:446
std::array< std::unique_ptr< RaidMarker >, RAID_MARKERS_COUNT > m_markers
Definition Group.h:461
void SetLootThreshold(ItemQualities threshold)
Definition Group.cpp:1420
void Disband(bool hideDestroy=false)
Definition Group.cpp:708
void LoadGroupFromDB(Field *field)
Definition Group.cpp:211
bool AddMember(Player *player)
Definition Group.cpp:424
bool IsLeader(ObjectGuid guid) const
Definition Group.cpp:1660
Battleground * m_bgGroup
Definition Group.h:441
Difficulty m_raidDifficulty
Definition Group.h:439
void SetMemberReadyCheck(ObjectGuid guid, bool ready)
Definition Group.cpp:1502
void BroadcastAddonMessagePacket(WorldPacket const *packet, const std::string &prefix, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignore=ObjectGuid::Empty) const
Definition Group.cpp:945
GroupRefManager m_memberMgr
Definition Group.h:431
void SetDungeonDifficultyID(Difficulty difficulty)
Definition Group.cpp:1270
void SetRestrictPingsTo(RestrictPingsTo restrictTo)
Definition Group.cpp:1862
uint32 m_activeMarkers
Definition Group.h:462
void SetMasterLooterGuid(ObjectGuid guid)
Definition Group.cpp:1415
void SetRaidDifficultyID(Difficulty difficulty)
Definition Group.cpp:1286
Trinity::unique_trackable_ptr< Group > m_scriptRef
Definition Group.h:469
ObjectGuid GetGUID() const
Definition Group.cpp:1623
void RemoveInvite(Player *player)
Definition Group.cpp:386
void SetLegacyRaidDifficultyID(Difficulty difficulty)
Definition Group.cpp:1302
bool isBGGroup() const
Definition Group.cpp:1603
void ConvertToRaid()
Definition Group.cpp:299
ItemQualities GetLootThreshold() const
Definition Group.cpp:1650
void SetOfflineMembersReadyChecked(void)
Definition Group.cpp:1523
std::unordered_map< uint32, std::pair< ObjectGuid, uint32 > > m_recentInstances
Definition Group.h:448
MemberSlotList m_memberSlots
Definition Group.h:430
void StartReadyCheck(ObjectGuid starterGuid, Milliseconds duration=Milliseconds(READYCHECK_DURATION))
Definition Group.cpp:1454
void SendRaidMarkersChanged(WorldSession *session=nullptr) const
Definition Group.cpp:1571
uint32 GetMembersCount() const
Definition Group.h:339
Group()
Definition Group.cpp:58
void StopLeaderOfflineTimer()
Definition Group.cpp:1829
void UpdatePlayerOutOfRange(Player const *player) const
Definition Group.cpp:928
void Update(uint32 diff)
Definition Group.cpp:90
void ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)
Definition Group.cpp:1815
void _homebindIfInstance(Player *player)
Definition Group.cpp:1365
void SetLfgRoles(ObjectGuid guid, uint8 roles)
Definition Group.cpp:1425
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag)
Definition Group.cpp:1721
void SendUpdateToPlayer(Player *player, MemberSlot const *slot=nullptr) const
Definition Group.cpp:821
TimeTracker m_leaderOfflineTimer
Definition Group.h:454
void ResetMemberReadyChecked(void)
Definition Group.cpp:1540
member_witerator _getMemberWSlot(ObjectGuid Guid)
Definition Group.cpp:1791
ObjectGuid GetLooterGuid() const
Definition Group.cpp:1638
Milliseconds m_readyCheckTimer
Definition Group.h:458
uint32 m_dbStoreId
Definition Group.h:452
void DelinkMember(ObjectGuid guid)
Definition Group.cpp:1767
void ChangeLeader(ObjectGuid guid)
Definition Group.cpp:663
const char * GetLeaderName() const
Definition Group.cpp:1628
void ConvertToLFG()
Definition Group.cpp:281
ObjectGuid m_masterLooterGuid
Definition Group.h:447
MemberSlotList::iterator member_witerator
Definition Group.h:246
void SetBattlegroundGroup(Battleground *bg)
Definition Group.cpp:1711
uint8 GetLfgRoles(ObjectGuid guid) const
Definition Group.cpp:1435
LootMethod GetLootMethod() const
Definition Group.cpp:1633
void UpdateLooterGuid(WorldObject *pLootedObject, bool ifneed=false)
Definition Group.cpp:1114
CountdownInfo const * GetCountdownInfo(CountdownTimerType timerType) const
Definition Group.cpp:1397
bool RemoveMember(ObjectGuid guid, RemoveMethod method=GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker=ObjectGuid::Empty, const char *reason=nullptr)
Definition Group.cpp:547
bool m_readyCheckStarted
Definition Group.h:457
Player * GetInvited(ObjectGuid guid) const
Definition Group.cpp:404
bool HasFreeSlotSubGroup(uint8 subgroup) const
Definition Group.cpp:1698
bool isBFGroup() const
Definition Group.cpp:1608
void LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
Definition Group.cpp:248
bool IsMember(ObjectGuid guid) const
Definition Group.cpp:1655
void UpdateReadyCheck(uint32 diff)
Definition Group.cpp:1444
LootMethod m_lootMethod
Definition Group.h:444
void BroadcastPacket(WorldPacket const *packet, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignoredPlayer=ObjectGuid::Empty) const
Definition Group.cpp:958
void SelectNewPartyOrRaidLeader()
Definition Group.cpp:105
GroupRefManager & GetMembers()
Definition Group.h:336
bool SameSubGroup(ObjectGuid guid1, ObjectGuid guid2) const
Definition Group.cpp:1682
void LinkOwnedInstance(GroupInstanceReference *ref)
Definition Group.cpp:1360
ObjectGuid m_guid
Definition Group.h:451
bool AddInvite(Player *player)
Definition Group.cpp:354
void ConvertToGroup()
Definition Group.cpp:323
uint8 * m_subGroupsCounts
Definition Group.h:450
Difficulty GetDifficultyID(MapEntry const *mapEntry) const
Definition Group.cpp:1318
MemberSlotList::const_iterator member_citerator
Definition Group.h:223
std::array< std::unique_ptr< CountdownInfo >, 3 > m_countdowns
Definition Group.h:464
void SetMemberReadyChecked(MemberSlot *slot)
Definition Group.cpp:1533
void SubGroupCounterIncrease(uint8 subgroup)
Definition Group.cpp:1796
void SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy)
Definition Group.cpp:775
bool Create(Player *leader)
Definition Group.cpp:141
RestrictPingsTo GetRestrictPings() const
Definition Group.cpp:1857
bool IsFull() const
Definition Group.cpp:1588
ObjectGuid GetLeaderGUID() const
Definition Group.cpp:1618
Difficulty m_dungeonDifficulty
Definition Group.h:438
uint8 GetMemberFlags(ObjectGuid guid) const
Definition Group.cpp:1674
~Group()
Definition Group.cpp:73
void SetLooterGuid(ObjectGuid guid)
Definition Group.cpp:1410
void LinkMember(GroupReference *pRef)
Definition Group.cpp:1762
ItemQualities m_lootThreshold
Definition Group.h:445
bool isRaidGroup() const
Definition Group.cpp:1598
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(BattlegroundTemplate const *bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid &errorGuid) const
Definition Group.cpp:1176
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag)
Definition Group.cpp:1808
GroupInstanceRefManager m_ownedInstancesMgr
Definition Group.h:449
void SendUpdateDestroyGroupToPlayer(Player *player) const
Definition Group.cpp:916
GroupFlags m_groupFlags
Definition Group.h:436
void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional< time_t > startTime={ })
Definition Group.cpp:1386
InstanceResetResult Reset(InstanceResetMethod method)
Definition Map.cpp:3078
uint32 size() const
Definition LinkedList.h:129
void push_back(LinkedListElement *pElem)
Definition LinkedList.h:114
void push_front(LinkedListElement *pElem)
Definition LinkedList.h:109
uint32 GetId() const
Definition Map.cpp:3288
InstanceMap * ToInstanceMap()
Definition Map.h:495
LowType GetCounter() const
Definition ObjectGuid.h:336
static ObjectGuid const Empty
Definition ObjectGuid.h:314
bool IsEmpty() const
Definition ObjectGuid.h:362
uint64 GetRawValue(std::size_t i) const
Definition ObjectGuid.h:325
void SetRawValue(std::span< uint8 const > rawBytes)
static constexpr std::size_t BytesSize
Definition ObjectGuid.h:319
uint64 LowType
Definition ObjectGuid.h:321
void Clear()
Definition ObjectGuid.h:329
void BuildValuesUpdateBlockForPlayerWithFlag(UpdateData *data, UF::UpdateFieldFlag flags, Player const *target) const
Definition Object.cpp:100
Definition Pet.h:40
bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:25699
bool m_InstanceValid
Definition Player.h:2748
void SetOriginalGroup(Group *group, int8 subgroup=-1)
Definition Player.cpp:26711
void SetPlayerFlag(PlayerFlags flags)
Definition Player.h:2896
void SetPartyType(GroupCategory category, uint8 type)
Definition Player.cpp:26724
int32 NextGroupUpdateSequenceNumber(GroupCategory category)
Definition Player.cpp:26741
void SetGroupUpdateFlag(uint32 flag)
Definition Player.h:2789
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6193
void SendResetInstanceFailed(ResetFailedReason reason, uint32 mapID) const
Definition Player.cpp:21879
void SetGroup(Group *group, int8 subgroup=-1)
Definition Player.cpp:24890
void SetGroupInvite(Group *group)
Definition Player.h:2780
void RemoveFromBattlegroundOrBattlefieldRaid()
Definition Player.cpp:26699
Group * GetOriginalGroup() const
Definition Player.h:2800
bool CanRewardQuest(Quest const *quest, bool msg) const
Definition Player.cpp:14576
void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects)
Definition Player.cpp:25880
bool HaveAtClient(BaseEntity const *u) const
Definition Player.cpp:24425
Pet * GetPet() const
Definition Player.cpp:22007
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition Player.cpp:26375
bool IsDeserter() const
Definition Player.h:2578
bool InBattlegroundQueue(bool ignoreArena=false) const
Definition Player.cpp:25666
WorldSession * GetSession() const
Definition Player.h:2256
void ResetGroupUpdateSequenceIfNeeded(Group const *group)
Definition Player.cpp:26730
Difficulty GetDungeonDifficultyID() const
Definition Player.h:2166
bool CanJoinToBattleground(BattlegroundTemplate const *bg) const
Definition Player.cpp:24310
bool HasFreeBattlegroundQueueId() const
Definition Player.cpp:25727
bool IsGameMaster() const
Definition Player.h:1293
static Difficulty CheckLoadedLegacyRaidDifficultyID(Difficulty difficulty)
Definition Player.cpp:30590
static uint8 GetFactionGroupForRace(uint8 race)
Definition Player.cpp:6398
bool CheckInstanceValidity(bool)
Definition Player.cpp:20140
Difficulty GetRaidDifficultyID() const
Definition Player.h:2167
void SendResetInstanceSuccess(uint32 MapId) const
Definition Player.cpp:21872
static Difficulty CheckLoadedRaidDifficultyID(Difficulty difficulty)
Definition Player.cpp:30575
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2781
uint8 GetSubGroup() const
Definition Player.h:2787
void FailCriteria(CriteriaFailEvent condition, int32 failAsset)
Definition Player.cpp:27526
Group * GetGroupInvite() const
Definition Player.h:2779
static Difficulty CheckLoadedDungeonDifficultyID(Difficulty difficulty)
Definition Player.cpp:30560
uint32 GetArenaTeamId(uint8) const
Definition Player.h:2158
Difficulty GetLegacyRaidDifficultyID() const
Definition Player.h:2168
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition Player.cpp:26689
Team GetTeam() const
Definition Player.h:2406
bool isUsingLfg() const
Definition Player.cpp:26673
void setInt8(uint8 index, int8 value)
void setBinary(uint8 index, std::vector< uint8 > &&value)
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setUInt64(uint8 index, uint64 value)
void setUInt8(uint8 index, uint8 value)
iterator end()
Definition RefManager.h:36
iterator begin()
Definition RefManager.h:35
FROM * GetSource() const
Definition Reference.h:87
uint8 GetClass() const
Definition Unit.h:776
bool IsAlive() const
Definition Unit.h:1205
void RemoveAllGroupBuffsFromCaster(ObjectGuid casterGUID)
Definition Unit.cpp:4577
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1897
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
uint8 GetLevel() const
Definition Unit.h:769
uint8 GetRace() const
Definition Unit.h:773
bool HasData() const
Definition UpdateData.h:49
bool BuildPacket(WorldPacket *packet)
constexpr uint32 GetMapId() const
Definition Position.h:216
Map * GetMap() const
Definition Object.h:411
float GetSightRange(WorldObject const *target=nullptr) const
Definition Object.cpp:795
std::string const & GetName() const
Definition Object.h:342
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:494
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:467
WorldPacket const * GetRawPacket() const
Definition Packet.h:38
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
Optional< PartyLootSettings > LootSettings
Optional< PartyDifficultySettings > DifficultySettings
std::vector< PartyPlayerInfo > PlayerList
WorldPacket const * Write() override
Optional< PartyLFGInfo > LfgInfos
WorldPacket const * Write() override
std::vector< RaidMarker const * > RaidMarkers
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPackets::Duration< Milliseconds > Duration
std::vector< std::pair< uint8, ObjectGuid > > TargetIcons
Player session in the World.
bool PlayerLogout() const
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
bool IsAddonRegistered(std::string_view prefix) const
time_t GetGameTime()
Definition GameTime.cpp:52
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
@ LFG_STATE_FINISHED_DUNGEON
Definition LFG.h:81
BattlegroundTypeId Id
std::vector< int32 > MapIDs
ObjectGuid guid
Definition Group.h:213
std::string name
Definition Group.h:214
bool readyChecked
Definition Group.h:220
bool IsRaid() const
void Update(int32 diff)
Definition Timer.h:121
bool Passed() const
Definition Timer.h:131
void Reset(int32 expiry)
Definition Timer.h:136
UpdateField< int32, 32, 47 > FactionTemplate
UpdateField< uint8, 64, 88 > PvpFlags
Reward info.
Definition LFGMgr.h:237