diff options
author | Spp <spp@jorge.gr> | 2012-10-18 14:31:28 +0200 |
---|---|---|
committer | Spp <spp@jorge.gr> | 2012-10-18 14:31:28 +0200 |
commit | 479d34d2a0e54c13160d8f52c37dbf691d14d933 (patch) | |
tree | 504f6adc72e82743846068a1aac0c6d72e6c5a88 | |
parent | d0334bf94839301cda93f95913db8ea3f27c19cb (diff) |
Core/Dungeon Finder: Minor optimizations
- Internal changes in store types
- Remove of (Player *) and (Group *) From LFGMgr.cpp (step 2)
-rw-r--r-- | sql/updates/world/2012_10_18_00_world_trinity_string.sql | 16 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFG.h | 13 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGGroupData.cpp | 42 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGGroupData.h | 14 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.cpp | 700 | ||||
-rwxr-xr-x | src/server/game/DungeonFinding/LFGMgr.h | 90 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGPlayerData.cpp | 38 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGPlayerData.h | 22 | ||||
-rw-r--r-- | src/server/game/DungeonFinding/LFGScripts.cpp | 92 | ||||
-rwxr-xr-x | src/server/game/Handlers/LFGHandler.cpp | 103 | ||||
-rwxr-xr-x | src/server/game/Miscellaneous/Language.h | 17 |
11 files changed, 644 insertions, 503 deletions
diff --git a/sql/updates/world/2012_10_18_00_world_trinity_string.sql b/sql/updates/world/2012_10_18_00_world_trinity_string.sql new file mode 100644 index 00000000000..8d62174d868 --- /dev/null +++ b/sql/updates/world/2012_10_18_00_world_trinity_string.sql @@ -0,0 +1,16 @@ +REPLACE INTO `trinity_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) +VALUES + (11015, 'Error', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11014, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11013, 'Leader', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11012, 'Dps', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11011, 'Healer', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11010, 'Tank', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11009, 'Raid browser', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11008, 'Finished dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11007, 'In dungeon', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11006, 'Vote kick', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11005, 'Proposal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11004, 'Queued', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11003, 'Role check', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), + (11002, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h index c00cc830ce8..abdb0ffa511 100755 --- a/src/server/game/DungeonFinding/LFG.h +++ b/src/server/game/DungeonFinding/LFG.h @@ -39,7 +39,7 @@ enum LfgRoles enum LfgUpdateType { LFG_UPDATETYPE_DEFAULT = 0, // Internal Use - LFG_UPDATETYPE_LEADER = 1, + LFG_UPDATETYPE_LEADER_UNK1 = 1, // FIXME: At group leave LFG_UPDATETYPE_ROLECHECK_ABORTED = 4, LFG_UPDATETYPE_JOIN_PROPOSAL = 5, LFG_UPDATETYPE_ROLECHECK_FAILED = 6, @@ -51,7 +51,7 @@ enum LfgUpdateType LFG_UPDATETYPE_PROPOSAL_BEGIN = 13, LFG_UPDATETYPE_CLEAR_LOCK_LIST = 14, LFG_UPDATETYPE_GROUP_MEMBER_OFFLINE = 15, - LFG_UPDATETYPE_GROUP_DISBAND = 16 + LFG_UPDATETYPE_GROUP_DISBAND_UNK16 = 16, // FIXME: Sometimes at group disband }; enum LfgState @@ -69,7 +69,6 @@ enum LfgState /// 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, @@ -92,18 +91,12 @@ enum LfgAnswer LFG_ANSWER_AGREE = 1 }; -/// Dungeon and reason why player can't join -struct LfgLockStatus -{ - uint32 dungeon; ///< Dungeon Id - LfgLockStatusType lockstatus; ///< Lock type -}; - typedef std::set<uint32> LfgDungeonSet; typedef std::map<uint32, uint32> LfgLockMap; typedef std::map<uint64, LfgLockMap> LfgLockPartyMap; typedef std::set<uint64> LfgGuidSet; typedef std::list<uint64> LfgGuidList; typedef std::map<uint64, uint8> LfgRolesMap; +typedef std::map<uint64, uint64> LfgGroupsMap; #endif diff --git a/src/server/game/DungeonFinding/LFGGroupData.cpp b/src/server/game/DungeonFinding/LFGGroupData.cpp index cbcb1d130bb..712ae5132b0 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.cpp +++ b/src/server/game/DungeonFinding/LFGGroupData.cpp @@ -19,7 +19,7 @@ #include "LFGGroupData.h" LfgGroupData::LfgGroupData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), - m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS) + m_Leader(0), m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS) { } LfgGroupData::~LfgGroupData() @@ -34,9 +34,9 @@ void LfgGroupData::SetState(LfgState state) { switch (state) { + case LFG_STATE_FINISHED_DUNGEON: case LFG_STATE_NONE: case LFG_STATE_DUNGEON: - case LFG_STATE_FINISHED_DUNGEON: m_OldState = state; // No break on purpose default: @@ -49,6 +49,29 @@ void LfgGroupData::RestoreState() m_State = m_OldState; } +void LfgGroupData::AddPlayer(uint64 guid) +{ + m_Players.insert(guid); +} + +uint8 LfgGroupData::RemovePlayer(uint64 guid) +{ + LfgGuidSet::iterator it = m_Players.find(guid); + if (it != m_Players.end()) + m_Players.erase(it); + return uint8(m_Players.size()); +} + +void LfgGroupData::RemoveAllPlayers() +{ + m_Players.clear(); +} + +void LfgGroupData::SetLeader(uint64 guid) +{ + m_Leader = guid; +} + void LfgGroupData::SetDungeon(uint32 dungeon) { m_Dungeon = dungeon; @@ -65,6 +88,21 @@ LfgState LfgGroupData::GetState() const return m_State; } +LfgState LfgGroupData::GetOldState() const +{ + return m_OldState; +} + +const LfgGuidSet &LfgGroupData::GetPlayers() const +{ + return m_Players; +} + +uint64 LfgGroupData::GetLeader() const +{ + return m_Leader; +} + uint32 LfgGroupData::GetDungeon(bool asId /* = true */) const { if (asId) diff --git a/src/server/game/DungeonFinding/LFGGroupData.h b/src/server/game/DungeonFinding/LFGGroupData.h index 359f7be7eee..43cd64f97c3 100644 --- a/src/server/game/DungeonFinding/LFGGroupData.h +++ b/src/server/game/DungeonFinding/LFGGroupData.h @@ -35,18 +35,30 @@ class LfgGroupData ~LfgGroupData(); bool IsLfgGroup(); + // General void SetState(LfgState state); void RestoreState(); + void AddPlayer(uint64 guid); + uint8 RemovePlayer(uint64 guid); + void RemoveAllPlayers(); + void SetLeader(uint64 guid); + // Dungeon void SetDungeon(uint32 dungeon); + // VoteKick void DecreaseKicksLeft(); // General LfgState GetState() const; + LfgState GetOldState() const; + LfgGuidSet const& GetPlayers() const; + uint64 GetLeader() const; + // Dungeon uint32 GetDungeon(bool asId = true) const; + // VoteKick uint8 GetKicksLeft() const; @@ -54,6 +66,8 @@ class LfgGroupData // General LfgState m_State; ///< State if group in LFG LfgState m_OldState; ///< Old State + uint64 m_Leader; ///< Leader GUID + LfgGuidSet m_Players; ///< Players in group // Dungeon uint32 m_Dungeon; ///< Dungeon entry // Vote Kick diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 1b4a2fcdda3..af12ce93c65 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -34,8 +34,6 @@ LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1), m_options(sWorld->getBoolConfig(CONFIG_DUNGEON_FINDER_ENABLE)), - 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_lfgPlayerScript(new LFGPlayerScript()), m_lfgGroupScript(new LFGGroupScript()) { } @@ -121,64 +119,67 @@ std::string LFGMgr::GetRolesString(uint8 roles) std::string rolesstr = ""; if (roles & PLAYER_ROLE_TANK) - rolesstr.append("Tank"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_TANK)); if (roles & PLAYER_ROLE_HEALER) { if (!rolesstr.empty()) rolesstr.append(", "); - rolesstr.append("Healer"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_HEALER)); } if (roles & PLAYER_ROLE_DAMAGE) { if (!rolesstr.empty()) rolesstr.append(", "); - rolesstr.append("Dps"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_DAMAGE)); } if (roles & PLAYER_ROLE_LEADER) { if (!rolesstr.empty()) rolesstr.append(", "); - rolesstr.append("Leader"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_LEADER)); } if (rolesstr.empty()) - rolesstr.append("None"); + rolesstr.append(sObjectMgr->GetTrinityStringForDBCLocale(LANG_LFG_ROLE_NONE)); return rolesstr; } char const * LFGMgr::GetStateString(LfgState state) { + int32 entry = LANG_LFG_ERROR; switch (state) { case LFG_STATE_NONE: - return "None"; + entry = LANG_LFG_STATE_NONE; break; case LFG_STATE_ROLECHECK: - return "Rolecheck"; + entry = LANG_LFG_STATE_ROLECHECK; break; case LFG_STATE_QUEUED: - return "Queued"; + entry = LANG_LFG_STATE_QUEUED; break; case LFG_STATE_PROPOSAL: - return "Proposal"; + entry = LANG_LFG_STATE_PROPOSAL; break; case LFG_STATE_DUNGEON: - return "In Dungeon"; + entry = LANG_LFG_STATE_DUNGEON; break; case LFG_STATE_BOOT: - return "Boot Player"; + entry = LANG_LFG_STATE_BOOT; break; case LFG_STATE_FINISHED_DUNGEON: - return "Finished"; + entry = LANG_LFG_STATE_FINISHED_DUNGEON; break; case LFG_STATE_RAIDBROWSER: - return "RaidBrowser"; + entry = LANG_LFG_STATE_RAIDBROWSER; + break; } - return "Error"; + char const * const str = sObjectMgr->GetTrinityStringForDBCLocale(entry); + return str; } /// Load rewards for completing dungeons @@ -488,20 +489,22 @@ void LFGMgr::Update(uint32 diff) waitTime = -1; break; case PLAYER_ROLE_TANK: - waitTime = m_WaitTimeTank; + waitTime = m_waitTimesTank.time; break; case PLAYER_ROLE_HEALER: - waitTime = m_WaitTimeHealer; + waitTime = m_waitTimesHealer.time; break; case PLAYER_ROLE_DAMAGE: - waitTime = m_WaitTimeDps; + waitTime = m_waitTimesDps.time; break; default: - waitTime = m_WaitTimeAvg; + waitTime = m_waitTimesAvg.time; break; } - LfgQueueStatusData queueData(dungeonId, waitTime, m_WaitTimeAvg, m_WaitTimeTank, m_WaitTimeHealer, m_WaitTimeDps, queuedTime, queue->tanks, queue->healers, queue->dps); + LfgQueueStatusData queueData(dungeonId, waitTime, m_waitTimesAvg.time, m_waitTimesTank.time, + m_waitTimesHealer.time, m_waitTimesDps.time, queuedTime, + queue->tanks, queue->healers, queue->dps); for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) SendLfgQueueStatus(itPlayer->first, queueData); } @@ -648,7 +651,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const uint64 guid = player->GetGUID(); uint64 gguid = grp ? grp->GetGUID() : guid; LfgJoinResultData joinData; - PlayerSet players; + LfgGuidSet players; uint32 rDungeonId = 0; bool isContinue = grp && grp->isLFGGroup() && GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; @@ -707,15 +710,16 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue()) joinData.result = LFG_JOIN_USING_BG_SYSTEM; ++memberCount; - players.insert(plrg); + players.insert(plrg->GetGUID()); } } - if (memberCount != grp->GetMembersCount()) + + if (joinData.result == LFG_JOIN_OK && memberCount != grp->GetMembersCount()) joinData.result = LFG_JOIN_DISCONNECTED; } } else - players.insert(player); + players.insert(player->GetGUID()); // Check if all dungeons are valid bool isRaid = false; @@ -865,57 +869,52 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const 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] player Player trying to leave (can be NULL) - @param[in] grp Group trying to leave (default NULL) + @param[in] guid Player or group guid */ -void LFGMgr::LeaveLfg(Player* player, Group* grp /* = NULL*/) +void LFGMgr::LeaveLfg(uint64 guid) { - if (!player && !grp) - return; - - uint64 guid = grp ? grp->GetGUID() : player->GetGUID(); LfgState state = GetState(guid); + uint64 gguid = IS_GROUP(guid) ? guid : GetGroup(guid); sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::Leave: [" UI64FMTD "]", guid); switch (state) { case LFG_STATE_QUEUED: + if (gguid) { - RemoveFromQueue(guid); - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); - if (grp) + RemoveFromQueue(gguid); + RestoreState(gguid, "Leave queue"); + const LfgGuidSet& players = GetPlayers(gguid); + for (LfgGuidSet::const_iterator it = players.begin(); it != players.end(); ++it) { - RestoreState(guid, "Leave queue"); - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player* plrg = itr->getSource()) - { - plrg->GetSession()->SendLfgUpdateParty(updateData); - uint64 pguid = plrg->GetGUID(); - ClearState(pguid, "Leave queue"); - } - } - else - { - player->GetSession()->SendLfgUpdatePlayer(updateData); + uint64 guid = (*it); ClearState(guid, "Leave queue"); + SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE)); } } + else + { + RemoveFromQueue(guid); + SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE)); + ClearState(guid, "Leave queue"); + } break; case LFG_STATE_ROLECHECK: - if (grp) - UpdateRoleCheck(guid); // No player to update role = LFG_ROLECHECK_ABORTED + if (gguid) + UpdateRoleCheck(gguid); // No player to update role = LFG_ROLECHECK_ABORTED break; case LFG_STATE_PROPOSAL: { // Remove from Proposals LfgProposalMap::iterator it = m_Proposals.begin(); + uint64 pguid = gguid == guid ? GetLeader(gguid) : guid; while (it != m_Proposals.end()) { - LfgProposalPlayerMap::iterator itPlayer = it->second->players.find(player ? player->GetGUID() : grp->GetLeaderGUID()); + LfgProposalPlayerMap::iterator itPlayer = it->second->players.find(pguid); 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; + itPlayer->second.accept = LFG_ANSWER_DENY; break; } ++it; @@ -932,21 +931,6 @@ void LFGMgr::LeaveLfg(Player* player, Group* grp /* = NULL*/) } /** - 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 (grp) - { - uint64 gguid = grp->GetGUID(); - if (Player* leader = ObjectAccessor::FindPlayer(grp->GetLeaderGUID())) - leader->GetSession()->SendLfgOfferContinue(GetDungeon(gguid, false)); - } -} - -/** 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 @@ -1022,7 +1006,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) uint8 numPlayers = 0; uint8 numLfgGroups = 0; - uint32 groupLowGuid = 0; + uint64 groupGuid = 0; LfgQueueInfoMap pqInfoMap; for (LfgGuidList::const_iterator it = check.begin(); it != check.end() && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE; ++it) { @@ -1039,12 +1023,11 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) if (IS_GROUP(guid)) { - uint32 lowGuid = GUID_LOPART(guid); - if (Group* grp = sGroupMgr->GetGroupByGUID(lowGuid)) + if (Group* grp = sGroupMgr->GetGroupByGUID(GUID_LOPART(guid))) if (grp->isLFGGroup()) { if (!numLfgGroups) - groupLowGuid = lowGuid; + groupGuid = guid; ++numLfgGroups; } } @@ -1082,25 +1065,16 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) if (rolesMap.size() != numPlayers) // Player in multiples queues! return false; - PlayerSet players; + LfgGuidSet players; for (LfgRolesMap::const_iterator it = rolesMap.begin(); it != rolesMap.end(); ++it) { - Player* player = ObjectAccessor::FindPlayer(it->first); - if (!player) - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Warning! [" UI64FMTD "] offline! Marking as not compatibles!", strGuids.c_str(), it->first); - else - { - for (PlayerSet::const_iterator itPlayer = players.begin(); itPlayer != players.end() && player; ++itPlayer) - { - if (HasIgnore((*itPlayer)->GetGUID(), player->GetGUID())) - { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) Players [" UI64FMTD "] and [" UI64FMTD "] ignoring", strGuids.c_str(), (*itPlayer)->GetGUID(), player->GetGUID()); - player = NULL; - } - } - if (player) - players.insert(player); - } + uint64 guid = it->first; + LfgRolesMap::const_iterator it2 = ++it; + for (; it2 != rolesMap.end(); ++it2) + if (HasIgnore(guid, it2->first)) + break; + if (it2 == rolesMap.end()) + players.insert(guid); } // if we dont have the same ammount of players then we have self ignoring candidates or different faction groups @@ -1159,17 +1133,15 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) --Dps_Needed; } } - for (PlayerSet::const_iterator itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) + + for (LfgGuidSet::const_iterator itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) { for (LfgQueueInfoMap::const_iterator itQueue = pqInfoMap.begin(); itQueue != pqInfoMap.end(); ++itQueue) { - LfgQueueInfo* queue = itQueue->second; - if (!queue) - continue; - - for (LfgRolesMap::const_iterator itPlayer = queue->roles.begin(); itPlayer != queue->roles.end(); ++itPlayer) + if (LfgQueueInfo* queue = itQueue->second) { - if (*itPlayers == ObjectAccessor::FindPlayer(itPlayer->first)) + LfgRolesMap::const_iterator itPlayer = queue->roles.find(*itPlayers); + if (itPlayer != queue->roles.end()) { queue->tanks = Tanks_Needed; queue->healers = Healers_Needed; @@ -1178,6 +1150,7 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) } } } + return true; } sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::CheckCompatibility: (%s) MATCH! Group formed", strGuids.c_str()); @@ -1193,36 +1166,37 @@ bool LFGMgr::CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal) pProposal->cancelTime = time_t(time(NULL)) + LFG_TIME_PROPOSAL; pProposal->state = LFG_PROPOSAL_INITIATING; pProposal->queues = check; - pProposal->groupLowGuid = groupLowGuid; + pProposal->group = groupGuid; + pProposal->isNew = true; // Assign new roles to players and assign new leader - PlayerSet::const_iterator itPlayers = players.begin(); + LfgGuidSet::const_iterator itPlayers = players.begin(); if (!leader) { uint8 pos = uint8(urand(0, players.size() - 1)); for (uint8 i = 0; i < pos; ++i) ++itPlayers; - leader = (*itPlayers)->GetGUID(); + leader = *itPlayers; } pProposal->leader = leader; uint8 numAccept = 0; for (itPlayers = players.begin(); itPlayers != players.end(); ++itPlayers) { - uint64 guid = (*itPlayers)->GetGUID(); - LfgProposalPlayer* ppPlayer = new LfgProposalPlayer(); - if (Group* grp = (*itPlayers)->GetGroup()) + uint64 guid = *itPlayers; + LfgProposalPlayer& player = pProposal->players[guid]; + uint64 gguid = GetGroup(guid); + player.group = gguid; + if (gguid == groupGuid) { - ppPlayer->groupLowGuid = grp->GetLowGUID(); - if (grp->isLFGGroup()) // Player from existing group, autoaccept - { - ppPlayer->accept = LFG_ANSWER_AGREE; - ++numAccept; - } + player.accept = LFG_ANSWER_AGREE; + ++numAccept; } - ppPlayer->role = rolesMap[guid]; - pProposal->players[guid] = ppPlayer; + player.role = rolesMap[guid]; + if (pProposal->group && pProposal->group != gguid) + pProposal->isNew = false; } + if (numAccept == MAXGROUPSIZE) pProposal->state = LFG_PROPOSAL_SUCCESS; @@ -1270,7 +1244,6 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* } } - uint8 team = 0; LfgDungeonSet dungeons; if (roleCheck.rDungeonId) dungeons.insert(roleCheck.rDungeonId); @@ -1291,7 +1264,6 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* continue; } - team = uint8(plrg->GetTeam()); if (!sendRoleChosen) SendLfgRoleChosen(pguid, guid, roles); @@ -1333,6 +1305,7 @@ void LFGMgr::UpdateRoleCheck(uint64 gguid, uint64 guid /* = 0 */, uint8 roles /* --pqInfo->dps; } + uint8 team = GetTeam(guid); m_QueueInfoMap[gguid] = pqInfo; if (GetState(gguid) != LFG_STATE_NONE) { @@ -1402,12 +1375,12 @@ LfgAnswer LFGMgr::GetCompatibles(std::string key) @param[in] players Set of players to check their dungeon restrictions @param[out] lockMap Map of players Lock status info of given dungeons (Empty if dungeons is not empty) */ -void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, const PlayerSet& players, LfgLockPartyMap& lockMap) +void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, const LfgGuidSet& players, LfgLockPartyMap& lockMap) { lockMap.clear(); - for (PlayerSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) + for (LfgGuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) { - uint64 guid = (*it)->GetGUID(); + uint64 guid = (*it); LfgLockMap const& cachedLockMap = GetLockedDungeons(guid); for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2) { @@ -1498,6 +1471,79 @@ bool LFGMgr::CheckGroupRoles(LfgRolesMap& groles, bool removeLeaderFlag /*= true } /** + Makes a new group given a proposal + @param[in] proposal Proposal to get info from +*/ +void LFGMgr::MakeNewGroup(const LfgProposal& proposal) +{ + LfgGuidList players; + LfgGuidList playersToTeleport; + + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + { + uint64 guid = it->first; + if (guid == proposal.leader) + players.push_front(guid); + else + players.push_back(guid); + + if (GetGroup(guid) != proposal.group || GetState(proposal.group) == LFG_STATE_FINISHED_DUNGEON) + playersToTeleport.push_back(guid); + } + + // Set the dungeon difficulty + LFGDungeonEntry const* dungeon = GetLFGDungeon(proposal.dungeonId); + ASSERT(dungeon); + + Group* grp = proposal.group ? sGroupMgr->GetGroupByGUID(GUID_LOPART(proposal.group)) : NULL; + for (LfgGuidList::const_iterator it = players.begin(); it != players.end(); ++it) + { + uint64 pguid = (*it); + Player* player = ObjectAccessor::FindPlayer(pguid); + if (!player) + continue; + + Group* group = player->GetGroup(); + if (group && group != grp) + player->RemoveFromGroup(); + + if (!grp) + { + grp = new Group(); + grp->ConvertToLFG(); + grp->Create(player); + uint64 gguid = grp->GetGUID(); + SetState(gguid, LFG_STATE_PROPOSAL); + sGroupMgr->AddGroup(grp); + } + else if (group != grp) + grp->AddMember(player); + + grp->SetLfgRoles(pguid, proposal.players.find(pguid)->second.role); + SetState(pguid, LFG_STATE_DUNGEON); + + // Add the cooldown spell if queued for a random dungeon + if (dungeon->type == LFG_TYPE_RANDOM) + player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false); + } + + grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); + uint64 gguid = grp->GetGUID(); + SetDungeon(gguid, dungeon->Entry()); + SetState(gguid, LFG_STATE_DUNGEON); + + _SaveToDB(gguid, grp->GetDbStoreId()); + + // Teleport Player + for (LfgGuidList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it) + if (Player* player = ObjectAccessor::FindPlayer(*it)) + TeleportPlayer(player, false); + + // Update group info + grp->SendUpdate(); +} + +/** Update Proposal info with player answer @param[in] proposalId Proposal id to be updated @@ -1510,15 +1556,17 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) LfgProposalMap::iterator itProposal = m_Proposals.find(proposalId); if (itProposal == m_Proposals.end()) return; - LfgProposal* pProposal = itProposal->second; + + LfgProposal& proposal = *(itProposal->second); // Check if proposal have the current player - LfgProposalPlayerMap::iterator itProposalPlayer = pProposal->players.find(guid); - if (itProposalPlayer == pProposal->players.end()) + LfgProposalPlayerMap::iterator itProposalPlayer = proposal.players.find(guid); + if (itProposalPlayer == proposal.players.end()) return; - LfgProposalPlayer* ppPlayer = itProposalPlayer->second; - ppPlayer->accept = LfgAnswer(accept); + LfgProposalPlayer& player = itProposalPlayer->second; + player.accept = LfgAnswer(accept); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::UpdateProposal: Player [" UI64FMTD "] of proposal %u selected: %u", guid, proposalId, accept); if (!accept) { @@ -1526,157 +1574,77 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) return; } - LfgPlayerList players; - LfgPlayerList playersToTeleport; - // 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) - { - if (Player* player = ObjectAccessor::FindPlayer(itPlayers->first)) - { - if (itPlayers->first == pProposal->leader) - players.push_front(player); - else - players.push_back(player); - - // Only teleport new players - Group* grp = player->GetGroup(); - uint64 gguid = grp ? grp->GetGUID() : 0; - if (!gguid || !grp->isLFGGroup() || GetState(gguid) == LFG_STATE_FINISHED_DUNGEON) - playersToTeleport.push_back(player); - } - - if (itPlayers->second->accept != LFG_ANSWER_AGREE) // No answer (-1) or not accepted (0) + for (LfgProposalPlayerMap::const_iterator itPlayers = proposal.players.begin(); itPlayers != proposal.players.end(); ++itPlayers) + if (itPlayers->second.accept != LFG_ANSWER_AGREE) // No answer (-1) or not accepted (0) allAnswered = false; - } if (!allAnswered) { - for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) - (*it)->GetSession()->SendLfgUpdateProposal(proposalId, *pProposal); - } - else - { - bool sendUpdate = pProposal->state != LFG_PROPOSAL_SUCCESS; - pProposal->state = LFG_PROPOSAL_SUCCESS; - time_t joinTime = time_t(time(NULL)); - std::map<uint64, int32> waitTimesMap; - // Save wait times before redoing groups - for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - LfgProposalPlayer* player = pProposal->players[(*it)->GetGUID()]; - uint32 lowgroupguid = (*it)->GetGroup() ? (*it)->GetGroup()->GetLowGUID() : 0; - if (player->groupLowGuid != lowgroupguid) - sLog->outError(LOG_FILTER_LFG, "LFGMgr::UpdateProposal: [" UI64FMTD "] group mismatch: actual (%u) - queued (%u)", (*it)->GetGUID(), lowgroupguid, player->groupLowGuid); - - uint64 guid2 = player->groupLowGuid ? MAKE_NEW_GUID(player->groupLowGuid, 0, HIGHGUID_GROUP) : (*it)->GetGUID(); - LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid2); - if (itQueue == m_QueueInfoMap.end()) - { - sLog->outError(LOG_FILTER_LFG, "LFGMgr::UpdateProposal: Queue info for guid [" UI64FMTD "] not found!", guid); - waitTimesMap[(*it)->GetGUID()] = -1; - } - else - waitTimesMap[(*it)->GetGUID()] = int32(joinTime - itQueue->second->joinTime); + uint64 guid = it->first; + SendLfgUpdateProposal(guid, proposalId, proposal); } + return; + } - // Set the dungeon difficulty - LFGDungeonEntry const* dungeon = GetLFGDungeon(pProposal->dungeonId); - ASSERT(dungeon); - - // Create a new group (if needed) - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); - Group* grp = pProposal->groupLowGuid ? sGroupMgr->GetGroupByGUID(pProposal->groupLowGuid) : NULL; - for (LfgPlayerList::const_iterator it = players.begin(); it != players.end(); ++it) - { - Player* player = (*it); - uint64 pguid = player->GetGUID(); - Group* group = player->GetGroup(); - if (sendUpdate) - player->GetSession()->SendLfgUpdateProposal(proposalId, *pProposal); - - if (group) - { - player->GetSession()->SendLfgUpdateParty(updateData); - if (group != grp) - player->RemoveFromGroup(); - } - else - player->GetSession()->SendLfgUpdatePlayer(updateData); - - if (!grp) - { - grp = new Group(); - grp->Create(player); - grp->ConvertToLFG(); - uint64 gguid = grp->GetGUID(); - SetState(gguid, LFG_STATE_PROPOSAL); - sGroupMgr->AddGroup(grp); - } - else if (group != grp) - grp->AddMember(player); - - // Update timers - uint8 role = GetRoles(pguid); - role &= ~PLAYER_ROLE_LEADER; - switch (role) - { - case PLAYER_ROLE_DAMAGE: - { - uint32 old_number = m_NumWaitTimeDps++; - m_WaitTimeDps = int32((m_WaitTimeDps * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeDps); - break; - } - case PLAYER_ROLE_HEALER: - { - uint32 old_number = m_NumWaitTimeHealer++; - m_WaitTimeHealer = int32((m_WaitTimeHealer * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeHealer); - break; - } - case PLAYER_ROLE_TANK: - { - uint32 old_number = m_NumWaitTimeTank++; - m_WaitTimeTank = int32((m_WaitTimeTank * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeTank); - break; - } - default: - { - uint32 old_number = m_NumWaitTimeAvg++; - m_WaitTimeAvg = int32((m_WaitTimeAvg * old_number + waitTimesMap[player->GetGUID()]) / m_NumWaitTimeAvg); - break; - } - } + bool sendUpdate = proposal.state != LFG_PROPOSAL_SUCCESS; + proposal.state = LFG_PROPOSAL_SUCCESS; + time_t joinTime = time_t(time(NULL)); - m_teleport.push_back(pguid); - grp->SetLfgRoles(pguid, pProposal->players[pguid]->role); - SetState(pguid, LFG_STATE_DUNGEON); + LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + { + uint64 pguid = it->first; + uint64 gguid = it->second.group; + int32 waitTime = -1; + if (sendUpdate) + SendLfgUpdateProposal(pguid, proposalId, proposal); - // Add the cooldown spell if queued for a random dungeon - if (dungeon->type == LFG_TYPE_RANDOM) - player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false); + if (gguid) + { + SendLfgUpdateParty(pguid, updateData); } + else + SendLfgUpdatePlayer(pguid, updateData); - grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); - uint64 gguid = grp->GetGUID(); - SetDungeon(gguid, dungeon->Entry()); - SetState(gguid, LFG_STATE_DUNGEON); - _SaveToDB(gguid, grp->GetDbStoreId()); + uint64 guid2 = gguid ? gguid : pguid; + LfgQueueInfoMap::iterator itQueue = m_QueueInfoMap.find(guid2); + if (itQueue != m_QueueInfoMap.end()) + waitTime = int32(joinTime - itQueue->second->joinTime); - // Remove players/groups from Queue - for (LfgGuidList::const_iterator it = pProposal->queues.begin(); it != pProposal->queues.end(); ++it) - RemoveFromQueue(*it); + // Update timers + uint8 role = GetRoles(pguid); + role &= ~PLAYER_ROLE_LEADER; + switch (role) + { + case PLAYER_ROLE_DAMAGE: + UpdateWaitTimeDps(waitTime); + break; + case PLAYER_ROLE_HEALER: + UpdateWaitTimeHealer(waitTime); + break; + case PLAYER_ROLE_TANK: + UpdateWaitTimeTank(waitTime); + break; + default: + UpdateWaitTimeAvg(waitTime); + break; + } - // Teleport Player - for (LfgPlayerList::const_iterator it = playersToTeleport.begin(); it != playersToTeleport.end(); ++it) - TeleportPlayer(*it, false); + m_teleport.push_back(pguid); + SetState(pguid, LFG_STATE_DUNGEON); + } - // Update group info - grp->SendUpdate(); + // Remove players/groups from Queue + for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) + RemoveFromQueue(*it); - delete pProposal; - m_Proposals.erase(itProposal); - } + MakeNewGroup(proposal); + delete itProposal->second; + m_Proposals.erase(itProposal); } /** @@ -1693,45 +1661,38 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: Proposal %u, state FAILED, UpdateType %u", itProposal->first, type); // Mark all people that didn't answered as no accept if (type == LFG_UPDATETYPE_PROPOSAL_FAILED) - for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) - if (it->second->accept == LFG_ANSWER_PENDING) - it->second->accept = LFG_ANSWER_DENY; + for (LfgProposalPlayerMap::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + if (it->second.accept == LFG_ANSWER_PENDING) + it->second.accept = LFG_ANSWER_DENY; // Mark players/groups to be removed LfgGuidSet toRemove; - for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) + for (LfgProposalPlayerMap::iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - if (it->second->accept == LFG_ANSWER_AGREE) + if (it->second.accept == LFG_ANSWER_AGREE) continue; - uint64 guid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : it->first; + uint64 guid = it->second.group ? it->second.group : it->first; // Player didn't accept or still pending when no secs left - if (it->second->accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED) + if (it->second.accept == LFG_ANSWER_DENY || type == LFG_UPDATETYPE_PROPOSAL_FAILED) { - it->second->accept = LFG_ANSWER_DENY; + it->second.accept = LFG_ANSWER_DENY; toRemove.insert(guid); } } - uint8 team = 0; // Notify players for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - Player* player = ObjectAccessor::FindPlayer(it->first); - if (!player) - continue; - - team = uint8(player->GetTeam()); - player->GetSession()->SendLfgUpdateProposal(itProposal->first, proposal); + uint64 guid = it->first; + uint64 gguid = it->second.group ? it->second.group : guid; - Group* grp = player->GetGroup(); - uint64 guid = player->GetGUID(); - uint64 gguid = it->second->groupLowGuid ? MAKE_NEW_GUID(it->second->groupLowGuid, 0, HIGHGUID_GROUP) : guid; + SendLfgUpdateProposal(guid, itProposal->first, proposal); if (toRemove.find(gguid) != toRemove.end()) // Didn't accept or in same group that someone that didn't accept { LfgUpdateData updateData; - if (it->second->accept == LFG_ANSWER_DENY) + if (it->second.accept == LFG_ANSWER_DENY) { updateData.updateType = type; sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: [" UI64FMTD "] didn't accept. Removing from queue and compatible cache", guid); @@ -1742,25 +1703,25 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: [" UI64FMTD "] in same group that someone that didn't accept. Removing from queue and compatible cache", guid); } ClearState(guid, "Proposal Fail (didn't accepted or in group with someone that didn't accept"); - if (grp) + if (gguid != guid) { RestoreState(gguid, "Proposal Fail (someone in group didn't accepted)"); - player->GetSession()->SendLfgUpdateParty(updateData); + SendLfgUpdateParty(guid, updateData); } else - player->GetSession()->SendLfgUpdatePlayer(updateData); + SendLfgUpdatePlayer(guid, updateData); } else { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RemoveProposal: Readding [" UI64FMTD "] to queue.", guid); SetState(guid, LFG_STATE_QUEUED); - if (grp) + if (gguid != guid) { SetState(gguid, LFG_STATE_QUEUED); - player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); + SendLfgUpdateParty(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); } else - player->GetSession()->SendLfgUpdatePlayer(LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); + SendLfgUpdatePlayer(guid, LfgUpdateData(LFG_UPDATETYPE_ADDED_TO_QUEUE, GetSelectedDungeons(guid), GetComment(guid))); } } @@ -1776,29 +1737,26 @@ void LFGMgr::RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType t for (LfgGuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) { uint64 guid = *it; + uint8 team = GetTeam(guid); LfgGuidList& currentQueue = m_currentQueue[team]; currentQueue.push_front(guid); //Add GUID for high priority AddToQueue(guid, team); //We have to add each GUID in newQueue to check for a new groups } - delete &proposal; + delete itProposal->second; m_Proposals.erase(itProposal); } /** Initialize a boot kick vote - @param[in] grp Group the vote kicks belongs to + @param[in] gguid Group the vote kicks belongs to @param[in] kicker Kicker guid @param[in] victim Victim guid @param[in] reason Kick reason */ -void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string const& reason) +void LFGMgr::InitBoot(uint64 gguid, uint64 kicker, uint64 victim, std::string const& reason) { - if (!grp) - return; - - uint32 gguid = grp->GetLowGUID(); SetState(gguid, LFG_STATE_BOOT); LfgPlayerBoot& boot = m_Boots[gguid]; @@ -1807,10 +1765,7 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string cons boot.reason = reason; boot.victim = victim; - LfgGuidSet players; - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - if (Player* player = itr->getSource()) - players.insert(player->GetGUID()); + LfgGuidSet const& players = GetPlayers(gguid); // Set votes for (LfgGuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) @@ -1831,18 +1786,15 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string cons /** Update Boot info with player answer - @param[in] player Player who has answered + @param[in] guid Player who has answered @param[in] accept player answer */ -void LFGMgr::UpdateBoot(Player* player, bool accept) +void LFGMgr::UpdateBoot(uint64 guid, bool accept) { - Group* grp = player ? player->GetGroup() : NULL; - if (!grp) + uint64 gguid = GetGroup(guid); + if (!gguid) return; - uint32 gguid = grp->GetLowGUID(); - uint64 guid = player->GetGUID(); - LfgPlayerBootMap::iterator itBoot = m_Boots.find(gguid); if (itBoot == m_Boots.end()) return; @@ -1882,17 +1834,20 @@ void LFGMgr::UpdateBoot(Player* player, bool accept) } } - gguid = grp->GetGUID(); SetState(gguid, LFG_STATE_DUNGEON); if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player { - Player::RemoveFromGroup(grp, boot.victim); + if (Group* group = sGroupMgr->GetGroupByGUID(GUID_LOPART(gguid))) + Player::RemoveFromGroup(group, boot.victim); + if (Player* victim = ObjectAccessor::FindPlayer(boot.victim)) { TeleportPlayer(victim, true, false); SetState(boot.victim, LFG_STATE_NONE); } - OfferContinue(grp); + + if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid))) + leader->GetSession()->SendLfgOfferContinue(GetDungeon(gguid, false)); DecreaseKicksLeft(gguid); } m_Boots.erase(itBoot); @@ -2120,49 +2075,35 @@ LfgType LFGMgr::GetDungeonType(uint32 dungeonId) return LfgType(dungeon->type); } -/** - 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()) - return ""; - - std::ostringstream o; - LfgGuidList::const_iterator it = check.begin(); - o << (*it); - for (++it; it != check.end(); ++it) - o << '|' << (*it); - return o.str(); -} - LfgState LFGMgr::GetState(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetState: [" UI64FMTD "]", guid); + LfgState state; if (IS_GROUP(guid)) - return m_Groups[guid].GetState(); + state = m_Groups[guid].GetState(); else - return m_Players[guid].GetState(); + state = m_Players[guid].GetState(); + + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetState: [" UI64FMTD "] = %u", guid, state); + return state; } -uint32 LFGMgr::GetDungeon(uint64 guid, bool asId /*= true*/) +uint32 LFGMgr::GetDungeon(uint64 guid, bool asId /*= true */) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetDungeon: [" UI64FMTD "] asId: %u", guid, asId); - return m_Groups[guid].GetDungeon(asId); + uint32 dungeon = m_Groups[guid].GetDungeon(asId); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetDungeon: [" UI64FMTD "] asId: %u = %u", guid, asId, dungeon); + return dungeon; } uint8 LFGMgr::GetRoles(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetRoles: [" UI64FMTD "]", guid); - return m_Players[guid].GetRoles(); + uint8 roles = m_Players[guid].GetRoles(); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetRoles: [" UI64FMTD "] = %u", guid, roles); + return roles; } const std::string& LFGMgr::GetComment(uint64 guid) { - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetComment: [" UI64FMTD "]", guid); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::GetComment: [" UI64FMTD "] = %s", guid, m_Players[guid].GetComment().c_str()); return m_Players[guid].GetComment(); } @@ -2199,7 +2140,8 @@ void LFGMgr::RestoreState(uint64 guid, char const *debugMsg) { LfgGroupData& data = m_Groups[guid]; char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RestoreState: Group: [" UI64FMTD "] (%s), State: %s", guid, debugMsg, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::RestoreState: Group: [" UI64FMTD "] (%s), State: %s, oldState: %s", guid, debugMsg, ps, os); data.RestoreState(); } @@ -2207,7 +2149,8 @@ void LFGMgr::ClearState(uint64 guid, char const *debugMsg) { LfgPlayerData& data = m_Players[guid]; char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::ClearState: Player: [" UI64FMTD "] (%s) State: %s", guid, debugMsg, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::ClearState: Player: [" UI64FMTD "] (%s) State: %s, oldState: %s", guid, debugMsg, ps, os); data.ClearState(); } @@ -2218,7 +2161,8 @@ void LFGMgr::SetState(uint64 guid, LfgState state) LfgGroupData& data = m_Groups[guid]; char const * const ns = GetStateString(state); char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Group: [" UI64FMTD "] newState: %s, previous: %s", guid, ns, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Group: [" UI64FMTD "] newState: %s, previous: %s, oldState: %s", guid, ns, ps, os); data.SetState(state); } else @@ -2226,7 +2170,8 @@ void LFGMgr::SetState(uint64 guid, LfgState state) LfgPlayerData& data = m_Players[guid]; char const * const ns = GetStateString(state); char const * const ps = GetStateString(data.GetState()); - sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Player: [" UI64FMTD "] newState: %s, previous: %s", guid, ns, ps); + char const * const os = GetStateString(data.GetOldState()); + sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::SetState: Player: [" UI64FMTD "] newState: %s, previous: %s, oldState: %s", guid, ns, ps, os); data.SetState(state); } } @@ -2283,6 +2228,54 @@ void LFGMgr::RemoveGroupData(uint64 guid) m_Groups.erase(it); } +uint8 LFGMgr::GetTeam(uint64 guid) +{ + return m_Players[guid].GetTeam(); +} + +uint8 LFGMgr::RemovePlayerFromGroup(uint64 gguid, uint64 guid) +{ + return m_Groups[gguid].RemovePlayer(guid); +} + +void LFGMgr::AddPlayerToGroup(uint64 gguid, uint64 guid) +{ + m_Groups[gguid].AddPlayer(guid); +} + +void LFGMgr::SetLeader(uint64 gguid, uint64 leader) +{ + m_Groups[gguid].SetLeader(leader); +} + +void LFGMgr::SetTeam(uint64 guid, uint8 team) +{ + if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP)) + team = 0; + + m_Players[guid].SetTeam(team); +} + +uint64 LFGMgr::GetGroup(uint64 guid) +{ + return m_Players[guid].GetGroup(); +} + +void LFGMgr::SetGroup(uint64 guid, uint64 group) +{ + m_Players[guid].SetGroup(group); +} + +const LfgGuidSet& LFGMgr::GetPlayers(uint64 guid) +{ + return m_Groups[guid].GetPlayers(); +} + +uint64 LFGMgr::GetLeader(uint64 guid) +{ + return m_Groups[guid].GetLeader(); +} + bool LFGMgr::HasIgnore(uint64 guid1, uint64 guid2) { Player* plr1 = ObjectAccessor::FindPlayer(guid1); @@ -2360,3 +2353,50 @@ bool LFGMgr::IsSeasonActive(uint32 dungeonId) } return false; } + +void LFGMgr::UpdateWaitTimeAvg(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesAvg; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LFGMgr::UpdateWaitTimeTank(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesTank; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LFGMgr::UpdateWaitTimeHealer(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesHealer; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +void LFGMgr::UpdateWaitTimeDps(int32 waitTime) +{ + LfgWaitTime &wt = m_waitTimesDps; + uint32 old_number = wt.number++; + wt.time = int32((wt.time * old_number + waitTime) / wt.number); +} + +/** + 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()) + return ""; + + std::ostringstream o; + LfgGuidList::const_iterator it = check.begin(); + o << (*it); + for (++it; it != check.end(); ++it) + o << '|' << (*it); + return o.str(); +}
\ No newline at end of file diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index d4d35974604..756f7094be6 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -21,6 +21,7 @@ #include "Common.h" #include <ace/Singleton.h> #include "LFG.h" + #include "LFGGroupData.h" #include "LFGPlayerData.h" @@ -127,20 +128,28 @@ struct LfgPlayerBoot; typedef std::map<uint8, LfgGuidList> LfgGuidListMap; typedef std::set<Player*> PlayerSet; typedef std::list<Player*> LfgPlayerList; +typedef std::map<std::string, LfgAnswer> LfgCompatibleMap; +typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap; + 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<uint8, LfgDungeonSet> LfgCachedDungeonMap; typedef std::map<uint64, LfgAnswer> LfgAnswerMap; typedef std::map<uint64, LfgRoleCheck> LfgRoleCheckMap; -typedef std::map<uint64, LfgQueueInfo*> LfgQueueInfoMap; typedef std::map<uint32, LfgProposal*> LfgProposalMap; -typedef std::map<uint64, LfgProposalPlayer*> LfgProposalPlayerMap; +typedef std::map<uint64, LfgProposalPlayer> LfgProposalPlayerMap; typedef std::map<uint64, LfgPlayerBoot> LfgPlayerBootMap; typedef std::map<uint64, LfgGroupData> LfgGroupDataMap; typedef std::map<uint64, LfgPlayerData> LfgPlayerDataMap; typedef UNORDERED_MAP<uint32, LFGDungeonEntry> LFGDungeonMap; +struct LfgWaitTime +{ + LfgWaitTime(): time(-1), number(0) {} + int32 time; ///< Wait time + uint32 number; ///< Number of people used to get that wait time +}; + // Data needed by SMSG_LFG_JOIN_RESULT struct LfgJoinResultData { @@ -221,27 +230,26 @@ struct LfgQueueInfo /// Stores player data related to proposal to join struct LfgProposalPlayer { - LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), groupLowGuid(0) {}; + LfgProposalPlayer(): role(0), accept(LFG_ANSWER_PENDING), group(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 + uint64 group; ///< Original group guid. 0 if no original group }; /// Stores group data related to proposal to join struct LfgProposal { - LfgProposal(uint32 dungeon = 0): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING), groupLowGuid(0), leader(0), cancelTime(0) {} + LfgProposal(uint32 dungeon = 0): dungeonId(dungeon), state(LFG_PROPOSAL_INITIATING), + group(0), leader(0), cancelTime(0), encounters(0), isNew(true) + { } - ~LfgProposal() - { - for (LfgProposalPlayerMap::iterator it = players.begin(); it != players.end(); ++it) - delete it->second; - }; uint32 dungeonId; ///< Dungeon to join LfgProposalState state; ///< State of the proposal - uint32 groupLowGuid; ///< Proposal group (0 if new) + uint64 group; ///< Proposal group (0 if new) uint64 leader; ///< Leader guid. time_t cancelTime; ///< Time when we will cancel this proposal + uint32 encounters; ///< Dungeon Encounters + bool isNew; ///< Determines if it's new group or not LfgGuidList queues; ///< Queue Ids to remove/readd LfgProposalPlayerMap players; ///< Players data }; @@ -264,7 +272,6 @@ struct LfgPlayerBoot bool inProgress; ///< Vote in progress LfgAnswerMap votes; ///< Player votes (-1 not answer | 0 Not agree | 1 agree) uint64 victim; ///< Player guid to be kicked (can't vote) - uint8 votedNeeded; ///< Votes needed to kick the player std::string reason; ///< kick reason }; @@ -313,26 +320,33 @@ class LFGMgr // Queue void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment); - void LeaveLfg(Player* player, Group* grp = NULL); + void LeaveLfg(uint64 guid); // Role Check void UpdateRoleCheck(uint64 gguid, uint64 guid = 0, uint8 roles = PLAYER_ROLE_NONE); + // Group Matching + static bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, LfgGuidSet const& players, LfgLockPartyMap& lockMap); + // Proposals + uint32 AddProposal(LfgProposal const& proposal); void UpdateProposal(uint32 proposalId, uint64 guid, bool accept); // Teleportation void TeleportPlayer(Player* player, bool out, bool fromOpcode = false); // Vote kick - void InitBoot(Group* grp, uint64 kguid, uint64 vguid, std::string const& reason); - void UpdateBoot(Player* player, bool accept); - void OfferContinue(Group* grp); + void InitBoot(uint64 gguid, uint64 kguid, uint64 vguid, std::string const& reason); + void UpdateBoot(uint64 guid, bool accept); void InitializeLockedDungeons(Player* player, uint8 level = 0); void SetRoles(uint64 guid, uint8 roles); void SetComment(uint64 guid, std::string const& comment); + void SetTeam(uint64 guid, uint8 team); + void SetGroup(uint64 guid, uint64 group); + void SetLeader(uint64 gguid, uint64 leader); void SetState(uint64 guid, LfgState state); void SetSelectedDungeons(uint64 guid, LfgDungeonSet const& dungeons); @@ -341,15 +355,20 @@ class LFGMgr void RemovePlayerData(uint64 guid); void RemoveGroupData(uint64 guid); + uint8 RemovePlayerFromGroup(uint64 gguid, uint64 guid); + void AddPlayerToGroup(uint64 gguid, uint64 guid); LfgLockMap const& GetLockedDungeons(uint64 guid); LfgDungeonSet const& GetSelectedDungeons(uint64 guid); uint32 GetDungeon(uint64 guid, bool asId = true); LfgState GetState(uint64 guid); uint8 GetKicksLeft(uint64 gguid); + uint64 GetLeader(uint64 guid); bool IsLfgGroup(uint64 guid); uint8 GetRoles(uint64 guid); std::string const& GetComment(uint64 gguid); + LfgGuidSet const& GetPlayers(uint64 guid); + bool IsTeleported(uint64 guid); static bool HasIgnore(uint64 guid1, uint64 guid2); @@ -368,6 +387,8 @@ class LFGMgr void ClearState(uint64 guid, char const *debugMsg); private: + uint8 GetTeam(uint64 guid); + uint64 GetGroup(uint64 guid); void RestoreState(uint64 guid, char const *debugMsg); void SetDungeon(uint64 guid, uint32 dungeon); @@ -380,21 +401,23 @@ class LFGMgr // Proposals void RemoveProposal(LfgProposalMap::iterator itProposal, LfgUpdateType type); + void MakeNewGroup(LfgProposal const& proposal); // Group Matching LfgProposal* FindNewGroups(LfgGuidList& check, LfgGuidList& all); - bool CheckGroupRoles(LfgRolesMap &groles, bool removeLeaderFlag = true); bool CheckCompatibility(LfgGuidList check, LfgProposal*& pProposal); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, PlayerSet const& players, LfgLockPartyMap& lockMap); void SetCompatibles(std::string concatenatedGuids, bool compatibles); LfgAnswer GetCompatibles(std::string concatenatedGuids); - void RemoveFromCompatibles(uint64 guid); // Generic LfgDungeonSet const& GetDungeonsByRandom(uint32 randomdungeon); LfgType GetDungeonType(uint32 dungeon); std::string ConcatenateGuids(LfgGuidList check); - + void RemoveFromCompatibles(uint64 guid); + void UpdateWaitTimeAvg(int32 waitTime); + void UpdateWaitTimeTank(int32 waitTime); + void UpdateWaitTimeHealer(int32 waitTime); + void UpdateWaitTimeDps(int32 waitTime); void SendLfgBootProposalUpdate(uint64 guid, LfgPlayerBoot const& boot); void SendLfgJoinResult(uint64 guid, LfgJoinResultData const& data); void SendLfgRoleChosen(uint64 guid, uint64 pguid, uint8 roles); @@ -408,30 +431,27 @@ class LFGMgr uint32 m_lfgProposalId; ///< used as internal counter for proposals uint32 m_options; ///< Stores config options - 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 LfgCachedDungeonMap m_CachedDungeonMap; ///< Stores all dungeons by groupType // Reward System LfgRewardMap m_RewardMap; ///< Stores rewards for random dungeons LFGDungeonMap m_LfgDungeonMap; - // Queue - LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups - LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups - LfgGuidListMap m_newToQueue; ///< New groups to add to queue - LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons - LfgGuidList m_teleport; ///< Players being teleported // Rolecheck - Proposal - Vote Kicks LfgRoleCheckMap m_RoleChecks; ///< Current Role checks LfgProposalMap m_Proposals; ///< Current Proposals LfgPlayerBootMap m_Boots; ///< Current player kicks LfgPlayerDataMap m_Players; ///< Player data LfgGroupDataMap m_Groups; ///< Group data + LfgGuidList m_teleport; ///< Players being teleported + + // Queue + LfgQueueInfoMap m_QueueInfoMap; ///< Queued groups + LfgGuidListMap m_currentQueue; ///< Ordered list. Used to find groups + LfgGuidListMap m_newToQueue; ///< New groups to add to queue + LfgCompatibleMap m_CompatibleMap; ///< Compatible dungeons + LfgWaitTime m_waitTimesAvg; ///< Average wait time to find a group queuing as multiple roles + LfgWaitTime m_waitTimesTank; ///< Average wait time to find a group queuing as tank + LfgWaitTime m_waitTimesHealer; ///< Average wait time to find a group queuing as healer + LfgWaitTime m_waitTimesDps; ///< Average wait time to find a group queuing as dps LFGPlayerScript *m_lfgPlayerScript; LFGGroupScript *m_lfgGroupScript; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.cpp b/src/server/game/DungeonFinding/LFGPlayerData.cpp index 4a6e86ab966..6f030831342 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.cpp +++ b/src/server/game/DungeonFinding/LFGPlayerData.cpp @@ -17,8 +17,8 @@ #include "LFGPlayerData.h" -LfgPlayerData::LfgPlayerData(): -m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), m_Roles(0), m_Comment("") +LfgPlayerData::LfgPlayerData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE), + m_Team(0), m_Group(0), m_Roles(0), m_Comment("") {} LfgPlayerData::~LfgPlayerData() @@ -30,10 +30,10 @@ void LfgPlayerData::SetState(LfgState state) switch (state) { case LFG_STATE_NONE: - case LFG_STATE_DUNGEON: case LFG_STATE_FINISHED_DUNGEON: + case LFG_STATE_DUNGEON: m_OldState = state; - // No break on purpose + // No break on purpose default: m_State = state; } @@ -51,6 +51,16 @@ void LfgPlayerData::SetLockedDungeons(const LfgLockMap& lockStatus) m_LockedDungeons = lockStatus; } +void LfgPlayerData::SetTeam(uint8 team) +{ + m_Team = team; +} + +void LfgPlayerData::SetGroup(uint64 group) +{ + m_Group = group; +} + void LfgPlayerData::SetRoles(uint8 roles) { m_Roles = roles; @@ -66,21 +76,31 @@ void LfgPlayerData::SetSelectedDungeons(const LfgDungeonSet& dungeons) m_SelectedDungeons = dungeons; } -void LfgPlayerData::ClearSelectedDungeons() +LfgState LfgPlayerData::GetState() const { - m_SelectedDungeons.clear(); + return m_State; } -LfgState LfgPlayerData::GetState() const +LfgState LfgPlayerData::GetOldState() const { - return m_State; + return m_OldState; } -const LfgLockMap & LfgPlayerData::GetLockedDungeons() const +const LfgLockMap& LfgPlayerData::GetLockedDungeons() const { return m_LockedDungeons; } +uint8 LfgPlayerData::GetTeam() const +{ + return m_Team; +} + +uint64 LfgPlayerData::GetGroup() const +{ + return m_Group; +} + uint8 LfgPlayerData::GetRoles() const { return m_Roles; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h index e8bae1c5a0f..0682ad66698 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.h +++ b/src/server/game/DungeonFinding/LFGPlayerData.h @@ -18,7 +18,6 @@ #ifndef _LFGPLAYERDATA_H #define _LFGPLAYERDATA_H -#include "Common.h" #include "LFG.h" /** @@ -33,20 +32,26 @@ class LfgPlayerData // General void SetState(LfgState state); void ClearState(); - void SetLockedDungeons(const LfgLockMap& lock); + void SetLockedDungeons(LfgLockMap const& lock); + void SetTeam(uint8 team); + void SetGroup(uint64 group); + // Queue void SetRoles(uint8 roles); - void SetComment(const std::string& comment); + void SetComment(std::string const& comment); void SetSelectedDungeons(const LfgDungeonSet& dungeons); - void ClearSelectedDungeons(); // General LfgState GetState() const; - const LfgLockMap& GetLockedDungeons() const; + LfgState GetOldState() const; + LfgLockMap const& GetLockedDungeons() const; + uint8 GetTeam() const; + uint64 GetGroup() const; + // Queue uint8 GetRoles() const; - const std::string& GetComment() const; - const LfgDungeonSet& GetSelectedDungeons() const; + std::string const& GetComment() const; + LfgDungeonSet const& GetSelectedDungeons() const; private: // General @@ -54,6 +59,9 @@ class LfgPlayerData LfgState m_OldState; ///< Old State // Player LfgLockMap m_LockedDungeons; ///< Dungeons player can't do and reason + uint8 m_Team; ///< Player team - determines the queue to join + uint64 m_Group; ///< Original group of player when joined LFG + // Queue uint8 m_Roles; ///< Roles the player selected when joined LFG std::string m_Comment; ///< Player comment used when joined LFG diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 26686dbaa33..76cc169f477 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -40,7 +40,7 @@ void LFGPlayerScript::OnLevelChanged(Player* player, uint8 /*oldLevel*/) void LFGPlayerScript::OnLogout(Player* player) { uint64 guid = player->GetGUID(); - sLFGMgr->LeaveLfg(player); + sLFGMgr->LeaveLfg(guid); LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); player->GetSession()->SendLfgUpdateParty(updateData); player->GetSession()->SendLfgUpdatePlayer(updateData); @@ -52,6 +52,7 @@ void LFGPlayerScript::OnLogout(Player* player) void LFGPlayerScript::OnLogin(Player* player) { sLFGMgr->InitializeLockedDungeons(player); + sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam()); // TODO - Restore LfgPlayerData and send proper status to player if it was in a group } @@ -69,73 +70,85 @@ LFGGroupScript::LFGGroupScript() : GroupScript("LFGGroupScript") void LFGGroupScript::OnAddMember(Group* group, uint64 guid) { uint64 gguid = group->GetGUID(); - if (!gguid) - return; + uint64 leader = group->GetLeaderGUID(); - sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "]", gguid, guid); - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_CLEAR_LOCK_LIST); - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + if (leader == guid) + { + sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "]", gguid, guid, leader); + sLFGMgr->SetLeader(gguid, guid); + } + else { - if (Player* plrg = itr->getSource()) + LfgState gstate = sLFGMgr->GetState(gguid); + LfgState state = sLFGMgr->GetState(guid); + sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnAddMember [" UI64FMTD "]: added [" UI64FMTD "] leader " UI64FMTD "] gstate: %u, state: %u", gguid, guid, leader, gstate, state); + LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_CLEAR_LOCK_LIST); + for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { - plrg->GetSession()->SendLfgUpdatePlayer(updateData); - plrg->GetSession()->SendLfgUpdateParty(updateData); + if (Player* plrg = itr->getSource()) + { + plrg->GetSession()->SendLfgUpdatePlayer(updateData); + plrg->GetSession()->SendLfgUpdateParty(updateData); + } } - } - // TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued - if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED) - sLFGMgr->LeaveLfg(NULL, group); + if (state == LFG_STATE_QUEUED) + sLFGMgr->LeaveLfg(guid); - if (sLFGMgr->GetState(guid) == LFG_STATE_QUEUED) - if (Player* player = ObjectAccessor::FindPlayer(guid)) - sLFGMgr->LeaveLfg(player); + // TODO - if group is queued and new player is added convert to rolecheck without notify the current players queued + if (gstate == LFG_STATE_QUEUED) + sLFGMgr->LeaveLfg(gguid); + } + + sLFGMgr->SetGroup(guid, gguid); + sLFGMgr->AddPlayerToGroup(gguid, guid); } void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod method, uint64 kicker, char const* reason) { uint64 gguid = group->GetGUID(); - if (!gguid || method == GROUP_REMOVEMETHOD_DEFAULT) - return; - sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnRemoveMember [" UI64FMTD "]: remove [" UI64FMTD "] Method: %d Kicker: [" UI64FMTD "] Reason: %s", gguid, guid, method, kicker, (reason ? reason : "")); - if (sLFGMgr->GetState(gguid) == LFG_STATE_QUEUED) - { - // TODO - Do not remove, just remove the one leaving and rejoin queue with all other data - sLFGMgr->LeaveLfg(NULL, group); - } - if (!group->isLFGGroup()) + if (method == GROUP_REMOVEMETHOD_DEFAULT) return; - if (method == GROUP_REMOVEMETHOD_KICK) // Player have been kicked + LfgState state = sLFGMgr->GetState(gguid); + if (state == LFG_STATE_QUEUED) + sLFGMgr->LeaveLfg(gguid); // TODO - Remove the one leaving and rejoin group + + bool isLFG = group->isLFGGroup(); + + if (isLFG && 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, kicker, guid, str_reason); + sLFGMgr->InitBoot(gguid, kicker, guid, str_reason); return; } - uint32 state = sLFGMgr->GetState(gguid); sLFGMgr->ClearState(guid, "OnRemoveMember"); sLFGMgr->SetState(guid, LFG_STATE_NONE); + sLFGMgr->SetGroup(guid, 0); + sLFGMgr->RemovePlayerFromGroup(gguid, guid); + if (Player* player = ObjectAccessor::FindPlayer(guid)) { - if (method == GROUP_REMOVEMETHOD_LEAVE && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON && sLFGMgr->GetDungeon(gguid, false)) + if (method == GROUP_REMOVEMETHOD_LEAVE && state == LFG_STATE_DUNGEON && + sLFGMgr->GetDungeon(gguid, false)) player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, true); //else if (state == LFG_STATE_BOOT) // Update internal kick cooldown of kicked - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER); - player->GetSession()->SendLfgUpdateParty(updateData); - if (player->GetMap()->IsDungeon()) // Teleport player out the dungeon + player->GetSession()->SendLfgUpdateParty(LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1)); + if (isLFG && player->GetMap()->IsDungeon()) // Teleport player out the dungeon sLFGMgr->TeleportPlayer(player, true); } - if (state != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon - sLFGMgr->OfferContinue(group); + if (isLFG && state != LFG_STATE_FINISHED_DUNGEON) // Need more players to finish the dungeon + if (Player* leader = ObjectAccessor::FindPlayer(sLFGMgr->GetLeader(gguid))) + leader->GetSession()->SendLfgOfferContinue(sLFGMgr->GetDungeon(gguid, false)); } void LFGGroupScript::OnDisband(Group* group) @@ -149,20 +162,19 @@ void LFGGroupScript::OnDisband(Group* group) void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 oldLeaderGuid) { uint64 gguid = group->GetGUID(); - if (!gguid) - return; sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnChangeLeader [" UI64FMTD "]: old [" UI64FMTD "] new [" UI64FMTD "]", gguid, newLeaderGuid, oldLeaderGuid); + sLFGMgr->SetLeader(gguid, newLeaderGuid); Player* player = ObjectAccessor::FindPlayer(newLeaderGuid); - LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER); + LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_LEADER_UNK1); if (player) player->GetSession()->SendLfgUpdateParty(updateData); player = ObjectAccessor::FindPlayer(oldLeaderGuid); if (player) { - updateData.updateType = LFG_UPDATETYPE_GROUP_DISBAND; + updateData.updateType = LFG_UPDATETYPE_GROUP_DISBAND_UNK16; player->GetSession()->SendLfgUpdateParty(updateData); } } @@ -170,9 +182,7 @@ void LFGGroupScript::OnChangeLeader(Group* group, uint64 newLeaderGuid, uint64 o void LFGGroupScript::OnInviteMember(Group* group, uint64 guid) { uint64 gguid = group->GetGUID(); - if (!gguid) - return; sLog->outDebug(LOG_FILTER_LFG, "LFGScripts::OnInviteMember [" UI64FMTD "]: invite [" UI64FMTD "] leader [" UI64FMTD "]", gguid, guid, group->GetLeaderGUID()); - sLFGMgr->LeaveLfg(NULL, group); + sLFGMgr->LeaveLfg(gguid); } diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index 59631618757..4f208d33bde 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -23,7 +23,6 @@ #include "LFGMgr.h" #include "ObjectMgr.h" #include "GroupMgr.h" -#include "InstanceScript.h" void BuildPlayerLockDungeonBlock(WorldPacket& data, const LfgLockMap& lock) { @@ -88,12 +87,13 @@ void WorldSession::HandleLfgLeaveOpcode(WorldPacket& /*recv_data*/) { Group* grp = GetPlayer()->GetGroup(); uint64 guid = GetPlayer()->GetGUID(); + uint64 gguid = grp ? grp->GetGUID() : guid; sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_LEAVE [" UI64FMTD "] in group: %u", guid, grp ? 1 : 0); // Check cheating - only leader can leave the queue if (!grp || grp->GetLeaderGUID() == GetPlayer()->GetGUID()) - sLFGMgr->LeaveLfg(GetPlayer(), grp); + sLFGMgr->LeaveLfg(gguid); } void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recv_data) @@ -140,7 +140,7 @@ void WorldSession::HandleLfgSetBootVoteOpcode(WorldPacket& recv_data) uint64 guid = GetPlayer()->GetGUID(); sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_LFG_SET_BOOT_VOTE [" UI64FMTD "] agree: %u", guid, agree ? 1 : 0); - sLFGMgr->UpdateBoot(GetPlayer(), agree); + sLFGMgr->UpdateBoot(guid, agree); } void WorldSession::HandleLfgTeleportOpcode(WorldPacket& recv_data) @@ -285,6 +285,8 @@ void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData) { bool queued = false; bool extrainfo = false; + uint64 guid = GetPlayer()->GetGUID(); + uint8 size = uint8(updateData.dungeons.size()); switch (updateData.updateType) { @@ -301,9 +303,6 @@ void WorldSession::SendLfgUpdatePlayer(const LfgUpdateData& updateData) break; } - uint64 guid = GetPlayer()->GetGUID(); - uint8 size = uint8(updateData.dungeons.size()); - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PLAYER [" UI64FMTD "] updatetype: %u", guid, updateData.updateType); WorldPacket data(SMSG_LFG_UPDATE_PLAYER, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + size * 4 + updateData.comment.length())); data << uint8(updateData.updateType); // Lfg Update type @@ -328,6 +327,8 @@ void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData) bool join = false; bool extrainfo = false; bool queued = false; + uint64 guid = GetPlayer()->GetGUID(); + uint8 size = uint8(updateData.dungeons.size()); switch (updateData.updateType) { @@ -351,9 +352,6 @@ void WorldSession::SendLfgUpdateParty(const LfgUpdateData& updateData) break; } - uint64 guid = GetPlayer()->GetGUID(); - uint8 size = uint8(updateData.dungeons.size()); - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_UPDATE_PARTY [" UI64FMTD "] updatetype: %u", guid, updateData.updateType); WorldPacket data(SMSG_LFG_UPDATE_PARTY, 1 + 1 + (extrainfo ? 1 : 0) * (1 + 1 + 1 + 1 + 1 + size * 4 + updateData.comment.length())); data << uint8(updateData.updateType); // Lfg Update type @@ -522,7 +520,7 @@ void WorldSession::SendLfgBootProposalUpdate(const LfgPlayerBoot& boot) } } sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s", - guid, uint8(boot.inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), boot.victim, votesNum, agreeNum, secsleft, boot.votedNeeded, boot.reason.c_str()); + guid, uint8(boot.inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), boot.victim, votesNum, agreeNum, secsleft, LFG_GROUP_KICK_VOTES_NEEDED, boot.reason.c_str()); WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + boot.reason.length()); data << uint8(boot.inProgress); // Vote in progress data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote @@ -531,87 +529,56 @@ void WorldSession::SendLfgBootProposalUpdate(const LfgPlayerBoot& boot) data << uint32(votesNum); // Total Votes data << uint32(agreeNum); // Agree Count data << uint32(secsleft); // Time Left - data << uint32(boot.votedNeeded); // Needed Votes + data << uint32(LFG_GROUP_KICK_VOTES_NEEDED); // Needed Votes data << boot.reason.c_str(); // Kick reason SendPacket(&data); } -void WorldSession::SendLfgUpdateProposal(uint32 proposalId, const LfgProposal& proposal) +void WorldSession::SendLfgUpdateProposal(uint32 proposalId, LfgProposal const& proposal) { uint64 guid = GetPlayer()->GetGUID(); - LfgProposalPlayerMap::const_iterator itPlayer = proposal.players.find(guid); - if (itPlayer == proposal.players.end()) // Player MUST be in the proposal - return; + uint64 gguid = proposal.players.find(guid)->second.group; + bool silent = !proposal.isNew && gguid == proposal.group; + uint32 dungeonEntry = proposal.dungeonId; - LfgProposalPlayer* ppPlayer = itPlayer->second; - uint32 pLowGroupGuid = ppPlayer->groupLowGuid; - uint32 dLowGuid = proposal.groupLowGuid; - uint32 dungeonId = proposal.dungeonId; - bool isSameDungeon = false; - bool isContinue = false; - Group* grp = dLowGuid ? sGroupMgr->GetGroupByGUID(dLowGuid) : NULL; - uint32 completedEncounters = 0; - if (grp) - { - uint64 gguid = grp->GetGUID(); - isContinue = grp->isLFGGroup() && sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON; - isSameDungeon = GetPlayer()->GetGroup() == grp && isContinue; - } - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", GetPlayer()->GetGUID(), proposal.state); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_PROPOSAL_UPDATE [" UI64FMTD "] state: %u", guid, proposal.state); WorldPacket data(SMSG_LFG_PROPOSAL_UPDATE, 4 + 1 + 4 + 4 + 1 + 1 + proposal.players.size() * (4 + 1 + 1 + 1 + 1 +1)); - if (!isContinue) // Only show proposal dungeon if it's continue + // show random dungeon if player selected random dungeon and it's not lfg group + if (!silent) { - LfgDungeonSet playerDungeons = sLFGMgr->GetSelectedDungeons(guid); - if (playerDungeons.size() == 1) - dungeonId = (*playerDungeons.begin()); + LfgDungeonSet const& playerDungeons = sLFGMgr->GetSelectedDungeons(guid); + if (playerDungeons.find(proposal.dungeonId) == playerDungeons.end()) + dungeonEntry = (*playerDungeons.begin()); } - if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonId)) - { - dungeonId = dungeon->Entry(); - - // Select a player inside to be get completed encounters from - if (grp) - { - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* groupMember = itr->getSource(); - if (groupMember && groupMember->GetMapId() == uint32(dungeon->map)) - { - if (InstanceScript* instance = groupMember->GetInstanceScript()) - completedEncounters = instance->GetCompletedEncounterMask(); - break; - } - } - } - } + if (LFGDungeonEntry const* dungeon = sLFGMgr->GetLFGDungeon(dungeonEntry)) + dungeonEntry = dungeon->Entry(); - data << uint32(dungeonId); // Dungeon - data << uint8(proposal.state); // Result state - data << uint32(proposalId); // Internal Proposal ID - data << uint32(completedEncounters); // Bosses killed - data << uint8(isSameDungeon); // Silent (show client window) + data << uint32(dungeonEntry); // Dungeon + data << uint8(proposal.state); // Proposal state + data << uint32(proposalId); // Proposal ID + data << uint32(proposal.encounters); // encounters done + data << uint8(silent); // Show proposal window data << uint8(proposal.players.size()); // Group size - for (itPlayer = proposal.players.begin(); itPlayer != proposal.players.end(); ++itPlayer) + for (LfgProposalPlayerMap::const_iterator it = proposal.players.begin(); it != proposal.players.end(); ++it) { - ppPlayer = itPlayer->second; - data << uint32(ppPlayer->role); // Role - data << uint8(itPlayer->first == guid); // Self player - if (!ppPlayer->groupLowGuid) // Player not it a group + LfgProposalPlayer const& player = it->second; + data << uint32(player.role); // Role + data << uint8(it->first == guid); // Self player + if (!player.group) // Player not it a group { data << uint8(0); // Not in dungeon data << uint8(0); // Not same group } else { - data << uint8(ppPlayer->groupLowGuid == dLowGuid); // In dungeon (silent) - data << uint8(ppPlayer->groupLowGuid == pLowGroupGuid); // Same Group than player + data << uint8(player.group == proposal.group); // In dungeon (silent) + data << uint8(player.group == gguid); // Same Group than player } - data << uint8(ppPlayer->accept != LFG_ANSWER_PENDING); // Answered - data << uint8(ppPlayer->accept == LFG_ANSWER_AGREE); // Accepted + data << uint8(player.accept != LFG_ANSWER_PENDING); // Answered + data << uint8(player.accept == LFG_ANSWER_AGREE); // Accepted } SendPacket(&data); } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 5893bbd6564..ee3be6f2b2d 100755 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1076,7 +1076,22 @@ enum TrinityStrings // Use for custom patches 11000-11999 LANG_AUTO_BROADCAST = 11000, - LANG_INVALID_REALMID = 11001 + LANG_INVALID_REALMID = 11001, + + LANG_LFG_STATE_NONE = 11002, + LANG_LFG_STATE_ROLECHECK = 11003, + LANG_LFG_STATE_QUEUED = 11004, + LANG_LFG_STATE_PROPOSAL = 11005, + LANG_LFG_STATE_BOOT = 11006, + LANG_LFG_STATE_DUNGEON = 11007, + LANG_LFG_STATE_FINISHED_DUNGEON = 11008, + LANG_LFG_STATE_RAIDBROWSER = 11009, + LANG_LFG_ROLE_TANK = 11010, + LANG_LFG_ROLE_HEALER = 11011, + LANG_LFG_ROLE_DAMAGE = 11012, + LANG_LFG_ROLE_LEADER = 11013, + LANG_LFG_ROLE_NONE = 11014, + LANG_LFG_ERROR = 11015, // NOT RESERVED IDS 12000-1999999999 // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) |