TrinityCore
Loading...
Searching...
No Matches
LFGMgr.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 "LFGMgr.h"
19#include "Common.h"
20#include "DatabaseEnv.h"
21#include "DBCStores.h"
22#include "DisableMgr.h"
23#include "GameEventMgr.h"
24#include "GameTime.h"
25#include "Group.h"
26#include "GroupMgr.h"
27#include "InstanceSaveMgr.h"
28#include "LFGGroupData.h"
29#include "LFGPlayerData.h"
30#include "LFGScripts.h"
31#include "LFGQueue.h"
32#include "Log.h"
33#include "Map.h"
34#include "MapUtils.h"
35#include "ObjectAccessor.h"
36#include "ObjectMgr.h"
37#include "Player.h"
38#include "RBAC.h"
39#include "SharedDefines.h"
40#include "SocialMgr.h"
41#include "World.h"
42#include "WorldSession.h"
43
44namespace lfg
45{
46
47LFGDungeonData::LFGDungeonData() : id(0), name(), map(0), type(0), expansion(0), group(0), minlevel(),
48 maxlevel(), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
49{
50}
51
52LFGDungeonData::LFGDungeonData(LFGDungeonEntry const* dbc) : id(dbc->ID), name(dbc->Name[0]), map(dbc->MapID),
53 type(dbc->TypeID), expansion(uint8(dbc->ExpansionLevel)), group(uint8(dbc->GroupID)),
54 minlevel({ uint8(dbc->MinLevel), uint8(dbc->MinLevel), uint8(dbc->MinLevel) }),
55 maxlevel({ uint8(dbc->MaxLevel), uint8(dbc->MaxLevel), uint8(dbc->MaxLevel) }),
56 difficulty(Difficulty(dbc->Difficulty)), seasonal((dbc->Flags & LFG_FLAG_SEASONAL) != 0), x(0.0f), y(0.0f), z(0.0f), o(0.0f)
57{
58}
59
60LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1),
61 m_options(sWorld->getIntConfig(CONFIG_LFG_OPTIONSMASK))
62{
63}
64
66{
67 for (LfgRewardContainer::iterator itr = RewardMapStore.begin(); itr != RewardMapStore.end(); ++itr)
68 delete itr->second;
69}
70
72{
73 if (!fields)
74 return;
75
76 if (!guid.IsGroup())
77 return;
78
79 SetLeader(guid, ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt32()));
80
81 uint32 dungeon = fields[17].GetUInt32();
82 uint8 state = fields[18].GetUInt8();
83
84 if (!dungeon || !state)
85 return;
86
87 SetDungeon(guid, dungeon);
88
89 switch (state)
90 {
93 SetState(guid, (LfgState)state);
94 break;
95 default:
96 break;
97 }
98}
99
101{
102 if (!guid.IsGroup())
103 return;
104
105 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
106
108 stmt->setUInt32(0, db_guid);
109 trans->Append(stmt);
110
111 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LFG_DATA);
112 stmt->setUInt32(0, db_guid);
113 stmt->setUInt32(1, GetDungeon(guid));
114 stmt->setUInt32(2, GetState(guid));
115 trans->Append(stmt);
116
117 CharacterDatabase.CommitTransaction(trans);
118}
119
122{
123 uint32 oldMSTime = getMSTime();
124
125 for (LfgRewardContainer::iterator itr = RewardMapStore.begin(); itr != RewardMapStore.end(); ++itr)
126 delete itr->second;
127 RewardMapStore.clear();
128
129 // ORDER BY is very important for GetRandomDungeonReward!
130 QueryResult result = WorldDatabase.Query("SELECT dungeonId, maxLevel, firstQuestId, otherQuestId FROM lfg_dungeon_rewards ORDER BY dungeonId, maxLevel ASC");
131
132 if (!result)
133 {
134 TC_LOG_INFO("server.loading", ">> Loaded 0 lfg dungeon rewards. DB table `lfg_dungeon_rewards` is empty!");
135 return;
136 }
137
138 uint32 count = 0;
139
140 Field* fields = nullptr;
141 do
142 {
143 fields = result->Fetch();
144 uint32 dungeonId = fields[0].GetUInt32();
145 uint32 maxLevel = fields[1].GetUInt8();
146 uint32 firstQuestId = fields[2].GetUInt32();
147 uint32 otherQuestId = fields[3].GetUInt32();
148
149 if (!GetLFGDungeonEntry(dungeonId))
150 {
151 TC_LOG_ERROR("sql.sql", "Dungeon {} specified in table `lfg_dungeon_rewards` does not exist!", dungeonId);
152 continue;
153 }
154
155 if (!maxLevel || maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
156 {
157 TC_LOG_ERROR("sql.sql", "Level {} specified for dungeon {} in table `lfg_dungeon_rewards` can never be reached!", maxLevel, dungeonId);
158 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
159 }
160
161 if (!firstQuestId || !sObjectMgr->GetQuestTemplate(firstQuestId))
162 {
163 TC_LOG_ERROR("sql.sql", "First quest {} specified for dungeon {} in table `lfg_dungeon_rewards` does not exist!", firstQuestId, dungeonId);
164 continue;
165 }
166
167 if (otherQuestId && !sObjectMgr->GetQuestTemplate(otherQuestId))
168 {
169 TC_LOG_ERROR("sql.sql", "Other quest {} specified for dungeon {} in table `lfg_dungeon_rewards` does not exist!", otherQuestId, dungeonId);
170 otherQuestId = 0;
171 }
172
173 RewardMapStore.insert(LfgRewardContainer::value_type(dungeonId, new LfgReward(maxLevel, firstQuestId, otherQuestId)));
174 ++count;
175 }
176 while (result->NextRow());
177
178 TC_LOG_INFO("server.loading", ">> Loaded {} lfg dungeon rewards in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
179}
180
182{
183 LFGDungeonContainer::const_iterator itr = LfgDungeonStore.find(id);
184 if (itr != LfgDungeonStore.end())
185 return &(itr->second);
186
187 return nullptr;
188}
189
191{
192 uint32 oldMSTime = getMSTime();
193
194 LfgDungeonStore.clear();
195
196 // Initialize Dungeon map with data from dbcs
197 for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
198 {
199 LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i);
200 if (!dungeon)
201 continue;
202
203 switch (dungeon->TypeID)
204 {
205 case LFG_TYPE_DUNGEON:
206 case LFG_TYPE_HEROIC:
207 case LFG_TYPE_RAID:
208 case LFG_TYPE_RANDOM:
209 LfgDungeonStore[dungeon->ID] = LFGDungeonData(dungeon);
210 break;
211 }
212 }
213
214 for (LFGDungeonExpansionEntry const* dungeonExpansion : sLFGDungeonExpansionStore)
215 {
216 if (LFGDungeonData* dungeon = Trinity::Containers::MapGetValuePtr(LfgDungeonStore, dungeonExpansion->LfgID))
217 {
218 dungeon->minlevel[dungeonExpansion->ExpansionLevel] = dungeonExpansion->HardLevelMin;
219 dungeon->maxlevel[dungeonExpansion->ExpansionLevel] = dungeonExpansion->HardLevelMax;
220 }
221 }
222
223 // Fill teleport locations from DB
224 // 0 1 2 3 4
225 QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_dungeon_template");
226 if (!result)
227 {
228 TC_LOG_INFO("server.loading", ">> Loaded 0 lfg dungeon templates. DB table `lfg_dungeon_template` is empty!");
229 return;
230 }
231
232 uint32 count = 0;
233
234 do
235 {
236 Field* fields = result->Fetch();
237 uint32 dungeonId = fields[0].GetUInt32();
238 LFGDungeonContainer::iterator dungeonItr = LfgDungeonStore.find(dungeonId);
239 if (dungeonItr == LfgDungeonStore.end())
240 {
241 TC_LOG_ERROR("sql.sql", "table `lfg_dungeon_template` contains coordinates for wrong dungeon {}", dungeonId);
242 continue;
243 }
244
245 LFGDungeonData& data = dungeonItr->second;
246 data.x = fields[1].GetFloat();
247 data.y = fields[2].GetFloat();
248 data.z = fields[3].GetFloat();
249 data.o = fields[4].GetFloat();
250
251 ++count;
252 }
253 while (result->NextRow());
254
255 TC_LOG_INFO("server.loading", ">> Loaded {} lfg dungeon templates in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
256
257 CachedDungeonMapStore.clear();
258
259 // Fill all other teleport coords from areatriggers
260 for (LFGDungeonContainer::iterator itr = LfgDungeonStore.begin(); itr != LfgDungeonStore.end(); ++itr)
261 {
262 LFGDungeonData& dungeon = itr->second;
263
264 // No teleport coords in database, load from areatriggers
265 if (dungeon.type != LFG_TYPE_RANDOM && dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f)
266 {
267 AreaTriggerTeleport const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map);
268 if (!at)
269 {
270 TC_LOG_ERROR("sql.sql", "Failed to load dungeon {} (Id: {}), cant find areatrigger for map {}", dungeon.name, dungeon.id, dungeon.map);
271 continue;
272 }
273
274 dungeon.map = at->target_mapId;
275 dungeon.x = at->target_X;
276 dungeon.y = at->target_Y;
277 dungeon.z = at->target_Z;
278 dungeon.o = at->target_Orientation;
279 }
280
281 if (dungeon.type != LFG_TYPE_RANDOM)
282 CachedDungeonMapStore[dungeon.group].insert(dungeon.id);
283 CachedDungeonMapStore[0].insert(dungeon.id);
284 }
285}
286
288{
289 static LFGMgr instance;
290 return &instance;
291}
292
294{
296 return;
297
298 time_t currTime = GameTime::GetGameTime();
299
300 // Remove obsolete role checks
301 for (LfgRoleCheckContainer::iterator it = RoleChecksStore.begin(); it != RoleChecksStore.end();)
302 {
303 LfgRoleCheckContainer::iterator itRoleCheck = it++;
304 LfgRoleCheck& roleCheck = itRoleCheck->second;
305 if (currTime < roleCheck.cancelTime)
306 continue;
308
309 for (LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin(); itRoles != roleCheck.roles.end(); ++itRoles)
310 {
311 ObjectGuid guid = itRoles->first;
312 RestoreState(guid, "Remove Obsolete RoleCheck");
313 SendLfgRoleCheckUpdate(guid, roleCheck);
314 if (guid == roleCheck.leader)
316 }
317
318 RestoreState(itRoleCheck->first, "Remove Obsolete RoleCheck");
319 RoleChecksStore.erase(itRoleCheck);
320 }
321
322 // Remove obsolete proposals
323 for (LfgProposalContainer::iterator it = ProposalsStore.begin(); it != ProposalsStore.end();)
324 {
325 LfgProposalContainer::iterator itRemove = it++;
326 if (itRemove->second.cancelTime < currTime)
328 }
329
330 // Remove obsolete kicks
331 for (LfgPlayerBootContainer::iterator it = BootsStore.begin(); it != BootsStore.end();)
332 {
333 LfgPlayerBootContainer::iterator itBoot = it++;
334 LfgPlayerBoot& boot = itBoot->second;
335 if (boot.cancelTime < currTime)
336 {
337 boot.inProgress = false;
338 for (LfgAnswerContainer::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes)
339 {
340 ObjectGuid pguid = itVotes->first;
341 if (pguid != boot.victim)
342 SendLfgBootProposalUpdate(pguid, boot);
343 }
344 SetVoteKick(itBoot->first, false);
345 BootsStore.erase(itBoot);
346 }
347 }
348
349 uint32 lastProposalId = m_lfgProposalId;
350 // Check if a proposal can be formed with the new groups being added
351 for (LfgQueueContainer::iterator it = QueuesStore.begin(); it != QueuesStore.end(); ++it)
352 if (uint8 newProposals = it->second.FindGroups())
353 TC_LOG_DEBUG("lfg.update", "Found {} new groups in queue {}", newProposals, it->first);
354
355 if (lastProposalId != m_lfgProposalId)
356 {
357 // FIXME lastProposalId ? lastProposalId +1 ?
358 for (LfgProposalContainer::const_iterator itProposal = ProposalsStore.find(m_lfgProposalId); itProposal != ProposalsStore.end(); ++itProposal)
359 {
360 uint32 proposalId = itProposal->first;
361 LfgProposal& proposal = ProposalsStore[proposalId];
362
363 ObjectGuid guid;
364 for (LfgProposalPlayerContainer::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers)
365 {
366 guid = itPlayers->first;
368 ObjectGuid gguid = GetGroup(guid);
369 if (!gguid.IsEmpty())
370 {
373 }
374 else
376 SendLfgUpdateProposal(guid, proposal);
377 }
378
379 if (proposal.state == LFG_PROPOSAL_SUCCESS)
380 UpdateProposal(proposalId, guid, true);
381 }
382 }
383
384 // Update all players status queue info
386 {
387 m_QueueTimer = 0;
388 for (LfgQueueContainer::iterator it = QueuesStore.begin(); it != QueuesStore.end(); ++it)
389 it->second.UpdateQueueTimers(currTime);
390 }
391 else
392 m_QueueTimer += diff;
393}
394
405void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const std::string& comment)
406{
407 if (!player || !player->GetSession() || dungeons.empty())
408 return;
409
410 // Sanitize input roles
411 roles &= PLAYER_ROLE_ANY;
412 roles = FilterClassRoles(player, roles);
413
414 // At least 1 role must be selected
416 return;
417
418 Group* grp = player->GetGroup();
419 ObjectGuid guid = player->GetGUID();
420 ObjectGuid gguid = grp ? grp->GetGUID() : guid;
421 LfgJoinResultData joinData;
422 GuidSet players;
423 uint32 rDungeonId = 0;
424 bool isContinue = grp && grp->isLFGGroup() && GetState(gguid) != LFG_STATE_FINISHED_DUNGEON;
425
426 // Do not allow to change dungeon in the middle of a current dungeon
427 if (isContinue)
428 {
429 dungeons.clear();
430 dungeons.insert(GetDungeon(gguid));
431 }
432
433 // Already in queue?
434 LfgState state = GetState(gguid);
435 if (state == LFG_STATE_QUEUED)
436 {
437 LFGQueue& queue = GetQueue(gguid);
438 queue.RemoveFromQueue(gguid);
439 }
440
441 // Check player or group member restrictions
444 else if (player->InBattleground() || player->InArena() || player->InBattlegroundQueue())
446 else if (player->HasAura(LFG_SPELL_DUNGEON_DESERTER))
447 joinData.result = LFG_JOIN_DESERTER;
448 else if (!isContinue && player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
450 else if (dungeons.empty())
452 else if (player->HasAura(9454)) // check Freeze debuff
454 else if (grp)
455 {
456 if (grp->GetMembersCount() > MAX_GROUP_SIZE)
458 else
459 {
460 uint8 memberCount = 0;
461 for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr && joinData.result == LFG_JOIN_OK; itr = itr->next())
462 {
463 if (Player* plrg = itr->GetSource())
464 {
465 if (!plrg->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER))
467 if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER))
469 else if (!isContinue && plrg->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
471 else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue())
473 else if (plrg->HasAura(9454)) // check Freeze debuff
475 ++memberCount;
476 players.insert(plrg->GetGUID());
477 }
478 }
479
480 if (joinData.result == LFG_JOIN_OK && memberCount != grp->GetMembersCount())
481 joinData.result = LFG_JOIN_DISCONNECTED;
482 }
483 }
484 else
485 players.insert(player->GetGUID());
486
487 // Check if all dungeons are valid
488 bool isRaid = false;
489 if (joinData.result == LFG_JOIN_OK)
490 {
491 bool isDungeon = false;
492 for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end() && joinData.result == LFG_JOIN_OK; ++it)
493 {
494 LfgType type = GetDungeonType(*it);
495 switch (type)
496 {
497 case LFG_TYPE_RANDOM:
498 if (dungeons.size() > 1) // Only allow 1 random dungeon
500 else
501 rDungeonId = (*dungeons.begin());
502 [[fallthrough]]; // Random can only be dungeon or heroic dungeon
503 case LFG_TYPE_HEROIC:
504 case LFG_TYPE_DUNGEON:
505 if (isRaid)
507 isDungeon = true;
508 break;
509 case LFG_TYPE_RAID:
510 if (isDungeon)
512 isRaid = true;
513 break;
514 default:
516 break;
517 }
518 }
519
520 // it could be changed
521 if (joinData.result == LFG_JOIN_OK)
522 {
523 // Expand random dungeons and check restrictions
524 if (rDungeonId)
525 dungeons = GetDungeonsByRandom(rDungeonId);
526
527 // if we have lockmap then there are no compatible dungeons
528 GetCompatibleDungeons(dungeons, players, joinData.lockmap, isContinue);
529 if (dungeons.empty())
531 }
532 }
533
534 // Can't join. Send result
535 if (joinData.result != LFG_JOIN_OK)
536 {
537 TC_LOG_DEBUG("lfg.join", "{} joining with {} members. Result: {}, Dungeons: {}",
538 guid.ToString(), grp ? grp->GetMembersCount() : 1, joinData.result, ConcatenateDungeons(dungeons));
539
540 if (!dungeons.empty()) // Only should show lockmap when have no dungeons available
541 joinData.lockmap.clear();
542 player->GetSession()->SendLfgJoinResult(joinData);
543 return;
544 }
545
546 SetComment(guid, comment);
547
548 if (isRaid)
549 {
550 TC_LOG_DEBUG("lfg.join", "{} trying to join raid browser and it's disabled.", guid.ToString());
551 return;
552 }
553
554 std::string debugNames = "";
555 if (grp) // Begin rolecheck
556 {
557 // Create new rolecheck
558 LfgRoleCheck& roleCheck = RoleChecksStore[gguid];
561 roleCheck.leader = guid;
562 roleCheck.dungeons = dungeons;
563 roleCheck.rDungeonId = rDungeonId;
564
565 if (rDungeonId)
566 {
567 dungeons.clear();
568 dungeons.insert(rDungeonId);
569 }
570
572 // Send update to player
573 LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment);
574 for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
575 {
576 if (Player* plrg = itr->GetSource())
577 {
578 ObjectGuid pguid = plrg->GetGUID();
579 plrg->GetSession()->SendLfgUpdateParty(updateData);
581 if (!isContinue)
582 SetSelectedDungeons(pguid, dungeons);
583 roleCheck.roles[pguid] = 0;
584 if (!debugNames.empty())
585 debugNames.append(", ");
586 debugNames.append(plrg->GetName());
587 }
588 }
589 // Update leader role
590 UpdateRoleCheck(gguid, guid, roles);
591 }
592 else // Add player to queue
593 {
594 LfgRolesMap rolesMap;
595 rolesMap[guid] = roles;
596 LFGQueue& queue = GetQueue(guid);
597 queue.AddQueueData(guid, GameTime::GetGameTime(), dungeons, rolesMap);
598
599 if (!isContinue)
600 {
601 if (rDungeonId)
602 {
603 dungeons.clear();
604 dungeons.insert(rDungeonId);
605 }
606 SetSelectedDungeons(guid, dungeons);
607 }
608 // Send update to player
609 player->GetSession()->SendLfgJoinResult(joinData);
612 SetRoles(guid, roles);
613 debugNames.append(player->GetName());
614 }
615
616 TC_LOG_DEBUG("lfg.join", "{} joined ({}), Members: {}. Dungeons ({}): {}", guid.ToString(),
617 grp ? "group" : "player", debugNames, uint32(dungeons.size()), ConcatenateDungeons(dungeons));
618}
619
626void LFGMgr::LeaveLfg(ObjectGuid guid, bool disconnected)
627{
628 ObjectGuid gguid = guid.IsGroup() ? guid : GetGroup(guid);
629
630 TC_LOG_DEBUG("lfg.leave", "{} left ({})", guid.ToString(), guid == gguid ? "group" : "player");
631
632 LfgState state = GetState(guid);
633 switch (state)
634 {
635 case LFG_STATE_QUEUED:
636 if (!gguid.IsEmpty())
637 {
638 LfgState newState = LFG_STATE_NONE;
639 LfgState oldState = GetOldState(gguid);
640
641 // Set the new state to LFG_STATE_DUNGEON/LFG_STATE_FINISHED_DUNGEON if the group is already in a dungeon
642 // This is required in case a LFG group vote-kicks a player in a dungeon, queues, then leaves the queue (maybe to queue later again)
643 if (Group* group = sGroupMgr->GetGroupByGUID(gguid))
644 if (group->isLFGGroup() && GetDungeon(gguid) && (oldState == LFG_STATE_DUNGEON || oldState == LFG_STATE_FINISHED_DUNGEON))
645 newState = oldState;
646
647 LFGQueue& queue = GetQueue(gguid);
648 queue.RemoveFromQueue(gguid);
649 SetState(gguid, newState);
650 GuidSet const& players = GetPlayers(gguid);
651 for (GuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
652 {
653 SetState(*it, newState);
655 }
656 }
657 else
658 {
659 LFGQueue& queue = GetQueue(guid);
660 queue.RemoveFromQueue(guid);
663 }
664 break;
666 if (!gguid.IsEmpty())
667 UpdateRoleCheck(gguid); // No player to update role = LFG_ROLECHECK_ABORTED
668 break;
670 {
671 // Remove from Proposals
672 LfgProposalContainer::iterator it = ProposalsStore.begin();
673 ObjectGuid pguid = gguid == guid ? GetLeader(gguid) : guid;
674 while (it != ProposalsStore.end())
675 {
676 LfgProposalPlayerContainer::iterator itPlayer = it->second.players.find(pguid);
677 if (itPlayer != it->second.players.end())
678 {
679 // Mark the player/leader of group who left as didn't accept the proposal
680 itPlayer->second.accept = LFG_ANSWER_DENY;
681 break;
682 }
683 ++it;
684 }
685
686 // Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
687 if (it != ProposalsStore.end())
689 break;
690 }
691 case LFG_STATE_NONE:
693 break;
696 if (guid != gguid && !disconnected) // Player
698 break;
699 }
700}
701
709void LFGMgr::UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid /* = ObjectGuid::Empty */, uint8 roles /* = PLAYER_ROLE_NONE */)
710{
711 if (!gguid)
712 return;
713
714 LfgRolesMap check_roles;
715 LfgRoleCheckContainer::iterator itRoleCheck = RoleChecksStore.find(gguid);
716 if (itRoleCheck == RoleChecksStore.end())
717 return;
718
719 // Sanitize input roles
720 roles &= PLAYER_ROLE_ANY;
721
722 if (!guid.IsEmpty())
723 {
724 if (Player* player = ObjectAccessor::FindPlayer(guid))
725 roles = FilterClassRoles(player, roles);
726 else
727 return;
728 }
729
730 LfgRoleCheck& roleCheck = itRoleCheck->second;
731 bool sendRoleChosen = roleCheck.state != LFG_ROLECHECK_DEFAULT && !guid.IsEmpty();
732
733 if (!guid)
734 roleCheck.state = LFG_ROLECHECK_ABORTED;
735 else if (roles < PLAYER_ROLE_TANK) // Player selected no role.
736 roleCheck.state = LFG_ROLECHECK_NO_ROLE;
737 else
738 {
739 roleCheck.roles[guid] = roles;
740
741 // Check if all players have selected a role
742 LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin();
743 while (itRoles != roleCheck.roles.end() && itRoles->second != PLAYER_ROLE_NONE)
744 ++itRoles;
745
746 if (itRoles == roleCheck.roles.end())
747 {
748 // use temporal var to check roles, CheckGroupRoles modifies the roles
749 check_roles = roleCheck.roles;
751 }
752 }
753
754 LfgDungeonSet dungeons;
755 if (roleCheck.rDungeonId)
756 dungeons.insert(roleCheck.rDungeonId);
757 else
758 dungeons = roleCheck.dungeons;
759
761 for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it)
762 {
763 ObjectGuid pguid = it->first;
764
765 if (sendRoleChosen)
766 SendLfgRoleChosen(pguid, guid, roles);
767
768 SendLfgRoleCheckUpdate(pguid, roleCheck);
769 switch (roleCheck.state)
770 {
772 continue;
775 SetRoles(pguid, it->second);
777 break;
778 default:
779 if (roleCheck.leader == pguid)
780 SendLfgJoinResult(pguid, joinData);
782 RestoreState(pguid, "Rolecheck Failed");
783 break;
784 }
785 }
786
787 if (roleCheck.state == LFG_ROLECHECK_FINISHED)
788 {
790 LFGQueue& queue = GetQueue(gguid);
791 queue.AddQueueData(gguid, GameTime::GetGameTime(), roleCheck.dungeons, roleCheck.roles);
792 RoleChecksStore.erase(itRoleCheck);
793 }
794 else if (roleCheck.state != LFG_ROLECHECK_INITIALITING)
795 {
796 RestoreState(gguid, "Rolecheck Failed");
797 RoleChecksStore.erase(itRoleCheck);
798 }
799}
800
808void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue)
809{
810 lockMap.clear();
811
812 std::map<uint32, uint32> lockedDungeons;
813
814 for (GuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it)
815 {
816 ObjectGuid guid = (*it);
817 LfgLockMap const& cachedLockMap = GetLockedDungeons(guid);
819 for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2)
820 {
821 uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids
822 LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId);
823 if (itDungeon != dungeons.end())
824 {
825 bool eraseDungeon = true;
826
827 // Don't remove the dungeon if team members are trying to continue a locked instance
828 if (it2->second == LFG_LOCKSTATUS_RAID_LOCKED && isContinue)
829 {
830 LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
831 ASSERT(dungeon);
832 ASSERT(player);
833 if (InstancePlayerBind* playerBind = player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty)))
834 {
835 if (InstanceSave* playerSave = playerBind->save)
836 {
837 uint32 dungeonInstanceId = playerSave->GetInstanceId();
838 auto itLockedDungeon = lockedDungeons.find(dungeonId);
839 if (itLockedDungeon == lockedDungeons.end() || itLockedDungeon->second == dungeonInstanceId)
840 eraseDungeon = false;
841
842 lockedDungeons[dungeonId] = dungeonInstanceId;
843 }
844 }
845 }
846
847 if (eraseDungeon)
848 dungeons.erase(itDungeon);
849
850 lockMap[guid][dungeonId] = it2->second;
851 }
852 }
853 }
854 if (!dungeons.empty())
855 lockMap.clear();
856}
857
865{
866 if (groles.empty())
867 return false;
868
869 uint8 damage = 0;
870 uint8 tank = 0;
871 uint8 healer = 0;
872
873 for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it)
874 {
875 uint8 role = it->second & ~PLAYER_ROLE_LEADER;
876 if (role == PLAYER_ROLE_NONE)
877 return false;
878
879 if (role & PLAYER_ROLE_DAMAGE)
880 {
881 if (role != PLAYER_ROLE_DAMAGE)
882 {
883 it->second -= PLAYER_ROLE_DAMAGE;
884 if (CheckGroupRoles(groles))
885 return true;
886 it->second += PLAYER_ROLE_DAMAGE;
887 }
888 else if (damage == LFG_DPS_NEEDED)
889 return false;
890 else
891 damage++;
892 }
893
894 if (role & PLAYER_ROLE_HEALER)
895 {
896 if (role != PLAYER_ROLE_HEALER)
897 {
898 it->second -= PLAYER_ROLE_HEALER;
899 if (CheckGroupRoles(groles))
900 return true;
901 it->second += PLAYER_ROLE_HEALER;
902 }
903 else if (healer == LFG_HEALERS_NEEDED)
904 return false;
905 else
906 healer++;
907 }
908
909 if (role & PLAYER_ROLE_TANK)
910 {
911 if (role != PLAYER_ROLE_TANK)
912 {
913 it->second -= PLAYER_ROLE_TANK;
914 if (CheckGroupRoles(groles))
915 return true;
916 it->second += PLAYER_ROLE_TANK;
917 }
918 else if (tank == LFG_TANKS_NEEDED)
919 return false;
920 else
921 tank++;
922 }
923 }
924 return (tank + healer + damage) == uint8(groles.size());
925}
926
932{
933 GuidList players, tankPlayers, healPlayers, dpsPlayers;
934 GuidList playersToTeleport;
935
936 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
937 {
938 ObjectGuid guid = it->first;
939 if (guid == proposal.leader)
940 players.push_back(guid);
941 else
942 switch (it->second.role & ~PLAYER_ROLE_LEADER)
943 {
944 case PLAYER_ROLE_TANK:
945 tankPlayers.push_back(guid);
946 break;
948 healPlayers.push_back(guid);
949 break;
951 dpsPlayers.push_back(guid);
952 break;
953 default:
954 ABORT_MSG("Invalid LFG role %u", it->second.role);
955 break;
956 }
957
958 if (proposal.isNew || GetGroup(guid) != proposal.group)
959 playersToTeleport.push_back(guid);
960 }
961
962 players.splice(players.end(), tankPlayers);
963 players.splice(players.end(), healPlayers);
964 players.splice(players.end(), dpsPlayers);
965
966 // Set the dungeon difficulty
967 LFGDungeonData const* dungeon = GetLFGDungeon(proposal.dungeonId);
968 ASSERT(dungeon);
969
970 Group* grp = !proposal.group.IsEmpty() ? sGroupMgr->GetGroupByGUID(proposal.group) : nullptr;
971 for (GuidList::const_iterator it = players.begin(); it != players.end(); ++it)
972 {
973 ObjectGuid pguid = (*it);
975 if (!player)
976 continue;
977
978 Group* group = player->GetGroup();
979 if (group && group != grp)
980 group->RemoveMember(player->GetGUID());
981
982 if (!grp)
983 {
984 grp = new Group();
985 grp->ConvertToLFG();
986 grp->Create(player);
987 ObjectGuid gguid = grp->GetGUID();
989 sGroupMgr->AddGroup(grp);
990 }
991 else if (group != grp)
992 grp->AddMember(player);
993
994 grp->SetLfgRoles(pguid, proposal.players.find(pguid)->second.role);
995
996 // Add the cooldown spell if queued for a random dungeon
997 const LfgDungeonSet& dungeons = GetSelectedDungeons(player->GetGUID());
998 if (!dungeons.empty())
999 {
1000 uint32 rDungeonId = (*dungeons.begin());
1001 LFGDungeonEntry const* dungeonEntry = sLFGDungeonStore.LookupEntry(rDungeonId);
1002 if (dungeonEntry && dungeonEntry->TypeID == LFG_TYPE_RANDOM)
1003 player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false);
1004 }
1005 }
1006
1007 ASSERT(grp);
1009 ObjectGuid gguid = grp->GetGUID();
1010 SetDungeon(gguid, dungeon->Entry());
1012
1013 _SaveToDB(gguid, grp->GetDbStoreId());
1014
1015 // Teleport Player
1016 for (GuidList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it)
1017 if (Player* player = ObjectAccessor::FindPlayer(*it))
1018 TeleportPlayer(player, false);
1019
1020 // Update group info
1021 grp->SendUpdate();
1022}
1023
1025{
1026 proposal.id = ++m_lfgProposalId;
1027 ProposalsStore[m_lfgProposalId] = proposal;
1028 return m_lfgProposalId;
1029}
1030
1038void LFGMgr::UpdateProposal(uint32 proposalId, ObjectGuid guid, bool accept)
1039{
1040 // Check if the proposal exists
1041 LfgProposalContainer::iterator itProposal = ProposalsStore.find(proposalId);
1042 if (itProposal == ProposalsStore.end())
1043 return;
1044
1045 LfgProposal& proposal = itProposal->second;
1046
1047 // Check if proposal have the current player
1048 LfgProposalPlayerContainer::iterator itProposalPlayer = proposal.players.find(guid);
1049 if (itProposalPlayer == proposal.players.end())
1050 return;
1051
1052 LfgProposalPlayer& player = itProposalPlayer->second;
1053 player.accept = LfgAnswer(accept);
1054
1055 TC_LOG_DEBUG("lfg.proposal.update", "{}, Proposal {}, Selection: {}", guid.ToString(), proposalId, accept);
1056 if (!accept)
1057 {
1059 return;
1060 }
1061
1062 // check if all have answered and reorder players (leader first)
1063 bool allAnswered = true;
1064 for (LfgProposalPlayerContainer::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers)
1065 if (itPlayers->second.accept != LFG_ANSWER_AGREE) // No answer (-1) or not accepted (0)
1066 allAnswered = false;
1067
1068 if (!allAnswered)
1069 {
1070 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1071 SendLfgUpdateProposal(it->first, proposal);
1072
1073 return;
1074 }
1075
1076 bool sendUpdate = proposal.state != LFG_PROPOSAL_SUCCESS;
1077 proposal.state = LFG_PROPOSAL_SUCCESS;
1078 time_t joinTime = GameTime::GetGameTime();
1079
1080 LFGQueue& queue = GetQueue(guid);
1082 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1083 {
1084 ObjectGuid pguid = it->first;
1085 ObjectGuid gguid = it->second.group;
1086 uint32 dungeonId = (*GetSelectedDungeons(pguid).begin());
1087 int32 waitTime = -1;
1088 if (sendUpdate)
1089 SendLfgUpdateProposal(pguid, proposal);
1090
1091 if (!gguid.IsEmpty())
1092 {
1093 waitTime = int32((joinTime - queue.GetJoinTime(gguid)) / IN_MILLISECONDS);
1094 SendLfgUpdateParty(pguid, updateData);
1095 }
1096 else
1097 {
1098 waitTime = int32((joinTime - queue.GetJoinTime(pguid)) / IN_MILLISECONDS);
1099 SendLfgUpdatePlayer(pguid, updateData);
1100 }
1102 SendLfgUpdatePlayer(pguid, updateData);
1103 SendLfgUpdateParty(pguid, updateData);
1104
1105 // Update timers
1106 uint8 role = GetRoles(pguid);
1107 role &= ~PLAYER_ROLE_LEADER;
1108 switch (role)
1109 {
1110 case PLAYER_ROLE_DAMAGE:
1111 queue.UpdateWaitTimeDps(waitTime, dungeonId);
1112 break;
1113 case PLAYER_ROLE_HEALER:
1114 queue.UpdateWaitTimeHealer(waitTime, dungeonId);
1115 break;
1116 case PLAYER_ROLE_TANK:
1117 queue.UpdateWaitTimeTank(waitTime, dungeonId);
1118 break;
1119 default:
1120 queue.UpdateWaitTimeAvg(waitTime, dungeonId);
1121 break;
1122 }
1123
1124 // Store the number of players that were present in group when joining RFD, used for achievement purposes
1125 if (Player* player = ObjectAccessor::FindConnectedPlayer(pguid))
1126 if (Group* group = player->GetGroup())
1127 PlayersStore[pguid].SetNumberOfPartyMembersAtJoin(group->GetMembersCount());
1128
1130 }
1131
1132 // Remove players/groups from Queue
1133 for (GuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it)
1134 queue.RemoveFromQueue(*it);
1135
1136 MakeNewGroup(proposal);
1137 ProposalsStore.erase(itProposal);
1138}
1139
1146void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdateType type)
1147{
1148 LfgProposal& proposal = itProposal->second;
1149 proposal.state = LFG_PROPOSAL_FAILED;
1150
1151 TC_LOG_DEBUG("lfg.proposal.remove", "Proposal {}, state FAILED, UpdateType {}", itProposal->first, type);
1152 // Mark all people that didn't answered as no accept
1154 for (LfgProposalPlayerContainer::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1155 if (it->second.accept == LFG_ANSWER_PENDING)
1156 it->second.accept = LFG_ANSWER_DENY;
1157
1158 // Mark players/groups to be removed
1159 GuidSet toRemove;
1160 for (LfgProposalPlayerContainer::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1161 {
1162 if (it->second.accept == LFG_ANSWER_AGREE)
1163 continue;
1164
1165 ObjectGuid guid = !it->second.group.IsEmpty() ? it->second.group : it->first;
1166 // Player didn't accept or still pending when no secs left
1167 if (it->second.accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED)
1168 {
1169 it->second.accept = LFG_ANSWER_DENY;
1170 toRemove.insert(guid);
1171 }
1172 }
1173
1174 // Notify players
1175 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1176 {
1177 ObjectGuid guid = it->first;
1178 ObjectGuid gguid = !it->second.group.IsEmpty() ? it->second.group : guid;
1179
1180 SendLfgUpdateProposal(guid, proposal);
1181
1182 if (toRemove.find(gguid) != toRemove.end()) // Didn't accept or in same group that someone that didn't accept
1183 {
1184 LfgUpdateData updateData;
1185 if (it->second.accept == LFG_ANSWER_DENY)
1186 {
1187 updateData.updateType = type;
1188 TC_LOG_DEBUG("lfg.proposal.remove", "{} didn't accept. Removing from queue and compatible cache", guid.ToString());
1189 }
1190 else
1191 {
1193 TC_LOG_DEBUG("lfg.proposal.remove", "{} in same group that someone that didn't accept. Removing from queue and compatible cache", guid.ToString());
1194 }
1195
1196 RestoreState(guid, "Proposal Fail (didn't accepted or in group with someone that didn't accept");
1197 if (gguid != guid)
1198 {
1199 RestoreState(it->second.group, "Proposal Fail (someone in group didn't accepted)");
1200 SendLfgUpdateParty(guid, updateData);
1201 }
1202 else
1203 SendLfgUpdatePlayer(guid, updateData);
1204 }
1205 else
1206 {
1207 TC_LOG_DEBUG("lfg.proposal.remove", "Readding {} to queue.", guid.ToString());
1209 if (gguid != guid)
1210 {
1211 SetState(gguid, LFG_STATE_QUEUED);
1213 }
1214 else
1216 }
1217 }
1218
1219 LFGQueue& queue = GetQueue(proposal.players.begin()->first);
1220 // Remove players/groups from queue
1221 for (GuidSet::const_iterator it = toRemove.begin(); it != toRemove.end(); ++it)
1222 {
1223 ObjectGuid guid = *it;
1224 queue.RemoveFromQueue(guid);
1225 proposal.queues.remove(guid);
1226 }
1227
1228 // Readd to queue
1229 for (GuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it)
1230 {
1231 ObjectGuid guid = *it;
1232 queue.AddToQueue(guid, true);
1233 }
1234
1235 ProposalsStore.erase(itProposal);
1236}
1237
1246void LFGMgr::InitBoot(ObjectGuid gguid, ObjectGuid kicker, ObjectGuid victim, std::string const& reason)
1247{
1248 SetVoteKick(gguid, true);
1249
1250 LfgPlayerBoot& boot = BootsStore[gguid];
1251 boot.inProgress = true;
1253 boot.reason = reason;
1254 boot.victim = victim;
1255
1256 GuidSet const& players = GetPlayers(gguid);
1257
1258 // Set votes
1259 for (GuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr)
1260 {
1261 ObjectGuid guid = (*itr);
1262 boot.votes[guid] = LFG_ANSWER_PENDING;
1263 }
1264
1265 boot.votes[victim] = LFG_ANSWER_DENY; // Victim auto vote NO
1266 boot.votes[kicker] = LFG_ANSWER_AGREE; // Kicker auto vote YES
1267
1268 // Notify players
1269 for (GuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
1270 SendLfgBootProposalUpdate(*it, boot);
1271}
1272
1279void LFGMgr::UpdateBoot(ObjectGuid guid, bool accept)
1280{
1281 ObjectGuid gguid = GetGroup(guid);
1282 if (!gguid)
1283 return;
1284
1285 LfgPlayerBootContainer::iterator itBoot = BootsStore.find(gguid);
1286 if (itBoot == BootsStore.end())
1287 return;
1288
1289 LfgPlayerBoot& boot = itBoot->second;
1290
1291 if (boot.votes[guid] != LFG_ANSWER_PENDING) // Cheat check: Player can't vote twice
1292 return;
1293
1294 boot.votes[guid] = LfgAnswer(accept);
1295
1296 uint8 agreeNum = 0;
1297 uint8 denyNum = 0;
1298 for (LfgAnswerContainer::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes)
1299 {
1300 switch (itVotes->second)
1301 {
1302 case LFG_ANSWER_PENDING:
1303 break;
1304 case LFG_ANSWER_AGREE:
1305 ++agreeNum;
1306 break;
1307 case LFG_ANSWER_DENY:
1308 ++denyNum;
1309 break;
1310 }
1311 }
1312
1313 // if we don't have enough votes (agree or deny) do nothing
1314 if (agreeNum < LFG_GROUP_KICK_VOTES_NEEDED && (boot.votes.size() - denyNum) >= LFG_GROUP_KICK_VOTES_NEEDED)
1315 return;
1316
1317 // Send update info to all players
1318 boot.inProgress = false;
1319 for (LfgAnswerContainer::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes)
1320 {
1321 ObjectGuid pguid = itVotes->first;
1322 if (pguid != boot.victim)
1323 SendLfgBootProposalUpdate(pguid, boot);
1324 }
1325
1326 SetVoteKick(gguid, false);
1327 if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player
1328 {
1329 if (Group* group = sGroupMgr->GetGroupByGUID(gguid))
1331 DecreaseKicksLeft(gguid);
1332 }
1333 BootsStore.erase(itBoot);
1334}
1335
1343void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*/)
1344{
1345 LFGDungeonData const* dungeon = nullptr;
1346 Group* group = player->GetGroup();
1347
1348 if (group && group->isLFGGroup())
1349 dungeon = GetLFGDungeon(GetDungeon(group->GetGUID()));
1350
1351 if (!dungeon)
1352 {
1353 TC_LOG_DEBUG("lfg.teleport", "Player {} not in group/lfggroup or dungeon not found!",
1354 player->GetName());
1356 return;
1357 }
1358
1359 if (out)
1360 {
1361 TC_LOG_DEBUG("lfg.teleport", "Player {} is being teleported out. Current Map {} - Expected Map {}",
1362 player->GetName(), player->GetMapId(), uint32(dungeon->map));
1363 if (player->GetMapId() == uint32(dungeon->map))
1364 player->TeleportToBGEntryPoint();
1365
1366 return;
1367 }
1368
1370
1371 if (!player->IsAlive())
1373 else if (player->IsFalling() || player->HasUnitState(UNIT_STATE_JUMPING))
1375 else if (player->IsMirrorTimerActive(FATIGUE_TIMER))
1377 else if (player->GetVehicle())
1379 else if (!player->GetCharmedGUID().IsEmpty())
1381 else if (player->HasAura(9454)) // check Freeze debuff
1383 else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance
1384 {
1385 uint32 mapid = dungeon->map;
1386 float x = dungeon->x;
1387 float y = dungeon->y;
1388 float z = dungeon->z;
1389 float orientation = dungeon->o;
1390
1391 if (!fromOpcode)
1392 {
1393 // Select a player inside to be teleported to
1394 for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
1395 {
1396 Player* plrg = itr->GetSource();
1397 if (plrg && plrg != player && plrg->GetMapId() == uint32(dungeon->map))
1398 {
1399 mapid = plrg->GetMapId();
1400 x = plrg->GetPositionX();
1401 y = plrg->GetPositionY();
1402 z = plrg->GetPositionZ();
1403 orientation = plrg->GetOrientation();
1404 break;
1405 }
1406 }
1407 }
1408
1409 if (!player->GetMap()->IsDungeon())
1410 player->SetBattlegroundEntryPoint();
1411
1412 player->FinishTaxiFlight();
1413
1414 if (!player->TeleportTo(mapid, x, y, z, orientation))
1416 }
1417 else
1419
1420 if (error != LFG_TELEPORTERROR_OK)
1421 player->GetSession()->SendLfgTeleportError(uint8(error));
1422
1423 TC_LOG_DEBUG("lfg.teleport", "Player {} is being teleported in to map {} "
1424 "(x: {}, y: {}, z: {}) Result: {}", player->GetName(), dungeon->map,
1425 dungeon->x, dungeon->y, dungeon->z, error);
1426}
1427
1434void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId, Map const* currMap)
1435{
1436 uint32 gDungeonId = GetDungeon(gguid);
1437 if (gDungeonId != dungeonId)
1438 {
1439 TC_LOG_DEBUG("lfg.dungeon.finish", "Group {} finished dungeon {} but queued for {}", gguid.ToString(), dungeonId, gDungeonId);
1440 return;
1441 }
1442
1443 if (GetState(gguid) == LFG_STATE_FINISHED_DUNGEON) // Shouldn't happen. Do not reward multiple times
1444 {
1445 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {} already rewarded", gguid.ToString());
1446 return;
1447 }
1448
1450
1451 GuidSet const& players = GetPlayers(gguid);
1452 for (GuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
1453 {
1454 ObjectGuid guid = (*it);
1456 {
1457 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {}, Player: {} already rewarded", gguid.ToString(), guid.ToString());
1458 continue;
1459 }
1460
1461 uint32 rDungeonId = 0;
1462 LfgDungeonSet const& dungeons = GetSelectedDungeons(guid);
1463 if (!dungeons.empty())
1464 rDungeonId = (*dungeons.begin());
1465
1467
1468 // Give rewards only if its a random dungeon
1469 LFGDungeonData const* dungeon = GetLFGDungeon(rDungeonId);
1470
1471 if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !dungeon->seasonal))
1472 {
1473 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {}, Player: {} dungeon {} is not random or seasonal", gguid.ToString(), guid.ToString(), rDungeonId);
1474 continue;
1475 }
1476
1477 Player* player = ObjectAccessor::FindPlayer(guid);
1478 if (!player)
1479 {
1480 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {}, Player: {} not found in world", gguid.ToString(), guid.ToString());
1481 continue;
1482 }
1483
1484 if (player->FindMap() != currMap)
1485 {
1486 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {}, Player: {} is in a different map", gguid.ToString(), guid.ToString());
1487 continue;
1488 }
1489
1491
1492 LFGDungeonData const* dungeonDone = GetLFGDungeon(dungeonId);
1493 uint32 mapId = dungeonDone ? uint32(dungeonDone->map) : 0;
1494
1495 if (player->GetMapId() != mapId)
1496 {
1497 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {}, Player: {} is in map {} and should be in {} to get reward", gguid.ToString(), guid.ToString(), player->GetMapId(), mapId);
1498 continue;
1499 }
1500
1501 // Update achievements
1502 if (dungeon->difficulty == DUNGEON_DIFFICULTY_HEROIC)
1503 {
1504 uint8 lfdRandomPlayers = 0;
1505 if (uint8 numParty = PlayersStore[guid].GetNumberOfPartyMembersAtJoin())
1506 lfdRandomPlayers = 5 - numParty;
1507 else
1508 lfdRandomPlayers = 4;
1510 }
1511
1512 LfgReward const* reward = GetRandomDungeonReward(rDungeonId, player->GetLevel());
1513 if (!reward)
1514 continue;
1515
1516 bool done = false;
1517 Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest);
1518 if (!quest)
1519 continue;
1520
1521 // if we can take the quest, means that we haven't done this kind of "run", IE: First Heroic Random of Day.
1522 if (player->CanRewardQuest(quest, false))
1523 player->RewardQuest(quest, 0, nullptr, false);
1524 else
1525 {
1526 done = true;
1527 quest = sObjectMgr->GetQuestTemplate(reward->otherQuest);
1528 if (!quest)
1529 continue;
1530 // we give reward without informing client (retail does this)
1531 player->RewardQuest(quest, 0, nullptr, false);
1532 }
1533
1534 // Give rewards
1535 TC_LOG_DEBUG("lfg.dungeon.finish", "Group: {}, Player: {} done dungeon {}, {} previously done.", gguid.ToString(), guid.ToString(), GetDungeon(gguid), done ? " " : " not");
1536 LfgPlayerRewardData data = LfgPlayerRewardData(dungeon->Entry(), GetDungeon(gguid, false), done, quest);
1537 player->GetSession()->SendLfgPlayerReward(data);
1538 }
1539}
1540
1541// --------------------------------------------------------------------------//
1542// Auxiliar Functions
1543// --------------------------------------------------------------------------//
1544
1552{
1553 LFGDungeonData const* dungeon = GetLFGDungeon(randomdungeon);
1554 uint32 group = dungeon ? dungeon->group : 0;
1555 return CachedDungeonMapStore[group];
1556}
1557
1566{
1567 LfgReward const* rew = nullptr;
1568 LfgRewardContainerBounds bounds = RewardMapStore.equal_range(dungeon & 0x00FFFFFF);
1569 for (LfgRewardContainer::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
1570 {
1571 rew = itr->second;
1572 // ordered properly at loading
1573 if (itr->second->maxLevel >= level)
1574 break;
1575 }
1576
1577 return rew;
1578}
1579
1587{
1588 LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
1589 if (!dungeon)
1590 return LFG_TYPE_NONE;
1591
1592 return LfgType(dungeon->type);
1593}
1594
1596{
1597 LfgState state;
1598 if (guid.IsGroup())
1599 {
1600 state = GroupsStore[guid].GetState();
1601 TC_LOG_TRACE("lfg.data.group.state.get", "Group: {}, State: {}", guid.ToString(), GetStateString(state));
1602 }
1603 else
1604 {
1605 state = PlayersStore[guid].GetState();
1606 TC_LOG_TRACE("lfg.data.player.state.get", "Player: {}, State: {}", guid.ToString(), GetStateString(state));
1607 }
1608
1609 return state;
1610}
1611
1613{
1614 LfgState state;
1615 if (guid.IsGroup())
1616 {
1617 state = GroupsStore[guid].GetOldState();
1618 TC_LOG_TRACE("lfg.data.group.oldstate.get", "Group: {}, Old state: {}", guid.ToString(), state);
1619 }
1620 else
1621 {
1622 state = PlayersStore[guid].GetOldState();
1623 TC_LOG_TRACE("lfg.data.player.oldstate.get", "Player: {}, Old state: {}", guid.ToString(), state);
1624 }
1625
1626 return state;
1627}
1628
1630{
1631 ASSERT(gguid.IsGroup());
1632
1633 bool active = GroupsStore[gguid].IsVoteKickActive();
1634 TC_LOG_TRACE("lfg.data.group.votekick.get", "Group: {}, Active: {}", gguid.ToString(), active);
1635
1636 return active;
1637}
1638
1639uint32 LFGMgr::GetDungeon(ObjectGuid guid, bool asId /*= true */)
1640{
1641 uint32 dungeon = GroupsStore[guid].GetDungeon(asId);
1642 TC_LOG_TRACE("lfg.data.group.dungeon.get", "Group: {}, asId: {}, Dungeon: {}", guid.ToString(), asId, dungeon);
1643 return dungeon;
1644}
1645
1647{
1648 uint32 dungeonId = GroupsStore[guid].GetDungeon(true);
1649 uint32 mapId = 0;
1650 if (dungeonId)
1651 if (LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId))
1652 mapId = dungeon->map;
1653
1654 TC_LOG_TRACE("lfg.data.group.dungeon.map", "Group: {}, MapId: {} (DungeonId: {})", guid.ToString(), mapId, dungeonId);
1655
1656 return mapId;
1657}
1658
1660{
1661 uint8 roles = PlayersStore[guid].GetRoles();
1662 TC_LOG_TRACE("lfg.data.player.role.get", "Player: {}, Role: {}", guid.ToString(), roles);
1663 return roles;
1664}
1665
1666const std::string& LFGMgr::GetComment(ObjectGuid guid)
1667{
1668 TC_LOG_TRACE("lfg.data.player.comment.get", "Player: {}, Comment: {}", guid.ToString(), PlayersStore[guid].GetComment());
1669 return PlayersStore[guid].GetComment();
1670}
1671
1673{
1674 TC_LOG_TRACE("lfg.data.player.dungeons.selected.get", "Player: {}, Selected Dungeons: {}", guid.ToString(), ConcatenateDungeons(PlayersStore[guid].GetSelectedDungeons()));
1675 return PlayersStore[guid].GetSelectedDungeons();
1676}
1677
1679{
1680 TC_LOG_TRACE("lfg.data.player.dungeons.locked.get", "Player: {}, LockedDungeons.", guid.ToString());
1681 LfgLockMap lock;
1683 if (!player)
1684 {
1685 TC_LOG_WARN("lfg.data.player.dungeons.locked.get", "Player: {} not ingame while retrieving his LockedDungeons.", guid.ToString());
1686 return lock;
1687 }
1688
1689 uint8 level = player->GetLevel();
1690 uint8 expansion = player->GetSession()->Expansion();
1691 LfgDungeonSet const& dungeons = GetDungeonsByRandom(0);
1693
1694 for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it)
1695 {
1696 LFGDungeonData const* dungeon = GetLFGDungeon(*it);
1697 if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore
1698 continue;
1699
1700 uint32 lockStatus = 0;
1701 if (denyJoin)
1702 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
1703 else if (dungeon->expansion > expansion)
1705 else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
1706 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
1707 else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_LFG_MAP, dungeon->map, player))
1708 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
1709 else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty)))
1710 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
1711 else if (dungeon->minlevel[expansion] > level)
1712 lockStatus = LFG_LOCKSTATUS_TOO_LOW_LEVEL;
1713 else if (dungeon->maxlevel[expansion] < level)
1714 lockStatus = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
1715 else if (dungeon->seasonal && !IsSeasonActive(dungeon->id))
1716 lockStatus = LFG_LOCKSTATUS_NOT_IN_SEASON;
1717 else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty)))
1718 {
1719 if (ar->item_level && player->GetAverageItemLevel() < ar->item_level)
1721 else if (ar->achievement && !player->HasAchieved(ar->achievement))
1723 else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A))
1725 else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H))
1727 else
1728 if (ar->item)
1729 {
1730 if (!player->HasItemCount(ar->item) && (!ar->item2 || !player->HasItemCount(ar->item2)))
1731 lockStatus = LFG_LOCKSTATUS_MISSING_ITEM;
1732 }
1733 else if (ar->item2 && !player->HasItemCount(ar->item2))
1734 lockStatus = LFG_LOCKSTATUS_MISSING_ITEM;
1735 }
1736
1737 /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
1738 lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE;
1739 lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL;
1740 lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
1741 */
1742
1743 if (lockStatus)
1744 lock[dungeon->Entry()] = lockStatus;
1745 }
1746
1747 return lock;
1748}
1749
1751{
1752 uint8 kicks = GroupsStore[guid].GetKicksLeft();
1753 TC_LOG_TRACE("lfg.data.group.kickleft.get", "Group: {}, Kicks left: {}", guid.ToString(), kicks);
1754 return kicks;
1755}
1756
1757void LFGMgr::RestoreState(ObjectGuid guid, char const* debugMsg)
1758{
1759 if (guid.IsGroup())
1760 {
1761 LfgGroupData& data = GroupsStore[guid];
1762 TC_LOG_TRACE("lfg.data.group.state.restore", "Group: {} ({}), State: {}, Old state: {}",
1763 guid.ToString(), debugMsg, GetStateString(data.GetState()),
1764 GetStateString(data.GetOldState()));
1765
1766 data.RestoreState();
1767 }
1768 else
1769 {
1770 LfgPlayerData& data = PlayersStore[guid];
1771 TC_LOG_TRACE("lfg.data.player.state.restore", "Player: {} ({}), State: {}, Old state: {}",
1772 guid.ToString(), debugMsg, GetStateString(data.GetState()),
1773 GetStateString(data.GetOldState()));
1774
1775 data.RestoreState();
1776 }
1777}
1778
1780{
1781 if (guid.IsGroup())
1782 {
1783 LfgGroupData& data = GroupsStore[guid];
1784 TC_LOG_TRACE("lfg.data.group.state.set", "Group: {}, New state: {}, Previous: {}, Old state: {}",
1785 guid.ToString(), GetStateString(state), GetStateString(data.GetState()),
1786 GetStateString(data.GetOldState()));
1787
1788 data.SetState(state);
1789 }
1790 else
1791 {
1792 LfgPlayerData& data = PlayersStore[guid];
1793 TC_LOG_TRACE("lfg.data.player.state.set", "Player: {}, New state: {}, Previous: {}, OldState: {}",
1794 guid.ToString(), GetStateString(state), GetStateString(data.GetState()),
1795 GetStateString(data.GetOldState()));
1796
1797 data.SetState(state);
1798 }
1799}
1800
1801void LFGMgr::SetVoteKick(ObjectGuid gguid, bool active)
1802{
1803 ASSERT(gguid.IsGroup());
1804
1805 LfgGroupData& data = GroupsStore[gguid];
1806 TC_LOG_TRACE("lfg.data.group.votekick.set", "Group: {}, New state: {}, Previous: {}",
1807 gguid.ToString(), active, data.IsVoteKickActive());
1808
1809 data.SetVoteKick(active);
1810}
1811
1813{
1814 TC_LOG_TRACE("lfg.data.group.dungeon.set", "Group: {}, Dungeon: {}", guid.ToString(), dungeon);
1815 GroupsStore[guid].SetDungeon(dungeon);
1816}
1817
1819{
1820 TC_LOG_TRACE("lfg.data.player.role.set", "Player: {}, Roles: {}", guid.ToString(), roles);
1821 PlayersStore[guid].SetRoles(roles);
1822}
1823
1824void LFGMgr::SetComment(ObjectGuid guid, std::string const& comment)
1825{
1826 TC_LOG_TRACE("lfg.data.player.comment.set", "Player: {}, Comment: {}", guid.ToString(), comment);
1827 PlayersStore[guid].SetComment(comment);
1828}
1829
1831{
1832 TC_LOG_TRACE("lfg.data.player.dungeon.selected.set", "Player: {}, Dungeons: {}", guid.ToString(), ConcatenateDungeons(dungeons));
1833 PlayersStore[guid].SetSelectedDungeons(dungeons);
1834}
1835
1837{
1838 GroupsStore[guid].DecreaseKicksLeft();
1839 TC_LOG_TRACE("lfg.data.group.kicksleft.decrease", "Group: {}, Kicks: {}", guid.ToString(), GroupsStore[guid].GetKicksLeft());
1840}
1841
1843{
1844 TC_LOG_TRACE("lfg.data.player.remove", "Player: {}", guid.ToString());
1845 LfgPlayerDataContainer::iterator it = PlayersStore.find(guid);
1846 if (it != PlayersStore.end())
1847 PlayersStore.erase(it);
1848}
1849
1851{
1852 TC_LOG_TRACE("lfg.data.group.remove", "Group: {}", guid.ToString());
1853 LfgGroupDataContainer::iterator it = GroupsStore.find(guid);
1854 if (it == GroupsStore.end())
1855 return;
1856
1857 LfgState state = GetState(guid);
1858 // If group is being formed after proposal success do nothing more
1859 GuidSet const& players = it->second.GetPlayers();
1860 for (ObjectGuid playerGUID : players)
1861 {
1862 SetGroup(playerGUID, ObjectGuid::Empty);
1863 if (state != LFG_STATE_PROPOSAL)
1864 {
1865 SetState(playerGUID, LFG_STATE_NONE);
1867 }
1868 }
1869 GroupsStore.erase(it);
1870}
1871
1873{
1874 uint8 team = PlayersStore[guid].GetTeam();
1875 TC_LOG_TRACE("lfg.data.player.team.get", "Player: {}, Team: {}", guid.ToString(), team);
1876 return team;
1877}
1878
1880{
1881 roles &= PLAYER_ROLE_ANY;
1882 if (!(LfgRoleClasses::TANK & player->GetClassMask()))
1883 roles &= ~PLAYER_ROLE_TANK;
1884 if (!(LfgRoleClasses::HEALER & player->GetClassMask()))
1885 roles &= ~PLAYER_ROLE_HEALER;
1886 return roles;
1887}
1888
1890{
1891 return GroupsStore[gguid].RemovePlayer(guid);
1892}
1893
1895{
1896 GroupsStore[gguid].AddPlayer(guid);
1897}
1898
1900{
1901 GroupsStore[gguid].SetLeader(leader);
1902}
1903
1905{
1907 team = 0;
1908
1909 PlayersStore[guid].SetTeam(team);
1910}
1911
1913{
1914 return PlayersStore[guid].GetGroup();
1915}
1916
1918{
1919 PlayersStore[guid].SetGroup(group);
1920}
1921
1923{
1924 return GroupsStore[guid].GetPlayers();
1925}
1926
1928{
1929 return GroupsStore[guid].GetPlayerCount();
1930}
1931
1933{
1934 return GroupsStore[guid].GetLeader();
1935}
1936
1938{
1941 return plr1 && plr2 && (plr1->GetSocial()->HasIgnore(guid2) || plr2->GetSocial()->HasIgnore(guid1));
1942}
1943
1945{
1946 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1947 player->GetSession()->SendLfgRoleChosen(pguid, roles);
1948}
1949
1951{
1952 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1953 player->GetSession()->SendLfgRoleCheckUpdate(roleCheck);
1954}
1955
1957{
1958 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1959 player->GetSession()->SendLfgUpdatePlayer(data);
1960}
1961
1963{
1964 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1965 player->GetSession()->SendLfgUpdateParty(data);
1966}
1967
1969{
1970 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1971 player->GetSession()->SendLfgJoinResult(data);
1972}
1973
1975{
1976 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1977 player->GetSession()->SendLfgBootProposalUpdate(boot);
1978}
1979
1981{
1982 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1983 player->GetSession()->SendLfgUpdateProposal(proposal);
1984}
1985
1987{
1988 if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
1989 player->GetSession()->SendLfgQueueStatus(data);
1990}
1991
1993{
1994 return !guid.IsEmpty() && guid.IsGroup() && GroupsStore[guid].IsLfgGroup();
1995}
1996
1998{
1999 if (guid.IsGroup())
2000 {
2001 GuidSet const& players = GetPlayers(guid);
2002 ObjectGuid pguid = players.empty() ? ObjectGuid::Empty : (*players.begin());
2003 if (!pguid.IsEmpty())
2004 return GetTeam(pguid);
2005 }
2006
2007 return GetTeam(guid);
2008}
2009
2011{
2012 uint8 queueId = GetQueueId(guid);
2013 return QueuesStore[queueId];
2014}
2015
2016bool LFGMgr::AllQueued(GuidList const& check)
2017{
2018 if (check.empty())
2019 return false;
2020
2021 for (GuidList::const_iterator it = check.begin(); it != check.end(); ++it)
2022 {
2023 LfgState state = GetState(*it);
2024 if (state != LFG_STATE_QUEUED)
2025 {
2026 if (state != LFG_STATE_PROPOSAL)
2027 TC_LOG_DEBUG("lfg.allqueued", "Unexpected state found while trying to form new group. Guid: {}, State: {}", (*it).ToString(), GetStateString(state));
2028
2029 return false;
2030 }
2031 }
2032 return true;
2033}
2034
2036{
2037 uint8 queueId = GetQueueId(guid);
2038 LfgQueueContainer::const_iterator itr = QueuesStore.find(queueId);
2039 if (itr != QueuesStore.end())
2040 return itr->second.GetJoinTime(guid);
2041
2042 return 0;
2043}
2044
2045// Only for debugging purposes
2047{
2048 QueuesStore.clear();
2049}
2050
2052{
2053 return (m_options & option) != 0;
2054}
2055
2057{
2058 return m_options;
2059}
2060
2062{
2063 m_options = options;
2064}
2065
2067{
2068 LfgPlayerData& playerData = PlayersStore[guid];
2069 return LfgUpdateData(LFG_UPDATETYPE_UPDATE_STATUS, playerData.GetState(), playerData.GetSelectedDungeons());
2070}
2071
2073{
2074 switch (dungeonId)
2075 {
2076 case 285: // The Headless Horseman
2078 case 286: // The Frost Lord Ahune
2080 case 287: // Coren Direbrew
2082 case 288: // The Crown Chemical Co.
2084 }
2085 return false;
2086}
2087
2088std::string LFGMgr::DumpQueueInfo(bool full)
2089{
2090 uint32 size = uint32(QueuesStore.size());
2091 std::ostringstream o;
2092
2093 o << "Number of Queues: " << size << "\n";
2094 for (LfgQueueContainer::const_iterator itr = QueuesStore.begin(); itr != QueuesStore.end(); ++itr)
2095 {
2096 std::string const& queued = itr->second.DumpQueueInfo();
2097 std::string const& compatibles = itr->second.DumpCompatibleInfo(full);
2098 o << queued << compatibles;
2099 }
2100
2101 return o.str();
2102}
2103
2105{
2106 LfgDungeonSet dungeons;
2107 dungeons.insert(GetDungeon(gguid));
2108 SetSelectedDungeons(guid, dungeons);
2109 SetState(guid, GetState(gguid));
2110 SetGroup(guid, gguid);
2111 AddPlayerToGroup(gguid, guid);
2112}
2113
2115{
2116 if (GetState(guid) != LFG_STATE_NONE)
2117 {
2118 LfgDungeonSet const& dungeons = GetSelectedDungeons(guid);
2119 if (!dungeons.empty())
2120 {
2121 LFGDungeonData const* dungeon = GetLFGDungeon(*dungeons.begin());
2122 if (dungeon && (dungeon->type == LFG_TYPE_RANDOM || dungeon->seasonal))
2123 return true;
2124 }
2125 }
2126
2127 return false;
2128}
2129
2131{
2132 if (!guid.IsGroup())
2133 guid = GetGroup(guid);
2134
2135 if (uint32 dungeonId = GetDungeon(guid, true))
2136 if (LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId))
2137 if (uint32(dungeon->map) == map && dungeon->difficulty == difficulty)
2138 return true;
2139
2140 return false;
2141}
2142
2144{
2145 if (id)
2146 if (LFGDungeonData const* dungeon = GetLFGDungeon(id))
2147 return dungeon->Entry();
2148
2149 return 0;
2150}
2151
2153{
2154 LfgDungeonSet randomDungeons;
2155 for (lfg::LFGDungeonContainer::const_iterator itr = LfgDungeonStore.begin(); itr != LfgDungeonStore.end(); ++itr)
2156 {
2157 lfg::LFGDungeonData const& dungeon = itr->second;
2158 if ((dungeon.type == lfg::LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id)))
2159 && dungeon.expansion <= expansion && dungeon.minlevel[expansion] <= level && level <= dungeon.maxlevel[expansion])
2160 randomDungeons.insert(dungeon.Entry());
2161 }
2162 return randomDungeons;
2163}
2164
2165} // namespace lfg
@ CHAR_INS_LFG_DATA
@ CHAR_DEL_LFG_DATA
@ IN_MILLISECONDS
Definition Common.h:35
Difficulty
Definition DBCEnums.h:279
@ DUNGEON_DIFFICULTY_NORMAL
Definition DBCEnums.h:282
@ REGULAR_DIFFICULTY
Definition DBCEnums.h:280
@ DUNGEON_DIFFICULTY_HEROIC
Definition DBCEnums.h:283
@ ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS
Definition DBCEnums.h:235
DBCStorage< LFGDungeonEntry > sLFGDungeonStore(LFGDungeonEntryfmt)
DBCStorage< LFGDungeonExpansionEntry > sLFGDungeonExpansionStore(LFGDungeonExpansionfmt)
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
@ DISABLE_TYPE_MAP
Definition DisableMgr.h:29
@ DISABLE_TYPE_LFG_MAP
Definition DisableMgr.h:35
#define ABORT_MSG
Definition Errors.h:75
#define ASSERT
Definition Errors.h:68
bool IsHolidayActive(HolidayIds id)
#define sGroupMgr
Definition GroupMgr.h:58
#define MAX_GROUP_SIZE
Definition Group.h:43
#define sLFGMgr
Definition LFGMgr.h:492
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_TRACE(filterType__,...)
Definition Log.h:153
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
std::list< ObjectGuid > GuidList
Definition ObjectGuid.h:261
TypeID
Definition ObjectGuid.h:34
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:260
#define sObjectMgr
Definition ObjectMgr.h:1721
@ FATIGUE_TIMER
Definition Player.h:442
Role Based Access Control related classes definition.
@ ALLIANCE
@ HORDE
@ HOLIDAY_HALLOWS_END
@ HOLIDAY_FIRE_FESTIVAL
@ HOLIDAY_LOVE_IS_IN_THE_AIR
@ HOLIDAY_BREWFEST
@ GROUP_REMOVEMETHOD_KICK_LFG
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
@ UNIT_STATE_JUMPING
Definition Unit.h:238
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
float GetFloat() const
Definition Field.cpp:93
uint32 GetUInt32() const
Definition Field.cpp:61
Definition Group.h:165
bool isLFGGroup() const
Definition Group.cpp:2443
void SetDungeonDifficulty(Difficulty difficulty)
Definition Group.cpp:2104
bool AddMember(Player *player)
Definition Group.cpp:395
void SendUpdate()
Definition Group.cpp:1697
ObjectGuid GetGUID() const
Definition Group.cpp:2473
uint32 GetMembersCount() const
Definition Group.h:249
void SetLfgRoles(ObjectGuid guid, uint8 roles)
Definition Group.cpp:2428
void ConvertToLFG()
Definition Group.cpp:285
GroupReference * GetFirstMember()
Definition Group.h:247
bool RemoveMember(ObjectGuid guid, RemoveMethod const &method=GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker=ObjectGuid::Empty, char const *reason=nullptr)
Definition Group.cpp:538
bool Create(Player *leader)
Definition Group.cpp:151
uint32 GetDbStoreId() const
Definition Group.h:226
Definition Map.h:281
bool IsDungeon() const
Definition Map.cpp:4236
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
std::string ToString() const
bool IsGroup() const
Definition ObjectGuid.h:189
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
bool HasIgnore(ObjectGuid const &ignoreGuid)
uint32 GetTeam() const
Definition Player.h:1832
void RewardQuest(Quest const *quest, uint32 reward, Object *questGiver, bool announce=true)
Definition Player.cpp:14843
bool GetQuestRewardStatus(uint32 quest_id) const
Definition Player.cpp:15626
bool HasItemCount(uint32 item, uint32 count=1, bool inBankAlso=false) const
Definition Player.cpp:9763
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24940
void SetBattlegroundEntryPoint()
Definition Player.cpp:21901
bool InBattleground() const
Definition Player.h:1982
bool CanRewardQuest(Quest const *quest, bool msg)
Definition Player.cpp:14580
bool HasAchieved(uint32 achievementId) const
Definition Player.cpp:24920
bool InBattlegroundQueue(bool ignoreArena=false) const
Definition Player.cpp:23057
WorldSession * GetSession() const
Definition Player.h:1719
bool TeleportToBGEntryPoint()
Definition Player.cpp:1766
void FinishTaxiFlight()
Definition Player.cpp:21202
bool IsMirrorTimerActive(MirrorTimerType type) const
Definition Player.cpp:728
Group * GetGroup()
Definition Player.h:2171
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
float GetAverageItemLevel() const
Definition Player.cpp:26146
static void RemoveFromGroup(Group *group, ObjectGuid guid, RemoveMethod method=GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker=ObjectGuid::Empty, char const *reason=nullptr)
Definition Player.cpp:2326
PlayerSocial * GetSocial()
Definition Player.h:982
bool InArena() const
Definition Player.cpp:23148
InstancePlayerBind * GetBoundInstance(uint32 mapid, Difficulty difficulty, bool withExpired=false)
Definition Player.cpp:18564
void setUInt32(uint8 index, uint32 value)
Vehicle * GetVehicle() const
Definition Unit.h:1737
uint32 GetClassMask() const
Definition Unit.h:897
ObjectGuid GetCharmedGUID() const
Definition Unit.h:1255
bool IsAlive() const
Definition Unit.h:1234
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
bool IsFalling() const
Definition Unit.cpp:12813
uint8 GetLevel() const
Definition Unit.h:889
uint32 GetMapId() const
Definition Position.h:193
Map * GetMap() const
Definition Object.h:449
Map * FindMap() const
Definition Object.h:450
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
std::string const & GetName() const
Definition Object.h:382
void SendLfgJoinResult(lfg::LfgJoinResultData const &joinData)
uint8 Expansion() const
void SendLfgTeleportError(uint8 err)
void SendLfgUpdatePlayer(lfg::LfgUpdateData const &updateData)
void SendLfgPlayerReward(lfg::LfgPlayerRewardData const &lfgPlayerRewardData)
bool HasPermission(uint32 permissionId)
void SendLfgRoleChosen(ObjectGuid guid, uint8 roles)
uint8 GetKicksLeft(ObjectGuid gguid)
Get kicks left in current group.
Definition LFGMgr.cpp:1750
void _LoadFromDB(Field *fields, ObjectGuid guid)
Load Lfg group info from DB.
Definition LFGMgr.cpp:71
void InitBoot(ObjectGuid gguid, ObjectGuid kguid, ObjectGuid vguid, std::string const &reason)
Inits new proposal to boot a player.
Definition LFGMgr.cpp:1246
uint32 GetLFGDungeonEntry(uint32 id)
Return Lfg dungeon entry for given dungeon id.
Definition LFGMgr.cpp:2143
time_t GetQueueJoinTime(ObjectGuid guid)
Gets queue join time.
Definition LFGMgr.cpp:2035
LfgProposalContainer ProposalsStore
Current Role checks.
Definition LFGMgr.h:479
uint8 GetPlayerCount(ObjectGuid guid)
Gets the player count of given group.
Definition LFGMgr.cpp:1927
void SetSelectedDungeons(ObjectGuid guid, LfgDungeonSet const &dungeons)
Definition LFGMgr.cpp:1830
ObjectGuid GetLeader(ObjectGuid guid)
Get leader of the group (using internal data)
Definition LFGMgr.cpp:1932
void FinishDungeon(ObjectGuid gguid, uint32 dungeonId, Map const *currMap)
Finish the dungeon for the given group. All check are performed using internal lfg data.
Definition LFGMgr.cpp:1434
void TeleportPlayer(Player *player, bool out, bool fromOpcode=false)
Teleport a player to/from selected dungeon.
Definition LFGMgr.cpp:1343
LfgState GetOldState(ObjectGuid guid)
Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON)
Definition LFGMgr.cpp:1612
void SetComment(ObjectGuid guid, std::string const &comment)
Sets player lfr comment.
Definition LFGMgr.cpp:1824
void AddPlayerToGroup(ObjectGuid gguid, ObjectGuid guid)
Adds player to group.
Definition LFGMgr.cpp:1894
void SetGroup(ObjectGuid guid, ObjectGuid group)
Sets player group.
Definition LFGMgr.cpp:1917
LFGDungeonContainer LfgDungeonStore
Stores rewards for random dungeons.
Definition LFGMgr.h:476
void SendLfgBootProposalUpdate(ObjectGuid guid, LfgPlayerBoot const &boot)
Definition LFGMgr.cpp:1974
void SetDungeon(ObjectGuid guid, uint32 dungeon)
Definition LFGMgr.cpp:1812
LfgPlayerBootContainer BootsStore
Current Proposals.
Definition LFGMgr.h:480
uint8 GetTeam(ObjectGuid guid)
Definition LFGMgr.cpp:1872
void SetupGroupMember(ObjectGuid guid, ObjectGuid gguid)
Initializes player data after loading group data from DB.
Definition LFGMgr.cpp:2104
static LFGMgr * instance()
Definition LFGMgr.cpp:287
void RestoreState(ObjectGuid guid, char const *debugMsg)
Definition LFGMgr.cpp:1757
void Update(uint32 diff)
Definition LFGMgr.cpp:293
std::string DumpQueueInfo(bool full=false)
Dumps the state of the queue - Only for internal testing.
Definition LFGMgr.cpp:2088
void SendLfgRoleCheckUpdate(ObjectGuid guid, LfgRoleCheck const &roleCheck)
Definition LFGMgr.cpp:1950
GuidSet const & GetPlayers(ObjectGuid guid)
Definition LFGMgr.cpp:1922
uint32 GetOptions()
Gets current lfg options.
Definition LFGMgr.cpp:2056
LfgDungeonSet const & GetDungeonsByRandom(uint32 randomdungeon)
Definition LFGMgr.cpp:1551
void LeaveLfg(ObjectGuid guid, bool disconnected=false)
Leaves lfg.
Definition LFGMgr.cpp:626
std::string const & GetComment(ObjectGuid gguid)
Get current player comment (used for LFR)
Definition LFGMgr.cpp:1666
void UpdateBoot(ObjectGuid guid, bool accept)
Updates player boot proposal with new player answer.
Definition LFGMgr.cpp:1279
void LoadRewards()
Loads rewards for random dungeons.
Definition LFGMgr.cpp:121
void SendLfgJoinResult(ObjectGuid guid, LfgJoinResultData const &data)
Definition LFGMgr.cpp:1968
LfgCachedDungeonContainer CachedDungeonMapStore
Queues.
Definition LFGMgr.h:473
bool isOptionEnabled(uint32 option)
Checks if given lfg option is enabled.
Definition LFGMgr.cpp:2051
void UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid=ObjectGuid::Empty, uint8 roles=PLAYER_ROLE_NONE)
Updates the role check with player answer.
Definition LFGMgr.cpp:709
void Clean()
Clears queue - Only for internal testing.
Definition LFGMgr.cpp:2046
bool IsVoteKickActive(ObjectGuid gguid)
Get current vote kick state.
Definition LFGMgr.cpp:1629
LfgRoleCheckContainer RoleChecksStore
Definition LFGMgr.h:478
void SetOptions(uint32 options)
Sets new lfg options.
Definition LFGMgr.cpp:2061
uint32 m_lfgProposalId
used to check interval of update
Definition LFGMgr.h:469
uint8 RemovePlayerFromGroup(ObjectGuid gguid, ObjectGuid guid)
Removes a player from a group.
Definition LFGMgr.cpp:1889
LFGDungeonData const * GetLFGDungeon(uint32 id)
Definition LFGMgr.cpp:181
uint32 GetDungeonMapId(ObjectGuid guid)
Get the map id of the current dungeon.
Definition LFGMgr.cpp:1646
void RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdateType type)
Definition LFGMgr.cpp:1146
void GetCompatibleDungeons(LfgDungeonSet &dungeons, GuidSet const &players, LfgLockPartyMap &lockMap, bool isContinue)
Definition LFGMgr.cpp:808
void RemovePlayerData(ObjectGuid guid)
Definition LFGMgr.cpp:1842
void JoinLfg(Player *player, uint8 roles, LfgDungeonSet &dungeons, std::string const &comment)
Join Lfg with selected roles, dungeons and comment.
Definition LFGMgr.cpp:405
LfgRewardContainer RewardMapStore
Stores all dungeons by groupType.
Definition LFGMgr.h:475
void SetState(ObjectGuid guid, LfgState state)
Definition LFGMgr.cpp:1779
void SendLfgRoleChosen(ObjectGuid guid, ObjectGuid pguid, uint8 roles)
Definition LFGMgr.cpp:1944
bool selectedRandomLfgDungeon(ObjectGuid guid)
Check if given guid applied for random dungeon.
Definition LFGMgr.cpp:2114
bool inLfgDungeonMap(ObjectGuid guid, uint32 map, Difficulty difficulty)
Check if given guid applied for given map and difficulty. Used to know.
Definition LFGMgr.cpp:2130
void SetLeader(ObjectGuid gguid, ObjectGuid leader)
Sets the leader of the group.
Definition LFGMgr.cpp:1899
LfgGroupDataContainer GroupsStore
Player data.
Definition LFGMgr.h:482
void UpdateProposal(uint32 proposalId, ObjectGuid guid, bool accept)
Updates proposal to join dungeon with player answer.
Definition LFGMgr.cpp:1038
LfgState GetState(ObjectGuid guid)
Get current lfg state.
Definition LFGMgr.cpp:1595
LFGQueue & GetQueue(ObjectGuid guid)
Definition LFGMgr.cpp:2010
bool IsLfgGroup(ObjectGuid guid)
Check if given group guid is lfg.
Definition LFGMgr.cpp:1992
void SetRoles(ObjectGuid guid, uint8 roles)
Sets player lfg roles.
Definition LFGMgr.cpp:1818
uint8 GetQueueId(ObjectGuid guid)
Returns queue id.
Definition LFGMgr.cpp:1997
uint32 m_options
used as internal counter for proposals
Definition LFGMgr.h:470
void RemoveGroupData(ObjectGuid guid)
Removes saved group data.
Definition LFGMgr.cpp:1850
void _SaveToDB(ObjectGuid guid, uint32 db_guid)
Definition LFGMgr.cpp:100
static bool CheckGroupRoles(LfgRolesMap &groles)
Checks if given roles match, modifies given roles map with new roles.
Definition LFGMgr.cpp:864
uint32 GetDungeon(ObjectGuid guid, bool asId=true)
Get current dungeon.
Definition LFGMgr.cpp:1639
uint8 FilterClassRoles(Player *player, uint8 roles)
Definition LFGMgr.cpp:1879
LfgPlayerDataContainer PlayersStore
Current player kicks.
Definition LFGMgr.h:481
LfgQueueContainer QueuesStore
Stores config options.
Definition LFGMgr.h:472
uint32 AddProposal(LfgProposal &proposal)
Add a new Proposal.
Definition LFGMgr.cpp:1024
uint8 GetRoles(ObjectGuid guid)
Get current player roles.
Definition LFGMgr.cpp:1659
void SetVoteKick(ObjectGuid gguid, bool active)
Definition LFGMgr.cpp:1801
bool IsSeasonActive(uint32 dungeonId)
Checks if Seasonal dungeon is active.
Definition LFGMgr.cpp:2072
bool AllQueued(GuidList const &check)
Checks if all players are queued.
Definition LFGMgr.cpp:2016
LfgType GetDungeonType(uint32 dungeon)
Definition LFGMgr.cpp:1586
void DecreaseKicksLeft(ObjectGuid guid)
Definition LFGMgr.cpp:1836
void LoadLFGDungeons()
Loads dungeons from dbc and adds teleport coords.
Definition LFGMgr.cpp:190
LfgDungeonSet const & GetSelectedDungeons(ObjectGuid guid)
Get selected dungeons.
Definition LFGMgr.cpp:1672
static bool HasIgnore(ObjectGuid guid1, ObjectGuid guid2)
Checks if given players are ignoring each other.
Definition LFGMgr.cpp:1937
LfgLockMap const GetLockedDungeons(ObjectGuid guid)
Get locked dungeons.
Definition LFGMgr.cpp:1678
static void SendLfgQueueStatus(ObjectGuid guid, LfgQueueStatusData const &data)
Sends queue status to player.
Definition LFGMgr.cpp:1986
ObjectGuid GetGroup(ObjectGuid guid)
Gets player group.
Definition LFGMgr.cpp:1912
void SetTeam(ObjectGuid guid, uint8 team)
Sets player team.
Definition LFGMgr.cpp:1904
LfgReward const * GetRandomDungeonReward(uint32 dungeon, uint8 level)
Gets the random dungeon reward corresponding to given dungeon and player level.
Definition LFGMgr.cpp:1565
void MakeNewGroup(LfgProposal const &proposal)
Definition LFGMgr.cpp:931
void SendLfgUpdateProposal(ObjectGuid guid, LfgProposal const &proposal)
Definition LFGMgr.cpp:1980
LfgUpdateData GetLfgStatus(ObjectGuid guid)
Returns current lfg status.
Definition LFGMgr.cpp:2066
uint32 m_QueueTimer
Definition LFGMgr.h:468
LfgDungeonSet GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion)
Returns all random and seasonal dungeons for given level and expansion.
Definition LFGMgr.cpp:2152
void SendLfgUpdateParty(ObjectGuid guid, LfgUpdateData const &data)
Definition LFGMgr.cpp:1962
void SendLfgUpdatePlayer(ObjectGuid guid, LfgUpdateData const &data)
Definition LFGMgr.cpp:1956
void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const &dungeons, LfgRolesMap const &rolesMap)
Definition LFGQueue.cpp:192
time_t GetJoinTime(ObjectGuid guid) const
Definition LFGQueue.cpp:639
void AddToQueue(ObjectGuid guid, bool reAdd=false)
Definition LFGQueue.cpp:125
void UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:205
void RemoveFromQueue(ObjectGuid guid)
Definition LFGQueue.cpp:140
void UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:219
void UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:212
void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:226
bool IsVoteKickActive() const
void SetVoteKick(bool active)
LfgState GetState() const
void SetState(LfgState state)
LfgState GetOldState() const
LfgState GetOldState() const
void SetState(LfgState state)
LfgState GetState() const
LfgDungeonSet const & GetSelectedDungeons() const
#define sWorld
Definition World.h:900
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:236
@ CONFIG_LFG_OPTIONSMASK
Definition World.h:355
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP
Definition World.h:98
bool IsDisabledFor(DisableType type, uint32 entry, WorldObject const *ref, uint8 flags)
time_t GetGameTime()
Definition GameTime.cpp:42
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:29
Definition LFG.cpp:24
@ LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION
Definition LFG.h:80
@ LFG_LOCKSTATUS_TOO_LOW_LEVEL
Definition LFG.h:81
@ LFG_LOCKSTATUS_RAID_LOCKED
Definition LFG.h:85
@ LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE
Definition LFG.h:83
@ LFG_LOCKSTATUS_MISSING_ITEM
Definition LFG.h:89
@ LFG_LOCKSTATUS_TOO_HIGH_LEVEL
Definition LFG.h:82
@ LFG_LOCKSTATUS_MISSING_ACHIEVEMENT
Definition LFG.h:91
@ LFG_LOCKSTATUS_NOT_IN_SEASON
Definition LFG.h:90
@ LFG_LOCKSTATUS_QUEST_NOT_COMPLETED
Definition LFG.h:88
@ LFG_HEALERS_NEEDED
Definition LFG.h:33
@ LFG_TANKS_NEEDED
Definition LFG.h:32
@ LFG_DPS_NEEDED
Definition LFG.h:34
@ LFG_OPTION_ENABLE_DUNGEON_FINDER
Definition LFGMgr.h:42
@ LFG_OPTION_ENABLE_RAID_BROWSER
Definition LFGMgr.h:43
std::map< ObjectGuid, uint8 > LfgRolesMap
Definition LFG.h:105
LfgTeleportError
Teleport errors.
Definition LFGMgr.h:86
@ LFG_TELEPORTERROR_INVALID_LOCATION
Definition LFGMgr.h:93
@ LFG_TELEPORTERROR_OK
Definition LFGMgr.h:88
@ LFG_TELEPORTERROR_FATIGUE
Definition LFGMgr.h:92
@ LFG_TELEPORTERROR_PLAYER_DEAD
Definition LFGMgr.h:89
@ LFG_TELEPORTERROR_CHARMING
Definition LFGMgr.h:94
@ LFG_TELEPORTERROR_FALLING
Definition LFGMgr.h:90
@ LFG_TELEPORTERROR_IN_VEHICLE
Definition LFGMgr.h:91
LfgState
Definition LFG.h:66
@ LFG_STATE_RAIDBROWSER
Definition LFG.h:74
@ LFG_STATE_ROLECHECK
Definition LFG.h:68
@ LFG_STATE_FINISHED_DUNGEON
Definition LFG.h:73
@ LFG_STATE_DUNGEON
Definition LFG.h:72
@ LFG_STATE_PROPOSAL
Definition LFG.h:70
@ LFG_STATE_NONE
Definition LFG.h:67
@ LFG_STATE_QUEUED
Definition LFG.h:69
LfgUpdateType
Definition LFG.h:48
@ LFG_UPDATETYPE_ROLECHECK_FAILED
Definition LFG.h:53
@ LFG_UPDATETYPE_GROUP_FOUND
Definition LFG.h:57
@ LFG_UPDATETYPE_ADDED_TO_QUEUE
Definition LFG.h:58
@ LFG_UPDATETYPE_UPDATE_STATUS
Definition LFG.h:60
@ LFG_UPDATETYPE_PROPOSAL_FAILED
Definition LFG.h:55
@ LFG_UPDATETYPE_PROPOSAL_DECLINED
Definition LFG.h:56
@ LFG_UPDATETYPE_REMOVED_FROM_QUEUE
Definition LFG.h:54
@ LFG_UPDATETYPE_PROPOSAL_BEGIN
Definition LFG.h:59
@ LFG_UPDATETYPE_JOIN_QUEUE
Definition LFG.h:52
@ LFG_SPELL_DUNGEON_COOLDOWN
Definition LFGMgr.h:52
@ LFG_TIME_BOOT
Definition LFGMgr.h:49
@ LFG_GROUP_KICK_VOTES_NEEDED
Definition LFGMgr.h:55
@ LFG_TIME_ROLECHECK
Definition LFGMgr.h:48
@ LFG_QUEUEUPDATE_INTERVAL
Definition LFGMgr.h:51
@ LFG_SPELL_DUNGEON_DESERTER
Definition LFGMgr.h:53
LfgType
Determines the type of instance.
Definition LFGMgr.h:68
@ LFG_TYPE_NONE
Definition LFGMgr.h:69
@ LFG_TYPE_RANDOM
Definition LFGMgr.h:73
@ LFG_TYPE_RAID
Definition LFGMgr.h:71
@ LFG_TYPE_DUNGEON
Definition LFGMgr.h:70
@ LFG_TYPE_HEROIC
Definition LFGMgr.h:72
LfgAnswer
Answer state (Also used to check compatibilites)
Definition LFG.h:96
@ LFG_ANSWER_AGREE
Definition LFG.h:99
@ LFG_ANSWER_PENDING
Definition LFG.h:97
@ LFG_ANSWER_DENY
Definition LFG.h:98
std::string GetStateString(LfgState state)
Definition LFG.cpp:75
std::map< uint32, uint32 > LfgLockMap
Definition LFG.h:103
std::set< uint32 > LfgDungeonSet
Definition LFG.h:102
@ TANK
Definition LFGMgr.h:133
@ HEALER
Definition LFGMgr.h:138
@ LFG_ROLECHECK_WRONG_ROLES
Definition LFGMgr.h:127
@ LFG_ROLECHECK_MISSING_ROLE
Definition LFGMgr.h:126
@ LFG_ROLECHECK_ABORTED
Definition LFGMgr.h:128
@ LFG_ROLECHECK_DEFAULT
Definition LFGMgr.h:123
@ LFG_ROLECHECK_FINISHED
Definition LFGMgr.h:124
@ LFG_ROLECHECK_NO_ROLE
Definition LFGMgr.h:129
@ LFG_ROLECHECK_INITIALITING
Definition LFGMgr.h:125
@ LFG_FLAG_SEASONAL
Definition LFGMgr.h:62
std::string ConcatenateDungeons(LfgDungeonSet const &dungeons)
Definition LFG.cpp:26
std::pair< LfgRewardContainer::const_iterator, LfgRewardContainer::const_iterator > LfgRewardContainerBounds
Definition LFGMgr.h:155
@ PLAYER_ROLE_DAMAGE
Definition LFG.h:43
@ PLAYER_ROLE_ANY
Definition LFG.h:44
@ PLAYER_ROLE_TANK
Definition LFG.h:41
@ PLAYER_ROLE_NONE
Definition LFG.h:39
@ PLAYER_ROLE_LEADER
Definition LFG.h:40
@ PLAYER_ROLE_HEALER
Definition LFG.h:42
std::map< ObjectGuid, LfgLockMap > LfgLockPartyMap
Definition LFG.h:104
@ LFG_PROPOSAL_SUCCESS
Definition LFGMgr.h:81
@ LFG_PROPOSAL_FAILED
Definition LFGMgr.h:80
@ LFG_JOIN_TOO_MUCH_MEMBERS
Definition LFGMgr.h:116
@ LFG_JOIN_DISCONNECTED
Definition LFGMgr.h:109
@ LFG_JOIN_DUNGEON_INVALID
Definition LFGMgr.h:111
@ LFG_JOIN_USING_BG_SYSTEM
Definition LFGMgr.h:117
@ LFG_JOIN_MIXED_RAID_DUNGEON
Definition LFGMgr.h:107
@ LFG_JOIN_PARTY_NOT_MEET_REQS
Definition LFGMgr.h:106
@ LFG_JOIN_DESERTER
Definition LFGMgr.h:112
@ LFG_JOIN_RANDOM_COOLDOWN
Definition LFGMgr.h:114
@ LFG_JOIN_PARTY_RANDOM_COOLDOWN
Definition LFGMgr.h:115
@ LFG_JOIN_OK
Definition LFGMgr.h:101
@ LFG_JOIN_PARTY_DESERTER
Definition LFGMgr.h:113
@ LFG_JOIN_FAILED
Definition LFGMgr.h:102
@ LFG_JOIN_NOT_MEET_REQS
Definition LFGMgr.h:105
@ RBAC_PERM_JOIN_DUNGEON_FINDER
Definition RBAC.h:59
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
std::array< uint8, MAX_EXPANSIONS > maxlevel
Definition LFGMgr.h:294
Difficulty difficulty
Definition LFGMgr.h:295
std::string name
Definition LFGMgr.h:288
uint32 Entry() const
Definition LFGMgr.h:300
std::array< uint8, MAX_EXPANSIONS > minlevel
Definition LFGMgr.h:293
LfgJoinResult result
Definition LFGMgr.h:171
LfgLockPartyMap lockmap
Definition LFGMgr.h:173
Stores information of a current vote to kick someone from a group.
Definition LFGMgr.h:274
std::string reason
Player guid to be kicked (can't vote)
Definition LFGMgr.h:279
time_t cancelTime
Definition LFGMgr.h:275
LfgAnswerContainer votes
Vote in progress.
Definition LFGMgr.h:277
bool inProgress
Time left to vote.
Definition LFGMgr.h:276
ObjectGuid victim
Player votes (-1 not answer | 0 Not agree | 1 agree)
Definition LFGMgr.h:278
Stores player data related to proposal to join.
Definition LFGMgr.h:234
LfgAnswer accept
Proposed role.
Definition LFGMgr.h:237
Stores group data related to proposal to join.
Definition LFGMgr.h:243
ObjectGuid leader
Proposal group (0 if new)
Definition LFGMgr.h:252
uint32 dungeonId
Proposal Id.
Definition LFGMgr.h:249
GuidList queues
Determines if it's new group or not.
Definition LFGMgr.h:256
LfgProposalPlayerContainer players
Show order in update window.
Definition LFGMgr.h:258
bool isNew
Dungeon Encounters.
Definition LFGMgr.h:255
LfgProposalState state
Dungeon to join.
Definition LFGMgr.h:250
ObjectGuid group
State of the proposal.
Definition LFGMgr.h:251
Reward info.
Definition LFGMgr.h:223
uint32 firstQuest
Definition LFGMgr.h:228
uint32 otherQuest
Definition LFGMgr.h:229
Stores all rolecheck info of a group that wants to join.
Definition LFGMgr.h:263
LfgDungeonSet dungeons
State of the rolecheck.
Definition LFGMgr.h:267
LfgRolesMap roles
Time when the rolecheck will fail.
Definition LFGMgr.h:265
LfgRoleCheckState state
Player selected roles.
Definition LFGMgr.h:266
time_t cancelTime
Definition LFGMgr.h:264
ObjectGuid leader
Random Dungeon Id.
Definition LFGMgr.h:269
uint32 rDungeonId
Dungeons group is applying for (expanded random dungeons)
Definition LFGMgr.h:268
LfgUpdateType updateType
Definition LFGMgr.h:185