Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
LFGMgr.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Common.h"
7#include "DBCStores.h"
8#include "DisableMgr.h"
9#include "GameEventMgr.h"
10#include "Group.h"
11#include "GroupMgr.h"
12#include "GridDefines.h"
13#include "InstanceSaveMgr.h"
14#include "LFGGroupData.h"
15#include "LFGMgr.h"
16#include "LFGPlayerData.h"
17#include "LFGQueue.h"
18#include "LFGScripts.h"
19#include "MapManager.h"
20#include "ObjectMgr.h"
21#include "Player.h"
22#include "RBAC.h"
23#include "SharedDefines.h"
24#include "SocialMgr.h"
25#include "WorldSession.h"
26
27#include <algorithm>
28#include <vector>
29
30namespace lfg
31{
32 namespace
33 {
34 uint8 const LFG_COMBAT_ROLE_MASK = PLAYER_ROLE_TANK | PLAYER_ROLE_HEALER | PLAYER_ROLE_DAMAGE;
35
36 bool IsScenarioDifficulty(uint32 difficulty)
37 {
38 return difficulty == DIFFICULTY_SCE_NORMAL || difficulty == DIFFICULTY_SCE_HEROIC;
39 }
40
41 bool IsScenarioDungeon(LFGDungeonEntry const* dungeon)
42 {
43 if (!dungeon)
44 return false;
45
46 if (IsScenarioDifficulty(dungeon->m_DifficultyID))
47 return true;
48
49 MapEntry const* map = sMapStore.LookupEntry(dungeon->m_ContinentID);
50 return map && map->IsScenario();
51 }
52
53 bool IsScenarioDungeon(LFGDungeonData const& dungeon)
54 {
55 if (IsScenarioDifficulty(dungeon.difficulty))
56 return true;
57
58 MapEntry const* map = sMapStore.LookupEntry(dungeon.map);
59 return map && map->IsScenario();
60 }
61
62 bool IsRaidDungeon(LFGDungeonData const& dungeon)
63 {
64 if (dungeon.type == LFG_TYPE_RAID)
65 return true;
66
67 MapEntry const* map = sMapStore.LookupEntry(dungeon.map);
68 return map && map->IsRaid();
69 }
70
71 bool IsFlexibleRaidData(LFGDungeonData const& dungeon)
72 {
73 return dungeon.difficulty == DIFFICULTY_FLEX && IsRaidDungeon(dungeon);
74 }
75
76 bool HasValidLfgTeleportLocation(LFGDungeonData const& dungeon)
77 {
78 if (!dungeon.map || (dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f))
79 return false;
80
81 return Skyfire::IsValidMapCoord(dungeon.x, dungeon.y, dungeon.z, dungeon.o);
82 }
83
84 bool BindLfgGroupToDungeonInstance(Group* group, LFGDungeonData const& dungeon)
85 {
86 if (!group)
87 return false;
88
89 MapEntry const* map = sMapStore.LookupEntry(dungeon.map);
90 if (!map || (!map->IsInstance() && !map->IsScenario()))
91 return true;
92
93 DifficultyID difficulty = DifficultyID(dungeon.difficulty);
94 if (group->GetBoundInstance(difficulty, dungeon.map))
95 return true;
96
97 InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(dungeon.map, sMapMgr->GenerateInstanceId(), difficulty, 0, true);
98 if (!save)
99 return false;
100
101 return group->BindToInstance(save, false) != NULL;
102 }
103
104 struct LfgRoleAssignment
105 {
106 uint64 guid;
107 uint8 leader;
108 uint8 availableRoles;
109 uint8 assignedRole;
110 };
111
112 uint8 CountAvailableRoles(uint8 roles)
113 {
114 uint8 count = 0;
115 if (roles & PLAYER_ROLE_TANK)
116 ++count;
117 if (roles & PLAYER_ROLE_HEALER)
118 ++count;
119 if (roles & PLAYER_ROLE_DAMAGE)
120 ++count;
121 return count;
122 }
123
124 bool TryAssignLfgRoles(std::vector<LfgRoleAssignment>& assignments, size_t index, uint8 tanks, uint8 healers, uint8 damage)
125 {
126 if (index == assignments.size())
127 return true;
128
129 LfgRoleAssignment& assignment = assignments[index];
130 uint8 const rolePreference[] = { PLAYER_ROLE_TANK, PLAYER_ROLE_HEALER, PLAYER_ROLE_DAMAGE };
131
132 for (uint8 role : rolePreference)
133 {
134 if (!(assignment.availableRoles & role))
135 continue;
136
137 if (role == PLAYER_ROLE_TANK && tanks >= LFG_TANKS_NEEDED)
138 continue;
139 if (role == PLAYER_ROLE_HEALER && healers >= LFG_HEALERS_NEEDED)
140 continue;
141 if (role == PLAYER_ROLE_DAMAGE && damage >= LFG_DPS_NEEDED)
142 continue;
143
144 assignment.assignedRole = role | assignment.leader;
145
146 if (TryAssignLfgRoles(assignments, index + 1,
147 tanks + (role == PLAYER_ROLE_TANK),
148 healers + (role == PLAYER_ROLE_HEALER),
149 damage + (role == PLAYER_ROLE_DAMAGE)))
150 return true;
151 }
152
153 assignment.assignedRole = PLAYER_ROLE_NONE;
154 return false;
155 }
156 }
157
166
168 {
169 for (LfgRewardContainer::iterator itr = RewardMapStore.begin(); itr != RewardMapStore.end(); ++itr)
170 delete itr->second;
171 }
172
173 void LFGMgr::_LoadFromDB(Field* fields, uint64 guid)
174 {
175 if (!fields)
176 return;
177
178 if (!IS_GROUP_GUID(guid))
179 return;
180
181 SetLeader(guid, MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER));
182
183 uint32 dungeon = fields[16].GetUInt32();
184 uint8 state = fields[17].GetUInt8();
185
186 if (!dungeon || !state)
187 return;
188
189 SetDungeon(guid, dungeon);
190
191 switch (state)
192 {
195 //case LFG_STATE_BOOT:
196 SetState(guid, (LfgState)state);
197 break;
198 default:
199 break;
200 }
201 }
202
203 void LFGMgr::_SaveToDB(uint64 guid, uint32 db_guid)
204 {
205 if (!IS_GROUP_GUID(guid))
206 return;
207 SQLTransaction trans = CharacterDatabase.BeginTransaction();
208 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
209
210 stmt->setUInt32(0, db_guid);
211
212 trans->Append(stmt);
213
214 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_LFG_DATA);
215 stmt->setUInt32(0, db_guid);
216
217 stmt->setUInt32(1, GetDungeon(guid));
218 stmt->setUInt32(2, GetState(guid));
219 trans->Append(stmt);
220 CharacterDatabase.CommitTransaction(trans);
221 }
222
225 {
226 uint32 oldMSTime = getMSTime();
227
228 for (LfgRewardContainer::iterator itr = RewardMapStore.begin(); itr != RewardMapStore.end(); ++itr)
229 delete itr->second;
230 RewardMapStore.clear();
231
232 // ORDER BY is very important for GetRandomDungeonReward!
233 QueryResult result = WorldDatabase.Query("SELECT dungeonId, maxLevel, firstQuestId, otherQuestId FROM lfg_dungeon_rewards ORDER BY dungeonId, maxLevel ASC");
234
235 if (!result)
236 {
237 SF_LOG_ERROR("server.loading", ">> Loaded 0 lfg dungeon rewards. DB table `lfg_dungeon_rewards` is empty!");
238 return;
239 }
240
241 uint32 count = 0;
242
243 Field* fields = NULL;
244 do
245 {
246 fields = result->Fetch();
247 uint32 dungeonId = fields[0].GetUInt32();
248 uint32 maxLevel = fields[1].GetUInt8();
249 uint32 firstQuestId = fields[2].GetUInt32();
250 uint32 otherQuestId = fields[3].GetUInt32();
251
252 if (!GetLFGDungeonEntry(dungeonId))
253 {
254 SF_LOG_ERROR("sql.sql", "Dungeon %u specified in table `lfg_dungeon_rewards` does not exist!", dungeonId);
255 continue;
256 }
257
258 if (!maxLevel || maxLevel > sWorld->getIntConfig(WorldIntConfigs::CONFIG_MAX_PLAYER_LEVEL))
259 {
260 SF_LOG_ERROR("sql.sql", "Level %u specified for dungeon %u in table `lfg_dungeon_rewards` can never be reached!", maxLevel, dungeonId);
261 maxLevel = sWorld->getIntConfig(WorldIntConfigs::CONFIG_MAX_PLAYER_LEVEL);
262 }
263
264 if (!firstQuestId || !sObjectMgr->GetQuestTemplate(firstQuestId))
265 {
266 SF_LOG_ERROR("sql.sql", "First quest %u specified for dungeon %u in table `lfg_dungeon_rewards` does not exist!", firstQuestId, dungeonId);
267 continue;
268 }
269
270 if (otherQuestId && !sObjectMgr->GetQuestTemplate(otherQuestId))
271 {
272 SF_LOG_ERROR("sql.sql", "Other quest %u specified for dungeon %u in table `lfg_dungeon_rewards` does not exist!", otherQuestId, dungeonId);
273 otherQuestId = 0;
274 }
275
276 RewardMapStore.insert(LfgRewardContainer::value_type(dungeonId, new LfgReward(maxLevel, firstQuestId, otherQuestId)));
277 ++count;
278 } while (result->NextRow());
279
280 SF_LOG_INFO("server.loading", ">> Loaded %u lfg dungeon rewards in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
281 }
282
284 {
285 LFGDungeonContainer::const_iterator itr = LfgDungeonStore.find(id);
286 if (itr != LfgDungeonStore.end())
287 return &(itr->second);
288
289 return NULL;
290 }
291
292 void LFGMgr::LoadLFGDungeons(bool reload /* = false */)
293 {
294 uint32 oldMSTime = getMSTime();
295
296 LfgDungeonStore.clear();
297
298 // Initialize Dungeon map with data from dbcs
299 for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
300 {
301 LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i);
302 if (!dungeon)
303 continue;
304
305 MapEntry const* dungeonMap = sMapStore.LookupEntry(dungeon->m_ContinentID);
306 if (dungeonMap && dungeonMap->IsBattlegroundOrArena())
307 continue;
308
309 switch (dungeon->m_Type)
310 {
311 case LFG_TYPE_DUNGEON:
312 case LFG_TYPE_RAID:
313 case LFG_TYPE_RANDOM:
314 LfgDungeonStore[dungeon->m_ID] = LFGDungeonData(dungeon);
315 break;
316 default:
317 if (IsScenarioDungeon(dungeon))
318 LfgDungeonStore[dungeon->m_ID] = LFGDungeonData(dungeon);
319 break;
320 }
321 }
322
323 // Fill teleport locations and lock metadata from DB.
324 QueryResult result;
325 bool usingDungeonTemplate = false;
326 QueryResult dungeonTemplateTable = WorldDatabase.Query("SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'lfg_dungeon_template' LIMIT 1");
327 if (dungeonTemplateTable)
328 {
329 result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation, requiredItemLevel FROM lfg_dungeon_template");
330 if (result)
331 usingDungeonTemplate = true;
332 }
333
334 if (!result)
335 result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_entrances");
336
337 uint32 count = 0;
338
339 if (result)
340 {
341 do
342 {
343 Field* fields = result->Fetch();
344 uint32 dungeonId = fields[0].GetUInt32();
345 LFGDungeonContainer::iterator dungeonItr = LfgDungeonStore.find(dungeonId);
346 if (dungeonItr == LfgDungeonStore.end())
347 {
348 SF_LOG_ERROR("sql.sql", "table `%s` contains data for wrong dungeon %u", usingDungeonTemplate ? "lfg_dungeon_template" : "lfg_entrances", dungeonId);
349 continue;
350 }
351
352 LFGDungeonData& data = dungeonItr->second;
353 data.x = fields[1].GetFloat();
354 data.y = fields[2].GetFloat();
355 data.z = fields[3].GetFloat();
356 data.o = fields[4].GetFloat();
357
358 if (usingDungeonTemplate)
359 data.requiredItemLevel = fields[5].GetUInt32();
360
361 ++count;
362 } while (result->NextRow());
363 }
364
365 if (usingDungeonTemplate)
366 SF_LOG_INFO("server.loading", ">> Loaded %u lfg dungeon templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
367 else if (result)
368 SF_LOG_INFO("server.loading", ">> Loaded %u lfg entrance positions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
369 else
370 SF_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB tables `lfg_dungeon_template` and `lfg_entrances` are empty or missing!");
371
372 // Fill all other teleport coords from areatriggers
373 for (LFGDungeonContainer::iterator itr = LfgDungeonStore.begin(); itr != LfgDungeonStore.end(); ++itr)
374 {
375 LFGDungeonData& dungeon = itr->second;
376
377 // No teleport coords in database, load from areatriggers
378 if (dungeon.type != LFG_TYPE_RANDOM && dungeon.x == 0.0f && dungeon.y == 0.0f && dungeon.z == 0.0f)
379 {
380 AreaTriggerStruct const* at = sObjectMgr->GetMapEntranceTrigger(dungeon.map);
381 if (!at)
382 {
383 SF_LOG_ERROR("sql.sql", "Failed to load dungeon %s, cant find areatrigger for map %u", dungeon.name.c_str(), dungeon.map);
384 continue;
385 }
386
387 dungeon.map = at->target_mapId;
388 dungeon.x = at->target_X;
389 dungeon.y = at->target_Y;
390 dungeon.z = at->target_Z;
391 dungeon.o = at->target_Orientation;
392 }
393
394 if (dungeon.type != LFG_TYPE_RANDOM && !HasValidLfgTeleportLocation(dungeon))
395 {
396 SF_LOG_ERROR("sql.sql", "LFG dungeon %u (%s) has no valid teleport location for map %u. Add lfg_dungeon_template data.",
397 dungeon.id, dungeon.name.c_str(), uint32(dungeon.map));
398 continue;
399 }
400
401 if (dungeon.type != LFG_TYPE_RANDOM)
402 CachedDungeonMapStore[dungeon.group].insert(dungeon.id);
403 CachedDungeonMapStore[0].insert(dungeon.id);
404 }
405
406 if (reload)
407 CachedDungeonMapStore.clear();
408 }
409
411 {
413 return;
414
415 time_t currTime = time(NULL);
416
417 // Remove obsolete role checks
418 for (LfgRoleCheckContainer::iterator it = RoleChecksStore.begin(); it != RoleChecksStore.end();)
419 {
420 LfgRoleCheckContainer::iterator itRoleCheck = it++;
421 LfgRoleCheck& roleCheck = itRoleCheck->second;
422 if (currTime < roleCheck.cancelTime)
423 continue;
424
425 if (IS_GROUP_GUID(itRoleCheck->first) && GroupsStore.find(itRoleCheck->first) == GroupsStore.end())
426 {
427 RoleChecksStore.erase(itRoleCheck);
428 continue;
429 }
430
432
433 for (LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin(); itRoles != roleCheck.roles.end(); ++itRoles)
434 {
435 uint64 guid = itRoles->first;
436 SendLfgRoleCheckUpdate(guid, roleCheck);
437 if (guid == roleCheck.leader)
440 RestoreOrClearState(guid, "Remove Obsolete RoleCheck");
441 }
442
443 RestoreOrClearState(itRoleCheck->first, "Remove Obsolete RoleCheck");
444 RoleChecksStore.erase(itRoleCheck);
445 }
446
447 // Remove obsolete proposals
448 for (LfgProposalContainer::iterator it = ProposalsStore.begin(); it != ProposalsStore.end();)
449 {
450 LfgProposalContainer::iterator itRemove = it++;
451 if (itRemove->second.cancelTime < currTime)
453 }
454
455 // Remove obsolete kicks
456 for (LfgPlayerBootContainer::iterator it = BootsStore.begin(); it != BootsStore.end();)
457 {
458 LfgPlayerBootContainer::iterator itBoot = it++;
459 LfgPlayerBoot& boot = itBoot->second;
460 if (boot.cancelTime < currTime)
461 {
462 LfgGroupDataContainer::const_iterator groupData = GroupsStore.find(itBoot->first);
463 if (groupData == GroupsStore.end())
464 {
465 BootsStore.erase(itBoot);
466 continue;
467 }
468
469 boot.inProgress = false;
470 for (LfgAnswerContainer::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes)
471 {
472 uint64 pguid = itVotes->first;
473 if (pguid != boot.victim)
474 SendLfgBootProposalUpdate(pguid, boot);
476 }
477 SetState(itBoot->first, LFG_STATE_DUNGEON);
478 SetVoteKick(itBoot->first, false);
479 BootsStore.erase(itBoot);
480 }
481 }
482
483 uint32 lastProposalId = m_lfgProposalId;
484 // Check if a proposal can be formed with the new groups being added
485 for (LfgQueueContainer::iterator it = QueuesStore.begin(); it != QueuesStore.end(); ++it)
486 if (uint8 newProposals = it->second.FindGroups())
487 SF_LOG_DEBUG("lfg.update", "Found %u new groups in queue %u", newProposals, it->first);
488
489 if (lastProposalId != m_lfgProposalId)
490 {
491 for (LfgProposalContainer::const_iterator itProposal = ProposalsStore.upper_bound(lastProposalId); itProposal != ProposalsStore.end(); ++itProposal)
492 {
493 uint32 proposalId = itProposal->first;
494 LfgProposal& proposal = ProposalsStore[proposalId];
495
496 uint64 guid = 0;
497 for (LfgProposalPlayerContainer::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers)
498 {
499 guid = itPlayers->first;
501 if (uint64 gguid = GetGroup(guid))
502 {
505 }
506 else
508 SendLfgUpdateProposal(guid, proposal);
509 }
510
511 if (proposal.state == LFG_PROPOSAL_SUCCESS)
512 UpdateProposal(proposalId, guid, true);
513 }
514 }
515
516 // Update all players status queue info
518 {
519 m_QueueTimer = 0;
520 time_t currTime = time(NULL);
521 for (LfgQueueContainer::iterator it = QueuesStore.begin(); it != QueuesStore.end(); ++it)
522 it->second.UpdateQueueTimers(it->first, currTime);
523 }
524 else
525 m_QueueTimer += diff;
526 }
527
538 void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const std::string& comment)
539 {
540 if (!player || !player->GetSession() || dungeons.empty())
541 return;
542
543 Group* grp = player->GetGroup();
544 uint64 guid = player->GetGUID();
545 uint64 gguid = grp ? grp->GetGUID() : guid;
546 uint8 queueId = GetTeam(guid);
547 LfgJoinResultData joinData;
548 LfgGuidSet players;
549 uint32 rDungeonId = 0;
550 bool isContinue = grp && grp->isLFGGroup() && GetState(gguid) == LFG_STATE_DUNGEON;
551 bool hasFlexibleRaid = false;
552
553 // Do not allow to change dungeon in the middle of a current dungeon
554 if (isContinue)
555 {
556 dungeons.clear();
557 dungeons.insert(GetDungeon(gguid));
558 }
559
560 for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it)
561 if (IsFlexibleRaidDungeon(*it))
562 {
563 hasFlexibleRaid = true;
564 break;
565 }
566
567 // Already in queue?
568 LfgState state = GetState(gguid);
569 bool hasActiveQueueState = state == LFG_STATE_ROLECHECK || state == LFG_STATE_PROPOSAL ||
570 state == LFG_STATE_DUNGEON || state == LFG_STATE_BOOT;
571 if (state == LFG_STATE_QUEUED)
572 {
573 LFGQueue& queue = GetQueue(gguid);
574 queue.RemoveFromQueue(gguid);
575 }
576
577 // Check player or group member restrictions
578 if (hasActiveQueueState && !isContinue)
580 else if (!IsValidPlayerRoles(roles))
581 {
583 joinData.state = LFG_ROLECHECK_NO_ROLE;
584 }
585 else if (grp && !grp->isLFGGroup() && !grp->IsLeader(guid))
589 else if (player->InBattleground() || player->InArena() || player->InBattlegroundQueue())
591 else if (player->HasAura(LFG_SPELL_DUNGEON_DESERTER))
592 joinData.result = LFG_JOIN_DESERTER;
593 else if (player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
595 else if (dungeons.empty())
597 else if (grp)
598 {
599 uint8 groupMemberLimit = hasFlexibleRaid ? MAXRAIDSIZE : MAXGROUPSIZE;
600 if (grp->GetMembersCount() > groupMemberLimit)
602 else
603 {
604 uint8 memberCount = 0;
605 for (GroupReference* itr = grp->GetFirstMember(); itr != NULL && joinData.result == LFG_JOIN_OK; itr = itr->next())
606 {
607 if (Player* plrg = itr->GetSource())
608 {
609 if (!plrg->GetSession()->HasPermission(rbac::RBAC_PERM_JOIN_DUNGEON_FINDER))
611 if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER))
613 else if (plrg->HasAura(LFG_SPELL_DUNGEON_COOLDOWN))
615 else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue())
617 ++memberCount;
618 players.insert(plrg->GetGUID());
619 }
620 }
621
622 if (joinData.result == LFG_JOIN_OK && memberCount != grp->GetMembersCount())
623 joinData.result = LFG_JOIN_DISCONNECTED;
624 }
625 }
626 else
627 players.insert(player->GetGUID());
628
629 // Check if all dungeons are valid
630 bool isRaid = false;
631 if (joinData.result == LFG_JOIN_OK)
632 {
633 bool isDungeon = false;
634 bool hasNonFlexibleRaid = false;
635 for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end() && joinData.result == LFG_JOIN_OK; ++it)
636 {
637 LfgType type = GetDungeonType(*it);
638 switch (type)
639 {
640 case LFG_TYPE_RANDOM:
641 if (dungeons.size() > 1) // Only allow 1 random dungeon
643 else
644 rDungeonId = (*dungeons.begin());
645 // No break on purpose (Random can only be dungeon or heroic dungeon)
646 case LFG_TYPE_DUNGEON:
647 if (isRaid)
649 isDungeon = true;
650 break;
651 case LFG_TYPE_RAID:
652 if (isDungeon)
654 isRaid = true;
655 if (IsFlexibleRaidDungeon(*it))
656 hasFlexibleRaid = true;
657 else
658 hasNonFlexibleRaid = true;
659 if (hasFlexibleRaid && hasNonFlexibleRaid)
661 break;
662 default:
664 break;
665 }
666 }
667
668 // it could be changed
669 if (joinData.result == LFG_JOIN_OK)
670 {
671 // Expand random dungeons and check restrictions
672 if (rDungeonId)
673 dungeons = GetDungeonsByRandom(rDungeonId);
674
675 // if we have lockmap then there are no compatible dungeons
676 GetCompatibleDungeons(dungeons, players, joinData.lockmap, isContinue);
677 if (dungeons.empty())
679 }
680 }
681
682 // Can't join. Send result
683 if (joinData.result != LFG_JOIN_OK)
684 {
685 SF_LOG_DEBUG("lfg.join", "%u joining with %u members. Result: %u, Dungeons: %s",
686 GUID_LOPART(guid), grp ? grp->GetMembersCount() : 1, joinData.result, ConcatenateDungeons(dungeons).c_str());
687 if (!dungeons.empty()) // Only should show lockmap when have no dungeons available
688 joinData.lockmap.clear();
689 player->GetSession()->SendLfgJoinResult(joinData);
690 return;
691 }
692
693 if (isRaid && !hasFlexibleRaid)
694 {
695 SF_LOG_DEBUG("lfg.join", "%u trying to join raid browser and it's disabled.", GUID_LOPART(guid));
696 return;
697 }
698
699 if (grp)
700 SetActiveQueueId(gguid, queueId);
701
702 SetActiveQueueId(guid, queueId);
703 SetComment(guid, comment);
704
705 std::string debugNames = "";
706 if (grp) // Begin rolecheck
707 {
708 // Create new rolecheck
709 LfgRoleCheck& roleCheck = RoleChecksStore[gguid];
710 roleCheck.cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK;
712 roleCheck.leader = guid;
713 roleCheck.dungeons = dungeons;
714 roleCheck.rDungeonId = rDungeonId;
715
716 if (rDungeonId)
717 {
718 dungeons.clear();
719 dungeons.insert(rDungeonId);
720 }
721
723 // Send update to player
724 LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment);
725 for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
726 {
727 if (Player* plrg = itr->GetSource())
728 {
729 uint64 pguid = plrg->GetGUID();
730 plrg->GetSession()->SendLfgUpdateStatus(updateData, false);
731 SetActiveQueueId(pguid, queueId);
733 if (!isContinue)
734 SetSelectedDungeons(pguid, dungeons);
735 roleCheck.roles[pguid] = grp->GetMemberRole(pguid);
736 if (!debugNames.empty())
737 debugNames.append(", ");
738 debugNames.append(plrg->GetName());
739 }
740 }
741 // Update leader role
742 UpdateRoleCheck(gguid, guid, roles);
743 }
744 else // Add player to queue
745 {
746 LfgRolesMap rolesMap;
747 rolesMap[guid] = roles;
748 LFGQueue& queue = GetQueue(guid);
749 queue.AddQueueData(guid, time(NULL), dungeons, rolesMap);
750
751 if (!isContinue)
752 {
753 if (rDungeonId)
754 {
755 dungeons.clear();
756 dungeons.insert(rDungeonId);
757 }
758 SetSelectedDungeons(guid, dungeons);
759 }
760 // Send update to player
761 player->GetSession()->SendLfgJoinResult(joinData);
762 player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment), false);
764 SetRoles(guid, roles);
765 debugNames.append(player->GetName());
766 }
767
768 SF_LOG_DEBUG("lfg.join", "%u joined (%s), Members: %s. Dungeons (%u): %s", GUID_LOPART(guid),
769 grp ? "group" : "player", debugNames.c_str(), uint32(dungeons.size()), ConcatenateDungeons(dungeons).c_str());
770 }
771
778 void LFGMgr::LeaveLfg(uint64 guid, bool disconnected)
779 {
780 uint64 gguid = IS_GROUP_GUID(guid) ? guid : GetGroup(guid);
781
782 SF_LOG_DEBUG("lfg.leave", "%u left (%s)", GUID_LOPART(guid), guid == gguid ? "group" : "player");
783
784 LfgState state = GetState(guid);
785 switch (state)
786 {
787 case LFG_STATE_QUEUED:
788 if (gguid)
789 ClearGroupQueueState(gguid, "Leave queued group", true);
790 else
791 {
792 LFGQueue& queue = GetQueue(guid);
793 queue.RemoveFromQueue(guid);
795 ClearQueueState(guid, "Leave queued player");
796 }
797 break;
799 if (gguid)
800 UpdateRoleCheck(gguid); // No player to update role = LFG_ROLECHECK_ABORTED
801 break;
803 {
804 // Remove from Proposals
805 LfgProposalContainer::iterator it = ProposalsStore.begin();
806 uint64 pguid = gguid == guid ? GetLeader(gguid) : guid;
807 while (it != ProposalsStore.end())
808 {
809 LfgProposalPlayerContainer::iterator itPlayer = it->second.players.find(pguid);
810 if (itPlayer != it->second.players.end())
811 {
812 // Mark the player/leader of group who left as didn't accept the proposal
813 itPlayer->second.accept = LFG_ANSWER_DENY;
814 break;
815 }
816 ++it;
817 }
818
819 // Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
820 if (it != ProposalsStore.end())
822 break;
823 }
824 case LFG_STATE_NONE:
826 break;
829 //case LFG_STATE_BOOT:
830 if (guid == gguid && gguid && !disconnected)
831 ClearGroupQueueState(gguid, "Leave dungeon group", true);
832 else if (guid != gguid && !disconnected) // Player
833 ClearQueueState(guid, "Leave dungeon member");
834 break;
835 }
836 }
837
838 void LFGMgr::LeaveSoloLfg(uint64 guid, uint32 queueId, bool disconnected)
839 {
840 SF_LOG_DEBUG("lfg.leave", "Player: %u left queue.", GUID_LOPART(guid));
841
842 LfgState state = GetState(guid);
843 switch (state)
844 {
845 case LFG_STATE_QUEUED:
846 {
847 LFGQueue& queue = GetQueue(queueId);
848 queue.RemoveFromQueue(guid);
850 ClearQueueState(guid, "Leave queued solo player");
851 break;
852 }
854 {
855 // Remove from Proposals
856 LfgProposalContainer::iterator it = ProposalsStore.begin();
857 while (it != ProposalsStore.end())
858 {
859 LfgProposalPlayerContainer::iterator itPlayer = it->second.players.find(guid);
860 if (itPlayer != it->second.players.end())
861 {
862 // Mark the player/leader of group who left as didn't accept the proposal
863 itPlayer->second.accept = LFG_ANSWER_DENY;
864 break;
865 }
866 ++it;
867 }
868
869 // Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
870 if (it != ProposalsStore.end())
872 break;
873 }
874 case LFG_STATE_NONE:
876 break;
879 case LFG_STATE_BOOT:
880 {
881 ClearQueueState(guid, "Leave solo dungeon player");
882 break;
883 }
884 }
885 }
886
894 void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* = PLAYER_ROLE_NONE */)
895 {
896 if (!gguid)
897 return;
898
899 LfgRolesMap check_roles;
900 LfgRoleCheckContainer::iterator itRoleCheck = RoleChecksStore.find(gguid);
901 if (itRoleCheck == RoleChecksStore.end())
902 return;
903
904 LfgRoleCheck& roleCheck = itRoleCheck->second;
905 bool sendRoleChosen = roleCheck.state != LFG_ROLECHECK_DEFAULT && guid;
906
907 if (!guid)
908 roleCheck.state = LFG_ROLECHECK_ABORTED;
909 else if (!IsValidPlayerRoles(roles)) // Player selected no role or an invalid role mask.
910 roleCheck.state = LFG_ROLECHECK_NO_ROLE;
911 else
912 {
913 roleCheck.roles[guid] = roles;
914
915 // Check if all players have selected a role
916 LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin();
917 while (itRoles != roleCheck.roles.end() && itRoles->second != PLAYER_ROLE_NONE)
918 ++itRoles;
919
920 if (itRoles == roleCheck.roles.end())
921 {
922 // use temporal var to check roles, CheckGroupRoles modifies the roles
923 check_roles = roleCheck.roles;
924 bool scenario = false;
925 bool flexibleRaid = false;
926 for (LfgDungeonSet::const_iterator it = roleCheck.dungeons.begin(); it != roleCheck.dungeons.end(); ++it)
927 {
928 LFGDungeonData const* dungeon = GetLFGDungeon(*it);
929 if (!dungeon)
930 continue;
931
932 if (IsScenarioDungeon(*dungeon))
933 {
934 scenario = true;
935 break;
936 }
937
938 if (IsFlexibleRaidData(*dungeon))
939 flexibleRaid = true;
940 }
941
942 bool rolesOk = false;
943 if (scenario)
944 rolesOk = CheckDpsOnlyRoles(check_roles, uint8(check_roles.size()));
945 else if (flexibleRaid)
946 rolesOk = CheckFlexibleRaidRoles(check_roles, MAXRAIDSIZE);
947 else
948 rolesOk = CheckGroupRoles(check_roles);
949
951 }
952 }
953
954 LfgDungeonSet dungeons;
955 if (roleCheck.rDungeonId)
956 dungeons.insert(roleCheck.rDungeonId);
957 else
958 dungeons = roleCheck.dungeons;
959
960 LfgJoinResult joinResult = LFG_JOIN_FAILED;
961 switch (roleCheck.state)
962 {
967 joinResult = LFG_JOIN_ROLE_CHECK_FAILED;
968 break;
969 default:
970 break;
971 }
972
973 LfgJoinResultData joinData = LfgJoinResultData(joinResult, roleCheck.state);
974 for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it)
975 {
976 uint64 pguid = it->first;
977
978 if (sendRoleChosen)
979 SendLfgRoleChosen(pguid, guid, roles);
980
981 SendLfgRoleCheckUpdate(pguid, roleCheck);
982 switch (roleCheck.state)
983 {
985 continue;
988 SetRoles(pguid, it->second);
990 break;
991 default:
992 if (roleCheck.leader == pguid)
993 SendLfgJoinResult(pguid, joinData);
995 RestoreOrClearState(pguid, "Rolecheck Failed");
996 break;
997 }
998 }
999
1000 if (roleCheck.state == LFG_ROLECHECK_FINISHED)
1001 {
1002 SetState(gguid, LFG_STATE_QUEUED);
1003 LFGQueue& queue = GetQueue(gguid);
1004 queue.AddQueueData(gguid, time_t(time(NULL)), roleCheck.dungeons, roleCheck.roles);
1005 RoleChecksStore.erase(itRoleCheck);
1006 }
1007 else if (roleCheck.state != LFG_ROLECHECK_INITIALITING)
1008 {
1009 RestoreOrClearState(gguid, "Rolecheck Failed");
1010 RoleChecksStore.erase(itRoleCheck);
1011 }
1012 }
1013
1021 void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue)
1022 {
1023 lockMap.clear();
1024 std::map<uint32, uint32> lockedDungeons;
1025 for (LfgGuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it)
1026 {
1027 uint64 guid = (*it);
1028 LfgLockMap const& cachedLockMap = GetLockedDungeons(guid);
1029 Player* player = ObjectAccessor::FindPlayer(guid);
1030 for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2)
1031 {
1032 uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids
1033 LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId);
1034 if (itDungeon != dungeons.end())
1035 {
1036 bool eraseDungeon = true;
1037 // Don't remove the dungeon if team members are trying to continue a locked instance
1038 if (it2->second.lockStatus == LFG_LOCKSTATUS_RAID_LOCKED && isContinue)
1039 {
1040 LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
1041 ASSERT(dungeon);
1042 ASSERT(player);
1043 if (InstancePlayerBind* playerBind = player->GetBoundInstance(dungeon->map, DifficultyID(dungeon->difficulty)))
1044 {
1045 if (InstanceSave* playerSave = playerBind->save)
1046 {
1047 uint32 dungeonInstanceId = playerSave->GetInstanceId();
1048 auto itLockedDungeon = lockedDungeons.find(dungeonId);
1049 if (itLockedDungeon == lockedDungeons.end() || itLockedDungeon->second == dungeonInstanceId)
1050 eraseDungeon = false;
1051 lockedDungeons[dungeonId] = dungeonInstanceId;
1052 }
1053 }
1054 }
1055
1056 if (eraseDungeon)
1057 dungeons.erase(itDungeon);
1058
1059 lockMap[guid][dungeonId] = it2->second;
1060 }
1061 }
1062 }
1063 if (!dungeons.empty())
1064 lockMap.clear();
1065 }
1066
1074 {
1075 if (groles.empty() || groles.size() > MAXGROUPSIZE)
1076 return false;
1077
1078 std::vector<LfgRoleAssignment> assignments;
1079 assignments.reserve(groles.size());
1080
1081 for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it)
1082 {
1083 uint8 roles = it->second & LFG_COMBAT_ROLE_MASK;
1084 if (!roles)
1085 return false;
1086
1087 LfgRoleAssignment assignment;
1088 assignment.guid = it->first;
1089 assignment.leader = it->second & PLAYER_ROLE_LEADER;
1090 assignment.availableRoles = roles;
1091 assignment.assignedRole = PLAYER_ROLE_NONE;
1092 assignments.push_back(assignment);
1093 }
1094
1095 std::sort(assignments.begin(), assignments.end(), [](LfgRoleAssignment const& left, LfgRoleAssignment const& right)
1096 {
1097 uint8 leftCount = CountAvailableRoles(left.availableRoles);
1098 uint8 rightCount = CountAvailableRoles(right.availableRoles);
1099 if (leftCount != rightCount)
1100 return leftCount < rightCount;
1101
1102 return left.guid < right.guid;
1103 });
1104
1105 if (!TryAssignLfgRoles(assignments, 0, 0, 0, 0))
1106 return false;
1107
1108 for (LfgRoleAssignment const& assignment : assignments)
1109 groles[assignment.guid] = assignment.assignedRole;
1110
1111 return true;
1112 }
1113
1114 bool LFGMgr::CheckDpsOnlyRoles(LfgRolesMap& groles, uint8 neededDamage)
1115 {
1116 if (groles.empty() || groles.size() > neededDamage)
1117 return false;
1118
1119 for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it)
1120 it->second = PLAYER_ROLE_DAMAGE | (it->second & PLAYER_ROLE_LEADER);
1121
1122 return true;
1123 }
1124
1126 {
1127 if (groles.empty() || !maxPlayers || groles.size() > maxPlayers)
1128 return false;
1129
1130 for (LfgRolesMap::iterator it = groles.begin(); it != groles.end(); ++it)
1131 {
1132 uint8 leader = it->second & PLAYER_ROLE_LEADER;
1133 uint8 roles = it->second & LFG_COMBAT_ROLE_MASK;
1134 if (!roles)
1135 return false;
1136
1137 if (roles & PLAYER_ROLE_TANK)
1138 it->second = PLAYER_ROLE_TANK | leader;
1139 else if (roles & PLAYER_ROLE_HEALER)
1140 it->second = PLAYER_ROLE_HEALER | leader;
1141 else
1142 it->second = PLAYER_ROLE_DAMAGE | leader;
1143 }
1144
1145 return true;
1146 }
1147
1152 bool LFGMgr::MakeNewGroup(LfgProposal const& proposal)
1153 {
1154 LfgGuidList players;
1155 LfgGuidList playersToTeleport;
1156 LfgGuidSet expectedPlayers;
1157
1158 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1159 {
1160 uint64 guid = it->first;
1161 expectedPlayers.insert(guid);
1162 if (guid == proposal.leader)
1163 players.push_front(guid);
1164 else
1165 players.push_back(guid);
1166
1167 if (proposal.isNew || proposal.group || GetGroup(guid) != proposal.group)
1168 playersToTeleport.push_back(guid);
1169 }
1170
1171 // Set the dungeon difficulty
1172 LFGDungeonData const* dungeon = GetLFGDungeon(proposal.dungeonId);
1173 if (!dungeon)
1174 {
1175 SF_LOG_ERROR("lfg.proposal.group.make", "Proposal %u cannot create group for missing dungeon %u.",
1176 proposal.id, proposal.dungeonId);
1177 return false;
1178 }
1179
1180 Group* grp = proposal.group ? sGroupMgr->GetGroupByGUID(GUID_LOPART(proposal.group)) : NULL;
1181 bool const groupAlreadyExisted = grp != NULL;
1182 for (LfgGuidList::const_iterator it = players.begin(); it != players.end(); ++it)
1183 {
1184 uint64 pguid = (*it);
1185 Player* player = ObjectAccessor::FindPlayer(pguid);
1186 if (!player)
1187 {
1188 SF_LOG_DEBUG("lfg.proposal.group.make", "Proposal %u cannot create group, player %u is offline.",
1189 proposal.id, GUID_LOPART(pguid));
1190 return false;
1191 }
1192
1193 Group* group = player->GetGroup();
1194 if (group && group != grp)
1195 group->RemoveMember(player->GetGUID());
1196
1197 if (!grp)
1198 {
1199 grp = new Group();
1200 grp->ConvertToLFG();
1201 if (!grp->Create(player))
1202 {
1203 delete grp;
1204 SF_LOG_ERROR("lfg.proposal.group.make", "Proposal %u failed to create LFG group with leader %u.",
1205 proposal.id, GUID_LOPART(pguid));
1206 return false;
1207 }
1208
1209 uint64 gguid = grp->GetGUID();
1210 SetActiveQueueId(gguid, GetActiveQueueId(proposal.leader));
1212 sGroupMgr->AddGroup(grp);
1213 }
1214 else if (group != grp)
1215 {
1216 if (!grp->AddMember(player))
1217 {
1218 SF_LOG_ERROR("lfg.proposal.group.make", "Proposal %u failed to add player %u to group %u.",
1219 proposal.id, GUID_LOPART(pguid), GUID_LOPART(grp->GetGUID()));
1220 return false;
1221 }
1222 }
1223
1224 grp->SetLfgRoles(pguid, proposal.players.find(pguid)->second.role);
1225
1226 // Add the cooldown spell if queued for a random dungeon
1227 if (dungeon->type == LFG_TYPE_RANDOM)
1228 player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false);
1229 }
1230
1231 if (!grp)
1232 {
1233 SF_LOG_ERROR("lfg.proposal.group.make", "Proposal %u did not create or find a group.", proposal.id);
1234 return false;
1235 }
1236
1237 for (LfgGuidSet::const_iterator it = expectedPlayers.begin(); it != expectedPlayers.end(); ++it)
1238 {
1239 if (!grp->IsMember(*it))
1240 {
1241 SF_LOG_ERROR("lfg.proposal.group.make", "Proposal %u created incomplete group %u, missing player %u.",
1242 proposal.id, GUID_LOPART(grp->GetGUID()), GUID_LOPART(*it));
1243 return false;
1244 }
1245 }
1246
1247 bool const isRaidDungeon = IsRaidDungeon(*dungeon);
1248 if (isRaidDungeon && !grp->isRaidGroup())
1249 grp->ConvertToRaid();
1250
1251 DifficultyID const difficulty = DifficultyID(dungeon->difficulty);
1252 if (isRaidDungeon)
1253 grp->SetRaidDifficulty(difficulty);
1254 else
1255 grp->SetDungeonDifficulty(difficulty);
1256
1257 uint64 gguid = grp->GetGUID();
1258 SetActiveQueueId(gguid, GetActiveQueueId(proposal.leader));
1259 SetDungeon(gguid, dungeon->Entry());
1261
1262 uint64 leader = proposal.leader && grp->IsMember(proposal.leader) ? proposal.leader : grp->GetLeaderGUID();
1263 if (leader && grp->GetLeaderGUID() != leader)
1264 grp->ChangeLeader(leader);
1265
1266 SetLeader(gguid, leader);
1267
1268 for (LfgGuidList::const_iterator it = players.begin(); it != players.end(); ++it)
1269 if (grp->IsMember(*it))
1270 SetupGroupMember(*it, gguid);
1271
1272 _SaveToDB(gguid, grp->GetDbStoreId());
1273
1274 if (!BindLfgGroupToDungeonInstance(grp, *dungeon))
1275 {
1276 SF_LOG_ERROR("lfg.proposal.group.make", "Proposal %u failed to bind group %u to dungeon %u map %u.",
1277 proposal.id, GUID_LOPART(gguid), dungeon->id, uint32(dungeon->map));
1278 return false;
1279 }
1280
1281 bool const forceChangeInstance = !proposal.isNew && groupAlreadyExisted;
1282
1283 // Teleport Player
1284 for (LfgGuidList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it)
1285 if (Player* player = ObjectAccessor::FindPlayer(*it))
1286 if (player->GetMapId() != uint32(dungeon->map) || forceChangeInstance)
1287 TeleportPlayer(player, false, false, forceChangeInstance);
1288
1289 // Update group info
1290 grp->SendUpdate();
1291 return true;
1292 }
1293
1295 {
1296 proposal.id = ++m_lfgProposalId;
1297 ProposalsStore[m_lfgProposalId] = proposal;
1298 return m_lfgProposalId;
1299 }
1300
1308 void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept)
1309 {
1310 // Check if the proposal exists
1311 LfgProposalContainer::iterator itProposal = ProposalsStore.find(proposalId);
1312 if (itProposal == ProposalsStore.end())
1313 return;
1314
1315 LfgProposal& proposal = itProposal->second;
1316
1317 // Check if proposal have the current player
1318 LfgProposalPlayerContainer::iterator itProposalPlayer = proposal.players.find(guid);
1319 if (itProposalPlayer == proposal.players.end())
1320 return;
1321
1322 LfgProposalPlayer& player = itProposalPlayer->second;
1323 if (proposal.state != LFG_PROPOSAL_INITIATING || player.accept != LFG_ANSWER_PENDING)
1324 {
1325 SF_LOG_DEBUG("lfg.proposal.update", "Ignoring stale proposal response. Player %u, Proposal %u, Selection: %u, State: %u, Previous: %d",
1326 GUID_LOPART(guid), proposalId, accept, proposal.state, player.accept);
1327 return;
1328 }
1329
1330 if (player.group && GetGroup(guid) != player.group)
1331 {
1332 SF_LOG_DEBUG("lfg.proposal.update", "Player %u is no longer in proposal group %u. Removing stale proposal %u.",
1333 GUID_LOPART(guid), GUID_LOPART(player.group), proposalId);
1334 player.accept = LFG_ANSWER_DENY;
1336 return;
1337 }
1338
1339 for (LfgGuidList::const_iterator itQueue = proposal.queues.begin(); itQueue != proposal.queues.end(); ++itQueue)
1340 {
1341 if (GetQueue(*itQueue).HasQueueData(*itQueue))
1342 continue;
1343
1344 SF_LOG_DEBUG("lfg.proposal.update", "Proposal %u has stale queue owner %u. Removing proposal.",
1345 proposalId, GUID_LOPART(*itQueue));
1346 player.accept = LFG_ANSWER_DENY;
1348 return;
1349 }
1350
1351 player.accept = LfgAnswer(accept);
1352
1353 SF_LOG_DEBUG("lfg.proposal.update", "Player %u, Proposal %u, Selection: %u", GUID_LOPART(guid), proposalId, accept);
1354 if (!accept)
1355 {
1357 return;
1358 }
1359
1360 // check if all have answered and reorder players (leader first)
1361 bool allAnswered = true;
1362 for (LfgProposalPlayerContainer::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers)
1363 if (itPlayers->second.accept != LFG_ANSWER_AGREE) // No answer (-1) or not accepted (0)
1364 allAnswered = false;
1365
1366 if (!allAnswered)
1367 {
1368 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1369 SendLfgUpdateProposal(it->first, proposal);
1370
1371 return;
1372 }
1373
1374 if (!GetLFGDungeon(proposal.dungeonId))
1375 {
1376 SF_LOG_ERROR("lfg.proposal.update", "Proposal %u accepted but dungeon %u no longer exists.",
1377 proposalId, proposal.dungeonId);
1379 return;
1380 }
1381
1382 for (LfgProposalPlayerContainer::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1383 {
1384 uint64 pguid = it->first;
1385 if (!ObjectAccessor::FindPlayer(pguid))
1386 {
1387 SF_LOG_DEBUG("lfg.proposal.update", "Proposal %u accepted but player %u is offline.",
1388 proposalId, GUID_LOPART(pguid));
1389 it->second.accept = LFG_ANSWER_DENY;
1391 return;
1392 }
1393
1394 if (it->second.group && GetGroup(pguid) != it->second.group)
1395 {
1396 SF_LOG_DEBUG("lfg.proposal.update", "Proposal %u accepted but player %u left proposal group %u.",
1397 proposalId, GUID_LOPART(pguid), GUID_LOPART(it->second.group));
1398 it->second.accept = LFG_ANSWER_DENY;
1400 return;
1401 }
1402 }
1403
1404 bool sendUpdate = proposal.state != LFG_PROPOSAL_SUCCESS;
1405 proposal.state = LFG_PROPOSAL_SUCCESS;
1406 time_t joinTime = time(NULL);
1407
1408 uint64 queueOwner = proposal.queues.empty() ? guid : proposal.queues.front();
1409 LFGQueue& queue = GetQueue(queueOwner);
1412 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1413 {
1414 uint64 pguid = it->first;
1415 uint64 gguid = it->second.group;
1416 LfgDungeonSet const& selectedDungeons = GetSelectedDungeons(pguid);
1417 uint32 dungeonId = selectedDungeons.empty() ? proposal.dungeonId : (*selectedDungeons.begin());
1418 int32 waitTime = -1;
1419 uint64 queuedGuid = gguid ? gguid : pguid;
1420 time_t queueJoinTime = queue.GetJoinTime(queuedGuid);
1421 if (!queueJoinTime && queuedGuid != pguid)
1422 queueJoinTime = queue.GetJoinTime(pguid);
1423
1424 if (queueJoinTime)
1425 waitTime = int32(joinTime - queueJoinTime);
1426 else
1427 SF_LOG_DEBUG("lfg.proposal.update", "Proposal %u missing queue join time for player %u queue owner %u",
1428 proposalId, GUID_LOPART(pguid), GUID_LOPART(queuedGuid));
1429
1430 if (waitTime >= 0 && dungeonId)
1431 {
1432 // Update timers
1433 uint8 role = GetRoles(pguid);
1434 role &= ~PLAYER_ROLE_LEADER;
1435 switch (role)
1436 {
1437 case PLAYER_ROLE_DAMAGE:
1438 queue.UpdateWaitTimeDps(waitTime, dungeonId);
1439 break;
1440 case PLAYER_ROLE_HEALER:
1441 queue.UpdateWaitTimeHealer(waitTime, dungeonId);
1442 break;
1443 case PLAYER_ROLE_TANK:
1444 queue.UpdateWaitTimeTank(waitTime, dungeonId);
1445 break;
1446 default:
1447 queue.UpdateWaitTimeAvg(waitTime, dungeonId);
1448 break;
1449 }
1450 }
1451 }
1452
1453 if (sendUpdate)
1454 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1455 SendLfgUpdateProposal(it->first, proposal);
1456
1457 if (!MakeNewGroup(proposal))
1458 {
1459 for (LfgProposalPlayerContainer::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1460 it->second.accept = LFG_ANSWER_DENY;
1461
1463 return;
1464 }
1465
1466 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1467 {
1468 uint64 pguid = it->first;
1469 uint64 gguid = it->second.group;
1470
1471 SendLfgUpdateStatus(pguid, groupFoundData, gguid != 0);
1472 SendLfgUpdateStatus(pguid, removedFromQueueData, true);
1473 SendLfgUpdateStatus(pguid, removedFromQueueData, false);
1475 }
1476
1477 // Remove players/groups from Queue
1478 for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it)
1479 GetQueue(*it).RemoveFromQueue(*it);
1480
1481 ProposalsStore.erase(itProposal);
1482 }
1483
1490 void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdateType type)
1491 {
1492 LfgProposal& proposal = itProposal->second;
1493 proposal.state = LFG_PROPOSAL_FAILED;
1494
1495 SF_LOG_DEBUG("lfg.proposal.remove", "Proposal %u, state FAILED, UpdateType %u", itProposal->first, type);
1496 if (proposal.players.empty())
1497 {
1498 ProposalsStore.erase(itProposal);
1499 return;
1500 }
1501
1502 // Mark all people that didn't answered as no accept
1504 for (LfgProposalPlayerContainer::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1505 if (it->second.accept == LFG_ANSWER_PENDING)
1506 it->second.accept = LFG_ANSWER_DENY;
1507
1508 // Mark players/groups to be removed
1509 LfgGuidSet toRemove;
1510 for (LfgProposalPlayerContainer::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1511 {
1512 if (it->second.accept == LFG_ANSWER_AGREE)
1513 continue;
1514
1515 uint64 guid = it->second.group ? it->second.group : it->first;
1516 // Player didn't accept or still pending when no secs left
1517 if (it->second.accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED)
1518 {
1519 it->second.accept = LFG_ANSWER_DENY;
1520 toRemove.insert(guid);
1521 }
1522 }
1523
1524 LfgGuidSet missingQueueData;
1525 for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it)
1526 {
1527 if (!GetQueue(*it).HasQueueData(*it))
1528 {
1529 missingQueueData.insert(*it);
1530 toRemove.insert(*it);
1531 SF_LOG_DEBUG("lfg.proposal.remove", "Proposal %u missing queue data for %u while removing proposal",
1532 proposal.id, GUID_LOPART(*it));
1533 }
1534 }
1535
1536 // Notify players
1537 for (LfgProposalPlayerContainer::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it)
1538 {
1539 uint64 guid = it->first;
1540 uint64 gguid = it->second.group ? it->second.group : guid;
1541 bool canRequeue = toRemove.find(gguid) == toRemove.end() && GetQueue(gguid).HasQueueData(gguid);
1542
1543 SendLfgUpdateProposal(guid, proposal);
1544
1545 if (!canRequeue) // Didn't accept, stale queue data, or same group as someone that didn't accept
1546 {
1547 LfgUpdateData updateData;
1548 if (it->second.accept == LFG_ANSWER_DENY)
1549 {
1550 updateData.updateType = type;
1551 SF_LOG_DEBUG("lfg.proposal.remove", "%u didn't accept. Removing from queue and compatible cache", GUID_LOPART(guid));
1552 }
1553 else if (missingQueueData.find(gguid) != missingQueueData.end())
1554 {
1556 SF_LOG_DEBUG("lfg.proposal.remove", "%u no longer has queue data. Removing stale proposal state", GUID_LOPART(guid));
1557 }
1558 else
1559 {
1561 SF_LOG_DEBUG("lfg.proposal.remove", "%u cannot be requeued. Removing from queue and compatible cache", GUID_LOPART(guid));
1562 }
1563
1564 RestoreOrClearState(guid, "Proposal Fail (didn't accept or in group with someone that didn't accept)");
1565 if (gguid != guid)
1566 {
1567 RestoreOrClearState(it->second.group, "Proposal Fail (someone in group didn't accept)");
1568 SendLfgUpdateStatus(guid, updateData, true);
1569 }
1570 else
1571 SendLfgUpdateStatus(guid, updateData, false);
1572 }
1573 else
1574 {
1575 SF_LOG_DEBUG("lfg.proposal.remove", "Readding %u to queue.", GUID_LOPART(guid));
1577 if (gguid != guid)
1578 {
1579 SetState(gguid, LFG_STATE_QUEUED);
1581 }
1582 else
1584 }
1585 }
1586
1587 // Remove players/groups from queue
1588 for (LfgGuidSet::const_iterator it = toRemove.begin(); it != toRemove.end(); ++it)
1589 {
1590 uint64 guid = *it;
1591 GetQueue(guid).RemoveFromQueue(guid);
1592 proposal.queues.remove(guid);
1593 }
1594
1595 // Readd to queue
1596 for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it)
1597 {
1598 uint64 guid = *it;
1599 LFGQueue& queue = GetQueue(guid);
1600 if (queue.HasQueueData(guid))
1601 queue.AddToQueue(guid, true);
1602 }
1603
1604 ProposalsStore.erase(itProposal);
1605 }
1606
1615 void LFGMgr::InitBoot(uint64 gguid, uint64 kicker, uint64 victim, std::string const& reason)
1616 {
1617 LfgGroupDataContainer::const_iterator groupData = GroupsStore.find(gguid);
1618 if (groupData == GroupsStore.end())
1619 return;
1620
1621 LfgGuidSet const& players = groupData->second.GetPlayers();
1622 if (players.find(kicker) == players.end() || players.find(victim) == players.end())
1623 {
1624 SF_LOG_DEBUG("lfg.boot", "Group %u rejected boot init for invalid kicker %u or victim %u",
1625 GUID_LOPART(gguid), GUID_LOPART(kicker), GUID_LOPART(victim));
1626 return;
1627 }
1628
1629 SetVoteKick(gguid, true);
1630 SetState(gguid, LFG_STATE_BOOT);
1631
1632 LfgPlayerBoot& boot = BootsStore[gguid];
1633 boot.inProgress = true;
1634 boot.cancelTime = time_t(time(NULL)) + LFG_TIME_BOOT;
1635 boot.reason = reason;
1636 boot.victim = victim;
1637 boot.votes.clear();
1638
1639 // Set votes
1640 for (LfgGuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr)
1641 {
1642 uint64 guid = (*itr);
1643 boot.votes[guid] = LFG_ANSWER_PENDING;
1644 SetState(guid, LFG_STATE_BOOT);
1645 }
1646
1647 LfgAnswerContainer::iterator victimVote = boot.votes.find(victim);
1648 if (victimVote != boot.votes.end())
1649 victimVote->second = LFG_ANSWER_DENY; // Victim auto vote NO
1650
1651 LfgAnswerContainer::iterator kickerVote = boot.votes.find(kicker);
1652 if (kickerVote != boot.votes.end())
1653 kickerVote->second = LFG_ANSWER_AGREE; // Kicker auto vote YES
1654
1655 // Notify players
1656 for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
1657 SendLfgBootProposalUpdate(*it, boot);
1658 }
1659
1666 void LFGMgr::UpdateBoot(uint64 guid, bool accept)
1667 {
1668 uint64 gguid = GetGroup(guid);
1669 if (!gguid)
1670 return;
1671
1672 LfgPlayerBootContainer::iterator itBoot = BootsStore.find(gguid);
1673 if (itBoot == BootsStore.end())
1674 return;
1675
1676 LfgGroupDataContainer::const_iterator groupData = GroupsStore.find(gguid);
1677 if (groupData == GroupsStore.end())
1678 {
1679 BootsStore.erase(itBoot);
1680 return;
1681 }
1682
1683 LfgPlayerBoot& boot = itBoot->second;
1684
1685 LfgAnswerContainer::iterator itVote = boot.votes.find(guid);
1686 if (itVote == boot.votes.end())
1687 return;
1688
1689 if (itVote->second != LFG_ANSWER_PENDING) // Cheat check: Player can't vote twice
1690 return;
1691
1692 itVote->second = LfgAnswer(accept);
1693
1694 uint8 votesNum = 0;
1695 uint8 agreeNum = 0;
1696 for (LfgAnswerContainer::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes)
1697 {
1698 if (itVotes->second != LFG_ANSWER_PENDING)
1699 {
1700 ++votesNum;
1701 if (itVotes->second == LFG_ANSWER_AGREE)
1702 ++agreeNum;
1703 }
1704 }
1705
1706 // if we don't have enough votes (agree or deny) do nothing
1707 if (agreeNum < LFG_GROUP_KICK_VOTES_NEEDED && (votesNum - agreeNum) < LFG_GROUP_KICK_VOTES_NEEDED)
1708 return;
1709
1710 // Send update info to all players
1711 boot.inProgress = false;
1712 for (LfgAnswerContainer::const_iterator itVotes = boot.votes.begin(); itVotes != boot.votes.end(); ++itVotes)
1713 {
1714 uint64 pguid = itVotes->first;
1715 if (pguid != boot.victim)
1716 SendLfgBootProposalUpdate(pguid, boot);
1718 }
1719
1721 SetVoteKick(gguid, false);
1722 if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player
1723 {
1724 if (Group* group = sGroupMgr->GetGroupByGUID(GUID_LOPART(gguid)))
1726 DecreaseKicksLeft(gguid);
1727 }
1728 BootsStore.erase(itBoot);
1729 }
1730
1738 void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*/, bool forceChangeInstance /*= false*/)
1739 {
1740 LFGDungeonData const* dungeon = NULL;
1741 Group* group = player->GetGroup();
1742
1743 if (group && group->isLFGGroup())
1744 dungeon = GetLFGDungeon(GetDungeon(group->GetGUID()));
1745
1746 if (!dungeon)
1747 {
1748 SF_LOG_DEBUG("lfg.teleport", "Player %s not in group/lfggroup or dungeon not found!",
1749 player->GetName().c_str());
1751 return;
1752 }
1753
1754 if (player->IsBeingTeleported())
1755 {
1756 SF_LOG_DEBUG("lfg.teleport", "Player %s already has a pending teleport, skipping LFG teleport %s.",
1757 player->GetName().c_str(), out ? "out" : "in");
1758 return;
1759 }
1760
1761 if (out)
1762 {
1763 SF_LOG_DEBUG("lfg.teleport", "Player %s is being teleported out. Current Map %u - Expected Map %u",
1764 player->GetName().c_str(), player->GetMapId(), uint32(dungeon->map));
1765 if (player->GetMapId() == uint32(dungeon->map))
1766 {
1767 uint64 const guid = player->GetGUID();
1768 LfgPlayerData& playerData = PlayersStore[guid];
1769 LfgReturnLocation const& returnLocation = playerData.GetReturnLocation();
1770 if (returnLocation.IsSet && MapManager::IsValidMapCoord(returnLocation.MapId, returnLocation.X, returnLocation.Y, returnLocation.Z, returnLocation.O))
1771 {
1772 if (player->TeleportTo(returnLocation.MapId, returnLocation.X, returnLocation.Y, returnLocation.Z, returnLocation.O))
1773 {
1774 playerData.ClearReturnLocation();
1775 return;
1776 }
1777
1778 SF_LOG_DEBUG("lfg.teleport", "Player %s failed LFG return teleport to map %u (x: %f, y: %f, z: %f), falling back to battleground entry point",
1779 player->GetName().c_str(), returnLocation.MapId, returnLocation.X, returnLocation.Y, returnLocation.Z);
1780 }
1781
1782 playerData.ClearReturnLocation();
1783 player->TeleportToBGEntryPoint();
1784 }
1785
1786 return;
1787 }
1788
1790
1791 if (!player->IsAlive())
1793 else if (player->IsInCombat())
1795 else if (player->IsFalling() || player->HasUnitState(UNIT_STATE_JUMPING))
1797 else if (player->IsMirrorTimerActive(FATIGUE_TIMER))
1799 else if (player->GetVehicle())
1801 else if (player->GetCharmGUID())
1803 else if (player->GetMapId() != uint32(dungeon->map) || forceChangeInstance) // Do not teleport players in dungeon to the entrance
1804 {
1805 uint32 mapid = dungeon->map;
1806 float x = dungeon->x;
1807 float y = dungeon->y;
1808 float z = dungeon->z;
1809 float orientation = dungeon->o;
1810
1811 if (!HasValidLfgTeleportLocation(*dungeon))
1812 {
1813 SF_LOG_ERROR("lfg.teleport", "Player %s cannot teleport to LFG dungeon %u (%s): invalid entrance map %u position %f %f %f %f",
1814 player->GetName().c_str(), dungeon->id, dungeon->name.c_str(), uint32(dungeon->map), dungeon->x, dungeon->y, dungeon->z, dungeon->o);
1816 }
1817
1818 if (error == LFG_TELEPORTERROR_OK && !fromOpcode && !forceChangeInstance)
1819 {
1820 // Select a player inside to be teleported to
1821 for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
1822 {
1823 Player* plrg = itr->GetSource();
1824 if (plrg && plrg != player && plrg->GetMapId() == uint32(dungeon->map))
1825 {
1826 mapid = plrg->GetMapId();
1827 x = plrg->GetPositionX();
1828 y = plrg->GetPositionY();
1829 z = plrg->GetPositionZ();
1830 orientation = plrg->GetOrientation();
1831 break;
1832 }
1833 }
1834 }
1835
1836 if (error == LFG_TELEPORTERROR_OK && !player->GetMap()->IsInstance())
1837 {
1838 if (MapManager::IsValidMapCoord(player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation()))
1839 PlayersStore[uint64(player->GetGUID())].SetReturnLocation(player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation());
1840
1841 player->SetBattlegroundEntryPoint();
1842 }
1843
1844 if (error == LFG_TELEPORTERROR_OK && player->IsInFlight())
1845 {
1846 player->GetMotionMaster()->MovementExpired();
1847 player->CleanupAfterTaxiFlight();
1848 }
1849
1850 if (error == LFG_TELEPORTERROR_OK)
1851 {
1852 player->SetForcedTeleportFar(forceChangeInstance);
1853 if (!player->TeleportTo(mapid, x, y, z, orientation))
1854 {
1856 if (forceChangeInstance)
1857 player->SetSemaphoreTeleportForcedFar(false);
1858 }
1859 player->SetForcedTeleportFar(false);
1860 }
1861 }
1862 else
1864
1865 if (error != LFG_TELEPORTERROR_OK)
1866 player->GetSession()->SendLfgTeleportError(uint8(error));
1867
1868 SF_LOG_DEBUG("lfg.teleport", "Player %s is being teleported in to map %u "
1869 "(x: %f, y: %f, z: %f) Result: %u", player->GetName().c_str(), dungeon->map,
1870 dungeon->x, dungeon->y, dungeon->z, error);
1871 }
1872
1874 {
1875 if (!group || !group->isLFGGroup())
1876 return;
1877
1878 uint64 const groupGuid = group->GetGUID();
1879 LfgState const groupState = GetState(groupGuid);
1880 if (groupState != LFG_STATE_DUNGEON && groupState != LFG_STATE_FINISHED_DUNGEON)
1881 return;
1882
1883 LFGDungeonData const* dungeon = GetLFGDungeon(GetDungeon(groupGuid));
1884 if (!dungeon)
1885 return;
1886
1887 for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
1888 {
1889 Player* member = itr->GetSource();
1890 if (!member || member->GetMapId() != uint32(dungeon->map))
1891 continue;
1892
1893 TeleportPlayer(member, true);
1894 }
1895 }
1896
1903 void LFGMgr::FinishDungeon(uint64 gguid, const uint32 dungeonId)
1904 {
1905 uint32 gDungeonId = GetDungeon(gguid);
1906 if (gDungeonId != dungeonId)
1907 {
1908 SF_LOG_DEBUG("lfg.dungeon.finish", "Group %u finished dungeon %u but queued for %u", GUID_LOPART(gguid), dungeonId, gDungeonId);
1909 return;
1910 }
1911
1912 if (GetState(gguid) == LFG_STATE_FINISHED_DUNGEON) // Shouldn't happen. Do not reward multiple times
1913 {
1914 SF_LOG_DEBUG("lfg.dungeon.finish", "Group: %u already rewarded", GUID_LOPART(gguid));
1915 return;
1916 }
1917
1919
1920 const LfgGuidSet& players = GetPlayers(gguid);
1921 for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
1922 {
1923 uint64 guid = (*it);
1925 {
1926 SF_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u already rewarded", GUID_LOPART(gguid), GUID_LOPART(guid));
1927 continue;
1928 }
1929
1930 uint32 rDungeonId = 0;
1931 const LfgDungeonSet& dungeons = GetSelectedDungeons(guid);
1932 if (!dungeons.empty())
1933 rDungeonId = (*dungeons.begin());
1934
1936
1937 // Give rewards only if its a random dungeon
1938 LFGDungeonData const* dungeon = GetLFGDungeon(rDungeonId);
1939
1940 if (!dungeon || (dungeon->type != LFG_TYPE_RANDOM && !dungeon->seasonal))
1941 {
1942 SF_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u dungeon %u is not random or seasonal", GUID_LOPART(gguid), GUID_LOPART(guid), rDungeonId);
1943 continue;
1944 }
1945
1946 Player* player = ObjectAccessor::FindPlayer(guid);
1947 if (!player || !player->IsInWorld())
1948 {
1949 SF_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u not found in world", GUID_LOPART(gguid), GUID_LOPART(guid));
1950 continue;
1951 }
1952
1953 LFGDungeonData const* dungeonDone = GetLFGDungeon(dungeonId);
1954 uint32 mapId = dungeonDone ? uint32(dungeonDone->map) : 0;
1955
1956 if (player->GetMapId() != mapId)
1957 {
1958 SF_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u is in map %u and should be in %u to get reward", GUID_LOPART(gguid), GUID_LOPART(guid), player->GetMapId(), mapId);
1959 continue;
1960 }
1961
1962 // Update achievements
1963 if (dungeon->difficulty == DIFFICULTY_HEROIC)
1965
1966 LfgReward const* reward = GetRandomDungeonReward(rDungeonId, player->getLevel());
1967 if (!reward)
1968 continue;
1969
1970 bool done = false;
1971 Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest);
1972 if (!quest)
1973 continue;
1974
1975 // if we can take the quest, means that we haven't done this kind of "run", IE: First Heroic Random of Day.
1976 if (player->CanRewardQuest(quest, false))
1977 player->RewardQuest(quest, 0, NULL, false);
1978 else
1979 {
1980 done = true;
1981 quest = sObjectMgr->GetQuestTemplate(reward->otherQuest);
1982 if (!quest)
1983 continue;
1984 // we give reward without informing client (retail does this)
1985 player->RewardQuest(quest, 0, NULL, false);
1986 }
1987
1988 // Give rewards
1989 SF_LOG_DEBUG("lfg.dungeon.finish", "Group: %u, Player: %u done dungeon %u, %s previously done.", GUID_LOPART(gguid), GUID_LOPART(guid), GetDungeon(gguid), done ? " " : " not");
1990 LfgPlayerRewardData data = LfgPlayerRewardData(dungeon->Entry(), GetDungeon(gguid, false), done, quest);
1991 player->GetSession()->SendLfgPlayerReward(data);
1992 }
1993 }
1994
1995 // --------------------------------------------------------------------------//
1996 // Auxiliar Functions
1997 // --------------------------------------------------------------------------//
1998
2006 {
2007 LFGDungeonData const* dungeon = GetLFGDungeon(randomdungeon);
2008 uint32 group = dungeon ? dungeon->group : 0;
2009 return CachedDungeonMapStore[group];
2010 }
2011
2020 {
2021 LfgReward const* rew = NULL;
2022 LfgRewardContainerBounds bounds = RewardMapStore.equal_range(dungeon & 0x00FFFFFF);
2023 for (LfgRewardContainer::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
2024 {
2025 rew = itr->second;
2026 // ordered properly at loading
2027 if (itr->second->maxLevel >= level)
2028 break;
2029 }
2030
2031 return rew;
2032 }
2033
2041 {
2042 LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
2043 if (!dungeon)
2044 return LFG_TYPE_NONE;
2045
2046 return LfgType(dungeon->type);
2047 }
2048
2050 {
2051 LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
2052 return dungeon && dungeon->difficulty == DIFFICULTY_25MAN_LFR && IsRaidDungeon(*dungeon);
2053 }
2054
2056 {
2057 LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId);
2058 return dungeon && IsFlexibleRaidData(*dungeon);
2059 }
2060
2062 {
2063 LfgState state;
2064 if (IS_GROUP_GUID(guid))
2065 {
2066 state = GroupsStore[guid].GetState();
2067 SF_LOG_TRACE("lfg.data.group.state.get", "Group: %u, State: %u", GUID_LOPART(guid), state);
2068 }
2069 else
2070 {
2071 state = PlayersStore[guid].GetState();
2072 SF_LOG_TRACE("lfg.data.player.state.get", "Player: %u, State: %u", GUID_LOPART(guid), state);
2073 }
2074 return state;
2075 }
2076
2078 {
2079 LfgState state;
2080 if (IS_GROUP_GUID(guid))
2081 {
2082 state = GroupsStore[guid].GetOldState();
2083 SF_LOG_TRACE("lfg.data.group.oldstate.get", "Group: %u, Old state: %u", GUID_LOPART(guid), state);
2084 }
2085 else
2086 {
2087 state = PlayersStore[guid].GetOldState();
2088 SF_LOG_TRACE("lfg.data.player.oldstate.get", "Player: %u, Old state: %u", GUID_LOPART(guid), state);
2089 }
2090 return state;
2091 }
2092
2093 uint32 LFGMgr::GetDungeon(uint64 guid, bool asId /*= true */)
2094 {
2095 uint32 dungeon = GroupsStore[guid].GetDungeon(asId);
2096 SF_LOG_TRACE("lfg.data.group.dungeon.get", "Group: %u, asId: %u, Dungeon: %u", GUID_LOPART(guid), asId, dungeon);
2097 return dungeon;
2098 }
2099
2101 {
2102 uint32 dungeonId = GroupsStore[guid].GetDungeon(true);
2103 uint32 mapId = 0;
2104 if (dungeonId)
2105 if (LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId))
2106 mapId = dungeon->map;
2107
2108 SF_LOG_TRACE("lfg.data.group.dungeon.map", "Group: %u, MapId: %u (DungeonId: %u)", GUID_LOPART(guid), mapId, dungeonId);
2109 return mapId;
2110 }
2111
2113 {
2114 uint8 roles = PlayersStore[guid].GetRoles();
2115 SF_LOG_TRACE("lfg.data.player.role.get", "Player: %u, Role: %u", GUID_LOPART(guid), roles);
2116 return roles;
2117 }
2118
2120 {
2121 uint8 queueId = 0;
2122 if (IS_GROUP_GUID(guid))
2123 {
2124 queueId = GroupsStore[guid].GetActiveQueueId();
2125 SF_LOG_TRACE("lfg.data.group.queue.active.get", "Group: %u, QueueId: %u", GUID_LOPART(guid), queueId);
2126 }
2127 else
2128 {
2129 queueId = PlayersStore[guid].GetActiveQueueId();
2130 SF_LOG_TRACE("lfg.data.player.queue.active.get", "Player: %u, QueueId: %u", GUID_LOPART(guid), queueId);
2131 }
2132
2133 return queueId;
2134 }
2135
2137 {
2138 bool active = GroupsStore[guid].IsVoteKickActive();
2139 SF_LOG_TRACE("lfg.data.group.votekick.get", "Group: %u, Active: %d", GUID_LOPART(guid), active);
2140 return active;
2141 }
2142
2143 void LFGMgr::SetVoteKick(uint64 guid, bool active)
2144 {
2145 LfgGroupData& data = GroupsStore[guid];
2146 SF_LOG_TRACE("lfg.data.group.votekick.set", "Group: %u, New state: %d, Previous: %d", GUID_LOPART(guid), active, data.IsVoteKickActive());
2147 data.SetVoteKick(active);
2148 }
2149
2150 const std::string& LFGMgr::GetComment(uint64 guid)
2151 {
2152 SF_LOG_TRACE("lfg.data.player.comment.get", "Player: %u, Comment: %s", GUID_LOPART(guid), PlayersStore[guid].GetComment().c_str());
2153 return PlayersStore[guid].GetComment();
2154 }
2155
2157 {
2158 SF_LOG_TRACE("lfg.data.player.dungeons.selected.get", "Player: %u, Selected Dungeons: %s", GUID_LOPART(guid), ConcatenateDungeons(PlayersStore[guid].GetSelectedDungeons()).c_str());
2159 return PlayersStore[guid].GetSelectedDungeons();
2160 }
2161
2163 {
2164 SF_LOG_TRACE("lfg.data.player.dungeons.locked.get", "Player: %u, LockedDungeons.", GUID_LOPART(guid));
2165 LfgLockMap lock;
2166 Player* player = ObjectAccessor::FindPlayer(guid);
2167 if (!player)
2168 {
2169 SF_LOG_WARN("lfg.data.player.dungeons.locked.get", "Player: %u not ingame while retrieving his LockedDungeons.", GUID_LOPART(guid));
2170 return lock;
2171 }
2172
2173 uint8 level = player->getLevel();
2174 uint8 expansion = player->GetSession()->Expansion();
2175 float playerItemLevel = player->GetAverageItemLevel();
2176 uint32 currentItemLevel = uint32(playerItemLevel);
2177 LfgDungeonSet const& dungeons = GetDungeonsByRandom(0);
2179
2180 for (LfgDungeonSet::const_iterator it = dungeons.begin(); it != dungeons.end(); ++it)
2181 {
2182 LFGDungeonData const* dungeon = GetLFGDungeon(*it);
2183 if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore
2184 continue;
2185
2186 uint32 lockStatus = 0;
2187 uint32 requiredItemLevel = dungeon->requiredItemLevel;
2188 bool bypassLfgRequirements = IsDebugRequirementOverrideEnabled();
2189
2190 if (denyJoin)
2191 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
2192 else if (!bypassLfgRequirements)
2193 {
2194 if (dungeon->expansion > expansion)
2196 else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player))
2197 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
2198 else if (dungeon->difficulty > DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, DifficultyID(dungeon->difficulty)))
2199 lockStatus = LFG_LOCKSTATUS_RAID_LOCKED;
2200 else if (dungeon->minlevel > level)
2201 lockStatus = LFG_LOCKSTATUS_TOO_LOW_LEVEL;
2202 else if (dungeon->maxlevel < level)
2203 lockStatus = LFG_LOCKSTATUS_TOO_HIGH_LEVEL;
2204 else if (dungeon->seasonal && !IsSeasonActive(dungeon->id))
2205 lockStatus = LFG_LOCKSTATUS_NOT_IN_SEASON;
2206 else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, DifficultyID(dungeon->difficulty)))
2207 {
2208 if (!requiredItemLevel)
2209 requiredItemLevel = ar->iLvl;
2210
2211 if (requiredItemLevel && playerItemLevel < requiredItemLevel)
2213 else if (ar->achievement && !player->HasAchieved(ar->achievement))
2215 else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A))
2217 else if (player->GetTeam() == HORDE && ar->quest_H && !player->GetQuestRewardStatus(ar->quest_H))
2219 else if (ar->item)
2220 {
2221 if (!player->HasItemCount(ar->item) && (!ar->item2 || !player->HasItemCount(ar->item2)))
2222 lockStatus = LFG_LOCKSTATUS_MISSING_ITEM;
2223 }
2224 else if (ar->item2 && !player->HasItemCount(ar->item2))
2225 lockStatus = LFG_LOCKSTATUS_MISSING_ITEM;
2226 }
2227 else if (requiredItemLevel && playerItemLevel < requiredItemLevel)
2229
2230 /* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
2231 lockStatus = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE;
2232 lockStatus = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL;
2233 lockStatus = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
2234 */
2235 }
2236
2237 if (lockStatus)
2238 lock[dungeon->Entry()] = LfgLockData(lockStatus, currentItemLevel, requiredItemLevel);
2239 }
2240
2241 return lock;
2242 }
2243
2245 {
2246 uint8 kicks = GroupsStore[guid].GetKicksLeft();
2247 SF_LOG_TRACE("lfg.data.group.kickleft.get", "Group: %u, Kicks left: %u", GUID_LOPART(guid), kicks);
2248 return kicks;
2249 }
2250
2251 void LFGMgr::RestoreState(uint64 guid, char const* debugMsg)
2252 {
2253 if (IS_GROUP_GUID(guid))
2254 {
2255 LfgGroupData& data = GroupsStore[guid];
2256 SF_LOG_TRACE("lfg.data.group.state.restore", "Group: %u (%s), State: %s, Old state: %s",
2257 GUID_LOPART(guid), debugMsg, GetStateString(data.GetState()).c_str(),
2258 GetStateString(data.GetOldState()).c_str());
2259
2260 data.RestoreState();
2261 }
2262 else
2263 {
2264 LfgPlayerData& data = PlayersStore[guid];
2265 SF_LOG_TRACE("lfg.data.player.state.restore", "Player: %u (%s), State: %s, Old state: %s",
2266 GUID_LOPART(guid), debugMsg, GetStateString(data.GetState()).c_str(),
2267 GetStateString(data.GetOldState()).c_str());
2268 data.RestoreState();
2269 }
2270 }
2271
2272 void LFGMgr::RestoreOrClearState(uint64 guid, char const* debugMsg)
2273 {
2274 if (GetOldState(guid) == LFG_STATE_NONE)
2275 ClearQueueState(guid, debugMsg);
2276 else
2277 RestoreState(guid, debugMsg);
2278 }
2279
2281 {
2282 if (IS_GROUP_GUID(guid))
2283 {
2284 LfgGroupData& data = GroupsStore[guid];
2285 SF_LOG_TRACE("lfg.data.group.state.set", "Group: %u, New state: %s, Previous: %s, Old state: %s",
2286 GUID_LOPART(guid), GetStateString(state).c_str(), GetStateString(data.GetState()).c_str(),
2287 GetStateString(data.GetOldState()).c_str());
2288 data.SetState(state);
2289 }
2290 else
2291 {
2292 LfgPlayerData& data = PlayersStore[guid];
2293 SF_LOG_TRACE("lfg.data.player.state.set", "Player: %u, New state: %s, Previous: %s, OldState: %s",
2294 GUID_LOPART(guid), GetStateString(state).c_str(), GetStateString(data.GetState()).c_str(),
2295 GetStateString(data.GetOldState()).c_str());
2296 data.SetState(state);
2297 }
2298 }
2299
2300 void LFGMgr::ClearState(uint64 guid, char const* debugMsg)
2301 {
2302 ClearQueueState(guid, debugMsg);
2303 }
2304
2305 void LFGMgr::ClearQueueState(uint64 guid, char const* debugMsg)
2306 {
2307 SF_LOG_TRACE("lfg.data.queue.clear", "%s: %u", debugMsg ? debugMsg : "Clear queue state", GUID_LOPART(guid));
2308
2309 for (LfgQueueContainer::iterator itr = QueuesStore.begin(); itr != QueuesStore.end(); ++itr)
2310 itr->second.RemoveFromQueue(guid);
2311
2312 while (RestoreActiveQueue(guid))
2313 SetState(guid, LFG_STATE_NONE);
2314
2315 SetState(guid, LFG_STATE_NONE);
2316 }
2317
2318 void LFGMgr::ClearGroupQueueState(uint64 guid, char const* debugMsg, bool sendUpdate)
2319 {
2320 if (!guid || !IS_GROUP_GUID(guid))
2321 return;
2322
2323 LfgGroupDataContainer::const_iterator itr = GroupsStore.find(guid);
2324 if (itr == GroupsStore.end())
2325 {
2326 ClearQueueState(guid, debugMsg);
2327 return;
2328 }
2329
2330 LfgGuidSet const players = itr->second.GetPlayers();
2332
2333 RoleChecksStore.erase(guid);
2334 BootsStore.erase(guid);
2335
2336 ClearQueueState(guid, debugMsg);
2337 for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it)
2338 {
2339 SetGroup(*it, 0);
2340 ClearQueueState(*it, debugMsg);
2341 if (sendUpdate)
2342 {
2343 if (Player* player = ObjectAccessor::FindPlayer(*it))
2344 player->GetSession()->SendLfgClearStatus();
2345 else
2346 {
2347 SendLfgUpdateStatus(*it, removedFromQueueData, true);
2348 SendLfgUpdateStatus(*it, removedFromQueueData, false);
2349 }
2350 }
2351 }
2352 }
2353
2354 void LFGMgr::ClearDungeonGroupState(uint64 guid, uint32 dbGuid, char const* debugMsg, bool sendUpdate)
2355 {
2356 ClearGroupQueueState(guid, debugMsg, sendUpdate);
2357
2358 if (!dbGuid)
2359 return;
2360
2361 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA);
2362 stmt->setUInt32(0, dbGuid);
2363 CharacterDatabase.Execute(stmt);
2364 }
2365
2367 {
2368 if (IS_GROUP_GUID(guid))
2369 {
2370 SF_LOG_TRACE("lfg.data.group.queue.active.set", "Group: %u, QueueId: %u", GUID_LOPART(guid), queueId);
2371 GroupsStore[guid].SetActiveQueueId(queueId);
2372 }
2373 else
2374 {
2375 SF_LOG_TRACE("lfg.data.player.queue.active.set", "Player: %u, QueueId: %u", GUID_LOPART(guid), queueId);
2376 PlayersStore[guid].SetActiveQueueId(queueId);
2377 }
2378 }
2379
2381 {
2382 SF_LOG_TRACE("lfg.data.group.dungeon.set", "Group: %u, Dungeon: %u", GUID_LOPART(guid), dungeon);
2383 GroupsStore[guid].SetDungeon(dungeon);
2384 }
2385
2387 {
2388 SF_LOG_TRACE("lfg.data.player.role.set", "Player: %u, Roles: %u", GUID_LOPART(guid), roles);
2389 PlayersStore[guid].SetRoles(roles);
2390 }
2391
2392 void LFGMgr::SetComment(uint64 guid, std::string const& comment)
2393 {
2394 SF_LOG_TRACE("lfg.data.player.comment.set", "Player: %u, Comment: %s", GUID_LOPART(guid), comment.c_str());
2395 PlayersStore[guid].SetComment(comment);
2396 }
2397
2399 {
2400 SF_LOG_TRACE("lfg.data.player.dungeon.selected.set", "Player: %u, Dungeons: %s", GUID_LOPART(guid), ConcatenateDungeons(dungeons).c_str());
2401 PlayersStore[guid].SetSelectedDungeons(dungeons);
2402 }
2403
2405 {
2406 GroupsStore[guid].DecreaseKicksLeft();
2407 SF_LOG_TRACE("lfg.data.group.kicksleft.decrease", "Group: %u, Kicks: %u", GUID_LOPART(guid), GroupsStore[guid].GetKicksLeft());
2408 }
2409
2411 {
2412 SF_LOG_TRACE("lfg.data.player.remove", "Player: %u", GUID_LOPART(guid));
2413 LfgPlayerDataContainer::iterator it = PlayersStore.find(guid);
2414 if (it != PlayersStore.end())
2415 PlayersStore.erase(it);
2416 }
2417
2419 {
2420 SF_LOG_TRACE("lfg.data.group.remove", "Group: %u", GUID_LOPART(guid));
2421 LfgGroupDataContainer::iterator it = GroupsStore.find(guid);
2422 if (it == GroupsStore.end())
2423 return;
2424
2425 LfgState state = GetState(guid);
2426
2427 for (LfgProposalContainer::iterator itProposal = ProposalsStore.begin(); itProposal != ProposalsStore.end();)
2428 {
2429 LfgProposalContainer::iterator itProposalRemove = itProposal++;
2430 bool removeProposal = false;
2431
2432 for (LfgProposalPlayerContainer::iterator itPlayer = itProposalRemove->second.players.begin();
2433 itPlayer != itProposalRemove->second.players.end(); ++itPlayer)
2434 {
2435 if (itPlayer->second.group != guid)
2436 continue;
2437
2438 itPlayer->second.accept = LFG_ANSWER_DENY;
2439 removeProposal = true;
2440 }
2441
2442 if (removeProposal)
2444 }
2445
2446 for (LfgQueueContainer::iterator itQueue = QueuesStore.begin(); itQueue != QueuesStore.end(); ++itQueue)
2447 itQueue->second.RemoveFromQueue(guid);
2448
2449 // If group is being formed after proposal success do nothing more
2450 LfgGuidSet players = it->second.GetPlayers();
2451 for (LfgGuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr)
2452 {
2453 uint64 guid = (*itr);
2454 SetGroup(guid, 0);
2455 if (state != LFG_STATE_PROPOSAL)
2456 {
2457 ClearQueueState(guid, "Remove group data");
2458 if (state != LFG_STATE_NONE)
2459 {
2462 }
2463 }
2464 else
2465 ClearQueueState(guid, "Remove proposal group data");
2466 }
2467
2468 RoleChecksStore.erase(guid);
2469 BootsStore.erase(guid);
2470 GroupsStore.erase(it);
2471 }
2472
2474 {
2475 uint8 team = PlayersStore[guid].GetTeam();
2476 SF_LOG_TRACE("lfg.data.player.team.get", "Player: %u, Team: %u", GUID_LOPART(guid), team);
2477 return team;
2478 }
2479
2481 {
2482 return GroupsStore[gguid].RemovePlayer(guid);
2483 }
2484
2486 {
2487 GroupsStore[gguid].AddPlayer(guid);
2488 }
2489
2490 void LFGMgr::SetLeader(uint64 gguid, uint64 leader)
2491 {
2492 GroupsStore[gguid].SetLeader(leader);
2493 }
2494
2496 {
2498 team = 0;
2499
2500 PlayersStore[guid].SetTeam(team);
2501 }
2502
2504 {
2505 return PlayersStore[guid].GetGroup();
2506 }
2507
2509 {
2510 PlayersStore[guid].SetGroup(group);
2511 }
2512
2514 {
2515 return GroupsStore[guid].GetPlayers();
2516 }
2517
2519 {
2520 return GroupsStore[guid].GetPlayerCount();
2521 }
2522
2524 {
2525 return GroupsStore[guid].GetLeader();
2526 }
2527
2529 {
2530 Player* plr1 = ObjectAccessor::FindPlayer(guid1);
2531 Player* plr2 = ObjectAccessor::FindPlayer(guid2);
2532 uint32 low1 = GUID_LOPART(guid1);
2533 uint32 low2 = GUID_LOPART(guid2);
2534 return plr1 && plr2 && (plr1->GetSocial()->HasIgnore(low2) || plr2->GetSocial()->HasIgnore(low1));
2535 }
2536
2538 {
2539 if (Player* player = ObjectAccessor::FindPlayer(guid))
2540 player->GetSession()->SendLfgRoleChosen(pguid, roles);
2541 }
2542
2544 {
2545 if (Player* player = ObjectAccessor::FindPlayer(guid))
2546 player->GetSession()->SendLfgRoleCheckUpdate(roleCheck);
2547 }
2548
2549 void LFGMgr::SendLfgUpdateStatus(uint64 guid, LfgUpdateData const& data, bool party)
2550 {
2551 if (Player* player = ObjectAccessor::FindPlayer(guid))
2552 player->GetSession()->SendLfgUpdateStatus(data, party);
2553 }
2554
2556 {
2557 if (Player* player = ObjectAccessor::FindPlayer(guid))
2558 player->GetSession()->SendLfgJoinResult(data);
2559 }
2560
2562 {
2563 if (Player* player = ObjectAccessor::FindPlayer(guid))
2564 player->GetSession()->SendLfgBootProposalUpdate(boot);
2565 }
2566
2568 {
2569 if (Player* player = ObjectAccessor::FindPlayer(guid))
2570 player->GetSession()->SendLfgUpdateProposal(proposal);
2571 }
2572
2574 {
2575 if (Player* player = ObjectAccessor::FindPlayer(guid))
2576 player->GetSession()->SendLfgQueueStatus(data);
2577 }
2578
2580 {
2581 return guid && IS_GROUP_GUID(guid) && GroupsStore[guid].IsLfgGroup();
2582 }
2583
2585 {
2586 if (IS_GROUP_GUID(guid))
2587 {
2588 LfgGroupData const& groupData = GroupsStore[guid];
2589 if (groupData.GetQueues().find(groupData.GetActiveQueueId()) != groupData.GetQueues().end())
2590 return groupData.GetActiveQueueId();
2591
2592 LfgGuidSet const& players = GetPlayers(guid);
2593 uint64 pguid = players.empty() ? 0 : (*players.begin());
2594 if (pguid)
2595 return GetQueueId(pguid);
2596 }
2597
2598 LfgPlayerData const& playerData = PlayersStore[guid];
2599 if (playerData.GetQueues().find(playerData.GetActiveQueueId()) != playerData.GetQueues().end())
2600 return playerData.GetActiveQueueId();
2601
2602 return GetTeam(guid);
2603 }
2604
2606 {
2607 uint8 queueId = GetQueueId(guid);
2608 return QueuesStore[queueId];
2609 }
2610
2612 {
2613 if (check.empty())
2614 return false;
2615
2616 for (LfgGuidList::const_iterator it = check.begin(); it != check.end(); ++it)
2617 {
2618 LfgState state = GetState(*it);
2619 if (state != LFG_STATE_QUEUED)
2620 {
2621 if (state != LFG_STATE_PROPOSAL)
2622 SF_LOG_DEBUG("lfg.allqueued", "Unexpected state found while trying to form new group. Guid: %u, State: %s", GUID_LOPART((*it)), GetStateString(state).c_str());
2623 return false;
2624 }
2625 }
2626 return true;
2627 }
2628
2630 {
2631 uint8 queueId = GetQueueId(guid);
2632 LfgQueueContainer::const_iterator itr = QueuesStore.find(queueId);
2633 uint64 queueGuid = guid;
2634 if (!IS_GROUP_GUID(guid))
2635 if (uint64 gguid = GetGroup(guid))
2636 {
2637 LfgState groupState = GetState(gguid);
2638 if (groupState == LFG_STATE_QUEUED || groupState == LFG_STATE_PROPOSAL)
2639 queueGuid = gguid;
2640 }
2641
2642 if (itr != QueuesStore.end())
2643 return itr->second.GetJoinTime(queueGuid);
2644
2645 return 0;
2646 }
2647
2648 // Only for debugging purposes
2650 {
2651 SF_LOG_INFO("lfg", "Clearing all Dungeon Finder runtime state: queues=%u players=%u groups=%u roleChecks=%u proposals=%u boots=%u",
2652 uint32(QueuesStore.size()), uint32(PlayersStore.size()), uint32(GroupsStore.size()),
2653 uint32(RoleChecksStore.size()), uint32(ProposalsStore.size()), uint32(BootsStore.size()));
2654
2655 QueuesStore.clear();
2656 PlayersStore.clear();
2657 GroupsStore.clear();
2658 RoleChecksStore.clear();
2659 ProposalsStore.clear();
2660 BootsStore.clear();
2661 }
2662
2664 {
2665 return m_options & option;
2666 }
2667
2669 {
2670 return m_options;
2671 }
2672
2674 {
2675 m_options = options;
2676 }
2677
2679 {
2680 RestoreActiveQueue(guid);
2681
2682 LfgPlayerData& playerData = PlayersStore[guid];
2683 if (uint64 gguid = GetGroup(guid))
2684 {
2685 if (!sGroupMgr->GetGroupByGUID(GUID_LOPART(gguid)))
2686 {
2687 SF_LOG_DEBUG("lfg.status", "Player %u had stale LFG group %u while requesting status; clearing finder state.",
2688 GUID_LOPART(guid), GUID_LOPART(gguid));
2689 SetGroup(guid, 0);
2690 ClearQueueState(guid, "Stale group status request");
2692 }
2693
2694 RestoreActiveQueue(gguid);
2695 LfgState groupState = GetState(gguid);
2696 if (groupState != LFG_STATE_NONE)
2697 {
2698 LfgDungeonSet statusDungeons = playerData.GetSelectedDungeons();
2699 if (statusDungeons.empty())
2700 if (uint32 dungeon = GetDungeon(gguid, false))
2701 statusDungeons.insert(dungeon);
2702
2703 return LfgUpdateData(LFG_UPDATETYPE_UPDATE_STATUS, groupState, statusDungeons);
2704 }
2705 }
2706
2707 return LfgUpdateData(LFG_UPDATETYPE_UPDATE_STATUS, playerData.GetState(), playerData.GetSelectedDungeons());
2708 }
2709
2711 {
2712 if (!guid)
2713 return false;
2714
2715 for (LfgProposalContainer::const_iterator itr = ProposalsStore.begin(); itr != ProposalsStore.end(); ++itr)
2716 {
2717 LfgProposalPlayerContainer::const_iterator itPlayer = itr->second.players.find(guid);
2718 if (itPlayer == itr->second.players.end())
2719 continue;
2720
2721 SendLfgUpdateProposal(guid, itr->second);
2722 return true;
2723 }
2724
2725 return false;
2726 }
2727
2729 {
2730 if (!guid)
2731 return false;
2732
2733 if (IS_GROUP_GUID(guid))
2734 {
2735 LfgGroupData& groupData = GroupsStore[guid];
2736 uint8 activeQueueId = groupData.GetActiveQueueId();
2737 LfgGroupQueueDataContainer const& queues = groupData.GetQueues();
2738 LfgGroupQueueDataContainer::const_iterator activeItr = queues.find(activeQueueId);
2739 if (activeItr != queues.end() && (activeItr->second.State != LFG_STATE_NONE || activeItr->second.OldState != LFG_STATE_NONE))
2740 return true;
2741
2742 for (LfgGroupQueueDataContainer::const_iterator itr = queues.begin(); itr != queues.end(); ++itr)
2743 {
2744 if (itr->second.State == LFG_STATE_NONE && itr->second.OldState == LFG_STATE_NONE)
2745 continue;
2746
2747 groupData.SetActiveQueueId(itr->first);
2748 return true;
2749 }
2750
2751 return false;
2752 }
2753
2754 LfgPlayerData& playerData = PlayersStore[guid];
2755 uint8 activeQueueId = playerData.GetActiveQueueId();
2756 LfgPlayerQueueDataContainer const& queues = playerData.GetQueues();
2757 LfgPlayerQueueDataContainer::const_iterator activeItr = queues.find(activeQueueId);
2758 if (activeItr != queues.end() && (activeItr->second.State != LFG_STATE_NONE || activeItr->second.OldState != LFG_STATE_NONE))
2759 return true;
2760
2761 for (LfgPlayerQueueDataContainer::const_iterator itr = queues.begin(); itr != queues.end(); ++itr)
2762 {
2763 if (itr->second.State == LFG_STATE_NONE && itr->second.OldState == LFG_STATE_NONE)
2764 continue;
2765
2766 playerData.SetActiveQueueId(itr->first);
2767 return true;
2768 }
2769
2770 return false;
2771 }
2772
2774 {
2775 switch (dungeonId)
2776 {
2777 case 285: // The Headless Horseman
2779 case 286: // The Frost Lord Ahune
2781 case 287: // Coren Direbrew
2783 case 288: // The Crown Chemical Co.
2785 }
2786 return false;
2787 }
2788
2789 std::string LFGMgr::DumpQueueInfo(bool full)
2790 {
2791 uint32 size = uint32(QueuesStore.size());
2792 std::ostringstream o;
2793
2794 o << "Number of Queues: " << size << "\n";
2795 for (LfgQueueContainer::const_iterator itr = QueuesStore.begin(); itr != QueuesStore.end(); ++itr)
2796 {
2797 o << "Queue Id: " << uint32(itr->first) << "\n";
2798 std::string const& queued = itr->second.DumpQueueInfo(full);
2799 std::string const& compatibles = itr->second.DumpCompatibleInfo(full);
2800 o << queued << compatibles;
2801 }
2802
2803 if (full)
2804 {
2805 time_t const currTime = time(NULL);
2806
2807 o << "Role Checks: " << RoleChecksStore.size() << "\n";
2808 for (LfgRoleCheckContainer::const_iterator itr = RoleChecksStore.begin(); itr != RoleChecksStore.end(); ++itr)
2809 {
2810 LfgRoleCheck const& roleCheck = itr->second;
2811 o << " Group " << itr->first
2812 << " state: " << uint32(roleCheck.state)
2813 << " leader: " << roleCheck.leader
2814 << " expires: " << uint32(roleCheck.cancelTime > currTime ? roleCheck.cancelTime - currTime : 0) << "s"
2815 << " random: " << roleCheck.rDungeonId
2816 << " dungeons: " << ConcatenateDungeons(roleCheck.dungeons) << "\n";
2817
2818 for (LfgRolesMap::const_iterator itRoles = roleCheck.roles.begin(); itRoles != roleCheck.roles.end(); ++itRoles)
2819 o << " role " << itRoles->first << ": " << GetRolesString(itRoles->second) << "\n";
2820 }
2821
2822 o << "Proposals: " << ProposalsStore.size() << "\n";
2823 for (LfgProposalContainer::const_iterator itr = ProposalsStore.begin(); itr != ProposalsStore.end(); ++itr)
2824 {
2825 LfgProposal const& proposal = itr->second;
2826 o << " Proposal " << itr->first
2827 << " state: " << uint32(proposal.state)
2828 << " dungeon: " << proposal.dungeonId
2829 << " group: " << proposal.group
2830 << " leader: " << proposal.leader
2831 << " expires: " << uint32(proposal.cancelTime > currTime ? proposal.cancelTime - currTime : 0) << "s"
2832 << " queues: " << ConcatenateGuids(proposal.queues) << "\n";
2833
2834 for (LfgProposalPlayerContainer::const_iterator itPlayer = proposal.players.begin(); itPlayer != proposal.players.end(); ++itPlayer)
2835 {
2836 LfgProposalPlayer const& player = itPlayer->second;
2837 o << " player " << itPlayer->first
2838 << " role: " << GetRolesString(player.role)
2839 << " accept: " << int32(player.accept)
2840 << " group: " << player.group << "\n";
2841 }
2842 }
2843
2844 o << "Boot Votes: " << BootsStore.size() << "\n";
2845 }
2846
2847 return o.str();
2848 }
2849
2851 {
2852 std::ostringstream o;
2853 LfgPlayerDataContainer::const_iterator itr = PlayersStore.find(guid);
2854 if (itr == PlayersStore.end())
2855 {
2856 o << "LFG player data missing for guid " << guid << "\n";
2857 return o.str();
2858 }
2859
2860 LfgPlayerData const& playerData = itr->second;
2861 time_t const currTime = time(NULL);
2862 uint64 const group = playerData.GetGroup();
2863
2864 o << "LFG Player: " << guid << "\n";
2865 o << " Active Queue: " << uint32(playerData.GetActiveQueueId()) << "\n";
2866 o << " Original Group: " << group << "\n";
2867 if (group)
2868 o << " Original Group Exists: " << (sGroupMgr->GetGroupByGUID(GUID_LOPART(group)) ? "yes" : "no") << "\n";
2869 o << " State: " << GetStateString(playerData.GetState()) << " old: " << GetStateString(playerData.GetOldState()) << "\n";
2870 o << " Roles: " << GetRolesString(playerData.GetRoles()) << "\n";
2871 o << " Dungeons: " << ConcatenateDungeons(playerData.GetSelectedDungeons()) << "\n";
2872 o << " Locked Dungeons: " << GetLockedDungeons(guid).size() << "\n";
2873 if (!playerData.GetComment().empty())
2874 o << " Comment: " << playerData.GetComment() << "\n";
2875
2876 LfgPlayerQueueDataContainer const& queues = playerData.GetQueues();
2877 o << " Saved Queues: " << queues.size() << "\n";
2878 for (LfgPlayerQueueDataContainer::const_iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue)
2879 {
2880 time_t joinTime = 0;
2881 LfgQueueContainer::const_iterator itLfgQueue = QueuesStore.find(itQueue->first);
2882 if (itLfgQueue != QueuesStore.end())
2883 joinTime = itLfgQueue->second.GetJoinTime(guid);
2884
2885 o << " Queue " << uint32(itQueue->first)
2886 << " state: " << GetStateString(itQueue->second.State)
2887 << " old: " << GetStateString(itQueue->second.OldState)
2888 << " roles: " << GetRolesString(itQueue->second.Roles)
2889 << " dungeons: " << ConcatenateDungeons(itQueue->second.SelectedDungeons);
2890
2891 if (joinTime)
2892 o << " queued: " << uint32(currTime > joinTime ? currTime - joinTime : 0) << "s";
2893
2894 if (!itQueue->second.Comment.empty())
2895 o << " comment: " << itQueue->second.Comment;
2896
2897 o << "\n";
2898 }
2899
2900 return o.str();
2901 }
2902
2904 {
2905 std::ostringstream o;
2906 LfgGroupDataContainer::const_iterator itr = GroupsStore.find(guid);
2907 if (itr == GroupsStore.end())
2908 {
2909 o << "LFG group data missing for guid " << guid << "\n";
2910 return o.str();
2911 }
2912
2913 LfgGroupData const& groupData = itr->second;
2914 time_t const currTime = time(NULL);
2915
2916 o << "LFG Group: " << guid << "\n";
2917 o << " Is LFG Group: " << (groupData.IsLfgGroup() ? "yes" : "no") << "\n";
2918 o << " Active Queue: " << uint32(groupData.GetActiveQueueId()) << "\n";
2919 o << " State: " << GetStateString(groupData.GetState()) << " old: " << GetStateString(groupData.GetOldState()) << "\n";
2920 o << " Dungeon: " << groupData.GetDungeon(true) << "\n";
2921 o << " Leader: " << groupData.GetLeader() << "\n";
2922 o << " Players: " << groupData.GetPlayers().size() << "\n";
2923 o << " Kicks Left: " << uint32(groupData.GetKicksLeft()) << "\n";
2924 o << " Vote Kick: " << (groupData.IsVoteKickActive() ? "active" : "inactive") << "\n";
2925
2926 LfgGroupQueueDataContainer const& queues = groupData.GetQueues();
2927 o << " Saved Queues: " << queues.size() << "\n";
2928 for (LfgGroupQueueDataContainer::const_iterator itQueue = queues.begin(); itQueue != queues.end(); ++itQueue)
2929 {
2930 time_t joinTime = 0;
2931 LfgQueueContainer::const_iterator itLfgQueue = QueuesStore.find(itQueue->first);
2932 if (itLfgQueue != QueuesStore.end())
2933 joinTime = itLfgQueue->second.GetJoinTime(guid);
2934
2935 o << " Queue " << uint32(itQueue->first)
2936 << " state: " << GetStateString(itQueue->second.State)
2937 << " old: " << GetStateString(itQueue->second.OldState)
2938 << " dungeon: " << itQueue->second.Dungeon;
2939
2940 if (joinTime)
2941 o << " queued: " << uint32(currTime > joinTime ? currTime - joinTime : 0) << "s";
2942
2943 o << "\n";
2944 }
2945
2946 for (LfgGuidSet::const_iterator itPlayer = groupData.GetPlayers().begin(); itPlayer != groupData.GetPlayers().end(); ++itPlayer)
2947 o << " Member: " << *itPlayer << "\n";
2948
2949 return o.str();
2950 }
2951
2953 {
2954 LfgDungeonSet dungeons;
2955 dungeons.insert(GetDungeon(gguid));
2956 SetActiveQueueId(guid, GetActiveQueueId(gguid));
2957 SetSelectedDungeons(guid, dungeons);
2958 SetState(guid, GetState(gguid));
2959 SetGroup(guid, gguid);
2960 AddPlayerToGroup(gguid, guid);
2961 }
2962
2964 {
2965 if (GetState(guid) != LFG_STATE_NONE)
2966 {
2967 LfgDungeonSet const& dungeons = GetSelectedDungeons(guid);
2968 if (!dungeons.empty())
2969 {
2970 LFGDungeonData const* dungeon = GetLFGDungeon(*dungeons.begin());
2971 if (dungeon && (dungeon->type == LFG_TYPE_RANDOM || dungeon->seasonal))
2972 return true;
2973 }
2974 }
2975
2976 return false;
2977 }
2978
2980 {
2981 if (IS_GROUP_GUID(guid))
2982 {
2983 if (uint32 dungeonId = GetDungeon(guid, true))
2984 if (LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId))
2985 if (uint32(dungeon->map) == map && dungeon->difficulty == difficulty)
2986 return true;
2987
2988 return false;
2989 }
2990
2991 if (uint64 gguid = GetGroup(guid))
2992 if (uint32 dungeonId = GetDungeon(gguid, true))
2993 if (LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId))
2994 if (uint32(dungeon->map) == map && dungeon->difficulty == difficulty)
2995 return true;
2996
2997 LfgDungeonSet const& selectedDungeons = GetSelectedDungeons(guid);
2998 for (LfgDungeonSet::const_iterator itr = selectedDungeons.begin(); itr != selectedDungeons.end(); ++itr)
2999 if (LFGDungeonData const* dungeon = GetLFGDungeon(*itr))
3000 if (uint32(dungeon->map) == map && dungeon->difficulty == difficulty)
3001 return true;
3002
3003 return false;
3004 }
3005
3007 {
3008 if (id)
3009 if (LFGDungeonData const* dungeon = GetLFGDungeon(id))
3010 return dungeon->Entry();
3011
3012 return 0;
3013 }
3014
3016 {
3017 if (id)
3018 if (LFGDungeonData const* dungeon = GetLFGDungeon(id))
3019 return dungeon->category;
3020
3021 return 0;
3022 }
3023
3025 {
3026 LfgDungeonSet randomDungeons;
3027 for (lfg::LFGDungeonContainer::const_iterator itr = LfgDungeonStore.begin(); itr != LfgDungeonStore.end(); ++itr)
3028 {
3029 lfg::LFGDungeonData const& dungeon = itr->second;
3030 if ((dungeon.type == lfg::LFG_TYPE_RANDOM || (dungeon.seasonal && sLFGMgr->IsSeasonActive(dungeon.id)))
3031 && dungeon.expansion <= expansion && dungeon.minlevel <= level && level <= dungeon.maxlevel)
3032 randomDungeons.insert(dungeon.Entry());
3033 }
3034 return randomDungeons;
3035 }
3036
3037} // namespace lfg
@ CHAR_INS_LFG_DATA
@ CHAR_DEL_LFG_DATA
@ ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS
Definition DBCEnums.h:270
DifficultyID
Definition DBCEnums.h:330
@ DIFFICULTY_SCE_HEROIC
Definition DBCEnums.h:341
@ DIFFICULTY_NORMAL
Definition DBCEnums.h:332
@ DIFFICULTY_SCE_NORMAL
Definition DBCEnums.h:342
@ DIFFICULTY_HEROIC
Definition DBCEnums.h:333
@ DIFFICULTY_25MAN_LFR
Definition DBCEnums.h:338
@ DIFFICULTY_FLEX
Definition DBCEnums.h:343
DBCStorage< LFGDungeonEntry > sLFGDungeonStore(LFGDungeonEntryfmt)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
@ DISABLE_TYPE_MAP
Definition DisableMgr.h:17
#define ASSERT
Definition Errors.h:29
bool IsHolidayActive(HolidayIds id)
#define MAXGROUPSIZE
Definition Group.h:29
#define MAXRAIDSIZE
Definition Group.h:30
#define sGroupMgr
Definition GroupMgr.h:44
#define sInstanceSaveMgr
#define sLFGMgr
Definition LFGMgr.h:518
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_WARN(filterType__,...)
Definition Log.h:140
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_TRACE(filterType__,...)
Definition Log.h:131
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
#define sMapMgr
Definition MapManager.h:145
uint32 GUID_LOPART(uint64 x)
bool IS_GROUP_GUID(uint64 guid)
@ HIGHGUID_PLAYER
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ FATIGUE_TIMER
Definition Player.h:592
Skyfire::AutoPtr< ResultSet, Skyfire::Mutex > QueryResult
Definition QueryResult.h:48
Role Based Access Control related classes definition.
@ GROUP_REMOVEMETHOD_KICK_LFG
@ ALLIANCE
@ HORDE
@ HOLIDAY_LOVE_IS_IN_THE_AIR
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:22
uint32 getMSTime()
Definition Timer.h:12
Skyfire::AutoPtr< Transaction, Skyfire::Mutex > SQLTransaction
Definition Transaction.h:42
@ UNIT_STATE_JUMPING
Definition Unit.h:530
static Summons Group[]
Definition boss_urom.cpp:65
Definition Field.h:16
uint8 GetUInt8() const
Definition Field.h:26
float GetFloat() const
Definition Field.h:177
uint32 GetUInt32() const
Definition Field.h:105
Definition Group.h:147
bool isLFGGroup() const
Definition Group.cpp:2543
InstanceGroupBind * BindToInstance(InstanceSave *save, bool permanent, bool load=false)
Definition Group.cpp:2426
bool AddMember(Player *player)
Definition Group.cpp:353
void SendUpdate()
Definition Group.cpp:1594
void SetDungeonDifficulty(DifficultyID difficulty)
Definition Group.cpp:2240
void ConvertToRaid()
Definition Group.cpp:229
uint32 GetMembersCount() const
Definition Group.h:227
uint64 GetGUID() const
Definition Group.cpp:2573
void SetLfgRoles(uint64 guid, const uint8 roles)
Definition Group.cpp:2528
void ConvertToLFG()
Definition Group.cpp:212
void SetRaidDifficulty(DifficultyID difficulty)
Definition Group.cpp:2264
bool IsMember(uint64 guid) const
Definition Group.cpp:2603
bool RemoveMember(uint64 guid, const RemoveMethod &method=GROUP_REMOVEMETHOD_DEFAULT, uint64 kicker=0, const char *reason=NULL)
Definition Group.cpp:501
GroupReference * GetFirstMember()
Definition Group.h:225
uint32 GetMemberRole(uint64 guid) const
Definition Group.cpp:2837
bool RoleCheckAllResponded() const
Definition Group.cpp:2846
bool Create(Player *leader)
Definition Group.cpp:81
InstanceGroupBind * GetBoundInstance(Player *player)
Definition Group.cpp:2393
uint32 GetDbStoreId() const
Definition Group.h:206
uint64 GetLeaderGUID() const
Definition Group.cpp:2568
bool IsLeader(uint64 guid) const
Definition Group.cpp:2608
bool isRaidGroup() const
Definition Group.cpp:2548
void ChangeLeader(uint64 guid)
Definition Group.cpp:628
GroupReference * next()
bool IsInstance() const
Definition Map.h:368
static bool IsValidMapCoord(uint32 mapid, float x, float y)
Definition MapManager.h:75
void MovementExpired(bool reset=true)
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
bool IsInWorld() const
Definition Object.h:114
uint32 GetTeam() const
Definition Player.h:2527
void RewardQuest(Quest const *quest, uint32 reward, Object *questGiver, bool announce=true)
InstancePlayerBind * GetBoundInstance(uint32 mapid, DifficultyID difficulty)
Definition Player.cpp:13877
bool GetQuestRewardStatus(uint32 quest_id) const
bool HasItemCount(uint32 item, uint32 count=1, bool inBankAlso=false) const
void SetBattlegroundEntryPoint()
Definition Player.cpp:17930
bool InBattleground() const
Definition Player.h:2692
bool IsMirrorTimerActive(MirrorTimerType type)
Definition Player.cpp:1215
bool CanRewardQuest(Quest const *quest, bool msg)
bool HasAchieved(uint32 achievementId) const
Definition Player.cpp:21013
WorldSession * GetSession() const
Definition Player.h:2417
bool InBattlegroundQueue() const
Definition Player.cpp:19220
bool TeleportToBGEntryPoint()
Definition Player.cpp:2341
float GetAverageItemLevel()
Definition Player.cpp:22428
Group * GetGroup()
Definition Player.h:2972
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, Unit *unit=NULL)
Definition Player.cpp:21033
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
void SetSemaphoreTeleportForcedFar(bool semphsetting)
Definition Player.h:2521
static void RemoveFromGroup(Group *group, uint64 guid, RemoveMethod method=GROUP_REMOVEMETHOD_DEFAULT, uint64 kicker=0, const char *reason=NULL)
Definition Player.cpp:3059
PlayerSocial * GetSocial()
Definition Player.h:1346
bool InArena() const
Definition Player.cpp:19310
void SetForcedTeleportFar(bool forced)
Definition Player.h:2514
void CleanupAfterTaxiFlight()
Definition Player.cpp:16748
bool IsBeingTeleported() const
Definition Player.h:2493
bool HasIgnore(uint32 ignore_guid)
void setUInt32(const uint8 index, const uint32 value)
Vehicle * GetVehicle() const
Definition Unit.h:2743
uint64 GetCharmGUID() const
Definition Unit.h:2079
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
bool IsAlive() const
Definition Unit.h:2032
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
bool IsInFlight() const
Definition Unit.h:1891
bool HasUnitState(const uint32 f) const
Definition Unit.h:1485
uint8 getLevel() const
Definition Unit.h:1528
bool IsFalling() const
Definition Unit.cpp:8388
bool IsInCombat() const
Definition Unit.h:1896
uint32 GetMapId() const
Definition Object.h:546
Map * GetMap() const
Definition Object.h:740
std::string const & GetName() const
Definition Object.h:664
void SendLfgJoinResult(lfg::LfgJoinResultData const &joinData)
uint8 Expansion() const
void SendLfgTeleportError(uint8 err)
void SendLfgPlayerReward(lfg::LfgPlayerRewardData const &lfgPlayerRewardData)
void SendLfgUpdateStatus(lfg::LfgUpdateData const &updateData, bool party, uint64 queueGuidOverride=0, uint8 queueIdOverride=0)
bool HasPermission(uint32 permissionId)
void SetActiveQueueId(uint64 guid, uint8 queueId)
Definition LFGMgr.cpp:2366
void SendLfgRoleCheckUpdate(uint64 guid, LfgRoleCheck const &roleCheck)
Definition LFGMgr.cpp:2543
void SetSelectedDungeons(uint64 guid, LfgDungeonSet const &dungeons)
Definition LFGMgr.cpp:2398
static bool CheckDpsOnlyRoles(LfgRolesMap &groles, uint8 neededDamage)
Assigns queued players to damage roles for role-neutral scenario queues.
Definition LFGMgr.cpp:1114
void RemovePlayerData(uint64 guid)
Definition LFGMgr.cpp:2410
bool inLfgDungeonMap(uint64 guid, uint32 map, DifficultyID difficulty)
Check if given guid applied for given map and difficulty. Used to know.
Definition LFGMgr.cpp:2979
uint32 GetLFGDungeonEntry(uint32 id)
Return Lfg dungeon entry for given dungeon id.
Definition LFGMgr.cpp:3006
void LoadLFGDungeons(bool reload=false)
Loads dungeons from dbc and adds teleport coords.
Definition LFGMgr.cpp:292
void SetupGroupMember(uint64 guid, uint64 gguid)
Initializes player data after loading group data from DB.
Definition LFGMgr.cpp:2952
void LeaveSoloLfg(uint64 guid, uint32 queueID, bool disconnected=false)
Leaves Solo lfg.
Definition LFGMgr.cpp:838
uint32 GetDungeon(uint64 guid, bool asId=true)
Get current dungeon.
Definition LFGMgr.cpp:2093
LfgProposalContainer ProposalsStore
Current Proposals.
Definition LFGMgr.h:510
uint64 GetGroup(uint64 guid)
Gets player group.
Definition LFGMgr.cpp:2503
std::string const & GetComment(uint64 gguid)
Get current player comment (used for LFR).
Definition LFGMgr.cpp:2150
void SetTeam(uint64 guid, uint8 team)
Sets player team.
Definition LFGMgr.cpp:2495
void ClearQueueState(uint64 guid, char const *debugMsg)
Definition LFGMgr.cpp:2305
bool RestoreActiveQueue(uint64 guid)
Restores the active queue id from saved queue data.
Definition LFGMgr.cpp:2728
bool IsRaidFinderDungeon(uint32 dungeonId)
Check whether the dungeon id belongs to a Raid Finder queue entry.
Definition LFGMgr.cpp:2049
void LeaveLfg(uint64 guid, bool disconnected=false)
Leaves lfg.
Definition LFGMgr.cpp:778
uint8 RemovePlayerFromGroup(uint64 gguid, uint64 guid)
Removes a player from a group.
Definition LFGMgr.cpp:2480
LFGDungeonContainer LfgDungeonStore
Definition LFGMgr.h:507
LfgPlayerBootContainer BootsStore
Current player kicks.
Definition LFGMgr.h:511
LfgDungeonSet const & GetSelectedDungeons(uint64 guid)
Get selected dungeons.
Definition LFGMgr.cpp:2156
uint8 GetTeam(uint64 guid)
Definition LFGMgr.cpp:2473
void SetComment(uint64 guid, std::string const &comment)
Sets player lfr comment.
Definition LFGMgr.cpp:2392
void ClearGroupQueueState(uint64 guid, char const *debugMsg, bool sendUpdate)
Definition LFGMgr.cpp:2318
void UpdateBoot(uint64 guid, bool accept)
Updates player boot proposal with new player answer.
Definition LFGMgr.cpp:1666
void SetGroup(uint64 guid, uint64 group)
Sets player group.
Definition LFGMgr.cpp:2508
void SendLfgUpdateStatus(uint64 guid, LfgUpdateData const &data, bool party)
Definition LFGMgr.cpp:2549
void Update(uint32 diff)
Definition LFGMgr.cpp:410
bool m_debugRequirementOverride
bypasses LFG entry requirements for server-wide debugging
Definition LFGMgr.h:500
std::string DumpQueueInfo(bool full=false)
Dumps the state of the queue - Only for internal testing.
Definition LFGMgr.cpp:2789
bool selectedRandomLfgDungeon(uint64 guid)
Check if given guid applied for random dungeon.
Definition LFGMgr.cpp:2963
LfgGuidSet const & GetPlayers(uint64 guid)
Definition LFGMgr.cpp:2513
void DecreaseKicksLeft(uint64 guid)
Definition LFGMgr.cpp:2404
time_t GetQueueJoinTime(uint64 guid)
Gets queue join time.
Definition LFGMgr.cpp:2629
LfgUpdateData GetLfgStatus(uint64 guid)
Returns current lfg status.
Definition LFGMgr.cpp:2678
void RestoreOrClearState(uint64 guid, char const *debugMsg)
Definition LFGMgr.cpp:2272
void UpdateRoleCheck(uint64 gguid, uint64 guid=0, uint8 roles=PLAYER_ROLE_NONE)
Updates the role check with player answer.
Definition LFGMgr.cpp:894
uint32 GetOptions()
Gets current lfg options.
Definition LFGMgr.cpp:2668
LfgState GetState(uint64 guid)
Get current lfg state.
Definition LFGMgr.cpp:2061
LfgLockMap const GetLockedDungeons(uint64 guid)
Get locked dungeons.
Definition LFGMgr.cpp:2162
void GetCompatibleDungeons(LfgDungeonSet &dungeons, LfgGuidSet const &players, LfgLockPartyMap &lockMap, bool isContinue)
Definition LFGMgr.cpp:1021
LfgDungeonSet const & GetDungeonsByRandom(uint32 randomdungeon)
Definition LFGMgr.cpp:2005
void ClearDungeonGroupState(uint64 guid, uint32 dbGuid, char const *debugMsg, bool sendUpdate)
Clears active dungeon finder state for an LFG dungeon group.
Definition LFGMgr.cpp:2354
bool MakeNewGroup(LfgProposal const &proposal)
Definition LFGMgr.cpp:1152
void SetRoles(uint64 guid, uint8 roles)
Sets player lfg roles.
Definition LFGMgr.cpp:2386
static void SendLfgQueueStatus(uint64 guid, LfgQueueStatusData const &data)
Sends queue status to player.
Definition LFGMgr.cpp:2573
uint8 GetKicksLeft(uint64 gguid)
Get kicks left in current group.
Definition LFGMgr.cpp:2244
void SetDungeon(uint64 guid, uint32 dungeon)
Definition LFGMgr.cpp:2380
void SendLfgBootProposalUpdate(uint64 guid, LfgPlayerBoot const &boot)
Definition LFGMgr.cpp:2561
bool IsVoteKickActive(uint64 gguid)
Get current vote kick state.
Definition LFGMgr.cpp:2136
void LoadRewards()
Loads rewards for random dungeons.
Definition LFGMgr.cpp:224
void SendLfgUpdateProposal(uint64 guid, LfgProposal const &proposal)
Definition LFGMgr.cpp:2567
LfgCachedDungeonContainer CachedDungeonMapStore
Stores all dungeons by groupType.
Definition LFGMgr.h:504
bool isOptionEnabled(uint32 option)
Checks if given lfg option is enabled.
Definition LFGMgr.cpp:2663
void Clean()
Clears queue - Only for internal testing.
Definition LFGMgr.cpp:2649
LfgRoleCheckContainer RoleChecksStore
Current Role checks.
Definition LFGMgr.h:509
void TeleportDungeonGroupOut(Group *group)
Teleport online members of an LFG dungeon group back to their saved entry points.
Definition LFGMgr.cpp:1873
void SetOptions(uint32 options)
Sets new lfg options.
Definition LFGMgr.cpp:2673
uint32 m_lfgProposalId
used as internal counter for proposals
Definition LFGMgr.h:498
void AddPlayerToGroup(uint64 gguid, uint64 guid)
Adds player to group.
Definition LFGMgr.cpp:2485
LFGDungeonData const * GetLFGDungeon(uint32 id)
Definition LFGMgr.cpp:283
void RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdateType type)
Definition LFGMgr.cpp:1490
bool m_debugFlexRaidMinimumOverride
allows flexible raid queues to form below normal minimum for debugging
Definition LFGMgr.h:501
void SetVoteKick(uint64 guid, bool active)
Definition LFGMgr.cpp:2143
void TeleportPlayer(Player *player, bool out, bool fromOpcode=false, bool forceChangeInstance=false)
Teleport a player to/from selected dungeon.
Definition LFGMgr.cpp:1738
uint64 GetLeader(uint64 guid)
Get leader of the group (using internal data).
Definition LFGMgr.cpp:2523
void JoinLfg(Player *player, uint8 roles, LfgDungeonSet &dungeons, std::string const &comment)
Join Lfg with selected roles, dungeons and comment.
Definition LFGMgr.cpp:538
uint8 GetActiveQueueId(uint64 guid)
Get active LFG queue id.
Definition LFGMgr.cpp:2119
LfgRewardContainer RewardMapStore
Stores rewards for random dungeons.
Definition LFGMgr.h:506
void RestoreState(uint64 guid, char const *debugMsg)
Definition LFGMgr.cpp:2251
uint8 GetQueueId(uint64 guid)
Returns queue id.
Definition LFGMgr.cpp:2584
LFGQueue & GetQueue(uint64 guid)
Definition LFGMgr.cpp:2605
uint8 GetPlayerCount(uint64 guid)
Gets the player count of given group.
Definition LFGMgr.cpp:2518
void SendLfgJoinResult(uint64 guid, LfgJoinResultData const &data)
Definition LFGMgr.cpp:2555
LfgGroupDataContainer GroupsStore
Group data.
Definition LFGMgr.h:513
static bool HasIgnore(uint64 guid1, uint64 guid2)
Checks if given players are ignoring each other.
Definition LFGMgr.cpp:2528
bool IsDebugRequirementOverrideEnabled() const
Gets the server-wide debug override for dungeon and raid finder requirements.
Definition LFGMgr.h:363
void ClearState(uint64 guid, char const *debugMsg)
Definition LFGMgr.cpp:2300
void UpdateProposal(uint32 proposalId, uint64 guid, bool accept)
Updates proposal to join dungeon with player answer.
Definition LFGMgr.cpp:1308
uint32 m_options
Stores config options.
Definition LFGMgr.h:499
void _LoadFromDB(Field *fields, uint64 guid)
Load Lfg group info from DB.
Definition LFGMgr.cpp:173
static bool CheckGroupRoles(LfgRolesMap &groles)
Checks if given roles match, modifies given roles map with new roles.
Definition LFGMgr.cpp:1073
void SetState(uint64 guid, LfgState state)
Definition LFGMgr.cpp:2280
void SetLeader(uint64 gguid, uint64 leader)
Sets the leader of the group.
Definition LFGMgr.cpp:2490
uint8 GetRoles(uint64 guid)
Get current player roles.
Definition LFGMgr.cpp:2112
LfgPlayerDataContainer PlayersStore
Player data.
Definition LFGMgr.h:512
LfgQueueContainer QueuesStore
Queues.
Definition LFGMgr.h:503
uint32 AddProposal(LfgProposal &proposal)
Add a new Proposal.
Definition LFGMgr.cpp:1294
void FinishDungeon(uint64 gguid, uint32 dungeonId)
Finish the dungeon for the given group. All check are performed using internal lfg data.
Definition LFGMgr.cpp:1903
bool IsSeasonActive(uint32 dungeonId)
Checks if Seasonal dungeon is active.
Definition LFGMgr.cpp:2773
bool AllQueued(LfgGuidList const &check)
Checks if all players are queued.
Definition LFGMgr.cpp:2611
LfgType GetDungeonType(uint32 dungeon)
Definition LFGMgr.cpp:2040
static bool CheckFlexibleRaidRoles(LfgRolesMap &groles, uint8 maxPlayers)
Assigns queued players to their preferred combat role for flexible raid queues.
Definition LFGMgr.cpp:1125
void _SaveToDB(uint64 guid, uint32 db_guid)
Definition LFGMgr.cpp:203
std::string DumpGroupInfo(uint64 guid)
Dumps queue-scoped group state - Only for internal testing.
Definition LFGMgr.cpp:2903
std::string DumpPlayerInfo(uint64 guid)
Dumps queue-scoped player state - Only for internal testing.
Definition LFGMgr.cpp:2850
LfgState GetOldState(uint64 guid)
Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON).
Definition LFGMgr.cpp:2077
bool IsFlexibleRaidDungeon(uint32 dungeonId)
Check whether the dungeon id belongs to a flexible raid queue entry.
Definition LFGMgr.cpp:2055
void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles)
Definition LFGMgr.cpp:2537
LfgReward const * GetRandomDungeonReward(uint32 dungeon, uint8 level)
Gets the random dungeon reward corresponding to given dungeon and player level.
Definition LFGMgr.cpp:2019
bool IsLfgGroup(uint64 guid)
Check if given group guid is lfg.
Definition LFGMgr.cpp:2579
bool SendActiveProposal(uint64 guid)
Resends an active dungeon proposal to a player if one exists.
Definition LFGMgr.cpp:2710
void InitBoot(uint64 gguid, uint64 kguid, uint64 vguid, std::string const &reason)
Inits new proposal to boot a player.
Definition LFGMgr.cpp:1615
uint32 m_QueueTimer
used to check interval of update
Definition LFGMgr.h:497
void RemoveGroupData(uint64 guid)
Removes saved group data.
Definition LFGMgr.cpp:2418
uint32 GetDungeonMapId(uint64 guid)
Get the map id of the current dungeon.
Definition LFGMgr.cpp:2100
LfgDungeonSet GetRandomAndSeasonalDungeons(uint8 level, uint8 expansion)
Returns all random and seasonal dungeons for given level and expansion.
Definition LFGMgr.cpp:3024
uint8 GetLFGDungeonCategory(uint32 id)
Return Lfg dungeon category for given dungeon id.
Definition LFGMgr.cpp:3015
void RemoveFromQueue(uint64 guid)
Definition LFGQueue.cpp:308
void AddToQueue(uint64 guid, bool reQueue=false)
Definition LFGQueue.cpp:293
time_t GetJoinTime(uint64 guid) const
Definition LFGQueue.cpp:836
void UpdateWaitTimeAvg(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:371
bool HasQueueData(uint64 guid) const
Definition LFGQueue.cpp:366
void UpdateWaitTimeHealer(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:385
void UpdateWaitTimeTank(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:378
void UpdateWaitTimeDps(int32 waitTime, uint32 dungeonId)
Definition LFGQueue.cpp:392
void AddQueueData(uint64 guid, time_t joinTime, LfgDungeonSet const &dungeons, LfgRolesMap const &rolesMap)
Definition LFGQueue.cpp:353
uint32 GetDungeon(bool asId=true) const
bool IsVoteKickActive() const
uint64 GetLeader() const
bool IsLfgGroup() const
void SetVoteKick(bool active)
LfgState GetState() const
void SetActiveQueueId(uint8 queueId)
void SetState(LfgState state)
uint8 GetActiveQueueId() const
uint8 GetKicksLeft() const
LfgGuidSet const & GetPlayers() const
LfgState GetOldState() const
LfgGroupQueueDataContainer const & GetQueues() const
LfgReturnLocation const & GetReturnLocation() const
LfgState GetOldState() const
LfgPlayerQueueDataContainer const & GetQueues() const
std::string const & GetComment() const
void SetState(LfgState state)
uint8 GetActiveQueueId() const
uint8 GetRoles() const
LfgState GetState() const
uint64 GetGroup() const
void SetActiveQueueId(uint8 queueId)
LfgDungeonSet const & GetSelectedDungeons() const
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
WorldDatabaseWorkerPool WorldDatabase
Accessor to the world database.
Definition Main.cpp:40
#define sWorld
Definition World.h:910
WorldIntConfigs
Definition World.h:198
@ CONFIG_LFG_OPTIONSMASK
Definition World.h:331
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:224
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP
Definition World.h:98
bool IsDisabledFor(DisableType type, uint32 entry, Unit const *unit, uint8 flags)
bool IsValidMapCoord(float c)
Definition LFG.cpp:11
bool IsValidPlayerRoles(uint8 roles)
Definition LFG.cpp:28
@ LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION
Definition LFG.h:75
@ LFG_LOCKSTATUS_TOO_LOW_LEVEL
Definition LFG.h:76
@ LFG_LOCKSTATUS_RAID_LOCKED
Definition LFG.h:80
@ LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE
Definition LFG.h:78
@ LFG_LOCKSTATUS_MISSING_ITEM
Definition LFG.h:84
@ LFG_LOCKSTATUS_TOO_HIGH_LEVEL
Definition LFG.h:77
@ LFG_LOCKSTATUS_MISSING_ACHIEVEMENT
Definition LFG.h:86
@ LFG_LOCKSTATUS_NOT_IN_SEASON
Definition LFG.h:85
@ LFG_LOCKSTATUS_QUEST_NOT_COMPLETED
Definition LFG.h:83
@ LFG_HEALERS_NEEDED
Definition LFG.h:17
@ LFG_TANKS_NEEDED
Definition LFG.h:16
@ LFG_DPS_NEEDED
Definition LFG.h:18
@ LFG_OPTION_ENABLE_DUNGEON_FINDER
Definition LFGMgr.h:26
@ LFG_OPTION_ENABLE_RAID_BROWSER
Definition LFGMgr.h:27
std::map< uint8, LfgGroupQueueData > LfgGroupQueueDataContainer
LfgTeleportError
Teleport errors.
Definition LFGMgr.h:79
@ LFG_TELEPORTERROR_INVALID_LOCATION
Definition LFGMgr.h:86
@ LFG_TELEPORTERROR_OK
Definition LFGMgr.h:81
@ LFG_TELEPORTERROR_FATIGUE
Definition LFGMgr.h:85
@ LFG_TELEPORTERROR_PLAYER_DEAD
Definition LFGMgr.h:82
@ LFG_TELEPORTERROR_CHARMING
Definition LFGMgr.h:88
@ LFG_TELEPORTERROR_FALLING
Definition LFGMgr.h:83
@ LFG_TELEPORTERROR_IN_COMBAT
Definition LFGMgr.h:87
@ LFG_TELEPORTERROR_IN_VEHICLE
Definition LFGMgr.h:84
LfgState
Definition LFG.h:61
@ LFG_STATE_RAIDBROWSER
Definition LFG.h:69
@ LFG_STATE_ROLECHECK
Definition LFG.h:63
@ LFG_STATE_FINISHED_DUNGEON
Definition LFG.h:68
@ LFG_STATE_DUNGEON
Definition LFG.h:67
@ LFG_STATE_PROPOSAL
Definition LFG.h:65
@ LFG_STATE_BOOT
Definition LFG.h:66
@ LFG_STATE_NONE
Definition LFG.h:62
@ LFG_STATE_QUEUED
Definition LFG.h:64
LfgUpdateType
Definition LFG.h:39
@ LFG_UPDATETYPE_ROLECHECK_FAILED
Definition LFG.h:44
@ LFG_UPDATETYPE_GROUP_FOUND
Definition LFG.h:48
@ LFG_UPDATETYPE_ADDED_TO_QUEUE
Definition LFG.h:49
@ LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE
Definition LFG.h:52
@ LFG_UPDATETYPE_UPDATE_STATUS
Definition LFG.h:51
@ LFG_UPDATETYPE_PROPOSAL_FAILED
Definition LFG.h:46
@ LFG_UPDATETYPE_PROPOSAL_DECLINED
Definition LFG.h:47
@ LFG_UPDATETYPE_REMOVED_FROM_QUEUE
Definition LFG.h:45
@ LFG_UPDATETYPE_PROPOSAL_BEGIN
Definition LFG.h:50
@ LFG_UPDATETYPE_JOIN_QUEUE
Definition LFG.h:43
@ LFG_SPELL_DUNGEON_COOLDOWN
Definition LFGMgr.h:36
@ LFG_TIME_BOOT
Definition LFGMgr.h:33
@ LFG_GROUP_KICK_VOTES_NEEDED
Definition LFGMgr.h:39
@ LFG_TIME_ROLECHECK
Definition LFGMgr.h:32
@ LFG_QUEUEUPDATE_INTERVAL
Definition LFGMgr.h:35
@ LFG_SPELL_DUNGEON_DESERTER
Definition LFGMgr.h:37
LfgType
Determines the type of instance.
Definition LFGMgr.h:62
@ LFG_TYPE_NONE
Definition LFGMgr.h:63
@ LFG_TYPE_RANDOM
Definition LFGMgr.h:66
@ LFG_TYPE_RAID
Definition LFGMgr.h:65
@ LFG_TYPE_DUNGEON
Definition LFGMgr.h:64
LfgAnswer
Answer state (Also used to check compatibilites).
Definition LFG.h:91
@ LFG_ANSWER_AGREE
Definition LFG.h:94
@ LFG_ANSWER_PENDING
Definition LFG.h:92
@ LFG_ANSWER_DENY
Definition LFG.h:93
std::map< uint32, LfgLockData > LfgLockMap
Definition LFG.h:108
std::set< uint32 > LfgDungeonSet
Definition LFG.h:107
std::list< uint64 > LfgGuidList
Definition LFG.h:111
@ LFG_ROLECHECK_WRONG_ROLES
Definition LFGMgr.h:121
@ LFG_ROLECHECK_MISSING_ROLE
Definition LFGMgr.h:120
@ LFG_ROLECHECK_ABORTED
Definition LFGMgr.h:122
@ LFG_ROLECHECK_DEFAULT
Definition LFGMgr.h:117
@ LFG_ROLECHECK_FINISHED
Definition LFGMgr.h:118
@ LFG_ROLECHECK_NO_ROLE
Definition LFGMgr.h:123
@ LFG_ROLECHECK_INITIALITING
Definition LFGMgr.h:119
std::string GetStateString(LfgState state)
Definition LFG.cpp:70
std::string ConcatenateGuids(LfgGuidList const &guids)
Definition LFGQueue.cpp:246
std::pair< LfgRewardContainer::const_iterator, LfgRewardContainer::const_iterator > LfgRewardContainerBounds
Definition LFGMgr.h:137
std::map< uint64, uint8 > LfgRolesMap
Definition LFG.h:112
@ PLAYER_ROLE_DAMAGE
Definition LFG.h:27
@ PLAYER_ROLE_TANK
Definition LFG.h:25
@ PLAYER_ROLE_NONE
Definition LFG.h:23
@ PLAYER_ROLE_LEADER
Definition LFG.h:24
@ PLAYER_ROLE_HEALER
Definition LFG.h:26
std::string GetRolesString(uint8 roles)
Definition LFG.cpp:36
std::set< uint64 > LfgGuidSet
Definition LFG.h:110
std::string ConcatenateDungeons(LfgDungeonSet const &dungeons)
Definition LFG.cpp:13
std::map< uint64, LfgLockMap > LfgLockPartyMap
Definition LFG.h:109
std::map< uint8, LfgPlayerQueueData > LfgPlayerQueueDataContainer
@ LFG_PROPOSAL_SUCCESS
Definition LFGMgr.h:74
@ LFG_PROPOSAL_FAILED
Definition LFGMgr.h:73
@ LFG_PROPOSAL_INITIATING
Definition LFGMgr.h:72
LfgJoinResult
Queue join results.
Definition LFGMgr.h:93
@ LFG_JOIN_TOO_MUCH_MEMBERS
Definition LFGMgr.h:109
@ LFG_JOIN_DISCONNECTED
Definition LFGMgr.h:102
@ LFG_JOIN_DUNGEON_INVALID
Definition LFGMgr.h:104
@ LFG_JOIN_ROLE_CHECK_FAILED
Definition LFGMgr.h:111
@ LFG_JOIN_USING_BG_SYSTEM
Definition LFGMgr.h:110
@ LFG_JOIN_INTERNAL_ERROR
Definition LFGMgr.h:98
@ LFG_JOIN_MIXED_RAID_DUNGEON
Definition LFGMgr.h:100
@ LFG_JOIN_DESERTER
Definition LFGMgr.h:105
@ LFG_JOIN_RANDOM_COOLDOWN
Definition LFGMgr.h:107
@ LFG_JOIN_PARTY_RANDOM_COOLDOWN
Definition LFGMgr.h:108
@ LFG_JOIN_OK
Definition LFGMgr.h:95
@ LFG_JOIN_PARTY_DESERTER
Definition LFGMgr.h:106
@ LFG_JOIN_FAILED
Definition LFGMgr.h:96
@ LFG_JOIN_NOT_MEET_REQS
Definition LFGMgr.h:99
@ RBAC_PERM_JOIN_DUNGEON_FINDER
Definition RBAC.h:46
float target_Orientation
Definition ObjectMgr.h:410
uint32 m_ID
int32 m_ContinentID
uint32 m_DifficultyID
uint32 m_Type
bool IsScenario() const
bool IsInstance() const
bool IsBattlegroundOrArena() const
bool IsRaid() const
float GetPositionZ() const
Definition Object.h:330
float GetOrientation() const
Definition Object.h:331
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
uint32 requiredItemLevel
Definition LFGMgr.h:287
std::string name
Definition LFGMgr.h:278
uint32 Entry() const
Definition LFGMgr.h:292
DifficultyID difficulty
Definition LFGMgr.h:285
LfgRoleCheckState state
Definition LFGMgr.h:154
LfgJoinResult result
Definition LFGMgr.h:153
LfgLockPartyMap lockmap
Definition LFGMgr.h:155
Stores information of a current vote to kick someone from a group.
Definition LFGMgr.h:258
uint64 victim
Player guid to be kicked (can't vote).
Definition LFGMgr.h:262
std::string reason
kick reason
Definition LFGMgr.h:263
time_t cancelTime
Time left to vote.
Definition LFGMgr.h:259
LfgAnswerContainer votes
Player votes (-1 not answer | 0 Not agree | 1 agree).
Definition LFGMgr.h:261
bool inProgress
Vote in progress.
Definition LFGMgr.h:260
Stores group data related to proposal to join.
Definition LFGMgr.h:227
uint32 dungeonId
Dungeon to join.
Definition LFGMgr.h:233
uint64 group
Proposal group (0 if new).
Definition LFGMgr.h:235
uint32 id
Proposal Id.
Definition LFGMgr.h:232
LfgGuidList queues
Queue Ids to remove/readd.
Definition LFGMgr.h:240
uint64 leader
Leader guid.
Definition LFGMgr.h:236
LfgProposalPlayerContainer players
Players data.
Definition LFGMgr.h:242
bool isNew
Determines if it's new group or not.
Definition LFGMgr.h:239
LfgProposalState state
State of the proposal.
Definition LFGMgr.h:234
time_t cancelTime
Time when we will cancel this proposal.
Definition LFGMgr.h:237
Stores player data related to proposal to join.
Definition LFGMgr.h:218
uint8 role
Proposed role.
Definition LFGMgr.h:220
LfgAnswer accept
Accept status (-1 not answer | 0 Not agree | 1 agree).
Definition LFGMgr.h:221
uint64 group
Original group guid. 0 if no original group.
Definition LFGMgr.h:222
Reward info.
Definition LFGMgr.h:207
uint32 firstQuest
Definition LFGMgr.h:212
uint32 otherQuest
Definition LFGMgr.h:213
Stores all rolecheck info of a group that wants to join.
Definition LFGMgr.h:247
LfgDungeonSet dungeons
Dungeons group is applying for (expanded random dungeons).
Definition LFGMgr.h:251
LfgRolesMap roles
Player selected roles.
Definition LFGMgr.h:249
uint64 leader
Leader of the group.
Definition LFGMgr.h:253
LfgRoleCheckState state
State of the rolecheck.
Definition LFGMgr.h:250
time_t cancelTime
Time when the rolecheck will fail.
Definition LFGMgr.h:248
uint32 rDungeonId
Random Dungeon Id.
Definition LFGMgr.h:252
LfgUpdateType updateType
Definition LFGMgr.h:167