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 "DatabaseEnv.h"
30#include "DBCStores.h"
31#include "DisableMgr.h"
32#include "GameTime.h"
33#include "Group.h"
34#include "Language.h"
35#include "Log.h"
36#include "NPCPackets.h"
37#include "Object.h"
38#include "ObjectAccessor.h"
39#include "Player.h"
40#include "World.h"
41
43{
45 if (!unit)
46 return;
47
48 // Stop the npc if moving
50 unit->PauseMovement(pause);
51 unit->SetHomePosition(unit->GetPosition());
52
53 BattlegroundTypeId bgTypeId = sBattlegroundMgr->GetBattleMasterBG(unit->GetEntry());
54
55 if (!_player->GetBGAccessByLevel(bgTypeId))
56 {
57 // temp, must be gossip message...
59 return;
60 }
61
62 sBattlegroundMgr->SendBattlegroundList(_player, hello.Unit, bgTypeId);
63}
64
66{
67 bool isPremade = false;
68 if (!sBattlemasterListStore.LookupEntry(battlemasterJoin.BattlemasterListID))
69 {
70 TC_LOG_ERROR("network", "Battleground: invalid bgtype ({}) received. possible cheater? {}", battlemasterJoin.BattlemasterListID, _player->GetGUID().ToString());
71 return;
72 }
73
75 {
77 return;
78 }
79
80 BattlegroundTypeId bgTypeId = BattlegroundTypeId(battlemasterJoin.BattlemasterListID);
81
82 // ignore if player is already in BG
84 return;
85
86 // get bg instance or bg template if instance not found
87 Battleground* bg = nullptr;
88 if (battlemasterJoin.InstanceID)
89 bg = sBattlegroundMgr->GetBattlegroundThroughClientInstance(battlemasterJoin.InstanceID, bgTypeId);
90
91 if (!bg)
92 bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
93 if (!bg)
94 return;
95
96 // expected bracket entry
98 if (!bracketEntry)
99 return;
100
101 // can do this, since it's battleground, not arena
102 BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, bracketEntry->GetBracketId(), 0);
103
105
106 Group const* grp = _player->GetGroup();
107
108 // check queue conditions
109 if (!battlemasterJoin.JoinAsGroup)
110 {
111 if (GetPlayer()->isUsingLfg())
112 {
115 SendPacket(battlefieldStatus.Write());
116 return;
117 }
118
119 // check RBAC permissions
121 {
124 SendPacket(battlefieldStatus.Write());
125 return;
126 }
127
128 // check Deserter debuff
129 if (_player->IsDeserter())
130 {
133 SendPacket(battlefieldStatus.Write());
134 return;
135 }
136
137 bool isInRandomBgQueue = [&]
138 {
139 for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
141 return true;
142 return false;
143 }();
144 if (!BattlegroundMgr::IsRandomBattleground(bgTypeId) && isInRandomBgQueue)
145 {
146 // player is already in random queue
149 SendPacket(battlefieldStatus.Write());
150 return;
151 }
152
153 if (_player->InBattlegroundQueue(true) && !isInRandomBgQueue && BattlegroundMgr::IsRandomBattleground(bgTypeId))
154 {
155 // player is already in queue, can't start random queue
158 SendPacket(battlefieldStatus.Write());
159 return;
160 }
161
162 // check if already in queue
164 // player is already in this queue
165 return;
166
167 // check if has free queue slots
169 {
172 SendPacket(battlefieldStatus.Write());
173 return;
174 }
175
176 // check Freeze debuff
177 if (_player->HasAura(9454))
178 return;
179
180 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
181 GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, bracketEntry, false, isPremade, 0, 0);
182 uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo);
183 uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
184
186 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, bg, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime);
187 SendPacket(battlefieldStatus.Write());
188
189 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, {}, NAME {}",
190 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize),
192 }
193 else
194 {
195 if (!grp)
196 return;
197 if (grp->GetLeaderGUID() != _player->GetGUID())
198 return;
199
200 ObjectGuid errorGuid;
201 err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0, errorGuid);
202 isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam());
203
204 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
205 GroupQueueInfo* ginfo = nullptr;
206 uint32 avgTime = 0;
207
208 if (err > 0)
209 {
210 TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:");
211 ginfo = bgQueue.AddGroup(_player, grp, bracketEntry, false, isPremade, 0, 0);
212 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo);
213 }
214
215 for (GroupReference const* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
216 {
217 Player* member = itr->GetSource();
218 if (!member)
219 continue; // this should never happen
220
221 if (err <= 0)
222 {
224 BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, err, &errorGuid);
225 member->SendDirectMessage(battlefieldStatus.Write());
226 continue;
227 }
228
229 // add to queue
230 uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
231
233 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, bg, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime);
234 member->SendDirectMessage(battlefieldStatus.Write());
235
238 member->SendDirectMessage(battlefieldStatus.Write());
239 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, {}, NAME {}",
240 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize),
241 member->GetGUID().ToString(), member->GetName());
242 }
243 TC_LOG_DEBUG("bg.battleground", "Battleground: group end");
244 }
245 sBattlegroundMgr->ScheduleQueueUpdate(0, bgQueueTypeId);
246}
247
249{
251 if (!bg) // can't be received if player not in battleground
252 return;
253
256 if (!guid.IsEmpty())
257 if (Player* allianceFlagCarrier = ObjectAccessor::GetPlayer(*_player, guid))
258 playerPositions.FlagCarriers.emplace_back(guid, allianceFlagCarrier->GetPosition());
259
260 guid = bg->GetFlagPickerGUID(TEAM_HORDE);
261 if (!guid.IsEmpty())
262 if (Player* hordeFlagCarrier = ObjectAccessor::GetPlayer(*_player, guid))
263 playerPositions.FlagCarriers.emplace_back(guid, hordeFlagCarrier->GetPosition());
264
265 SendPacket(playerPositions.Write());
266}
267
269{
271 if (!bg)
272 return;
273
274 // Prevent players from sending BuildPvpLogDataPacket in an arena except for when sent in BattleGround::EndBattleGround.
275 if (bg->isArena())
276 return;
277
279 bg->BuildPvPLogDataPacket(pvpMatchStatistics);
280 SendPacket(pvpMatchStatistics.Write());
281}
282
284{
285 BattlemasterListEntry const* battlemasterListEntry = sBattlemasterListStore.LookupEntry(battlefieldList.ListID);
286 if (!battlemasterListEntry)
287 {
288 TC_LOG_DEBUG("bg.battleground", "BattlegroundHandler: invalid bgtype ({}) with player (Name: {}, {}) received.", battlefieldList.ListID, _player->GetName(), _player->GetGUID().ToString());
289 return;
290 }
291
292 sBattlegroundMgr->SendBattlegroundList(_player, ObjectGuid::Empty, BattlegroundTypeId(battlefieldList.ListID));
293}
294
296{
298 uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId);
299 if (queueSlot >= PLAYER_MAX_BATTLEGROUND_QUEUES)
300 {
301 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, AcceptedInvite: {}. Invalid queueSlot.",
302 GetPlayerInfo(), bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize), battlefieldPort.AcceptedInvite);
303 return;
304 }
305
306 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
307
308 //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue::RemovePlayer() function
309 GroupQueueInfo ginfo;
310 if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
311 {
312 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, AcceptedInvite: {}. Player not in queue (No player Group Info)!",
313 GetPlayerInfo(), bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize), battlefieldPort.AcceptedInvite);
314 return;
315 }
316 // if action == 1, then player must have been invited to join
317 if (!ginfo.IsInvitedToBGInstanceGUID && battlefieldPort.AcceptedInvite)
318 {
319 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, AcceptedInvite: {}. Player is not invited to any bg!",
320 GetPlayerInfo(), bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize), battlefieldPort.AcceptedInvite);
321 return;
322 }
323
325 Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
326 if (!bg)
327 {
328 if (battlefieldPort.AcceptedInvite)
329 {
330 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, AcceptedInvite: {}. Cant find BG with id {}!",
331 GetPlayerInfo(), bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize), battlefieldPort.AcceptedInvite, ginfo.IsInvitedToBGInstanceGUID);
332 return;
333 }
334
335 bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
336 if (!bg)
337 {
338 TC_LOG_ERROR("network", "BattlegroundHandler: BattlegroundTemplate not found for type id {}.", bgTypeId);
339 return;
340 }
341 }
342
343 TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT {} queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, AcceptedInvite: {}.",
344 GetPlayerInfo(), bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize), battlefieldPort.AcceptedInvite);
345
346 // expected bracket entry
348 if (!bracketEntry)
349 return;
350
351 //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it
352 if (battlefieldPort.AcceptedInvite && bgQueue.GetQueueId().TeamSize == 0)
353 {
354 //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue
355 if (_player->IsDeserter())
356 {
357 //send bg command result to show nice message
360 SendPacket(battlefieldStatus.Write());
361 battlefieldPort.AcceptedInvite = false;
362 TC_LOG_DEBUG("bg.battleground", "Player {} {} has a deserter debuff, do not port him to battleground!", _player->GetName(), _player->GetGUID().ToString());
363 }
364 //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
365 if (_player->GetLevel() > bg->GetMaxLevel())
366 {
367 TC_LOG_ERROR("network", "Player {} {} has level ({}) higher than maxlevel ({}) of battleground ({})! Do not port him to battleground!",
369 battlefieldPort.AcceptedInvite = false;
370 }
371 }
372
373 if (battlefieldPort.AcceptedInvite)
374 {
375 // check Freeze debuff
376 if (_player->HasAura(9454))
377 return;
378
379 if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
380 return; // cheating?
381
382 if (!_player->InBattleground())
384
385 // resurrect the player
386 if (!_player->IsAlive())
387 {
390 }
391 // stop taxi flight at port
393
395 BattlegroundMgr::BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, queueSlot, bgQueueTypeId);
396 SendPacket(battlefieldStatus.Write());
397
398 // remove battleground queue status from BGmgr
399 bgQueue.RemovePlayer(_player->GetGUID(), false);
400 // this is still needed here if battleground "jumping" shouldn't add deserter debuff
401 // also this is required to prevent stuck at old battleground after SetBattlegroundId set to new
402 if (Battleground* currentBg = _player->GetBattleground())
403 currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
404
405 // set the destination instance id
406 _player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId);
407 // set the destination team
408 _player->SetBGTeam(ginfo.Team);
409
410 // bg->HandleBeforeTeleportToBattleground(_player);
411 sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
412 // add only in HandleMoveWorldPortAck()
413 // bg->AddPlayer(_player, team);
414 TC_LOG_DEBUG("bg.battleground", "Battleground: player {} ({}) joined battle for bg {}, bgtype {}, queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}.",
416 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize));
417 }
418 else // leave queue
419 {
420 if (bg->isArena() && bg->GetStatus() > STATUS_WAIT_QUEUE)
421 return;
422
423 // if player leaves rated arena match before match start, it is counted as he played but he lost
424 if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID)
425 {
426 ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ginfo.Team);
427 if (at)
428 {
429 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);
431 at->SaveToDB();
432 }
433 }
434
436 BattlegroundMgr::BuildBattlegroundStatusNone(&battlefieldStatus, queueSlot);
437 SendPacket(battlefieldStatus.Write());
438
439 _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
440 bgQueue.RemovePlayer(_player->GetGUID(), true);
441 // player left queue, we should update it - do not update Arena Queue
442 if (!bgQueue.GetQueueId().TeamSize)
443 sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, bgQueueTypeId);
444
445 TC_LOG_DEBUG("bg.battleground", "Battleground: player {} ({}) left queue for bgtype {}, queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}.",
447 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize));
448
449 // track if player refuses to join the BG after being invited
450 if (bg->isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) &&
452 {
454 stmt->setUInt32(0, _player->GetGUID().GetCounter());
456 CharacterDatabase.Execute(stmt);
457 }
458 }
459}
460
462{
463 // not allow leave battleground in combat
464 if (_player->IsInCombat())
466 if (bg->GetStatus() != STATUS_WAIT_LEAVE)
467 return;
468
470}
471
473{
474 // we must update all queues here
475 Battleground* bg = nullptr;
476 for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
477 {
479 if (bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
480 continue;
482 bg = _player->GetBattleground();
483 if (bg)
484 {
486 if (bgPlayer)
487 {
488 //i cannot check any variable from player class because player class doesn't know if player is in 2v2 / 3v3 or 5v5 arena
489 //so i must use bg pointer to get that information
491 BattlegroundMgr::BuildBattlegroundStatusActive(&battlefieldStatus, bg, _player, i, bgQueueTypeId);
492 SendPacket(battlefieldStatus.Write());
493 continue;
494 }
495 }
496
497 //we are sending update to player about queue - he can be invited there!
498 //get GroupQueueInfo for queue status
499 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
500 GroupQueueInfo ginfo;
501 if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo))
502 continue;
504 {
505 bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId);
506 if (!bg)
507 continue;
508
511 SendPacket(battlefieldStatus.Write());
512 }
513 else
514 {
515 bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId);
516 if (!bg)
517 continue;
518
519 // expected bracket entry
521 if (!bracketEntry)
522 continue;
523
524 uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo);
526 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, bg, i, 0, bgQueueTypeId, avgTime);
527 SendPacket(battlefieldStatus.Write());
528 }
529 }
530}
531
533{
534 // ignore if rated but queued solo
535 if (packet.IsRated && !packet.JoinAsGroup)
536 return;
537
538 // ignore if we already in BG or BG queue
539 if (_player->InBattleground())
540 return;
541
543 if (!unit)
544 return;
545
546 uint8 arenatype = ArenaTeam::GetTypeBySlot(packet.TeamSizeIndex);
547 uint32 arenaRating = 0;
548 uint32 matchmakerRating = 0;
549 uint32 previousOpponents = 0;
550
551 //check existence
552 Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA);
553 if (!bg)
554 {
555 TC_LOG_ERROR("network", "Battleground: template bg (all arenas) not found");
556 return;
557 }
558
560 {
562 return;
563 }
564
565 BattlegroundTypeId bgTypeId = bg->GetTypeID();
567 if (!bracketEntry)
568 return;
569
570 BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, bracketEntry->GetBracketId(), arenatype);
571 Group* grp = _player->GetGroup();
572 if (!packet.JoinAsGroup)
573 {
574 if (_player->isUsingLfg())
575 {
576 // player is using dungeon finder or raid finder
579 SendPacket(battlefieldStatus.Write());
580 return;
581 }
582
584 {
587 SendPacket(battlefieldStatus.Write());
588 return;
589 }
590
591 // check if already in queue
593 //player is already in this queue
594 return;
595 // check if has free queue slots
597 return;
598 }
599 else
600 {
601 // no group found, error
602 if (!grp)
603 return;
604 if (grp->GetLeaderGUID() != _player->GetGUID())
605 return;
606 }
607
608 uint32 ateamId = 0;
609
610 if (packet.IsRated)
611 {
612 ateamId = _player->GetArenaTeamId(packet.TeamSizeIndex);
613 // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
614 ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ateamId);
615 if (!at)
616 {
617 SendNotInArenaTeamPacket(arenatype);
618 return;
619 }
620
621 // get the team rating for queueing
622 arenaRating = at->GetRating();
623 matchmakerRating = at->GetAverageMMR(grp);
624 // the arenateam id must match for everyone in the group
625
626 if (arenaRating <= 0)
627 arenaRating = 1;
628
629 previousOpponents = at->GetPreviousOpponents();
630 }
631
632 BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
633 if (packet.JoinAsGroup)
634 {
635 uint32 avgTime = 0;
636 GroupQueueInfo* ginfo = nullptr;
637
638 ObjectGuid errorGuid;
639 GroupJoinBattlegroundResult err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, true, packet.TeamSizeIndex, errorGuid);
640 if (err > 0)
641 {
642 if (packet.IsRated)
643 {
644 TC_LOG_DEBUG("bg.battleground", "Battleground: arena team id {}, leader {} queued with matchmaker rating {} for type {}", _player->GetArenaTeamId(packet.TeamSizeIndex), _player->GetName(), matchmakerRating, arenatype);
645 bg->SetRated(true);
646 }
647 else
648 bg->SetRated(false);
649
650 ginfo = bgQueue.AddGroup(_player, grp, bracketEntry, packet.IsRated, false, arenaRating, matchmakerRating, ateamId, previousOpponents);
651 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo);
652 }
653
654 for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next())
655 {
656 Player* member = itr->GetSource();
657 if (!member)
658 continue;
659
660 if (err <= 0)
661 {
663 BattlegroundMgr::BuildBattlegroundStatusFailed(&battlefieldStatus, err, &errorGuid);
664 member->SendDirectMessage(battlefieldStatus.Write());
665 continue;
666 }
667
669 {
672 member->SendDirectMessage(battlefieldStatus.Write());
673 return;
674 }
675
676 // add to queue
677 uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId);
678
680 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, bg, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime);
681 member->SendDirectMessage(battlefieldStatus.Write());
682
685 member->SendDirectMessage(groupJoinedBattleground.Write());
686 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena as group bg queue {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}, {}, NAME {}",
687 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize),
688 member->GetGUID().ToString(), member->GetName());
689 }
690 }
691 else
692 {
693 GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, nullptr, bracketEntry, packet.IsRated, false, arenaRating, matchmakerRating, ateamId, previousOpponents);
694 uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo);
695 uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId);
696
698 BattlegroundMgr::BuildBattlegroundStatusQueued(&battlefieldStatus, bg, queueSlot, ginfo->JoinTime, bgQueueTypeId, avgTime);
699 SendPacket(battlefieldStatus.Write());
700
701 TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for arena, skirmish, bg queue type {{ BattlemasterListId: {}, BracketId: {}, TeamSize: {} }}: {}, NAME {}",
702 bgQueueTypeId.BattlemasterListId, uint32(bgQueueTypeId.BracketId), uint32(bgQueueTypeId.TeamSize),
704 }
705
706 sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, bgQueueTypeId);
707}
708
710{
711 Player* reportedPlayer = ObjectAccessor::FindPlayer(reportPvPPlayerAFK.Offender);
712 if (!reportedPlayer)
713 {
714 TC_LOG_INFO("bg.reportpvpafk", "WorldSession::HandleReportPvPAFK: {} [IP: {}] reported {}", _player->GetName(), _player->GetSession()->GetRemoteAddress(), reportPvPPlayerAFK.Offender.ToString());
715 return;
716 }
717
718 TC_LOG_DEBUG("bg.battleground", "WorldSession::HandleReportPvPAFK: {} reported {}", _player->GetName(), reportedPlayer->GetName());
719
720 reportedPlayer->ReportedAfkBy(_player);
721}
722
724{
725 Player* player = GetPlayer();
726 Creature* spiritHealer = ObjectAccessor::GetCreature(*player, areaSpiritHealerQuery.HealerGuid);
727 if (!spiritHealer)
728 return;
729
730 if (!spiritHealer->IsSpiritService())
731 return;
732
734 sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, areaSpiritHealerQuery.HealerGuid);
735
736 if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetZoneId()))
737 bf->SendAreaSpiritHealerQueryOpcode(_player, areaSpiritHealerQuery.HealerGuid);
738}
739
741{
742 Creature* spiritHealer = ObjectAccessor::GetCreature(*GetPlayer(), areaSpiritHealerQueue.HealerGuid);
743 if (!spiritHealer)
744 return;
745
746 if (!spiritHealer->IsSpiritService())
747 return;
748
750 bg->AddPlayerToResurrectQueue(areaSpiritHealerQueue.HealerGuid, _player->GetGUID());
751
752 if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetZoneId()))
753 bf->AddPlayerToResurrectQueue(areaSpiritHealerQueue.HealerGuid, _player->GetGUID());
754}
755
757{
758 if (_player->IsInFlight())
759 return;
760
761 if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(_player->GetZoneId()))
762 {
763 bf->PlayerAskToLeave(_player);
764 return;
765 }
766
767 AreaTableEntry const* atEntry = sAreaTableStore.LookupEntry(_player->GetAreaId());
768 if (!atEntry || !(atEntry->Flags & AREA_FLAG_WINTERGRASP_2))
769 return;
770
774}
#define sArenaTeamMgr
#define sBattlefieldMgr
#define sBattlegroundMgr
@ BG_DESERTION_TYPE_LEAVE_QUEUE
@ STATUS_WAIT_QUEUE
@ STATUS_WAIT_LEAVE
@ STATUS_WAIT_JOIN
@ STATUS_IN_PROGRESS
@ CHAR_INS_DESERTER_TRACK
@ AREA_FLAG_WINTERGRASP_2
Definition DBCEnums.h:274
DBCStorage< BattlemasterListEntry > sBattlemasterListStore(BattlemasterListEntryfmt)
PvPDifficultyEntry const * GetBattlegroundBracketByLevel(uint32 mapid, uint32 level)
DBCStorage< AreaTableEntry > sAreaTableStore(AreaTableEntryfmt)
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ 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__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
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
@ TEAM_ALLIANCE
@ TEAM_HORDE
BattlegroundTypeId
@ BATTLEGROUND_AA
@ BATTLEGROUND_RB
#define PLAYER_MAX_BATTLEGROUND_QUEUES
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition Timer.h:40
@ UNIT_NPC_FLAG_BATTLEMASTER
void SaveToDB(bool forceMemberSave=false)
uint32 GetPreviousOpponents()
Definition ArenaTeam.h:188
uint32 GetRating() const
Definition ArenaTeam.h:137
void MemberLost(Player *player, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange=-12)
uint32 GetAverageMMR(Group *group) const
static uint8 GetTypeBySlot(uint8 slot)
static void BuildGroupJoinedBattlegroundPacket(WorldPackets::Battleground::GroupJoinedBattleground *groupJoinedBattleground, BattlegroundTypeId bgTypeId)
static void BuildBattlegroundStatusNeedConfirmation(WorldPackets::Battleground::BattlefieldStatusNeedConfirmation *battlefieldStatus, Battleground const *bg, uint32 queueSlot, uint32 timeout, BattlegroundQueueTypeId queueId)
static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 bracketId, uint8 arenaType)
static void BuildBattlegroundStatusQueued(WorldPackets::Battleground::BattlefieldStatusQueued *battlefieldStatus, Battleground const *bg, uint32 queueSlot, uint32 joinTime, BattlegroundQueueTypeId queueId, uint32 avgWaitTime)
static bool IsRandomBattleground(uint32 battlemasterListId)
static void BuildBattlegroundStatusFailed(WorldPackets::Battleground::BattlefieldStatusFailed *battlefieldStatus, GroupJoinBattlegroundResult result, ObjectGuid const *errorGuid=nullptr)
static void BuildBattlegroundStatusNone(WorldPackets::Battleground::BattlefieldStatusNone *battlefieldStatus, uint32 queueSlot)
static void BuildBattlegroundStatusActive(WorldPackets::Battleground::BattlefieldStatusActive *battlefieldStatus, Battleground const *bg, Player const *player, uint32 queueSlot, BattlegroundQueueTypeId queueId)
BattlegroundQueueTypeId GetQueueId() const
uint32 GetAverageQueueWaitTime(GroupQueueInfo *ginfo) const
bool GetPlayerGroupInfoData(ObjectGuid guid, GroupQueueInfo *ginfo)
void RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
GroupQueueInfo * AddGroup(Player *leader, Group const *group, PvPDifficultyEntry const *bracketEntry, bool isRated, bool isPremade, uint32 ArenaRating, uint32 MatchmakerRating, uint32 ArenaTeamId=0, uint32 OpponentsArenaTeamId=0)
virtual ObjectGuid GetFlagPickerGUID(int32=-1) const
uint32 GetMapId() const
BattlegroundTypeId GetTypeID(bool GetRandom=false) const
void BuildPvPLogDataPacket(WorldPackets::Battleground::PVPMatchStatistics &pvpLogData)
uint32 GetMinPlayersPerTeam() const
uint32 GetMaxPlayersPerTeam() const
void SetRated(bool state)
uint32 GetInstanceID() const
BattlegroundPlayer const * GetBattlegroundPlayerData(ObjectGuid const &playerGuid) const
bool isArena() const
bool isBattleground() const
BattlegroundStatus GetStatus() const
uint32 GetMaxLevel() const
void PSendSysMessage(char const *fmt, Args &&... args)
Definition Chat.h:69
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:293
CreatureMovementData const & GetMovementTemplate() const
Definition Group.h:165
uint32 GetMembersCount() const
Definition Group.h:249
GroupReference * GetFirstMember()
Definition Group.h:247
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(Battleground const *bgOrTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot, ObjectGuid &errorGuid) const
Definition Group.cpp:2008
ObjectGuid GetLeaderGUID() const
Definition Group.cpp:2468
LowType GetCounter() const
Definition ObjectGuid.h:156
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
std::string ToString() const
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SetBGTeam(uint32 team)
Definition Player.cpp:21944
float m_homebindZ
Definition Player.h:2089
void LeaveBattleground(bool teleportToEntryPoint=true, bool withoutDeserterDebuff=false)
Definition Player.cpp:21955
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
uint32 m_homebindMapId
Definition Player.h:2085
bool IsInvitedForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:23079
void SetBattlegroundEntryPoint()
Definition Player.cpp:21901
bool InBattleground() const
Definition Player.h:1982
void SpawnCorpseBones(bool triggerSave=true)
Definition Player.cpp:4536
bool IsDeserter() const
Definition Player.h:1989
bool InBattlegroundQueue(bool ignoreArena=false) const
Definition Player.cpp:23057
WorldSession * GetSession() const
Definition Player.h:1719
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition Player.cpp:23120
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags) const
Definition Player.cpp:2094
uint32 GetArenaTeamId(uint8 slot) const
Definition Player.h:1629
bool HasFreeBattlegroundQueueId() const
Definition Player.cpp:23112
void FinishTaxiFlight()
Definition Player.cpp:21202
Battleground * GetBattleground() const
Definition Player.cpp:23049
float m_homebindY
Definition Player.h:2088
Group * GetGroup()
Definition Player.h:2171
uint32 AddBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition Player.cpp:23098
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
bool CanJoinToBattleground(Battleground const *bg) const
Definition Player.cpp:21993
uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:23071
void BuildPlayerRepop()
Definition Player.cpp:4292
void ReportedAfkBy(Player *reporter)
This player has been blamed to be inactive in a battleground.
Definition Player.cpp:22014
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId)
Definition Player.cpp:23092
BattlegroundQueueTypeId GetBattlegroundQueueTypeId(uint32 index) const
Definition Player.cpp:23066
bool GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const
Definition Player.cpp:23157
float m_homebindX
Definition Player.h:2087
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:4346
bool isUsingLfg() const
Definition Player.cpp:23974
void setUInt32(uint8 index, uint32 value)
void setUInt8(uint8 index, uint8 value)
void PauseMovement(uint32 timer=0, uint8 slot=0, bool forced=true)
Definition Unit.cpp:10327
bool IsAlive() const
Definition Unit.h:1234
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
bool IsInFlight() const
Definition Unit.h:1119
bool IsSpiritService() const
Definition Unit.h:1116
uint8 GetLevel() const
Definition Unit.h:889
bool IsInCombat() const
Definition Unit.h:1144
std::string const & GetName() const
Definition Object.h:382
uint32 GetAreaId() const
Definition Object.h:374
uint32 GetZoneId() const
Definition Object.h:373
std::vector< BattlegroundPlayerPosition > FlagCarriers
void HandleHearthAndResurrect(WorldPackets::Battleground::HearthAndResurrect &hearthAndResurrect)
void HandleBattlefieldLeaveOpcode(WorldPackets::Battleground::BattlefieldLeave &battlefieldLeave)
void HandleRequestBattlefieldStatusOpcode(WorldPackets::Battleground::RequestBattlefieldStatus &requestBattlefieldStatus)
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
void SendNotification(const char *format,...) ATTR_PRINTF(2
void SendNotInArenaTeamPacket(uint8 type)
std::string GetPlayerInfo() const
Player * GetPlayer() const
void HandleBattleFieldPortOpcode(WorldPackets::Battleground::BattlefieldPort &battlefieldPort)
void HandleAreaSpiritHealerQueueOpcode(WorldPackets::Battleground::AreaSpiritHealerQueue &areaSpiritHealerQueue)
std::string const & GetRemoteAddress() const
Player * _player
void HandleBattlemasterJoinArena(WorldPackets::Battleground::BattlemasterJoinArena &packet)
void HandleBattlemasterJoinOpcode(WorldPackets::Battleground::BattlemasterJoin &battlemasterJoin)
void HandleBattlegroundPlayerPositionsOpcode(WorldPackets::Battleground::BattlegroundPlayerPositionsRequest &battlegroundPlayerPositionsRequest)
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)
#define sWorld
Definition World.h:900
@ CONFIG_BATTLEGROUND_TRACK_DESERTERS
Definition World.h:128
bool IsDisabledFor(DisableType type, uint32 entry, WorldObject const *ref, uint8 flags)
uint32 GetGameTimeMS()
Definition GameTime.cpp:47
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
static constexpr BattlegroundQueueTypeId FromPacked(uint64 packedQueueId)
uint32 GetInteractionPauseTimer() const
uint32 IsInvitedToBGInstanceGUID
uint32 OpponentsMatchmakerRating
float GetOrientation() const
Definition Position.h:82
void GetPosition(float &x, float &y) const
Definition Position.h:84
BattlegroundBracketId GetBracketId() const