diff options
| -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)  | 
