TrinityCore
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
63{
64 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
65 m_targetIcons[i].Clear();
66
67 for (uint8 i = 0; i < RAID_MARKERS_COUNT; ++i)
68 m_markers[i] = nullptr;
69
70 m_countdowns = { nullptr, nullptr, nullptr };
71}
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 = ObjectGuid::Create<HighGuid::Player>(fields[16].GetUInt64());
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
282{
286 if (!isBGGroup() && !isBFGroup())
287 {
289
290 stmt->setUInt16(0, m_groupFlags);
291 stmt->setUInt32(1, m_dbStoreId);
292
293 CharacterDatabase.Execute(stmt);
294 }
295
296 SendUpdate();
297}
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
497 if (!IsLeader(player->GetGUID()) && !isBGGroup() && !isBFGroup())
498 {
500 {
502 player->SendDungeonDifficulty();
503 }
504 if (player->GetRaidDifficultyID() != GetRaidDifficultyID())
505 {
507 player->SendRaidDifficulty(false);
508 }
510 {
512 player->SendRaidDifficulty(true);
513 }
514 }
515
517 if (Pet* pet = player->GetPet())
518 pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
519
521
522 // quest related GO state dependent from raid membership
523 if (isRaidGroup())
524 player->UpdateVisibleObjectInteractions(false, true, false, true);
525
527
528 {
529 // Broadcast new player group member fields to rest of the group
530 UpdateData groupData(player->GetMapId());
531 WorldPacket groupDataPacket;
532
533 // Broadcast group members' fields to player
534 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
535 {
536 if (itr->GetSource() == player)
537 continue;
538
539 if (Player* existingMember = itr->GetSource())
540 {
541 if (player->HaveAtClient(existingMember))
542 existingMember->BuildValuesUpdateBlockForPlayerWithFlag(&groupData, UF::UpdateFieldFlag::PartyMember, player);
543
544 if (existingMember->HaveAtClient(player))
545 {
546 UpdateData newData(player->GetMapId());
547 WorldPacket newDataPacket;
549 if (newData.HasData())
550 {
551 newData.BuildPacket(&newDataPacket);
552 existingMember->SendDirectMessage(&newDataPacket);
553 }
554 }
555 }
556 }
557
558 if (groupData.HasData())
559 {
560 groupData.BuildPacket(&groupDataPacket);
561 player->SendDirectMessage(&groupDataPacket);
562 }
563 }
564
565 return true;
566}
567
568bool Group::RemoveMember(ObjectGuid guid, RemoveMethod method /*= GROUP_REMOVEMETHOD_DEFAULT*/, ObjectGuid kicker /*= 0*/, const char* reason /*= nullptr*/)
569{
571
572 sScriptMgr->OnGroupRemoveMember(this, guid, method, kicker, reason);
573
575 if (player)
576 {
577 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
578 {
579 if (Player* groupMember = itr->GetSource())
580 {
581 if (groupMember->GetGUID() == guid)
582 continue;
583
584 groupMember->RemoveAllGroupBuffsFromCaster(guid);
585 player->RemoveAllGroupBuffsFromCaster(groupMember->GetGUID());
586 }
587 }
588 }
589
590 // LFG group vote kick handled in scripts
591 if (isLFGGroup() && method == GROUP_REMOVEMETHOD_KICK)
592 return !m_memberSlots.empty();
593
594 if (player)
596
597 // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group)
598 if (GetMembersCount() > ((isBGGroup() || isLFGGroup() || isBFGroup()) ? 1u : 2u))
599 {
600 if (player)
601 {
602 // Battleground group handling
603 if (isBGGroup() || isBFGroup())
605 else
606 // Regular group
607 {
608 if (player->GetOriginalGroup() == this)
609 player->SetOriginalGroup(nullptr);
610 else
611 player->SetGroup(nullptr);
612
613 // quest related GO state dependent from raid membership
614 player->UpdateVisibleObjectInteractions(false, true, false, true);
615 }
616
618
619 if (method == GROUP_REMOVEMETHOD_KICK || method == GROUP_REMOVEMETHOD_KICK_LFG)
621
622 _homebindIfInstance(player);
623 }
624
625 // Remove player from group in DB
626 if (!isBGGroup() && !isBFGroup())
627 {
629 stmt->setUInt64(0, guid.GetCounter());
630 CharacterDatabase.Execute(stmt);
631 DelinkMember(guid);
632 }
633
634 // Update subgroups
636 if (slot != m_memberSlots.end())
637 {
638 SubGroupCounterDecrease(slot->group);
639 m_memberSlots.erase(slot);
640 }
641
642 // Pick new leader if necessary
643 if (m_leaderGuid == guid)
644 {
645 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
646 {
648 {
649 ChangeLeader(itr->guid);
650 break;
651 }
652 }
653 }
654
655 SendUpdate();
656
657 if (isLFGGroup() && GetMembersCount() == 1)
658 {
660 uint32 mapId = sLFGMgr->GetDungeonMapId(GetGUID());
661 if (!mapId || !leader || (leader->IsAlive() && leader->GetMapId() != mapId))
662 {
663 Disband();
664 return false;
665 }
666 }
667
668 if (m_memberMgr.getSize() < ((isLFGGroup() || isBGGroup()) ? 1u : 2u))
669 Disband();
670 else if (player)
671 {
672 // send update to removed player too so party frames are destroyed clientside
674 }
675
676 return true;
677 }
678 // If group size before player removal <= 2 then disband it
679 else
680 {
681 Disband();
682 return false;
683 }
684}
685
687{
688 member_witerator slot = _getMemberWSlot(newLeaderGuid);
689
690 if (slot == m_memberSlots.end())
691 return;
692
693 Player* newLeader = ObjectAccessor::FindConnectedPlayer(slot->guid);
694
695 // Don't allow switching leader to offline players
696 if (!newLeader)
697 return;
698
699 sScriptMgr->OnGroupChangeLeader(this, newLeaderGuid, m_leaderGuid);
700
701 if (!isBGGroup() && !isBFGroup())
702 {
703 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
704
705 // Update the group leader
707
708 stmt->setUInt64(0, newLeader->GetGUID().GetCounter());
709 stmt->setUInt32(1, m_dbStoreId);
710
711 trans->Append(stmt);
712
713 CharacterDatabase.CommitTransaction(trans);
714 }
715
717 oldLeader->RemovePlayerFlag(PLAYER_FLAGS_GROUP_LEADER);
718
720 m_leaderGuid = newLeader->GetGUID();
722 m_leaderName = newLeader->GetName();
724
726 groupNewLeader.Name = m_leaderName;
727 groupNewLeader.PartyIndex = GetGroupCategory();
728 BroadcastPacket(groupNewLeader.Write(), true);
729}
730
731void Group::Disband(bool hideDestroy /* = false */)
732{
733 sScriptMgr->OnGroupDisband(this);
734
735 Player* player;
736 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
737 {
738 player = ObjectAccessor::FindConnectedPlayer(citr->guid);
739 if (!player)
740 continue;
741
742 //we cannot call _removeMember because it would invalidate member iterator
743 //if we are removing player from battleground raid
744 if (isBGGroup() || isBFGroup())
746 else
747 {
748 //we can remove player who is in battleground from his original group
749 if (player->GetOriginalGroup() == this)
750 player->SetOriginalGroup(nullptr);
751 else
752 player->SetGroup(nullptr);
753 }
754
756
757 // quest related GO state dependent from raid membership
758 if (isRaidGroup())
759 player->UpdateVisibleObjectInteractions(false, true, false, true);
760
761 if (!hideDestroy)
763
765
766 _homebindIfInstance(player);
767 }
768
769 m_memberSlots.clear();
770
772
773 if (!isBGGroup() && !isBFGroup())
774 {
775 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
776
778 stmt->setUInt32(0, m_dbStoreId);
779 trans->Append(stmt);
780
781 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_MEMBER_ALL);
782 stmt->setUInt32(0, m_dbStoreId);
783 trans->Append(stmt);
784
785 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
786 stmt->setUInt32(0, m_dbStoreId);
787 trans->Append(stmt);
788
789 CharacterDatabase.CommitTransaction(trans);
790
791 sGroupMgr->FreeGroupDbStoreId(this);
792 }
793
794 sGroupMgr->RemoveGroup(this);
795 delete this;
796}
797
798void Group::SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy)
799{
800 if (symbol >= TARGET_ICONS_COUNT)
801 return;
802
803 // clean other icons
804 if (!target.IsEmpty())
805 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
806 if (m_targetIcons[i] == target)
807 SetTargetIcon(i, ObjectGuid::Empty, changedBy);
808
809 m_targetIcons[symbol] = target;
810
812 updateSingle.PartyIndex = GetGroupCategory();
813 updateSingle.Target = target;
814 updateSingle.ChangedBy = changedBy;
815 updateSingle.Symbol = symbol;
816 BroadcastPacket(updateSingle.Write(), true);
817}
818
820{
821 if (!session)
822 return;
823
825 updateAll.PartyIndex = GetGroupCategory();
826 for (uint8 i = 0; i < TARGET_ICONS_COUNT; i++)
827 updateAll.TargetIcons.try_emplace(i, m_targetIcons[i]);
828
829 session->SendPacket(updateAll.Write());
830}
831
833{
834 for (MemberSlot const& memberSlot : m_memberSlots)
835 SendUpdateToPlayer(memberSlot.guid, &memberSlot);
836}
837
838void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot const* slot) const
839{
840 Player* player = ObjectAccessor::FindConnectedPlayer(playerGUID);
841
842 if (!player || !player->GetSession() || player->GetGroup() != this)
843 return;
844
845 // if MemberSlot wasn't provided
846 if (!slot)
847 {
848 member_citerator witr = _getMemberCSlot(playerGUID);
849
850 if (witr == m_memberSlots.end()) // if there is no MemberSlot for such a player
851 return;
852
853 slot = &(*witr);
854 }
855
857
858 partyUpdate.PartyFlags = m_groupFlags;
859 partyUpdate.PartyIndex = m_groupCategory;
861
862 partyUpdate.PartyGUID = m_guid;
863 partyUpdate.LeaderGUID = m_leaderGuid;
865
867
869
870 partyUpdate.MyIndex = -1;
871 uint8 index = 0;
872 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr, ++index)
873 {
874 if (slot->guid == citr->guid)
875 partyUpdate.MyIndex = index;
876
877 Player* member = ObjectAccessor::FindConnectedPlayer(citr->guid);
878
879 WorldPackets::Party::PartyPlayerInfo& playerInfos = partyUpdate.PlayerList.emplace_back();
880
881 playerInfos.GUID = citr->guid;
882 playerInfos.Name = citr->name;
883 playerInfos.Class = citr->_class;
884
885 playerInfos.FactionGroup = Player::GetFactionGroupForRace(citr->race);
886
887 playerInfos.Connected = member && member->GetSession() && !member->GetSession()->PlayerLogout();
888
889 playerInfos.Subgroup = citr->group; // groupid
890 playerInfos.Flags = citr->flags; // See enum GroupMemberFlags
891 playerInfos.RolesAssigned = citr->roles; // Lfg Roles
892 }
893
894 if (GetMembersCount() > 1)
895 {
896 // LootSettings
897 partyUpdate.LootSettings.emplace();
898 partyUpdate.LootSettings->Method = m_lootMethod;
899 partyUpdate.LootSettings->Threshold = m_lootThreshold;
901
902 // Difficulty Settings
903 partyUpdate.DifficultySettings.emplace();
904 partyUpdate.DifficultySettings->DungeonDifficultyID = m_dungeonDifficulty;
905 partyUpdate.DifficultySettings->RaidDifficultyID = m_raidDifficulty;
906 partyUpdate.DifficultySettings->LegacyRaidDifficultyID = m_legacyRaidDifficulty;
907 }
908
909 // LfgInfos
910 if (isLFGGroup())
911 {
912 partyUpdate.LfgInfos.emplace();
913
914 partyUpdate.LfgInfos->Slot = sLFGMgr->GetLFGDungeonEntry(sLFGMgr->GetDungeon(m_guid));
915 partyUpdate.LfgInfos->BootCount = 0;
916 partyUpdate.LfgInfos->Aborted = false;
917
918 partyUpdate.LfgInfos->MyFlags = sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0;
919 partyUpdate.LfgInfos->MyRandomSlot = sLFGMgr->GetSelectedRandomDungeon(player->GetGUID());
920
921 partyUpdate.LfgInfos->MyPartialClear = 0;
922 partyUpdate.LfgInfos->MyGearDiff = 0.0f;
923 partyUpdate.LfgInfos->MyFirstReward = false;
924 if (lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(partyUpdate.LfgInfos->MyRandomSlot, player->GetLevel()))
925 if (Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest))
926 partyUpdate.LfgInfos->MyFirstReward = player->CanRewardQuest(quest, false);
927
928 partyUpdate.LfgInfos->MyStrangerCount = 0;
929 partyUpdate.LfgInfos->MyKickVoteCount = 0;
930 }
931
932 player->SendDirectMessage(partyUpdate.Write());
933}
934
936{
938 partyUpdate.PartyFlags = GROUP_FLAG_DESTROYED;
939 partyUpdate.PartyIndex = m_groupCategory;
940 partyUpdate.PartyType = GROUP_TYPE_NONE;
941 partyUpdate.PartyGUID = m_guid;
942 partyUpdate.MyIndex = -1;
944 player->SendDirectMessage(partyUpdate.Write());
945}
946
947void Group::UpdatePlayerOutOfRange(Player const* player) const
948{
949 if (!player || !player->IsInWorld())
950 return;
951
953 packet.Initialize(player);
954 packet.Write();
955
956 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
957 {
958 Player const* member = itr->GetSource();
959 if (member && member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
960 member->SendDirectMessage(packet.GetRawPacket());
961 }
962}
963
964void Group::BroadcastAddonMessagePacket(WorldPacket const* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group /*= -1*/, ObjectGuid ignore /*= ObjectGuid::Empty*/) const
965{
966 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
967 {
968 Player* player = itr->GetSource();
969 if (!player || (!ignore.IsEmpty() && player->GetGUID() == ignore) || (ignorePlayersInBGRaid && player->GetGroup() != this))
970 continue;
971
972 if (player->GetSession()->IsAddonRegistered(prefix) && (group == -1 || itr->getSubGroup() == group))
973 player->SendDirectMessage(packet);
974 }
975}
976
977void Group::BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRaid, int group, ObjectGuid ignoredPlayer) const
978{
979 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
980 {
981 Player const* player = itr->GetSource();
982 if (!player || (!ignoredPlayer.IsEmpty() && player->GetGUID() == ignoredPlayer) || (ignorePlayersInBGRaid && player->GetGroup() != this))
983 continue;
984
985 if (group == -1 || itr->getSubGroup() == group)
986 player->SendDirectMessage(packet);
987 }
988}
989
991{
993 if (slot == m_memberSlots.end())
994 return false;
995
996 slot->group = group;
997
999
1000 if (!isBGGroup() && !isBFGroup())
1001 {
1003
1004 stmt->setUInt8(0, group);
1005 stmt->setUInt64(1, guid.GetCounter());
1006
1007 CharacterDatabase.Execute(stmt);
1008 }
1009
1010 return true;
1011}
1012
1013bool Group::SameSubGroup(Player const* member1, Player const* member2) const
1014{
1015 if (!member1 || !member2)
1016 return false;
1017
1018 if (member1->GetGroup() != this || member2->GetGroup() != this)
1019 return false;
1020 else
1021 return member1->GetSubGroup() == member2->GetSubGroup();
1022}
1023
1024// Allows setting sub groups both for online or offline members
1026{
1027 // Only raid groups have sub groups
1028 if (!isRaidGroup())
1029 return;
1030
1031 // Check if player is really in the raid
1032 member_witerator slot = _getMemberWSlot(guid);
1033 if (slot == m_memberSlots.end())
1034 return;
1035
1036 uint8 prevSubGroup = slot->group;
1037 // Abort if the player is already in the target sub group
1038 if (prevSubGroup == group)
1039 return;
1040
1041 // Update the player slot with the new sub group setting
1042 slot->group = group;
1043
1044 // Increase the counter of the new sub group..
1046
1047 // ..and decrease the counter of the previous one
1048 SubGroupCounterDecrease(prevSubGroup);
1049
1050 // Preserve new sub group in database for non-raid groups
1051 if (!isBGGroup() && !isBFGroup())
1052 {
1054
1055 stmt->setUInt8(0, group);
1056 stmt->setUInt64(1, guid.GetCounter());
1057
1058 CharacterDatabase.Execute(stmt);
1059 }
1060
1061 // In case the moved player is online, update the player object with the new sub group references
1062 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1063 {
1064 if (player->GetGroup() == this)
1065 player->GetGroupRef().setSubGroup(group);
1066 else
1067 {
1068 // 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
1069 player->GetOriginalGroupRef().setSubGroup(group);
1070 }
1071 }
1072
1073 // Broadcast the changes to the group
1074 SendUpdate();
1075}
1076
1078{
1079 if (!isRaidGroup())
1080 return;
1081
1082 member_witerator slots[2];
1083 slots[0] = _getMemberWSlot(firstGuid);
1084 slots[1] = _getMemberWSlot(secondGuid);
1085 if (slots[0] == m_memberSlots.end() || slots[1] == m_memberSlots.end())
1086 return;
1087
1088 if (slots[0]->group == slots[1]->group)
1089 return;
1090
1091 uint8 tmp = slots[0]->group;
1092 slots[0]->group = slots[1]->group;
1093 slots[1]->group = tmp;
1094
1095 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1096 for (uint8 i = 0; i < 2; i++)
1097 {
1098 // Preserve new sub group in database for non-raid groups
1099 if (!isBGGroup() && !isBFGroup())
1100 {
1102
1103 stmt->setUInt8(0, slots[i]->group);
1104 stmt->setUInt64(1, slots[i]->guid.GetCounter());
1105
1106 trans->Append(stmt);
1107 }
1108
1109 if (Player* player = ObjectAccessor::FindConnectedPlayer(slots[i]->guid))
1110 {
1111 if (player->GetGroup() == this)
1112 player->GetGroupRef().setSubGroup(slots[i]->group);
1113 else
1114 player->GetOriginalGroupRef().setSubGroup(slots[i]->group);
1115 }
1116 }
1117 CharacterDatabase.CommitTransaction(trans);
1118
1119 SendUpdate();
1120}
1121
1122// Retrieve the next Round-Roubin player for the group
1123//
1124// No update done if loot method is FFA.
1125//
1126// If the RR player is not yet set for the group, the first group member becomes the round-robin player.
1127// If the RR player is set, the next player in group becomes the round-robin player.
1128//
1129// If ifneed is true,
1130// the current RR player is checked to be near the looted object.
1131// if yes, no update done.
1132// if not, he loses his turn.
1133void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed)
1134{
1135 // round robin style looting applies for all low
1136 // quality items in each loot method except free for all
1137 if (GetLootMethod() == FREE_FOR_ALL)
1138 return;
1139
1140 ObjectGuid oldLooterGUID = GetLooterGuid();
1141 member_citerator guid_itr = _getMemberCSlot(oldLooterGUID);
1142 if (guid_itr != m_memberSlots.end())
1143 {
1144 if (ifneed)
1145 {
1146 // not update if only update if need and ok
1147 Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
1148 if (looter && looter->IsAtGroupRewardDistance(pLootedObject))
1149 return;
1150 }
1151 ++guid_itr;
1152 }
1153
1154 // search next after current
1155 Player* pNewLooter = nullptr;
1156 for (member_citerator itr = guid_itr; itr != m_memberSlots.end(); ++itr)
1157 {
1158 if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1159 if (player->IsAtGroupRewardDistance(pLootedObject))
1160 {
1161 pNewLooter = player;
1162 break;
1163 }
1164 }
1165
1166 if (!pNewLooter)
1167 {
1168 // search from start
1169 for (member_citerator itr = m_memberSlots.begin(); itr != guid_itr; ++itr)
1170 {
1171 if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1172 if (player->IsAtGroupRewardDistance(pLootedObject))
1173 {
1174 pNewLooter = player;
1175 break;
1176 }
1177 }
1178 }
1179
1180 if (pNewLooter)
1181 {
1182 if (oldLooterGUID != pNewLooter->GetGUID())
1183 {
1184 SetLooterGuid(pNewLooter->GetGUID());
1185 SendUpdate();
1186 }
1187 }
1188 else
1189 {
1191 SendUpdate();
1192 }
1193}
1194
1195GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(BattlegroundTemplate const* bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 /*MaxPlayerCount*/, bool isRated, uint32 arenaSlot, ObjectGuid& errorGuid) const
1196{
1197 // check if this group is LFG group
1198 if (isLFGGroup())
1200
1201 BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->Id);
1202 if (!bgEntry)
1203 return ERR_BATTLEGROUND_JOIN_FAILED; // shouldn't happen
1204
1205 // check for min / max count
1206 uint32 memberscount = GetMembersCount();
1207
1208 if (int32(memberscount) > bgEntry->MaxGroupSize) // no MinPlayerCount for battlegrounds
1209 return ERR_BATTLEGROUND_NONE; // ERR_GROUP_JOIN_BATTLEGROUND_TOO_MANY handled on client side
1210
1211 // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
1212 Player* reference = ASSERT_NOTNULL(GetFirstMember())->GetSource();
1213 // no reference found, can't join this way
1214 if (!reference)
1216
1217 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgOrTemplate->MapIDs.front(), reference->GetLevel());
1218 if (!bracketEntry)
1220
1221 uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
1222 Team team = reference->GetTeam();
1223 bool isMercenary = reference->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || reference->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE);
1224
1225 // check every member of the group to be able to join
1226 memberscount = 0;
1227 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next(), ++memberscount)
1228 {
1229 Player* member = itr->GetSource();
1230 // offline member? don't let join
1231 if (!member)
1233 // rbac permissions
1234 if (!member->CanJoinToBattleground(bgOrTemplate))
1236 // don't allow cross-faction join as group
1237 if (member->GetTeam() != team)
1238 {
1239 errorGuid = member->GetGUID();
1241 }
1242 // not in the same battleground level braket, don't let join
1243 PVPDifficultyEntry const* memberBracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bracketEntry->MapID, member->GetLevel());
1244 if (memberBracketEntry != bracketEntry)
1246 // don't let join rated matches if the arena team id doesn't match
1247 if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
1249 // don't let join if someone from the group is already in that bg queue
1250 if (member->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId))
1251 return ERR_BATTLEGROUND_JOIN_FAILED; // not blizz-like
1252 // don't let join if someone from the group is in bg queue random
1255 if (bgOrTemplate->Id != BATTLEGROUND_AA && isInRandomBgQueue)
1256 return ERR_IN_RANDOM_BG;
1257 // don't let join to bg queue random if someone from the group is already in bg queue
1258 if (BattlegroundMgr::IsRandomBattleground(bgOrTemplate->Id) && member->InBattlegroundQueue(true) && !isInRandomBgQueue)
1259 return ERR_IN_NON_RANDOM_BG;
1260 // check for deserter debuff in case not arena queue
1261 if (bgOrTemplate->Id != BATTLEGROUND_AA && member->IsDeserter())
1263 // check if member can join any more battleground queues
1264 if (!member->HasFreeBattlegroundQueueId())
1265 return ERR_BATTLEGROUND_TOO_MANY_QUEUES; // not blizz-like
1266 // check if someone in party is using dungeon system
1267 if (member->isUsingLfg())
1269 // check Freeze debuff
1270 if (member->HasAura(9454))
1272 if (isMercenary != (member->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || member->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE)))
1274 }
1275
1276 // only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
1277 if (bgOrTemplate->IsArena() && memberscount != MinPlayerCount)
1279
1280 return ERR_BATTLEGROUND_NONE;
1281}
1282
1284{
1285 m_dungeonDifficulty = difficulty;
1286 if (!isBGGroup() && !isBFGroup())
1287 {
1289
1291 stmt->setUInt32(1, m_dbStoreId);
1292
1293 CharacterDatabase.Execute(stmt);
1294 }
1295
1296 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
1297 {
1298 Player* player = itr->GetSource();
1299 if (!player->GetSession())
1300 continue;
1301
1302 player->SetDungeonDifficultyID(difficulty);
1303 player->SendDungeonDifficulty();
1304 }
1305}
1306
1308{
1309 m_raidDifficulty = difficulty;
1310 if (!isBGGroup() && !isBFGroup())
1311 {
1313
1314 stmt->setUInt8(0, uint8(m_raidDifficulty));
1315 stmt->setUInt32(1, m_dbStoreId);
1316
1317 CharacterDatabase.Execute(stmt);
1318 }
1319
1320 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
1321 {
1322 Player* player = itr->GetSource();
1323 if (!player->GetSession())
1324 continue;
1325
1326 player->SetRaidDifficultyID(difficulty);
1327 player->SendRaidDifficulty(false);
1328 }
1329}
1330
1332{
1333 m_legacyRaidDifficulty = difficulty;
1334 if (!isBGGroup() && !isBFGroup())
1335 {
1337
1339 stmt->setUInt32(1, m_dbStoreId);
1340
1341 CharacterDatabase.Execute(stmt);
1342 }
1343
1344 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
1345 {
1346 Player* player = itr->GetSource();
1347 if (!player->GetSession())
1348 continue;
1349
1350 player->SetLegacyRaidDifficultyID(difficulty);
1351 player->SendRaidDifficulty(true);
1352 }
1353}
1354
1356{
1357 if (!mapEntry->IsRaid())
1358 return m_dungeonDifficulty;
1359
1360 MapDifficultyEntry const* defaultDifficulty = sDB2Manager.GetDefaultMapDifficulty(mapEntry->ID);
1361 if (!defaultDifficulty)
1363
1364 DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(defaultDifficulty->DifficultyID);
1365 if (!difficulty || difficulty->Flags & DIFFICULTY_FLAG_LEGACY)
1367
1368 return m_raidDifficulty;
1369}
1370
1372{
1374 {
1375 InstanceMap* map = ref.GetSource();
1376 switch (map->Reset(method))
1377 {
1379 notifyPlayer->SendResetInstanceSuccess(map->GetId());
1380 m_recentInstances.erase(map->GetId());
1381 break;
1383 if (method == InstanceResetMethod::Manual)
1385 else if (method == InstanceResetMethod::OnChangeDifficulty)
1386 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
1387 break;
1389 m_recentInstances.erase(map->GetId()); // forget the instance, allows retrying different lockout with a new leader
1390 break;
1391 default:
1392 break;
1393 }
1394 }
1395}
1396
1398{
1400}
1401
1403{
1404 if (player && !player->IsGameMaster() && sMapStore.LookupEntry(player->GetMapId())->IsDungeon())
1405 player->m_InstanceValid = false;
1406}
1407
1409{
1410 // FG: HACK: force flags update on group leave - for values update hack
1411 // -- not very efficient but safe
1412 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1413 {
1414 if (Player * pp = ObjectAccessor::FindPlayer(citr->guid))
1415 {
1416 pp->ForceUpdateFieldChange(pp->m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PvpFlags));
1417 pp->ForceUpdateFieldChange(pp->m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::FactionTemplate));
1418 TC_LOG_DEBUG("misc", "-- Forced group value update for '{}'", pp->GetName());
1419 }
1420 }
1421}
1422
1424{
1425 if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(m_countdowns))
1426 return;
1427
1428 if (!m_countdowns[AsUnderlyingType(timerType)])
1429 m_countdowns[AsUnderlyingType(timerType)] = std::make_unique<CountdownInfo>();
1430
1431 m_countdowns[AsUnderlyingType(timerType)]->StartCountdown(duration, startTime);
1432}
1433
1435{
1436 if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(m_countdowns))
1437 return nullptr;
1438
1439 return m_countdowns[AsUnderlyingType(timerType)].get();
1440}
1441
1443{
1444 m_lootMethod = method;
1445}
1446
1448{
1449 m_looterGuid = guid;
1450}
1451
1453{
1454 m_masterLooterGuid = guid;
1455}
1456
1458{
1459 m_lootThreshold = threshold;
1460}
1461
1463{
1464 member_witerator slot = _getMemberWSlot(guid);
1465 if (slot == m_memberSlots.end())
1466 return;
1467
1468 slot->roles = roles;
1469 SendUpdate();
1470}
1471
1473{
1474 member_citerator slot = _getMemberCSlot(guid);
1475 if (slot == m_memberSlots.end())
1476 return 0;
1477
1478 return slot->roles;
1479}
1480
1482{
1484 return;
1485
1487 if (m_readyCheckTimer <= Milliseconds::zero())
1488 EndReadyCheck();
1489}
1490
1492{
1494 return;
1495
1496 member_witerator slot = _getMemberWSlot(starterGuid);
1497 if (slot == m_memberSlots.end())
1498 return ;
1499
1500 m_readyCheckStarted = true;
1501 m_readyCheckTimer = duration;
1502
1504
1505 SetMemberReadyChecked(&(*slot));
1506
1508 readyCheckStarted.PartyGUID = m_guid;
1509 readyCheckStarted.PartyIndex = GetGroupCategory();
1510 readyCheckStarted.InitiatorGUID = starterGuid;
1511 readyCheckStarted.Duration = duration;
1512 BroadcastPacket(readyCheckStarted.Write(), false);
1513}
1514
1516{
1518 return;
1519
1520 m_readyCheckStarted = false;
1521 m_readyCheckTimer = Milliseconds::zero();
1522
1524
1525 WorldPackets::Party::ReadyCheckCompleted readyCheckCompleted;
1526 readyCheckCompleted.PartyIndex = 0;
1527 readyCheckCompleted.PartyGUID = m_guid;
1528 BroadcastPacket(readyCheckCompleted.Write(), false);
1529}
1530
1532{
1533 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1534 if (!citr->readyChecked)
1535 return false;
1536 return true;
1537}
1538
1540{
1542 return;
1543
1544 member_witerator slot = _getMemberWSlot(guid);
1545 if (slot != m_memberSlots.end())
1546 SetMemberReadyCheck(&(*slot), ready);
1547}
1548
1550{
1552 response.PartyGUID = m_guid;
1553 response.Player = slot->guid;
1554 response.IsReady = ready;
1555 BroadcastPacket(response.Write(), false);
1556
1558}
1559
1561{
1562 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1563 {
1564 Player* player = ObjectAccessor::FindConnectedPlayer(itr->guid);
1565 if (!player || !player->GetSession())
1566 SetMemberReadyCheck(&(*itr), false);
1567 }
1568}
1569
1571{
1572 slot->readyChecked = true;
1574 EndReadyCheck();
1575}
1576
1578{
1579 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1580 itr->readyChecked = false;
1581}
1582
1583void Group::AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid)
1584{
1585 if (markerId >= RAID_MARKERS_COUNT || m_markers[markerId])
1586 return;
1587
1588 m_activeMarkers |= (1 << markerId);
1589 m_markers[markerId] = std::make_unique<RaidMarker>(mapId, positionX, positionY, positionZ, transportGuid);
1591}
1592
1594{
1595 if (markerId > RAID_MARKERS_COUNT)
1596 return;
1597
1598 for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
1599 if (m_markers[i] && (markerId == i || markerId == RAID_MARKERS_COUNT))
1600 {
1601 m_markers[i] = nullptr;
1602 m_activeMarkers &= ~(1 << i);
1603 }
1604
1606}
1607
1609{
1611
1612 packet.PartyIndex = GetGroupCategory();
1614
1615 for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
1616 if (m_markers[i])
1617 packet.RaidMarkers.push_back(m_markers[i].get());
1618
1619 if (session)
1620 session->SendPacket(packet.Write());
1621 else
1622 BroadcastPacket(packet.Write(), false);
1623}
1624
1625bool Group::IsFull() const
1626{
1627 return isRaidGroup() ? (m_memberSlots.size() >= MAX_RAID_SIZE) : (m_memberSlots.size() >= MAX_GROUP_SIZE);
1628}
1629
1631{
1632 return (m_groupFlags & GROUP_FLAG_LFG) != 0;
1633}
1634
1636{
1637 return (m_groupFlags & GROUP_FLAG_RAID) != 0;
1638}
1639
1641{
1642 return m_bgGroup != nullptr;
1643}
1644
1646{
1647 return m_bfGroup != nullptr;
1648}
1649
1651{
1652 return GetMembersCount() > 0;
1653}
1654
1656{
1657 return m_leaderGuid;
1658}
1659
1661{
1662 return m_guid;
1663}
1664
1665char const* Group::GetLeaderName() const
1666{
1667 return m_leaderName.c_str();
1668}
1669
1671{
1672 return m_lootMethod;
1673}
1674
1676{
1677 if (GetLootMethod() == FREE_FOR_ALL)
1678 return ObjectGuid::Empty;
1679 return m_looterGuid;
1680}
1681
1683{
1684 return m_masterLooterGuid;
1685}
1686
1688{
1689 return m_lootThreshold;
1690}
1691
1693{
1694 return _getMemberCSlot(guid) != m_memberSlots.end();
1695}
1696
1698{
1699 return (GetLeaderGUID() == guid);
1700}
1701
1702ObjectGuid Group::GetMemberGUID(std::string const& name) const
1703{
1704 auto itr = std::ranges::find(m_memberSlots, name, &MemberSlot::name);
1705 if (itr != m_memberSlots.end())
1706 return itr->guid;
1707
1708 return ObjectGuid::Empty;
1709}
1710
1712{
1713 member_citerator mslot = _getMemberCSlot(guid);
1714 if (mslot == m_memberSlots.end())
1715 return 0u;
1716 return mslot->flags;
1717}
1718
1720{
1721 member_citerator mslot2 = _getMemberCSlot(guid2);
1722 if (mslot2 == m_memberSlots.end())
1723 return false;
1724 return SameSubGroup(guid1, &*mslot2);
1725}
1726
1727bool Group::SameSubGroup(ObjectGuid guid1, MemberSlot const* slot2) const
1728{
1729 member_citerator mslot1 = _getMemberCSlot(guid1);
1730 if (mslot1 == m_memberSlots.end() || !slot2)
1731 return false;
1732 return (mslot1->group == slot2->group);
1733}
1734
1736{
1737 return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAX_GROUP_SIZE);
1738}
1739
1741{
1742 member_citerator mslot = _getMemberCSlot(guid);
1743 if (mslot == m_memberSlots.end())
1744 return (MAX_RAID_SUBGROUPS+1);
1745 return mslot->group;
1746}
1747
1749{
1750 m_bgGroup = bg;
1751}
1752
1754{
1755 m_bfGroup = bf;
1756}
1757
1759{
1760 // Assistants, main assistants and main tanks are only available in raid groups
1761 if (!isRaidGroup())
1762 return;
1763
1764 // Check if player is really in the raid
1765 member_witerator slot = _getMemberWSlot(guid);
1766 if (slot == m_memberSlots.end())
1767 return;
1768
1769 // Do flag specific actions, e.g ensure uniqueness
1770 switch (flag)
1771 {
1773 RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINASSIST); // Remove main assist flag from current if any.
1774 break;
1776 RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINTANK); // Remove main tank flag from current if any.
1777 break;
1779 break;
1780 default:
1781 return; // This should never happen
1782 }
1783
1784 // Switch the actual flag
1785 ToggleGroupMemberFlag(slot, flag, apply);
1786
1787 // Preserve the new setting in the db
1789
1790 stmt->setUInt8(0, slot->flags);
1791 stmt->setUInt64(1, guid.GetCounter());
1792
1793 CharacterDatabase.Execute(stmt);
1794
1795 // Broadcast the changes to the group
1796 SendUpdate();
1797}
1798
1800{
1802}
1803
1805{
1807 while (ref)
1808 {
1809 GroupReference* nextRef = ref->next();
1810 if (ref->GetSource()->GetGUID() == guid)
1811 {
1812 ref->unlink();
1813 break;
1814 }
1815 ref = nextRef;
1816 }
1817}
1818
1820{
1821 // Sub group counters initialization
1822 if (!m_subGroupsCounts)
1824
1825 memset((void*)m_subGroupsCounts, 0, (MAX_RAID_SUBGROUPS)*sizeof(uint8));
1826
1827 for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1828 ++m_subGroupsCounts[itr->group];
1829}
1830
1832{
1833 return std::ranges::find(m_memberSlots, Guid, &MemberSlot::guid);
1834}
1835
1837{
1838 return std::ranges::find(m_memberSlots, Guid, &MemberSlot::guid);
1839}
1840
1842{
1844 ++m_subGroupsCounts[subgroup];
1845}
1846
1848{
1850 --m_subGroupsCounts[subgroup];
1851}
1852
1854{
1855 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1856 if (itr->flags & flag)
1857 itr->flags &= ~flag;
1858}
1859
1861{
1862 if (apply)
1863 slot->flags |= flag;
1864 else
1865 slot->flags &= ~flag;
1866}
1867
1869{
1870 m_isLeaderOffline = true;
1872}
1873
1875{
1876 m_isLeaderOffline = false;
1877}
1878
1880{
1881 if (apply)
1883 else
1885
1886 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1888
1889 if (!isBGGroup() && !isBFGroup())
1890 {
1892
1893 stmt->setUInt16(0, m_groupFlags);
1894 stmt->setUInt32(1, m_dbStoreId);
1895
1896 CharacterDatabase.Execute(stmt);
1897 }
1898
1899 SendUpdate();
1900}
1901
1903{
1904 return m_pingRestriction;
1905}
1906
1908{
1909 m_pingRestriction = restrictTo;
1910
1911 if (!isBGGroup() && !isBFGroup())
1912 {
1914
1915 stmt->setInt8(0, int8(m_pingRestriction));
1916 stmt->setUInt32(1, m_dbStoreId);
1917
1918 CharacterDatabase.Execute(stmt);
1919 }
1920
1921 SendUpdate();
1922}
@ SPELL_MERCENARY_CONTRACT_ALLIANCE
Definition: Battleground.h:118
@ SPELL_MERCENARY_CONTRACT_HORDE
Definition: Battleground.h:117
#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:35
@ MINUTE
Definition: Common.h:29
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:553
Difficulty
Definition: DBCEnums.h:918
@ DIFFICULTY_NORMAL_RAID
Definition: DBCEnums.h:931
@ DIFFICULTY_NORMAL
Definition: DBCEnums.h:920
@ DIFFICULTY_10_N
Definition: DBCEnums.h:922
@ DIFFICULTY_FLAG_LEGACY
Definition: DBCEnums.h:966
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
#define ASSERT
Definition: Errors.h:68
#define sGroupMgr
Definition: GroupMgr.h:61
RestrictPingsTo
Definition: Group.h:195
@ 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:512
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition: Log.h:179
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:188
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:878
#define sObjectMgr
Definition: ObjectMgr.h:1995
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ PLAYER_FLAGS_GROUP_LEADER
Definition: Player.h:451
Races
Definition: RaceMask.h:26
#define sScriptMgr
Definition: ScriptMgr.h:1417
GroupJoinBattlegroundResult
@ ERR_BATTLEGROUND_NONE
@ INSTANCE_RESET_FAILED
ItemQualities
@ ITEM_QUALITY_UNCOMMON
@ ERR_IN_RANDOM_BG
@ ERR_IN_NON_RANDOM_BG
@ ERR_BATTLEGROUND_JOIN_RANGE_INDEX
@ ERR_BATTLEGROUND_JOIN_TIMED_OUT
@ ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS
@ ERR_LFG_CANT_USE_BATTLEGROUND
@ ERR_BATTLEGROUND_JOIN_MERCENARY
@ ERR_BATTLEGROUND_JOIN_FAILED
@ ERR_BATTLEGROUND_TOO_MANY_QUEUES
@ ERR_ARENA_TEAM_PARTY_SIZE
Team
@ 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:528
static BattlegroundQueueTypeId BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize)
static bool IsRandomBattleground(uint32 battlemasterListId)
Group * GetBgRaid(Team team) const
Definition: Battleground.h:372
void SetBgRaid(Team team, Group *bg_raid)
static PVPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
Definition: DB2Stores.cpp:2866
Class used to access individual fields of database query result.
Definition: Field.h:93
uint32 GetUInt32() const
Definition: Field.cpp:61
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:205
ObjectGuid m_targetIcons[TARGET_ICONS_COUNT]
Definition: Group.h:439
member_citerator _getMemberCSlot(ObjectGuid Guid) const
Definition: Group.cpp:1831
bool IsReadyCheckCompleted(void) const
Definition: Group.cpp:1531
void BroadcastGroupUpdate(void)
Definition: Group.cpp:1408
bool isLFGGroup() const
Definition: Group.cpp:1630
bool m_isLeaderOffline
Definition: Group.h:449
void StartLeaderOfflineTimer()
Definition: Group.cpp:1868
uint8 GetMemberGroup(ObjectGuid guid) const
Definition: Group.cpp:1740
void SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid)
Definition: Group.cpp:1077
ObjectGuid GetMasterLooterGuid() const
Definition: Group.cpp:1682
Battlefield * m_bfGroup
Definition: Group.h:438
void SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot const *slot=nullptr) const
Definition: Group.cpp:838
uint8 m_leaderFactionGroup
Definition: Group.h:430
ObjectGuid GetMemberGUID(std::string const &name) const
Definition: Group.cpp:1702
bool AddLeaderInvite(Player *player)
Definition: Group.cpp:375
void SetBattlefieldGroup(Battlefield *bf)
Definition: Group.cpp:1753
InvitesList m_invitees
Definition: Group.h:428
void ResetInstances(InstanceResetMethod method, Player *notifyPlayer)
Definition: Group.cpp:1371
void DeleteRaidMarker(uint8 markerId)
Definition: Group.cpp:1593
GroupCategory GetGroupCategory() const
Definition: Group.h:303
RestrictPingsTo m_pingRestriction
Definition: Group.h:462
Difficulty m_legacyRaidDifficulty
Definition: Group.h:436
bool IsCreated() const
Definition: Group.cpp:1650
void SendUpdate() const
Definition: Group.cpp:832
bool _setMembersGroup(ObjectGuid guid, uint8 group)
Definition: Group.cpp:990
void SubGroupCounterDecrease(uint8 subgroup)
Definition: Group.cpp:1847
void SetLootMethod(LootMethod method)
Definition: Group.cpp:1442
void ChangeMembersGroup(ObjectGuid guid, uint8 group)
Definition: Group.cpp:1025
void SendTargetIconList(WorldSession *session) const
Definition: Group.cpp:819
void SetEveryoneIsAssistant(bool apply)
Definition: Group.cpp:1879
GroupCategory m_groupCategory
Definition: Group.h:433
ObjectGuid m_leaderGuid
Definition: Group.h:429
void RemoveAllInvites()
Definition: Group.cpp:395
std::string m_leaderName
Definition: Group.h:431
void AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid=ObjectGuid::Empty)
Definition: Group.cpp:1583
void _initRaidSubGroupsCounter()
Definition: Group.cpp:1819
void EndReadyCheck()
Definition: Group.cpp:1515
ObjectGuid m_looterGuid
Definition: Group.h:442
std::array< std::unique_ptr< RaidMarker >, RAID_MARKERS_COUNT > m_markers
Definition: Group.h:457
void SetLootThreshold(ItemQualities threshold)
Definition: Group.cpp:1457
void Disband(bool hideDestroy=false)
Definition: Group.cpp:731
void LoadGroupFromDB(Field *field)
Definition: Group.cpp:211
bool AddMember(Player *player)
Definition: Group.cpp:424
bool IsLeader(ObjectGuid guid) const
Definition: Group.cpp:1697
Battleground * m_bgGroup
Definition: Group.h:437
Difficulty m_raidDifficulty
Definition: Group.h:435
void SetMemberReadyCheck(ObjectGuid guid, bool ready)
Definition: Group.cpp:1539
void BroadcastAddonMessagePacket(WorldPacket const *packet, const std::string &prefix, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignore=ObjectGuid::Empty) const
Definition: Group.cpp:964
GroupRefManager m_memberMgr
Definition: Group.h:427
void SetDungeonDifficultyID(Difficulty difficulty)
Definition: Group.cpp:1283
void SetRestrictPingsTo(RestrictPingsTo restrictTo)
Definition: Group.cpp:1907
uint32 m_activeMarkers
Definition: Group.h:458
void SetMasterLooterGuid(ObjectGuid guid)
Definition: Group.cpp:1452
void SetRaidDifficultyID(Difficulty difficulty)
Definition: Group.cpp:1307
Trinity::unique_trackable_ptr< Group > m_scriptRef
Definition: Group.h:465
ObjectGuid GetGUID() const
Definition: Group.cpp:1660
void RemoveInvite(Player *player)
Definition: Group.cpp:386
void SetLegacyRaidDifficultyID(Difficulty difficulty)
Definition: Group.cpp:1331
bool isBGGroup() const
Definition: Group.cpp:1640
void ConvertToRaid()
Definition: Group.cpp:299
ItemQualities GetLootThreshold() const
Definition: Group.cpp:1687
void SetOfflineMembersReadyChecked(void)
Definition: Group.cpp:1560
std::unordered_map< uint32, std::pair< ObjectGuid, uint32 > > m_recentInstances
Definition: Group.h:444
MemberSlotList m_memberSlots
Definition: Group.h:426
void StartReadyCheck(ObjectGuid starterGuid, Milliseconds duration=Milliseconds(READYCHECK_DURATION))
Definition: Group.cpp:1491
void SendRaidMarkersChanged(WorldSession *session=nullptr) const
Definition: Group.cpp:1608
uint32 GetMembersCount() const
Definition: Group.h:335
Group()
Definition: Group.cpp:58
void StopLeaderOfflineTimer()
Definition: Group.cpp:1874
void UpdatePlayerOutOfRange(Player const *player) const
Definition: Group.cpp:947
void Update(uint32 diff)
Definition: Group.cpp:90
void ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)
Definition: Group.cpp:1860
void _homebindIfInstance(Player *player)
Definition: Group.cpp:1402
Difficulty GetRaidDifficultyID() const
Definition: Group.h:360
void SetLfgRoles(ObjectGuid guid, uint8 roles)
Definition: Group.cpp:1462
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag)
Definition: Group.cpp:1758
TimeTracker m_leaderOfflineTimer
Definition: Group.h:450
void ResetMemberReadyChecked(void)
Definition: Group.cpp:1577
member_witerator _getMemberWSlot(ObjectGuid Guid)
Definition: Group.cpp:1836
ObjectGuid GetLooterGuid() const
Definition: Group.cpp:1675
Milliseconds m_readyCheckTimer
Definition: Group.h:454
uint32 m_dbStoreId
Definition: Group.h:448
void DelinkMember(ObjectGuid guid)
Definition: Group.cpp:1804
void ChangeLeader(ObjectGuid guid)
Definition: Group.cpp:686
const char * GetLeaderName() const
Definition: Group.cpp:1665
void ConvertToLFG()
Definition: Group.cpp:281
ObjectGuid m_masterLooterGuid
Definition: Group.h:443
MemberSlotList::iterator member_witerator
Definition: Group.h:242
void SetBattlegroundGroup(Battleground *bg)
Definition: Group.cpp:1748
uint8 GetLfgRoles(ObjectGuid guid) const
Definition: Group.cpp:1472
LootMethod GetLootMethod() const
Definition: Group.cpp:1670
void UpdateLooterGuid(WorldObject *pLootedObject, bool ifneed=false)
Definition: Group.cpp:1133
CountdownInfo const * GetCountdownInfo(CountdownTimerType timerType) const
Definition: Group.cpp:1434
bool RemoveMember(ObjectGuid guid, RemoveMethod method=GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker=ObjectGuid::Empty, const char *reason=nullptr)
Definition: Group.cpp:568
bool m_readyCheckStarted
Definition: Group.h:453
Player * GetInvited(ObjectGuid guid) const
Definition: Group.cpp:404
bool HasFreeSlotSubGroup(uint8 subgroup) const
Definition: Group.cpp:1735
bool isBFGroup() const
Definition: Group.cpp:1645
void LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
Definition: Group.cpp:248
bool IsMember(ObjectGuid guid) const
Definition: Group.cpp:1692
GroupReference * GetFirstMember()
Definition: Group.h:333
void UpdateReadyCheck(uint32 diff)
Definition: Group.cpp:1481
LootMethod m_lootMethod
Definition: Group.h:440
Difficulty GetDungeonDifficultyID() const
Definition: Group.h:359
void BroadcastPacket(WorldPacket const *packet, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignoredPlayer=ObjectGuid::Empty) const
Definition: Group.cpp:977
void SelectNewPartyOrRaidLeader()
Definition: Group.cpp:105
bool SameSubGroup(ObjectGuid guid1, ObjectGuid guid2) const
Definition: Group.cpp:1719
void LinkOwnedInstance(GroupInstanceReference *ref)
Definition: Group.cpp:1397
ObjectGuid m_guid
Definition: Group.h:447
bool AddInvite(Player *player)
Definition: Group.cpp:354
void ConvertToGroup()
Definition: Group.cpp:323
uint8 * m_subGroupsCounts
Definition: Group.h:446
Difficulty GetDifficultyID(MapEntry const *mapEntry) const
Definition: Group.cpp:1355
MemberSlotList::const_iterator member_citerator
Definition: Group.h:219
std::array< std::unique_ptr< CountdownInfo >, 3 > m_countdowns
Definition: Group.h:460
void SetMemberReadyChecked(MemberSlot *slot)
Definition: Group.cpp:1570
void SubGroupCounterIncrease(uint8 subgroup)
Definition: Group.cpp:1841
void SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy)
Definition: Group.cpp:798
bool Create(Player *leader)
Definition: Group.cpp:141
RestrictPingsTo GetRestrictPings() const
Definition: Group.cpp:1902
bool IsFull() const
Definition: Group.cpp:1625
ObjectGuid GetLeaderGUID() const
Definition: Group.cpp:1655
Difficulty m_dungeonDifficulty
Definition: Group.h:434
uint8 GetMemberFlags(ObjectGuid guid) const
Definition: Group.cpp:1711
Difficulty GetLegacyRaidDifficultyID() const
Definition: Group.h:361
~Group()
Definition: Group.cpp:73
void SetLooterGuid(ObjectGuid guid)
Definition: Group.cpp:1447
void LinkMember(GroupReference *pRef)
Definition: Group.cpp:1799
ItemQualities m_lootThreshold
Definition: Group.h:441
bool isRaidGroup() const
Definition: Group.cpp:1635
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(BattlegroundTemplate const *bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid &errorGuid) const
Definition: Group.cpp:1195
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag)
Definition: Group.cpp:1853
GroupInstanceRefManager m_ownedInstancesMgr
Definition: Group.h:445
void SendUpdateDestroyGroupToPlayer(Player *player) const
Definition: Group.cpp:935
GroupFlags m_groupFlags
Definition: Group.h:432
void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional< time_t > startTime={ })
Definition: Group.cpp:1423
InstanceResetResult Reset(InstanceResetMethod method)
Definition: Map.cpp:3017
void insertLast(LinkedListElement *pElem)
Definition: LinkedList.h:123
uint32 getSize() const
Definition: LinkedList.h:128
void insertFirst(LinkedListElement *pElem)
Definition: LinkedList.h:118
uint32 GetId() const
Definition: Map.cpp:3210
InstanceMap * ToInstanceMap()
Definition: Map.h:487
LowType GetCounter() const
Definition: ObjectGuid.h:296
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:322
uint64 GetRawValue(std::size_t i) const
Definition: ObjectGuid.h:285
void SetRawValue(std::span< uint8 const > rawBytes)
Definition: ObjectGuid.cpp:807
static constexpr std::size_t BytesSize
Definition: ObjectGuid.h:279
uint64 LowType
Definition: ObjectGuid.h:281
void Clear()
Definition: ObjectGuid.h:289
bool IsInWorld() const
Definition: Object.h:190
void BuildValuesUpdateBlockForPlayerWithFlag(UpdateData *data, UF::UpdateFieldFlag flags, Player const *target) const
Definition: Object.cpp:231
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:195
Definition: Pet.h:40
bool HaveAtClient(Object const *u) const
Definition: Player.cpp:24162
bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25458
bool m_InstanceValid
Definition: Player.h:2673
void SetOriginalGroup(Group *group, int8 subgroup=-1)
Definition: Player.cpp:26463
void SetPlayerFlag(PlayerFlags flags)
Definition: Player.h:2840
void SetPartyType(GroupCategory category, uint8 type)
Definition: Player.cpp:26476
int32 NextGroupUpdateSequenceNumber(GroupCategory category)
Definition: Player.cpp:26493
void SetGroupUpdateFlag(uint32 flag)
Definition: Player.h:2716
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
void SendResetInstanceFailed(ResetFailedReason reason, uint32 mapID) const
Definition: Player.cpp:21711
void SetGroup(Group *group, int8 subgroup=-1)
Definition: Player.cpp:24627
void SendDungeonDifficulty(int32 forcedDifficulty=-1) const
Definition: Player.cpp:21645
void SetGroupInvite(Group *group)
Definition: Player.h:2707
void RemoveFromBattlegroundOrBattlefieldRaid()
Definition: Player.cpp:26451
void SetRaidDifficultyID(Difficulty raid_difficulty)
Definition: Player.h:2110
Group * GetOriginalGroup() const
Definition: Player.h:2727
bool CanRewardQuest(Quest const *quest, bool msg) const
Definition: Player.cpp:14661
void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects)
Definition: Player.cpp:25638
Pet * GetPet() const
Definition: Player.cpp:21839
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition: Player.cpp:26127
bool IsDeserter() const
Definition: Player.h:2504
bool InBattlegroundQueue(bool ignoreArena=false) const
Definition: Player.cpp:25425
WorldSession * GetSession() const
Definition: Player.h:2195
void ResetGroupUpdateSequenceIfNeeded(Group const *group)
Definition: Player.cpp:26482
Difficulty GetDungeonDifficultyID() const
Definition: Player.h:2106
void SetLegacyRaidDifficultyID(Difficulty raid_difficulty)
Definition: Player.h:2111
bool CanJoinToBattleground(BattlegroundTemplate const *bg) const
Definition: Player.cpp:24074
bool HasFreeBattlegroundQueueId() const
Definition: Player.cpp:25486
bool IsGameMaster() const
Definition: Player.h:1247
static Difficulty CheckLoadedLegacyRaidDifficultyID(Difficulty difficulty)
Definition: Player.cpp:30260
static uint8 GetFactionGroupForRace(uint8 race)
Definition: Player.cpp:6514
void SetDungeonDifficultyID(Difficulty dungeon_difficulty)
Definition: Player.h:2109
bool CheckInstanceValidity(bool)
Definition: Player.cpp:20081
Difficulty GetRaidDifficultyID() const
Definition: Player.h:2107
void SendResetInstanceSuccess(uint32 MapId) const
Definition: Player.cpp:21704
static Difficulty CheckLoadedRaidDifficultyID(Difficulty difficulty)
Definition: Player.cpp:30245
void SendRaidDifficulty(bool legacy, int32 forcedDifficulty=-1) const
Definition: Player.cpp:21652
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2708
uint8 GetSubGroup() const
Definition: Player.h:2714
void FailCriteria(CriteriaFailEvent condition, int32 failAsset)
Definition: Player.cpp:27230
Group * GetGroupInvite() const
Definition: Player.h:2706
static Difficulty CheckLoadedDungeonDifficultyID(Difficulty difficulty)
Definition: Player.cpp:30230
uint32 GetArenaTeamId(uint8) const
Definition: Player.h:2098
Difficulty GetLegacyRaidDifficultyID() const
Definition: Player.h:2108
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition: Player.cpp:26441
Team GetTeam() const
Definition: Player.h:2334
bool isUsingLfg() const
Definition: Player.cpp:26425
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)
ReferenceType * getFirst()
Definition: RefManager.h:32
Derived * next()
Definition: Reference.h:84
FROM * GetSource() const
Definition: Reference.h:97
void unlink()
Definition: Reference.h:62
uint8 GetClass() const
Definition: Unit.h:759
bool IsAlive() const
Definition: Unit.h:1175
void RemoveAllGroupBuffsFromCaster(ObjectGuid casterGUID)
Definition: Unit.cpp:4488
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition: Unit.h:1844
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4733
uint8 GetLevel() const
Definition: Unit.h:752
uint8 GetRace() const
Definition: Unit.h:756
bool HasData() const
Definition: UpdateData.h:52
bool BuildPacket(WorldPacket *packet)
Definition: UpdateData.cpp:40
constexpr uint32 GetMapId() const
Definition: Position.h:215
Map * GetMap() const
Definition: Object.h:749
float GetSightRange(WorldObject const *target=nullptr) const
Definition: Object.cpp:1506
std::string const & GetName() const
Definition: Object.h:680
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition: Object.cpp:1191
bool IsInMap(WorldObject const *obj) const
Definition: Object.cpp:1164
WorldPacket const * GetRawPacket() const
Definition: Packet.h:38
WorldPacket const * Write() override
void Initialize(Player const *player)
WorldPacket const * Write() override
Optional< PartyLootSettings > LootSettings
Definition: PartyPackets.h:570
Optional< PartyDifficultySettings > DifficultySettings
Definition: PartyPackets.h:571
std::vector< PartyPlayerInfo > PlayerList
Definition: PartyPackets.h:567
WorldPacket const * Write() override
Optional< PartyLFGInfo > LfgInfos
Definition: PartyPackets.h:569
WorldPacket const * Write() override
std::vector< RaidMarker const * > RaidMarkers
Definition: PartyPackets.h:629
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPackets::Duration< Milliseconds > Duration
Definition: PartyPackets.h:417
std::map< uint8, ObjectGuid > TargetIcons
Definition: PartyPackets.h:350
WorldPacket const * Write() override
Player session in the World.
Definition: WorldSession.h:976
bool PlayerLogout() const
Definition: WorldSession.h:983
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
bool IsAddonRegistered(std::string_view prefix) const
void apply(T *val)
Definition: ByteConverter.h:41
time_t GetGameTime()
Definition: GameTime.cpp:44
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:209
uint8 _class
Definition: Group.h:212
std::string name
Definition: Group.h:210
bool readyChecked
Definition: Group.h:216
uint32 ID
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, 44 > FactionTemplate
Definition: UpdateFields.h:312
UpdateField< uint8, 64, 84 > PvpFlags
Definition: UpdateFields.h:356
Reward info.
Definition: LFGMgr.h:234