2010-10-07 15:35:36 +02:00
/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2010-05-20 23:35:27 +02:00
*/
2010-06-25 00:18:01 +02:00
2010-05-20 23:35:27 +02:00
#include "Common.h"
2010-06-08 15:50:23 -06:00
#include "SharedDefines.h"
2010-09-09 14:49:52 +02:00
2010-08-11 16:17:05 +02:00
#include "DisableMgr.h"
2010-09-09 14:49:52 +02:00
#include "ObjectMgr.h"
2010-09-03 20:11:14 +02:00
#include "ProgressBar.h"
2010-09-09 14:49:52 +02:00
#include "SocialMgr.h"
#include "LFGMgr.h"
#include "Group.h"
#include "Player.h"
2010-05-20 23:35:27 +02:00
2010-09-08 13:19:05 +02:00
// --- Temporal functions
// Added to try to find bugs that leaves data inconsistent
void LFGMgr :: Cleaner ()
{
LfgQueueInfoMap :: iterator itQueue ;
LfgGuidList :: iterator itGuidListRemove ;
LfgGuidList eraseList ;
for ( LfgQueueInfoMap :: iterator it = m_QueueInfoMap . begin (); it != m_QueueInfoMap . end ();)
{
itQueue = it ++ ;
// Remove empty queues
if ( ! itQueue -> second )
{
sLog . outError ( "LFGMgr::Cleaner: removing [" UI64FMTD "] from QueueInfoMap, data is null" , itQueue -> first );
m_QueueInfoMap . erase ( itQueue );
}
// Remove queue with empty players
else if ( ! itQueue -> second -> roles . size ())
{
sLog . outError ( "LFGMgr::Cleaner: removing [" UI64FMTD "] from QueueInfoMap, no players in queue!" , itQueue -> first );
m_QueueInfoMap . erase ( itQueue );
}
}
// Remove from NewToQueue those guids that do not exist in queueMap
for ( LfgGuidList :: iterator it = m_newToQueue . begin (); it != m_newToQueue . end ();)
{
itGuidListRemove = it ++ ;
if ( m_QueueInfoMap . find ( * itGuidListRemove ) == m_QueueInfoMap . end ())
{
eraseList . push_back ( * itGuidListRemove );
m_newToQueue . erase ( itGuidListRemove );
2010-09-20 14:06:21 +02:00
sLog . outError ( "LFGMgr::Cleaner: removing [" UI64FMTD "] from newToQueue, no queue info with that guid" , ( * itGuidListRemove ));
2010-09-08 13:19:05 +02:00
}
}
// Remove from currentQueue those guids that do not exist in queueMap
for ( LfgGuidList :: iterator it = m_currentQueue . begin (); it != m_currentQueue . end ();)
{
itGuidListRemove = it ++ ;
if ( m_QueueInfoMap . find ( * itGuidListRemove ) == m_QueueInfoMap . end ())
{
eraseList . push_back ( * itGuidListRemove );
m_newToQueue . erase ( itGuidListRemove );
2010-09-20 14:06:21 +02:00
sLog . outError ( "LFGMgr::Cleaner: removing [" UI64FMTD "] from currentQueue, no queue info with that guid" , ( * itGuidListRemove ));
2010-09-08 13:19:05 +02:00
}
}
for ( LfgGuidList :: iterator it = eraseList . begin (); it != eraseList . end (); ++ it )
{
if ( IS_GROUP ( * it ))
{
2010-09-20 14:06:21 +02:00
if ( Group * grp = sObjectMgr . GetGroupByGUID ( GUID_LOPART ( * it )))
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
if ( Player * plr = itr -> getSource ())
2010-09-08 13:19:05 +02:00
plr -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_REMOVED_FROM_QUEUE );
}
else
2010-09-20 14:06:21 +02:00
if ( Player * plr = sObjectMgr . GetPlayer ( * it ))
2010-09-08 13:19:05 +02:00
plr -> GetSession () -> SendLfgUpdatePlayer ( LFG_UPDATETYPE_REMOVED_FROM_QUEUE );
}
}
2010-05-20 23:35:27 +02:00
LFGMgr :: LFGMgr ()
{
2010-05-31 20:25:21 +02:00
m_QueueTimer = 0 ;
2010-08-18 00:30:17 +02:00
m_WaitTimeAvg = - 1 ;
m_WaitTimeTank = - 1 ;
m_WaitTimeHealer = - 1 ;
m_WaitTimeDps = - 1 ;
m_NumWaitTimeAvg = 0 ;
m_NumWaitTimeTank = 0 ;
m_NumWaitTimeHealer = 0 ;
m_NumWaitTimeDps = 0 ;
2010-05-31 20:25:21 +02:00
m_update = true ;
2010-08-11 15:55:27 +02:00
m_lfgProposalId = 1 ;
2010-09-04 18:20:10 +02:00
GetAllDungeons ();
2010-05-20 23:35:27 +02:00
}
LFGMgr ::~ LFGMgr ()
{
2010-09-03 20:11:14 +02:00
for ( LfgRewardMap :: iterator itr = m_RewardMap . begin (); itr != m_RewardMap . end (); ++ itr )
delete itr -> second ;
m_RewardMap . clear ();
2010-05-20 23:35:27 +02:00
2010-09-03 20:11:14 +02:00
m_EncountersByAchievement . clear ();
2010-05-20 23:35:27 +02:00
2010-08-11 12:44:49 +02:00
for ( LfgQueueInfoMap :: iterator it = m_QueueInfoMap . begin (); it != m_QueueInfoMap . end (); ++ it )
2010-05-20 23:35:27 +02:00
delete it -> second ;
2010-08-11 12:44:49 +02:00
m_QueueInfoMap . clear ();
2010-05-31 20:25:21 +02:00
2010-08-11 15:55:27 +02:00
for ( LfgProposalMap :: iterator it = m_Proposals . begin (); it != m_Proposals . end (); ++ it )
delete it -> second ;
m_Proposals . clear ();
2010-08-13 15:38:10 +02:00
for ( LfgPlayerBootMap :: iterator it = m_Boots . begin (); it != m_Boots . end (); ++ it )
delete it -> second ;
m_Boots . clear ();
2010-05-31 20:25:21 +02:00
for ( LfgRoleCheckMap :: iterator it = m_RoleChecks . begin (); it != m_RoleChecks . end (); ++ it )
delete it -> second ;
m_RoleChecks . clear ();
2010-08-11 12:44:49 +02:00
2010-08-11 13:25:14 +02:00
for ( LfgDungeonMap :: iterator it = m_CachedDungeonMap . begin (); it != m_CachedDungeonMap . end (); ++ it )
delete it -> second ;
m_CachedDungeonMap . clear ();
2010-09-05 22:05:14 +02:00
m_CompatibleMap . clear ();
2010-08-11 12:44:49 +02:00
m_QueueInfoMap . clear ();
m_currentQueue . clear ();
m_newToQueue . clear ();
2010-05-31 20:25:21 +02:00
}
2010-09-05 21:29:52 +02:00
/// <summary>
/// Load achievement <-> encounter associations
/// </summary>
void LFGMgr :: LoadDungeonEncounters ()
{
m_EncountersByAchievement . clear ();
uint32 count = 0 ;
2010-09-11 21:10:54 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT achievementId, dungeonId FROM lfg_dungeon_encounters" );
2010-09-05 21:29:52 +02:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outErrorDb ( ">> Loaded 0 dungeon encounter lfg associations. DB table `lfg_dungeon_encounters` is empty!" );
return ;
}
barGoLink bar ( result -> GetRowCount ());
Field * fields = NULL ;
do
{
bar . step ();
fields = result -> Fetch ();
uint32 achievementId = fields [ 0 ]. GetUInt32 ();
uint32 dungeonId = fields [ 1 ]. GetUInt32 ();
if ( AchievementEntry const * achievement = sAchievementStore . LookupEntry ( achievementId ))
{
if ( ! ( achievement -> flags & ACHIEVEMENT_FLAG_COUNTER ))
{
sLog . outErrorDb ( "Achievement %u specified in table `lfg_dungeon_encounters` is not a statistic!" , achievementId );
continue ;
}
}
else
{
sLog . outErrorDb ( "Achievement %u specified in table `lfg_dungeon_encounters` does not exist!" , achievementId );
continue ;
}
if ( ! sLFGDungeonStore . LookupEntry ( dungeonId ))
{
sLog . outErrorDb ( "Dungeon %u specified in table `lfg_dungeon_encounters` does not exist!" , dungeonId );
continue ;
}
m_EncountersByAchievement [ achievementId ] = dungeonId ;
++ count ;
} while ( result -> NextRow ());
sLog . outString ();
sLog . outString ( ">> Loaded %u dungeon encounter lfg associations." , count );
}
/// <summary>
/// Load rewards for completing dungeons
/// </summary>
void LFGMgr :: LoadRewards ()
{
for ( LfgRewardMap :: iterator itr = m_RewardMap . begin (); itr != m_RewardMap . end (); ++ itr )
delete itr -> second ;
m_RewardMap . clear ();
uint32 count = 0 ;
// ORDER BY is very important for GetRandomDungeonReward!
2010-09-11 21:10:54 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT dungeonId, maxLevel, firstQuestId, firstMoneyVar, firstXPVar, otherQuestId, otherMoneyVar, otherXPVar FROM lfg_dungeon_rewards ORDER BY dungeonId, maxLevel ASC" );
2010-09-05 21:29:52 +02:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outErrorDb ( ">> Loaded 0 lfg dungeon rewards. DB table `lfg_dungeon_rewards` is empty!" );
return ;
}
barGoLink bar ( result -> GetRowCount ());
Field * fields = NULL ;
do
{
bar . step ();
fields = result -> Fetch ();
uint32 dungeonId = fields [ 0 ]. GetUInt32 ();
uint32 maxLevel = fields [ 1 ]. GetUInt8 ();
uint32 firstQuestId = fields [ 2 ]. GetUInt32 ();
uint32 firstMoneyVar = fields [ 3 ]. GetUInt32 ();
uint32 firstXPVar = fields [ 4 ]. GetUInt32 ();
uint32 otherQuestId = fields [ 5 ]. GetUInt32 ();
uint32 otherMoneyVar = fields [ 6 ]. GetUInt32 ();
uint32 otherXPVar = fields [ 7 ]. GetUInt32 ();
if ( ! sLFGDungeonStore . LookupEntry ( dungeonId ))
{
sLog . outErrorDb ( "Dungeon %u specified in table `lfg_dungeon_rewards` does not exist!" , dungeonId );
continue ;
}
if ( ! maxLevel || maxLevel > sWorld . getIntConfig ( CONFIG_MAX_PLAYER_LEVEL ))
{
sLog . outErrorDb ( "Level %u specified for dungeon %u in table `lfg_dungeon_rewards` can never be reached!" , maxLevel , dungeonId );
maxLevel = sWorld . getIntConfig ( CONFIG_MAX_PLAYER_LEVEL );
}
if ( firstQuestId && ! sObjectMgr . GetQuestTemplate ( firstQuestId ))
{
sLog . outErrorDb ( "First quest %u specified for dungeon %u in table `lfg_dungeon_rewards` does not exist!" , firstQuestId , dungeonId );
firstQuestId = 0 ;
}
if ( otherQuestId && ! sObjectMgr . GetQuestTemplate ( otherQuestId ))
{
sLog . outErrorDb ( "Other quest %u specified for dungeon %u in table `lfg_dungeon_rewards` does not exist!" , otherQuestId , dungeonId );
otherQuestId = 0 ;
}
m_RewardMap . insert ( LfgRewardMap :: value_type ( dungeonId , new LfgReward ( maxLevel , firstQuestId , firstMoneyVar , firstXPVar , otherQuestId , otherMoneyVar , otherXPVar )));
++ count ;
} while ( result -> NextRow ());
sLog . outString ();
sLog . outString ( ">> Loaded %u lfg dungeon rewards." , count );
}
2010-08-14 19:30:15 +02:00
2010-05-31 20:25:21 +02:00
void LFGMgr :: Update ( uint32 diff )
{
2010-08-23 19:56:47 -07:00
if ( ! m_update || ! sWorld . getBoolConfig ( CONFIG_DUNGEON_FINDER_ENABLE ))
2010-05-31 20:25:21 +02:00
return ;
2010-08-11 12:44:49 +02:00
m_update = false ;
2010-05-31 20:25:21 +02:00
time_t currTime = time ( NULL );
// Remove obsolete role checks
LfgRoleCheckMap :: iterator itRoleCheck ;
2010-09-20 14:06:21 +02:00
LfgRoleCheck * pRoleCheck ;
2010-05-31 20:25:21 +02:00
for ( LfgRoleCheckMap :: iterator it = m_RoleChecks . begin (); it != m_RoleChecks . end ();)
{
itRoleCheck = it ++ ;
pRoleCheck = itRoleCheck -> second ;
if ( currTime < pRoleCheck -> cancelTime )
continue ;
pRoleCheck -> result = LFG_ROLECHECK_MISSING_ROLE ;
2010-09-20 14:06:21 +02:00
Player * plr = NULL ;
2010-05-31 20:25:21 +02:00
for ( LfgRolesMap :: const_iterator itRoles = pRoleCheck -> roles . begin (); itRoles != pRoleCheck -> roles . end (); ++ itRoles )
{
2010-09-13 09:20:07 +02:00
plr = sObjectMgr . GetPlayerByLowGUID ( itRoles -> first );
2010-05-31 20:25:21 +02:00
if ( ! plr )
continue ;
2010-09-09 14:49:52 +02:00
plr -> GetSession () -> SendLfgRoleCheckUpdate ( pRoleCheck );
2010-08-11 11:54:03 +02:00
plr -> GetLfgDungeons () -> clear ();
plr -> SetLfgRoles ( ROLE_NONE );
2010-09-26 13:59:51 +02:00
if ( ! plr -> GetGroup () || ! plr -> GetGroup () -> isLFGGroup ())
plr -> SetLfgState ( LFG_STATE_NONE );
2010-05-31 20:25:21 +02:00
if ( itRoles -> first == pRoleCheck -> leader )
plr -> GetSession () -> SendLfgJoinResult ( LFG_JOIN_FAILED , pRoleCheck -> result );
}
delete pRoleCheck ;
m_RoleChecks . erase ( itRoleCheck );
}
2010-08-11 12:44:49 +02:00
2010-08-11 15:55:27 +02:00
// Remove obsolete proposals
LfgProposalMap :: iterator itRemove ;
for ( LfgProposalMap :: iterator it = m_Proposals . begin (); it != m_Proposals . end ();)
{
itRemove = it ++ ;
if ( itRemove -> second -> cancelTime < currTime )
RemoveProposal ( itRemove , LFG_UPDATETYPE_PROPOSAL_FAILED );
}
2010-08-14 02:21:07 +02:00
// Remove obsolete kicks
LfgPlayerBootMap :: iterator itBoot ;
2010-09-20 14:06:21 +02:00
LfgPlayerBoot * pBoot ;
2010-08-14 02:21:07 +02:00
for ( LfgPlayerBootMap :: iterator it = m_Boots . begin (); it != m_Boots . end ();)
{
itBoot = it ++ ;
pBoot = itBoot -> second ;
if ( pBoot -> cancelTime < currTime )
{
2010-09-20 14:06:21 +02:00
Group * grp = sObjectMgr . GetGroupByGUID ( itBoot -> first );
2010-08-14 02:21:07 +02:00
pBoot -> inProgress = false ;
for ( LfgAnswerMap :: const_iterator itVotes = pBoot -> votes . begin (); itVotes != pBoot -> votes . end (); ++ itVotes )
2010-09-20 14:06:21 +02:00
if ( Player * plrg = sObjectMgr . GetPlayerByLowGUID ( itVotes -> first ))
2010-08-14 02:21:07 +02:00
if ( plrg -> GetGUIDLow () != pBoot -> victimLowGuid )
2010-09-04 18:20:10 +02:00
plrg -> GetSession () -> SendLfgBootPlayer ( pBoot );
2010-08-14 02:21:07 +02:00
if ( grp )
grp -> SetLfgKickActive ( false );
delete pBoot ;
m_Boots . erase ( itBoot );
}
}
2010-08-14 19:30:15 +02:00
// Consistency cleaner
Cleaner ();
2010-08-14 02:05:05 +02:00
2010-08-11 15:55:27 +02:00
// Check if a proposal can be formed with the new groups being added
2010-10-25 07:16:46 +02:00
LfgProposal * pProposal = NULL ;
2010-08-11 15:55:27 +02:00
LfgGuidList firstNew ;
2010-09-05 22:05:14 +02:00
while ( ! m_newToQueue . empty ())
2010-08-11 15:55:27 +02:00
{
2010-10-16 13:32:30 +06:00
sLog . outDebug ( "LFGMgr::Update: checking [" UI64FMTD "] m_newToQueue(%u), m_currentQueue(%u)" , m_newToQueue . front (), uint32 ( m_newToQueue . size ()), uint32 ( m_currentQueue . size ()));
2010-08-11 15:55:27 +02:00
firstNew . push_back ( m_newToQueue . front ());
2010-10-25 07:16:46 +02:00
pProposal = FindNewGroups ( firstNew , m_currentQueue );
if ( pProposal ) // Group found!
2010-08-11 15:55:27 +02:00
{
2010-09-05 21:29:52 +02:00
// Remove groups in the proposal from new and current queues (not from queue map)
2010-08-11 15:55:27 +02:00
for ( LfgGuidList :: const_iterator it = pProposal -> queues . begin (); it != pProposal -> queues . end (); ++ it )
2010-08-18 00:32:11 +02:00
{
m_currentQueue . remove ( * it );
m_newToQueue . remove ( * it );
}
2010-08-11 15:55:27 +02:00
m_Proposals [ ++ m_lfgProposalId ] = pProposal ;
2010-08-17 13:18:18 +02:00
uint32 lowGuid = 0 ;
2010-08-11 15:55:27 +02:00
for ( LfgProposalPlayerMap :: const_iterator itPlayers = pProposal -> players . begin (); itPlayers != pProposal -> players . end (); ++ itPlayers )
{
2010-08-17 13:18:18 +02:00
lowGuid = itPlayers -> first ;
2010-09-20 14:06:21 +02:00
if ( Player * plr = sObjectMgr . GetPlayerByLowGUID ( itPlayers -> first ))
2010-08-11 15:55:27 +02:00
{
if ( plr -> GetGroup ())
2010-11-26 04:43:07 +01:00
plr -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_PROPOSAL_BEGIN , plr -> GetLfgDungeons (), plr -> GetLfgComment ());
2010-08-11 15:55:27 +02:00
else
2010-11-26 04:43:07 +01:00
plr -> GetSession () -> SendLfgUpdatePlayer ( LFG_UPDATETYPE_PROPOSAL_BEGIN , plr -> GetLfgDungeons (), plr -> GetLfgComment ());
2010-09-04 18:20:10 +02:00
plr -> GetSession () -> SendUpdateProposal ( m_lfgProposalId , pProposal );
2010-08-11 15:55:27 +02:00
}
}
2010-08-24 10:32:53 +02:00
2010-08-17 13:18:18 +02:00
if ( pProposal -> state == LFG_PROPOSAL_SUCCESS )
2010-09-05 21:29:52 +02:00
UpdateProposal ( m_lfgProposalId , lowGuid , true );
2010-08-11 15:55:27 +02:00
}
else
2010-08-17 11:38:30 +02:00
{
2010-10-25 07:16:46 +02:00
m_currentQueue . push_back ( m_newToQueue . front ()); // Group not found, add this group to the queue.
2010-08-17 11:38:30 +02:00
m_newToQueue . pop_front ();
}
2010-08-11 15:55:27 +02:00
firstNew . clear ();
}
2010-08-11 12:44:49 +02:00
// Update all players status queue info
if ( m_QueueTimer > LFG_QUEUEUPDATE_INTERVAL )
{
m_QueueTimer = 0 ;
time_t currTime = time ( NULL );
int32 waitTime ;
2010-09-20 14:06:21 +02:00
LfgQueueInfo * queue ;
2010-08-11 12:44:49 +02:00
uint32 dungeonId ;
uint32 queuedTime ;
uint8 role ;
for ( LfgQueueInfoMap :: const_iterator itQueue = m_QueueInfoMap . begin (); itQueue != m_QueueInfoMap . end (); ++ itQueue )
{
queue = itQueue -> second ;
if ( ! queue )
{
2010-09-08 13:19:05 +02:00
sLog . outError ( "LFGMgr::Update: [" UI64FMTD "] queued with null queue info!" , itQueue -> first );
2010-08-11 12:44:49 +02:00
continue ;
}
2010-09-20 14:06:21 +02:00
dungeonId = ( * queue -> dungeons . begin ());
2010-08-11 12:44:49 +02:00
queuedTime = uint32 ( currTime - queue -> joinTime );
role = ROLE_NONE ;
for ( LfgRolesMap :: const_iterator itPlayer = queue -> roles . begin (); itPlayer != queue -> roles . end (); ++ itPlayer )
role |= itPlayer -> second ;
2010-11-24 15:37:03 +01:00
role &= ~ ROLE_LEADER ;
2010-08-11 12:44:49 +02:00
2010-11-24 15:37:03 +01:00
switch ( role )
2010-08-11 12:44:49 +02:00
{
2010-11-24 15:37:03 +01:00
case ROLE_NONE : // Should not happen - just in case
waitTime = - 1 ;
break ;
case ROLE_TANK :
2010-08-18 00:30:17 +02:00
waitTime = m_WaitTimeTank ;
2010-11-24 15:37:03 +01:00
break ;
case ROLE_HEALER :
2010-08-18 00:30:17 +02:00
waitTime = m_WaitTimeHealer ;
2010-11-24 15:37:03 +01:00
break ;
case ROLE_DAMAGE :
waitTime = m_WaitTimeDps ;
break ;
default :
waitTime = m_WaitTimeAvg ;
break ;
2010-08-11 12:44:49 +02:00
}
for ( LfgRolesMap :: const_iterator itPlayer = queue -> roles . begin (); itPlayer != queue -> roles . end (); ++ itPlayer )
2010-09-20 14:06:21 +02:00
if ( Player * plr = sObjectMgr . GetPlayerByLowGUID ( itPlayer -> first ))
2010-08-18 00:30:17 +02:00
plr -> GetSession () -> SendLfgQueueStatus ( dungeonId , waitTime , m_WaitTimeAvg , m_WaitTimeTank , m_WaitTimeHealer , m_WaitTimeDps , queuedTime , queue -> tanks , queue -> healers , queue -> dps );
2010-08-11 12:44:49 +02:00
}
}
else
m_QueueTimer += diff ;
m_update = true ;
2010-05-20 23:35:27 +02:00
}
2010-09-03 20:11:14 +02:00
/// <summary>
2010-09-05 21:29:52 +02:00
/// Add a guid to new queue, checks consistency
2010-09-03 20:11:14 +02:00
/// </summary>
2010-09-05 21:29:52 +02:00
/// <param name="uint64">Player or group guid</param>
void LFGMgr :: AddGuidToNewQueue ( uint64 guid )
2010-09-03 20:11:14 +02:00
{
2010-09-05 21:29:52 +02:00
// Consistency check
2010-09-27 23:19:22 +02:00
LfgGuidList :: iterator it = std :: find ( m_newToQueue . begin (), m_newToQueue . end (), guid );
if ( it != m_newToQueue . end ())
2010-09-03 20:11:14 +02:00
{
2010-09-27 23:19:22 +02:00
sLog . outError ( "LFGMgr::AddGuidToNewQueue: [" UI64FMTD "] being added to queue and it was already added. ignoring" , guid );
return ;
2010-09-03 20:11:14 +02:00
}
2010-09-27 23:19:22 +02:00
it = std :: find ( m_currentQueue . begin (), m_currentQueue . end (), guid );
if ( it != m_currentQueue . end ())
2010-09-03 20:11:14 +02:00
{
2010-09-27 23:19:22 +02:00
sLog . outError ( "LFGMgr::AddGuidToNewQueue: [" UI64FMTD "] being added to queue and already in current queue (removing to readd)" , guid );
m_currentQueue . erase ( it );
2010-09-05 21:29:52 +02:00
}
2010-09-27 23:19:22 +02:00
// Add to queue
m_newToQueue . push_back ( guid );
2010-10-16 13:32:30 +06:00
sLog . outDebug ( "LFGMgr::AddGuidToNewQueue: [" UI64FMTD "] added to m_newToQueue (size: %u)" , guid , uint32 ( m_newToQueue . size ()));
2010-09-03 20:11:14 +02:00
}
2010-09-05 21:29:52 +02:00
/// <summary>
/// Removes the player/group from all queues
/// </summary>
/// <param name="uint64">Player or group guid</param>
/// <returns>bool</returns>
bool LFGMgr :: RemoveFromQueue ( uint64 guid )
{
bool ret = false ;
uint32 before = m_QueueInfoMap . size ();
2010-09-03 20:11:14 +02:00
2010-09-05 21:29:52 +02:00
m_currentQueue . remove ( guid );
m_newToQueue . remove ( guid );
2010-09-05 22:05:14 +02:00
RemoveFromCompatibles ( guid );
2010-09-05 21:29:52 +02:00
LfgQueueInfoMap :: iterator it = m_QueueInfoMap . find ( guid );
if ( it != m_QueueInfoMap . end ())
{
delete it -> second ;
m_QueueInfoMap . erase ( it );
ret = true ;
}
2010-10-16 13:32:30 +06:00
sLog . outDebug ( "LFGMgr::RemoveFromQueue: [" UI64FMTD "] %s - Queue(%u)" , guid ,
before != m_QueueInfoMap . size () ? "Removed" : "Not in queue" , uint32 ( m_QueueInfoMap . size ()));
2010-09-05 21:29:52 +02:00
return ret ;
2010-09-03 20:11:14 +02:00
}
2010-08-11 13:25:14 +02:00
/// Adds the player/group to lfg queue
2010-11-26 04:43:07 +01:00
void LFGMgr :: Join ( Player * plr , uint8 roles , LfgDungeonSet * dungeons , std :: string comment )
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
if ( ! plr || ! plr -> GetSession () || ! dungeons || ! dungeons -> size ())
return ;
2010-05-31 20:25:21 +02:00
2010-11-26 04:43:07 +01:00
Group * grp = plr -> GetGroup ();
uint64 guid = plr -> GetGUID ();
uint64 gguid = grp ? grp -> GetGUID () : guid ;
LfgJoinResult result = LFG_JOIN_OK ;
PlayerSet players ;
uint32 rDungeonId = 0 ;
bool isContinue = grp && grp -> isLFGGroup () && ! grp -> isLfgDungeonComplete ();
2010-05-31 20:25:21 +02:00
2010-11-26 04:43:07 +01:00
// Do not allow to change dungeon in the middle of a current dungeon
if ( isContinue )
{
dungeons -> clear ();
dungeons -> insert ( grp -> GetLfgDungeonEntry ());
}
2010-08-11 12:44:49 +02:00
2010-11-26 04:43:07 +01:00
// Already in queue?
LfgQueueInfoMap :: iterator itQueue = m_QueueInfoMap . find ( gguid );
2010-08-14 02:05:05 +02:00
if ( itQueue != m_QueueInfoMap . end ())
2010-08-11 12:44:49 +02:00
{
2010-11-26 04:43:07 +01:00
bool sameDungeons = true ;
for ( LfgDungeonSet :: const_iterator it = plr -> GetLfgDungeons () -> begin (); it != plr -> GetLfgDungeons () -> end () && sameDungeons ; ++ it )
if ( dungeons -> find ( * it ) == dungeons -> end ())
sameDungeons = false ;
if ( sameDungeons ) // Joining the same dungeons -- Send OK
{
plr -> GetSession () -> SendLfgJoinResult ( LFG_JOIN_OK );
2010-11-26 17:16:21 +01:00
if ( grp )
{
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
if ( itr -> getSource () && itr -> getSource () -> GetSession ())
itr -> getSource () -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_ADDED_TO_QUEUE , dungeons , comment );
}
2010-11-26 04:43:07 +01:00
dungeons -> clear ();
delete dungeons ;
return ;
}
else if ( ! isContinue ) // Different dungeons and it's not an offer to continue
{
// Different dungeons and it's not a LfgGroup in the middle of a dungeon that need more people
Leave ( plr , grp );
Join ( plr , roles , dungeons , comment );
return ;
}
2010-08-11 12:44:49 +02:00
}
2010-11-26 04:43:07 +01:00
// Check player or group member restrictions
if ( plr -> InBattleground () || plr -> InArena () || plr -> InBattlegroundQueue ())
2010-05-31 20:25:21 +02:00
result = LFG_JOIN_USING_BG_SYSTEM ;
2010-09-26 14:49:55 +02:00
else if ( plr -> HasAura ( LFG_SPELL_DUNGEON_DESERTER ))
2010-05-31 20:25:21 +02:00
result = LFG_JOIN_DESERTER ;
2010-09-26 14:49:55 +02:00
else if ( plr -> HasAura ( LFG_SPELL_DUNGEON_COOLDOWN ))
2010-05-31 20:25:21 +02:00
result = LFG_JOIN_RANDOM_COOLDOWN ;
2010-11-26 04:43:07 +01:00
else if ( ! dungeons || ! dungeons -> size ())
result = LFG_JOIN_NOT_MEET_REQS ;
else if ( grp )
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
if ( grp -> GetMembersCount () > MAXGROUPSIZE )
result = LFG_JOIN_TOO_MUCH_MEMBERS ;
else
2010-11-22 12:28:06 +01:00
{
2010-11-26 04:43:07 +01:00
Player * plrg ;
uint8 memberCount = 0 ;
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL && result == LFG_JOIN_OK ; itr = itr -> next ())
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
plrg = itr -> getSource ();
if ( plrg )
2010-09-30 13:52:29 +02:00
{
2010-11-26 04:43:07 +01:00
if ( plrg -> HasAura ( LFG_SPELL_DUNGEON_DESERTER ))
result = LFG_JOIN_PARTY_DESERTER ;
else if ( plrg -> HasAura ( LFG_SPELL_DUNGEON_COOLDOWN ))
result = LFG_JOIN_PARTY_RANDOM_COOLDOWN ;
else if ( plrg -> InBattleground () || plrg -> InArena () || plrg -> InBattlegroundQueue ())
result = LFG_JOIN_USING_BG_SYSTEM ;
++ memberCount ;
players . insert ( plrg );
2010-09-30 13:52:29 +02:00
}
2010-05-31 20:25:21 +02:00
}
2010-11-26 04:43:07 +01:00
if ( memberCount != grp -> GetMembersCount ())
result = LFG_JOIN_DISCONNECTED ;
2010-11-22 12:28:06 +01:00
}
2010-05-31 20:25:21 +02:00
}
2010-11-26 04:43:07 +01:00
else
players . insert ( plr );
2010-05-31 20:25:21 +02:00
2010-11-26 04:43:07 +01:00
// Check if all dungeons are valid
bool isRaid = false ;
2010-11-22 13:16:09 +01:00
if ( result == LFG_JOIN_OK )
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
bool isDungeon = false ;
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end () && result == LFG_JOIN_OK ; ++ it )
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
switch ( GetDungeonType ( * it ))
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
case LFG_TYPE_RANDOM :
if ( dungeons -> size () > 1 ) // Only allow 1 random dungeon
result = LFG_JOIN_DUNGEON_INVALID ;
else
rDungeonId = ( * dungeons -> begin ());
// No break on purpose (Random can only be dungeon or heroic dungeon)
case LFG_TYPE_HEROIC :
case LFG_TYPE_DUNGEON :
if ( isRaid )
result = LFG_JOIN_MIXED_RAID_DUNGEON ;
isDungeon = true ;
break ;
case LFG_TYPE_RAID :
if ( isDungeon )
result = LFG_JOIN_MIXED_RAID_DUNGEON ;
isRaid = true ;
break ;
default :
result = LFG_JOIN_DUNGEON_INVALID ;
break ;
2010-05-31 20:25:21 +02:00
}
2010-11-22 13:16:09 +01:00
}
2010-11-26 04:43:07 +01:00
// Expand random dungeons and check restrictions
if ( rDungeonId )
2010-11-22 13:16:09 +01:00
{
2010-11-26 04:43:07 +01:00
dungeons -> clear ();
delete dungeons ;
dungeons = GetDungeonsByRandom ( rDungeonId );
2010-05-31 20:25:21 +02:00
}
2010-11-26 04:43:07 +01:00
CheckCompatibleDungeons ( dungeons , & players , false );
if ( ! dungeons || ! dungeons -> size ())
result = LFG_JOIN_NOT_MEET_REQS ;
2010-05-31 20:25:21 +02:00
}
2010-11-26 04:43:07 +01:00
// Can't join. Send result
if ( result != LFG_JOIN_OK )
2010-05-31 20:25:21 +02:00
{
2010-10-06 18:48:39 +02:00
sLog . outDebug ( "LFGMgr::Join: [" UI64FMTD "] joining with %u members. result: %u" , guid , grp ? grp -> GetMembersCount () : 1 , result );
2010-11-26 04:43:07 +01:00
plr -> GetSession () -> SendLfgJoinResult ( result );
if ( dungeons )
dungeons -> clear ();
delete dungeons ;
dungeons = NULL ;
return ;
}
// FIXME - Raid browser not supported yet
if ( isRaid )
{
sLog . outDebug ( "LFGMgr::Join: [" UI64FMTD "] trying to join raid browser and it's disabled." , guid );
dungeons -> clear ();
delete dungeons ;
dungeons = NULL ;
return ;
}
// All ok, Update player info
if ( ! isContinue )
{
2010-08-11 11:54:03 +02:00
plr -> GetLfgDungeons () -> clear ();
2010-11-26 04:43:07 +01:00
if ( rDungeonId )
plr -> GetLfgDungeons () -> insert ( rDungeonId );
else
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end (); ++ it )
plr -> GetLfgDungeons () -> insert ( * it );
}
plr -> SetLfgComment ( comment );
plr -> SetLfgRoles ( roles );
if ( grp ) // Begin rolecheck
{
LfgRoleCheck * pRoleCheck = new LfgRoleCheck ();
pRoleCheck -> cancelTime = time_t ( time ( NULL )) + LFG_TIME_ROLECHECK ;
pRoleCheck -> result = LFG_ROLECHECK_INITIALITING ;
pRoleCheck -> leader = plr -> GetGUIDLow ();
m_RoleChecks [ grp -> GetLowGUID ()] = pRoleCheck ;
if ( isContinue )
2010-05-31 20:25:21 +02:00
{
2010-11-26 04:43:07 +01:00
dungeons -> clear ();
dungeons -> insert ( grp -> GetLfgDungeonEntry ());
2010-05-31 20:25:21 +02:00
}
2010-11-26 04:43:07 +01:00
else if ( rDungeonId )
2010-11-22 13:16:09 +01:00
{
dungeons -> clear ();
2010-11-26 04:43:07 +01:00
dungeons -> insert ( rDungeonId );
2010-11-22 13:16:09 +01:00
}
2010-11-26 04:43:07 +01:00
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end (); ++ it )
pRoleCheck -> dungeons . insert ( * it );
2010-09-08 13:19:05 +02:00
2010-11-26 04:43:07 +01:00
Player * plrg ;
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
2010-09-08 13:19:05 +02:00
{
2010-11-26 04:43:07 +01:00
plrg = itr -> getSource ();
if ( ! plrg )
continue ;
plrg -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_JOIN_PROPOSAL , dungeons , comment );
plrg -> SetLfgState ( LFG_STATE_LFG );
if ( ! isContinue )
2010-09-30 13:52:29 +02:00
{
2010-11-26 04:43:07 +01:00
plrg -> GetLfgDungeons () -> clear ();
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end (); ++ it )
plrg -> GetLfgDungeons () -> insert ( * it );
2010-09-30 13:52:29 +02:00
}
2010-11-26 04:43:07 +01:00
pRoleCheck -> roles [ plrg -> GetGUIDLow ()] = 0 ;
2010-09-08 13:19:05 +02:00
}
2010-11-26 04:43:07 +01:00
UpdateRoleCheck ( grp , plr , true );
2010-05-31 20:25:21 +02:00
}
2010-11-26 04:43:07 +01:00
else // Add player to queue
2010-11-22 13:16:09 +01:00
{
2010-11-26 04:43:07 +01:00
plr -> GetSession () -> SendLfgJoinResult ( LFG_JOIN_OK );
plr -> GetSession () -> SendLfgUpdatePlayer ( LFG_UPDATETYPE_JOIN_PROPOSAL , dungeons , comment );
plr -> SetLfgState ( LFG_STATE_LFG );
LfgQueueInfo * pqInfo = new LfgQueueInfo ();
pqInfo -> joinTime = time_t ( time ( NULL ));
pqInfo -> roles [ plr -> GetGUIDLow ()] = plr -> GetLfgRoles ();
uint8 roles = plr -> GetLfgRoles ();
if ( roles & ROLE_TANK )
-- pqInfo -> tanks ;
else if ( roles & ROLE_HEALER )
-- pqInfo -> healers ;
else
-- pqInfo -> dps ;
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end (); ++ it )
pqInfo -> dungeons . insert ( * it );
m_QueueInfoMap [ guid ] = pqInfo ;
AddGuidToNewQueue ( guid );
}
std :: string dungeonsstr = ConcatenateDungeons ( dungeons );
sLog . outDebug ( "LFGMgr::Join: [" UI64FMTD "] joined with %u members. dungeons: %s" , guid , grp ? grp -> GetMembersCount () : 1 , dungeonsstr . c_str ());
dungeons -> clear ();
delete dungeons ;
dungeons = NULL ;
2010-05-31 20:25:21 +02:00
}
/// <summary>
/// Leave the lfg queue
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Player*">Player (could be NULL)</param>
/// <param name="Group*">Group (could be NULL)</param>
void LFGMgr :: Leave ( Player * plr , Group * grp /* = NULL*/ )
2010-05-31 20:25:21 +02:00
{
2010-09-26 13:59:51 +02:00
if (( plr && ( ! plr -> GetLfgUpdate () || ! plr -> isUsingLfg ())) || ! sWorld . getBoolConfig ( CONFIG_DUNGEON_FINDER_ENABLE ))
2010-08-18 00:30:17 +02:00
return ;
2010-09-21 10:16:54 +02:00
2010-05-31 20:25:21 +02:00
uint64 guid = grp ? grp -> GetGUID () : plr ? plr -> GetGUID () : 0 ;
2010-10-06 18:48:39 +02:00
sLog . outDebug ( "LFGMgr::Leave: [" UI64FMTD "]" , guid );
2010-10-25 11:26:01 +02:00
if ( ! guid )
return ;
2010-05-31 20:25:21 +02:00
2010-08-11 12:44:49 +02:00
// Remove from Role Checks
2010-05-31 20:25:21 +02:00
if ( grp )
{
2010-08-11 15:20:20 +02:00
grp -> SetLfgQueued ( false );
2010-08-11 12:44:49 +02:00
LfgRoleCheckMap :: const_iterator itRoleCheck = m_RoleChecks . find ( GUID_LOPART ( guid ));
2010-05-31 20:25:21 +02:00
if ( itRoleCheck != m_RoleChecks . end ())
{
2010-10-25 07:16:46 +02:00
UpdateRoleCheck ( grp ); // No player to update role = LFG_ROLECHECK_ABORTED
2010-05-31 20:25:21 +02:00
return ;
}
}
2010-08-11 15:55:27 +02:00
// Remove from Proposals
2010-09-20 14:06:21 +02:00
bool proposalFound = false ;
2010-09-27 23:19:22 +02:00
LfgProposalMap :: iterator it = m_Proposals . begin ();
while ( it != m_Proposals . end () && ! proposalFound )
2010-08-11 15:55:27 +02:00
{
// Mark the player/leader of group who left as didn't accept the proposal
for ( LfgProposalPlayerMap :: iterator itPlayer = it -> second -> players . begin (); itPlayer != it -> second -> players . end (); ++ itPlayer )
2010-09-20 14:06:21 +02:00
{
2010-08-11 15:55:27 +02:00
if (( plr && itPlayer -> first == plr -> GetGUIDLow ()) || ( grp && itPlayer -> first == GUID_LOPART ( grp -> GetLeaderGUID ())))
2010-09-20 14:06:21 +02:00
{
2010-09-05 21:29:52 +02:00
itPlayer -> second -> accept = LFG_ANSWER_DENY ;
2010-09-20 14:06:21 +02:00
proposalFound = true ;
}
}
2010-09-27 23:19:22 +02:00
if ( ! proposalFound )
++ it ;
2010-08-11 15:55:27 +02:00
}
2010-09-20 14:06:21 +02:00
// Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
if ( proposalFound )
RemoveProposal ( it , LFG_UPDATETYPE_PROPOSAL_DECLINED );
else
RemoveFromQueue ( guid );
2010-05-31 20:25:21 +02:00
if ( grp )
{
2010-09-20 14:06:21 +02:00
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
if ( Player * plrg = itr -> getSource ())
2010-05-31 20:25:21 +02:00
{
plrg -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_REMOVED_FROM_QUEUE );
2010-08-11 11:54:03 +02:00
plrg -> GetLfgDungeons () -> clear ();
plrg -> SetLfgRoles ( ROLE_NONE );
2010-09-26 13:59:51 +02:00
plrg -> SetLfgState ( LFG_STATE_NONE );
2010-05-31 20:25:21 +02:00
}
}
else
{
plr -> GetSession () -> SendLfgUpdatePlayer ( LFG_UPDATETYPE_REMOVED_FROM_QUEUE );
2010-08-11 11:54:03 +02:00
plr -> GetLfgDungeons () -> clear ();
plr -> SetLfgRoles ( ROLE_NONE );
2010-09-26 13:59:51 +02:00
plr -> SetLfgState ( LFG_STATE_NONE );
2010-09-26 14:49:55 +02:00
plr -> RemoveAurasDueToSpell ( LFG_SPELL_LUCK_OF_THE_DRAW );
2010-05-31 20:25:21 +02:00
}
}
2010-08-11 15:55:27 +02:00
/// <summary>
/// Given a Lfg group checks if leader needs to be show the popup to select more players
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Group*">Group than needs new players</param>
void LFGMgr :: OfferContinue ( Group * grp )
2010-08-11 15:55:27 +02:00
{
2010-09-21 10:16:54 +02:00
if ( ! sWorld . getBoolConfig ( CONFIG_DUNGEON_FINDER_ENABLE ))
return ;
2010-09-20 14:06:21 +02:00
ASSERT ( grp );
if ( Player * leader = sObjectMgr . GetPlayer ( grp -> GetLeaderGUID ()))
leader -> GetSession () -> SendLfgOfferContinue ( grp -> GetLfgDungeonEntry ( false ));
2010-08-11 15:55:27 +02:00
}
/// <summary>
2010-09-13 09:20:07 +02:00
/// Check the queue to try to match groups. Returns all the possible matches
2010-08-11 15:55:27 +02:00
/// </summary>
/// <param name="LfgGuidList &">Guids we trying to match with the rest of groups</param>
/// <param name="LfgGuidList">All guids in queue</param>
2010-10-25 07:16:46 +02:00
/// <returns>LfgProposal*</returns>
LfgProposal * LFGMgr :: FindNewGroups ( LfgGuidList check , LfgGuidList all )
2010-08-11 15:55:27 +02:00
{
2010-10-06 18:48:39 +02:00
sLog . outDebug ( "LFGMgr::FindNewGroup: (%s) - all(%s)" , ConcatenateGuids ( check ). c_str (), ConcatenateGuids ( all ). c_str ());
2010-09-16 18:53:25 +02:00
2010-10-25 07:16:46 +02:00
LfgProposal * pProposal = NULL ;
if ( ! check . size () || check . size () > MAXGROUPSIZE || ! CheckCompatibility ( check , pProposal ))
return NULL ;
2010-09-05 22:05:14 +02:00
2010-10-25 07:16:46 +02:00
// Try to match with queued groups
while ( ! pProposal && all . size () > 0 )
2010-09-05 22:05:14 +02:00
{
2010-10-25 07:16:46 +02:00
check . push_back ( all . front ());
all . pop_front ();
pProposal = FindNewGroups ( check , all );
2010-09-05 22:05:14 +02:00
check . pop_back ();
}
2010-10-25 07:16:46 +02:00
return pProposal ;
2010-09-05 22:05:14 +02:00
}
/// <summary>
/// Check compatibilities between groups.
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="LfgGuidList">Guids we checking compatibility</param>
2010-09-05 22:05:14 +02:00
/// <returns>bool</returns>
2010-10-25 07:16:46 +02:00
/// <param name="LfgProposal*&">Proposals found.</param>
bool LFGMgr :: CheckCompatibility ( LfgGuidList check , LfgProposal *& pProposal )
2010-09-05 22:05:14 +02:00
{
2010-10-25 07:16:46 +02:00
if ( pProposal ) // Do not check anything if we already have a proposal
return false ;
2010-09-05 22:05:14 +02:00
std :: string strGuids = ConcatenateGuids ( check );
if ( check . size () > MAXGROUPSIZE || ! check . size ())
{
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s): Size wrong - Not compatibles" , strGuids . c_str ());
2010-09-05 22:05:14 +02:00
return false ;
}
2010-09-12 01:40:27 +02:00
2010-10-25 07:16:46 +02:00
if ( check . size () == 1 && IS_PLAYER_GUID ( check . front ())) // Player joining dungeon... compatible
return true ;
// Previously cached?
LfgAnswer answer = GetCompatibles ( strGuids );
if ( answer != LFG_ANSWER_PENDING )
{
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) compatibles (cached): %d" , strGuids . c_str (), answer );
return bool ( answer );
}
// Check all but new compatiblitity
if ( check . size () > 2 )
{
uint64 frontGuid = check . front ();
check . pop_front ();
// Check all-but-new compatibilities (New,A,B,C,D) --> check(A,B,C,D)
if ( ! CheckCompatibility ( check , pProposal )) // Group not compatible
{
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) not compatibles (%s not compatibles)" , strGuids . c_str (), ConcatenateGuids ( check ). c_str ());
SetCompatibles ( strGuids , false );
return false ;
}
check . push_front ( frontGuid );
// all-but-new compatibles, now check with new
}
2010-08-11 15:55:27 +02:00
uint8 numPlayers = 0 ;
uint8 numLfgGroups = 0 ;
uint32 groupLowGuid = 0 ;
LfgQueueInfoMap pqInfoMap ;
2010-08-14 02:05:05 +02:00
LfgQueueInfoMap :: iterator itQueue ;
2010-08-18 22:50:04 +02:00
for ( LfgGuidList :: const_iterator it = check . begin (); it != check . end () && numLfgGroups < 2 && numPlayers <= MAXGROUPSIZE ; ++ it )
2010-08-11 15:55:27 +02:00
{
2010-08-14 02:05:05 +02:00
itQueue = m_QueueInfoMap . find ( * it );
if ( itQueue == m_QueueInfoMap . end ())
2010-08-11 15:55:27 +02:00
{
2010-09-20 14:06:21 +02:00
sLog . outError ( "LFGMgr::CheckCompatibility: [" UI64FMTD "] is not queued but listed as queued!" , ( * it ));
2010-09-13 09:43:59 +02:00
RemoveFromQueue ( * it );
2010-09-05 22:05:14 +02:00
return false ;
2010-08-11 15:55:27 +02:00
}
2010-08-14 02:05:05 +02:00
pqInfoMap [ * it ] = itQueue -> second ;
numPlayers += itQueue -> second -> roles . size ();
2010-08-11 15:55:27 +02:00
if ( IS_GROUP ( * it ))
{
uint32 lowGuid = GUID_LOPART ( * it );
2010-09-20 14:06:21 +02:00
if ( Group * grp = sObjectMgr . GetGroupByGUID ( lowGuid ))
2010-08-11 15:55:27 +02:00
if ( grp -> isLFGGroup ())
{
if ( ! numLfgGroups )
groupLowGuid = lowGuid ;
++ numLfgGroups ;
}
}
}
2010-10-25 07:16:46 +02:00
if ( check . size () == 1 )
2010-08-11 15:55:27 +02:00
{
2010-10-25 07:16:46 +02:00
if ( numPlayers != MAXGROUPSIZE ) // Single group with less than MAXGROUPSIZE - Compatibles
return true ;
2010-09-05 22:05:14 +02:00
}
// Do not match - groups already in a lfgDungeon or too much players
if ( numLfgGroups > 1 || numPlayers > MAXGROUPSIZE )
{
2010-08-11 15:55:27 +02:00
pqInfoMap . clear ();
2010-09-05 22:05:14 +02:00
SetCompatibles ( strGuids , false );
if ( numLfgGroups > 1 )
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) More than one Lfggroup (%u)" , strGuids . c_str (), numLfgGroups );
2010-09-05 22:05:14 +02:00
else
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) Too much players (%u)" , strGuids . c_str (), numPlayers );
2010-09-05 22:05:14 +02:00
return false ;
2010-08-11 15:55:27 +02:00
}
// ----- Player checks -----
LfgRolesMap rolesMap ;
uint32 newLeaderLowGuid = 0 ;
for ( LfgQueueInfoMap :: const_iterator it = pqInfoMap . begin (); it != pqInfoMap . end (); ++ it )
{
for ( LfgRolesMap :: const_iterator itRoles = it -> second -> roles . begin (); itRoles != it -> second -> roles . end (); ++ itRoles )
{
// Assign new leader
if ( itRoles -> second & ROLE_LEADER && ( ! newLeaderLowGuid || urand ( 0 , 1 )))
newLeaderLowGuid = itRoles -> first ;
2010-10-25 07:16:46 +02:00
if ( rolesMap [ itRoles -> first ]) // Player already added!
2010-09-16 18:54:36 +02:00
{
// Find the other guid
uint64 guid1 = it -> first ;
uint64 guid2 = 0 ;
for ( LfgQueueInfoMap :: const_iterator it2 = pqInfoMap . begin (); it2 != it && ! guid2 ; ++ it2 )
{
if ( it2 -> second -> roles . find ( itRoles -> first ) != it2 -> second -> roles . end ())
guid2 = it2 -> first ;
}
uint64 playerguid ;
// store in guid2 the obsolete group
if ( pqInfoMap [ guid2 ] -> joinTime > it -> second -> joinTime )
{
playerguid = guid2 ;
guid2 = guid1 ;
guid1 = playerguid ;
}
playerguid = MAKE_NEW_GUID ( itRoles -> first , 0 , HIGHGUID_PLAYER );
2010-09-25 22:03:57 +02:00
sLog . outError ( "LFGMgr::CheckCompatibility: check(%s) player [" UI64FMTD "] in queue with [" UI64FMTD "] and OBSOLETE! [" UI64FMTD "]" ,
2010-09-16 18:54:36 +02:00
strGuids . c_str (), playerguid , guid1 , guid2 );
}
2010-08-11 15:55:27 +02:00
rolesMap [ itRoles -> first ] = itRoles -> second ;
}
}
2010-09-05 22:05:14 +02:00
if ( rolesMap . size () != numPlayers )
2010-08-11 15:55:27 +02:00
{
2010-09-05 22:05:14 +02:00
pqInfoMap . clear ();
rolesMap . clear ();
return false ;
2010-08-11 15:55:27 +02:00
}
2010-09-20 14:06:21 +02:00
Player * plr ;
2010-08-11 15:55:27 +02:00
PlayerSet players ;
for ( LfgRolesMap :: const_iterator it = rolesMap . begin (); it != rolesMap . end (); ++ it )
{
2010-09-13 09:20:07 +02:00
plr = sObjectMgr . GetPlayerByLowGUID ( it -> first );
2010-09-05 22:05:14 +02:00
if ( ! plr )
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) Warning! %u offline! Marking as not compatibles!" , strGuids . c_str (), it -> first );
2010-09-09 14:49:52 +02:00
else
2010-08-11 15:55:27 +02:00
{
2010-09-09 14:49:52 +02:00
for ( PlayerSet :: const_iterator itPlayer = players . begin (); itPlayer != players . end () && plr ; ++ itPlayer )
{
// Do not form a group with ignoring candidates
if ( plr -> GetSocial () -> HasIgnore (( * itPlayer ) -> GetGUIDLow ()) || ( * itPlayer ) -> GetSocial () -> HasIgnore ( plr -> GetGUIDLow ()))
2010-09-20 14:06:21 +02:00
{
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) Players [" UI64FMTD "] and [" UI64FMTD "] ignoring" , strGuids . c_str (), ( * itPlayer ) -> GetGUID (), plr -> GetGUID ());
2010-09-09 14:49:52 +02:00
plr = NULL ;
2010-09-20 14:06:21 +02:00
}
2010-09-09 14:49:52 +02:00
// neither with diferent faction if it's not a mixed faction server
else if ( plr -> GetTeam () != ( * itPlayer ) -> GetTeam () && ! sWorld . getBoolConfig ( CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP ))
2010-09-20 14:06:21 +02:00
{
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) Players [" UI64FMTD "] and [" UI64FMTD "] are from diff sides" , strGuids . c_str (), ( * itPlayer ) -> GetGUID (), plr -> GetGUID ());
2010-09-09 14:49:52 +02:00
plr = NULL ;
2010-09-20 14:06:21 +02:00
}
2010-09-09 14:49:52 +02:00
}
if ( plr )
players . insert ( plr );
2010-08-11 15:55:27 +02:00
}
}
2010-09-05 22:05:14 +02:00
// if we dont have the same ammount of players then we have self ignoring candidates or different faction groups
2010-08-11 15:55:27 +02:00
// otherwise check if roles are compatible
2010-09-05 22:05:14 +02:00
if ( players . size () != numPlayers || ! CheckGroupRoles ( rolesMap ))
2010-08-11 15:55:27 +02:00
{
2010-09-20 14:06:21 +02:00
if ( players . size () == numPlayers )
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) Roles not compatible" , strGuids . c_str ());
2010-08-11 15:55:27 +02:00
pqInfoMap . clear ();
2010-09-05 22:05:14 +02:00
rolesMap . clear ();
players . clear ();
SetCompatibles ( strGuids , false );
return false ;
2010-08-11 15:55:27 +02:00
}
// ----- Selected Dungeon checks -----
// Check if there are any compatible dungeon from the selected dungeons
2010-09-05 22:05:14 +02:00
LfgDungeonMap dungeonMap ;
for ( LfgQueueInfoMap :: const_iterator it = pqInfoMap . begin (); it != pqInfoMap . end (); ++ it )
dungeonMap [ it -> first ] = & it -> second -> dungeons ;
2010-08-11 15:55:27 +02:00
2010-09-20 14:06:21 +02:00
LfgDungeonSet * compatibleDungeons = CheckCompatibleDungeons ( & dungeonMap , & players );
2010-09-05 22:05:14 +02:00
dungeonMap . clear ();
pqInfoMap . clear ();
if ( ! compatibleDungeons || ! compatibleDungeons -> size ())
2010-08-11 15:55:27 +02:00
{
2010-09-05 22:05:14 +02:00
if ( compatibleDungeons )
delete compatibleDungeons ;
players . clear ();
rolesMap . clear ();
2010-09-06 03:51:08 +02:00
SetCompatibles ( strGuids , false );
2010-09-05 22:05:14 +02:00
return false ;
2010-08-11 15:55:27 +02:00
}
2010-09-06 03:51:08 +02:00
SetCompatibles ( strGuids , true );
2010-08-11 15:55:27 +02:00
2010-09-05 22:05:14 +02:00
// ----- Group is compatible, if we have MAXGROUPSIZE members then match is found
if ( numPlayers != MAXGROUPSIZE )
2010-08-11 15:55:27 +02:00
{
players . clear ();
2010-09-05 22:05:14 +02:00
rolesMap . clear ();
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) Compatibles but not match. Players(%u)" , strGuids . c_str (), numPlayers );
2010-09-05 22:05:14 +02:00
return true ;
2010-08-11 15:55:27 +02:00
}
2010-10-06 18:48:39 +02:00
sLog . outDebug ( "LFGMgr::CheckCompatibility: (%s) MATCH! Group formed" , strGuids . c_str ());
2010-08-11 15:55:27 +02:00
2010-10-25 07:16:46 +02:00
// GROUP FORMED!
// TODO - Improve algorithm to select proper group based on Item Level
// Do not match bad tank and bad healer on same group
2010-08-11 15:55:27 +02:00
// Select a random dungeon from the compatible list
2010-10-25 07:16:46 +02:00
// TODO - Select the dungeon based on group item Level, not just random
2010-09-05 22:05:14 +02:00
LfgDungeonSet :: iterator itDungeon = compatibleDungeons -> begin ();
2010-08-11 15:55:27 +02:00
uint32 selectedDungeon = urand ( 0 , compatibleDungeons -> size () - 1 );
while ( selectedDungeon > 0 )
{
++ itDungeon ;
-- selectedDungeon ;
}
2010-09-20 14:06:21 +02:00
selectedDungeon = ( * itDungeon );
2010-08-11 15:55:27 +02:00
compatibleDungeons -> clear ();
delete compatibleDungeons ;
// Create a new proposal
2010-10-25 07:16:46 +02:00
pProposal = new LfgProposal ( selectedDungeon );
2010-08-11 15:55:27 +02:00
pProposal -> cancelTime = time_t ( time ( NULL )) + LFG_TIME_PROPOSAL ;
pProposal -> queues = check ;
pProposal -> groupLowGuid = groupLowGuid ;
// Assign new roles to players and assign new leader
2010-09-20 14:06:21 +02:00
LfgProposalPlayer * ppPlayer ;
2010-08-11 15:55:27 +02:00
uint32 lowGuid ;
PlayerSet :: const_iterator itPlayers = players . begin ();
if ( ! newLeaderLowGuid )
{
uint8 pos = urand ( 0 , players . size () - 1 );
for ( uint8 i = 0 ; i < pos ; ++ i )
++ itPlayers ;
newLeaderLowGuid = ( * itPlayers ) -> GetGUIDLow ();
}
pProposal -> leaderLowGuid = newLeaderLowGuid ;
2010-08-17 13:18:18 +02:00
uint8 numAccept = 0 ;
2010-08-11 15:55:27 +02:00
for ( itPlayers = players . begin (); itPlayers != players . end (); ++ itPlayers )
{
lowGuid = ( * itPlayers ) -> GetGUIDLow ();
ppPlayer = new LfgProposalPlayer ();
2010-09-20 14:06:21 +02:00
Group * grp = ( * itPlayers ) -> GetGroup ();
2010-08-17 13:18:18 +02:00
if ( grp )
2010-08-11 15:55:27 +02:00
{
2010-08-17 13:18:18 +02:00
ppPlayer -> groupLowGuid = grp -> GetLowGUID ();
if ( grp -> GetLfgDungeonEntry () == selectedDungeon && ppPlayer -> groupLowGuid == pProposal -> groupLowGuid ) // Player from existing group, autoaccept
{
2010-09-05 21:29:52 +02:00
ppPlayer -> accept = LFG_ANSWER_AGREE ;
2010-08-17 13:18:18 +02:00
++ numAccept ;
}
2010-08-11 15:55:27 +02:00
}
ppPlayer -> role = rolesMap [ lowGuid ];
pProposal -> players [ lowGuid ] = ppPlayer ;
}
2010-08-17 13:18:18 +02:00
if ( numAccept == MAXGROUPSIZE )
pProposal -> state = LFG_PROPOSAL_SUCCESS ;
2010-09-05 22:05:14 +02:00
rolesMap . clear ();
2010-08-11 15:55:27 +02:00
players . clear ();
2010-09-05 22:05:14 +02:00
return true ;
2010-08-11 15:55:27 +02:00
}
2010-05-31 20:25:21 +02:00
/// Update the Role check info with the player selected role.
2010-11-26 04:43:07 +01:00
void LFGMgr :: UpdateRoleCheck ( Group * grp , Player * plr /* = NULL*/ , bool newRoleCheck /* = false */ )
2010-05-31 20:25:21 +02:00
{
2010-08-13 08:06:04 +02:00
if ( ! grp )
return ;
2010-05-31 20:25:21 +02:00
2010-09-20 14:06:21 +02:00
LfgRoleCheck * pRoleCheck = NULL ;
2010-05-31 20:25:21 +02:00
LfgRolesMap check_roles ;
2010-11-26 04:43:07 +01:00
LfgRoleCheckMap :: iterator itRoleCheck = m_RoleChecks . find ( grp -> GetLowGUID ());
if ( itRoleCheck == m_RoleChecks . end ())
return ;
2010-05-31 20:25:21 +02:00
2010-11-26 04:43:07 +01:00
pRoleCheck = itRoleCheck -> second ;
2010-09-20 14:06:21 +02:00
LfgLockStatusMap * playersLockMap = NULL ;
2010-05-31 20:25:21 +02:00
if ( plr )
{
// Player selected no role.
2010-08-11 11:54:03 +02:00
if ( plr -> GetLfgRoles () < ROLE_TANK )
2010-05-31 20:25:21 +02:00
pRoleCheck -> result = LFG_ROLECHECK_NO_ROLE ;
else
{
// Check if all players have selected a role
2010-08-11 12:44:49 +02:00
pRoleCheck -> roles [ plr -> GetGUIDLow ()] = plr -> GetLfgRoles ();
2010-05-31 20:25:21 +02:00
uint8 size = 0 ;
2010-06-01 09:38:05 +02:00
for ( LfgRolesMap :: const_iterator itRoles = pRoleCheck -> roles . begin (); itRoles != pRoleCheck -> roles . end () && itRoles -> second != ROLE_NONE ; ++ itRoles )
2010-05-31 20:25:21 +02:00
++ size ;
if ( pRoleCheck -> roles . size () == size )
{
// use temporal var to check roles, CheckGroupRoles modifies the roles
2010-08-11 12:44:49 +02:00
check_roles = pRoleCheck -> roles ;
2010-10-25 07:16:46 +02:00
if ( ! CheckGroupRoles ( check_roles )) // Group is not posible
2010-05-31 20:25:21 +02:00
pRoleCheck -> result = LFG_ROLECHECK_WRONG_ROLES ;
else
{
// Check if we can find a dungeon for that group
pRoleCheck -> result = LFG_ROLECHECK_FINISHED ;
2010-09-08 13:19:05 +02:00
if ( pRoleCheck -> dungeons . size () == 1 && isRandomDungeon ( * pRoleCheck -> dungeons . begin ()))
2010-05-31 20:25:21 +02:00
{
2010-09-08 13:19:05 +02:00
// Random dungeon - select the compatible dungeons
2010-09-20 14:06:21 +02:00
LfgDungeonSet * dungeons = GetDungeonsByRandom ( * pRoleCheck -> dungeons . begin ());
2010-09-08 13:19:05 +02:00
PlayerSet players ;
for ( LfgRolesMap :: const_iterator it = pRoleCheck -> roles . begin (); it != pRoleCheck -> roles . end (); ++ it )
2010-09-20 14:06:21 +02:00
if ( Player * plr = sObjectMgr . GetPlayerByLowGUID ( it -> first ))
2010-09-08 13:19:05 +02:00
players . insert ( plr );
2010-09-09 14:49:52 +02:00
playersLockMap = CheckCompatibleDungeons ( dungeons , & players );
2010-09-20 14:06:21 +02:00
std :: string dungeonstr = ConcatenateDungeons ( dungeons );
2010-10-06 18:48:39 +02:00
sLog . outDebug ( "LFGMgr::UpdateRoleCheck: [" UI64FMTD "] done. Dungeons: %s" , plr -> GetGUID (), dungeonstr . c_str ());
2010-09-08 13:19:05 +02:00
pRoleCheck -> dungeons . clear ();
if ( dungeons )
{
if ( dungeons -> empty ())
delete dungeons ;
else
{
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end (); ++ it )
pRoleCheck -> dungeons . insert ( * it );
if ( playersLockMap )
{
for ( LfgLockStatusMap :: iterator itMap = playersLockMap -> begin (); itMap != playersLockMap -> end (); ++ itMap )
{
itMap -> second -> clear ();
delete itMap -> second ;
}
playersLockMap -> clear ();
delete playersLockMap ;
playersLockMap = NULL ;
}
}
}
2010-05-31 20:25:21 +02:00
}
2010-09-08 13:19:05 +02:00
else
playersLockMap = GetPartyLockStatusDungeons ( plr , & pRoleCheck -> dungeons );
2010-05-31 20:25:21 +02:00
}
}
}
}
else
pRoleCheck -> result = LFG_ROLECHECK_ABORTED ;
2010-09-20 14:06:21 +02:00
WorldSession * session ;
Player * plrg = NULL ;
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
2010-05-31 20:25:21 +02:00
{
plrg = itr -> getSource ();
if ( ! plrg )
continue ;
session = plrg -> GetSession ();
if ( ! newRoleCheck && plr )
2010-08-11 11:54:03 +02:00
session -> SendLfgRoleChosen ( plr -> GetGUID (), plr -> GetLfgRoles ());
2010-09-09 14:49:52 +02:00
session -> SendLfgRoleCheckUpdate ( pRoleCheck );
2010-05-31 20:25:21 +02:00
switch ( pRoleCheck -> result )
{
case LFG_ROLECHECK_INITIALITING :
continue ;
case LFG_ROLECHECK_FINISHED :
if ( ! playersLockMap )
2010-11-26 04:43:07 +01:00
session -> SendLfgUpdateParty ( LFG_UPDATETYPE_ADDED_TO_QUEUE , & pRoleCheck -> dungeons , plrg -> GetLfgComment ());
2010-05-31 20:25:21 +02:00
else
{
2010-08-11 12:44:49 +02:00
if ( grp -> GetLeaderGUID () == plrg -> GetGUID ())
2010-09-09 14:49:52 +02:00
session -> SendLfgJoinResult ( LFG_JOIN_PARTY_NOT_MEET_REQS , 0 , playersLockMap );
2010-05-31 20:25:21 +02:00
session -> SendLfgUpdateParty ( LFG_UPDATETYPE_ROLECHECK_FAILED );
2010-08-11 11:54:03 +02:00
plrg -> GetLfgDungeons () -> clear ();
plrg -> SetLfgRoles ( ROLE_NONE );
2010-09-26 13:59:51 +02:00
if ( ! grp -> isLFGGroup ())
2010-09-26 15:13:21 +02:00
plrg -> SetLfgState ( LFG_STATE_NONE );
2010-05-31 20:25:21 +02:00
}
break ;
default :
2010-08-11 12:44:49 +02:00
if ( grp -> GetLeaderGUID () == plrg -> GetGUID ())
2010-05-31 20:25:21 +02:00
session -> SendLfgJoinResult ( LFG_JOIN_FAILED , pRoleCheck -> result );
session -> SendLfgUpdateParty ( LFG_UPDATETYPE_ROLECHECK_FAILED );
2010-08-11 11:54:03 +02:00
plrg -> GetLfgDungeons () -> clear ();
2010-09-26 13:59:51 +02:00
if ( grp -> isLFGGroup ())
plrg -> SetLfgRoles ( ROLE_NONE );
2010-09-26 15:13:21 +02:00
plrg -> SetLfgState ( LFG_STATE_NONE );
2010-05-31 20:25:21 +02:00
break ;
}
}
2010-09-08 13:19:05 +02:00
if ( pRoleCheck -> result == LFG_ROLECHECK_FINISHED && pRoleCheck -> dungeons . size ())
2010-08-11 15:20:20 +02:00
{
grp -> SetLfgQueued ( true );
2010-11-22 14:20:48 +01:00
LfgQueueInfo * pqInfo = new LfgQueueInfo ();
pqInfo -> joinTime = time_t ( time ( NULL ));
for ( LfgRolesMap :: const_iterator it = check_roles . begin (); it != check_roles . end (); ++ it )
{
if ( pqInfo -> tanks && it -> second & ROLE_TANK )
-- pqInfo -> tanks ;
else if ( pqInfo -> healers && it -> second & ROLE_HEALER )
-- pqInfo -> healers ;
else
-- pqInfo -> dps ;
}
for ( LfgRolesMap :: const_iterator itRoles = pRoleCheck -> roles . begin (); itRoles != pRoleCheck -> roles . end (); ++ itRoles )
pqInfo -> roles [ itRoles -> first ] = itRoles -> second ;
for ( LfgDungeonSet :: const_iterator it = pRoleCheck -> dungeons . begin (); it != pRoleCheck -> dungeons . end (); ++ it )
pqInfo -> dungeons . insert ( * it );
m_QueueInfoMap [ grp -> GetGUID ()] = pqInfo ;
AddGuidToNewQueue ( grp -> GetGUID ());
2010-08-11 15:20:20 +02:00
}
2010-05-31 20:25:21 +02:00
if ( pRoleCheck -> result != LFG_ROLECHECK_INITIALITING )
{
2010-08-11 12:44:49 +02:00
pRoleCheck -> dungeons . clear ();
pRoleCheck -> roles . clear ();
2010-06-02 17:03:48 +02:00
delete pRoleCheck ;
2010-11-26 04:43:07 +01:00
m_RoleChecks . erase ( itRoleCheck );
2010-05-31 20:25:21 +02:00
}
}
2010-09-05 22:05:14 +02:00
/// <summary>
/// Remove from cached compatible dungeons any entry that contains the given guid
/// </summary>
/// <param name="uint64">guid to remove from any list</param>
void LFGMgr :: RemoveFromCompatibles ( uint64 guid )
{
LfgGuidList lista ;
lista . push_back ( guid );
std :: string strGuid = ConcatenateGuids ( lista );
lista . clear ();
2010-09-08 13:44:57 +02:00
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::RemoveFromCompatibles: Removing [" UI64FMTD "]" , guid );
2010-09-05 22:05:14 +02:00
LfgCompatibleMap :: iterator it ;
for ( LfgCompatibleMap :: iterator itNext = m_CompatibleMap . begin (); itNext != m_CompatibleMap . end ();)
{
it = itNext ++ ;
if ( it -> first . find ( strGuid ) != std :: string :: npos ) // Found, remove it
m_CompatibleMap . erase ( it );
}
}
/// <summary>
/// Set the compatibility of a list of guids
/// </summary>
/// <param name="std::string">list of guids concatenated by |</param>
/// <param name="bool">compatibles or not</param>
void LFGMgr :: SetCompatibles ( std :: string key , bool compatibles )
{
m_CompatibleMap [ key ] = LfgAnswer ( compatibles );
}
/// <summary>
/// Get the compatible dungeons between two groups from cache
/// </summary>
/// <param name="std::string">list of guids concatenated by |</param>
2010-09-12 01:40:27 +02:00
/// <returns>LfgAnswer,
2010-09-05 22:05:14 +02:00
LfgAnswer LFGMgr :: GetCompatibles ( std :: string key )
{
LfgAnswer answer = LFG_ANSWER_PENDING ;
LfgCompatibleMap :: iterator it = m_CompatibleMap . find ( key );
if ( it != m_CompatibleMap . end ())
answer = it -> second ;
return answer ;
}
2010-09-08 13:19:05 +02:00
/// <summary>
/// Given a list of dungeons remove the dungeons with restrictions.
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="LfgDungeonSet*">dungeons to check</param>
/// <param name="PlayerSet*">Players to check restrictions</param>
/// <param name="LfgLockStatusMap*">Used to return the lockStatusMap</param>
2010-09-08 13:19:05 +02:00
/// <param name="boot">Return lockMap or discard it</param>
/// <returns>LfgLockStatusMap*</returns>
2010-09-20 14:06:21 +02:00
LfgLockStatusMap * LFGMgr :: CheckCompatibleDungeons ( LfgDungeonSet * dungeons , PlayerSet * players , bool returnLockMap /* = true */ )
2010-09-08 13:19:05 +02:00
{
if ( ! dungeons )
return NULL ;
2010-09-20 14:06:21 +02:00
LfgLockStatusMap * pLockDungeons = GetGroupLockStatusDungeons ( players , dungeons , false );
2010-09-08 13:19:05 +02:00
if ( pLockDungeons ) // Found dungeons not compatible, remove them from the set
{
for ( LfgLockStatusMap :: const_iterator itLockMap = pLockDungeons -> begin (); itLockMap != pLockDungeons -> end () && dungeons -> size (); ++ itLockMap )
{
for ( LfgLockStatusSet :: const_iterator itLockSet = itLockMap -> second -> begin (); itLockSet != itLockMap -> second -> end (); ++ itLockSet )
{
LfgDungeonSet :: iterator itDungeon = dungeons -> find (( * itLockSet ) -> dungeon );
if ( itDungeon != dungeons -> end ())
dungeons -> erase ( itDungeon );
}
if ( ! returnLockMap )
{
itLockMap -> second -> clear ();
delete itLockMap -> second ;
}
}
if ( ! returnLockMap )
{
pLockDungeons -> clear ();
delete pLockDungeons ;
return NULL ;
}
}
return pLockDungeons ;
}
2010-09-05 22:05:14 +02:00
/// <summary>
/// Given a list of groups checks the compatible dungeons. If players is not null also check restictions
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="LfgDungeonMap*">dungeons to check</param>
/// <param name="PlayerSet*">Players to check restrictions</param>
2010-09-05 22:05:14 +02:00
/// <returns>LfgDungeonSet*</returns>
2010-09-20 14:06:21 +02:00
LfgDungeonSet * LFGMgr :: CheckCompatibleDungeons ( LfgDungeonMap * dungeonsMap , PlayerSet * players )
2010-09-05 22:05:14 +02:00
{
if ( ! dungeonsMap || dungeonsMap -> empty ())
return NULL ;
LfgDungeonMap :: const_iterator itMap = ++ dungeonsMap -> begin ();
2010-09-20 14:06:21 +02:00
LfgDungeonSet * compatibleDungeons = new LfgDungeonSet ();
2010-09-08 13:44:57 +02:00
2010-09-05 22:05:14 +02:00
bool compatibleDungeon ;
// Get the first group and compare with the others to select all common dungeons
for ( LfgDungeonSet :: const_iterator itDungeon = dungeonsMap -> begin () -> second -> begin (); itDungeon != dungeonsMap -> begin () -> second -> end (); ++ itDungeon )
{
compatibleDungeon = true ;
for ( LfgDungeonMap :: const_iterator it = itMap ; it != dungeonsMap -> end () && compatibleDungeon ; ++ it )
if ( it -> second -> find ( * itDungeon ) == it -> second -> end ())
compatibleDungeon = false ;
if ( compatibleDungeon )
compatibleDungeons -> insert ( * itDungeon );
}
2010-09-08 13:19:05 +02:00
// if we have players remove restrictions
2010-09-05 22:05:14 +02:00
if ( players && ! players -> empty ())
2010-09-09 14:49:52 +02:00
CheckCompatibleDungeons ( compatibleDungeons , players , false );
2010-09-05 22:05:14 +02:00
// Any compatible dungeon after checking restrictions?
2010-09-08 13:19:05 +02:00
if ( compatibleDungeons && ! compatibleDungeons -> size ())
2010-09-05 22:05:14 +02:00
{
delete compatibleDungeons ;
compatibleDungeons = NULL ;
}
return compatibleDungeons ;
}
2010-05-31 20:25:21 +02:00
/// <summary>
/// Check if a group can be formed with the given group
/// </summary>
2010-08-11 11:27:36 +02:00
/// <param name="LfgRolesMap &">Roles to check</param>
/// <param name="bool">Used to remove ROLE_LEADER</param>
2010-05-31 20:25:21 +02:00
/// <returns>bool</returns>
2010-06-04 22:26:59 +02:00
bool LFGMgr :: CheckGroupRoles ( LfgRolesMap & groles , bool removeLeaderFlag /*= true*/ )
2010-05-31 20:25:21 +02:00
{
if ( ! groles . size ())
return false ;
uint8 damage = 0 ;
uint8 tank = 0 ;
uint8 healer = 0 ;
2010-06-04 22:26:59 +02:00
if ( removeLeaderFlag )
for ( LfgRolesMap :: iterator it = groles . begin (); it != groles . end (); ++ it )
it -> second &= ~ ROLE_LEADER ;
2010-08-11 11:27:36 +02:00
for ( LfgRolesMap :: iterator it = groles . begin (); it != groles . end (); ++ it )
2010-05-31 20:25:21 +02:00
{
2010-11-23 15:01:15 +01:00
if ( it -> second == ROLE_NONE )
2010-08-11 11:27:36 +02:00
return false ;
2010-11-23 15:01:15 +01:00
if ( it -> second & ROLE_TANK )
{
if ( tank == LFG_TANKS_NEEDED )
2010-08-11 11:27:36 +02:00
return false ;
2010-11-23 15:01:15 +01:00
if ( it -> second != ROLE_TANK )
2010-05-31 20:25:21 +02:00
{
2010-08-11 11:27:36 +02:00
it -> second -= ROLE_TANK ;
if ( CheckGroupRoles ( groles , false ))
return true ;
it -> second += ROLE_TANK ;
2010-05-31 20:25:21 +02:00
}
2010-11-23 15:01:15 +01:00
else
tank ++ ;
}
2010-05-31 20:25:21 +02:00
2010-11-23 15:01:15 +01:00
if ( it -> second & ROLE_HEALER )
{
if ( healer == LFG_HEALERS_NEEDED )
return false ;
if ( it -> second != ROLE_HEALER )
2010-05-31 20:25:21 +02:00
{
2010-08-11 11:27:36 +02:00
it -> second -= ROLE_HEALER ;
if ( CheckGroupRoles ( groles , false ))
return true ;
it -> second += ROLE_HEALER ;
2010-05-31 20:25:21 +02:00
}
2010-11-23 15:01:15 +01:00
else
healer ++ ;
}
if ( it -> second & ROLE_DAMAGE )
{
if ( damage == LFG_DPS_NEEDED )
return false ;
2010-05-31 20:25:21 +02:00
2010-11-23 15:01:15 +01:00
if ( it -> second != ROLE_DAMAGE )
2010-05-31 20:25:21 +02:00
{
2010-08-11 11:27:36 +02:00
it -> second -= ROLE_DAMAGE ;
2010-11-23 15:01:15 +01:00
if ( CheckGroupRoles ( groles , false ))
return true ;
it -> second += ROLE_DAMAGE ;
2010-05-31 20:25:21 +02:00
}
2010-11-23 15:01:15 +01:00
else
damage ++ ;
2010-06-04 22:26:59 +02:00
}
2010-05-31 20:25:21 +02:00
}
2010-11-24 15:37:03 +01:00
return ( tank + healer + damage ) == uint8 ( groles . size ());
2010-05-20 23:35:27 +02:00
}
2010-08-11 15:55:27 +02:00
/// <summary>
/// Update Proposal info with player answer
/// </summary>
/// <param name="uint32">Id of the proposal</param>
/// <param name="uint32">Player low guid</param>
2010-09-05 21:29:52 +02:00
/// <param name="bool">Player answer</param>
void LFGMgr :: UpdateProposal ( uint32 proposalId , uint32 lowGuid , bool accept )
2010-08-11 15:55:27 +02:00
{
// Check if the proposal exists
LfgProposalMap :: iterator itProposal = m_Proposals . find ( proposalId );
if ( itProposal == m_Proposals . end ())
return ;
2010-09-20 14:06:21 +02:00
LfgProposal * pProposal = itProposal -> second ;
2010-08-11 15:55:27 +02:00
// Check if proposal have the current player
2010-08-18 22:32:11 +02:00
LfgProposalPlayerMap :: iterator itProposalPlayer = pProposal -> players . find ( lowGuid );
if ( itProposalPlayer == pProposal -> players . end ())
2010-08-11 15:55:27 +02:00
return ;
2010-09-20 14:06:21 +02:00
LfgProposalPlayer * ppPlayer = itProposalPlayer -> second ;
2010-08-11 15:55:27 +02:00
2010-09-05 21:29:52 +02:00
ppPlayer -> accept = LfgAnswer ( accept );
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::UpdateProposal: Player [" UI64FMTD "] of proposal %u selected: %u" , MAKE_NEW_GUID ( lowGuid , 0 , HIGHGUID_PLAYER ), proposalId , accept );
2010-08-11 15:55:27 +02:00
if ( ! accept )
{
RemoveProposal ( itProposal , LFG_UPDATETYPE_PROPOSAL_DECLINED );
return ;
}
LfgPlayerList players ;
2010-09-20 14:06:21 +02:00
Player * plr ;
2010-08-11 15:55:27 +02:00
// 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 )
{
2010-09-13 09:20:07 +02:00
plr = sObjectMgr . GetPlayerByLowGUID ( itPlayers -> first );
2010-08-11 15:55:27 +02:00
2010-08-18 22:32:11 +02:00
if ( plr )
{
if ( itPlayers -> first == pProposal -> leaderLowGuid )
players . push_front ( plr );
else
players . push_back ( plr );
}
2010-08-11 15:55:27 +02:00
2010-10-25 07:16:46 +02:00
if ( itPlayers -> second -> accept != LFG_ANSWER_AGREE ) // No answer (-1) or not accepted (0)
2010-08-11 15:55:27 +02:00
allAnswered = false ;
}
if ( ! allAnswered )
{
for ( LfgPlayerList :: const_iterator it = players . begin (); it != players . end (); ++ it )
2010-09-04 18:20:10 +02:00
( * it ) -> GetSession () -> SendUpdateProposal ( proposalId , pProposal );
2010-08-11 15:55:27 +02:00
}
else
{
2010-08-17 13:18:18 +02:00
bool sendUpdate = pProposal -> state != LFG_PROPOSAL_SUCCESS ;
2010-08-11 15:55:27 +02:00
pProposal -> state = LFG_PROPOSAL_SUCCESS ;
2010-08-18 00:30:17 +02:00
time_t joinTime = time_t ( time ( NULL ));
2010-09-14 20:04:00 +02:00
std :: map < uint64 , int32 > waitTimesMap ;
// Save wait times before redoing groups
for ( LfgPlayerList :: const_iterator it = players . begin (); it != players . end (); ++ it )
{
2010-09-20 14:06:21 +02:00
LfgProposalPlayer * pPlayer = pProposal -> players [( * it ) -> GetGUIDLow ()];
2010-09-16 18:54:00 +02:00
uint32 lowgroupguid = ( * it ) -> GetGroup () ? ( * it ) -> GetGroup () -> GetLowGUID () : 0 ;
if ( pPlayer -> groupLowGuid != lowgroupguid )
sLog . outError ( "LFGMgr::UpdateProposal: [" UI64FMTD "] group mismatch: actual (%u) - queued (%u)" , ( * it ) -> GetGUID (), lowgroupguid , pPlayer -> groupLowGuid );
uint64 guid = pPlayer -> groupLowGuid ? MAKE_NEW_GUID ( pPlayer -> groupLowGuid , 0 , HIGHGUID_GROUP ) : ( * it ) -> GetGUID ();
2010-09-14 20:04:00 +02:00
LfgQueueInfoMap :: iterator itQueue = m_QueueInfoMap . find ( guid );
if ( itQueue == m_QueueInfoMap . end ())
{
sLog . outError ( "LFGMgr::UpdateProposal: Queue info for guid [" UI64FMTD "] not found!" , guid );
waitTimesMap [( * it ) -> GetGUID ()] = - 1 ;
}
else
waitTimesMap [( * it ) -> GetGUID ()] = int32 ( joinTime - itQueue -> second -> joinTime );
}
2010-08-11 15:55:27 +02:00
// Create a new group (if needed)
2010-09-20 14:06:21 +02:00
Group * grp = sObjectMgr . GetGroupByGUID ( pProposal -> groupLowGuid );
2010-08-11 15:55:27 +02:00
for ( LfgPlayerList :: const_iterator it = players . begin (); it != players . end (); ++ it )
{
2010-09-20 14:06:21 +02:00
plr = ( * it );
2010-08-17 13:18:18 +02:00
if ( sendUpdate )
2010-09-04 18:20:10 +02:00
plr -> GetSession () -> SendUpdateProposal ( proposalId , pProposal );
2010-08-11 15:55:27 +02:00
if ( plr -> GetGroup ())
2010-10-25 12:21:42 +02:00
{
2010-08-18 00:30:17 +02:00
plr -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_GROUP_FOUND );
2010-10-25 12:21:42 +02:00
plr -> SetLfgUpdate ( false );
if ( plr -> GetGroup () != grp )
{
plr -> GetGroup () -> SetLfgQueued ( false );
plr -> RemoveFromGroup ();
}
}
2010-08-11 15:55:27 +02:00
else
2010-10-25 11:26:22 +02:00
{
2010-10-25 12:21:42 +02:00
plr -> GetSession () -> SendLfgUpdatePlayer ( LFG_UPDATETYPE_GROUP_FOUND );
plr -> SetLfgUpdate ( false );
2010-10-25 11:26:22 +02:00
}
2010-08-11 15:55:27 +02:00
if ( ! grp )
{
grp = new Group ();
grp -> Create ( plr -> GetGUID (), plr -> GetName ());
grp -> ConvertToLFG ();
sObjectMgr . AddGroup ( grp );
}
else if ( plr -> GetGroup () != grp )
2010-09-06 03:03:21 +02:00
{
grp -> SetLfgQueued ( false );
2010-08-11 15:55:27 +02:00
grp -> AddMember ( plr -> GetGUID (), plr -> GetName ());
2010-09-06 03:03:21 +02:00
}
2010-08-18 00:30:17 +02:00
plr -> SetLfgUpdate ( true );
2010-09-14 20:04:00 +02:00
2010-08-18 00:30:17 +02:00
// Update timers
2010-09-14 20:04:00 +02:00
uint8 role = plr -> GetLfgRoles ();
if ( role & ROLE_TANK )
2010-08-18 00:30:17 +02:00
{
2010-09-14 20:04:00 +02:00
if ( role & ROLE_HEALER || role & ROLE_DAMAGE )
m_WaitTimeAvg = int32 (( m_WaitTimeAvg * m_NumWaitTimeAvg + waitTimesMap [ plr -> GetGUID ()]) / ++ m_NumWaitTimeAvg );
else
m_WaitTimeTank = int32 (( m_WaitTimeTank * m_NumWaitTimeTank + waitTimesMap [ plr -> GetGUID ()]) / ++ m_NumWaitTimeTank );
2010-08-18 00:30:17 +02:00
}
2010-09-14 20:04:00 +02:00
else if ( role & ROLE_HEALER )
2010-08-18 00:30:17 +02:00
{
2010-09-14 20:04:00 +02:00
if ( role & ROLE_DAMAGE )
m_WaitTimeAvg = int32 (( m_WaitTimeAvg * m_NumWaitTimeAvg + waitTimesMap [ plr -> GetGUID ()]) / ++ m_NumWaitTimeAvg );
else
m_WaitTimeHealer = int32 (( m_WaitTimeHealer * m_NumWaitTimeHealer + waitTimesMap [ plr -> GetGUID ()]) / ++ m_NumWaitTimeHealer );
2010-08-18 00:30:17 +02:00
}
2010-09-14 20:04:00 +02:00
else if ( role & ROLE_DAMAGE )
m_WaitTimeDps = int32 (( m_WaitTimeDps * m_NumWaitTimeDps + waitTimesMap [ plr -> GetGUID ()]) / ++ m_NumWaitTimeDps );
2010-08-24 10:32:53 +02:00
2010-08-11 15:55:27 +02:00
grp -> SetLfgRoles ( plr -> GetGUID (), pProposal -> players [ plr -> GetGUIDLow ()] -> role );
}
// Set the dungeon difficulty
2010-09-20 14:06:21 +02:00
LFGDungeonEntry const * dungeon = sLFGDungeonStore . LookupEntry ( pProposal -> dungeonId );
2010-08-11 15:55:27 +02:00
ASSERT ( dungeon );
grp -> SetDungeonDifficulty ( Difficulty ( dungeon -> difficulty ));
grp -> SetLfgDungeonEntry ( dungeon -> Entry ());
grp -> SetLfgStatus ( LFG_STATUS_NOT_SAVED );
// Remove players/groups from Queue
for ( LfgGuidList :: const_iterator it = pProposal -> queues . begin (); it != pProposal -> queues . end (); ++ it )
RemoveFromQueue ( * it );
// Teleport Player
for ( LfgPlayerList :: const_iterator it = players . begin (); it != players . end (); ++ it )
TeleportPlayer ( * it , false );
2010-11-03 14:21:59 +01:00
// Update group info
grp -> SendUpdate ();
2010-08-11 15:55:27 +02:00
for ( LfgProposalPlayerMap :: const_iterator it = pProposal -> players . begin (); it != pProposal -> players . end (); ++ it )
delete it -> second ;
pProposal -> players . clear ();
pProposal -> queues . clear ();
delete pProposal ;
m_Proposals . erase ( itProposal );
}
players . clear ();
}
/// <summary>
/// Remove a proposal from the pool, remove the group that didn't accept (if needed) and readd the other members to the queue
/// </summary>
/// <param name="LfgProposalMap::iterator">Proposal to remove</param>
/// <param name="LfgUpdateType">Type of removal (LFG_UPDATETYPE_PROPOSAL_FAILED, LFG_UPDATETYPE_PROPOSAL_DECLINED)</param>
void LFGMgr :: RemoveProposal ( LfgProposalMap :: iterator itProposal , LfgUpdateType type )
{
2010-09-20 14:06:21 +02:00
Player * plr ;
2010-08-11 15:55:27 +02:00
uint64 guid ;
LfgUpdateType updateType ;
LfgQueueInfoMap :: iterator itQueue ;
2010-09-20 14:06:21 +02:00
LfgProposal * pProposal = itProposal -> second ;
2010-08-11 15:55:27 +02:00
pProposal -> state = LFG_PROPOSAL_FAILED ;
2010-10-06 17:26:12 +02:00
sLog . outDebug ( "LFGMgr::RemoveProposal: Proposal %u, state FAILED, UpdateType %u" , itProposal -> first , type );
2010-08-11 15:55:27 +02:00
// Mark all people that didn't answered as no accept
2010-08-14 02:08:00 +02:00
if ( type == LFG_UPDATETYPE_PROPOSAL_FAILED )
2010-08-11 15:55:27 +02:00
for ( LfgProposalPlayerMap :: const_iterator it = pProposal -> players . begin (); it != pProposal -> players . end (); ++ it )
2010-09-05 21:29:52 +02:00
if ( it -> second -> accept != LFG_ANSWER_AGREE )
it -> second -> accept = LFG_ANSWER_DENY ;
2010-08-11 15:55:27 +02:00
2010-11-26 04:44:57 +01:00
// Remove from queue all players/groups that didn't accept
for ( LfgProposalPlayerMap :: const_iterator it = pProposal -> players . begin (); it != pProposal -> players . end (); ++ it )
if ( it -> second -> accept == LFG_ANSWER_DENY )
RemoveFromQueue ( it -> second -> groupLowGuid ? MAKE_NEW_GUID ( it -> second -> groupLowGuid , 0 , HIGHGUID_GROUP ) : MAKE_NEW_GUID ( it -> first , 0 , HIGHGUID_PLAYER ));
2010-08-11 15:55:27 +02:00
// Inform players
for ( LfgProposalPlayerMap :: const_iterator it = pProposal -> players . begin (); it != pProposal -> players . end (); ++ it )
{
2010-09-13 09:20:07 +02:00
plr = sObjectMgr . GetPlayerByLowGUID ( it -> first );
2010-08-11 15:55:27 +02:00
if ( ! plr )
continue ;
2010-11-26 04:44:57 +01:00
plr -> GetSession () -> SendUpdateProposal ( itProposal -> first , pProposal );
2010-09-16 18:55:24 +02:00
guid = it -> second -> groupLowGuid ? MAKE_NEW_GUID ( it -> second -> groupLowGuid , 0 , HIGHGUID_GROUP ) : plr -> GetGUID ();
2010-08-11 15:55:27 +02:00
2010-11-26 04:44:57 +01:00
itQueue = m_QueueInfoMap . find ( guid );
if ( itQueue == m_QueueInfoMap . end ()) // Didn't accept or in same group that someone that didn't accept
2010-08-11 15:55:27 +02:00
{
2010-11-26 04:44:57 +01:00
if ( it -> second -> accept == LFG_ANSWER_DENY )
{
updateType = type ;
sLog . outDebug ( "LFGMgr::RemoveProposal: [" UI64FMTD "] didn't accept. Removing from queue and compatible cache" , guid );
}
else
{
updateType = LFG_UPDATETYPE_REMOVED_FROM_QUEUE ;
sLog . outDebug ( "LFGMgr::RemoveProposal: [" UI64FMTD "] in same group that someone that didn't accept. Removing from queue and compatible cache" , guid );
}
2010-08-11 15:55:27 +02:00
plr -> GetLfgDungeons () -> clear ();
plr -> SetLfgRoles ( ROLE_NONE );
2010-09-26 13:59:51 +02:00
if ( ! plr -> GetGroup () || ! plr -> GetGroup () -> isLFGGroup ())
plr -> SetLfgState ( LFG_STATE_NONE );
2010-08-24 10:32:53 +02:00
2010-11-26 04:44:57 +01:00
if ( plr -> GetGroup ())
plr -> GetSession () -> SendLfgUpdateParty ( updateType );
else
plr -> GetSession () -> SendLfgUpdatePlayer ( updateType );
2010-08-11 15:55:27 +02:00
}
2010-11-26 04:44:57 +01:00
else
2010-08-11 15:55:27 +02:00
{
2010-11-26 04:44:57 +01:00
sLog . outDebug ( "LFGMgr::RemoveProposal: Readding [" UI64FMTD "] to queue." , guid );
itQueue -> second -> joinTime = time_t ( time ( NULL ));
AddGuidToNewQueue ( guid );
if ( plr -> GetGroup ())
plr -> GetSession () -> SendLfgUpdateParty ( LFG_UPDATETYPE_ADDED_TO_QUEUE , plr -> GetLfgDungeons (), plr -> GetLfgComment ());
2010-08-14 02:05:05 +02:00
else
2010-11-26 04:44:57 +01:00
plr -> GetSession () -> SendLfgUpdatePlayer ( LFG_UPDATETYPE_ADDED_TO_QUEUE , plr -> GetLfgDungeons (), plr -> GetLfgComment ());
2010-08-11 15:55:27 +02:00
}
}
for ( LfgProposalPlayerMap :: const_iterator it = pProposal -> players . begin (); it != pProposal -> players . end (); ++ it )
delete it -> second ;
pProposal -> players . clear ();
pProposal -> queues . clear ();
delete pProposal ;
m_Proposals . erase ( itProposal );
}
2010-08-13 15:38:10 +02:00
/// <summary>
/// Initialize a boot kick vote
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Group*">Group</param>
2010-08-13 15:38:10 +02:00
/// <param name="uint32">Player low guid who inits the vote kick</param>
/// <param name="uint32">Player low guid to be kicked </param>
/// <param name="std::string">kick reason</param>
2010-09-20 14:06:21 +02:00
void LFGMgr :: InitBoot ( Group * grp , uint32 iLowGuid , uint32 vLowguid , std :: string reason )
2010-08-13 15:38:10 +02:00
{
if ( ! grp )
return ;
2010-09-20 14:06:21 +02:00
LfgPlayerBoot * pBoot = new LfgPlayerBoot ();
2010-08-13 15:38:10 +02:00
pBoot -> inProgress = true ;
pBoot -> cancelTime = time_t ( time ( NULL )) + LFG_TIME_BOOT ;
pBoot -> reason = reason ;
pBoot -> victimLowGuid = vLowguid ;
pBoot -> votedNeeded = GROUP_LFG_KICK_VOTES_NEEDED ;
PlayerSet players ;
uint32 pLowGuid = 0 ;
2010-09-20 14:06:21 +02:00
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
2010-08-13 15:38:10 +02:00
{
2010-09-20 14:06:21 +02:00
if ( Player * plrg = itr -> getSource ())
2010-08-13 15:38:10 +02:00
{
pLowGuid = plrg -> GetGUIDLow ();
if ( pLowGuid == vLowguid )
2010-10-25 07:16:46 +02:00
pBoot -> votes [ pLowGuid ] = LFG_ANSWER_DENY ; // Victim auto vote NO
2010-08-13 15:38:10 +02:00
else if ( pLowGuid == iLowGuid )
2010-10-25 07:16:46 +02:00
pBoot -> votes [ pLowGuid ] = LFG_ANSWER_AGREE ; // Kicker auto vote YES
2010-08-13 15:38:10 +02:00
else
{
2010-10-25 07:16:46 +02:00
pBoot -> votes [ pLowGuid ] = LFG_ANSWER_PENDING ; // Other members need to vote
2010-08-13 15:38:10 +02:00
players . insert ( plrg );
}
}
}
for ( PlayerSet :: const_iterator it = players . begin (); it != players . end (); ++ it )
2010-09-04 18:20:10 +02:00
( * it ) -> GetSession () -> SendLfgBootPlayer ( pBoot );
2010-08-13 15:38:10 +02:00
grp -> SetLfgKickActive ( true );
m_Boots [ grp -> GetLowGUID ()] = pBoot ;
}
/// <summary>
/// Update Boot info with player answer
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Player*">Player guid</param>
2010-09-05 21:29:52 +02:00
/// <param name="bool">Player answer</param>
2010-09-20 14:06:21 +02:00
void LFGMgr :: UpdateBoot ( Player * plr , bool accept )
2010-08-13 15:38:10 +02:00
{
2010-09-20 14:06:21 +02:00
Group * grp = plr ? plr -> GetGroup () : NULL ;
2010-08-13 15:38:10 +02:00
if ( ! grp )
return ;
uint32 bootId = grp -> GetLowGUID ();
uint32 lowGuid = plr -> GetGUIDLow ();
LfgPlayerBootMap :: iterator itBoot = m_Boots . find ( bootId );
if ( itBoot == m_Boots . end ())
return ;
2010-09-20 14:06:21 +02:00
LfgPlayerBoot * pBoot = itBoot -> second ;
2010-08-13 15:38:10 +02:00
if ( ! pBoot )
return ;
2010-10-25 07:16:46 +02:00
if ( pBoot -> votes [ lowGuid ] != LFG_ANSWER_PENDING ) // Cheat check: Player can't vote twice
2010-08-13 15:38:10 +02:00
return ;
2010-09-05 21:29:52 +02:00
pBoot -> votes [ lowGuid ] = LfgAnswer ( accept );
2010-08-13 15:38:10 +02:00
uint8 votesNum = 0 ;
uint8 agreeNum = 0 ;
for ( LfgAnswerMap :: const_iterator itVotes = pBoot -> votes . begin (); itVotes != pBoot -> votes . end (); ++ itVotes )
{
2010-09-05 21:29:52 +02:00
if ( itVotes -> second != LFG_ANSWER_PENDING )
2010-08-13 15:38:10 +02:00
{
++ votesNum ;
2010-09-05 21:29:52 +02:00
if ( itVotes -> second == LFG_ANSWER_AGREE )
2010-08-13 15:38:10 +02:00
++ agreeNum ;
}
}
2010-10-25 07:16:46 +02:00
if ( agreeNum == pBoot -> votedNeeded || // Vote passed
votesNum == pBoot -> votes . size () || // All voted but not passed
2010-08-13 15:38:10 +02:00
( pBoot -> votes . size () - votesNum + agreeNum ) < pBoot -> votedNeeded ) // Vote didnt passed
{
// Send update info to all players
pBoot -> inProgress = false ;
for ( LfgAnswerMap :: const_iterator itVotes = pBoot -> votes . begin (); itVotes != pBoot -> votes . end (); ++ itVotes )
2010-09-20 14:06:21 +02:00
if ( Player * plrg = sObjectMgr . GetPlayerByLowGUID ( itVotes -> first ))
2010-08-13 15:38:10 +02:00
if ( plrg -> GetGUIDLow () != pBoot -> victimLowGuid )
2010-09-04 18:20:10 +02:00
plrg -> GetSession () -> SendLfgBootPlayer ( pBoot );
2010-08-13 15:38:10 +02:00
2010-10-25 07:16:46 +02:00
if ( agreeNum == pBoot -> votedNeeded ) // Vote passed - Kick player
2010-08-13 15:38:10 +02:00
{
Player :: RemoveFromGroup ( grp , MAKE_NEW_GUID ( pBoot -> victimLowGuid , 0 , HIGHGUID_PLAYER ));
2010-09-20 14:06:21 +02:00
if ( Player * victim = sObjectMgr . GetPlayerByLowGUID ( pBoot -> victimLowGuid ))
2010-10-19 12:39:24 +02:00
TeleportPlayer ( victim , true , false );
2010-08-13 15:38:10 +02:00
OfferContinue ( grp );
grp -> SetLfgKicks ( grp -> GetLfgKicks () + 1 );
}
grp -> SetLfgKickActive ( false );
delete pBoot ;
m_Boots . erase ( itBoot );
}
}
2010-08-11 15:55:27 +02:00
/// <summary>
/// Teleports the player in or out the dungeon
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Player*">Player</param>
2010-08-11 15:55:27 +02:00
/// <param name="bool">Teleport out</param>
2010-10-06 15:52:39 +02:00
/// <param name="bool">Automatic or manual teleport</param>
void LFGMgr :: TeleportPlayer ( Player * plr , bool out , bool fromOpcode /*= false*/ )
2010-08-11 15:55:27 +02:00
{
2010-10-06 18:48:39 +02:00
sLog . outDebug ( "LFGMgr::TeleportPlayer: [" UI64FMTD "] is being teleported %s" , plr -> GetGUID (), out ? "out" : "in" );
2010-08-11 15:55:27 +02:00
if ( out )
{
2010-09-26 14:49:55 +02:00
plr -> RemoveAurasDueToSpell ( LFG_SPELL_LUCK_OF_THE_DRAW );
2010-08-11 15:55:27 +02:00
plr -> TeleportToBGEntryPoint ();
return ;
}
2010-10-06 15:52:39 +02:00
// TODO Add support for LFG_TELEPORTERROR_FATIGUE
LfgTeleportError error = LFG_TELEPORTERROR_OK ;
Group * grp = plr -> GetGroup ();
2010-08-11 15:55:27 +02:00
2010-10-25 07:16:46 +02:00
if ( ! grp || ! grp -> isLFGGroup ()) // should never happen, but just in case...
2010-10-06 15:52:39 +02:00
error = LFG_TELEPORTERROR_INVALID_LOCATION ;
else if ( ! plr -> isAlive ())
error = LFG_TELEPORTERROR_PLAYER_DEAD ;
else if ( plr -> IsFalling () || plr -> hasUnitState ( UNIT_STAT_JUMPING ))
error = LFG_TELEPORTERROR_FALLING ;
else
2010-08-11 15:55:27 +02:00
{
2010-10-06 15:52:39 +02:00
LFGDungeonEntry const * dungeon = sLFGDungeonStore . LookupEntry ( grp -> GetLfgDungeonEntry ());
2010-08-11 15:55:27 +02:00
2010-10-06 15:52:39 +02:00
if ( ! dungeon )
error = LFG_TELEPORTERROR_INVALID_LOCATION ;
else if ( plr -> GetMapId () != uint32 ( dungeon -> map )) // Do not teleport players in dungeon to the entrance
{
uint32 mapid = 0 ;
float x = 0 ;
float y = 0 ;
float z = 0 ;
float orientation = 0 ;
if ( ! fromOpcode )
{
Player * plrg ;
// Select a player inside to be teleported to
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL && ! mapid ; itr = itr -> next ())
{
plrg = itr -> getSource ();
if ( plrg && plrg != plr && plrg -> GetMapId () == uint32 ( dungeon -> map ))
{
mapid = plrg -> GetMapId ();
x = plrg -> GetPositionX ();
y = plrg -> GetPositionY ();
z = plrg -> GetPositionZ ();
orientation = plrg -> GetOrientation ();
}
}
}
if ( ! mapid )
{
AreaTrigger const * at = sObjectMgr . GetMapEntranceTrigger ( dungeon -> map );
if ( ! at )
2010-10-06 17:31:54 +02:00
{
sLog . outError ( "LfgMgr::TeleportPlayer: Failed to teleport [" UI64FMTD "]: No areatrigger found for map: %u difficulty: %u" , plr -> GetGUID (), dungeon -> map , dungeon -> difficulty );
2010-10-06 15:52:39 +02:00
error = LFG_TELEPORTERROR_INVALID_LOCATION ;
2010-10-06 17:31:54 +02:00
}
2010-10-06 15:52:39 +02:00
else
{
mapid = at -> target_mapId ;
x = at -> target_X ;
y = at -> target_Y ;
z = at -> target_Z ;
orientation = at -> target_Orientation ;
}
}
2010-10-07 14:00:52 +02:00
2010-10-06 15:52:39 +02:00
if ( error == LFG_TELEPORTERROR_OK )
2010-08-11 15:55:27 +02:00
{
if ( ! plr -> GetMap () -> IsDungeon () && ! plr -> GetMap () -> IsRaid ())
plr -> SetBattlegroundEntryPoint ();
2010-10-06 15:52:39 +02:00
2010-10-19 12:39:03 +02:00
if ( plr -> isInFlight ())
{
plr -> GetMotionMaster () -> MovementExpired ();
plr -> CleanupAfterTaxiFlight ();
}
2010-10-06 15:52:39 +02:00
if ( plr -> TeleportTo ( mapid , x , y , z , orientation ))
plr -> RemoveAurasByType ( SPELL_AURA_MOUNTED );
2010-09-26 14:49:55 +02:00
else
2010-10-06 15:52:39 +02:00
{
error = LFG_TELEPORTERROR_INVALID_LOCATION ;
2010-10-06 17:31:54 +02:00
sLog . outError ( "LfgMgr::TeleportPlayer: Failed to teleport [" UI64FMTD "] to map %u: " , plr -> GetGUID (), mapid );
2010-10-06 15:52:39 +02:00
}
2010-08-11 15:55:27 +02:00
}
2010-10-06 15:52:39 +02:00
}
}
if ( error != LFG_TELEPORTERROR_OK )
plr -> GetSession () -> SendLfgTeleportError ( error );
2010-08-11 15:55:27 +02:00
}
2010-09-03 20:25:03 +02:00
/// <summary>
/// Give completion reward to player
/// </summary>
/// <param name="const uint32">dungeonId</param>
2010-09-20 14:06:21 +02:00
/// <param name="Player*">player</param>
2010-11-22 10:19:54 +01:00
void LFGMgr :: RewardDungeonDoneFor ( const uint32 /*dungeonId*/ , Player * player )
2010-09-03 20:25:03 +02:00
{
Group * group = player -> GetGroup ();
2010-11-22 10:19:54 +01:00
if ( ! group || ! group -> isLFGGroup () || ! sWorld . getBoolConfig ( CONFIG_DUNGEON_FINDER_ENABLE ))
2010-09-03 20:25:03 +02:00
return ;
2010-09-04 15:40:43 +02:00
// Mark dungeon as finished
2010-09-03 20:25:03 +02:00
if ( ! group -> isLfgDungeonComplete ())
group -> SetLfgStatus ( LFG_STATUS_COMPLETE );
2010-09-04 15:40:43 +02:00
// Clear player related lfg stuff
2010-09-20 14:06:21 +02:00
uint32 rDungeonId = ( * player -> GetLfgDungeons () -> begin ());
2010-09-04 15:40:43 +02:00
player -> GetLfgDungeons () -> clear ();
player -> SetLfgRoles ( ROLE_NONE );
2010-09-08 13:44:57 +02:00
2010-09-04 15:40:43 +02:00
// Give rewards only if its a random dungeon
2010-11-22 10:19:54 +01:00
LFGDungeonEntry const * dungeon = sLFGDungeonStore . LookupEntry ( rDungeonId );
2010-09-04 15:40:43 +02:00
if ( ! dungeon || dungeon -> type != LFG_TYPE_RANDOM )
return ;
// Update achievements
if ( dungeon -> difficulty == DUNGEON_DIFFICULTY_HEROIC )
player -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS , 1 );
2010-09-03 20:25:03 +02:00
2010-09-04 15:40:43 +02:00
LfgReward const * reward = GetRandomDungeonReward ( rDungeonId , player -> getLevel ());
2010-09-03 20:25:03 +02:00
if ( ! reward )
return ;
2010-09-28 00:19:37 -03:00
uint8 index = 0 ;
2010-09-03 20:25:03 +02:00
Quest const * qReward = sObjectMgr . GetQuestTemplate ( reward -> reward [ index ]. questId );
if ( ! qReward )
return ;
2010-09-28 00:19:37 -03:00
// if we can take the quest, means that we haven't done this kind of "run", IE: First Heroic Random of Day.
if ( player -> CanRewardQuest ( qReward , false ))
player -> RewardQuest ( qReward , 0 , NULL , false );
else
2010-09-03 20:25:03 +02:00
{
2010-09-28 00:19:37 -03:00
index = 1 ;
qReward = sObjectMgr . GetQuestTemplate ( reward -> reward [ index ]. questId );
if ( ! qReward )
return ;
// we give reward without informing client (retail does this)
player -> RewardQuest ( qReward , 0 , NULL , false );
2010-09-03 20:25:03 +02:00
}
2010-09-28 00:19:37 -03:00
// Give rewards
2010-11-22 10:19:54 +01:00
sLog . outDebug ( "LFGMgr::RewardDungeonDoneFor: [" UI64FMTD "] done dungeon %u, %s previously done." , player -> GetGUID (), rDungeonId , index > 0 ? "" : "not " );
2010-09-28 00:19:37 -03:00
player -> GetSession () -> SendLfgPlayerReward ( dungeon -> Entry (), group -> GetLfgDungeonEntry ( false ), index , reward , qReward );
2010-09-03 20:25:03 +02:00
}
2010-05-20 23:35:27 +02:00
// --------------------------------------------------------------------------//
// Auxiliar Functions
// --------------------------------------------------------------------------//
2010-08-11 13:25:14 +02:00
/// <summary>
/// Given a group get the dungeons that can't be done and reason
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="PlayerSet*">Players to check lock status</param>
/// <param name="LfgDungeonSet*">Dungeons to check</param>
2010-09-06 04:42:02 +02:00
/// <param name="bool">Use dungeon entry (true) or id (false)</param>
2010-08-11 13:25:14 +02:00
/// <returns>LfgLockStatusMap*</returns>
2010-09-20 14:06:21 +02:00
LfgLockStatusMap * LFGMgr :: GetGroupLockStatusDungeons ( PlayerSet * pPlayers , LfgDungeonSet * dungeons , bool useEntry /* = true */ )
2010-08-11 13:25:14 +02:00
{
2010-08-13 08:06:04 +02:00
if ( ! pPlayers || ! dungeons )
return NULL ;
2010-08-11 13:25:14 +02:00
2010-09-20 14:06:21 +02:00
LfgLockStatusSet * dungeonSet = NULL ;
LfgLockStatusMap * dungeonMap = new LfgLockStatusMap ();
2010-08-11 13:25:14 +02:00
for ( PlayerSet :: const_iterator itr = pPlayers -> begin (); itr != pPlayers -> end (); ++ itr )
{
2010-09-06 04:42:02 +02:00
dungeonSet = GetPlayerLockStatusDungeons ( * itr , dungeons , useEntry );
2010-08-11 13:25:14 +02:00
if ( dungeonSet )
2010-08-27 19:27:50 +02:00
( * dungeonMap )[( * itr ) -> GetGUIDLow ()] = dungeonSet ;
2010-08-11 13:25:14 +02:00
}
if ( ! dungeonMap -> size ())
{
delete dungeonMap ;
dungeonMap = NULL ;
}
return dungeonMap ;
}
2010-05-20 23:35:27 +02:00
/// <summary>
/// Get all Group members list of dungeons that can't be done and reason
/// leader excluded as the list given is he list he can do
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Player*">Player to get Party Lock info</param>
/// <param name="LfgDungeonSet*">Dungeons to check</param>
2010-05-20 23:35:27 +02:00
/// <returns>LfgLockStatusMap*</returns>
2010-09-20 14:06:21 +02:00
LfgLockStatusMap * LFGMgr :: GetPartyLockStatusDungeons ( Player * plr , LfgDungeonSet * dungeons /* = NULL */ )
2010-05-20 23:35:27 +02:00
{
2010-09-04 18:20:10 +02:00
if ( ! plr )
2010-08-13 08:06:04 +02:00
return NULL ;
2010-09-04 18:20:10 +02:00
if ( ! dungeons )
dungeons = GetAllDungeons ();
2010-09-20 14:06:21 +02:00
Group * grp = plr -> GetGroup ();
2010-05-20 23:35:27 +02:00
if ( ! grp )
return NULL ;
2010-09-20 14:06:21 +02:00
PlayerSet * pPlayers = new PlayerSet ();
Player * plrg ;
for ( GroupReference * itr = grp -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
2010-05-20 23:35:27 +02:00
{
plrg = itr -> getSource ();
2010-08-11 13:25:14 +02:00
if ( plrg && plrg != plr )
pPlayers -> insert ( plrg );
2010-05-20 23:35:27 +02:00
}
2010-09-20 14:06:21 +02:00
LfgLockStatusMap * dungeonMap = GetGroupLockStatusDungeons ( pPlayers , dungeons );
2010-08-11 13:25:14 +02:00
pPlayers -> clear ();
delete pPlayers ;
2010-05-20 23:35:27 +02:00
return dungeonMap ;
}
/// <summary>
/// Get list of dungeons player can't do and reasons
/// </summary>
2010-09-20 14:06:21 +02:00
/// <param name="Player*">Player to check lock status</param>
/// <param name="LfgDungeonSet*">Dungeons to check</param>
2010-09-06 04:42:02 +02:00
/// <param name="bool">Use dungeon entry (true) or id (false)</param>
2010-05-20 23:35:27 +02:00
/// <returns>LfgLockStatusSet*</returns>
2010-09-20 14:06:21 +02:00
LfgLockStatusSet * LFGMgr :: GetPlayerLockStatusDungeons ( Player * plr , LfgDungeonSet * dungeons /* = NULL */ , bool useEntry /* = true */ )
2010-05-20 23:35:27 +02:00
{
2010-09-20 14:06:21 +02:00
LfgLockStatusSet * list = new LfgLockStatusSet ();
LfgLockStatus * lockstatus = NULL ;
LFGDungeonEntry const * dungeon ;
2010-05-20 23:35:27 +02:00
LfgLockStatusType locktype ;
uint8 level = plr -> getLevel ();
uint8 expansion = plr -> GetSession () -> Expansion ();
2010-08-11 16:17:05 +02:00
AccessRequirement const * ar ;
2010-05-20 23:35:27 +02:00
2010-09-04 18:20:10 +02:00
if ( ! dungeons )
dungeons = GetAllDungeons ();
2010-05-20 23:35:27 +02:00
for ( LfgDungeonSet :: const_iterator it = dungeons -> begin (); it != dungeons -> end (); ++ it )
{
dungeon = sLFGDungeonStore . LookupEntry ( * it );
2010-08-13 08:06:04 +02:00
if ( ! dungeon ) // should never happen - We provide a list from sLFGDungeonStore
continue ;
2010-08-11 16:17:05 +02:00
ar = sObjectMgr . GetAccessRequirement ( dungeon -> map , Difficulty ( dungeon -> difficulty ));
2010-05-20 23:35:27 +02:00
locktype = LFG_LOCKSTATUS_OK ;
if ( dungeon -> expansion > expansion )
locktype = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION ;
2010-08-11 16:17:05 +02:00
else if ( sDisableMgr . IsDisabledFor ( DISABLE_TYPE_MAP , dungeon -> map , plr ))
locktype = LFG_LOCKSTATUS_RAID_LOCKED ;
else if ( dungeon -> difficulty > DUNGEON_DIFFICULTY_NORMAL && plr -> GetBoundInstance ( dungeon -> map , Difficulty ( dungeon -> difficulty )))
locktype = LFG_LOCKSTATUS_RAID_LOCKED ;
2010-08-17 10:24:52 +02:00
else if ( dungeon -> minlevel > level )
locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL ;
else if ( dungeon -> maxlevel < level )
locktype = LFG_LOCKSTATUS_TOO_HIGH_LEVEL ;
else if ( locktype == LFG_LOCKSTATUS_OK && ar )
2010-08-11 16:17:05 +02:00
{
2010-08-17 10:24:52 +02:00
if ( ar -> achievement && ! plr -> GetAchievementMgr (). HasAchieved ( sAchievementStore . LookupEntry ( ar -> achievement )))
2010-10-25 07:16:46 +02:00
locktype = LFG_LOCKSTATUS_RAID_LOCKED ; // FIXME: Check the correct lock value
2010-08-17 10:24:52 +02:00
else if ( plr -> GetTeam () == ALLIANCE && ar -> quest_A && ! plr -> GetQuestRewardStatus ( ar -> quest_A ))
locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED ;
else if ( plr -> GetTeam () == HORDE && ar -> quest_H && ! plr -> GetQuestRewardStatus ( ar -> quest_H ))
locktype = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED ;
else
if ( ar -> item )
{
if ( ! plr -> HasItemCount ( ar -> item , 1 ) && ( ! ar -> item2 || ! plr -> HasItemCount ( ar -> item2 , 1 )))
2010-08-11 16:17:05 +02:00
locktype = LFG_LOCKSTATUS_MISSING_ITEM ;
2010-08-17 10:24:52 +02:00
}
else if ( ar -> item2 && ! plr -> HasItemCount ( ar -> item2 , 1 ))
locktype = LFG_LOCKSTATUS_MISSING_ITEM ;
2010-08-11 16:17:05 +02:00
}
/* TODO VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
2010-05-21 08:11:28 +02:00
locktype = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
2010-05-20 23:35:27 +02:00
locktype = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE;
locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL;
locktype = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
2010-08-11 16:17:05 +02:00
locktype = LFG_LOCKSTATUS_NOT_IN_SEASON; // Need list of instances and needed season to open
2010-05-20 23:35:27 +02:00
*/
if ( locktype != LFG_LOCKSTATUS_OK )
{
lockstatus = new LfgLockStatus ();
2010-09-06 04:42:02 +02:00
lockstatus -> dungeon = useEntry ? dungeon -> Entry () : dungeon -> ID ;
2010-05-20 23:35:27 +02:00
lockstatus -> lockstatus = locktype ;
list -> insert ( lockstatus );
}
}
2010-05-31 20:25:21 +02:00
if ( ! list -> size ())
{
delete list ;
list = NULL ;
}
2010-05-20 23:35:27 +02:00
return list ;
}
/// <summary>
/// Get the dungeon list that can be done.
/// </summary>
/// <returns>LfgDungeonSet*</returns>
LfgDungeonSet * LFGMgr :: GetAllDungeons ()
{
2010-09-20 14:06:21 +02:00
LfgDungeonSet * alldungeons = m_CachedDungeonMap [ 0 ];
2010-08-11 13:25:14 +02:00
if ( alldungeons )
return alldungeons ;
2010-09-20 14:06:21 +02:00
LfgDungeonSet * dungeons ;
LFGDungeonEntry const * dungeon ;
2010-08-11 13:25:14 +02:00
alldungeons = new LfgDungeonSet ();
m_CachedDungeonMap [ 0 ] = alldungeons ;
2010-05-20 23:35:27 +02:00
for ( uint32 i = 0 ; i < sLFGDungeonStore . GetNumRows (); ++ i )
{
dungeon = sLFGDungeonStore . LookupEntry ( i );
if ( ! dungeon || dungeon -> type == LFG_TYPE_ZONE )
continue ;
2010-08-11 13:25:14 +02:00
dungeons = m_CachedDungeonMap [ dungeon -> grouptype ];
if ( ! dungeons )
{
dungeons = new LfgDungeonSet ();
m_CachedDungeonMap [ dungeon -> grouptype ] = dungeons ;
}
if ( dungeon -> type != LFG_TYPE_RANDOM )
dungeons -> insert ( dungeon -> ID );
alldungeons -> insert ( dungeon -> ID );
2010-05-20 23:35:27 +02:00
}
2010-08-11 13:25:14 +02:00
return alldungeons ;
2010-05-20 23:35:27 +02:00
}
/// <summary>
/// Get the dungeon list that can be done given a random dungeon entry.
2010-08-11 13:25:14 +02:00
/// Special case: randomdungeon == 0 then will return all dungeons
2010-05-20 23:35:27 +02:00
/// </summary>
2010-08-11 13:25:14 +02:00
/// <param name="uint32">Random dungeon entry</param>
2010-05-20 23:35:27 +02:00
/// <returns>LfgDungeonSet*</returns>
LfgDungeonSet * LFGMgr :: GetDungeonsByRandom ( uint32 randomdungeon )
{
2010-08-11 13:25:14 +02:00
uint8 groupType = 0 ;
2010-09-20 14:06:21 +02:00
if ( LFGDungeonEntry const * dungeon = sLFGDungeonStore . LookupEntry ( randomdungeon ))
2010-08-11 13:25:14 +02:00
groupType = dungeon -> grouptype ;
2010-05-20 23:35:27 +02:00
2010-09-08 13:19:05 +02:00
LfgDungeonMap :: const_iterator itMap = m_CachedDungeonMap . find ( groupType );
if ( itMap == m_CachedDungeonMap . end ())
return NULL ;
2010-09-20 14:06:21 +02:00
LfgDungeonSet * dungeons = new LfgDungeonSet ();
2010-09-08 13:19:05 +02:00
for ( LfgDungeonSet :: const_iterator it = itMap -> second -> begin (); it != itMap -> second -> end (); ++ it )
dungeons -> insert ( * it );
return dungeons ;
2010-05-20 23:35:27 +02:00
}
/// <summary>
/// Get the random dungeon list that can be done at a certain level and expansion.
/// </summary>
2010-08-11 13:25:14 +02:00
/// <param name="uint8">Player level</param>
/// <param name="uint8">Player account expansion</param>
2010-05-20 23:35:27 +02:00
/// <returns>LfgDungeonSet*</returns>
LfgDungeonSet * LFGMgr :: GetRandomDungeons ( uint8 level , uint8 expansion )
{
2010-09-20 14:06:21 +02:00
LfgDungeonSet * list = new LfgDungeonSet ();
LFGDungeonEntry const * dungeon ;
2010-05-20 23:35:27 +02:00
for ( uint32 i = 0 ; i < sLFGDungeonStore . GetNumRows (); ++ i )
{
dungeon = sLFGDungeonStore . LookupEntry ( i );
if ( dungeon && dungeon -> expansion <= expansion && dungeon -> type == LFG_TYPE_RANDOM &&
dungeon -> minlevel <= level && level <= dungeon -> maxlevel )
list -> insert ( dungeon -> Entry ());
}
return list ;
}
/// <summary>
2010-08-11 13:25:14 +02:00
/// Get the reward of a given random dungeon at a certain level
2010-05-20 23:35:27 +02:00
/// </summary>
2010-08-11 13:25:14 +02:00
/// <param name="uint32">random dungeon id</param>
/// <param name="uint8">Player level</param>
2010-09-03 20:11:14 +02:00
/// <returns>LfgReward const*</returns>
LfgReward const * LFGMgr :: GetRandomDungeonReward ( uint32 dungeon , uint8 level )
2010-05-20 23:35:27 +02:00
{
2010-09-03 20:11:14 +02:00
LfgReward const * rew = NULL ;
LfgRewardMapBounds bounds = m_RewardMap . equal_range ( dungeon & 0x00FFFFFF );
for ( LfgRewardMap :: const_iterator itr = bounds . first ; itr != bounds . second ; ++ itr )
{
rew = itr -> second ;
// ordered properly at loading
if ( itr -> second -> maxLevel >= level )
break ;
}
return rew ;
2010-05-21 08:11:28 +02:00
}
2010-05-31 20:25:21 +02:00
/// <summary>
2010-11-22 12:28:06 +01:00
/// Given a Dungeon id returns the dungeon Type
2010-05-31 20:25:21 +02:00
/// </summary>
2010-08-11 13:25:14 +02:00
/// <param name="uint32">Dungeon id</param>
2010-11-22 12:28:06 +01:00
/// <returns>uint8: Type</returns>
LfgType LFGMgr :: GetDungeonType ( uint32 dungeonId )
2010-05-31 20:25:21 +02:00
{
2010-09-20 14:06:21 +02:00
LFGDungeonEntry const * dungeon = sLFGDungeonStore . LookupEntry ( dungeonId );
2010-05-31 20:25:21 +02:00
if ( ! dungeon )
2010-11-22 12:28:06 +01:00
return LFG_TYPE_NONE ;
2010-05-31 20:25:21 +02:00
2010-11-22 12:28:06 +01:00
return LfgType ( dungeon -> type );
2010-05-31 20:25:21 +02:00
}
2010-08-11 12:44:49 +02:00
/// <summary>
/// Given a Dungeon id returns if it's random
/// </summary>
/// <param name="uint32">Dungeon id</param>
/// <returns>bool</returns>
bool LFGMgr :: isRandomDungeon ( uint32 dungeonId )
{
2010-09-20 14:06:21 +02:00
LFGDungeonEntry const * dungeon = sLFGDungeonStore . LookupEntry ( dungeonId );
2010-08-11 12:44:49 +02:00
if ( ! dungeon )
return false ;
return dungeon -> type == LFG_TYPE_RANDOM ;
2010-08-17 11:26:31 +02:00
}
2010-09-05 22:05:14 +02:00
2010-09-20 14:06:21 +02:00
/// <summary>
/// Given a Achievement id returns the related dungeon id
/// </summary>
/// <param name="uint32">Achievement id</param>
/// <returns>uint32</returns>
uint32 LFGMgr :: GetDungeonIdForAchievement ( uint32 achievementId )
{
std :: map < uint32 , uint32 >:: iterator itr = m_EncountersByAchievement . find ( achievementId );
if ( itr != m_EncountersByAchievement . end ())
return itr -> second ;
return 0 ;
};
2010-09-05 22:05:14 +02:00
/// <summary>
/// Given a list of guids returns the concatenation using | as delimiter
/// </summary>
/// <param name="LfgGuidList ">list of guids</param>
/// <returns>std::string</returns>
std :: string LFGMgr :: ConcatenateGuids ( LfgGuidList check )
{
if ( check . empty ())
return "" ;
2010-09-08 13:44:57 +02:00
LfgGuidSet guidSet ;
2010-09-05 22:05:14 +02:00
while ( ! check . empty ())
{
guidSet . insert ( check . front ());
check . pop_front ();
}
std :: ostringstream o ;
2010-09-08 13:19:05 +02:00
LfgGuidSet :: const_iterator it = guidSet . begin ();
2010-09-20 14:06:21 +02:00
o << ( * it );
2010-09-05 22:05:14 +02:00
for ( ++ it ; it != guidSet . end (); ++ it )
2010-09-20 14:06:21 +02:00
o << "|" << ( * it );
2010-09-05 22:05:14 +02:00
guidSet . clear ();
return o . str ();
2010-09-06 15:23:08 +02:00
}
2010-09-20 14:06:21 +02:00
/// <summary>
/// Given a list of dungeonIds returns the concatenation using , as delimiter
/// </summary>
/// <param name="LfgDungeonSet ">list of dungeons</param>
/// <returns>std::string</returns>
std :: string LFGMgr :: ConcatenateDungeons ( LfgDungeonSet * dungeons )
{
std :: string dungeonstr = "" ;
if ( dungeons && ! dungeons -> empty ())
{
std :: ostringstream o ;
LfgDungeonSet :: const_iterator it = dungeons -> begin ();
o << ( * it );
for ( ++ it ; it != dungeons -> end (); ++ it )
o << ", " << ( * it );
dungeonstr = o . str ();
}
return dungeonstr ;
}