aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/2012_10_18_00_world_trinity_string.sql16
-rwxr-xr-xsrc/server/game/DungeonFinding/LFG.h13
-rw-r--r--src/server/game/DungeonFinding/LFGGroupData.cpp42
-rw-r--r--src/server/game/DungeonFinding/LFGGroupData.h14
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.cpp700
-rwxr-xr-xsrc/server/game/DungeonFinding/LFGMgr.h90
-rw-r--r--src/server/game/DungeonFinding/LFGPlayerData.cpp38
-rw-r--r--src/server/game/DungeonFinding/LFGPlayerData.h22
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.cpp92
-rwxr-xr-xsrc/server/game/Handlers/LFGHandler.cpp103
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h17
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)