void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) { Player *plr = objmgr.GetPlayer(guid); uint32 queue_id = 0; QueuedPlayersMap::iterator itr; GroupQueueInfo * group; QueuedGroupsList::iterator group_itr; bool IsSet = false; if(plr) { queue_id = plr->GetBattleGroundQueueIdFromLevel(); itr = m_QueuedPlayers[queue_id].find(guid); if(itr != m_QueuedPlayers[queue_id].end()) IsSet = true; } if(!IsSet) { // either player is offline, or he levelled up to another queue category // sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { itr = m_QueuedPlayers[i].find(guid); if(itr != m_QueuedPlayers[i].end()) { queue_id = i; IsSet = true; break; } } } // couldn't find the player in bg queue, return if(!IsSet) { sLog.outError("Battleground: couldn't find player to remove."); return; } group = itr->second.GroupInfo; for(group_itr=m_QueuedGroups[queue_id].begin(); group_itr != m_QueuedGroups[queue_id].end(); ++group_itr) { if(group == (GroupQueueInfo*)(*group_itr)) break; } // variables are set (what about leveling up when in queue????) // remove player from group // if only player there, remove group // remove player queue info from group queue info std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid); if(pitr != group->Players.end()) group->Players.erase(pitr); // check for iterator correctness if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end()) { // used when player left the queue, NOT used when porting to bg if (decreaseInvitedCount) { // if invited to bg, and should decrease invited count, then do it if(group->IsInvitedToBGInstanceGUID) { BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); if (bg) bg->DecreaseInvitedCount(group->Team); if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE)) { // no more players on battleground, set delete it bg->SetDeleteThis(); } } // update the join queue, maybe now the player's group fits in a queue! // not yet implemented (should store bgTypeId in group queue info?) } // remove player queue info m_QueuedPlayers[queue_id].erase(itr); // remove group queue info if needed if(group->Players.empty()) { m_QueuedGroups[queue_id].erase(group_itr); delete group; } // NEEDS TESTING! // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too // don't remove recursively if already invited to bg! else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount) { // remove next player, this is recursive // first send removal information if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) { BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId); uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); plr2->GetSession()->SendPacket(&data); } // then actually delete, this may delete the group as well! RemovePlayer(group->Players.begin()->first,decreaseInvitedCount); } } }