void WorldSession::HandleBattlegroundPlayerPositionsOpcode(WorldPacket &recv_data) { // empty opcode CBattleground *bg = _player->m_bg; if(!_player->IsInWorld() || !bg) return; if(bg->GetType() == BATTLEGROUND_WARSONG_GULCH) { uint32 count1 = 0; uint32 count2 = 0; Player *ap = objmgr.GetPlayer(((WarsongGulch*)bg)->GetAllianceFlagHolderGUID()); if(ap) ++count2; Player *hp = objmgr.GetPlayer(((WarsongGulch*)bg)->GetHordeFlagHolderGUID()); if(hp) ++count2; WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2)); data << count1; data << count2; if(ap) { data << (uint64)ap->GetGUID(); data << (float)ap->GetPositionX(); data << (float)ap->GetPositionY(); } if(hp) { data << (uint64)hp->GetGUID(); data << (float)hp->GetPositionX(); data << (float)hp->GetPositionY(); } SendPacket(&data); } else if(bg->GetType() == BATTLEGROUND_EYE_OF_THE_STORM) { uint32 count1 = 0; uint32 count2 = 0; Player *ap = objmgr.GetPlayer(((EyeOfTheStorm*)bg)->GetFlagHolderGUID()); if(ap) ++count2; WorldPacket data(MSG_BATTLEGROUND_PLAYER_POSITIONS, (4+4+16*count1+16*count2)); data << count1; data << count2; if(ap) { data << (uint64)ap->GetGUID(); data << (float)ap->GetPositionX(); data << (float)ap->GetPositionY(); } SendPacket(&data); } }
void CBattlegroundManager::EventQueueUpdate(bool forceStart) { deque<uint32> tempPlayerVec[2]; uint32 i, j, k; Player* plr; CBattleground* bg; list<uint32>::iterator it3, it4; map<uint32, CBattleground*>::iterator iitr; Arena* arena; int32 team; uint32 plrguid; uint32 factionMap[MAX_PLAYER_TEAMS]; uint32 count; std::queue< uint32 > teams[MAX_PLAYER_TEAMS]; m_queueLock.Acquire(); m_instanceLock.Acquire(); for (i = 0; i < BATTLEGROUND_NUM_TYPES; ++i) { for (j = 0; j < MAX_LEVEL_GROUP; ++j) { if (!m_queuedPlayers[i][j].size()) continue; tempPlayerVec[0].clear(); tempPlayerVec[1].clear(); // We try to add the players who queued for a specific Bg/Arena instance to // the Bg/Arena where they queued to, and add the rest to another list for (it3 = m_queuedPlayers[i][j].begin(); it3 != m_queuedPlayers[i][j].end();) { it4 = it3++; plrguid = *it4; plr = objmgr.GetPlayer(plrguid); // Player has left the game or switched level group since queuing (by leveling for example) if (!plr || GetLevelGrouping(plr->getLevel()) != j) { m_queuedPlayers[i][j].erase(it4); continue; } // queued to a specific instance id? if (plr->m_bgQueueInstanceId != 0) { iitr = m_instances[i].find(plr->m_bgQueueInstanceId); if (iitr == m_instances[i].end()) { // queue no longer valid, since instance has closed since queuing plr->GetSession()->SystemMessage(plr->GetSession()->LocalizedWorldSrv(52), plr->m_bgQueueInstanceId); plr->m_bgIsQueued = false; plr->m_bgQueueType = 0; plr->m_bgQueueInstanceId = 0; m_queuedPlayers[i][j].erase(it4); continue; } // can we join the specified Bg instance? bg = iitr->second; if (bg->CanPlayerJoin(plr, bg->GetType())) { bg->AddPlayer(plr, plr->GetTeam()); m_queuedPlayers[i][j].erase(it4); } } else { if (IS_ARENA(i)) tempPlayerVec[plr->GetTeam()].push_back(plrguid); else if (!plr->HasAura(BG_DESERTER)) tempPlayerVec[plr->GetTeam()].push_back(plrguid); } } // Now that we have a list of players who didn't queue for a specific instance // try to add them to a Bg/Arena that is already under way for (iitr = m_instances[i].begin(); iitr != m_instances[i].end(); ++iitr) { if (iitr->second->HasEnded() || iitr->second->GetLevelGroup() != j) continue; if (IS_ARENA(i)) { arena = TO< Arena* >(iitr->second); if (arena->Rated()) continue; factionMap[0] = arena->GetTeamFaction(0); factionMap[1] = arena->GetTeamFaction(1); team = arena->GetFreeTeam(); while ((team >= 0) && (tempPlayerVec[factionMap[team]].size() > 0)) { plrguid = *tempPlayerVec[factionMap[team]].begin(); tempPlayerVec[factionMap[team]].pop_front(); plr = objmgr.GetPlayer(plrguid); if (plr) { plr->m_bgTeam = team; arena->AddPlayer(plr, team); team = arena->GetFreeTeam(); } ErasePlayerFromList(plrguid, &m_queuedPlayers[i][j]); } } else { bg = iitr->second; int size = (int)min(tempPlayerVec[0].size(), tempPlayerVec[1].size()); for (int counter = 0; (counter < size) && (bg->IsFull() == false); counter++) { AddPlayerToBgTeam(bg, &tempPlayerVec[0], i, j, 0); AddPlayerToBgTeam(bg, &tempPlayerVec[1], i, j, 1); } while (tempPlayerVec[0].size() > 0 && bg->HasFreeSlots(0, bg->GetType())) { AddPlayerToBgTeam(bg, &tempPlayerVec[0], i, j, 0); } while (tempPlayerVec[1].size() > 0 && bg->HasFreeSlots(1, bg->GetType())) { AddPlayerToBgTeam(bg, &tempPlayerVec[1], i, j, 1); } } } // Now that that we added everyone we could to a running Bg/Arena // We shall see if we can start a new one! if (IS_ARENA(i)) { // enough players to start a round? uint32 minPlayers = BattlegroundManager.GetMinimumPlayers(i); if (!forceStart && ((tempPlayerVec[0].size() + tempPlayerVec[1].size()) < (minPlayers * 2))) continue; if (CanCreateInstance(i, j)) { arena = TO< Arena* >(CreateInstance(i, j)); if (arena == NULL) { sLog.Error("BattlegroundMgr", "%s (%u): Couldn't create Arena Instance", __FILE__, __LINE__); m_queueLock.Release(); m_instanceLock.Release(); return; } // No alliance in the queue if (tempPlayerVec[0].size() == 0) { count = GetMaximumPlayers(i) * 2; while ((count > 0) && (tempPlayerVec[1].size() > 0)) { if (teams[0].size() > teams[1].size()) teams[1].push(tempPlayerVec[1].front()); else teams[0].push(tempPlayerVec[1].front()); tempPlayerVec[1].pop_front(); count--; } } else // No horde in the queue if (tempPlayerVec[1].size() == 0) { count = GetMaximumPlayers(i) * 2; while ((count > 0) && (tempPlayerVec[0].size() > 0)) { if (teams[0].size() > teams[1].size()) teams[1].push(tempPlayerVec[0].front()); else teams[0].push(tempPlayerVec[0].front()); tempPlayerVec[0].pop_front(); count--; } } else // There are both alliance and horde players in the queue { count = GetMaximumPlayers(i); while ((count > 0) && (tempPlayerVec[0].size() > 0) && (tempPlayerVec[1].size() > 0)) { teams[0].push(tempPlayerVec[0].front()); teams[1].push(tempPlayerVec[1].front()); tempPlayerVec[0].pop_front(); tempPlayerVec[1].pop_front(); count--; } } // Now we just need to add the players to the Arena instance while (teams[0].size() > 0) { for (uint32 team = 0; team < 2; team++) { plrguid = teams[team].front(); teams[team].pop(); plr = objmgr.GetPlayer(plrguid); if (plr == NULL) continue; plr->m_bgTeam = team; arena->AddPlayer(plr, plr->m_bgTeam); // remove from the main queue (painful!) ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } } else { uint32 minPlayers = BattlegroundManager.GetMinimumPlayers(i); if (forceStart || (tempPlayerVec[0].size() >= minPlayers && tempPlayerVec[1].size() >= minPlayers)) { if (CanCreateInstance(i, j)) { bg = CreateInstance(i, j); if (bg == NULL) { m_queueLock.Release(); m_instanceLock.Release(); return; } // push as many as possible in if (forceStart) { for (k = 0; k < 2; ++k) { while (tempPlayerVec[k].size() && bg->HasFreeSlots(k, bg->GetType())) { AddPlayerToBgTeam(bg, &tempPlayerVec[k], i, j, k); } } } else { int size = (int)min(tempPlayerVec[0].size(), tempPlayerVec[1].size()); for (int counter = 0; (counter < size) && (bg->IsFull() == false); counter++) { AddPlayerToBgTeam(bg, &tempPlayerVec[0], i, j, 0); AddPlayerToBgTeam(bg, &tempPlayerVec[1], i, j, 1); } } } } } } } /* Handle paired arena team joining */ Group* group1, *group2; uint32 teamids[2] = { 0, 0 }; uint32 avgRating[2] = { 0, 0 }; uint32 n; list<uint32>::iterator itz; for (i = BATTLEGROUND_ARENA_2V2; i <= BATTLEGROUND_ARENA_5V5; ++i) { if (!forceStart && m_queuedGroups[i].size() < 2) /* got enough to have an arena battle ;P */ { continue; } for (j = 0; j < (uint32)m_queuedGroups[i].size(); j++) { group1 = group2 = NULL; n = RandomUInt((uint32)m_queuedGroups[i].size()) - 1; for (itz = m_queuedGroups[i].begin(); itz != m_queuedGroups[i].end() && n > 0; ++itz) --n; if (itz == m_queuedGroups[i].end()) itz = m_queuedGroups[i].begin(); if (itz == m_queuedGroups[i].end()) { sLog.Error("BattlegroundMgr", "Internal error at %s:%u", __FILE__, __LINE__); m_queueLock.Release(); m_instanceLock.Release(); return; } group1 = objmgr.GetGroupById(*itz); if (group1 == NULL) { continue; } if (forceStart && m_queuedGroups[i].size() == 1) { if (CreateArenaType(i, group1, NULL) == -1) return; m_queuedGroups[i].remove(group1->GetID()); continue; } teamids[0] = GetArenaGroupQInfo(group1, i, &avgRating[0]); list<uint32> possibleGroups; for (itz = m_queuedGroups[i].begin(); itz != m_queuedGroups[i].end(); ++itz) { group2 = objmgr.GetGroupById(*itz); if (group2) { teamids[1] = GetArenaGroupQInfo(group2, i, &avgRating[1]); uint32 delta = abs((int32)avgRating[0] - (int32)avgRating[1]); if (teamids[0] != teamids[1] && delta <= sWorld.ArenaQueueDiff) { possibleGroups.push_back(group2->GetID()); } } } if (possibleGroups.size() > 0) { n = RandomUInt((uint32)possibleGroups.size()) - 1; for (itz = possibleGroups.begin(); itz != possibleGroups.end() && n > 0; ++itz) --n; if (itz == possibleGroups.end()) itz = possibleGroups.begin(); if (itz == possibleGroups.end()) { sLog.Error("BattlegroundMgr", "Internal error at %s:%u", __FILE__, __LINE__); m_queueLock.Release(); m_instanceLock.Release(); return; } group2 = objmgr.GetGroupById(*itz); if (group2) { if (CreateArenaType(i, group1, group2) == -1) return; m_queuedGroups[i].remove(group1->GetID()); m_queuedGroups[i].remove(group2->GetID()); } } } } m_queueLock.Release(); m_instanceLock.Release(); }