diff options
Diffstat (limited to 'src/game/BattleGround.cpp')
-rw-r--r-- | src/game/BattleGround.cpp | 771 |
1 files changed, 513 insertions, 258 deletions
diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 8ef926b4aaf..f542ff1f145 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 @@ -21,23 +21,119 @@ #include "Object.h" #include "Player.h" #include "BattleGround.h" +#include "BattleGroundMgr.h" #include "Creature.h" #include "MapManager.h" #include "Language.h" -#include "Chat.h" #include "SpellAuras.h" #include "ArenaTeam.h" #include "World.h" +#include "Group.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" #include "Util.h" +#include "Formulas.h" +#include "GridNotifiersImpl.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::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 +184,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,13 +211,17 @@ 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()) @@ -120,65 +230,32 @@ BattleGround::~BattleGround() this->RemoveFromBGFreeSlotQueue(); } -void BattleGround::Update(time_t diff) +void BattleGround::Update(uint32 diff) { - if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) + if(!GetPlayersSize() && !GetReviveQueueSize()) //BG is empty return; - 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) { @@ -228,6 +305,10 @@ 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())) { @@ -235,39 +316,140 @@ void BattleGround::Update(time_t diff) { m_PrematureCountDown = true; m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime(); - SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); } 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; + /*********************************************************/ + /*** 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); + + 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) @@ -281,7 +463,7 @@ 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::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); if(plr) @@ -293,7 +475,7 @@ void BattleGround::SendPacketToAll(WorldPacket *packet) 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::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -306,7 +488,7 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player * 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) @@ -325,7 +507,7 @@ 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::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -335,7 +517,7 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) continue; } - uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + uint32 team = itr->second.Team; if(!team) team = plr->GetTeam(); if(team == TeamID) @@ -348,7 +530,7 @@ 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::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -358,7 +540,7 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) continue; } - uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + uint32 team = itr->second.Team; if(!team) team = plr->GetTeam(); if(team == TeamID) @@ -385,7 +567,7 @@ 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::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -395,7 +577,7 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) continue; } - uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + uint32 team = itr->second.Team; if(!team) team = plr->GetTeam(); if(team == TeamID) @@ -410,7 +592,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, if(!factionEntry) return; - 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); @@ -420,7 +602,7 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, continue; } - uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + uint32 team = itr->second.Team; if(!team) team = plr->GetTeam(); if(team == TeamID) @@ -451,15 +633,11 @@ void BattleGround::EndBattleGround(uint32 winner) uint32 loser_rating = 0; uint32 winner_rating = 0; WorldPacket data; - Player *Source = NULL; - const char *winmsg = ""; + int32 winmsg_id = 0; 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 @@ -467,10 +645,7 @@ void BattleGround::EndBattleGround(uint32 winner) } 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 @@ -482,38 +657,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(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 ) { 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); } else { @@ -522,11 +682,21 @@ void BattleGround::EndBattleGround(uint32 winner) } } - 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); + uint32 team = itr->second.Team; + if(!plr) { + //if rated arena match - make member lost! + if(isArena() && isRated() && 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 " I64FMTD " not found!", itr->first); continue; } @@ -541,8 +711,8 @@ void BattleGround::EndBattleGround(uint32 winner) 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) @@ -555,10 +725,7 @@ void BattleGround::EndBattleGround(uint32 winner) if(team == winner) { - if(!Source) - Source = plr; RewardMark(plr,ITEM_WINNER_COUNT); - UpdatePlayerScore(plr, SCORE_BONUS_HONOR, 20); RewardQuest(plr); } else @@ -573,9 +740,10 @@ 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) @@ -593,13 +761,16 @@ void BattleGround::EndBattleGround(uint32 winner) } // inform invited players about the removal - sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); - if(Source) - { - ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg); - SendPacketToAll(&data); - } + if(winmsg_id) + SendMessageToAll(winmsg_id, CHAT_MSG_BG_SYSTEM_NEUTRAL); +} + +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 @@ -735,10 +906,10 @@ 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); + 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; @@ -767,21 +938,21 @@ 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()) { - 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->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()) @@ -796,67 +967,64 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac 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)); - } + ArenaTeam * winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(team))); + ArenaTeam * loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(team)); if(winner_arena_team && loser_arena_team) - { loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); - } } } - - WorldPacket data; 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()); - } + plr->TeleportTo(plr->GetBattleGroundEntryPoint()); - // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } @@ -876,7 +1044,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); @@ -896,9 +1064,6 @@ void BattleGround::Reset() m_Players.clear(); m_PlayerScores.clear(); - - // reset BGSubclass - ResetBGSubclass(); } void BattleGround::StartBattleGround() @@ -917,7 +1082,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 @@ -962,7 +1127,7 @@ void BattleGround::AddPlayer(Player *plr) } (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); } - else + else (plr)->SetTemporaryUnsummonedPetNumber(0); if(GetStatus() == STATUS_WAIT_JOIN) // not started yet @@ -979,15 +1144,83 @@ void BattleGround::AddPlayer(Player *plr) plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells. } + // 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; @@ -1000,7 +1233,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) { @@ -1011,61 +1244,12 @@ 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 - if (GetStatus() == STATUS_WAIT_JOIN) + //return free slot count to MaxPlayerPerTeam + if (GetStatus() == STATUS_WAIT_JOIN || GetStatus() == STATUS_IN_PROGRESS) return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; - //if BG is already started .. do not allow to join too much players of one faction - uint32 otherTeam; - uint32 otherIn; - if (Team == ALLIANCE) - { - otherTeam = GetInvitedCount(HORDE); - otherIn = GetPlayersCountByTeam(HORDE); - } - else - { - otherTeam = GetInvitedCount(ALLIANCE); - otherIn = GetPlayersCountByTeam(ALLIANCE); - } - if (GetStatus() == STATUS_IN_PROGRESS) - { - // difference based on ppl invited (not necessarily entered battle) - // default: allow 0 - uint32 diff = 0; - // allow join one person if the sides are equal (to fill up bg to minplayersperteam) - if (otherTeam == GetInvitedCount(Team)) - diff = 1; - // allow join more ppl if the other side has more players - else if(otherTeam > GetInvitedCount(Team)) - diff = otherTeam - GetInvitedCount(Team); - - // 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; - // allow join one person if the sides are equal (to fill up bg minplayersperteam) - if (otherIn == GetPlayersCountByTeam(Team)) - diff3 = 1; - // allow join more ppl if the other side has more players - else if (otherIn > GetPlayersCountByTeam(Team)) - diff3 = otherIn - GetPlayersCountByTeam(Team); - // or other side has less than minPlayersPerTeam - else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam()) - diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1; - - // return the minimum of the 3 differences - - // min of diff and diff 2 - diff = diff < diff2 ? diff : diff2; - - // min of diff, diff2 and diff3 - return diff < diff3 ? diff : diff3 ; - } return 0; } @@ -1165,7 +1349,8 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float // 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,1)) { sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); @@ -1288,7 +1473,7 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f 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)) { sLog.outError("Can't create creature entry: %u",entry); delete pCreature; @@ -1344,6 +1529,9 @@ 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) { @@ -1359,6 +1547,9 @@ 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) { @@ -1392,10 +1583,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 @@ -1406,31 +1599,42 @@ 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); + SetEndTime(0); // inform invited players about the removal - sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } -// 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 @@ -1490,7 +1694,7 @@ void BattleGround::HandleKillPlayer( Player *player, Player *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::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -1502,24 +1706,55 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) } } - // 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); + 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) { @@ -1552,3 +1787,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() ); +} |