Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
BattlegroundQueue.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ArenaTeam.h"
7#include "ArenaTeamMgr.h"
8#include "BattlegroundMgr.h"
9#include "BattlegroundQueue.h"
10#include "Chat.h"
11#include "Group.h"
12#include "Language.h"
13#include "Log.h"
14#include "ObjectMgr.h"
15#include "Player.h"
16
17/*********************************************************/
18/*** BATTLEGROUND QUEUE SYSTEM ***/
19/*********************************************************/
20
22{
23 for (uint32 i = 0; i < BG_TEAMS_COUNT; ++i)
24 {
25 for (uint32 j = 0; j < MAX_BATTLEGROUND_BRACKETS; ++j)
26 {
27 m_SumOfWaitTimes[i][j] = 0;
28 m_WaitTimeLastPlayer[i][j] = 0;
30 m_WaitTimes[i][j][k] = 0;
31 }
32 }
33}
34
36{
37 m_events.KillAllEvents(false);
38
39 for (int i = 0; i < MAX_BATTLEGROUND_BRACKETS; ++i)
40 {
41 for (uint32 j = 0; j < BG_QUEUE_GROUP_TYPES_COUNT; ++j)
42 {
43 for (GroupsQueueType::iterator itr = m_QueuedGroups[i][j].begin(); itr != m_QueuedGroups[i][j].end(); ++itr)
44 delete (*itr);
45 }
46 }
47}
48
49/*********************************************************/
50/*** BATTLEGROUND QUEUE SELECTION POOLS ***/
51/*********************************************************/
52
53// selection pool initialization, used to clean up from prev selection
59
60// remove group info from selection pool
61// returns true when we need to try to add new group to selection pool
62// returns false when selection pool is ok or when we kicked smaller group than we need to kick
63// sometimes it can be called on empty selection pool
65{
66 //find maxgroup or LAST group with size == size and kick it
67 bool found = false;
68 GroupsQueueType::iterator groupToKick = SelectedGroups.begin();
69 for (GroupsQueueType::iterator itr = groupToKick; itr != SelectedGroups.end(); ++itr)
70 {
71 if (abs((int32)((*itr)->Players.size() - size)) <= 1)
72 {
73 groupToKick = itr;
74 found = true;
75 }
76 else if (!found && (*itr)->Players.size() >= (*groupToKick)->Players.size())
77 groupToKick = itr;
78 }
79 //if pool is empty, do nothing
80 if (GetPlayerCount())
81 {
82 //update player count
83 GroupQueueInfo* ginfo = (*groupToKick);
84 SelectedGroups.erase(groupToKick);
85 PlayerCount -= ginfo->Players.size();
86 //return false if we kicked smaller group or there are enough players in selection pool
87 if (ginfo->Players.size() <= size + 1)
88 return false;
89 }
90 return true;
91}
92
93// add group to selection pool
94// used when building selection pools
95// returns true if we can invite more players, or when we added group to selection pool
96// returns false when selection pool is full
98{
99 //if group is larger than desired count - don't allow to add it to pool
100 if (!ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size())
101 {
102 SelectedGroups.push_back(ginfo);
103 // increase selected players count
104 PlayerCount += ginfo->Players.size();
105 return true;
106 }
107 if (PlayerCount < desiredCount)
108 return true;
109 return false;
110}
111
112/*********************************************************/
113/*** BATTLEGROUND QUEUES ***/
114/*********************************************************/
115
116// add group or player (grp == NULL) to bg queue with the given leader and bg specifications
117GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, BattlegroundTypeId BgTypeId, PvPDifficultyEntry const* bracketEntry, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating)
118{
119 uint8 BracketID = uint8(bracketEntry->GetBracketId());
120
121 // create new ginfo
122 GroupQueueInfo* ginfo = new GroupQueueInfo;
123 ginfo->BgTypeId = BgTypeId;
124 ginfo->ArenaType = ArenaType;
125 ginfo->ArenaGroup = grp;
126 ginfo->IsRated = isRated;
127 ginfo->IsInvitedToBGInstanceGUID = 0;
128 ginfo->JoinTime = getMSTime();
129 ginfo->RemoveInviteTime = 0;
130 ginfo->Team = leader->GetTeam();
131 ginfo->ArenaTeamRating = ArenaRating;
132 ginfo->ArenaMatchmakerRating = MatchmakerRating;
133 ginfo->OpponentsTeamRating = 0;
134 ginfo->OpponentsMatchmakerRating = 0;
135
136 ginfo->Players.clear();
137
138 //compute index (if group is premade or joined a rated match) to queues
139 uint32 index = 0;
140 if (!isRated && !isPremade)
141 index += BG_TEAMS_COUNT;
142 if (ginfo->Team == HORDE)
143 index++;
144 SF_LOG_DEBUG("bg.battleground", "Adding Group to BattlegroundQueue bgTypeId : %u, bracket_id : %u, index : %u", uint32(BgTypeId), BracketID, index);
145
146 uint32 lastOnlineTime = getMSTime();
147
148 //add players from group to ginfo
149 if (grp)
150 {
151 for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
152 {
153 Player* member = itr->GetSource();
154 if (!member)
155 continue; // this should never happen
156 PlayerQueueInfo& pl_info = m_QueuedPlayers[member->GetGUID()];
157 pl_info.LastOnlineTime = lastOnlineTime;
158 pl_info.GroupInfo = ginfo;
159 // add the pinfo to ginfo's list
160 ginfo->Players[member->GetGUID()] = &pl_info;
161 }
162 }
163 else
164 {
165 PlayerQueueInfo& pl_info = m_QueuedPlayers[leader->GetGUID()];
166 pl_info.LastOnlineTime = lastOnlineTime;
167 pl_info.GroupInfo = ginfo;
168 ginfo->Players[leader->GetGUID()] = &pl_info;
169 }
170
171 //add GroupInfo to m_QueuedGroups
172 {
173 m_QueuedGroups[BracketID][index].push_back(ginfo);
174
175 //announce to world, this code needs mutex
176 if (!isRated && !isPremade && sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
177 {
178 if (Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(ginfo->BgTypeId))
179 {
180 char const* bgName = bg->GetName();
181 uint32 MinPlayers = bg->GetMinPlayersPerTeam();
182 uint32 qHorde = 0;
183 uint32 qAlliance = 0;
184 uint32 q_min_level = bracketEntry->minLevel;
185 uint32 q_max_level = bracketEntry->maxLevel;
186 GroupsQueueType::const_iterator itr;
187 for (itr = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE].begin(); itr != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE].end(); ++itr)
188 if (!(*itr)->IsInvitedToBGInstanceGUID)
189 qAlliance += (*itr)->Players.size();
190 for (itr = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_HORDE].begin(); itr != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_HORDE].end(); ++itr)
191 if (!(*itr)->IsInvitedToBGInstanceGUID)
192 qHorde += (*itr)->Players.size();
193
194 // Show queue status to player only (when joining queue)
196 {
197 ChatHandler(leader->GetSession()).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, bgName, q_min_level, q_max_level,
198 qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
199 }
200 // System message
201 else
202 {
203 sWorld->SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level,
204 qAlliance, (MinPlayers > qAlliance) ? MinPlayers - qAlliance : (uint32)0, qHorde, (MinPlayers > qHorde) ? MinPlayers - qHorde : (uint32)0);
205 }
206 }
207 }
208 //release mutex
209 }
210
211 return ginfo;
212}
213
215{
216 uint32 timeInQueue = getMSTimeDiff(ginfo->JoinTime, getMSTime());
217 uint8 team_index = TEAM_ALLIANCE; //default set to TEAM_ALLIANCE - or non rated arenas!
218 uint8 BracketID = uint8(bracket_id);
219 if (!ginfo->ArenaType)
220 {
221 if (ginfo->Team == HORDE)
222 team_index = TEAM_HORDE;
223 }
224 else
225 {
226 if (ginfo->IsRated)
227 team_index = TEAM_HORDE; //for rated arenas use TEAM_HORDE
228 }
229
230 //store pointer to arrayindex of player that was added first
231 uint32* lastPlayerAddedPointer = &(m_WaitTimeLastPlayer[team_index][BracketID]);
232 //remove his time from sum
233 m_SumOfWaitTimes[team_index][BracketID] -= m_WaitTimes[team_index][BracketID][(*lastPlayerAddedPointer)];
234 //set average time to new
235 m_WaitTimes[team_index][BracketID][(*lastPlayerAddedPointer)] = timeInQueue;
236 //add new time to sum
237 m_SumOfWaitTimes[team_index][BracketID] += timeInQueue;
238 //set index of last player added to next one
239 (*lastPlayerAddedPointer)++;
240 (*lastPlayerAddedPointer) %= COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME;
241}
242
244{
245 uint8 team_index = TEAM_ALLIANCE; //default set to TEAM_ALLIANCE - or non rated arenas!
246 uint8 BracketID = uint8(bracket_id);
247 if (!ginfo->ArenaType)
248 {
249 if (ginfo->Team == HORDE)
250 team_index = TEAM_HORDE;
251 }
252 else
253 {
254 if (ginfo->IsRated)
255 team_index = TEAM_HORDE; //for rated arenas use TEAM_HORDE
256 }
257 //check if there is enought values(we always add values > 0)
258 if (m_WaitTimes[team_index][BracketID][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME - 1])
259 return (m_SumOfWaitTimes[team_index][BracketID] / COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME);
260 else
261 //if there aren't enough values return 0 - not available
262 return 0;
263}
264
265//remove player from queue and from group info, if group info is empty then remove it too
266void BattlegroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount)
267{
268 int32 bracket_id = -1; // signed for proper for-loop finish
269 QueuedPlayersMap::iterator itr;
270
271 //remove player from map, if he's there
272 itr = m_QueuedPlayers.find(guid);
273 if (itr == m_QueuedPlayers.end())
274 {
275 std::string playerName = "Unknown";
276 if (Player* player = ObjectAccessor::FindPlayer(guid))
277 playerName = player->GetName();
278 SF_LOG_ERROR("bg.battleground", "BattlegroundQueue: couldn't find player %s (GUID: %u)", playerName.c_str(), GUID_LOPART(guid));
279 return;
280 }
281
282 GroupQueueInfo* group = itr->second.GroupInfo;
283 GroupsQueueType::iterator group_itr;
284 // mostly people with the highest levels are in battlegrounds, thats why
285 // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0
286
288
289 for (int32 bracket_id_tmp = MAX_BATTLEGROUND_BRACKETS - 1; bracket_id_tmp >= 0 && bracket_id == -1; --bracket_id_tmp)
290 {
291 //we must check premade and normal team's queue - because when players from premade are joining bg,
292 //they leave groupinfo so we can't use its players size to find out index
293 for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT; j += BG_TEAMS_COUNT)
294 {
295 GroupsQueueType::iterator k = m_QueuedGroups[bracket_id_tmp][j].begin();
296 for (; k != m_QueuedGroups[bracket_id_tmp][j].end(); ++k)
297 {
298 if ((*k) == group)
299 {
300 bracket_id = bracket_id_tmp;
301 group_itr = k;
302 //we must store index to be able to erase iterator
303 index = j;
304 break;
305 }
306 }
307 }
308 }
309
310 //player can't be in queue without group, but just in case
311 if (bracket_id == -1)
312 {
313 SF_LOG_ERROR("bg.battleground", "BattlegroundQueue: ERROR Cannot find groupinfo for player GUID: %u", GUID_LOPART(guid));
314 return;
315 }
316 SF_LOG_DEBUG("bg.battleground", "BattlegroundQueue: Removing player GUID %u, from bracket_id %u", GUID_LOPART(guid), (uint32)bracket_id);
317
318 // ALL variables are correctly set
319 // We can ignore leveling up in queue - it should not cause crash
320 // remove player from group
321 // if only one player there, remove group
322
323 // remove player queue info from group queue info
324 std::map<uint64, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid);
325 if (pitr != group->Players.end())
326 group->Players.erase(pitr);
327
328 // if invited to bg, and should decrease invited count, then do it
329 if (decreaseInvitedCount && group->IsInvitedToBGInstanceGUID)
330 if (Battleground* bg = sBattlegroundMgr->GetBattleground(group->IsInvitedToBGInstanceGUID, group->BgTypeId))
331 bg->DecreaseInvitedCount(group->Team);
332
333 // remove player queue info
334 m_QueuedPlayers.erase(itr);
335
336 // if player leaves queue and he is invited to rated arena match, then he have to lose
337 if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount)
338 {
339 /*
340 if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
341 {
342 SF_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(guid), group->OpponentsTeamRating);
343 if (Player* player = ObjectAccessor::FindPlayer(guid))
344 at->MemberLost(player, group->OpponentsMatchmakerRating);
345 else
346 at->OfflineMemberLost(guid, group->OpponentsMatchmakerRating);
347 at->SaveToDB();
348 }
349 */
350 }
351
352 // remove group queue info if needed
353 if (group->Players.empty())
354 {
355 m_QueuedGroups[bracket_id][index].erase(group_itr);
356 delete group;
357 return;
358 }
359
360 // if group wasn't empty, so it wasn't deleted, and player have left a rated
361 // queue -> everyone from the group should leave too
362 // don't remove recursively if already invited to bg!
363 if (!group->IsInvitedToBGInstanceGUID && group->IsRated)
364 {
365 // remove next player, this is recursive
366 // first send removal information
367 if (Player* plr2 = ObjectAccessor::FindPlayer(group->Players.begin()->first))
368 {
369 Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId);
371 uint32 queueSlot = plr2->GetBattlegroundQueueIndex(bgQueueTypeId);
372
373 plr2->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to
374 // queue->removeplayer, it causes bugs
375 WorldPacket data;
376 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, plr2, queueSlot, STATUS_NONE, plr2->GetBattlegroundQueueJoinTime(group->BgTypeId), 0, 0);
377 plr2->GetSession()->SendPacket(&data);
378 }
379 // then actually delete, this may delete the group as well!
380 RemovePlayer(group->Players.begin()->first, decreaseInvitedCount);
381 }
382}
383
384//returns true when player pl_guid is in queue and is invited to bgInstanceGuid
385bool BattlegroundQueue::IsPlayerInvited(uint64 pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime)
386{
387 QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(pl_guid);
388 return (qItr != m_QueuedPlayers.end()
389 && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == bgInstanceGuid
390 && qItr->second.GroupInfo->RemoveInviteTime == removeTime);
391}
392
394{
395 QueuedPlayersMap::const_iterator qItr = m_QueuedPlayers.find(guid);
396 if (qItr == m_QueuedPlayers.end())
397 return false;
398 *ginfo = *(qItr->second.GroupInfo);
399 return true;
400}
401
403{
404 return m_SelectionPools[id].GetPlayerCount();
405}
406
408{
409 // set side if needed
410 if (side)
411 ginfo->Team = side;
412
413 if (!ginfo->IsInvitedToBGInstanceGUID)
414 {
415 // not yet invited
416 // set invitation
418 BattlegroundTypeId bgTypeId = bg->GetTypeID();
420 BattlegroundBracketId bracket_id = bg->GetBracketId();
421
423
424 // loop through the players
425 for (std::map<uint64, PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
426 {
427 // get the player
428 Player* player = ObjectAccessor::FindPlayer(itr->first);
429 // if offline, skip him, this should not happen - player is removed from queue when he logs out
430 if (!player)
431 continue;
432
433 // invite the player
435 //sBattlegroundMgr->InvitePlayer(player, bg, ginfo->Team);
436
437 // set invited player counters
438 bg->IncreaseInvitedCount(ginfo->Team);
439
441
442 // create remind invite events
443 BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, ginfo->ArenaType, ginfo->RemoveInviteTime);
444 m_events.AddEvent(inviteEvent, m_events.CalculateTime(INVITATION_REMIND_TIME));
445 // create automatic remove events
446 BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(player->GetGUID(), ginfo->IsInvitedToBGInstanceGUID, bgTypeId, bgQueueTypeId, ginfo->RemoveInviteTime);
447 m_events.AddEvent(removeEvent, m_events.CalculateTime(INVITE_ACCEPT_WAIT_TIME));
448
449 WorldPacket data;
450
451 uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
452
453 SF_LOG_DEBUG("bg.battleground", "Battleground: invited player %s (%u) to BG instance %u queueindex %u bgtype %u",
454 player->GetName().c_str(), player->GetGUIDLow(), bg->GetInstanceID(), queueSlot, uint32(bg->GetTypeID()));
455
456 // send status packet
457 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, player->GetBattlegroundQueueJoinTime(bgTypeId), ginfo->ArenaType);
458 player->GetSession()->SendPacket(&data);
459 }
460 return true;
461 }
462
463 return false;
464}
465
466/*
467This function is inviting players to already running battlegrounds
468Invitation type is based on config file
469large groups are disadvantageous, because they will be kicked first if invitation type = 1
470*/
472{
473 int32 hordeFree = bg->GetFreeSlotsForTeam(HORDE);
474 int32 aliFree = bg->GetFreeSlotsForTeam(ALLIANCE);
475 uint8 BracketID = uint8(bracket_id);
476
477 //iterator for iterating through bg queue
478 GroupsQueueType::const_iterator Ali_itr = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE].begin();
479 //count of groups in queue - used to stop cycles
480 uint32 aliCount = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE].size();
481 //index to queue which group is current
482 uint32 aliIndex = 0;
483 for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), aliFree); aliIndex++)
484 ++Ali_itr;
485 //the same thing for horde
486 GroupsQueueType::const_iterator Horde_itr = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_HORDE].begin();
487 uint32 hordeCount = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_HORDE].size();
488 uint32 hordeIndex = 0;
489 for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), hordeFree); hordeIndex++)
490 ++Horde_itr;
491
492 //if ofc like BG queue invitation is set in config, then we are happy
494 return;
495
496 /*
497 if we reached this code, then we have to solve NP - complete problem called Subset sum problem
498 So one solution is to check all possible invitation subgroups, or we can use these conditions:
499 1. Last time when BattlegroundQueue::Update was executed we invited all possible players - so there is only small possibility
500 that we will invite now whole queue, because only 1 change has been made to queues from the last BattlegroundQueue::Update call
501 2. Other thing we should consider is group order in queue
502 */
503
504 // At first we need to compare free space in bg and our selection pool
505 int32 diffAli = aliFree - int32(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
506 int32 diffHorde = hordeFree - int32(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
507 while (abs(diffAli - diffHorde) > 1 && (m_SelectionPools[TEAM_HORDE].GetPlayerCount() > 0 || m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() > 0))
508 {
509 //each cycle execution we need to kick at least 1 group
510 if (diffAli < diffHorde)
511 {
512 //kick alliance group, add to pool new group if needed
513 if (m_SelectionPools[TEAM_ALLIANCE].KickGroup(diffHorde - diffAli))
514 {
515 for (; aliIndex < aliCount && m_SelectionPools[TEAM_ALLIANCE].AddGroup((*Ali_itr), (aliFree >= diffHorde) ? aliFree - diffHorde : 0); aliIndex++)
516 ++Ali_itr;
517 }
518 //if ali selection is already empty, then kick horde group, but if there are less horde than ali in bg - break;
519 if (!m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
520 {
521 if (aliFree <= diffHorde + 1)
522 break;
523 m_SelectionPools[TEAM_HORDE].KickGroup(diffHorde - diffAli);
524 }
525 }
526 else
527 {
528 //kick horde group, add to pool new group if needed
529 if (m_SelectionPools[TEAM_HORDE].KickGroup(diffAli - diffHorde))
530 {
531 for (; hordeIndex < hordeCount && m_SelectionPools[TEAM_HORDE].AddGroup((*Horde_itr), (hordeFree >= diffAli) ? hordeFree - diffAli : 0); hordeIndex++)
532 ++Horde_itr;
533 }
534 if (!m_SelectionPools[TEAM_HORDE].GetPlayerCount())
535 {
536 if (hordeFree <= diffAli + 1)
537 break;
538 m_SelectionPools[TEAM_ALLIANCE].KickGroup(diffAli - diffHorde);
539 }
540 }
541 //count diffs after small update
542 diffAli = aliFree - int32(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount());
543 diffHorde = hordeFree - int32(m_SelectionPools[TEAM_HORDE].GetPlayerCount());
544 }
545}
546
547// this method checks if premade versus premade battleground is possible
548// then after 30 mins (default) in queue it moves premade group to normal queue
549// it tries to invite as much players as it can - to MaxPlayersPerTeam, because premade groups have more than MinPlayersPerTeam players
550bool BattlegroundQueue::CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam)
551{
552 uint8 BracketID = uint8(bracket_id);
553 //check match
554 if (!m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].empty() && !m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].empty())
555 {
556 //start premade match
557 //if groups aren't invited
558 GroupsQueueType::const_iterator ali_group, horde_group;
559 for (ali_group = m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].begin(); ali_group != m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].end(); ++ali_group)
560 if (!(*ali_group)->IsInvitedToBGInstanceGUID)
561 break;
562 for (horde_group = m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].begin(); horde_group != m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].end(); ++horde_group)
563 if (!(*horde_group)->IsInvitedToBGInstanceGUID)
564 break;
565
566 if (ali_group != m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].end() && horde_group != m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].end())
567 {
568 m_SelectionPools[TEAM_ALLIANCE].AddGroup((*ali_group), MaxPlayersPerTeam);
569 m_SelectionPools[TEAM_HORDE].AddGroup((*horde_group), MaxPlayersPerTeam);
570 //add groups/players from normal queue to size of bigger group
571 uint32 maxPlayers = std::min(m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount(), m_SelectionPools[TEAM_HORDE].GetPlayerCount());
572 GroupsQueueType::const_iterator itr;
573 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
574 {
575 for (itr = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr)
576 {
577 //if itr can join BG and player count is less that maxPlayers, then add group to selectionpool
578 if (!(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers))
579 break;
580 }
581 }
582 //premade selection pools are set
583 return true;
584 }
585 }
586 // now check if we can move group from Premade queue to normal queue (timer has expired) or group size lowered!!
587 // this could be 2 cycles but i'm checking only first team in queue - it can cause problem -
588 // 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
589 // and when they click or after 80 seconds the queue info is removed from queue
591 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
592 {
593 if (!m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE + i].empty())
594 {
595 GroupsQueueType::iterator itr = m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE + i].begin();
596 if (!(*itr)->IsInvitedToBGInstanceGUID && ((*itr)->JoinTime < time_before || (*itr)->Players.size() < MinPlayersPerTeam))
597 {
598 //we must insert group to normal queue and erase pointer from premade queue
599 m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr));
600 m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr);
601 }
602 }
603 }
604 //selection pools are not set
605 return false;
606}
607
608// this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam
609bool BattlegroundQueue::CheckNormalMatch(Battleground* /*bg_template*/, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
610{
611 uint8 BracketID = uint8(bracket_id);
612 GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT];
613 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
614 {
615 itr_team[i] = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + i].begin();
616 for (; itr_team[i] != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++(itr_team[i]))
617 {
618 if (!(*(itr_team[i]))->IsInvitedToBGInstanceGUID)
619 {
620 m_SelectionPools[i].AddGroup(*(itr_team[i]), maxPlayers);
621 if (m_SelectionPools[i].GetPlayerCount() >= minPlayers)
622 break;
623 }
624 }
625 }
626 //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
628 if (m_SelectionPools[TEAM_HORDE].GetPlayerCount() < m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())
629 j = TEAM_HORDE;
631 && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers)
632 {
633 //we will try to invite more groups to team with less players indexed by j
634 ++(itr_team[j]); //this will not cause a crash, because for cycle above reached break;
635 for (; itr_team[j] != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j]))
636 {
637 if (!(*(itr_team[j]))->IsInvitedToBGInstanceGUID)
638 if (!m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()))
639 break;
640 }
641 // do not allow to start bg with more than 2 players more on 1 faction
642 if (abs((int32)(m_SelectionPools[TEAM_HORDE].GetPlayerCount() - m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount())) > 2)
643 return false;
644 }
645 //allow 1v0 if debug bg
646 if (sBattlegroundMgr->isTesting() && (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() || m_SelectionPools[TEAM_HORDE].GetPlayerCount()))
647 return true;
648 //return true if there are enough players in selection pools - enable to work .debug bg command correctly
649 return m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[TEAM_HORDE].GetPlayerCount() >= minPlayers;
650}
651
652// this method will check if we can invite players to same faction skirmish match
654{
655 if (m_SelectionPools[TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam)
656 return false;
657 uint8 BracketID = uint8(bracket_id);
658 uint32 teamIndex = TEAM_ALLIANCE;
659 uint32 otherTeam = TEAM_HORDE;
660 uint32 otherTeamId = HORDE;
661 if (m_SelectionPools[TEAM_HORDE].GetPlayerCount() == minPlayersPerTeam)
662 {
663 teamIndex = TEAM_HORDE;
664 otherTeam = TEAM_ALLIANCE;
665 otherTeamId = ALLIANCE;
666 }
667 //clear other team's selection
668 m_SelectionPools[otherTeam].Init();
669 //store last ginfo pointer
670 GroupQueueInfo* ginfo = m_SelectionPools[teamIndex].SelectedGroups.back();
671 //set itr_team to group that was added to selection pool latest
672 GroupsQueueType::iterator itr_team = m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].begin();
673 for (; itr_team != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team)
674 if (ginfo == *itr_team)
675 break;
676 if (itr_team == m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end())
677 return false;
678 GroupsQueueType::iterator itr_team2 = itr_team;
679 ++itr_team2;
680 //invite players to other selection pool
681 for (; itr_team2 != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2)
682 {
683 //if selection pool is full then break;
684 if (!(*itr_team2)->IsInvitedToBGInstanceGUID && !m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam))
685 break;
686 }
687 if (m_SelectionPools[otherTeam].GetPlayerCount() != minPlayersPerTeam)
688 return false;
689
690 //here we have correct 2 selections and we need to change one teams team and move selection pool teams to other team's queue
691 for (GroupsQueueType::iterator itr = m_SelectionPools[otherTeam].SelectedGroups.begin(); itr != m_SelectionPools[otherTeam].SelectedGroups.end(); ++itr)
692 {
693 //set correct team
694 (*itr)->Team = otherTeamId;
695 //add team to other queue
696 m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + otherTeam].push_front(*itr);
697 //remove team from old queue
698 GroupsQueueType::iterator itr2 = itr_team;
699 ++itr2;
700 for (; itr2 != m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2)
701 {
702 if (*itr2 == *itr)
703 {
704 m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].erase(itr2);
705 break;
706 }
707 }
708 }
709 return true;
710}
711
713{
714 m_events.Update(diff);
715}
716
717/*
718this 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
719it must be called after fully adding the members of a group to ensure group joining
720should be called from Battleground::RemovePlayer function in some cases
721*/
722void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType, bool isRated, uint32 arenaRating)
723{
724 uint8 BracketID = uint8(bracket_id);
725 //if no players in queue - do nothing
726 if (m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].empty() &&
727 m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].empty() &&
728 m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_ALLIANCE].empty() &&
729 m_QueuedGroups[BracketID][BG_QUEUE_NORMAL_HORDE].empty())
730 return;
731
732 // battleground with free slot for player should be always in the beggining of the queue
733 // maybe it would be better to create bgfreeslotqueue for each bracket_id
734 BGFreeSlotQueueContainer& bgQueues = sBattlegroundMgr->GetBGFreeSlotQueueStore(bgTypeId);
735 for (BGFreeSlotQueueContainer::iterator itr = bgQueues.begin(); itr != bgQueues.end();)
736 {
737 Battleground* bg = *itr; ++itr;
738 // DO NOT allow queue manager to invite new player to rated games
739 if (!bg->isRated() && bg->GetTypeID() == bgTypeId && bg->GetBracketId() == bracket_id &&
741 {
742 // clear selection pools
745
746 // call a function that does the job for us
747 FillPlayersToBG(bg, bracket_id);
748
749 // now everything is set, invite players
750 for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE].SelectedGroups.end(); ++citr)
751 InviteGroupToBG((*citr), bg, (*citr)->Team);
752
753 for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_HORDE].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_HORDE].SelectedGroups.end(); ++citr)
754 InviteGroupToBG((*citr), bg, (*citr)->Team);
755
756 if (!bg->HasFreeSlots())
758 }
759 }
760
761 // finished iterating through the bgs with free slots, maybe we need to create a new bg
762
763 Battleground* bg_template = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
764 if (!bg_template)
765 {
766 SF_LOG_ERROR("bg.battleground", "Battleground: Update: bg template not found for %u", uint32(bgTypeId));
767 return;
768 }
769
770 PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketById(bg_template->GetMapId(), bracket_id);
771 if (!bracketEntry)
772 {
773 SF_LOG_ERROR("bg.battleground", "Battleground: Update: bg bracket entry not found for map %u bracket id %u", bg_template->GetMapId(), BracketID);
774 return;
775 }
776
777 // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!)
778 uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam();
779 uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam();
780
781 if (bg_template->isArena())
782 {
783 MaxPlayersPerTeam = arenaType;
784 MinPlayersPerTeam = sBattlegroundMgr->isArenaTesting() ? 1 : arenaType;
785 }
786 else if (sBattlegroundMgr->isTesting())
787 MinPlayersPerTeam = 1;
788
791
792 if (bg_template->isBattleground())
793 {
794 if (CheckPremadeMatch(bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam))
795 {
796 // create new battleground
797 Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, 0, false);
798 if (!bg2)
799 {
800 SF_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create battleground: %u", uint32(bgTypeId));
801 return;
802 }
803 // invite those selection pools
804 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
805 for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
806 InviteGroupToBG((*citr), bg2, (*citr)->Team);
807
808 bg2->StartBattleground();
809 //clear structures
812 }
813 }
814
815 // now check if there are in queues enough players to start new game of (normal battleground, or non-rated arena)
816 if (!isRated)
817 {
818 // if there are enough players in pools, start new battleground or non rated arena
819 if (CheckNormalMatch(bg_template, bracket_id, MinPlayersPerTeam, MaxPlayersPerTeam)
820 || (bg_template->isArena() && CheckSkirmishForSameFaction(bracket_id, MinPlayersPerTeam)))
821 {
822 // we successfully created a pool
823 Battleground* bg2 = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, false);
824 if (!bg2)
825 {
826 SF_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update - Cannot create battleground: %u", uint32(bgTypeId));
827 return;
828 }
829
830 // invite those selection pools
831 for (uint32 i = 0; i < BG_TEAMS_COUNT; i++)
832 for (GroupsQueueType::const_iterator citr = m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.begin(); citr != m_SelectionPools[TEAM_ALLIANCE + i].SelectedGroups.end(); ++citr)
833 InviteGroupToBG((*citr), bg2, (*citr)->Team);
834 // start bg
835 bg2->StartBattleground();
836 }
837 }
838 else if (bg_template->isArena())
839 {
840 // found out the minimum and maximum ratings the newly added team should battle against
841 // arenaRating is the rating of the latest joined team, or 0
842 // 0 is on (automatic update call) and we must set it to team's with longest wait time
843 if (!arenaRating)
844 {
845 GroupQueueInfo* front1 = NULL;
846 GroupQueueInfo* front2 = NULL;
847 if (!m_QueuedGroups[uint8(bracket_id)][BG_QUEUE_PREMADE_ALLIANCE].empty())
848 {
849 front1 = m_QueuedGroups[uint8(bracket_id)][BG_QUEUE_PREMADE_ALLIANCE].front();
850 arenaRating = front1->ArenaMatchmakerRating;
851 }
852 if (!m_QueuedGroups[uint8(bracket_id)][BG_QUEUE_PREMADE_HORDE].empty())
853 {
854 front2 = m_QueuedGroups[uint8(bracket_id)][BG_QUEUE_PREMADE_HORDE].front();
855 arenaRating = front2->ArenaMatchmakerRating;
856 }
857 if (front1 && front2)
858 {
859 if (front1->JoinTime < front2->JoinTime)
860 arenaRating = front1->ArenaMatchmakerRating;
861 }
862 else if (!front1 && !front2)
863 return; //queues are empty
864 }
865
866 //set rating range
867 uint32 arenaMinRating = (arenaRating <= sBattlegroundMgr->GetMaxRatingDifference()) ? 0 : arenaRating - sBattlegroundMgr->GetMaxRatingDifference();
868 uint32 arenaMaxRating = arenaRating + sBattlegroundMgr->GetMaxRatingDifference();
869 // if max rating difference is set and the time past since server startup is greater than the rating discard time
870 // (after what time the ratings aren't taken into account when making teams) then
871 // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
872 // else leave the discard time on 0, this way all ratings will be discarded
873 uint32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer();
874
875 // we need to find 2 teams which will play next game
876 GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT];
877 uint8 found = 0;
878 uint8 team = 0;
879 uint8 BracketID = uint8(bracket_id);
880
882 {
883 // take the group that joined first
884 GroupsQueueType::iterator itr2 = m_QueuedGroups[BracketID][i].begin();
885 for (; itr2 != m_QueuedGroups[BracketID][i].end(); ++itr2)
886 {
887 // if group match conditions, then add it to pool
888 if (!(*itr2)->IsInvitedToBGInstanceGUID
889 && (((*itr2)->ArenaMatchmakerRating >= arenaMinRating && (*itr2)->ArenaMatchmakerRating <= arenaMaxRating)
890 || (*itr2)->JoinTime < discardTime))
891 {
892 itr_teams[found++] = itr2;
893 team = i;
894 break;
895 }
896 }
897 }
898
899 if (!found)
900 return;
901
902 if (found == 1)
903 {
904 for (GroupsQueueType::iterator itr3 = itr_teams[0]; itr3 != m_QueuedGroups[BracketID][team].end(); ++itr3)
905 {
906 if (!(*itr3)->IsInvitedToBGInstanceGUID
907 && (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating)
908 || (*itr3)->JoinTime < discardTime)
909 && (*itr_teams[0])->ArenaGroup != (*itr3)->ArenaGroup)
910 {
911 itr_teams[found++] = itr3;
912 break;
913 }
914 }
915 }
916
917 //if we have 2 teams, then start new arena and invite players!
918 if (found == 2)
919 {
920 GroupQueueInfo* aTeam = *itr_teams[TEAM_ALLIANCE];
921 GroupQueueInfo* hTeam = *itr_teams[TEAM_HORDE];
922 Battleground* arena = sBattlegroundMgr->CreateNewBattleground(bgTypeId, bracketEntry, arenaType, true);
923 if (!arena)
924 {
925 SF_LOG_ERROR("bg.battleground", "BattlegroundQueue::Update couldn't create arena instance for rated arena match!");
926 return;
927 }
928
929 aTeam->OpponentsTeamRating = hTeam->ArenaTeamRating;
930 hTeam->OpponentsTeamRating = aTeam->ArenaTeamRating;
933
934 // 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
935 if (aTeam->Team != ALLIANCE)
936 {
937 m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].push_front(aTeam);
938 m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].erase(itr_teams[TEAM_ALLIANCE]);
939 }
940 if (hTeam->Team != HORDE)
941 {
942 m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_HORDE].push_front(hTeam);
943 m_QueuedGroups[BracketID][BG_QUEUE_PREMADE_ALLIANCE].erase(itr_teams[TEAM_HORDE]);
944 }
945
948 InviteGroupToBG(aTeam, arena, ALLIANCE);
949 InviteGroupToBG(hTeam, arena, HORDE);
950
951 SF_LOG_DEBUG("bg.battleground", "Starting rated arena match!");
952 arena->StartBattleground();
953 }
954 }
955}
956
957/*********************************************************/
958/*** BATTLEGROUND QUEUE EVENTS ***/
959/*********************************************************/
960
961bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
962{
964 // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
965 if (!player)
966 return true;
967
969 //if battleground ended and its instance deleted - do nothing
970 if (!bg)
971 return true;
972
974 uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
975 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue or in battleground
976 {
977 // check if player is invited to this bg
978 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
980 {
981 WorldPacket data;
982 //we must send remaining time in queue
983 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME - INVITATION_REMIND_TIME, player->GetBattlegroundQueueJoinTime(m_BgTypeId), m_ArenaType);
984 player->GetSession()->SendPacket(&data);
985 }
986 }
987 return true; //event will be deleted
988}
989
991{
992 //do nothing
993}
994
995/*
996 this event has many possibilities when it is executed:
997 1. player is in battleground (he clicked enter on invitation window)
998 2. player left battleground queue and he isn't there any more
999 3. player left battleground queue and he joined it again and IsInvitedToBGInstanceGUID = 0
1000 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
1001 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
1002 we must remove player in the 5. case even if battleground object doesn't exist!
1003*/
1004bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
1005{
1007 if (!player)
1008 // player logged off (we should do nothing, he is correctly removed from queue in another procedure)
1009 return true;
1010
1012 //battleground can be deleted already when we are removing queue info
1013 //bg pointer can be NULL! so use it carefully!
1014
1016 if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue, or in Battleground
1017 {
1018 // check if player is in queue for this BG and if we are removing his invite event
1019 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(m_BgQueueTypeId);
1021 {
1022 SF_LOG_DEBUG("bg.battleground", "Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.", player->GetGUIDLow(), m_BgInstanceGUID);
1023
1025 bgQueue.RemovePlayer(m_PlayerGuid, true);
1026 //update queues if battleground isn't ended
1027 if (bg && bg->isBattleground() && bg->GetStatus() != STATUS_WAIT_LEAVE)
1028 sBattlegroundMgr->ScheduleQueueUpdate(0, 0, m_BgQueueTypeId, m_BgTypeId, bg->GetBracketId());
1029
1030 WorldPacket data;
1031 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, player, queueSlot, STATUS_NONE, player->GetBattlegroundQueueJoinTime(m_BgTypeId), 0, 0);
1032 player->GetSession()->SendPacket(&data);
1033 }
1034 }
1035
1036 //event will be deleted
1037 return true;
1038}
1039
1041{
1042 //do nothing
1043}
@ INVITE_ACCEPT_WAIT_TIME
@ INVITATION_REMIND_TIME
ArenaType
#define BG_TEAMS_COUNT
@ STATUS_WAIT_QUEUE
@ STATUS_NONE
@ STATUS_WAIT_LEAVE
@ STATUS_WAIT_JOIN
#define sBattlegroundMgr
@ BG_QUEUE_PREMADE_HORDE
@ BG_QUEUE_NORMAL_ALLIANCE
@ BG_QUEUE_PREMADE_ALLIANCE
@ BG_QUEUE_NORMAL_HORDE
#define BG_QUEUE_GROUP_TYPES_COUNT
#define COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME
std::list< Battleground * > BGFreeSlotQueueContainer
#define MAX_BATTLEGROUND_BRACKETS
Definition DBCEnums.h:34
BattlegroundBracketId
Definition DBCEnums.h:28
PvPDifficultyEntry const * GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id)
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
@ LANG_BG_QUEUE_ANNOUNCE_SELF
Definition Language.h:691
@ LANG_BG_QUEUE_ANNOUNCE_WORLD
Definition Language.h:692
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
uint32 GUID_LOPART(uint64 x)
BattlegroundQueueTypeId
TeamId
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ ALLIANCE
@ HORDE
BattlegroundTypeId
#define PLAYER_MAX_BATTLEGROUND_QUEUES
uint32 getMSTime()
Definition Timer.h:12
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition Timer.h:17
BattlegroundTypeId m_BgTypeId
virtual bool Execute(uint64 e_time, uint32 p_time)
virtual void Abort(uint64 e_time)
virtual bool Execute(uint64 e_time, uint32 p_time)
virtual void Abort(uint64 e_time)
BattlegroundTypeId m_BgTypeId
BattlegroundQueueTypeId m_BgQueueTypeId
void IncreaseInvitedCount(uint32 team)
uint32 GetMapId() const
BattlegroundTypeId GetTypeID(bool GetRandom=false) const
uint32 GetMinPlayersPerTeam() const
uint8 GetArenaType() const
uint32 GetMaxPlayersPerTeam() const
bool isRated() const
void StartBattleground()
uint32 GetInstanceID() const
bool isArena() const
void SetArenaMatchmakerRating(uint32 Team, uint32 MMR)
bool isBattleground() const
BattlegroundStatus GetStatus() const
bool HasFreeSlots() const
void RemoveFromBGFreeSlotQueue()
BattlegroundBracketId GetBracketId() const
uint32 GetFreeSlotsForTeam(uint32 Team) const
static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType)
bool AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount)
uint32 m_SumOfWaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]
void FillPlayersToBG(Battleground *bg, BattlegroundBracketId bracket_id)
void UpdateEvents(uint32 diff)
void PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo *ginfo, BattlegroundBracketId bracket_id)
uint32 m_WaitTimes[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS][COUNT_OF_PLAYERS_TO_AVERAGE_WAIT_TIME]
GroupQueueInfo * AddGroup(Player *leader, Group *group, BattlegroundTypeId bgTypeId, PvPDifficultyEntry const *bracketEntry, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating)
uint32 GetAverageQueueWaitTime(GroupQueueInfo *ginfo, BattlegroundBracketId bracket_id) const
QueuedPlayersMap m_QueuedPlayers
bool CheckNormalMatch(Battleground *bg_template, BattlegroundBracketId bracket_id, uint32 minPlayers, uint32 maxPlayers)
bool InviteGroupToBG(GroupQueueInfo *ginfo, Battleground *bg, uint32 side)
bool CheckSkirmishForSameFaction(BattlegroundBracketId bracket_id, uint32 minPlayersPerTeam)
bool GetPlayerGroupInfoData(uint64 guid, GroupQueueInfo *ginfo)
void BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id, uint8 arenaType=0, bool isRated=false, uint32 minRating=0)
bool IsPlayerInvited(uint64 pl_guid, const uint32 bgInstanceGuid, const uint32 removeTime)
void RemovePlayer(uint64 guid, bool decreaseInvitedCount)
GroupsQueueType m_QueuedGroups[MAX_BATTLEGROUND_BRACKETS][BG_QUEUE_GROUP_TYPES_COUNT]
uint32 GetPlayersInQueue(TeamId id)
bool CheckPremadeMatch(BattlegroundBracketId bracket_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam)
EventProcessor m_events
uint32 m_WaitTimeLastPlayer[BG_TEAMS_COUNT][MAX_BATTLEGROUND_BRACKETS]
SelectionPool m_SelectionPools[BG_TEAMS_COUNT]
void PSendSysMessage(const char *format,...) ATTR_PRINTF(2
Definition Chat.cpp:221
Definition Group.h:147
GroupReference * GetFirstMember()
Definition Group.h:225
GroupReference * next()
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
uint32 GetGUIDLow() const
Definition Object.h:120
uint32 GetTeam() const
Definition Player.h:2527
uint32 GetBattlegroundQueueJoinTime(BattlegroundTypeId bgTypeId) const
Definition Player.h:2707
WorldSession * GetSession() const
Definition Player.h:2417
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition Player.cpp:19282
uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:19233
void SetInviteForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId, uint32 instanceId)
Definition Player.cpp:19295
std::string const & GetName() const
Definition Object.h:664
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
#define sWorld
Definition World.h:910
@ CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH
Definition World.h:294
@ CONFIG_BATTLEGROUND_INVITATION_TYPE
Definition World.h:292
@ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY
Definition World.h:127
@ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE
Definition World.h:126
uint32 IsInvitedToBGInstanceGUID
std::map< uint64, PlayerQueueInfo * > Players
uint32 OpponentsMatchmakerRating
BattlegroundTypeId BgTypeId
GroupQueueInfo * GroupInfo
uint32 maxLevel
BattlegroundBracketId GetBracketId() const
uint32 minLevel