//----------------------------------------------------------------------------- // Purpose: Get the next player from the queue, and shuffle the rest up //----------------------------------------------------------------------------- CBasePlayer *CDiscArena::GetNextPlayer( void ) { if ( m_pPlayerQueue == NULL ) return NULL; CBasePlayer *pCurr = (CBasePlayer*)(CBaseEntity*)m_pPlayerQueue; RemovePlayerFromQueue( (CBasePlayer*)(CBaseEntity*)m_pPlayerQueue ); return pCurr; }
void WorldSession::HandleMeetingStoneLeaveOpcode(WorldPacket & recv_data) { DEBUG_LOG("WORLD: Recvd CMSG_MEETINGSTONE_LEAVE"); if (Group *grp = _player->GetGroup()) { } else { RemovePlayerFromQueue(_player->GetGUIDLow()); } SendMeetingstoneSetqueue(0, MEETINGSTONE_STATUS_NONE); }
//----------------------------------------------------------------------------- // Purpose: Client was removed from the arena //----------------------------------------------------------------------------- void CDiscArena::RemoveClient( CBasePlayer *pPlayer ) { m_iPlayers--; pPlayer->pev->groupinfo = 0; pPlayer->m_pCurrentArena = NULL; // Is she in the current battle? if ( pPlayer->pev->playerclass != 0 ) { // No, she's in the queue, so remove her. RemovePlayerFromQueue( pPlayer ); } else if ( m_iArenaState != ARENA_WAITING_FOR_PLAYERS ) { // This team loses m_iWinningTeam = (pPlayer->pev->team == 1) ? 2 : 1; if ( m_iWinningTeam == 1 ) m_iTeamOneScore = m_iMaxRounds - 1; // -1 because we'll get 1 point for winning this round in CheckOverThink else m_iTeamTwoScore = m_iMaxRounds - 1; // -1 because we'll get 1 point for winning this round in CheckOverThink // Find the player in the combatant list for ( int i = 0; i < (m_iPlayersPerTeam * 2); i++ ) { // Check to see if this slot's already full if ( m_hCombatants[ i ] == pPlayer ) { m_hCombatants[i] = NULL; break; } } CheckOverThink(); } }
bool LFGQueue::FindRoleToGroup(Player* plr, Group* grp, ClassRoles role) { // Safe check if(!plr || !grp) return false; QueuedGroupsMap::iterator qGroup = m_QueuedGroups.find(grp->GetId()); QueuedPlayersMap::iterator qPlayer = m_QueuedPlayers.find(plr->GetObjectGuid()); if(qGroup != m_QueuedGroups.end() && qPlayer != m_QueuedPlayers.end()) { if (getPriority((Classes)plr->getClass(), role) >= LFG_PRIORITY_HIGH || qPlayer->second.hasQueuePriority) { bool hasBeenLongerInQueue = false; // Iterate over QueuedPlayersMap to find if players have been longer in Queue. for (QueuedPlayersMap::iterator qPlayer_loop = m_QueuedPlayers.begin(); qPlayer_loop != m_QueuedPlayers.end(); ++qPlayer_loop) { if (qPlayer->first == qPlayer_loop->first) continue; if(qPlayer->second.timeInLFG > qPlayer_loop->second.timeInLFG) hasBeenLongerInQueue = true; } if(hasBeenLongerInQueue) { switch(role) { case LFG_ROLE_TANK: { // Remove tank flag if player can perform tank role. qGroup->second.availableRoles &= ~LFG_ROLE_TANK; break; } case LFG_ROLE_HEALER: { // Remove healer flag if player can perform healer role. qGroup->second.availableRoles &= ~LFG_ROLE_HEALER; break; } case LFG_ROLE_DPS: { if(qGroup->second.dpsCount < 3) { // Update dps count first. ++qGroup->second.dpsCount; // Remove dps flag if there is enough dps in group. if(qGroup->second.dpsCount >= 3) qGroup->second.availableRoles &= ~LFG_ROLE_DPS; } break; } default: { return false; } } } WorldPacket data; BuildMemberAddedPacket(data, plr->GetGUID()); grp->BroadcastPacket(&data, true); // Add member to the group. grp->AddMember(plr->GetObjectGuid(), plr->GetName(), GROUP_LFG); // Remove player from queue. RemovePlayerFromQueue(qPlayer->first, PLAYER_SYSTEM_LEAVE); // Found player return true. return true; } else if (getPriority((Classes)plr->getClass(), role) < LFG_PRIORITY_HIGH) { bool hasFoundPriority = false; bool hasBeenLongerInQueue = false; // Iterate over QueuedPlayersMap to find if players in queue have higher priority or they have been longer in Queue. for (QueuedPlayersMap::iterator qPlayer_loop = m_QueuedPlayers.begin(); qPlayer_loop != m_QueuedPlayers.end(); ++qPlayer_loop) { if (qPlayer->first == qPlayer_loop->first) continue; Player* m_loopMember = sObjectMgr.GetPlayer(qPlayer_loop->first); // If there is anyone in group for class with higher priority then ignore current member. if (getPriority((Classes)plr->getClass(), role) < getPriority((Classes)m_loopMember->getClass(), role)) hasFoundPriority = true; if(qPlayer->second.timeInLFG > qPlayer_loop->second.timeInLFG) hasBeenLongerInQueue = true; } // If there were no one in group for role with higher priority add this member to group if(!hasFoundPriority && hasBeenLongerInQueue) { switch(role) { case LFG_ROLE_TANK: { // Remove tank flag if player can perform tank role. qGroup->second.availableRoles &= ~LFG_ROLE_TANK; break; } case LFG_ROLE_HEALER: { // Remove healer flag if player can perform healer role. qGroup->second.availableRoles &= ~LFG_ROLE_HEALER; break; } case LFG_ROLE_DPS: { if(qGroup->second.dpsCount < 3) { // Update dps count first. ++qGroup->second.dpsCount; // Remove dps flag if there is enough dps in group. if(qGroup->second.dpsCount >= 3) qGroup->second.availableRoles &= ~LFG_ROLE_DPS; } break; } // This is impossible... default: { return false; } } WorldPacket data; BuildMemberAddedPacket(data, plr->GetGUID()); grp->BroadcastPacket(&data, true); // Add member to the group. grp->AddMember(plr->GetObjectGuid(), plr->GetName(), GROUP_LFG); // Now remove player from queue RemovePlayerFromQueue(qPlayer->first, PLAYER_SYSTEM_LEAVE); // found player return true return true; } } } return false; }
void LFGQueue::Update(uint32 diff) { if(m_QueuedGroups.empty() && m_QueuedPlayers.empty()) return; // Iterate over QueuedPlayersMap to update players timers and remove offline/disconnected players. for(QueuedPlayersMap::iterator qPlayer = m_QueuedPlayers.begin(); qPlayer != m_QueuedPlayers.end(); ++qPlayer) { Player* plr = sObjectMgr.GetPlayer(qPlayer->first); // Player could have been disconnected if(!plr ||!plr->IsInWorld()) { m_OfflinePlayers[qPlayer->first] = qPlayer->second; m_QueuedPlayers.erase(qPlayer); break; } qPlayer->second.timeInLFG += diff; // Update player timer and give him queue priority. if(qPlayer->second.timeInLFG >= (30 * MINUTE * IN_MILLISECONDS)) { qPlayer->second.hasQueuePriority = true; } } if(!m_QueuedGroups.empty()) { // Iterate over QueuedGroupsMap to fill groups with roles they're missing. for(QueuedGroupsMap::iterator qGroup = m_QueuedGroups.begin(); qGroup != m_QueuedGroups.end(); ++qGroup) { Group* grp = sObjectMgr.GetGroupById(qGroup->first); // Safe check if(!grp) return; // Remove group from Queue if it's full if(grp->IsFull()) { RemoveGroupFromQueue(qGroup->first, GROUP_SYSTEM_LEAVE); break; } // Iterate over QueuedPlayersMap to find suitable player to join group for(QueuedPlayersMap::iterator qPlayer = m_QueuedPlayers.begin(); qPlayer != m_QueuedPlayers.end(); ++qPlayer) { Player* plr = sObjectMgr.GetPlayer(qPlayer->first); // Check here that players team and areaId they're in queue are same if(qPlayer->second.team == qGroup->second.team && qPlayer->second.areaId == qGroup->second.areaId) { // Check if player can perform tank role if((canPerformRole(qPlayer->second.roleMask, LFG_ROLE_TANK) & qGroup->second.availableRoles) == LFG_ROLE_TANK) { if(FindRoleToGroup(plr, grp, LFG_ROLE_TANK)) { break; } else { continue; } } // Check if player can perform healer role if((canPerformRole(qPlayer->second.roleMask, LFG_ROLE_HEALER) & qGroup->second.availableRoles) == LFG_ROLE_HEALER) { if(FindRoleToGroup(plr, grp, LFG_ROLE_HEALER)) { break; } else { continue; } } // Check if player can perform dps role if((canPerformRole(qPlayer->second.roleMask, LFG_ROLE_DPS) & qGroup->second.availableRoles) == LFG_ROLE_DPS) { if(FindRoleToGroup(plr, grp, LFG_ROLE_DPS)) { break; } else { continue; } } // Check if group is full, no need to try to iterate same group if it's already full. if(grp->IsFull()) { RemoveGroupFromQueue(qGroup->first, GROUP_SYSTEM_LEAVE); break; } } } // Update group timer. After each 5 minutes group will be broadcasted they're still waiting more members. if (qGroup->second.groupTimer <= diff) { WorldPacket data; BuildInProgressPacket(data); grp->BroadcastPacket(&data, true); qGroup->second.groupTimer = 5 * MINUTE * IN_MILLISECONDS; } else { qGroup->second.groupTimer -= diff; } } } // Pick first 2 players and form group out of them also inserting them into queue as group. if(m_QueuedPlayers.size() > 5) { // Pick Leader as first target. QueuedPlayersMap::iterator nPlayer1 = m_QueuedPlayers.begin(); if(findInArea(nPlayer1->second.areaId) > 5) { Group* newQueueGroup = new Group; // Iterate of QueuedPlayersMap and pick first member to accompany leader. for(QueuedPlayersMap::iterator nPlayer2 = m_QueuedPlayers.begin(); nPlayer2 != m_QueuedPlayers.end(); ++nPlayer2) { if(nPlayer1->first == nPlayer2->first) continue; if(nPlayer1->second.team == nPlayer2->second.team && nPlayer1->second.areaId == nPlayer2->second.areaId) { Player* leader = sObjectMgr.GetPlayer(nPlayer1->first); Player* member = sObjectMgr.GetPlayer(nPlayer2->first); uint32 areaId = nPlayer1->second.areaId; if(!newQueueGroup->IsCreated()) { if(newQueueGroup->Create(leader->GetObjectGuid(), leader->GetName())) sObjectMgr.AddGroup(newQueueGroup); else return; } WorldPacket data; BuildMemberAddedPacket(data, member->GetGUID()); leader->GetSession()->SendPacket(&data); // Add member to the group. Leader is already added upon creation of group. newQueueGroup->AddMember(member->GetObjectGuid(), member->GetName(), GROUP_LFG); // Add this new group to GroupQueue now and remove players from PlayerQueue RemovePlayerFromQueue(nPlayer1->first, PLAYER_SYSTEM_LEAVE); RemovePlayerFromQueue(nPlayer2->first, PLAYER_SYSTEM_LEAVE); AddToQueue(leader, areaId); break; } } } } }
void WorldSession::LFGLoop() { QueryResult *result = WorldDatabase.Query("SELECT guid,zoneid,is_group FROM lfg_queue"); if (result) { do { Field* fields = result->Fetch(); //is this entry a group? if(fields[2].GetUInt32() == 1) { //is there anyone in the queue looking for a group for this groups instance? QueryResult *resultLFG = WorldDatabase.PQuery("SELECT guid,zoneid,is_group,player_name FROM lfg_queue WHERE zoneid = '%u' AND is_group = 0", fields[1].GetUInt32()); if (resultLFG) { do { Field* fieldsLFG = resultLFG->Fetch(); Player *plr = sObjectAccessor.FindPlayerByName(fieldsLFG[3].GetString()); Group *grp = sObjectMgr.GetGroupById(fields[0].GetUInt32()); if(!grp->IsFull()) { //check for roles if(GroupHasRole(ROLE_TANK, grp) && GroupHasRole(ROLE_HEALER, grp)) { //group has both dps & tank, add anyone. grp->AddMember(plr->GetGUID(), plr->GetName()); RemovePlayerFromQueue(plr->GetGUIDLow()); if(grp->IsFull()) { SendMeetingStoneCompleteToParty(grp); } } else if(GroupHasRole(ROLE_TANK, grp) && !GroupHasRole(ROLE_HEALER, grp)) { //tank but healers missing //is player healer? if(isPlayerHealer(plr)) { grp->AddMember(plr->GetGUID(), plr->GetName()); RemovePlayerFromQueue(plr->GetGUIDLow()); if(grp->IsFull()) { SendMeetingStoneCompleteToParty(grp); } } //player is not healer but group can take one more random.. else if(!isPlayerHealer(plr) && grp->GetMembersCount() < 4) { grp->AddMember(plr->GetGUID(), plr->GetName()); RemovePlayerFromQueue(plr->GetGUIDLow()); if(grp->IsFull()) { SendMeetingStoneCompleteToParty(grp); } } } else if(!GroupHasRole(ROLE_TANK, grp) && !GroupHasRole(ROLE_HEALER, grp)) { //group has neither tank or healer if(isPlayerHealer(plr) || isPlayerTank(plr)) { grp->AddMember(plr->GetGUID(), plr->GetName()); RemovePlayerFromQueue(plr->GetGUIDLow()); if(grp->IsFull()) { SendMeetingStoneCompleteToParty(grp); } } else { if(grp->GetMembersCount() < 3) { //theres room for 1 more random, let the player join. grp->AddMember(plr->GetGUID(), plr->GetName()); RemovePlayerFromQueue(plr->GetGUIDLow()); if(grp->IsFull()) { SendMeetingStoneCompleteToParty(grp); } } } } } } while (resultLFG->NextRow()); } } else { //its a player, is there any other non-grouped players thats looking for the same instance? QueryResult *result_mp = WorldDatabase.PQuery("SELECT guid,zoneid,is_group,player_name FROM lfg_queue WHERE zoneid = '%u' AND is_group = 0", fields[1].GetUInt32()); if(result_mp->GetRowCount() > 1) { int i = 1; Group* grp; grp = new Group; do { Field* fields_mp = result_mp->Fetch(); Player *plr = sObjectAccessor.FindPlayerByName(fields_mp[3].GetString()); if(!grp->IsCreated()) { if (grp->Create(plr->GetGUID(), plr->GetName())) { sObjectMgr.AddGroup(grp); RemovePlayerFromQueue(plr->GetGUIDLow()); } } else { grp->AddMember(plr->GetGUID(), plr->GetName()); RemovePlayerFromQueue(plr->GetGUIDLow()); } plr = NULL; } while (result_mp->NextRow()); //if this group did not fill up, add it into LFM queue if(!grp->IsFull()) { AddGroupToQueue(grp->GetId(), fields[1].GetUInt32()); } } } } while (result->NextRow()); } }