aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/server/game/DungeonFinding/LFG.h13
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.cpp1139
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.h362
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.cpp165
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.h45
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp4
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h25
-rwxr-xr-xsrc/server/game/Groups/Group.cpp56
-rwxr-xr-xsrc/server/game/Groups/Group.h22
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h12
-rwxr-xr-xsrc/server/game/Scripting/ScriptLoader.cpp2
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/LFGHandler.cpp6
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.cpp2
-rwxr-xr-xsrc/server/game/Server/WorldSession.h4
-rw-r--r--src/server/scripts/World/CMakeLists.txt1
-rw-r--r--src/server/scripts/World/dungeon_finder.cpp163
16 files changed, 1006 insertions, 1015 deletions
diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h
index cf49f57aac9..4280466789e 100755
--- a/src/server/game/DungeonFinding/LFG.h
+++ b/src/server/game/DungeonFinding/LFG.h
@@ -18,6 +18,8 @@
#ifndef _LFG_H
#define _LFG_H
+#include "Common.h"
+
enum LfgRoles
{
ROLE_NONE = 0x00,
@@ -27,13 +29,6 @@ enum LfgRoles
ROLE_DAMAGE = 0x08,
};
-enum LfgState
-{
- LFG_STATE_NONE = 0, // Not using LFG / LFR
- LFG_STATE_LFG = 1, // Using Dungeon finder
- LFG_STATE_LFR = 2, // Using Raid finder
-};
-
enum LfgUpdateType
{
LFG_UPDATETYPE_LEADER = 1,
@@ -55,10 +50,10 @@ typedef std::set<uint32> LfgDungeonSet;
struct LookingForGroup
{
- LookingForGroup(): roles(0), update(true), state(LFG_STATE_NONE) {}
+ LookingForGroup(): roles(0), state(LFG_STATE_NONE), oldState(LFG_STATE_NONE) {}
uint8 roles;
- bool update;
LfgState state;
+ LfgState oldState;
LfgDungeonSet applyDungeons; // Dungeons the player have applied for
std::string comment;
};
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 649d642375c..f66837c84c2 100755
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -23,88 +23,23 @@
#include "ProgressBar.h"
#include "SocialMgr.h"
#include "LFGMgr.h"
+#include "LFGScripts.h"
#include "Group.h"
#include "Player.h"
-// --- Temporal functions
-// Added to try to find bugs that leaves data inconsistent
-void LFGMgr::Cleaner()
+LFGMgr::LFGMgr(): m_update(true), m_QueueTimer(0), m_lfgProposalId(1),
+m_WaitTimeAvg(-1), m_WaitTimeTank(-1), m_WaitTimeHealer(-1), m_WaitTimeDps(-1),
+m_NumWaitTimeAvg(0), m_NumWaitTimeTank(0), m_NumWaitTimeHealer(0), m_NumWaitTimeDps(0)
{
- LfgQueueInfoMap::iterator itQueue;
- LfgGuidList::iterator itGuidListRemove;
- LfgGuidList eraseList;
-
- for (LfgQueueInfoMap::iterator it = m_QueueInfoMap.begin(); it != m_QueueInfoMap.end();)
- {
- itQueue = it++;
- // Remove empty queues
- if (!itQueue->second)
- {
- sLog.outError("LFGMgr::Cleaner: removing [" UI64FMTD "] from QueueInfoMap, data is null", itQueue->first);
- m_QueueInfoMap.erase(itQueue);
- }
- // Remove queue with empty players
- else if(!itQueue->second->roles.size())
- {
- sLog.outError("LFGMgr::Cleaner: removing [" UI64FMTD "] from QueueInfoMap, no players in queue!", itQueue->first);
- m_QueueInfoMap.erase(itQueue);
- }
- }
-
- // Remove from NewToQueue those guids that do not exist in queueMap
- for (LfgGuidList::iterator it = m_newToQueue.begin(); it != m_newToQueue.end();)
- {
- itGuidListRemove = it++;
- if (m_QueueInfoMap.find(*itGuidListRemove) == m_QueueInfoMap.end())
- {
- eraseList.push_back(*itGuidListRemove);
- m_newToQueue.erase(itGuidListRemove);
- sLog.outError("LFGMgr::Cleaner: removing [" UI64FMTD "] from newToQueue, no queue info with that guid", (*itGuidListRemove));
- }
- }
-
- // Remove from currentQueue those guids that do not exist in queueMap
- for (LfgGuidList::iterator it = m_currentQueue.begin(); it != m_currentQueue.end();)
- {
- itGuidListRemove = it++;
- if (m_QueueInfoMap.find(*itGuidListRemove) == m_QueueInfoMap.end())
- {
- eraseList.push_back(*itGuidListRemove);
- m_newToQueue.erase(itGuidListRemove);
- sLog.outError("LFGMgr::Cleaner: removing [" UI64FMTD "] from currentQueue, no queue info with that guid", (*itGuidListRemove));
- }
- }
-
- for (LfgGuidList::iterator it = eraseList.begin(); it != eraseList.end(); ++it)
+ if (sWorld.getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE))
{
- if (IS_GROUP(*it))
- {
- if (Group* grp = sObjectMgr.GetGroupByGUID(GUID_LOPART(*it)))
- for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
- if (Player* plr = itr->getSource())
- plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
- }
- else
- if (Player* plr = sObjectMgr.GetPlayer(*it))
- plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
+ new LFGScripts();
+ GetAllDungeons();
+ m_update = true;
}
-}
-
-LFGMgr::LFGMgr()
-{
- m_QueueTimer = 0;
- m_WaitTimeAvg = -1;
- m_WaitTimeTank = -1;
- m_WaitTimeHealer = -1;
- m_WaitTimeDps = -1;
- m_NumWaitTimeAvg = 0;
- m_NumWaitTimeTank = 0;
- m_NumWaitTimeHealer = 0;
- m_NumWaitTimeDps = 0;
- m_update = true;
- m_lfgProposalId = 1;
- GetAllDungeons();
+ else
+ m_update = false;
}
LFGMgr::~LFGMgr()
@@ -136,14 +71,11 @@ LFGMgr::~LFGMgr()
m_CachedDungeonMap.clear();
m_CompatibleMap.clear();
- m_QueueInfoMap.clear();
m_currentQueue.clear();
m_newToQueue.clear();
}
-/// <summary>
/// Load achievement <-> encounter associations
-/// </summary>
void LFGMgr::LoadDungeonEncounters()
{
m_EncountersByAchievement.clear();
@@ -199,9 +131,8 @@ void LFGMgr::LoadDungeonEncounters()
sLog.outString(">> Loaded %u dungeon encounter lfg associations.", count);
}
-/// <summary>
+
/// Load rewards for completing dungeons
-/// </summary>
void LFGMgr::LoadRewards()
{
for (LfgRewardMap::iterator itr = m_RewardMap.begin(); itr != m_RewardMap.end(); ++itr)
@@ -272,85 +203,66 @@ void LFGMgr::LoadRewards()
void LFGMgr::Update(uint32 diff)
{
- if (!m_update || !sWorld.getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE))
+ if (!m_update)
return;
m_update = false;
time_t currTime = time(NULL);
// Remove obsolete role checks
- LfgRoleCheckMap::iterator itRoleCheck;
- LfgRoleCheck* pRoleCheck;
for (LfgRoleCheckMap::iterator it = m_RoleChecks.begin(); it != m_RoleChecks.end();)
{
- itRoleCheck = it++;
- pRoleCheck = itRoleCheck->second;
+ LfgRoleCheckMap::iterator itRoleCheck = it++;
+ LfgRoleCheck* pRoleCheck = itRoleCheck->second;
if (currTime < pRoleCheck->cancelTime)
continue;
pRoleCheck->result = LFG_ROLECHECK_MISSING_ROLE;
- Player* plr = NULL;
for (LfgRolesMap::const_iterator itRoles = pRoleCheck->roles.begin(); itRoles != pRoleCheck->roles.end(); ++itRoles)
- {
- plr = sObjectMgr.GetPlayerByLowGUID(itRoles->first);
- if (!plr)
- continue;
- plr->GetSession()->SendLfgRoleCheckUpdate(pRoleCheck);
- plr->GetLfgDungeons()->clear();
- plr->SetLfgRoles(ROLE_NONE);
- if (!plr->GetGroup() || !plr->GetGroup()->isLFGGroup())
- plr->SetLfgState(LFG_STATE_NONE);
+ if (Player* plr = sObjectMgr.GetPlayerByLowGUID(itRoles->first))
+ {
+ plr->GetSession()->SendLfgRoleCheckUpdate(pRoleCheck);
+ plr->ClearLfgState();
- if (itRoles->first == pRoleCheck->leader)
- plr->GetSession()->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result);
- }
+ if (itRoles->first == pRoleCheck->leader)
+ plr->GetSession()->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result);
+ }
delete pRoleCheck;
m_RoleChecks.erase(itRoleCheck);
}
// Remove obsolete proposals
- LfgProposalMap::iterator itRemove;
for (LfgProposalMap::iterator it = m_Proposals.begin(); it != m_Proposals.end();)
{
- itRemove = it++;
+ LfgProposalMap::iterator itRemove = it++;
if (itRemove->second->cancelTime < currTime)
RemoveProposal(itRemove, LFG_UPDATETYPE_PROPOSAL_FAILED);
}
// Remove obsolete kicks
- LfgPlayerBootMap::iterator itBoot;
- LfgPlayerBoot* pBoot;
for (LfgPlayerBootMap::iterator it = m_Boots.begin(); it != m_Boots.end();)
{
- itBoot = it++;
- pBoot = itBoot->second;
+ LfgPlayerBootMap::iterator itBoot = it++;
+ LfgPlayerBoot* pBoot = itBoot->second;
if (pBoot->cancelTime < currTime)
{
- Group* grp = sObjectMgr.GetGroupByGUID(itBoot->first);
pBoot->inProgress = false;
for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes)
if (Player* plrg = sObjectMgr.GetPlayerByLowGUID(itVotes->first))
if (plrg->GetGUIDLow() != pBoot->victimLowGuid)
plrg->GetSession()->SendLfgBootPlayer(pBoot);
- if (grp)
- grp->SetLfgKickActive(false);
delete pBoot;
m_Boots.erase(itBoot);
}
}
- // Consistency cleaner
- Cleaner();
-
// Check if a proposal can be formed with the new groups being added
- LfgProposal* pProposal = NULL;
LfgGuidList firstNew;
while (!m_newToQueue.empty())
{
sLog.outDebug("LFGMgr::Update: checking [" UI64FMTD "] m_newToQueue(%u), m_currentQueue(%u)", m_newToQueue.front(), uint32(m_newToQueue.size()), uint32(m_currentQueue.size()));
firstNew.push_back(m_newToQueue.front());
- pProposal = FindNewGroups(firstNew, m_currentQueue);
- if (pProposal) // Group found!
+ if (LfgProposal* pProposal = FindNewGroups(firstNew, m_currentQueue)) // Group found!
{
// Remove groups in the proposal from new and current queues (not from queue map)
for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it)
@@ -370,7 +282,7 @@ void LFGMgr::Update(uint32 diff)
plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_PROPOSAL_BEGIN, plr->GetLfgDungeons(), plr->GetLfgComment());
else
plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_PROPOSAL_BEGIN, plr->GetLfgDungeons(), plr->GetLfgComment());
- plr->GetSession()->SendUpdateProposal(m_lfgProposalId, pProposal);
+ plr->GetSession()->SendLfgUpdateProposal(m_lfgProposalId, pProposal);
}
}
@@ -390,26 +302,22 @@ void LFGMgr::Update(uint32 diff)
{
m_QueueTimer = 0;
time_t currTime = time(NULL);
- int32 waitTime;
- LfgQueueInfo* queue;
- uint32 dungeonId;
- uint32 queuedTime;
- uint8 role;
for (LfgQueueInfoMap::const_iterator itQueue = m_QueueInfoMap.begin(); itQueue != m_QueueInfoMap.end(); ++itQueue)
{
- queue = itQueue->second;
+ LfgQueueInfo* queue = itQueue->second;
if (!queue)
{
sLog.outError("LFGMgr::Update: [" UI64FMTD "] queued with null queue info!", itQueue->first);
continue;
}
- dungeonId = (*queue->dungeons.begin());
- queuedTime = uint32(currTime - queue->joinTime);
- role = ROLE_NONE;
+ uint32 dungeonId = (*queue->dungeons.begin());
+ uint32 queuedTime = uint32(currTime - queue->joinTime);
+ uint8 role = ROLE_NONE;
for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer)
role |= itPlayer->second;
role &= ~ROLE_LEADER;
+ int32 waitTime = -1;
switch(role)
{
case ROLE_NONE: // Should not happen - just in case
@@ -439,43 +347,32 @@ void LFGMgr::Update(uint32 diff)
m_update = true;
}
-/// <summary>
-/// Add a guid to new queue, checks consistency
-/// </summary>
-/// <param name="uint64">Player or group guid</param>
-void LFGMgr::AddGuidToNewQueue(uint64 guid)
-{
- // Consistency check
- LfgGuidList::iterator it = std::find(m_newToQueue.begin(), m_newToQueue.end(), guid);
-
- if (it != m_newToQueue.end())
- {
- sLog.outError("LFGMgr::AddGuidToNewQueue: [" UI64FMTD "] being added to queue and it was already added. ignoring", guid);
- return;
- }
+/**
+ Add a guid to the queue of guids to be added to main queue. It guid its already
+ in queue does nothing. If this function is called guid is not in the main queue
+ (No need to check it here)
- it = std::find(m_currentQueue.begin(), m_currentQueue.end(), guid);
- if (it != m_currentQueue.end())
+ @param[in] guid Player or group guid to add to queue
+*/
+void LFGMgr::AddToQueue(uint64& guid)
+{
+ if (std::find(m_newToQueue.begin(), m_newToQueue.end(), guid) != m_newToQueue.end())
+ sLog.outDebug("LFGMgr::AddToQueue: [" UI64FMTD "] already in new queue. ignoring", guid);
+ else
{
- sLog.outError("LFGMgr::AddGuidToNewQueue: [" UI64FMTD "] being added to queue and already in current queue (removing to readd)", guid);
- m_currentQueue.erase(it);
+ m_newToQueue.push_back(guid);
+ sLog.outDebug("LFGMgr::AddToQueue: [" UI64FMTD "] added to m_newToQueue (size: %u)", guid, uint32(m_newToQueue.size()));
}
-
- // Add to queue
- m_newToQueue.push_back(guid);
- sLog.outDebug("LFGMgr::AddGuidToNewQueue: [" UI64FMTD "] added to m_newToQueue (size: %u)", guid, uint32(m_newToQueue.size()));
}
-/// <summary>
-/// Removes the player/group from all queues
-/// </summary>
-/// <param name="uint64">Player or group guid</param>
-/// <returns>bool</returns>
-bool LFGMgr::RemoveFromQueue(uint64 guid)
-{
- bool ret = false;
- uint32 before = m_QueueInfoMap.size();
+/**
+ Removes a guid from the main and new queues.
+ @param[in] guid Player or group guid to add to queue
+ @return true if guid was found in main queue.
+*/
+bool LFGMgr::RemoveFromQueue(uint64& guid)
+{
m_currentQueue.remove(guid);
m_newToQueue.remove(guid);
RemoveFromCompatibles(guid);
@@ -485,14 +382,27 @@ bool LFGMgr::RemoveFromQueue(uint64 guid)
{
delete it->second;
m_QueueInfoMap.erase(it);
- ret = true;
+ sLog.outDebug("LFGMgr::RemoveFromQueue: [" UI64FMTD "] removed", guid);
+ return true;
+ }
+ else
+ {
+ sLog.outDebug("LFGMgr::RemoveFromQueue: [" UI64FMTD "] not in queue", guid);
+ return false;
}
- sLog.outDebug("LFGMgr::RemoveFromQueue: [" UI64FMTD "] %s - Queue(%u)", guid,
- before != m_QueueInfoMap.size() ? "Removed" : "Not in queue", uint32(m_QueueInfoMap.size()));
- return ret;
+
}
-/// Adds the player/group to lfg queue
+/**
+ Adds the player/group to lfg queue. If player is in a group then it is the leader
+ of the group tying to join the group. Join conditions are checked before adding
+ to the new queue.
+
+ @param[in] plr Player trying to join (or leader of group trying to join)
+ @param[in] roles Player selected roles
+ @param[in] dungeons Dungeons the player/group is applying for
+ @param[in] comment Player selected comment
+*/
void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string comment)
{
if (!plr || !plr->GetSession() || !dungeons || !dungeons->size())
@@ -504,7 +414,7 @@ void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string
LfgJoinResult result = LFG_JOIN_OK;
PlayerSet players;
uint32 rDungeonId = 0;
- bool isContinue = grp && grp->isLFGGroup() && !grp->isLfgDungeonComplete();
+ bool isContinue = grp && grp->isLFGGroup() && grp->GetLfgState() != LFG_STATE_FINISHED_DUNGEON;
// Do not allow to change dungeon in the middle of a current dungeon
if (isContinue)
@@ -531,17 +441,16 @@ void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string
if (itr->getSource() && itr->getSource()->GetSession())
itr->getSource()->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, comment);
}
- dungeons->clear();
- delete dungeons;
- return;
}
else if (!isContinue) // Different dungeons and it's not an offer to continue
{
// Different dungeons and it's not a LfgGroup in the middle of a dungeon that need more people
Leave(plr, grp);
Join(plr, roles, dungeons, comment);
- return;
}
+ dungeons->clear();
+ delete dungeons;
+ return;
}
// Check player or group member restrictions
@@ -559,12 +468,10 @@ void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string
result = LFG_JOIN_TOO_MUCH_MEMBERS;
else
{
- Player* plrg;
uint8 memberCount = 0;
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL && result == LFG_JOIN_OK; itr = itr->next())
{
- plrg = itr->getSource();
- if (plrg)
+ if (Player* plrg = itr->getSource())
{
if (plrg->HasAura(LFG_SPELL_DUNGEON_DESERTER))
result = LFG_JOIN_PARTY_DESERTER;
@@ -649,65 +556,63 @@ void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string
return;
}
- // All ok, Update player info
- if (!isContinue)
- {
- plr->GetLfgDungeons()->clear();
- if (rDungeonId)
- plr->GetLfgDungeons()->insert(rDungeonId);
- else
- for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
- plr->GetLfgDungeons()->insert(*it);
- }
-
plr->SetLfgComment(comment);
plr->SetLfgRoles(roles);
if (grp) // Begin rolecheck
{
+ // Create new rolecheck
LfgRoleCheck* pRoleCheck = new LfgRoleCheck();
pRoleCheck->cancelTime = time_t(time(NULL)) + LFG_TIME_ROLECHECK;
pRoleCheck->result = LFG_ROLECHECK_INITIALITING;
pRoleCheck->leader = plr->GetGUIDLow();
m_RoleChecks[grp->GetLowGUID()] = pRoleCheck;
- if (isContinue)
- {
- dungeons->clear();
- dungeons->insert(grp->GetLfgDungeonEntry());
- }
- else if (rDungeonId)
+ if (rDungeonId)
{
dungeons->clear();
dungeons->insert(rDungeonId);
}
+ // Assign dungeons
for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
pRoleCheck->dungeons.insert(*it);
- Player* plrg;
+ // Send update to player
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
- plrg = itr->getSource();
- if (!plrg)
- continue;
-
- plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_JOIN_PROPOSAL, dungeons, comment);
- plrg->SetLfgState(LFG_STATE_LFG);
- if (!isContinue)
+ if (Player* plrg = itr->getSource())
{
- plrg->GetLfgDungeons()->clear();
- for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
- plrg->GetLfgDungeons()->insert(*it);
+ plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_JOIN_PROPOSAL, dungeons, comment);
+ plrg->SetLfgState(LFG_STATE_ROLECHECK);
+ if (!isContinue)
+ {
+ plrg->GetLfgDungeons()->clear();
+ for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
+ plrg->GetLfgDungeons()->insert(*it);
+ }
+ pRoleCheck->roles[plrg->GetGUIDLow()] = 0;
}
- pRoleCheck->roles[plrg->GetGUIDLow()] = 0;
}
+ // Update leader role
UpdateRoleCheck(grp, plr, true);
}
else // Add player to queue
{
+ // Send update to player
plr->GetSession()->SendLfgJoinResult(LFG_JOIN_OK);
plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_JOIN_PROPOSAL, dungeons, comment);
- plr->SetLfgState(LFG_STATE_LFG);
+ plr->SetLfgState(LFG_STATE_QUEUED);
+ if (!isContinue)
+ {
+ plr->GetLfgDungeons()->clear();
+ if (rDungeonId)
+ plr->GetLfgDungeons()->insert(rDungeonId);
+ else
+ for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
+ plr->GetLfgDungeons()->insert(*it);
+ }
+
+ // Queue player
LfgQueueInfo* pqInfo = new LfgQueueInfo();
pqInfo->joinTime = time_t(time(NULL));
pqInfo->roles[plr->GetGUIDLow()] = plr->GetLfgRoles();
@@ -721,7 +626,7 @@ void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string
for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
pqInfo->dungeons.insert(*it);
m_QueueInfoMap[guid] = pqInfo;
- AddGuidToNewQueue(guid);
+ AddToQueue(guid);
}
std::string dungeonsstr = ConcatenateDungeons(dungeons);
sLog.outDebug("LFGMgr::Join: [" UI64FMTD "] joined with %u members. dungeons: %s", guid, grp ? grp->GetMembersCount() : 1, dungeonsstr.c_str());
@@ -730,99 +635,104 @@ void LFGMgr::Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string
dungeons = NULL;
}
-/// <summary>
-/// Leave the lfg queue
-/// </summary>
-/// <param name="Player*">Player (could be NULL)</param>
-/// <param name="Group*">Group (could be NULL)</param>
+/**
+ Leaves Dungeon System. Player/Group is removed from queue, rolechecks, proposals
+ or votekicks. Player or group needs to be not NULL and using Dungeon System
+
+ @param[in] plr Player trying to leave (can be NULL)
+ @param[in] grp Group trying to leave (default NULL)
+*/
void LFGMgr::Leave(Player* plr, Group* grp /* = NULL*/)
{
- if ((plr && (!plr->GetLfgUpdate() || !plr->isUsingLfg())) || !sWorld.getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE))
+ if (!plr && !grp)
return;
- uint64 guid = grp ? grp->GetGUID() : plr ? plr->GetGUID() : 0;
- sLog.outDebug("LFGMgr::Leave: [" UI64FMTD "]", guid);
-
- if (!guid)
- return;
+ uint64 guid = 0;
+ LfgState state;
- // Remove from Role Checks
if (grp)
{
- grp->SetLfgQueued(false);
- LfgRoleCheckMap::const_iterator itRoleCheck = m_RoleChecks.find(GUID_LOPART(guid));
- if (itRoleCheck != m_RoleChecks.end())
- {
- UpdateRoleCheck(grp); // No player to update role = LFG_ROLECHECK_ABORTED
- return;
- }
+ guid = grp->GetGUID();
+ state = grp->GetLfgState();
}
-
- // Remove from Proposals
- bool proposalFound = false;
- LfgProposalMap::iterator it = m_Proposals.begin();
- while (it != m_Proposals.end() && !proposalFound)
+ else
{
- // Mark the player/leader of group who left as didn't accept the proposal
- for (LfgProposalPlayerMap::iterator itPlayer = it->second->players.begin(); itPlayer != it->second->players.end(); ++itPlayer)
- {
- if ((plr && itPlayer->first == plr->GetGUIDLow()) || (grp && itPlayer->first == GUID_LOPART(grp->GetLeaderGUID())))
- {
- itPlayer->second->accept = LFG_ANSWER_DENY;
- proposalFound = true;
- }
- }
- if (!proposalFound)
- ++it;
+ guid = plr->GetGUID();
+ state = plr->GetLfgState();
}
- // Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
- if (proposalFound)
- RemoveProposal(it, LFG_UPDATETYPE_PROPOSAL_DECLINED);
- else
- RemoveFromQueue(guid);
-
- if (grp)
+ sLog.outDebug("LFGMgr::Leave: [" UI64FMTD "]", guid);
+ switch(state)
{
- for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
- if (Player* plrg = itr->getSource())
+ case LFG_STATE_QUEUED:
+ RemoveFromQueue(guid);
+ if (grp)
{
- plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
- plrg->GetLfgDungeons()->clear();
- plrg->SetLfgRoles(ROLE_NONE);
- plrg->SetLfgState(LFG_STATE_NONE);
+ grp->RestoreLfgState();
+ for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
+ if (Player* plrg = itr->getSource())
+ {
+ plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
+ plrg->ClearLfgState();
+ }
}
- }
- else
- {
- plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
- plr->GetLfgDungeons()->clear();
- plr->SetLfgRoles(ROLE_NONE);
- plr->SetLfgState(LFG_STATE_NONE);
- plr->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW);
+ else
+ {
+ plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
+ plr->ClearLfgState();
+ }
+ break;
+ case LFG_STATE_ROLECHECK:
+ if (grp)
+ UpdateRoleCheck(grp); // No player to update role = LFG_ROLECHECK_ABORTED
+ break;
+ case LFG_STATE_PROPOSAL:
+ {
+ // Remove from Proposals
+ LfgProposalMap::iterator it = m_Proposals.begin();
+ uint32 lowguid = plr ? plr->GetGUIDLow() : GUID_LOPART(grp->GetLeaderGUID());
+ while (it != m_Proposals.end())
+ {
+ LfgProposalPlayerMap::iterator itPlayer = it->second->players.find(lowguid);
+ if (itPlayer != it->second->players.end())
+ {
+ // Mark the player/leader of group who left as didn't accept the proposal
+ itPlayer->second->accept = LFG_ANSWER_DENY;
+ break;
+ }
+ ++it;
+ }
+
+ // Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
+ if (it != m_Proposals.end())
+ RemoveProposal(it, LFG_UPDATETYPE_PROPOSAL_DECLINED);
+ break;
+ }
+ default:
+ sLog.outError("LFGMgr::Leave: [" UI64FMTD "], state %u - This shouldn't happen", guid, uint8(state));
+ break;
}
}
-/// <summary>
-/// Given a Lfg group checks if leader needs to be show the popup to select more players
-/// </summary>
-/// <param name="Group*">Group than needs new players</param>
+/**
+ Sends the leader of a group the offer to continue popup
+
+ @param[in] grp Group to send offer to
+*/
void LFGMgr::OfferContinue(Group* grp)
{
- if (!sWorld.getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE))
- return;
-
- ASSERT(grp);
- if (Player* leader = sObjectMgr.GetPlayer(grp->GetLeaderGUID()))
+ Player* leader = grp ? sObjectMgr.GetPlayer(grp->GetLeaderGUID()) : NULL;
+ if (leader)
leader->GetSession()->SendLfgOfferContinue(grp->GetLfgDungeonEntry(false));
}
-/// <summary>
-/// Check the queue to try to match groups. Returns all the possible matches
-/// </summary>
-/// <param name="LfgGuidList &">Guids we trying to match with the rest of groups</param>
-/// <param name="LfgGuidList">All guids in queue</param>
-/// <returns>LfgProposal*</returns>
+/**
+ Checks que main queue to try to form a Lfg group. Returns first match found (if any)
+
+ @param[in] check List of guids trying to match with other groups
+ @param[in] all List of all other guids in main queue to match against
+ @return Pointer to proposal, if match is found
+*/
LfgProposal* LFGMgr::FindNewGroups(LfgGuidList check, LfgGuidList all)
{
sLog.outDebug("LFGMgr::FindNewGroup: (%s) - all(%s)", ConcatenateGuids(check).c_str(), ConcatenateGuids(all).c_str());
@@ -842,15 +752,16 @@ LfgProposal* LFGMgr::FindNewGroups(LfgGuidList check, LfgGuidList all)
return pProposal;
}
-/// <summary>
-/// Check compatibilities between groups.
-/// </summary>
-/// <param name="LfgGuidList">Guids we checking compatibility</param>
-/// <returns>bool</returns>
-/// <param name="LfgProposal*&">Proposals found.</param>
+/**
+ Check compatibilities between groups
+
+ @param[in] check List of guids to check compatibilities
+ @param[out] pProposal Proposal found if groups are compatibles and Match
+ @return true if group are compatibles
+*/
bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
{
- if (pProposal) // Do not check anything if we already have a proposal
+ if (pProposal) // Do not check anything if we already have a proposal
return false;
std::string strGuids = ConcatenateGuids(check);
@@ -893,22 +804,22 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
uint8 numLfgGroups = 0;
uint32 groupLowGuid = 0;
LfgQueueInfoMap pqInfoMap;
- LfgQueueInfoMap::iterator itQueue;
for (LfgGuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it)
{
- itQueue = m_QueueInfoMap.find(*it);
+ uint64 guid = (*it);
+ LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid);
if (itQueue == m_QueueInfoMap.end())
{
sLog.outError("LFGMgr::CheckCompatibility: [" UI64FMTD "] is not queued but listed as queued!", (*it));
- RemoveFromQueue(*it);
+ RemoveFromQueue(guid);
return false;
}
- pqInfoMap[*it] = itQueue->second;
+ pqInfoMap[guid] = itQueue->second;
numPlayers += itQueue->second->roles.size();
- if (IS_GROUP(*it))
+ if (IS_GROUP(guid))
{
- uint32 lowGuid = GUID_LOPART(*it);
+ uint32 lowGuid = GUID_LOPART(guid);
if (Group* grp = sObjectMgr.GetGroupByGUID(lowGuid))
if (grp->isLFGGroup())
{
@@ -919,11 +830,8 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
}
}
- if (check.size() == 1)
- {
- if (numPlayers != MAXGROUPSIZE) // Single group with less than MAXGROUPSIZE - Compatibles
- return true;
- }
+ if (check.size() == 1 && numPlayers != MAXGROUPSIZE) // Single group with less than MAXGROUPSIZE - Compatibles
+ return true;
// Do not match - groups already in a lfgDungeon or too much players
if (numLfgGroups > 1 || numPlayers > MAXGROUPSIZE)
@@ -947,29 +855,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
// Assign new leader
if (itRoles->second & ROLE_LEADER && (!newLeaderLowGuid || urand(0, 1)))
newLeaderLowGuid = itRoles->first;
- if (rolesMap[itRoles->first]) // Player already added!
- {
- // Find the other guid
- uint64 guid1 = it->first;
- uint64 guid2 = 0;
- for (LfgQueueInfoMap::const_iterator it2 = pqInfoMap.begin(); it2 != it && !guid2; ++it2)
- {
- if (it2->second->roles.find(itRoles->first) != it2->second->roles.end())
- guid2 = it2->first;
- }
- uint64 playerguid;
- // store in guid2 the obsolete group
- if (pqInfoMap[guid2]->joinTime > it->second->joinTime)
- {
- playerguid = guid2;
- guid2 = guid1;
- guid1 = playerguid;
- }
- playerguid = MAKE_NEW_GUID(itRoles->first, 0, HIGHGUID_PLAYER);
- sLog.outError("LFGMgr::CheckCompatibility: check(%s) player [" UI64FMTD "] in queue with [" UI64FMTD "] and OBSOLETE! [" UI64FMTD "]",
- strGuids.c_str(), playerguid, guid1, guid2);
- }
rolesMap[itRoles->first] = itRoles->second;
}
}
@@ -981,11 +867,10 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
return false;
}
- Player* plr;
PlayerSet players;
for (LfgRolesMap::const_iterator it = rolesMap.begin(); it != rolesMap.end(); ++it)
{
- plr = sObjectMgr.GetPlayerByLowGUID(it->first);
+ Player* plr = sObjectMgr.GetPlayerByLowGUID(it->first);
if (!plr)
sLog.outDebug("LFGMgr::CheckCompatibility: (%s) Warning! %u offline! Marking as not compatibles!", strGuids.c_str(), it->first);
else
@@ -1034,8 +919,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
pqInfoMap.clear();
if (!compatibleDungeons || !compatibleDungeons->size())
{
- if (compatibleDungeons)
- delete compatibleDungeons;
+ delete compatibleDungeons;
players.clear();
rolesMap.clear();
SetCompatibles(strGuids, false);
@@ -1077,8 +961,6 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
pProposal->groupLowGuid = groupLowGuid;
// Assign new roles to players and assign new leader
- LfgProposalPlayer* ppPlayer;
- uint32 lowGuid;
PlayerSet::const_iterator itPlayers = players.begin();
if (!newLeaderLowGuid)
{
@@ -1092,13 +974,12 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
uint8 numAccept = 0;
for (itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers)
{
- lowGuid = (*itPlayers)->GetGUIDLow();
- ppPlayer = new LfgProposalPlayer();
- Group* grp = (*itPlayers)->GetGroup();
- if (grp)
+ uint32 lowGuid = (*itPlayers)->GetGUIDLow();
+ LfgProposalPlayer* ppPlayer = new LfgProposalPlayer();
+ if (Group* grp = (*itPlayers)->GetGroup())
{
ppPlayer->groupLowGuid = grp->GetLowGUID();
- if (grp->GetLfgDungeonEntry() == selectedDungeon && ppPlayer->groupLowGuid == pProposal->groupLowGuid) // Player from existing group, autoaccept
+ if (groupLowGuid && groupLowGuid == ppPlayer->groupLowGuid) // Player from existing group, autoaccept
{
ppPlayer->accept = LFG_ANSWER_AGREE;
++numAccept;
@@ -1115,19 +996,24 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal)
return true;
}
-/// Update the Role check info with the player selected role.
+/**
+ Update the Role check info with the player selected role.
+
+ @param[in] grp Group to update rolecheck
+ @param[in] plr Player to update role (NULL = Rolecheck Failed)
+ @param[in] newRoleCheck Determines if its a new rolecheck (Default false)
+*/
void LFGMgr::UpdateRoleCheck(Group* grp, Player* plr /* = NULL*/, bool newRoleCheck /* = false */)
{
if (!grp)
return;
- LfgRoleCheck* pRoleCheck = NULL;
LfgRolesMap check_roles;
LfgRoleCheckMap::iterator itRoleCheck = m_RoleChecks.find(grp->GetLowGUID());
if (itRoleCheck == m_RoleChecks.end())
return;
- pRoleCheck = itRoleCheck->second;
+ LfgRoleCheck* pRoleCheck = itRoleCheck->second;
LfgLockStatusMap* playersLockMap = NULL;
if (plr)
{
@@ -1146,7 +1032,7 @@ void LFGMgr::UpdateRoleCheck(Group* grp, Player* plr /* = NULL*/, bool newRoleCh
{
// use temporal var to check roles, CheckGroupRoles modifies the roles
check_roles = pRoleCheck->roles;
- if (!CheckGroupRoles(check_roles)) // Group is not posible
+ if (!CheckGroupRoles(check_roles)) // Group is not posible
pRoleCheck->result = LFG_ROLECHECK_WRONG_ROLES;
else
{
@@ -1197,52 +1083,47 @@ void LFGMgr::UpdateRoleCheck(Group* grp, Player* plr /* = NULL*/, bool newRoleCh
else
pRoleCheck->result = LFG_ROLECHECK_ABORTED;
- WorldSession* session;
- Player* plrg = NULL;
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
- plrg = itr->getSource();
+ Player* plrg = itr->getSource();
if (!plrg)
continue;
- session = plrg->GetSession();
+ WorldSession* session = plrg->GetSession();
if (!newRoleCheck && plr)
session->SendLfgRoleChosen(plr->GetGUID(), plr->GetLfgRoles());
session->SendLfgRoleCheckUpdate(pRoleCheck);
switch(pRoleCheck->result)
{
- case LFG_ROLECHECK_INITIALITING:
- continue;
- case LFG_ROLECHECK_FINISHED:
- if (!playersLockMap)
- session->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE, &pRoleCheck->dungeons, plrg->GetLfgComment());
- else
- {
+ case LFG_ROLECHECK_INITIALITING:
+ continue;
+ case LFG_ROLECHECK_FINISHED:
+ if (!playersLockMap)
+ {
+ plrg->SetLfgState(LFG_STATE_QUEUED);
+ session->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE, &pRoleCheck->dungeons, plrg->GetLfgComment());
+ }
+ else
+ {
+ if (grp->GetLeaderGUID() == plrg->GetGUID())
+ session->SendLfgJoinResult(LFG_JOIN_PARTY_NOT_MEET_REQS, 0, playersLockMap);
+ session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED);
+ plrg->ClearLfgState();
+ }
+ break;
+ default:
if (grp->GetLeaderGUID() == plrg->GetGUID())
- session->SendLfgJoinResult(LFG_JOIN_PARTY_NOT_MEET_REQS, 0, playersLockMap);
+ session->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result);
session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED);
- plrg->GetLfgDungeons()->clear();
- plrg->SetLfgRoles(ROLE_NONE);
- if (!grp->isLFGGroup())
- plrg->SetLfgState(LFG_STATE_NONE);
- }
- break;
- default:
- if (grp->GetLeaderGUID() == plrg->GetGUID())
- session->SendLfgJoinResult(LFG_JOIN_FAILED, pRoleCheck->result);
- session->SendLfgUpdateParty(LFG_UPDATETYPE_ROLECHECK_FAILED);
- plrg->GetLfgDungeons()->clear();
- if (grp->isLFGGroup())
- plrg->SetLfgRoles(ROLE_NONE);
- plrg->SetLfgState(LFG_STATE_NONE);
- break;
+ plrg->ClearLfgState();
+ break;
}
}
if (pRoleCheck->result == LFG_ROLECHECK_FINISHED && pRoleCheck->dungeons.size())
{
- grp->SetLfgQueued(true);
+ grp->SetLfgState(LFG_STATE_QUEUED);
LfgQueueInfo* pqInfo = new LfgQueueInfo();
pqInfo->joinTime = time_t(time(NULL));
for (LfgRolesMap::const_iterator it = check_roles.begin(); it != check_roles.end(); ++it)
@@ -1260,8 +1141,9 @@ void LFGMgr::UpdateRoleCheck(Group* grp, Player* plr /* = NULL*/, bool newRoleCh
for (LfgDungeonSet::const_iterator it = pRoleCheck->dungeons.begin(); it != pRoleCheck->dungeons.end(); ++it)
pqInfo->dungeons.insert(*it);
- m_QueueInfoMap[grp->GetGUID()] = pqInfo;
- AddGuidToNewQueue(grp->GetGUID());
+ uint64 guid = grp->GetGUID();
+ m_QueueInfoMap[guid] = pqInfo;
+ AddToQueue(guid);
}
if (pRoleCheck->result != LFG_ROLECHECK_INITIALITING)
@@ -1270,45 +1152,59 @@ void LFGMgr::UpdateRoleCheck(Group* grp, Player* plr /* = NULL*/, bool newRoleCh
pRoleCheck->roles.clear();
delete pRoleCheck;
m_RoleChecks.erase(itRoleCheck);
+ if (pRoleCheck->result != LFG_ROLECHECK_FINISHED)
+ grp->RestoreLfgState();
+ }
+
+ if (playersLockMap)
+ {
+ for (LfgLockStatusMap::iterator itMap = playersLockMap->begin(); itMap != playersLockMap->end(); ++itMap)
+ {
+ itMap->second->clear();
+ delete itMap->second;
+ }
+ playersLockMap->clear();
+ delete playersLockMap;
}
}
-/// <summary>
-/// Remove from cached compatible dungeons any entry that contains the given guid
-/// </summary>
-/// <param name="uint64">guid to remove from any list</param>
+/**
+ Remove from cached compatible dungeons any entry that contains the given guid
+
+ @param[in] guid Guid to remove from compatible cache
+*/
void LFGMgr::RemoveFromCompatibles(uint64 guid)
{
- LfgGuidList lista;
- lista.push_back(guid);
- std::string strGuid = ConcatenateGuids(lista);
- lista.clear();
+ std::stringstream out;
+ out << guid;
+ std::string strGuid = out.str();
sLog.outDebug("LFGMgr::RemoveFromCompatibles: Removing [" UI64FMTD "]", guid);
- LfgCompatibleMap::iterator it;
for (LfgCompatibleMap::iterator itNext = m_CompatibleMap.begin(); itNext != m_CompatibleMap.end();)
{
- it = itNext++;
- if (it->first.find(strGuid) != std::string::npos) // Found, remove it
+ LfgCompatibleMap::iterator it = itNext++;
+ if (it->first.find(strGuid) != std::string::npos) // Found, remove it
m_CompatibleMap.erase(it);
}
}
-/// <summary>
-/// Set the compatibility of a list of guids
-/// </summary>
-/// <param name="std::string">list of guids concatenated by |</param>
-/// <param name="bool">compatibles or not</param>
+/**
+ Stores the compatibility of a list of guids
+
+ @param[in] key String concatenation of guids (| used as separator)
+ @param[in] compatibles Compatibles or not
+*/
void LFGMgr::SetCompatibles(std::string key, bool compatibles)
{
m_CompatibleMap[key] = LfgAnswer(compatibles);
}
-/// <summary>
-/// Get the compatible dungeons between two groups from cache
-/// </summary>
-/// <param name="std::string">list of guids concatenated by |</param>
-/// <returns>LfgAnswer,
+/**
+ Get the compatibility of a group of guids
+
+ @param[in] key String concatenation of guids (| used as separator)
+ @return 1 (Compatibles), 0 (Not compatibles), -1 (Not set)
+*/
LfgAnswer LFGMgr::GetCompatibles(std::string key)
{
LfgAnswer answer = LFG_ANSWER_PENDING;
@@ -1319,14 +1215,14 @@ LfgAnswer LFGMgr::GetCompatibles(std::string key)
return answer;
}
-/// <summary>
-/// Given a list of dungeons remove the dungeons with restrictions.
-/// </summary>
-/// <param name="LfgDungeonSet*">dungeons to check</param>
-/// <param name="PlayerSet*">Players to check restrictions</param>
-/// <param name="LfgLockStatusMap*">Used to return the lockStatusMap</param>
-/// <param name="boot">Return lockMap or discard it</param>
-/// <returns>LfgLockStatusMap*</returns>
+/**
+ Given a list of dungeons remove the dungeons players have restrictions.
+
+ @param[in,out] dungeons Dungeons to check restrictions
+ @param[in] players Set of players to check their dungeon restrictions
+ @param[in] returnLockMap Determines when to return a function value (Default true)
+ @return Map of players Lock status info of given dungeons
+*/
LfgLockStatusMap* LFGMgr::CheckCompatibleDungeons(LfgDungeonSet* dungeons, PlayerSet* players, bool returnLockMap /* = true */)
{
if (!dungeons)
@@ -1359,12 +1255,13 @@ LfgLockStatusMap* LFGMgr::CheckCompatibleDungeons(LfgDungeonSet* dungeons, Playe
return pLockDungeons;
}
-/// <summary>
-/// Given a list of groups checks the compatible dungeons. If players is not null also check restictions
-/// </summary>
-/// <param name="LfgDungeonMap*">dungeons to check</param>
-/// <param name="PlayerSet*">Players to check restrictions</param>
-/// <returns>LfgDungeonSet*</returns>
+/**
+ Given a list of groups checks the compatible dungeons. If players is not null also check restictions
+
+ @param[in] dungeonsMap Map of each player dungeons
+ @param[in] players Set of players to check their dungeon restrictions
+ @return Compatible dungeons of given players
+*/
LfgDungeonSet* LFGMgr::CheckCompatibleDungeons(LfgDungeonMap* dungeonsMap, PlayerSet* players)
{
if (!dungeonsMap || dungeonsMap->empty())
@@ -1399,13 +1296,14 @@ LfgDungeonSet* LFGMgr::CheckCompatibleDungeons(LfgDungeonMap* dungeonsMap, Playe
return compatibleDungeons;
}
-/// <summary>
-/// Check if a group can be formed with the given group
-/// </summary>
-/// <param name="LfgRolesMap &">Roles to check</param>
-/// <param name="bool">Used to remove ROLE_LEADER</param>
-/// <returns>bool</returns>
-bool LFGMgr::CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag /*= true*/)
+/**
+ Check if a group can be formed with the given group roles
+
+ @param[in] groles Map of roles to check
+ @param[in] removeLeaderFlag Determines if we have to remove leader flag (only used first call, Default = true)
+ @return True if roles are compatible
+*/
+bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true*/)
{
if (!groles.size())
return false;
@@ -1471,12 +1369,13 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag /*= true
return (tank + healer + damage) == uint8(groles.size());
}
-/// <summary>
-/// Update Proposal info with player answer
-/// </summary>
-/// <param name="uint32">Id of the proposal</param>
-/// <param name="uint32">Player low guid</param>
-/// <param name="bool">Player answer</param>
+/**
+ Update Proposal info with player answer
+
+ @param[in] proposalId Proposal id to be updated
+ @param[in] lowguid Player low guid to update answer
+ @param[in] accept Player answer
+*/
void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
{
// Check if the proposal exists
@@ -1501,15 +1400,12 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
LfgPlayerList players;
LfgPlayerList playersToTeleport;
- Player* plr;
// check if all have answered and reorder players (leader first)
bool allAnswered = true;
for (LfgProposalPlayerMap::const_iterator itPlayers = pProposal->players.begin(); itPlayers != pProposal->players.end(); ++itPlayers)
{
- plr = sObjectMgr.GetPlayerByLowGUID(itPlayers->first);
-
- if (plr)
+ if (Player* plr = sObjectMgr.GetPlayerByLowGUID(itPlayers->first))
{
if (itPlayers->first == pProposal->leaderLowGuid)
players.push_front(plr);
@@ -1517,7 +1413,8 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
players.push_back(plr);
// Only teleport new players
- if (!plr->GetGroup() || !plr->GetGroup()->isLFGGroup() || plr->GetGroup()->isLfgDungeonComplete())
+ Group* grp = plr->GetGroup();
+ if (!grp || !grp->isLFGGroup() || grp->GetLfgState() == LFG_STATE_FINISHED_DUNGEON)
playersToTeleport.push_back(plr);
}
@@ -1528,7 +1425,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
if (!allAnswered)
{
for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it)
- (*it)->GetSession()->SendUpdateProposal(proposalId, pProposal);
+ (*it)->GetSession()->SendLfgUpdateProposal(proposalId, pProposal);
}
else
{
@@ -1556,61 +1453,51 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
}
// Create a new group (if needed)
- Group* grp = sObjectMgr.GetGroupByGUID(pProposal->groupLowGuid);
+ Group* grp = pProposal->groupLowGuid ? sObjectMgr.GetGroupByGUID(pProposal->groupLowGuid) : NULL;
for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it)
{
- plr = (*it);
+ Player* plr = (*it);
+ Group* group = plr->GetGroup();
if (sendUpdate)
- plr->GetSession()->SendUpdateProposal(proposalId, pProposal);
- if (plr->GetGroup())
+ plr->GetSession()->SendLfgUpdateProposal(proposalId, pProposal);
+ if (group)
{
plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_GROUP_FOUND);
- plr->SetLfgUpdate(false);
- if (plr->GetGroup() != grp)
- {
- plr->GetGroup()->SetLfgQueued(false);
+ if (group != grp)
plr->RemoveFromGroup();
- }
}
else
- {
plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_GROUP_FOUND);
- plr->SetLfgUpdate(false);
- }
if (!grp)
{
grp = new Group();
grp->Create(plr->GetGUID(), plr->GetName());
grp->ConvertToLFG();
+ grp->SetLfgState(LFG_STATE_PROPOSAL);
sObjectMgr.AddGroup(grp);
}
- else if (plr->GetGroup() != grp)
- {
- grp->SetLfgQueued(false);
+ else if (group != grp)
grp->AddMember(plr->GetGUID(), plr->GetName());
- }
- plr->SetLfgUpdate(true);
// Update timers
uint8 role = plr->GetLfgRoles();
- if (role & ROLE_TANK)
+ role &= ~ROLE_LEADER;
+ switch(role)
{
- if (role & ROLE_HEALER || role & ROLE_DAMAGE)
- m_WaitTimeAvg = int32((m_WaitTimeAvg * m_NumWaitTimeAvg + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeAvg);
- else
+ case ROLE_DAMAGE:
+ m_WaitTimeDps = int32((m_WaitTimeDps * m_NumWaitTimeDps + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeDps);
+ break;
+ case ROLE_HEALER:
+ m_WaitTimeHealer = int32((m_WaitTimeHealer * m_NumWaitTimeHealer + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeHealer);
+ break;
+ case ROLE_TANK:
m_WaitTimeTank = int32((m_WaitTimeTank * m_NumWaitTimeTank + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeTank);
- }
- else if (role & ROLE_HEALER)
- {
- if (role & ROLE_DAMAGE)
+ break;
+ default:
m_WaitTimeAvg = int32((m_WaitTimeAvg * m_NumWaitTimeAvg + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeAvg);
- else
- m_WaitTimeHealer = int32((m_WaitTimeHealer * m_NumWaitTimeHealer + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeHealer);
+ break;
}
- else if (role & ROLE_DAMAGE)
- m_WaitTimeDps = int32((m_WaitTimeDps * m_NumWaitTimeDps + waitTimesMap[plr->GetGUID()]) / ++m_NumWaitTimeDps);
-
grp->SetLfgRoles(plr->GetGUID(), pProposal->players[plr->GetGUIDLow()]->role);
}
@@ -1619,11 +1506,14 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
ASSERT(dungeon);
grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty));
grp->SetLfgDungeonEntry(dungeon->Entry());
- grp->SetLfgStatus(LFG_STATUS_NOT_SAVED);
+ grp->SetLfgState(LFG_STATE_DUNGEON);
// Remove players/groups from Queue
for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it)
- RemoveFromQueue(*it);
+ {
+ uint64 guid = (*it);
+ RemoveFromQueue(guid);
+ }
// Teleport Player
for (LfgPlayerList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it)
@@ -1643,17 +1533,14 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept)
playersToTeleport.clear();
}
-/// <summary>
-/// Remove a proposal from the pool, remove the group that didn't accept (if needed) and readd the other members to the queue
-/// </summary>
-/// <param name="LfgProposalMap::iterator">Proposal to remove</param>
-/// <param name="LfgUpdateType">Type of removal (LFG_UPDATETYPE_PROPOSAL_FAILED, LFG_UPDATETYPE_PROPOSAL_DECLINED)</param>
+/**
+ Remove a proposal from the pool, remove the group that didn't accept (if needed) and readd the other members to the queue
+
+ @param[in] itProposal Iterator to the proposal to remove
+ @param[in] type Type of removal (LFG_UPDATETYPE_PROPOSAL_FAILED, LFG_UPDATETYPE_PROPOSAL_DECLINED)
+*/
void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type)
{
- Player* plr;
- uint64 guid;
- LfgUpdateType updateType;
- LfgQueueInfoMap::iterator itQueue;
LfgProposal* pProposal = itProposal->second;
pProposal->state = LFG_PROPOSAL_FAILED;
@@ -1661,26 +1548,41 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t
// Mark all people that didn't answered as no accept
if (type == LFG_UPDATETYPE_PROPOSAL_FAILED)
for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it)
- if (it->second->accept != LFG_ANSWER_AGREE)
+ if (it->second->accept == LFG_ANSWER_PENDING)
it->second->accept = LFG_ANSWER_DENY;
- // Remove from queue all players/groups that didn't accept
+ // Mark players/groups to be removed
+ LfgGuidSet toRemove;
for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it)
- if (it->second->accept == LFG_ANSWER_DENY)
- RemoveFromQueue(it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : MAKE_NEW_GUID(it->first, 0, HIGHGUID_PLAYER));
+ {
+ if (it->second->accept == LFG_ANSWER_AGREE)
+ continue;
+
+ uint64 guid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : MAKE_NEW_GUID(it->first, 0, HIGHGUID_PLAYER);
+ // Player didn't accept or still pending when no secs left
+ if (it->second->accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED)
+ {
+ it->second->accept = LFG_ANSWER_DENY;
+ toRemove.insert(guid);
+ }
+ }
- // Inform players
+ // Notify players
for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it)
{
- plr = sObjectMgr.GetPlayerByLowGUID(it->first);
+ Player* plr = sObjectMgr.GetPlayerByLowGUID(it->first);
if (!plr)
continue;
- plr->GetSession()->SendUpdateProposal(itProposal->first, pProposal);
- guid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : plr->GetGUID();
- itQueue = m_QueueInfoMap.find(guid);
- if (itQueue == m_QueueInfoMap.end()) // Didn't accept or in same group that someone that didn't accept
+ plr->GetSession()->SendLfgUpdateProposal(itProposal->first, pProposal);
+
+ Group* grp = plr->GetGroup();
+ uint64 guid = plr->GetGUID();
+ uint64 gguid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : guid;
+
+ if (toRemove.find(gguid) != toRemove.end()) // Didn't accept or in same group that someone that didn't accept
{
+ LfgUpdateType updateType;
if (it->second->accept == LFG_ANSWER_DENY)
{
updateType = type;
@@ -1691,28 +1593,45 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t
updateType = LFG_UPDATETYPE_REMOVED_FROM_QUEUE;
sLog.outDebug("LFGMgr::RemoveProposal: [" UI64FMTD "] in same group that someone that didn't accept. Removing from queue and compatible cache", guid);
}
- plr->GetLfgDungeons()->clear();
- plr->SetLfgRoles(ROLE_NONE);
- if (!plr->GetGroup() || !plr->GetGroup()->isLFGGroup())
- plr->SetLfgState(LFG_STATE_NONE);
-
- if (plr->GetGroup())
+ plr->ClearLfgState();
+ if (grp)
+ {
+ grp->RestoreLfgState();
plr->GetSession()->SendLfgUpdateParty(updateType);
+ }
else
plr->GetSession()->SendLfgUpdatePlayer(updateType);
}
else
{
sLog.outDebug("LFGMgr::RemoveProposal: Readding [" UI64FMTD "] to queue.", guid);
- itQueue->second->joinTime = time_t(time(NULL));
- AddGuidToNewQueue(guid);
- if (plr->GetGroup())
+ plr->SetLfgState(LFG_STATE_QUEUED);
+ if (grp)
+ {
+ grp->SetLfgState(LFG_STATE_QUEUED);
plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_ADDED_TO_QUEUE, plr->GetLfgDungeons(), plr->GetLfgComment());
+ }
else
plr->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_ADDED_TO_QUEUE, plr->GetLfgDungeons(), plr->GetLfgComment());
}
}
+ // Remove players/groups from queue
+ for (LfgGuidSet::const_iterator it = toRemove.begin(); it != toRemove.end(); ++it)
+ {
+ uint64 guid = *it;
+ RemoveFromQueue(guid);
+ pProposal->queues.remove(guid);
+ }
+
+ // Readd to queue
+ for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it)
+ {
+ uint64 guid = *it;
+ AddToQueue(guid);
+ }
+
+ // Delete proposal
for (LfgProposalPlayerMap::const_iterator it = pProposal->players.begin(); it != pProposal->players.end(); ++it)
delete it->second;
pProposal->players.clear();
@@ -1721,36 +1640,40 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t
m_Proposals.erase(itProposal);
}
-/// <summary>
-/// Initialize a boot kick vote
-/// </summary>
-/// <param name="Group*">Group</param>
-/// <param name="uint32">Player low guid who inits the vote kick</param>
-/// <param name="uint32">Player low guid to be kicked </param>
-/// <param name="std::string">kick reason</param>
-void LFGMgr::InitBoot(Group* grp, uint32 iLowGuid, uint32 vLowguid, std::string reason)
+/**
+ Initialize a boot kick vote
+
+ @param[in] grp Group the vote kicks belongs to
+ @param[in] kicker Kicker low guid
+ @param[in] victim Victim low guid
+ @param[in] reason Kick reason
+*/
+void LFGMgr::InitBoot(Group* grp, uint32 kicker, uint32 victim, std::string reason)
{
if (!grp)
return;
+ grp->SetLfgState(LFG_STATE_BOOT);
+
LfgPlayerBoot* pBoot = new LfgPlayerBoot();
pBoot->inProgress = true;
pBoot->cancelTime = time_t(time(NULL)) + LFG_TIME_BOOT;
pBoot->reason = reason;
- pBoot->victimLowGuid = vLowguid;
+ pBoot->victimLowGuid = victim;
pBoot->votedNeeded = GROUP_LFG_KICK_VOTES_NEEDED;
PlayerSet players;
- uint32 pLowGuid = 0;
+ // Set votes
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
if (Player* plrg = itr->getSource())
{
- pLowGuid = plrg->GetGUIDLow();
- if (pLowGuid == vLowguid)
- pBoot->votes[pLowGuid] = LFG_ANSWER_DENY; // Victim auto vote NO
- else if (pLowGuid == iLowGuid)
- pBoot->votes[pLowGuid] = LFG_ANSWER_AGREE; // Kicker auto vote YES
+ plrg->SetLfgState(LFG_STATE_BOOT);
+ uint32 pLowGuid = plrg->GetGUIDLow();
+ if (pLowGuid == victim)
+ pBoot->votes[pLowGuid] = LFG_ANSWER_DENY; // Victim auto vote NO
+ else if (pLowGuid == kicker)
+ pBoot->votes[pLowGuid] = LFG_ANSWER_AGREE; // Kicker auto vote YES
else
{
pBoot->votes[pLowGuid] = LFG_ANSWER_PENDING; // Other members need to vote
@@ -1759,18 +1682,19 @@ void LFGMgr::InitBoot(Group* grp, uint32 iLowGuid, uint32 vLowguid, std::string
}
}
+ // Notify players
for (PlayerSet::const_iterator it = players.begin(); it != players.end(); ++it)
(*it)->GetSession()->SendLfgBootPlayer(pBoot);
- grp->SetLfgKickActive(true);
m_Boots[grp->GetLowGUID()] = pBoot;
}
-/// <summary>
-/// Update Boot info with player answer
-/// </summary>
-/// <param name="Player*">Player guid</param>
-/// <param name="bool">Player answer</param>
+/**
+ Update Boot info with player answer
+
+ @param[in] plr Player who has answered
+ @param[in] accept player answer
+*/
void LFGMgr::UpdateBoot(Player* plr, bool accept)
{
Group* grp = plr ? plr->GetGroup() : NULL;
@@ -1788,7 +1712,7 @@ void LFGMgr::UpdateBoot(Player* plr, bool accept)
if (!pBoot)
return;
- if (pBoot->votes[lowGuid] != LFG_ANSWER_PENDING) // Cheat check: Player can't vote twice
+ if (pBoot->votes[lowGuid] != LFG_ANSWER_PENDING) // Cheat check: Player can't vote twice
return;
pBoot->votes[lowGuid] = LfgAnswer(accept);
@@ -1805,8 +1729,8 @@ void LFGMgr::UpdateBoot(Player* plr, bool accept)
}
}
- if (agreeNum == pBoot->votedNeeded || // Vote passed
- votesNum == pBoot->votes.size() || // All voted but not passed
+ if (agreeNum == pBoot->votedNeeded || // Vote passed
+ votesNum == pBoot->votes.size() || // All voted but not passed
(pBoot->votes.size() - votesNum + agreeNum) < pBoot->votedNeeded) // Vote didnt passed
{
// Send update info to all players
@@ -1814,28 +1738,36 @@ void LFGMgr::UpdateBoot(Player* plr, bool accept)
for (LfgAnswerMap::const_iterator itVotes = pBoot->votes.begin(); itVotes != pBoot->votes.end(); ++itVotes)
if (Player* plrg = sObjectMgr.GetPlayerByLowGUID(itVotes->first))
if (plrg->GetGUIDLow() != pBoot->victimLowGuid)
+ {
+ plrg->SetLfgState(LFG_STATE_DUNGEON);
plrg->GetSession()->SendLfgBootPlayer(pBoot);
+ }
- if (agreeNum == pBoot->votedNeeded) // Vote passed - Kick player
+ grp->SetLfgState(LFG_STATE_DUNGEON);
+ if (agreeNum == pBoot->votedNeeded) // Vote passed - Kick player
{
Player::RemoveFromGroup(grp, MAKE_NEW_GUID(pBoot->victimLowGuid, 0, HIGHGUID_PLAYER));
if (Player* victim = sObjectMgr.GetPlayerByLowGUID(pBoot->victimLowGuid))
+ {
TeleportPlayer(victim, true, false);
+ victim->SetLfgState(LFG_STATE_NONE);
+ }
OfferContinue(grp);
grp->SetLfgKicks(grp->GetLfgKicks() + 1);
+
}
- grp->SetLfgKickActive(false);
delete pBoot;
m_Boots.erase(itBoot);
}
}
-/// <summary>
-/// Teleports the player in or out the dungeon
-/// </summary>
-/// <param name="Player*">Player</param>
-/// <param name="bool">Teleport out</param>
-/// <param name="bool">Automatic or manual teleport</param>
+/**
+ Teleports the player in or out the dungeon
+
+ @param[in] plr Player to teleport
+ @param[in] out Teleport out (true) or in (false)
+ @param[in] fromOpcode Function called from opcode handlers? (Default false)
+*/
void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/)
{
sLog.outDebug("LFGMgr::TeleportPlayer: [" UI64FMTD "] is being teleported %s", plr->GetGUID(), out ? "out" : "in");
@@ -1850,7 +1782,7 @@ void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/)
LfgTeleportError error = LFG_TELEPORTERROR_OK;
Group* grp = plr->GetGroup();
- if (!grp || !grp->isLFGGroup()) // should never happen, but just in case...
+ if (!grp || !grp->isLFGGroup()) // should never happen, but just in case...
error = LFG_TELEPORTERROR_INVALID_LOCATION;
else if (!plr->isAlive())
error = LFG_TELEPORTERROR_PLAYER_DEAD;
@@ -1862,7 +1794,7 @@ void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/)
if (!dungeon)
error = LFG_TELEPORTERROR_INVALID_LOCATION;
- else if (plr->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance
+ else if (plr->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance
{
uint32 mapid = 0;
float x = 0;
@@ -1872,11 +1804,11 @@ void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/)
if (!fromOpcode)
{
- Player *plrg;
+
// Select a player inside to be teleported to
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL && !mapid; itr = itr->next())
{
- plrg = itr->getSource();
+ Player* plrg = itr->getSource();
if (plrg && plrg != plr && plrg->GetMapId() == uint32(dungeon->map))
{
mapid = plrg->GetMapId();
@@ -1918,6 +1850,7 @@ void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/)
}
if (plr->TeleportTo(mapid, x, y, z, orientation))
+ // FIXME - HACK - this should be done by teleport, when teleporting far
plr->RemoveAurasByType(SPELL_AURA_MOUNTED);
else
{
@@ -1932,25 +1865,25 @@ void LFGMgr::TeleportPlayer(Player* plr, bool out, bool fromOpcode /*= false*/)
plr->GetSession()->SendLfgTeleportError(error);
}
-/// <summary>
-/// Give completion reward to player
-/// </summary>
-/// <param name="const uint32">dungeonId</param>
-/// <param name="Player*">player</param>
+/**
+ Give completion reward to player
+
+ @param[in] dungeonId Dungeonid (Obsolete)
+ @param[in] plr Player to reward
+*/
void LFGMgr::RewardDungeonDoneFor(const uint32 /*dungeonId*/, Player* player)
{
Group* group = player->GetGroup();
- if (!group || !group->isLFGGroup() || !sWorld.getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE))
+ if (!group || !group->isLFGGroup())
return;
// Mark dungeon as finished
- if (!group->isLfgDungeonComplete())
- group->SetLfgStatus(LFG_STATUS_COMPLETE);
+ group->SetLfgState(LFG_STATE_FINISHED_DUNGEON);
// Clear player related lfg stuff
uint32 rDungeonId = (*player->GetLfgDungeons()->begin());
- player->GetLfgDungeons()->clear();
- player->SetLfgRoles(ROLE_NONE);
+ player->ClearLfgState();
+ player->SetLfgState(LFG_STATE_FINISHED_DUNGEON);
// Give rewards only if its a random dungeon
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(rDungeonId);
@@ -1992,13 +1925,14 @@ void LFGMgr::RewardDungeonDoneFor(const uint32 /*dungeonId*/, Player* player)
// Auxiliar Functions
// --------------------------------------------------------------------------//
-/// <summary>
-/// Given a group get the dungeons that can't be done and reason
-/// </summary>
-/// <param name="PlayerSet*">Players to check lock status</param>
-/// <param name="LfgDungeonSet*">Dungeons to check</param>
-/// <param name="bool">Use dungeon entry (true) or id (false)</param>
-/// <returns>LfgLockStatusMap*</returns>
+/**
+ Given a group get the dungeons that can't be done and reason
+
+ @param[in] pPlayers Players to check lock status
+ @param[in] dungeons Dungeons to check
+ @param[in] useEntry Use dungeon entry (true) or id (false)
+ @returns Map of player's dungeon Lock status
+*/
LfgLockStatusMap* LFGMgr::GetGroupLockStatusDungeons(PlayerSet* pPlayers, LfgDungeonSet* dungeons, bool useEntry /* = true */)
{
if (!pPlayers || !dungeons)
@@ -2021,25 +1955,26 @@ LfgLockStatusMap* LFGMgr::GetGroupLockStatusDungeons(PlayerSet* pPlayers, LfgDun
return dungeonMap;
}
-/// <summary>
-/// Get all Group members list of dungeons that can't be done and reason
-/// leader excluded as the list given is he list he can do
-/// </summary>
-/// <param name="Player*">Player to get Party Lock info</param>
-/// <param name="LfgDungeonSet*">Dungeons to check</param>
-/// <returns>LfgLockStatusMap*</returns>
+/**
+ Get all Group members list of dungeons that can't be done and reason
+ leader excluded as the list given is he list he can do
+
+ @param[in] plr Players to check group lock status
+ @param[in] dungeons Dungeons to check (Default = NULL, means check all dungeons)
+ @returns Map of player's group dungeon Lock status
+*/
LfgLockStatusMap* LFGMgr::GetPartyLockStatusDungeons(Player* plr, LfgDungeonSet* dungeons /* = NULL */)
{
if (!plr)
return NULL;
- if (!dungeons)
- dungeons = GetAllDungeons();
-
Group* grp = plr->GetGroup();
if (!grp)
return NULL;
+ if (!dungeons)
+ dungeons = GetAllDungeons();
+
PlayerSet* pPlayers = new PlayerSet();
Player* plrg;
for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
@@ -2054,35 +1989,32 @@ LfgLockStatusMap* LFGMgr::GetPartyLockStatusDungeons(Player* plr, LfgDungeonSet*
return dungeonMap;
}
-/// <summary>
-/// Get list of dungeons player can't do and reasons
-/// </summary>
-/// <param name="Player*">Player to check lock status</param>
-/// <param name="LfgDungeonSet*">Dungeons to check</param>
-/// <param name="bool">Use dungeon entry (true) or id (false)</param>
-/// <returns>LfgLockStatusSet*</returns>
+/**
+ Get list of dungeons player can't do and reasons
+
+ @param[in] plr Players to check dungeon lock status
+ @param[in] dungeons Dungeons to check (Default = NULL, means check all dungeons)
+ @param[in] useEntry Use dungeon entry (true) or id (false)
+ @returns Set of player's dungeon Lock status
+*/
LfgLockStatusSet* LFGMgr::GetPlayerLockStatusDungeons(Player* plr, LfgDungeonSet* dungeons /* = NULL */, bool useEntry /* = true */)
{
LfgLockStatusSet* list = new LfgLockStatusSet();
- LfgLockStatus* lockstatus = NULL;
- LFGDungeonEntry const* dungeon;
- LfgLockStatusType locktype;
uint8 level = plr->getLevel();
uint8 expansion = plr->GetSession()->Expansion();
- AccessRequirement const* ar;
if (!dungeons)
dungeons = GetAllDungeons();
for (LfgDungeonSet::const_iterator it = dungeons->begin(); it != dungeons->end(); ++it)
{
- dungeon = sLFGDungeonStore.LookupEntry(*it);
+ LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(*it);
if (!dungeon) // should never happen - We provide a list from sLFGDungeonStore
continue;
- ar = sObjectMgr.GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty));
+ AccessRequirement const* ar = sObjectMgr.GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty));
- locktype = LFG_LOCKSTATUS_OK;
+ LfgLockStatusType locktype = LFG_LOCKSTATUS_OK;
if (dungeon->expansion > expansion)
locktype = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION;
else if (sDisableMgr.IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, plr))
@@ -2120,7 +2052,7 @@ LfgLockStatusSet* LFGMgr::GetPlayerLockStatusDungeons(Player* plr, LfgDungeonSet
if (locktype != LFG_LOCKSTATUS_OK)
{
- lockstatus = new LfgLockStatus();
+ LfgLockStatus* lockstatus = new LfgLockStatus();
lockstatus->dungeon = useEntry ? dungeon->Entry(): dungeon->ID;
lockstatus->lockstatus = locktype;
list->insert(lockstatus);
@@ -2134,28 +2066,24 @@ LfgLockStatusSet* LFGMgr::GetPlayerLockStatusDungeons(Player* plr, LfgDungeonSet
return list;
}
-/// <summary>
-/// Get the dungeon list that can be done.
-/// </summary>
-/// <returns>LfgDungeonSet*</returns>
+/**
+ Get the dungeon list that can be done.
+
+ @returns Set with all dungeons
+*/
LfgDungeonSet* LFGMgr::GetAllDungeons()
{
- LfgDungeonSet* alldungeons = m_CachedDungeonMap[0];
-
- if (alldungeons)
+ if (LfgDungeonSet* alldungeons = m_CachedDungeonMap[0])
return alldungeons;
- LfgDungeonSet* dungeons;
- LFGDungeonEntry const* dungeon;
-
- alldungeons = new LfgDungeonSet();
+ LfgDungeonSet* alldungeons = new LfgDungeonSet();
m_CachedDungeonMap[0] = alldungeons;
for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i)
{
- dungeon = sLFGDungeonStore.LookupEntry(i);
+ LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i);
if (!dungeon || dungeon->type == LFG_TYPE_ZONE)
continue;
- dungeons = m_CachedDungeonMap[dungeon->grouptype];
+ LfgDungeonSet* dungeons = m_CachedDungeonMap[dungeon->grouptype];
if (!dungeons)
{
dungeons = new LfgDungeonSet();
@@ -2169,12 +2097,12 @@ LfgDungeonSet* LFGMgr::GetAllDungeons()
return alldungeons;
}
-/// <summary>
-/// Get the dungeon list that can be done given a random dungeon entry.
-/// Special case: randomdungeon == 0 then will return all dungeons
-/// </summary>
-/// <param name="uint32">Random dungeon entry</param>
-/// <returns>LfgDungeonSet*</returns>
+/**
+ Get the dungeon list that can be done given a random dungeon entry.
+
+ @param[in] randomdungeon Random dungeon id (if value = 0 will return all dungeons)
+ @returns Set of dungeons
+*/
LfgDungeonSet* LFGMgr::GetDungeonsByRandom(uint32 randomdungeon)
{
uint8 groupType = 0;
@@ -2191,12 +2119,13 @@ LfgDungeonSet* LFGMgr::GetDungeonsByRandom(uint32 randomdungeon)
return dungeons;
}
-/// <summary>
-/// Get the random dungeon list that can be done at a certain level and expansion.
-/// </summary>
-/// <param name="uint8">Player level</param>
-/// <param name="uint8">Player account expansion</param>
-/// <returns>LfgDungeonSet*</returns>
+/**
+ Get the random dungeon list that can be done at a certain level and expansion.
+
+ @param[in] level Player level
+ @param[in] expansion Player account expansion
+ @returns Set of random dungeons entries
+*/
LfgDungeonSet* LFGMgr::GetRandomDungeons(uint8 level, uint8 expansion)
{
LfgDungeonSet* list = new LfgDungeonSet();
@@ -2211,12 +2140,13 @@ LfgDungeonSet* LFGMgr::GetRandomDungeons(uint8 level, uint8 expansion)
return list;
}
-/// <summary>
-/// Get the reward of a given random dungeon at a certain level
-/// </summary>
-/// <param name="uint32">random dungeon id</param>
-/// <param name="uint8">Player level</param>
-/// <returns>LfgReward const*</returns>
+/**
+ Get the reward of a given random dungeon at a certain level
+
+ @param[in] dungeon dungeon id
+ @param[in] level Player level
+ @returns Reward
+*/
LfgReward const* LFGMgr::GetRandomDungeonReward(uint32 dungeon, uint8 level)
{
LfgReward const* rew = NULL;
@@ -2232,11 +2162,12 @@ LfgReward const* LFGMgr::GetRandomDungeonReward(uint32 dungeon, uint8 level)
return rew;
}
-/// <summary>
-/// Given a Dungeon id returns the dungeon Type
-/// </summary>
-/// <param name="uint32">Dungeon id</param>
-/// <returns>uint8: Type</returns>
+/**
+ Given a Dungeon id returns the dungeon Type
+
+ @param[in] dungeon dungeon id
+ @returns Dungeon type
+*/
LfgType LFGMgr::GetDungeonType(uint32 dungeonId)
{
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId);
@@ -2246,11 +2177,12 @@ LfgType LFGMgr::GetDungeonType(uint32 dungeonId)
return LfgType(dungeon->type);
}
-/// <summary>
-/// Given a Dungeon id returns if it's random
-/// </summary>
-/// <param name="uint32">Dungeon id</param>
-/// <returns>bool</returns>
+/**
+ Given a Dungeon id returns if it's random
+
+ @param[in] dungeon dungeon id
+ @returns True if it's random dungeon
+*/
bool LFGMgr::isRandomDungeon(uint32 dungeonId)
{
LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId);
@@ -2260,11 +2192,12 @@ bool LFGMgr::isRandomDungeon(uint32 dungeonId)
return dungeon->type == LFG_TYPE_RANDOM;
}
-/// <summary>
-/// Given a Achievement id returns the related dungeon id
-/// </summary>
-/// <param name="uint32">Achievement id</param>
-/// <returns>uint32</returns>
+/**
+ Given a Achievement id returns the related dungeon id
+
+ @param[in] achievementId Achievement id
+ @returns dungeon id
+*/
uint32 LFGMgr::GetDungeonIdForAchievement(uint32 achievementId)
{
std::map<uint32, uint32>::iterator itr = m_EncountersByAchievement.find(achievementId);
@@ -2274,11 +2207,12 @@ uint32 LFGMgr::GetDungeonIdForAchievement(uint32 achievementId)
return 0;
};
-/// <summary>
-/// Given a list of guids returns the concatenation using | as delimiter
-/// </summary>
-/// <param name="LfgGuidList ">list of guids</param>
-/// <returns>std::string</returns>
+/**
+ Given a list of guids returns the concatenation using | as delimiter
+
+ @param[in] check list of guids
+ @returns Concatenated string
+*/
std::string LFGMgr::ConcatenateGuids(LfgGuidList check)
{
if (check.empty())
@@ -2300,11 +2234,12 @@ std::string LFGMgr::ConcatenateGuids(LfgGuidList check)
return o.str();
}
-/// <summary>
-/// Given a list of dungeonIds returns the concatenation using , as delimiter
-/// </summary>
-/// <param name="LfgDungeonSet ">list of dungeons</param>
-/// <returns>std::string</returns>
+/**
+ Given a list of dungeonIds returns the concatenation using , as delimiter
+
+ @param[in] dungeons list of dungeons
+ @returns Concatenated string
+*/
std::string LFGMgr::ConcatenateDungeons(LfgDungeonSet* dungeons)
{
std::string dungeonstr = "";
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 02b0694146a..2594b630756 100755
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -27,113 +27,144 @@ class Player;
enum LFGenum
{
- LFG_TIME_ROLECHECK = 2*MINUTE,
- LFG_TIME_BOOT = 2*MINUTE,
- LFG_TIME_PROPOSAL = 2*MINUTE,
- LFG_TANKS_NEEDED = 1,
- LFG_HEALERS_NEEDED = 1,
- LFG_DPS_NEEDED = 3,
- LFG_QUEUEUPDATE_INTERVAL = 15*IN_MILLISECONDS,
- LFG_SPELL_DUNGEON_COOLDOWN = 71328,
- LFG_SPELL_DUNGEON_DESERTER = 71041,
- LFG_SPELL_LUCK_OF_THE_DRAW = 72221,
+ LFG_TIME_ROLECHECK = 2*MINUTE,
+ LFG_TIME_BOOT = 2*MINUTE,
+ LFG_TIME_PROPOSAL = 2*MINUTE,
+ LFG_TANKS_NEEDED = 1,
+ LFG_HEALERS_NEEDED = 1,
+ LFG_DPS_NEEDED = 3,
+ LFG_QUEUEUPDATE_INTERVAL = 15*IN_MILLISECONDS,
+ LFG_SPELL_DUNGEON_COOLDOWN = 71328,
+ LFG_SPELL_DUNGEON_DESERTER = 71041,
+ LFG_SPELL_LUCK_OF_THE_DRAW = 72221,
};
+/// Determines the type of instance
enum LfgType
{
- LFG_TYPE_NONE = 0, // Internal use only
- LFG_TYPE_DUNGEON = 1,
- LFG_TYPE_RAID = 2,
- LFG_TYPE_QUEST = 3,
- LFG_TYPE_ZONE = 4,
- LFG_TYPE_HEROIC = 5,
- LFG_TYPE_RANDOM = 6,
+ LFG_TYPE_NONE = 0, // Internal use only
+ LFG_TYPE_DUNGEON = 1,
+ LFG_TYPE_RAID = 2,
+ LFG_TYPE_QUEST = 3,
+ LFG_TYPE_ZONE = 4,
+ LFG_TYPE_HEROIC = 5,
+ LFG_TYPE_RANDOM = 6,
};
+/// Proposal states
enum LfgProposalState
{
- LFG_PROPOSAL_INITIATING = 0,
- LFG_PROPOSAL_FAILED = 1,
- LFG_PROPOSAL_SUCCESS = 2,
+ LFG_PROPOSAL_INITIATING = 0,
+ LFG_PROPOSAL_FAILED = 1,
+ LFG_PROPOSAL_SUCCESS = 2,
};
+/// Instance lock types
enum LfgLockStatusType
{
- LFG_LOCKSTATUS_OK = 0, // Internal use only
- LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1,
- LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2,
- LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3,
- LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE = 4,
- LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE = 5,
- LFG_LOCKSTATUS_RAID_LOCKED = 6,
- LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL = 1001,
- LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002,
- LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022,
- LFG_LOCKSTATUS_MISSING_ITEM = 1025,
- LFG_LOCKSTATUS_NOT_IN_SEASON = 1031,
+ LFG_LOCKSTATUS_OK = 0, // Internal use only
+ LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION = 1,
+ LFG_LOCKSTATUS_TOO_LOW_LEVEL = 2,
+ LFG_LOCKSTATUS_TOO_HIGH_LEVEL = 3,
+ LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE = 4,
+ LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE = 5,
+ LFG_LOCKSTATUS_RAID_LOCKED = 6,
+ LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL = 1001,
+ LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL = 1002,
+ LFG_LOCKSTATUS_QUEST_NOT_COMPLETED = 1022,
+ LFG_LOCKSTATUS_MISSING_ITEM = 1025,
+ LFG_LOCKSTATUS_NOT_IN_SEASON = 1031,
};
+/// Teleport errors
enum LfgTeleportError
{
- LFG_TELEPORTERROR_OK = 0, // Internal use
- LFG_TELEPORTERROR_PLAYER_DEAD = 1,
- LFG_TELEPORTERROR_FALLING = 2,
- //LFG_TELEPORTERROR_UNK2 = 3, // You can't do that right now
- LFG_TELEPORTERROR_FATIGUE = 4,
- //LFG_TELEPORTERROR_UNK3 = 5, // No reaction
- LFG_TELEPORTERROR_INVALID_LOCATION = 6,
- //LFG_TELEPORTERROR_UNK4 = 7, // You can't do that right now
- //LFG_TELEPORTERROR_UNK5 = 8, // You can't do that right now
+ // 3, 7, 8 = "You can't do that right now" | 5 = No client reaction
+ LFG_TELEPORTERROR_OK = 0, // Internal use
+ LFG_TELEPORTERROR_PLAYER_DEAD = 1,
+ LFG_TELEPORTERROR_FALLING = 2,
+ LFG_TELEPORTERROR_FATIGUE = 4,
+ LFG_TELEPORTERROR_INVALID_LOCATION = 6,
};
+/// Queue join results
enum LfgJoinResult
{
- LFG_JOIN_OK = 0, // Joined (no client msg)
- LFG_JOIN_FAILED = 1, // RoleCheck Failed
- LFG_JOIN_GROUPFULL = 2, // Your group is full
- //LFG_JOIN_UNK3 = 3, // No client reaction
- LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error
- LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons
- LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons
- LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons
- LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms
- LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected
- LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members
- LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid
- LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off
- LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff
- LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown
- LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown
- LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members
- LFG_JOIN_USING_BG_SYSTEM = 17, // You can not use the dungeon system while in BG or arenas
- //LFG_JOIN_FAILED2 = 18, // RoleCheck Failed
+ // 3 = No client reaction | 18 = "Rolecheck failed"
+ LFG_JOIN_OK = 0, // Joined (no client msg)
+ LFG_JOIN_FAILED = 1, // RoleCheck Failed
+ LFG_JOIN_GROUPFULL = 2, // Your group is full
+ LFG_JOIN_INTERNAL_ERROR = 4, // Internal LFG Error
+ LFG_JOIN_NOT_MEET_REQS = 5, // You do not meet the requirements for the chosen dungeons
+ LFG_JOIN_PARTY_NOT_MEET_REQS = 6, // One or more party members do not meet the requirements for the chosen dungeons
+ LFG_JOIN_MIXED_RAID_DUNGEON = 7, // You cannot mix dungeons, raids, and random when picking dungeons
+ LFG_JOIN_MULTI_REALM = 8, // The dungeon you chose does not support players from multiple realms
+ LFG_JOIN_DISCONNECTED = 9, // One or more party members are pending invites or disconnected
+ LFG_JOIN_PARTY_INFO_FAILED = 10, // Could not retrieve information about some party members
+ LFG_JOIN_DUNGEON_INVALID = 11, // One or more dungeons was not valid
+ LFG_JOIN_DESERTER = 12, // You can not queue for dungeons until your deserter debuff wears off
+ LFG_JOIN_PARTY_DESERTER = 13, // One or more party members has a deserter debuff
+ LFG_JOIN_RANDOM_COOLDOWN = 14, // You can not queue for random dungeons while on random dungeon cooldown
+ LFG_JOIN_PARTY_RANDOM_COOLDOWN = 15, // One or more party members are on random dungeon cooldown
+ LFG_JOIN_TOO_MUCH_MEMBERS = 16, // You can not enter dungeons with more that 5 party members
+ LFG_JOIN_USING_BG_SYSTEM = 17, // You can not use the dungeon system while in BG or arenas
};
-enum LfgRoleCheckResult
+/// Role check states
+enum LfgRoleCheckState
{
- LFG_ROLECHECK_FINISHED = 1, // Role check finished
- LFG_ROLECHECK_INITIALITING = 2, // Role check begins
- LFG_ROLECHECK_MISSING_ROLE = 3, // Someone didn't selected a role after 2 mins
- LFG_ROLECHECK_WRONG_ROLES = 4, // Can't form a group with that role selection
- LFG_ROLECHECK_ABORTED = 5, // Someone leave the group
- LFG_ROLECHECK_NO_ROLE = 6, // Someone selected no role
+ LFG_ROLECHECK_FINISHED = 1, // Role check finished
+ LFG_ROLECHECK_INITIALITING = 2, // Role check begins
+ LFG_ROLECHECK_MISSING_ROLE = 3, // Someone didn't selected a role after 2 mins
+ LFG_ROLECHECK_WRONG_ROLES = 4, // Can't form a group with that role selection
+ LFG_ROLECHECK_ABORTED = 5, // Someone leave the group
+ LFG_ROLECHECK_NO_ROLE = 6, // Someone selected no role
};
+/// Answer state (Also used to check compatibilites)
enum LfgAnswer
{
- LFG_ANSWER_PENDING = -1,
- LFG_ANSWER_DENY = 0,
- LFG_ANSWER_AGREE = 1,
+ LFG_ANSWER_PENDING = -1,
+ LFG_ANSWER_DENY = 0,
+ LFG_ANSWER_AGREE = 1,
};
-// Dungeon and reason why player can't join
+
+// Forward declaration (just to have all typedef together)
+struct LfgReward;
+struct LfgLockStatus;
+struct LfgQueueInfo;
+struct LfgRoleCheck;
+struct LfgProposal;
+struct LfgProposalPlayer;
+struct LfgPlayerBoot;
+
+typedef std::set<uint64> LfgGuidSet;
+typedef std::list<uint64> LfgGuidList;
+typedef std::set<Player*> PlayerSet;
+typedef std::list<Player*> LfgPlayerList;
+typedef std::multimap<uint32, LfgReward const*> LfgRewardMap;
+typedef std::pair<LfgRewardMap::const_iterator, LfgRewardMap::const_iterator> LfgRewardMapBounds;
+typedef std::map<std::string, LfgAnswer> LfgCompatibleMap;
+typedef std::map<uint64, LfgDungeonSet*> LfgDungeonMap;
+typedef std::set<LfgLockStatus*> LfgLockStatusSet;
+typedef std::map<uint32, LfgLockStatusSet*> LfgLockStatusMap;
+typedef std::map<uint32, uint8> LfgRolesMap;
+typedef std::map<uint32, LfgAnswer> LfgAnswerMap;
+typedef std::map<uint32, LfgRoleCheck*> LfgRoleCheckMap;
+typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap;
+typedef std::map<uint32, LfgProposal*> LfgProposalMap;
+typedef std::map<uint32, LfgProposalPlayer*> LfgProposalPlayerMap;
+typedef std::map<uint32, LfgPlayerBoot*> LfgPlayerBootMap;
+
+/// Dungeon and reason why player can't join
struct LfgLockStatus
{
- uint32 dungeon;
- LfgLockStatusType lockstatus;
+ uint32 dungeon; ///< Dungeon Id
+ LfgLockStatusType lockstatus; ///< Lock type
};
-// Reward info
+/// Reward info
struct LfgReward
{
uint32 maxLevel;
@@ -156,34 +187,29 @@ struct LfgReward
}
};
-typedef std::map<uint32, uint8> LfgRolesMap;
-typedef std::map<uint32, LfgAnswer> LfgAnswerMap;
-typedef std::list<uint64> LfgGuidList;
-typedef std::map<uint64, LfgDungeonSet*> LfgDungeonMap;
-
-// Stores player or group queue info
+/// Stores player or group queue info
struct LfgQueueInfo
{
LfgQueueInfo(): tanks(LFG_TANKS_NEEDED), healers(LFG_HEALERS_NEEDED), dps(LFG_DPS_NEEDED) {};
- time_t joinTime; // Player queue join time (to calculate wait times)
- uint8 tanks; // Tanks needed
- uint8 healers; // Healers needed
- uint8 dps; // Dps needed
- LfgDungeonSet dungeons; // Selected Player/Group Dungeon/s
- LfgRolesMap roles; // Selected Player Role/s
+ time_t joinTime; ///< Player queue join time (to calculate wait times)
+ uint8 tanks; ///< Tanks needed
+ uint8 healers; ///< Healers needed
+ uint8 dps; ///< Dps needed
+ LfgDungeonSet dungeons; ///< Selected Player/Group Dungeon/s
+ LfgRolesMap roles; ///< Selected Player Role/s
};
+/// Stores player data related to proposal to join
struct LfgProposalPlayer
{
LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), groupLowGuid(0) {};
- uint8 role; // Proposed role
- LfgAnswer accept; // Accept status (-1 not answer | 0 Not agree | 1 agree)
- uint32 groupLowGuid; // Original group guid (Low guid) 0 if no original group
+ uint8 role; ///< Proposed role
+ LfgAnswer accept; ///< Accept status (-1 not answer | 0 Not agree | 1 agree)
+ uint32 groupLowGuid; ///< Original group guid (Low guid) 0 if no original group
};
-typedef std::map<uint32, LfgProposalPlayer*> LfgProposalPlayerMap;
-// Stores all Dungeon Proposal after matching candidates
+/// Stores group data related to proposal to join
struct LfgProposal
{
LfgProposal(uint32 dungeon): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING), groupLowGuid(0), leaderLowGuid(0) {}
@@ -195,89 +221,88 @@ struct LfgProposal
players.clear();
queues.clear();
};
- uint32 dungeonId; // Dungeon to join
- LfgProposalState state; // State of the proposal
- uint32 groupLowGuid; // Proposal group (0 if new)
- uint32 leaderLowGuid; // Leader guid.
- time_t cancelTime; // Time when we will cancel this proposal
- LfgGuidList queues; // Queue Ids to remove/readd
- LfgProposalPlayerMap players; // Player current groupId
+ uint32 dungeonId; ///< Dungeon to join
+ LfgProposalState state; ///< State of the proposal
+ uint32 groupLowGuid; ///< Proposal group (0 if new)
+ uint32 leaderLowGuid; ///< Leader guid.
+ time_t cancelTime; ///< Time when we will cancel this proposal
+ LfgGuidList queues; ///< Queue Ids to remove/readd
+ LfgProposalPlayerMap players; ///< Players data
};
-// Stores all rolecheck info of a group that wants to join LFG
+/// Stores all rolecheck info of a group that wants to join
struct LfgRoleCheck
{
- time_t cancelTime;
- LfgRolesMap roles;
- LfgRoleCheckResult result;
- LfgDungeonSet dungeons;
- uint32 leader;
+ time_t cancelTime; ///< Time when the rolecheck will fail
+ LfgRolesMap roles; ///< Player selected roles
+ LfgRoleCheckState result; ///< State of the rolecheck
+ LfgDungeonSet dungeons; ///< Dungeons group is applying for
+ uint32 leader; ///< Leader of the group
};
-// Stores information of a current vote to kick someone from a group
+/// Stores information of a current vote to kick someone from a group
struct LfgPlayerBoot
{
- time_t cancelTime; // Time left to vote
- bool inProgress; // Vote in progress
- LfgAnswerMap votes; // Player votes (-1 not answer | 0 Not agree | 1 agree)
- uint32 victimLowGuid; // Player guid to be kicked (can't vote)
- uint8 votedNeeded; // Votes needed to kick the player
- std::string reason; // kick reason
+ time_t cancelTime; ///< Time left to vote
+ bool inProgress; ///< Vote in progress
+ LfgAnswerMap votes; ///< Player votes (-1 not answer | 0 Not agree | 1 agree)
+ uint32 victimLowGuid; ///< Player guid to be kicked (can't vote)
+ uint8 votedNeeded; ///< Votes needed to kick the player
+ std::string reason; ///< kick reason
};
-typedef std::set<Player*> PlayerSet;
-typedef std::set<LfgLockStatus*> LfgLockStatusSet;
-typedef std::map<uint32, LfgLockStatusSet*> LfgLockStatusMap;
-typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap;
-typedef std::map<uint32, LfgRoleCheck*> LfgRoleCheckMap;
-typedef std::map<uint32, LfgProposal*> LfgProposalMap;
-typedef std::map<uint32, LfgPlayerBoot*> LfgPlayerBootMap;
-typedef std::multimap<uint32, LfgReward const*> LfgRewardMap;
-typedef std::pair<LfgRewardMap::const_iterator, LfgRewardMap::const_iterator> LfgRewardMapBounds;
-typedef std::list<Player*> LfgPlayerList;
-typedef std::set<uint64> LfgGuidSet;
-typedef std::map<std::string, LfgAnswer> LfgCompatibleMap;
-
-
class LFGMgr
{
friend class ACE_Singleton<LFGMgr, ACE_Null_Mutex>;
public:
LFGMgr();
~LFGMgr();
-
- void Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string comment);
- void Leave(Player* plr, Group* grp = NULL);
- void OfferContinue(Group* grp);
- void TeleportPlayer(Player* plr, bool out, bool fromOpcode = false);
- void UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept);
- void UpdateBoot(Player* plr, bool accept);
- void UpdateRoleCheck(Group* grp, Player* plr = NULL, bool newRoleCheck = false);
void Update(uint32 diff);
- bool isRandomDungeon(uint32 dungeonId);
- void InitBoot(Group* grp, uint32 plowGuid, uint32 vlowGuid, std::string reason);
-
+ // Reward
void LoadDungeonEncounters();
void LoadRewards();
void RewardDungeonDoneFor(const uint32 dungeonId, Player* player);
uint32 GetDungeonIdForAchievement(uint32 achievementId);
+ LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level);
+
+ // Queue
+ void Join(Player* plr, uint8 roles, LfgDungeonSet* dungeons, std::string comment);
+ void Leave(Player* plr, Group* grp = NULL);
+
+ // Role Check
+ void UpdateRoleCheck(Group* grp, Player* plr = NULL, bool newRoleCheck = false);
+ // Proposals
+ void UpdateProposal(uint32 proposalId, uint32 lowGuid, bool accept);
+
+ // Teleportation
+ void TeleportPlayer(Player* plr, bool out, bool fromOpcode = false);
+
+ // Vote kick
+ void InitBoot(Group* grp, uint32 plowGuid, uint32 vlowGuid, std::string reason);
+ void UpdateBoot(Player* plr, bool accept);
+ void OfferContinue(Group* grp);
+
+ // Lock info
LfgLockStatusMap* GetPartyLockStatusDungeons(Player* plr, LfgDungeonSet* dungeons = NULL);
- LfgDungeonSet* GetRandomDungeons(uint8 level, uint8 expansion);
LfgLockStatusSet* GetPlayerLockStatusDungeons(Player* plr, LfgDungeonSet* dungeons = NULL, bool useEntry = true);
- LfgReward const* GetRandomDungeonReward(uint32 dungeon, uint8 level);
+
+ // Generic
+ bool isRandomDungeon(uint32 dungeonId);
+ LfgDungeonSet* GetRandomDungeons(uint8 level, uint8 expansion);
private:
- void Cleaner();
- void AddGuidToNewQueue(uint64 guid);
+ // Queue
+ void AddToQueue(uint64& guid);
+ bool RemoveFromQueue(uint64& guid);
- bool RemoveFromQueue(uint64 guid);
+ // Proposals
void RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type);
+ // Group Matching
LfgProposal* FindNewGroups(LfgGuidList check, LfgGuidList all);
-
bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true);
bool CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal);
LfgDungeonSet* CheckCompatibleDungeons(LfgDungeonMap* dungeonsMap, PlayerSet* players);
@@ -285,35 +310,42 @@ class LFGMgr
void SetCompatibles(std::string concatenatedGuids, bool compatibles);
LfgAnswer GetCompatibles(std::string concatenatedGuids);
void RemoveFromCompatibles(uint64 guid);
- std::string ConcatenateGuids(LfgGuidList check);
- std::string ConcatenateDungeons(LfgDungeonSet* dungeons);
+ // Lock info
LfgLockStatusMap* GetGroupLockStatusDungeons(PlayerSet* pPlayers, LfgDungeonSet* dungeons, bool useEntry = true);
+
+ // Generic
LfgDungeonSet* GetDungeonsByRandom(uint32 randomdungeon);
LfgDungeonSet* GetAllDungeons();
LfgType GetDungeonType(uint32 dungeon);
+ std::string ConcatenateGuids(LfgGuidList check);
+ std::string ConcatenateDungeons(LfgDungeonSet* dungeons);
- LfgRewardMap m_RewardMap; // Stores rewards for random dungeons
- std::map<uint32, uint32> m_EncountersByAchievement; // Stores dungeon ids associated with achievements (for rewards)
- LfgDungeonMap m_CachedDungeonMap; // Stores all dungeons by groupType
- LfgQueueInfoMap m_QueueInfoMap; // Queued groups
- LfgGuidList m_currentQueue; // Ordered list. Used to find groups
- LfgGuidList m_newToQueue; // New groups to add to queue
- LfgCompatibleMap m_CompatibleMap; // Compatible dungeons
- LfgProposalMap m_Proposals; // Current Proposals
- LfgPlayerBootMap m_Boots; // Current player kicks
- LfgRoleCheckMap m_RoleChecks; // Current Role checks
- uint32 m_QueueTimer; // used to check interval of update
- uint32 m_lfgProposalId; // used as internal counter for proposals
- int32 m_WaitTimeAvg;
- int32 m_WaitTimeTank;
- int32 m_WaitTimeHealer;
- int32 m_WaitTimeDps;
- uint32 m_NumWaitTimeAvg;
- uint32 m_NumWaitTimeTank;
- uint32 m_NumWaitTimeHealer;
- uint32 m_NumWaitTimeDps;
- bool m_update;
+ // General variables
+ bool m_update; ///< Doing an update?
+ uint32 m_QueueTimer; ///< used to check interval of update
+ uint32 m_lfgProposalId; ///< used as internal counter for proposals
+ int32 m_WaitTimeAvg; ///< Average wait time to find a group queuing as multiple roles
+ int32 m_WaitTimeTank; ///< Average wait time to find a group queuing as tank
+ int32 m_WaitTimeHealer; ///< Average wait time to find a group queuing as healer
+ int32 m_WaitTimeDps; ///< Average wait time to find a group queuing as dps
+ uint32 m_NumWaitTimeAvg; ///< Num of players used to calc avs wait time
+ uint32 m_NumWaitTimeTank; ///< Num of players used to calc tank wait time
+ uint32 m_NumWaitTimeHealer; ///< Num of players used to calc healers wait time
+ uint32 m_NumWaitTimeDps; ///< Num of players used to calc dps wait time
+ LfgDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType
+ // Reward System
+ LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons
+ std::map<uint32, uint32> m_EncountersByAchievement;///< Stores dungeon ids associated with achievements (for rewards)
+ // Queue
+ LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups
+ LfgGuidList m_currentQueue; ///< Ordered list. Used to find groups
+ LfgGuidList m_newToQueue; ///< New groups to add to queue
+ LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons
+ // Rolecheck - Proposal - Vote Kicks
+ LfgRoleCheckMap m_RoleChecks; ///< Current Role checks
+ LfgProposalMap m_Proposals; ///< Current Proposals
+ LfgPlayerBootMap m_Boots; ///< Current player kicks
};
#define sLFGMgr (*ACE_Singleton<LFGMgr, ACE_Null_Mutex>::instance())
diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp
new file mode 100644
index 00000000000..465cf7047a3
--- /dev/null
+++ b/src/server/game/DungeonFinding/LFGScripts.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Interaction between core and LFGScripts
+ */
+
+#include "Common.h"
+#include "SharedDefines.h"
+#include "Player.h"
+#include "Group.h"
+#include "ScriptPCH.h"
+#include "LFGScripts.h"
+#include "LFGMgr.h"
+
+LFGScripts::LFGScripts(): GroupScript("LFGScripts"), PlayerScript("LFGScripts") {}
+
+void LFGScripts::OnAddMember(Group* group, uint64 guid)
+{
+ uint64 gguid = group->GetGUID();
+ if (!gguid)
+ return;
+
+ sLog.outDebug("LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "]", gguid, guid);
+ for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ if (Player *plrg = itr->getSource())
+ {
+ plrg->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
+ plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
+ }
+ }
+
+ // TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued
+ if (group->GetLfgState() == LFG_STATE_QUEUED)
+ sLFGMgr.Leave(NULL, group);
+
+ Player *plr = sObjectMgr.GetPlayer(guid);
+ if (plr && plr->GetLfgState() == LFG_STATE_QUEUED)
+ sLFGMgr.Leave(plr);
+}
+
+void LFGScripts::OnRemoveMember(Group* group, uint64 guid, RemoveMethod& method, uint64 kicker, const char* reason)
+{
+ uint64 gguid = group->GetGUID();
+ if (!gguid || method == GROUP_REMOVEMETHOD_DEFAULT)
+ return;
+
+ sLog.outDebug("LFGScripts::OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : ""));
+ if (group->GetLfgState() == LFG_STATE_QUEUED)
+ {
+ // TODO - Do not remove, just remove the one leaving and rejoin queue with all other data
+ sLFGMgr.Leave(NULL, group);
+ }
+
+ if (!group->isLFGGroup())
+ return;
+
+ if (method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked
+ {
+ // TODO - Update internal kick cooldown of kicker
+ std::string str_reason = "";
+ if (reason)
+ str_reason = std::string(reason);
+ sLFGMgr.InitBoot(group, GUID_LOPART(kicker), GUID_LOPART(guid), str_reason);
+ return;
+ }
+
+ if (Player *plr = sObjectMgr.GetPlayer(guid))
+ {
+ /*
+ if (method == GROUP_REMOVEMETHOD_LEAVE)
+ // Add deserter flag
+ else if (group->isLfgKickActive())
+ // Update internal kick cooldown of kicked
+ */
+
+ plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
+ if (plr->GetMap()->IsDungeon()) // Teleport player out the dungeon
+ sLFGMgr.TeleportPlayer(plr, true);
+ }
+
+ if (group->GetLfgState() != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon
+ sLFGMgr.OfferContinue(group);
+}
+
+void LFGScripts::OnDisband(Group* group)
+{
+ uint64 gguid = group->GetGUID();
+ if (!gguid)
+ return;
+
+ sLog.outDebug("LFGScripts::OnDisband [" UI64FMTD "]", gguid);
+ if (group->GetLfgState() == LFG_STATE_QUEUED)
+ sLFGMgr.Leave(NULL, group);
+
+ for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ if (Player *plrg = itr->getSource())
+ {
+ plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_GROUP_DISBAND);
+ plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
+ if (plrg->GetMap()->IsDungeon()) // Teleport player out the dungeon
+ sLFGMgr.TeleportPlayer(plrg, true);
+ }
+ }
+}
+
+void LFGScripts::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
+{
+ uint64 gguid = group->GetGUID();
+ if (!gguid)
+ return;
+
+ sLog.outDebug("LFGScripts::OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid);
+ Player *plr = sObjectMgr.GetPlayer(newLeaderGuid);
+ if (plr)
+ plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
+
+ plr = sObjectMgr.GetPlayer(oldLeaderGuid);
+ if (plr)
+ plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_GROUP_DISBAND);
+}
+
+void LFGScripts::OnInviteMember(Group* group, uint64 guid)
+{
+ uint64 gguid = group->GetGUID();
+ if (!gguid)
+ return;
+
+ sLog.outDebug("LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID());
+ sLFGMgr.Leave(NULL, group);
+}
+
+void LFGScripts::OnLevelChanged(Player* /*player*/, uint8 /*newLevel*/)
+{
+ // TODO - Invalidate LockStatus from cache
+}
+
+void LFGScripts::OnLogout(Player* player)
+{
+ sLFGMgr.Leave(player);
+ player->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
+ player->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
+ player->GetSession()->SendLfgUpdateSearch(false);
+}
+
+void LFGScripts::OnLogin(Player* /*player*/)
+{
+ // TODO - Restore LfgPlayerData and send proper status to player if it was in a group
+} \ No newline at end of file
diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h
new file mode 100644
index 00000000000..e6216cf8d8e
--- /dev/null
+++ b/src/server/game/DungeonFinding/LFGScripts.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Interaction between core and LFGScripts
+ */
+
+#include "Common.h"
+#include "SharedDefines.h"
+#include "ScriptPCH.h"
+
+class Player;
+class Group;
+
+class LFGScripts: public GroupScript, PlayerScript
+{
+ public:
+ LFGScripts();
+
+ // Group Hooks
+ void OnAddMember(Group* group, uint64 guid);
+ void OnRemoveMember(Group* group, uint64 guid, RemoveMethod& method, uint64 kicker, const char* reason);
+ void OnDisband(Group* group);
+ void OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid);
+ void OnInviteMember(Group* group, uint64 guid);
+
+ // Player Hooks
+ void OnLevelChanged(Player* player, uint8 newLevel);
+ void OnLogout(Player* player);
+ void OnLogin(Player* player);
+};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index cc4ca11f207..5cbddf37082 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -22190,13 +22190,13 @@ PartyResult Player::CanUninviteFromGroup() const
if (grp->GetLfgKicks() == GROUP_MAX_LFG_KICKS)
return ERR_PARTY_LFG_BOOT_LIMIT;
- if (grp->isLfgKickActive())
+ if (GetLfgState() == LFG_STATE_BOOT)
return ERR_PARTY_LFG_BOOT_IN_PROGRESS;
if (grp->GetMembersCount() <= GROUP_LFG_KICK_VOTES_NEEDED)
return ERR_PARTY_LFG_BOOT_TOO_FEW_PLAYERS;
- if (grp->isLfgDungeonComplete())
+ if (GetLfgState() == LFG_STATE_FINISHED_DUNGEON)
return ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE;
if (grp->isRollLootActive())
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index e64c7d0807b..05c1f45199f 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2260,10 +2260,27 @@ class Player : public Unit, public GridObject<Player>
void SetLfgComment(std::string _comment) { m_LookingForGroup.comment = _comment; }
uint8 GetLfgRoles() { return m_LookingForGroup.roles; }
void SetLfgRoles(uint8 _roles) { m_LookingForGroup.roles = _roles; }
- bool GetLfgUpdate() { return m_LookingForGroup.update; }
- void SetLfgUpdate(bool update) { m_LookingForGroup.update = update; }
- LfgState GetLfgState() { return m_LookingForGroup.state; }
- void SetLfgState(LfgState state) { m_LookingForGroup.state = state; }
+ LfgState GetLfgState() const { return m_LookingForGroup.state; }
+ void SetLfgState(LfgState state)
+ {
+
+ switch(state)
+ {
+ case LFG_STATE_NONE:
+ case LFG_STATE_DUNGEON:
+ case LFG_STATE_FINISHED_DUNGEON:
+ m_LookingForGroup.oldState = state;
+ // No break on purpose
+ default:
+ m_LookingForGroup.state = state;
+ }
+ }
+ void ClearLfgState()
+ {
+ m_LookingForGroup.applyDungeons.clear();
+ m_LookingForGroup.roles = ROLE_NONE;
+ m_LookingForGroup.state = m_LookingForGroup.oldState;
+ }
bool isUsingLfg() { return GetLfgState() != LFG_STATE_NONE; }
typedef std::set<uint32> DFQuestsDoneList;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 9244544e91a..78fe393e696 100755
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -53,24 +53,11 @@ Loot* Roll::getLoot()
return getTarget();
}
-Group::Group()
-{
- m_leaderGuid = 0;
- m_groupType = GroupType(0);
- m_bgGroup = NULL;
- m_lootMethod = LootMethod(0);
- m_looterGuid = 0;
- m_lootThreshold = ITEM_QUALITY_UNCOMMON;
- m_subGroupsCounts = NULL;
- m_guid = 0;
- m_counter = 0;
- m_maxEnchantingLevel= 0;
- m_LfgQueued = false;
- m_LfgStatus = LFG_STATUS_NOT_SAVED;
- m_LfgDungeonEntry = 0;
- m_Lfgkicks = 0;
- m_LfgkicksActive = false;
-
+Group::Group() : m_leaderGuid(0), m_groupType(GROUPTYPE_NORMAL), m_bgGroup(NULL),
+m_lootMethod(FREE_FOR_ALL), m_looterGuid(0), m_lootThreshold(ITEM_QUALITY_UNCOMMON),
+m_subGroupsCounts(NULL), m_guid(0), m_counter(0), m_maxEnchantingLevel(0),
+m_LfgState(LFG_STATE_NONE), m_LfgOldState(LFG_STATE_NONE), m_LfgDungeonEntry(0), m_Lfgkicks(0)
+{
for (uint8 i = 0; i < TARGETICONCOUNT; ++i)
m_targetIcons[i] = 0;
}
@@ -1119,7 +1106,7 @@ void Group::SendUpdate()
data << uint8(citr->roles);
if (isLFGGroup())
{
- data << uint8(m_LfgStatus);
+ data << uint8(m_LfgState == LFG_STATE_FINISHED_DUNGEON ? 2 : 0); // FIXME - Dungeon save status? 2 = done
data << uint32(m_LfgDungeonEntry);
}
@@ -1936,30 +1923,21 @@ void Group::SetLootThreshold(ItemQualities threshold)
m_lootThreshold = threshold;
}
-void Group::SetLfgQueued(bool queued)
+void Group::SetLfgState(LfgState state)
{
- m_LfgQueued = queued;
+ m_LfgState = state;
}
-bool Group::isLfgQueued()
+LfgState Group::GetLfgState()
{
- return m_LfgQueued;
+ return m_LfgState;
}
-void Group::SetLfgStatus(uint8 status)
+void Group::RestoreLfgState()
{
- m_LfgStatus = status;
+ m_LfgState = m_LfgOldState;
}
-uint8 Group::GetLfgStatus()
-{
- return m_LfgStatus;
-}
-
-bool Group::isLfgDungeonComplete() const
-{
- return m_LfgStatus == LFG_STATUS_COMPLETE;
-}
void Group::SetLfgDungeonEntry(uint32 dungeonEntry)
{
@@ -1974,16 +1952,6 @@ uint32 Group::GetLfgDungeonEntry(bool id /* = true*/)
return m_LfgDungeonEntry;
}
-bool Group::isLfgKickActive() const
-{
- return m_LfgkicksActive;
-}
-
-void Group::SetLfgKickActive(bool active)
-{
- m_LfgkicksActive = active;
-}
-
uint8 Group::GetLfgKicks() const
{
return m_Lfgkicks;
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 7d6eea412b6..7e0cfe1413c 100755
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -55,13 +55,6 @@ enum RollVote
NOT_VALID = 5
};
-enum LfgDungeonStatus
-{
- LFG_STATUS_SAVED = 0,
- LFG_STATUS_NOT_SAVED = 1,
- LFG_STATUS_COMPLETE = 2,
-};
-
enum GroupMemberOnlineStatus
{
MEMBER_STATUS_OFFLINE = 0x0000,
@@ -202,15 +195,11 @@ class Group
void Disband(bool hideDestroy=false);
// Dungeon Finder
- void SetLfgQueued(bool queued);
- bool isLfgQueued();
- void SetLfgStatus(uint8 status);
- uint8 GetLfgStatus();
- bool isLfgDungeonComplete() const;
+ void SetLfgState(LfgState state);
+ LfgState GetLfgState();
+ void RestoreLfgState();
void SetLfgDungeonEntry(uint32 dungeonEntry);
uint32 GetLfgDungeonEntry(bool id = true);
- bool isLfgKickActive() const;
- void SetLfgKickActive(bool active);
uint8 GetLfgKicks() const;
void SetLfgKicks(uint8 kicks);
void SetLfgRoles(uint64 guid, const uint8 roles);
@@ -357,10 +346,9 @@ class Group
uint64 m_guid;
uint32 m_counter; // used only in SMSG_GROUP_LIST
uint32 m_maxEnchantingLevel;
- bool m_LfgQueued;
- uint8 m_LfgStatus;
+ LfgState m_LfgState;
+ LfgState m_LfgOldState;
uint32 m_LfgDungeonEntry;
uint8 m_Lfgkicks;
- bool m_LfgkicksActive;
};
#endif
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index a08e5a74cfd..c7e82516bdf 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -2874,4 +2874,16 @@ enum RemoveMethod
GROUP_REMOVEMETHOD_LEAVE = 2,
};
+enum LfgState
+{
+ LFG_STATE_NONE, // Not using LFG / LFR
+ LFG_STATE_ROLECHECK, // Rolecheck active
+ LFG_STATE_QUEUED, // Queued
+ LFG_STATE_PROPOSAL, // Proposal active
+ LFG_STATE_BOOT, // Vote kick active
+ LFG_STATE_DUNGEON, // In LFG Group, in a Dungeon
+ LFG_STATE_FINISHED_DUNGEON, // In LFG Group, in a finished Dungeon
+ LFG_STATE_RAIDBROWSER, // Using Raid finder
+};
+
#endif
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index d2b1cfc6bdb..78da1ad549d 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -76,7 +76,6 @@ void AddSC_npc_innkeeper();
void AddSC_npcs_special();
void AddSC_npc_taxi();
void AddSC_achievement_scripts();
-void AddSC_dungeon_finder();
//eastern kingdoms
void AddSC_alterac_valley(); //Alterac Valley
@@ -664,7 +663,6 @@ void AddWorldScripts()
AddSC_npc_taxi();
AddSC_achievement_scripts();
AddSC_chat_log();
- AddSC_dungeon_finder();
#endif
}
diff --git a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp
index 45dea6d98ce..fd0c77de0c8 100755
--- a/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/LFGHandler.cpp
@@ -137,7 +137,7 @@ void WorldSession::HandleLfgSetRolesOpcode(WorldPacket &recv_data)
sLFGMgr.UpdateRoleCheck(grp, GetPlayer());
}
-void WorldSession::HandleSetLfgCommentOpcode(WorldPacket & recv_data)
+void WorldSession::HandleLfgSetCommentOpcode(WorldPacket & recv_data)
{
std::string comment;
recv_data >> comment;
@@ -535,7 +535,7 @@ void WorldSession::SendLfgBootPlayer(LfgPlayerBoot* pBoot)
SendPacket(&data);
}
-void WorldSession::SendUpdateProposal(uint32 proposalId, LfgProposal* pProp)
+void WorldSession::SendLfgUpdateProposal(uint32 proposalId, LfgProposal* pProp)
{
if (!pProp)
return;
@@ -554,7 +554,7 @@ void WorldSession::SendUpdateProposal(uint32 proposalId, LfgProposal* pProp)
Group* grp = dLowGuid ? sObjectMgr.GetGroupByGUID(dLowGuid) : NULL;
if (grp)
{
- isContinue = grp->isLFGGroup() && !grp->isLfgDungeonComplete();
+ isContinue = grp->isLFGGroup() && grp->GetLfgState() != LFG_STATE_FINISHED_DUNGEON;
isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue;
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 457aeb195e9..4101014b29c 100755
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -896,7 +896,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x363*/ { "SMSG_LFG_ROLE_CHECK_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x364*/ { "SMSG_LFG_JOIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x365*/ { "SMSG_LFG_QUEUE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
- /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgCommentOpcode },
+ /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode },
/*0x367*/ { "SMSG_LFG_UPDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x368*/ { "SMSG_LFG_UPDATE_PARTY", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x369*/ { "SMSG_LFG_UPDATE_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide },
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 9c853ef9b2f..083d4c0786d 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -718,7 +718,7 @@ class WorldSession
void HandleHearthAndResurrect(WorldPacket& recv_data);
// Looking for Dungeon/Raid
- void HandleSetLfgCommentOpcode(WorldPacket & recv_data);
+ void HandleLfgSetCommentOpcode(WorldPacket & recv_data);
void HandleLfgPlayerLockInfoRequestOpcode(WorldPacket& recv_data);
void HandleLfgPartyLockInfoRequestOpcode(WorldPacket& recv_data);
void HandleLfgJoinOpcode(WorldPacket &recv_data);
@@ -739,7 +739,7 @@ class WorldSession
void SendLfgQueueStatus(uint32 dungeon, int32 waitTime, int32 avgWaitTime, int32 waitTimeTanks, int32 waitTimeHealer, int32 waitTimeDps, uint32 queuedTime, uint8 tanks, uint8 healers, uint8 dps);
void SendLfgPlayerReward(uint32 rdungeonEntry, uint32 sdungeonEntry, uint8 done, const LfgReward *reward, const Quest *qRew);
void SendLfgBootPlayer(LfgPlayerBoot *pBoot);
- void SendUpdateProposal(uint32 proposalId, LfgProposal *pProp);
+ void SendLfgUpdateProposal(uint32 proposalId, LfgProposal *pProp);
void SendLfgDisabled();
void SendLfgOfferContinue(uint32 dungeonEntry);
void SendLfgTeleportError(uint8 err);
diff --git a/src/server/scripts/World/CMakeLists.txt b/src/server/scripts/World/CMakeLists.txt
index 3cc27cd8b5e..2f015db7cb4 100644
--- a/src/server/scripts/World/CMakeLists.txt
+++ b/src/server/scripts/World/CMakeLists.txt
@@ -7,7 +7,6 @@ set(scripts_STAT_SRCS
World/boss_taerar.cpp
World/boss_ysondre.cpp
World/chat_log.cpp
- World/dungeon_finder.cpp
World/go_scripts.cpp
World/guards.cpp
World/item_scripts.cpp
diff --git a/src/server/scripts/World/dungeon_finder.cpp b/src/server/scripts/World/dungeon_finder.cpp
deleted file mode 100644
index 60a8ede4360..00000000000
--- a/src/server/scripts/World/dungeon_finder.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Interaction between core and LFGMgr
- */
-
-#include "ScriptPCH.h"
-#include "LFGMgr.h"
-#include "Group.h"
-
-class DungeonFinderScript: public GroupScript, PlayerScript
-{
-public:
- DungeonFinderScript(): GroupScript("DungeonFinderScript"), PlayerScript("DungeonFinderScript") { }
-
- void OnAddMember(Group* group, uint64 guid)
- {
- uint64 gguid = group->GetGUID();
- sLog.outDebug("OnAddMember [" UI64FMTD "]: added [" UI64FMTD "]", gguid, guid);
- if (!gguid)
- return;
-
- for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- if (Player *plrg = itr->getSource())
- {
- plrg->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
- plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_CLEAR_LOCK_LIST);
- }
- }
-
- if (group->isLfgQueued())
- sLFGMgr.Leave(NULL, group);
-
- Player *plr = sObjectMgr.GetPlayer(guid);
- if (plr && plr->isUsingLfg())
- sLFGMgr.Leave(plr);
- }
-
- void OnRemoveMember(Group* group, uint64 guid, RemoveMethod& method, uint64 kicker, const char* reason)
- {
- uint64 gguid = group->GetGUID();
- sLog.outDebug("OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : ""));
- if (!gguid)
- return;
-
- if (group->isLfgQueued())
- {
- // TODO - Do not remove, just remove the one leaving and rejoin queue with all other data
- sLFGMgr.Leave(NULL, group);
- }
-
- if (!group->isLFGGroup())
- return;
-
- if (method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked
- {
- // TODO - Update internal kick cooldown of kicker
- std::string str_reason = "";
- if (reason)
- str_reason = std::string(reason);
- sLFGMgr.InitBoot(group, GUID_LOPART(kicker), GUID_LOPART(guid), str_reason);
- return;
- }
-
- if (Player *plr = sObjectMgr.GetPlayer(guid))
- {
- /*
- if (method == GROUP_REMOVEMETHOD_LEAVE)
- // Add deserter flag
- else if (group->isLfgKickActive())
- // Update internal kick cooldown of kicked
- */
-
- plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
- if (plr->GetMap()->IsDungeon()) // Teleport player out the dungeon
- sLFGMgr.TeleportPlayer(plr, true);
- }
-
- if (!group->isLfgDungeonComplete()) // Need more players to finish the dungeon
- sLFGMgr.OfferContinue(group);
- }
-
- void OnDisband(Group* group)
- {
- uint64 gguid = group->GetGUID();
- sLog.outDebug("OnDisband [" UI64FMTD "]", gguid);
- if (!gguid)
- return;
-
- if (group->isLfgQueued())
- sLFGMgr.Leave(NULL, group);
-
- for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
- {
- if (Player *plrg = itr->getSource())
- {
- plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_GROUP_DISBAND);
- plrg->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
- if (plrg->GetMap()->IsDungeon()) // Teleport player out the dungeon
- sLFGMgr.TeleportPlayer(plrg, true);
- }
- }
- }
-
- void OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid)
- {
- uint64 gguid = group->GetGUID();
- sLog.outDebug("OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid);
- if (!gguid)
- return;
-
- Player *plr = sObjectMgr.GetPlayer(newLeaderGuid);
- if (plr)
- plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_LEADER);
-
- plr = sObjectMgr.GetPlayer(oldLeaderGuid);
- if (plr)
- plr->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_GROUP_DISBAND);
- }
-
- void OnInviteMember(Group* group, uint64 guid)
- {
- uint64 gguid = group->GetGUID();
- sLog.outDebug("OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID());
- if (!gguid)
- return;
-
- sLFGMgr.Leave(NULL, group);
- }
-
- void OnLevelChanged(Player* /*player*/, uint8 /*newLevel*/)
- {
- }
-
- void OnLogout(Player* player)
- {
- sLFGMgr.Leave(player);
- player->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
- player->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE);
- player->GetSession()->SendLfgUpdateSearch(false);
- }
-};
-
-void AddSC_dungeon_finder()
-{
- new DungeonFinderScript();
-}