diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/DungeonFinding/LFG.h | 13 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.cpp | 1139 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.h | 362 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGScripts.cpp | 165 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGScripts.h | 45 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 4 | ||||
-rwxr-xr-x | src/server/game/Entities/Player/Player.h | 25 | ||||
-rwxr-xr-x | src/server/game/Groups/Group.cpp | 56 | ||||
-rwxr-xr-x | src/server/game/Groups/Group.h | 22 | ||||
-rwxr-xr-x | src/server/game/Miscellaneous/SharedDefines.h | 12 | ||||
-rwxr-xr-x | src/server/game/Scripting/ScriptLoader.cpp | 2 | ||||
-rwxr-xr-x | src/server/game/Server/Protocol/Handlers/LFGHandler.cpp | 6 | ||||
-rwxr-xr-x | src/server/game/Server/Protocol/Opcodes.cpp | 2 | ||||
-rwxr-xr-x | src/server/game/Server/WorldSession.h | 4 | ||||
-rw-r--r-- | src/server/scripts/World/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/server/scripts/World/dungeon_finder.cpp | 163 |
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(); -} |