2 * Copyright (C) 2005-2008 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"
23 #include "MapManager.h"
26 #include "SpellAuras.h"
27 #include "ArenaTeam.h"
31 BattleGround::BattleGround()
37 m_LastResurrectTime
= 0;
38 m_Queue_type
= MAX_BATTLEGROUND_QUEUES
;
39 m_InvitedAlliance
= 0;
51 m_InBGFreeSlotQueue
= false;
52 m_SetDeleteThis
= false;
54 m_MaxPlayersPerTeam
= 0;
56 m_MinPlayersPerTeam
= 0;
61 m_TeamStartLocX
[BG_TEAM_ALLIANCE
] = 0;
62 m_TeamStartLocX
[BG_TEAM_HORDE
] = 0;
64 m_TeamStartLocY
[BG_TEAM_ALLIANCE
] = 0;
65 m_TeamStartLocY
[BG_TEAM_HORDE
] = 0;
67 m_TeamStartLocZ
[BG_TEAM_ALLIANCE
] = 0;
68 m_TeamStartLocZ
[BG_TEAM_HORDE
] = 0;
70 m_TeamStartLocO
[BG_TEAM_ALLIANCE
] = 0;
71 m_TeamStartLocO
[BG_TEAM_HORDE
] = 0;
73 m_ArenaTeamIds
[BG_TEAM_ALLIANCE
] = 0;
74 m_ArenaTeamIds
[BG_TEAM_HORDE
] = 0;
76 m_ArenaTeamRatingChanges
[BG_TEAM_ALLIANCE
] = 0;
77 m_ArenaTeamRatingChanges
[BG_TEAM_HORDE
] = 0;
79 m_BgRaids
[BG_TEAM_ALLIANCE
] = NULL
;
80 m_BgRaids
[BG_TEAM_HORDE
] = NULL
;
82 m_PlayersCount
[BG_TEAM_ALLIANCE
] = 0;
83 m_PlayersCount
[BG_TEAM_HORDE
] = 0;
85 m_PrematureCountDown
= false;
86 m_PrematureCountDown
= 0;
89 BattleGround::~BattleGround()
91 // remove objects and creatures
92 // (this is done automatically in mapmanager update, when the instance is reset after the reset time)
93 int size
= m_BgCreatures
.size();
94 for(int i
= 0; i
< size
; ++i
)
98 size
= m_BgObjects
.size();
99 for(int i
= 0; i
< size
; ++i
)
104 // delete creature and go respawn times
105 WorldDatabase
.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
106 WorldDatabase
.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID());
107 // delete instance from db
108 CharacterDatabase
.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID());
109 // remove from battlegrounds
110 sBattleGroundMgr
.RemoveBattleGround(GetInstanceID());
112 if(Map
* map
= MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
113 if(map
->IsBattleGroundOrArena())
114 ((BattleGroundMap
*)map
)->SetUnload();
115 // remove from bg free slot queue
116 this->RemoveFromBGFreeSlotQueue();
119 void BattleGround::Update(time_t diff
)
121 if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
127 if(GetRemovedPlayersSize())
129 for(std::map
<uint64
, uint8
>::iterator itr
= m_RemovedPlayers
.begin(); itr
!= m_RemovedPlayers
.end(); ++itr
)
131 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
134 //following code is handled by event:
136 sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first);
137 //RemovePlayerFromQueue(itr->first);
140 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
141 plr->GetSession()->SendPacket(&data);
144 case 1: // currently in bg and was removed from bg
146 RemovePlayerAtLeave(itr
->first
, true, true);
148 RemovePlayerAtLeave(itr
->first
, false, false);
150 case 2: // revive queue
151 RemovePlayerFromResurrectQueue(itr
->first
);
154 sLog
.outError("BattleGround: Unknown remove player case!");
157 m_RemovedPlayers
.clear();
160 // this code isn't efficient and its idea isn't implemented yet
161 /* offline players are removed from battleground in worldsession::LogoutPlayer()
162 // remove offline players from bg after ~5 minutes
165 for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
167 Player *plr = objmgr.GetPlayer(itr->first);
168 itr->second.LastOnlineTime += diff;
171 itr->second.LastOnlineTime = 0; // update last online time
173 if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes
174 m_RemovedPlayers[itr->first] = 1; // add to remove list (BG)
178 m_LastResurrectTime
+= diff
;
179 if (m_LastResurrectTime
>= RESURRECTION_INTERVAL
)
181 if(GetReviveQueueSize())
183 for(std::map
<uint64
, std::vector
<uint64
> >::iterator itr
= m_ReviveQueue
.begin(); itr
!= m_ReviveQueue
.end(); ++itr
)
186 for(std::vector
<uint64
>::iterator itr2
= (itr
->second
).begin(); itr2
!= (itr
->second
).end(); ++itr2
)
188 Player
*plr
= objmgr
.GetPlayer(*itr2
);
194 sh
= ObjectAccessor::GetCreature(*plr
, itr
->first
);
195 // only for visual effect
197 sh
->CastSpell(sh
, SPELL_SPIRIT_HEAL
, true); // Spirit Heal, effect 117
200 plr
->CastSpell(plr
, SPELL_RESURRECTION_VISUAL
, true); // Resurrection visual
201 m_ResurrectQueue
.push_back(*itr2
);
203 (itr
->second
).clear();
206 m_ReviveQueue
.clear();
207 m_LastResurrectTime
= 0;
210 // queue is clear and time passed, just update last resurrection time
211 m_LastResurrectTime
= 0;
213 else if (m_LastResurrectTime
> 500) // Resurrect players only half a second later, to see spirit heal effect on NPC
215 for(std::vector
<uint64
>::iterator itr
= m_ResurrectQueue
.begin(); itr
!= m_ResurrectQueue
.end(); ++itr
)
217 Player
*plr
= objmgr
.GetPlayer(*itr
);
220 plr
->ResurrectPlayer(1.0f
);
221 plr
->CastSpell(plr
, SPELL_SPIRIT_HEAL_MANA
, true);
222 ObjectAccessor::Instance().ConvertCorpseForPlayer(*itr
);
224 m_ResurrectQueue
.clear();
227 // if less then minimum players are in on one side, then start premature finish timer
228 if(GetStatus() == STATUS_IN_PROGRESS
&& !isArena() && sBattleGroundMgr
.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE
) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE
) < GetMinPlayersPerTeam()))
230 if(!m_PrematureCountDown
)
232 m_PrematureCountDown
= true;
233 m_PrematureCountDownTimer
= sBattleGroundMgr
.GetPrematureFinishTime();
234 SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
);
236 else if(m_PrematureCountDownTimer
< diff
)
239 EndBattleGround(0); // noone wins
240 m_PrematureCountDown
= false;
244 uint32 newtime
= m_PrematureCountDownTimer
- diff
;
245 // announce every minute
246 if(m_PrematureCountDownTimer
!= sBattleGroundMgr
.GetPrematureFinishTime() && newtime
/ 60000 != m_PrematureCountDownTimer
/ 60000)
247 SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING
);
248 m_PrematureCountDownTimer
= newtime
;
251 else if (m_PrematureCountDown
)
252 m_PrematureCountDown
= false;
254 if(GetStatus() == STATUS_WAIT_LEAVE
)
256 // remove all players from battleground after 2 minutes
258 if(m_EndTime
>= TIME_TO_AUTOREMOVE
) // 2 minutes
260 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
262 m_RemovedPlayers
[itr
->first
] = 1; // add to remove list (BG)
264 // do not change any battleground's private variables
269 void BattleGround::SetTeamStartLoc(uint32 TeamID
, float X
, float Y
, float Z
, float O
)
271 uint8 idx
= GetTeamIndexByTeamId(TeamID
);
272 m_TeamStartLocX
[idx
] = X
;
273 m_TeamStartLocY
[idx
] = Y
;
274 m_TeamStartLocZ
[idx
] = Z
;
275 m_TeamStartLocO
[idx
] = O
;
278 void BattleGround::SendPacketToAll(WorldPacket
*packet
)
280 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
282 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
284 plr
->GetSession()->SendPacket(packet
);
286 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
290 void BattleGround::SendPacketToTeam(uint32 TeamID
, WorldPacket
*packet
, Player
*sender
, bool self
)
292 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
294 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
298 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
302 if(!self
&& sender
== plr
)
305 uint32 team
= itr
->second
.Team
;//GetPlayerTeam(plr->GetGUID());
306 if(!team
) team
= plr
->GetTeam();
309 plr
->GetSession()->SendPacket(packet
);
313 void BattleGround::PlaySoundToAll(uint32 SoundID
)
316 sBattleGroundMgr
.BuildPlaySoundPacket(&data
, SoundID
);
317 SendPacketToAll(&data
);
320 void BattleGround::PlaySoundToTeam(uint32 SoundID
, uint32 TeamID
)
324 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
326 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
330 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
334 uint32 team
= itr
->second
.Team
;//GetPlayerTeam(plr->GetGUID());
335 if(!team
) team
= plr
->GetTeam();
339 sBattleGroundMgr
.BuildPlaySoundPacket(&data
, SoundID
);
340 plr
->GetSession()->SendPacket(&data
);
345 void BattleGround::CastSpellOnTeam(uint32 SpellID
, uint32 TeamID
)
347 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
349 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
353 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
357 uint32 team
= itr
->second
.Team
;//GetPlayerTeam(plr->GetGUID());
358 if(!team
) team
= plr
->GetTeam();
361 plr
->CastSpell(plr
, SpellID
, true);
365 void BattleGround::RewardHonorToTeam(uint32 Honor
, uint32 TeamID
)
367 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
369 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
373 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
377 uint32 team
= itr
->second
.Team
;//GetPlayerTeam(plr->GetGUID());
378 if(!team
) team
= plr
->GetTeam();
381 UpdatePlayerScore(plr
, SCORE_BONUS_HONOR
, Honor
);
385 void BattleGround::RewardReputationToTeam(uint32 faction_id
, uint32 Reputation
, uint32 TeamID
)
387 FactionEntry
const* factionEntry
= sFactionStore
.LookupEntry(faction_id
);
392 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
394 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
398 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
402 uint32 team
= itr
->second
.Team
;//GetPlayerTeam(plr->GetGUID());
403 if(!team
) team
= plr
->GetTeam();
406 plr
->ModifyFactionReputation(factionEntry
, Reputation
);
410 void BattleGround::UpdateWorldState(uint32 Field
, uint32 Value
)
413 sBattleGroundMgr
.BuildUpdateWorldStatePacket(&data
, Field
, Value
);
414 SendPacketToAll(&data
);
417 void BattleGround::UpdateWorldStateForPlayer(uint32 Field
, uint32 Value
, Player
*Source
)
420 sBattleGroundMgr
.BuildUpdateWorldStatePacket(&data
, Field
, Value
);
421 Source
->GetSession()->SendPacket(&data
);
424 void BattleGround::EndBattleGround(uint32 winner
)
426 this->RemoveFromBGFreeSlotQueue();
428 ArenaTeam
* winner_arena_team
= NULL
;
429 ArenaTeam
* loser_arena_team
= NULL
;
430 uint32 loser_rating
= 0;
431 uint32 winner_rating
= 0;
433 Player
*Source
= NULL
;
434 const char *winmsg
= "";
436 if(winner
== ALLIANCE
)
439 winmsg
= GetMangosString(LANG_BG_A_WINS
);
441 winmsg
= GetMangosString(LANG_ARENA_GOLD_WINS
);
443 PlaySoundToAll(SOUND_ALLIANCE_WINS
); // alliance wins sound
445 SetWinner(WINNER_ALLIANCE
);
447 else if(winner
== HORDE
)
450 winmsg
= GetMangosString(LANG_BG_H_WINS
);
452 winmsg
= GetMangosString(LANG_ARENA_GREEN_WINS
);
454 PlaySoundToAll(SOUND_HORDE_WINS
); // horde wins sound
456 SetWinner(WINNER_HORDE
);
463 SetStatus(STATUS_WAIT_LEAVE
);
466 // arena rating calculation
467 if(isArena() && isRated())
469 if(winner
== ALLIANCE
)
471 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
472 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
474 else if(winner
== HORDE
)
476 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
477 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
479 if(winner_arena_team
&& loser_arena_team
)
481 loser_rating
= loser_arena_team
->GetStats().rating
;
482 winner_rating
= winner_arena_team
->GetStats().rating
;
483 int32 winner_change
= winner_arena_team
->WonAgainst(loser_rating
);
484 int32 loser_change
= loser_arena_team
->LostAgainst(winner_rating
);
485 sLog
.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating
, loser_rating
, winner_change
, loser_change
);
486 if(winner
== ALLIANCE
)
488 SetArenaTeamRatingChangeForTeam(ALLIANCE
, winner_change
);
489 SetArenaTeamRatingChangeForTeam(HORDE
, loser_change
);
493 SetArenaTeamRatingChangeForTeam(HORDE
, winner_change
);
494 SetArenaTeamRatingChangeForTeam(ALLIANCE
, loser_change
);
499 SetArenaTeamRatingChangeForTeam(ALLIANCE
, 0);
500 SetArenaTeamRatingChangeForTeam(HORDE
, 0);
504 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
506 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
509 sLog
.outError("BattleGround: Player " I64FMTD
" not found!", itr
->first
);
513 // should remove spirit of redemption
514 if(plr
->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION
))
515 plr
->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT
);
519 plr
->ResurrectPlayer(1.0f
);
520 plr
->SpawnCorpseBones();
523 uint32 team
= itr
->second
.Team
;
524 if(!team
) team
= plr
->GetTeam();
526 // per player calculation
527 if(isArena() && isRated() && winner_arena_team
&& loser_arena_team
)
530 winner_arena_team
->MemberWon(plr
,loser_rating
);
532 loser_arena_team
->MemberLost(plr
,winner_rating
);
539 RewardMark(plr
,ITEM_WINNER_COUNT
);
540 UpdatePlayerScore(plr
, SCORE_BONUS_HONOR
, 20);
545 RewardMark(plr
,ITEM_LOSER_COUNT
);
548 plr
->CombatStopWithPets(true);
552 sBattleGroundMgr
.BuildPvpLogDataPacket(&data
, this);
553 plr
->GetSession()->SendPacket(&data
);
555 uint32 bgQueueTypeId
= sBattleGroundMgr
.BGQueueTypeId(GetTypeID(), GetArenaType());
556 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, this, plr
->GetTeam(), plr
->GetBattleGroundQueueIndex(bgQueueTypeId
), STATUS_IN_PROGRESS
, TIME_TO_AUTOREMOVE
, GetStartTime());
557 plr
->GetSession()->SendPacket(&data
);
560 if(isArena() && isRated() && winner_arena_team
&& loser_arena_team
)
562 // update arena points only after increasing the player's match count!
563 //obsolete: winner_arena_team->UpdateArenaPointsHelper();
564 //obsolete: loser_arena_team->UpdateArenaPointsHelper();
565 // save the stat changes
566 winner_arena_team
->SaveToDB();
567 loser_arena_team
->SaveToDB();
568 // send updated arena team stats to players
569 // this way all arena team members will get notified, not only the ones who participated in this match
570 winner_arena_team
->NotifyStatsChanged();
571 loser_arena_team
->NotifyStatsChanged();
574 // inform invited players about the removal
575 sBattleGroundMgr
.m_BattleGroundQueues
[sBattleGroundMgr
.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
579 ChatHandler(Source
).FillMessageData(&data
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, Source
->GetGUID(), winmsg
);
580 SendPacketToAll(&data
);
584 uint32
BattleGround::GetBattlemasterEntry() const
588 case BATTLEGROUND_AV
: return 15972;
589 case BATTLEGROUND_WS
: return 14623;
590 case BATTLEGROUND_AB
: return 14879;
591 case BATTLEGROUND_EY
: return 22516;
592 case BATTLEGROUND_NA
: return 20200;
597 void BattleGround::RewardMark(Player
*plr
,uint32 count
)
599 // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
600 if(plr
->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE
))
603 BattleGroundMarks mark
;
607 case BATTLEGROUND_AV
:
609 if(count
== ITEM_WINNER_COUNT
)
610 mark
= SPELL_AV_MARK_WINNER
;
612 mark
= SPELL_AV_MARK_LOSER
;
614 case BATTLEGROUND_WS
:
616 if(count
== ITEM_WINNER_COUNT
)
617 mark
= SPELL_WS_MARK_WINNER
;
619 mark
= SPELL_WS_MARK_LOSER
;
621 case BATTLEGROUND_AB
:
623 if(count
== ITEM_WINNER_COUNT
)
624 mark
= SPELL_AB_MARK_WINNER
;
626 mark
= SPELL_AB_MARK_LOSER
;
628 case BATTLEGROUND_EY
:
630 mark
= ITEM_EY_MARK_OF_HONOR
;
637 plr
->CastSpell(plr
, mark
, true);
638 else if ( objmgr
.GetItemPrototype( mark
) )
640 ItemPosCountVec dest
;
641 uint32 no_space_count
= 0;
642 uint8 msg
= plr
->CanStoreNewItem( NULL_BAG
, NULL_SLOT
, dest
, mark
, count
, &no_space_count
);
643 if( msg
!= EQUIP_ERR_OK
) // convert to possible store amount
644 count
-= no_space_count
;
646 if( count
!= 0 && !dest
.empty()) // can add some
647 if(Item
* item
= plr
->StoreNewItem( dest
, mark
, true, 0))
648 plr
->SendNewItem(item
,count
,false,true);
650 if(no_space_count
> 0)
651 SendRewardMarkByMail(plr
,mark
,no_space_count
);
655 void BattleGround::SendRewardMarkByMail(Player
*plr
,uint32 mark
, uint32 count
)
657 uint32 bmEntry
= GetBattlemasterEntry();
661 ItemPrototype
const* markProto
= objmgr
.GetItemPrototype(mark
);
665 if(Item
* markItem
= Item::CreateItem(mark
,count
,plr
))
667 // save new item before send
668 markItem
->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
672 mi
.AddItem(markItem
->GetGUIDLow(), markItem
->GetEntry(), markItem
);
674 // subject: item name
675 std::string subject
= markProto
->Name1
;
676 int loc_idx
= plr
->GetSession()->GetSessionDbLocaleIndex();
678 if(ItemLocale
const *il
= objmgr
.GetItemLocale(markProto
->ItemId
))
679 if (il
->Name
.size() > size_t(loc_idx
) && !il
->Name
[loc_idx
].empty())
680 subject
= il
->Name
[loc_idx
];
683 std::string textFormat
= plr
->GetSession()->GetMangosString(LANG_BG_MARK_BY_MAIL
);
685 snprintf(textBuf
,300,textFormat
.c_str(),GetName(),GetName());
686 uint32 itemTextId
= objmgr
.CreateItemText( textBuf
);
688 WorldSession::SendMailTo(plr
, MAIL_CREATURE
, MAIL_STATIONERY_NORMAL
, bmEntry
, plr
->GetGUIDLow(), subject
, itemTextId
, &mi
, 0, 0, MAIL_CHECK_MASK_NONE
);
692 void BattleGround::RewardQuest(Player
*plr
)
694 // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
695 if(plr
->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE
))
701 case BATTLEGROUND_AV
:
702 quest
= SPELL_AV_QUEST_REWARD
;
704 case BATTLEGROUND_WS
:
705 quest
= SPELL_WS_QUEST_REWARD
;
707 case BATTLEGROUND_AB
:
708 quest
= SPELL_AB_QUEST_REWARD
;
710 case BATTLEGROUND_EY
:
711 quest
= SPELL_EY_QUEST_REWARD
;
717 plr
->CastSpell(plr
, quest
, true);
720 void BattleGround::BlockMovement(Player
*plr
)
722 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()
725 void BattleGround::RemovePlayerAtLeave(uint64 guid
, bool Transport
, bool SendPacket
)
727 uint32 team
= GetPlayerTeam(guid
);
728 bool participant
= false;
729 // Remove from lists/maps
730 std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.find(guid
);
731 if(itr
!= m_Players
.end())
733 UpdatePlayersCountByTeam(team
, true); // -1 player
734 m_Players
.erase(itr
);
735 // check if the player was a participant of the match, or only entered through gm command (goname)
739 std::map
<uint64
, BattleGroundScore
*>::iterator itr2
= m_PlayerScores
.find(guid
);
740 if(itr2
!= m_PlayerScores
.end())
742 delete itr2
->second
; // delete player's score
743 m_PlayerScores
.erase(itr2
);
746 RemovePlayerFromResurrectQueue(guid
);
748 Player
*plr
= objmgr
.GetPlayer(guid
);
750 // should remove spirit of redemption
751 if(plr
&& plr
->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION
))
752 plr
->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT
);
754 if(plr
&& !plr
->isAlive()) // resurrect on exit
756 plr
->ResurrectPlayer(1.0f
);
757 plr
->SpawnCorpseBones();
760 RemovePlayer(plr
, guid
); // BG subclass specific code
764 plr
->ClearAfkReports();
766 if(participant
) // if the player was a match participant, remove auras, calc rating, update queue
768 if(!team
) team
= plr
->GetTeam();
770 uint32 bgTypeId
= GetTypeID();
771 uint32 bgQueueTypeId
= sBattleGroundMgr
.BGQueueTypeId(GetTypeID(), GetArenaType());
772 // if arena, remove the specific arena auras
775 plr
->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
776 bgTypeId
=BATTLEGROUND_AA
; // set the bg type to all arenas (it will be used for queue refreshing)
778 // summon old pet if there was one and there isn't a current pet
779 if(!plr
->GetPet() && plr
->GetTemporaryUnsummonedPetNumber())
781 Pet
* NewPet
= new Pet
;
782 if(!NewPet
->LoadPetFromDB(plr
, 0, (plr
)->GetTemporaryUnsummonedPetNumber(), true))
785 (plr
)->SetTemporaryUnsummonedPetNumber(0);
788 if(isRated() && GetStatus() == STATUS_IN_PROGRESS
)
790 //left a rated match while the encounter was in progress, consider as loser
791 ArenaTeam
* winner_arena_team
= 0;
792 ArenaTeam
* loser_arena_team
= 0;
795 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
796 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
800 winner_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE
));
801 loser_arena_team
= objmgr
.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE
));
803 if(winner_arena_team
&& loser_arena_team
)
805 loser_arena_team
->MemberLost(plr
,winner_arena_team
->GetRating());
813 sBattleGroundMgr
.BuildBattleGroundStatusPacket(&data
, this, team
, plr
->GetBattleGroundQueueIndex(bgQueueTypeId
), STATUS_NONE
, 0, 0);
814 plr
->GetSession()->SendPacket(&data
);
817 // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
818 plr
->RemoveBattleGroundQueueId(bgQueueTypeId
);
820 DecreaseInvitedCount(team
);
821 //we should update battleground queue, but only if bg isn't ending
822 if (GetQueueType() < MAX_BATTLEGROUND_QUEUES
)
823 sBattleGroundMgr
.m_BattleGroundQueues
[bgQueueTypeId
].Update(bgTypeId
, GetQueueType());
825 Group
* group
= plr
->GetGroup();
826 // remove from raid group if exist
827 if(group
&& group
== GetBgRaid(team
))
829 if(!group
->RemoveMember(guid
, 0)) // group was disbanded
831 SetBgRaid(team
, NULL
);
837 sBattleGroundMgr
.BuildPlayerLeftBattleGroundPacket(&data
, plr
);
838 SendPacketToTeam(team
, &data
, plr
, false);
841 // Do next only if found in battleground
842 plr
->SetBattleGroundId(0); // We're not in BG.
843 // reset destination bg team
848 plr
->TeleportTo(plr
->GetBattleGroundEntryPointMap(), plr
->GetBattleGroundEntryPointX(), plr
->GetBattleGroundEntryPointY(), plr
->GetBattleGroundEntryPointZ(), plr
->GetBattleGroundEntryPointO());
852 sLog
.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr
->GetName());
855 if(!GetPlayersSize() && !GetInvitedCount(HORDE
) && !GetInvitedCount(ALLIANCE
))
857 // if no players left AND no invitees left, set this bg to delete in next update
858 // direct deletion could cause crashes
859 m_SetDeleteThis
= true;
860 // return to prevent addition to freeslotqueue
864 // a player exited the battleground, so there are free slots. add to queue
865 this->AddToBGFreeSlotQueue();
868 // this method is called when no players remains in battleground
869 void BattleGround::Reset()
871 SetQueueType(MAX_BATTLEGROUND_QUEUES
);
872 SetWinner(WINNER_NONE
);
873 SetStatus(STATUS_WAIT_QUEUE
);
876 SetLastResurrectTime(0);
882 if (m_InvitedAlliance
> 0 || m_InvitedHorde
> 0)
883 sLog
.outError("BattleGround system ERROR: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance
, m_InvitedHorde
);
885 m_InvitedAlliance
= 0;
887 m_InBGFreeSlotQueue
= false;
890 m_PlayerScores
.clear();
896 void BattleGround::StartBattleGround()
898 ///this method should spawn spirit guides and so on
901 SetLastResurrectTime(0);
904 void BattleGround::AddPlayer(Player
*plr
)
906 // score struct must be created in inherited class
908 uint64 guid
= plr
->GetGUID();
909 uint32 team
= plr
->GetBGTeam();
911 BattleGroundPlayer bp
;
912 bp
.LastOnlineTime
= 0;
916 m_Players
[guid
] = bp
;
918 UpdatePlayersCountByTeam(team
, false); // +1 player
921 sBattleGroundMgr
.BuildPlayerJoinedBattleGroundPacket(&data
, plr
);
922 SendPacketToTeam(team
, &data
, plr
, false);
924 // add arena specific auras
927 plr
->RemoveArenaSpellCooldowns();
928 plr
->RemoveArenaAuras();
929 plr
->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT
);
930 if(team
== ALLIANCE
) // gold
932 if(plr
->GetTeam() == HORDE
)
933 plr
->CastSpell(plr
, SPELL_HORDE_GOLD_FLAG
,true);
935 plr
->CastSpell(plr
, SPELL_ALLIANCE_GOLD_FLAG
,true);
939 if(plr
->GetTeam() == HORDE
)
940 plr
->CastSpell(plr
, SPELL_HORDE_GREEN_FLAG
,true);
942 plr
->CastSpell(plr
, SPELL_ALLIANCE_GREEN_FLAG
,true);
945 plr
->DestroyConjuredItems(true);
947 Pet
* pet
= plr
->GetPet();
950 if(pet
->getPetType() == SUMMON_PET
|| pet
->getPetType() == HUNTER_PET
)
952 (plr
)->SetTemporaryUnsummonedPetNumber(pet
->GetCharmInfo()->GetPetNumber());
953 (plr
)->SetOldPetSpell(pet
->GetUInt32Value(UNIT_CREATED_BY_SPELL
));
955 (plr
)->RemovePet(NULL
,PET_SAVE_NOT_IN_SLOT
);
958 (plr
)->SetTemporaryUnsummonedPetNumber(0);
960 if(GetStatus() == STATUS_WAIT_JOIN
) // not started yet
962 plr
->CastSpell(plr
, SPELL_ARENA_PREPARATION
, true);
964 plr
->SetHealth(plr
->GetMaxHealth());
965 plr
->SetPower(POWER_MANA
, plr
->GetMaxPower(POWER_MANA
));
970 if(GetStatus() == STATUS_WAIT_JOIN
) // not started yet
971 plr
->CastSpell(plr
, SPELL_PREPARATION
, true); // reduces all mana cost of spells.
975 sLog
.outDetail("BATTLEGROUND: Player %s joined the battle.", plr
->GetName());
978 /* This method should be called only once ... it adds pointer to queue */
979 void BattleGround::AddToBGFreeSlotQueue()
981 // make sure to add only once
982 if(!m_InBGFreeSlotQueue
)
984 sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].push_front(this);
985 m_InBGFreeSlotQueue
= true;
989 /* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/
990 void BattleGround::RemoveFromBGFreeSlotQueue()
992 // set to be able to re-add if needed
993 m_InBGFreeSlotQueue
= false;
994 // uncomment this code when battlegrounds will work like instances
995 for (std::deque
<BattleGround
*>::iterator itr
= sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].begin(); itr
!= sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].end(); ++itr
)
997 if ((*itr
)->GetInstanceID() == m_InstanceID
)
999 sBattleGroundMgr
.BGFreeSlotQueue
[m_TypeID
].erase(itr
);
1005 // get the number of free slots for team
1006 // works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group
1007 uint32
BattleGround::GetFreeSlotsForTeam(uint32 Team
) const
1009 //if BG is starting ... invite anyone
1010 if (GetStatus() == STATUS_WAIT_JOIN
)
1011 return (GetInvitedCount(Team
) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team
) : 0;
1012 //if BG is already started .. do not allow to join too much players of one faction
1015 if (Team
== ALLIANCE
)
1017 otherTeam
= GetInvitedCount(HORDE
);
1018 otherIn
= GetPlayersCountByTeam(HORDE
);
1022 otherTeam
= GetInvitedCount(ALLIANCE
);
1023 otherIn
= GetPlayersCountByTeam(ALLIANCE
);
1025 if (GetStatus() == STATUS_IN_PROGRESS
)
1027 // difference based on ppl invited (not necessarily entered battle)
1030 // allow join one person if the sides are equal (to fill up bg to minplayersperteam)
1031 if (otherTeam
== GetInvitedCount(Team
))
1033 // allow join more ppl if the other side has more players
1034 else if(otherTeam
> GetInvitedCount(Team
))
1035 diff
= otherTeam
- GetInvitedCount(Team
);
1037 // difference based on max players per team (don't allow inviting more)
1038 uint32 diff2
= (GetInvitedCount(Team
) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team
) : 0;
1040 // difference based on players who already entered
1043 // allow join one person if the sides are equal (to fill up bg minplayersperteam)
1044 if (otherIn
== GetPlayersCountByTeam(Team
))
1046 // allow join more ppl if the other side has more players
1047 else if (otherIn
> GetPlayersCountByTeam(Team
))
1048 diff3
= otherIn
- GetPlayersCountByTeam(Team
);
1049 // or other side has less than minPlayersPerTeam
1050 else if (GetInvitedCount(Team
) <= GetMinPlayersPerTeam())
1051 diff3
= GetMinPlayersPerTeam() - GetInvitedCount(Team
) + 1;
1053 // return the minimum of the 3 differences
1055 // min of diff and diff 2
1056 diff
= diff
< diff2
? diff
: diff2
;
1058 // min of diff, diff2 and diff3
1059 return diff
< diff3
? diff
: diff3
;
1065 bool BattleGround::HasFreeSlots() const
1067 return GetPlayersSize() < GetMaxPlayers();
1070 void BattleGround::UpdatePlayerScore(Player
*Source
, uint32 type
, uint32 value
)
1072 //this procedure is called from virtual function implemented in bg subclass
1073 std::map
<uint64
, BattleGroundScore
*>::iterator itr
= m_PlayerScores
.find(Source
->GetGUID());
1075 if(itr
== m_PlayerScores
.end()) // player not found...
1080 case SCORE_KILLING_BLOWS
: // Killing blows
1081 itr
->second
->KillingBlows
+= value
;
1083 case SCORE_DEATHS
: // Deaths
1084 itr
->second
->Deaths
+= value
;
1086 case SCORE_HONORABLE_KILLS
: // Honorable kills
1087 itr
->second
->HonorableKills
+= value
;
1089 case SCORE_BONUS_HONOR
: // Honor bonus
1090 // do not add honor in arenas
1091 if(isBattleGround())
1093 // reward honor instantly
1094 if(Source
->RewardHonor(NULL
, 1, value
))
1095 itr
->second
->BonusHonor
+= value
;
1098 //used only in EY, but in MSG_PVP_LOG_DATA opcode
1099 case SCORE_DAMAGE_DONE
: // Damage Done
1100 itr
->second
->DamageDone
+= value
;
1102 case SCORE_HEALING_DONE
: // Healing Done
1103 itr
->second
->HealingDone
+= value
;
1106 sLog
.outError("BattleGround: Unknown player score type %u", type
);
1111 void BattleGround::AddPlayerToResurrectQueue(uint64 npc_guid
, uint64 player_guid
)
1113 m_ReviveQueue
[npc_guid
].push_back(player_guid
);
1115 Player
*plr
= objmgr
.GetPlayer(player_guid
);
1119 plr
->CastSpell(plr
, SPELL_WAITING_FOR_RESURRECT
, true);
1120 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry( SPELL_WAITING_FOR_RESURRECT
);
1123 Aura
*Aur
= CreateAura(spellInfo
, 0, NULL
, plr
);
1128 void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid
)
1130 for(std::map
<uint64
, std::vector
<uint64
> >::iterator itr
= m_ReviveQueue
.begin(); itr
!= m_ReviveQueue
.end(); ++itr
)
1132 for(std::vector
<uint64
>::iterator itr2
=(itr
->second
).begin(); itr2
!= (itr
->second
).end(); ++itr2
)
1134 if(*itr2
== player_guid
)
1136 (itr
->second
).erase(itr2
);
1138 Player
*plr
= objmgr
.GetPlayer(player_guid
);
1142 plr
->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT
);
1150 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
)
1152 Map
* map
= MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
1156 // must be created this way, adding to godatamap would add it to the base map of the instance
1157 // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
1158 // so we must create it specific for this instance
1159 GameObject
* go
= new GameObject
;
1160 if(!go
->Create(objmgr
.GenerateLowGuid(HIGHGUID_GAMEOBJECT
),entry
, map
,x
,y
,z
,o
,rotation0
,rotation1
,rotation2
,rotation3
,100,1))
1162 sLog
.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry
);
1163 sLog
.outError("Cannot create gameobject template %u! BattleGround not created!", entry
);
1168 uint32 guid = go->GetGUIDLow();
1170 // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
1171 // 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
1172 GameObjectData& data = objmgr.NewGOData(guid);
1175 data.mapid = GetMapId();
1179 data.orientation = o;
1180 data.rotation0 = rotation0;
1181 data.rotation1 = rotation1;
1182 data.rotation2 = rotation2;
1183 data.rotation3 = rotation3;
1184 data.spawntimesecs = respawnTime;
1186 data.animprogress = 100;
1189 // add to world, so it can be later looked up from HashMapHolder
1191 m_BgObjects
[type
] = go
->GetGUID();
1195 //some doors aren't despawned so we cannot handle their closing in gameobject::update()
1196 //it would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
1197 void BattleGround::DoorClose(uint32 type
)
1199 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1202 //if doors are open, close it
1203 if( obj
->getLootState() == GO_ACTIVATED
&& !obj
->GetGoState() )
1205 //change state to allow door to be closed
1206 obj
->SetLootState(GO_READY
);
1207 obj
->UseDoorOrButton(RESPAWN_ONE_DAY
);
1212 sLog
.outError("BattleGround: Door object not found (cannot close doors)");
1216 void BattleGround::DoorOpen(uint32 type
)
1218 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1221 //change state to be sure they will be opened
1222 obj
->SetLootState(GO_READY
);
1223 obj
->UseDoorOrButton(RESPAWN_ONE_DAY
);
1227 sLog
.outError("BattleGround: Door object not found! - doors will be closed.");
1231 void BattleGround::SpawnBGObject(uint32 type
, uint32 respawntime
)
1233 Map
* map
= MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
1236 if( respawntime
== 0 )
1238 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1241 //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
1242 if( obj
->getLootState() == GO_JUST_DEACTIVATED
)
1243 obj
->SetLootState(GO_READY
);
1244 obj
->SetRespawnTime(0);
1250 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1254 obj
->SetRespawnTime(respawntime
);
1255 obj
->SetLootState(GO_JUST_DEACTIVATED
);
1260 Creature
* BattleGround::AddCreature(uint32 entry
, uint32 type
, uint32 teamval
, float x
, float y
, float z
, float o
, uint32 respawntime
)
1262 Map
* map
= MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
1266 Creature
* pCreature
= new Creature
;
1267 if (!pCreature
->Create(objmgr
.GenerateLowGuid(HIGHGUID_UNIT
), map
, entry
, teamval
))
1269 sLog
.outError("Can't create creature entry: %u",entry
);
1274 pCreature
->Relocate(x
, y
, z
, o
);
1276 if(!pCreature
->IsPositionValid())
1278 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());
1282 pCreature
->AIM_Initialize();
1284 //pCreature->SetDungeonDifficulty(0);
1286 map
->Add(pCreature
);
1287 m_BgCreatures
[type
] = pCreature
->GetGUID();
1292 void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
1294 Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
1298 if(respawntime == 0)
1300 Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1303 //obj->Respawn(); // bugged
1304 obj->SetRespawnTime(0);
1305 objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);
1311 Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1314 obj->setDeathState(DEAD);
1315 obj->SetRespawnTime(respawntime);
1321 bool BattleGround::DelCreature(uint32 type
)
1323 Creature
*cr
= HashMapHolder
<Creature
>::Find(m_BgCreatures
[type
]);
1326 sLog
.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures
[type
]));
1329 cr
->CleanupsBeforeDelete();
1330 cr
->AddObjectToRemoveList();
1331 m_BgCreatures
[type
] = 0;
1335 bool BattleGround::DelObject(uint32 type
)
1337 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(m_BgObjects
[type
]);
1340 sLog
.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects
[type
]));
1343 obj
->SetRespawnTime(0); // not save respawn time
1345 m_BgObjects
[type
] = 0;
1349 bool BattleGround::AddSpiritGuide(uint32 type
, float x
, float y
, float z
, float o
, uint32 team
)
1353 if(team
== ALLIANCE
)
1358 Creature
* pCreature
= AddCreature(entry
,type
,team
,x
,y
,z
,o
);
1361 sLog
.outError("Can't create Spirit guide. BattleGround not created!");
1366 pCreature
->setDeathState(DEAD
);
1368 pCreature
->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT
, pCreature
->GetGUID());
1370 pCreature
->SetUInt32Value(UNIT_FIELD_AURA
, SPELL_SPIRIT_HEAL_CHANNEL
);
1371 pCreature
->SetUInt32Value(UNIT_FIELD_AURAFLAGS
, 0x00000009);
1372 pCreature
->SetUInt32Value(UNIT_FIELD_AURALEVELS
, 0x0000003C);
1373 pCreature
->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS
, 0x000000FF);
1374 // casting visual effect
1375 pCreature
->SetUInt32Value(UNIT_CHANNEL_SPELL
, SPELL_SPIRIT_HEAL_CHANNEL
);
1376 // correct cast speed
1377 pCreature
->SetFloatValue(UNIT_MOD_CAST_SPEED
, 1.0f
);
1379 //pCreature->CastSpell(pCreature, SPELL_SPIRIT_HEAL_CHANNEL, true);
1384 void BattleGround::SendMessageToAll(char const* text
)
1387 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, text
, NULL
);
1388 SendPacketToAll(&data
);
1391 void BattleGround::SendMessageToAll(int32 entry
)
1393 char const* text
= GetMangosString(entry
);
1395 ChatHandler::FillMessageData(&data
, NULL
, CHAT_MSG_BG_SYSTEM_NEUTRAL
, LANG_UNIVERSAL
, NULL
, 0, text
, NULL
);
1396 SendPacketToAll(&data
);
1399 void BattleGround::EndNow()
1401 RemoveFromBGFreeSlotQueue();
1402 SetStatus(STATUS_WAIT_LEAVE
);
1403 SetEndTime(TIME_TO_AUTOREMOVE
);
1404 // inform invited players about the removal
1405 sBattleGroundMgr
.m_BattleGroundQueues
[sBattleGroundMgr
.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
1408 // Battleground messages are localized using the dbc lang, they are not client language dependent
1409 const char *BattleGround::GetMangosString(int32 entry
)
1411 // FIXME: now we have different DBC locales and need localized message for each target client
1412 return objmgr
.GetMangosStringForDBCLocale(entry
);
1417 buffs aren't spawned/despawned when players captures anything
1418 buffs are in their positions when battleground starts
1420 void BattleGround::HandleTriggerBuff(uint64
const& go_guid
)
1422 GameObject
*obj
= HashMapHolder
<GameObject
>::Find(go_guid
);
1423 if(!obj
|| obj
->GetGoType() != GAMEOBJECT_TYPE_TRAP
|| !obj
->isSpawned())
1426 //change buff type, when buff is used:
1427 int32 index
= m_BgObjects
.size() - 1;
1428 while (index
>= 0 && m_BgObjects
[index
] != go_guid
)
1432 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());
1436 //randomly select new buff
1437 uint8 buff
= urand(0, 2);
1438 uint32 entry
= obj
->GetEntry();
1439 if( m_BuffChange
&& entry
!= Buff_Entries
[buff
] )
1441 //despawn current buff
1442 SpawnBGObject(index
, RESPAWN_ONE_DAY
);
1443 //set index for new one
1444 for (uint8 currBuffTypeIndex
= 0; currBuffTypeIndex
< 3; ++currBuffTypeIndex
)
1445 if( entry
== Buff_Entries
[currBuffTypeIndex
] )
1447 index
-= currBuffTypeIndex
;
1452 SpawnBGObject(index
, BUFF_RESPAWN_TIME
);
1455 void BattleGround::HandleKillPlayer( Player
*player
, Player
*killer
)
1457 //keep in mind that for arena this will have to be changed a bit
1460 UpdatePlayerScore(player
, SCORE_DEATHS
, 1);
1462 // add +1 kills to group and +1 killing_blows to killer
1465 UpdatePlayerScore(killer
, SCORE_HONORABLE_KILLS
, 1);
1466 UpdatePlayerScore(killer
, SCORE_KILLING_BLOWS
, 1);
1468 for(std::map
<uint64
, BattleGroundPlayer
>::iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
1470 Player
*plr
= objmgr
.GetPlayer(itr
->first
);
1472 if(!plr
|| plr
== killer
)
1475 if( plr
->GetTeam() == killer
->GetTeam() && plr
->IsAtGroupRewardDistance(player
) )
1476 UpdatePlayerScore(plr
, SCORE_HONORABLE_KILLS
, 1);
1480 // to be able to remove insignia
1481 player
->SetFlag( UNIT_FIELD_FLAGS
, UNIT_FLAG_SKINNABLE
);
1484 // return the player's team based on battlegroundplayer info
1485 // used in same faction arena matches mainly
1486 uint32
BattleGround::GetPlayerTeam(uint64 guid
)
1488 std::map
<uint64
, BattleGroundPlayer
>::const_iterator itr
= m_Players
.find(guid
);
1489 if(itr
!=m_Players
.end())
1490 return itr
->second
.Team
;
1494 uint32
BattleGround::GetAlivePlayersCountByTeam(uint32 Team
) const
1497 for(std::map
<uint64
, BattleGroundPlayer
>::const_iterator itr
= m_Players
.begin(); itr
!= m_Players
.end(); ++itr
)
1499 if(itr
->second
.Team
== Team
)
1501 Player
* pl
= objmgr
.GetPlayer(itr
->first
);
1502 if(pl
&& pl
->isAlive())