2010-10-07 15:35:36 +02:00
/*
2012-01-01 00:32:13 +01:00
* Copyright (C) 2008-2012 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"
2011-05-03 15:01:10 +02:00
#include "ArenaTeamMgr.h"
2009-06-04 21:41:07 +02:00
#include "World.h"
2010-06-08 13:05:47 -06:00
#include "WorldPacket.h"
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 )
{
2012-03-29 13:42:04 +08: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-11-07 07:16:31 +01:00
data << uint8 ( _source ? _source -> GetChatTag () : 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-11-07 07:16:31 +01:00
data << uint8 ( _source ? _source -> GetChatTag () : 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 )
2011-11-07 11:06:39 -06:00
if ( Player * player = ObjectAccessor :: FindPlayer ( MAKE_NEW_GUID ( itr -> first , 0 , HIGHGUID_PLAYER )))
_do ( player );
2009-03-09 17:06:13 -06: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
{
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
2012-02-11 19:44:10 -05:00
StartDelayTimes [ BG_STARTING_EVENT_FIRST ] = BG_START_DELAY_2M ;
StartDelayTimes [ BG_STARTING_EVENT_SECOND ] = BG_START_DELAY_1M ;
StartDelayTimes [ BG_STARTING_EVENT_THIRD ] = BG_START_DELAY_30S ;
StartDelayTimes [ BG_STARTING_EVENT_FOURTH ] = BG_START_DELAY_NONE ;
2009-03-07 12:05:30 -06:00
//we must set to some default existing values
2012-02-11 19:44:10 -05:00
StartMessageIds [ BG_STARTING_EVENT_FIRST ] = LANG_BG_WS_START_TWO_MINUTES ;
StartMessageIds [ BG_STARTING_EVENT_SECOND ] = LANG_BG_WS_START_ONE_MINUTE ;
StartMessageIds [ BG_STARTING_EVENT_THIRD ] = LANG_BG_WS_START_HALF_MINUTE ;
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)
2012-02-11 19:44:10 -05:00
uint32 size = uint32 ( BgCreatures . size ());
2011-03-14 19:21:34 +06:00
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
2012-02-11 19:44:10 -05:00
size = uint32 ( BgObjects . size ());
2011-03-14 19:21:34 +06:00
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 )
2011-09-27 17:26:13 -04:00
{
2009-12-17 10:43:12 +01:00
m_Map -> SetUnload ();
2011-09-27 17:26:13 -04:00
//unlink to prevent crash, always unlink all pointer reference before destruction
m_Map -> SetBG ( NULL );
m_Map = NULL ;
}
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
2012-02-11 19:44:10 -05:00
for ( BattlegroundScoreMap :: const_iterator itr = PlayerScores . begin (); itr != 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
{
2011-08-06 10:00:09 +02:00
if ( ! PreUpdateImpl ( diff ))
return ;
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-09-29 12:43:05 +02:00
switch ( GetStatus ())
2011-08-05 11:57:09 +02:00
{
case STATUS_WAIT_JOIN :
if ( GetPlayersSize ())
_ProcessJoin ( diff );
break ;
case STATUS_IN_PROGRESS :
_ProcessOfflineQueue ();
// after 47 minutes without one team losing, the arena closes with no winner and no rating change
if ( isArena ())
{
if ( GetStartTime () >= 47 * MINUTE * IN_MILLISECONDS )
{
UpdateArenaWorldState ();
CheckArenaAfterTimerConditions ();
return ;
}
}
else
{
_ProcessRessurect ( diff );
if ( sBattlegroundMgr -> GetPrematureFinishTime () && ( GetPlayersCountByTeam ( ALLIANCE ) < GetMinPlayersPerTeam () || GetPlayersCountByTeam ( HORDE ) < GetMinPlayersPerTeam ()))
_ProcessProgress ( diff );
else if ( m_PrematureCountDown )
m_PrematureCountDown = false ;
}
break ;
case STATUS_WAIT_LEAVE :
_ProcessLeave ( diff );
break ;
default :
break ;
}
2011-03-14 19:21:34 +06:00
// Update start time and reset stats timer
m_StartTime += diff ;
m_ResetStatTimer += diff ;
2011-08-06 10:00:09 +02:00
PostUpdateImpl ( diff );
}
2011-03-14 19:21:34 +06:00
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
{
2011-09-15 14:08:17 +02: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
{
2011-11-07 11:06:39 -06:00
Player * player = ObjectAccessor :: FindPlayer ( * itr2 );
if ( ! player )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
if ( ! sh && player -> IsInWorld ())
2008-10-02 16:23:55 -05:00
{
2011-11-07 11:06:39 -06:00
sh = player -> 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
2011-11-07 11:06:39 -06:00
player -> CastSpell ( player , 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
{
2011-11-07 11:06:39 -06:00
Player * player = ObjectAccessor :: FindPlayer ( * itr );
if ( ! player )
2008-10-02 16:23:55 -05:00
continue ;
2011-11-07 11:06:39 -06:00
player -> ResurrectPlayer ( 1.0f );
player -> CastSpell ( player , 6962 , true );
player -> CastSpell ( player , 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 )
2011-11-07 11:06:39 -06:00
if ( Player * player = ObjectAccessor :: FindPlayer ( itr -> first ))
player -> ResetAllPowers ();
2011-03-14 19:21:34 +06:00
}
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-10-18 14:23:08 +02:00
if ( ! FindBgMap ())
2011-10-07 13:21:01 -04:00
{
sLog -> outError ( "Battleground::_ProcessJoin: map (map id: %u, instance id: %u) is not created!" , m_MapId , m_InstanceID );
EndNow ();
return ;
}
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 ();
2012-02-11 19:44:10 -05:00
SetStartDelayTime ( StartDelayTimes [ BG_STARTING_EVENT_FIRST ]);
2011-03-14 19:21:34 +06:00
// First start warning - 2 or 1 minute
2012-02-11 19:44:10 -05:00
SendMessageToAll ( StartMessageIds [ BG_STARTING_EVENT_FIRST ], CHAT_MSG_BG_SYSTEM_NEUTRAL );
2011-03-14 19:21:34 +06:00
}
// After 1 minute or 30 seconds, warning is signalled
2012-02-11 19:44:10 -05:00
else if ( GetStartDelayTime () <= StartDelayTimes [ BG_STARTING_EVENT_SECOND ] && ! ( m_Events & BG_STARTING_EVENT_2 ))
2011-03-14 19:21:34 +06:00
{
m_Events |= BG_STARTING_EVENT_2 ;
2012-02-11 19:44:10 -05:00
SendMessageToAll ( StartMessageIds [ BG_STARTING_EVENT_SECOND ], CHAT_MSG_BG_SYSTEM_NEUTRAL );
2011-03-14 19:21:34 +06:00
}
// After 30 or 15 seconds, warning is signalled
2012-02-11 19:44:10 -05:00
else if ( GetStartDelayTime () <= StartDelayTimes [ BG_STARTING_EVENT_THIRD ] && ! ( m_Events & BG_STARTING_EVENT_3 ))
2011-03-14 19:21:34 +06:00
{
m_Events |= BG_STARTING_EVENT_3 ;
2012-02-11 19:44:10 -05:00
SendMessageToAll ( StartMessageIds [ BG_STARTING_EVENT_THIRD ], CHAT_MSG_BG_SYSTEM_NEUTRAL );
2011-03-14 19:21:34 +06:00
}
// 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
2012-02-11 19:44:10 -05:00
SendWarningToAll ( StartMessageIds [ BG_STARTING_EVENT_FOURTH ]);
2011-03-14 19:21:34 +06:00
SetStatus ( STATUS_IN_PROGRESS );
2012-02-11 19:44:10 -05:00
SetStartDelayTime ( 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 )
2011-11-07 11:06:39 -06:00
if ( Player * player = ObjectAccessor :: FindPlayer ( itr -> first ))
2011-03-14 19:21:34 +06:00
{
// BG Status packet
WorldPacket status ;
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr -> BGQueueTypeId ( m_TypeID , GetArenaType ());
2011-11-07 11:06:39 -06:00
uint32 queueSlot = player -> GetBattlegroundQueueIndex ( bgQueueTypeId );
2011-03-14 19:21:34 +06:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & status , this , queueSlot , STATUS_IN_PROGRESS , 0 , GetStartTime (), GetArenaType ());
2011-11-07 11:06:39 -06:00
player -> GetSession () -> SendPacket ( & status );
2011-03-14 19:21:34 +06:00
2011-11-07 11:06:39 -06:00
player -> RemoveAurasDueToSpell ( SPELL_ARENA_PREPARATION );
player -> ResetAllPowers ();
2011-03-14 19:21:34 +06:00
// remove auras with duration lower than 30s
2011-11-07 11:06:39 -06:00
Unit :: AuraApplicationMap & auraMap = player -> GetAppliedAuras ();
2011-03-14 19:21:34 +06:00
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 ;
2011-09-15 14:08:17 +02:00
Aura * aura = aurApp -> GetBase ();
2011-03-14 19:21:34 +06:00
if ( ! aura -> IsPermanent ()
&& aura -> GetDuration () <= 30 * IN_MILLISECONDS
&& aurApp -> IsPositive ()
2011-07-26 23:09:28 +02:00
&& ( ! ( aura -> GetSpellInfo () -> Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY ))
2011-03-14 19:21:34 +06:00
&& ( ! aura -> HasEffectType ( SPELL_AURA_MOD_INVISIBILITY )))
2011-11-07 11:06:39 -06:00
player -> RemoveAura ( iter );
2011-03-14 19:21:34 +06:00
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 )
2011-11-07 11:06:39 -06:00
if ( Player * player = ObjectAccessor :: FindPlayer ( itr -> first ))
2009-03-07 12:05:30 -06:00
{
2011-11-07 11:06:39 -06:00
player -> RemoveAurasDueToSpell ( SPELL_PREPARATION );
player -> 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-08-05 11:57:09 +02:00
inline Player * Battleground :: _GetPlayer ( uint64 guid , bool offlineRemove , const char * context ) const
2011-03-14 19:21:34 +06:00
{
Player * player = NULL ;
if ( ! offlineRemove )
{
2011-07-27 12:14:27 +02:00
player = ObjectAccessor :: FindPlayer ( guid );
2011-03-14 19:21:34 +06:00
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
{
2011-05-07 20:09:45 +02:00
Player * player = _GetPlayer ( itr , context );
if ( player )
2011-03-14 19:21:34 +06:00
{
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
2011-06-12 02:06:07 +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
2011-09-15 14:08:17 +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 ;
2011-07-30 22:46:45 +02:00
int32 loser_matchmaker_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 ;
2011-07-30 22:46:45 +02:00
int32 winner_matchmaker_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
{
2011-05-03 15:01:10 +02:00
winner_arena_team = sArenaTeamMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( winner ));
loser_arena_team = sArenaTeamMgr -> 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 );
2011-07-30 22:46:45 +02:00
winner_matchmaker_change = winner_arena_team -> WonAgainst ( winner_matchmaker_rating , loser_matchmaker_rating , winner_change );
loser_matchmaker_change = loser_arena_team -> LostAgainst ( loser_matchmaker_rating , winner_matchmaker_rating , loser_change );
2012-03-13 01:16:04 +02:00
sLog -> outArena ( "match Type: %u --- Winner: old rating: %u, rating gain: %d, old MMR: %u, MMR gain: %d --- Loser: old rating: %u, rating loss: %d, old MMR: %u, MMR loss: %d ---" , m_ArenaType , winner_team_rating , winner_change , winner_matchmaker_rating ,
2011-07-30 22:46:45 +02:00
winner_matchmaker_change , loser_team_rating , loser_change , loser_matchmaker_rating , loser_matchmaker_change );
SetArenaMatchmakerRating ( winner , winner_matchmaker_rating + winner_matchmaker_change );
SetArenaMatchmakerRating ( GetOtherTeam ( winner ), loser_matchmaker_rating + loser_matchmaker_change );
2010-12-03 23:14:38 +01:00
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 ))
2011-08-06 10:00:09 +02:00
for ( Battleground :: BattlegroundScoreMap :: const_iterator itr = GetPlayerScoresBegin (); itr != GetPlayerScoresEnd (); ++ itr )
2011-07-27 12:14:27 +02:00
if ( Player * player = ObjectAccessor :: FindPlayer ( itr -> first ))
2012-03-13 01:16:04 +02:00
sLog -> outArena ( "Statistics match Type: %u for %s (GUID: " UI64FMTD ", Team: %d, IP: %s): %u damage, %u healing, %u killing blows" , m_ArenaType , 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
2012-01-12 02:05:11 -05:00
uint8 aliveWinners = GetAlivePlayersCountByTeam ( winner );
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 )
2011-07-30 22:46:45 +02:00
winner_arena_team -> OfflineMemberLost ( itr -> first , loser_matchmaker_rating , winner_matchmaker_change );
2009-03-09 17:07:40 -06:00
else
2011-07-30 22:46:45 +02:00
loser_arena_team -> OfflineMemberLost ( itr -> first , winner_matchmaker_rating , loser_matchmaker_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
2011-11-07 11:06:39 -06:00
Player * player = _GetPlayer ( itr , "EndBattleground" );
if ( ! player )
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
2011-11-07 11:06:39 -06:00
if ( player -> HasAuraType ( SPELL_AURA_SPIRIT_OF_REDEMPTION ))
player -> RemoveAurasByType ( SPELL_AURA_MOD_SHAPESHIFT );
2009-10-17 15:51:44 -07:00
2012-01-12 02:21:44 -05:00
// Last standing - Rated 5v5 arena & be solely alive player
if ( team == winner && isArena () && isRated () && GetArenaType () == ARENA_TYPE_5v5 && aliveWinners == 1 && player -> isAlive ())
player -> CastSpell ( player , SPELL_THE_LAST_STANDING , true );
2011-11-07 11:06:39 -06:00
if ( ! player -> isAlive ())
2008-10-02 16:23:55 -05:00
{
2011-11-07 11:06:39 -06:00
player -> ResurrectPlayer ( 1.0f );
player -> 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
2011-11-07 11:06:39 -06:00
player -> CombatStop ();
player -> 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
2011-11-07 11:06:39 -06:00
//if (!team) team = player->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
2011-11-07 11:06:39 -06:00
ArenaTeamMember * member = winner_arena_team -> GetMember ( player -> GetGUID ());
2009-06-14 10:02:20 -05:00
if ( member )
2012-01-31 16:28:10 -05:00
player -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA , 1 );
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
winner_arena_team -> MemberWon ( player , loser_matchmaker_rating , winner_matchmaker_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
{
2011-11-07 11:06:39 -06:00
loser_arena_team -> MemberLost ( player , winner_matchmaker_rating , loser_matchmaker_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
2011-11-07 11:06:39 -06:00
player -> 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
2011-11-07 11:06:39 -06:00
uint32 winner_kills = player -> GetRandomWinner () ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST ;
uint32 loser_kills = player -> GetRandomWinner () ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST ;
uint32 winner_arena = player -> 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
{
2011-11-07 11:06:39 -06:00
UpdatePlayerScore ( player , SCORE_BONUS_HONOR , GetBonusHonorFromKill ( winner_kills ));
2010-08-07 01:58:23 +06:00
if ( CanAwardArenaPoints ())
2011-11-07 11:06:39 -06:00
player -> ModifyArenaPoints ( winner_arena );
if ( ! player -> GetRandomWinner ())
player -> SetRandomWinner ( true );
2010-05-26 11:34:37 +02:00
}
2011-11-07 11:06:39 -06:00
player -> 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 ()))
2011-11-07 11:06:39 -06:00
UpdatePlayerScore ( player , SCORE_BONUS_HONOR , GetBonusHonorFromKill ( loser_kills ));
2010-08-08 19:45:53 +02:00
}
2010-05-26 11:34:37 +02:00
2011-11-07 11:06:39 -06:00
player -> ResetAllPowers ();
player -> CombatStopWithPets ( true );
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
BlockMovement ( player );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPvpLogDataPacket ( & data , this );
2011-11-07 11:06:39 -06:00
player -> 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 ());
2011-11-07 11:06:39 -06:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & data , this , player -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_IN_PROGRESS , TIME_TO_AUTOREMOVE , GetStartTime (), GetArenaType ());
player -> GetSession () -> SendPacket ( & data );
player -> 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
2011-11-07 11:06:39 -06:00
void Battleground :: BlockMovement ( Player * player )
2008-10-02 16:23:55 -05:00
{
2011-11-07 11:06:39 -06:00
player -> SetClientControl ( player , 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()
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-08-05 11:57:09 +02:00
void Battleground :: RemovePlayerAtLeave ( 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 );
2011-06-18 14:08:51 +03:00
bool participant = false ;
// Remove from lists/maps
BattlegroundPlayerMap :: iterator itr = m_Players . find ( guid );
if ( itr != m_Players . end ())
{
UpdatePlayersCountByTeam ( team , true ); // -1 player
m_Players . erase ( itr );
// check if the player was a participant of the match, or only entered through gm command (goname)
participant = true ;
}
2009-10-17 15:51:44 -07:00
2012-02-11 19:44:10 -05:00
BattlegroundScoreMap :: iterator itr2 = PlayerScores . find ( guid );
if ( itr2 != PlayerScores . end ())
2008-10-02 16:23:55 -05:00
{
delete itr2 -> second ; // delete player's score
2012-02-11 19:44:10 -05:00
PlayerScores . erase ( itr2 );
2008-10-02 16:23:55 -05:00
}
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
2011-11-07 11:06:39 -06:00
Player * player = ObjectAccessor :: FindPlayer ( guid );
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// should remove spirit of redemption
2011-11-07 11:06:39 -06:00
if ( player )
2008-10-02 16:23:55 -05:00
{
2011-11-07 11:06:39 -06:00
if ( player -> HasAuraType ( SPELL_AURA_SPIRIT_OF_REDEMPTION ))
player -> RemoveAurasByType ( SPELL_AURA_MOD_SHAPESHIFT );
2011-08-05 11:57:09 +02:00
2011-11-07 11:06:39 -06:00
if ( ! player -> isAlive ()) // resurrect on exit
2011-08-05 11:57:09 +02:00
{
2011-11-07 11:06:39 -06:00
player -> ResurrectPlayer ( 1.0f );
player -> SpawnCorpseBones ();
2011-08-05 11:57:09 +02:00
}
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
RemovePlayer ( player , guid , team ); // BG subclass specific code
2011-06-17 21:26:33 +03: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 ());
2011-11-07 11:06:39 -06:00
if ( player )
2008-10-02 16:23:55 -05:00
{
2011-11-07 11:06:39 -06:00
player -> ClearAfkReports ();
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
if ( ! team ) team = player -> 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
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
2011-11-07 11:06:39 -06:00
player -> RemovePet ( NULL , PET_SAVE_NOT_IN_SLOT );
player -> 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
2011-09-15 14:08:17 +02:00
ArenaTeam * winner_arena_team = sArenaTeamMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( team )));
ArenaTeam * loser_arena_team = sArenaTeamMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( team ));
2009-06-16 12:25:18 -05:00
if ( winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2011-11-07 11:06:39 -06:00
loser_arena_team -> MemberLost ( player , 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 ;
2011-11-07 11:06:39 -06:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & data , this , player -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_NONE , 0 , 0 , 0 );
player -> GetSession () -> SendPacket ( & data );
2008-10-05 08:48:32 -05:00
}
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
2011-11-07 11:06:39 -06:00
player -> 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
2011-09-15 14:08:17 +02:00
ArenaTeam * others_arena_team = sArenaTeamMgr -> GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( team )));
ArenaTeam * players_arena_team = sArenaTeamMgr -> 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
2011-06-12 01:47:45 +02: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 );
2011-11-07 11:06:39 -06:00
SendPacketToTeam ( team , & data , player , false );
2009-03-09 17:07:40 -06:00
}
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
if ( player )
2009-03-09 17:07:40 -06:00
{
2008-10-02 16:23:55 -05:00
// Do next only if found in battleground
2011-11-07 11:06:39 -06:00
player -> SetBattlegroundId ( 0 , BATTLEGROUND_TYPE_NONE ); // We're not in BG.
2008-10-05 08:48:32 -05:00
// reset destination bg team
2011-11-07 11:06:39 -06:00
player -> SetBGTeam ( 0 );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( Transport )
2011-11-07 11:06:39 -06:00
player -> TeleportToBGEntryPoint ();
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
sLog -> outDetail ( "BATTLEGROUND: Removed player %s from Battleground." , player -> GetName ());
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
2012-02-11 19:44:10 -05:00
for ( BattlegroundScoreMap :: const_iterator itr = PlayerScores . begin (); itr != PlayerScores . end (); ++ itr )
2009-08-06 17:45:37 -05:00
delete itr -> second ;
2012-02-11 19:44:10 -05:00
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-11-07 11:06:39 -06:00
void Battleground :: AddPlayer ( Player * player )
2008-10-02 16:23:55 -05:00
{
2009-08-27 20:28:28 -05:00
// remove afk from player
2011-11-07 11:06:39 -06:00
if ( player -> HasFlag ( PLAYER_FLAGS , PLAYER_FLAGS_AFK ))
player -> 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
2011-11-07 11:06:39 -06:00
uint64 guid = player -> GetGUID ();
uint32 team = player -> 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 ;
2011-11-07 11:06:39 -06:00
sBattlegroundMgr -> BuildPlayerJoinedBattlegroundPacket ( & data , player );
SendPacketToTeam ( team , & data , player , 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 ());
2011-11-07 11:06:39 -06:00
uint32 queueSlot = player -> GetBattlegroundQueueIndex ( bgQueueTypeId );
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & status , this , queueSlot , STATUS_IN_PROGRESS , 0 , GetStartTime (), GetArenaType (), isArena () ? 0 : 1 );
2011-11-07 11:06:39 -06:00
player -> GetSession () -> SendPacket ( & status );
2010-01-14 11:22:52 +01:00
2011-11-07 11:06:39 -06:00
player -> RemoveAurasByType ( SPELL_AURA_MOUNTED );
2010-06-03 16:24:10 +02:00
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
{
2011-11-07 11:06:39 -06:00
player -> RemoveArenaEnchantments ( TEMP_ENCHANTMENT_SLOT );
2010-04-07 19:14:10 +02:00
if ( team == ALLIANCE ) // gold
2008-11-30 12:47:26 -06:00
{
2011-11-07 11:06:39 -06:00
if ( player -> GetTeam () == HORDE )
player -> CastSpell ( player , SPELL_HORDE_GOLD_FLAG , true );
2008-11-30 12:47:26 -06:00
else
2011-11-07 11:06:39 -06:00
player -> CastSpell ( player , SPELL_ALLIANCE_GOLD_FLAG , true );
2008-11-30 12:47:26 -06:00
}
else // green
{
2011-11-07 11:06:39 -06:00
if ( player -> GetTeam () == HORDE )
player -> CastSpell ( player , SPELL_HORDE_GREEN_FLAG , true );
2008-11-30 12:47:26 -06:00
else
2011-11-07 11:06:39 -06:00
player -> CastSpell ( player , SPELL_ALLIANCE_GREEN_FLAG , true );
2008-11-30 12:47:26 -06:00
}
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
player -> DestroyConjuredItems ( true );
player -> 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
{
2011-11-07 11:06:39 -06:00
player -> CastSpell ( player , SPELL_ARENA_PREPARATION , true );
player -> 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 );
2011-11-07 11:06:39 -06:00
teammate << uint64 ( player -> GetGUID ());
SendPacketToTeam ( team , & teammate , player , 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
2011-11-07 11:06:39 -06:00
player -> CastSpell ( player , SPELL_PREPARATION , true ); // reduces all mana cost of spells.
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_BG , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
player -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL , ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP , GetMapId (), true );
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
// setup BG group membership
2011-11-07 11:06:39 -06:00
PlayerAddedToBGCheckIfBGIsRunning ( player );
AddOrSetPlayerToCorrectBgGroup ( player , team );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// Log
2011-11-07 11:06:39 -06:00
sLog -> outDetail ( "BATTLEGROUND: Player %s joined the battle." , player -> 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
{
2011-08-05 11:57:09 +02:00
uint64 guid = player -> GetGUID ();
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-08-05 11:57:09 +02:00
if ( * itr == guid )
2009-03-09 17:07:12 -06:00
{
m_OfflineQueue . erase ( itr );
break ;
}
}
2011-08-05 11:57:09 +02:00
m_Players [ guid ]. 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
{
2011-08-05 11:57:09 +02:00
uint64 guid = player -> GetGUID ();
2009-03-09 17:07:12 -06:00
// player is correct pointer, it is checked in WorldSession::LogoutPlayer()
m_OfflineQueue . push_back ( player -> GetGUID ());
2011-08-05 11:57:09 +02:00
m_Players [ guid ]. 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
2011-08-05 11:57:09 +02:00
RemovePlayer ( player , guid , GetPlayerTeam ( guid ));
2010-02-15 15:31:27 +01:00
// 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
}
}
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
2012-02-11 19:44:10 -05:00
BattlegroundScoreMap :: const_iterator itr = PlayerScores . find ( Source -> GetGUID ());
if ( itr == 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 ;
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-08-05 11:57:09 +02:00
void Battleground :: AddPlayerToResurrectQueue ( uint64 npc_guid , 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
2011-11-07 11:06:39 -06:00
Player * player = ObjectAccessor :: FindPlayer ( player_guid );
if ( ! player )
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
player -> CastSpell ( player , SPELL_WAITING_FOR_RESURRECT , true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2011-08-05 11:57:09 +02:00
void Battleground :: RemovePlayerFromResurrectQueue ( 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-11-07 11:06:39 -06:00
if ( Player * player = ObjectAccessor :: FindPlayer ( player_guid ))
player -> 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
{
2012-02-11 19:44:10 -05:00
// If the assert is called, means that BgObjects must be resized!
ASSERT ( type < BgObjects . size ());
2011-01-09 00:00:08 -03:00
2011-10-07 13:21:01 -04:00
Map * map = FindBgMap ();
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
2011-06-11 22:35:29 +02: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
2011-11-28 14:05:25 -05:00
if ( ! map -> AddToMap ( go ))
{
delete go ;
return false ;
}
2012-02-11 19:44:10 -05:00
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
{
2012-02-11 19:44:10 -05:00
if ( GameObject * obj = GetBgMap () -> GetGameObject ( 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
{
obj -> SetLootState ( GO_READY );
2012-04-10 20:04:45 -05:00
obj -> SetGoState ( GO_STATE_READY );
2008-10-02 16:23:55 -05:00
}
}
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)!" ,
2012-02-11 19:44:10 -05:00
type , GUID_LOPART ( 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
{
2012-02-11 19:44:10 -05:00
if ( GameObject * obj = GetBgMap () -> GetGameObject ( BgObjects [ type ]))
2008-10-02 16:23:55 -05:00
{
2012-04-10 20:04:45 -05:00
obj -> SetLootState ( GO_ACTIVATED );
obj -> SetGoState ( GO_STATE_ACTIVE );
2008-10-02 16:23:55 -05:00
}
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)!" ,
2012-02-11 19:44:10 -05:00
type , GUID_LOPART ( 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
{
2012-02-11 19:44:10 -05:00
GameObject * obj = GetBgMap () -> GetGameObject ( 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)!" ,
2012-02-11 19:44:10 -05:00
type , GUID_LOPART ( 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
{
2012-02-11 19:44:10 -05:00
Creature * creature = GetBgMap () -> GetCreature ( 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)!" ,
2012-02-11 19:44:10 -05:00
type , GUID_LOPART ( 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-10-07 13:21:01 -04:00
if ( Map * map = FindBgMap ())
2012-02-11 19:44:10 -05:00
if ( GameObject * obj = map -> GetGameObject ( 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-10-10 17:39:34 -04:00
map -> AddToMap ( 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
{
2012-02-11 19:44:10 -05:00
// If the assert is called, means that BgCreatures must be resized!
ASSERT ( type < BgCreatures . size ());
2011-01-09 00:00:08 -03:00
2011-10-07 13:21:01 -04:00
Map * map = FindBgMap ();
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
2011-10-07 11:08:09 -05:00
Creature * creature = new Creature ;
if ( ! creature -> 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 );
2011-10-07 11:08:09 -05:00
delete creature ;
2008-10-02 16:23:55 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2011-10-07 11:08:09 -05:00
creature -> SetHomePosition ( x , y , z , o );
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
CreatureTemplate const * cinfo = sObjectMgr -> 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 );
2011-10-07 11:08:09 -05:00
delete creature ;
2010-05-04 12:16:45 +02:00
return NULL ;
}
2011-03-14 19:21:34 +06:00
// Force using DB speeds
2011-10-07 11:08:09 -05:00
creature -> SetSpeed ( MOVE_WALK , cinfo -> speed_walk );
creature -> SetSpeed ( MOVE_RUN , cinfo -> speed_run );
2009-10-17 15:51:44 -07:00
2011-11-28 14:05:25 -05:00
if ( ! map -> AddToMap ( creature ))
{
delete creature ;
return NULL ;
}
2012-02-11 19:44:10 -05:00
BgCreatures [ type ] = creature -> GetGUID ();
2009-10-17 15:51:44 -07:00
2010-05-31 23:01:47 +02:00
if ( respawntime )
2011-10-07 11:08:09 -05:00
creature -> SetRespawnDelay ( respawntime );
2010-05-31 23:01:47 +02:00
2011-10-07 11:08:09 -05:00
return creature ;
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 :: DelCreature ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2012-02-11 19:44:10 -05:00
if ( ! BgCreatures [ type ])
2009-02-10 09:55:16 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2012-02-11 19:44:10 -05:00
if ( Creature * creature = GetBgMap () -> GetCreature ( BgCreatures [ type ]))
2008-10-02 16:23:55 -05:00
{
2011-03-14 19:21:34 +06:00
creature -> AddObjectToRemoveList ();
2012-02-11 19:44:10 -05:00
BgCreatures [ type ] = 0 ;
2011-03-14 19:21:34 +06:00
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)!" ,
2012-02-11 19:44:10 -05:00
type , GUID_LOPART ( BgCreatures [ type ]), m_MapId , m_InstanceID );
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
{
2012-02-11 19:44:10 -05:00
if ( ! BgObjects [ type ])
2009-02-10 09:55:16 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2012-02-11 19:44:10 -05:00
if ( GameObject * obj = GetBgMap () -> GetGameObject ( 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 ();
2012-02-11 19:44:10 -05:00
BgObjects [ type ] = 0 ;
2011-03-14 19:21:34 +06:00
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)!" ,
2012-02-11 19:44:10 -05:00
type , GUID_LOPART ( BgObjects [ type ]), m_MapId , m_InstanceID );
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-10-07 11:08:09 -05:00
if ( Creature * creature = AddCreature ( entry , type , team , x , y , z , o ))
2008-10-02 16:23:55 -05:00
{
2011-10-07 11:08:09 -05:00
creature -> setDeathState ( DEAD );
creature -> SetUInt64Value ( UNIT_FIELD_CHANNEL_OBJECT , creature -> GetGUID ());
2011-03-14 19:21:34 +06:00
// aura
// TODO: Fix display here
2011-10-07 11:08:09 -05:00
// creature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
2011-03-14 19:21:34 +06:00
// casting visual effect
2011-10-07 11:08:09 -05:00
creature -> SetUInt32Value ( UNIT_CHANNEL_SPELL , SPELL_SPIRIT_HEAL_CHANNEL );
2011-03-14 19:21:34 +06:00
// correct cast speed
2011-10-07 11:08:09 -05:00
creature -> SetFloatValue ( UNIT_MOD_CAST_SPEED , 1.0f );
//creature->CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
2011-03-14 19:21:34 +06:00
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
{
2011-08-05 11:57:09 +02:00
if ( ! entry )
return ;
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
{
2011-08-05 11:57:09 +02:00
if ( ! entry )
return ;
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
{
2011-08-05 11:57:09 +02:00
if ( ! entry )
return ;
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 ;
2011-08-23 18:05:01 +03:00
data << ( uint32 )( msg . length () + 1 );
2010-06-01 23:55:09 +02:00
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 )
2011-11-07 11:06:39 -06:00
if ( Player * player = ObjectAccessor :: FindPlayer ( MAKE_NEW_GUID ( itr -> first , 0 , HIGHGUID_PLAYER )))
if ( player -> GetSession ())
player -> GetSession () -> SendPacket ( & data );
2010-06-01 23:55:09 +02:00
}
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
2011-08-05 11:57:09 +02:00
void Battleground :: HandleTriggerBuff ( uint64 go_guid )
2008-10-02 16:23:55 -05:00
{
2011-09-15 14:08:17 +02: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:
2012-02-11 19:44:10 -05:00
int32 index = BgObjects . size () - 1 ;
while ( index >= 0 && BgObjects [ index ] != go_guid )
2008-10-02 16:23:55 -05:00
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-11-23 17:55:16 +01:00
Player * creditedPlayer = ObjectAccessor :: FindPlayer ( itr -> first );
if ( ! creditedPlayer || creditedPlayer == killer )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2011-11-23 17:55:16 +01:00
if ( creditedPlayer -> GetTeam () == killer -> GetTeam () && creditedPlayer -> IsAtGroupRewardDistance ( player ))
UpdatePlayerScore ( creditedPlayer , SCORE_HONORABLE_KILLS , 1 );
2008-10-02 16:23:55 -05:00
}
}
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
2011-08-05 11:57:09 +02:00
uint32 Battleground :: GetPlayerTeam ( 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-08-05 11:57:09 +02:00
bool Battleground :: IsPlayerInBattleground ( 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
2011-11-07 11:06:39 -06:00
void Battleground :: PlayerAddedToBGCheckIfBGIsRunning ( Player * player )
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
2011-11-07 11:06:39 -06:00
BlockMovement ( player );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
sBattlegroundMgr -> BuildPvpLogDataPacket ( & data , this );
2011-11-07 11:06:39 -06:00
player -> GetSession () -> SendPacket ( & data );
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
sBattlegroundMgr -> BuildBattlegroundStatusPacket ( & data , this , player -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_IN_PROGRESS , GetEndTime (), GetStartTime (), GetArenaType ());
player -> GetSession () -> SendPacket ( & data );
2009-02-10 01:16:16 -06:00
}
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-11-07 11:18:00 -06:00
Player * player = ObjectAccessor :: FindPlayer ( itr -> first );
if ( player && player -> isAlive () && ! player -> 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-08-05 11:57:09 +02:00
int32 Battleground :: GetObjectType ( uint64 guid )
2008-11-21 19:45:49 -06:00
{
2012-02-11 19:44:10 -05:00
for ( uint32 i = 0 ; i < BgObjects . size (); ++ i )
if ( 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
}
2011-09-15 14:08:17 +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 )
2011-10-07 11:08:09 -05:00
if ( Player * player = ObjectAccessor :: FindPlayer ( itr -> first ))
player -> GetAchievementMgr (). StartTimedAchievement ( type , entry );
2010-08-13 13:48:59 +02:00
}
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
}