2010-10-07 15:35:36 +02:00
/*
2011-01-01 15:01:13 +01:00
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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 the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "Player.h"
2009-06-04 21:41:07 +02:00
#include "ObjectMgr.h"
#include "World.h"
2010-06-08 13:05:47 -06:00
#include "WorldPacket.h"
2009-10-17 15:51:44 -07:00
2009-06-04 21:41:07 +02:00
#include "ArenaTeam.h"
2010-08-08 04:37:24 +02:00
#include "Battleground.h"
#include "BattlegroundMgr.h"
2008-10-02 16:23:55 -05:00
#include "Creature.h"
2010-06-08 13:05:47 -06:00
#include "Formulas.h"
#include "GridNotifiersImpl.h"
2009-06-04 21:41:07 +02:00
#include "Group.h"
2010-06-08 13:05:47 -06:00
#include "Language.h"
2009-06-04 21:41:07 +02:00
#include "MapManager.h"
#include "Object.h"
2008-10-02 16:23:55 -05:00
#include "SpellAuras.h"
2010-01-10 01:23:15 +01:00
#include "SpellAuraEffects.h"
2010-06-08 13:05:47 -06:00
#include "Util.h"
2009-06-04 21:41:07 +02:00
2009-12-20 15:20:04 +01:00
namespace Trinity
2009-03-09 17:00:31 -06:00
{
2010-08-08 04:37:24 +02:00
class BattlegroundChatBuilder
2009-03-09 17:00:31 -06:00
{
public :
2010-08-08 04:37:24 +02:00
BattlegroundChatBuilder ( ChatMsg msgtype , int32 textId , Player const * source , va_list * args = NULL )
2011-03-14 19:21:34 +06:00
: _msgtype ( msgtype ), _textId ( textId ), _source ( source ), _args ( args ) { }
2010-09-17 07:04:29 +02:00
void operator ()( WorldPacket & data , LocaleConstant loc_idx )
2009-03-09 17:00:31 -06:00
{
2011-03-14 19:21:34 +06:00
char const * text = sObjectMgr -> GetTrinityString ( _textId , loc_idx );
if ( _args )
2009-03-09 17:00:31 -06:00
{
// we need copy va_list before use or original va_list will corrupted
va_list ap ;
2011-03-14 19:21:34 +06:00
va_copy ( ap , * _args );
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
char str [ 2048 ];
vsnprintf ( str , 2048 , text , ap );
2009-03-09 17:00:31 -06:00
va_end ( ap );
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
do_helper ( data , & str [ 0 ]);
2009-03-09 17:00:31 -06:00
}
else
2011-03-14 19:21:34 +06:00
do_helper ( data , text );
2009-03-09 17:00:31 -06:00
}
2011-03-14 19:21:34 +06:00
2009-03-09 17:00:31 -06:00
private :
void do_helper ( WorldPacket & data , char const * text )
{
2011-03-14 19:21:34 +06:00
uint64 target_guid = _source ? _source -> GetGUID () : 0 ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
data << uint8 ( _msgtype );
2009-03-09 17:00:31 -06:00
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 );
2011-03-14 19:21:34 +06:00
data << uint32 ( strlen ( text ) + 1 );
2009-03-09 17:00:31 -06:00
data << text ;
2011-03-14 19:21:34 +06:00
data << uint8 ( _source ? _source -> chatTag () : uint8 ( 0 ));
2009-03-09 17:00:31 -06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
ChatMsg _msgtype ;
int32 _textId ;
Player const * _source ;
va_list * _args ;
2009-03-09 17:00:31 -06:00
};
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
class Battleground2ChatBuilder
2009-03-09 17:06:13 -06:00
{
public :
2010-08-08 04:37:24 +02:00
Battleground2ChatBuilder ( ChatMsg msgtype , int32 textId , Player const * source , int32 arg1 , int32 arg2 )
2011-03-14 19:21:34 +06:00
: _msgtype ( msgtype ), _textId ( textId ), _source ( source ), _arg1 ( arg1 ), _arg2 ( arg2 ) {}
2010-09-17 07:04:29 +02:00
void operator ()( WorldPacket & data , LocaleConstant loc_idx )
2009-03-09 17:06:13 -06:00
{
2011-03-14 19:21:34 +06:00
char const * text = sObjectMgr -> GetTrinityString ( _textId , loc_idx );
char const * arg1str = _arg1 ? sObjectMgr -> GetTrinityString ( _arg1 , loc_idx ) : "" ;
char const * arg2str = _arg2 ? sObjectMgr -> GetTrinityString ( _arg2 , loc_idx ) : "" ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
char str [ 2048 ];
snprintf ( str , 2048 , text , arg1str , arg2str );
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
uint64 target_guid = _source ? _source -> GetGUID () : 0 ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
data << uint8 ( _msgtype );
2009-03-09 17:06:13 -06:00
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 );
2011-03-14 19:21:34 +06:00
data << uint32 ( strlen ( str ) + 1 );
2009-03-09 17:06:13 -06:00
data << str ;
2011-03-14 19:21:34 +06:00
data << uint8 ( _source ? _source -> chatTag () : uint8 ( 0 ));
2009-03-09 17:06:13 -06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
private :
ChatMsg _msgtype ;
int32 _textId ;
Player const * _source ;
int32 _arg1 ;
int32 _arg2 ;
2009-03-09 17:06:13 -06:00
};
2009-12-20 15:20:04 +01:00
} // namespace Trinity
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
template < class Do >
2010-08-08 04:37:24 +02:00
void Battleground :: BroadcastWorker ( Do & _do )
2009-03-09 17:06:13 -06:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2009-04-08 16:33:46 -05:00
if ( Player * plr = ObjectAccessor :: FindPlayer ( MAKE_NEW_GUID ( itr -> first , 0 , HIGHGUID_PLAYER )))
2009-03-09 17:06:13 -06:00
_do ( plr );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground :: Battleground ()
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
m_TypeID = BATTLEGROUND_TYPE_NONE ;
m_RandomTypeID = BATTLEGROUND_TYPE_NONE ;
2008-10-02 16:23:55 -05:00
m_InstanceID = 0 ;
2009-03-05 19:02:08 -06:00
m_Status = STATUS_NONE ;
2009-03-10 15:30:44 -06:00
m_ClientInstanceID = 0 ;
2008-10-02 16:23:55 -05:00
m_EndTime = 0 ;
m_LastResurrectTime = 0 ;
2010-02-15 15:31:27 +01:00
m_BracketId = BG_BRACKET_ID_FIRST ;
2008-10-02 16:23:55 -05:00
m_InvitedAlliance = 0 ;
m_InvitedHorde = 0 ;
m_ArenaType = 0 ;
m_IsArena = false ;
m_Winner = 2 ;
m_StartTime = 0 ;
2010-12-02 22:50:30 +01:00
m_ResetStatTimer = 0 ;
2008-10-02 16:23:55 -05:00
m_Events = 0 ;
m_IsRated = false ;
m_BuffChange = false ;
2010-05-26 11:34:37 +02:00
m_IsRandom = false ;
2008-10-02 16:23:55 -05:00
m_Name = "" ;
m_LevelMin = 0 ;
m_LevelMax = 0 ;
2008-10-05 08:48:32 -05:00
m_InBGFreeSlotQueue = false ;
m_SetDeleteThis = false ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_MaxPlayersPerTeam = 0 ;
m_MaxPlayers = 0 ;
m_MinPlayersPerTeam = 0 ;
m_MinPlayers = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_MapId = 0 ;
2009-12-17 10:43:12 +01:00
m_Map = NULL ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_TeamStartLocX [ BG_TEAM_ALLIANCE ] = 0 ;
m_TeamStartLocX [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_TeamStartLocY [ BG_TEAM_ALLIANCE ] = 0 ;
m_TeamStartLocY [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_TeamStartLocZ [ BG_TEAM_ALLIANCE ] = 0 ;
m_TeamStartLocZ [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_TeamStartLocO [ BG_TEAM_ALLIANCE ] = 0 ;
m_TeamStartLocO [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
m_ArenaTeamIds [ BG_TEAM_ALLIANCE ] = 0 ;
m_ArenaTeamIds [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
m_ArenaTeamRatingChanges [ BG_TEAM_ALLIANCE ] = 0 ;
m_ArenaTeamRatingChanges [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_BgRaids [ BG_TEAM_ALLIANCE ] = NULL ;
m_BgRaids [ BG_TEAM_HORDE ] = NULL ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_PlayersCount [ BG_TEAM_ALLIANCE ] = 0 ;
m_PlayersCount [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2009-07-31 11:34:38 +08:00
m_TeamScores [ BG_TEAM_ALLIANCE ] = 0 ;
m_TeamScores [ BG_TEAM_HORDE ] = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
m_PrematureCountDown = false ;
2009-10-17 15:51:44 -07:00
2008-10-17 16:36:07 -05:00
m_HonorMode = BG_NORMAL ;
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
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 ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground ::~ Battleground ()
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
// remove objects and creatures
2008-12-19 16:05:13 -06:00
// (this is done automatically in mapmanager update, when the instance is reset after the reset time)
2011-03-14 19:21:34 +06:00
uint32 size = uint32 ( m_BgCreatures . size ());
for ( uint32 i = 0 ; i < size ; ++ i )
2008-10-05 08:48:32 -05:00
DelCreature ( i );
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
size = uint32 ( m_BgObjects . size ());
for ( uint32 i = 0 ; i < size ; ++ i )
2008-10-05 08:48:32 -05:00
DelObject ( i );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> RemoveBattleground ( GetInstanceID (), GetTypeID ());
2008-10-05 08:48:32 -05:00
// unload map
2009-12-17 10:43:12 +01:00
if ( m_Map )
m_Map -> SetUnload ();
2008-10-05 08:48:32 -05:00
// remove from bg free slot queue
2011-03-14 19:21:34 +06:00
RemoveFromBGFreeSlotQueue ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundScoreMap :: const_iterator itr = m_PlayerScores . begin (); itr != m_PlayerScores . end (); ++ itr )
2009-08-06 17:45:37 -05:00
delete itr -> second ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: Update ( uint32 diff )
2008-10-02 16:23:55 -05:00
{
2009-09-11 16:25:11 -07:00
if ( ! GetPlayersSize ())
{
2008-10-02 16:23:55 -05:00
//BG is empty
2009-09-11 16:25:11 -07:00
// if there are no players invited, delete BG
// this will delete arena or bg object, where any player entered
// [[ but if you use battleground object again (more battles possible to be played on 1 instance)
// then this condition should be removed and code:
// if (!GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
// this->AddToFreeBGObjectsQueue(); // not yet implemented
// should be used instead of current
// ]]
2010-08-08 04:37:24 +02:00
// Battleground Template instance cannot be updated, because it would be deleted
2009-09-11 16:25:11 -07:00
if ( ! GetInvitedCount ( HORDE ) && ! GetInvitedCount ( ALLIANCE ))
m_SetDeleteThis = true ;
2008-10-02 16:23:55 -05:00
return ;
2009-09-11 16:25:11 -07:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
_ProcessOfflineQueue ();
_ProcessRessurect ( diff );
if ( GetStatus () == STATUS_IN_PROGRESS && ! isArena () && sBattlegroundMgr -> GetPrematureFinishTime () && ( GetPlayersCountByTeam ( ALLIANCE ) < GetMinPlayersPerTeam () || GetPlayersCountByTeam ( HORDE ) < GetMinPlayersPerTeam ()))
_ProcessProgress ( diff );
else if ( m_PrematureCountDown )
m_PrematureCountDown = false ;
if ( GetStatus () == STATUS_WAIT_JOIN && GetPlayersSize ())
_ProcessJoin ( diff );
if ( GetStatus () == STATUS_WAIT_LEAVE )
_ProcessLeave ( diff );
// Update start time and reset stats timer
m_StartTime += diff ;
m_ResetStatTimer += diff ;
}
inline void Battleground :: _ProcessOfflineQueue ()
{
2009-03-09 16:36:58 -06:00
// remove offline players from bg after 5 minutes
2009-04-08 16:33:46 -05:00
if ( ! m_OfflineQueue . empty ())
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: iterator itr = m_Players . find ( * ( m_OfflineQueue . begin ()));
2009-04-08 16:33:46 -05:00
if ( itr != m_Players . end ())
2008-10-02 16:23:55 -05:00
{
2010-12-23 23:25:44 +01:00
if ( itr -> second . OfflineRemoveTime <= sWorld -> GetGameTime ())
2009-03-09 17:07:12 -06:00
{
2009-03-09 17:07:40 -06:00
RemovePlayerAtLeave ( itr -> first , true , true ); // remove player from BG
2009-03-09 17:07:12 -06:00
m_OfflineQueue . pop_front (); // remove from offline queue
2009-03-09 17:58:04 -06:00
//do not use itr for anything, because it is erased in RemovePlayerAtLeave()
2009-03-09 17:07:12 -06:00
}
2008-10-02 16:23:55 -05:00
}
2009-02-10 01:16:16 -06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
inline void Battleground :: _ProcessRessurect ( uint32 diff )
{
// *********************************************************
// *** BATTLEGROUND RESSURECTION SYSTEM ***
// *********************************************************
// this should be handled by spell system
2008-10-02 16:23:55 -05:00
m_LastResurrectTime += diff ;
if ( m_LastResurrectTime >= RESURRECTION_INTERVAL )
{
2009-04-08 16:33:46 -05:00
if ( GetReviveQueueSize ())
2008-10-02 16:23:55 -05:00
{
2009-10-17 16:20:24 -07:00
for ( std :: map < uint64 , std :: vector < uint64 > >:: iterator itr = m_ReviveQueue . begin (); itr != m_ReviveQueue . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
Creature * sh = NULL ;
2009-10-17 16:20:24 -07:00
for ( std :: vector < uint64 >:: const_iterator itr2 = ( itr -> second ). begin (); itr2 != ( itr -> second ). end (); ++ itr2 )
2008-10-02 16:23:55 -05:00
{
2010-12-22 21:25:23 +01:00
Player * plr = sObjectMgr -> GetPlayer ( * itr2 );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-20 20:28:19 -05:00
if ( ! sh && plr -> IsInWorld ())
2008-10-02 16:23:55 -05:00
{
2009-04-20 20:28:19 -05:00
sh = plr -> GetMap () -> GetCreature ( itr -> first );
2008-10-02 16:23:55 -05:00
// only for visual effect
if ( sh )
2009-08-09 15:33:45 -05:00
// Spirit Heal, effect 117
sh -> CastSpell ( sh , SPELL_SPIRIT_HEAL , true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-09 15:33:45 -05:00
// Resurrection visual
plr -> CastSpell ( plr , SPELL_RESURRECTION_VISUAL , true );
2008-10-02 16:23:55 -05:00
m_ResurrectQueue . push_back ( * itr2 );
}
( itr -> second ). clear ();
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_ReviveQueue . clear ();
m_LastResurrectTime = 0 ;
}
else
// queue is clear and time passed, just update last resurrection time
m_LastResurrectTime = 0 ;
}
else if ( m_LastResurrectTime > 500 ) // Resurrect players only half a second later, to see spirit heal effect on NPC
{
2009-10-17 16:20:24 -07:00
for ( std :: vector < uint64 >:: const_iterator itr = m_ResurrectQueue . begin (); itr != m_ResurrectQueue . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2010-12-22 21:25:23 +01:00
Player * plr = sObjectMgr -> GetPlayer ( * itr );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
continue ;
plr -> ResurrectPlayer ( 1.0f );
2009-10-06 22:41:37 +02:00
plr -> CastSpell ( plr , 6962 , true );
2008-10-02 16:23:55 -05:00
plr -> CastSpell ( plr , SPELL_SPIRIT_HEAL_MANA , true );
2010-12-23 23:25:44 +01:00
sObjectAccessor -> ConvertCorpseForPlayer ( * itr );
2008-10-02 16:23:55 -05:00
}
m_ResurrectQueue . clear ();
}
2011-03-14 19:21:34 +06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
inline void Battleground :: _ProcessProgress ( uint32 diff )
{
// *********************************************************
// *** BATTLEGROUND BALLANCE SYSTEM ***
// *********************************************************
2008-10-05 08:48:32 -05:00
// if less then minimum players are in on one side, then start premature finish timer
2011-03-14 19:21:34 +06:00
if ( ! m_PrematureCountDown )
{
m_PrematureCountDown = true ;
m_PrematureCountDownTimer = sBattlegroundMgr -> GetPrematureFinishTime ();
}
else if ( m_PrematureCountDownTimer < diff )
2008-10-05 08:48:32 -05:00
{
2011-03-14 19:21:34 +06:00
// time's up!
uint32 winner = 0 ;
if ( GetPlayersCountByTeam ( ALLIANCE ) >= GetMinPlayersPerTeam ())
winner = ALLIANCE ;
else if ( GetPlayersCountByTeam ( HORDE ) >= GetMinPlayersPerTeam ())
winner = HORDE ;
EndBattleground ( winner );
m_PrematureCountDown = false ;
}
else if ( ! sBattlegroundMgr -> isTesting ())
{
uint32 newtime = m_PrematureCountDownTimer - diff ;
// announce every minute
if ( newtime > ( MINUTE * IN_MILLISECONDS ))
2008-10-05 08:48:32 -05:00
{
2011-03-14 19:21:34 +06:00
if ( newtime / ( MINUTE * IN_MILLISECONDS ) != m_PrematureCountDownTimer / ( MINUTE * IN_MILLISECONDS ))
PSendMessageToAll ( LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING , CHAT_MSG_SYSTEM , NULL , ( uint32 )( m_PrematureCountDownTimer / ( MINUTE * IN_MILLISECONDS )));
2008-10-05 08:48:32 -05:00
}
2011-03-14 19:21:34 +06:00
else
2008-10-05 08:48:32 -05:00
{
2011-03-14 19:21:34 +06:00
//announce every 15 seconds
if ( newtime / ( 15 * IN_MILLISECONDS ) != m_PrematureCountDownTimer / ( 15 * IN_MILLISECONDS ))
PSendMessageToAll ( LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS , CHAT_MSG_SYSTEM , NULL , ( uint32 )( m_PrematureCountDownTimer / IN_MILLISECONDS ));
2008-10-05 08:48:32 -05:00
}
2011-03-14 19:21:34 +06:00
m_PrematureCountDownTimer = newtime ;
2008-10-05 08:48:32 -05:00
}
2011-03-14 19:21:34 +06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
inline void Battleground :: _ProcessJoin ( uint32 diff )
{
// *********************************************************
// *** BATTLEGROUND STARTING SYSTEM ***
// *********************************************************
ModifyStartDelayTime ( diff );
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
if ( m_ResetStatTimer <= 5000 )
2009-03-07 12:05:30 -06:00
{
2011-03-14 19:21:34 +06:00
m_ResetStatTimer = 0 ;
for ( BattlegroundPlayerMap :: const_iterator itr = GetPlayers (). begin (); itr != GetPlayers (). end (); ++ itr )
if ( Player * plr = sObjectMgr -> GetPlayer ( itr -> first ))
plr -> ResetAllPowers ();
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
if ( ! ( m_Events & BG_STARTING_EVENT_1 ))
{
m_Events |= BG_STARTING_EVENT_1 ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// Setup here, only when at least one player has ported to the map
if ( ! SetupBattleground ())
2009-03-07 12:05:30 -06:00
{
2011-03-14 19:21:34 +06:00
EndNow ();
return ;
2009-03-07 12:05:30 -06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
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 ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
StartingEventOpenDoors ();
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
SendWarningToAll ( m_StartMessageIds [ BG_STARTING_EVENT_FOURTH ]);
SetStatus ( STATUS_IN_PROGRESS );
SetStartDelayTime ( m_StartDelayTimes [ BG_STARTING_EVENT_FOURTH ]);
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// 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 = sObjectMgr -> GetPlayer ( itr -> first ))
{
// BG Status packet
WorldPacket status ;
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr -> BGQueueTypeId ( m_TypeID , GetArenaType ());
uint32 queueSlot = plr -> GetBattlegroundQueueIndex ( bgQueueTypeId );
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & status , this , queueSlot , STATUS_IN_PROGRESS , 0 , GetStartTime (), GetArenaType ());
plr -> GetSession () -> SendPacket ( & status );
plr -> RemoveAurasDueToSpell ( SPELL_ARENA_PREPARATION );
plr -> ResetAllPowers ();
// remove auras with duration lower than 30s
Unit :: AuraApplicationMap & auraMap = plr -> GetAppliedAuras ();
for ( Unit :: AuraApplicationMap :: iterator iter = auraMap . begin (); iter != auraMap . end ();)
2009-05-24 22:54:13 +02:00
{
2011-03-14 19:21:34 +06:00
AuraApplication * aurApp = iter -> second ;
Aura * aura = aurApp -> GetBase ();
if ( ! aura -> IsPermanent ()
&& aura -> GetDuration () <= 30 * IN_MILLISECONDS
&& aurApp -> IsPositive ()
&& ( ! ( aura -> GetSpellProto () -> Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY ))
&& ( ! aura -> HasEffectType ( SPELL_AURA_MOD_INVISIBILITY )))
plr -> RemoveAura ( iter );
else
++ iter ;
2009-05-24 22:54:13 +02:00
}
2011-03-14 19:21:34 +06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
CheckArenaWinConditions ();
}
else
{
PlaySoundToAll ( SOUND_BG_START );
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
for ( BattlegroundPlayerMap :: const_iterator itr = GetPlayers (). begin (); itr != GetPlayers (). end (); ++ itr )
if ( Player * plr = sObjectMgr -> GetPlayer ( itr -> first ))
2009-03-07 12:05:30 -06:00
{
2011-03-14 19:21:34 +06:00
plr -> RemoveAurasDueToSpell ( SPELL_PREPARATION );
plr -> ResetAllPowers ();
2009-03-07 12:05:30 -06:00
}
2011-03-14 19:21:34 +06:00
// Announce BG starting
if ( sWorld -> getBoolConfig ( CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE ))
sWorld -> SendWorldText ( LANG_BG_STARTED_ANNOUNCE_WORLD , GetName (), GetMinLevel (), GetMaxLevel ());
2009-03-07 12:05:30 -06:00
}
}
2011-03-14 19:21:34 +06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
inline void Battleground :: _ProcessLeave ( uint32 diff )
{
// *********************************************************
// *** BATTLEGROUND ENDING SYSTEM ***
// *********************************************************
// remove all players from battleground after 2 minutes
m_EndTime -= diff ;
if ( m_EndTime <= 0 )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
m_EndTime = 0 ;
BattlegroundPlayerMap :: iterator itr , next ;
for ( itr = m_Players . begin (); itr != m_Players . end (); itr = next )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
next = itr ;
++ next ;
//itr is erased here!
RemovePlayerAtLeave ( itr -> first , true , true ); // remove player from BG
// do not change any battleground's private variables
2008-10-02 16:23:55 -05:00
}
}
2011-03-14 19:21:34 +06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
inline Player * Battleground :: _GetPlayer ( const uint64 & guid , bool offlineRemove , const char * context ) const
{
Player * player = NULL ;
if ( ! offlineRemove )
{
player = sObjectMgr -> GetPlayer ( guid );
if ( ! player )
sLog -> outError ( "Battleground::%s: player (GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
context , GUID_LOPART ( guid ), m_MapId , m_InstanceID );
}
return player ;
}
inline Player * Battleground :: _GetPlayer ( BattlegroundPlayerMap :: iterator itr , const char * context )
{
return _GetPlayer ( itr -> first , itr -> second . OfflineRemoveTime , context );
}
inline Player * Battleground :: _GetPlayer ( BattlegroundPlayerMap :: const_iterator itr , const char * context ) const
{
return _GetPlayer ( itr -> first , itr -> second . OfflineRemoveTime , context );
}
inline Player * Battleground :: _GetPlayerForTeam ( uint32 teamId , BattlegroundPlayerMap :: const_iterator itr , const char * context ) const
{
Player * player = NULL ;
if ( player = _GetPlayer ( itr , context ))
{
uint32 team = itr -> second . Team ;
if ( ! team )
team = player -> GetTeam ();
if ( team != teamId )
player = NULL ;
}
return player ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SetTeamStartLoc ( uint32 TeamID , float X , float Y , float Z , float O )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundTeamId idx = GetTeamIndexByTeamId ( TeamID );
2008-10-02 16:23:55 -05:00
m_TeamStartLocX [ idx ] = X ;
m_TeamStartLocY [ idx ] = Y ;
m_TeamStartLocZ [ idx ] = Z ;
m_TeamStartLocO [ idx ] = O ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendPacketToAll ( WorldPacket * packet )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2011-03-14 19:21:34 +06:00
if ( Player * player = _GetPlayer ( itr , "SendPacketToAll" ))
player -> GetSession () -> SendPacket ( packet );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendPacketToTeam ( uint32 TeamID , WorldPacket * packet , Player * sender , bool self )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2011-03-14 19:21:34 +06:00
if ( Player * player = _GetPlayerForTeam ( TeamID , itr , "SendPacketToTeam" ))
if ( self || sender != player )
player -> GetSession () -> SendPacket ( packet );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: PlaySoundToAll ( uint32 SoundID )
2008-10-02 16:23:55 -05:00
{
WorldPacket data ;
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPlaySoundPacket ( & data , SoundID );
2008-10-02 16:23:55 -05:00
SendPacketToAll ( & data );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: PlaySoundToTeam ( uint32 SoundID , uint32 TeamID )
2008-10-02 16:23:55 -05:00
{
WorldPacket data ;
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2011-03-14 19:21:34 +06:00
if ( Player * player = _GetPlayerForTeam ( TeamID , itr , "PlaySoundToTeam" ))
2008-10-02 16:23:55 -05:00
{
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPlaySoundPacket ( & data , SoundID );
2011-03-14 19:21:34 +06:00
player -> GetSession () -> SendPacket ( & data );
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: CastSpellOnTeam ( uint32 SpellID , uint32 TeamID )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2011-03-14 19:21:34 +06:00
if ( Player * player = _GetPlayerForTeam ( TeamID , itr , "CastSpellOnTeam" ))
player -> CastSpell ( player , SpellID , true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-01-09 00:00:08 -03:00
void Battleground :: RemoveAuraOnTeam ( uint32 SpellID , uint32 TeamID )
{
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2011-03-14 19:21:34 +06:00
if ( Player * player = _GetPlayerForTeam ( TeamID , itr , "RemoveAuraOnTeam" ))
player -> RemoveAura ( SpellID );
2011-01-09 00:00:08 -03:00
}
2010-08-08 04:37:24 +02:00
void Battleground :: YellToAll ( Creature * creature , const char * text , uint32 language )
2008-11-21 19:45:49 -06:00
{
2011-03-14 19:21:34 +06:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
if ( Player * player = _GetPlayer ( itr , "YellToAll" ))
2008-11-21 19:45:49 -06:00
{
2011-03-14 19:21:34 +06:00
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
creature -> BuildMonsterChat ( & data , CHAT_MSG_MONSTER_YELL , text , language , creature -> GetName (), itr -> first );
player -> GetSession () -> SendPacket ( & data );
2008-11-21 19:45:49 -06:00
}
}
2010-08-08 04:37:24 +02:00
void Battleground :: RewardHonorToTeam ( uint32 Honor , uint32 TeamID )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2011-03-14 19:21:34 +06:00
if ( Player * player = _GetPlayerForTeam ( TeamID , itr , "RewardHonorToTeam" ))
UpdatePlayerScore ( player , SCORE_BONUS_HONOR , Honor );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: RewardReputationToTeam ( uint32 faction_id , uint32 Reputation , uint32 TeamID )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
if ( FactionEntry const * factionEntry = sFactionStore . LookupEntry ( faction_id ))
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
if ( Player * player = _GetPlayerForTeam ( TeamID , itr , "RewardReputationToTeam" ))
player -> GetReputationMgr (). ModifyReputation ( factionEntry , Reputation );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: UpdateWorldState ( uint32 Field , uint32 Value )
2008-10-02 16:23:55 -05:00
{
WorldPacket data ;
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildUpdateWorldStatePacket ( & data , Field , Value );
2008-10-02 16:23:55 -05:00
SendPacketToAll ( & data );
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: UpdateWorldStateForPlayer ( uint32 Field , uint32 Value , Player * Source )
2008-10-02 16:23:55 -05:00
{
WorldPacket data ;
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildUpdateWorldStatePacket ( & data , Field , Value );
2008-10-02 16:23:55 -05:00
Source -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: EndBattleground ( uint32 winner )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
RemoveFromBGFreeSlotQueue ();
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
ArenaTeam * winner_arena_team = NULL ;
ArenaTeam * loser_arena_team = NULL ;
2010-08-27 18:18:26 +02:00
uint32 loser_team_rating = 0 ;
uint32 loser_matchmaker_rating = 0 ;
2010-09-10 23:08:49 +02:00
int32 loser_change = 0 ;
2010-08-27 18:18:26 +02:00
uint32 winner_team_rating = 0 ;
uint32 winner_matchmaker_rating = 0 ;
2010-09-10 23:08:49 +02:00
int32 winner_change = 0 ;
2008-10-02 16:23:55 -05:00
WorldPacket data ;
2009-03-09 17:00:31 -06:00
int32 winmsg_id = 0 ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( winner == ALLIANCE )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
winmsg_id = isBattleground () ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
PlaySoundToAll ( SOUND_ALLIANCE_WINS ); // alliance wins sound
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SetWinner ( WINNER_ALLIANCE );
}
2009-04-08 16:33:46 -05:00
else if ( winner == HORDE )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
winmsg_id = isBattleground () ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
PlaySoundToAll ( SOUND_HORDE_WINS ); // horde wins sound
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SetWinner ( WINNER_HORDE );
}
2008-10-05 08:48:32 -05:00
else
{
SetWinner ( 3 );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SetStatus ( STATUS_WAIT_LEAVE );
2009-03-13 18:06:36 -06:00
//we must set it this way, because end time is sent in packet!
m_EndTime = TIME_TO_AUTOREMOVE ;
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// arena rating calculation
2009-04-08 16:33:46 -05:00
if ( isArena () && isRated ())
2008-10-05 08:48:32 -05:00
{
2010-12-22 21:25:23 +01:00
winner_arena_team = sObjectMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( winner ));
loser_arena_team = sObjectMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( winner )));
2010-12-03 23:14:38 +01:00
if ( winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2008-10-05 08:48:32 -05:00
{
2010-12-03 23:14:38 +01:00
if ( winner != WINNER_NONE )
{
loser_team_rating = loser_arena_team -> GetRating ();
loser_matchmaker_rating = GetArenaMatchmakerRating ( GetOtherTeam ( winner ));
winner_team_rating = winner_arena_team -> GetRating ();
winner_matchmaker_rating = GetArenaMatchmakerRating ( winner );
winner_change = winner_arena_team -> WonAgainst ( loser_matchmaker_rating );
loser_change = loser_arena_team -> LostAgainst ( winner_matchmaker_rating );
2011-02-20 20:16:34 +01:00
sLog -> outArena ( "--- Winner rating: %u, Loser rating: %u, Winner MMR: %u, Loser MMR: %u, Winner change: %u, Loser change: %u ---" , winner_team_rating , loser_team_rating ,
2010-12-03 23:14:38 +01:00
winner_matchmaker_rating , loser_matchmaker_rating , winner_change , loser_change );
SetArenaTeamRatingChangeForTeam ( winner , winner_change );
SetArenaTeamRatingChangeForTeam ( GetOtherTeam ( winner ), loser_change );
2010-12-23 23:25:44 +01:00
sLog -> outArena ( "Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. Winner rating: +%d, Loser rating: %d" , m_ArenaType , m_ArenaTeamIds [ BG_TEAM_ALLIANCE ], m_ArenaTeamIds [ BG_TEAM_HORDE ], winner_arena_team -> GetId (), winner_change , loser_change );
if ( sWorld -> getBoolConfig ( CONFIG_ARENA_LOG_EXTENDED_INFO ))
2010-12-03 23:14:38 +01:00
for ( Battleground :: BattlegroundScoreMap :: const_iterator itr = GetPlayerScoresBegin (); itr != GetPlayerScoresEnd (); itr ++ )
2010-12-22 21:25:23 +01:00
if ( Player * player = sObjectMgr -> GetPlayer ( itr -> first ))
2010-12-23 23:25:44 +01:00
sLog -> outArena ( "Statistics for %s (GUID: " UI64FMTD ", Team: %d, IP: %s): %u damage, %u healing, %u killing blows" , player -> GetName (), itr -> first , player -> GetArenaTeamId ( m_ArenaType == 5 ? 2 : m_ArenaType == 3 ), player -> GetSession () -> GetRemoteAddress (). c_str (), itr -> second -> DamageDone , itr -> second -> HealingDone , itr -> second -> KillingBlows );
2010-12-03 23:14:38 +01:00
}
// Deduct 16 points from each teams arena-rating if there are no winners after 45+2 minutes
else
{
SetArenaTeamRatingChangeForTeam ( ALLIANCE , ARENA_TIMELIMIT_POINTS_LOSS );
SetArenaTeamRatingChangeForTeam ( HORDE , ARENA_TIMELIMIT_POINTS_LOSS );
winner_arena_team -> FinishGame ( ARENA_TIMELIMIT_POINTS_LOSS );
loser_arena_team -> FinishGame ( ARENA_TIMELIMIT_POINTS_LOSS );
}
2010-12-02 22:25:32 +01:00
}
2008-10-05 08:48:32 -05:00
else
{
SetArenaTeamRatingChangeForTeam ( ALLIANCE , 0 );
SetArenaTeamRatingChangeForTeam ( HORDE , 0 );
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
uint32 team = itr -> second . Team ;
2009-10-17 15:51:44 -07:00
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
//if rated arena match - make member lost!
2009-06-16 12:25:18 -05:00
if ( isArena () && isRated () && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2009-03-09 17:07:40 -06:00
{
2009-04-08 16:33:46 -05:00
if ( team == winner )
2010-09-10 23:08:49 +02:00
winner_arena_team -> OfflineMemberLost ( itr -> first , loser_matchmaker_rating , winner_change );
2009-03-09 17:07:40 -06:00
else
2010-09-10 23:08:49 +02:00
loser_arena_team -> OfflineMemberLost ( itr -> first , winner_matchmaker_rating , loser_change );
2009-03-09 17:07:40 -06:00
}
2008-10-02 16:23:55 -05:00
continue ;
}
2011-03-14 19:21:34 +06:00
Player * plr = _GetPlayer ( itr , "EndBattleground" );
2010-02-15 15:31:27 +01:00
if ( ! plr )
2010-02-25 00:26:47 +01:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// should remove spirit of redemption
2010-04-07 19:14:10 +02:00
if ( plr -> HasAuraType ( SPELL_AURA_SPIRIT_OF_REDEMPTION ))
2009-04-06 13:31:14 +02:00
plr -> RemoveAurasByType ( SPELL_AURA_MOD_SHAPESHIFT );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr -> isAlive ())
2008-10-02 16:23:55 -05:00
{
plr -> ResurrectPlayer ( 1.0f );
plr -> SpawnCorpseBones ();
2010-02-25 00:26:47 +01:00
}
else
2009-08-14 22:09:06 +02:00
{
//needed cause else in av some creatures will kill the players at the end
plr -> CombatStop ();
2010-03-09 11:11:10 +01:00
plr -> getHostileRefManager (). deleteReferences ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:07:40 -06:00
//this line is obsolete - team is set ALWAYS
2010-04-07 19:14:10 +02:00
//if (!team) team = plr->GetTeam();
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// per player calculation
2009-06-16 12:25:18 -05:00
if ( isArena () && isRated () && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2008-10-05 08:48:32 -05:00
{
2009-04-08 16:33:46 -05:00
if ( team == winner )
2009-06-01 21:51:34 -05:00
{
// update achievement BEFORE personal rating update
2009-06-14 10:02:20 -05:00
ArenaTeamMember * member = winner_arena_team -> GetMember ( plr -> GetGUID ());
if ( member )
plr -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA , member -> personal_rating );
2009-10-17 15:51:44 -07:00
2010-09-10 23:08:49 +02:00
winner_arena_team -> MemberWon ( plr , loser_matchmaker_rating , winner_change );
2009-06-01 21:51:34 -05:00
}
2008-10-05 08:48:32 -05:00
else
2009-06-01 21:51:34 -05:00
{
2010-09-10 23:08:49 +02:00
loser_arena_team -> MemberLost ( plr , winner_matchmaker_rating , loser_change );
2009-10-17 15:51:44 -07:00
2010-11-14 23:46:34 +02:00
// Arena lost => reset the win_rated_arena having the "no_lose" condition
2010-09-28 08:21:51 +03:00
plr -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA , ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE );
2009-06-01 21:51:34 -05:00
}
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-11-14 23:46:34 +02:00
uint32 winner_kills = plr -> GetRandomWinner () ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST ;
uint32 loser_kills = plr -> GetRandomWinner () ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST ;
uint32 winner_arena = plr -> GetRandomWinner () ? BG_REWARD_WINNER_ARENA_LAST : BG_REWARD_WINNER_ARENA_FIRST ;
2010-05-26 11:34:37 +02:00
2010-05-04 17:30:50 +02:00
// Reward winner team
2009-04-08 16:33:46 -05:00
if ( team == winner )
2010-05-26 11:34:37 +02:00
{
2010-08-08 04:37:24 +02:00
if ( IsRandom () || BattlegroundMgr :: IsBGWeekend ( GetTypeID ()))
2010-05-26 11:34:37 +02:00
{
2010-11-14 23:46:34 +02:00
UpdatePlayerScore ( plr , SCORE_BONUS_HONOR , GetBonusHonorFromKill ( winner_kills ));
2010-08-07 01:58:23 +06:00
if ( CanAwardArenaPoints ())
2010-11-14 23:46:34 +02:00
plr -> ModifyArenaPoints ( winner_arena );
2010-05-26 11:34:37 +02:00
if ( ! plr -> GetRandomWinner ())
plr -> SetRandomWinner ( true );
}
2009-07-22 23:51:39 +02:00
plr -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_BG , 1 );
2010-05-26 11:34:37 +02:00
}
else
{
2010-08-08 04:37:24 +02:00
if ( IsRandom () || BattlegroundMgr :: IsBGWeekend ( GetTypeID ()))
2010-11-14 23:46:34 +02:00
UpdatePlayerScore ( plr , SCORE_BONUS_HONOR , GetBonusHonorFromKill ( loser_kills ));
2010-08-08 19:45:53 +02:00
}
2010-05-26 11:34:37 +02:00
2010-12-02 22:50:30 +01:00
plr -> ResetAllPowers ();
2008-10-02 16:23:55 -05:00
plr -> CombatStopWithPets ( true );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
BlockMovement ( plr );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPvpLogDataPacket ( & data , this );
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( & data );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr :: BGQueueTypeId ( GetTypeID (), GetArenaType ());
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & data , this , plr -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_IN_PROGRESS , TIME_TO_AUTOREMOVE , GetStartTime (), GetArenaType ());
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( & data );
2008-12-24 09:58:26 -06:00
plr -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND , 1 );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-16 12:25:18 -05:00
if ( isArena () && isRated () && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2008-10-05 08:48:32 -05:00
{
// update arena points only after increasing the player's match count!
2008-12-19 16:05:13 -06:00
//obsolete: winner_arena_team->UpdateArenaPointsHelper();
//obsolete: loser_arena_team->UpdateArenaPointsHelper();
2008-10-05 08:48:32 -05:00
// save the stat changes
winner_arena_team -> SaveToDB ();
loser_arena_team -> SaveToDB ();
// send updated arena team stats to players
// 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 ();
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( winmsg_id )
2009-03-09 18:14:06 -06:00
SendMessageToAll ( winmsg_id , CHAT_MSG_BG_SYSTEM_NEUTRAL );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetBonusHonorFromKill ( uint32 kills ) const
2009-03-09 18:14:06 -06:00
{
//variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
2010-12-11 20:37:38 +06:00
uint32 maxLevel = std :: min ( GetMaxLevel (), 80U );
return Trinity :: Honor :: hk_honor_at_level ( maxLevel , float ( kills ));
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetBattlemasterEntry () const
2008-10-02 16:23:55 -05:00
{
2010-05-26 11:34:37 +02:00
switch ( GetTypeID ( true ))
2008-10-02 16:23:55 -05:00
{
case BATTLEGROUND_AV : return 15972 ;
case BATTLEGROUND_WS : return 14623 ;
case BATTLEGROUND_AB : return 14879 ;
case BATTLEGROUND_EY : return 22516 ;
case BATTLEGROUND_NA : return 20200 ;
default : return 0 ;
}
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: BlockMovement ( Player * plr )
2008-10-02 16:23:55 -05:00
{
plr -> SetClientControl ( plr , 0 ); // movement disabled NOTE: the effect will be automatically removed by client when the player is teleported from the battleground, so no need to send with uint8(1) in RemovePlayerAtLeave()
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: RemovePlayerAtLeave ( const uint64 & guid , bool Transport , bool SendPacket )
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
uint32 team = GetPlayerTeam ( guid );
bool participant = false ;
2008-10-02 16:23:55 -05:00
// Remove from lists/maps
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: iterator itr = m_Players . find ( guid );
2009-04-08 16:33:46 -05:00
if ( itr != m_Players . end ())
2008-10-02 16:23:55 -05:00
{
2009-03-09 18:14:06 -06:00
UpdatePlayersCountByTeam ( team , true ); // -1 player
2008-10-02 16:23:55 -05:00
m_Players . erase ( itr );
2008-10-05 08:48:32 -05:00
// check if the player was a participant of the match, or only entered through gm command (goname)
participant = true ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundScoreMap :: iterator itr2 = m_PlayerScores . find ( guid );
2009-04-08 16:33:46 -05:00
if ( itr2 != m_PlayerScores . end ())
2008-10-02 16:23:55 -05:00
{
delete itr2 -> second ; // delete player's score
m_PlayerScores . erase ( itr2 );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
RemovePlayerFromResurrectQueue ( guid );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
Player * plr = sObjectMgr -> GetPlayer ( guid );
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// should remove spirit of redemption
2010-04-07 19:14:10 +02:00
if ( plr && plr -> HasAuraType ( SPELL_AURA_SPIRIT_OF_REDEMPTION ))
2009-04-06 13:31:14 +02:00
plr -> RemoveAurasByType ( SPELL_AURA_MOD_SHAPESHIFT );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( plr && ! plr -> isAlive ()) // resurrect on exit
2008-10-02 16:23:55 -05:00
{
plr -> ResurrectPlayer ( 1.0f );
plr -> SpawnCorpseBones ();
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
RemovePlayer ( plr , guid ); // BG subclass specific code
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( participant ) // if the player was a match participant, remove auras, calc rating, update queue
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundTypeId bgTypeId = GetTypeID ();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr :: BGQueueTypeId ( GetTypeID (), GetArenaType ());
2009-04-08 16:33:46 -05:00
if ( plr )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
plr -> ClearAfkReports ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// if arena, remove the specific arena auras
2009-04-08 16:33:46 -05:00
if ( isArena ())
2008-10-05 08:48:32 -05:00
{
2009-03-09 18:14:06 -06:00
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)
2009-10-17 15:51:44 -07:00
2009-04-11 14:47:38 -05:00
// 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 ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( isRated () && GetStatus () == STATUS_IN_PROGRESS )
2008-10-05 08:48:32 -05:00
{
//left a rated match while the encounter was in progress, consider as loser
2010-12-22 21:25:23 +01:00
ArenaTeam * winner_arena_team = sObjectMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( team )));
ArenaTeam * loser_arena_team = sObjectMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( team ));
2009-06-16 12:25:18 -05:00
if ( winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2010-09-12 18:41:47 +02:00
loser_arena_team -> MemberLost ( plr , GetArenaMatchmakerRating ( GetOtherTeam ( team )));
2008-10-05 08:48:32 -05:00
}
}
2009-04-08 16:33:46 -05:00
if ( SendPacket )
2008-10-05 08:48:32 -05:00
{
2009-03-09 17:07:40 -06:00
WorldPacket data ;
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & data , this , plr -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_NONE , 0 , 0 , 0 );
2008-10-05 08:48:32 -05:00
plr -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
2010-08-08 04:37:24 +02:00
plr -> RemoveBattlegroundQueueId ( bgQueueTypeId );
2009-03-09 17:07:40 -06:00
}
else
// removing offline participant
{
2009-04-08 16:33:46 -05:00
if ( isRated () && GetStatus () == STATUS_IN_PROGRESS )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
//left a rated match while the encounter was in progress, consider as loser
2010-12-22 21:25:23 +01:00
ArenaTeam * others_arena_team = sObjectMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( team )));
ArenaTeam * players_arena_team = sObjectMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( team ));
2009-04-08 16:33:46 -05:00
if ( others_arena_team && players_arena_team )
2010-09-12 18:41:47 +02:00
players_arena_team -> OfflineMemberLost ( guid , GetArenaMatchmakerRating ( GetOtherTeam ( team )));
2008-10-02 16:23:55 -05:00
}
2009-03-09 17:07:40 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:07:40 -06:00
// remove from raid group if player is member
2009-04-08 16:33:46 -05:00
if ( Group * group = GetBgRaid ( team ))
2009-03-09 17:07:40 -06:00
{
2010-09-10 13:37:55 +02:00
if ( ! group -> RemoveMember ( guid )) // group was disbanded
2009-03-09 17:07:40 -06:00
{
SetBgRaid ( team , NULL );
}
2008-10-02 16:23:55 -05:00
}
2009-03-09 17:07:40 -06:00
DecreaseInvitedCount ( team );
//we should update battleground queue, but only if bg isn't ending
2010-08-08 04:37:24 +02:00
if ( isBattleground () && GetStatus () < STATUS_WAIT_LEAVE )
2009-09-11 16:25:11 -07:00
{
// a player has left the battleground, so there are free slots -> add to queue
AddToBGFreeSlotQueue ();
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> ScheduleQueueUpdate ( 0 , 0 , bgQueueTypeId , bgTypeId , GetBracketId ());
2009-09-11 16:25:11 -07:00
}
2009-03-09 17:07:40 -06:00
// Let others know
WorldPacket data ;
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPlayerLeftBattlegroundPacket ( & data , guid );
2009-03-09 17:07:40 -06:00
SendPacketToTeam ( team , & data , plr , false );
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( plr )
2009-03-09 17:07:40 -06:00
{
2008-10-02 16:23:55 -05:00
// Do next only if found in battleground
2010-08-08 04:37:24 +02:00
plr -> SetBattlegroundId ( 0 , BATTLEGROUND_TYPE_NONE ); // We're not in BG.
2008-10-05 08:48:32 -05:00
// reset destination bg team
plr -> SetBGTeam ( 0 );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( Transport )
2009-08-12 20:27:00 -05:00
plr -> TeleportToBGEntryPoint ();
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
sLog -> outDetail ( "BATTLEGROUND: Removed player %s from Battleground." , plr -> GetName ());
2010-08-07 18:31:06 +02:00
plr -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE , ACHIEVEMENT_CRITERIA_CONDITION_MAP , GetMapId (), true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
//battleground object will be deleted next Battleground::Update() call
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// this method is called when no players remains in battleground
2010-08-08 04:37:24 +02:00
void Battleground :: Reset ()
2008-10-02 16:23:55 -05:00
{
SetWinner ( WINNER_NONE );
SetStatus ( STATUS_WAIT_QUEUE );
SetStartTime ( 0 );
SetEndTime ( 0 );
SetLastResurrectTime ( 0 );
2008-10-05 08:48:32 -05:00
SetArenaType ( 0 );
SetRated ( false );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_Events = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
if ( m_InvitedAlliance > 0 || m_InvitedHorde > 0 )
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::Reset: one of the counters is not 0 (alliance: %u, horde: %u) for BG (map: %u, instance id: %u)!" ,
m_InvitedAlliance , m_InvitedHorde , m_MapId , m_InstanceID );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_InvitedAlliance = 0 ;
m_InvitedHorde = 0 ;
2008-10-05 08:48:32 -05:00
m_InBGFreeSlotQueue = false ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_Players . clear ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundScoreMap :: const_iterator itr = m_PlayerScores . begin (); itr != m_PlayerScores . end (); ++ itr )
2009-08-06 17:45:37 -05:00
delete itr -> second ;
2008-10-02 16:23:55 -05:00
m_PlayerScores . clear ();
2009-10-17 15:51:44 -07:00
2009-08-04 23:16:44 +02:00
ResetBGSubclass ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: StartBattleground ()
2008-10-02 16:23:55 -05:00
{
SetStartTime ( 0 );
SetLastResurrectTime ( 0 );
2009-09-11 16:25:11 -07:00
// add BG to free slot queue
AddToBGFreeSlotQueue ();
2009-10-17 15:51:44 -07:00
2009-09-11 16:25:11 -07:00
// add bg to update list
// This must be done here, because we need to have already invited some players when first BG::Update() method is executed
2010-08-08 04:37:24 +02:00
// and it doesn't matter if we call StartBattleground() more times, because m_Battlegrounds is a map and instance id never changes
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> AddBattleground ( GetInstanceID (), GetTypeID (), this );
2010-04-07 19:14:10 +02:00
if ( m_IsRated )
2010-12-23 23:25:44 +01:00
sLog -> outArena ( "Arena match type: %u for Team1Id: %u - Team2Id: %u started." , m_ArenaType , m_ArenaTeamIds [ BG_TEAM_ALLIANCE ], m_ArenaTeamIds [ BG_TEAM_HORDE ]);
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: AddPlayer ( Player * plr )
2008-10-02 16:23:55 -05:00
{
2009-08-27 20:28:28 -05:00
// remove afk from player
if ( plr -> HasFlag ( PLAYER_FLAGS , PLAYER_FLAGS_AFK ))
plr -> ToggleAFK ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// score struct must be created in inherited class
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint64 guid = plr -> GetGUID ();
uint32 team = plr -> GetBGTeam ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundPlayer bp ;
2009-03-09 17:07:12 -06:00
bp . OfflineRemoveTime = 0 ;
2008-10-02 16:23:55 -05:00
bp . Team = team ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// Add to list/maps
m_Players [ guid ] = bp ;
2009-10-17 15:51:44 -07:00
2008-12-19 16:05:13 -06:00
UpdatePlayersCountByTeam ( team , false ); // +1 player
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
WorldPacket data ;
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPlayerJoinedBattlegroundPacket ( & data , plr );
2008-10-02 16:23:55 -05:00
SendPacketToTeam ( team , & data , plr , false );
2009-10-17 15:51:44 -07:00
2010-01-14 11:22:52 +01:00
// BG Status packet
WorldPacket status ;
2010-12-22 21:25:23 +01:00
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr -> BGQueueTypeId ( m_TypeID , GetArenaType ());
2010-08-08 04:37:24 +02:00
uint32 queueSlot = plr -> GetBattlegroundQueueIndex ( bgQueueTypeId );
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & status , this , queueSlot , STATUS_IN_PROGRESS , 0 , GetStartTime (), GetArenaType (), isArena () ? 0 : 1 );
2010-01-14 11:22:52 +01:00
plr -> GetSession () -> SendPacket ( & status );
2010-06-03 16:24:10 +02:00
plr -> RemoveAurasByType ( SPELL_AURA_MOUNTED );
2008-10-05 08:48:32 -05:00
// add arena specific auras
2009-04-08 16:33:46 -05:00
if ( isArena ())
2008-10-02 16:23:55 -05:00
{
2009-05-24 22:54:13 +02:00
plr -> RemoveArenaEnchantments ( TEMP_ENCHANTMENT_SLOT );
2010-04-07 19:14:10 +02:00
if ( team == ALLIANCE ) // gold
2008-11-30 12:47:26 -06:00
{
2009-04-08 16:33:46 -05:00
if ( plr -> GetTeam () == HORDE )
2008-11-30 12:47:26 -06:00
plr -> CastSpell ( plr , SPELL_HORDE_GOLD_FLAG , true );
else
plr -> CastSpell ( plr , SPELL_ALLIANCE_GOLD_FLAG , true );
}
else // green
{
2009-04-08 16:33:46 -05:00
if ( plr -> GetTeam () == HORDE )
2008-11-30 12:47:26 -06:00
plr -> CastSpell ( plr , SPELL_HORDE_GREEN_FLAG , true );
else
plr -> CastSpell ( plr , SPELL_ALLIANCE_GREEN_FLAG , true );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
plr -> DestroyConjuredItems ( true );
2009-04-11 14:47:38 -05:00
plr -> UnsummonPetTemporaryIfAny ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetStatus () == STATUS_WAIT_JOIN ) // not started yet
2008-10-02 16:23:55 -05:00
{
2009-03-12 13:59:03 +01:00
plr -> CastSpell ( plr , SPELL_ARENA_PREPARATION , true );
2010-12-02 22:50:30 +01:00
plr -> ResetAllPowers ();
2008-10-02 16:23:55 -05:00
}
2010-08-27 04:49:04 +03:00
WorldPacket teammate ;
teammate . Initialize ( SMSG_ARENA_OPPONENT_UPDATE , 8 );
teammate << uint64 ( plr -> GetGUID ());
SendPacketToTeam ( team , & teammate , plr , false );
2008-10-02 16:23:55 -05:00
}
else
{
2010-04-07 19:14:10 +02:00
if ( GetStatus () == STATUS_WAIT_JOIN ) // not started yet
2008-10-02 16:23:55 -05:00
plr -> CastSpell ( plr , SPELL_PREPARATION , true ); // reduces all mana cost of spells.
}
2009-10-17 15:51:44 -07:00
2009-04-23 22:07:37 -05:00
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 ());
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
// setup BG group membership
2009-03-09 17:07:12 -06:00
PlayerAddedToBGCheckIfBGIsRunning ( plr );
2011-02-09 16:47:12 +01:00
AddOrSetPlayerToCorrectBgGroup ( plr , team );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// Log
2010-12-23 23:25:44 +01:00
sLog -> outDetail ( "BATTLEGROUND: Player %s joined the battle." , plr -> GetName ());
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// 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 * player , uint32 team )
2009-02-13 20:10:14 -06:00
{
2011-02-09 16:47:12 +01:00
uint64 playerGuid = player -> GetGUID ();
2009-02-13 20:10:14 -06:00
Group * group = GetBgRaid ( team );
2010-04-07 19:14:10 +02:00
if ( ! group ) // first player joined
2009-02-13 20:10:14 -06:00
{
group = new Group ;
SetBgRaid ( team , group );
2011-02-18 18:35:52 +01:00
group -> Create ( player );
2009-02-13 20:10:14 -06:00
}
else // raid already exist
{
2011-02-09 16:47:12 +01:00
if ( group -> IsMember ( playerGuid ))
2009-02-13 20:10:14 -06:00
{
2011-02-09 16:47:12 +01:00
uint8 subgroup = group -> GetMemberGroup ( playerGuid );
player -> SetBattlegroundRaid ( group , subgroup );
2009-02-13 20:10:14 -06:00
}
else
2009-03-14 20:06:00 -06:00
{
2011-02-18 18:35:52 +01:00
group -> AddMember ( player );
2011-02-09 16:47:12 +01:00
if ( Group * originalGroup = player -> GetOriginalGroup ())
if ( originalGroup -> IsLeader ( playerGuid ))
2011-02-18 18:35:52 +01:00
{
2011-02-09 16:47:12 +01:00
group -> ChangeLeader ( playerGuid );
2011-02-18 18:35:52 +01:00
group -> SendUpdate ();
}
2009-03-14 20:06:00 -06:00
}
2009-02-13 20:10:14 -06:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:07:12 -06:00
// This method should be called when player logs into running battleground
2011-02-09 16:47:12 +01:00
void Battleground :: EventPlayerLoggedIn ( Player * player )
2009-03-09 17:07:12 -06:00
{
// player is correct pointer
2009-10-17 16:20:24 -07:00
for ( std :: deque < uint64 >:: iterator itr = m_OfflineQueue . begin (); itr != m_OfflineQueue . end (); ++ itr )
2009-03-09 17:07:12 -06:00
{
2011-02-09 16:47:12 +01:00
if ( * itr == player -> GetGUID ())
2009-03-09 17:07:12 -06:00
{
m_OfflineQueue . erase ( itr );
break ;
}
}
2011-02-09 16:47:12 +01:00
m_Players [ player -> GetGUID ()]. OfflineRemoveTime = 0 ;
2009-03-09 17:07:12 -06:00
PlayerAddedToBGCheckIfBGIsRunning ( player );
2009-03-09 17:07:40 -06:00
// 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
2009-03-09 17:07:12 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 16:36:58 -06:00
// This method should be called when player logs out from running battleground
2010-08-08 04:37:24 +02:00
void Battleground :: EventPlayerLoggedOut ( Player * player )
2009-03-09 16:36:58 -06:00
{
2009-03-09 17:07:12 -06:00
// player is correct pointer, it is checked in WorldSession::LogoutPlayer()
m_OfflineQueue . push_back ( player -> GetGUID ());
2010-12-23 23:25:44 +01:00
m_Players [ player -> GetGUID ()]. OfflineRemoveTime = sWorld -> GetGameTime () + MAX_OFFLINE_TIME ;
2009-04-08 16:33:46 -05:00
if ( GetStatus () == STATUS_IN_PROGRESS )
2009-03-09 16:36:58 -06:00
{
2010-02-15 15:31:27 +01:00
// drop flag and handle other cleanups
RemovePlayer ( player , player -> GetGUID ());
// 1 player is logging out, if it is the last, then end arena!
if ( isArena ())
2009-04-08 16:33:46 -05:00
if ( GetAlivePlayersCountByTeam ( player -> GetTeam ()) <= 1 && GetPlayersCountByTeam ( GetOtherTeam ( player -> GetTeam ())))
2010-08-08 04:37:24 +02:00
EndBattleground ( GetOtherTeam ( player -> GetTeam ()));
2009-03-09 16:36:58 -06:00
}
2010-02-15 15:31:27 +01:00
2009-12-17 10:43:12 +01:00
player -> LeaveBattleground ();
2009-03-09 16:36:58 -06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// This method should be called only once ... it adds pointer to queue
2010-08-08 04:37:24 +02:00
void Battleground :: AddToBGFreeSlotQueue ()
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
// make sure to add only once
2010-08-08 04:37:24 +02:00
if ( ! m_InBGFreeSlotQueue && isBattleground ())
2008-10-05 08:48:32 -05:00
{
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BGFreeSlotQueue [ m_TypeID ]. push_front ( this );
2008-10-05 08:48:32 -05:00
m_InBGFreeSlotQueue = true ;
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// This method removes this battleground from free queue - it must be called when deleting battleground - not used now
2010-08-08 04:37:24 +02:00
void Battleground :: RemoveFromBGFreeSlotQueue ()
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
// set to be able to re-add if needed
m_InBGFreeSlotQueue = false ;
// uncomment this code when battlegrounds will work like instances
2010-12-22 21:25:23 +01:00
for ( BGFreeSlotQueueType :: iterator itr = sBattlegroundMgr -> BGFreeSlotQueue [ m_TypeID ]. begin (); itr != sBattlegroundMgr -> BGFreeSlotQueue [ m_TypeID ]. end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
if (( * itr ) -> GetInstanceID () == m_InstanceID )
{
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BGFreeSlotQueue [ m_TypeID ]. erase ( itr );
2008-10-02 16:23:55 -05:00
return ;
}
2008-10-05 08:48:32 -05:00
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// get the number of free slots for team
2009-02-27 12:13:59 -06:00
// returns the number how many players can join battleground to MaxPlayersPerTeam
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetFreeSlotsForTeam ( uint32 Team ) const
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
// if BG is starting ... invite anyone
2009-06-03 00:43:04 -05:00
if ( GetStatus () == STATUS_WAIT_JOIN )
2008-10-05 08:48:32 -05:00
return ( GetInvitedCount ( Team ) < GetMaxPlayersPerTeam ()) ? GetMaxPlayersPerTeam () - GetInvitedCount ( Team ) : 0 ;
2011-03-14 19:21:34 +06:00
// if BG is already started .. do not allow to join too much players of one faction
2009-06-03 00:43:04 -05:00
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
2010-04-07 19:14:10 +02:00
else if ( otherTeam > GetInvitedCount ( Team ))
2009-06-03 00:43:04 -05:00
diff = otherTeam - GetInvitedCount ( Team );
2009-10-17 15:51:44 -07:00
2009-06-03 00:43:04 -05:00
// 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 ;
2009-10-17 15:51:44 -07:00
2009-06-03 00:43:04 -05:00
// return the minimum of the 3 differences
2009-10-17 15:51:44 -07:00
2009-06-03 00:43:04 -05:00
// min of diff and diff 2
2011-03-14 19:21:34 +06:00
diff = std :: min ( diff , diff2 );
2009-06-03 00:43:04 -05:00
// min of diff, diff2 and diff3
2011-03-14 19:21:34 +06:00
return std :: min ( diff , diff3 );
2009-06-03 00:43:04 -05:00
}
2008-10-05 08:48:32 -05:00
return 0 ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: HasFreeSlots () const
2008-10-02 16:23:55 -05:00
{
return GetPlayersSize () < GetMaxPlayers ();
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: UpdatePlayerScore ( Player * Source , uint32 type , uint32 value , bool doAddHonor )
2008-10-02 16:23:55 -05:00
{
//this procedure is called from virtual function implemented in bg subclass
2010-08-08 04:37:24 +02:00
BattlegroundScoreMap :: const_iterator itr = m_PlayerScores . find ( Source -> GetGUID ());
2010-04-07 19:14:10 +02:00
if ( itr == m_PlayerScores . end ()) // player not found...
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
switch ( type )
2008-10-02 16:23:55 -05:00
{
case SCORE_KILLING_BLOWS : // Killing blows
itr -> second -> KillingBlows += value ;
break ;
case SCORE_DEATHS : // Deaths
itr -> second -> Deaths += value ;
2010-08-07 18:31:06 +02:00
Source -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE , ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH );
2008-10-02 16:23:55 -05:00
break ;
case SCORE_HONORABLE_KILLS : // Honorable kills
itr -> second -> HonorableKills += value ;
break ;
case SCORE_BONUS_HONOR : // Honor bonus
2008-10-05 08:48:32 -05:00
// do not add honor in arenas
2010-08-08 04:37:24 +02:00
if ( isBattleground ())
2008-10-05 08:48:32 -05:00
{
// reward honor instantly
2010-05-17 17:10:24 +02:00
if ( doAddHonor )
2011-03-14 19:21:34 +06:00
Source -> RewardHonor ( NULL , 1 , value ); // RewardHonor calls UpdatePlayerScore with doAddHonor = false
else
itr -> second -> BonusHonor += value ;
2008-10-05 08:48:32 -05:00
}
2008-10-02 16:23:55 -05:00
break ;
2011-03-14 19:21:34 +06:00
// used only in EY, but in MSG_PVP_LOG_DATA opcode
2008-10-02 16:23:55 -05:00
case SCORE_DAMAGE_DONE : // Damage Done
itr -> second -> DamageDone += value ;
break ;
case SCORE_HEALING_DONE : // Healing Done
itr -> second -> HealingDone += value ;
break ;
default :
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::UpdatePlayerScore: unknown score type (%u) for BG (map: %u, instance id: %u)!" ,
type , m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
break ;
}
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: AddPlayerToResurrectQueue ( const uint64 & npc_guid , const uint64 & player_guid )
2008-10-02 16:23:55 -05:00
{
m_ReviveQueue [ npc_guid ]. push_back ( player_guid );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
Player * plr = sObjectMgr -> GetPlayer ( player_guid );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-09 15:33:45 -05:00
plr -> CastSpell ( plr , SPELL_WAITING_FOR_RESURRECT , true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: RemovePlayerFromResurrectQueue ( const uint64 & player_guid )
2008-10-02 16:23:55 -05:00
{
2009-10-17 16:20:24 -07:00
for ( std :: map < uint64 , std :: vector < uint64 > >:: iterator itr = m_ReviveQueue . begin (); itr != m_ReviveQueue . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
for ( std :: vector < uint64 >:: iterator itr2 = ( itr -> second ). begin (); itr2 != ( itr -> second ). end (); ++ itr2 )
2008-10-02 16:23:55 -05:00
{
2009-04-08 16:33:46 -05:00
if ( * itr2 == player_guid )
2008-10-02 16:23:55 -05:00
{
( itr -> second ). erase ( itr2 );
2011-03-14 19:21:34 +06:00
if ( Player * plr = sObjectMgr -> GetPlayer ( player_guid ))
plr -> RemoveAurasDueToSpell ( SPELL_WAITING_FOR_RESURRECT );
2008-10-02 16:23:55 -05:00
return ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
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*/ )
2008-10-02 16:23:55 -05:00
{
2011-01-09 00:00:08 -03:00
// If the assert is called, means that m_BgObjects must be resized!
ASSERT ( type < m_BgObjects . size ());
2009-12-17 10:43:12 +01:00
Map * map = GetBgMap ();
2009-04-08 16:33:46 -05:00
if ( ! map )
2008-10-05 08:48:32 -05:00
return false ;
2011-03-14 19:21:34 +06:00
// Must be created this way, adding to godatamap would add it to the base map of the instance
2008-10-05 08:48:32 -05:00
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
2011-03-14 19:21:34 +06:00
// So we must create it specific for this instance
2008-10-05 08:48:32 -05:00
GameObject * go = new GameObject ;
2011-03-14 19:21:34 +06:00
if ( ! go -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_GAMEOBJECT ), entry , GetBgMap (),
PHASEMASK_NORMAL , x , y , z , o , rotation0 , rotation1 , rotation2 , rotation3 , 100 , GO_STATE_READY ))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
sLog -> outErrorDb ( "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!" ,
entry , m_MapId , m_InstanceID );
sLog -> outError ( "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!" ,
entry , m_MapId , m_InstanceID );
2008-10-05 08:48:32 -05:00
delete go ;
2008-10-02 16:23:55 -05:00
return false ;
}
2008-10-05 08:48:32 -05:00
/*
uint32 guid = go->GetGUIDLow();
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
// iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed
2010-12-22 21:25:23 +01:00
GameObjectData& data = sObjectMgr->NewGOData(guid);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
data.id = entry;
data.mapid = GetMapId();
data.posX = x;
data.posY = y;
data.posZ = z;
data.orientation = o;
data.rotation0 = rotation0;
data.rotation1 = rotation1;
data.rotation2 = rotation2;
data.rotation3 = rotation3;
data.spawntimesecs = respawnTime;
2008-10-05 08:48:32 -05:00
data.spawnMask = 1;
2008-10-02 16:23:55 -05:00
data.animprogress = 100;
data.go_state = 1;
2008-10-05 08:48:32 -05:00
*/
2011-03-14 19:21:34 +06:00
// Add to world, so it can be later looked up from HashMapHolder
2009-04-08 17:23:57 -05:00
map -> Add ( go );
2008-10-05 08:48:32 -05:00
m_BgObjects [ type ] = go -> GetGUID ();
2008-10-02 16:23:55 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// Some doors aren't despawned so we cannot handle their closing in gameobject::update()
// It would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code
2010-08-08 04:37:24 +02:00
void Battleground :: DoorClose ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
if ( GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
// If doors are open, close it
2009-04-27 18:36:10 -05:00
if ( obj -> getLootState () == GO_ACTIVATED && obj -> GetGoState () != GO_STATE_READY )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
// Change state to allow door to be closed
2008-10-02 16:23:55 -05:00
obj -> SetLootState ( GO_READY );
obj -> UseDoorOrButton ( RESPAWN_ONE_DAY );
}
}
else
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::DoorClose: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
type , GUID_LOPART ( m_BgObjects [ type ]), m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: DoorOpen ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
if ( GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
// Change state to be sure they will be opened
2008-10-02 16:23:55 -05:00
obj -> SetLootState ( GO_READY );
obj -> UseDoorOrButton ( RESPAWN_ONE_DAY );
}
else
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::DoorOpen: door gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
type , GUID_LOPART ( m_BgObjects [ type ]), m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
GameObject * Battleground :: GetBGObject ( uint32 type )
2008-11-21 19:45:49 -06:00
{
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]);
2010-04-07 19:14:10 +02:00
if ( ! obj )
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::GetBGObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
type , GUID_LOPART ( m_BgObjects [ type ]), m_MapId , m_InstanceID );
2008-11-21 19:45:49 -06:00
return obj ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Creature * Battleground :: GetBGCreature ( uint32 type )
2008-11-21 19:45:49 -06:00
{
2009-12-17 10:43:12 +01:00
Creature * creature = GetBgMap () -> GetCreature ( m_BgCreatures [ type ]);
2010-04-07 19:14:10 +02:00
if ( ! creature )
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::GetBGCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
type , GUID_LOPART ( m_BgCreatures [ type ]), m_MapId , m_InstanceID );
2008-11-21 19:45:49 -06:00
return creature ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SpawnBGObject ( uint32 type , uint32 respawntime )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
if ( Map * map = GetBgMap ())
if ( GameObject * obj = map -> GetGameObject ( m_BgObjects [ type ]))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
if ( respawntime )
obj -> SetLootState ( GO_JUST_DEACTIVATED );
else
if ( obj -> getLootState () == GO_JUST_DEACTIVATED )
// Change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
obj -> SetLootState ( GO_READY );
2008-10-02 16:23:55 -05:00
obj -> SetRespawnTime ( respawntime );
2011-03-14 19:21:34 +06:00
map -> Add ( obj );
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Creature * Battleground :: AddCreature ( uint32 entry , uint32 type , uint32 teamval , float x , float y , float z , float o , uint32 respawntime )
2008-10-02 16:23:55 -05:00
{
2011-01-09 00:00:08 -03:00
// If the assert is called, means that m_BgCreatures must be resized!
ASSERT ( type < m_BgCreatures . size ());
2011-03-14 19:21:34 +06:00
Map * map = GetBgMap ();
2009-04-08 16:33:46 -05:00
if ( ! map )
2008-10-05 08:48:32 -05:00
return NULL ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Creature * pCreature = new Creature ;
2010-12-22 21:25:23 +01:00
if ( ! pCreature -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_UNIT ), map , PHASEMASK_NORMAL , entry , 0 , teamval , x , y , z , o ))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::AddCreature: cannot create creature (entry: %u) for BG (map: %u, instance id: %u)!" ,
entry , m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
delete pCreature ;
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-03-20 14:05:14 -06:00
pCreature -> SetHomePosition ( x , y , z , o );
2009-10-17 15:51:44 -07:00
2010-12-22 20:23:47 +01:00
CreatureInfo const * cinfo = ObjectMgr :: GetCreatureTemplate ( entry );
2010-05-04 12:16:45 +02:00
if ( ! cinfo )
{
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::AddCreature: creature template (entry: %u) does not exist for BG (map: %u, instance id: %u)!" ,
entry , m_MapId , m_InstanceID );
delete pCreature ;
2010-05-04 12:16:45 +02:00
return NULL ;
}
2011-03-14 19:21:34 +06:00
// Force using DB speeds
2010-05-04 12:16:45 +02:00
pCreature -> SetSpeed ( MOVE_WALK , cinfo -> speed_walk );
pCreature -> SetSpeed ( MOVE_RUN , cinfo -> speed_run );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
map -> Add ( pCreature );
m_BgCreatures [ type ] = pCreature -> GetGUID ();
2009-10-17 15:51:44 -07:00
2010-05-31 23:01:47 +02:00
if ( respawntime )
pCreature -> SetRespawnDelay ( respawntime );
2008-10-02 16:23:55 -05:00
return pCreature ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: DelCreature ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2009-04-08 16:33:46 -05:00
if ( ! m_BgCreatures [ type ])
2009-02-10 09:55:16 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
if ( Creature * creature = GetBgMap () -> GetCreature ( m_BgCreatures [ type ]))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
creature -> AddObjectToRemoveList ();
m_BgCreatures [ type ] = 0 ;
return true ;
2008-10-02 16:23:55 -05:00
}
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::DelCreature: creature (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
type , GUID_LOPART ( m_BgCreatures [ type ]), m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
m_BgCreatures [ type ] = 0 ;
2011-03-14 19:21:34 +06:00
return false ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: DelObject ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2009-04-08 16:33:46 -05:00
if ( ! m_BgObjects [ type ])
2009-02-10 09:55:16 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
if ( GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
obj -> SetRespawnTime ( 0 ); // not save respawn time
obj -> Delete ();
m_BgObjects [ type ] = 0 ;
return true ;
2008-10-02 16:23:55 -05:00
}
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::DelObject: gameobject (type: %u, GUID: %u) not found for BG (map: %u, instance id: %u)!" ,
type , GUID_LOPART ( m_BgObjects [ type ]), m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
m_BgObjects [ type ] = 0 ;
2011-03-14 19:21:34 +06:00
return false ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: AddSpiritGuide ( uint32 type , float x , float y , float z , float o , uint32 team )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
uint32 entry = ( team == ALLIANCE ) ?
BG_CREATURE_ENTRY_A_SPIRITGUIDE :
BG_CREATURE_ENTRY_H_SPIRITGUIDE ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
if ( Creature * pCreature = AddCreature ( entry , type , team , x , y , z , o ))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
pCreature -> setDeathState ( DEAD );
pCreature -> SetUInt64Value ( UNIT_FIELD_CHANNEL_OBJECT , pCreature -> GetGUID ());
// aura
// TODO: Fix display here
// pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
// casting visual effect
pCreature -> SetUInt32Value ( UNIT_CHANNEL_SPELL , SPELL_SPIRIT_HEAL_CHANNEL );
// correct cast speed
pCreature -> SetFloatValue ( UNIT_MOD_CAST_SPEED , 1.0f );
//pCreature->CastSpell(pCreature, SPELL_SPIRIT_HEAL_CHANNEL, true);
return true ;
2008-10-02 16:23:55 -05:00
}
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::AddSpiritGuide: cannot create spirit guide (type: %u, entry: %u) for BG (map: %u, instance id: %u)!" ,
type , entry , m_MapId , m_InstanceID );
EndNow ();
return false ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendMessageToAll ( int32 entry , ChatMsg type , Player const * source )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
Trinity :: BattlegroundChatBuilder bg_builder ( type , entry , source );
Trinity :: LocalizedPacketDo < Trinity :: BattlegroundChatBuilder > bg_do ( bg_builder );
2009-03-09 17:00:31 -06:00
BroadcastWorker ( bg_do );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: PSendMessageToAll ( int32 entry , ChatMsg type , Player const * source , ...)
2008-10-02 16:23:55 -05:00
{
2009-03-06 15:25:20 -06:00
va_list ap ;
2009-03-09 17:07:12 -06:00
va_start ( ap , source );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Trinity :: BattlegroundChatBuilder bg_builder ( type , entry , source , & ap );
Trinity :: LocalizedPacketDo < Trinity :: BattlegroundChatBuilder > bg_do ( bg_builder );
2009-03-09 17:00:31 -06:00
BroadcastWorker ( bg_do );
2009-10-17 15:51:44 -07:00
2009-03-06 15:25:20 -06:00
va_end ( ap );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendWarningToAll ( int32 entry , ...)
2010-06-01 23:55:09 +02:00
{
2010-12-22 21:25:23 +01:00
const char * format = sObjectMgr -> GetTrinityStringForDBCLocale ( entry );
2011-03-14 19:21:34 +06:00
char str [ 1024 ];
2010-06-01 23:55:09 +02:00
va_list ap ;
va_start ( ap , entry );
2011-03-14 19:21:34 +06:00
vsnprintf ( str , 1024 , format , ap );
2010-06-01 23:55:09 +02:00
va_end ( ap );
2011-03-14 19:21:34 +06:00
std :: string msg ( str );
2010-06-01 23:55:09 +02:00
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
data << ( uint8 ) CHAT_MSG_RAID_BOSS_EMOTE ;
data << ( uint32 ) LANG_UNIVERSAL ;
data << ( uint64 ) 0 ;
data << ( uint32 ) 0 ; // 2.1.0
data << ( uint32 ) 1 ;
2010-08-08 19:45:53 +02:00
data << ( uint8 ) 0 ;
2010-06-01 23:55:09 +02:00
data << ( uint64 ) 0 ;
data << ( uint32 )( strlen ( msg . c_str ()) + 1 );
data << msg . c_str ();
data << ( uint8 ) 0 ;
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2010-06-01 23:55:09 +02:00
if ( Player * plr = ObjectAccessor :: FindPlayer ( MAKE_NEW_GUID ( itr -> first , 0 , HIGHGUID_PLAYER )))
if ( plr -> GetSession ())
plr -> GetSession () -> SendPacket ( & data );
}
2010-08-08 04:37:24 +02:00
void Battleground :: SendMessage2ToAll ( int32 entry , ChatMsg type , Player const * source , int32 arg1 , int32 arg2 )
2009-03-09 17:06:13 -06:00
{
2010-08-08 04:37:24 +02:00
Trinity :: Battleground2ChatBuilder bg_builder ( type , entry , source , arg1 , arg2 );
Trinity :: LocalizedPacketDo < Trinity :: Battleground2ChatBuilder > bg_do ( bg_builder );
2009-03-09 17:06:13 -06:00
BroadcastWorker ( bg_do );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: EndNow ()
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
RemoveFromBGFreeSlotQueue ();
2008-10-02 16:23:55 -05:00
SetStatus ( STATUS_WAIT_LEAVE );
2009-03-13 18:06:36 -06:00
SetEndTime ( 0 );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// To be removed
const char * Battleground :: GetTrinityString ( int32 entry )
2008-10-02 16:23:55 -05:00
{
// FIXME: now we have different DBC locales and need localized message for each target client
2010-12-22 21:25:23 +01:00
return sObjectMgr -> GetTrinityStringForDBCLocale ( entry );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// IMPORTANT NOTICE:
// buffs aren't spawned/despawned when players captures anything
// buffs are in their positions when battleground starts
void Battleground :: HandleTriggerBuff ( const uint64 & go_guid )
2008-10-02 16:23:55 -05:00
{
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( go_guid );
2009-04-08 16:33:46 -05:00
if ( ! obj || obj -> GetGoType () != GAMEOBJECT_TYPE_TRAP || ! obj -> isSpawned ())
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// Change buff type, when buff is used:
2008-10-02 16:23:55 -05:00
int32 index = m_BgObjects . size () - 1 ;
while ( index >= 0 && m_BgObjects [ index ] != go_guid )
index -- ;
if ( index < 0 )
{
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::HandleTriggerBuff: cannot find buff gameobject (GUID: %u, entry: %u, type: %u) in internal data for BG (map: %u, instance id: %u)!" ,
GUID_LOPART ( go_guid ), obj -> GetEntry (), obj -> GetGoType (), m_MapId , m_InstanceID );
2008-10-02 16:23:55 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// Randomly select new buff
2008-10-02 16:23:55 -05:00
uint8 buff = urand ( 0 , 2 );
uint32 entry = obj -> GetEntry ();
2009-04-08 16:33:46 -05:00
if ( m_BuffChange && entry != Buff_Entries [ buff ])
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
// Despawn current buff
2008-10-02 16:23:55 -05:00
SpawnBGObject ( index , RESPAWN_ONE_DAY );
2011-03-14 19:21:34 +06:00
// Set index for new one
2008-10-02 16:23:55 -05:00
for ( uint8 currBuffTypeIndex = 0 ; currBuffTypeIndex < 3 ; ++ currBuffTypeIndex )
2009-04-08 16:33:46 -05:00
if ( entry == Buff_Entries [ currBuffTypeIndex ])
2008-10-02 16:23:55 -05:00
{
index -= currBuffTypeIndex ;
index += buff ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SpawnBGObject ( index , BUFF_RESPAWN_TIME );
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: HandleKillPlayer ( Player * player , Player * killer )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
// Keep in mind that for arena this will have to be changed a bit
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// Add +1 deaths
2008-10-02 16:23:55 -05:00
UpdatePlayerScore ( player , SCORE_DEATHS , 1 );
2011-03-14 19:21:34 +06:00
// Add +1 kills to group and +1 killing_blows to killer
2009-04-08 16:33:46 -05:00
if ( killer )
2008-10-02 16:23:55 -05:00
{
UpdatePlayerScore ( killer , SCORE_HONORABLE_KILLS , 1 );
UpdatePlayerScore ( killer , SCORE_KILLING_BLOWS , 1 );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
Player * plr = sObjectMgr -> GetPlayer ( itr -> first );
2009-04-08 16:33:46 -05:00
if ( ! plr || plr == killer )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( plr -> GetTeam () == killer -> GetTeam () && plr -> IsAtGroupRewardDistance ( player ))
2008-10-02 16:23:55 -05:00
UpdatePlayerScore ( plr , SCORE_HONORABLE_KILLS , 1 );
}
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! isArena ())
2010-05-11 21:48:03 +02:00
{
2011-03-14 19:21:34 +06:00
// To be able to remove insignia -- ONLY IN Battlegrounds
2010-04-07 22:59:46 +02:00
player -> SetFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_SKINNABLE );
2010-05-11 21:48:03 +02:00
RewardXPAtKill ( killer , player );
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
// Return the player's team based on battlegroundplayer info
// Used in same faction arena matches mainly
uint32 Battleground :: GetPlayerTeam ( const uint64 & guid ) const
2008-10-05 08:48:32 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: const_iterator itr = m_Players . find ( guid );
2010-04-08 08:20:08 +02:00
if ( itr != m_Players . end ())
2008-10-05 08:48:32 -05:00
return itr -> second . Team ;
return 0 ;
}
2009-10-17 15:51:44 -07:00
2010-12-06 02:07:53 +01:00
uint32 Battleground :: GetOtherTeam ( uint32 teamId ) const
2009-03-09 17:07:40 -06:00
{
2011-03-14 19:21:34 +06:00
return teamId ? (( teamId == ALLIANCE ) ? HORDE : ALLIANCE ) : 0 ;
2009-03-09 17:07:40 -06:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
bool Battleground :: IsPlayerInBattleground ( const uint64 & guid ) const
2009-02-10 01:16:16 -06:00
{
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: const_iterator itr = m_Players . find ( guid );
2009-04-08 16:33:46 -05:00
if ( itr != m_Players . end ())
2009-02-10 01:16:16 -06:00
return true ;
return false ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: PlayerAddedToBGCheckIfBGIsRunning ( Player * plr )
2009-02-10 01:16:16 -06:00
{
2009-04-08 16:33:46 -05:00
if ( GetStatus () != STATUS_WAIT_LEAVE )
2009-02-10 01:16:16 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-02-10 01:16:16 -06:00
WorldPacket data ;
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr :: BGQueueTypeId ( GetTypeID (), GetArenaType ());
2009-10-17 15:51:44 -07:00
2009-02-10 01:16:16 -06:00
BlockMovement ( plr );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPvpLogDataPacket ( & data , this );
2009-02-10 01:16:16 -06:00
plr -> GetSession () -> SendPacket ( & data );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & data , this , plr -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_IN_PROGRESS , GetEndTime (), GetStartTime (), GetArenaType ());
2009-02-10 01:16:16 -06:00
plr -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetAlivePlayersCountByTeam ( uint32 Team ) const
2008-10-05 08:48:32 -05:00
{
int count = 0 ;
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-05 08:48:32 -05:00
{
2009-04-08 16:33:46 -05:00
if ( itr -> second . Team == Team )
2008-10-05 08:48:32 -05:00
{
2011-03-14 19:21:34 +06:00
Player * pl = sObjectMgr -> GetPlayer ( itr -> first );
2009-05-12 10:01:09 -05:00
if ( pl && pl -> isAlive () && ! pl -> HasByteFlag ( UNIT_FIELD_BYTES_2 , 3 , FORM_SPIRITOFREDEMPTION ))
2008-10-05 08:48:32 -05:00
++ count ;
}
}
return count ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SetHoliday ( bool is_holiday )
2008-10-17 16:36:07 -05:00
{
2011-03-14 19:21:34 +06:00
m_HonorMode = is_holiday ? BG_HOLIDAY : BG_NORMAL ;
2008-10-17 16:36:07 -05:00
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
int32 Battleground :: GetObjectType ( const uint64 & guid )
2008-11-21 19:45:49 -06:00
{
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < m_BgObjects . size (); ++ i )
2010-04-07 19:14:10 +02:00
if ( m_BgObjects [ i ] == guid )
2008-11-21 19:45:49 -06:00
return i ;
2011-03-14 19:21:34 +06:00
sLog -> outError ( "Battleground::GetObjectType: player used gameobject (GUID: %u) which is not in internal data for BG (map: %u, instance id: %u), cheating?" ,
GUID_LOPART ( guid ), m_MapId , m_InstanceID );
2008-11-21 19:45:49 -06:00
return - 1 ;
}
2009-10-17 15:51:44 -07:00
2011-03-14 19:21:34 +06:00
void Battleground :: HandleKillUnit ( Creature * /*creature*/ , Player * /*killer*/ )
2008-11-21 19:45:49 -06:00
{
}
2009-10-17 15:51:44 -07:00
2010-12-02 22:25:32 +01:00
void Battleground :: CheckArenaAfterTimerConditions ()
{
EndBattleground ( WINNER_NONE );
}
2010-08-08 04:37:24 +02:00
void Battleground :: CheckArenaWinConditions ()
2009-03-09 16:36:58 -06:00
{
2009-04-08 16:33:46 -05:00
if ( ! GetAlivePlayersCountByTeam ( ALLIANCE ) && GetPlayersCountByTeam ( HORDE ))
2010-08-08 04:37:24 +02:00
EndBattleground ( HORDE );
2009-04-08 16:33:46 -05:00
else if ( GetPlayersCountByTeam ( ALLIANCE ) && ! GetAlivePlayersCountByTeam ( HORDE ))
2010-08-08 04:37:24 +02:00
EndBattleground ( ALLIANCE );
2009-03-09 16:36:58 -06:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: UpdateArenaWorldState ()
2009-12-16 23:23:42 +02:00
{
2009-12-17 10:43:12 +01:00
UpdateWorldState ( 0xe10 , GetAlivePlayersCountByTeam ( HORDE ));
UpdateWorldState ( 0xe11 , GetAlivePlayersCountByTeam ( ALLIANCE ));
2009-12-16 23:23:42 +02:00
}
2010-08-08 04:37:24 +02:00
void Battleground :: SetBgRaid ( uint32 TeamID , Group * bg_raid )
2009-02-09 22:08:06 -06:00
{
2011-03-14 19:21:34 +06:00
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 );
2009-02-09 22:08:06 -06:00
old_raid = bg_raid ;
2009-02-18 22:39:00 +01:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
WorldSafeLocsEntry const * Battleground :: GetClosestGraveYard ( Player * player )
2009-03-02 17:13:12 -06:00
{
2010-12-22 21:25:23 +01:00
return sObjectMgr -> GetClosestGraveYard ( player -> GetPositionX (), player -> GetPositionY (), player -> GetPositionZ (), player -> GetMapId (), player -> GetTeam ());
2009-03-08 13:05:56 -06:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: IsTeamScoreInRange ( uint32 team , uint32 minScore , uint32 maxScore ) const
2009-07-31 11:36:02 +08:00
{
2011-03-14 19:21:34 +06:00
BattlegroundTeamId teamIndex = GetTeamIndexByTeamId ( team );
uint32 score = std :: max ( m_TeamScores [ teamIndex ], 0 );
2009-09-18 14:10:37 -07:00
return score >= minScore && score <= maxScore ;
2009-07-31 11:36:02 +08:00
}
2010-02-15 15:31:27 +01:00
2010-08-13 13:48:59 +02:00
void Battleground :: StartTimedAchievement ( AchievementCriteriaTimedTypes type , uint32 entry )
{
for ( BattlegroundPlayerMap :: const_iterator itr = GetPlayers (). begin (); itr != GetPlayers (). end (); ++ itr )
2010-12-22 21:25:23 +01:00
if ( Player * pPlayer = sObjectMgr -> GetPlayer ( itr -> first ))
2010-08-13 13:48:59 +02:00
pPlayer -> GetAchievementMgr (). StartTimedAchievement ( type , entry );
}
2010-08-08 04:37:24 +02:00
void Battleground :: SetBracket ( PvPDifficultyEntry const * bracketEntry )
2010-02-15 15:31:27 +01:00
{
2011-03-14 19:21:34 +06:00
m_BracketId = bracketEntry -> GetBracketId ();
SetLevelRange ( bracketEntry -> minLevel , bracketEntry -> maxLevel );
2010-02-15 15:31:27 +01:00
}
2010-05-11 21:42:39 +02:00
2011-03-13 15:28:45 +06:00
void Battleground :: RewardXPAtKill ( Player * killer , Player * victim )
2010-05-11 21:42:39 +02:00
{
2011-03-13 15:28:45 +06:00
if ( sWorld -> getBoolConfig ( CONFIG_BG_XP_FOR_KILL ) && killer && victim )
killer -> RewardPlayerAndGroupAtKill ( victim , true );
2010-06-07 12:08:15 -06:00
}