TrinityCore
Battleground.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 "Battleground.h"
19#include "BattlegroundMgr.h"
20#include "BattlegroundPackets.h"
21#include "BattlegroundScore.h"
22#include "BattlegroundScript.h"
23#include "ChatTextBuilder.h"
24#include "Creature.h"
25#include "CreatureTextMgr.h"
26#include "DatabaseEnv.h"
27#include "DB2Stores.h"
28#include "Formulas.h"
29#include "GameEventSender.h"
30#include "GameTime.h"
31#include "GridNotifiersImpl.h"
32#include "Group.h"
33#include "Guild.h"
34#include "GuildMgr.h"
35#include "KillRewarder.h"
36#include "Language.h"
37#include "Log.h"
38#include "Map.h"
39#include "MapUtils.h"
40#include "MiscPackets.h"
41#include "ObjectAccessor.h"
42#include "ObjectMgr.h"
43#include "Player.h"
44#include "ReputationMgr.h"
45#include "SpellAuras.h"
46#include "TemporarySummon.h"
47#include "Transport.h"
48#include "Util.h"
49#include "WorldStateMgr.h"
50#include <cstdarg>
51
52template<class Do>
54{
55 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
56 if (Player* player = _GetPlayer(itr, "BroadcastWorker"))
57 _do(player);
58}
59
60Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _battlegroundTemplate(battlegroundTemplate), _pvpDifficultyEntry(nullptr), _pvpStatIds(nullptr), _preparationStartTime(0)
61{
62 ASSERT(_battlegroundTemplate, "Nonexisting Battleground Template passed to battleground ctor!");
63
64 m_InstanceID = 0;
67 m_EndTime = 0;
70 m_ArenaType = 0;
72 m_StartTime = 0;
75 m_Events = 0;
77 m_IsRated = false;
78 m_InBGFreeSlotQueue = false;
79 m_SetDeleteThis = false;
80
81 m_Map = nullptr;
82
85
88
89 m_BgRaids[TEAM_ALLIANCE] = nullptr;
90 m_BgRaids[TEAM_HORDE] = nullptr;
91
94
97
100
102
107
112}
113
115
117{
118 // unload map
119 if (m_Map)
120 {
121 m_Map->UnloadAll(); // unload all objects (they may hold a reference to bg in their ZoneScript pointer)
122 m_Map->SetUnload(); // mark for deletion by MapManager
123
124 //unlink to prevent crash, always unlink all pointer reference before destruction
125 m_Map->SetBG(nullptr);
126 m_Map = nullptr;
127 }
128 // remove from bg free slot queue
130
131 for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr)
132 delete itr->second;
133
134 _playerPositions.clear();
135}
136
138{
139 if (!PreUpdateImpl(diff))
140 return;
141
142 if (!GetPlayersSize())
143 {
144 //BG is empty
145 // if there are no players invited, delete BG
146 // this will delete arena or bg object, where any player entered
147 // [[ but if you use battleground object again (more battles possible to be played on 1 instance)
148 // then this condition should be removed and code:
149 // if (!GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
150 // AddToFreeBGObjectsQueue(); // not yet implemented
151 // should be used instead of current
152 // ]]
153 // Battleground Template instance cannot be updated, because it would be deleted
155 m_SetDeleteThis = true;
156 return;
157 }
158
159 switch (GetStatus())
160 {
161 case STATUS_WAIT_JOIN:
162 if (GetPlayersSize())
163 {
164 _ProcessJoin(diff);
166 }
167 break;
171 // after 47 minutes without one team losing, the arena closes with no winner and no rating change
172 if (isArena())
173 {
175 {
177 return;
178 }
179 }
180 else
181 {
183 _ProcessProgress(diff);
184 else if (m_PrematureCountDown)
185 m_PrematureCountDown = false;
186 }
187 break;
189 _ProcessLeave(diff);
190 break;
191 default:
192 break;
193 }
194
195 // Update start time and reset stats timer
198 m_ResetStatTimer += diff;
199
200 PostUpdateImpl(diff);
201}
202
204{
205 float maxDist = GetStartMaxDist();
206 if (!maxDist)
207 return;
208
211 {
213
214 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
215 {
216 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
217 {
218 if (player->IsGameMaster())
219 continue;
220
221 Position pos = player->GetPosition();
222 WorldSafeLocsEntry const* startPos = GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(player->GetBGTeam()));
223 if (pos.GetExactDistSq(startPos->Loc) > maxDist)
224 {
225 TC_LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending {} back to start location (map: {}) (possible exploit)", player->GetName(), GetMapId());
226 player->TeleportTo(startPos->Loc);
227 }
228 }
229 }
230 }
231}
232
234{
237 {
239
241
243 {
244 // Update position data if we found player.
245 if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), playerPosition.Guid))
246 playerPosition.Pos = player->GetPosition();
247
248 playerPositions.FlagCarriers.push_back(playerPosition);
249 }
250
251 SendPacketToAll(playerPositions.Write());
252 }
253}
254
256{
257 // remove offline players from bg after 5 minutes
258 if (!m_OfflineQueue.empty())
259 {
260 BattlegroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin()));
261 if (itr != m_Players.end())
262 {
263 if (itr->second.OfflineRemoveTime <= GameTime::GetGameTime())
264 {
265 RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
266 m_OfflineQueue.pop_front(); // remove from offline queue
267 //do not use itr for anything, because it is erased in RemovePlayerAtLeave()
268 }
269 }
270 }
271}
272
274{
275 Team winner = TEAM_OTHER;
277 winner = ALLIANCE;
279 winner = HORDE;
280
281 return winner;
282}
283
285{
286 // *********************************************************
287 // *** BATTLEGROUND BALLANCE SYSTEM ***
288 // *********************************************************
289 // if less then minimum players are in on one side, then start premature finish timer
291 {
293 m_PrematureCountDownTimer = sBattlegroundMgr->GetPrematureFinishTime();
294 }
295 else if (m_PrematureCountDownTimer < diff)
296 {
297 // time's up!
299 m_PrematureCountDown = false;
300 }
301 else if (!sBattlegroundMgr->isTesting())
302 {
303 uint32 newtime = m_PrematureCountDownTimer - diff;
304 // announce every minute
305 if (newtime > (MINUTE * IN_MILLISECONDS))
306 {
309 }
310 else
311 {
312 //announce every 15 seconds
313 if (newtime / (15 * IN_MILLISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILLISECONDS))
315 }
317 }
318}
319
321{
322 // *********************************************************
323 // *** BATTLEGROUND STARTING SYSTEM ***
324 // *********************************************************
326
327 if (!isArena())
328 SetRemainingTime(300000);
329
330 if (m_ResetStatTimer > 5000)
331 {
333 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
334 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
335 player->ResetAllPowers();
336 }
337
339 {
341
342 if (!FindBgMap())
343 {
344 TC_LOG_ERROR("bg.battleground", "Battleground::_ProcessJoin: map (map id: {}, instance id: {}) is not created!", GetMapId(), m_InstanceID);
345 EndNow();
346 return;
347 }
348
350 for (Group* group : m_BgRaids)
351 if (group)
353
356 // First start warning - 2 or 1 minute
359 }
360 // After 1 minute or 30 seconds, warning is signaled
362 {
367 }
368 // After 30 or 15 seconds, warning is signaled
370 {
375 }
376 // Delay expired (after 2 or 1 minute)
377 else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
378 {
380
382
387
389
390 for (auto const& [guid, _] : GetPlayers())
391 {
392 if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), guid))
393 {
394 player->StartCriteria(CriteriaStartEvent::StartBattleground, GetBgMap()->GetId());
395 player->AtStartOfEncounter(EncounterType::Battleground);
396 }
397 }
398
399 // Remove preparation
400 if (isArena())
401 {
403 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
404 {
405 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
406 {
407 // Correctly display EnemyUnitFrame
408 player->SetArenaFaction(player->GetBGTeam());
409
410 player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
411 player->ResetAllPowers();
412 if (!player->IsGameMaster())
413 {
414 // remove auras with duration lower than 30s
415 player->RemoveAppliedAuras([](AuraApplication const* aurApp)
416 {
417 Aura* aura = aurApp->GetBase();
418 return !aura->IsPermanent()
419 && aura->GetDuration() <= 30 * IN_MILLISECONDS
420 && aurApp->IsPositive()
423 });
424 }
425 }
426 }
427
429 }
430 else
431 {
433
434 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
435 {
436 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
437 {
438 player->RemoveAurasDueToSpell(SPELL_PREPARATION);
439 player->ResetAllPowers();
440 }
441 }
442 // Announce BG starting
445 }
446 }
447
448 if (GetRemainingTime() > 0 && (m_EndTime -= diff) > 0)
450}
451
453{
454 // *********************************************************
455 // *** BATTLEGROUND ENDING SYSTEM ***
456 // *********************************************************
457 // remove all players from battleground after 2 minutes
459 if (GetRemainingTime() <= 0)
460 {
462 BattlegroundPlayerMap::iterator itr, next;
463 for (itr = m_Players.begin(); itr != m_Players.end(); itr = next)
464 {
465 next = itr;
466 ++next;
467 //itr is erased here!
468 RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
469 // do not change any battleground's private variables
470 }
471 }
472}
473
474Player* Battleground::_GetPlayer(ObjectGuid guid, bool offlineRemove, char const* context) const
475{
476 Player* player = nullptr;
477 if (!offlineRemove)
478 {
479 // should this be ObjectAccessor::FindConnectedPlayer() to return players teleporting ?
480 player = ObjectAccessor::FindPlayer(guid);
481 if (!player)
482 TC_LOG_ERROR("bg.battleground", "Battleground::{}: player ({}) not found for BG (map: {}, instance id: {})!",
483 context, guid.ToString(), GetMapId(), m_InstanceID);
484 }
485 return player;
486}
487
488Player* Battleground::_GetPlayerForTeam(Team team, BattlegroundPlayerMap::const_iterator itr, char const* context) const
489{
490 Player* player = _GetPlayer(itr, context);
491 if (player)
492 {
493 Team playerTeam = itr->second.Team;
494 if (!playerTeam)
495 playerTeam = player->GetEffectiveTeam();
496 if (playerTeam != team)
497 player = nullptr;
498 }
499 return player;
500}
501
503{
504 ASSERT(m_Map);
505 return m_Map;
506}
507
509{
510 ASSERT(teamId < TEAM_NEUTRAL);
511 return _battlegroundTemplate->StartLocation[teamId];
512}
513
515{
517}
518
520{
521 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
522 if (Player* player = _GetPlayer(itr, "SendPacketToAll"))
523 player->SendDirectMessage(packet);
524}
525
526void Battleground::SendPacketToTeam(Team team, WorldPacket const* packet, Player* except /*= nullptr*/) const
527{
528 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
529 {
530 if (Player* player = _GetPlayerForTeam(team, itr, "SendPacketToTeam"))
531 if (player != except)
532 player->SendDirectMessage(packet);
533 }
534}
535
536void Battleground::SendChatMessage(Creature* source, uint8 textId, WorldObject* target /*= nullptr*/)
537{
538 sCreatureTextMgr->SendChat(source, textId, target);
539}
540
542{
543 if (!sBroadcastTextStore.LookupEntry(id))
544 {
545 TC_LOG_ERROR("bg.battleground", "Battleground::SendBroadcastText: `broadcast_text` (ID: {}) was not found", id);
546 return;
547 }
548
549 Trinity::BroadcastTextBuilder builder(nullptr, msgType, id, GENDER_MALE, target);
551 BroadcastWorker(localizer);
552}
553
555{
557}
558
560{
562}
563
565{
566 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
567 if (Player* player = _GetPlayerForTeam(team, itr, "CastSpellOnTeam"))
568 player->CastSpell(player, SpellID, true);
569}
570
572{
573 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
574 if (Player* player = _GetPlayerForTeam(team, itr, "RemoveAuraOnTeam"))
575 player->RemoveAura(SpellID);
576}
577
579{
580 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
581 if (Player* player = _GetPlayerForTeam(team, itr, "RewardHonorToTeam"))
583}
584
585void Battleground::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, Team team)
586{
587 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
588 if (!factionEntry)
589 return;
590
591 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
592 {
593 Player* player = _GetPlayerForTeam(team, itr, "RewardReputationToTeam");
594 if (!player)
595 continue;
596
598 continue;
599
600 uint32 repGain = Reputation;
603 player->GetReputationMgr().ModifyReputation(factionEntry, repGain);
604 }
605}
606
607void Battleground::UpdateWorldState(int32 worldStateId, int32 value, bool hidden /*= false*/)
608{
609 sWorldStateMgr->SetValue(worldStateId, value, hidden, GetBgMap());
610}
611
613{
615
616 bool guildAwarded = false;
617
618 if (winner == ALLIANCE)
619 {
620 if (isBattleground())
622
623 PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
624
626 }
627 else if (winner == HORDE)
628 {
629 if (isBattleground())
631
632 PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
633
635 }
636 else
637 {
639 }
640
642 uint64 battlegroundId = 1;
644 {
645 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PVPSTATS_MAXID);
646 PreparedQueryResult result = CharacterDatabase.Query(stmt);
647
648 if (result)
649 {
650 Field* fields = result->Fetch();
651 battlegroundId = fields[0].GetUInt64() + 1;
652 }
653
654 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_BATTLEGROUND);
655 stmt->setUInt64(0, battlegroundId);
656 stmt->setUInt8(1, GetWinner());
657 stmt->setUInt8(2, GetUniqueBracketId());
658 stmt->setUInt32(3, GetTypeID());
659 CharacterDatabase.Execute(stmt);
660 }
661
663 //we must set it this way, because end time is sent in packet!
665
667 pvpMatchComplete.Winner = GetWinner();
668 pvpMatchComplete.Duration = std::chrono::duration_cast<Seconds>(Milliseconds(std::max<int32>(0, (GetElapsedTime() - BG_START_DELAY_2M))));
669 pvpMatchComplete.LogData.emplace();
670 BuildPvPLogDataPacket(*pvpMatchComplete.LogData);
671 pvpMatchComplete.Write();
672
673 for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
674 {
675 Team team = itr->second.Team;
676
677 Player* player = _GetPlayer(itr, "EndBattleground");
678 if (!player)
679 continue;
680
681 // should remove spirit of redemption
684
685 if (!player->IsAlive())
686 {
687 player->ResurrectPlayer(1.0f);
688 player->SpawnCorpseBones();
689 }
690 else
691 //needed cause else in av some creatures will kill the players at the end
692 player->CombatStop();
693
694 // remove temporary currency bonus auras before rewarding player
697
698 uint32 winnerKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST);
699 uint32 loserKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
700
702 {
703 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER);
704 BattlegroundScoreMap::const_iterator score = PlayerScores.find(player->GetGUID());
705
706 stmt->setUInt32(0, battlegroundId);
707 stmt->setUInt64(1, player->GetGUID().GetCounter());
708 stmt->setBool (2, team == winner);
709 stmt->setUInt32(3, score->second->GetKillingBlows());
710 stmt->setUInt32(4, score->second->GetDeaths());
711 stmt->setUInt32(5, score->second->GetHonorableKills());
712 stmt->setUInt32(6, score->second->GetBonusHonor());
713 stmt->setUInt32(7, score->second->GetDamageDone());
714 stmt->setUInt32(8, score->second->GetHealingDone());
715 stmt->setUInt32(9, score->second->GetAttr(0));
716 stmt->setUInt32(10, score->second->GetAttr(1));
717 stmt->setUInt32(11, score->second->GetAttr(2));
718 stmt->setUInt32(12, score->second->GetAttr(3));
719 stmt->setUInt32(13, score->second->GetAttr(4));
720
721 CharacterDatabase.Execute(stmt);
722 }
723
724 // Reward winner team
725 if (team == winner)
726 {
727 if (BattlegroundPlayer const* bgPlayer = GetBattlegroundPlayerData(player->GetGUID()))
728 {
729 if (BattlegroundMgr::IsRandomBattleground(bgPlayer->queueTypeId.BattlemasterListId)
730 || BattlegroundMgr::IsBGWeekend(BattlegroundTypeId(bgPlayer->queueTypeId.BattlemasterListId)))
731 {
733 if (!player->GetRandomWinner())
734 {
735 player->SetRandomWinner(true);
736 // TODO: win honor xp
737 }
738 }
739 else
740 {
741 // TODO: loss honor xp
742 }
743 }
744
746 if (!guildAwarded)
747 {
748 guildAwarded = true;
749 if (ObjectGuid::LowType guildId = GetBgMap()->GetOwnerGuildId(player->GetBGTeam()))
750 {
751 if (Guild* guild = sGuildMgr->GetGuildById(guildId))
752 guild->UpdateCriteria(CriteriaType::WinBattleground, player->GetMapId(), 0, 0, nullptr, player);
753 }
754 }
755 }
756 else
757 {
758 if (BattlegroundPlayer const* bgPlayer = GetBattlegroundPlayerData(player->GetGUID()))
759 {
760 if (BattlegroundMgr::IsRandomBattleground(bgPlayer->queueTypeId.BattlemasterListId)
761 || BattlegroundMgr::IsBGWeekend(BattlegroundTypeId(bgPlayer->queueTypeId.BattlemasterListId)))
763 }
764 }
765
766 player->ResetAllPowers();
767 player->CombatStopWithPets(true);
768
769 BlockMovement(player);
770
771 player->SendDirectMessage(pvpMatchComplete.GetRawPacket());
772
774
776 }
777}
778
780{
782}
783
785{
786 //variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
787 uint32 maxLevel = std::min<uint32>(GetMaxLevel(), 80U);
788 return Trinity::Honor::hk_honor_at_level(maxLevel, float(kills));
789}
790
792{
793 // movement disabled NOTE: the effect will be automatically removed by client when the player is teleported from the battleground, so no need to send with uint8(1) in RemovePlayerAtLeave()
794 player->SetClientControl(player, false);
795}
796
798{
799 Team team = GetPlayerTeam(guid);
800 bool participant = false;
801 // Remove from lists/maps
802 BattlegroundPlayerMap::iterator itr = m_Players.find(guid);
804 if (itr != m_Players.end())
805 {
806 bgQueueTypeId = itr->second.queueTypeId;
807 UpdatePlayersCountByTeam(team, true); // -1 player
808 m_Players.erase(itr);
809 // check if the player was a participant of the match, or only entered through gm command (goname)
810 participant = true;
811 }
812
813 BattlegroundScoreMap::iterator itr2 = PlayerScores.find(guid);
814 if (itr2 != PlayerScores.end())
815 {
816 delete itr2->second; // delete player's score
817 PlayerScores.erase(itr2);
818 }
819
820 Player* player = ObjectAccessor::FindPlayer(guid);
821
822 if (player)
823 {
824 // should remove spirit of redemption
827
835
837
839
840 if (!player->IsAlive()) // resurrect on exit
841 {
842 player->ResurrectPlayer(1.0f);
843 player->SpawnCorpseBones();
844 }
845 }
846 else
847 {
848 CharacterDatabaseTransaction trans(nullptr);
849 Player::OfflineResurrect(guid, trans);
850 }
851
852 RemovePlayer(player, guid, team); // BG subclass specific code
853
854 if (participant) // if the player was a match participant, remove auras, calc rating, update queue
855 {
856 if (player)
857 {
858 player->ClearAfkReports();
859
860 // if arena, remove the specific arena auras
861 if (isArena())
862 {
863 // unsummon current and summon old pet if there was one and there isn't a current pet
864 player->RemovePet(nullptr, PET_SAVE_NOT_IN_SLOT);
866 }
867
868 if (SendPacket && bgQueueTypeId)
869 {
871 sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, player->GetBattlegroundQueueIndex(*bgQueueTypeId), player->GetBattlegroundQueueJoinTime(*bgQueueTypeId));
872 player->SendDirectMessage(battlefieldStatus.Write());
873 }
874
875 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
876 if (bgQueueTypeId)
877 player->RemoveBattlegroundQueueId(*bgQueueTypeId);
878 }
879
880 // remove from raid group if player is member
881 if (Group* group = GetBgRaid(team))
882 {
883 if (!group->RemoveMember(guid)) // group was disbanded
884 SetBgRaid(team, nullptr);
885 }
887 //we should update battleground queue, but only if bg isn't ending
888 if (isBattleground() && GetStatus() < STATUS_WAIT_LEAVE && bgQueueTypeId)
889 {
890 // a player has left the battleground, so there are free slots -> add to queue
892 sBattlegroundMgr->ScheduleQueueUpdate(0, *bgQueueTypeId, GetBracketId());
893 }
894
895 // Let others know
897 playerLeft.Guid = guid;
898 SendPacketToTeam(team, playerLeft.Write(), player);
899 }
900
901 if (player)
902 {
903 // Do next only if found in battleground
905 // reset destination bg team
906 player->SetBGTeam(TEAM_OTHER);
907
908 // remove all criterias on bg leave
910
911 if (Transport)
912 player->TeleportToBGEntryPoint();
913
914 TC_LOG_DEBUG("bg.battleground", "Removed player {} from Battleground.", player->GetName());
915 }
916
917 //battleground object will be deleted next Battleground::Update() call
918}
919
920// this method is called when no players remains in battleground
922{
927 m_Events = 0;
928
929 if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
930 TC_LOG_ERROR("bg.battleground", "Battleground::Reset: one of the counters is not 0 (alliance: {}, horde: {}) for BG (map: {}, instance id: {})!",
932
934 m_InvitedHorde = 0;
935 m_InBGFreeSlotQueue = false;
936
937 m_Players.clear();
938
939 for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr)
940 delete itr->second;
941 PlayerScores.clear();
942
943 _playerPositions.clear();
944}
945
947{
949 // add BG to free slot queue
951
952 // add bg to update list
953 // This must be done here, because we need to have already invited some players when first BG::Update() method is executed
954 // and it doesn't matter if we call StartBattleground() more times, because m_Battlegrounds is a map and instance id never changes
955 sBattlegroundMgr->AddBattleground(this);
956
957 if (m_IsRated)
958 TC_LOG_DEBUG("bg.arena", "Arena match type: {} for Team1Id: {} - Team2Id: {} started.", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE]);
959}
960
962{
963 if (WorldSafeLocsEntry const* loc = GetExploitTeleportLocation(Team(player->GetBGTeam())))
964 player->TeleportTo(loc->Loc);
965}
966
968{
969 // remove afk from player
970 if (player->isAFK())
971 player->ToggleAFK();
972
973 // score struct must be created in inherited class
974
975 Team team = player->GetBGTeam();
976
978 bp.OfflineRemoveTime = 0;
979 bp.Team = team;
981 bp.queueTypeId = queueId;
982
983 bool const isInBattleground = IsPlayerInBattleground(player->GetGUID());
984 // Add to list/maps
985 m_Players[player->GetGUID()] = bp;
986
987 if (!isInBattleground)
988 {
989 UpdatePlayersCountByTeam(team, false); // +1 player
990 PlayerScores[player->GetGUID()] = new BattlegroundScore(player->GetGUID(), player->GetBGTeam(), _pvpStatIds);
991 }
992
994 playerJoined.Guid = player->GetGUID();
995 SendPacketToTeam(team, playerJoined.Write(), player);
996
998 pvpMatchInitialize.MapID = GetMapId();
999 switch (GetStatus())
1000 {
1001 case STATUS_NONE:
1002 case STATUS_WAIT_QUEUE:
1004 break;
1005 case STATUS_WAIT_JOIN:
1007 break;
1008 case STATUS_IN_PROGRESS:
1010 break;
1011 case STATUS_WAIT_LEAVE:
1013 break;
1014 default:
1015 break;
1016 }
1017
1019 {
1021 pvpMatchInitialize.Duration = std::chrono::duration_cast<Seconds>(duration);
1022 pvpMatchInitialize.StartTime = GameTime::GetSystemTime() - duration;
1023 }
1024
1025 pvpMatchInitialize.ArenaFaction = player->GetBGTeam() == HORDE ? PVP_TEAM_HORDE : PVP_TEAM_ALLIANCE;
1026 pvpMatchInitialize.BattlemasterListID = queueId.BattlemasterListId;
1027 pvpMatchInitialize.Registered = false;
1028 pvpMatchInitialize.AffectsRating = isRated();
1029
1030 player->SendDirectMessage(pvpMatchInitialize.Write());
1031
1033
1034 // add arena specific auras
1035 if (isArena())
1036 {
1038 player->DestroyConjuredItems(true);
1039 player->UnsummonPetTemporaryIfAny();
1040
1041 if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
1042 {
1043 player->CastSpell(player, SPELL_ARENA_PREPARATION, true);
1044 player->ResetAllPowers();
1045 }
1046 }
1047 else
1048 {
1049 if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
1050 player->CastSpell(player, SPELL_PREPARATION, true); // reduces all mana cost of spells.
1051
1052 if (bp.Mercenary)
1053 {
1054 if (bp.Team == HORDE)
1055 {
1056 player->CastSpell(player, SPELL_MERCENARY_HORDE_1);
1058 }
1059 else if (bp.Team == ALLIANCE)
1060 {
1061 player->CastSpell(player, SPELL_MERCENARY_ALLIANCE_1);
1063 }
1064 player->CastSpell(player, SPELL_MERCENARY_SHAPESHIFT);
1066 }
1067 }
1068
1069 // setup BG group membership
1071 AddOrSetPlayerToCorrectBgGroup(player, team);
1072
1073 GetBgMap()->GetBattlegroundScript()->OnPlayerJoined(player, isInBattleground);
1074}
1075
1076// this method adds player to his team's bg group, or sets his correct group if player is already in bg group
1078{
1079 ObjectGuid playerGuid = player->GetGUID();
1080 Group* group = GetBgRaid(team);
1081 if (!group) // first player joined
1082 {
1083 group = new Group;
1084 SetBgRaid(team, group);
1085 group->Create(player);
1086 Seconds countdownMaxForBGType = Seconds(StartDelayTimes[BG_STARTING_EVENT_FIRST] / 1000);
1088 group->StartCountdown(CountdownTimerType::Pvp, countdownMaxForBGType, _preparationStartTime);
1089 else
1090 group->StartCountdown(CountdownTimerType::Pvp, countdownMaxForBGType);
1091 }
1092 else // raid already exist
1093 {
1094 if (group->IsMember(playerGuid))
1095 {
1096 uint8 subgroup = group->GetMemberGroup(playerGuid);
1097 player->SetBattlegroundOrBattlefieldRaid(group, subgroup);
1098 }
1099 else
1100 {
1101 group->AddMember(player);
1102 if (Group* originalGroup = player->GetOriginalGroup())
1103 if (originalGroup->IsLeader(playerGuid))
1104 {
1105 group->ChangeLeader(playerGuid);
1106 group->SendUpdate();
1107 }
1108 }
1109 }
1110}
1111
1112// This method should be called when player logs into running battleground
1114{
1115 ObjectGuid guid = player->GetGUID();
1116 // player is correct pointer
1117 for (auto itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
1118 {
1119 if (*itr == guid)
1120 {
1121 m_OfflineQueue.erase(itr);
1122 break;
1123 }
1124 }
1125 m_Players[guid].OfflineRemoveTime = 0;
1127 // if battleground is starting, then add preparation aura
1128 // we don't have to do that, because preparation aura isn't removed when player logs out
1129}
1130
1131// This method should be called when player logs out from running battleground
1133{
1134 ObjectGuid guid = player->GetGUID();
1135 if (!IsPlayerInBattleground(guid)) // Check if this player really is in battleground (might be a GM who teleported inside)
1136 return;
1137
1138 // player is correct pointer, it is checked in WorldSession::LogoutPlayer()
1139 m_OfflineQueue.push_back(player->GetGUID());
1140 m_Players[guid].OfflineRemoveTime = GameTime::GetGameTime() + MAX_OFFLINE_TIME;
1142 {
1143 // drop flag and handle other cleanups
1144 RemovePlayer(player, guid, GetPlayerTeam(guid));
1145
1146 // 1 player is logging out, if it is the last alive, then end arena!
1147 if (isArena() && player->IsAlive())
1150 }
1151}
1152
1153// This method should be called only once ... it adds pointer to queue
1155{
1157 {
1158 sBattlegroundMgr->AddToBGFreeSlotQueue(this);
1159 m_InBGFreeSlotQueue = true;
1160 }
1161}
1162
1163// This method removes this battleground from free queue - it must be called when deleting battleground
1165{
1167 {
1168 sBattlegroundMgr->RemoveFromBGFreeSlotQueue(GetMapId(), m_InstanceID);
1169 m_InBGFreeSlotQueue = false;
1170 }
1171}
1172
1173// get the number of free slots for team
1174// returns the number how many players can join battleground to MaxPlayersPerTeam
1176{
1177 // if BG is starting and CONFIG_BATTLEGROUND_INVITATION_TYPE == BG_QUEUE_INVITATION_TYPE_NO_BALANCE, invite anyone
1180
1181 // if BG is already started or CONFIG_BATTLEGROUND_INVITATION_TYPE != BG_QUEUE_INVITATION_TYPE_NO_BALANCE, do not allow to join too much players of one faction
1182 uint32 otherTeamInvitedCount;
1183 uint32 thisTeamInvitedCount;
1184 uint32 otherTeamPlayersCount;
1185 uint32 thisTeamPlayersCount;
1186
1187 if (team == ALLIANCE)
1188 {
1189 thisTeamInvitedCount = GetInvitedCount(ALLIANCE);
1190 otherTeamInvitedCount = GetInvitedCount(HORDE);
1191 thisTeamPlayersCount = GetPlayersCountByTeam(ALLIANCE);
1192 otherTeamPlayersCount = GetPlayersCountByTeam(HORDE);
1193 }
1194 else
1195 {
1196 thisTeamInvitedCount = GetInvitedCount(HORDE);
1197 otherTeamInvitedCount = GetInvitedCount(ALLIANCE);
1198 thisTeamPlayersCount = GetPlayersCountByTeam(HORDE);
1199 otherTeamPlayersCount = GetPlayersCountByTeam(ALLIANCE);
1200 }
1202 {
1203 // difference based on ppl invited (not necessarily entered battle)
1204 // default: allow 0
1205 uint32 diff = 0;
1206
1207 // allow join one person if the sides are equal (to fill up bg to minPlayerPerTeam)
1208 if (otherTeamInvitedCount == thisTeamInvitedCount)
1209 diff = 1;
1210 // allow join more ppl if the other side has more players
1211 else if (otherTeamInvitedCount > thisTeamInvitedCount)
1212 diff = otherTeamInvitedCount - thisTeamInvitedCount;
1213
1214 // difference based on max players per team (don't allow inviting more)
1215 uint32 diff2 = (thisTeamInvitedCount < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - thisTeamInvitedCount : 0;
1216
1217 // difference based on players who already entered
1218 // default: allow 0
1219 uint32 diff3 = 0;
1220 // allow join one person if the sides are equal (to fill up bg minPlayerPerTeam)
1221 if (otherTeamPlayersCount == thisTeamPlayersCount)
1222 diff3 = 1;
1223 // allow join more ppl if the other side has more players
1224 else if (otherTeamPlayersCount > thisTeamPlayersCount)
1225 diff3 = otherTeamPlayersCount - thisTeamPlayersCount;
1226 // or other side has less than minPlayersPerTeam
1227 else if (thisTeamInvitedCount <= GetMinPlayersPerTeam())
1228 diff3 = GetMinPlayersPerTeam() - thisTeamInvitedCount + 1;
1229
1230 // return the minimum of the 3 differences
1231
1232 // min of diff and diff 2
1233 diff = std::min(diff, diff2);
1234 // min of diff, diff2 and diff3
1235 return std::min(diff, diff3);
1236 }
1237 return 0;
1238}
1239
1241{
1243}
1244
1246{
1247 return !isArena();
1248}
1249
1251{
1252 return GetPlayersSize() < GetMaxPlayers();
1253}
1254
1256{
1257 pvpLogData.Statistics.reserve(GetPlayerScoresSize());
1258 for (auto const& score : PlayerScores)
1259 {
1260 if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), score.first))
1261 {
1263 score.second->BuildPvPLogPlayerDataPacket(playerData);
1264
1265 playerData.IsInWorld = true;
1266 playerData.PrimaryTalentTree = AsUnderlyingType(player->GetPrimarySpecialization());
1267 playerData.Sex = player->GetGender();
1268 playerData.Race = player->GetRace();
1269 playerData.Class = player->GetClass();
1270 playerData.HonorLevel = player->GetHonorLevel();
1271
1272 pvpLogData.Statistics.push_back(playerData);
1273 }
1274 }
1275
1278}
1279
1281{
1283}
1284
1285bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
1286{
1287 BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUID());
1288 if (itr == PlayerScores.end()) // player not found...
1289 return false;
1290
1291 if (type == SCORE_BONUS_HONOR && doAddHonor && isBattleground())
1292 player->RewardHonor(nullptr, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
1293 else
1294 itr->second->UpdateScore(type, value);
1295
1296 return true;
1297}
1298
1299void Battleground::UpdatePvpStat(Player* player, uint32 pvpStatId, uint32 value)
1300{
1302 score->UpdatePvpStat(pvpStatId, value);
1303}
1304
1306{
1307 return _battlegroundTemplate->MapIDs.front();
1308}
1309
1311{
1312 m_Map = map;
1313 if (map)
1314 _pvpStatIds = sDB2Manager.GetPVPStatIDsForMap(map->GetId());
1315 else
1316 _pvpStatIds = nullptr;
1317}
1318
1319void Battleground::SendMessageToAll(uint32 entry, ChatMsg msgType, Player const* source)
1320{
1321 if (!entry)
1322 return;
1323
1324 Trinity::TrinityStringChatBuilder builder(nullptr, msgType, entry, source);
1326 BroadcastWorker(localizer);
1327}
1328
1329void Battleground::PSendMessageToAll(uint32 entry, ChatMsg msgType, Player const* source, ...)
1330{
1331 if (!entry)
1332 return;
1333
1334 va_list ap;
1335 va_start(ap, source);
1336
1337 Trinity::TrinityStringChatBuilder builder(nullptr, msgType, entry, source, &ap);
1339 BroadcastWorker(localizer);
1340
1341 va_end(ap);
1342}
1343
1345{
1346 _playerPositions.push_back(position);
1347}
1348
1350{
1351 auto itr = std::remove_if(_playerPositions.begin(), _playerPositions.end(), [guid](WorldPackets::Battleground::BattlegroundPlayerPosition const& playerPosition)
1352 {
1353 return playerPosition.Guid == guid;
1354 });
1355
1356 _playerPositions.erase(itr, _playerPositions.end());
1357}
1358
1360{
1364}
1365
1367{
1368 // Keep in mind that for arena this will have to be changed a bit
1369
1370 // Add +1 deaths
1371 UpdatePlayerScore(victim, SCORE_DEATHS, 1);
1372 // Add +1 kills to group and +1 killing_blows to killer
1373 if (killer)
1374 {
1375 // Don't reward credit for killing ourselves, like fall damage of hellfire (warlock)
1376 if (killer == victim)
1377 return;
1378
1379 Team killerTeam = GetPlayerTeam(killer->GetGUID());
1380
1383 killer->UpdateCriteria(CriteriaType::KillPlayer, 1, 0, 0, victim);
1384
1385 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1386 {
1387 Player* creditedPlayer = ObjectAccessor::FindPlayer(itr->first);
1388 if (!creditedPlayer || creditedPlayer == killer)
1389 continue;
1390
1391 if (itr->second.Team == killerTeam && creditedPlayer->IsAtGroupRewardDistance(victim))
1392 {
1393 UpdatePlayerScore(creditedPlayer, SCORE_HONORABLE_KILLS, 1);
1394 creditedPlayer->UpdateCriteria(CriteriaType::KillPlayer, 1, 0, 0, victim);
1395 }
1396 }
1397 }
1398
1399 if (!isArena())
1400 {
1401 // To be able to remove insignia -- ONLY IN Battlegrounds
1403 RewardXPAtKill(killer, victim);
1404 }
1405
1406 if (BattlegroundScript* script = GetBgMap()->GetBattlegroundScript())
1407 script->OnPlayerKilled(victim, killer);
1408}
1409
1411{
1412 if (BattlegroundScript* script = GetBgMap()->GetBattlegroundScript())
1413 script->OnUnitKilled(victim, killer);
1414}
1415
1416// Return the player's team based on battlegroundplayer info
1417// Used in same faction arena matches mainly
1419{
1420 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1421 if (itr != m_Players.end())
1422 return itr->second.Team;
1423 return TEAM_OTHER;
1424}
1425
1427{
1428 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1429 if (itr != m_Players.end())
1430 return true;
1431 return false;
1432}
1433
1435{
1436 auto itr = m_Players.find(guid);
1437 if (itr != m_Players.end())
1438 return itr->second.Mercenary;
1439 return false;
1440}
1441
1443{
1445 return;
1446
1447 BlockMovement(player);
1448
1450 BuildPvPLogDataPacket(pvpMatchStatistics.Data);
1451 player->SendDirectMessage(pvpMatchStatistics.Write());
1452}
1453
1455{
1456 int count = 0;
1457 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1458 {
1459 if (itr->second.Team == team)
1460 {
1461 Player* player = ObjectAccessor::FindPlayer(itr->first);
1462 if (player && player->IsAlive())
1463 ++count;
1464 }
1465 }
1466 return count;
1467}
1468
1470{
1471 Group*& old_raid = team == ALLIANCE ? m_BgRaids[TEAM_ALLIANCE] : m_BgRaids[TEAM_HORDE];
1472 if (old_raid)
1473 old_raid->SetBattlegroundGroup(nullptr);
1474 if (bg_raid)
1475 bg_raid->SetBattlegroundGroup(this);
1476 old_raid = bg_raid;
1477}
1478
1480{
1481 _pvpDifficultyEntry = bracketEntry;
1482}
1483
1485{
1486 if (sWorld->getBoolConfig(CONFIG_BG_XP_FOR_KILL) && killer && victim)
1487 {
1488 Player* killers[] = { killer };
1489 KillRewarder(Trinity::IteratorPair(std::begin(killers), std::end(killers)), victim, true).Reward();
1490 }
1491}
1492
1494{
1495 if (teamId == TEAM_ALLIANCE || teamId == TEAM_HORDE)
1496 return m_TeamScores[teamId];
1497
1498 TC_LOG_ERROR("bg.battleground", "GetTeamScore with wrong Team {} for BG {}", teamId, GetTypeID());
1499 return 0;
1500}
1501
1502char const* Battleground::GetName() const
1503{
1504 return _battlegroundTemplate->BattlemasterEntry->Name[sWorld->GetDefaultDbcLocale()];
1505}
1506
1508{
1509 return _battlegroundTemplate->Id;
1510}
1511
1513{
1515}
1516
1518{
1519 return uint8(GetMinLevel() / 5) - 1; // 10 - 1, 15 - 2, 20 - 3, etc.
1520}
1521
1523{
1524 return GetMaxPlayersPerTeam() * 2;
1525}
1526
1528{
1529 return GetMinPlayersPerTeam() * 2;
1530}
1531
1533{
1536
1538}
1539
1541{
1544
1546}
1547
1549{
1550 if (isArena())
1551 {
1552 switch (GetArenaType())
1553 {
1554 case ARENA_TYPE_2v2:
1555 return 2;
1556 case ARENA_TYPE_3v3:
1557 return 3;
1558 case ARENA_TYPE_5v5: // removed
1559 return 5;
1560 default:
1561 break;
1562 }
1563 }
1564
1566}
1567
1569{
1571}
#define sBattlegroundMgr
@ BG_QUEUE_INVITATION_TYPE_NO_BALANCE
@ SCORE_KILLING_BLOWS
@ SCORE_BONUS_HONOR
@ SCORE_DEATHS
@ SCORE_HONORABLE_KILLS
@ PLAYER_POSITION_UPDATE_INTERVAL
Definition: Battleground.h:141
@ MAX_OFFLINE_TIME
Definition: Battleground.h:135
@ TIME_AUTOCLOSE_BATTLEGROUND
Definition: Battleground.h:134
@ CHECK_PLAYER_POSITION_INVERVAL
Definition: Battleground.h:129
@ ARENA_TYPE_5v5
Definition: Battleground.h:192
@ ARENA_TYPE_3v3
Definition: Battleground.h:191
@ ARENA_TYPE_2v2
Definition: Battleground.h:190
@ BG_STARTING_EVENT_3
Definition: Battleground.h:200
@ BG_STARTING_EVENT_2
Definition: Battleground.h:199
@ BG_STARTING_EVENT_1
Definition: Battleground.h:198
@ BG_STARTING_EVENT_4
Definition: Battleground.h:201
@ BG_TEXT_START_TWO_MINUTES
Definition: Battleground.h:61
@ BG_TEXT_BATTLE_HAS_BEGUN
Definition: Battleground.h:64
@ BG_TEXT_ALLIANCE_WINS
Definition: Battleground.h:58
@ BG_TEXT_HORDE_WINS
Definition: Battleground.h:59
@ BG_TEXT_START_ONE_MINUTE
Definition: Battleground.h:62
@ BG_TEXT_START_HALF_MINUTE
Definition: Battleground.h:63
@ SPELL_MERCENARY_SHAPESHIFT
Definition: Battleground.h:123
@ SPELL_MERCENARY_ALLIANCE_REACTIONS
Definition: Battleground.h:122
@ SPELL_MERCENARY_HORDE_REACTIONS
Definition: Battleground.h:120
@ SPELL_MERCENARY_HORDE_1
Definition: Battleground.h:119
@ SPELL_ARENA_PREPARATION
Definition: Battleground.h:108
@ SPELL_HONORABLE_DEFENDER_25Y
Definition: Battleground.h:115
@ SPELL_MERCENARY_ALLIANCE_1
Definition: Battleground.h:121
@ SPELL_HONORABLE_DEFENDER_60Y
Definition: Battleground.h:116
@ BG_START_DELAY_1M
Definition: Battleground.h:147
@ BG_START_DELAY_30S
Definition: Battleground.h:148
@ BG_START_DELAY_2M
Definition: Battleground.h:146
@ BG_START_DELAY_NONE
Definition: Battleground.h:150
@ STATUS_WAIT_QUEUE
Definition: Battleground.h:165
@ STATUS_NONE
Definition: Battleground.h:164
@ STATUS_WAIT_LEAVE
Definition: Battleground.h:168
@ STATUS_WAIT_JOIN
Definition: Battleground.h:166
@ STATUS_IN_PROGRESS
Definition: Battleground.h:167
@ SOUND_BG_START
Definition: Battleground.h:71
@ SOUND_ALLIANCE_WINS
Definition: Battleground.h:70
@ SOUND_HORDE_WINS
Definition: Battleground.h:69
@ BG_STARTING_EVENT_THIRD
Definition: Battleground.h:208
@ BG_STARTING_EVENT_SECOND
Definition: Battleground.h:207
@ BG_STARTING_EVENT_FIRST
Definition: Battleground.h:206
@ BG_STARTING_EVENT_FOURTH
Definition: Battleground.h:209
@ CHAR_SEL_PVPSTATS_MAXID
@ CHAR_INS_PVPSTATS_PLAYER
@ CHAR_INS_PVPSTATS_BATTLEGROUND
@ IN_MILLISECONDS
Definition: Common.h:35
@ MINUTE
Definition: Common.h:29
#define sCreatureTextMgr
DB2Storage< BroadcastTextEntry > sBroadcastTextStore("BroadcastText.db2", &BroadcastTextLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:553
BattlegroundBracketId
Definition: DBCEnums.h:59
@ ParticipateInBattleground
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint8_t uint8
Definition: Define.h:144
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:24
#define ASSERT
Definition: Errors.h:68
#define sGuildMgr
Definition: GuildMgr.h:70
@ TEMP_ENCHANTMENT_SLOT
Definition: ItemDefines.h:192
@ LANG_BG_STARTED_ANNOUNCE_WORLD
Definition: Language.h:710
@ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
Definition: Language.h:743
@ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS
Definition: Language.h:744
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition: Log.h:179
#define TC_LOG_ERROR(filterType__, message__,...)
Definition: Log.h:188
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ PET_SAVE_NOT_IN_SLOT
Definition: PetDefines.h:48
@ SPELL_PREPARATION
Definition: PlayerAI.cpp:174
@ PLAYER_FLAGS_EX_MERCENARY_MODE
Definition: Player.h:490
@ GENDER_MALE
constexpr BattlegroundQueueTypeId BATTLEGROUND_QUEUE_NONE
TeamId
@ TEAM_NEUTRAL
@ TEAM_ALLIANCE
@ TEAM_HORDE
constexpr TeamId GetOtherTeam(TeamId team)
Team
@ TEAM_OTHER
@ ALLIANCE
@ HORDE
@ SPELL_ATTR0_NO_IMMUNITIES
BattlegroundTypeId
@ BATTLEGROUND_TYPE_NONE
@ PVP_TEAM_NEUTRAL
@ PVP_TEAM_HORDE
@ PVP_TEAM_ALLIANCE
ChatMsg
@ CHAT_MSG_SYSTEM
@ CHAT_MSG_BG_SYSTEM_NEUTRAL
@ SPELL_AURA_MOD_SHAPESHIFT
@ SPELL_AURA_SPIRIT_OF_REDEMPTION
@ SPELL_AURA_MOD_INVISIBILITY
@ SPELL_AURA_MOD_REPUTATION_GAIN
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
@ UNIT_FLAG_SKINNABLE
Definition: UnitDefines.h:193
T AddPct(T &base, U pct)
Definition: Util.h:85
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:528
#define sWorldStateMgr
Definition: WorldStateMgr.h:50
static Summons Group[]
Definition: boss_urom.cpp:83
bool IsPositive() const
Definition: SpellAuras.h:86
Aura * GetBase() const
Definition: SpellAuras.h:80
int32 GetDuration() const
Definition: SpellAuras.h:176
bool HasEffectType(AuraType type) const
SpellInfo const * GetSpellInfo() const
Definition: SpellAuras.h:137
bool IsPermanent() const
Definition: SpellAuras.h:181
void SetUnload()
Definition: Map.cpp:3452
void SetBG(Battleground *bg)
Definition: Map.h:952
BattlegroundScript * GetBattlegroundScript()
Definition: Map.h:956
static bool IsRandomBattleground(uint32 battlemasterListId)
static bool IsBGWeekend(BattlegroundTypeId bgTypeId)
virtual void OnStart()
virtual void OnPrepareStage1()
virtual void OnEnd(Team winner)
virtual void OnPrepareStage2()
virtual void OnPrepareStage3()
virtual void OnPlayerJoined(Player *player, bool inBattleground)
uint32 m_InvitedAlliance
Definition: Battleground.h:548
void UpdatePlayersCountByTeam(Team team, bool remove)
Definition: Battleground.h:385
void SetRemainingTime(uint32 Time)
Definition: Battleground.h:300
uint32 m_ArenaTeamMMR[PVP_TEAMS_COUNT]
Definition: Battleground.h:560
bool m_SetDeleteThis
Definition: Battleground.h:533
WorldSafeLocsEntry const * GetTeamStartPosition(TeamId teamId) const
uint32 GetMapId() const
Team GetPrematureWinner()
PvPTeamId _winnerTeamId
Definition: Battleground.h:535
void SendPacketToTeam(Team team, WorldPacket const *packet, Player *except=nullptr) const
char const * GetName() const
PVPDifficultyEntry const * _pvpDifficultyEntry
Definition: Battleground.h:567
void SendPacketToAll(WorldPacket const *packet) const
void RemovePlayerPosition(ObjectGuid guid)
uint32 GetMinLevel() const
void ModifyStartDelayTime(int diff)
Definition: Battleground.h:306
void SetElapsedTime(uint32 Time)
Definition: Battleground.h:299
virtual void HandleKillPlayer(Player *player, Player *killer)
uint32 m_ArenaTeamIds[PVP_TEAMS_COUNT]
Definition: Battleground.h:558
void _ProcessPlayerPositionBroadcast(uint32 diff)
void AddOrSetPlayerToCorrectBgGroup(Player *player, Team team)
std::deque< ObjectGuid > m_OfflineQueue
Definition: Battleground.h:543
uint32 GetMinPlayersPerTeam() const
void PlayerAddedToBGCheckIfBGIsRunning(Player *player)
uint8 GetArenaType() const
Definition: Battleground.h:288
BattlegroundPlayerMap m_Players
Definition: Battleground.h:512
Player * _GetPlayerForTeam(Team team, BattlegroundPlayerMap::const_iterator itr, char const *context) const
uint32 GetMaxPlayersPerTeam() const
time_t _preparationStartTime
Definition: Battleground.h:573
uint32 m_ValidStartPositionTimer
Definition: Battleground.h:529
int32 m_StartDelayTime
Definition: Battleground.h:536
Group * GetBgRaid(Team team) const
Definition: Battleground.h:372
BattlegroundTemplate const * _battlegroundTemplate
Definition: Battleground.h:566
uint32 GetInvitedCount(Team team) const
Definition: Battleground.h:315
void SetWinner(PvPTeamId winnerTeamId)
Definition: Battleground.h:303
uint8 GetUniqueBracketId() const
void PlaySoundToAll(uint32 SoundID)
uint32 m_ClientInstanceID
Definition: Battleground.h:526
void AddToBGFreeSlotQueue()
uint32 GetTeamScore(TeamId teamId) const
uint32 GetPlayerScoresSize() const
Definition: Battleground.h:328
void DecreaseInvitedCount(Team team)
Definition: Battleground.h:312
bool isRated() const
Definition: Battleground.h:321
void RewardHonorToTeam(uint32 Honor, Team team)
void SetBgMap(BattlegroundMap *map)
virtual void HandleKillUnit(Creature *, Unit *)
uint32 GetMaxPlayers() const
BattlegroundMap * GetBgMap() const
virtual void PostUpdateImpl(uint32)
Post-update hook.
Definition: Battleground.h:497
PvPTeamId GetWinner() const
Definition: Battleground.h:289
Battleground(BattlegroundTemplate const *battlegroundTemplate)
virtual void RemovePlayer(Player *, ObjectGuid, uint32)
Definition: Battleground.h:509
BattlegroundMap * FindBgMap() const
Definition: Battleground.h:341
void BlockMovement(Player *player)
uint32 GetRemainingTime() const
Definition: Battleground.h:277
Player * _GetPlayer(ObjectGuid guid, bool offlineRemove, char const *context) const
void StartBattleground()
BattlegroundTypeId GetTypeID() const
void Update(uint32 diff)
bool m_PrematureCountDown
Definition: Battleground.h:538
uint32 m_PlayersCount[PVP_TEAMS_COUNT]
Definition: Battleground.h:555
Group * m_BgRaids[PVP_TEAMS_COUNT]
Definition: Battleground.h:552
uint32 m_PrematureCountDownTimer
Definition: Battleground.h:539
void RemoveAuraOnTeam(uint32 SpellID, Team team)
virtual WorldSafeLocsEntry const * GetExploitTeleportLocation(Team)
Definition: Battleground.h:410
int32 m_TeamScores[PVP_TEAMS_COUNT]
Definition: Battleground.h:520
void PSendMessageToAll(uint32 entry, ChatMsg type, Player const *source,...)
void SendMessageToAll(uint32 entry, ChatMsg type, Player const *source=nullptr)
void EventPlayerLoggedOut(Player *player)
void SendChatMessage(Creature *source, uint8 textId, WorldObject *target=nullptr)
BattlegroundPlayer const * GetBattlegroundPlayerData(ObjectGuid const &playerGuid) const
Definition: Battleground.h:443
void RewardXPAtKill(Player *killer, Player *victim)
bool m_InBGFreeSlotQueue
Definition: Battleground.h:532
static TeamId GetTeamIndexByTeamId(Team team)
Definition: Battleground.h:382
void UpdateWorldState(int32 worldStateId, int32 value, bool hidden=false)
void SetStatus(BattlegroundStatus Status)
Definition: Battleground.h:297
bool IsPlayerMercenaryInBattleground(ObjectGuid guid) const
void BroadcastWorker(Do &_do)
virtual void EndBattleground(Team winner)
bool IsPlayerInBattleground(ObjectGuid guid) const
BattlegroundStartTimeIntervals StartDelayTimes[BG_STARTING_EVENT_COUNT]
Definition: Battleground.h:516
bool isArena() const
uint32 m_LastPlayerPositionBroadcast
Definition: Battleground.h:540
void SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const *target=nullptr)
BattlegroundScore const * GetBattlegroundScore(Player *player) const
uint32 m_InstanceID
Definition: Battleground.h:524
void AddPlayerPosition(WorldPackets::Battleground::BattlegroundPlayerPosition const &position)
void PlaySoundToTeam(uint32 SoundID, Team team)
uint32 m_ResetStatTimer
Definition: Battleground.h:528
void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, Team team)
BattlegroundPlayerMap const & GetPlayers() const
Definition: Battleground.h:324
int32 GetStartDelayTime() const
Definition: Battleground.h:287
BattlegroundScoreMap PlayerScores
Definition: Battleground.h:507
float GetStartMaxDist() const
bool isBattleground() const
std::vector< WorldPackets::Battleground::BattlegroundPlayerPosition > _playerPositions
Definition: Battleground.h:570
virtual void AddPlayer(Player *player, BattlegroundQueueTypeId queueId)
BattlegroundStatus GetStatus() const
Definition: Battleground.h:274
bool HasFreeSlots() const
bool UpdatePlayerScore(Player *player, uint32 type, uint32 value, bool doAddHonor=true)
uint8 m_ArenaType
Definition: Battleground.h:531
uint32 GetPlayersCountByTeam(Team team) const
Definition: Battleground.h:383
void _ProcessOfflineQueue()
uint32 GetAlivePlayersCountByTeam(Team team) const
void RemoveFromBGFreeSlotQueue()
void TeleportPlayerToExploitLocation(Player *player)
void _ProcessProgress(uint32 diff)
uint32 GetFreeSlotsForTeam(Team team) const
virtual bool PreUpdateImpl(uint32)
Pre-update hook.
Definition: Battleground.h:484
uint32 GetScriptId() const
virtual ~Battleground()
virtual void CheckWinConditions()
Definition: Battleground.h:393
void EventPlayerLoggedIn(Player *player)
void _CheckSafePositions(uint32 diff)
void _ProcessJoin(uint32 diff)
BattlegroundBracketId GetBracketId() const
std::unordered_set< uint32 > const * _pvpStatIds
Definition: Battleground.h:568
Team GetPlayerTeam(ObjectGuid guid) const
uint32 m_InvitedHorde
Definition: Battleground.h:549
uint32 GetBonusHonorFromKill(uint32 kills) const
void UpdatePvpStat(Player *player, uint32 pvpStatId, uint32 value)
uint32 GetMaxLevel() const
uint32 GetElapsedTime() const
Definition: Battleground.h:276
void CastSpellOnTeam(uint32 SpellID, Team team)
void SetBracket(PVPDifficultyEntry const *bracketEntry)
uint32 GetPlayersSize() const
Definition: Battleground.h:325
uint32 m_StartTime
Definition: Battleground.h:527
void SetBgRaid(Team team, Group *bg_raid)
void SetStartDelayTime(int Time)
Definition: Battleground.h:307
virtual void BuildPvPLogDataPacket(WorldPackets::Battleground::PVPMatchStatistics &pvpLogData) const
virtual void RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool SendPacket)
BattlegroundMap * m_Map
Definition: Battleground.h:563
uint32 GetMinPlayers() const
void _ProcessLeave(uint32 diff)
BattlegroundStatus m_Status
Definition: Battleground.h:525
uint32 StartMessageIds[BG_STARTING_EVENT_COUNT]
Definition: Battleground.h:518
Class used to access individual fields of database query result.
Definition: Field.h:93
uint64 GetUInt64() const
Definition: Field.cpp:77
Definition: Group.h:205
uint8 GetMemberGroup(ObjectGuid guid) const
Definition: Group.cpp:1740
void SendUpdate() const
Definition: Group.cpp:832
bool AddMember(Player *player)
Definition: Group.cpp:424
void ChangeLeader(ObjectGuid guid)
Definition: Group.cpp:686
void SetBattlegroundGroup(Battleground *bg)
Definition: Group.cpp:1748
bool IsMember(ObjectGuid guid) const
Definition: Group.cpp:1692
bool Create(Player *leader)
Definition: Group.cpp:141
void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional< time_t > startTime={ })
Definition: Group.cpp:1423
Definition: Guild.h:329
void UnloadAll()
Definition: Map.cpp:1656
uint32 GetId() const
Definition: Map.cpp:3210
LowType GetCounter() const
Definition: ObjectGuid.h:296
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
std::string ToString() const
Definition: ObjectGuid.cpp:777
uint64 LowType
Definition: ObjectGuid.h:281
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:195
void SetClientControl(Unit *target, bool allowMove)
Definition: Player.cpp:26193
void SetBGTeam(Team team)
Definition: Player.cpp:24039
void SetPlayerFlagEx(PlayerFlagsEx flags)
Definition: Player.h:2845
bool HasPlayerFlagEx(PlayerFlagsEx flags) const
Definition: Player.h:2844
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId, BattlegroundQueueTypeId queueId)
Definition: Player.cpp:25463
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
void ClearAfkReports()
Definition: Player.h:2529
static void OfflineResurrect(ObjectGuid const &guid, CharacterDatabaseTransaction trans)
Definition: Player.cpp:4531
void RemovePlayerFlagEx(PlayerFlagsEx flags)
Definition: Player.h:2846
void SpawnCorpseBones(bool triggerSave=true)
Definition: Player.cpp:4600
Group * GetOriginalGroup() const
Definition: Player.h:2727
uint32 GetBattlegroundQueueJoinTime(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25417
bool IsMercenaryForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25531
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition: Player.cpp:26127
void DestroyConjuredItems(bool update)
Definition: Player.cpp:12493
void UnsummonPetTemporaryIfAny()
Definition: Player.cpp:27633
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition: Player.cpp:25494
bool GetRandomWinner() const
Definition: Player.h:2536
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition: Player.cpp:27236
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition: Player.cpp:21863
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:1231
bool TeleportToBGEntryPoint()
Definition: Player.cpp:1491
void ToggleAFK()
Definition: Player.cpp:1193
uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25442
void ResetAllPowers()
Definition: Player.cpp:1868
bool RewardHonor(Unit *victim, uint32 groupsize, int32 honor=-1, bool pvptoken=false)
Definition: Player.cpp:6789
bool isAFK() const
Definition: Player.h:1221
Team GetEffectiveTeam() const
Definition: Player.h:2338
void FailCriteria(CriteriaFailEvent condition, int32 failAsset)
Definition: Player.cpp:27230
void ResummonPetTemporaryUnSummonedIfAny()
Definition: Player.cpp:27648
Team GetBGTeam() const
Definition: Player.cpp:24045
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition: Player.cpp:26441
ReputationMgr & GetReputationMgr()
Definition: Player.h:2350
void RemoveArenaEnchantments(EnchantmentSlot slot)
Definition: Player.cpp:13430
void SetRandomWinner(bool isWinner)
Definition: Player.cpp:29580
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition: Player.cpp:4416
void setUInt32(uint8 index, uint32 value)
void setBool(uint8 index, bool value)
void setUInt64(uint8 index, uint64 value)
void setUInt8(uint8 index, uint8 value)
bool ModifyReputation(FactionEntry const *factionEntry, int32 standing, bool spillOverOnly=false, bool noSpillover=false)
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:448
Utility class to enable range for loop syntax for multimap.equal_range uses.
Definition: IteratorPair.h:32
Definition: Unit.h:630
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3878
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition: Unit.cpp:5917
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3751
void AtEndOfEncounter(EncounterType type)
Definition: Unit.cpp:568
bool IsAlive() const
Definition: Unit.h:1175
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4743
int32 GetTotalAuraModifier(AuraType auraType) const
Definition: Unit.cpp:4998
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
Definition: Unit.cpp:4170
int32 GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition: Unit.cpp:5058
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:841
void CombatStopWithPets(bool includingCast=false)
Definition: Unit.cpp:5945
constexpr uint32 GetMapId() const
Definition: Position.h:215
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2977
std::string const & GetName() const
Definition: Object.h:680
std::vector< BattlegroundPlayerPosition > FlagCarriers
WorldPackets::Duration< Seconds > Duration
WorldPackets::Duration< Seconds > Duration
WorldPacket const * GetRawPacket() const
Definition: Packet.h:38
#define sWorld
Definition: World.h:927
@ CONFIG_BG_REWARD_LOSER_HONOR_LAST
Definition: World.h:411
@ CONFIG_BATTLEGROUND_INVITATION_TYPE
Definition: World.h:339
@ CONFIG_BG_REWARD_WINNER_HONOR_FIRST
Definition: World.h:408
@ CONFIG_BG_REWARD_LOSER_HONOR_FIRST
Definition: World.h:410
@ CONFIG_BG_REWARD_WINNER_HONOR_LAST
Definition: World.h:409
@ CONFIG_BG_XP_FOR_KILL
Definition: World.h:139
@ CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE
Definition: World.h:138
@ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE
Definition: World.h:136
TC_GAME_API uint32 GetId(std::string_view username)
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition: GameTime.cpp:54
time_t GetGameTime()
Definition: GameTime.cpp:44
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:37
uint32 hk_honor_at_level(uint8 level, float multiplier=1.0f)
Definition: Formulas.h:58
BattlegroundQueueTypeId queueTypeId
Definition: Battleground.h:176
BattlegroundTypeId Id
uint8 GetMinLevel() const
BattlemasterListEntry const * BattlemasterEntry
uint16 GetMaxPlayersPerTeam() const
std::vector< int32 > MapIDs
WorldSafeLocsEntry const * StartLocation[PVP_TEAMS_COUNT]
uint16 GetMinPlayersPerTeam() const
uint8 GetMaxLevel() const
LocalizedString Name
Definition: DB2Structure.h:511
BattlegroundBracketId GetBracketId() const
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:91
constexpr float GetExactDistSq(float x, float y, float z) const
Definition: Position.h:120
std::vector< PVPMatchPlayerStatistics > Statistics
WorldLocation Loc
Definition: ObjectMgr.h:850