Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Battleground.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ArenaTeam.h"
7#include "ArenaTeamMgr.h"
8#include "Battleground.h"
9#include "BattlegroundMgr.h"
10#include "BattlePetMgr.h"
11#include "Chat.h"
12#include "Creature.h"
13#include "Formulas.h"
14#include "GridNotifiersImpl.h"
15#include "Group.h"
16#include "Guild.h"
17#include "GuildMgr.h"
18#include "MapManager.h"
19#include "Object.h"
20#include "ObjectMgr.h"
21#include "Player.h"
22#include "ReputationMgr.h"
23#include "SpellAuraEffects.h"
24#include "SpellAuras.h"
25#include "Util.h"
26#include "World.h"
27#include "WorldPacket.h"
28
29namespace Skyfire
30{
32 {
33 public:
34 BattlegroundChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, Player* const target = NULL, va_list* args = NULL)
35 : _msgtype(msgtype), _textId(textId), _source(source), _target(target), _args(args) { }
36
38 {
39 char const* text = sObjectMgr->GetSkyFireString(_textId, loc_idx);
40 if (_args)
41 {
42 // we need copy va_list before use or original va_list will corrupted
43 va_list ap;
44 va_copy(ap, *_args);
45
46 char str[2048];
47 vsnprintf(str, sizeof(str), text, ap);
48 va_end(ap);
49
50 do_helper(data, &str[0]);
51 }
52 else
53 do_helper(data, text);
54 }
55
56 private:
57 void do_helper(WorldPacket& data, char const* text)
58 {
60 }
61
66 va_list* _args;
67 };
68
70 {
71 public:
72 Battleground2ChatBuilder(ChatMsg msgtype, int32 textId, int32 arg1, int32 arg2, Player const* source = NULL, Player const* target = NULL)
73 : _msgtype(msgtype), _textId(textId), _source(source), _target(target), _arg1(arg1), _arg2(arg2) { }
74
76 {
77 char const* text = sObjectMgr->GetSkyFireString(_textId, loc_idx);
78 char const* arg1str = _arg1 ? sObjectMgr->GetSkyFireString(_arg1, loc_idx) : "";
79 char const* arg2str = _arg2 ? sObjectMgr->GetSkyFireString(_arg2, loc_idx) : "";
80
81 char str[2048];
82 snprintf(str, sizeof(str), text, arg1str, arg2str);
83
85 }
86
87 private:
94 };
95} // namespace Skyfire
96
97template<class Do>
99{
100 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
101 if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
102 _do(player);
103}
104
111{
114
117
120
123
126
129
132
133 m_BgRaids[TEAM_ALLIANCE] = NULL;
134 m_BgRaids[TEAM_HORDE] = NULL;
135
138
141
146 //we must set to some default existing values
151}
152
154{
155 // remove objects and creatures
156 // (this is done automatically in mapmanager update, when the instance is reset after the reset time)
157 uint32 size = uint32(BgCreatures.size());
158 for (uint32 i = 0; i < size; ++i)
159 DelCreature(i);
160
161 size = uint32(BgObjects.size());
162 for (uint32 i = 0; i < size; ++i)
163 DelObject(i);
164
165 sBattlegroundMgr->RemoveBattleground(GetTypeID(), GetInstanceID());
166 // unload map
167 if (m_Map)
168 {
169 m_Map->SetUnload();
170 //unlink to prevent crash, always unlink all pointer reference before destruction
171 m_Map->SetBG(NULL);
172 m_Map = NULL;
173 }
174 // remove from bg free slot queue
176
177 for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr)
178 delete itr->second;
179}
180
182{
183 if (!PreUpdateImpl(diff))
184 return;
185
186 if (!GetPlayersSize())
187 {
188 //BG is empty
189 // if there are no players invited, delete BG
190 // this will delete arena or bg object, where any player entered
191 // [[ but if you use battleground object again (more battles possible to be played on 1 instance)
192 // then this condition should be removed and code:
193 // if (!GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
194 // this->AddToFreeBGObjectsQueue(); // not yet implemented
195 // should be used instead of current
196 // ]]
197 // Battleground Template instance cannot be updated, because it would be deleted
199 m_SetDeleteThis = true;
200 return;
201 }
202
203 switch (GetStatus())
204 {
205 case STATUS_WAIT_JOIN:
206 if (GetPlayersSize())
207 {
209 {
210 _ProcessJoin(diff);
212 }
213 }
214 break;
217 // after 47 minutes without one team losing, the arena closes with no winner and no rating change
218 if (isArena())
219 {
220 if (GetElapsedTime() >= 47 * MINUTE * IN_MILLISECONDS)
221 {
224 return;
225 }
226 }
227 else
228 {
229 _ProcessRessurect(diff);
231 _ProcessProgress(diff);
232 else if (m_PrematureCountDown)
233 m_PrematureCountDown = false;
234 }
235 break;
237 _ProcessLeave(diff);
238 break;
239 default:
240 break;
241 }
242
243 // Update start time and reset stats timer
245 return;
246
249 {
250 m_ResetStatTimer += diff;
251 m_CountdownTimer += diff;
252 }
253
254 PostUpdateImpl(diff);
255}
256
258{
259 float maxDist = GetStartMaxDist();
260 if (!maxDist)
261 return;
262
265 {
267
268 Position pos;
269 float x, y, z, o;
270 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
271 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
272 {
273 player->GetPosition(&pos);
274 GetTeamStartLoc(player->GetBGTeam(), x, y, z, o);
275 if (pos.GetExactDistSq(x, y, z) > maxDist)
276 {
277 SF_LOG_DEBUG("bg.battleground", "BATTLEGROUND: Sending %s back to start location (map: %u) (possible exploit)", player->GetName().c_str(), GetMapId());
278 player->TeleportTo(GetMapId(), x, y, z, o);
279 }
280 }
281 }
282}
283
285{
286 // remove offline players from bg after 5 minutes
287 if (!m_OfflineQueue.empty())
288 {
289 BattlegroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin()));
290 if (itr != m_Players.end())
291 {
292 if (itr->second.OfflineRemoveTime <= sWorld->GetGameTime())
293 {
294 RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
295 m_OfflineQueue.pop_front(); // remove from offline queue
296 //do not use itr for anything, because it is erased in RemovePlayerAtLeave()
297 }
298 }
299 }
300}
301
303{
304 // *********************************************************
305 // *** BATTLEGROUND RESSURECTION SYSTEM ***
306 // *********************************************************
307 // this should be handled by spell system
308 m_LastResurrectTime += diff;
310 {
311 if (GetReviveQueueSize())
312 {
313 for (std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
314 {
315 Creature* sh = NULL;
316 for (std::vector<uint64>::const_iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
317 {
318 Player* player = ObjectAccessor::FindPlayer(*itr2);
319 if (!player)
320 continue;
321
322 if (!sh && player->IsInWorld())
323 {
324 sh = player->GetMap()->GetCreature(itr->first);
325 // only for visual effect
326 if (sh)
327 // Spirit Heal, effect 117
328 sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true);
329 }
330
331 // Resurrection visual
332 player->CastSpell(player, SPELL_RESURRECTION_VISUAL, true);
333 m_ResurrectQueue.push_back(*itr2);
334 }
335 (itr->second).clear();
336 }
337
338 m_ReviveQueue.clear();
340 }
341 else
342 // queue is clear and time passed, just update last resurrection time
344 }
345 else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC
346 {
347 for (std::vector<uint64>::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
348 {
349 Player* player = ObjectAccessor::FindPlayer(*itr);
350 if (!player)
351 continue;
352 player->ResurrectPlayer(1.0f);
353 player->CastSpell(player, 6962, true);
354 player->CastSpell(player, SPELL_SPIRIT_HEAL_MANA, true);
355 sObjectAccessor->ConvertCorpseForPlayer(*itr);
356 }
357 m_ResurrectQueue.clear();
358 }
359}
360
362{
363 uint32 winner = 0;
365 winner = ALLIANCE;
367 winner = HORDE;
368
369 return winner;
370}
371
373{
374 // *********************************************************
375 // *** BATTLEGROUND BALLANCE SYSTEM ***
376 // *********************************************************
377 if (sBattlegroundMgr->isTesting())
378 {
379 m_PrematureCountDown = false;
380 return;
381 }
382
383 // if less then minimum players are in on one side, then start premature finish timer
385 {
387 m_PrematureCountDownTimer = sBattlegroundMgr->GetPrematureFinishTime();
388 }
389 else if (m_PrematureCountDownTimer < diff)
390 {
391 // time's up!
393 m_PrematureCountDown = false;
394 }
395 else
396 {
397 uint32 newtime = m_PrematureCountDownTimer - diff;
398 // announce every minute
399 if (newtime > (MINUTE * IN_MILLISECONDS))
400 {
403 }
404 else
405 {
406 //announce every 15 seconds
407 if (newtime / (15 * IN_MILLISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILLISECONDS))
409 }
411 }
412}
413
415{
416 // *********************************************************
417 // *** BATTLEGROUND STARTING SYSTEM ***
418 // *********************************************************
420
421 if (!isArena())
422 SetRemainingTime(300000);
423
424 if (m_ResetStatTimer > 5000)
425 {
427 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
428 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
429 player->ResetAllPowers();
430 }
431
432 // Send packet every 10 seconds until the 2nd field reach 0
433 if (m_CountdownTimer >= 10000)
434 {
435 uint32 countdownMaxForBGType = isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX;
436
437 WorldPacket data(SMSG_START_TIMER, 4 + 4 + 4);
438 data << uint32(countdownMaxForBGType);
439 data << uint32(countdownMaxForBGType - (GetElapsedTime() / 1000));
440 data << uint32(0); // unk
441
442 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
443 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
444 player->GetSession()->SendPacket(&data);
445
447 }
448
450 {
452
453 if (!FindBgMap())
454 {
455 SF_LOG_ERROR("bg.battleground", "Battleground::_ProcessJoin: map (map id: %u, instance id: %u) is not created!", m_MapId, m_InstanceID);
456 EndNow();
457 return;
458 }
459
460 // Setup here, only when at least one player has ported to the map
461 if (!SetupBattleground())
462 {
463 EndNow();
464 return;
465 }
466
469 // First start warning - 2 or 1 minute
471 }
472 // After 1 minute or 30 seconds, warning is signaled
474 {
477 }
478 // After 30 or 15 seconds, warning is signaled
480 {
483 }
484 // Delay expired (after 2 or 1 minute)
485 else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
486 {
488
490
494
495 // Remove preparation
496 if (isArena())
497 {
499 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
500 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
501 {
502 // BG Status packet
503 WorldPacket status;
504 BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
505 uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
506
507 sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, player, queueSlot, STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(m_TypeID), GetElapsedTime(), GetArenaType());
508 player->GetSession()->SendPacket(&status);
509
510 // Correctly display EnemyUnitFrame
511 player->SetByteValue(PLAYER_FIELD_PVP_INFO, 3, player->GetBGTeam());
512
513 player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
514 player->ResetAllPowers();
515 if (!player->IsGameMaster())
516 {
517 // remove auras with duration lower than 30s
518 Unit::AuraApplicationMap& auraMap = player->GetAppliedAuras();
519 for (Unit::AuraApplicationMap::iterator iter = auraMap.begin(); iter != auraMap.end();)
520 {
521 AuraApplication* aurApp = iter->second;
522 Aura* aura = aurApp->GetBase();
523 if (!aura->IsPermanent()
524 && aura->GetDuration() <= 30 * IN_MILLISECONDS
525 && aurApp->IsPositive()
528 player->RemoveAura(iter);
529 else
530 ++iter;
531 }
532 }
533 }
534
536 }
537 else
538 {
540
541 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
542 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
543 {
544 player->RemoveAurasDueToSpell(SPELL_PREPARATION);
545 player->ResetAllPowers();
546 }
547 // Announce BG starting
550 }
551 }
552
553 if (GetRemainingTime() > 0 && (m_EndTime -= diff) > 0)
555}
556
558{
559 // *********************************************************
560 // *** BATTLEGROUND ENDING SYSTEM ***
561 // *********************************************************
562 // remove all players from battleground after 2 minutes
564 if (GetRemainingTime() <= 0)
565 {
567 BattlegroundPlayerMap::iterator itr, next;
568 for (itr = m_Players.begin(); itr != m_Players.end(); itr = next)
569 {
570 next = itr;
571 ++next;
572 //itr is erased here!
573 RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
574 // do not change any battleground's private variables
575 }
576 }
577}
578
579inline Player* Battleground::_GetPlayer(uint64 guid, bool offlineRemove, char const* context) const
580{
581 Player* player = NULL;
582 if (!offlineRemove)
583 {
584 player = ObjectAccessor::FindPlayer(guid);
585 if (!player)
586 SF_LOG_ERROR("bg.battleground", "Battleground::%s: player (GUID: %u) not found for BG (map: %u, instance id: %u)!",
587 context, GUID_LOPART(guid), m_MapId, m_InstanceID);
588 }
589 return player;
590}
591
592inline Player* Battleground::_GetPlayer(BattlegroundPlayerMap::iterator itr, char const* context)
593{
594 return _GetPlayer(itr->first, itr->second.OfflineRemoveTime, context);
595}
596
597inline Player* Battleground::_GetPlayer(BattlegroundPlayerMap::const_iterator itr, char const* context) const
598{
599 return _GetPlayer(itr->first, itr->second.OfflineRemoveTime, context);
600}
601
602inline Player* Battleground::_GetPlayerForTeam(uint32 teamId, BattlegroundPlayerMap::const_iterator itr, char const* context) const
603{
604 Player* player = _GetPlayer(itr, context);
605 if (player)
606 {
607 uint32 team = itr->second.Team;
608 if (!team)
609 team = player->GetTeam();
610 if (team != teamId)
611 player = NULL;
612 }
613 return player;
614}
615
616void Battleground::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
617{
618 TeamId idx = GetTeamIndexByTeamId(TeamID);
619 m_TeamStartLocX[idx] = X;
620 m_TeamStartLocY[idx] = Y;
621 m_TeamStartLocZ[idx] = Z;
622 m_TeamStartLocO[idx] = O;
623}
624
626{
627 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
628 if (Player* player = _GetPlayer(itr, "SendPacketToAll"))
629 player->SendDirectMessage(packet);
630}
631
632void Battleground::SendPacketToTeam(uint32 TeamID, WorldPacket* packet, Player* sender, bool self)
633{
634 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
635 {
636 if (Player* player = _GetPlayerForTeam(TeamID, itr, "SendPacketToTeam"))
637 {
638 if (self || sender != player)
639 player->SendDirectMessage(packet);
640 }
641 }
642}
643
645{
646 WorldPacket data;
647 sBattlegroundMgr->BuildPlaySoundPacket(&data, SoundID);
648 SendPacketToAll(&data);
649}
650
652{
653 WorldPacket data;
654 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
655 if (Player* player = _GetPlayerForTeam(TeamID, itr, "PlaySoundToTeam"))
656 {
657 sBattlegroundMgr->BuildPlaySoundPacket(&data, SoundID);
658 player->SendDirectMessage(&data);
659 }
660}
661
663{
664 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
665 if (Player* player = _GetPlayerForTeam(TeamID, itr, "CastSpellOnTeam"))
666 player->CastSpell(player, SpellID, true);
667}
668
670{
671 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
672 if (Player* player = _GetPlayerForTeam(TeamID, itr, "RemoveAuraOnTeam"))
673 player->RemoveAura(SpellID);
674}
675
676void Battleground::YellToAll(Creature* creature, char const* text, Language language)
677{
678 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
679 if (Player* player = _GetPlayer(itr, "YellToAll"))
680 {
681 WorldPacket data;
682 ChatHandler::BuildChatPacket(data, ChatMsg::CHAT_MSG_MONSTER_YELL, language, creature, player, text);
683 player->SendDirectMessage(&data);
684 }
685}
686
688{
689 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
690 if (Player* player = _GetPlayerForTeam(TeamID, itr, "RewardHonorToTeam"))
691 UpdatePlayerScore(player, SCORE_BONUS_HONOR, Honor);
692}
693
694void Battleground::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID)
695{
696 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id))
697 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
698 if (Player* player = _GetPlayerForTeam(TeamID, itr, "RewardReputationToTeam"))
699 player->GetReputationMgr().ModifyReputation(factionEntry, Reputation);
700}
701
703{
704 WorldPacket data;
705 sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, Field, Value);
706 SendPacketToAll(&data);
707}
708
710{
711 WorldPacket data;
712 sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, field, value);
713 player->SendDirectMessage(&data);
714}
715
717{
719
720 ArenaTeam* winnerArenaTeam = NULL;
721 ArenaTeam* loserArenaTeam = NULL;
722
723 uint32 loserTeamRating = 0;
724 uint32 loserMatchmakerRating = 0;
725 int32 loserChange = 0;
726 int32 loserMatchmakerChange = 0;
727 uint32 winnerTeamRating = 0;
728 uint32 winnerMatchmakerRating = 0;
729 int32 winnerChange = 0;
730 int32 winnerMatchmakerChange = 0;
731
732 int32 winmsg_id = 0;
733
734 if (winner == ALLIANCE)
735 {
737
738 PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
739
741 }
742 else if (winner == HORDE)
743 {
745
746 PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
747
749 }
750 else
751 {
752 SetWinner(3);
753 }
754
756 //we must set it this way, because end time is sent in packet!
758
759 // arena rating calculation
760 if (isArena() && isRated())
761 {
762 winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(winner));
763 loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner)));
764
765 if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
766 {
767 if (winner != WINNER_NONE)
768 {
769 loserTeamRating = loserArenaTeam->GetRating();
770 loserMatchmakerRating = GetArenaMatchmakerRating(GetOtherTeam(winner));
771 winnerTeamRating = winnerArenaTeam->GetRating();
772 winnerMatchmakerRating = GetArenaMatchmakerRating(winner);
773 winnerMatchmakerChange = winnerArenaTeam->WonAgainst(winnerMatchmakerRating, loserMatchmakerRating, winnerChange);
774 loserMatchmakerChange = loserArenaTeam->LostAgainst(loserMatchmakerRating, winnerMatchmakerRating, loserChange);
775 SF_LOG_DEBUG("bg.arena", "match Type: %u --- Winner: old rating: %u, rating gain: %d, old MMR: %u, MMR gain: %d --- Loser: old rating: %u, rating loss: %d, old MMR: %u, MMR loss: %d ---", m_ArenaType, winnerTeamRating, winnerChange, winnerMatchmakerRating,
776 winnerMatchmakerChange, loserTeamRating, loserChange, loserMatchmakerRating, loserMatchmakerChange);
777 SetArenaMatchmakerRating(winner, winnerMatchmakerRating + winnerMatchmakerChange);
778 SetArenaMatchmakerRating(GetOtherTeam(winner), loserMatchmakerRating + loserMatchmakerChange);
779 SetArenaTeamRatingChangeForTeam(winner, winnerChange);
780 SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loserChange);
781 SF_LOG_DEBUG("bg.arena", "Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. Winner rating: +%d, Loser rating: %d", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE], winnerArenaTeam->GetId(), winnerChange, loserChange);
783 for (Battleground::BattlegroundScoreMap::const_iterator itr = GetPlayerScoresBegin(); itr != GetPlayerScoresEnd(); ++itr)
784 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
785 {
786 SF_LOG_DEBUG("bg.arena", "Statistics match Type: %u for %s (GUID: " UI64FMTD ", IP: %s): %u damage, %u healing, %u killing blows",
787 m_ArenaType, player->GetName().c_str(), itr->first, player->GetSession()->GetRemoteAddress().c_str(), itr->second->DamageDone, itr->second->HealingDone,
788 itr->second->KillingBlows);
789 }
790 }
791 // Deduct 16 points from each teams arena-rating if there are no winners after 45+2 minutes
792 else
793 {
796 winnerArenaTeam->FinishGame(ARENA_TIMELIMIT_POINTS_LOSS);
798 }
799 }
800 else
801 {
804 }
805 }
806
807 bool guildAwarded = false;
808 WorldPacket pvpLogData;
809 sBattlegroundMgr->BuildPvpLogDataPacket(&pvpLogData, this);
810
812
813 uint8 aliveWinners = GetAlivePlayersCountByTeam(winner);
814 for (BattlegroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
815 {
816 uint32 team = itr->second.Team;
817
818 if (itr->second.OfflineRemoveTime)
819 {
820 //if rated arena match - make member lost!
821 if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
822 {
823 if (team == winner)
824 winnerArenaTeam->OfflineMemberLost(itr->first, loserMatchmakerRating, winnerMatchmakerChange);
825 else
826 loserArenaTeam->OfflineMemberLost(itr->first, winnerMatchmakerRating, loserMatchmakerChange);
827 }
828 continue;
829 }
830
831 Player* player = _GetPlayer(itr, "EndBattleground");
832 if (!player)
833 continue;
834
835 // should remove spirit of redemption
838
839 // Last standing - Rated 5v5 arena & be solely alive player
840 if (team == winner && isArena() && isRated() && GetArenaType() == ARENA_TYPE_5v5 && aliveWinners == 1 && player->IsAlive())
841 player->CastSpell(player, SPELL_THE_LAST_STANDING, true);
842
843 if (!player->IsAlive())
844 {
845 player->ResurrectPlayer(1.0f);
846 player->SpawnCorpseBones();
847 }
848 else
849 {
850 //needed cause else in av some creatures will kill the players at the end
851 player->CombatStop();
853 }
854
855 // per player calculation
856 if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
857 {
858 if (team == winner)
859 {
860 // update achievement BEFORE personal rating update
861 uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
865
866 winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
867 }
868 else
869 {
870 loserArenaTeam->MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange);
871
872 // Arena lost => reset the win_rated_arena having the "no_lose" condition
874 }
875 }
876
879
880 // remove temporary currency bonus auras before rewarding player
883
884 // Reward winner team
885 if (team == winner)
886 {
888 {
890 if (!player->GetRandomWinner())
891 {
892 // 100cp awarded for the first random battleground won each day
894 player->SetRandomWinner(true);
895 }
896 }
897 else // 50cp awarded for each non-rated battleground won
899
901 if (!guildAwarded)
902 {
903 guildAwarded = true;
904 if (uint32 guildId = GetBgMap()->GetOwnerGuildId(player->GetTeam()))
905 if (Guild* guild = sGuildMgr->GetGuildById(guildId))
906 {
907 guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1, 0, 0, NULL, player);
908 if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
909 guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, std::max<uint32>(winnerArenaTeam->GetRating(), 1), 0, 0, NULL, player);
910 }
911 }
912 }
913 else
914 {
917 }
918
919 player->ResetAllPowers();
920 player->CombatStopWithPets(true);
921
922 BlockMovement(player);
923
924 player->SendDirectMessage(&pvpLogData);
925
926 WorldPacket data;
927 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(GetTypeID()), GetElapsedTime(), GetArenaType());
928 player->SendDirectMessage(&data);
929
931 }
932
933 if (isArena() && isRated() && winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
934 {
935 /*
936 // save the stat changes
937 winnerArenaTeam->SaveToDB();
938 loserArenaTeam->SaveToDB();
939 */
940 // send updated arena team stats to players
941 // this way all arena team members will get notified, not only the ones who participated in this match
942 winnerArenaTeam->NotifyStatsChanged();
943 loserArenaTeam->NotifyStatsChanged();
944 }
945
946 if (winmsg_id)
948}
949
951{
952 //variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
953 uint32 maxLevel = std::min<uint32>(GetMaxLevel(), 80U);
954 return Skyfire::Honor::hk_honor_at_level(maxLevel, float(kills));
955}
956
958{
959 player->SetClientControl(player, 0); // 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()
960}
961
962void Battleground::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket)
963{
964 uint32 team = GetPlayerTeam(guid);
965 bool participant = false;
966 // Remove from lists/maps
967 BattlegroundPlayerMap::iterator itr = m_Players.find(guid);
968 if (itr != m_Players.end())
969 {
970 UpdatePlayersCountByTeam(team, true); // -1 player
971 m_Players.erase(itr);
972 // check if the player was a participant of the match, or only entered through gm command (goname)
973 participant = true;
974 }
975
976 BattlegroundScoreMap::iterator itr2 = PlayerScores.find(guid);
977 if (itr2 != PlayerScores.end())
978 {
979 delete itr2->second; // delete player's score
980 PlayerScores.erase(itr2);
981 }
982
984
985 Player* player = ObjectAccessor::FindPlayer(guid);
986
987 // should remove spirit of redemption
988 if (player)
989 {
992
993 if (!player->IsAlive()) // resurrect on exit
994 {
995 player->ResurrectPlayer(1.0f);
996 player->SpawnCorpseBones();
997 }
998 }
999
1000 RemovePlayer(player, guid, team); // BG subclass specific code
1001
1002 BattlegroundTypeId bgTypeId = GetTypeID();
1004
1005 if (participant) // if the player was a match participant, remove auras, calc rating, update queue
1006 {
1007 if (player)
1008 {
1009 player->ClearAfkReports();
1010
1011 if (!team) team = player->GetTeam();
1012
1013 // if arena, remove the specific arena auras
1014 if (isArena())
1015 {
1016 bgTypeId = BattlegroundTypeId::BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
1017
1018 // unsummon current and summon old pet if there was one and there isn't a current pet
1019 player->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT);
1021
1022 if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
1023 {
1024 //left a rated match while the encounter was in progress, consider as loser
1025 ArenaTeam* winnerArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
1026 ArenaTeam* loserArenaTeam = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(team));
1027 if (winnerArenaTeam && loserArenaTeam && winnerArenaTeam != loserArenaTeam)
1028 loserArenaTeam->MemberLost(player, GetArenaMatchmakerRating(GetOtherTeam(team)));
1029 }
1030 }
1031 if (SendPacket)
1032 {
1033 WorldPacket data;
1034 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_NONE, player->GetBattlegroundQueueJoinTime(bgTypeId), 0, 0);
1035 player->SendDirectMessage(&data);
1036 }
1037
1038 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
1039 player->RemoveBattlegroundQueueId(bgQueueTypeId);
1040 }
1041 else
1042 // removing offline participant
1043 {
1044 if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
1045 {
1046 //left a rated match while the encounter was in progress, consider as loser
1047 ArenaTeam* others_arena_team = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
1048 ArenaTeam* players_arena_team = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamIdForTeam(team));
1049 if (others_arena_team && players_arena_team)
1050 players_arena_team->OfflineMemberLost(guid, GetArenaMatchmakerRating(GetOtherTeam(team)));
1051 }
1052 }
1053
1054 // remove from raid group if player is member
1055 if (Group* group = GetBgRaid(team))
1056 {
1057 if (!group->RemoveMember(guid)) // group was disbanded
1058 {
1059 SetBgRaid(team, NULL);
1060 }
1061 }
1063 //we should update battleground queue, but only if bg isn't ending
1065 {
1066 // a player has left the battleground, so there are free slots -> add to queue
1068 sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, GetBracketId());
1069 }
1070 // Let others know
1071 WorldPacket data;
1072 sBattlegroundMgr->BuildPlayerLeftBattlegroundPacket(&data, guid);
1073 SendPacketToTeam(team, &data, player, false);
1074 }
1075
1076 if (player)
1077 {
1078 // Do next only if found in battleground
1079 player->SetBattlegroundId(0, BattlegroundTypeId::BATTLEGROUND_TYPE_NONE); // We're not in BG.
1080 // reset destination bg team
1081 player->SetBGTeam(0);
1082 player->RemoveBattlegroundQueueJoinTime(bgTypeId);
1083
1084 if (Transport)
1085 player->TeleportToBGEntryPoint();
1086
1087 SF_LOG_DEBUG("bg.battleground", "Removed player %s from Battleground.", player->GetName().c_str());
1088 }
1089
1091 m_SetDeleteThis = true;
1092
1093 //battleground object will be deleted next Battleground::Update() call
1094}
1095
1096// this method is called when no players remains in battleground
1098{
1101 SetElapsedTime(0);
1104 m_Events = 0;
1105
1106 if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
1107 SF_LOG_ERROR("bg.battleground", "Battleground::Reset: one of the counters is not 0 (alliance: %u, horde: %u) for BG (map: %u, instance id: %u)!",
1109
1111 m_InvitedHorde = 0;
1112 m_InBGFreeSlotQueue = false;
1113
1114 m_Players.clear();
1115
1116 for (BattlegroundScoreMap::const_iterator itr = PlayerScores.begin(); itr != PlayerScores.end(); ++itr)
1117 delete itr->second;
1118 PlayerScores.clear();
1119
1121}
1122
1124{
1125 SetElapsedTime(0);
1127 // add BG to free slot queue
1129
1130 // add bg to update list
1131 // This must be done here, because we need to have already invited some players when first BG::Update() method is executed
1132 // and it doesn't matter if we call StartBattleground() more times, because m_Battlegrounds is a map and instance id never changes
1133 sBattlegroundMgr->AddBattleground(this);
1134
1135 if (m_IsRated)
1136 SF_LOG_DEBUG("bg.arena", "Arena match type: %u for Team1Id: %u - Team2Id: %u started.", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE]);
1137}
1138
1140{
1141 // remove afk from player
1143 player->ToggleAFK();
1144
1145 // score struct must be created in inherited class
1146
1147 uint64 guid = player->GetGUID();
1148 uint32 team = player->GetBGTeam();
1149
1151 bp.OfflineRemoveTime = 0;
1152 bp.Team = team;
1153 bp.ActiveSpec = player->GetTalentSpecialization(player->GetActiveSpec());
1154
1155 // Add to list/maps
1156 m_Players[guid] = bp;
1157
1158 UpdatePlayersCountByTeam(team, false); // +1 player
1159
1160 WorldPacket data;
1161 sBattlegroundMgr->BuildPlayerJoinedBattlegroundPacket(&data, player->GetGUID());
1162 SendPacketToTeam(team, &data, player, false);
1163
1164 // BG Status packet
1165 BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType());
1166 uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId);
1167
1168 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, queueSlot, STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(m_TypeID), GetElapsedTime(), GetArenaType());
1169 player->GetSession()->SendPacket(&data);
1170
1172
1173 // add arena specific auras
1174 if (isArena())
1175 {
1177 if (team == ALLIANCE) // gold
1178 {
1179 if (player->GetTeam() == HORDE)
1180 player->CastSpell(player, SPELL_HORDE_GOLD_FLAG, true);
1181 else
1182 player->CastSpell(player, SPELL_ALLIANCE_GOLD_FLAG, true);
1183 }
1184 else // green
1185 {
1186 if (player->GetTeam() == HORDE)
1187 player->CastSpell(player, SPELL_HORDE_GREEN_FLAG, true);
1188 else
1189 player->CastSpell(player, SPELL_ALLIANCE_GREEN_FLAG, true);
1190 }
1191
1192 player->DestroyConjuredItems(true);
1193 player->UnsummonPetTemporaryIfAny();
1194 player->GetBattlePetMgr()->UnSummonCurrentBattlePet(false);
1195
1196 if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
1197 {
1198 player->CastSpell(player, SPELL_ARENA_PREPARATION, true);
1199 player->ResetAllPowers();
1200 }
1201 }
1202 else
1203 {
1204 if (GetStatus() == STATUS_WAIT_JOIN) // not started yet
1205 {
1206 player->CastSpell(player, SPELL_PREPARATION, true); // reduces all mana cost of spells.
1207
1208 int32 countdownMaxForBGType = isArena() ? ARENA_COUNTDOWN_MAX : BATTLEGROUND_COUNTDOWN_MAX;
1209 WorldPacket data(SMSG_START_TIMER, 4 + 4 + 4);
1210 data << uint32(countdownMaxForBGType);
1211 data << uint32(countdownMaxForBGType - (GetElapsedTime() / 1000));
1212 data << uint32(0); // unk
1213 player->GetSession()->SendPacket(&data);
1214 }
1215 }
1216
1228
1229 // setup BG group membership
1231 AddOrSetPlayerToCorrectBgGroup(player, team);
1232}
1233
1234// this method adds player to his team's bg group, or sets his correct group if player is already in bg group
1236{
1237 uint64 playerGuid = player->GetGUID();
1238 Group* group = GetBgRaid(team);
1239 if (!group) // first player joined
1240 {
1241 group = new Group;
1242 SetBgRaid(team, group);
1243 group->Create(player);
1244 }
1245 else // raid already exist
1246 {
1247 if (group->IsMember(playerGuid))
1248 {
1249 uint8 subgroup = group->GetMemberGroup(playerGuid);
1250 player->SetBattlegroundOrBattlefieldRaid(group, subgroup);
1251 }
1252 else
1253 {
1254 group->AddMember(player);
1255 if (Group* originalGroup = player->GetOriginalGroup())
1256 if (originalGroup->IsLeader(playerGuid))
1257 {
1258 group->ChangeLeader(playerGuid);
1259 group->SendUpdate();
1260 }
1261 }
1262 }
1263}
1264
1265// This method should be called when player logs into running battleground
1267{
1268 uint64 guid = player->GetGUID();
1269 // player is correct pointer
1270 for (std::deque<uint64>::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
1271 {
1272 if (*itr == guid)
1273 {
1274 m_OfflineQueue.erase(itr);
1275 break;
1276 }
1277 }
1278 m_Players[guid].OfflineRemoveTime = 0;
1280 // if battleground is starting, then add preparation aura
1281 // we don't have to do that, because preparation aura isn't removed when player logs out
1282}
1283
1284// This method should be called when player logs out from running battleground
1286{
1287 uint64 guid = player->GetGUID();
1288 if (!IsPlayerInBattleground(guid)) // Check if this player really is in battleground (might be a GM who teleported inside)
1289 return;
1290
1291 // player is correct pointer, it is checked in WorldSession::LogoutPlayer()
1292 m_OfflineQueue.push_back(player->GetGUID());
1293 m_Players[guid].OfflineRemoveTime = sWorld->GetGameTime() + MAX_OFFLINE_TIME;
1295 {
1296 // drop flag and handle other cleanups
1297 RemovePlayer(player, guid, GetPlayerTeam(guid));
1298
1299 // 1 player is logging out, if it is the last, then end arena!
1300 if (isArena())
1303 }
1304}
1305
1306// This method should be called only once ... it adds pointer to queue
1308{
1310 {
1311 sBattlegroundMgr->AddToBGFreeSlotQueue(m_TypeID, this);
1312 m_InBGFreeSlotQueue = true;
1313 }
1314}
1315
1316// This method removes this battleground from free queue - it must be called when deleting battleground
1318{
1320 {
1321 sBattlegroundMgr->RemoveFromBGFreeSlotQueue(m_TypeID, m_InstanceID);
1322 m_InBGFreeSlotQueue = false;
1323 }
1324}
1325
1326// get the number of free slots for team
1327// returns the number how many players can join battleground to MaxPlayersPerTeam
1329{
1330 // if BG is starting ... invite anyone
1331 if (GetStatus() == STATUS_WAIT_JOIN)
1333 // if BG is already started .. do not allow to join too much players of one faction
1334 uint32 otherTeam;
1335 uint32 otherIn;
1336 if (Team == ALLIANCE)
1337 {
1338 otherTeam = GetInvitedCount(HORDE);
1339 otherIn = GetPlayersCountByTeam(HORDE);
1340 }
1341 else
1342 {
1343 otherTeam = GetInvitedCount(ALLIANCE);
1345 }
1347 {
1348 // difference based on ppl invited (not necessarily entered battle)
1349 // default: allow 0
1350 uint32 diff = 0;
1351 // allow join one person if the sides are equal (to fill up bg to minplayersperteam)
1352 if (otherTeam == GetInvitedCount(Team))
1353 diff = 1;
1354 // allow join more ppl if the other side has more players
1355 else if (otherTeam > GetInvitedCount(Team))
1356 diff = otherTeam - GetInvitedCount(Team);
1357
1358 // difference based on max players per team (don't allow inviting more)
1360 // difference based on players who already entered
1361 // default: allow 0
1362 uint32 diff3 = 0;
1363 // allow join one person if the sides are equal (to fill up bg minplayersperteam)
1364 if (otherIn == GetPlayersCountByTeam(Team))
1365 diff3 = 1;
1366 // allow join more ppl if the other side has more players
1367 else if (otherIn > GetPlayersCountByTeam(Team))
1368 diff3 = otherIn - GetPlayersCountByTeam(Team);
1369 // or other side has less than minPlayersPerTeam
1371 diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1;
1372
1373 // return the minimum of the 3 differences
1374
1375 // min of diff and diff 2
1376 diff = std::min(diff, diff2);
1377 // min of diff, diff2 and diff3
1378 return std::min(diff, diff3);
1379 }
1380 return 0;
1381}
1382
1384{
1385 return GetPlayersSize() < GetMaxPlayers();
1386}
1387
1388void Battleground::UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor)
1389{
1390 //this procedure is called from virtual function implemented in bg subclass
1391 BattlegroundScoreMap::const_iterator itr = PlayerScores.find(Source->GetGUID());
1392 if (itr == PlayerScores.end()) // player not found...
1393 return;
1394
1395 switch (type)
1396 {
1397 case SCORE_KILLING_BLOWS: // Killing blows
1398 itr->second->KillingBlows += value;
1399 break;
1400 case SCORE_DEATHS: // Deaths
1401 itr->second->Deaths += value;
1402 break;
1403 case SCORE_HONORABLE_KILLS: // Honorable kills
1404 itr->second->HonorableKills += value;
1405 break;
1406 case SCORE_BONUS_HONOR: // Honor bonus
1407 // do not add honor in arenas
1408 if (isBattleground())
1409 {
1410 // reward honor instantly
1411 if (doAddHonor)
1412 Source->RewardHonor(NULL, 1, value); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
1413 else
1414 itr->second->BonusHonor += value;
1415 }
1416 break;
1417 // used only in EY, but in MSG_PVP_LOG_DATA opcode
1418 case SCORE_DAMAGE_DONE: // Damage Done
1419 itr->second->DamageDone += value;
1420 break;
1421 case SCORE_HEALING_DONE: // Healing Done
1422 itr->second->HealingDone += value;
1423 break;
1424 default:
1425 SF_LOG_ERROR("bg.battleground", "Battleground::UpdatePlayerScore: unknown score type (%u) for BG (map: %u, instance id: %u)!",
1426 type, m_MapId, m_InstanceID);
1427 break;
1428 }
1429}
1430
1432{
1433 m_ReviveQueue[npc_guid].push_back(player_guid);
1434
1435 Player* player = ObjectAccessor::FindPlayer(player_guid);
1436 if (!player)
1437 return;
1438
1439 player->CastSpell(player, SPELL_WAITING_FOR_RESURRECT, true);
1440}
1441
1443{
1444 for (std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
1445 {
1446 for (std::vector<uint64>::iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
1447 {
1448 if (*itr2 == player_guid)
1449 {
1450 (itr->second).erase(itr2);
1451 if (Player* player = ObjectAccessor::FindPlayer(player_guid))
1452 player->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
1453 return;
1454 }
1455 }
1456 }
1457}
1458
1460{
1461 // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard
1462 std::vector<uint64>& ghostList = m_ReviveQueue[queueIndex];
1463 if (!ghostList.empty())
1464 {
1465 WorldSafeLocsEntry const* closestGrave = NULL;
1466 for (std::vector<uint64>::const_iterator itr = ghostList.begin(); itr != ghostList.end(); ++itr)
1467 {
1468 Player* player = ObjectAccessor::FindPlayer(*itr);
1469 if (!player)
1470 continue;
1471
1472 if (!closestGrave)
1473 closestGrave = GetClosestGraveYard(player);
1474
1475 if (closestGrave)
1476 player->TeleportTo(GetMapId(), closestGrave->x, closestGrave->y, closestGrave->z, player->GetOrientation());
1477 }
1478 ghostList.clear();
1479 }
1480}
1481
1482bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 /*respawnTime*/)
1483{
1484 // If the assert is called, means that BgObjects must be resized!
1485 ASSERT(type < BgObjects.size());
1486
1487 Map* map = FindBgMap();
1488 if (!map)
1489 return false;
1490 // Must be created this way, adding to godatamap would add it to the base map of the instance
1491 // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
1492 // So we must create it specific for this instance
1493 GameObject* go = new GameObject;
1494 if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, GetBgMap(),
1495 x, y, z, o, rotation0, rotation1, rotation2, rotation3, 100, GOState::GO_STATE_READY))
1496 {
1497 SF_LOG_ERROR("sql.sql", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!",
1498 entry, m_MapId, m_InstanceID);
1499 SF_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!",
1500 entry, m_MapId, m_InstanceID);
1501 delete go;
1502 return false;
1503 }
1504
1505 for (auto phase : go->GetPhases())
1506 go->SetPhased(phase, false, true);
1507 /*
1508 uint32 guid = go->GetGUIDLow();
1509
1510 // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
1511 // 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
1512 GameObjectData& data = sObjectMgr->NewGOData(guid);
1513
1514 data.id = entry;
1515 data.mapid = GetMapId();
1516 data.posX = x;
1517 data.posY = y;
1518 data.posZ = z;
1519 data.orientation = o;
1520 data.rotation0 = rotation0;
1521 data.rotation1 = rotation1;
1522 data.rotation2 = rotation2;
1523 data.rotation3 = rotation3;
1524 data.spawntimesecs = respawnTime;
1525 data.spawnMask = 1;
1526 data.animprogress = 100;
1527 data.go_state = 1;
1528 */
1529 // Add to world, so it can be later looked up from HashMapHolder
1530 if (!map->AddToMap(go))
1531 {
1532 delete go;
1533 return false;
1534 }
1535 BgObjects[type] = go->GetGUID();
1536 return true;
1537}
1538
1539// Some doors aren't despawned so we cannot handle their closing in gameobject::update()
1540// It would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
1542{
1543 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1544 {
1545 // If doors are open, close it
1546 if (obj->getLootState() == LootState::GO_ACTIVATED && obj->GetGoState() != GOState::GO_STATE_READY)
1547 {
1548 obj->SetLootState(LootState::GO_READY);
1549 obj->SetGoState(GOState::GO_STATE_READY);
1550 }
1551 }
1552 else
1553 SF_LOG_ERROR("bg.battleground", "Battleground::DoorClose: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
1554 type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
1555}
1556
1558{
1559 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1560 {
1561 obj->SetLootState(LootState::GO_ACTIVATED);
1562 obj->SetGoState(GOState::GO_STATE_ACTIVE);
1563 }
1564 else
1565 SF_LOG_ERROR("bg.battleground", "Battleground::DoorOpen: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
1566 type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
1567}
1568
1570{
1571 GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]);
1572 if (!obj)
1573 SF_LOG_ERROR("bg.battleground", "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
1574 type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
1575 return obj;
1576}
1577
1579{
1580 Creature* creature = GetBgMap()->GetCreature(BgCreatures[type]);
1581 if (!creature)
1582 SF_LOG_ERROR("bg.battleground", "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
1584 return creature;
1585}
1586
1588{
1589 if (Map* map = FindBgMap())
1590 if (GameObject* obj = map->GetGameObject(BgObjects[type]))
1591 {
1592 if (respawntime)
1593 obj->SetLootState(LootState::GO_JUST_DEACTIVATED);
1594 else
1595 if (obj->getLootState() == LootState::GO_JUST_DEACTIVATED)
1596 // Change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
1597 obj->SetLootState(LootState::GO_READY);
1598 obj->SetRespawnTime(respawntime);
1599 map->AddToMap(obj);
1600 }
1601}
1602
1603Creature* Battleground::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime)
1604{
1605 // If the assert is called, means that BgCreatures must be resized!
1606 ASSERT(type < BgCreatures.size());
1607
1608 Map* map = FindBgMap();
1609 if (!map)
1610 return NULL;
1611
1612 Creature* creature = new Creature;
1613 if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, entry, 0, teamval, x, y, z, o))
1614 {
1615 SF_LOG_ERROR("bg.battleground", "Battleground::AddCreature: cannot create creature (entry: %u) for BG (map: %u, instance id: %u)!",
1616 entry, m_MapId, m_InstanceID);
1617 delete creature;
1618 return NULL;
1619 }
1620
1621 creature->SetHomePosition(x, y, z, o);
1622
1623 CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
1624 if (!cinfo)
1625 {
1626 SF_LOG_ERROR("bg.battleground", "Battleground::AddCreature: creature template (entry: %u) does not exist for BG (map: %u, instance id: %u)!",
1627 entry, m_MapId, m_InstanceID);
1628 delete creature;
1629 return NULL;
1630 }
1631 // Force using DB speeds
1632 creature->SetSpeed(MOVE_WALK, cinfo->speed_walk);
1633 creature->SetSpeed(MOVE_RUN, cinfo->speed_run);
1634
1635 if (!map->AddToMap(creature))
1636 {
1637 delete creature;
1638 return NULL;
1639 }
1640
1641 BgCreatures[type] = creature->GetGUID();
1642
1643 if (respawntime)
1644 creature->SetRespawnDelay(respawntime);
1645
1646 return creature;
1647}
1648
1650{
1651 if (!BgCreatures[type])
1652 return true;
1653
1654 if (Creature* creature = GetBgMap()->GetCreature(BgCreatures[type]))
1655 {
1656 creature->AddObjectToRemoveList();
1657 BgCreatures[type] = 0;
1658 return true;
1659 }
1660
1661 SF_LOG_ERROR("bg.battleground", "Battleground::DelCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
1663 BgCreatures[type] = 0;
1664 return false;
1665}
1666
1668{
1669 if (!BgObjects[type])
1670 return true;
1671
1672 if (GameObject* obj = GetBgMap()->GetGameObject(BgObjects[type]))
1673 {
1674 obj->SetRespawnTime(0); // not save respawn time
1675 obj->Delete();
1676 BgObjects[type] = 0;
1677 return true;
1678 }
1679 SF_LOG_ERROR("bg.battleground", "Battleground::DelObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!",
1680 type, GUID_LOPART(BgObjects[type]), m_MapId, m_InstanceID);
1681 BgObjects[type] = 0;
1682 return false;
1683}
1684
1685bool Battleground::AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team)
1686{
1687 uint32 entry = (team == ALLIANCE) ?
1690
1691 if (Creature* creature = AddCreature(entry, type, team, x, y, z, o))
1692 {
1693 creature->setDeathState(DeathState::DEAD);
1694 creature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, creature->GetGUID());
1695 // aura
1697 // creature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
1698 // casting visual effect
1699 creature->SetUInt32Value(UNIT_FIELD_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
1700 // correct cast speed
1701 creature->SetFloatValue(UNIT_FIELD_MOD_CASTING_SPEED, 1.0f);
1702 creature->SetFloatValue(UNIT_FIELD_MOD_SPELL_HASTE, 1.0f);
1703 //creature->CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
1704 return true;
1705 }
1706 SF_LOG_ERROR("bg.battleground", "Battleground::AddSpiritGuide: cannot create spirit guide (type: %u, entry: %u) for BG (map: %u, instance id: %u)!",
1707 type, entry, m_MapId, m_InstanceID);
1708 EndNow();
1709 return false;
1710}
1711
1712void Battleground::SendMessageToAll(int32 entry, ChatMsg type, Player const* source)
1713{
1714 if (!entry)
1715 return;
1716
1717 Skyfire::BattlegroundChatBuilder bg_builder(type, entry, source);
1719 BroadcastWorker(bg_do);
1720}
1721
1722void Battleground::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...)
1723{
1724 if (!entry)
1725 return;
1726
1727 va_list ap;
1728 va_start(ap, source);
1729
1730 Skyfire::BattlegroundChatBuilder bg_builder(type, entry, source, NULL, &ap);
1732 BroadcastWorker(bg_do);
1733
1734 va_end(ap);
1735}
1736
1738{
1739 if (!entry)
1740 return;
1741
1742 std::map<uint32, WorldPacket> localizedPackets;
1743
1744 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1745 if (Player* player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
1746 {
1747 if (localizedPackets.find(player->GetSession()->GetSessionDbLocaleIndex()) == localizedPackets.end())
1748 {
1749 char const* format = sObjectMgr->GetSkyFireString(entry, player->GetSession()->GetSessionDbLocaleIndex());
1750
1751 char str[1024];
1752 va_list ap;
1753 va_start(ap, entry);
1754 vsnprintf(str, 1024, format, ap);
1755 va_end(ap);
1756
1757 ChatHandler::BuildChatPacket(localizedPackets[player->GetSession()->GetSessionDbLocaleIndex()], ChatMsg::CHAT_MSG_RAID_BOSS_EMOTE, Language::LANG_UNIVERSAL, NULL, NULL, str);
1758 }
1759
1760 player->SendDirectMessage(&localizedPackets[player->GetSession()->GetSessionDbLocaleIndex()]);
1761 }
1762}
1763
1764void Battleground::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 arg1, int32 arg2)
1765{
1766 Skyfire::Battleground2ChatBuilder bg_builder(type, entry, arg1, arg2, source);
1768 BroadcastWorker(bg_do);
1769}
1770
1777
1778// To be removed
1780{
1781 // FIXME: now we have different DBC locales and need localized message for each target client
1782 return sObjectMgr->GetSkyFireStringForDBCLocale(entry);
1783}
1784
1785// IMPORTANT NOTICE:
1786// buffs aren't spawned/despawned when players captures anything
1787// buffs are in their positions when battleground starts
1789{
1790 GameObject* obj = GetBgMap()->GetGameObject(go_guid);
1791 if (!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
1792 return;
1793
1794 // Change buff type, when buff is used:
1795 int32 index = BgObjects.size() - 1;
1796 while (index >= 0 && BgObjects[index] != go_guid)
1797 index--;
1798 if (index < 0)
1799 {
1800 SF_LOG_ERROR("bg.battleground", "Battleground::HandleTriggerBuff: cannot find buff gameobject (GUID: %u, entry: %u, type: %u) in internal data for BG (map: %u, instance id: %u)!",
1801 GUID_LOPART(go_guid), obj->GetEntry(), obj->GetGoType(), m_MapId, m_InstanceID);
1802 return;
1803 }
1804
1805 // Randomly select new buff
1806 uint8 buff = std::rand() % 2;
1807 uint32 entry = obj->GetEntry();
1808 if (m_BuffChange && entry != Buff_Entries[buff])
1809 {
1810 // Despawn current buff
1812 // Set index for new one
1813 for (uint8 currBuffTypeIndex = 0; currBuffTypeIndex < 3; ++currBuffTypeIndex)
1814 if (entry == Buff_Entries[currBuffTypeIndex])
1815 {
1816 index -= currBuffTypeIndex;
1817 index += buff;
1818 }
1819 }
1820
1822}
1823
1825{
1826 // Keep in mind that for arena this will have to be changed a bit
1827
1828 // Add +1 deaths
1829 UpdatePlayerScore(victim, SCORE_DEATHS, 1);
1830 // Add +1 kills to group and +1 killing_blows to killer
1831 if (killer)
1832 {
1833 // Don't reward credit for killing ourselves, like fall damage of hellfire (warlock)
1834 if (killer == victim)
1835 return;
1836
1839
1840 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1841 {
1842 Player* creditedPlayer = ObjectAccessor::FindPlayer(itr->first);
1843 if (!creditedPlayer || creditedPlayer == killer)
1844 continue;
1845
1846 if (creditedPlayer->GetTeam() == killer->GetTeam() && creditedPlayer->IsAtGroupRewardDistance(victim))
1847 UpdatePlayerScore(creditedPlayer, SCORE_HONORABLE_KILLS, 1);
1848 }
1849 }
1850
1851 if (!isArena())
1852 {
1853 // To be able to remove insignia -- ONLY IN Battlegrounds
1855 RewardXPAtKill(killer, victim);
1856 }
1857}
1858
1859// Return the player's team based on battlegroundplayer info
1860// Used in same faction arena matches mainly
1862{
1863 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1864 if (itr != m_Players.end())
1865 return itr->second.Team;
1866 return 0;
1867}
1868
1870{
1871 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1872 if (itr != m_Players.end())
1873 return itr->second.ActiveSpec;
1874 return 0;
1875}
1876
1878{
1879 return teamId ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0;
1880}
1881
1883{
1884 BattlegroundPlayerMap::const_iterator itr = m_Players.find(guid);
1885 if (itr != m_Players.end())
1886 return true;
1887 return false;
1888}
1889
1891{
1893 return;
1894
1895 WorldPacket data;
1897
1898 BlockMovement(player);
1899
1900 sBattlegroundMgr->BuildPvpLogDataPacket(&data, this);
1901 player->SendDirectMessage(&data);
1902
1903 sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, player->GetBattlegroundQueueJoinTime(GetTypeID()), GetElapsedTime(), GetArenaType());
1904 player->SendDirectMessage(&data);
1905}
1906
1908{
1909 int count = 0;
1910 for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
1911 {
1912 if (itr->second.Team == Team)
1913 {
1914 Player* player = ObjectAccessor::FindPlayer(itr->first);
1915 if (player && player->IsAlive() && !player->HasByteFlag(UNIT_FIELD_SHAPESHIFT_FORM, 3, FORM_SPIRITOFREDEMPTION))
1916 ++count;
1917 }
1918 }
1919 return count;
1920}
1921
1922void Battleground::SetHoliday(bool is_holiday)
1923{
1925}
1926
1928{
1929 for (uint32 i = 0; i < BgObjects.size(); ++i)
1930 if (BgObjects[i] == guid)
1931 return i;
1932 SF_LOG_ERROR("bg.battleground", "Battleground::GetObjectType: player used gameobject (GUID: %u) which is not in internal data for BG (map: %u, instance id: %u), cheating?",
1934 return -1;
1935}
1936
1937void Battleground::HandleKillUnit(Creature* /*victim*/, Player* /*killer*/) { }
1938
1943
1951
1957
1959{
1960 Group*& old_raid = TeamID == ALLIANCE ? m_BgRaids[TEAM_ALLIANCE] : m_BgRaids[TEAM_HORDE];
1961 if (old_raid)
1962 old_raid->SetBattlegroundGroup(NULL);
1963 if (bg_raid)
1964 bg_raid->SetBattlegroundGroup(this);
1965 old_raid = bg_raid;
1966}
1967
1969{
1970 return sObjectMgr->GetClosestGraveYard(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam());
1971}
1972
1974{
1975 for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
1976 if (Player* player = ObjectAccessor::FindPlayer(itr->first))
1977 player->StartTimedAchievement(type, entry);
1978}
1979
1981{
1982 m_BracketId = bracketEntry->GetBracketId();
1983 SetLevelRange(bracketEntry->minLevel, bracketEntry->maxLevel);
1984}
1985
1987{
1988 if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_BG_XP_FOR_KILL) && killer && victim)
1989 killer->RewardPlayerAndGroupAtKill(victim, true);
1990}
1991
1993{
1994 if (teamId == TEAM_ALLIANCE || teamId == TEAM_HORDE)
1995 return m_TeamScores[teamId];
1996
1997 SF_LOG_ERROR("bg.battleground", "GetTeamScore with wrong Team %u for BG %u", teamId, uint32(GetTypeID()));
1998 return 0;
1999}
2000
2002{
2003 SF_LOG_DEBUG("bg.battleground", "Unhandled AreaTrigger %u in Battleground %u. Player coords (x: %f, y: %f, z: %f)",
2004 trigger, player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
2005}
2006
2007bool Battleground::CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/)
2008{
2009 SF_LOG_ERROR("bg.battleground", "Battleground::CheckAchievementCriteriaMeet: No implementation for criteria %u", criteriaId);
2010 return false;
2011}
#define sArenaTeamMgr
@ WINNER_HORDE
@ WINNER_ALLIANCE
@ WINNER_NONE
@ RESURRECTION_INTERVAL
@ ARENA_COUNTDOWN_MAX
@ MAX_OFFLINE_TIME
@ BUFF_RESPAWN_TIME
@ TIME_AUTOCLOSE_BATTLEGROUND
@ BATTLEGROUND_COUNTDOWN_MAX
@ RESPAWN_ONE_DAY
@ CHECK_PLAYER_POSITION_INVERVAL
@ ARENA_TYPE_5v5
@ BG_STARTING_EVENT_3
@ BG_STARTING_EVENT_2
@ BG_STARTING_EVENT_1
@ BG_STARTING_EVENT_4
@ BG_CREATURE_ENTRY_H_SPIRITGUIDE
@ BG_CREATURE_ENTRY_A_SPIRITGUIDE
uint32 const Buff_Entries[3]
BGHonorMode
@ BG_NORMAL
@ BG_HOLIDAY
@ SPELL_SPIRIT_HEAL
@ SPELL_ALLIANCE_GOLD_FLAG
@ SPELL_THE_LAST_STANDING
@ SPELL_SPIRIT_HEAL_CHANNEL
@ SPELL_HORDE_GOLD_FLAG
@ SPELL_ARENA_PREPARATION
@ SPELL_SPIRIT_HEAL_MANA
@ SPELL_HONORABLE_DEFENDER_25Y
@ SPELL_PREPARATION
@ SPELL_RESURRECTION_VISUAL
@ SPELL_HORDE_GREEN_FLAG
@ SPELL_ALLIANCE_GREEN_FLAG
@ SPELL_WAITING_FOR_RESURRECT
@ SPELL_HONORABLE_DEFENDER_60Y
@ SCORE_KILLING_BLOWS
@ SCORE_BONUS_HONOR
@ SCORE_DEATHS
@ SCORE_DAMAGE_DONE
@ SCORE_HEALING_DONE
@ SCORE_HONORABLE_KILLS
@ BG_START_DELAY_1M
@ BG_START_DELAY_30S
@ BG_START_DELAY_2M
@ BG_START_DELAY_NONE
#define ARENA_TIMELIMIT_POINTS_LOSS
@ STATUS_WAIT_QUEUE
@ STATUS_NONE
@ STATUS_WAIT_LEAVE
@ STATUS_WAIT_JOIN
@ STATUS_IN_PROGRESS
@ SOUND_BG_START
@ SOUND_ALLIANCE_WINS
@ SOUND_HORDE_WINS
@ BG_STARTING_EVENT_THIRD
@ BG_STARTING_EVENT_SECOND
@ BG_STARTING_EVENT_FIRST
@ BG_STARTING_EVENT_FOURTH
#define sBattlegroundMgr
#define vsnprintf
Definition Common.h:100
LocaleConstant
Definition Common.h:138
@ IN_MILLISECONDS
Definition Common.h:125
@ MINUTE
Definition Common.h:119
@ CURRENCY_TYPE_CONQUEST_META_ARENA
Definition DBCEnums.h:588
AchievementCriteriaTimedTypes
Definition DBCEnums.h:157
@ ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE
Definition DBCEnums.h:85
@ ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP
Definition DBCEnums.h:84
@ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET
Definition DBCEnums.h:193
@ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL
Definition DBCEnums.h:194
@ ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND
Definition DBCEnums.h:183
@ ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE
Definition DBCEnums.h:220
@ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL
Definition DBCEnums.h:200
@ ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE
Definition DBCEnums.h:181
@ ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
Definition DBCEnums.h:202
@ ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE
Definition DBCEnums.h:171
@ ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA
Definition DBCEnums.h:196
@ ACHIEVEMENT_CRITERIA_TYPE_WIN_BG
Definition DBCEnums.h:172
@ ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL
Definition DBCEnums.h:233
@ ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE
Definition DBCEnums.h:195
@ ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS
Definition DBCEnums.h:221
@ ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA
Definition DBCEnums.h:197
BattlegroundBracketId
Definition DBCEnums.h:28
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
std::int32_t int32
Definition Define.h:73
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
@ GO_JUST_DEACTIVATED
Definition GameObject.h:619
@ GO_STATE_ACTIVE
Definition GameObject.h:576
@ GO_STATE_READY
Definition GameObject.h:577
#define sGuildMgr
Definition GuildMgr.h:53
@ TEMP_ENCHANTMENT_SLOT
Definition Item.h:151
@ LANG_ARENA_GREEN_WINS
Definition Language.h:706
@ LANG_BG_WS_HAS_BEGUN
Definition Language.h:617
@ LANG_ARENA_GOLD_WINS
Definition Language.h:705
@ LANG_BG_STARTED_ANNOUNCE_WORLD
Definition Language.h:697
@ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
Definition Language.h:732
@ LANG_BG_WS_START_ONE_MINUTE
Definition Language.h:615
@ LANG_BG_WS_START_HALF_MINUTE
Definition Language.h:616
@ LANG_BG_A_WINS
Definition Language.h:611
@ LANG_BG_H_WINS
Definition Language.h:612
@ LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS
Definition Language.h:733
@ LANG_BG_WS_START_TWO_MINUTES
Definition Language.h:614
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define sObjectAccessor
uint32 GUID_LOPART(uint64 x)
@ HIGHGUID_GAMEOBJECT
@ HIGHGUID_PLAYER
@ HIGHGUID_UNIT
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ PET_SAVE_NOT_IN_SLOT
Definition PetDefines.h:25
@ PLAYER_FLAGS_AFK
Definition Player.h:538
@ GAMEOBJECT_TYPE_TRAP
@ SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY
ChatMsg
@ CHAT_MSG_BG_SYSTEM_NEUTRAL
@ CHAT_MSG_RAID_BOSS_EMOTE
@ CHAT_MSG_MONSTER_YELL
Language
BattlegroundQueueTypeId
TeamId
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ ALLIANCE
@ HORDE
BattlegroundTypeId
@ SPELL_AURA_MOD_SHAPESHIFT
@ SPELL_AURA_SPIRIT_OF_REDEMPTION
@ SPELL_AURA_MOD_INVISIBILITY
@ SPELL_AURA_MOUNTED
@ FORM_SPIRITOFREDEMPTION
Definition Unit.h:239
@ MOVE_RUN
Definition Unit.h:556
@ MOVE_WALK
Definition Unit.h:555
@ UNIT_FLAG_SKINNABLE
Definition Unit.h:651
@ UNIT_FIELD_MOD_CASTING_SPEED
@ UNIT_FIELD_CHANNEL_OBJECT
@ UNIT_FIELD_SHAPESHIFT_FORM
@ UNIT_FIELD_MOD_SPELL_HASTE
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_CHANNEL_SPELL
@ PLAYER_FIELD_PVP_INFO
@ PLAYER_FIELD_PLAYER_FLAGS
int32 WonAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32 &rating_change)
uint32 GetRating() const
Definition ArenaTeam.h:115
void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 matchmakerRatingChange=-12)
uint8 GetSlot() const
Definition ArenaTeam.h:108
void MemberWon(Player *player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange=12)
void FinishGame(int32 mod)
void NotifyStatsChanged()
Definition ArenaTeam.cpp:44
void MemberLost(Player *player, uint32 againstMatchmakerRating, int32 matchmakerRatingChange=-12)
uint32 GetId() const
Definition ArenaTeam.h:106
int32 LostAgainst(uint32 ownMMRating, uint32 opponentMMRating, int32 &rating_change)
bool IsPositive() const
Definition SpellAuras.h:61
Aura * GetBase() const
Definition SpellAuras.h:55
int32 GetDuration() const
Definition SpellAuras.h:119
bool HasEffectType(AuraType type) const
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:87
bool IsPermanent() const
Definition SpellAuras.h:124
void UnSummonCurrentBattlePet(bool temporary)
void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const
virtual void AddPlayer(Player *player)
uint32 m_InvitedAlliance
void SetRemainingTime(uint32 Time)
uint32 GetAlivePlayersCountByTeam(uint32 Team) const
uint32 GetMapId() const
BattlegroundTypeId GetTypeID(bool GetRandom=false) const
void EndBattleground(uint32 winner)
uint32 m_CountdownTimer
virtual void HandleKillUnit(Creature *, Player *)
uint32 GetReviveQueueSize() const
char const * GetName() const
BGHonorMode m_HonorMode
Group * m_BgRaids[BG_TEAMS_COUNT]
uint32 GetMinLevel() const
void ModifyStartDelayTime(int diff)
uint32 m_ArenaTeamIds[BG_TEAMS_COUNT]
void CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
void SetElapsedTime(uint32 Time)
virtual void HandleKillPlayer(Player *player, Player *killer)
static TeamId GetTeamIndexByTeamId(uint32 Team)
virtual bool SetupBattleground()
float m_TeamStartLocX[BG_TEAMS_COUNT]
void DoorOpen(uint32 type)
uint32 GetMinPlayersPerTeam() const
void PlayerAddedToBGCheckIfBGIsRunning(Player *player)
bool DelCreature(uint32 type)
uint8 GetArenaType() const
float m_TeamStartLocY[BG_TEAMS_COUNT]
BattlegroundPlayerMap m_Players
void SpawnBGObject(uint32 type, uint32 respawntime)
uint32 GetMaxPlayersPerTeam() const
virtual void Reset()
uint32 m_ValidStartPositionTimer
void SendPacketToAll(WorldPacket *packet)
void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player *player)
void HandleTriggerBuff(uint64 go_guid)
void YellToAll(Creature *creature, const char *text, Language language)
int32 m_StartDelayTime
void AddOrSetPlayerToCorrectBgGroup(Player *player, uint32 team)
void PlaySoundToAll(uint32 SoundID)
uint32 GetArenaMatchmakerRating(uint32 Team) const
uint32 m_ClientInstanceID
uint32 m_LevelMax
void AddToBGFreeSlotQueue()
BattlegroundTypeId m_TypeID
std::map< uint64, std::vector< uint64 > > m_ReviveQueue
void PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
Group * GetBgRaid(uint32 TeamID) const
uint32 GetPlayerActiveSpec(uint64 guid) const
uint32 m_LastResurrectTime
bool isRated() const
uint32 GetOtherTeam(uint32 teamId) const
uint32 GetMaxPlayers() const
BattlegroundMap * GetBgMap() const
virtual void PostUpdateImpl(uint32)
Post-update hook.
BattlegroundTypeId m_RandomTypeID
void SetBracket(PvPDifficultyEntry const *bracketEntry)
void DecreaseInvitedCount(uint32 team)
void _ProcessRessurect(uint32 diff)
void CheckArenaWinConditions()
uint32 m_ArenaTeamMMR[BG_TEAMS_COUNT]
uint32 GetArenaTeamIdForTeam(uint32 Team) const
BattlegroundMap * FindBgMap() const
void BlockMovement(Player *player)
uint32 GetRemainingTime() const
void RemoveAuraOnTeam(uint32 SpellID, uint32 TeamID)
void StartBattleground()
virtual void ResetBGSubclass()
void DoorClose(uint32 type)
float m_TeamStartLocZ[BG_TEAMS_COUNT]
void Update(uint32 diff)
void RelocateDeadPlayers(uint64 queueIndex)
Relocate all players in ReviveQueue to the closest graveyard.
void SetBgRaid(uint32 TeamID, Group *bg_raid)
bool m_PrematureCountDown
uint32 GetInstanceID() const
uint32 m_PrematureCountDownTimer
virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket)
int32 GetObjectType(uint64 guid)
BattlegroundScoreMap::const_iterator GetPlayerScoresBegin() const
void SetLevelRange(uint32 min, uint32 max)
BGObjects BgObjects
void EventPlayerLoggedOut(Player *player)
void UpdateWorldState(uint32 Field, uint32 Value)
const char * GetSkyFireString(int32 entry)
Player * _GetPlayer(uint64 guid, bool offlineRemove, const char *context) const
uint32 m_MinPlayers
void RewardXPAtKill(Player *killer, Player *victim)
bool m_InBGFreeSlotQueue
void SetStatus(BattlegroundStatus Status)
virtual void StartingEventCloseDoors()
BattlegroundBracketId m_BracketId
void BroadcastWorker(Do &_do)
BattlegroundStartTimeIntervals StartDelayTimes[BG_STARTING_EVENT_COUNT]
bool isArena() const
char const * m_Name
void SetWinner(uint8 winner)
void SetArenaMatchmakerRating(uint32 Team, uint32 MMR)
uint32 m_InstanceID
void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
int32 m_ArenaTeamRatingChanges[BG_TEAMS_COUNT]
bool DelObject(uint32 type)
uint32 m_ResetStatTimer
BattlegroundPlayerMap const & GetPlayers() const
int32 GetStartDelayTime() const
virtual void RemovePlayer(Player *, uint64, uint32)
BattlegroundScoreMap PlayerScores
virtual void StartingEventOpenDoors()
float GetStartMaxDist() const
bool isBattleground() const
uint32 m_MinPlayersPerTeam
virtual bool ShouldDelayStartForDebug() const
void SetLastResurrectTime(uint32 Time)
void RewardHonorToTeam(uint32 Honor, uint32 TeamID)
void SendWarningToAll(int32 entry,...)
bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team)
void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
BattlegroundStatus GetStatus() const
bool HasFreeSlots() const
virtual bool CheckAchievementCriteriaMeet(uint32, Player const *, Unit const *=NULL, uint32=0)
bool IsRandom() const
virtual WorldSafeLocsEntry const * GetClosestGraveYard(Player *player)
uint32 m_PlayersCount[BG_TEAMS_COUNT]
virtual void HandleAreaTrigger(Player *, uint32)
void _ProcessOfflineQueue()
void RemoveFromBGFreeSlotQueue()
void _ProcessProgress(uint32 diff)
float m_TeamStartLocO[BG_TEAMS_COUNT]
void SetHoliday(bool is_holiday)
BGCreatures BgCreatures
GameObject * GetBGObject(uint32 type)
uint32 GetPlayersCountByTeam(uint32 Team) const
virtual bool PreUpdateImpl(uint32)
Pre-update hook.
float m_StartMaxDist
void UpdateArenaWorldState()
virtual ~Battleground()
uint32 GetTeamScore(uint32 TeamID) const
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
uint32 m_MaxPlayersPerTeam
void EventPlayerLoggedIn(Player *player)
void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange)
void SendMessage2ToAll(int32 entry, ChatMsg type, Player const *source, int32 strId1=0, int32 strId2=0)
void _CheckSafePositions(uint32 diff)
std::vector< uint64 > m_ResurrectQueue
void _ProcessJoin(uint32 diff)
BattlegroundBracketId GetBracketId() const
uint32 m_InvitedHorde
void UpdatePlayersCountByTeam(uint32 Team, bool remove)
uint32 m_MaxPlayers
void SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender=NULL, bool self=true)
bool IsPlayerInBattleground(uint64 guid) const
uint32 GetBonusHonorFromKill(uint32 kills) const
void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID)
uint32 GetMaxLevel() const
virtual void UpdatePlayerScore(Player *player, uint32 type, uint32 value, bool doAddHonor=true)
BattlegroundScoreMap::const_iterator GetPlayerScoresEnd() const
Creature * AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime=0)
uint32 GetElapsedTime() const
uint32 GetPlayersSize() const
uint32 m_LevelMin
uint32 GetPlayerTeam(uint64 guid) const
void PSendMessageToAll(int32 entry, ChatMsg type, Player const *source,...)
void SendMessageToAll(int32 entry, ChatMsg type, Player const *source=NULL)
int32 m_TeamScores[BG_TEAMS_COUNT]
std::deque< uint64 > m_OfflineQueue
uint32 m_StartTime
Creature * GetBGCreature(uint32 type)
void SetStartDelayTime(int Time)
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)
uint32 GetFreeSlotsForTeam(uint32 Team) const
void RemovePlayerFromResurrectQueue(uint64 player_guid)
BattlegroundMap * m_Map
uint32 GetInvitedCount(uint32 team) const
void _ProcessLeave(uint32 diff)
virtual uint32 GetPrematureWinner()
Player * _GetPlayerForTeam(uint32 teamId, BattlegroundPlayerMap::const_iterator itr, const char *context) const
BattlegroundStatus m_Status
void CheckArenaAfterTimerConditions()
uint32 StartMessageIds[BG_STARTING_EVENT_COUNT]
static BattlegroundQueueTypeId BGQueueTypeId(BattlegroundTypeId bgTypeId, uint8 arenaType)
static bool IsBGWeekend(BattlegroundTypeId bgTypeId)
static size_t BuildChatPacket(WorldPacket &data, ChatMsg chatType, Language language, ObjectGuid senderGUID, ObjectGuid receiverGUID, std::string const &message, uint8 chatTag, std::string const &senderName="", std::string const &receiverName="", uint32 achievementId=0, bool gmMessage=false, std::string const &channelName="", std::string const &addonPrefix="")
Definition Chat.cpp:580
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:626
void SetRespawnDelay(uint32 delay)
Definition Creature.h:603
bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData *data=NULL)
Definition Creature.cpp:740
Definition Field.h:16
bool isSpawned() const
Definition GameObject.h:705
bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit=0)
static GameObject * GetGameObject(WorldObject &object, uint64 guid)
GameobjectTypes GetGoType() const
Definition GameObject.h:719
bool SetPhased(uint32 id, bool update, bool apply) OVERRIDE
Definition Group.h:147
bool AddMember(Player *player)
Definition Group.cpp:353
void SendUpdate()
Definition Group.cpp:1594
uint8 GetMemberGroup(uint64 guid) const
Definition Group.cpp:2651
void SetBattlegroundGroup(Battleground *bg)
Definition Group.cpp:2659
bool IsMember(uint64 guid) const
Definition Group.cpp:2603
bool Create(Player *leader)
Definition Group.cpp:81
void ChangeLeader(uint64 guid)
Definition Group.cpp:628
Definition Guild.h:324
Definition Map.h:238
bool AddToMap(T *)
Definition Map.cpp:504
GameObject * GetGameObject(uint64 guid)
Definition Map.cpp:3184
Creature * GetCreature(uint64 guid)
Definition Map.cpp:3179
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
bool IsInWorld() const
Definition Object.h:114
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
uint32 GetEntry() const
Definition Object.h:125
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
bool HasByteFlag(uint16 index, uint8 offset, uint8 flag) const
Definition Object.cpp:1376
uint32 GetTeam() const
Definition Player.h:2527
void SetBGTeam(uint32 team)
Definition Player.cpp:17973
uint32 GetBGTeam() const
Definition Player.cpp:17979
void ClearAfkReports()
Definition Player.h:2746
BattlePetMgr * GetBattlePetMgr()
Definition Player.h:2573
uint32 GetTalentSpecialization(uint8 spec) const
Definition Player.h:2075
void SendDirectMessage(WorldPacket *data)
Definition Player.cpp:6904
uint32 GetBattlegroundQueueJoinTime(BattlegroundTypeId bgTypeId) const
Definition Player.h:2707
uint32 GetArenaPersonalRating(uint8) const
Definition Player.h:2304
bool IsAtGroupRewardDistance(WorldObject const *pRewardSource) const
Definition Player.cpp:19789
WorldSession * GetSession() const
Definition Player.h:2417
void DestroyConjuredItems(bool update)
void UnsummonPetTemporaryIfAny()
Definition Player.cpp:21113
void RemoveBattlegroundQueueId(BattlegroundQueueTypeId val)
Definition Player.cpp:19282
bool GetRandomWinner() const
Definition Player.h:2757
void RewardPlayerAndGroupAtKill(Unit *victim, bool isBattleGround)
Definition Player.cpp:19757
void ModifyCurrency(uint32 id, int32 count, bool printLog=true, bool ignoreMultipliers=false)
Definition Player.cpp:7691
void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1=0, uint64 miscValue2=0, bool evenIfCriteriaComplete=false)
Definition Player.cpp:21028
void RemovePet(Pet *pet, PetSaveMode mode, bool returnreagent=false)
Definition Player.cpp:15663
bool TeleportToBGEntryPoint()
Definition Player.cpp:2341
void RemoveBattlegroundQueueJoinTime(BattlegroundTypeId bgTypeId)
Definition Player.h:2715
void SetClientControl(Unit *target, uint8 allowMove)
Definition Player.cpp:19853
void SpawnCorpseBones()
Definition Player.cpp:5378
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, Unit *unit=NULL)
Definition Player.cpp:21033
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
uint8 GetActiveSpec() const
Definition Player.h:2077
void ToggleAFK()
Definition Player.cpp:2060
uint32 GetBattlegroundQueueIndex(BattlegroundQueueTypeId bgQueueTypeId) const
Definition Player.cpp:19233
void ResetAllPowers()
Definition Player.cpp:2778
bool RewardHonor(Unit *victim, uint32 groupsize, int32 honor=-1, bool pvptoken=false)
Definition Player.cpp:7316
void ResummonPetTemporaryUnSummonedIfAny()
Definition Player.cpp:21128
void SetBattlegroundId(uint32 val, BattlegroundTypeId bgTypeId)
Definition Player.cpp:19254
Group * GetOriginalGroup()
Definition Player.h:3015
void SetBattlegroundOrBattlefieldRaid(Group *group, int8 subgroup=-1)
Definition Player.cpp:20119
void RemoveArenaEnchantments(EnchantmentSlot slot)
Definition Player.cpp:10849
void SetRandomWinner(bool isWinner)
Definition Player.cpp:22407
void ResurrectPlayer(float restore_percent, bool applySickness=false)
Definition Player.cpp:5203
void operator()(WorldPacket &data, LocaleConstant loc_idx)
Battleground2ChatBuilder(ChatMsg msgtype, int32 textId, int32 arg1, int32 arg2, Player const *source=NULL, Player const *target=NULL)
void do_helper(WorldPacket &data, char const *text)
void operator()(WorldPacket &data, LocaleConstant loc_idx)
BattlegroundChatBuilder(ChatMsg msgtype, int32 textId, Player const *source, Player *const target=NULL, va_list *args=NULL)
uint32 Attributes
Definition SpellInfo.h:164
Definition Unit.h:1367
void CombatStop(bool includingCast=false)
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
std::multimap< uint32, AuraApplication * > AuraApplicationMap
Definition Unit.h:1376
bool IsAlive() const
Definition Unit.h:2032
bool HasAuraType(AuraType auraType) const
HostileRefManager & getHostileRefManager()
Definition Unit.h:2466
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
void SetSpeed(UnitMoveType mtype, float rate, bool forced=false)
Definition Unit.cpp:4318
void CombatStopWithPets(bool includingCast=false)
uint32 GetMapId() const
Definition Object.h:546
Map * GetMap() const
Definition Object.h:740
std::set< uint32 > const & GetPhases() const
Definition Object.h:647
std::string const & GetName() const
Definition Object.h:664
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
@ SMSG_START_TIMER
Definition Opcodes.h:1019
#define sWorld
Definition World.h:910
@ CONFIG_BG_REWARD_WINNER_HONOR_FIRST
Definition World.h:355
@ CONFIG_BG_REWARD_WINNER_HONOR_LAST
Definition World.h:356
@ CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD
Definition World.h:236
@ CONFIG_BG_REWARD_WINNER_CONQUEST_LAST
Definition World.h:360
@ CONFIG_BG_REWARD_LOSER_HONOR_FIRST
Definition World.h:357
@ CONFIG_BG_REWARD_LOSER_HONOR_LAST
Definition World.h:358
@ CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST
Definition World.h:359
@ CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE
Definition World.h:126
@ CONFIG_BG_XP_FOR_KILL
Definition World.h:128
@ CONFIG_ARENA_LOG_EXTENDED_INFO
Definition World.h:132
uint32 hk_honor_at_level(uint8 level, float multiplier=1.0f)
Definition Formulas.h:26
float GetPositionZ() const
Definition Object.h:330
float GetOrientation() const
Definition Object.h:331
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
float GetExactDistSq(float x, float y, float z) const
Definition Object.h:378
uint32 maxLevel
BattlegroundBracketId GetBracketId() const
uint32 minLevel
float x
float z
float y