aboutsummaryrefslogtreecommitdiff
path: root/src/game/BattleGround.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/BattleGround.cpp')
-rw-r--r--src/game/BattleGround.cpp1103
1 files changed, 700 insertions, 403 deletions
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
index 822606d9a80..71062657c0b 100644
--- a/src/game/BattleGround.cpp
+++ b/src/game/BattleGround.cpp
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
- * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,26 +18,124 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "Object.h"
#include "Player.h"
+#include "ObjectMgr.h"
+#include "World.h"
+#include "WorldPacket.h"
+
+#include "ArenaTeam.h"
#include "BattleGround.h"
+#include "BattleGroundMgr.h"
#include "Creature.h"
-#include "MapManager.h"
+#include "Formulas.h"
+#include "GridNotifiersImpl.h"
+#include "Group.h"
#include "Language.h"
-#include "Chat.h"
+#include "MapManager.h"
+#include "Object.h"
#include "SpellAuras.h"
-#include "ArenaTeam.h"
-#include "World.h"
#include "Util.h"
+
+namespace MaNGOS
+{
+ class BattleGroundChatBuilder
+ {
+ public:
+ BattleGroundChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, va_list* args = NULL)
+ : i_msgtype(msgtype), i_textId(textId), i_source(source), i_args(args) {}
+ void operator()(WorldPacket& data, int32 loc_idx)
+ {
+ char const* text = objmgr.GetMangosString(i_textId,loc_idx);
+
+ if (i_args)
+ {
+ // we need copy va_list before use or original va_list will corrupted
+ va_list ap;
+ va_copy(ap,*i_args);
+
+ char str [2048];
+ vsnprintf(str,2048,text, ap );
+ va_end(ap);
+
+ do_helper(data,&str[0]);
+ }
+ else
+ do_helper(data,text);
+ }
+ private:
+ void do_helper(WorldPacket& data, char const* text)
+ {
+ uint64 target_guid = i_source ? i_source ->GetGUID() : 0;
+
+ data << uint8(i_msgtype);
+ data << uint32(LANG_UNIVERSAL);
+ data << uint64(target_guid); // there 0 for BG messages
+ data << uint32(0); // can be chat msg group or something
+ data << uint64(target_guid);
+ data << uint32(strlen(text)+1);
+ data << text;
+ data << uint8(i_source ? i_source->chatTag() : uint8(0));
+ }
+
+ ChatMsg i_msgtype;
+ int32 i_textId;
+ Player const* i_source;
+ va_list* i_args;
+ };
+
+ class BattleGround2ChatBuilder
+ {
+ public:
+ BattleGround2ChatBuilder(ChatMsg msgtype, int32 textId, Player const* source, int32 arg1, int32 arg2)
+ : i_msgtype(msgtype), i_textId(textId), i_source(source), i_arg1(arg1), i_arg2(arg2) {}
+ void operator()(WorldPacket& data, int32 loc_idx)
+ {
+ char const* text = objmgr.GetMangosString(i_textId,loc_idx);
+ char const* arg1str = i_arg1 ? objmgr.GetMangosString(i_arg1,loc_idx) : "";
+ char const* arg2str = i_arg2 ? objmgr.GetMangosString(i_arg2,loc_idx) : "";
+
+ char str [2048];
+ snprintf(str,2048,text, arg1str, arg2str );
+
+ uint64 target_guid = i_source ? i_source ->GetGUID() : 0;
+
+ data << uint8(i_msgtype);
+ data << uint32(LANG_UNIVERSAL);
+ data << uint64(target_guid); // there 0 for BG messages
+ data << uint32(0); // can be chat msg group or something
+ data << uint64(target_guid);
+ data << uint32(strlen(str)+1);
+ data << str;
+ data << uint8(i_source ? i_source->chatTag() : uint8(0));
+ }
+ private:
+
+ ChatMsg i_msgtype;
+ int32 i_textId;
+ Player const* i_source;
+ int32 i_arg1;
+ int32 i_arg2;
+ };
+} // namespace MaNGOS
+
+template<class Do>
+void BattleGround::BroadcastWorker(Do& _do)
+{
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ if (Player *plr = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
+ _do(plr);
+}
+
BattleGround::BattleGround()
{
- m_TypeID = 0;
+ m_TypeID = BattleGroundTypeId(0);
m_InstanceID = 0;
- m_Status = 0;
+ m_Status = STATUS_NONE;
+ m_ClientInstanceID = 0;
m_EndTime = 0;
m_LastResurrectTime = 0;
- m_Queue_type = MAX_BATTLEGROUND_QUEUES;
+ m_QueueId = QUEUE_ID_MAX_LEVEL_19;
m_InvitedAlliance = 0;
m_InvitedHorde = 0;
m_ArenaType = 0;
@@ -88,6 +186,16 @@ BattleGround::BattleGround()
m_PrematureCountDown = 0;
m_HonorMode = BG_NORMAL;
+
+ m_StartDelayTimes[BG_STARTING_EVENT_FIRST] = BG_START_DELAY_2M;
+ m_StartDelayTimes[BG_STARTING_EVENT_SECOND] = BG_START_DELAY_1M;
+ m_StartDelayTimes[BG_STARTING_EVENT_THIRD] = BG_START_DELAY_30S;
+ m_StartDelayTimes[BG_STARTING_EVENT_FOURTH] = BG_START_DELAY_NONE;
+ //we must set to some default existing values
+ m_StartMessageIds[BG_STARTING_EVENT_FIRST] = LANG_BG_WS_START_TWO_MINUTES;
+ m_StartMessageIds[BG_STARTING_EVENT_SECOND] = LANG_BG_WS_START_ONE_MINUTE;
+ m_StartMessageIds[BG_STARTING_EVENT_THIRD] = LANG_BG_WS_START_HALF_MINUTE;
+ m_StartMessageIds[BG_STARTING_EVENT_FOURTH] = LANG_BG_WS_HAS_BEGUN;
}
BattleGround::~BattleGround()
@@ -105,99 +213,68 @@ BattleGround::~BattleGround()
DelObject(i);
}
- // delete creature and go respawn times
- WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
- WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID());
- // delete instance from db
- CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID());
- // remove from battlegrounds
- sBattleGroundMgr.RemoveBattleGround(GetInstanceID());
+ if(GetInstanceID()) // not spam by useless queries in case BG templates
+ {
+ // delete creature and go respawn times
+ WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
+ WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID());
+ // delete instance from db
+ CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID());
+ // remove from battlegrounds
+ }
+
+ sBattleGroundMgr.RemoveBattleGround(GetInstanceID(), GetTypeID());
// unload map
- if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
- if(map->IsBattleGroundOrArena())
+ if (Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
+ if (map->IsBattleGroundOrArena())
((BattleGroundMap*)map)->SetUnload();
// remove from bg free slot queue
this->RemoveFromBGFreeSlotQueue();
}
-void BattleGround::Update(time_t diff)
+void BattleGround::Update(uint32 diff)
{
- if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
+ if (!GetPlayersSize() && !GetReviveQueueSize())
//BG is empty
return;
- m_StartTime += diff;
-
- // WorldPacket data;
-
- if(GetRemovedPlayersSize())
+ // remove offline players from bg after 5 minutes
+ if (!m_OfflineQueue.empty())
{
- for(std::map<uint64, uint8>::iterator itr = m_RemovedPlayers.begin(); itr != m_RemovedPlayers.end(); ++itr)
+ BattleGroundPlayerMap::iterator itr = m_Players.find(*(m_OfflineQueue.begin()));
+ if (itr != m_Players.end())
{
- Player *plr = objmgr.GetPlayer(itr->first);
- switch(itr->second)
+ if (itr->second.OfflineRemoveTime <= sWorld.GetGameTime())
{
- //following code is handled by event:
- /*case 0:
- sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].RemovePlayer(itr->first);
- //RemovePlayerFromQueue(itr->first);
- if(plr)
- {
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
- plr->GetSession()->SendPacket(&data);
- }
- break;*/
- case 1: // currently in bg and was removed from bg
- if(plr)
- RemovePlayerAtLeave(itr->first, true, true);
- else
- RemovePlayerAtLeave(itr->first, false, false);
- break;
- case 2: // revive queue
- RemovePlayerFromResurrectQueue(itr->first);
- break;
- default:
- sLog.outError("BattleGround: Unknown remove player case!");
+ RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
+ m_OfflineQueue.pop_front(); // remove from offline queue
+ //do not use itr for anything, because it is erased in RemovePlayerAtLeave()
}
}
- m_RemovedPlayers.clear();
}
- // this code isn't efficient and its idea isn't implemented yet
- /* offline players are removed from battleground in worldsession::LogoutPlayer()
- // remove offline players from bg after ~5 minutes
- if(GetPlayersSize())
- {
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
- {
- Player *plr = objmgr.GetPlayer(itr->first);
- itr->second.LastOnlineTime += diff;
-
- if(plr)
- itr->second.LastOnlineTime = 0; // update last online time
- else
- if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes
- m_RemovedPlayers[itr->first] = 1; // add to remove list (BG)
- }
- }*/
+ /*********************************************************/
+ /*** BATTLEGROUND RESSURECTION SYSTEM ***/
+ /*********************************************************/
+ //this should be handled by spell system
m_LastResurrectTime += diff;
if (m_LastResurrectTime >= RESURRECTION_INTERVAL)
{
- if(GetReviveQueueSize())
+ if (GetReviveQueueSize())
{
for(std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr)
{
Creature *sh = NULL;
- for(std::vector<uint64>::iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
+ for(std::vector<uint64>::const_iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
{
Player *plr = objmgr.GetPlayer(*itr2);
- if(!plr)
+ if (!plr)
continue;
- if (!sh)
+ if (!sh && plr->IsInWorld())
{
- sh = ObjectAccessor::GetCreature(*plr, itr->first);
+ sh = plr->GetMap()->GetCreature(itr->first);
// only for visual effect
if (sh)
sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true); // Spirit Heal, effect 117
@@ -218,10 +295,10 @@ void BattleGround::Update(time_t diff)
}
else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC
{
- for(std::vector<uint64>::iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
+ for(std::vector<uint64>::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(*itr);
- if(!plr)
+ if (!plr)
continue;
plr->ResurrectPlayer(1.0f);
plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true);
@@ -230,46 +307,168 @@ void BattleGround::Update(time_t diff)
m_ResurrectQueue.clear();
}
+ /*********************************************************/
+ /*** BATTLEGROUND BALLANCE SYSTEM ***/
+ /*********************************************************/
+
// if less then minimum players are in on one side, then start premature finish timer
- if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
+ if (GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
{
- if(!m_PrematureCountDown)
+ if (!m_PrematureCountDown)
{
m_PrematureCountDown = true;
m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime();
- SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
}
- else if(m_PrematureCountDownTimer < diff)
+ else if (m_PrematureCountDownTimer < diff)
{
// time's up!
- EndBattleGround(0); // noone wins
+ uint32 winner = 0;
+ if (GetPlayersCountByTeam(ALLIANCE) >= GetMinPlayersPerTeam())
+ winner = ALLIANCE;
+ else if (GetPlayersCountByTeam(HORDE) >= GetMinPlayersPerTeam())
+ winner = HORDE;
+
+ EndBattleGround(winner);
m_PrematureCountDown = false;
}
else
{
uint32 newtime = m_PrematureCountDownTimer - diff;
// announce every minute
- if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000)
- SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
+ if (newtime > (MINUTE * IN_MILISECONDS))
+ {
+ if (newtime / (MINUTE * IN_MILISECONDS) != m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS))
+ PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / (MINUTE * IN_MILISECONDS)));
+ }
+ else
+ {
+ //announce every 15 seconds
+ if (newtime / (15 * IN_MILISECONDS) != m_PrematureCountDownTimer / (15 * IN_MILISECONDS))
+ PSendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS, CHAT_MSG_SYSTEM, NULL, (uint32)(m_PrematureCountDownTimer / IN_MILISECONDS));
+ }
m_PrematureCountDownTimer = newtime;
}
}
else if (m_PrematureCountDown)
m_PrematureCountDown = false;
- if(GetStatus() == STATUS_WAIT_LEAVE)
+ /*********************************************************/
+ /*** BATTLEGROUND STARTING SYSTEM ***/
+ /*********************************************************/
+
+ if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize())
+ {
+ ModifyStartDelayTime(diff);
+
+ if (!(m_Events & BG_STARTING_EVENT_1))
+ {
+ m_Events |= BG_STARTING_EVENT_1;
+
+ // setup here, only when at least one player has ported to the map
+ if (!SetupBattleGround())
+ {
+ EndNow();
+ return;
+ }
+
+ StartingEventCloseDoors();
+ SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FIRST]);
+ //first start warning - 2 or 1 minute
+ SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FIRST], CHAT_MSG_BG_SYSTEM_NEUTRAL);
+ }
+ // After 1 minute or 30 seconds, warning is signalled
+ else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_SECOND] && !(m_Events & BG_STARTING_EVENT_2))
+ {
+ m_Events |= BG_STARTING_EVENT_2;
+ SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_SECOND], CHAT_MSG_BG_SYSTEM_NEUTRAL);
+ }
+ // After 30 or 15 seconds, warning is signalled
+ else if (GetStartDelayTime() <= m_StartDelayTimes[BG_STARTING_EVENT_THIRD] && !(m_Events & BG_STARTING_EVENT_3))
+ {
+ m_Events |= BG_STARTING_EVENT_3;
+ SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_THIRD], CHAT_MSG_BG_SYSTEM_NEUTRAL);
+ }
+ // delay expired (atfer 2 or 1 minute)
+ else if (GetStartDelayTime() <= 0 && !(m_Events & BG_STARTING_EVENT_4))
+ {
+ m_Events |= BG_STARTING_EVENT_4;
+
+ StartingEventOpenDoors();
+
+ SendMessageToAll(m_StartMessageIds[BG_STARTING_EVENT_FOURTH], CHAT_MSG_BG_SYSTEM_NEUTRAL);
+ SetStatus(STATUS_IN_PROGRESS);
+ SetStartDelayTime(m_StartDelayTimes[BG_STARTING_EVENT_FOURTH]);
+
+ //remove preparation
+ if (isArena())
+ {
+ //TODO : add arena sound PlaySoundToAll(SOUND_ARENA_START);
+
+ for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
+ if (Player *plr = objmgr.GetPlayer(itr->first))
+ {
+ plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
+ // remove auras with duration lower than 30s
+ Unit::AuraMap & aurMap = plr->GetAuras();
+ for(Unit::AuraMap::iterator iter = aurMap.begin(); iter != aurMap.end();)
+ {
+ if (!iter->second->IsPermanent()
+ && iter->second->GetAuraDuration()<=30*IN_MILISECONDS
+ && iter->second->IsPositive()
+ && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY))
+ && (!iter->second->IsAuraType(SPELL_AURA_MOD_INVISIBILITY)))
+ {
+ plr->RemoveAura(iter);
+ }
+ else
+ ++iter;
+ }
+ }
+
+ CheckArenaWinConditions();
+ }
+ else
+ {
+
+ PlaySoundToAll(SOUND_BG_START);
+
+ for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
+ if (Player* plr = objmgr.GetPlayer(itr->first))
+ plr->RemoveAurasDueToSpell(SPELL_PREPARATION);
+ //Announce BG starting
+ if (sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE))
+ {
+ sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, GetName(), GetMinLevel(), GetMaxLevel());
+ }
+ }
+ }
+ }
+
+ /*********************************************************/
+ /*** BATTLEGROUND ENDING SYSTEM ***/
+ /*********************************************************/
+
+ if (GetStatus() == STATUS_WAIT_LEAVE)
{
// remove all players from battleground after 2 minutes
- m_EndTime += diff;
- if(m_EndTime >= TIME_TO_AUTOREMOVE) // 2 minutes
+ m_EndTime -= diff;
+ if (m_EndTime <= 0)
{
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ m_EndTime = 0;
+ BattleGroundPlayerMap::iterator itr, next;
+ for(itr = m_Players.begin(); itr != m_Players.end(); itr = next)
{
- m_RemovedPlayers[itr->first] = 1; // add to remove list (BG)
+ next = itr;
+ ++next;
+ //itr is erased here!
+ RemovePlayerAtLeave(itr->first, true, true);// remove player from BG
+ // do not change any battleground's private variables
}
- // do not change any battleground's private variables
}
}
+
+ //update start time
+ m_StartTime += diff;
}
void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O)
@@ -283,35 +482,35 @@ void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, flo
void BattleGround::SendPacketToAll(WorldPacket *packet)
{
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(plr)
+ if (plr)
plr->GetSession()->SendPacket(packet);
else
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
}
}
void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *sender, bool self)
{
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
continue;
}
- if(!self && sender == plr)
+ if (!self && sender == plr)
continue;
- uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
+ uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
plr->GetSession()->SendPacket(packet);
}
}
@@ -327,20 +526,20 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
{
WorldPacket data;
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
continue;
}
- uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
+ uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
{
sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID);
plr->GetSession()->SendPacket(&data);
@@ -350,20 +549,20 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
{
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
continue;
}
- uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
+ uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
plr->CastSpell(plr, SpellID, true);
}
}
@@ -376,7 +575,7 @@ void BattleGround::YellToAll(Creature* creature, const char* text, uint32 langua
Player *plr = objmgr.GetPlayer(itr->first);
if(!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player " UI64FMTD " not found!", itr->first);
continue;
}
creature->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,text,language,creature->GetName(),itr->first);
@@ -387,20 +586,20 @@ void BattleGround::YellToAll(Creature* creature, const char* text, uint32 langua
void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
{
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
continue;
}
- uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
+ uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
+ if (team == TeamID)
UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor);
}
}
@@ -409,24 +608,24 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
{
FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
- if(!factionEntry)
+ if (!factionEntry)
return;
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ if (!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
continue;
}
- uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
+ uint32 team = itr->second.Team;
if(!team) team = plr->GetTeam();
- if(team == TeamID)
- plr->ModifyFactionReputation(factionEntry, Reputation);
+ if (team == TeamID)
+ plr->GetReputationMgr().ModifyReputation(factionEntry, Reputation);
}
}
@@ -447,32 +646,25 @@ void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player
void BattleGround::EndBattleGround(uint32 winner)
{
this->RemoveFromBGFreeSlotQueue();
- uint32 almost_winning_team = HORDE;
+
ArenaTeam * winner_arena_team = NULL;
ArenaTeam * loser_arena_team = NULL;
uint32 loser_rating = 0;
uint32 winner_rating = 0;
WorldPacket data;
- Player *Source = NULL;
- const char *winmsg = "";
+ int32 winmsg_id = 0;
- if(winner == ALLIANCE)
+ if (winner == ALLIANCE)
{
- if(isBattleGround())
- winmsg = GetTrinityString(LANG_BG_A_WINS);
- else
- winmsg = GetTrinityString(LANG_ARENA_GOLD_WINS);
+ winmsg_id = isBattleGround() ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS;
PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
SetWinner(WINNER_ALLIANCE);
}
- else if(winner == HORDE)
+ else if (winner == HORDE)
{
- if(isBattleGround())
- winmsg = GetTrinityString(LANG_BG_H_WINS);
- else
- winmsg = GetTrinityString(LANG_ARENA_GREEN_WINS);
+ winmsg_id = isBattleGround() ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS;
PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
@@ -484,38 +676,23 @@ void BattleGround::EndBattleGround(uint32 winner)
}
SetStatus(STATUS_WAIT_LEAVE);
- m_EndTime = 0;
+ //we must set it this way, because end time is sent in packet!
+ m_EndTime = TIME_TO_AUTOREMOVE;
// arena rating calculation
- if(isArena() && isRated())
+ if (isArena() && isRated())
{
- if(winner == ALLIANCE)
- {
- winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
- loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
- }
- else if(winner == HORDE)
- {
- winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
- loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
- }
- if(winner_arena_team && loser_arena_team)
+ winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner));
+ loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(winner)));
+ if (winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team)
{
loser_rating = loser_arena_team->GetStats().rating;
winner_rating = winner_arena_team->GetStats().rating;
int32 winner_change = winner_arena_team->WonAgainst(loser_rating);
int32 loser_change = loser_arena_team->LostAgainst(winner_rating);
sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change);
- if(winner == ALLIANCE)
- {
- SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change);
- SetArenaTeamRatingChangeForTeam(HORDE, loser_change);
- }
- else
- {
- SetArenaTeamRatingChangeForTeam(HORDE, winner_change);
- SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change);
- }
+ SetArenaTeamRatingChangeForTeam(winner, winner_change);
+ SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loser_change);
sLog.outArena("Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. RatingChange: %i.", m_ArenaType, m_ArenaTeamIds[BG_TEAM_ALLIANCE], m_ArenaTeamIds[BG_TEAM_HORDE], winner_arena_team->GetId(), winner_change);
}
else
@@ -525,69 +702,66 @@ void BattleGround::EndBattleGround(uint32 winner)
}
}
- if(!isArena()){
-
- if(m_score[GetTeamIndexByTeamId(ALLIANCE)] == m_score[GetTeamIndexByTeamId(HORDE)])
- almost_winning_team = 0; //no real winner
- if(m_score[GetTeamIndexByTeamId(ALLIANCE)] > m_score[GetTeamIndexByTeamId(HORDE)])
- almost_winning_team = ALLIANCE;
-
- }
-
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr)
+ uint32 team = itr->second.Team;
+
+ if (!plr)
{
- sLog.outError("BattleGround: Player " I64FMTD " not found!", itr->first);
+ //if rated arena match - make member lost!
+ if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team)
+ {
+ if (team == winner)
+ winner_arena_team->OfflineMemberLost(itr->first, loser_rating);
+ else
+ loser_arena_team->OfflineMemberLost(itr->first, winner_rating);
+ }
+ sLog.outError("BattleGround: Player (GUID: %u) not found!", GUID_LOPART(itr->first));
continue;
}
// should remove spirit of redemption
if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
- plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
+ plr->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
- if(!plr->isAlive())
+ if (!plr->isAlive())
{
plr->ResurrectPlayer(1.0f);
plr->SpawnCorpseBones();
}
- uint32 team = itr->second.Team;
- if(!team) team = plr->GetTeam();
+ //this line is obsolete - team is set ALWAYS
+ //if(!team) team = plr->GetTeam();
// per player calculation
- if(isArena() && isRated() && winner_arena_team && loser_arena_team)
+ if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team)
{
- if(team == winner)
+ if (team == winner)
+ {
+ // update achievement BEFORE personal rating update
+ ArenaTeamMember* member = winner_arena_team->GetMember(plr->GetGUID());
+ if (member)
+ plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, member->personal_rating);
+
winner_arena_team->MemberWon(plr,loser_rating);
+ }
else
+ {
loser_arena_team->MemberLost(plr,winner_rating);
+
+ // Arena lost => reset the win_rated_arena having the "no_loose" condition
+ plr->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, ACHIEVEMENT_CRITERIA_CONDITION_NO_LOOSE);
+ }
}
- if(team == winner)
+ if (team == winner)
{
- if(!Source)
- Source = plr;
RewardMark(plr,ITEM_WINNER_COUNT);
- UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20);
- RewardQuest(plr);
- }
- else if(winner !=0)
- {
- RewardMark(plr,ITEM_LOSER_COUNT);
- }
- else if(winner == 0)
- {
- if(sWorld.getConfig(CONFIG_PREMATURE_BG_REWARD)) // We're feeling generous, giving rewards to people who not earned them ;)
- { //nested ifs for the win! its boring writing that, forgive me my unfunniness
-
- if(almost_winning_team == team) //player's team had more points
- RewardMark(plr,ITEM_WINNER_COUNT);
- else
- RewardMark(plr,ITEM_LOSER_COUNT); // if scores were the same, each team gets 1 mark.
+ RewardQuestComplete(plr);
}
- }
+ else if(winner)
+ RewardMark(plr,ITEM_LOSER_COUNT);
plr->CombatStopWithPets(true);
@@ -596,12 +770,13 @@ void BattleGround::EndBattleGround(uint32 winner)
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
plr->GetSession()->SendPacket(&data);
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
+ sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType());
plr->GetSession()->SendPacket(&data);
+ plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
- if(isArena() && isRated() && winner_arena_team && loser_arena_team)
+ if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team)
{
// update arena points only after increasing the player's match count!
//obsolete: winner_arena_team->UpdateArenaPointsHelper();
@@ -613,17 +788,16 @@ void BattleGround::EndBattleGround(uint32 winner)
// this way all arena team members will get notified, not only the ones who participated in this match
winner_arena_team->NotifyStatsChanged();
loser_arena_team->NotifyStatsChanged();
- sLog.outDebug("Rated arena match between %s and %s finished, winner: %s", loser_arena_team->GetName().c_str(),winner_arena_team->GetName().c_str(),winner_arena_team->GetName().c_str());
}
- // inform invited players about the removal
- sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
+ if (winmsg_id)
+ SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL);
+}
- if(Source)
- {
- ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg);
- SendPacketToAll(&data);
- }
+uint32 BattleGround::GetBonusHonorFromKill(uint32 kills) const
+{
+ //variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
+ return MaNGOS::Honor::hk_honor_at_level(GetMaxLevel(), kills);
}
uint32 BattleGround::GetBattlemasterEntry() const
@@ -641,14 +815,7 @@ uint32 BattleGround::GetBattlemasterEntry() const
void BattleGround::RewardMark(Player *plr,uint32 count)
{
- // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
- if(plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
- return;
-
- if(!plr || !count)
- return;
-
- BattleGroundMarks mark;
+ BattleGroundMarks mark;
switch(GetTypeID())
{
case BATTLEGROUND_AV:
@@ -660,41 +827,73 @@ void BattleGround::RewardMark(Player *plr,uint32 count)
case BATTLEGROUND_AB:
mark = ITEM_AB_MARK_OF_HONOR;
break;
- case BATTLEGROUND_EY:
+ case BATTLEGROUND_EY:
mark = ITEM_EY_MARK_OF_HONOR;
break;
default:
return;
}
- if ( objmgr.GetItemPrototype( mark ) )
+ //if (IsSpell)
+ // RewardSpellCast(plr,mark);
+ //else
+ RewardItem(plr,mark,count);
+}
+
+void BattleGround::RewardSpellCast(Player *plr, uint32 spell_id)
+{
+ // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
+ if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
+ return;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
+ if(!spellInfo)
{
- ItemPosCountVec dest;
- uint32 no_space_count = 0;
- uint8 msg = plr->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, mark, count, &no_space_count );
- if( msg != EQUIP_ERR_OK ) // convert to possible store amount
- count -= no_space_count;
+ sLog.outError("Battleground reward casting spell %u not exist.",spell_id);
+ return;
+ }
+
+ plr->CastSpell(plr, spellInfo, true);
+}
+
+void BattleGround::RewardItem(Player *plr, uint32 item_id, uint32 count)
+{
+ // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
+ if (plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
+ return;
- if(!dest.empty()) // can add some
- if(Item* item = plr->StoreNewItem( dest, mark, true, 0))
- plr->SendNewItem(item,count,false,true);
+ ItemPosCountVec dest;
+ uint32 no_space_count = 0;
+ uint8 msg = plr->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item_id, count, &no_space_count );
- if(no_space_count > 0)
- SendRewardMarkByMail(plr,mark,no_space_count);
+ if( msg == EQUIP_ERR_ITEM_NOT_FOUND)
+ {
+ sLog.outErrorDb("Battleground reward item (Entry %u) not exist in `item_template`.",item_id);
+ return;
}
+
+ if( msg != EQUIP_ERR_OK ) // convert to possible store amount
+ count -= no_space_count;
+
+ if( count != 0 && !dest.empty()) // can add some
+ if (Item* item = plr->StoreNewItem( dest, item_id, true, 0))
+ plr->SendNewItem(item,count,false,true);
+
+ if (no_space_count > 0)
+ SendRewardMarkByMail(plr,item_id,no_space_count);
}
void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
{
uint32 bmEntry = GetBattlemasterEntry();
- if(!bmEntry)
+ if (!bmEntry)
return;
ItemPrototype const* markProto = objmgr.GetItemPrototype(mark);
- if(!markProto)
+ if (!markProto)
return;
- if(Item* markItem = Item::CreateItem(mark,count,plr))
+ if (Item* markItem = Item::CreateItem(mark,count,plr))
{
// save new item before send
markItem->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted
@@ -706,8 +905,8 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
// subject: item name
std::string subject = markProto->Name1;
int loc_idx = plr->GetSession()->GetSessionDbLocaleIndex();
- if ( loc_idx >= 0 )
- if(ItemLocale const *il = objmgr.GetItemLocale(markProto->ItemId))
+ if (loc_idx >= 0 )
+ if (ItemLocale const *il = objmgr.GetItemLocale(markProto->ItemId))
if (il->Name.size() > size_t(loc_idx) && !il->Name[loc_idx].empty())
subject = il->Name[loc_idx];
@@ -721,12 +920,8 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
}
}
-void BattleGround::RewardQuest(Player *plr)
+void BattleGround::RewardQuestComplete(Player *plr)
{
- // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens
- if(plr->GetDummyAura(SPELL_AURA_PLAYER_INACTIVE))
- return;
-
uint32 quest;
switch(GetTypeID())
{
@@ -746,7 +941,7 @@ void BattleGround::RewardQuest(Player *plr)
return;
}
- plr->CastSpell(plr, quest, true);
+ RewardSpellCast(plr, quest);
}
void BattleGround::BlockMovement(Player *plr)
@@ -759,17 +954,17 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
uint32 team = GetPlayerTeam(guid);
bool participant = false;
// Remove from lists/maps
- std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid);
- if(itr != m_Players.end())
+ BattleGroundPlayerMap::iterator itr = m_Players.find(guid);
+ if (itr != m_Players.end())
{
- UpdatePlayersCountByTeam(team, true); // -1 player
+ UpdatePlayersCountByTeam(team, true); // -1 player
m_Players.erase(itr);
// check if the player was a participant of the match, or only entered through gm command (goname)
participant = true;
}
std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid);
- if(itr2 != m_PlayerScores.end())
+ if (itr2 != m_PlayerScores.end())
{
delete itr2->second; // delete player's score
m_PlayerScores.erase(itr2);
@@ -781,7 +976,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
// should remove spirit of redemption
if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
- plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
+ plr->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
if(plr && !plr->isAlive()) // resurrect on exit
{
@@ -791,100 +986,91 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
RemovePlayer(plr, guid); // BG subclass specific code
- if(plr)
+ if(participant) // if the player was a match participant, remove auras, calc rating, update queue
{
- plr->ClearAfkReports();
-
- if(participant) // if the player was a match participant, remove auras, calc rating, update queue
+ BattleGroundTypeId bgTypeId = GetTypeID();
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
+ if (plr)
{
+ plr->ClearAfkReports();
+
if(!team) team = plr->GetTeam();
- uint32 bgTypeId = GetTypeID();
- uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
// if arena, remove the specific arena auras
- if(isArena())
+ if (isArena())
{
- plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
- bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
-
- // summon old pet if there was one and there isn't a current pet
- if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber())
- {
- Pet* NewPet = new Pet;
- if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true))
- delete NewPet;
+ plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
+ bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
- (plr)->SetTemporaryUnsummonedPetNumber(0);
- }
+ // unsummon current and summon old pet if there was one and there isn't a current pet
+ plr->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT);
+ plr->ResummonPetTemporaryUnSummonedIfAny();
- if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
+ if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
//left a rated match while the encounter was in progress, consider as loser
- ArenaTeam * winner_arena_team = 0;
- ArenaTeam * loser_arena_team = 0;
- if(team == HORDE)
- {
- winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
- loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
- }
- else
- {
- winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
- loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
- }
- if(winner_arena_team && loser_arena_team)
- {
+ ArenaTeam * winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
+ ArenaTeam * loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team));
+ if (winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team)
loser_arena_team->MemberLost(plr,winner_arena_team->GetRating());
- }
}
}
-
- WorldPacket data;
- if(SendPacket)
+ if (SendPacket)
{
- sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0);
+ WorldPacket data;
+ sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0, 0);
plr->GetSession()->SendPacket(&data);
}
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
-
- DecreaseInvitedCount(team);
- //we should update battleground queue, but only if bg isn't ending
- if (GetQueueType() < MAX_BATTLEGROUND_QUEUES)
- sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType());
-
- Group * group = plr->GetGroup();
- // remove from raid group if exist
- if(group && group == GetBgRaid(team))
+ }
+ else
+ // removing offline participant
+ {
+ if (isRated() && GetStatus() == STATUS_IN_PROGRESS)
{
- if(!group->RemoveMember(guid, 0)) // group was disbanded
- {
- SetBgRaid(team, NULL);
- delete group;
- }
+ //left a rated match while the encounter was in progress, consider as loser
+ ArenaTeam * others_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team)));
+ ArenaTeam * players_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team));
+ if (others_arena_team && players_arena_team)
+ players_arena_team->OfflineMemberLost(guid, others_arena_team->GetRating());
}
+ }
- // Let others know
- sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);
- SendPacketToTeam(team, &data, plr, false);
+ // remove from raid group if player is member
+ if (Group *group = GetBgRaid(team))
+ {
+ if( !group->RemoveMember(guid, 0) ) // group was disbanded
+ {
+ SetBgRaid(team, NULL);
+ delete group;
+ }
}
+ DecreaseInvitedCount(team);
+ //we should update battleground queue, but only if bg isn't ending
+ if (isBattleGround() && GetStatus() < STATUS_WAIT_LEAVE)
+ sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueId());
+ // Let others know
+ WorldPacket data;
+ sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, guid);
+ SendPacketToTeam(team, &data, plr, false);
+ }
+ if (plr)
+ {
// Do next only if found in battleground
- plr->SetBattleGroundId(0); // We're not in BG.
+ plr->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG.
// reset destination bg team
plr->SetBGTeam(0);
- if(Transport)
- {
- plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO());
- }
+ if (Transport)
+ plr->TeleportTo(plr->GetBattleGroundEntryPoint());
- // Log
sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());
}
- if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
+ if (!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
{
// if no players left AND no invitees left, set this bg to delete in next update
// direct deletion could cause crashes
@@ -900,7 +1086,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
// this method is called when no players remains in battleground
void BattleGround::Reset()
{
- SetQueueType(MAX_BATTLEGROUND_QUEUES);
+ SetQueueId(QUEUE_ID_MAX_LEVEL_19);
SetWinner(WINNER_NONE);
SetStatus(STATUS_WAIT_QUEUE);
SetStartTime(0);
@@ -912,7 +1098,7 @@ void BattleGround::Reset()
m_Events = 0;
if (m_InvitedAlliance > 0 || m_InvitedHorde > 0)
- sLog.outError("BattleGround system ERROR: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance, m_InvitedHorde);
+ sLog.outError("BattleGround system: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d", m_InvitedAlliance, m_InvitedHorde);
m_InvitedAlliance = 0;
m_InvitedHorde = 0;
@@ -920,9 +1106,6 @@ void BattleGround::Reset()
m_Players.clear();
m_PlayerScores.clear();
-
- // reset BGSubclass
- ResetBGSubclass();
}
void BattleGround::StartBattleGround()
@@ -942,7 +1125,7 @@ void BattleGround::AddPlayer(Player *plr)
uint32 team = plr->GetBGTeam();
BattleGroundPlayer bp;
- bp.LastOnlineTime = 0;
+ bp.OfflineRemoveTime = 0;
bp.Team = team;
// Add to list/maps
@@ -955,40 +1138,28 @@ void BattleGround::AddPlayer(Player *plr)
SendPacketToTeam(team, &data, plr, false);
// add arena specific auras
- if(isArena())
+ if (isArena())
{
plr->RemoveArenaSpellCooldowns();
plr->RemoveArenaAuras();
- plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT, true);
+ plr->RemoveArenaEnchantments(TEMP_ENCHANTMENT_SLOT);
if(team == ALLIANCE) // gold
{
- if(plr->GetTeam() == HORDE)
+ if (plr->GetTeam() == HORDE)
plr->CastSpell(plr, SPELL_HORDE_GOLD_FLAG,true);
else
plr->CastSpell(plr, SPELL_ALLIANCE_GOLD_FLAG,true);
}
else // green
{
- if(plr->GetTeam() == HORDE)
+ if (plr->GetTeam() == HORDE)
plr->CastSpell(plr, SPELL_HORDE_GREEN_FLAG,true);
else
plr->CastSpell(plr, SPELL_ALLIANCE_GREEN_FLAG,true);
}
plr->DestroyConjuredItems(true);
-
- Pet* pet = plr->GetPet();
- if(pet)
- {
- if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)
- {
- (plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
- (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
- }
- (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
- }
- else
- (plr)->SetTemporaryUnsummonedPetNumber(0);
+ plr->UnsummonPetTemporaryIfAny();
if(GetStatus() == STATUS_WAIT_JOIN) // not started yet
{
@@ -1004,15 +1175,86 @@ void BattleGround::AddPlayer(Player *plr)
plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells.
}
+ plr->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, ACHIEVEMENT_CRITERIA_CONDITION_MAP, GetMapId());
+ plr->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, ACHIEVEMENT_CRITERIA_CONDITION_MAP, GetMapId());
+
+ // setup BG group membership
+ PlayerAddedToBGCheckIfBGIsRunning(plr);
+ AddOrSetPlayerToCorrectBgGroup(plr, guid, team);
+
// Log
sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName());
}
+/* this method adds player to his team's bg group, or sets his correct group if player is already in bg group */
+void BattleGround::AddOrSetPlayerToCorrectBgGroup(Player *plr, uint64 plr_guid, uint32 team)
+{
+ Group* group = GetBgRaid(team);
+ if(!group) // first player joined
+ {
+ group = new Group;
+ SetBgRaid(team, group);
+ group->Create(plr_guid, plr->GetName());
+ }
+ else // raid already exist
+ {
+ if (group->IsMember(plr_guid))
+ {
+ uint8 subgroup = group->GetMemberGroup(plr_guid);
+ plr->SetBattleGroundRaid(group, subgroup);
+ }
+ else
+ {
+ group->AddMember(plr_guid, plr->GetName());
+ if (Group* originalGroup = plr->GetOriginalGroup())
+ if (originalGroup->IsLeader(plr_guid))
+ group->ChangeLeader(plr_guid);
+ }
+ }
+}
+
+// This method should be called when player logs into running battleground
+void BattleGround::EventPlayerLoggedIn(Player* player, uint64 plr_guid)
+{
+ // player is correct pointer
+ for(std::deque<uint64>::iterator itr = m_OfflineQueue.begin(); itr != m_OfflineQueue.end(); ++itr)
+ {
+ if (*itr == plr_guid)
+ {
+ m_OfflineQueue.erase(itr);
+ break;
+ }
+ }
+ m_Players[plr_guid].OfflineRemoveTime = 0;
+ PlayerAddedToBGCheckIfBGIsRunning(player);
+ // if battleground is starting, then add preparation aura
+ // we don't have to do that, because preparation aura isn't removed when player logs out
+}
+
+// This method should be called when player logs out from running battleground
+void BattleGround::EventPlayerLoggedOut(Player* player)
+{
+ // player is correct pointer, it is checked in WorldSession::LogoutPlayer()
+ m_OfflineQueue.push_back(player->GetGUID());
+ m_Players[player->GetGUID()].OfflineRemoveTime = sWorld.GetGameTime() + MAX_OFFLINE_TIME;
+ if (GetStatus() == STATUS_IN_PROGRESS)
+ {
+ if (isBattleGround())
+ EventPlayerDroppedFlag(player);
+ else
+ {
+ //1 player is logging out, if it is the last, then end arena!
+ if (GetAlivePlayersCountByTeam(player->GetTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player->GetTeam())))
+ EndBattleGround(GetOtherTeam(player->GetTeam()));
+ }
+ }
+}
+
/* This method should be called only once ... it adds pointer to queue */
void BattleGround::AddToBGFreeSlotQueue()
{
// make sure to add only once
- if(!m_InBGFreeSlotQueue)
+ if (!m_InBGFreeSlotQueue && isBattleGround())
{
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
m_InBGFreeSlotQueue = true;
@@ -1025,7 +1267,7 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
// set to be able to re-add if needed
m_InBGFreeSlotQueue = false;
// uncomment this code when battlegrounds will work like instances
- for (std::deque<BattleGround*>::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr)
+ for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr)
{
if ((*itr)->GetInstanceID() == m_InstanceID)
{
@@ -1036,7 +1278,7 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
}
// get the number of free slots for team
-// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group
+// returns the number how many players can join battleground to MaxPlayersPerTeam
uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
{
//if BG is starting ... invite anyone
@@ -1069,7 +1311,6 @@ uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
// difference based on max players per team (don't allow inviting more)
uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
-
// difference based on players who already entered
// default: allow 0
uint32 diff3 = 0;
@@ -1087,11 +1328,9 @@ uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
// min of diff and diff 2
diff = diff < diff2 ? diff : diff2;
-
// min of diff, diff2 and diff3
return diff < diff3 ? diff : diff3 ;
}
-
return 0;
}
@@ -1103,7 +1342,7 @@ bool BattleGround::HasFreeSlots() const
void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
//this procedure is called from virtual function implemented in bg subclass
- std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
+ std::map<uint64, BattleGroundScore*>::const_iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;
@@ -1121,10 +1360,10 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
break;
case SCORE_BONUS_HONOR: // Honor bonus
// do not add honor in arenas
- if(isBattleGround())
+ if (isBattleGround())
{
// reward honor instantly
- if(Source->RewardHonor(NULL, 1, value))
+ if (Source->RewardHonor(NULL, 1, value))
itr->second->BonusHonor += value;
}
break;
@@ -1146,14 +1385,13 @@ void BattleGround::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid
m_ReviveQueue[npc_guid].push_back(player_guid);
Player *plr = objmgr.GetPlayer(player_guid);
- if(!plr)
+ if (!plr)
return;
- plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true);
SpellEntry const *spellInfo = sSpellStore.LookupEntry( SPELL_WAITING_FOR_RESURRECT );
- if(spellInfo)
+ if (spellInfo)
{
- Aura *Aur = CreateAura(spellInfo, 0, NULL, plr);
+ Aura *Aur = new Aura(spellInfo, 1, NULL, plr);
plr->AddAura(Aur);
}
}
@@ -1164,12 +1402,12 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
{
for(std::vector<uint64>::iterator itr2 =(itr->second).begin(); itr2 != (itr->second).end(); ++itr2)
{
- if(*itr2 == player_guid)
+ if (*itr2 == player_guid)
{
(itr->second).erase(itr2);
Player *plr = objmgr.GetPlayer(player_guid);
- if(!plr)
+ if (!plr)
return;
plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT);
@@ -1183,14 +1421,15 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
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)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
- if(!map)
+ if (!map)
return false;
// must be created this way, adding to godatamap would add it to the base map of the instance
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// so we must create it specific for this instance
GameObject * go = new GameObject;
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,
+ PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,GO_STATE_READY))
{
sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);
sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry);
@@ -1230,10 +1469,10 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
void BattleGround::DoorClose(uint32 type)
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
//if doors are open, close it
- if( obj->getLootState() == GO_ACTIVATED && !obj->GetGoState() )
+ if (obj->getLootState() == GO_ACTIVATED && obj->GetGoState() != GO_STATE_READY)
{
//change state to allow door to be closed
obj->SetLootState(GO_READY);
@@ -1249,7 +1488,7 @@ void BattleGround::DoorClose(uint32 type)
void BattleGround::DoorOpen(uint32 type)
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
//change state to be sure they will be opened
obj->SetLootState(GO_READY);
@@ -1280,15 +1519,15 @@ Creature* BattleGround::GetBGCreature(uint32 type)
void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
- if(!map)
+ if (!map)
return;
- if( respawntime == 0 )
+ if (respawntime == 0)
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
- if( obj->getLootState() == GO_JUST_DEACTIVATED )
+ if (obj->getLootState() == GO_JUST_DEACTIVATED)
obj->SetLootState(GO_READY);
obj->SetRespawnTime(0);
map->Add(obj);
@@ -1297,7 +1536,7 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
else
{
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(obj)
+ if (obj)
{
map->Add(obj);
obj->SetRespawnTime(respawntime);
@@ -1309,28 +1548,18 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
- if(!map)
+ if (!map)
return NULL;
Creature* pCreature = new Creature;
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval))
+ if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, teamval, x, y, z, o))
{
sLog.outError("Can't create creature entry: %u",entry);
delete pCreature;
return NULL;
}
- pCreature->Relocate(x, y, z, o);
-
- if(!pCreature->IsPositionValid())
- {
- 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());
- delete pCreature;
- return NULL;
- }
-
pCreature->SetHomePosition(x, y, z, o);
- pCreature->AIM_Initialize();
//pCreature->SetDungeonDifficulty(0);
@@ -1343,13 +1572,13 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
{
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
- if(!map)
+ if (!map)
return false;
- if(respawntime == 0)
+ if (respawntime == 0)
{
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
- if(obj)
+ if (obj)
{
//obj->Respawn(); // bugged
obj->SetRespawnTime(0);
@@ -1360,7 +1589,7 @@ void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
else
{
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
- if(obj)
+ if (obj)
{
obj->setDeathState(DEAD);
obj->SetRespawnTime(respawntime);
@@ -1371,8 +1600,11 @@ void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
*/
bool BattleGround::DelCreature(uint32 type)
{
+ if (!m_BgCreatures[type])
+ return true;
+
Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
- if(!cr)
+ if (!cr)
{
sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type]));
return false;
@@ -1386,8 +1618,11 @@ bool BattleGround::DelCreature(uint32 type)
bool BattleGround::DelObject(uint32 type)
{
+ if (!m_BgObjects[type])
+ return true;
+
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
- if(!obj)
+ if (!obj)
{
sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type]));
return false;
@@ -1402,13 +1637,13 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
{
uint32 entry = 0;
- if(team == ALLIANCE)
+ if (team == ALLIANCE)
entry = 13116;
else
entry = 13117;
Creature* pCreature = AddCreature(entry,type,team,x,y,z,o);
- if(!pCreature)
+ if (!pCreature)
{
sLog.outError("Can't create Spirit guide. BattleGround not created!");
EndNow();
@@ -1419,10 +1654,12 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID());
// aura
- pCreature->SetUInt32Value(UNIT_FIELD_AURA, SPELL_SPIRIT_HEAL_CHANNEL);
- pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
- pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
- pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
+ //TODO: Fix display here
+ //pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
+
+ //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
+ //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
+ //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
// casting visual effect
pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
// correct cast speed
@@ -1433,31 +1670,40 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
return true;
}
-void BattleGround::SendMessageToAll(char const* text)
+void BattleGround::SendMessageToAll(int32 entry, ChatMsg type, Player const* source)
{
- WorldPacket data;
- ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL);
- SendPacketToAll(&data);
+ MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source);
+ MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundChatBuilder> bg_do(bg_builder);
+ BroadcastWorker(bg_do);
}
-void BattleGround::SendMessageToAll(int32 entry)
+void BattleGround::PSendMessageToAll(int32 entry, ChatMsg type, Player const* source, ...)
{
- char const* text = GetTrinityString(entry);
- WorldPacket data;
- ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, text, NULL);
- SendPacketToAll(&data);
+ va_list ap;
+ va_start(ap, source);
+
+ MaNGOS::BattleGroundChatBuilder bg_builder(type, entry, source, &ap);
+ MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundChatBuilder> bg_do(bg_builder);
+ BroadcastWorker(bg_do);
+
+ va_end(ap);
+}
+
+void BattleGround::SendMessage2ToAll(int32 entry, ChatMsg type, Player const* source, int32 arg1, int32 arg2)
+{
+ MaNGOS::BattleGround2ChatBuilder bg_builder(type, entry, source, arg1, arg2);
+ MaNGOS::LocalizedPacketDo<MaNGOS::BattleGround2ChatBuilder> bg_do(bg_builder);
+ BroadcastWorker(bg_do);
}
void BattleGround::EndNow()
{
RemoveFromBGFreeSlotQueue();
SetStatus(STATUS_WAIT_LEAVE);
- SetEndTime(TIME_TO_AUTOREMOVE);
- // inform invited players about the removal
- sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
+ SetEndTime(0);
}
-// Battleground messages are localized using the dbc lang, they are not client language dependent
+//to be removed
const char *BattleGround::GetTrinityString(int32 entry)
{
// FIXME: now we have different DBC locales and need localized message for each target client
@@ -1472,7 +1718,7 @@ buffs are in their positions when battleground starts
void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
{
GameObject *obj = HashMapHolder<GameObject>::Find(go_guid);
- if(!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
+ if (!obj || obj->GetGoType() != GAMEOBJECT_TYPE_TRAP || !obj->isSpawned())
return;
//change buff type, when buff is used:
@@ -1488,13 +1734,13 @@ void BattleGround::HandleTriggerBuff(uint64 const& go_guid)
//randomly select new buff
uint8 buff = urand(0, 2);
uint32 entry = obj->GetEntry();
- if( m_BuffChange && entry != Buff_Entries[buff] )
+ if (m_BuffChange && entry != Buff_Entries[buff])
{
//despawn current buff
SpawnBGObject(index, RESPAWN_ONE_DAY);
//set index for new one
for (uint8 currBuffTypeIndex = 0; currBuffTypeIndex < 3; ++currBuffTypeIndex)
- if( entry == Buff_Entries[currBuffTypeIndex] )
+ if (entry == Buff_Entries[currBuffTypeIndex])
{
index -= currBuffTypeIndex;
index += buff;
@@ -1512,46 +1758,77 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
UpdatePlayerScore(player, SCORE_DEATHS, 1);
// add +1 kills to group and +1 killing_blows to killer
- if( killer )
+ if (killer)
{
UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1);
UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1);
- for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
Player *plr = objmgr.GetPlayer(itr->first);
- if(!plr || plr == killer)
+ if (!plr || plr == killer)
continue;
- if( plr->GetTeam() == killer->GetTeam() && plr->IsAtGroupRewardDistance(player) )
+ if (plr->GetTeam() == killer->GetTeam() && plr->IsAtGroupRewardDistance(player))
UpdatePlayerScore(plr, SCORE_HONORABLE_KILLS, 1);
}
}
- // to be able to remove insignia
- player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );
+ // to be able to remove insignia -- ONLY IN BattleGrounds
+ if (!isArena())
+ player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );
}
// return the player's team based on battlegroundplayer info
// used in same faction arena matches mainly
uint32 BattleGround::GetPlayerTeam(uint64 guid)
{
- std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid);
- if(itr!=m_Players.end())
+ BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid);
+ if (itr!=m_Players.end())
return itr->second.Team;
return 0;
}
+uint32 BattleGround::GetOtherTeam(uint32 teamId)
+{
+ return (teamId) ? ((teamId == ALLIANCE) ? HORDE : ALLIANCE) : 0;
+}
+
+bool BattleGround::IsPlayerInBattleGround(uint64 guid)
+{
+ BattleGroundPlayerMap::const_iterator itr = m_Players.find(guid);
+ if (itr != m_Players.end())
+ return true;
+ return false;
+}
+
+void BattleGround::PlayerAddedToBGCheckIfBGIsRunning(Player* plr)
+{
+ if (GetStatus() != STATUS_WAIT_LEAVE)
+ return;
+
+ WorldPacket data;
+ BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType());
+
+ BlockMovement(plr);
+
+ sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
+ plr->GetSession()->SendPacket(&data);
+
+ sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType());
+ plr->GetSession()->SendPacket(&data);
+}
+
uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
{
int count = 0;
- for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
+ for(BattleGroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
- if(itr->second.Team == Team)
+ if (itr->second.Team == Team)
{
Player * pl = objmgr.GetPlayer(itr->first);
- if(pl && pl->isAlive())
+ if (pl && pl->isAlive() && !pl->HasByteFlag(UNIT_FIELD_BYTES_2, 3, FORM_SPIRITOFREDEMPTION))
++count;
}
}
@@ -1568,7 +1845,7 @@ void BattleGround::SetHoliday(bool is_holiday)
int32 BattleGround::GetObjectType(uint64 guid)
{
- for(uint32 i = 0;i <= m_BgObjects.size(); i++)
+ for(uint32 i = 0; i < m_BgObjects.size(); ++i)
if(m_BgObjects[i] == guid)
return i;
sLog.outError("BattleGround: cheating? a player used a gameobject which isnt supposed to be a usable object!");
@@ -1579,3 +1856,23 @@ void BattleGround::HandleKillUnit(Creature *creature, Player *killer)
{
}
+void BattleGround::CheckArenaWinConditions()
+{
+ if (!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
+ EndBattleGround(HORDE);
+ else if (GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
+ EndBattleGround(ALLIANCE);
+}
+
+void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid )
+{
+ Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE];
+ if(old_raid) old_raid->SetBattlegroundGroup(NULL);
+ if(bg_raid) bg_raid->SetBattlegroundGroup(this);
+ old_raid = bg_raid;
+}
+
+WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player )
+{
+ return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() );
+}