2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "BattleGround.h"
22 #include "BattleGroundMgr.h"
24 #include "MapManager.h"
27 #include "SpellAuras.h"
28 #include "ArenaTeam.h"
31 #include "ObjectMgr.h"
32 #include "WorldPacket.h"
35 BattleGround::BattleGround()
37 m_TypeID
= BattleGroundTypeId(0);
41 m_LastResurrectTime
= 0;
42 m_QueueId
= MAX_BATTLEGROUND_QUEUES
;
43 m_InvitedAlliance
= 0;
55 m_InBGFreeSlotQueue
= false;
56 m_SetDeleteThis
= false;
58 m_MaxPlayersPerTeam
= 0;
60 m_MinPlayersPerTeam
= 0;
65 m_TeamStartLocX
[BG_TEAM_ALLIANCE
] = 0;
66 m_TeamStartLocX
[BG_TEAM_HORDE
] = 0;
68 m_TeamStartLocY
[BG_TEAM_ALLIANCE
] = 0;
69 m_TeamStartLocY
[BG_TEAM_HORDE
] = 0;
71 m_TeamStartLocZ
[BG_TEAM_ALLIANCE
] = 0;
72 m_TeamStartLocZ
[BG_TEAM_HORDE
] = 0;
74 m_TeamStartLocO
[BG_TEAM_ALLIANCE
] = 0;
75 m_TeamStartLocO
[BG_TEAM_HORDE
] = 0;
77 m_ArenaTeamIds
[BG_TEAM_ALLIANCE
] = 0;
78 m_ArenaTeamIds
[BG_TEAM_HORDE
] = 0;
80 m_ArenaTeamRatingChanges
[BG_TEAM_ALLIANCE
] = 0;
81 m_ArenaTeamRatingChanges
[BG_TEAM_HORDE
] = 0;
83 m_BgRaids
[BG_TEAM_ALLIANCE
] = NULL
;
84 m_BgRaids
[BG_TEAM_HORDE
] = NULL
;
86 m_PlayersCount
[BG_TEAM_ALLIANCE
] = 0;
87 m_PlayersCount
[BG_TEAM_HORDE
] = 0;
89 m_PrematureCountDown
= false;
90 m_PrematureCountDown
= 0;
93 BattleGround::~BattleGround()
95 // remove objects and creatures
96 // (this is done automatically in mapmanager update, when the instance is reset after the reset time)
97 int size
= m_BgCreatures
.size();
98 for(int i
= 0; i
< size
; ++i
)
102 size
= m_BgObjects
.size();
103 for(int i
= 0; i
< size
; ++i
)
108 if(GetInstanceID()) // not spam by useless queries in case BG templates
110 // delete creature and go respawn times
111 WorldDatabase
.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
112 WorldDatabase
.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID());
113 // delete instance from db
114 CharacterDatabase
.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID());
115 // remove from battlegrounds
118 sBattleGroundMgr
.RemoveBattleGround(GetInstanceID());
120 if(Map
* map
= MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
121 if(map
->IsBattleGroundOrArena())
122 ((BattleGroundMap
*)map
)->SetUnload();
123 // remove from bg free slot queue
124 this->RemoveFromBGFreeSlotQueue();
127 void BattleGround::Update(uint32 diff
)
129 if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
135 if(GetRemovedPlayersSize())
137 for(std::map
<uint64
, uint8
>::iterator itr
= m_RemovedPlayers
.begin(); itr
!= m_RemovedPlayers
.end(); ++itr
)
139 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
142 //following code is handled by event:
144 sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first);
145 //RemovePlayerFromQueue(itr->first);
148 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
149 plr->GetSession()->SendPacket(&data);
152 case 1: // currently in bg and was removed from bg
154 RemovePlayerAtLeave(itr
->first
, true, true);
156 RemovePlayerAtLeave(itr
->first
, false, false);
158 case 2: // revive queue
159 RemovePlayerFromResurrectQueue(itr
->first
);
162 sLog
.outError("BattleGround: Unknown remove player case!");
165 m_RemovedPlayers
.clear();
168 // remove offline players from bg after ~5 minutes
171 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
173 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
174 itr
->second
.LastOnlineTime
+= diff
;
177 itr
->second
.LastOnlineTime
= 0; // update last online time
179 if(itr
->second
.LastOnlineTime
>= MAX_OFFLINE_TIME
) // 5 minutes
180 m_RemovedPlayers
[itr
->first
] = 1; // add to remove list (BG)
184 //this should be handled by spell system:
185 m_LastResurrectTime
+= diff
;
186 if (m_LastResurrectTime
>= RESURRECTION_INTERVAL
)
188 if(GetReviveQueueSize())
190 for(std::map
<uint64
, std::vector
<uint64
> >::iterator itr
= m_ReviveQueue
.begin(); itr
!= m_ReviveQueue
.end(); ++itr
)
193 for(std::vector
<uint64
>::iterator itr2
= (itr
->second
).begin(); itr2
!= (itr
->second
).end(); ++itr2
)
195 Player
*plr
= objmgr
.GetPlayer(*itr2
);
201 sh
= ObjectAccessor::GetCreature(*plr
, itr
->first
);
202 // only for visual effect
204 sh
->CastSpell(sh
, SPELL_SPIRIT_HEAL
, true); // Spirit Heal, effect 117
207 plr
->CastSpell(plr
, SPELL_RESURRECTION_VISUAL
, true); // Resurrection visual
208 m_ResurrectQueue
.push_back(*itr2
);
210 (itr
->second
).clear();
213 m_ReviveQueue
.clear();
214 m_LastResurrectTime
= 0;
217 // queue is clear and time passed, just update last resurrection time
218 m_LastResurrectTime
= 0;
220 else if (m_LastResurrectTime
> 500) // Resurrect players only half a second later, to see spirit heal effect on NPC
222 for(std::vector
<uint64
>::iterator itr
= m_ResurrectQueue
.begin(); itr
!= m_ResurrectQueue
.end(); ++itr
)
224 Player
*plr
= objmgr
.GetPlayer(*itr
);
227 plr
->ResurrectPlayer(1.0f
);
228 plr
->CastSpell(plr
, SPELL_SPIRIT_HEAL_MANA
, true);
229 ObjectAccessor::Instance().ConvertCorpseForPlayer(*itr
);
231 m_ResurrectQueue
.clear();
234 // if less then minimum players are in on one side, then start premature finish timer
235 if(GetStatus() == STATUS_IN_PROGRESS
&& !isArena() && sBattleGroundMgr
.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE
) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE
) < GetMinPlayersPerTeam()))
237 if(!m_PrematureCountDown
)
239 m_PrematureCountDown
= true;
240 m_PrematureCountDownTimer
= sBattleGroundMgr
.GetPrematureFinishTime();
241 SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
);
243 else if(m_PrematureCountDownTimer
< diff
)
246 EndBattleGround(0); // noone wins
247 m_PrematureCountDown
= false;
251 uint32 newtime
= m_PrematureCountDownTimer
- diff
;
252 // announce every minute
253 if(m_PrematureCountDownTimer
!= sBattleGroundMgr
.GetPrematureFinishTime() && newtime
/ 60000 != m_PrematureCountDownTimer
/ 60000)
254 SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
);
255 m_PrematureCountDownTimer
= newtime
;
258 else if (m_PrematureCountDown
)
259 m_PrematureCountDown
= false;
261 if(GetStatus() == STATUS_WAIT_LEAVE
)
263 // remove all players from battleground after 2 minutes
265 if(m_EndTime
>= TIME_TO_AUTOREMOVE
) // 2 minutes
267 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
269 m_RemovedPlayers
[itr
->first
] = 1; // add to remove list (BG)
271 // do not change any battleground's private variables
276 void BattleGround::SetTeamStartLoc(uint32 TeamID
, float X
, float Y
, float Z
, float O
)
278 uint8 idx
= GetTeamIndexByTeamId(TeamID
);
279 m_TeamStartLocX
[idx
] = X
;
280 m_TeamStartLocY
[idx
] = Y
;
281 m_TeamStartLocZ
[idx
] = Z
;
282 m_TeamStartLocO
[idx
] = O
;
285 void BattleGround::SendPacketToAll(WorldPacket
*packet
)
287 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
289 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
291 plr
->GetSession()->SendPacket(packet
);
293 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
297 void BattleGround::SendPacketToTeam(uint32 TeamID
, WorldPacket
*packet
, Player
*sender
, bool self
)
299 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
301 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
305 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
309 if(!self
&& sender
== plr
)
312 uint32 team
= itr
->second
.Team
;
313 if(!team
) team
= plr
->GetTeam();
316 plr
->GetSession()->SendPacket(packet
);
320 void BattleGround::PlaySoundToAll(uint32 SoundID
)
323 sBattleGroundMgr
.BuildPlaySoundPacket(&data
, SoundID
);
324 SendPacketToAll(&data
);
327 void BattleGround::PlaySoundToTeam(uint32 SoundID
, uint32 TeamID
)
331 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
333 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
337 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
341 uint32 team
= itr
->second
.Team
;
342 if(!team
) team
= plr
->GetTeam();
346 sBattleGroundMgr
.BuildPlaySoundPacket(&data
, SoundID
);
347 plr
->GetSession()->SendPacket(&data
);
352 void BattleGround::CastSpellOnTeam(uint32 SpellID
, uint32 TeamID
)
354 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
356 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
360 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
364 uint32 team
= itr
->second
.Team
;
365 if(!team
) team
= plr
->GetTeam();
368 plr
->CastSpell(plr
, SpellID
, true);
372 void BattleGround::RewardHonorToTeam(uint32 Honor
, uint32 TeamID
)
374 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
376 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
380 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
384 uint32 team
= itr
->second
.Team
;
385 if(!team
) team
= plr
->GetTeam();
388 UpdatePlayerScore(plr
, SCORE_BONUS_HONOR
, Honor
);
392 void BattleGround::RewardReputationToTeam(uint32 faction_id
, uint32 Reputation
, uint32 TeamID
)
394 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
399 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
401 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
405 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
409 uint32 team
= itr
->second
.Team
;
410 if(!team
) team
= plr
->GetTeam();
413 plr
->ModifyFactionReputation(factionEntry
, Reputation
);
417 void BattleGround::UpdateWorldState(uint32 Field
, uint32 Value
)
420 sBattleGroundMgr
.BuildUpdateWorldStatePacket(&data
, Field
, Value
);
421 SendPacketToAll(&data
);
424 void BattleGround::UpdateWorldStateForPlayer(uint32 Field
, uint32 Value
, Player
*Source
)
427 sBattleGroundMgr
.BuildUpdateWorldStatePacket(&data
, Field
, Value
);
428 Source
->GetSession()->SendPacket(&data
);
431 void BattleGround::EndBattleGround(uint32 winner
)
433 this->RemoveFromBGFreeSlotQueue();
435 ArenaTeam
* winner_arena_team
= NULL
;
436 ArenaTeam
* loser_arena_team
= NULL
;
437 uint32 loser_rating
= 0;
438 uint32 winner_rating
= 0;
440 Player
*Source
= NULL
;
441 const char *winmsg
= "";
443 if(winner
== ALLIANCE
)
446 winmsg
= GetMangosString(LANG_BG_A_WINS
);
448 winmsg
= GetMangosString(LANG_ARENA_GOLD_WINS
);
450 PlaySoundToAll(SOUND_ALLIANCE_WINS
); // alliance wins sound
452 SetWinner(WINNER_ALLIANCE
);
454 else if(winner
== HORDE
)
457 winmsg
= GetMangosString(LANG_BG_H_WINS
);
459 winmsg
= GetMangosString(LANG_ARENA_GREEN_WINS
);
461 PlaySoundToAll(SOUND_HORDE_WINS
); // horde wins sound
463 SetWinner(WINNER_HORDE
);
470 SetStatus(STATUS_WAIT_LEAVE
);
473 // arena rating calculation
474 if(isArena() && isRated())
476 if(winner
== ALLIANCE
)
478 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
479 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
481 else if(winner
== HORDE
)
483 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
484 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
486 if(winner_arena_team
&& loser_arena_team
)
488 loser_rating
= loser_arena_team
->GetStats().rating
;
489 winner_rating
= winner_arena_team
->GetStats().rating
;
490 int32 winner_change
= winner_arena_team
->WonAgainst(loser_rating
);
491 int32 loser_change
= loser_arena_team
->LostAgainst(winner_rating
);
492 sLog
.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating
, loser_rating
, winner_change
, loser_change
);
493 if(winner
== ALLIANCE
)
495 SetArenaTeamRatingChangeForTeam(ALLIANCE
, winner_change
);
496 SetArenaTeamRatingChangeForTeam(HORDE
, loser_change
);
500 SetArenaTeamRatingChangeForTeam(HORDE
, winner_change
);
501 SetArenaTeamRatingChangeForTeam(ALLIANCE
, loser_change
);
506 SetArenaTeamRatingChangeForTeam(ALLIANCE
, 0);
507 SetArenaTeamRatingChangeForTeam(HORDE
, 0);
511 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
513 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
516 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
520 // should remove spirit of redemption
521 if(plr
->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION
))
522 plr
->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT
);
526 plr
->ResurrectPlayer(1.0f
);
527 plr
->SpawnCorpseBones();
530 uint32 team
= itr
->second
.Team
;
531 if(!team
) team
= plr
->GetTeam();
533 // per player calculation
534 if(isArena() && isRated() && winner_arena_team
&& loser_arena_team
)
537 winner_arena_team
->MemberWon(plr
,loser_rating
);
539 loser_arena_team
->MemberLost(plr
,winner_rating
);
546 RewardMark(plr
,ITEM_WINNER_COUNT
);
547 UpdatePlayerScore(plr
, SCORE_BONUS_HONOR
, 20);
552 RewardMark(plr
,ITEM_LOSER_COUNT
);
555 plr
->CombatStopWithPets(true);
559 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, this);
560 plr
->GetSession()->SendPacket(&data
);
562 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
563 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, this, plr
->GetTeam(), plr
->GetBattleGroundQueueIndex(bgQueueTypeId
), STATUS_IN_PROGRESS
, TIME_TO_AUTOREMOVE
, GetStartTime());
564 plr
->GetSession()->SendPacket(&data
);
565 plr
->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND
, 1);
568 if(isArena() && isRated() && winner_arena_team
&& loser_arena_team
)
570 // update arena points only after increasing the player's match count!
571 //obsolete: winner_arena_team->UpdateArenaPointsHelper();
572 //obsolete: loser_arena_team->UpdateArenaPointsHelper();
573 // save the stat changes
574 winner_arena_team
->SaveToDB();
575 loser_arena_team
->SaveToDB();
576 // send updated arena team stats to players
577 // this way all arena team members will get notified, not only the ones who participated in this match
578 winner_arena_team
->NotifyStatsChanged();
579 loser_arena_team
->NotifyStatsChanged();
582 // inform invited players about the removal
583 sBattleGroundMgr
.m_BattleGroundQueues
[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
587 ChatHandler(Source
).FillMessageData(&data
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, Source
->GetGUID(), winmsg
);
588 SendPacketToAll(&data
);
592 uint32
BattleGround::GetBattlemasterEntry() const
596 case BATTLEGROUND_AV
: return 15972;
597 case BATTLEGROUND_WS
: return 14623;
598 case BATTLEGROUND_AB
: return 14879;
599 case BATTLEGROUND_EY
: return 22516;
600 case BATTLEGROUND_NA
: return 20200;
605 void BattleGround::RewardMark(Player
*plr
,uint32 count
)
607 // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
608 if(plr
->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE
))
611 BattleGroundMarks mark
;
615 case BATTLEGROUND_AV
:
617 if(count
== ITEM_WINNER_COUNT
)
618 mark
= SPELL_AV_MARK_WINNER
;
620 mark
= SPELL_AV_MARK_LOSER
;
622 case BATTLEGROUND_WS
:
624 if(count
== ITEM_WINNER_COUNT
)
625 mark
= SPELL_WS_MARK_WINNER
;
627 mark
= SPELL_WS_MARK_LOSER
;
629 case BATTLEGROUND_AB
:
631 if(count
== ITEM_WINNER_COUNT
)
632 mark
= SPELL_AB_MARK_WINNER
;
634 mark
= SPELL_AB_MARK_LOSER
;
636 case BATTLEGROUND_EY
:
638 mark
= ITEM_EY_MARK_OF_HONOR
;
645 plr
->CastSpell(plr
, mark
, true);
646 else if ( objmgr
.GetItemPrototype( mark
) )
648 ItemPosCountVec dest
;
649 uint32 no_space_count
= 0;
650 uint8 msg
= plr
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, mark
, count
, &no_space_count
);
651 if( msg
!= EQUIP_ERR_OK
) // convert to possible store amount
652 count
-= no_space_count
;
654 if( count
!= 0 && !dest
.empty()) // can add some
655 if(Item
* item
= plr
->StoreNewItem( dest
, mark
, true, 0))
656 plr
->SendNewItem(item
,count
,false,true);
658 if(no_space_count
> 0)
659 SendRewardMarkByMail(plr
,mark
,no_space_count
);
663 void BattleGround::SendRewardMarkByMail(Player
*plr
,uint32 mark
, uint32 count
)
665 uint32 bmEntry
= GetBattlemasterEntry();
669 ItemPrototype
const* markProto
= objmgr
.GetItemPrototype(mark
);
673 if(Item
* markItem
= Item::CreateItem(mark
,count
,plr
))
675 // save new item before send
676 markItem
->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
680 mi
.AddItem(markItem
->GetGUIDLow(), markItem
->GetEntry(), markItem
);
682 // subject: item name
683 std::string subject
= markProto
->Name1
;
684 int loc_idx
= plr
->GetSession()->GetSessionDbLocaleIndex();
686 if(ItemLocale
const *il
= objmgr
.GetItemLocale(markProto
->ItemId
))
687 if (il
->Name
.size() > size_t(loc_idx
) && !il
->Name
[loc_idx
].empty())
688 subject
= il
->Name
[loc_idx
];
691 std::string textFormat
= plr
->GetSession()->GetMangosString(LANG_BG_MARK_BY_MAIL
);
693 snprintf(textBuf
,300,textFormat
.c_str(),GetName(),GetName());
694 uint32 itemTextId
= objmgr
.CreateItemText( textBuf
);
696 WorldSession::SendMailTo(plr
, MAIL_CREATURE
, MAIL_STATIONERY_NORMAL
, bmEntry
, plr
->GetGUIDLow(), subject
, itemTextId
, &mi
, 0, 0, MAIL_CHECK_MASK_NONE
);
700 void BattleGround::RewardQuest(Player
*plr
)
702 // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
703 if(plr
->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE
))
709 case BATTLEGROUND_AV
:
710 quest
= SPELL_AV_QUEST_REWARD
;
712 case BATTLEGROUND_WS
:
713 quest
= SPELL_WS_QUEST_REWARD
;
715 case BATTLEGROUND_AB
:
716 quest
= SPELL_AB_QUEST_REWARD
;
718 case BATTLEGROUND_EY
:
719 quest
= SPELL_EY_QUEST_REWARD
;
725 plr
->CastSpell(plr
, quest
, true);
728 void BattleGround::BlockMovement(Player
*plr
)
730 plr
->SetClientControl(plr
, 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()
733 void BattleGround::RemovePlayerAtLeave(uint64 guid
, bool Transport
, bool SendPacket
)
735 uint32 team
= GetPlayerTeam(guid
);
736 bool participant
= false;
737 // Remove from lists/maps
738 std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.find(guid
);
739 if(itr
!= m_Players
.end())
741 UpdatePlayersCountByTeam(team
, true); // -1 player
742 m_Players
.erase(itr
);
743 // check if the player was a participant of the match, or only entered through gm command (goname)
747 std::map
<uint64
, BattleGroundScore
*>::iterator itr2
= m_PlayerScores
.find(guid
);
748 if(itr2
!= m_PlayerScores
.end())
750 delete itr2
->second
; // delete player's score
751 m_PlayerScores
.erase(itr2
);
754 RemovePlayerFromResurrectQueue(guid
);
756 Player
*plr
= objmgr
.GetPlayer(guid
);
758 // should remove spirit of redemption
759 if(plr
&& plr
->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION
))
760 plr
->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT
);
762 if(plr
&& !plr
->isAlive()) // resurrect on exit
764 plr
->ResurrectPlayer(1.0f
);
765 plr
->SpawnCorpseBones();
768 RemovePlayer(plr
, guid
); // BG subclass specific code
772 plr
->ClearAfkReports();
774 if(participant
) // if the player was a match participant, remove auras, calc rating, update queue
776 if(!team
) team
= plr
->GetTeam();
778 BattleGroundTypeId bgTypeId
= GetTypeID();
779 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
780 // if arena, remove the specific arena auras
783 plr
->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
784 bgTypeId
=BATTLEGROUND_AA
; // set the bg type to all arenas (it will be used for queue refreshing)
786 // summon old pet if there was one and there isn't a current pet
787 if(!plr
->GetPet() && plr
->GetTemporaryUnsummonedPetNumber())
789 Pet
* NewPet
= new Pet
;
790 if(!NewPet
->LoadPetFromDB(plr
, 0, (plr
)->GetTemporaryUnsummonedPetNumber(), true))
793 (plr
)->SetTemporaryUnsummonedPetNumber(0);
796 if(isRated() && GetStatus() == STATUS_IN_PROGRESS
)
798 //left a rated match while the encounter was in progress, consider as loser
799 ArenaTeam
* winner_arena_team
= 0;
800 ArenaTeam
* loser_arena_team
= 0;
803 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
804 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
808 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
809 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
811 if(winner_arena_team
&& loser_arena_team
)
813 loser_arena_team
->MemberLost(plr
,winner_arena_team
->GetRating());
821 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, this, team
, plr
->GetBattleGroundQueueIndex(bgQueueTypeId
), STATUS_NONE
, 0, 0);
822 plr
->GetSession()->SendPacket(&data
);
825 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
826 plr
->RemoveBattleGroundQueueId(bgQueueTypeId
);
828 DecreaseInvitedCount(team
);
829 //we should update battleground queue, but only if bg isn't ending
830 if (GetQueueId() < MAX_BATTLEGROUND_QUEUES
)
831 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, GetQueueId());
833 Group
* group
= plr
->GetGroup();
834 // remove from raid group if exist
835 if(group
&& group
== GetBgRaid(team
))
837 if(!group
->RemoveMember(guid
, 0)) // group was disbanded
839 SetBgRaid(team
, NULL
);
845 sBattleGroundMgr
.BuildPlayerLeftBattleGroundPacket(&data
, plr
);
846 SendPacketToTeam(team
, &data
, plr
, false);
849 // Do next only if found in battleground
850 plr
->SetBattleGroundId(0); // We're not in BG.
851 // reset destination bg team
855 plr
->TeleportTo(plr
->GetBattleGroundEntryPoint());
858 sLog
.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr
->GetName());
861 if(!GetPlayersSize() && !GetInvitedCount(HORDE
) && !GetInvitedCount(ALLIANCE
))
863 // if no players left AND no invitees left, set this bg to delete in next update
864 // direct deletion could cause crashes
865 m_SetDeleteThis
= true;
866 // return to prevent addition to freeslotqueue
870 // a player exited the battleground, so there are free slots. add to queue
871 this->AddToBGFreeSlotQueue();
874 // this method is called when no players remains in battleground
875 void BattleGround::Reset()
877 SetQueueId(MAX_BATTLEGROUND_QUEUES
);
878 SetWinner(WINNER_NONE
);
879 SetStatus(STATUS_WAIT_QUEUE
);
882 SetLastResurrectTime(0);
888 if (m_InvitedAlliance
> 0 || m_InvitedHorde
> 0)
889 sLog
.outError("BattleGround system ERROR: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance
, m_InvitedHorde
);
891 m_InvitedAlliance
= 0;
893 m_InBGFreeSlotQueue
= false;
896 m_PlayerScores
.clear();
899 void BattleGround::StartBattleGround()
901 ///this method should spawn spirit guides and so on
904 SetLastResurrectTime(0);
907 void BattleGround::AddPlayer(Player
*plr
)
909 // score struct must be created in inherited class
911 uint64 guid
= plr
->GetGUID();
912 uint32 team
= plr
->GetBGTeam();
914 BattleGroundPlayer bp
;
915 bp
.LastOnlineTime
= 0;
919 m_Players
[guid
] = bp
;
921 UpdatePlayersCountByTeam(team
, false); // +1 player
924 sBattleGroundMgr
.BuildPlayerJoinedBattleGroundPacket(&data
, plr
);
925 SendPacketToTeam(team
, &data
, plr
, false);
927 // add arena specific auras
930 plr
->RemoveArenaSpellCooldowns();
931 plr
->RemoveArenaAuras();
932 plr
->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT
);
933 if(team
== ALLIANCE
) // gold
935 if(plr
->GetTeam() == HORDE
)
936 plr
->CastSpell(plr
, SPELL_HORDE_GOLD_FLAG
,true);
938 plr
->CastSpell(plr
, SPELL_ALLIANCE_GOLD_FLAG
,true);
942 if(plr
->GetTeam() == HORDE
)
943 plr
->CastSpell(plr
, SPELL_HORDE_GREEN_FLAG
,true);
945 plr
->CastSpell(plr
, SPELL_ALLIANCE_GREEN_FLAG
,true);
948 plr
->DestroyConjuredItems(true);
950 Pet
* pet
= plr
->GetPet();
953 if(pet
->getPetType() == SUMMON_PET
|| pet
->getPetType() == HUNTER_PET
)
955 (plr
)->SetTemporaryUnsummonedPetNumber(pet
->GetCharmInfo()->GetPetNumber());
956 (plr
)->SetOldPetSpell(pet
->GetUInt32Value(UNIT_CREATED_BY_SPELL
));
958 (plr
)->RemovePet(NULL
,PET_SAVE_NOT_IN_SLOT
);
961 (plr
)->SetTemporaryUnsummonedPetNumber(0);
963 if(GetStatus() == STATUS_WAIT_JOIN
) // not started yet
965 plr
->CastSpell(plr
, SPELL_ARENA_PREPARATION
, true);
967 plr
->SetHealth(plr
->GetMaxHealth());
968 plr
->SetPower(POWER_MANA
, plr
->GetMaxPower(POWER_MANA
));
973 if(GetStatus() == STATUS_WAIT_JOIN
) // not started yet
974 plr
->CastSpell(plr
, SPELL_PREPARATION
, true); // reduces all mana cost of spells.
977 // setup BG group membership
979 AddOrSetPlayerToCorrectBgGroup(plr
, guid
, team
);
982 sLog
.outDetail("BATTLEGROUND: Player %s joined the battle.", plr
->GetName());
985 /* this method adds player to his team's bg group, or sets his correct group if player is already in bg group */
986 void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player
*plr
, uint64 plr_guid
, uint32 team
)
988 Group
* group
= GetBgRaid(team
);
989 if(!group
) // first player joined
992 SetBgRaid(team
, group
);
993 group
->Create(plr_guid
, plr
->GetName());
995 else // raid already exist
997 if(group
->IsMember(plr_guid
))
999 uint8 subgroup
= group
->GetMemberGroup(plr_guid
);
1000 plr
->SetGroup(group
, subgroup
);
1003 GetBgRaid(team
)->AddMember(plr_guid
, plr
->GetName());
1008 /* This method should be called only once ... it adds pointer to queue */
1009 void BattleGround::AddToBGFreeSlotQueue()
1011 // make sure to add only once
1012 if(!m_InBGFreeSlotQueue
)
1014 sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].push_front(this);
1015 m_InBGFreeSlotQueue
= true;
1019 /* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/
1020 void BattleGround::RemoveFromBGFreeSlotQueue()
1022 // set to be able to re-add if needed
1023 m_InBGFreeSlotQueue
= false;
1024 // uncomment this code when battlegrounds will work like instances
1025 for (std::deque
<BattleGround
*>::iterator itr
= sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].begin(); itr
!= sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].end(); ++itr
)
1027 if ((*itr
)->GetInstanceID() == m_InstanceID
)
1029 sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].erase(itr
);
1035 // get the number of free slots for team
1036 // works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group
1037 uint32
BattleGround::GetFreeSlotsForTeam(uint32 Team
) const
1039 //if BG is starting ... invite anyone
1040 if (GetStatus() == STATUS_WAIT_JOIN
)
1041 return (GetInvitedCount(Team
) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team
) : 0;
1042 //if BG is already started .. do not allow to join too much players of one faction
1045 if (Team
== ALLIANCE
)
1047 otherTeam
= GetInvitedCount(HORDE
);
1048 otherIn
= GetPlayersCountByTeam(HORDE
);
1052 otherTeam
= GetInvitedCount(ALLIANCE
);
1053 otherIn
= GetPlayersCountByTeam(ALLIANCE
);
1055 if (GetStatus() == STATUS_IN_PROGRESS
)
1057 // difference based on ppl invited (not necessarily entered battle)
1060 // allow join one person if the sides are equal (to fill up bg to minplayersperteam)
1061 if (otherTeam
== GetInvitedCount(Team
))
1063 // allow join more ppl if the other side has more players
1064 else if(otherTeam
> GetInvitedCount(Team
))
1065 diff
= otherTeam
- GetInvitedCount(Team
);
1067 // difference based on max players per team (don't allow inviting more)
1068 uint32 diff2
= (GetInvitedCount(Team
) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team
) : 0;
1070 // difference based on players who already entered
1073 // allow join one person if the sides are equal (to fill up bg minplayersperteam)
1074 if (otherIn
== GetPlayersCountByTeam(Team
))
1076 // allow join more ppl if the other side has more players
1077 else if (otherIn
> GetPlayersCountByTeam(Team
))
1078 diff3
= otherIn
- GetPlayersCountByTeam(Team
);
1079 // or other side has less than minPlayersPerTeam
1080 else if (GetInvitedCount(Team
) <= GetMinPlayersPerTeam())
1081 diff3
= GetMinPlayersPerTeam() - GetInvitedCount(Team
) + 1;
1083 // return the minimum of the 3 differences
1085 // min of diff and diff 2
1086 diff
= diff
< diff2
? diff
: diff2
;
1088 // min of diff, diff2 and diff3
1089 return diff
< diff3
? diff
: diff3
;
1095 bool BattleGround::HasFreeSlots() const
1097 return GetPlayersSize() < GetMaxPlayers();
1100 void BattleGround::UpdatePlayerScore(Player
*Source
, uint32 type
, uint32 value
)
1102 //this procedure is called from virtual function implemented in bg subclass
1103 std::map
<uint64
, BattleGroundScore
*>::iterator itr
= m_PlayerScores
.find(Source
->GetGUID());
1105 if(itr
== m_PlayerScores
.end()) // player not found...
1110 case SCORE_KILLING_BLOWS
: // Killing blows
1111 itr
->second
->KillingBlows
+= value
;
1113 case SCORE_DEATHS
: // Deaths
1114 itr
->second
->Deaths
+= value
;
1116 case SCORE_HONORABLE_KILLS
: // Honorable kills
1117 itr
->second
->HonorableKills
+= value
;
1119 case SCORE_BONUS_HONOR
: // Honor bonus
1120 // do not add honor in arenas
1121 if(isBattleGround())
1123 // reward honor instantly
1124 if(Source
->RewardHonor(NULL
, 1, value
))
1125 itr
->second
->BonusHonor
+= value
;
1128 //used only in EY, but in MSG_PVP_LOG_DATA opcode
1129 case SCORE_DAMAGE_DONE
: // Damage Done
1130 itr
->second
->DamageDone
+= value
;
1132 case SCORE_HEALING_DONE
: // Healing Done
1133 itr
->second
->HealingDone
+= value
;
1136 sLog
.outError("BattleGround: Unknown player score type %u", type
);
1141 void BattleGround::AddPlayerToResurrectQueue(uint64 npc_guid
, uint64 player_guid
)
1143 m_ReviveQueue
[npc_guid
].push_back(player_guid
);
1145 Player
*plr
= objmgr
.GetPlayer(player_guid
);
1149 plr
->CastSpell(plr
, SPELL_WAITING_FOR_RESURRECT
, true);
1150 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( SPELL_WAITING_FOR_RESURRECT
);
1153 Aura
*Aur
= CreateAura(spellInfo
, 0, NULL
, plr
);
1158 void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid
)
1160 for(std::map
<uint64
, std::vector
<uint64
> >::iterator itr
= m_ReviveQueue
.begin(); itr
!= m_ReviveQueue
.end(); ++itr
)
1162 for(std::vector
<uint64
>::iterator itr2
=(itr
->second
).begin(); itr2
!= (itr
->second
).end(); ++itr2
)
1164 if(*itr2
== player_guid
)
1166 (itr
->second
).erase(itr2
);
1168 Player
*plr
= objmgr
.GetPlayer(player_guid
);
1172 plr
->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT
);
1180 bool BattleGround::AddObject(uint32 type
, uint32 entry
, float x
, float y
, float z
, float o
, float rotation0
, float rotation1
, float rotation2
, float rotation3
, uint32 respawnTime
)
1182 Map
* map
= MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
1186 // must be created this way, adding to godatamap would add it to the base map of the instance
1187 // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
1188 // so we must create it specific for this instance
1189 GameObject
* go
= new GameObject
;
1190 if(!go
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
),entry
, map
,
1191 PHASEMASK_NORMAL
, x
,y
,z
,o
,rotation0
,rotation1
,rotation2
,rotation3
,100,1))
1193 sLog
.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry
);
1194 sLog
.outError("Cannot create gameobject template %u! BattleGround not created!", entry
);
1199 uint32 guid = go->GetGUIDLow();
1201 // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
1202 // 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
1203 GameObjectData& data = objmgr.NewGOData(guid);
1206 data.mapid = GetMapId();
1210 data.orientation = o;
1211 data.rotation0 = rotation0;
1212 data.rotation1 = rotation1;
1213 data.rotation2 = rotation2;
1214 data.rotation3 = rotation3;
1215 data.spawntimesecs = respawnTime;
1217 data.animprogress = 100;
1220 // add to world, so it can be later looked up from HashMapHolder
1222 m_BgObjects
[type
] = go
->GetGUID();
1226 //some doors aren't despawned so we cannot handle their closing in gameobject::update()
1227 //it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
1228 void BattleGround::DoorClose(uint32 type
)
1230 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1233 //if doors are open, close it
1234 if( obj
->getLootState() == GO_ACTIVATED
&& !obj
->GetGoState() )
1236 //change state to allow door to be closed
1237 obj
->SetLootState(GO_READY
);
1238 obj
->UseDoorOrButton(RESPAWN_ONE_DAY
);
1243 sLog
.outError("BattleGround: Door object not found (cannot close doors)");
1247 void BattleGround::DoorOpen(uint32 type
)
1249 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1252 //change state to be sure they will be opened
1253 obj
->SetLootState(GO_READY
);
1254 obj
->UseDoorOrButton(RESPAWN_ONE_DAY
);
1258 sLog
.outError("BattleGround: Door object not found! - doors will be closed.");
1262 void BattleGround::SpawnBGObject(uint32 type
, uint32 respawntime
)
1264 Map
* map
= MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
1267 if( respawntime
== 0 )
1269 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1272 //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
1273 if( obj
->getLootState() == GO_JUST_DEACTIVATED
)
1274 obj
->SetLootState(GO_READY
);
1275 obj
->SetRespawnTime(0);
1281 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1285 obj
->SetRespawnTime(respawntime
);
1286 obj
->SetLootState(GO_JUST_DEACTIVATED
);
1291 Creature
* BattleGround::AddCreature(uint32 entry
, uint32 type
, uint32 teamval
, float x
, float y
, float z
, float o
, uint32 respawntime
)
1293 Map
* map
= MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
1297 Creature
* pCreature
= new Creature
;
1298 if (!pCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), map
, PHASEMASK_NORMAL
, entry
, teamval
))
1300 sLog
.outError("Can't create creature entry: %u",entry
);
1305 pCreature
->Relocate(x
, y
, z
, o
);
1307 if(!pCreature
->IsPositionValid())
1309 sLog
.outError("ERROR: Creature (guidlow %d, entry %d) not added to battleground. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature
->GetGUIDLow(),pCreature
->GetEntry(),pCreature
->GetPositionX(),pCreature
->GetPositionY());
1313 pCreature
->AIM_Initialize();
1315 //pCreature->SetDungeonDifficulty(0);
1317 map
->Add(pCreature
);
1318 m_BgCreatures
[type
] = pCreature
->GetGUID();
1323 void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
1325 Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
1329 if(respawntime == 0)
1331 Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1334 //obj->Respawn(); // bugged
1335 obj->SetRespawnTime(0);
1336 objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);
1342 Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1345 obj->setDeathState(DEAD);
1346 obj->SetRespawnTime(respawntime);
1352 bool BattleGround::DelCreature(uint32 type
)
1354 if(!m_BgCreatures
[type
])
1357 Creature
*cr
= HashMapHolder
<Creature
>::Find(m_BgCreatures
[type
]);
1360 sLog
.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures
[type
]));
1363 cr
->CleanupsBeforeDelete();
1364 cr
->AddObjectToRemoveList();
1365 m_BgCreatures
[type
] = 0;
1369 bool BattleGround::DelObject(uint32 type
)
1371 if(!m_BgObjects
[type
])
1374 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1377 sLog
.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects
[type
]));
1380 obj
->SetRespawnTime(0); // not save respawn time
1382 m_BgObjects
[type
] = 0;
1386 bool BattleGround::AddSpiritGuide(uint32 type
, float x
, float y
, float z
, float o
, uint32 team
)
1390 if(team
== ALLIANCE
)
1395 Creature
* pCreature
= AddCreature(entry
,type
,team
,x
,y
,z
,o
);
1398 sLog
.outError("Can't create Spirit guide. BattleGround not created!");
1403 pCreature
->setDeathState(DEAD
);
1405 pCreature
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
, pCreature
->GetGUID());
1407 pCreature
->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL
);
1408 //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
1409 //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
1410 //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
1411 // casting visual effect
1412 pCreature
->SetUInt32Value(UNIT_CHANNEL_SPELL
, SPELL_SPIRIT_HEAL_CHANNEL
);
1413 // correct cast speed
1414 pCreature
->SetFloatValue(UNIT_MOD_CAST_SPEED
, 1.0f
);
1416 //pCreature->CastSpell(pCreature, SPELL_SPIRIT_HEAL_CHANNEL, true);
1421 void BattleGround::SendMessageToAll(char const* text
)
1424 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, text
, NULL
);
1425 SendPacketToAll(&data
);
1428 void BattleGround::SendMessageToAll(int32 entry
)
1430 char const* text
= GetMangosString(entry
);
1432 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, text
, NULL
);
1433 SendPacketToAll(&data
);
1436 void BattleGround::EndNow()
1438 RemoveFromBGFreeSlotQueue();
1439 SetStatus(STATUS_WAIT_LEAVE
);
1440 SetEndTime(TIME_TO_AUTOREMOVE
);
1441 // inform invited players about the removal
1442 sBattleGroundMgr
.m_BattleGroundQueues
[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
1445 // Battleground messages are localized using the dbc lang, they are not client language dependent
1446 const char *BattleGround::GetMangosString(int32 entry
)
1448 // FIXME: now we have different DBC locales and need localized message for each target client
1449 return objmgr
.GetMangosStringForDBCLocale(entry
);
1454 buffs aren't spawned/despawned when players captures anything
1455 buffs are in their positions when battleground starts
1457 void BattleGround::HandleTriggerBuff(uint64
const& go_guid
)
1459 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(go_guid
);
1460 if(!obj
|| obj
->GetGoType() != GAMEOBJECT_TYPE_TRAP
|| !obj
->isSpawned())
1463 //change buff type, when buff is used:
1464 int32 index
= m_BgObjects
.size() - 1;
1465 while (index
>= 0 && m_BgObjects
[index
] != go_guid
)
1469 sLog
.outError("BattleGround (Type: %u) has buff gameobject (Guid: %u Entry: %u Type:%u) but it hasn't that object in its internal data",GetTypeID(),GUID_LOPART(go_guid
),obj
->GetEntry(),obj
->GetGoType());
1473 //randomly select new buff
1474 uint8 buff
= urand(0, 2);
1475 uint32 entry
= obj
->GetEntry();
1476 if( m_BuffChange
&& entry
!= Buff_Entries
[buff
] )
1478 //despawn current buff
1479 SpawnBGObject(index
, RESPAWN_ONE_DAY
);
1480 //set index for new one
1481 for (uint8 currBuffTypeIndex
= 0; currBuffTypeIndex
< 3; ++currBuffTypeIndex
)
1482 if( entry
== Buff_Entries
[currBuffTypeIndex
] )
1484 index
-= currBuffTypeIndex
;
1489 SpawnBGObject(index
, BUFF_RESPAWN_TIME
);
1492 void BattleGround::HandleKillPlayer( Player
*player
, Player
*killer
)
1494 //keep in mind that for arena this will have to be changed a bit
1497 UpdatePlayerScore(player
, SCORE_DEATHS
, 1);
1499 // add +1 kills to group and +1 killing_blows to killer
1502 UpdatePlayerScore(killer
, SCORE_HONORABLE_KILLS
, 1);
1503 UpdatePlayerScore(killer
, SCORE_KILLING_BLOWS
, 1);
1505 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
1507 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
1509 if(!plr
|| plr
== killer
)
1512 if( plr
->GetTeam() == killer
->GetTeam() && plr
->IsAtGroupRewardDistance(player
) )
1513 UpdatePlayerScore(plr
, SCORE_HONORABLE_KILLS
, 1);
1517 // to be able to remove insignia
1518 player
->SetFlag( UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
1521 // return the player's team based on battlegroundplayer info
1522 // used in same faction arena matches mainly
1523 uint32
BattleGround::GetPlayerTeam(uint64 guid
)
1525 std::map
<uint64
, BattleGroundPlayer
>::const_iterator itr
= m_Players
.find(guid
);
1526 if(itr
!=m_Players
.end())
1527 return itr
->second
.Team
;
1531 bool BattleGround::IsPlayerInBattleGround(uint64 guid
)
1533 std::map
<uint64
, BattleGroundPlayer
>::const_iterator itr
= m_Players
.find(guid
);
1534 if(itr
!=m_Players
.end())
1539 void BattleGround::PlayerRelogin(Player
* plr
)
1541 if(GetStatus() != STATUS_WAIT_LEAVE
)
1545 BattleGroundQueueTypeId bgQueueTypeId
= BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
1549 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, this);
1550 plr
->GetSession()->SendPacket(&data
);
1552 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, this, plr
->GetTeam(), plr
->GetBattleGroundQueueIndex(bgQueueTypeId
), STATUS_IN_PROGRESS
, TIME_TO_AUTOREMOVE
, GetStartTime());
1553 plr
->GetSession()->SendPacket(&data
);
1556 uint32
BattleGround::GetAlivePlayersCountByTeam(uint32 Team
) const
1559 for(std::map
<uint64
, BattleGroundPlayer
>::const_iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
1561 if(itr
->second
.Team
== Team
)
1563 Player
* pl
= objmgr
.GetPlayer(itr
->first
);
1564 if(pl
&& pl
->isAlive())
1571 void BattleGround::SetBgRaid( uint32 TeamID
, Group
*bg_raid
)
1573 Group
* &old_raid
= TeamID
== ALLIANCE
? m_BgRaids
[BG_TEAM_ALLIANCE
] : m_BgRaids
[BG_TEAM_HORDE
];
1574 if(old_raid
) old_raid
->SetBattlegroundGroup(NULL
);
1575 if(bg_raid
) bg_raid
->SetBattlegroundGroup(this);