TrinityCore
Loading...
Searching...
No Matches
BattleGroundHandler.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 "WorldSession.h"
19#include "ArenaTeam.h"
20#include "ArenaTeamMgr.h"
21#include "Battlefield.h"
22#include "BattlefieldMgr.h"
23#include "Battleground.h"
24#include "BattlegroundMgr.h"
25#include "BattlegroundPackets.h"
26#include "Chat.h"
27#include "Common.h"
28#include "Creature.h"
29#include "DB2Stores.h"
30#include "DisableMgr.h"
31#include "GameTime.h"
32#include "Group.h"
33#include "Language.h"
34#include "Log.h"
35#include "NPCPackets.h"
36#include "Object.h"
37#include "ObjectAccessor.h"
38#include "Player.h"
39#include "SpellAuras.h"
40#include "SpellMgr.h"
41#include "SpellInfo.h"
42#include "World.h"
43
45{
47 if (!unit)
48 return;
49
50 // Stop the npc if moving
52 unit->PauseMovement(pause);
53 unit->SetHomePosition(unit->GetPosition());
54
55 BattlegroundTypeId bgTypeId = sBattlegroundMgr->GetBattleMasterBG(unit->GetEntry());
56
57 if (!_player->GetBGAccessByLevel(bgTypeId))
58 {
59 // temp, must be gossip message...
61 return;
62 }
63
64 sBattlegroundMgr->SendBattlegroundList(_player, hello.Unit, bgTypeId);
65}
66
68{
69 bool isPremade = false;
70 if (battlemasterJoin.QueueIDs.empty())
71 {
72 TC_LOG_ERROR("network", "Battleground: no bgtype received. possible cheater? {}", _player->GetGUID().ToString());
73 return;
74 }
75
76 BattlegroundQueueTypeId bgQueueTypeId = BattlegroundQueueTypeId::FromPacked(battlemasterJoin.QueueIDs[0]);
77 if (!BattlegroundMgr::IsValidQueueId(bgQueueTypeId))
78 {
79 TC_LOG_ERROR("network", "Battleground: invalid bg queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }} received. possible cheater? {}",
80 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize),
82 return;
83 }
84
85 BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.AssertEntry(bgQueueTypeId.BattlemasterListId);
86
87 if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgQueueTypeId.BattlemasterListId, nullptr) || battlemasterListEntry->GetFlags().HasFlag(BattlemasterListFlags::InternalOnly))
88 {
90 return;
91 }
92
94
95 // ignore if player is already in BG
97 return;
98
99 BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(bgTypeId);
100 if (!bgTemplate)
101 return;
102
103 // expected bracket entry
104 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgTemplate->MapIDs.front(), _player->GetLevel());
105 if (!bracketEntry)
106 return;
107
109
110 Group const* grp = _player->GetGroup();
111
112 auto getQueueTeam = [&]() -> Team
113 {
114 // mercenary applies only to unrated battlegrounds
115 if (!bgQueueTypeId.Rated && !bgTemplate->IsArena())
116 {
118 return HORDE;
119
121 return ALLIANCE;
122 }
123
124 return Team(_player->GetTeam());
125 };
126
127 // check queue conditions
128 if (!grp)
129 {
130 if (GetPlayer()->isUsingLfg())
131 {
134 SendPacket(battlefieldStatus.Write());
135 return;
136 }
137
138 // check RBAC permissions
139 if (!_player->CanJoinToBattleground(bgTemplate))
140 {
143 SendPacket(battlefieldStatus.Write());
144 return;
145 }
146
147 // check Deserter debuff
148 if (_player->IsDeserter())
149 {
152 SendPacket(battlefieldStatus.Write());
153 return;
154 }
155
158 if (!BattlegroundMgr::IsRandomBattleground(bgTypeId) && isInRandomBgQueue)
159 {
160 // player is already in random queue
162 BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, bgQueueTypeId, _player, 0, ERR_IN_RANDOM_BG);
163 SendPacket(battlefieldStatus.Write());
164 return;
165 }
166
167 if (_player->InBattlegroundQueue(true) && !isInRandomBgQueue && BattlegroundMgr::IsRandomBattleground(bgTypeId))
168 {
169 // player is already in queue, can't start random queue
172 SendPacket(battlefieldStatus.Write());
173 return;
174 }
175
176 // check if already in queue
178 // player is already in this queue
179 return;
180
181 // check if has free queue slots
183 {
186 SendPacket(battlefieldStatus.Write());
187 return;
188 }
189
190 // check Freeze debuff
191 if (_player->HasAura(9454))
192 return;
193
194 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
195 GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, getQueueTeam(), bracketEntry, false, isPremade, 0);
196 uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
197 uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
198
200 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, _player, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, false);
201 SendPacket(battlefieldStatus.Write());
202
203 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }}, {}, NAME {}",
204 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize),
206 }
207 else
208 {
209 if (grp->GetLeaderGUID() != _player->GetGUID())
210 return;
211
212 ObjectGuid errorGuid;
213 err = grp->CanJoinBattlegroundQueue(bgTemplate, bgQueueTypeId, 0, bgTemplate->GetMaxPlayersPerTeam(), false, 0, errorGuid);
214 isPremade = (grp->GetMembersCount() >= bgTemplate->GetMinPlayersPerTeam());
215
216 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
217 GroupQueueInfo* ginfo = nullptr;
218 uint32 avgTime = 0;
219
220 if (!err)
221 {
222 TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:");
223 ginfo = bgQueue.AddGroup(_player, grp, getQueueTeam(), bracketEntry, false, isPremade, 0);
224 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
225 }
226
227 for (GroupReference const& itr : grp->GetMembers())
228 {
229 Player* member = itr.GetSource();
230 if (err)
231 {
233 BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, bgQueueTypeId, _player, 0, err, &errorGuid);
234 member->SendDirectMessage(battlefieldStatus.Write());
235 continue;
236 }
237
238 // add to queue
239 uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
240
242 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, member, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, true);
243 member->SendDirectMessage(battlefieldStatus.Write());
244 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }}, {}, NAME {}",
245 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize),
246 member->GetGUID().ToString(), member->GetName());
247 }
248 TC_LOG_DEBUG("bg.battleground", "Battleground: group end");
249 }
250
251 sBattlegroundMgr->ScheduleQueueUpdate(0, bgQueueTypeId, bracketEntry->GetBracketId());
252}
253
255{
257 if (!bg)
258 return;
259
260 // Prevent players from sending BuildPvpLogDataPacket in an arena except for when sent in BattleGround::EndBattleGround.
261 if (bg->isArena())
262 return;
263
265 bg->BuildPvPLogDataPacket(pvpMatchStatistics.Data);
266 SendPacket(pvpMatchStatistics.Write());
267}
268
270{
271 BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.LookupEntry(battlefieldList.ListID);
272 if (!battlemasterListEntry)
273 {
274 TC_LOG_DEBUG("bg.battleground", "BattlegroundHandler: invalid bgtype ({}) with player (Name: {}, {}) received.", battlefieldList.ListID, _player->GetName(), _player->GetGUID().ToString());
275 return;
276 }
277
278 sBattlegroundMgr->SendBattlegroundList(_player, ObjectGuid::Empty, BattlegroundTypeId(battlefieldList.ListID));
279}
280
282{
284 {
285 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} Slot: {}, Unk: {}, Time: {}, AcceptedInvite: {}. Player not in queue!",
286 GetPlayerInfo(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time.AsUnderlyingType(), uint32(battlefieldPort.AcceptedInvite));
287 return;
288 }
289
290 BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(battlefieldPort.Ticket.Id);
291 if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
292 {
293 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} Slot: {}, Unk: {}, Time: {}, AcceptedInvite: {}. Invalid queueSlot!",
294 GetPlayerInfo(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time.AsUnderlyingType(), uint32(battlefieldPort.AcceptedInvite));
295 return;
296 }
297
298 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
299
300 //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue::RemovePlayer() function
301 GroupQueueInfo ginfo;
302 if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
303 {
304 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} Slot: {}, Unk: {}, Time: {}, AcceptedInvite: {}. Player not in queue (No player Group Info)!",
305 GetPlayerInfo(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time.AsUnderlyingType(), uint32(battlefieldPort.AcceptedInvite));
306 return;
307 }
308 // if action == 1, then player must have been invited to join
309 if (!ginfo.IsInvitedToBGInstanceGUID && battlefieldPort.AcceptedInvite)
310 {
311 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} Slot: {}, Unk: {}, Time: {}, AcceptedInvite: {}. Player is not invited to any bg!",
312 GetPlayerInfo(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time.AsUnderlyingType(), uint32(battlefieldPort.AcceptedInvite));
313 return;
314 }
315
317 BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(bgTypeId);
318 if (!bgTemplate)
319 {
320 TC_LOG_ERROR("network", "BattlegroundHandle: BattlegroundTemplate not found for type id {}.", bgTypeId);
321 return;
322 }
323
324 uint32 mapId = bgTemplate->MapIDs.front();
325
326 // BGTemplateId returns BATTLEGROUND_AA when it is arena queue.
327 // Do instance id search as there is no AA bg instances.
328 Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId == BATTLEGROUND_AA ? BATTLEGROUND_TYPE_NONE : bgTypeId);
329 if (!bg && battlefieldPort.AcceptedInvite)
330 {
331 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} Slot: {}, Unk: {}, Time: {}, AcceptedInvite: {}. Cant find BG with id {}!",
332 GetPlayerInfo(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time.AsUnderlyingType(), uint32(battlefieldPort.AcceptedInvite), ginfo.IsInvitedToBGInstanceGUID);
333 return;
334 }
335 else if (bg)
336 mapId = bg->GetMapId();
337
338 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} Slot: {}, Unk: {}, Time: {}, AcceptedInvite: {}.",
339 GetPlayerInfo(), battlefieldPort.Ticket.Id, uint32(battlefieldPort.Ticket.Type), battlefieldPort.Ticket.Time.AsUnderlyingType(), uint32(battlefieldPort.AcceptedInvite));
340
341 // expected bracket entry
343 if (!bracketEntry)
344 return;
345
346 //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
347 if (battlefieldPort.AcceptedInvite && bgQueue.GetQueueId().TeamSize == 0)
348 {
349 //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
350 if (_player->IsDeserter())
351 {
352 //send bg command result to show nice message
355 SendPacket(battlefieldStatus.Write());
356 battlefieldPort.AcceptedInvite = false;
357 TC_LOG_DEBUG("bg.battleground", "Player {} {} has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUID().ToString());
358 }
359 //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue
360 if (_player->GetLevel() > bg->GetMaxLevel())
361 {
362 TC_LOG_ERROR("network", "Player {} {} has level ({}) higher than maxlevel ({}) of battleground ({})! Do not port him to battleground!",
364 battlefieldPort.AcceptedInvite = false;
365 }
366 }
367
368 if (battlefieldPort.AcceptedInvite)
369 {
370 // check Freeze debuff
371 if (_player->HasAura(9454))
372 return;
373
374 if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
375 return; // cheating?
376
377 if (!_player->InBattleground())
379
380 // resurrect the player
381 if (!_player->IsAlive())
382 {
385 }
386 // stop taxi flight at port
388
390 BattlegroundMgr::BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, battlefieldPort.Ticket.Id, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), bgQueueTypeId);
391 SendPacket(battlefieldStatus.Write());
392
393 // remove battleground queue status from BGmgr
394 bgQueue.RemovePlayer(_player->GetGUID(), false);
395 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
396 // also this is required to prevent stuck at old battleground after SetBattlegroundId set to new
397 if (Battleground* currentBg = _player->GetBattleground())
398 currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
399
400 // set the destination instance id
401 _player->SetBattlegroundId(bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId);
402 // set the destination team
403 _player->SetBGTeam(ginfo.Team);
404
405 // bg->HandleBeforeTeleportToBattleground(_player);
407 // add only in HandleMoveWorldPortAck()
408 // bg->AddPlayer(_player, team);
409 TC_LOG_DEBUG("bg.battleground", "Battleground: player {} ({}) joined battle for bg {}, bgtype {}, queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }}.",
411 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize));
412 }
413 else // leave queue
414 {
415 // if player leaves rated arena match before match start, it is counted as he played but he lost
416 if (bgQueue.GetQueueId().Rated && ginfo.IsInvitedToBGInstanceGUID)
417 {
418 ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ginfo.Team);
419 if (at)
420 {
421 TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for {} by opponents rating: {}, because he has left queue!", _player->GetGUID().ToString(), ginfo.OpponentsTeamRating);
423 at->SaveToDB();
424 }
425 }
426
428 battlefieldStatus.Ticket = battlefieldPort.Ticket;
429 SendPacket(battlefieldStatus.Write());
430
431 _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
432 bgQueue.RemovePlayer(_player->GetGUID(), true);
433 // player left queue, we should update it - do not update Arena Queue
434 if (!bgQueue.GetQueueId().TeamSize)
435 sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, bgQueueTypeId, bracketEntry->GetBracketId());
436
437 TC_LOG_DEBUG("bg.battleground", "Battleground: player {} ({}) left queue for bgtype {}, queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }}.",
439 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize));
440 }
441}
442
444{
445 // not allow leave battleground in combat
446 if (_player->IsInCombat())
448 if (bg->GetStatus() != STATUS_WAIT_LEAVE)
449 return;
450
452}
453
455{
456 // we must update all queues here
457 Battleground* bg = nullptr;
458 for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
459 {
461 if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
462 continue;
464 bg = _player->GetBattleground();
465 if (bg)
466 {
468 if (bgPlayer && bgPlayer->queueTypeId == bgQueueTypeId)
469 {
470 //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
471 //so i must use bg pointer to get that information
473 BattlegroundMgr::BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, i, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), bgQueueTypeId);
474 SendPacket(battlefieldStatus.Write());
475 continue;
476 }
477 }
478
479 //we are sending update to player about queue - he can be invited there!
480 //get GroupQueueInfo for queue status
481 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
482 GroupQueueInfo ginfo;
483 if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
484 continue;
486 {
487 bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
488 if (!bg)
489 continue;
490
493 SendPacket(battlefieldStatus.Write());
494 }
495 else
496 {
497 BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(bgTypeId);
498 if (!bgTemplate)
499 continue;
500
501 // expected bracket entry
502 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgTemplate->MapIDs.front(), _player->GetLevel());
503 if (!bracketEntry)
504 continue;
505
506 uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, bracketEntry->GetBracketId());
508 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, _player, i, _player->GetBattlegroundQueueJoinTime(bgQueueTypeId), bgQueueTypeId, avgTime, ginfo.Players.size() > 1);
509 SendPacket(battlefieldStatus.Write());
510 }
511 }
512}
513
515{
516 // ignore if we already in BG or BG queue
517 if (_player->InBattleground())
518 return;
519
520 uint8 arenatype = ArenaTeam::GetTypeBySlot(packet.TeamSizeIndex);
521
522 //check existence
523 BattlegroundTemplate const* bgTemplate = sBattlegroundMgr->GetBattlegroundTemplateByTypeId(BATTLEGROUND_AA);
524 if (!bgTemplate)
525 {
526 TC_LOG_ERROR("network", "Battleground: template bg (all arenas) not found");
527 return;
528 }
529
531 {
533 return;
534 }
535
536 BattlegroundTypeId bgTypeId = bgTemplate->Id;
538 PVPDifficultyEntry const* bracketEntry = DB2Manager::GetBattlegroundBracketByLevel(bgTemplate->MapIDs.front(), _player->GetLevel());
539 if (!bracketEntry)
540 return;
541
542 Group* grp = _player->GetGroup();
543 if (!grp)
544 {
545 grp = new Group();
546 grp->Create(_player);
547 }
548
549 // no group found, error
550 if (!grp)
551 return;
552
553 if (grp->GetLeaderGUID() != _player->GetGUID())
554 return;
555
556 // get the team rating for queuing
557 uint32 arenaRating = 1; //at->GetRating();
558 uint32 matchmakerRating = 1; //at->GetAverageMMR(grp);
559
560 if (arenaRating <= 0)
561 arenaRating = 1;
562
563 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
564
565 uint32 avgTime = 0;
566 GroupQueueInfo* ginfo = nullptr;
567
568 ObjectGuid errorGuid;
570 if (!sBattlegroundMgr->isArenaTesting())
571 err = grp->CanJoinBattlegroundQueue(bgTemplate, bgQueueTypeId, arenatype, arenatype, true, packet.TeamSizeIndex, errorGuid);
572
573 if (!err)
574 {
575 TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id {}, leader {} queued with matchmaker rating {} for type {}", _player->GetArenaTeamId(packet.TeamSizeIndex), _player->GetName(), matchmakerRating, arenatype);
576
577 ginfo = bgQueue.AddGroup(_player, grp, Team(_player->GetTeam()), bracketEntry, false, arenaRating, matchmakerRating);
578 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId());
579 }
580
581 for (GroupReference const& itr : grp->GetMembers())
582 {
583 Player* member = itr.GetSource();
584 if (err)
585 {
587 BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, bgQueueTypeId, _player, 0, err, &errorGuid);
588 member->SendDirectMessage(battlefieldStatus.Write());
589 continue;
590 }
591
592 if (!_player->CanJoinToBattleground(bgTemplate))
593 {
595 BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, bgQueueTypeId, _player, 0, ERR_BATTLEGROUND_JOIN_FAILED, &errorGuid);
596 member->SendDirectMessage(battlefieldStatus.Write());
597 return;
598 }
599
600 // add to queue
601 uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
602
604 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, member, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime, true);
605 member->SendDirectMessage(battlefieldStatus.Write());
606
607 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue {{ BattlemasterListId: {}, Type: {}, Rated: {}, TeamSize: {} }}, {}, NAME {}",
608 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.Type), bgQueueTypeId.Rated ? "true" : "false", uint32(bgQueueTypeId.TeamSize),
609 member->GetGUID().ToString(), member->GetName());
610 }
611
612 sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, bgQueueTypeId, bracketEntry->GetBracketId());
613}
614
616{
617 Player* reportedPlayer = ObjectAccessor::FindPlayer(reportPvPPlayerAFK.Offender);
618 if (!reportedPlayer)
619 {
620 TC_LOG_INFO("bg.reportpvpafk", "WorldSession::HandleReportPvPAFK: {} [IP: {}] reported {}", _player->GetName(), _player->GetSession()->GetRemoteAddress(), reportPvPPlayerAFK.Offender.ToString());
621 return;
622 }
623
624 TC_LOG_DEBUG("bg.battleground", "WorldSession::HandleReportPvPAFK: {} reported {}", _player->GetName(), reportedPlayer->GetName());
625
626 reportedPlayer->ReportedAfkBy(_player);
627}
628
634
636{
638 pvpOptionsEnabled.RatedBattlegrounds = false;
639 pvpOptionsEnabled.PugBattlegrounds = true;
640 pvpOptionsEnabled.WargameBattlegrounds = false;
641 pvpOptionsEnabled.WargameArenas = false;
642 pvpOptionsEnabled.RatedArenas = true;
643 pvpOptionsEnabled.ArenaSkirmish = false;
644 pvpOptionsEnabled.SoloShuffle = false;
645 pvpOptionsEnabled.RatedSoloShuffle = false;
646 pvpOptionsEnabled.BattlegroundBlitz = false;
647 pvpOptionsEnabled.RatedBattlegroundBlitz = false;
648 SendPacket(pvpOptionsEnabled.Write());
649}
650
655
657{
658 Player* player = GetPlayer();
659 Creature* spiritHealer = ObjectAccessor::GetCreature(*player, areaSpiritHealerQuery.HealerGuid);
660 if (!spiritHealer)
661 return;
662
663 if (!spiritHealer->IsAreaSpiritHealer())
664 return;
665
667 return;
668
669 if (spiritHealer->IsAreaSpiritHealerIndividual())
670 {
671 if (Aura* aura = player->GetAura(SPELL_SPIRIT_HEAL_PLAYER_AURA))
672 {
673 player->SendAreaSpiritHealerTime(spiritHealer->GetGUID(), aura->GetDuration());
674 }
675 else if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_SPIRIT_HEAL_PLAYER_AURA, DIFFICULTY_NONE))
676 {
677 spiritHealer->CastSpell(player, SPELL_SPIRIT_HEAL_PLAYER_AURA);
678 player->SendAreaSpiritHealerTime(spiritHealer->GetGUID(), spellInfo->GetDuration());
679 spiritHealer->CastSpell(nullptr, SPELL_SPIRIT_HEAL_CHANNEL_SELF);
680 }
681 }
682 else
683 _player->SendAreaSpiritHealerTime(spiritHealer);
684}
685
687{
688 Creature* spiritHealer = ObjectAccessor::GetCreature(*GetPlayer(), areaSpiritHealerQueue.HealerGuid);
689 if (!spiritHealer)
690 return;
691
692 if (!spiritHealer->IsAreaSpiritHealer())
693 return;
694
696 return;
697
698 _player->SetAreaSpiritHealer(spiritHealer);
699}
700
702{
703 if (_player->IsInFlight())
704 return;
705
706 if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetMap(), _player->GetZoneId()))
707 {
708 bf->PlayerAskToLeave(_player);
709 return;
710 }
711
712 AreaTableEntry const* atEntry = sAreaTableStore.LookupEntry(_player->GetAreaId());
713 if (!atEntry || !(atEntry->GetFlags().HasFlag(AreaFlags::AllowHearthAndRessurectFromArea)))
714 return;
715
719}
#define sArenaTeamMgr
#define sBattlefieldMgr
#define sBattlegroundMgr
@ SPELL_SPIRIT_HEAL_PLAYER_AURA
@ SPELL_MERCENARY_CONTRACT_ALLIANCE
@ SPELL_MERCENARY_CONTRACT_HORDE
@ SPELL_SPIRIT_HEAL_CHANNEL_SELF
@ STATUS_WAIT_LEAVE
DB2Storage< BattlemasterListEntry > sBattlemasterListStore("BattlemasterList.db2", &BattlemasterListLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
@ AllowHearthAndRessurectFromArea
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
uint8_t uint8
Definition Define.h:156
uint32_t uint32
Definition Define.h:154
@ DISABLE_TYPE_BATTLEGROUND
Definition DisableMgr.h:30
@ LANG_ARENA_DISABLED
Definition Language.h:741
@ LANG_YOUR_BG_LEVEL_REQ_ERROR
Definition Language.h:708
@ LANG_BG_DISABLED
Definition Language.h:740
#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
float constexpr MAX_AREA_SPIRIT_HEALER_RANGE
Definition Player.h:1211
GroupJoinBattlegroundResult
@ ERR_BATTLEGROUND_JOIN_TIMED_OUT
@ ERR_BATTLEGROUND_JOIN_FAILED
@ ERR_LFG_CANT_USE_BATTLEGROUND
@ ERR_IN_NON_RANDOM_BG
@ ERR_BATTLEGROUND_NONE
@ ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS
@ ERR_BATTLEGROUND_TOO_MANY_QUEUES
@ ERR_IN_RANDOM_BG
constexpr BattlegroundQueueTypeId BATTLEGROUND_QUEUE_NONE
static constexpr uint8 PLAYER_MAX_BATTLEGROUND_QUEUES
@ ALLIANCE
@ HORDE
BattlegroundTypeId
@ BATTLEGROUND_AA
@ BATTLEGROUND_TYPE_NONE
@ BATTLEGROUND_RANDOM_EPIC
@ BATTLEGROUND_RB
#define sSpellMgr
Definition SpellMgr.h:812
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition Timer.h:40
@ UNIT_NPC_FLAG_BATTLEMASTER
@ UNIT_NPC_FLAG_2_NONE
void SaveToDB(bool forceMemberSave=false)
void MemberLost(Player *player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange=-12)
static uint8 GetTypeBySlot(uint8 slot)
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
static void BuildBattlegroundStatusNeedConfirmation(WorldPackets::Battleground::BattlefieldStatusNeedConfirmation *battlefieldStatus, Battleground const *bg, Player const *player, uint32 ticketId, uint32 joinTime, uint32 timeout, BattlegroundQueueTypeId queueId)
static void BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive *battlefieldStatus, Battleground const *bg, Player const *player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId)
static BattlegroundQueueTypeId BGQueueTypeId(uint16 battlemasterListId, BattlegroundQueueIdType type, bool rated, uint8 teamSize)
static void SendToBattleground(Player *player, Battleground const *battleground)
static bool IsValidQueueId(BattlegroundQueueTypeId bgQueueTypeId)
static bool IsRandomBattleground(uint32 battlemasterListId)
static void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued *battlefieldStatus, Player const *player, uint32 ticketId, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime, bool asGroup)
static void BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed *battlefieldStatus, BattlegroundQueueTypeId queueId, Player const *player, uint32 ticketId, GroupJoinBattlegroundResult result, ObjectGuid const *errorGuid=nullptr)
BattlegroundQueueTypeId GetQueueId() const
GroupQueueInfo * AddGroup(Player const *leader, Group const *group, Team team, PVPDifficultyEntry const *bracketEntry, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating)
uint32 GetAverageQueueWaitTime(GroupQueueInfo *ginfo, BattlegroundBracketId bracket_id) const
bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo *ginfo)
void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
uint32 GetMapId() const
BattlegroundTypeId GetTypeID() const
uint32 GetInstanceID() const
BattlegroundPlayer const * GetBattlegroundPlayerData(ObjectGuid const &playerGuid) const
bool isArena() const
uint32 GetMaxLevel() const
virtual void BuildPvPLogDataPacket(WorldPackets::Battleground::PVPMatchStatistics &pvpLogData) const
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:62
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:386
CreatureMovementData const & GetMovementTemplate() const
static PVPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
Definition Group.h:205
uint32 GetMembersCount() const
Definition Group.h:335
GroupRefManager & GetMembers()
Definition Group.h:332
bool Create(Player *leader)
Definition Group.cpp:141
ObjectGuid GetLeaderGUID() const
Definition Group.cpp:1648
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(BattlegroundTemplate const *bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid &errorGuid) const
Definition Group.cpp:1191
static ObjectGuid const Empty
Definition ObjectGuid.h:314
std::string ToString() const
uint32 GetEntry() const
Definition Object.h:89
bool InBattlegroundQueueForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:25768
void SetBGTeam(Team team)
Definition Player.cpp:24352
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Definition Player.cpp:1903
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId, BattlegroundQueueTypeId queueId)
Definition Player.cpp:25773
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
bool IsInvitedForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:25760
void SetBattlegroundEntryPoint()
Definition Player.cpp:24309
bool InBattleground() const
Definition Player.h:2584
void SpawnCorpseBones(bool triggerSave=true)
Definition Player.cpp:4554
void LeaveBattleground(bool teleportToEntryPoint=true)
Definition Player.cpp:24363
uint32 GetBattlegroundQueueJoinTime(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:25727
WorldLocation m_homebind
Definition Player.h:2693
bool IsDeserter() const
Definition Player.h:2592
bool InBattlegroundQueue(bool ignoreArena=false) const
Definition Player.cpp:25735
WorldSession * GetSession() const
Definition Player.h:2272
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition Player.cpp:25804
void SendAreaSpiritHealerTime(Unit *spiritHealer) const
Definition Player.cpp:31485
void SendPvpRewards() const
Send conquest currency points and their cap week/arena.
Definition Player.cpp:7124
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
bool CanJoinToBattleground(BattlegroundTemplate const *bg) const
Definition Player.cpp:24387
bool HasFreeBattlegroundQueueId() const
Definition Player.cpp:25796
void FinishTaxiFlight()
Definition Player.cpp:23356
Battleground * GetBattleground() const
Definition Player.cpp:25719
uint32 AddBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition Player.cpp:25780
uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:25752
void SetAreaSpiritHealer(Creature *creature)
Definition Player.cpp:31469
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2796
void BuildPlayerRepop()
Definition Player.cpp:4321
void ReportedAfkBy(Player *reporter)
This player has been blamed to be inactive in a battleground.
Definition Player.cpp:24408
uint32 GetArenaTeamId(uint8) const
Definition Player.h:2175
BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const
Definition Player.cpp:25744
Team GetTeam() const
Definition Player.h:2423
bool GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const
Definition Player.cpp:25858
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:4379
bool IsAreaSpiritHealer() const
Definition Unit.h:1017
bool IsAreaSpiritHealerIndividual() const
Definition Unit.h:1024
void PauseMovement(uint32 timer=0, uint8 slot=0, bool forced=true)
Definition Unit.cpp:10695
bool IsAlive() const
Definition Unit.h:1185
bool IsInFlight() const
Definition Unit.h:1027
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4700
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
uint8 GetLevel() const
Definition Unit.h:757
bool IsInCombat() const
Definition Unit.h:1058
Map * GetMap() const
Definition Object.h:411
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
std::string const & GetName() const
Definition Object.h:342
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:501
uint32 GetAreaId() const
Definition Object.h:333
uint32 GetZoneId() const
Definition Object.h:332
Underlying AsUnderlyingType() const
void HandleHearthAndResurrect(WorldPackets::Battleground::HearthAndResurrect &hearthAndResurrect)
void HandleBattlefieldLeaveOpcode(WorldPackets::Battleground::BattlefieldLeave &battlefieldLeave)
void HandleRequestBattlefieldStatusOpcode(WorldPackets::Battleground::RequestBattlefieldStatus &requestBattlefieldStatus)
void SendNotification(char const *format,...) ATTR_PRINTF(2
std::string GetPlayerInfo() const
void HandleGetPVPOptionsEnabled(WorldPackets::Battleground::GetPVPOptionsEnabled &getPvPOptionsEnabled)
Player * GetPlayer() const
void HandleRequestRatedPvpInfo(WorldPackets::Battleground::RequestRatedPvpInfo &packet)
void HandleBattleFieldPortOpcode(WorldPackets::Battleground::BattlefieldPort &battlefieldPort)
void HandleAreaSpiritHealerQueueOpcode(WorldPackets::Battleground::AreaSpiritHealerQueue &areaSpiritHealerQueue)
std::string const & GetRemoteAddress() const
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
Player * _player
void HandleBattlemasterJoinArena(WorldPackets::Battleground::BattlemasterJoinArena &packet)
void HandleBattlemasterJoinOpcode(WorldPackets::Battleground::BattlemasterJoin &battlemasterJoin)
void HandleRequestPvpReward(WorldPackets::Battleground::RequestPVPRewards &packet)
void HandleAreaSpiritHealerQueryOpcode(WorldPackets::Battleground::AreaSpiritHealerQuery &areaSpiritHealerQuery)
void HandlePVPLogDataOpcode(WorldPackets::Battleground::PVPLogDataRequest &pvpLogDataRequest)
void HandleReportPvPAFK(WorldPackets::Battleground::ReportPvPPlayerAFK &reportPvPPlayerAFK)
void HandleBattlefieldListOpcode(WorldPackets::Battleground::BattlefieldListRequest &battlefieldList)
void HandleBattlemasterHelloOpcode(WorldPackets::NPC::Hello &hello)
bool IsDisabledFor(DisableType type, uint32 entry, WorldObject const *ref, uint8 flags)
uint32 GetGameTimeMS()
Definition GameTime.cpp:57
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
EnumFlag< AreaFlags > GetFlags() const
BattlegroundQueueTypeId queueTypeId
static constexpr BattlegroundQueueTypeId FromPacked(uint64 packedQueueId)
BattlegroundTypeId Id
uint16 GetMaxPlayersPerTeam() const
std::vector< int32 > MapIDs
uint16 GetMinPlayersPerTeam() const
EnumFlag< BattlemasterListFlags > GetFlags() const
uint32 GetInteractionPauseTimer() const
uint32 IsInvitedToBGInstanceGUID
std::map< ObjectGuid, PlayerQueueInfo * > Players
uint32 OpponentsMatchmakerRating
BattlegroundBracketId GetBracketId() const
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92