[6922] Whitespace and newline fixes
[getmangos.git] / src / game / BattleGround.cpp
blob5c2ca717aabb4a08a33dd564503b408afab3ccb2
1 /*
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
19 #include "Object.h"
20 #include "Player.h"
21 #include "BattleGround.h"
22 #include "Creature.h"
23 #include "MapManager.h"
24 #include "Language.h"
25 #include "Chat.h"
26 #include "SpellAuras.h"
27 #include "ArenaTeam.h"
28 #include "World.h"
29 #include "Util.h"
31 BattleGround::BattleGround()
33 m_TypeID = 0;
34 m_InstanceID = 0;
35 m_Status = 0;
36 m_EndTime = 0;
37 m_LastResurrectTime = 0;
38 m_Queue_type = MAX_BATTLEGROUND_QUEUES;
39 m_InvitedAlliance = 0;
40 m_InvitedHorde = 0;
41 m_ArenaType = 0;
42 m_IsArena = false;
43 m_Winner = 2;
44 m_StartTime = 0;
45 m_Events = 0;
46 m_IsRated = false;
47 m_BuffChange = false;
48 m_Name = "";
49 m_LevelMin = 0;
50 m_LevelMax = 0;
51 m_InBGFreeSlotQueue = false;
52 m_SetDeleteThis = false;
54 m_MaxPlayersPerTeam = 0;
55 m_MaxPlayers = 0;
56 m_MinPlayersPerTeam = 0;
57 m_MinPlayers = 0;
59 m_MapId = 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)
96 DelCreature(i);
98 size = m_BgObjects.size();
99 for(int i = 0; i < size; ++i)
101 DelObject(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());
111 // unload map
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())
122 //BG is empty
123 return;
125 WorldPacket data;
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);
132 switch(itr->second)
134 //following code is handled by event:
135 /*case 0:
136 sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first);
137 //RemovePlayerFromQueue(itr->first);
138 if(plr)
140 sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
141 plr->GetSession()->SendPacket(&data);
143 break;*/
144 case 1: // currently in bg and was removed from bg
145 if(plr)
146 RemovePlayerAtLeave(itr->first, true, true);
147 else
148 RemovePlayerAtLeave(itr->first, false, false);
149 break;
150 case 2: // revive queue
151 RemovePlayerFromResurrectQueue(itr->first);
152 break;
153 default:
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
163 if(GetPlayersSize())
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;
170 if(plr)
171 itr->second.LastOnlineTime = 0; // update last online time
172 else
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)
185 Creature *sh = NULL;
186 for(std::vector<uint64>::iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
188 Player *plr = objmgr.GetPlayer(*itr2);
189 if(!plr)
190 continue;
192 if (!sh)
194 sh = ObjectAccessor::GetCreature(*plr, itr->first);
195 // only for visual effect
196 if (sh)
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;
209 else
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);
218 if(!plr)
219 continue;
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)
238 // time's up!
239 EndBattleGround(0); // noone wins
240 m_PrematureCountDown = false;
242 else
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
257 m_EndTime += diff;
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);
283 if(plr)
284 plr->GetSession()->SendPacket(packet);
285 else
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);
296 if(!plr)
298 sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
299 continue;
302 if(!self && sender == plr)
303 continue;
305 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
306 if(!team) team = plr->GetTeam();
308 if(team == TeamID)
309 plr->GetSession()->SendPacket(packet);
313 void BattleGround::PlaySoundToAll(uint32 SoundID)
315 WorldPacket data;
316 sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID);
317 SendPacketToAll(&data);
320 void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
322 WorldPacket data;
324 for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
326 Player *plr = objmgr.GetPlayer(itr->first);
328 if(!plr)
330 sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
331 continue;
334 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
335 if(!team) team = plr->GetTeam();
337 if(team == TeamID)
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);
351 if(!plr)
353 sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
354 continue;
357 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
358 if(!team) team = plr->GetTeam();
360 if(team == TeamID)
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);
371 if(!plr)
373 sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
374 continue;
377 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
378 if(!team) team = plr->GetTeam();
380 if(team == TeamID)
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);
389 if(!factionEntry)
390 return;
392 for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
394 Player *plr = objmgr.GetPlayer(itr->first);
396 if(!plr)
398 sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
399 continue;
402 uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
403 if(!team) team = plr->GetTeam();
405 if(team == TeamID)
406 plr->ModifyFactionReputation(factionEntry, Reputation);
410 void BattleGround::UpdateWorldState(uint32 Field, uint32 Value)
412 WorldPacket data;
413 sBattleGroundMgr.BuildUpdateWorldStatePacket(&data, Field, Value);
414 SendPacketToAll(&data);
417 void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player *Source)
419 WorldPacket data;
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;
432 WorldPacket data;
433 Player *Source = NULL;
434 const char *winmsg = "";
436 if(winner == ALLIANCE)
438 if(isBattleGround())
439 winmsg = GetMangosString(LANG_BG_A_WINS);
440 else
441 winmsg = GetMangosString(LANG_ARENA_GOLD_WINS);
443 PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
445 SetWinner(WINNER_ALLIANCE);
447 else if(winner == HORDE)
449 if(isBattleGround())
450 winmsg = GetMangosString(LANG_BG_H_WINS);
451 else
452 winmsg = GetMangosString(LANG_ARENA_GREEN_WINS);
454 PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
456 SetWinner(WINNER_HORDE);
458 else
460 SetWinner(3);
463 SetStatus(STATUS_WAIT_LEAVE);
464 m_EndTime = 0;
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);
491 else
493 SetArenaTeamRatingChangeForTeam(HORDE, winner_change);
494 SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change);
497 else
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);
507 if(!plr)
509 sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
510 continue;
513 // should remove spirit of redemption
514 if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
515 plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
517 if(!plr->isAlive())
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)
529 if(team == winner)
530 winner_arena_team->MemberWon(plr,loser_rating);
531 else
532 loser_arena_team->MemberLost(plr,winner_rating);
535 if(team == winner)
537 if(!Source)
538 Source = plr;
539 RewardMark(plr,ITEM_WINNER_COUNT);
540 UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20);
541 RewardQuest(plr);
543 else
545 RewardMark(plr,ITEM_LOSER_COUNT);
548 plr->CombatStopWithPets(true);
550 BlockMovement(plr);
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);
577 if(Source)
579 ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg);
580 SendPacketToAll(&data);
584 uint32 BattleGround::GetBattlemasterEntry() const
586 switch(GetTypeID())
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;
593 default: return 0;
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))
601 return;
603 BattleGroundMarks mark;
604 bool IsSpell;
605 switch(GetTypeID())
607 case BATTLEGROUND_AV:
608 IsSpell = true;
609 if(count == ITEM_WINNER_COUNT)
610 mark = SPELL_AV_MARK_WINNER;
611 else
612 mark = SPELL_AV_MARK_LOSER;
613 break;
614 case BATTLEGROUND_WS:
615 IsSpell = true;
616 if(count == ITEM_WINNER_COUNT)
617 mark = SPELL_WS_MARK_WINNER;
618 else
619 mark = SPELL_WS_MARK_LOSER;
620 break;
621 case BATTLEGROUND_AB:
622 IsSpell = true;
623 if(count == ITEM_WINNER_COUNT)
624 mark = SPELL_AB_MARK_WINNER;
625 else
626 mark = SPELL_AB_MARK_LOSER;
627 break;
628 case BATTLEGROUND_EY:
629 IsSpell = false;
630 mark = ITEM_EY_MARK_OF_HONOR;
631 break;
632 default:
633 return;
636 if(IsSpell)
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();
658 if(!bmEntry)
659 return;
661 ItemPrototype const* markProto = objmgr.GetItemPrototype(mark);
662 if(!markProto)
663 return;
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
670 // item
671 MailItemsInfo mi;
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();
677 if ( loc_idx >= 0 )
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];
682 // text
683 std::string textFormat = plr->GetSession()->GetMangosString(LANG_BG_MARK_BY_MAIL);
684 char textBuf[300];
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))
696 return;
698 uint32 quest;
699 switch(GetTypeID())
701 case BATTLEGROUND_AV:
702 quest = SPELL_AV_QUEST_REWARD;
703 break;
704 case BATTLEGROUND_WS:
705 quest = SPELL_WS_QUEST_REWARD;
706 break;
707 case BATTLEGROUND_AB:
708 quest = SPELL_AB_QUEST_REWARD;
709 break;
710 case BATTLEGROUND_EY:
711 quest = SPELL_EY_QUEST_REWARD;
712 break;
713 default:
714 return;
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)
736 participant = true;
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
762 if(plr)
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
773 if(isArena())
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))
783 delete NewPet;
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;
793 if(team == HORDE)
795 winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
796 loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
798 else
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());
810 WorldPacket data;
811 if(SendPacket)
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);
832 delete group;
836 // Let others know
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
844 plr->SetBGTeam(0);
846 if(Transport)
848 plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO());
851 // Log
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
861 return;
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);
874 SetStartTime(0);
875 SetEndTime(0);
876 SetLastResurrectTime(0);
877 SetArenaType(0);
878 SetRated(false);
880 m_Events = 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;
886 m_InvitedHorde = 0;
887 m_InBGFreeSlotQueue = false;
889 m_Players.clear();
890 m_PlayerScores.clear();
892 // reset BGSubclass
893 ResetBGSubclass();
896 void BattleGround::StartBattleGround()
898 ///this method should spawn spirit guides and so on
899 SetStartTime(0);
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;
913 bp.Team = team;
915 // Add to list/maps
916 m_Players[guid] = bp;
918 UpdatePlayersCountByTeam(team, false); // +1 player
920 WorldPacket data;
921 sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr);
922 SendPacketToTeam(team, &data, plr, false);
924 // add arena specific auras
925 if(isArena())
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);
934 else
935 plr->CastSpell(plr, SPELL_ALLIANCE_GOLD_FLAG,true);
937 else // green
939 if(plr->GetTeam() == HORDE)
940 plr->CastSpell(plr, SPELL_HORDE_GREEN_FLAG,true);
941 else
942 plr->CastSpell(plr, SPELL_ALLIANCE_GREEN_FLAG,true);
945 plr->DestroyConjuredItems(true);
947 Pet* pet = plr->GetPet();
948 if(pet)
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);
957 else
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));
968 else
970 if(GetStatus() == STATUS_WAIT_JOIN) // not started yet
971 plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells.
974 // Log
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);
1000 return;
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
1013 uint32 otherTeam;
1014 uint32 otherIn;
1015 if (Team == ALLIANCE)
1017 otherTeam = GetInvitedCount(HORDE);
1018 otherIn = GetPlayersCountByTeam(HORDE);
1020 else
1022 otherTeam = GetInvitedCount(ALLIANCE);
1023 otherIn = GetPlayersCountByTeam(ALLIANCE);
1025 if (GetStatus() == STATUS_IN_PROGRESS)
1027 // difference based on ppl invited (not necessarily entered battle)
1028 // default: allow 0
1029 uint32 diff = 0;
1030 // allow join one person if the sides are equal (to fill up bg to minplayersperteam)
1031 if (otherTeam == GetInvitedCount(Team))
1032 diff = 1;
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
1041 // default: allow 0
1042 uint32 diff3 = 0;
1043 // allow join one person if the sides are equal (to fill up bg minplayersperteam)
1044 if (otherIn == GetPlayersCountByTeam(Team))
1045 diff3 = 1;
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 ;
1062 return 0;
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...
1076 return;
1078 switch(type)
1080 case SCORE_KILLING_BLOWS: // Killing blows
1081 itr->second->KillingBlows += value;
1082 break;
1083 case SCORE_DEATHS: // Deaths
1084 itr->second->Deaths += value;
1085 break;
1086 case SCORE_HONORABLE_KILLS: // Honorable kills
1087 itr->second->HonorableKills += value;
1088 break;
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;
1097 break;
1098 //used only in EY, but in MSG_PVP_LOG_DATA opcode
1099 case SCORE_DAMAGE_DONE: // Damage Done
1100 itr->second->DamageDone += value;
1101 break;
1102 case SCORE_HEALING_DONE: // Healing Done
1103 itr->second->HealingDone += value;
1104 break;
1105 default:
1106 sLog.outError("BattleGround: Unknown player score type %u", type);
1107 break;
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);
1116 if(!plr)
1117 return;
1119 plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true);
1120 SpellEntry const *spellInfo = sSpellStore.LookupEntry( SPELL_WAITING_FOR_RESURRECT );
1121 if(spellInfo)
1123 Aura *Aur = CreateAura(spellInfo, 0, NULL, plr);
1124 plr->AddAura(Aur);
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);
1139 if(!plr)
1140 return;
1142 plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
1144 return;
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());
1153 if(!map)
1154 return false;
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);
1164 delete go;
1165 return false;
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);
1174 data.id = entry;
1175 data.mapid = GetMapId();
1176 data.posX = x;
1177 data.posY = y;
1178 data.posZ = z;
1179 data.orientation = o;
1180 data.rotation0 = rotation0;
1181 data.rotation1 = rotation1;
1182 data.rotation2 = rotation2;
1183 data.rotation3 = rotation3;
1184 data.spawntimesecs = respawnTime;
1185 data.spawnMask = 1;
1186 data.animprogress = 100;
1187 data.go_state = 1;
1189 // add to world, so it can be later looked up from HashMapHolder
1190 go->AddToWorld();
1191 m_BgObjects[type] = go->GetGUID();
1192 return true;
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]);
1200 if(obj)
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);
1210 else
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]);
1219 if(obj)
1221 //change state to be sure they will be opened
1222 obj->SetLootState(GO_READY);
1223 obj->UseDoorOrButton(RESPAWN_ONE_DAY);
1225 else
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());
1234 if(!map)
1235 return;
1236 if( respawntime == 0 )
1238 GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
1239 if(obj)
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);
1245 map->Add(obj);
1248 else
1250 GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
1251 if(obj)
1253 map->Add(obj);
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());
1263 if(!map)
1264 return NULL;
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);
1270 delete pCreature;
1271 return NULL;
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());
1279 return NULL;
1282 pCreature->AIM_Initialize();
1284 //pCreature->SetDungeonDifficulty(0);
1286 map->Add(pCreature);
1287 m_BgCreatures[type] = pCreature->GetGUID();
1289 return pCreature;
1292 void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
1294 Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
1295 if(!map)
1296 return false;
1298 if(respawntime == 0)
1300 Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1301 if(obj)
1303 //obj->Respawn(); // bugged
1304 obj->SetRespawnTime(0);
1305 objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);
1306 map->Add(obj);
1309 else
1311 Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1312 if(obj)
1314 obj->setDeathState(DEAD);
1315 obj->SetRespawnTime(respawntime);
1316 map->Add(obj);
1321 bool BattleGround::DelCreature(uint32 type)
1323 Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
1324 if(!cr)
1326 sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type]));
1327 return false;
1329 cr->CleanupsBeforeDelete();
1330 cr->AddObjectToRemoveList();
1331 m_BgCreatures[type] = 0;
1332 return true;
1335 bool BattleGround::DelObject(uint32 type)
1337 GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
1338 if(!obj)
1340 sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type]));
1341 return false;
1343 obj->SetRespawnTime(0); // not save respawn time
1344 obj->Delete();
1345 m_BgObjects[type] = 0;
1346 return true;
1349 bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team)
1351 uint32 entry = 0;
1353 if(team == ALLIANCE)
1354 entry = 13116;
1355 else
1356 entry = 13117;
1358 Creature* pCreature = AddCreature(entry,type,team,x,y,z,o);
1359 if(!pCreature)
1361 sLog.outError("Can't create Spirit guide. BattleGround not created!");
1362 EndNow();
1363 return false;
1366 pCreature->setDeathState(DEAD);
1368 pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID());
1369 // aura
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);
1381 return true;
1384 void BattleGround::SendMessageToAll(char const* text)
1386 WorldPacket data;
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);
1394 WorldPacket data;
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);
1416 important notice:
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())
1424 return;
1426 //change buff type, when buff is used:
1427 int32 index = m_BgObjects.size() - 1;
1428 while (index >= 0 && m_BgObjects[index] != go_guid)
1429 index--;
1430 if (index < 0)
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());
1433 return;
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;
1448 index += buff;
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
1459 // add +1 deaths
1460 UpdatePlayerScore(player, SCORE_DEATHS, 1);
1462 // add +1 kills to group and +1 killing_blows to killer
1463 if( 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)
1473 continue;
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;
1491 return 0;
1494 uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
1496 int count = 0;
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())
1503 ++count;
1506 return count;