TrinityCore
Loading...
Searching...
No Matches
BattlegroundMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "BattlegroundMgr.h"
19#include "Arena.h"
20#include "BattlegroundPackets.h"
21#include "Containers.h"
22#include "DB2Stores.h"
23#include "DatabaseEnv.h"
24#include "DisableMgr.h"
25#include "GameEventMgr.h"
26#include "GossipDef.h"
27#include "Language.h"
28#include "Log.h"
29#include "MapManager.h"
30#include "MapUtils.h"
31#include "ObjectMgr.h"
32#include "Player.h"
33#include "SharedDefines.h"
34#include "World.h"
35#include "WorldSession.h"
36
41
46
51
56
61
62/*********************************************************/
63/*** BATTLEGROUND MANAGER ***/
64/*********************************************************/
65
67 m_NextRatedArenaUpdate(sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER)),
68 m_UpdateTimer(0), m_ArenaTesting(0), m_Testing(false)
69{ }
70
75
81
87
88// used to update running battlegrounds, and delete finished ones
90{
91 m_UpdateTimer += diff;
93 {
94 for (BattlegroundDataContainer::iterator itr1 = bgDataStore.begin(); itr1 != bgDataStore.end(); ++itr1)
95 {
96 BattlegroundContainer& bgs = itr1->second.m_Battlegrounds;
97 BattlegroundContainer::iterator itrDelete = bgs.begin();
98 for (BattlegroundContainer::iterator itr = itrDelete; itr != bgs.end();)
99 {
100 itrDelete = itr++;
101 Battleground* bg = itrDelete->second.get();
102
104 if (bg->ToBeDeleted())
105 {
106 BattlegroundClientIdsContainer& clients = itr1->second.m_ClientBattlegroundIds[bg->GetBracketId()];
107 if (!clients.empty())
108 clients.erase(bg->GetClientInstanceID());
109
110 // move out unique_ptr to delete after erasing
111 Trinity::unique_trackable_ptr<Battleground> bgPtr = std::move(itrDelete->second);
112
113 bgs.erase(itrDelete);
114 }
115 }
116 }
117
118 m_UpdateTimer = 0;
119 }
120
121 // update events timer
122 for (std::pair<BattlegroundQueueTypeId const, BattlegroundQueue>& pair : m_BattlegroundQueues)
123 pair.second.UpdateEvents(diff);
124
125 // update scheduled queues
126 if (!m_QueueUpdateScheduler.empty())
127 {
128 std::vector<ScheduledQueueUpdate> scheduled;
129 std::swap(scheduled, m_QueueUpdateScheduler);
130
131 for (auto& [arenaMMRating, bgQueueTypeId, bracket_id] : scheduled)
132 GetBattlegroundQueue(bgQueueTypeId).BattlegroundQueueUpdate(diff, bracket_id, arenaMMRating);
133 }
134
135 // if rating difference counts, maybe force-update queues
137 {
138 // it's time to force update
139 if (m_NextRatedArenaUpdate < diff)
140 {
141 // forced update for rated arenas (scan all, but skipped non rated)
142 TC_LOG_TRACE("bg.arena", "BattlegroundMgr: UPDATING ARENA QUEUES");
144 {
146 for (int bracket = BG_BRACKET_ID_FIRST; bracket < MAX_BATTLEGROUND_BRACKETS; ++bracket)
147 GetBattlegroundQueue(ratedArenaQueueId).BattlegroundQueueUpdate(diff, BattlegroundBracketId(bracket), 0);
148 }
149
151 }
152 else
154 }
155}
156
158{
159 header->Ticket.RequesterGuid = player->GetGUID();
160 header->Ticket.Id = ticketId;
162 header->Ticket.Time = joinTime;
163 header->QueueID.push_back(queueId.GetPacked());
164 header->RangeMin = 0; // seems to always be 0
165 header->RangeMax = GetMaxLevelForExpansion(CURRENT_EXPANSION); // alwyas max level of current expansion. Might be limited to account
166 header->TeamSize = queueId.TeamSize;
167 header->InstanceID = 0; // seems to always be 0
168 header->RegisteredMatch = queueId.Rated;
169 header->TournamentRules = false;
170}
171
173{
174 battlefieldStatus->Ticket.RequesterGuid = player->GetGUID();
175 battlefieldStatus->Ticket.Id = ticketId;
177 battlefieldStatus->Ticket.Time = joinTime;
178}
179
181{
182 BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, player, ticketId, joinTime, queueId);
183 battlefieldStatus->Mapid = bg->GetMapId();
184 battlefieldStatus->Timeout = timeout;
185 battlefieldStatus->Role = 0;
186}
187
189{
190 BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, player, ticketId, joinTime, queueId);
191 battlefieldStatus->ShutdownTimer = bg->GetRemainingTime();
192 battlefieldStatus->ArenaFaction = player->GetBGTeam() == HORDE ? PVP_TEAM_HORDE : PVP_TEAM_ALLIANCE;
193 battlefieldStatus->LeftEarly = false;
194 battlefieldStatus->StartTimer = bg->GetElapsedTime();
195 battlefieldStatus->Mapid = bg->GetMapId();
196}
197
198void BattlegroundMgr::BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued* battlefieldStatus, Player const* player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime, bool asGroup)
199{
200 BuildBattlegroundStatusHeader(&battlefieldStatus->Hdr, player, ticketId, joinTime, queueId);
201 battlefieldStatus->AverageWaitTime = avgWaitTime;
202 battlefieldStatus->AsGroup = asGroup;
203 battlefieldStatus->SuspendedQueue = false;
204 battlefieldStatus->EligibleForMatchmaking = true;
205 battlefieldStatus->WaitTime = GetMSTimeDiffToNow(joinTime);
206}
207
209{
210 battlefieldStatus->Ticket.RequesterGuid = player->GetGUID();
211 battlefieldStatus->Ticket.Id = ticketId;
213 battlefieldStatus->Ticket.Time = player->GetBattlegroundQueueJoinTime(queueId);
214 battlefieldStatus->QueueID = queueId.GetPacked();
215 battlefieldStatus->Reason = result;
216 if (errorGuid && (result == ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND || result == ERR_BATTLEGROUND_JOIN_TIMED_OUT))
217 battlefieldStatus->ClientID = *errorGuid;
218}
219
221{
222 if (!instanceId)
223 return nullptr;
224
225 BattlegroundDataContainer::const_iterator begin, end;
226
227 if (bgTypeId == BATTLEGROUND_TYPE_NONE || IsRandomBattleground(bgTypeId))
228 {
229 begin = bgDataStore.begin();
230 end = bgDataStore.end();
231 }
232 else
233 {
234 end = bgDataStore.find(bgTypeId);
235 if (end == bgDataStore.end())
236 return nullptr;
237 begin = end++;
238 }
239
240 for (BattlegroundDataContainer::const_iterator it = begin; it != end; ++it)
241 {
242 BattlegroundContainer const& bgs = it->second.m_Battlegrounds;
243 BattlegroundContainer::const_iterator itr = bgs.find(instanceId);
244 if (itr != bgs.end())
245 return itr->second.get();
246 }
247
248 return nullptr;
249}
250
252{
253 uint32 oldMSTime = getMSTime();
254 // 0 1 2
255 QueryResult result = WorldDatabase.Query("SELECT MapId, BattlemasterListId, ScriptName FROM battleground_scripts");
256
257 if (!result)
258 {
259 TC_LOG_INFO("server.loading", ">> Loaded 0 battleground scripts. DB table `battleground_scripts` is empty!");
260 return;
261 }
262
263 uint32 count = 0;
264 do
265 {
266 Field* fields = result->Fetch();
267
268 uint32 mapID = fields[0].GetUInt32();
269
270 MapEntry const* mapEntry = sMapStore.LookupEntry(mapID);
271 if (!mapEntry || !mapEntry->IsBattlegroundOrArena())
272 {
273 TC_LOG_ERROR("sql.sql", "BattlegroundMgr::LoadBattlegroundScriptTemplate: bad mapid {}! Map doesn't exist or is not a battleground/arena!", mapID);
274 continue;
275 }
276
277 BattlegroundTypeId bgTypeId = static_cast<BattlegroundTypeId>(fields[1].GetUInt32());
279 {
280 TC_LOG_ERROR("sql.sql", "BattlegroundMgr::LoadBattlegroundScriptTemplate: bad battlemasterlist id {}! Battleground doesn't exist or is not supported in battleground_template!", bgTypeId);
281 continue;
282 }
283
284 BattlegroundScriptTemplate& scriptTemplate = _battlegroundScriptTemplates[{ mapID, bgTypeId }];
285 scriptTemplate.MapId = mapID;
286 scriptTemplate.Id = bgTypeId;
287 scriptTemplate.ScriptId = sObjectMgr->GetScriptId(fields[2].GetStringView());
288
289 ++count;
290 } while (result->NextRow());
291
292 TC_LOG_INFO("server.loading", ">> Loaded {} battleground scripts in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
293}
294
296{
298 return scriptTemplate;
299
300 // fall back to 0 for no specific battleground type id
302}
303
304void BattlegroundMgr::QueuePlayerForArena(Player const* player, uint8 teamSize, uint8 roles)
305{
307 packet.TeamSizeIndex = teamSize;
308 packet.Roles = roles;
309
310 player->GetSession()->HandleBattlemasterJoinArena(packet);
311}
312
314{
315 if (IsArenaType(bgTypeId))
316 return 0; //arenas don't have client-instanceids
317
318 // we create here an instanceid, which is just for
319 // displaying this to the client and without any other use..
320 // the client-instanceIds are unique for each battleground-type
321 // the instance-id just needs to be as low as possible, beginning with 1
322 // the following works, because std::set is default ordered with "<"
323 // the optimalization would be to use as bitmask std::vector<uint32> - but that would only make code unreadable
324
325 BattlegroundClientIdsContainer& clientIds = bgDataStore[bgTypeId].m_ClientBattlegroundIds[bracket_id];
326 uint32 lastId = 0;
327 for (BattlegroundClientIdsContainer::const_iterator itr = clientIds.begin(); itr != clientIds.end();)
328 {
329 if ((++lastId) != *itr) //if there is a gap between the ids, we will break..
330 break;
331 lastId = *itr;
332 }
333
334 clientIds.insert(++lastId);
335 return lastId;
336}
337
338// create a new battleground that will really be used to play
340{
342
343 // get the template BG
344 BattlegroundTemplate const* bg_template = GetBattlegroundTemplateByTypeId(bgTypeId);
345
346 if (!bg_template)
347 {
348 TC_LOG_ERROR("bg.battleground", "Battleground: CreateNewBattleground - bg template not found for {}", bgTypeId);
349 return nullptr;
350 }
351
352 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketById(bg_template->MapIDs.front(), bracketId);
353 if (!bracketEntry)
354 {
355 TC_LOG_ERROR("bg.battleground", "Battleground: CreateNewBattleground: bg bracket entry not found for map {} bracket id {}", bg_template->MapIDs.front(), bracketId);
356 return nullptr;
357 }
358
359 Battleground* bg = nullptr;
360 if (bg_template->IsArena())
361 bg = new Arena(bg_template);
362 else
363 bg = new Battleground(bg_template);
364
365 bg->SetBracket(bracketEntry);
366 bg->SetInstanceID(sMapMgr->GenerateInstanceId());
368 // reset the new bg (set status to status_wait_queue from status_none)
369 // this shouldn't be needed anymore as a new Battleground instance is created each time. But some bg sub classes still depend on it.
370 bg->Reset();
371 bg->SetStatus(STATUS_WAIT_JOIN); // start the joining of the bg
372 bg->SetArenaType(queueId.TeamSize);
373 bg->SetRated(queueId.Rated);
374
375 return bg;
376}
377
379{
380 uint32 oldMSTime = getMSTime();
381
382 // 0 1 2 3 4 5
383 QueryResult result = WorldDatabase.Query("SELECT ID, AllianceStartLoc, HordeStartLoc, StartMaxDist, Weight, ScriptName FROM battleground_template");
384 if (!result)
385 {
386 TC_LOG_INFO("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty.");
387 return;
388 }
389
390 std::unordered_map<BattlegroundTypeId, std::vector<int32>> mapsByBattleground;
391 for (BattlemasterListXMapEntry const* battlemasterListXMap : sBattlemasterListXMapStore)
392 if (sBattlemasterListStore.HasRecord(battlemasterListXMap->BattlemasterListID) && sMapStore.HasRecord(battlemasterListXMap->MapID))
393 mapsByBattleground[BattlegroundTypeId(battlemasterListXMap->BattlemasterListID)].push_back(battlemasterListXMap->MapID);
394
395 uint32 count = 0;
396
397 do
398 {
399 Field* fields = result->Fetch();
400
401 BattlegroundTypeId bgTypeId = BattlegroundTypeId(fields[0].GetUInt32());
402
404 continue;
405
406 // can be overwrite by values from DB
407 BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
408 if (!bl)
409 {
410 TC_LOG_ERROR("bg.battleground", "Battleground ID {} could not be found in BattlemasterList.dbc. The battleground was not created.", bgTypeId);
411 continue;
412 }
413
414 BattlegroundTemplate& bgTemplate = _battlegroundTemplates[bgTypeId];
415 bgTemplate.Id = bgTypeId;
416 float dist = fields[3].GetFloat();
417 bgTemplate.MaxStartDistSq = dist * dist;
418 bgTemplate.Weight = fields[4].GetUInt8();
419 bgTemplate.ScriptId = sObjectMgr->GetScriptId(fields[5].GetStringView());
420 bgTemplate.BattlemasterEntry = bl;
421 bgTemplate.MapIDs = std::move(mapsByBattleground[bgTypeId]);
422
423 if (bgTemplate.Id != BATTLEGROUND_AA && !IsRandomBattleground(bgTemplate.Id))
424 {
425 uint32 startId = fields[1].GetUInt32();
426 if (WorldSafeLocsEntry const* start = sObjectMgr->GetWorldSafeLoc(startId))
427 bgTemplate.StartLocation[TEAM_ALLIANCE] = start;
428 else if (bgTemplate.StartLocation[TEAM_ALLIANCE]) // reload case
429 TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains a non-existing WorldSafeLocs.dbc id {} in field `AllianceStartLoc`. Ignoring.", bgTemplate.Id, startId);
430 else
431 {
432 TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains a non-existing WorldSafeLocs.dbc id {} in field `AllianceStartLoc`. BG not created.", bgTemplate.Id, startId);
433 _battlegroundTemplates.erase(bgTypeId);
434 continue;
435 }
436
437 startId = fields[2].GetUInt32();
438 if (WorldSafeLocsEntry const* start = sObjectMgr->GetWorldSafeLoc(startId))
439 bgTemplate.StartLocation[TEAM_HORDE] = start;
440 else if (bgTemplate.StartLocation[TEAM_HORDE]) // reload case
441 TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains a non-existing WorldSafeLocs.dbc id {} in field `HordeStartLoc`. Ignoring.", bgTemplate.Id, startId);
442 else
443 {
444 TC_LOG_ERROR("sql.sql", "Table `battleground_template` for id {} contains a non-existing WorldSafeLocs.dbc id {} in field `HordeStartLoc`. BG not created.", bgTemplate.Id, startId);
445 _battlegroundTemplates.erase(bgTypeId);
446 continue;
447 }
448 }
449
450 if (bgTemplate.MapIDs.size() == 1)
451 _battlegroundMapTemplates[bgTemplate.MapIDs.front()] = &_battlegroundTemplates[bgTypeId];
452
453 ++count;
454 }
455 while (result->NextRow());
456
457 TC_LOG_INFO("server.loading", ">> Loaded {} battlegrounds in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
458}
459
461{
462 BattlegroundTemplate const* bgTemplate = GetBattlegroundTemplateByTypeId(bgTypeId);
463 if (!bgTemplate)
464 return;
465
466 player->PlayerTalkClass->GetInteractionData().StartInteraction(guid, PlayerInteractionType::BattleMaster);
467
469 battlefieldList.BattlemasterGuid = guid;
470 battlefieldList.BattlemasterListID = bgTypeId;
471 battlefieldList.MinLevel = bgTemplate->GetMinLevel();
472 battlefieldList.MaxLevel = bgTemplate->GetMaxLevel();
473 battlefieldList.PvpAnywhere = guid.IsEmpty();
474 battlefieldList.HasRandomWinToday = player->GetRandomWinner();
475 player->SendDirectMessage(battlefieldList.Write());
476}
477
478/*static*/ void BattlegroundMgr::SendToBattleground(Player* player, Battleground const* battleground)
479{
480 if (!battleground)
481 {
482 TC_LOG_ERROR("bg.battleground", "BattlegroundMgr::SendToBattleground: Battleground not found while trying to teleport player {}", player->GetName());
483 return;
484 }
485
486 uint32 mapid = battleground->GetMapId();
487 Team team = player->GetBGTeam();
488
490 TC_LOG_DEBUG("bg.battleground", "BattlegroundMgr::SendToBattleground: Sending {} to map {}, {} (bgType {})", player->GetName(), mapid, pos->Loc, battleground->GetTypeID());
491 player->TeleportTo({ .Location = pos->Loc, .TransportGuid = pos->TransportSpawnId ? ObjectGuid::Create<HighGuid::Transport>(*pos->TransportSpawnId) : ObjectGuid::Empty });
492}
493
495{
496 return bgTypeId == BATTLEGROUND_AA
497 || bgTypeId == BATTLEGROUND_BE
498 || bgTypeId == BATTLEGROUND_NA
499 || bgTypeId == BATTLEGROUND_DS
500 || bgTypeId == BATTLEGROUND_RV
501 || bgTypeId == BATTLEGROUND_RL;
502}
503
505{
506 return battlemasterListId == BATTLEGROUND_RB || battlemasterListId == BATTLEGROUND_RANDOM_EPIC;
507}
508
510{
511 return { .BattlemasterListId = battlemasterListId, .Type = AsUnderlyingType(type), .Rated = rated, .TeamSize = teamSize };
512}
513
519
521{
522 if (battlemasterListId != 0)
523 {
524 BattlegroundTemplate const* bgTemplate = GetBattlegroundTemplateByTypeId(static_cast<BattlegroundTypeId>(battlemasterListId));
525 if (!bgTemplate)
526 return false;
527
528 if (!bgTemplate->IsArena())
529 return false;
530 }
531
532 if (m_ArenaTesting != battlemasterListId)
533 sWorld->SendWorldText((battlemasterListId != 0) ? LANG_DEBUG_ARENA_ON : LANG_DEBUG_ARENA_OFF);
534
535 m_ArenaTesting = battlemasterListId;
536 return true;
537}
538
540{
541 BattlemasterListEntry const* battlemasterList = sBattlemasterListStore.LookupEntry(bgQueueTypeId.BattlemasterListId);
542 if (!battlemasterList)
543 return false;
544
545 switch (BattlegroundQueueIdType(bgQueueTypeId.Type))
546 {
548 if (battlemasterList->GetType() != BattlemasterType::Battleground)
549 return false;
550 if (bgQueueTypeId.TeamSize)
551 return false;
552 break;
554 if (battlemasterList->GetType() != BattlemasterType::Arena)
555 return false;
556 if (!bgQueueTypeId.Rated)
557 return false;
558 if (!bgQueueTypeId.TeamSize)
559 return false;
560 break;
562 if (bgQueueTypeId.Rated)
563 return false;
564 break;
566 if (battlemasterList->GetType() != BattlemasterType::Arena)
567 return false;
568 if (!bgQueueTypeId.Rated)
569 return false;
570 if (bgQueueTypeId.TeamSize != ARENA_TYPE_3v3)
571 return false;
572 break;
573 default:
574 return false;
575 }
576
577 return true;
578}
579
581{
582 //This method must be atomic, @todo add mutex
583 //we will use only 1 number created of bgTypeId and bracket_id
584 ScheduledQueueUpdate scheduleId{ arenaMatchmakerRating, bgQueueTypeId, bracket_id };
585 if (std::find(m_QueueUpdateScheduler.begin(), m_QueueUpdateScheduler.end(), scheduleId) == m_QueueUpdateScheduler.end())
586 m_QueueUpdateScheduler.push_back(scheduleId);
587}
588
590{
591 // this is for stupid people who can't use brain and set max rating difference to 0
593 if (diff == 0)
594 diff = 5000;
595 return diff;
596}
597
602
607
609{
610 uint32 oldMSTime = getMSTime();
611
612 mBattleMastersMap.clear(); // need for reload case
613
614 QueryResult result = WorldDatabase.Query("SELECT entry, bg_template FROM battlemaster_entry");
615
616 if (!result)
617 {
618 TC_LOG_INFO("server.loading", ">> Loaded 0 battlemaster entries. DB table `battlemaster_entry` is empty!");
619 return;
620 }
621
622 uint32 count = 0;
623
624 do
625 {
626 ++count;
627
628 Field* fields = result->Fetch();
629
630 uint32 entry = fields[0].GetUInt32();
631 if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
632 {
633 if ((cInfo->npcflag & UNIT_NPC_FLAG_BATTLEMASTER) == 0)
634 TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) listed in `battlemaster_entry` is not a battlemaster.", entry);
635 }
636 else
637 {
638 TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) listed in `battlemaster_entry` does not exist.", entry);
639 continue;
640 }
641
642 uint32 bgTypeId = fields[1].GetUInt32();
643 if (!sBattlemasterListStore.LookupEntry(bgTypeId))
644 {
645 TC_LOG_ERROR("sql.sql", "Table `battlemaster_entry` contains entry {} for a non-existing battleground type {}, ignored.", entry, bgTypeId);
646 continue;
647 }
648
649 mBattleMastersMap[entry] = BattlegroundTypeId(bgTypeId);
650 }
651 while (result->NextRow());
652
654
655 TC_LOG_INFO("server.loading", ">> Loaded {} battlemaster entries in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
656}
657
659{
660 CreatureTemplateContainer const& ctc = sObjectMgr->GetCreatureTemplates();
661 for (auto const& creatureTemplatePair : ctc)
662 {
663 if ((creatureTemplatePair.second.npcflag & UNIT_NPC_FLAG_BATTLEMASTER) && !mBattleMastersMap.count(creatureTemplatePair.first))
664 {
665 TC_LOG_ERROR("sql.sql", "Creature_Template Entry: {} has UNIT_NPC_FLAG_BATTLEMASTER, but no data in the `battlemaster_entry` table. Removing flag.", creatureTemplatePair.first);
666 const_cast<CreatureTemplate&>(creatureTemplatePair.second).npcflag &= ~UNIT_NPC_FLAG_BATTLEMASTER;
667 }
668 }
669}
670
686
702
707
709{
710 if (BattlegroundTemplate const* bgTemplate = GetBattlegroundTemplateByTypeId(bgTypeId))
711 {
712 if (bgTemplate->IsArena() && isArenaTesting())
713 return static_cast<BattlegroundTypeId>(m_ArenaTesting);
714
715 std::vector<BattlegroundTemplate const*> ids;
716 ids.reserve(bgTemplate->MapIDs.size());
717 for (int32 mapId : bgTemplate->MapIDs)
719 ids.push_back(bg);
720
721 if (!ids.empty())
722 return (*Trinity::Containers::SelectRandomWeightedContainerElement(ids, [](BattlegroundTemplate const* bg) { return bg->Weight; }))->Id;
723 }
724
726}
727
732
737
739{
741 for (BGFreeSlotQueueContainer::iterator itr = queues.begin(); itr != queues.end(); ++itr)
742 if ((*itr)->GetInstanceID() == instanceId)
743 {
744 queues.erase(itr);
745 return;
746 }
747}
748
750{
751 if (bg)
752 {
754 ptr.reset(bg);
755 bg->SetWeakPtr(ptr);
756 }
757}
@ BATTLEGROUND_OBJECTIVE_UPDATE_INTERVAL
std::set< uint32 > BattlegroundClientIdsContainer
std::map< uint32, Trinity::unique_trackable_ptr< Battleground > > BattlegroundContainer
std::list< Battleground * > BGFreeSlotQueueContainer
@ ARENA_TYPE_5v5
@ ARENA_TYPE_3v3
@ ARENA_TYPE_2v2
BattlegroundQueueIdType
@ STATUS_WAIT_JOIN
DB2Storage< BattlemasterListEntry > sBattlemasterListStore("BattlemasterList.db2", &BattlemasterListLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< BattlemasterListXMapEntry > sBattlemasterListXMapStore("BattlemasterListXMap.db2", &BattlemasterListXMapLoadInfo::Instance)
BattlegroundBracketId
Definition DBCEnums.h:53
@ BG_BRACKET_ID_FIRST
Definition DBCEnums.h:54
@ MAX_BATTLEGROUND_BRACKETS
Definition DBCEnums.h:58
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
@ DISABLE_TYPE_BATTLEGROUND
Definition DisableMgr.h:30
bool IsHolidayActive(HolidayIds id)
@ LANG_DEBUG_BG_OFF
Definition Language.h:733
@ LANG_DEBUG_ARENA_OFF
Definition Language.h:731
@ LANG_DEBUG_BG_ON
Definition Language.h:732
@ LANG_DEBUG_ARENA_ON
Definition Language.h:730
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
#define TC_LOG_TRACE(filterType__, message__,...)
Definition Log.h:178
#define sMapMgr
Definition MapManager.h:186
#define sObjectMgr
Definition ObjectMgr.h:1885
std::unordered_map< uint32, CreatureTemplate > CreatureTemplateContainer
Definition ObjectMgr.h:488
@ CMSG_BATTLEMASTER_JOIN_ARENA
Definition Opcodes.h:107
GroupJoinBattlegroundResult
@ ERR_BATTLEGROUND_JOIN_TIMED_OUT
@ ERR_BATTLEGROUND_NOT_IN_BATTLEGROUND
#define CURRENT_EXPANSION
constexpr uint32 GetMaxLevelForExpansion(uint32 expansion)
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ HORDE
BattlegroundTypeId
@ BATTLEGROUND_BFG
@ BATTLEGROUND_IC
@ BATTLEGROUND_AA
@ BATTLEGROUND_WS
@ BATTLEGROUND_EY
@ BATTLEGROUND_AV
@ BATTLEGROUND_BE
@ BATTLEGROUND_TP
@ BATTLEGROUND_RV
@ BATTLEGROUND_TYPE_NONE
@ BATTLEGROUND_NA
@ BATTLEGROUND_RANDOM_EPIC
@ BATTLEGROUND_DS
@ BATTLEGROUND_SA
@ BATTLEGROUND_AB
@ BATTLEGROUND_RL
@ BATTLEGROUND_RB
HolidayIds
@ HOLIDAY_NONE
@ HOLIDAY_CALL_TO_ARMS_AB
@ HOLIDAY_CALL_TO_ARMS_ES
@ HOLIDAY_CALL_TO_ARMS_SA
@ HOLIDAY_CALL_TO_ARMS_IC
@ HOLIDAY_CALL_TO_ARMS_BG
@ HOLIDAY_CALL_TO_ARMS_AV
@ HOLIDAY_CALL_TO_ARMS_WG
@ HOLIDAY_CALL_TO_ARMS_TP
@ PVP_TEAM_HORDE
@ PVP_TEAM_ALLIANCE
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
@ UNIT_NPC_FLAG_BATTLEMASTER
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
Definition Arena.h:57
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
BattlegroundMapTemplateContainer _battlegroundMapTemplates
static void BuildBattlegroundStatusHeader(WorldPackets::Battleground::BattlefieldStatusHeader *header, Player const *player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId)
static void BuildBattlegroundStatusNeedConfirmation(WorldPackets::Battleground::BattlefieldStatusNeedConfirmation *battlefieldStatus, Battleground const *bg, Player const *player, uint32 ticketId, uint32 joinTime, uint32 timeout, BattlegroundQueueTypeId queueId)
std::map< BattlegroundQueueTypeId, BattlegroundQueue > m_BattlegroundQueues
BattlegroundTemplate const * GetBattlegroundTemplateByMapId(uint32 mapId)
static void BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive *battlefieldStatus, Battleground const *bg, Player const *player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId)
std::vector< ScheduledQueueUpdate > m_QueueUpdateScheduler
Battleground * GetBattleground(uint32 InstanceID, BattlegroundTypeId bgTypeId)
BattlegroundTemplateMap _battlegroundTemplates
static BattlegroundQueueTypeId BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize)
void LoadBattlegroundScriptTemplate()
uint32 GetMaxRatingDifference() const
static void QueuePlayerForArena(Player const *player, uint8 teamSize, uint8 roles)
static void SendToBattleground(Player *player, Battleground const *battleground)
static BattlegroundMgr * instance()
BGFreeSlotQueueContainer & GetBGFreeSlotQueueStore(uint32 mapId)
static bool IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId)
BattlegroundTypeId GetRandomBG(BattlegroundTypeId id)
static bool IsArenaType(BattlegroundTypeId bgTypeId)
static void BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone *battlefieldStatus, Player const *player, uint32 ticketId, uint32 joinTime)
bool isArenaTesting() const
BattlegroundQueue & GetBattlegroundQueue(BattlegroundQueueTypeId bgQueueTypeId)
void AddBattleground(Battleground *bg)
void AddToBGFreeSlotQueue(Battleground *bg)
BattleMastersMap mBattleMastersMap
std::map< uint32, BGFreeSlotQueueContainer > m_BGFreeSlotQueue
static bool IsRandomBattleground(uint32 battlemasterListId)
void ScheduleQueueUpdate(uint32 arenaMatchmakerRating, BattlegroundQueueTypeId bgQueueTypeId, BattlegroundBracketId bracket_id)
void SendBattlegroundList(Player *player, ObjectGuid const &guid, BattlegroundTypeId bgTypeId)
BattlegroundTemplate const * GetBattlegroundTemplateByTypeId(BattlegroundTypeId id)
Battleground * CreateNewBattleground(BattlegroundQueueTypeId queueId, BattlegroundBracketId bracketId)
void RemoveFromBGFreeSlotQueue(uint32 mapId, uint32 instanceId)
uint32 GetRatingDiscardTimer() const
bool ToggleArenaTesting(uint32 battlemasterListId)
static BattlegroundTypeId WeekendHolidayIdToBGType(HolidayIds holiday)
static HolidayIds BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId)
static void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued *battlefieldStatus, Player const *player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime, bool asGroup)
uint32 GetPrematureFinishTime() const
uint32 CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id)
void Update(uint32 diff)
uint32 m_NextRatedArenaUpdate
BattlegroundScriptTemplate const * FindBattlegroundScriptTemplate(uint32 mapId, BattlegroundTypeId bgTypeId) const
std::map< std::pair< int32, uint32 >, BattlegroundScriptTemplate > _battlegroundScriptTemplates
static bool IsBGWeekend(BattlegroundTypeId bgTypeId)
static void BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed *battlefieldStatus, BattlegroundQueueTypeId queueId, Player const *player, uint32 ticketId, GroupJoinBattlegroundResult result, ObjectGuid const *errorGuid=nullptr)
BattlegroundDataContainer bgDataStore
void BattlegroundQueueUpdate(uint32 diff, BattlegroundBracketId bracket_id, uint32 minRating=0)
void SetInstanceID(uint32 InstanceID)
WorldSafeLocsEntry const * GetTeamStartPosition(TeamId teamId) const
uint32 GetMapId() const
bool ToBeDeleted() const
void SetRated(bool state)
uint32 GetRemainingTime() const
BattlegroundTypeId GetTypeID() const
void Update(uint32 diff)
uint32 GetInstanceID() const
uint32 GetClientInstanceID() const
void SetClientInstanceID(uint32 InstanceID)
static TeamId GetTeamIndexByTeamId(Team team)
void SetStatus(BattlegroundStatus Status)
void SetArenaType(uint8 type)
BattlegroundBracketId GetBracketId() const
uint32 GetElapsedTime() const
void SetBracket(PVPDifficultyEntry const *bracketEntry)
void SetWeakPtr(Trinity::unique_weak_ptr< Battleground > weakRef)
static PVPDifficultyEntry const * GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id)
Class used to access individual fields of database query result.
Definition Field.h:94
float GetFloat() const noexcept
Definition Field.cpp:85
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
uint8 GetUInt8() const noexcept
Definition Field.cpp:29
static ObjectGuid const Empty
Definition ObjectGuid.h:314
bool IsEmpty() const
Definition ObjectGuid.h:362
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
uint32 GetBattlegroundQueueJoinTime(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:25727
WorldSession * GetSession() const
Definition Player.h:2272
bool GetRandomWinner() const
Definition Player.h:2624
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options=TELE_TO_NONE, Optional< uint32 > instanceId={}, uint32 teleportSpellId=0)
Definition Player.cpp:1226
Team GetBGTeam() const
Definition Player.cpp:24358
std::unique_ptr< PlayerMenu > PlayerTalkClass
Definition Player.h:2570
Specialized variant of std::shared_ptr that enforces unique ownership and/or std::unique_ptr with std...
std::string const & GetName() const
Definition Object.h:342
void HandleBattlemasterJoinArena(WorldPackets::Battleground::BattlemasterJoinArena &packet)
#define sWorld
Definition World.h:916
@ CONFIG_ARENA_MAX_RATING_DIFFERENCE
Definition World.h:341
@ CONFIG_ARENA_RATED_UPDATE_TIMER
Definition World.h:343
@ CONFIG_ARENA_RATING_DISCARD_TIMER
Definition World.h:342
@ CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER
Definition World.h:338
bool IsDisabledFor(DisableType type, uint32 entry, WorldObject const *ref, uint8 flags)
auto SelectRandomWeightedContainerElement(C const &container, std::span< double > const &weights) -> decltype(std::ranges::begin(container))
Definition Containers.h:127
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
Definition Session.h:37
constexpr uint64 GetPacked() const
BattlegroundTypeId Id
BattlemasterListEntry const * BattlemasterEntry
uint16 GetMaxPlayersPerTeam() const
std::vector< int32 > MapIDs
WorldSafeLocsEntry const * StartLocation[PVP_TEAMS_COUNT]
uint16 GetMinPlayersPerTeam() const
BattlemasterType GetType() const
bool IsBattlegroundOrArena() const
BattlegroundBracketId GetBracketId() const
Optional< ObjectGuid::LowType > TransportSpawnId
Definition ObjectMgr.h:837
WorldLocation Loc
Definition ObjectMgr.h:836