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 _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 stmt->setBinary(index++, m_targetIcons[0].GetRawValue());
189 stmt->setBinary(index++, m_targetIcons[1].GetRawValue());
190 stmt->setBinary(index++, m_targetIcons[2].GetRawValue());
191 stmt->setBinary(index++, m_targetIcons[3].GetRawValue());
192 stmt->setBinary(index++, m_targetIcons[4].GetRawValue());
193 stmt->setBinary(index++, m_targetIcons[5].GetRawValue());
194 stmt->setBinary(index++, m_targetIcons[6].GetRawValue());
195 stmt->setBinary(index++, m_targetIcons[7].GetRawValue());
196 stmt->setUInt16(index++, m_groupFlags);
197 stmt->setUInt32(index++, uint8(m_dungeonDifficulty));
198 stmt->setUInt32(index++, uint8(m_raidDifficulty));
199 stmt->setUInt32(index++, uint8(m_legacyRaidDifficulty));
200 stmt->setUInt64(index++, m_masterLooterGuid.GetCounter());
201
202 CharacterDatabase.Execute(stmt);
203
204 if (InstanceMap* leaderInstance = leader->GetMap()->ToInstanceMap())
205 leaderInstance->TrySetOwningGroup(this);
206
207 bool addMemberResult = AddMember(leader);
208 ASSERT(addMemberResult); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
209 }
210 else if (!AddMember(leader))
211 return false;
212
213 return true;
214}
215
217{
218 m_dbStoreId = fields[17].GetUInt32();
219 m_guid = ObjectGuid::Create<HighGuid::Party>(sGroupMgr->GenerateGroupId());
220 m_leaderGuid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
221
222 // group leader not exist
223 CharacterCacheEntry const* leader = sCharacterCache->GetCharacterCacheByGuid(m_leaderGuid);
224 if (!leader)
225 return;
226
228 m_leaderName = leader->Name;
229 m_lootMethod = LootMethod(fields[1].GetUInt8());
230 m_looterGuid = ObjectGuid::Create<HighGuid::Player>(fields[2].GetUInt64());
231 m_lootThreshold = ItemQualities(fields[3].GetUInt8());
232
233 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
234 m_targetIcons[i].SetRawValue(fields[4 + i].GetBinary());
235
236 m_groupFlags = GroupFlags(fields[12].GetUInt16());
239
243
244 m_masterLooterGuid = ObjectGuid::Create<HighGuid::Player>(fields[16].GetUInt64());
245
247 sLFGMgr->_LoadFromDB(fields, GetGUID());
248}
249
250void Group::LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
251{
252 MemberSlot member;
253 member.guid = ObjectGuid::Create<HighGuid::Player>(guidLow);
254
255 // skip non-existed member
256 CharacterCacheEntry const* character = sCharacterCache->GetCharacterCacheByGuid(member.guid);
257 if (!character)
258 {
260 stmt->setUInt64(0, guidLow);
261 CharacterDatabase.Execute(stmt);
262 return;
263 }
264
266 memberFlags |= MEMBER_FLAG_ASSISTANT;
267
268 member.name = character->Name;
269 member.race = Races(character->Race);
270 member._class = character->Class;
271 member.group = subgroup;
272 member.flags = memberFlags;
273 member.roles = roles;
274 member.readyChecked = false;
275
276 m_memberSlots.push_back(member);
277
278 SubGroupCounterIncrease(subgroup);
279
280 sLFGMgr->SetupGroupMember(member.guid, GetGUID());
281}
282
284{
288 if (!isBGGroup() && !isBFGroup())
289 {
291
292 stmt->setUInt16(0, m_groupFlags);
293 stmt->setUInt32(1, m_dbStoreId);
294
295 CharacterDatabase.Execute(stmt);
296 }
297
298 SendUpdate();
299}
300
302{
304
306
307 if (!isBGGroup() && !isBFGroup())
308 {
310
311 stmt->setUInt16(0, m_groupFlags);
312 stmt->setUInt32(1, m_dbStoreId);
313
314 CharacterDatabase.Execute(stmt);
315 }
316
317 SendUpdate();
318
319 // update quest related GO states (quest activity dependent from raid membership)
320 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
321 if (Player* player = ObjectAccessor::FindPlayer(citr->guid))
322 player->UpdateVisibleObjectInteractions(false, true, false, true);
323}
324
326{
327 if (m_memberSlots.size() > 5)
328 return; // What message error should we send?
329
331
333 {
334 delete[] m_subGroupsCounts;
335 m_subGroupsCounts = nullptr;
336 }
337
338 if (!isBGGroup() && !isBFGroup())
339 {
341
342 stmt->setUInt16(0, m_groupFlags);
343 stmt->setUInt32(1, m_dbStoreId);
344
345 CharacterDatabase.Execute(stmt);
346 }
347
348 SendUpdate();
349
350 // update quest related GO states (quest activity dependent from raid membership)
351 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
352 if (Player* player = ObjectAccessor::FindPlayer(citr->guid))
353 player->UpdateVisibleObjectInteractions(false, true, false, true);
354}
355
357{
358 if (!player || player->GetGroupInvite())
359 return false;
360 Group* group = player->GetGroup();
361 if (group && (group->isBGGroup() || group->isBFGroup()))
362 group = player->GetOriginalGroup();
363 if (group)
364 return false;
365
366 RemoveInvite(player);
367
368 m_invitees.insert(player);
369
370 player->SetGroupInvite(this);
371
372 sScriptMgr->OnGroupInviteMember(this, player->GetGUID());
373
374 return true;
375}
376
378{
379 if (!AddInvite(player))
380 return false;
381
382 m_leaderGuid = player->GetGUID();
384 m_leaderName = player->GetName();
385 return true;
386}
387
389{
390 if (player)
391 {
392 m_invitees.erase(player);
393 player->SetGroupInvite(nullptr);
394 }
395}
396
398{
399 for (InvitesList::iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
400 if (*itr)
401 (*itr)->SetGroupInvite(nullptr);
402
403 m_invitees.clear();
404}
405
407{
408 for (InvitesList::const_iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
409 {
410 if ((*itr) && (*itr)->GetGUID() == guid)
411 return (*itr);
412 }
413 return nullptr;
414}
415
416Player* Group::GetInvited(const std::string& name) const
417{
418 for (InvitesList::const_iterator itr = m_invitees.begin(); itr != m_invitees.end(); ++itr)
419 {
420 if ((*itr) && (*itr)->GetName() == name)
421 return (*itr);
422 }
423 return nullptr;
424}
425
427{
428 // Get first not-full group
429 uint8 subGroup = 0;
431 {
432 bool groupFound = false;
433 for (; subGroup < MAX_RAID_SUBGROUPS; ++subGroup)
434 {
435 if (m_subGroupsCounts[subGroup] < MAX_GROUP_SIZE)
436 {
437 groupFound = true;
438 break;
439 }
440 }
441 // We are raid group and no one slot is free
442 if (!groupFound)
443 return false;
444 }
445
446 MemberSlot member;
447 member.guid = player->GetGUID();
448 member.name = player->GetName();
449 member.race = Races(player->GetRace());
450 member._class = player->GetClass();
451 member.group = subGroup;
452 member.flags = 0;
453 member.roles = 0;
454 member.readyChecked = false;
455 m_memberSlots.push_back(member);
456
457 SubGroupCounterIncrease(subGroup);
458
459 player->SetGroupInvite(nullptr);
460 if (player->GetGroup())
461 {
462 if (isBGGroup() || isBFGroup()) // if player is in group and he is being added to BG raid group, then call SetBattlegroundRaid()
463 player->SetBattlegroundOrBattlefieldRaid(this, subGroup);
464 else //if player is in bg raid and we are adding him to normal group, then call SetOriginalGroup()
465 player->SetOriginalGroup(this, subGroup);
466 }
467 else //if player is not in group, then call set group
468 player->SetGroup(this, subGroup);
469
472
473 // if the same group invites the player back, cancel the homebind timer
474 player->m_InstanceValid = player->CheckInstanceValidity(false);
475
476 if (!isRaidGroup()) // reset targetIcons for non-raid-groups
477 {
478 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
479 m_targetIcons[i].Clear();
480 }
481
482 // insert into the table if we're not a battleground group
483 if (!isBGGroup() && !isBFGroup())
484 {
486
487 stmt->setUInt32(0, m_dbStoreId);
488 stmt->setUInt64(1, member.guid.GetCounter());
489 stmt->setUInt8(2, member.flags);
490 stmt->setUInt8(3, member.group);
491 stmt->setUInt8(4, member.roles);
492
493 CharacterDatabase.Execute(stmt);
494 }
495
496 SendUpdate();
497 sScriptMgr->OnGroupAddMember(this, player->GetGUID());
498
499 if (!IsLeader(player->GetGUID()) && !isBGGroup() && !isBFGroup())
500 {
502 {
504 player->SendDungeonDifficulty();
505 }
506 if (player->GetRaidDifficultyID() != GetRaidDifficultyID())
507 {
509 player->SendRaidDifficulty(false);
510 }
512 {
514 player->SendRaidDifficulty(true);
515 }
516 }
517
519 if (Pet* pet = player->GetPet())
520 pet->SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL);
521
523
524 // quest related GO state dependent from raid membership
525 if (isRaidGroup())
526 player->UpdateVisibleObjectInteractions(false, true, false, true);
527
529
530 {
531 // Broadcast new player group member fields to rest of the group
532 UpdateData groupData(player->GetMapId());
533 WorldPacket groupDataPacket;
534
535 // Broadcast group members' fields to player
536 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
537 {
538 if (itr->GetSource() == player)
539 continue;
540
541 if (Player* existingMember = itr->GetSource())
542 {
543 if (player->HaveAtClient(existingMember))
544 existingMember->BuildValuesUpdateBlockForPlayerWithFlag(&groupData, UF::UpdateFieldFlag::PartyMember, player);
545
546 if (existingMember->HaveAtClient(player))
547 {
548 UpdateData newData(player->GetMapId());
549 WorldPacket newDataPacket;
551 if (newData.HasData())
552 {
553 newData.BuildPacket(&newDataPacket);
554 existingMember->SendDirectMessage(&newDataPacket);
555 }
556 }
557 }
558 }
559
560 if (groupData.HasData())
561 {
562 groupData.BuildPacket(&groupDataPacket);
563 player->SendDirectMessage(&groupDataPacket);
564 }
565 }
566
567 return true;
568}
569
570bool Group::RemoveMember(ObjectGuid guid, RemoveMethod method /*= GROUP_REMOVEMETHOD_DEFAULT*/, ObjectGuid kicker /*= 0*/, const char* reason /*= nullptr*/)
571{
573
574 sScriptMgr->OnGroupRemoveMember(this, guid, method, kicker, reason);
575
577 if (player)
578 {
579 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
580 {
581 if (Player* groupMember = itr->GetSource())
582 {
583 if (groupMember->GetGUID() == guid)
584 continue;
585
586 groupMember->RemoveAllGroupBuffsFromCaster(guid);
587 player->RemoveAllGroupBuffsFromCaster(groupMember->GetGUID());
588 }
589 }
590 }
591
592 // LFG group vote kick handled in scripts
593 if (isLFGGroup() && method == GROUP_REMOVEMETHOD_KICK)
594 return !m_memberSlots.empty();
595
596 if (player)
598
599 // remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group)
600 if (GetMembersCount() > ((isBGGroup() || isLFGGroup() || isBFGroup()) ? 1u : 2u))
601 {
602 if (player)
603 {
604 // Battleground group handling
605 if (isBGGroup() || isBFGroup())
607 else
608 // Regular group
609 {
610 if (player->GetOriginalGroup() == this)
611 player->SetOriginalGroup(nullptr);
612 else
613 player->SetGroup(nullptr);
614
615 // quest related GO state dependent from raid membership
616 player->UpdateVisibleObjectInteractions(false, true, false, true);
617 }
618
620
621 if (method == GROUP_REMOVEMETHOD_KICK || method == GROUP_REMOVEMETHOD_KICK_LFG)
623
624 _homebindIfInstance(player);
625 }
626
627 // Remove player from group in DB
628 if (!isBGGroup() && !isBFGroup())
629 {
631 stmt->setUInt64(0, guid.GetCounter());
632 CharacterDatabase.Execute(stmt);
633 DelinkMember(guid);
634 }
635
636 // Update subgroups
638 if (slot != m_memberSlots.end())
639 {
640 SubGroupCounterDecrease(slot->group);
641 m_memberSlots.erase(slot);
642 }
643
644 // Pick new leader if necessary
645 if (m_leaderGuid == guid)
646 {
647 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
648 {
650 {
651 ChangeLeader(itr->guid);
652 break;
653 }
654 }
655 }
656
657 SendUpdate();
658
659 if (isLFGGroup() && GetMembersCount() == 1)
660 {
662 uint32 mapId = sLFGMgr->GetDungeonMapId(GetGUID());
663 if (!mapId || !leader || (leader->IsAlive() && leader->GetMapId() != mapId))
664 {
665 Disband();
666 return false;
667 }
668 }
669
670 if (m_memberMgr.getSize() < ((isLFGGroup() || isBGGroup()) ? 1u : 2u))
671 Disband();
672 else if (player)
673 {
674 // send update to removed player too so party frames are destroyed clientside
676 }
677
678 return true;
679 }
680 // If group size before player removal <= 2 then disband it
681 else
682 {
683 Disband();
684 return false;
685 }
686}
687
689{
690 member_witerator slot = _getMemberWSlot(newLeaderGuid);
691
692 if (slot == m_memberSlots.end())
693 return;
694
695 Player* newLeader = ObjectAccessor::FindConnectedPlayer(slot->guid);
696
697 // Don't allow switching leader to offline players
698 if (!newLeader)
699 return;
700
701 sScriptMgr->OnGroupChangeLeader(this, newLeaderGuid, m_leaderGuid);
702
703 if (!isBGGroup() && !isBFGroup())
704 {
705 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
706
707 // Update the group leader
709
710 stmt->setUInt64(0, newLeader->GetGUID().GetCounter());
711 stmt->setUInt32(1, m_dbStoreId);
712
713 trans->Append(stmt);
714
715 CharacterDatabase.CommitTransaction(trans);
716 }
717
719 oldLeader->RemovePlayerFlag(PLAYER_FLAGS_GROUP_LEADER);
720
722 m_leaderGuid = newLeader->GetGUID();
724 m_leaderName = newLeader->GetName();
726
728 groupNewLeader.Name = m_leaderName;
729 groupNewLeader.PartyIndex = GetGroupCategory();
730 BroadcastPacket(groupNewLeader.Write(), true);
731}
732
733void Group::Disband(bool hideDestroy /* = false */)
734{
735 sScriptMgr->OnGroupDisband(this);
736
737 Player* player;
738 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
739 {
740 player = ObjectAccessor::FindConnectedPlayer(citr->guid);
741 if (!player)
742 continue;
743
744 //we cannot call _removeMember because it would invalidate member iterator
745 //if we are removing player from battleground raid
746 if (isBGGroup() || isBFGroup())
748 else
749 {
750 //we can remove player who is in battleground from his original group
751 if (player->GetOriginalGroup() == this)
752 player->SetOriginalGroup(nullptr);
753 else
754 player->SetGroup(nullptr);
755 }
756
758
759 // quest related GO state dependent from raid membership
760 if (isRaidGroup())
761 player->UpdateVisibleObjectInteractions(false, true, false, true);
762
763 if (!hideDestroy)
765
767
768 _homebindIfInstance(player);
769 }
770
771 m_memberSlots.clear();
772
774
775 if (!isBGGroup() && !isBFGroup())
776 {
777 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
778
780 stmt->setUInt32(0, m_dbStoreId);
781 trans->Append(stmt);
782
783 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_MEMBER_ALL);
784 stmt->setUInt32(0, m_dbStoreId);
785 trans->Append(stmt);
786
787 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
788 stmt->setUInt32(0, m_dbStoreId);
789 trans->Append(stmt);
790
791 CharacterDatabase.CommitTransaction(trans);
792
793 sGroupMgr->FreeGroupDbStoreId(this);
794 }
795
796 sGroupMgr->RemoveGroup(this);
797 delete this;
798}
799
800void Group::SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy)
801{
802 if (symbol >= TARGET_ICONS_COUNT)
803 return;
804
805 // clean other icons
806 if (!target.IsEmpty())
807 for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
808 if (m_targetIcons[i] == target)
809 SetTargetIcon(i, ObjectGuid::Empty, changedBy);
810
811 m_targetIcons[symbol] = target;
812
814 updateSingle.PartyIndex = GetGroupCategory();
815 updateSingle.Target = target;
816 updateSingle.ChangedBy = changedBy;
817 updateSingle.Symbol = symbol;
818 BroadcastPacket(updateSingle.Write(), true);
819}
820
822{
823 if (!session)
824 return;
825
827 updateAll.PartyIndex = GetGroupCategory();
828 for (uint8 i = 0; i < TARGET_ICONS_COUNT; i++)
829 updateAll.TargetIcons.try_emplace(i, m_targetIcons[i]);
830
831 session->SendPacket(updateAll.Write());
832}
833
835{
836 for (member_witerator witr = m_memberSlots.begin(); witr != m_memberSlots.end(); ++witr)
837 SendUpdateToPlayer(witr->guid, &(*witr));
838}
839
841{
842 Player* player = ObjectAccessor::FindConnectedPlayer(playerGUID);
843
844 if (!player || !player->GetSession() || player->GetGroup() != this)
845 return;
846
847 // if MemberSlot wasn't provided
848 if (!slot)
849 {
850 member_witerator witr = _getMemberWSlot(playerGUID);
851
852 if (witr == m_memberSlots.end()) // if there is no MemberSlot for such a player
853 return;
854
855 slot = &(*witr);
856 }
857
859
860 partyUpdate.PartyFlags = m_groupFlags;
861 partyUpdate.PartyIndex = m_groupCategory;
863
864 partyUpdate.PartyGUID = m_guid;
865 partyUpdate.LeaderGUID = m_leaderGuid;
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
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 partyUpdate.PlayerList.push_back(playerInfos);
894 }
895
896 if (GetMembersCount() > 1)
897 {
898 // LootSettings
899 partyUpdate.LootSettings.emplace();
900 partyUpdate.LootSettings->Method = m_lootMethod;
901 partyUpdate.LootSettings->Threshold = m_lootThreshold;
903
904 // Difficulty Settings
905 partyUpdate.DifficultySettings.emplace();
906 partyUpdate.DifficultySettings->DungeonDifficultyID = m_dungeonDifficulty;
907 partyUpdate.DifficultySettings->RaidDifficultyID = m_raidDifficulty;
908 partyUpdate.DifficultySettings->LegacyRaidDifficultyID = m_legacyRaidDifficulty;
909 }
910
911 // LfgInfos
912 if (isLFGGroup())
913 {
914 partyUpdate.LfgInfos.emplace();
915
916 partyUpdate.LfgInfos->Slot = sLFGMgr->GetLFGDungeonEntry(sLFGMgr->GetDungeon(m_guid));
917 partyUpdate.LfgInfos->BootCount = 0;
918 partyUpdate.LfgInfos->Aborted = false;
919
920 partyUpdate.LfgInfos->MyFlags = sLFGMgr->GetState(m_guid) == lfg::LFG_STATE_FINISHED_DUNGEON ? 2 : 0;
921 partyUpdate.LfgInfos->MyRandomSlot = sLFGMgr->GetSelectedRandomDungeon(player->GetGUID());
922
923 partyUpdate.LfgInfos->MyPartialClear = 0;
924 partyUpdate.LfgInfos->MyGearDiff = 0.0f;
925 partyUpdate.LfgInfos->MyFirstReward = false;
926 if (lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(partyUpdate.LfgInfos->MyRandomSlot, player->GetLevel()))
927 if (Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest))
928 partyUpdate.LfgInfos->MyFirstReward = player->CanRewardQuest(quest, false);
929
930 partyUpdate.LfgInfos->MyStrangerCount = 0;
931 partyUpdate.LfgInfos->MyKickVoteCount = 0;
932 }
933
934 player->SendDirectMessage(partyUpdate.Write());
935}
936
938{
940 partyUpdate.PartyFlags = GROUP_FLAG_DESTROYED;
941 partyUpdate.PartyIndex = m_groupCategory;
942 partyUpdate.PartyType = GROUP_TYPE_NONE;
943 partyUpdate.PartyGUID = m_guid;
944 partyUpdate.MyIndex = -1;
946 player->SendDirectMessage(partyUpdate.Write());
947}
948
950{
951 if (!player || !player->IsInWorld())
952 return;
953
955 packet.Initialize(player);
956 packet.Write();
957
958 Player* member;
959 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
960 {
961 member = itr->GetSource();
962 if (member && member != player && (!member->IsInMap(player) || !member->IsWithinDist(player, member->GetSightRange(), false)))
963 member->SendDirectMessage(packet.GetRawPacket());
964 }
965}
966
967void Group::BroadcastAddonMessagePacket(WorldPacket const* packet, const std::string& prefix, bool ignorePlayersInBGRaid, int group /*= -1*/, ObjectGuid ignore /*= ObjectGuid::Empty*/) const
968{
969 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
970 {
971 Player* player = itr->GetSource();
972 if (!player || (!ignore.IsEmpty() && player->GetGUID() == ignore) || (ignorePlayersInBGRaid && player->GetGroup() != this))
973 continue;
974
975 if (player->GetSession()->IsAddonRegistered(prefix) && (group == -1 || itr->getSubGroup() == group))
976 player->SendDirectMessage(packet);
977 }
978}
979
980void Group::BroadcastPacket(WorldPacket const* packet, bool ignorePlayersInBGRaid, int group, ObjectGuid ignoredPlayer) const
981{
982 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
983 {
984 Player const* player = itr->GetSource();
985 if (!player || (!ignoredPlayer.IsEmpty() && player->GetGUID() == ignoredPlayer) || (ignorePlayersInBGRaid && player->GetGroup() != this))
986 continue;
987
988 if (group == -1 || itr->getSubGroup() == group)
989 player->SendDirectMessage(packet);
990 }
991}
992
994{
996 if (slot == m_memberSlots.end())
997 return false;
998
999 slot->group = group;
1000
1002
1003 if (!isBGGroup() && !isBFGroup())
1004 {
1006
1007 stmt->setUInt8(0, group);
1008 stmt->setUInt64(1, guid.GetCounter());
1009
1010 CharacterDatabase.Execute(stmt);
1011 }
1012
1013 return true;
1014}
1015
1016bool Group::SameSubGroup(Player const* member1, Player const* member2) const
1017{
1018 if (!member1 || !member2)
1019 return false;
1020
1021 if (member1->GetGroup() != this || member2->GetGroup() != this)
1022 return false;
1023 else
1024 return member1->GetSubGroup() == member2->GetSubGroup();
1025}
1026
1027// Allows setting sub groups both for online or offline members
1029{
1030 // Only raid groups have sub groups
1031 if (!isRaidGroup())
1032 return;
1033
1034 // Check if player is really in the raid
1035 member_witerator slot = _getMemberWSlot(guid);
1036 if (slot == m_memberSlots.end())
1037 return;
1038
1039 uint8 prevSubGroup = slot->group;
1040 // Abort if the player is already in the target sub group
1041 if (prevSubGroup == group)
1042 return;
1043
1044 // Update the player slot with the new sub group setting
1045 slot->group = group;
1046
1047 // Increase the counter of the new sub group..
1049
1050 // ..and decrease the counter of the previous one
1051 SubGroupCounterDecrease(prevSubGroup);
1052
1053 // Preserve new sub group in database for non-raid groups
1054 if (!isBGGroup() && !isBFGroup())
1055 {
1057
1058 stmt->setUInt8(0, group);
1059 stmt->setUInt64(1, guid.GetCounter());
1060
1061 CharacterDatabase.Execute(stmt);
1062 }
1063
1064 // In case the moved player is online, update the player object with the new sub group references
1065 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1066 {
1067 if (player->GetGroup() == this)
1068 player->GetGroupRef().setSubGroup(group);
1069 else
1070 {
1071 // 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
1072 player->GetOriginalGroupRef().setSubGroup(group);
1073 }
1074 }
1075
1076 // Broadcast the changes to the group
1077 SendUpdate();
1078}
1079
1081{
1082 if (!isRaidGroup())
1083 return;
1084
1085 member_witerator slots[2];
1086 slots[0] = _getMemberWSlot(firstGuid);
1087 slots[1] = _getMemberWSlot(secondGuid);
1088 if (slots[0] == m_memberSlots.end() || slots[1] == m_memberSlots.end())
1089 return;
1090
1091 if (slots[0]->group == slots[1]->group)
1092 return;
1093
1094 uint8 tmp = slots[0]->group;
1095 slots[0]->group = slots[1]->group;
1096 slots[1]->group = tmp;
1097
1098 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
1099 for (uint8 i = 0; i < 2; i++)
1100 {
1101 // Preserve new sub group in database for non-raid groups
1102 if (!isBGGroup() && !isBFGroup())
1103 {
1105
1106 stmt->setUInt8(0, slots[i]->group);
1107 stmt->setUInt64(1, slots[i]->guid.GetCounter());
1108
1109 trans->Append(stmt);
1110 }
1111
1112 if (Player* player = ObjectAccessor::FindConnectedPlayer(slots[i]->guid))
1113 {
1114 if (player->GetGroup() == this)
1115 player->GetGroupRef().setSubGroup(slots[i]->group);
1116 else
1117 player->GetOriginalGroupRef().setSubGroup(slots[i]->group);
1118 }
1119 }
1120 CharacterDatabase.CommitTransaction(trans);
1121
1122 SendUpdate();
1123}
1124
1125// Retrieve the next Round-Roubin player for the group
1126//
1127// No update done if loot method is FFA.
1128//
1129// If the RR player is not yet set for the group, the first group member becomes the round-robin player.
1130// If the RR player is set, the next player in group becomes the round-robin player.
1131//
1132// If ifneed is true,
1133// the current RR player is checked to be near the looted object.
1134// if yes, no update done.
1135// if not, he loses his turn.
1136void Group::UpdateLooterGuid(WorldObject* pLootedObject, bool ifneed)
1137{
1138 // round robin style looting applies for all low
1139 // quality items in each loot method except free for all
1140 if (GetLootMethod() == FREE_FOR_ALL)
1141 return;
1142
1143 ObjectGuid oldLooterGUID = GetLooterGuid();
1144 member_citerator guid_itr = _getMemberCSlot(oldLooterGUID);
1145 if (guid_itr != m_memberSlots.end())
1146 {
1147 if (ifneed)
1148 {
1149 // not update if only update if need and ok
1150 Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid);
1151 if (looter && looter->IsAtGroupRewardDistance(pLootedObject))
1152 return;
1153 }
1154 ++guid_itr;
1155 }
1156
1157 // search next after current
1158 Player* pNewLooter = nullptr;
1159 for (member_citerator itr = guid_itr; itr != m_memberSlots.end(); ++itr)
1160 {
1161 if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1162 if (player->IsAtGroupRewardDistance(pLootedObject))
1163 {
1164 pNewLooter = player;
1165 break;
1166 }
1167 }
1168
1169 if (!pNewLooter)
1170 {
1171 // search from start
1172 for (member_citerator itr = m_memberSlots.begin(); itr != guid_itr; ++itr)
1173 {
1174 if (Player* player = ObjectAccessor::FindPlayer(itr->guid))
1175 if (player->IsAtGroupRewardDistance(pLootedObject))
1176 {
1177 pNewLooter = player;
1178 break;
1179 }
1180 }
1181 }
1182
1183 if (pNewLooter)
1184 {
1185 if (oldLooterGUID != pNewLooter->GetGUID())
1186 {
1187 SetLooterGuid(pNewLooter->GetGUID());
1188 SendUpdate();
1189 }
1190 }
1191 else
1192 {
1194 SendUpdate();
1195 }
1196}
1197
1198GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(BattlegroundTemplate const* bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 /*MaxPlayerCount*/, bool isRated, uint32 arenaSlot, ObjectGuid& errorGuid) const
1199{
1200 // check if this group is LFG group
1201 if (isLFGGroup())
1203
1204 BattlemasterListEntry const* bgEntry = sBattlemasterListStore.LookupEntry(bgOrTemplate->Id);
1205 if (!bgEntry)
1206 return ERR_BATTLEGROUND_JOIN_FAILED; // shouldn't happen
1207
1208 // check for min / max count
1209 uint32 memberscount = GetMembersCount();
1210
1211 if (int32(memberscount) > bgEntry->MaxGroupSize) // no MinPlayerCount for battlegrounds
1212 return ERR_BATTLEGROUND_NONE; // ERR_GROUP_JOIN_BATTLEGROUND_TOO_MANY handled on client side
1213
1214 // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
1215 Player* reference = ASSERT_NOTNULL(GetFirstMember())->GetSource();
1216 // no reference found, can't join this way
1217 if (!reference)
1219
1220 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgOrTemplate->BattlemasterEntry->MapID[0], reference->GetLevel());
1221 if (!bracketEntry)
1223
1224 uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
1225 Team team = reference->GetTeam();
1226 bool isMercenary = reference->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || reference->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE);
1227
1228 // check every member of the group to be able to join
1229 memberscount = 0;
1230 for (GroupReference const* itr = GetFirstMember(); itr != nullptr; itr = itr->next(), ++memberscount)
1231 {
1232 Player* member = itr->GetSource();
1233 // offline member? don't let join
1234 if (!member)
1236 // rbac permissions
1237 if (!member->CanJoinToBattleground(bgOrTemplate))
1239 // don't allow cross-faction join as group
1240 if (member->GetTeam() != team)
1241 {
1242 errorGuid = member->GetGUID();
1244 }
1245 // not in the same battleground level braket, don't let join
1246 PVPDifficultyEntry const* memberBracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bracketEntry->MapID, member->GetLevel());
1247 if (memberBracketEntry != bracketEntry)
1249 // don't let join rated matches if the arena team id doesn't match
1250 if (isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
1252 // don't let join if someone from the group is already in that bg queue
1253 if (member->InBattlegroundQueueForBattlegroundQueueType(bgQueueTypeId))
1254 return ERR_BATTLEGROUND_JOIN_FAILED; // not blizz-like
1255 // don't let join if someone from the group is in bg queue random
1258 if (bgOrTemplate->Id != BATTLEGROUND_AA && isInRandomBgQueue)
1259 return ERR_IN_RANDOM_BG;
1260 // don't let join to bg queue random if someone from the group is already in bg queue
1261 if (BattlegroundMgr::IsRandomBattleground(bgOrTemplate->Id) && member->InBattlegroundQueue(true) && !isInRandomBgQueue)
1262 return ERR_IN_NON_RANDOM_BG;
1263 // check for deserter debuff in case not arena queue
1264 if (bgOrTemplate->Id != BATTLEGROUND_AA && member->IsDeserter())
1266 // check if member can join any more battleground queues
1267 if (!member->HasFreeBattlegroundQueueId())
1268 return ERR_BATTLEGROUND_TOO_MANY_QUEUES; // not blizz-like
1269 // check if someone in party is using dungeon system
1270 if (member->isUsingLfg())
1272 // check Freeze debuff
1273 if (member->HasAura(9454))
1275 if (isMercenary != (member->HasAura(SPELL_MERCENARY_CONTRACT_HORDE) || member->HasAura(SPELL_MERCENARY_CONTRACT_ALLIANCE)))
1277 }
1278
1279 // only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
1280 if (bgOrTemplate->IsArena() && memberscount != MinPlayerCount)
1282
1283 return ERR_BATTLEGROUND_NONE;
1284}
1285
1287{
1288 m_dungeonDifficulty = difficulty;
1289 if (!isBGGroup() && !isBFGroup())
1290 {
1292
1294 stmt->setUInt32(1, m_dbStoreId);
1295
1296 CharacterDatabase.Execute(stmt);
1297 }
1298
1299 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
1300 {
1301 Player* player = itr->GetSource();
1302 if (!player->GetSession())
1303 continue;
1304
1305 player->SetDungeonDifficultyID(difficulty);
1306 player->SendDungeonDifficulty();
1307 }
1308}
1309
1311{
1312 m_raidDifficulty = difficulty;
1313 if (!isBGGroup() && !isBFGroup())
1314 {
1316
1317 stmt->setUInt8(0, uint8(m_raidDifficulty));
1318 stmt->setUInt32(1, m_dbStoreId);
1319
1320 CharacterDatabase.Execute(stmt);
1321 }
1322
1323 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
1324 {
1325 Player* player = itr->GetSource();
1326 if (!player->GetSession())
1327 continue;
1328
1329 player->SetRaidDifficultyID(difficulty);
1330 player->SendRaidDifficulty(false);
1331 }
1332}
1333
1335{
1336 m_legacyRaidDifficulty = difficulty;
1337 if (!isBGGroup() && !isBFGroup())
1338 {
1340
1342 stmt->setUInt32(1, m_dbStoreId);
1343
1344 CharacterDatabase.Execute(stmt);
1345 }
1346
1347 for (GroupReference* itr = GetFirstMember(); itr != nullptr; itr = itr->next())
1348 {
1349 Player* player = itr->GetSource();
1350 if (!player->GetSession())
1351 continue;
1352
1353 player->SetLegacyRaidDifficultyID(difficulty);
1354 player->SendRaidDifficulty(true);
1355 }
1356}
1357
1359{
1360 if (!mapEntry->IsRaid())
1361 return m_dungeonDifficulty;
1362
1363 MapDifficultyEntry const* defaultDifficulty = sDB2Manager.GetDefaultMapDifficulty(mapEntry->ID);
1364 if (!defaultDifficulty)
1366
1367 DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(defaultDifficulty->DifficultyID);
1368 if (!difficulty || difficulty->Flags & DIFFICULTY_FLAG_LEGACY)
1370
1371 return m_raidDifficulty;
1372}
1373
1375{
1377 {
1378 InstanceMap* map = ref.GetSource();
1379 switch (map->Reset(method))
1380 {
1382 notifyPlayer->SendResetInstanceSuccess(map->GetId());
1383 m_recentInstances.erase(map->GetId());
1384 break;
1386 if (method == InstanceResetMethod::Manual)
1388 else if (method == InstanceResetMethod::OnChangeDifficulty)
1389 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
1390 break;
1392 m_recentInstances.erase(map->GetId()); // forget the instance, allows retrying different lockout with a new leader
1393 break;
1394 default:
1395 break;
1396 }
1397 }
1398}
1399
1401{
1403}
1404
1406{
1407 if (player && !player->IsGameMaster() && sMapStore.LookupEntry(player->GetMapId())->IsDungeon())
1408 player->m_InstanceValid = false;
1409}
1410
1412{
1413 // FG: HACK: force flags update on group leave - for values update hack
1414 // -- not very efficient but safe
1415 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1416 {
1417 if (Player * pp = ObjectAccessor::FindPlayer(citr->guid))
1418 {
1419 pp->ForceUpdateFieldChange(pp->m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PvpFlags));
1420 pp->ForceUpdateFieldChange(pp->m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::FactionTemplate));
1421 TC_LOG_DEBUG("misc", "-- Forced group value update for '{}'", pp->GetName());
1422 }
1423 }
1424}
1425
1427{
1428 if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(_countdowns))
1429 return;
1430
1431 if (!_countdowns[AsUnderlyingType(timerType)])
1432 _countdowns[AsUnderlyingType(timerType)] = std::make_unique<CountdownInfo>();
1433
1434 _countdowns[AsUnderlyingType(timerType)]->StartCountdown(duration, startTime);
1435}
1436
1438{
1439 if (AsUnderlyingType(timerType) < 0 || AsUnderlyingType(timerType) >= std::ssize(_countdowns))
1440 return nullptr;
1441
1442 return _countdowns[AsUnderlyingType(timerType)].get();
1443}
1444
1446{
1447 m_lootMethod = method;
1448}
1449
1451{
1452 m_looterGuid = guid;
1453}
1454
1456{
1457 m_masterLooterGuid = guid;
1458}
1459
1461{
1462 m_lootThreshold = threshold;
1463}
1464
1466{
1467 member_witerator slot = _getMemberWSlot(guid);
1468 if (slot == m_memberSlots.end())
1469 return;
1470
1471 slot->roles = roles;
1472 SendUpdate();
1473}
1474
1476{
1477 member_witerator slot = _getMemberWSlot(guid);
1478 if (slot == m_memberSlots.end())
1479 return 0;
1480
1481 return slot->roles;
1482}
1483
1485{
1487 return;
1488
1490 if (m_readyCheckTimer <= Milliseconds::zero())
1491 EndReadyCheck();
1492}
1493
1495{
1497 return;
1498
1499 member_witerator slot = _getMemberWSlot(starterGuid);
1500 if (slot == m_memberSlots.end())
1501 return ;
1502
1503 m_readyCheckStarted = true;
1504 m_readyCheckTimer = duration;
1505
1507
1508 SetMemberReadyChecked(&(*slot));
1509
1511 readyCheckStarted.PartyGUID = m_guid;
1512 readyCheckStarted.PartyIndex = GetGroupCategory();
1513 readyCheckStarted.InitiatorGUID = starterGuid;
1514 readyCheckStarted.Duration = duration;
1515 BroadcastPacket(readyCheckStarted.Write(), false);
1516}
1517
1519{
1521 return;
1522
1523 m_readyCheckStarted = false;
1524 m_readyCheckTimer = Milliseconds::zero();
1525
1527
1528 WorldPackets::Party::ReadyCheckCompleted readyCheckCompleted;
1529 readyCheckCompleted.PartyIndex = 0;
1530 readyCheckCompleted.PartyGUID = m_guid;
1531 BroadcastPacket(readyCheckCompleted.Write(), false);
1532}
1533
1535{
1536 for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
1537 if (!citr->readyChecked)
1538 return false;
1539 return true;
1540}
1541
1543{
1545 return;
1546
1547 member_witerator slot = _getMemberWSlot(guid);
1548 if (slot != m_memberSlots.end())
1549 SetMemberReadyCheck(&(*slot), ready);
1550}
1551
1553{
1555 response.PartyGUID = m_guid;
1556 response.Player = slot->guid;
1557 response.IsReady = ready;
1558 BroadcastPacket(response.Write(), false);
1559
1561}
1562
1564{
1565 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1566 {
1567 Player* player = ObjectAccessor::FindConnectedPlayer(itr->guid);
1568 if (!player || !player->GetSession())
1569 SetMemberReadyCheck(&(*itr), false);
1570 }
1571}
1572
1574{
1575 slot->readyChecked = true;
1577 EndReadyCheck();
1578}
1579
1581{
1582 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1583 itr->readyChecked = false;
1584}
1585
1586void Group::AddRaidMarker(uint8 markerId, uint32 mapId, float positionX, float positionY, float positionZ, ObjectGuid transportGuid)
1587{
1588 if (markerId >= RAID_MARKERS_COUNT || m_markers[markerId])
1589 return;
1590
1591 m_activeMarkers |= (1 << markerId);
1592 m_markers[markerId] = std::make_unique<RaidMarker>(mapId, positionX, positionY, positionZ, transportGuid);
1594}
1595
1597{
1598 if (markerId > RAID_MARKERS_COUNT)
1599 return;
1600
1601 for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
1602 if (m_markers[i] && (markerId == i || markerId == RAID_MARKERS_COUNT))
1603 {
1604 m_markers[i] = nullptr;
1605 m_activeMarkers &= ~(1 << i);
1606 }
1607
1609}
1610
1612{
1614
1615 packet.PartyIndex = GetGroupCategory();
1617
1618 for (uint8 i = 0; i < RAID_MARKERS_COUNT; i++)
1619 if (m_markers[i])
1620 packet.RaidMarkers.push_back(m_markers[i].get());
1621
1622 if (session)
1623 session->SendPacket(packet.Write());
1624 else
1625 BroadcastPacket(packet.Write(), false);
1626}
1627
1628bool Group::IsFull() const
1629{
1630 return isRaidGroup() ? (m_memberSlots.size() >= MAX_RAID_SIZE) : (m_memberSlots.size() >= MAX_GROUP_SIZE);
1631}
1632
1634{
1635 return (m_groupFlags & GROUP_FLAG_LFG) != 0;
1636}
1637
1639{
1640 return (m_groupFlags & GROUP_FLAG_RAID) != 0;
1641}
1642
1644{
1645 return m_bgGroup != nullptr;
1646}
1647
1649{
1650 return m_bfGroup != nullptr;
1651}
1652
1654{
1655 return GetMembersCount() > 0;
1656}
1657
1659{
1660 return m_leaderGuid;
1661}
1662
1664{
1665 return m_guid;
1666}
1667
1668char const* Group::GetLeaderName() const
1669{
1670 return m_leaderName.c_str();
1671}
1672
1674{
1675 return m_lootMethod;
1676}
1677
1679{
1680 if (GetLootMethod() == FREE_FOR_ALL)
1681 return ObjectGuid::Empty;
1682 return m_looterGuid;
1683}
1684
1686{
1687 return m_masterLooterGuid;
1688}
1689
1691{
1692 return m_lootThreshold;
1693}
1694
1696{
1697 return _getMemberCSlot(guid) != m_memberSlots.end();
1698}
1699
1701{
1702 return (GetLeaderGUID() == guid);
1703}
1704
1705ObjectGuid Group::GetMemberGUID(const std::string& name)
1706{
1707 for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1708 if (itr->name == name)
1709 return itr->guid;
1710 return ObjectGuid::Empty;
1711}
1712
1714{
1715 member_citerator mslot = _getMemberCSlot(guid);
1716 if (mslot == m_memberSlots.end())
1717 return 0u;
1718 return mslot->flags;
1719}
1720
1722{
1723 member_citerator mslot2 = _getMemberCSlot(guid2);
1724 if (mslot2 == m_memberSlots.end())
1725 return false;
1726 return SameSubGroup(guid1, &*mslot2);
1727}
1728
1729bool Group::SameSubGroup(ObjectGuid guid1, MemberSlot const* slot2) const
1730{
1731 member_citerator mslot1 = _getMemberCSlot(guid1);
1732 if (mslot1 == m_memberSlots.end() || !slot2)
1733 return false;
1734 return (mslot1->group == slot2->group);
1735}
1736
1738{
1739 return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAX_GROUP_SIZE);
1740}
1741
1743{
1744 member_citerator mslot = _getMemberCSlot(guid);
1745 if (mslot == m_memberSlots.end())
1746 return (MAX_RAID_SUBGROUPS+1);
1747 return mslot->group;
1748}
1749
1751{
1752 m_bgGroup = bg;
1753}
1754
1756{
1757 m_bfGroup = bg;
1758}
1759
1761{
1762 // Assistants, main assistants and main tanks are only available in raid groups
1763 if (!isRaidGroup())
1764 return;
1765
1766 // Check if player is really in the raid
1767 member_witerator slot = _getMemberWSlot(guid);
1768 if (slot == m_memberSlots.end())
1769 return;
1770
1771 // Do flag specific actions, e.g ensure uniqueness
1772 switch (flag)
1773 {
1775 RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINASSIST); // Remove main assist flag from current if any.
1776 break;
1778 RemoveUniqueGroupMemberFlag(MEMBER_FLAG_MAINTANK); // Remove main tank flag from current if any.
1779 break;
1781 break;
1782 default:
1783 return; // This should never happen
1784 }
1785
1786 // Switch the actual flag
1787 ToggleGroupMemberFlag(slot, flag, apply);
1788
1789 // Preserve the new setting in the db
1791
1792 stmt->setUInt8(0, slot->flags);
1793 stmt->setUInt64(1, guid.GetCounter());
1794
1795 CharacterDatabase.Execute(stmt);
1796
1797 // Broadcast the changes to the group
1798 SendUpdate();
1799}
1800
1802{
1804}
1805
1807{
1809 while (ref)
1810 {
1811 GroupReference* nextRef = ref->next();
1812 if (ref->GetSource()->GetGUID() == guid)
1813 {
1814 ref->unlink();
1815 break;
1816 }
1817 ref = nextRef;
1818 }
1819}
1820
1822{
1823 // Sub group counters initialization
1824 if (!m_subGroupsCounts)
1826
1827 memset((void*)m_subGroupsCounts, 0, (MAX_RAID_SUBGROUPS)*sizeof(uint8));
1828
1829 for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1830 ++m_subGroupsCounts[itr->group];
1831}
1832
1834{
1835 for (member_citerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1836 if (itr->guid == Guid)
1837 return itr;
1838 return m_memberSlots.end();
1839}
1840
1842{
1843 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1844 if (itr->guid == Guid)
1845 return itr;
1846 return m_memberSlots.end();
1847}
1848
1850{
1852 ++m_subGroupsCounts[subgroup];
1853}
1854
1856{
1858 --m_subGroupsCounts[subgroup];
1859}
1860
1862{
1863 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1864 if (itr->flags & flag)
1865 itr->flags &= ~flag;
1866}
1867
1869{
1870 if (apply)
1871 slot->flags |= flag;
1872 else
1873 slot->flags &= ~flag;
1874}
1875
1877{
1878 m_isLeaderOffline = true;
1880}
1881
1883{
1884 m_isLeaderOffline = false;
1885}
1886
1888{
1889 if (apply)
1891 else
1893
1894 for (member_witerator itr = m_memberSlots.begin(); itr != m_memberSlots.end(); ++itr)
1896
1897 if (!isBGGroup() && !isBFGroup())
1898 {
1900
1901 stmt->setUInt16(0, m_groupFlags);
1902 stmt->setUInt32(1, m_dbStoreId);
1903
1904 CharacterDatabase.Execute(stmt);
1905 }
1906
1907 SendUpdate();
1908}
1909
1911{
1913}
1914
1915void Group::SetRestrictPingsToAssistants(bool restrictPingsToAssistants)
1916{
1917 if (restrictPingsToAssistants)
1919 else
1921
1922 if (!isBGGroup() && !isBFGroup())
1923 {
1925
1926 stmt->setUInt16(0, m_groupFlags);
1927 stmt->setUInt32(1, m_dbStoreId);
1928
1929 CharacterDatabase.Execute(stmt);
1930 }
1931
1932 SendUpdate();
1933}
@ 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_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:538
Difficulty
Definition: DBCEnums.h:873
@ DIFFICULTY_NORMAL_RAID
Definition: DBCEnums.h:886
@ DIFFICULTY_NORMAL
Definition: DBCEnums.h:875
@ DIFFICULTY_10_N
Definition: DBCEnums.h:877
@ DIFFICULTY_FLAG_LEGACY
Definition: DBCEnums.h:921
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
#define ASSERT
Definition: Errors.h:68
#define sGroupMgr
Definition: GroupMgr.h:61
@ 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_FLAG_RESTRICT_PINGS
Definition: Group.h:106
@ 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:507
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
LootMethod
Definition: Loot.h:88
@ PERSONAL_LOOT
Definition: Loot.h:94
@ MASTER_LOOT
Definition: Loot.h:91
@ FREE_FOR_ALL
Definition: Loot.h:89
InstanceResetMethod
Definition: Map.h:845
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ PLAYER_FLAGS_GROUP_LEADER
Definition: Player.h:428
Races
Definition: RaceMask.h:26
#define sScriptMgr
Definition: ScriptMgr.h:1418
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:491
static BattlegroundQueueTypeId BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize)
static bool IsRandomBattleground(uint32 battlemasterListId)
Group * GetBgRaid(Team team) const
Definition: Battleground.h:382
void SetBgRaid(Team team, Group *bg_raid)
static PVPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
Definition: DB2Stores.cpp:2768
Class used to access individual fields of database query result.
Definition: Field.h:90
uint32 GetUInt32() const
Definition: Field.cpp:62
GroupReference * getFirst()
GroupReference * next()
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:197
ObjectGuid m_targetIcons[TARGET_ICONS_COUNT]
Definition: Group.h:439
member_citerator _getMemberCSlot(ObjectGuid Guid) const
Definition: Group.cpp:1833
bool IsReadyCheckCompleted(void) const
Definition: Group.cpp:1534
void BroadcastGroupUpdate(void)
Definition: Group.cpp:1411
std::array< std::unique_ptr< CountdownInfo >, 3 > _countdowns
Definition: Group.h:460
bool isLFGGroup() const
Definition: Group.cpp:1633
bool m_isLeaderOffline
Definition: Group.h:449
void StartLeaderOfflineTimer()
Definition: Group.cpp:1876
uint8 GetMemberGroup(ObjectGuid guid) const
Definition: Group.cpp:1742
void SwapMembersGroups(ObjectGuid firstGuid, ObjectGuid secondGuid)
Definition: Group.cpp:1080
ObjectGuid GetMasterLooterGuid() const
Definition: Group.cpp:1685
Battlefield * m_bfGroup
Definition: Group.h:438
uint8 m_leaderFactionGroup
Definition: Group.h:430
bool AddLeaderInvite(Player *player)
Definition: Group.cpp:377
void SetBattlefieldGroup(Battlefield *bf)
Definition: Group.cpp:1755
InvitesList m_invitees
Definition: Group.h:428
void ResetInstances(InstanceResetMethod method, Player *notifyPlayer)
Definition: Group.cpp:1374
void DeleteRaidMarker(uint8 markerId)
Definition: Group.cpp:1596
void SendTargetIconList(WorldSession *session)
Definition: Group.cpp:821
GroupCategory GetGroupCategory() const
Definition: Group.h:295
Difficulty m_legacyRaidDifficulty
Definition: Group.h:436
bool IsCreated() const
Definition: Group.cpp:1653
bool _setMembersGroup(ObjectGuid guid, uint8 group)
Definition: Group.cpp:993
uint8 GetLfgRoles(ObjectGuid guid)
Definition: Group.cpp:1475
void SubGroupCounterDecrease(uint8 subgroup)
Definition: Group.cpp:1855
void SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot *slot=nullptr)
Definition: Group.cpp:840
void SetLootMethod(LootMethod method)
Definition: Group.cpp:1445
void ChangeMembersGroup(ObjectGuid guid, uint8 group)
Definition: Group.cpp:1028
void SetEveryoneIsAssistant(bool apply)
Definition: Group.cpp:1887
GroupCategory m_groupCategory
Definition: Group.h:433
ObjectGuid m_leaderGuid
Definition: Group.h:429
void RemoveAllInvites()
Definition: Group.cpp:397
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:1586
void _initRaidSubGroupsCounter()
Definition: Group.cpp:1821
void EndReadyCheck()
Definition: Group.cpp:1518
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:1460
void Disband(bool hideDestroy=false)
Definition: Group.cpp:733
void LoadGroupFromDB(Field *field)
Definition: Group.cpp:216
bool AddMember(Player *player)
Definition: Group.cpp:426
bool IsLeader(ObjectGuid guid) const
Definition: Group.cpp:1700
Battleground * m_bgGroup
Definition: Group.h:437
bool IsRestrictPingsToAssistants() const
Definition: Group.cpp:1910
Difficulty m_raidDifficulty
Definition: Group.h:435
void SendUpdate()
Definition: Group.cpp:834
void SetMemberReadyCheck(ObjectGuid guid, bool ready)
Definition: Group.cpp:1542
void BroadcastAddonMessagePacket(WorldPacket const *packet, const std::string &prefix, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignore=ObjectGuid::Empty) const
Definition: Group.cpp:967
GroupRefManager m_memberMgr
Definition: Group.h:427
void SetDungeonDifficultyID(Difficulty difficulty)
Definition: Group.cpp:1286
uint32 m_activeMarkers
Definition: Group.h:458
void SetMasterLooterGuid(ObjectGuid guid)
Definition: Group.cpp:1455
void SetRaidDifficultyID(Difficulty difficulty)
Definition: Group.cpp:1310
Trinity::unique_trackable_ptr< Group > m_scriptRef
Definition: Group.h:463
ObjectGuid GetGUID() const
Definition: Group.cpp:1663
void RemoveInvite(Player *player)
Definition: Group.cpp:388
void SetLegacyRaidDifficultyID(Difficulty difficulty)
Definition: Group.cpp:1334
bool isBGGroup() const
Definition: Group.cpp:1643
void ConvertToRaid()
Definition: Group.cpp:301
ItemQualities GetLootThreshold() const
Definition: Group.cpp:1690
void SetOfflineMembersReadyChecked(void)
Definition: Group.cpp:1563
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:1494
uint32 GetMembersCount() const
Definition: Group.h:327
Group()
Definition: Group.cpp:58
void StopLeaderOfflineTimer()
Definition: Group.cpp:1882
void Update(uint32 diff)
Definition: Group.cpp:90
void ToggleGroupMemberFlag(member_witerator slot, uint8 flag, bool apply)
Definition: Group.cpp:1868
void _homebindIfInstance(Player *player)
Definition: Group.cpp:1405
Difficulty GetRaidDifficultyID() const
Definition: Group.h:352
void SendRaidMarkersChanged(WorldSession *session=nullptr)
Definition: Group.cpp:1611
void SetLfgRoles(ObjectGuid guid, uint8 roles)
Definition: Group.cpp:1465
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag)
Definition: Group.cpp:1760
TimeTracker m_leaderOfflineTimer
Definition: Group.h:450
void ResetMemberReadyChecked(void)
Definition: Group.cpp:1580
member_witerator _getMemberWSlot(ObjectGuid Guid)
Definition: Group.cpp:1841
ObjectGuid GetLooterGuid() const
Definition: Group.cpp:1678
Milliseconds m_readyCheckTimer
Definition: Group.h:454
uint32 m_dbStoreId
Definition: Group.h:448
void DelinkMember(ObjectGuid guid)
Definition: Group.cpp:1806
void ChangeLeader(ObjectGuid guid)
Definition: Group.cpp:688
const char * GetLeaderName() const
Definition: Group.cpp:1668
ObjectGuid GetMemberGUID(const std::string &name)
Definition: Group.cpp:1705
void ConvertToLFG()
Definition: Group.cpp:283
ObjectGuid m_masterLooterGuid
Definition: Group.h:443
MemberSlotList::iterator member_witerator
Definition: Group.h:234
void SetBattlegroundGroup(Battleground *bg)
Definition: Group.cpp:1750
void UpdatePlayerOutOfRange(Player *player)
Definition: Group.cpp:949
LootMethod GetLootMethod() const
Definition: Group.cpp:1673
void UpdateLooterGuid(WorldObject *pLootedObject, bool ifneed=false)
Definition: Group.cpp:1136
CountdownInfo const * GetCountdownInfo(CountdownTimerType timerType) const
Definition: Group.cpp:1437
bool RemoveMember(ObjectGuid guid, RemoveMethod method=GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker=ObjectGuid::Empty, const char *reason=nullptr)
Definition: Group.cpp:570
bool m_readyCheckStarted
Definition: Group.h:453
Player * GetInvited(ObjectGuid guid) const
Definition: Group.cpp:406
bool HasFreeSlotSubGroup(uint8 subgroup) const
Definition: Group.cpp:1737
bool isBFGroup() const
Definition: Group.cpp:1648
void LoadMemberFromDB(ObjectGuid::LowType guidLow, uint8 memberFlags, uint8 subgroup, uint8 roles)
Definition: Group.cpp:250
bool IsMember(ObjectGuid guid) const
Definition: Group.cpp:1695
GroupReference * GetFirstMember()
Definition: Group.h:325
void UpdateReadyCheck(uint32 diff)
Definition: Group.cpp:1484
LootMethod m_lootMethod
Definition: Group.h:440
Difficulty GetDungeonDifficultyID() const
Definition: Group.h:351
void BroadcastPacket(WorldPacket const *packet, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignoredPlayer=ObjectGuid::Empty) const
Definition: Group.cpp:980
void SelectNewPartyOrRaidLeader()
Definition: Group.cpp:105
bool SameSubGroup(ObjectGuid guid1, ObjectGuid guid2) const
Definition: Group.cpp:1721
void LinkOwnedInstance(GroupInstanceReference *ref)
Definition: Group.cpp:1400
ObjectGuid m_guid
Definition: Group.h:447
bool AddInvite(Player *player)
Definition: Group.cpp:356
void ConvertToGroup()
Definition: Group.cpp:325
void SetRestrictPingsToAssistants(bool restrictPingsToAssistants)
Definition: Group.cpp:1915
uint8 * m_subGroupsCounts
Definition: Group.h:446
Difficulty GetDifficultyID(MapEntry const *mapEntry) const
Definition: Group.cpp:1358
MemberSlotList::const_iterator member_citerator
Definition: Group.h:211
void SetMemberReadyChecked(MemberSlot *slot)
Definition: Group.cpp:1573
void SubGroupCounterIncrease(uint8 subgroup)
Definition: Group.cpp:1849
void SetTargetIcon(uint8 symbol, ObjectGuid target, ObjectGuid changedBy)
Definition: Group.cpp:800
bool Create(Player *leader)
Definition: Group.cpp:141
bool IsFull() const
Definition: Group.cpp:1628
ObjectGuid GetLeaderGUID() const
Definition: Group.cpp:1658
Difficulty m_dungeonDifficulty
Definition: Group.h:434
uint8 GetMemberFlags(ObjectGuid guid) const
Definition: Group.cpp:1713
Difficulty GetLegacyRaidDifficultyID() const
Definition: Group.h:353
~Group()
Definition: Group.cpp:73
void SetLooterGuid(ObjectGuid guid)
Definition: Group.cpp:1450
void LinkMember(GroupReference *pRef)
Definition: Group.cpp:1801
ItemQualities m_lootThreshold
Definition: Group.h:441
bool isRaidGroup() const
Definition: Group.cpp:1638
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(BattlegroundTemplate const *bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid &errorGuid) const
Definition: Group.cpp:1198
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag)
Definition: Group.cpp:1861
GroupInstanceRefManager m_ownedInstancesMgr
Definition: Group.h:445
void SendUpdateDestroyGroupToPlayer(Player *player) const
Definition: Group.cpp:937
GroupFlags m_groupFlags
Definition: Group.h:432
void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional< time_t > startTime={ })
Definition: Group.cpp:1426
InstanceResetResult Reset(InstanceResetMethod method)
Definition: Map.cpp:3035
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:3228
InstanceMap * ToInstanceMap()
Definition: Map.h:454
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
bool IsEmpty() const
Definition: ObjectGuid.h:319
uint64 LowType
Definition: ObjectGuid.h:278
void Clear()
Definition: ObjectGuid.h:286
bool IsInWorld() const
Definition: Object.h:154
void BuildValuesUpdateBlockForPlayerWithFlag(UpdateData *data, UF::UpdateFieldFlag flags, Player const *target) const
Definition: Object.cpp:206
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
Definition: Pet.h:40
bool HaveAtClient(Object const *u) const
Definition: Player.cpp:23726
bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25025
bool m_InstanceValid
Definition: Player.h:2571
void SetOriginalGroup(Group *group, int8 subgroup=-1)
Definition: Player.cpp:26009
void SetPlayerFlag(PlayerFlags flags)
Definition: Player.h:2738
void SetPartyType(GroupCategory category, uint8 type)
Definition: Player.cpp:26022
int32 NextGroupUpdateSequenceNumber(GroupCategory category)
Definition: Player.cpp:26039
void SetGroupUpdateFlag(uint32 flag)
Definition: Player.h:2614
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
void SendResetInstanceFailed(ResetFailedReason reason, uint32 mapID) const
Definition: Player.cpp:21385
void SetGroup(Group *group, int8 subgroup=-1)
Definition: Player.cpp:24188
void SendDungeonDifficulty(int32 forcedDifficulty=-1) const
Definition: Player.cpp:21319
void SetGroupInvite(Group *group)
Definition: Player.h:2605
void RemoveFromBattlegroundOrBattlefieldRaid()
Definition: Player.cpp:25997
void SetRaidDifficultyID(Difficulty raid_difficulty)
Definition: Player.h:2016
Group * GetOriginalGroup() const
Definition: Player.h:2625
bool CanRewardQuest(Quest const *quest, bool msg) const
Definition: Player.cpp:14717
void UpdateVisibleObjectInteractions(bool allUnits, bool onlySpellClicks, bool gameObjectQuestGiverStatus, bool questObjectiveGameObjects)
Definition: Player.cpp:25205
Pet * GetPet() const
Definition: Player.cpp:21513
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition: Player.cpp:25673
bool IsDeserter() const
Definition: Player.h:2402
bool InBattlegroundQueue(bool ignoreArena=false) const
Definition: Player.cpp:24992
WorldSession * GetSession() const
Definition: Player.h:2101
void ResetGroupUpdateSequenceIfNeeded(Group const *group)
Definition: Player.cpp:26028
Difficulty GetDungeonDifficultyID() const
Definition: Player.h:2012
void SetLegacyRaidDifficultyID(Difficulty raid_difficulty)
Definition: Player.h:2017
bool CanJoinToBattleground(BattlegroundTemplate const *bg) const
Definition: Player.cpp:23638
bool HasFreeBattlegroundQueueId() const
Definition: Player.cpp:25053
bool IsGameMaster() const
Definition: Player.h:1178
static Difficulty CheckLoadedLegacyRaidDifficultyID(Difficulty difficulty)
Definition: Player.cpp:29682
static uint8 GetFactionGroupForRace(uint8 race)
Definition: Player.cpp:6480
void SetDungeonDifficultyID(Difficulty dungeon_difficulty)
Definition: Player.h:2015
bool CheckInstanceValidity(bool)
Definition: Player.cpp:19821
Difficulty GetRaidDifficultyID() const
Definition: Player.h:2013
void SendResetInstanceSuccess(uint32 MapId) const
Definition: Player.cpp:21378
static Difficulty CheckLoadedRaidDifficultyID(Difficulty difficulty)
Definition: Player.cpp:29667
void SendRaidDifficulty(bool legacy, int32 forcedDifficulty=-1) const
Definition: Player.cpp:21326
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2606
uint8 GetSubGroup() const
Definition: Player.h:2612
void FailCriteria(CriteriaFailEvent condition, int32 failAsset)
Definition: Player.cpp:26761
Group * GetGroupInvite() const
Definition: Player.h:2604
static Difficulty CheckLoadedDungeonDifficultyID(Difficulty difficulty)
Definition: Player.cpp:29652
uint32 GetArenaTeamId(uint8) const
Definition: Player.h:2004
Difficulty GetLegacyRaidDifficultyID() const
Definition: Player.h:2014
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition: Player.cpp:25987
Team GetTeam() const
Definition: Player.h:2235
bool isUsingLfg() const
Definition: Player.cpp:25971
void setUInt8(const uint8 index, const uint8 value)
void setBinary(const uint8 index, const std::vector< uint8 > &value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt16(const uint8 index, const uint16 value)
void setUInt64(const uint8 index, const uint64 value)
void unlink()
Definition: Reference.h:61
FROM * GetSource() const
Definition: Reference.h:96
UF::UpdateField< UF::UnitData, 0, TYPEID_UNIT > m_unitData
Definition: Unit.h:1814
uint8 GetClass() const
Definition: Unit.h:752
bool IsAlive() const
Definition: Unit.h:1164
void RemoveAllGroupBuffsFromCaster(ObjectGuid casterGUID)
Definition: Unit.cpp:4419
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
uint8 GetLevel() const
Definition: Unit.h:746
uint8 GetRace() const
Definition: Unit.h:749
bool HasData() const
Definition: UpdateData.h:52
bool BuildPacket(WorldPacket *packet)
Definition: UpdateData.cpp:40
constexpr uint32 GetMapId() const
Definition: Position.h:201
Map * GetMap() const
Definition: Object.h:624
float GetSightRange(WorldObject const *target=nullptr) const
Definition: Object.cpp:1457
std::string const & GetName() const
Definition: Object.h:555
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition: Object.cpp:1142
bool IsInMap(WorldObject const *obj) const
Definition: Object.cpp:1115
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:567
Optional< PartyDifficultySettings > DifficultySettings
Definition: PartyPackets.h:568
std::vector< PartyPlayerInfo > PlayerList
Definition: PartyPackets.h:564
WorldPacket const * Write() override
Optional< PartyLFGInfo > LfgInfos
Definition: PartyPackets.h:566
WorldPacket const * Write() override
std::vector< RaidMarker const * > RaidMarkers
Definition: PartyPackets.h:626
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPackets::Duration< Milliseconds > Duration
Definition: PartyPackets.h:416
std::map< uint8, ObjectGuid > TargetIcons
Definition: PartyPackets.h:349
WorldPacket const * Write() override
Player session in the World.
Definition: WorldSession.h:963
bool PlayerLogout() const
Definition: WorldSession.h:970
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
BattlemasterListEntry const * BattlemasterEntry
std::array< int16, 16 > MapID
Definition: DB2Structure.h:517
ObjectGuid guid
Definition: Group.h:201
uint8 _class
Definition: Group.h:204
std::string name
Definition: Group.h:202
bool readyChecked
Definition: Group.h:208
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< uint8, 64, 83 > PvpFlags
Definition: UpdateFields.h:347
UpdateField< int32, 32, 43 > FactionTemplate
Definition: UpdateFields.h:304
Reward info.
Definition: LFGMgr.h:234