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 "ChatTextBuilder.h"
23#include "Creature.h"
24#include "CreatureTextMgr.h"
25#include "DatabaseEnv.h"
26#include "DB2Stores.h"
27#include "Formulas.h"
28#include "GameEventSender.h"
29#include "GameTime.h"
30#include "GridNotifiersImpl.h"
31#include "Group.h"
32#include "Guild.h"
33#include "GuildMgr.h"
34#include "KillRewarder.h"
35#include "Language.h"
36#include "Log.h"
37#include "Map.h"
38#include "MapUtils.h"
39#include "MiscPackets.h"
40#include "ObjectAccessor.h"
41#include "ObjectMgr.h"
42#include "Player.h"
43#include "ReputationMgr.h"
44#include "SpellAuras.h"
45#include "TemporarySummon.h"
46#include "Transport.h"
47#include "Util.h"
48#include "WorldStateMgr.h"
49#include <cstdarg>
50
51template<class Do>
53{
54 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
55 if (Player* player = _GetPlayer(itr, "BroadcastWorker"))
56 _do(player);
57}
58
59Battleground::Battleground(BattlegroundTemplate const* battlegroundTemplate) : _battlegroundTemplate(battlegroundTemplate), _pvpDifficultyEntry(nullptr), _pvpStatIds(nullptr), _preparationStartTime(0)
60{
61 ASSERT(_battlegroundTemplate, "Nonexisting Battleground Template passed to battleground ctor!");
62
63 m_InstanceID = 0;
66 m_EndTime = 0;
69 m_ArenaType = 0;
71 m_StartTime = 0;
74 m_Events = 0;
76 m_IsRated = false;
77 m_InBGFreeSlotQueue = false;
78 m_SetDeleteThis = false;
79
80 m_Map = nullptr;
81
84
87
88 m_BgRaids[TEAM_ALLIANCE] = nullptr;
89 m_BgRaids[TEAM_HORDE] = nullptr;
90
93
96
99
101
106
111}
112
114
116{
117 // remove objects and creatures
118 // (this is done automatically in mapmanager update, when the instance is reset after the reset time)
119 uint32 size = uint32(BgCreatures.size());
120 for (uint32 i = 0; i < size; ++i)
121 DelCreature(i);
122
123 size = uint32(BgObjects.size());
124 for (uint32 i = 0; i < size; ++i)
125 DelObject(i);
126
127 // unload map
128 if (m_Map)
129 {
130 m_Map->UnloadAll(); // unload all objects (they may hold a reference to bg in their ZoneScript pointer)
131 m_Map->SetUnload(); // mark for deletion by MapManager
132
133 //unlink to prevent crash, always unlink all pointer reference before destruction
134 m_Map->SetBG(nullptr);
135 m_Map = nullptr;
136 }
137 // remove from bg free slot queue
139
140 for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr)
141 delete itr->second;
142
143 _playerPositions.clear();
144}
145
147{
148 if (!PreUpdateImpl(diff))
149 return;
150
151 if (!GetPlayersSize())
152 {
153 //BG is empty
154 // if there are no players invited, delete BG
155 // this will delete arena or bg object, where any player entered
156 // [[ but if you use battleground object again (more battles possible to be played on 1 instance)
157 // then this condition should be removed and code:
158 // if (!GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
159 // AddToFreeBGObjectsQueue(); // not yet implemented
160 // should be used instead of current
161 // ]]
162 // Battleground Template instance cannot be updated, because it would be deleted
164 m_SetDeleteThis = true;
165 return;
166 }
167
168 switch (GetStatus())
169 {
170 case STATUS_WAIT_JOIN:
171 if (GetPlayersSize())
172 {
173 _ProcessJoin(diff);
175 }
176 break;
180 // after 47 minutes without one team losing, the arena closes with no winner and no rating change
181 if (isArena())
182 {
184 {
186 return;
187 }
188 }
189 else
190 {
192 _ProcessProgress(diff);
193 else if (m_PrematureCountDown)
194 m_PrematureCountDown = false;
195 }
196 break;
198 _ProcessLeave(diff);
199 break;
200 default:
201 break;
202 }
203
204 // Update start time and reset stats timer
207 m_ResetStatTimer += diff;
208
209 PostUpdateImpl(diff);
210}
211
213{
214 float maxDist = GetStartMaxDist();
215 if (!maxDist)
216 return;
217
220 {
222
223 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
224 {
225 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
226 {
227 if (player->IsGameMaster())
228 continue;
229
230 Position pos = player->GetPosition();
231 WorldSafeLocsEntry const* startPos = GetTeamStartPosition(Battleground::GetTeamIndexByTeamId(player->GetBGTeam()));
232 if (pos.GetExactDistSq(startPos->Loc) > maxDist)
233 {
234 TC_LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending {} back to start location (map: {}) (possible exploit)", player->GetName(), GetMapId());
235 player->TeleportTo(startPos->Loc);
236 }
237 }
238 }
239 }
240}
241
243{
246 {
248
250
252 {
253 // Update position data if we found player.
254 if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), playerPosition.Guid))
255 playerPosition.Pos = player->GetPosition();
256
257 playerPositions.FlagCarriers.push_back(playerPosition);
258 }
259
260 SendPacketToAll(playerPositions.Write());
261 }
262}
263
265{
266 // remove offline players from bg after 5 minutes
267 if (!m_OfflineQueue.empty())
268 {
269 BattlegroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin()));
270 if (itr != m_Players.end())
271 {
272 if (itr->second.OfflineRemoveTime <= GameTime::GetGameTime())
273 {
274 RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
275 m_OfflineQueue.pop_front(); // remove from offline queue
276 //do not use itr for anything, because it is erased in RemovePlayerAtLeave()
277 }
278 }
279 }
280}
281
283{
284 Team winner = TEAM_OTHER;
286 winner = ALLIANCE;
288 winner = HORDE;
289
290 return winner;
291}
292
294{
295 // *********************************************************
296 // *** BATTLEGROUND BALLANCE SYSTEM ***
297 // *********************************************************
298 // if less then minimum players are in on one side, then start premature finish timer
300 {
302 m_PrematureCountDownTimer = sBattlegroundMgr->GetPrematureFinishTime();
303 }
304 else if (m_PrematureCountDownTimer < diff)
305 {
306 // time's up!
308 m_PrematureCountDown = false;
309 }
310 else if (!sBattlegroundMgr->isTesting())
311 {
312 uint32 newtime = m_PrematureCountDownTimer - diff;
313 // announce every minute
314 if (newtime > (MINUTE * IN_MILLISECONDS))
315 {
318 }
319 else
320 {
321 //announce every 15 seconds
322 if (newtime / (15 * IN_MILLISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILLISECONDS))
324 }
326 }
327}
328
330{
331 // *********************************************************
332 // *** BATTLEGROUND STARTING SYSTEM ***
333 // *********************************************************
335
336 if (!isArena())
337 SetRemainingTime(300000);
338
339 if (m_ResetStatTimer > 5000)
340 {
342 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
343 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
344 player->ResetAllPowers();
345 }
346
348 {
350
351 if (!FindBgMap())
352 {
353 TC_LOG_ERROR("bg.battleground", "Battleground::_ProcessJoin: map (map id: {}, instance id: {}) is not created!", GetMapId(), m_InstanceID);
354 EndNow();
355 return;
356 }
357
358 // Setup here, only when at least one player has ported to the map
359 if (!SetupBattleground())
360 {
361 EndNow();
362 return;
363 }
364
366 for (Group* group : m_BgRaids)
367 if (group)
369
372 // First start warning - 2 or 1 minute
375 }
376 // After 1 minute or 30 seconds, warning is signaled
378 {
382 }
383 // After 30 or 15 seconds, warning is signaled
385 {
389 }
390 // Delay expired (after 2 or 1 minute)
391 else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
392 {
394
396
401
403
404 for (auto const& [guid, _] : GetPlayers())
405 {
406 if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), guid))
407 {
408 player->StartCriteria(CriteriaStartEvent::StartBattleground, GetBgMap()->GetId());
409 player->AtStartOfEncounter(EncounterType::Battleground);
410 }
411 }
412
413 // Remove preparation
414 if (isArena())
415 {
417 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
418 {
419 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
420 {
421 // Correctly display EnemyUnitFrame
422 player->SetArenaFaction(player->GetBGTeam());
423
424 player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
425 player->ResetAllPowers();
426 if (!player->IsGameMaster())
427 {
428 // remove auras with duration lower than 30s
429 player->RemoveAppliedAuras([](AuraApplication const* aurApp)
430 {
431 Aura* aura = aurApp->GetBase();
432 return !aura->IsPermanent()
433 && aura->GetDuration() <= 30 * IN_MILLISECONDS
434 && aurApp->IsPositive()
437 });
438 }
439 }
440 }
441
443 }
444 else
445 {
447
448 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
449 {
450 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
451 {
452 player->RemoveAurasDueToSpell(SPELL_PREPARATION);
453 player->ResetAllPowers();
454 }
455 }
456 // Announce BG starting
459 }
460 }
461
462 if (GetRemainingTime() > 0 && (m_EndTime -= diff) > 0)
464}
465
467{
468 // *********************************************************
469 // *** BATTLEGROUND ENDING SYSTEM ***
470 // *********************************************************
471 // remove all players from battleground after 2 minutes
473 if (GetRemainingTime() <= 0)
474 {
476 BattlegroundPlayerMap::iterator itr, next;
477 for (itr = m_Players.begin(); itr != m_Players.end(); itr = next)
478 {
479 next = itr;
480 ++next;
481 //itr is erased here!
482 RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
483 // do not change any battleground's private variables
484 }
485 }
486}
487
488Player* Battleground::_GetPlayer(ObjectGuid guid, bool offlineRemove, char const* context) const
489{
490 Player* player = nullptr;
491 if (!offlineRemove)
492 {
493 // should this be ObjectAccessor::FindConnectedPlayer() to return players teleporting ?
494 player = ObjectAccessor::FindPlayer(guid);
495 if (!player)
496 TC_LOG_ERROR("bg.battleground", "Battleground::{}: player ({}) not found for BG (map: {}, instance id: {})!",
497 context, guid.ToString(), GetMapId(), m_InstanceID);
498 }
499 return player;
500}
501
502Player* Battleground::_GetPlayerForTeam(Team team, BattlegroundPlayerMap::const_iterator itr, char const* context) const
503{
504 Player* player = _GetPlayer(itr, context);
505 if (player)
506 {
507 Team playerTeam = itr->second.Team;
508 if (!playerTeam)
509 playerTeam = player->GetEffectiveTeam();
510 if (playerTeam != team)
511 player = nullptr;
512 }
513 return player;
514}
515
517{
518 ASSERT(m_Map);
519 return m_Map;
520}
521
523{
524 ASSERT(teamId < TEAM_NEUTRAL);
525 return _battlegroundTemplate->StartLocation[teamId];
526}
527
529{
531}
532
534{
535 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
536 if (Player* player = _GetPlayer(itr, "SendPacketToAll"))
537 player->SendDirectMessage(packet);
538}
539
540void Battleground::SendPacketToTeam(Team team, WorldPacket const* packet, Player* except /*= nullptr*/) const
541{
542 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
543 {
544 if (Player* player = _GetPlayerForTeam(team, itr, "SendPacketToTeam"))
545 if (player != except)
546 player->SendDirectMessage(packet);
547 }
548}
549
550void Battleground::SendChatMessage(Creature* source, uint8 textId, WorldObject* target /*= nullptr*/)
551{
552 sCreatureTextMgr->SendChat(source, textId, target);
553}
554
556{
557 if (!sBroadcastTextStore.LookupEntry(id))
558 {
559 TC_LOG_ERROR("bg.battleground", "Battleground::SendBroadcastText: `broadcast_text` (ID: {}) was not found", id);
560 return;
561 }
562
563 Trinity::BroadcastTextBuilder builder(nullptr, msgType, id, GENDER_MALE, target);
565 BroadcastWorker(localizer);
566}
567
569{
571}
572
574{
576}
577
579{
580 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
581 if (Player* player = _GetPlayerForTeam(team, itr, "CastSpellOnTeam"))
582 player->CastSpell(player, SpellID, true);
583}
584
586{
587 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
588 if (Player* player = _GetPlayerForTeam(team, itr, "RemoveAuraOnTeam"))
589 player->RemoveAura(SpellID);
590}
591
593{
594 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
595 if (Player* player = _GetPlayerForTeam(team, itr, "RewardHonorToTeam"))
597}
598
599void Battleground::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, Team team)
600{
601 FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
602 if (!factionEntry)
603 return;
604
605 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
606 {
607 Player* player = _GetPlayerForTeam(team, itr, "RewardReputationToTeam");
608 if (!player)
609 continue;
610
612 continue;
613
614 uint32 repGain = Reputation;
617 player->GetReputationMgr().ModifyReputation(factionEntry, repGain);
618 }
619}
620
621void Battleground::UpdateWorldState(int32 worldStateId, int32 value, bool hidden /*= false*/)
622{
623 sWorldStateMgr->SetValue(worldStateId, value, hidden, GetBgMap());
624}
625
627{
629
630 bool guildAwarded = false;
631
632 if (winner == ALLIANCE)
633 {
634 if (isBattleground())
636
637 PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
638
640 }
641 else if (winner == HORDE)
642 {
643 if (isBattleground())
645
646 PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
647
649 }
650 else
651 {
653 }
654
656 uint64 battlegroundId = 1;
658 {
659 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PVPSTATS_MAXID);
660 PreparedQueryResult result = CharacterDatabase.Query(stmt);
661
662 if (result)
663 {
664 Field* fields = result->Fetch();
665 battlegroundId = fields[0].GetUInt64() + 1;
666 }
667
668 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_BATTLEGROUND);
669 stmt->setUInt64(0, battlegroundId);
670 stmt->setUInt8(1, GetWinner());
671 stmt->setUInt8(2, GetUniqueBracketId());
672 stmt->setUInt32(3, GetTypeID());
673 CharacterDatabase.Execute(stmt);
674 }
675
677 //we must set it this way, because end time is sent in packet!
679
681 pvpMatchComplete.Winner = GetWinner();
682 pvpMatchComplete.Duration = std::chrono::duration_cast<Seconds>(Milliseconds(std::max<int32>(0, (GetElapsedTime() - BG_START_DELAY_2M))));
683 pvpMatchComplete.LogData.emplace();
684 BuildPvPLogDataPacket(*pvpMatchComplete.LogData);
685 pvpMatchComplete.Write();
686
687 for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
688 {
689 Team team = itr->second.Team;
690
691 Player* player = _GetPlayer(itr, "EndBattleground");
692 if (!player)
693 continue;
694
695 // should remove spirit of redemption
698
699 if (!player->IsAlive())
700 {
701 player->ResurrectPlayer(1.0f);
702 player->SpawnCorpseBones();
703 }
704 else
705 //needed cause else in av some creatures will kill the players at the end
706 player->CombatStop();
707
708 // remove temporary currency bonus auras before rewarding player
711
712 uint32 winnerKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST);
713 uint32 loserKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST);
714
716 {
717 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PVPSTATS_PLAYER);
718 BattlegroundScoreMap::const_iterator score = PlayerScores.find(player->GetGUID());
719
720 stmt->setUInt32(0, battlegroundId);
721 stmt->setUInt64(1, player->GetGUID().GetCounter());
722 stmt->setBool (2, team == winner);
723 stmt->setUInt32(3, score->second->GetKillingBlows());
724 stmt->setUInt32(4, score->second->GetDeaths());
725 stmt->setUInt32(5, score->second->GetHonorableKills());
726 stmt->setUInt32(6, score->second->GetBonusHonor());
727 stmt->setUInt32(7, score->second->GetDamageDone());
728 stmt->setUInt32(8, score->second->GetHealingDone());
729 stmt->setUInt32(9, score->second->GetAttr(0));
730 stmt->setUInt32(10, score->second->GetAttr(1));
731 stmt->setUInt32(11, score->second->GetAttr(2));
732 stmt->setUInt32(12, score->second->GetAttr(3));
733 stmt->setUInt32(13, score->second->GetAttr(4));
734
735 CharacterDatabase.Execute(stmt);
736 }
737
738 // Reward winner team
739 if (team == winner)
740 {
741 if (BattlegroundPlayer const* bgPlayer = GetBattlegroundPlayerData(player->GetGUID()))
742 {
743 if (BattlegroundMgr::IsRandomBattleground(bgPlayer->queueTypeId.BattlemasterListId)
744 || BattlegroundMgr::IsBGWeekend(BattlegroundTypeId(bgPlayer->queueTypeId.BattlemasterListId)))
745 {
747 if (!player->GetRandomWinner())
748 {
749 player->SetRandomWinner(true);
750 // TODO: win honor xp
751 }
752 }
753 else
754 {
755 // TODO: loss honor xp
756 }
757 }
758
760 if (!guildAwarded)
761 {
762 guildAwarded = true;
763 if (ObjectGuid::LowType guildId = GetBgMap()->GetOwnerGuildId(player->GetBGTeam()))
764 {
765 if (Guild* guild = sGuildMgr->GetGuildById(guildId))
766 guild->UpdateCriteria(CriteriaType::WinBattleground, player->GetMapId(), 0, 0, nullptr, player);
767 }
768 }
769 }
770 else
771 {
772 if (BattlegroundPlayer const* bgPlayer = GetBattlegroundPlayerData(player->GetGUID()))
773 {
774 if (BattlegroundMgr::IsRandomBattleground(bgPlayer->queueTypeId.BattlemasterListId)
775 || BattlegroundMgr::IsBGWeekend(BattlegroundTypeId(bgPlayer->queueTypeId.BattlemasterListId)))
777 }
778 }
779
780 player->ResetAllPowers();
781 player->CombatStopWithPets(true);
782
783 BlockMovement(player);
784
785 player->SendDirectMessage(pvpMatchComplete.GetRawPacket());
786
788 }
789}
790
792{
794}
795
797{
798 //variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
799 uint32 maxLevel = std::min<uint32>(GetMaxLevel(), 80U);
800 return Trinity::Honor::hk_honor_at_level(maxLevel, float(kills));
801}
802
804{
805 // 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()
806 player->SetClientControl(player, false);
807}
808
810{
811 Team team = GetPlayerTeam(guid);
812 bool participant = false;
813 // Remove from lists/maps
814 BattlegroundPlayerMap::iterator itr = m_Players.find(guid);
816 if (itr != m_Players.end())
817 {
818 bgQueueTypeId = itr->second.queueTypeId;
819 UpdatePlayersCountByTeam(team, true); // -1 player
820 m_Players.erase(itr);
821 // check if the player was a participant of the match, or only entered through gm command (goname)
822 participant = true;
823 }
824
825 BattlegroundScoreMap::iterator itr2 = PlayerScores.find(guid);
826 if (itr2 != PlayerScores.end())
827 {
828 delete itr2->second; // delete player's score
829 PlayerScores.erase(itr2);
830 }
831
832 Player* player = ObjectAccessor::FindPlayer(guid);
833
834 if (player)
835 {
836 // should remove spirit of redemption
839
847
849
851
852 if (!player->IsAlive()) // resurrect on exit
853 {
854 player->ResurrectPlayer(1.0f);
855 player->SpawnCorpseBones();
856 }
857 }
858 else
859 {
860 CharacterDatabaseTransaction trans(nullptr);
861 Player::OfflineResurrect(guid, trans);
862 }
863
864 RemovePlayer(player, guid, team); // BG subclass specific code
865
866 if (participant) // if the player was a match participant, remove auras, calc rating, update queue
867 {
868 if (player)
869 {
870 player->ClearAfkReports();
871
872 // if arena, remove the specific arena auras
873 if (isArena())
874 {
875 // unsummon current and summon old pet if there was one and there isn't a current pet
876 player->RemovePet(nullptr, PET_SAVE_NOT_IN_SLOT);
878 }
879
880 if (SendPacket && bgQueueTypeId)
881 {
883 sBattlegroundMgr->BuildBattlegroundStatusNone(&battlefieldStatus, player, player->GetBattlegroundQueueIndex(*bgQueueTypeId), player->GetBattlegroundQueueJoinTime(*bgQueueTypeId));
884 player->SendDirectMessage(battlefieldStatus.Write());
885 }
886
887 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
888 if (bgQueueTypeId)
889 player->RemoveBattlegroundQueueId(*bgQueueTypeId);
890 }
891
892 // remove from raid group if player is member
893 if (Group* group = GetBgRaid(team))
894 {
895 if (!group->RemoveMember(guid)) // group was disbanded
896 SetBgRaid(team, nullptr);
897 }
899 //we should update battleground queue, but only if bg isn't ending
900 if (isBattleground() && GetStatus() < STATUS_WAIT_LEAVE && bgQueueTypeId)
901 {
902 // a player has left the battleground, so there are free slots -> add to queue
904 sBattlegroundMgr->ScheduleQueueUpdate(0, *bgQueueTypeId, GetBracketId());
905 }
906
907 // Let others know
909 playerLeft.Guid = guid;
910 SendPacketToTeam(team, playerLeft.Write(), player);
911 }
912
913 if (player)
914 {
915 // Do next only if found in battleground
917 // reset destination bg team
918 player->SetBGTeam(TEAM_OTHER);
919
920 // remove all criterias on bg leave
922
923 if (Transport)
924 player->TeleportToBGEntryPoint();
925
926 TC_LOG_DEBUG("bg.battleground", "Removed player {} from Battleground.", player->GetName());
927 }
928
929 //battleground object will be deleted next Battleground::Update() call
930}
931
932// this method is called when no players remains in battleground
934{
939 m_Events = 0;
940
941 if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
942 TC_LOG_ERROR("bg.battleground", "Battleground::Reset: one of the counters is not 0 (alliance: {}, horde: {}) for BG (map: {}, instance id: {})!",
944
946 m_InvitedHorde = 0;
947 m_InBGFreeSlotQueue = false;
948
949 m_Players.clear();
950
951 for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr)
952 delete itr->second;
953 PlayerScores.clear();
954
955 _playerPositions.clear();
956}
957
959{
961 // add BG to free slot queue
963
964 // add bg to update list
965 // This must be done here, because we need to have already invited some players when first BG::Update() method is executed
966 // and it doesn't matter if we call StartBattleground() more times, because m_Battlegrounds is a map and instance id never changes
967 sBattlegroundMgr->AddBattleground(this);
968
969 if (m_IsRated)
970 TC_LOG_DEBUG("bg.arena", "Arena match type: {} for Team1Id: {} - Team2Id: {} started.", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE]);
971}
972
974{
975 if (WorldSafeLocsEntry const* loc = GetExploitTeleportLocation(Team(player->GetBGTeam())))
976 player->TeleportTo(loc->Loc);
977}
978
980{
981 // remove afk from player
982 if (player->isAFK())
983 player->ToggleAFK();
984
985 // score struct must be created in inherited class
986
987 Team team = player->GetBGTeam();
988
990 bp.OfflineRemoveTime = 0;
991 bp.Team = team;
993 bp.queueTypeId = queueId;
994
995 bool const isInBattleground = IsPlayerInBattleground(player->GetGUID());
996 // Add to list/maps
997 m_Players[player->GetGUID()] = bp;
998
999 if (!isInBattleground)
1000 {
1001 UpdatePlayersCountByTeam(team, false); // +1 player
1002 PlayerScores[player->GetGUID()] = new BattlegroundScore(player->GetGUID(), player->GetBGTeam(), _pvpStatIds);
1003 }
1004
1006 playerJoined.Guid = player->GetGUID();
1007 SendPacketToTeam(team, playerJoined.Write(), player);
1008
1010 pvpMatchInitialize.MapID = GetMapId();
1011 switch (GetStatus())
1012 {
1013 case STATUS_NONE:
1014 case STATUS_WAIT_QUEUE:
1016 break;
1017 case STATUS_WAIT_JOIN:
1019 break;
1020 case STATUS_IN_PROGRESS:
1022 break;
1023 case STATUS_WAIT_LEAVE:
1025 break;
1026 default:
1027 break;
1028 }
1029
1031 {
1033 pvpMatchInitialize.Duration = std::chrono::duration_cast<Seconds>(duration);
1034 pvpMatchInitialize.StartTime = GameTime::GetSystemTime() - duration;
1035 }
1036
1037 pvpMatchInitialize.ArenaFaction = player->GetBGTeam() == HORDE ? PVP_TEAM_HORDE : PVP_TEAM_ALLIANCE;
1038 pvpMatchInitialize.BattlemasterListID = queueId.BattlemasterListId;
1039 pvpMatchInitialize.Registered = false;
1040 pvpMatchInitialize.AffectsRating = isRated();
1041
1042 player->SendDirectMessage(pvpMatchInitialize.Write());
1043
1045
1046 // add arena specific auras
1047 if (isArena())
1048 {
1050 player->DestroyConjuredItems(true);
1051 player->UnsummonPetTemporaryIfAny();
1052
1053 if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
1054 {
1055 player->CastSpell(player, SPELL_ARENA_PREPARATION, true);
1056 player->ResetAllPowers();
1057 }
1058 }
1059 else
1060 {
1061 if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
1062 player->CastSpell(player, SPELL_PREPARATION, true); // reduces all mana cost of spells.
1063
1064 if (bp.Mercenary)
1065 {
1066 if (bp.Team == HORDE)
1067 {
1068 player->CastSpell(player, SPELL_MERCENARY_HORDE_1);
1070 }
1071 else if (bp.Team == ALLIANCE)
1072 {
1073 player->CastSpell(player, SPELL_MERCENARY_ALLIANCE_1);
1075 }
1076 player->CastSpell(player, SPELL_MERCENARY_SHAPESHIFT);
1078 }
1079 }
1080
1081 // setup BG group membership
1083 AddOrSetPlayerToCorrectBgGroup(player, team);
1084}
1085
1086// this method adds player to his team's bg group, or sets his correct group if player is already in bg group
1088{
1089 ObjectGuid playerGuid = player->GetGUID();
1090 Group* group = GetBgRaid(team);
1091 if (!group) // first player joined
1092 {
1093 group = new Group;
1094 SetBgRaid(team, group);
1095 group->Create(player);
1096 Seconds countdownMaxForBGType = Seconds(StartDelayTimes[BG_STARTING_EVENT_FIRST] / 1000);
1098 group->StartCountdown(CountdownTimerType::Pvp, countdownMaxForBGType, _preparationStartTime);
1099 else
1100 group->StartCountdown(CountdownTimerType::Pvp, countdownMaxForBGType);
1101 }
1102 else // raid already exist
1103 {
1104 if (group->IsMember(playerGuid))
1105 {
1106 uint8 subgroup = group->GetMemberGroup(playerGuid);
1107 player->SetBattlegroundOrBattlefieldRaid(group, subgroup);
1108 }
1109 else
1110 {
1111 group->AddMember(player);
1112 if (Group* originalGroup = player->GetOriginalGroup())
1113 if (originalGroup->IsLeader(playerGuid))
1114 {
1115 group->ChangeLeader(playerGuid);
1116 group->SendUpdate();
1117 }
1118 }
1119 }
1120}
1121
1122// This method should be called when player logs into running battleground
1124{
1125 ObjectGuid guid = player->GetGUID();
1126 // player is correct pointer
1127 for (auto itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
1128 {
1129 if (*itr == guid)
1130 {
1131 m_OfflineQueue.erase(itr);
1132 break;
1133 }
1134 }
1135 m_Players[guid].OfflineRemoveTime = 0;
1137 // if battleground is starting, then add preparation aura
1138 // we don't have to do that, because preparation aura isn't removed when player logs out
1139}
1140
1141// This method should be called when player logs out from running battleground
1143{
1144 ObjectGuid guid = player->GetGUID();
1145 if (!IsPlayerInBattleground(guid)) // Check if this player really is in battleground (might be a GM who teleported inside)
1146 return;
1147
1148 // player is correct pointer, it is checked in WorldSession::LogoutPlayer()
1149 m_OfflineQueue.push_back(player->GetGUID());
1150 m_Players[guid].OfflineRemoveTime = GameTime::GetGameTime() + MAX_OFFLINE_TIME;
1152 {
1153 // drop flag and handle other cleanups
1154 RemovePlayer(player, guid, GetPlayerTeam(guid));
1155
1156 // 1 player is logging out, if it is the last alive, then end arena!
1157 if (isArena() && player->IsAlive())
1160 }
1161}
1162
1163// This method should be called only once ... it adds pointer to queue
1165{
1167 {
1168 sBattlegroundMgr->AddToBGFreeSlotQueue(this);
1169 m_InBGFreeSlotQueue = true;
1170 }
1171}
1172
1173// This method removes this battleground from free queue - it must be called when deleting battleground
1175{
1177 {
1178 sBattlegroundMgr->RemoveFromBGFreeSlotQueue(GetMapId(), m_InstanceID);
1179 m_InBGFreeSlotQueue = false;
1180 }
1181}
1182
1183// get the number of free slots for team
1184// returns the number how many players can join battleground to MaxPlayersPerTeam
1186{
1187 // if BG is starting and CONFIG_BATTLEGROUND_INVITATION_TYPE == BG_QUEUE_INVITATION_TYPE_NO_BALANCE, invite anyone
1190
1191 // 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
1192 uint32 otherTeamInvitedCount;
1193 uint32 thisTeamInvitedCount;
1194 uint32 otherTeamPlayersCount;
1195 uint32 thisTeamPlayersCount;
1196
1197 if (team == ALLIANCE)
1198 {
1199 thisTeamInvitedCount = GetInvitedCount(ALLIANCE);
1200 otherTeamInvitedCount = GetInvitedCount(HORDE);
1201 thisTeamPlayersCount = GetPlayersCountByTeam(ALLIANCE);
1202 otherTeamPlayersCount = GetPlayersCountByTeam(HORDE);
1203 }
1204 else
1205 {
1206 thisTeamInvitedCount = GetInvitedCount(HORDE);
1207 otherTeamInvitedCount = GetInvitedCount(ALLIANCE);
1208 thisTeamPlayersCount = GetPlayersCountByTeam(HORDE);
1209 otherTeamPlayersCount = GetPlayersCountByTeam(ALLIANCE);
1210 }
1212 {
1213 // difference based on ppl invited (not necessarily entered battle)
1214 // default: allow 0
1215 uint32 diff = 0;
1216
1217 // allow join one person if the sides are equal (to fill up bg to minPlayerPerTeam)
1218 if (otherTeamInvitedCount == thisTeamInvitedCount)
1219 diff = 1;
1220 // allow join more ppl if the other side has more players
1221 else if (otherTeamInvitedCount > thisTeamInvitedCount)
1222 diff = otherTeamInvitedCount - thisTeamInvitedCount;
1223
1224 // difference based on max players per team (don't allow inviting more)
1225 uint32 diff2 = (thisTeamInvitedCount < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - thisTeamInvitedCount : 0;
1226
1227 // difference based on players who already entered
1228 // default: allow 0
1229 uint32 diff3 = 0;
1230 // allow join one person if the sides are equal (to fill up bg minPlayerPerTeam)
1231 if (otherTeamPlayersCount == thisTeamPlayersCount)
1232 diff3 = 1;
1233 // allow join more ppl if the other side has more players
1234 else if (otherTeamPlayersCount > thisTeamPlayersCount)
1235 diff3 = otherTeamPlayersCount - thisTeamPlayersCount;
1236 // or other side has less than minPlayersPerTeam
1237 else if (thisTeamInvitedCount <= GetMinPlayersPerTeam())
1238 diff3 = GetMinPlayersPerTeam() - thisTeamInvitedCount + 1;
1239
1240 // return the minimum of the 3 differences
1241
1242 // min of diff and diff 2
1243 diff = std::min(diff, diff2);
1244 // min of diff, diff2 and diff3
1245 return std::min(diff, diff3);
1246 }
1247 return 0;
1248}
1249
1251{
1253}
1254
1256{
1257 return !isArena();
1258}
1259
1261{
1262 return GetPlayersSize() < GetMaxPlayers();
1263}
1264
1266{
1267 pvpLogData.Statistics.reserve(GetPlayerScoresSize());
1268 for (auto const& score : PlayerScores)
1269 {
1270 if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), score.first))
1271 {
1273 score.second->BuildPvPLogPlayerDataPacket(playerData);
1274
1275 playerData.IsInWorld = true;
1276 playerData.PrimaryTalentTree = AsUnderlyingType(player->GetPrimarySpecialization());
1277 playerData.Sex = player->GetGender();
1278 playerData.Race = player->GetRace();
1279 playerData.Class = player->GetClass();
1280 playerData.HonorLevel = player->GetHonorLevel();
1281
1282 pvpLogData.Statistics.push_back(playerData);
1283 }
1284 }
1285
1288}
1289
1291{
1293}
1294
1295bool Battleground::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor)
1296{
1297 BattlegroundScoreMap::const_iterator itr = PlayerScores.find(player->GetGUID());
1298 if (itr == PlayerScores.end()) // player not found...
1299 return false;
1300
1301 if (type == SCORE_BONUS_HONOR && doAddHonor && isBattleground())
1302 player->RewardHonor(nullptr, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
1303 else
1304 itr->second->UpdateScore(type, value);
1305
1306 return true;
1307}
1308
1309void Battleground::UpdatePvpStat(Player* player, uint32 pvpStatId, uint32 value)
1310{
1312 score->UpdatePvpStat(pvpStatId, value);
1313}
1314
1315bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 /*respawnTime*/, GOState goState)
1316{
1317 // If the assert is called, means that BgObjects must be resized!
1318 ASSERT(type < BgObjects.size());
1319
1320 Map* map = FindBgMap();
1321 if (!map)
1322 return false;
1323
1324 QuaternionData rot(rotation0, rotation1, rotation2, rotation3);
1325 // Temporally add safety check for bad spawns and send log (object rotations need to be rechecked in sniff)
1326 if (!rotation0 && !rotation1 && !rotation2 && !rotation3)
1327 {
1328 TC_LOG_DEBUG("bg.battleground", "Battleground::AddObject: gameoobject [entry: {}, object type: {}] for BG (map: {}) has zeroed rotation fields, "
1329 "orientation used temporally, but please fix the spawn", entry, type, GetMapId());
1330
1331 rot = QuaternionData::fromEulerAnglesZYX(o, 0.f, 0.f);
1332 }
1333
1334 // Must be created this way, adding to godatamap would add it to the base map of the instance
1335 // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
1336 // So we must create it specific for this instance
1337 GameObject* go = GameObject::CreateGameObject(entry, GetBgMap(), Position(x, y, z, o), rot, 255, goState);
1338 if (!go)
1339 {
1340 TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: {}) for BG (map: {}, instance id: {})!",
1341 entry, GetMapId(), m_InstanceID);
1342 return false;
1343 }
1344
1345/*
1346 uint32 guid = go->GetGUIDLow();
1347
1348 // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
1349 // iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed
1350 GameObjectData& data = sObjectMgr->NewGOData(guid);
1351
1352 data.id = entry;
1353 data.mapid = GetMapId();
1354 data.posX = x;
1355 data.posY = y;
1356 data.posZ = z;
1357 data.orientation = o;
1358 data.rotation0 = rotation0;
1359 data.rotation1 = rotation1;
1360 data.rotation2 = rotation2;
1361 data.rotation3 = rotation3;
1362 data.spawntimesecs = respawnTime;
1363 data.spawnMask = 1;
1364 data.animprogress = 100;
1365 data.go_state = 1;
1366*/
1367 // Add to world, so it can be later looked up from HashMapHolder
1368 if (!map->AddToMap(go))
1369 {
1370 delete go;
1371 return false;
1372 }
1373 BgObjects[type] = go->GetGUID();
1374 return true;
1375}
1376
1377bool Battleground::AddObject(uint32 type, uint32 entry, Position const& pos, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime /*= 0*/, GOState goState /*= GO_STATE_READY*/)
1378{
1379 return AddObject(type, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), rotation0, rotation1, rotation2, rotation3, respawnTime, goState);
1380}
1381
1382// Some doors aren't despawned so we cannot handle their closing in gameobject::update()
1383// It would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
1385{
1386 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1387 {
1388 // If doors are open, close it
1389 if (obj->getLootState() == GO_ACTIVATED && obj->GetGoState() != GO_STATE_READY)
1390 {
1391 obj->SetLootState(GO_READY);
1392 obj->SetGoState(GO_STATE_READY);
1393 }
1394 }
1395 else
1396 TC_LOG_ERROR("bg.battleground", "Battleground::DoorClose: door gameobject (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1397 type, BgObjects[type].ToString(), GetMapId(), m_InstanceID);
1398}
1399
1401{
1402 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1403 {
1404 obj->SetLootState(GO_ACTIVATED);
1405 obj->SetGoState(GO_STATE_ACTIVE);
1406 }
1407 else
1408 TC_LOG_ERROR("bg.battleground", "Battleground::DoorOpen: door gameobject (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1409 type, BgObjects[type].ToString(), GetMapId(), m_InstanceID);
1410}
1411
1413{
1414 GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]);
1415 if (!obj)
1416 {
1417 if (logError)
1418 TC_LOG_ERROR("bg.battleground", "Battleground::GetBGObject: gameobject (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1419 type, BgObjects[type].ToString(), GetMapId(), m_InstanceID);
1420 else
1421 TC_LOG_INFO("bg.battleground", "Battleground::GetBGObject: gameobject (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1422 type, BgObjects[type].ToString(), GetMapId(), m_InstanceID);
1423 }
1424 return obj;
1425}
1426
1428{
1429 Creature* creature = GetBgMap()->GetCreature(BgCreatures[type]);
1430 if (!creature)
1431 {
1432 if (logError)
1433 TC_LOG_ERROR("bg.battleground", "Battleground::GetBGCreature: creature (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1434 type, BgCreatures[type].ToString(), GetMapId(), m_InstanceID);
1435 else
1436 TC_LOG_INFO("bg.battleground", "Battleground::GetBGCreature: creature (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1437 type, BgCreatures[type].ToString(), GetMapId(), m_InstanceID);
1438 }
1439 return creature;
1440}
1441
1443{
1445}
1446
1448{
1449 m_Map = map;
1450 if (map)
1451 {
1452 _pvpStatIds = sDB2Manager.GetPVPStatIDsForMap(map->GetId());
1453 OnMapSet(map);
1454 }
1455 else
1456 _pvpStatIds = nullptr;
1457}
1458
1460{
1461 if (Map* map = FindBgMap())
1462 if (GameObject* obj = map->GetGameObject(BgObjects[type]))
1463 {
1464 if (respawntime)
1465 {
1466 obj->SetLootState(GO_JUST_DEACTIVATED);
1467
1468 if (GameObjectOverride const* goOverride = obj->GetGameObjectOverride())
1469 if (goOverride->Flags & GO_FLAG_NODESPAWN)
1470 {
1471 // This function should be called in GameObject::Update() but in case of
1472 // GO_FLAG_NODESPAWN flag the function is never called, so we call it here
1473 obj->SendGameObjectDespawn();
1474 }
1475 }
1476 else if (obj->getLootState() == GO_JUST_DEACTIVATED)
1477 {
1478 // Change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
1479 obj->SetLootState(GO_READY);
1480 }
1481 obj->SetRespawnTime(respawntime);
1482 map->AddToMap(obj);
1483 }
1484}
1485
1486Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId /*teamId = TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, Transport* transport)
1487{
1488 // If the assert is called, means that BgCreatures must be resized!
1489 ASSERT(type < BgCreatures.size());
1490
1491 Map* map = FindBgMap();
1492 if (!map)
1493 return nullptr;
1494
1495 if (!sObjectMgr->GetCreatureTemplate(entry))
1496 {
1497 TC_LOG_ERROR("bg.battleground", "Battleground::AddCreature: creature template (entry: {}) does not exist for BG (map: {}, instance id: {})!",
1498 entry, GetMapId(), m_InstanceID);
1499 return nullptr;
1500 }
1501
1502 if (transport)
1503 {
1504 if (Creature* creature = transport->SummonPassenger(entry, { x, y, z, o }, TEMPSUMMON_MANUAL_DESPAWN))
1505 {
1506 BgCreatures[type] = creature->GetGUID();
1507 return creature;
1508 }
1509
1510 return nullptr;
1511 }
1512
1513 Position pos = { x, y, z, o };
1514
1515 Creature* creature = Creature::CreateCreature(entry, map, pos);
1516 if (!creature)
1517 {
1518 TC_LOG_ERROR("bg.battleground", "Battleground::AddCreature: cannot create creature (entry: {}) for BG (map: {}, instance id: {})!",
1519 entry, GetMapId(), m_InstanceID);
1520 return nullptr;
1521 }
1522
1523 creature->SetHomePosition(pos);
1524
1525 if (!map->AddToMap(creature))
1526 {
1527 delete creature;
1528 return nullptr;
1529 }
1530
1531 BgCreatures[type] = creature->GetGUID();
1532
1533 if (respawntime)
1534 creature->SetRespawnDelay(respawntime);
1535
1536 return creature;
1537}
1538
1539Creature* Battleground::AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId /*= TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, Transport* transport)
1540{
1541 return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamId, respawntime, transport);
1542}
1543
1545{
1546 if (!BgCreatures[type])
1547 return true;
1548
1549 if (Creature* creature = GetBgMap()->GetCreature(BgCreatures[type]))
1550 {
1551 creature->AddObjectToRemoveList();
1552 BgCreatures[type].Clear();
1553 return true;
1554 }
1555
1556 TC_LOG_ERROR("bg.battleground", "Battleground::DelCreature: creature (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1557 type, BgCreatures[type].ToString(), GetMapId(), m_InstanceID);
1558 BgCreatures[type].Clear();
1559 return false;
1560}
1561
1563{
1564 if (!BgObjects[type])
1565 return true;
1566
1567 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1568 {
1569 obj->SetRespawnTime(0); // not save respawn time
1570 obj->Delete();
1571 BgObjects[type].Clear();
1572 return true;
1573 }
1574 TC_LOG_ERROR("bg.battleground", "Battleground::DelObject: gameobject (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1575 type, BgObjects[type].ToString(), GetMapId(), m_InstanceID);
1576 BgObjects[type].Clear();
1577 return false;
1578}
1579
1581{
1582 if (!BgObjects[type])
1583 return true;
1584
1585 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1586 {
1587 obj->RemoveFromWorld();
1588 BgObjects[type].Clear();
1589 return true;
1590 }
1591 TC_LOG_INFO("bg.battleground", "Battleground::RemoveObjectFromWorld: gameobject (type: {}, {}) not found for BG (map: {}, instance id: {})!",
1592 type, BgObjects[type].ToString(), GetMapId(), m_InstanceID);
1593 return false;
1594}
1595
1596bool Battleground::AddSpiritGuide(uint32 type, float x, float y, float z, float o, TeamId teamId /*= TEAM_NEUTRAL*/)
1597{
1599
1600 if (AddCreature(entry, type, x, y, z, o, teamId))
1601 return true;
1602
1603 TC_LOG_ERROR("bg.battleground", "Battleground::AddSpiritGuide: cannot create spirit guide (type: {}, entry: {}) for BG (map: {}, instance id: {})!",
1604 type, entry, GetMapId(), m_InstanceID);
1605 EndNow();
1606 return false;
1607}
1608
1609bool Battleground::AddSpiritGuide(uint32 type, Position const& pos, TeamId teamId /*= TEAM_NEUTRAL*/)
1610{
1611 return AddSpiritGuide(type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamId);
1612}
1613
1614void Battleground::SendMessageToAll(uint32 entry, ChatMsg msgType, Player const* source)
1615{
1616 if (!entry)
1617 return;
1618
1619 Trinity::TrinityStringChatBuilder builder(nullptr, msgType, entry, source);
1621 BroadcastWorker(localizer);
1622}
1623
1624void Battleground::PSendMessageToAll(uint32 entry, ChatMsg msgType, Player const* source, ...)
1625{
1626 if (!entry)
1627 return;
1628
1629 va_list ap;
1630 va_start(ap, source);
1631
1632 Trinity::TrinityStringChatBuilder builder(nullptr, msgType, entry, source, &ap);
1634 BroadcastWorker(localizer);
1635
1636 va_end(ap);
1637}
1638
1640{
1641 _playerPositions.push_back(position);
1642}
1643
1645{
1646 auto itr = std::remove_if(_playerPositions.begin(), _playerPositions.end(), [guid](WorldPackets::Battleground::BattlegroundPlayerPosition const& playerPosition)
1647 {
1648 return playerPosition.Guid == guid;
1649 });
1650
1651 _playerPositions.erase(itr, _playerPositions.end());
1652}
1653
1655{
1659}
1660
1662{
1663 // Keep in mind that for arena this will have to be changed a bit
1664
1665 // Add +1 deaths
1666 UpdatePlayerScore(victim, SCORE_DEATHS, 1);
1667 // Add +1 kills to group and +1 killing_blows to killer
1668 if (killer)
1669 {
1670 // Don't reward credit for killing ourselves, like fall damage of hellfire (warlock)
1671 if (killer == victim)
1672 return;
1673
1674 Team killerTeam = GetPlayerTeam(killer->GetGUID());
1675
1678
1679 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1680 {
1681 Player* creditedPlayer = ObjectAccessor::FindPlayer(itr->first);
1682 if (!creditedPlayer || creditedPlayer == killer)
1683 continue;
1684
1685 if (itr->second.Team == killerTeam && creditedPlayer->IsAtGroupRewardDistance(victim))
1686 UpdatePlayerScore(creditedPlayer, SCORE_HONORABLE_KILLS, 1);
1687 }
1688 }
1689
1690 if (!isArena())
1691 {
1692 // To be able to remove insignia -- ONLY IN Battlegrounds
1694 RewardXPAtKill(killer, victim);
1695 }
1696}
1697
1698// Return the player's team based on battlegroundplayer info
1699// Used in same faction arena matches mainly
1701{
1702 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1703 if (itr != m_Players.end())
1704 return itr->second.Team;
1705 return TEAM_OTHER;
1706}
1707
1709{
1710 return team ? ((team == ALLIANCE) ? HORDE : ALLIANCE) : TEAM_OTHER;
1711}
1712
1714{
1715 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1716 if (itr != m_Players.end())
1717 return true;
1718 return false;
1719}
1720
1722{
1723 auto itr = m_Players.find(guid);
1724 if (itr != m_Players.end())
1725 return itr->second.Mercenary;
1726 return false;
1727}
1728
1730{
1732 return;
1733
1734 BlockMovement(player);
1735
1737 BuildPvPLogDataPacket(pvpMatchStatistics.Data);
1738 player->SendDirectMessage(pvpMatchStatistics.Write());
1739}
1740
1742{
1743 int count = 0;
1744 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1745 {
1746 if (itr->second.Team == team)
1747 {
1748 Player* player = ObjectAccessor::FindPlayer(itr->first);
1749 if (player && player->IsAlive())
1750 ++count;
1751 }
1752 }
1753 return count;
1754}
1755
1757{
1758 for (uint32 i = 0; i < BgObjects.size(); ++i)
1759 if (BgObjects[i] == guid)
1760 return i;
1761 TC_LOG_ERROR("bg.battleground", "Battleground::GetObjectType: player used gameobject ({}) which is not in internal data for BG (map: {}, instance id: {}), cheating?",
1762 guid.ToString(), GetMapId(), m_InstanceID);
1763 return -1;
1764}
1765
1767{
1768 Group*& old_raid = team == ALLIANCE ? m_BgRaids[TEAM_ALLIANCE] : m_BgRaids[TEAM_HORDE];
1769 if (old_raid)
1770 old_raid->SetBattlegroundGroup(nullptr);
1771 if (bg_raid)
1772 bg_raid->SetBattlegroundGroup(this);
1773 old_raid = bg_raid;
1774}
1775
1777{
1778 return sObjectMgr->GetClosestGraveyard(*player, GetPlayerTeam(player->GetGUID()), player);
1779}
1780
1781void Battleground::TriggerGameEvent(uint32 gameEventId, WorldObject* source /*= nullptr*/, WorldObject* target /*= nullptr*/)
1782{
1783 ProcessEvent(target, gameEventId, source);
1784 GameEvents::TriggerForMap(gameEventId, GetBgMap(), source, target);
1785 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
1786 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
1787 GameEvents::TriggerForPlayer(gameEventId, player);
1788}
1789
1791{
1792 _pvpDifficultyEntry = bracketEntry;
1793}
1794
1796{
1797 if (sWorld->getBoolConfig(CONFIG_BG_XP_FOR_KILL) && killer && victim)
1798 {
1799 Player* killers[] = { killer };
1800 KillRewarder(Trinity::IteratorPair(std::begin(killers), std::end(killers)), victim, true).Reward();
1801 }
1802}
1803
1805{
1806 if (teamId == TEAM_ALLIANCE || teamId == TEAM_HORDE)
1807 return m_TeamScores[teamId];
1808
1809 TC_LOG_ERROR("bg.battleground", "GetTeamScore with wrong Team {} for BG {}", teamId, GetTypeID());
1810 return 0;
1811}
1812
1813void Battleground::HandleAreaTrigger(Player* player, uint32 trigger, bool /*entered*/)
1814{
1815 TC_LOG_DEBUG("bg.battleground", "Unhandled AreaTrigger {} in Battleground {}. Player coords (x: {}, y: {}, z: {})",
1816 trigger, player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
1817}
1818
1819char const* Battleground::GetName() const
1820{
1821 return _battlegroundTemplate->BattlemasterEntry->Name[sWorld->GetDefaultDbcLocale()];
1822}
1823
1825{
1826 return _battlegroundTemplate->Id;
1827}
1828
1830{
1832}
1833
1835{
1836 return uint8(GetMinLevel() / 5) - 1; // 10 - 1, 15 - 2, 20 - 3, etc.
1837}
1838
1840{
1841 return GetMaxPlayersPerTeam() * 2;
1842}
1843
1845{
1846 return GetMinPlayersPerTeam() * 2;
1847}
1848
1850{
1853
1855}
1856
1858{
1861
1863}
1864
1866{
1867 if (isArena())
1868 {
1869 switch (GetArenaType())
1870 {
1871 case ARENA_TYPE_2v2:
1872 return 2;
1873 case ARENA_TYPE_3v3:
1874 return 3;
1875 case ARENA_TYPE_5v5: // removed
1876 return 5;
1877 default:
1878 break;
1879 }
1880 }
1881
1883}
1884
1886{
1888}
#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_CREATURE_ENTRY_H_SPIRITGUIDE
Definition: Battleground.h:96
@ BG_CREATURE_ENTRY_A_SPIRITGUIDE
Definition: Battleground.h:95
@ 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:538
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:32
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
#define ASSERT
Definition: Errors.h:68
@ GO_ACTIVATED
Definition: GameObject.h:158
@ GO_READY
Definition: GameObject.h:157
@ GO_JUST_DEACTIVATED
Definition: GameObject.h:159
#define sGuildMgr
Definition: GuildMgr.h:70
@ TEMP_ENCHANTMENT_SLOT
Definition: ItemDefines.h:180
@ LANG_BG_STARTED_ANNOUNCE_WORLD
Definition: Language.h:707
@ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
Definition: Language.h:740
@ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS
Definition: Language.h:741
#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
@ TEMPSUMMON_MANUAL_DESPAWN
Definition: ObjectDefines.h:70
#define sObjectMgr
Definition: ObjectMgr.h:1946
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:467
@ GENDER_MALE
constexpr BattlegroundQueueTypeId BATTLEGROUND_QUEUE_NONE
TeamId
@ TEAM_NEUTRAL
@ TEAM_ALLIANCE
@ TEAM_HORDE
Team
@ TEAM_OTHER
@ ALLIANCE
@ HORDE
@ SPELL_ATTR0_NO_IMMUNITIES
BattlegroundTypeId
@ BATTLEGROUND_TYPE_NONE
@ GO_FLAG_NODESPAWN
@ PVP_TEAM_NEUTRAL
@ PVP_TEAM_HORDE
@ PVP_TEAM_ALLIANCE
ChatMsg
@ CHAT_MSG_SYSTEM
@ CHAT_MSG_BG_SYSTEM_NEUTRAL
GOState
@ GO_STATE_READY
@ GO_STATE_ACTIVE
@ 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:170
T AddPct(T &base, U pct)
Definition: Util.h:85
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
#define sWorldStateMgr
Definition: WorldStateMgr.h:50
static Summons Group[]
Definition: boss_urom.cpp:83
bool IsPositive() const
Definition: SpellAuras.h:84
Aura * GetBase() const
Definition: SpellAuras.h:78
int32 GetDuration() const
Definition: SpellAuras.h:173
bool HasEffectType(AuraType type) const
SpellInfo const * GetSpellInfo() const
Definition: SpellAuras.h:134
bool IsPermanent() const
Definition: SpellAuras.h:178
void SetUnload()
Definition: Map.cpp:3440
void SetBG(Battleground *bg)
Definition: Map.h:915
static bool IsRandomBattleground(uint32 battlemasterListId)
static bool IsBGWeekend(BattlegroundTypeId bgTypeId)
uint32 m_InvitedAlliance
Definition: Battleground.h:593
void UpdatePlayersCountByTeam(Team team, bool remove)
Definition: Battleground.h:395
void SetRemainingTime(uint32 Time)
Definition: Battleground.h:310
uint32 m_ArenaTeamMMR[PVP_TEAMS_COUNT]
Definition: Battleground.h:605
bool m_SetDeleteThis
Definition: Battleground.h:578
WorldSafeLocsEntry const * GetTeamStartPosition(TeamId teamId) const
uint32 GetMapId() const
virtual Team GetPrematureWinner()
virtual Creature * AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId teamId=TEAM_NEUTRAL, uint32 respawntime=0, Transport *transport=nullptr)
PvPTeamId _winnerTeamId
Definition: Battleground.h:580
void SendPacketToTeam(Team team, WorldPacket const *packet, Player *except=nullptr) const
char const * GetName() const
PVPDifficultyEntry const * _pvpDifficultyEntry
Definition: Battleground.h:612
void SendPacketToAll(WorldPacket const *packet) const
void RemovePlayerPosition(ObjectGuid guid)
uint32 GetMinLevel() const
void ModifyStartDelayTime(int diff)
Definition: Battleground.h:316
void SetElapsedTime(uint32 Time)
Definition: Battleground.h:309
virtual void HandleKillPlayer(Player *player, Player *killer)
uint32 m_ArenaTeamIds[PVP_TEAMS_COUNT]
Definition: Battleground.h:603
void _ProcessPlayerPositionBroadcast(uint32 diff)
virtual bool SetupBattleground()
Definition: Battleground.h:266
void AddOrSetPlayerToCorrectBgGroup(Player *player, Team team)
void DoorOpen(uint32 type)
std::deque< ObjectGuid > m_OfflineQueue
Definition: Battleground.h:588
uint32 GetMinPlayersPerTeam() const
void PlayerAddedToBGCheckIfBGIsRunning(Player *player)
virtual void OnMapSet(BattlegroundMap *map)
Definition: Battleground.h:499
bool DelCreature(uint32 type)
uint8 GetArenaType() const
Definition: Battleground.h:298
BattlegroundPlayerMap m_Players
Definition: Battleground.h:557
void SpawnBGObject(uint32 type, uint32 respawntime)
Player * _GetPlayerForTeam(Team team, BattlegroundPlayerMap::const_iterator itr, char const *context) const
uint32 GetMaxPlayersPerTeam() const
time_t _preparationStartTime
Definition: Battleground.h:618
virtual void Reset()
uint32 m_ValidStartPositionTimer
Definition: Battleground.h:574
virtual bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime=0, GOState goState=GO_STATE_READY)
int32 m_StartDelayTime
Definition: Battleground.h:581
Group * GetBgRaid(Team team) const
Definition: Battleground.h:382
BattlegroundTemplate const * _battlegroundTemplate
Definition: Battleground.h:611
uint32 GetInvitedCount(Team team) const
Definition: Battleground.h:325
void SetWinner(PvPTeamId winnerTeamId)
Definition: Battleground.h:313
uint8 GetUniqueBracketId() const
void PlaySoundToAll(uint32 SoundID)
uint32 m_ClientInstanceID
Definition: Battleground.h:571
int32 GetObjectType(ObjectGuid guid)
void AddToBGFreeSlotQueue()
uint32 GetTeamScore(TeamId teamId) const
GuidVector BgObjects
Definition: Battleground.h:443
uint32 GetPlayerScoresSize() const
Definition: Battleground.h:338
void DecreaseInvitedCount(Team team)
Definition: Battleground.h:322
Creature * GetBGCreature(uint32 type, bool logError=true)
bool isRated() const
Definition: Battleground.h:331
void RewardHonorToTeam(uint32 Honor, Team team)
void SetBgMap(BattlegroundMap *map)
uint32 GetMaxPlayers() const
BattlegroundMap * GetBgMap() const
virtual void PostUpdateImpl(uint32)
Post-update hook.
Definition: Battleground.h:542
PvPTeamId GetWinner() const
Definition: Battleground.h:299
Battleground(BattlegroundTemplate const *battlegroundTemplate)
virtual void RemovePlayer(Player *, ObjectGuid, uint32)
Definition: Battleground.h:554
BattlegroundMap * FindBgMap() const
Definition: Battleground.h:351
void BlockMovement(Player *player)
uint32 GetRemainingTime() const
Definition: Battleground.h:287
Player * _GetPlayer(ObjectGuid guid, bool offlineRemove, char const *context) const
void StartBattleground()
virtual bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, TeamId teamId=TEAM_NEUTRAL)
BattlegroundTypeId GetTypeID() const
void DoorClose(uint32 type)
void Update(uint32 diff)
bool m_PrematureCountDown
Definition: Battleground.h:583
uint32 m_PlayersCount[PVP_TEAMS_COUNT]
Definition: Battleground.h:600
Group * m_BgRaids[PVP_TEAMS_COUNT]
Definition: Battleground.h:597
uint32 m_PrematureCountDownTimer
Definition: Battleground.h:584
void RemoveAuraOnTeam(uint32 SpellID, Team team)
void ProcessEvent(WorldObject *, uint32, WorldObject *) override
Definition: Battleground.h:424
virtual WorldSafeLocsEntry const * GetExploitTeleportLocation(Team)
Definition: Battleground.h:431
void TriggerGameEvent(uint32 gameEventId, WorldObject *source=nullptr, WorldObject *target=nullptr) override
int32 m_TeamScores[PVP_TEAMS_COUNT]
Definition: Battleground.h:565
void PSendMessageToAll(uint32 entry, ChatMsg type, Player const *source,...)
void SendMessageToAll(uint32 entry, ChatMsg type, Player const *source=nullptr)
void EventPlayerLoggedOut(Player *player)
GuidVector BgCreatures
Definition: Battleground.h:444
virtual WorldSafeLocsEntry const * GetClosestGraveyard(Player *player)
void SendChatMessage(Creature *source, uint8 textId, WorldObject *target=nullptr)
BattlegroundPlayer const * GetBattlegroundPlayerData(ObjectGuid const &playerGuid) const
Definition: Battleground.h:489
void RewardXPAtKill(Player *killer, Player *victim)
bool m_InBGFreeSlotQueue
Definition: Battleground.h:577
Team GetOtherTeam(Team team) const
static TeamId GetTeamIndexByTeamId(Team team)
Definition: Battleground.h:392
void UpdateWorldState(int32 worldStateId, int32 value, bool hidden=false)
void SetStatus(BattlegroundStatus Status)
Definition: Battleground.h:307
bool IsPlayerMercenaryInBattleground(ObjectGuid guid) const
virtual void StartingEventCloseDoors()
Definition: Battleground.h:271
void BroadcastWorker(Do &_do)
virtual void EndBattleground(Team winner)
bool IsPlayerInBattleground(ObjectGuid guid) const
BattlegroundStartTimeIntervals StartDelayTimes[BG_STARTING_EVENT_COUNT]
Definition: Battleground.h:561
bool isArena() const
uint32 m_LastPlayerPositionBroadcast
Definition: Battleground.h:585
void SendBroadcastText(uint32 id, ChatMsg msgType, WorldObject const *target=nullptr)
BattlegroundScore const * GetBattlegroundScore(Player *player) const
uint32 m_InstanceID
Definition: Battleground.h:569
void AddPlayerPosition(WorldPackets::Battleground::BattlegroundPlayerPosition const &position)
bool DelObject(uint32 type)
void PlaySoundToTeam(uint32 SoundID, Team team)
uint32 m_ResetStatTimer
Definition: Battleground.h:573
void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, Team team)
BattlegroundPlayerMap const & GetPlayers() const
Definition: Battleground.h:334
int32 GetStartDelayTime() const
Definition: Battleground.h:297
BattlegroundScoreMap PlayerScores
Definition: Battleground.h:552
virtual void StartingEventOpenDoors()
Definition: Battleground.h:272
float GetStartMaxDist() const
bool isBattleground() const
std::vector< WorldPackets::Battleground::BattlegroundPlayerPosition > _playerPositions
Definition: Battleground.h:615
virtual void AddPlayer(Player *player, BattlegroundQueueTypeId queueId)
BattlegroundStatus GetStatus() const
Definition: Battleground.h:284
bool HasFreeSlots() const
virtual bool UpdatePlayerScore(Player *player, uint32 type, uint32 value, bool doAddHonor=true)
uint8 m_ArenaType
Definition: Battleground.h:576
uint32 GetPlayersCountByTeam(Team team) const
Definition: Battleground.h:393
virtual void HandleAreaTrigger(Player *, uint32, bool)
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:529
uint32 GetScriptId() const
virtual ~Battleground()
virtual void CheckWinConditions()
Definition: Battleground.h:403
void EventPlayerLoggedIn(Player *player)
void _CheckSafePositions(uint32 diff)
void _ProcessJoin(uint32 diff)
BattlegroundBracketId GetBracketId() const
std::unordered_set< uint32 > const * _pvpStatIds
Definition: Battleground.h:613
Team GetPlayerTeam(ObjectGuid guid) const
uint32 m_InvitedHorde
Definition: Battleground.h:594
bool RemoveObjectFromWorld(uint32 type)
uint32 GetBonusHonorFromKill(uint32 kills) const
void UpdatePvpStat(Player *player, uint32 pvpStatId, uint32 value)
uint32 GetMaxLevel() const
uint32 GetElapsedTime() const
Definition: Battleground.h:286
void CastSpellOnTeam(uint32 SpellID, Team team)
void SetBracket(PVPDifficultyEntry const *bracketEntry)
uint32 GetPlayersSize() const
Definition: Battleground.h:335
uint32 m_StartTime
Definition: Battleground.h:572
void SetBgRaid(Team team, Group *bg_raid)
void SetStartDelayTime(int Time)
Definition: Battleground.h:317
virtual void BuildPvPLogDataPacket(WorldPackets::Battleground::PVPMatchStatistics &pvpLogData) const
virtual void RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool SendPacket)
GameObject * GetBGObject(uint32 type, bool logError=true)
BattlegroundMap * m_Map
Definition: Battleground.h:608
uint32 GetMinPlayers() const
void _ProcessLeave(uint32 diff)
BattlegroundStatus m_Status
Definition: Battleground.h:570
uint32 StartMessageIds[BG_STARTING_EVENT_COUNT]
Definition: Battleground.h:563
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:371
static Creature * CreateCreature(uint32 entry, Map *map, Position const &pos, uint32 vehId=0)
Definition: Creature.cpp:1177
void SetRespawnDelay(uint32 delay)
Definition: Creature.h:338
Class used to access individual fields of database query result.
Definition: Field.h:90
uint64 GetUInt64() const
Definition: Field.cpp:78
static GameObject * CreateGameObject(uint32 entry, Map *map, Position const &pos, QuaternionData const &rotation, uint32 animProgress, GOState goState, uint32 artKit=0)
Definition: Group.h:197
uint8 GetMemberGroup(ObjectGuid guid) const
Definition: Group.cpp:1742
bool AddMember(Player *player)
Definition: Group.cpp:426
void SendUpdate()
Definition: Group.cpp:834
void ChangeLeader(ObjectGuid guid)
Definition: Group.cpp:688
void SetBattlegroundGroup(Battleground *bg)
Definition: Group.cpp:1750
bool IsMember(ObjectGuid guid) const
Definition: Group.cpp:1695
bool Create(Player *leader)
Definition: Group.cpp:141
void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional< time_t > startTime={ })
Definition: Group.cpp:1426
Definition: Guild.h:329
Definition: Map.h:189
bool AddToMap(T *)
Definition: Map.cpp:550
void UnloadAll()
Definition: Map.cpp:1684
GameObject * GetGameObject(ObjectGuid const &guid)
Definition: Map.cpp:3489
uint32 GetId() const
Definition: Map.cpp:3228
Creature * GetCreature(ObjectGuid const &guid)
Definition: Map.cpp:3479
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
std::string ToString() const
Definition: ObjectGuid.cpp:554
uint64 LowType
Definition: ObjectGuid.h:278
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void SetClientControl(Unit *target, bool allowMove)
Definition: Player.cpp:25739
void SetBGTeam(Team team)
Definition: Player.cpp:23603
void SetPlayerFlagEx(PlayerFlagsEx flags)
Definition: Player.h:2743
bool HasPlayerFlagEx(PlayerFlagsEx flags) const
Definition: Player.h:2742
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId, BattlegroundQueueTypeId queueId)
Definition: Player.cpp:25030
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
void ClearAfkReports()
Definition: Player.h:2427
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options=TELE_TO_NONE, Optional< uint32 > instanceId={})
Definition: Player.cpp:1250
static void OfflineResurrect(ObjectGuid const &guid, CharacterDatabaseTransaction trans)
Definition: Player.cpp:4529
void RemovePlayerFlagEx(PlayerFlagsEx flags)
Definition: Player.h:2744
void SpawnCorpseBones(bool triggerSave=true)
Definition: Player.cpp:4598
Group * GetOriginalGroup() const
Definition: Player.h:2625
uint32 GetBattlegroundQueueJoinTime(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:24984
bool IsMercenaryForBattlegroundQueueType(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25098
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition: Player.cpp:25673
void DestroyConjuredItems(bool update)
Definition: Player.cpp:12560
void UnsummonPetTemporaryIfAny()
Definition: Player.cpp:27165
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition: Player.cpp:25061
bool GetRandomWinner() const
Definition: Player.h:2434
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
Definition: Player.cpp:26767
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition: Player.cpp:21537
bool TeleportToBGEntryPoint()
Definition: Player.cpp:1496
void ToggleAFK()
Definition: Player.cpp:1214
uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
Definition: Player.cpp:25009
void ResetAllPowers()
Definition: Player.cpp:1903
bool RewardHonor(Unit *victim, uint32 groupsize, int32 honor=-1, bool pvptoken=false)
Definition: Player.cpp:6726
bool isAFK() const
Definition: Player.h:1156
Team GetEffectiveTeam() const
Definition: Player.h:2239
void FailCriteria(CriteriaFailEvent condition, int32 failAsset)
Definition: Player.cpp:26761
void ResummonPetTemporaryUnSummonedIfAny()
Definition: Player.cpp:27180
Team GetBGTeam() const
Definition: Player.cpp:23609
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition: Player.cpp:25987
ReputationMgr & GetReputationMgr()
Definition: Player.h:2251
void RemoveArenaEnchantments(EnchantmentSlot slot)
Definition: Player.cpp:13500
void SetRandomWinner(bool isWinner)
Definition: Player.cpp:28999
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition: Player.cpp:4408
void setUInt8(const uint8 index, const uint8 value)
void setBool(const uint8 index, const bool value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt64(const uint8 index, const uint64 value)
bool ModifyReputation(FactionEntry const *factionEntry, int32 standing, bool spillOverOnly=false, bool noSpillover=false)
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:449
TempSummon * SummonPassenger(uint32 entry, Position const &pos, TempSummonType summonType, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, Unit *summoner=nullptr, uint32 spellId=0, uint32 vehId=0)
Temporarily summons a creature as passenger on this transport.
Definition: Transport.cpp:409
Utility class to enable range for loop syntax for multimap.equal_range uses.
Definition: IteratorPair.h:32
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3812
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition: Unit.cpp:5827
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3685
void AtEndOfEncounter(EncounterType type)
Definition: Unit.cpp:536
bool IsAlive() const
Definition: Unit.h:1164
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4674
int32 GetTotalAuraModifier(AuraType auraType) const
Definition: Unit.cpp:4929
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
Definition: Unit.cpp:4101
int32 GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition: Unit.cpp:4989
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:833
void CombatStopWithPets(bool includingCast=false)
Definition: Unit.cpp:5855
constexpr uint32 GetMapId() const
Definition: Position.h:201
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
std::string const & GetName() const
Definition: Object.h:555
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:931
@ CONFIG_BG_REWARD_LOSER_HONOR_LAST
Definition: World.h:412
@ CONFIG_BATTLEGROUND_INVITATION_TYPE
Definition: World.h:340
@ CONFIG_BG_REWARD_WINNER_HONOR_FIRST
Definition: World.h:409
@ CONFIG_BG_REWARD_LOSER_HONOR_FIRST
Definition: World.h:411
@ CONFIG_BG_REWARD_WINNER_HONOR_LAST
Definition: World.h:410
@ CONFIG_BG_XP_FOR_KILL
Definition: World.h:140
@ CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE
Definition: World.h:139
@ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE
Definition: World.h:137
TC_GAME_API uint32 GetId(std::string_view username)
TC_GAME_API void TriggerForMap(uint32 gameEventId, Map *map, WorldObject *source=nullptr, WorldObject *target=nullptr)
TC_GAME_API void TriggerForPlayer(uint32 gameEventId, Player *source)
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition: GameTime.cpp:54
time_t GetGameTime()
Definition: GameTime.cpp:44
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
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)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:29
uint32 hk_honor_at_level(uint8 level, float multiplier=1.0f)
Definition: Formulas.h:58
std::string ToString(Type &&val, Params &&... params)
constexpr std::size_t size()
Definition: UpdateField.h:796
BattlegroundQueueTypeId queueTypeId
Definition: Battleground.h:176
BattlegroundTypeId Id
uint8 GetMinLevel() const
BattlemasterListEntry const * BattlemasterEntry
uint16 GetMaxPlayersPerTeam() const
WorldSafeLocsEntry const * StartLocation[PVP_TEAMS_COUNT]
uint16 GetMinPlayersPerTeam() const
uint8 GetMaxLevel() const
LocalizedString Name
Definition: DB2Structure.h:501
std::array< int16, 16 > MapID
Definition: DB2Structure.h:517
BattlegroundBracketId GetBracketId() const
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr float GetExactDistSq(float x, float y, float z) const
Definition: Position.h:110
constexpr float GetOrientation() const
Definition: Position.h:79
constexpr float GetPositionZ() const
Definition: Position.h:78
static QuaternionData fromEulerAnglesZYX(float Z, float Y, float X)
Definition: GameObject.cpp:118
std::vector< PVPMatchPlayerStatistics > Statistics
WorldLocation Loc
Definition: ObjectMgr.h:835