Advertisement
EmuDevs

BattlegroundQueue.cpp GvG

Feb 26th, 2014
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 65.41 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
  3.  * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2 of the License, or (at your
  8.  * option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful, but WITHOUT
  11.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12.  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13.  * more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program. If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include "ArenaTeam.h"
  20. #include "ArenaTeamMgr.h"
  21. #include "BattlegroundMgr.h"
  22. #include "BattlegroundQueue.h"
  23. #include "Chat.h"
  24. #include "Group.h"
  25. #include "Log.h"
  26. #include "Language.h"
  27. #include "ObjectMgr.h"
  28. #include "Player.h"
  29.  
  30. /*********************************************************/
  31. /***            BATTLEGROUND QUEUE SYSTEM              ***/
  32. /*********************************************************/
  33.  
  34. BattlegroundQueue::BattlegroundQueue()
  35. {
  36.     for (uint32 i = 0; i < BG_TEAMS_COUNT; ++i)
  37.     {
  38.         for (uint32 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j)
  39.         {
  40.             m_SumOfWaitTimes[i][j] = 0;
  41.             m_WaitTimeLastPlayer[i][j] = 0;
  42.             for (uint32 k = 0; k < COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME; ++k)
  43.                 m_WaitTimes[i][j][k] = 0;
  44.         }
  45.     }
  46. }
  47.  
  48. BattlegroundQueue::~BattlegroundQueue()
  49. {
  50.     m_events.KillAllEvents(false);
  51.  
  52.     for (int i = 0; i < MAX_BATTLEGROUND_BRACKETS; ++i)
  53.     {
  54.         for (uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; ++j)
  55.         {
  56.             for (uint32 k = 0; k < BG_QUEUE_GROUP_TYPES_GUILD; ++k)
  57.             {
  58.                 for (GroupsQueueType::iterator itr = m_QueuedGroups[i][j][k].begin(); itr!= m_QueuedGroups[i][j][k].end(); ++itr)
  59.                     delete (*itr);
  60.                 m_QueuedGroups[i][j][k].clear();
  61.             }
  62.         }
  63.     }
  64. }
  65.  
  66. /*********************************************************/
  67. /***      BATTLEGROUND QUEUE SELECTION POOLS           ***/
  68. /*********************************************************/
  69.  
  70. // selection pool initialization, used to clean up from prev selection
  71. void BattlegroundQueue::SelectionPool::Init()
  72. {
  73.     SelectedGroups.clear();
  74.     PlayerCount = 0;
  75. }
  76.  
  77. // remove group info from selection pool
  78. // returns true when we need to try to add new group to selection pool
  79. // returns false when selection pool is ok or when we kicked smaller group than we need to kick
  80. // sometimes it can be called on empty selection pool
  81. bool BattlegroundQueue::SelectionPool::KickGroup(uint32 size)
  82. {
  83.     //find maxgroup or LAST group with size == size and kick it
  84.     bool found = false;
  85.     GroupsQueueType::iterator groupToKick = SelectedGroups.begin();
  86.     for (GroupsQueueType::iterator itr = groupToKick; itr != SelectedGroups.end(); ++itr)
  87.     {
  88.         if (abs((int32)((*itr)->Players.size() - size)) <= 1)
  89.         {
  90.             groupToKick = itr;
  91.             found = true;
  92.         }
  93.         else if (!found && (*itr)->Players.size() >= (*groupToKick)->Players.size())
  94.             groupToKick = itr;
  95.     }
  96.     //if pool is empty, do nothing
  97.     if (GetPlayerCount())
  98.     {
  99.         //update player count
  100.         GroupQueueInfo* ginfo = (*groupToKick);
  101.         SelectedGroups.erase(groupToKick);
  102.         PlayerCount -= ginfo->Players.size();
  103.         //return false if we kicked smaller group or there are enough players in selection pool
  104.         if (ginfo->Players.size() <= size + 1)
  105.             return false;
  106.     }
  107.     return true;
  108. }
  109.  
  110. // add group to selection pool
  111. // used when building selection pools
  112. // returns true if we can invite more players, or when we added group to selection pool
  113. // returns false when selection pool is full
  114. bool BattlegroundQueue::SelectionPool::AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount)
  115. {
  116.     //if group is larger than desired count - don't allow to add it to pool
  117.     if (!ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size())
  118.     {
  119.         SelectedGroups.push_back(ginfo);
  120.         // increase selected players count
  121.         PlayerCount += ginfo->Players.size();
  122.         return true;
  123.     }
  124.     if (PlayerCount < desiredCount)
  125.         return true;
  126.     return false;
  127. }
  128.  
  129. /*********************************************************/
  130. /***               BATTLEGROUND QUEUES                 ***/
  131. /*********************************************************/
  132.  
  133. // add group or player (grp == NULL) to bg queue with the given leader and bg specifications
  134. GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, BattlegroundTypeId BgTypeId, PvPDifficultyEntry const*  bracketEntry, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 arenateamid, uint32 guildId)
  135. {
  136.     BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
  137.  
  138.     // create new ginfo
  139.     GroupQueueInfo* ginfo            = new GroupQueueInfo;
  140.     ginfo->BgTypeId                  = BgTypeId;
  141.     ginfo->ArenaType                 = ArenaType;
  142.     ginfo->ArenaTeamId               = arenateamid;
  143.     ginfo->IsRated                   = isRated;
  144.     ginfo->IsInvitedToBGInstanceGUID = 0;
  145.     ginfo->JoinTime                  = getMSTime();
  146.     ginfo->RemoveInviteTime          = 0;
  147.     ginfo->Team                      = leader->GetBGTeam();
  148.     ginfo->ArenaTeamRating           = ArenaRating;
  149.     ginfo->ArenaMatchmakerRating     = MatchmakerRating;
  150.     ginfo->OpponentsTeamRating       = 0;
  151.     ginfo->OpponentsMatchmakerRating = 0;
  152.     ginfo->guildId                   = guildId;
  153.  
  154.     ginfo->Players.clear();
  155.  
  156.     //compute index (if group is premade or joined a rated match) to queues
  157.     uint32 index = 0;
  158.     if (!isRated && !isPremade)
  159.         index += BG_TEAMS_COUNT;
  160.     if (ginfo->Team == HORDE)
  161.         index++;
  162.     if (ArenaType == 0)
  163.         index = BG_CROSS_FACTION;
  164.     sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Adding Group to BattlegroundQueue bgTypeId : %u, bracket_id : %u, index : %u", BgTypeId, bracketId, index);
  165.  
  166.     uint32 lastOnlineTime = getMSTime();
  167.  
  168.     //announce world (this don't need mutex)
  169.     if (isRated && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
  170.     {
  171.         ArenaTeam* Team = sArenaTeamMgr->GetArenaTeamById(arenateamid);
  172.         if (Team)
  173.             sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, Team->GetName().c_str(), ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
  174.     }
  175.  
  176.     //add players from group to ginfo
  177.     if (grp)
  178.     {
  179.         for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
  180.         {
  181.             Player* member = itr->getSource();
  182.             if (!member)
  183.                 continue;   // this should never happen
  184.             PlayerQueueInfo& pl_info = m_QueuedPlayers[member->GetGUID()];
  185.             pl_info.LastOnlineTime   = lastOnlineTime;
  186.             pl_info.GroupInfo        = ginfo;
  187.             // add the pinfo to ginfo's list
  188.             ginfo->Players[member->GetGUID()]  = &pl_info;
  189.         }
  190.     }
  191.     else
  192.     {
  193.         PlayerQueueInfo& pl_info = m_QueuedPlayers[leader->GetGUID()];
  194.         pl_info.LastOnlineTime   = lastOnlineTime;
  195.         pl_info.GroupInfo        = ginfo;
  196.         ginfo->Players[leader->GetGUID()]  = &pl_info;
  197.     }
  198.  
  199.     //add GroupInfo to m_QueuedGroups
  200.     {
  201.         //ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_Lock);
  202.         if (guildId > 0)
  203.             m_QueuedGroups[bracketId][index][BG_QUEUE_GUILD].push_back(ginfo);
  204.         else
  205.             m_QueuedGroups[bracketId][index][BG_QUEUE_NOT_GUILD].push_back(ginfo);
  206.  
  207.         //announce to world, this code needs mutex
  208.         if (!isRated && !isPremade && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
  209.         {
  210.             if (Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(ginfo->BgTypeId))
  211.             {
  212.                 char const* bgName = bg->GetName();
  213.                 uint32 MinPlayers = bg->GetMinPlayersPerTeam()*2;
  214.                 uint32 qHorde = 0;
  215.                 uint32 qAlliance = 0;
  216.                 uint32 bgPlayers = 0;
  217.                 uint32 q_min_level = bracketEntry->minLevel;
  218.                 uint32 q_max_level = bracketEntry->maxLevel;
  219.                 GroupsQueueType::const_iterator itr;
  220.                 if (guildId > 0)
  221.                 {
  222.                     for (itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_GUILD].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_GUILD].end(); ++itr)
  223.                         if (!(*itr)->IsInvitedToBGInstanceGUID)
  224.                             qAlliance += (*itr)->Players.size();
  225.                     for (itr = m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_GUILD].begin(); itr != m_QueuedGroups[bracketId][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_GUILD].end(); ++itr)
  226.                         if (!(*itr)->IsInvitedToBGInstanceGUID)
  227.                             qHorde += (*itr)->Players.size();
  228.                 }
  229.                 else
  230.                 {
  231.                     for (GroupsQueueType::const_iterator itr = m_QueuedGroups[bracketId][BG_CROSS_FACTION][BG_QUEUE_NOT_GUILD].begin(); itr != m_QueuedGroups[bracketId][BG_CROSS_FACTION][BG_QUEUE_NOT_GUILD].end(); ++itr)
  232.                         if (!(*itr)->IsInvitedToBGInstanceGUID)
  233.                             bgPlayers += (*itr)->Players.size();
  234.                 }
  235.  
  236.                 // Show queue status to player only (when joining queue)
  237.                 if (sWorld->getBoolConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY))
  238.                 {
  239.                     ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName, q_min_level, q_max_level,
  240.                         qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
  241.                 }
  242.                 // System message
  243.                 else
  244.                 {
  245.                     sWorld->SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level,
  246.                         qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
  247.                 }
  248.             }
  249.         }
  250.         //release mutex
  251.     }
  252.  
  253.     return ginfo;
  254. }
  255.  
  256. void BattlegroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BattlegroundBracketId bracket_id)
  257. {
  258.     uint32 timeInQueue = getMSTimeDiff(ginfo->JoinTime, getMSTime());
  259.     uint8 team_index = TEAM_ALLIANCE;                    //default set to TEAM_ALLIANCE - or non rated arenas!
  260.     if (!ginfo->ArenaType)
  261.     {
  262.         if (ginfo->Team == HORDE)
  263.             team_index = TEAM_HORDE;
  264.     }
  265.     else
  266.     {
  267.         if (ginfo->IsRated)
  268.             team_index = TEAM_HORDE;                     //for rated arenas use TEAM_HORDE
  269.     }
  270.  
  271.     //store pointer to arrayindex of player that was added first
  272.     uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][bracket_id]);
  273.     //remove his time from sum
  274.     m_SumOfWaitTimes[team_index][bracket_id] -= m_WaitTimes[team_index][bracket_id][(*lastPlayerAddedPointer)];
  275.     //set average time to new
  276.     m_WaitTimes[team_index][bracket_id][(*lastPlayerAddedPointer)] = timeInQueue;
  277.     //add new time to sum
  278.     m_SumOfWaitTimes[team_index][bracket_id] += timeInQueue;
  279.     //set index of last player added to next one
  280.     (*lastPlayerAddedPointer)++;
  281.     (*lastPlayerAddedPointer) %= COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME;
  282. }
  283.  
  284. uint32 BattlegroundQueue::GetAverageQueueWaitTime(GroupQueueInfo* ginfo, BattlegroundBracketId bracket_id) const
  285. {
  286.     uint8 team_index = TEAM_ALLIANCE;                    //default set to TEAM_ALLIANCE - or non rated arenas!
  287.     if (!ginfo->ArenaType)
  288.     {
  289.         if (ginfo->Team == HORDE)
  290.             team_index = TEAM_HORDE;
  291.     }
  292.     else
  293.     {
  294.         if (ginfo->IsRated)
  295.             team_index = TEAM_HORDE;                     //for rated arenas use TEAM_HORDE
  296.     }
  297.     //check if there is enought values(we always add values > 0)
  298.     if (m_WaitTimes[team_index][bracket_id][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1])
  299.         return (m_SumOfWaitTimes[team_index][bracket_id] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME);
  300.     else
  301.         //if there aren't enough values return 0 - not available
  302.         return 0;
  303. }
  304.  
  305. //remove player from queue and from group info, if group info is empty then remove it too
  306. void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
  307. {
  308.     //Player* player = ObjectAccessor::FindPlayer(guid);
  309.  
  310.     int32 bracket_id = -1;                                     // signed for proper for-loop finish
  311.     QueuedPlayersMap::iterator itr;
  312.  
  313.     //remove player from map, if he's there
  314.     itr = m_QueuedPlayers.find(guid);
  315.     if (itr == m_QueuedPlayers.end())
  316.     {
  317.         sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue: couldn't find player to remove GUID: %u", GUID_LOPART(guid));
  318.         return;
  319.     }
  320.  
  321.     GroupQueueInfo* group = itr->second.GroupInfo;
  322.     GroupsQueueType::iterator group_itr;
  323.     // mostly people with the highest levels are in battlegrounds, thats why
  324.     // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0
  325.  
  326.     uint32 index = (group->Team == HORDE) ? BG_QUEUE_PREMADE_HORDE : BG_QUEUE_PREMADE_ALLIANCE;
  327.  
  328.     for (int32 bracket_id_tmp = MAX_BATTLEGROUND_BRACKETS - 1; bracket_id_tmp >= 0 && bracket_id == -1; --bracket_id_tmp)
  329.     {
  330.         //we must check premade and normal team's queue - because when players from premade are joining bg,
  331.         //they leave groupinfo so we can't use its players size to find out index
  332.         for (uint32 l = index; l < BG_QUEUE_GROUP_TYPES_COUNT; ++l)
  333.         {
  334.             for (uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_GUILD; ++j)
  335.             {
  336.                 for (group_itr = m_QueuedGroups[bracket_id_tmp][l][j].begin(); group_itr != m_QueuedGroups[bracket_id_tmp][l][j].end(); ++group_itr)
  337.                 {
  338.                     if ((*group_itr) == group)
  339.                     {
  340.                         bracket_id = bracket_id_tmp;
  341.                         group_itr = group_itr;
  342.                         //we must store index to be able to erase iterator
  343.                         index = l;
  344.                         break;
  345.                     }
  346.                 }
  347.            }
  348.         }
  349.     }
  350.  
  351.     //player can't be in queue without group, but just in case
  352.     if (bracket_id == -1)
  353.     {
  354.         sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid));
  355.         return;
  356.     }
  357.     sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue: Removing player GUID %u, from bracket_id %u", GUID_LOPART(guid), (uint32)bracket_id);
  358.  
  359.     // ALL variables are correctly set
  360.     // We can ignore leveling up in queue - it should not cause crash
  361.     // remove player from group
  362.     // if only one player there, remove group
  363.  
  364.     // remove player queue info from group queue info
  365.     std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid);
  366.     if (pitr != group->Players.end())
  367.         group->Players.erase(pitr);
  368.  
  369.     // if invited to bg, and should decrease invited count, then do it
  370.     if (decreaseInvitedCount && group->IsInvitedToBGInstanceGUID)
  371.         if (Battleground* bg = sBattlegroundMgr->GetBattleground(group->IsInvitedToBGInstanceGUID, group->BgTypeId))
  372.             bg->DecreaseInvitedCount(group->Team);
  373.  
  374.     // remove player queue info
  375.     m_QueuedPlayers.erase(itr);
  376.  
  377.     // announce to world if arena team left queue for rated match, show only once
  378.     if (group->ArenaType && group->IsRated && group->Players.empty() && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
  379.         if (ArenaTeam* Team = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
  380.             sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, Team->GetName().c_str(), group->ArenaType, group->ArenaType, group->ArenaTeamRating);
  381.  
  382.     // if player leaves queue and he is invited to rated arena match, then he have to lose
  383.     if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount)
  384.     {
  385.         if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
  386.         {
  387.             sLog->outDebug(LOG_FILTER_BATTLEGROUND, "UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating);
  388.             if (Player* player = ObjectAccessor::FindPlayer(guid))
  389.             {
  390.                 at->MemberLost(player, group->ArenaMatchmakerRating, group->OpponentsMatchmakerRating);
  391.             }
  392.             else
  393.                 at->OfflineMemberLost(guid, group->ArenaMatchmakerRating, group->OpponentsMatchmakerRating);
  394.  
  395.             at->SaveToDB();
  396.         }
  397.     }
  398.  
  399.     // remove group queue info if needed
  400.     if (group->Players.empty())
  401.     {
  402.         if (group->guildId > 0)
  403.             m_QueuedGroups[bracket_id][index][BG_QUEUE_GUILD].erase(group_itr);
  404.         else
  405.             m_QueuedGroups[bracket_id][index][BG_QUEUE_NOT_GUILD].erase(group_itr);
  406.         delete group;
  407.         return;
  408.     }
  409.  
  410.     // if group wasn't empty, so it wasn't deleted, and player have left a rated
  411.     // queue -> everyone from the group should leave too
  412.     // don't remove recursively if already invited to bg!
  413.     if (!group->IsInvitedToBGInstanceGUID && group->IsRated)
  414.     {
  415.         // remove next player, this is recursive
  416.         // first send removal information
  417.         if (Player* plr2 = ObjectAccessor::FindPlayer(group->Players.begin()->first))
  418.         {
  419.             Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId);
  420.             BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType);
  421.             uint32 queueSlot = plr2->GetBattlegroundQueueIndex(bgQueueTypeId);
  422.  
  423.             plr2->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
  424.                                                             // queue->removeplayer, it causes bugs
  425.             WorldPacket data;
  426.             sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, plr2, queueSlot, STATUS_NONE, plr2->GetBattlegroundQueueJoinTime(group->BgTypeId), 0, 0);
  427.             plr2->GetSession()->SendPacket(&data);
  428.         }
  429.         // then actually delete, this may delete the group as well!
  430.         RemovePlayer(group->Players.begin()->first, decreaseInvitedCount);
  431.     }
  432. }
  433.  
  434. //returns true when player pl_guid is in queue and is invited to bgInstanceGuid
  435. bool BattlegroundQueue::IsPlayerInvited(uint64 pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime)
  436. {
  437.     QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(pl_guid);
  438.     return (qItr != m_QueuedPlayers.end()
  439.         && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == bgInstanceGuid
  440.         && qItr->second.GroupInfo->RemoveInviteTime == removeTime);
  441. }
  442.  
  443. bool BattlegroundQueue::GetPlayerGroupInfoData(uint64 guid, GroupQueueInfo* ginfo)
  444. {
  445.     QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(guid);
  446.     if (qItr == m_QueuedPlayers.end())
  447.         return false;
  448.     *ginfo = *(qItr->second.GroupInfo);
  449.     return true;
  450. }
  451.  
  452. uint32 BattlegroundQueue::GetPlayersInQueue(TeamId id)
  453. {
  454.     return m_SelectionPools[id].GetPlayerCount();
  455. }
  456.  
  457. bool BattlegroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, Battleground* bg, uint32 side)
  458. {
  459.     // set side if needed
  460.     if (side)
  461.         ginfo->Team = side;
  462.  
  463.     if (!ginfo->IsInvitedToBGInstanceGUID)
  464.     {
  465.         // not yet invited
  466.         // set invitation
  467.         ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID();
  468.         BattlegroundTypeId bgTypeId = bg->GetTypeID();
  469.         BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, bg->GetArenaType());
  470.         BattlegroundBracketId bracket_id = bg->GetBracketId();
  471.  
  472.         // set ArenaTeamId for rated matches
  473.         if (bg->isArena() && bg->isRated())
  474.             bg->SetArenaTeamIdForTeam(ginfo->Team, ginfo->ArenaTeamId);
  475.  
  476.         ginfo->RemoveInviteTime = getMSTime() + INVITE_ACCEPT_WAIT_TIME;
  477.  
  478.         // loop through the players
  479.         for (std::map<uint64, PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
  480.         {
  481.             // get the player
  482.             Player* player = ObjectAccessor::FindPlayer(itr->first);
  483.             // if offline, skip him, this should not happen - player is removed from queue when he logs out
  484.             if (!player)
  485.                 continue;
  486.  
  487.             // invite the player
  488.             PlayerInvitedToBGUpdateAverageWaitTime(ginfo, bracket_id);
  489.             //sBattlegroundMgr->InvitePlayer(player, bg, ginfo->Team);
  490.  
  491.             // set invited player counters
  492.             bg->IncreaseInvitedCount(ginfo->Team);
  493.  
  494.             player->SetInviteForBattlegroundQueueType(bgQueueTypeId, ginfo->IsInvitedToBGInstanceGUID);
  495.  
  496.             // create remind invite events
  497.             BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime);
  498.             m_events.AddEvent(inviteEvent, m_events.CalculateTime(INVITATION_REMIND_TIME));
  499.             // create automatic remove events
  500.             BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime);
  501.             m_events.AddEvent(removeEvent, m_events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
  502.  
  503.             WorldPacket data;
  504.  
  505.             uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
  506.  
  507.             sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: invited player %s (%u) to BG instance %u queueindex %u bgtype %u",
  508.                  player->GetName().c_str(), player->GetGUIDLow(), bg->GetInstanceID(), queueSlot, bg->GetTypeID());
  509.  
  510.             // send status packet
  511.             sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, player->GetBattlegroundQueueJoinTime(bgTypeId), ginfo->ArenaType);
  512.             player->GetSession()->SendPacket(&data);
  513.         }
  514.         return true;
  515.     }
  516.  
  517.     return false;
  518. }
  519.  
  520. /*
  521. This function is inviting players to already running battlegrounds
  522. Invitation type is based on config file
  523. large groups are disadvantageous, because they will be kicked first if invitation type = 1
  524. */
  525. void BattlegroundQueue::FillPlayersToBG(Battleground* bg, BattlegroundBracketId bracket_id, bool GuildvsGuild)
  526. {
  527.     int32 hordeFree = bg->GetFreeSlotsForTeam(HORDE);
  528.     int32 aliFree   = bg->GetFreeSlotsForTeam(ALLIANCE);
  529.  
  530.     uint32 aliCount = 0;
  531.     uint32 aliIndex = 0;
  532.     uint32 hordeCount = 0;
  533.     uint32 hordeIndex = 0;
  534.  
  535.     if (!bg->isArena())
  536.         if (CanFillPlayersToBGForCrossFaction(bg, bracket_id, false))
  537.             return;
  538.  
  539.     GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_GUILD].begin();
  540.     GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_GUILD].begin();
  541.     //iterator for iterating through bg queue
  542.     if (GuildvsGuild)
  543.     {
  544.         for (; Ali_itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_GUILD].end(); ++Ali_itr)
  545.         {
  546.             if ((*Ali_itr)->guildId == bg->getGuildIdFirst())
  547.             {
  548.                 if (!m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree))
  549.                     break;
  550.             }
  551.         }
  552.  
  553.         for (; Horde_itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_GUILD].end(); ++Horde_itr)
  554.         {
  555.             if ((*Horde_itr)->guildId == bg->getGuildIdSecond())
  556.             {
  557.                 if (!m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree))
  558.                     break;
  559.             }
  560.         }
  561.     }
  562.     else
  563.     {
  564.         Ali_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_NOT_GUILD].begin();
  565.         Horde_itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_NOT_GUILD].begin();
  566.  
  567.         aliCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_NOT_GUILD].size();
  568.         for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++)
  569.             ++Ali_itr;
  570.  
  571.         hordeCount = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_NOT_GUILD].size();
  572.         for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); hordeIndex++)
  573.             ++Horde_itr;
  574.     }
  575.  
  576.     //if ofc like BG queue invitation is set in config, then we are happy
  577.     if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) == 0)
  578.         return;
  579.  
  580.     /*
  581.     if we reached this code, then we have to solve NP - complete problem called Subset sum problem
  582.     So one solution is to check all possible invitation subgroups, or we can use these conditions:
  583.     1. Last time when BattlegroundQueue::Update was executed we invited all possible players - so there is only small possibility
  584.         that we will invite now whole queue, because only 1 change has been made to queues from the last BattlegroundQueue::Update call
  585.     2. Other thing we should consider is group order in queue
  586.     */
  587.  
  588.     // At first we need to compare free space in bg and our selection pool
  589.     int32 diffAli   = aliFree   - int32(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
  590.     int32 diffHorde = hordeFree - int32(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
  591.     while (abs(diffAli - diffHorde) > 1 && (m_SelectionPools[TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() > 0))
  592.     {
  593.         //each cycle execution we need to kick at least 1 group
  594.         if (diffAli < diffHorde)
  595.         {
  596.             //kick alliance group, add to pool new group if needed
  597.             if (m_SelectionPools[TEAM_ALLIANCE].KickGroup(diffHorde - diffAli))
  598.             {
  599.                 if (GuildvsGuild)
  600.                 {
  601.                     for (; Ali_itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_GUILD].end(); ++Ali_itr)
  602.                     {
  603.                         if ((*Ali_itr)->guildId == bg->getGuildIdFirst())
  604.                             if (!m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0))
  605.                                 break;
  606.                     }
  607.                 }
  608.                 else
  609.                 {
  610.                     if (m_SelectionPools[TEAM_ALLIANCE].KickGroup(diffHorde - diffAli))
  611.                     {
  612.                         for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); aliIndex++)
  613.                             ++Ali_itr;
  614.                     }
  615.                 }
  616.             }
  617.             //if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
  618.             if (!m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
  619.             {
  620.                 if (aliFree <= diffHorde + 1)
  621.                     break;
  622.                 m_SelectionPools[TEAM_HORDE].KickGroup(diffHorde - diffAli);
  623.             }
  624.         }
  625.         else
  626.         {
  627.             //kick horde group, add to pool new group if needed
  628.             if (m_SelectionPools[TEAM_HORDE].KickGroup(diffAli - diffHorde))
  629.             {
  630.                 if (GuildvsGuild)
  631.                 {
  632.                     for (; Horde_itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_GUILD].end(); ++Horde_itr)
  633.                     {
  634.                         if ((*Horde_itr)->guildId == bg->getGuildIdSecond())
  635.                             if (!m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0))
  636.                                 break;
  637.                    }
  638.                 }
  639.                 else
  640.                 {
  641.                     if (m_SelectionPools[TEAM_HORDE].KickGroup(diffAli - diffHorde))
  642.                     {
  643.                         for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); hordeIndex++)
  644.                             ++Horde_itr;
  645.                     }
  646.                 }
  647.             }
  648.             if (!m_SelectionPools[TEAM_HORDE].GetPlayerCount())
  649.             {
  650.                 if (hordeFree <= diffAli + 1)
  651.                     break;
  652.                  m_SelectionPools[TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
  653.             }
  654.         }
  655.         //count diffs after small update
  656.         diffAli   = aliFree   - int32(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
  657.         diffHorde = hordeFree - int32(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
  658.     }
  659. }
  660.  
  661. // this method checks if premade versus premade battleground is possible
  662. // then after 30 mins (default) in queue it moves premade group to normal queue
  663. // it tries to invite as much players as it can - to MaxPlayersPerTeam, because premade groups have more than MinPlayersPerTeam players
  664. bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, bool GuildvsGuild)
  665. {
  666.     //check match
  667.     GroupsQueueType::const_iterator ali_group, horde_group;
  668.     bool empty = true;
  669.     bool end = true;
  670.     uint32 guildId[BG_QUEUE_GROUP_TYPES_GUILD];
  671.     guildId[TEAM_ALLIANCE] = 0;
  672.     guildId[TEAM_HORDE] = 0;
  673.  
  674.     if (GuildvsGuild)
  675.     {
  676.         if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_GUILD].empty() && !m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_GUILD].empty())
  677.         {
  678.             empty = false;
  679.             //start premade match
  680.             //if groups aren't invited
  681.             for (ali_group = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_GUILD].begin(); ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_GUILD].end(); ++ali_group)
  682.                 if (!(*ali_group)->IsInvitedToBGInstanceGUID)
  683.                 {
  684.                     guildId[0] = (*ali_group)->guildId;
  685.                     break;
  686.                 }
  687.  
  688.             for (horde_group = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_GUILD].begin(); horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_GUILD].end(); ++horde_group)
  689.                 if (!(*horde_group)->IsInvitedToBGInstanceGUID)
  690.                 {
  691.                     guildId[1] = (*horde_group)->guildId;
  692.                     break;
  693.                 }
  694.         }
  695.     }
  696.     else
  697.     {
  698.         if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].empty() && !m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].empty())
  699.         {
  700.             empty = false;
  701.             //start premade match
  702.             //if groups aren't invited
  703.             for (ali_group = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].begin(); ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].end(); ++ali_group)
  704.                 if (!(*ali_group)->IsInvitedToBGInstanceGUID)
  705.                     break;
  706.  
  707.             for (horde_group = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].begin(); horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].end(); ++horde_group)
  708.                 if (!(*horde_group)->IsInvitedToBGInstanceGUID)
  709.                     break;
  710.         }
  711.     }
  712.  
  713.     if (!empty)
  714.     {
  715.         if (GuildvsGuild)
  716.         {
  717.             if (ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_GUILD].end() && horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_GUILD].end())
  718.                 end = false;
  719.             else
  720.                 if (ali_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].end() && horde_group != m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].end())
  721.                     end = false;
  722.         }
  723.  
  724.         if (!end)
  725.         {
  726.             m_SelectionPools[TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam);
  727.             m_SelectionPools[TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam);
  728.             uint32 maxPlayers = std::min(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount(), m_SelectionPools[TEAM_HORDE].GetPlayerCount());
  729.             GroupsQueueType::const_iterator itr;
  730.             if (GuildvsGuild)
  731.             {
  732.                 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  733.                 {
  734.                     for (itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_GUILD].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_GUILD].end(); ++itr)
  735.                     {
  736.                         if ((*itr)->guildId == guildId[i])
  737.                             if (!(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers))
  738.                                 break;
  739.                     }
  740.                 }
  741.             }
  742.             else
  743.             {
  744.                 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  745.                 {
  746.                     for (itr = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_NOT_GUILD].begin(); itr != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_NOT_GUILD].end(); ++itr)
  747.                         if (!(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers))
  748.                             break;
  749.                 }
  750.             }
  751.        }
  752.  
  753.         // now check if we can move group from Premade queue to normal queue (timer has expired) or group size lowered!!
  754.         // this could be 2 cycles but i'm checking only first team in queue - it can cause problem -
  755.         // if first is invited to BG and seconds timer expired, but we can ignore it, because players have only 80 seconds to click to enter bg
  756.         // and when they click or after 80 seconds the queue info is removed from queue
  757.         uint32 time_before = getMSTime() - sWorld->getIntConfig(CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
  758.         for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  759.         {
  760.             for (uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_GUILD; j++)
  761.             {
  762.                 if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i][j].empty())
  763.                 {
  764.                     GroupsQueueType::iterator itr = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i][j].begin();
  765.                     if (!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam))
  766.                     {
  767.                         //we must insert group to normal queue and erase pointer from premade queue
  768.                         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][j].push_front((*itr));
  769.                        m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i][j].erase(itr);
  770.                     }
  771.                 }
  772.             }
  773.         }
  774.     }
  775.     //selection pools are not set
  776.     return false;
  777. }
  778.  
  779. // this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam
  780. bool BattlegroundQueue::CheckNormalMatch(Battleground* bg_template, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers, bool GuildvsGuild)
  781. {
  782.     GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT];
  783.     uint32 guildId[BG_QUEUE_GROUP_TYPES_GUILD];
  784.  
  785.     if (GuildvsGuild)
  786.     {
  787.         for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  788.         {
  789.             guildId[i] = 0;
  790.             itr_team[i] = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_GUILD].begin();
  791.             for (; itr_team[i] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_GUILD].end(); ++(itr_team[i]))
  792.             {
  793.                 if (!(*(itr_team[i]))->IsInvitedToBGInstanceGUID)
  794.                 {
  795.                     if (guildId[i] > 0 && guildId[i] != (*(itr_team[i]))->guildId)
  796.                         continue;
  797.                     guildId[i] = (*(itr_team[i]))->guildId;
  798.                     m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
  799.                     if (m_SelectionPools[i].GetPlayerCount() >= minPlayers)
  800.                         break;
  801.                 }
  802.             }
  803.         }
  804.     }
  805.     else
  806.     {
  807.         for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  808.         {
  809.             itr_team[i] = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_NOT_GUILD].begin();
  810.             for (; itr_team[i] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + i][BG_QUEUE_NOT_GUILD].end(); ++(itr_team[i]))
  811.             {
  812.                 if (!(*(itr_team[i]))->IsInvitedToBGInstanceGUID)
  813.                 {
  814.                     m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
  815.                     if (m_SelectionPools[i].GetPlayerCount() >= minPlayers)
  816.                         break;
  817.                 }
  818.             }
  819.         }
  820.     }
  821.     //try to invite same number of players - this cycle may cause longer wait time even if there are enough players in queue, but we want ballanced bg
  822.     uint32 j = TEAM_ALLIANCE;
  823.     if (m_SelectionPools[TEAM_HORDE].GetPlayerCount() < m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
  824.         j = TEAM_HORDE;
  825.     if (sWorld->getIntConfig(CONFIG_BATTLEGROUND_INVITATION_TYPE) != 0
  826.         && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers)
  827.     {
  828.         if (GuildvsGuild)
  829.         {
  830.             //we will try to invite more groups to team with less players indexed by j
  831.             ++(itr_team[j]);                                         //this will not cause a crash, because for cycle above reached break;
  832.             for (; itr_team[j] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + j][BG_QUEUE_GUILD].end(); ++(itr_team[j]))
  833.             {
  834.                 if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID)
  835.                     if (guildId[j] == (*(itr_team[j]))->guildId)
  836.                         if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()))
  837.                             break;
  838.             }
  839.         }
  840.         else
  841.         {
  842.             //we will try to invite more groups to team with less players indexed by j
  843.             ++(itr_team[j]);                                         //this will not cause a crash, because for cycle above reached break;
  844.             for (; itr_team[j] != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + j][BG_QUEUE_NOT_GUILD].end(); ++(itr_team[j]))
  845.             {
  846.                 if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID)
  847.                     if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()))
  848.                         break;
  849.             }
  850.         }
  851.         // do not allow to start bg with more than 2 players more on 1 faction
  852.         if (abs((int32)(m_SelectionPools[TEAM_HORDE].GetPlayerCount() - m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())) > 2)
  853.             return false;
  854.     }
  855.     //allow 1v0 if debug bg
  856.     if (sBattlegroundMgr->isTesting() && bg_template->isBattleground() && GuildvsGuild)
  857.     {
  858.         uint32 i;
  859.         if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
  860.             i = TEAM_ALLIANCE;
  861.         else if (m_SelectionPools[TEAM_HORDE].GetPlayerCount())
  862.             i = TEAM_HORDE;
  863.        
  864.         GroupsQueueType::const_iterator itr = m_SelectionPools[i].SelectedGroups.begin();
  865.         if (GuildvsGuild && (*itr)->guildId > 0)
  866.             return true;
  867.         else if (!GuildvsGuild && (*itr)->guildId == 0)
  868.             return true;
  869.     }
  870.  
  871.     if (sBattlegroundMgr->isTesting() && !GuildvsGuild && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
  872.         return true;
  873.     //return true if there are enough players in selection pools - enable to work .debug bg command correctly
  874.     if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers && GuildvsGuild)
  875.     {
  876.         GroupsQueueType::const_iterator alliance = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.begin();
  877.         GroupsQueueType::const_iterator horde = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.begin();
  878.         if (GuildvsGuild && (*alliance)->guildId > 0 && (*horde)->guildId > 0)
  879.             return true;
  880.         return false;
  881.     }
  882.     return m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers;
  883. }
  884.  
  885. // this method will check if we can invite players to same faction skirmish match
  886. bool BattlegroundQueue::CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam)
  887. {
  888.     if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam)
  889.         return false;
  890.     uint32 teamIndex = TEAM_ALLIANCE;
  891.     uint32 otherTeam = TEAM_HORDE;
  892.     uint32 otherTeamId = HORDE;
  893.     if (m_SelectionPools[TEAM_HORDE].GetPlayerCount() == minPlayersPerTeam)
  894.     {
  895.         teamIndex = TEAM_HORDE;
  896.         otherTeam = TEAM_ALLIANCE;
  897.         otherTeamId = ALLIANCE;
  898.     }
  899.     //clear other team's selection
  900.     m_SelectionPools[otherTeam].Init();
  901.     //store last ginfo pointer
  902.     GroupQueueInfo* ginfo = m_SelectionPools[teamIndex].SelectedGroups.back();
  903.     //set itr_team to group that was added to selection pool latest
  904.     GroupsQueueType::iterator itr_team = m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex][BG_QUEUE_NOT_GUILD].begin();
  905.     for (; itr_team != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex][BG_QUEUE_NOT_GUILD].end(); ++itr_team)
  906.         if (ginfo == *itr_team)
  907.             break;
  908.     if (itr_team == m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex][BG_QUEUE_NOT_GUILD].end())
  909.         return false;
  910.     GroupsQueueType::iterator itr_team2 = itr_team;
  911.     ++itr_team2;
  912.     //invite players to other selection pool
  913.     for (; itr_team2 != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex][BG_QUEUE_NOT_GUILD].end(); ++itr_team2)
  914.     {
  915.         //if selection pool is full then break;
  916.         if (!(*itr_team2)->IsInvitedToBGInstanceGUID && !m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam))
  917.             break;
  918.     }
  919.     if (m_SelectionPools[otherTeam].GetPlayerCount() != minPlayersPerTeam)
  920.         return false;
  921.  
  922.     //here we have correct 2 selections and we need to change one teams team and move selection pool teams to other team's queue
  923.     for (GroupsQueueType::iterator itr = m_SelectionPools[otherTeam].SelectedGroups.begin(); itr != m_SelectionPools[otherTeam].SelectedGroups.end(); ++itr)
  924.     {
  925.         //set correct team
  926.         (*itr)->Team = otherTeamId;
  927.         //add team to other queue
  928.         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + otherTeam][BG_QUEUE_NOT_GUILD].push_front(*itr);
  929.         //remove team from old queue
  930.         GroupsQueueType::iterator itr2 = itr_team;
  931.         ++itr2;
  932.         for (; itr2 != m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex][BG_QUEUE_NOT_GUILD].end(); ++itr2)
  933.         {
  934.             if (*itr2 == *itr)
  935.             {
  936.                 m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex][BG_QUEUE_NOT_GUILD].erase(itr2);
  937.                 break;
  938.             }
  939.         }
  940.     }
  941.     return true;
  942. }
  943.  
  944. void BattlegroundQueue::UpdateEvents(uint32 diff)
  945. {
  946.     m_events.Update(diff);
  947. }
  948.  
  949. /*
  950. this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while (true) cycles to invite whole queue
  951. it must be called after fully adding the members of a group to ensure group joining
  952. should be called from Battleground::RemovePlayer function in some cases
  953. */
  954. void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating)
  955. {
  956.     //if no players in queue - do nothing
  957.     if (m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_GUILD].empty() &&
  958.         m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_GUILD].empty() &&
  959.         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_GUILD].empty() &&
  960.         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_GUILD].empty() &&
  961.         m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].empty() &&
  962.         m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].empty() &&
  963.         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_ALLIANCE][BG_QUEUE_NOT_GUILD].empty() &&
  964.         m_QueuedGroups[bracket_id][BG_QUEUE_NORMAL_HORDE][BG_QUEUE_NOT_GUILD].empty() &&
  965.         m_QueuedGroups[bracket_id][BG_CROSS_FACTION][BG_QUEUE_NOT_GUILD].empty())
  966.         return;
  967.  
  968.     // battleground with free slot for player should be always in the beggining of the queue
  969.     // maybe it would be better to create bgfreeslotqueue for each bracket_id
  970.     BGFreeSlotQueueContainer& bgQueues = sBattlegroundMgr->GetBGFreeSlotQueueStore(bgTypeId);
  971.     for (BGFreeSlotQueueContainer::iterator itr = bgQueues.begin(); itr != bgQueues.end();)
  972.     {
  973.         Battleground* bg = *itr; ++itr;
  974.         // DO NOT allow queue manager to invite new player to rated games
  975.         if (!bg->isRated() && bg->GetTypeID() == bgTypeId && bg->GetBracketId() == bracket_id &&
  976.             bg->GetStatus() > STATUS_WAIT_QUEUE && bg->GetStatus() < STATUS_WAIT_LEAVE)
  977.         {
  978.             // clear selection pools
  979.             m_SelectionPools[TEAM_ALLIANCE].Init();
  980.             m_SelectionPools[TEAM_HORDE].Init();
  981.  
  982.             // call a function that does the job for us
  983.             if (bg->IsGuildvsGuild())
  984.                 FillPlayersToBG(bg, bracket_id, true);
  985.             else
  986.                 FillPlayersToBG(bg, bracket_id, false);
  987.  
  988.             // now everything is set, invite players
  989.             for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.end(); ++citr)
  990.                 InviteGroupToBG((*citr), bg, (*citr)->Team);
  991.  
  992.             for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_HORDE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_HORDE].SelectedGroups.end(); ++citr)
  993.                 InviteGroupToBG((*citr), bg, (*citr)->Team);
  994.  
  995.             if (!bg->HasFreeSlots())
  996.                 bg->RemoveFromBGFreeSlotQueue();
  997.         }
  998.     }
  999.  
  1000.     // finished iterating through the bgs with free slots, maybe we need to create a new bg
  1001.  
  1002.     Battleground* bg_template = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
  1003.     if (!bg_template)
  1004.     {
  1005.         sLog->outError(LOG_FILTER_BATTLEGROUND, "Battleground: Update: bg template not found for %u", bgTypeId);
  1006.         return;
  1007.     }
  1008.  
  1009.     PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketById(bg_template->GetMapId(), bracket_id);
  1010.     if (!bracketEntry)
  1011.     {
  1012.         sLog->outError(LOG_FILTER_BATTLEGROUND, "Battleground: Update: bg bracket entry not found for map %u bracket id %u", bg_template->GetMapId(), bracket_id);
  1013.         return;
  1014.     }
  1015.  
  1016.     // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!)
  1017.     uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam();
  1018.     uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam();
  1019.  
  1020.     if (bg_template->isArena())
  1021.     {
  1022.         MaxPlayersPerTeam = arenaType;
  1023.         MinPlayersPerTeam = sBattlegroundMgr->isArenaTesting() ? 1 : arenaType;
  1024.     }
  1025.     else if (sBattlegroundMgr->isTesting())
  1026.         MinPlayersPerTeam = 1;
  1027.  
  1028.     m_SelectionPools[TEAM_ALLIANCE].Init();
  1029.     m_SelectionPools[TEAM_HORDE].Init();
  1030.  
  1031.     if (bg_template->isBattleground())
  1032.     {
  1033.         if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam))
  1034.         {
  1035.             // create new battleground
  1036.             Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, 0, false);
  1037.             if (!bg2)
  1038.             {
  1039.                 sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue::Update - Cannot create battleground: %u", bgTypeId);
  1040.                 return;
  1041.             }
  1042.             // invite those selection pools
  1043.             for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  1044.                 for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
  1045.                     InviteGroupToBG((*citr), bg2, (*citr)->Team);
  1046.  
  1047.             bg2->StartBattleground();
  1048.             //clear structures
  1049.             m_SelectionPools[TEAM_ALLIANCE].Init();
  1050.             m_SelectionPools[TEAM_HORDE].Init();
  1051.         }
  1052.  
  1053.         if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam, true))
  1054.         {
  1055.             uint32 guildIdFirst = 0;
  1056.             uint32 guildIdSecond = 0;
  1057.             bool check = true;
  1058.             for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.end(); ++citr)
  1059.             {
  1060.                 if (guildIdFirst > 0 && guildIdFirst != (*citr)->guildId)
  1061.                 {
  1062.                     check = false;
  1063.                     break;
  1064.                 }
  1065.                 guildIdFirst = (*citr)->guildId;
  1066.             }
  1067.  
  1068.             for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_HORDE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_HORDE].SelectedGroups.end(); ++citr)
  1069.             {
  1070.                 if (guildIdSecond > 0 && guildIdSecond != (*citr)->guildId)
  1071.                 {
  1072.                     check = false;
  1073.                     break;
  1074.                 }
  1075.                 guildIdSecond = (*citr)->guildId;
  1076.             }
  1077.  
  1078.             if (guildIdFirst > 0 && guildIdSecond > 0 && check)
  1079.             {
  1080.                 Battleground* battleGround = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, 0, false, guildIdFirst, guildIdSecond);
  1081.                 if (!battleGround)
  1082.                 {
  1083.                     sLog->outError(LOG_FILTER_GENERAL, "BattlegroundQueueUpdate::Cannot create battleground %u", bgTypeId);
  1084.                     return;
  1085.                 }
  1086.  
  1087.                 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  1088.                     for (GroupsQueueType::const_iterator itr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); itr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++itr)
  1089.                         InviteGroupToBG((*itr), battleGround, (*itr)->Team);
  1090.                 battleGround->StartBattleground();
  1091.             }
  1092.             m_SelectionPools[TEAM_ALLIANCE].Init();
  1093.             m_SelectionPools[TEAM_HORDE].Init();
  1094.         }
  1095.     }
  1096.  
  1097.     // now check if there are in queues enough players to start new game of (normal battleground, or non-rated arena)
  1098.     if (!isRated)
  1099.     {
  1100.         // if there are enough players in pools, start new battleground or non rated arena
  1101.         if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)
  1102.             || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam))
  1103.             || CheckCrossFactionMatch(bracket_id, bg_template))
  1104.         {
  1105.             // we successfully created a pool
  1106.             Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, false);
  1107.             if (!bg2)
  1108.             {
  1109.                 sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue::Update - Cannot create battleground: %u", bgTypeId);
  1110.                 return;
  1111.             }
  1112.  
  1113.             // invite those selection pools
  1114.             for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  1115.                 for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
  1116.                     InviteGroupToBG((*citr), bg2, (*citr)->Team);
  1117.             // start bg
  1118.             bg2->StartBattleground();
  1119.             m_SelectionPools[TEAM_ALLIANCE].Init();
  1120.             m_SelectionPools[TEAM_HORDE].Init();
  1121.         }
  1122.  
  1123.         if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam, true) && bg_template->isBattleground())
  1124.         {
  1125.             uint32 guildIdFirst = 0;
  1126.             uint32 guildIdSecond = 0;
  1127.             bool check = true;
  1128.  
  1129.             for (GroupsQueueType::const_iterator itr = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.end(); ++itr)
  1130.             {
  1131.                 if (guildIdFirst > 0 && guildIdFirst != (*itr)->guildId)
  1132.                 {
  1133.                     check = false;
  1134.                     break;
  1135.                 }
  1136.                 guildIdFirst = (*itr)->guildId;
  1137.             }
  1138.  
  1139.             for (GroupsQueueType::const_iterator itr = m_SelectionPools[TEAM_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[TEAM_HORDE].SelectedGroups.end(); ++itr)
  1140.             {
  1141.                 if (guildIdSecond > 0 && guildIdSecond != (*itr)->guildId)
  1142.                 {
  1143.                     check = false;
  1144.                     break;
  1145.                 }
  1146.                 guildIdSecond = (*itr)->guildId;
  1147.             }
  1148.  
  1149.             if (guildIdFirst > 0 || guildIdSecond > 0 && check)
  1150.             {
  1151.                 Battleground* battleGround = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, false, guildIdFirst, guildIdSecond);
  1152.                 if (!battleGround)
  1153.                 {
  1154.                     sLog->outError(LOG_FILTER_GENERAL, "BattlegroundQueueUpdate::Cannot create battleground %u", bgTypeId);
  1155.                     return;
  1156.                 }
  1157.  
  1158.                 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
  1159.                     for (GroupsQueueType::const_iterator itr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); itr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++itr)
  1160.                         InviteGroupToBG((*itr), battleGround, (*itr)->Team);
  1161.                 battleGround->StartBattleground();
  1162.             }
  1163.             m_SelectionPools[TEAM_ALLIANCE].Init();
  1164.             m_SelectionPools[TEAM_HORDE].Init();
  1165.         }
  1166.     }
  1167.     else if (bg_template->isArena())
  1168.     {
  1169.         // found out the minimum and maximum ratings the newly added team should battle against
  1170.         // arenaRating is the rating of the latest joined team, or 0
  1171.         // 0 is on (automatic update call) and we must set it to team's with longest wait time
  1172.         if (!arenaRating)
  1173.         {
  1174.             GroupQueueInfo* front1 = NULL;
  1175.             GroupQueueInfo* front2 = NULL;
  1176.             if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].empty())
  1177.             {
  1178.                 front1 = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].front();
  1179.                 arenaRating = front1->ArenaMatchmakerRating;
  1180.             }
  1181.             if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].empty())
  1182.             {
  1183.                 front2 = m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].front();
  1184.                 arenaRating = front2->ArenaMatchmakerRating;
  1185.             }
  1186.             if (front1 && front2)
  1187.             {
  1188.                 if (front1->JoinTime < front2->JoinTime)
  1189.                     arenaRating = front1->ArenaMatchmakerRating;
  1190.             }
  1191.             else if (!front1 && !front2)
  1192.                 return; //queues are empty
  1193.         }
  1194.  
  1195.         //set rating range
  1196.         uint32 arenaMinRating = (arenaRating <= sBattlegroundMgr->GetMaxRatingDifference()) ? 0 : arenaRating - sBattlegroundMgr->GetMaxRatingDifference();
  1197.         uint32 arenaMaxRating = arenaRating + sBattlegroundMgr->GetMaxRatingDifference();
  1198.         // if max rating difference is set and the time past since server startup is greater than the rating discard time
  1199.         // (after what time the ratings aren't taken into account when making teams) then
  1200.         // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
  1201.         // else leave the discard time on 0, this way all ratings will be discarded
  1202.         uint32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer();
  1203.  
  1204.         // we need to find 2 teams which will play next game
  1205.         GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT];
  1206.         uint8 found = 0;
  1207.         uint8 team = 0;
  1208.  
  1209.         for (uint8 i = BG_QUEUE_PREMADE_ALLIANCE; i < BG_QUEUE_NORMAL_ALLIANCE; i++)
  1210.         {
  1211.             // take the group that joined first
  1212.             GroupsQueueType::iterator itr2 = m_QueuedGroups[bracket_id][i][BG_QUEUE_NOT_GUILD].begin();
  1213.             for (; itr2 != m_QueuedGroups[bracket_id][i][BG_QUEUE_NOT_GUILD].end(); ++itr2)
  1214.             {
  1215.                 // if group match conditions, then add it to pool
  1216.                 if (!(*itr2)->IsInvitedToBGInstanceGUID
  1217.                     && (((*itr2)->ArenaMatchmakerRating >= arenaMinRating && (*itr2)->ArenaMatchmakerRating <= arenaMaxRating)
  1218.                         || (*itr2)->JoinTime < discardTime))
  1219.                 {
  1220.                     itr_teams[found++] = itr2;
  1221.                     team = i;
  1222.                     break;
  1223.                 }
  1224.             }
  1225.         }
  1226.  
  1227.         if (!found)
  1228.             return;
  1229.  
  1230.         if (found == 1)
  1231.         {
  1232.             for (GroupsQueueType::iterator itr3 = itr_teams[0]; itr3 != m_QueuedGroups[bracket_id][team][BG_QUEUE_NOT_GUILD].end(); ++itr3)
  1233.             {
  1234.                 if (!(*itr3)->IsInvitedToBGInstanceGUID
  1235.                     && (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating)
  1236.                         || (*itr3)->JoinTime < discardTime)
  1237.                     && (*itr_teams[0])->ArenaTeamId != (*itr3)->ArenaTeamId)
  1238.                 {
  1239.                     itr_teams[found++] = itr3;
  1240.                     break;
  1241.                 }
  1242.             }
  1243.         }
  1244.  
  1245.         //if we have 2 teams, then start new arena and invite players!
  1246.         if (found == 2)
  1247.         {
  1248.             GroupQueueInfo* aTeam = *itr_teams[TEAM_ALLIANCE];
  1249.             GroupQueueInfo* hTeam = *itr_teams[TEAM_HORDE];
  1250.             Battleground* arena = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, true);
  1251.             if (!arena)
  1252.             {
  1253.                 sLog->outError(LOG_FILTER_BATTLEGROUND, "BattlegroundQueue::Update couldn't create arena instance for rated arena match!");
  1254.                 return;
  1255.             }
  1256.  
  1257.             aTeam->OpponentsTeamRating = hTeam->ArenaTeamRating;
  1258.             hTeam->OpponentsTeamRating = aTeam->ArenaTeamRating;
  1259.             aTeam->OpponentsMatchmakerRating = hTeam->ArenaMatchmakerRating;
  1260.             hTeam->OpponentsMatchmakerRating = aTeam->ArenaMatchmakerRating;
  1261.             sLog->outDebug(LOG_FILTER_BATTLEGROUND, "setting oposite teamrating for team %u to %u", aTeam->ArenaTeamId, aTeam->OpponentsTeamRating);
  1262.             sLog->outDebug(LOG_FILTER_BATTLEGROUND, "setting oposite teamrating for team %u to %u", hTeam->ArenaTeamId, hTeam->OpponentsTeamRating);
  1263.  
  1264.             // now we must move team if we changed its faction to another faction queue, because then we will spam log by errors in Queue::RemovePlayer
  1265.             if (aTeam->Team != ALLIANCE)
  1266.             {
  1267.                 m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].push_front(aTeam);
  1268.                 m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].erase(itr_teams[TEAM_ALLIANCE]);
  1269.             }
  1270.             if (hTeam->Team != HORDE)
  1271.             {
  1272.                 m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_HORDE][BG_QUEUE_NOT_GUILD].push_front(hTeam);
  1273.                 m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE][BG_QUEUE_NOT_GUILD].erase(itr_teams[TEAM_HORDE]);
  1274.             }
  1275.  
  1276.             arena->SetArenaMatchmakerRating(ALLIANCE, aTeam->ArenaMatchmakerRating);
  1277.             arena->SetArenaMatchmakerRating(   HORDE, hTeam->ArenaMatchmakerRating);
  1278.             InviteGroupToBG(aTeam, arena, ALLIANCE);
  1279.             InviteGroupToBG(hTeam, arena, HORDE);
  1280.  
  1281.             sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Starting rated arena match!");
  1282.             arena->StartBattleground();
  1283.         }
  1284.     }
  1285. }
  1286.  
  1287. /*********************************************************/
  1288. /***            BATTLEGROUND QUEUE EVENTS              ***/
  1289. /*********************************************************/
  1290.  
  1291. bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
  1292. {
  1293.     Player* player = ObjectAccessor::FindPlayer(m_PlayerGuid);
  1294.     // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
  1295.     if (!player)
  1296.         return true;
  1297.  
  1298.     Battleground* bg = sBattlegroundMgr->GetBattleground(m_BgInstanceGUID, m_BgTypeId);
  1299.     //if battleground ended and its instance deleted - do nothing
  1300.     if (!bg)
  1301.         return true;
  1302.  
  1303.     BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
  1304.     uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
  1305.     if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)         // player is in queue or in battleground
  1306.     {
  1307.         // check if player is invited to this bg
  1308.         BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
  1309.         if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime))
  1310.         {
  1311.             WorldPacket data;
  1312.             //we must send remaining time in queue
  1313.             sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, player->GetBattlegroundQueueJoinTime(m_BgTypeId), m_ArenaType);
  1314.             player->GetSession()->SendPacket(&data);
  1315.         }
  1316.     }
  1317.     return true;                                            //event will be deleted
  1318. }
  1319.  
  1320. void BGQueueInviteEvent::Abort(uint64 /*e_time*/)
  1321. {
  1322.     //do nothing
  1323. }
  1324.  
  1325. /*
  1326.     this event has many possibilities when it is executed:
  1327.     1. player is in battleground (he clicked enter on invitation window)
  1328.     2. player left battleground queue and he isn't there any more
  1329.     3. player left battleground queue and he joined it again and IsInvitedToBGInstanceGUID = 0
  1330.     4. player left queue and he joined again and he has been invited to same battleground again -> we should not remove him from queue yet
  1331.     5. player is invited to bg and he didn't choose what to do and timer expired - only in this condition we should call queue::RemovePlayer
  1332.     we must remove player in the 5. case even if battleground object doesn't exist!
  1333. */
  1334. bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
  1335. {
  1336.     Player* player = ObjectAccessor::FindPlayer(m_PlayerGuid);
  1337.     if (!player)
  1338.         // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
  1339.         return true;
  1340.  
  1341.     Battleground* bg = sBattlegroundMgr->GetBattleground(m_BgInstanceGUID, m_BgTypeId);
  1342.     //battleground can be deleted already when we are removing queue info
  1343.     //bg pointer can be NULL! so use it carefully!
  1344.  
  1345.     uint32 queueSlot = player->GetBattlegroundQueueIndex(m_BgQueueTypeId);
  1346.     if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES)         // player is in queue, or in Battleground
  1347.     {
  1348.         // check if player is in queue for this BG and if we are removing his invite event
  1349.         BattlegroundQueue &bgQueue = sBattlegroundMgr->GetBattlegroundQueue(m_BgQueueTypeId);
  1350.         if (bgQueue.IsPlayerInvited(m_PlayerGuid, m_BgInstanceGUID, m_RemoveTime))
  1351.         {
  1352.             sLog->outDebug(LOG_FILTER_BATTLEGROUND, "Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.", player->GetGUIDLow(), m_BgInstanceGUID);
  1353.  
  1354.             player->RemoveBattlegroundQueueId(m_BgQueueTypeId);
  1355.             bgQueue.RemovePlayer(m_PlayerGuid, true);
  1356.             //update queues if battleground isn't ended
  1357.             if (bg && bg->isBattleground() && bg->GetStatus() != STATUS_WAIT_LEAVE)
  1358.                 sBattlegroundMgr->ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId());
  1359.  
  1360.             WorldPacket data;
  1361.             sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_NONE, player->GetBattlegroundQueueJoinTime(m_BgTypeId), 0, 0);
  1362.             player->GetSession()->SendPacket(&data);
  1363.         }
  1364.     }
  1365.  
  1366.     //event will be deleted
  1367.     return true;
  1368. }
  1369.  
  1370. void BGQueueRemoveEvent::Abort(uint64 /*e_time*/)
  1371. {
  1372.     //do nothing
  1373. }
  1374.  
  1375. bool BattlegroundQueue::CheckCrossFactionMatch(BattlegroundBracketId bracket_id, Battleground* bg)
  1376. {
  1377.     if (bg->isArena())
  1378.         return false;
  1379.  
  1380.     CanFillPlayersToBGForCrossFaction(bg, bracket_id, true);
  1381.  
  1382.     uint8 multiply = bg->GetMinPlayersPerTeam();
  1383.     if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() < multiply || m_SelectionPools[TEAM_HORDE].GetPlayerCount() < multiply)
  1384.         return false;
  1385.     return true;
  1386. }
  1387.  
  1388. bool BattlegroundQueue::CanFillPlayersToBGForCrossFaction(Battleground* bg, BattlegroundBracketId bracket_id, bool check)
  1389. {
  1390.     int32 allianceFree = check ? bg->GetMinPlayersPerTeam() : bg->GetFreeSlotsForTeam(ALLIANCE);
  1391.     int32 hordeFree = check ? bg->GetMinPlayersPerTeam() : bg->GetFreeSlotsForTeam(HORDE);
  1392.  
  1393.     m_SelectionPools[TEAM_ALLIANCE].Init();
  1394.     m_SelectionPools[TEAM_HORDE].Init();
  1395.  
  1396.     int32 valAlliance = allianceFree;
  1397.     int32 valHorde = hordeFree;
  1398.     int32 diff = 0;
  1399.  
  1400.     for (GroupsQueueType::iterator itr = m_QueuedGroups[bracket_id][BG_CROSS_FACTION][BG_QUEUE_NOT_GUILD].begin(); itr != m_QueuedGroups[bracket_id][BG_CROSS_FACTION][BG_QUEUE_NOT_GUILD].end(); ++itr)
  1401.     {
  1402.         if ((*itr)->IsInvitedToBGInstanceGUID)
  1403.             continue;
  1404.  
  1405.         diff = abs(valAlliance - valHorde);
  1406.         bool ally = valAlliance < valHorde;
  1407.  
  1408.         if (diff > 0)
  1409.             (*itr)->Team = ally ? HORDE : ALLIANCE;
  1410.  
  1411.         bool alliance = (*itr)->Team == ALLIANCE;
  1412.  
  1413.         if (m_SelectionPools[alliance ? TEAM_ALLIANCE : TEAM_HORDE].AddGroup((*itr), alliance ? allianceFree : hordeFree))
  1414.         {
  1415.             uint8 size = (*itr)->Players.size();
  1416.             alliance ? valAlliance -= size : valHorde -= size;
  1417.         }
  1418.     }
  1419.     return true;
  1420. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement