2010-10-07 15:35:36 +02:00
/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "Player.h"
2009-06-04 21:41:07 +02:00
#include "ObjectMgr.h"
#include "World.h"
2010-06-08 13:05:47 -06:00
#include "WorldPacket.h"
2009-10-17 15:51:44 -07:00
2009-06-04 21:41:07 +02:00
#include "ArenaTeam.h"
2010-08-08 04:37:24 +02:00
#include "Battleground.h"
#include "BattlegroundMgr.h"
2008-10-02 16:23:55 -05:00
#include "Creature.h"
2010-06-08 13:05:47 -06:00
#include "Formulas.h"
#include "GridNotifiersImpl.h"
2009-06-04 21:41:07 +02:00
#include "Group.h"
2010-06-08 13:05:47 -06:00
#include "Language.h"
2009-06-04 21:41:07 +02:00
#include "MapManager.h"
#include "Object.h"
2008-10-02 16:23:55 -05:00
#include "SpellAuras.h"
2010-01-10 01:23:15 +01:00
#include "SpellAuraEffects.h"
2010-06-08 13:05:47 -06:00
#include "Util.h"
2009-06-04 21:41:07 +02:00
2009-12-20 15:20:04 +01:00
namespace Trinity
2009-03-09 17:00:31 -06:00
{
2010-08-08 04:37:24 +02:00
class BattlegroundChatBuilder
2009-03-09 17:00:31 -06:00
{
public :
2010-08-08 04:37:24 +02:00
BattlegroundChatBuilder ( ChatMsg msgtype , int32 textId , Player const * source , va_list * args = NULL )
2009-03-09 17:00:31 -06:00
: i_msgtype ( msgtype ), i_textId ( textId ), i_source ( source ), i_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
{
2010-08-08 05:25:45 +02:00
char const * text = sObjectMgr . GetTrinityString ( i_textId , loc_idx );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( i_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 ;
va_copy ( ap , * i_args );
2009-10-17 15:51:44 -07:00
2009-03-09 17:00:31 -06:00
char str [ 2048 ];
2010-04-07 22:59:46 +02:00
vsnprintf ( str , 2048 , text , ap );
2009-03-09 17:00:31 -06:00
va_end ( ap );
2009-10-17 15:51:44 -07:00
2009-03-09 17:00:31 -06:00
do_helper ( data , & str [ 0 ]);
}
else
do_helper ( data , text );
}
private :
void do_helper ( WorldPacket & data , char const * text )
{
uint64 target_guid = i_source ? i_source -> GetGUID () : 0 ;
2009-10-17 15:51:44 -07:00
2009-03-09 17:00:31 -06:00
data << uint8 ( i_msgtype );
data << uint32 ( LANG_UNIVERSAL );
data << uint64 ( target_guid ); // there 0 for BG messages
data << uint32 ( 0 ); // can be chat msg group or something
data << uint64 ( target_guid );
data << uint32 ( strlen ( text ) + 1 );
data << text ;
data << uint8 ( i_source ? i_source -> chatTag () : uint8 ( 0 ));
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:00:31 -06:00
ChatMsg i_msgtype ;
int32 i_textId ;
Player const * i_source ;
va_list * i_args ;
};
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 )
2009-03-09 17:06:13 -06:00
: i_msgtype ( msgtype ), i_textId ( textId ), i_source ( source ), i_arg1 ( arg1 ), i_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
{
2010-08-08 05:25:45 +02:00
char const * text = sObjectMgr . GetTrinityString ( i_textId , loc_idx );
char const * arg1str = i_arg1 ? sObjectMgr . GetTrinityString ( i_arg1 , loc_idx ) : "" ;
char const * arg2str = i_arg2 ? sObjectMgr . GetTrinityString ( i_arg2 , loc_idx ) : "" ;
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
char str [ 2048 ];
2010-04-07 22:59:46 +02:00
snprintf ( str , 2048 , text , arg1str , arg2str );
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
uint64 target_guid = i_source ? i_source -> GetGUID () : 0 ;
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
data << uint8 ( i_msgtype );
data << uint32 ( LANG_UNIVERSAL );
data << uint64 ( target_guid ); // there 0 for BG messages
data << uint32 ( 0 ); // can be chat msg group or something
data << uint64 ( target_guid );
data << uint32 ( strlen ( str ) + 1 );
data << str ;
data << uint8 ( i_source ? i_source -> chatTag () : uint8 ( 0 ));
}
private :
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
ChatMsg i_msgtype ;
int32 i_textId ;
Player const * i_source ;
int32 i_arg1 ;
int32 i_arg2 ;
};
2009-12-20 15:20:04 +01:00
} // namespace Trinity
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
template < class Do >
2010-08-08 04:37:24 +02:00
void Battleground :: BroadcastWorker ( Do & _do )
2009-03-09 17:06:13 -06:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2009-04-08 16:33:46 -05:00
if ( Player * plr = ObjectAccessor :: FindPlayer ( MAKE_NEW_GUID ( itr -> first , 0 , HIGHGUID_PLAYER )))
2009-03-09 17:06:13 -06:00
_do ( plr );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground :: Battleground ()
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
m_TypeID = BattlegroundTypeId ( 0 );
m_RandomTypeID = BattlegroundTypeId ( 0 );
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 ;
m_PrematureCountDown = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-17 16:36:07 -05:00
m_HonorMode = BG_NORMAL ;
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
m_StartDelayTimes [ BG_STARTING_EVENT_FIRST ] = BG_START_DELAY_2M ;
m_StartDelayTimes [ BG_STARTING_EVENT_SECOND ] = BG_START_DELAY_1M ;
m_StartDelayTimes [ BG_STARTING_EVENT_THIRD ] = BG_START_DELAY_30S ;
m_StartDelayTimes [ BG_STARTING_EVENT_FOURTH ] = BG_START_DELAY_NONE ;
//we must set to some default existing values
m_StartMessageIds [ BG_STARTING_EVENT_FIRST ] = LANG_BG_WS_START_TWO_MINUTES ;
m_StartMessageIds [ BG_STARTING_EVENT_SECOND ] = LANG_BG_WS_START_ONE_MINUTE ;
m_StartMessageIds [ BG_STARTING_EVENT_THIRD ] = LANG_BG_WS_START_HALF_MINUTE ;
m_StartMessageIds [ BG_STARTING_EVENT_FOURTH ] = LANG_BG_WS_HAS_BEGUN ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Battleground ::~ Battleground ()
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
// remove objects and creatures
2008-12-19 16:05:13 -06:00
// (this is done automatically in mapmanager update, when the instance is reset after the reset time)
2008-10-05 08:48:32 -05:00
int size = m_BgCreatures . size ();
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < size ; ++ i )
2008-10-05 08:48:32 -05:00
DelCreature ( i );
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
size = m_BgObjects . size ();
2009-10-17 16:20:24 -07:00
for ( int i = 0 ; i < size ; ++ i )
2008-10-05 08:48:32 -05:00
DelObject ( i );
2009-10-17 15:51:44 -07:00
2009-08-06 17:45:37 -05:00
if ( GetInstanceID ()) // not spam by useless queries in case BG templates
2009-02-17 17:40:38 -06:00
{
// delete creature and go respawn times
2010-11-19 15:53:14 +01:00
CharacterDatabase . PExecute ( "DELETE FROM creature_respawn WHERE instance = '%u'" , GetInstanceID ());
CharacterDatabase . PExecute ( "DELETE FROM gameobject_respawn WHERE instance = '%u'" , GetInstanceID ());
2009-02-17 17:40:38 -06:00
// delete instance from db
CharacterDatabase . PExecute ( "DELETE FROM instance WHERE id = '%u'" , GetInstanceID ());
// remove from battlegrounds
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . RemoveBattleground ( GetInstanceID (), GetTypeID ());
2008-10-05 08:48:32 -05:00
// unload map
2009-12-17 10:43:12 +01:00
if ( m_Map )
m_Map -> SetUnload ();
2008-10-05 08:48:32 -05:00
// remove from bg free slot queue
this -> RemoveFromBGFreeSlotQueue ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundScoreMap :: const_iterator itr = m_PlayerScores . begin (); itr != m_PlayerScores . end (); ++ itr )
2009-08-06 17:45:37 -05:00
delete itr -> second ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: Update ( uint32 diff )
2008-10-02 16:23:55 -05:00
{
2009-09-11 16:25:11 -07:00
if ( ! GetPlayersSize ())
{
2008-10-02 16:23:55 -05:00
//BG is empty
2009-09-11 16:25:11 -07:00
// if there are no players invited, delete BG
// this will delete arena or bg object, where any player entered
// [[ but if you use battleground object again (more battles possible to be played on 1 instance)
// then this condition should be removed and code:
// if (!GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
// this->AddToFreeBGObjectsQueue(); // not yet implemented
// should be used instead of current
// ]]
2010-08-08 04:37:24 +02:00
// Battleground Template instance cannot be updated, because it would be deleted
2009-09-11 16:25:11 -07:00
if ( ! GetInvitedCount ( HORDE ) && ! GetInvitedCount ( ALLIANCE ))
m_SetDeleteThis = true ;
2008-10-02 16:23:55 -05:00
return ;
2009-09-11 16:25:11 -07:00
}
2009-10-17 15:51:44 -07:00
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
{
2009-12-24 10:20:15 +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
2009-03-07 12:05:30 -06:00
/*********************************************************/
/*** BATTLEGROUND RESSURECTION SYSTEM ***/
/*********************************************************/
2009-10-17 15:51:44 -07:00
2009-03-09 16:36:58 -06:00
//this should be handled by spell system
2008-10-02 16:23:55 -05:00
m_LastResurrectTime += diff ;
if ( m_LastResurrectTime >= RESURRECTION_INTERVAL )
{
2009-04-08 16:33:46 -05:00
if ( GetReviveQueueSize ())
2008-10-02 16:23:55 -05:00
{
2009-10-17 16:20:24 -07:00
for ( std :: map < uint64 , std :: vector < uint64 > >:: iterator itr = m_ReviveQueue . begin (); itr != m_ReviveQueue . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
Creature * sh = NULL ;
2009-10-17 16:20:24 -07:00
for ( std :: vector < uint64 >:: const_iterator itr2 = ( itr -> second ). begin (); itr2 != ( itr -> second ). end (); ++ itr2 )
2008-10-02 16:23:55 -05:00
{
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( * itr2 );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-20 20:28:19 -05:00
if ( ! sh && plr -> IsInWorld ())
2008-10-02 16:23:55 -05:00
{
2009-04-20 20:28:19 -05:00
sh = plr -> GetMap () -> GetCreature ( itr -> first );
2008-10-02 16:23:55 -05:00
// only for visual effect
if ( sh )
2009-08-09 15:33:45 -05:00
// Spirit Heal, effect 117
sh -> CastSpell ( sh , SPELL_SPIRIT_HEAL , true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-09 15:33:45 -05:00
// Resurrection visual
plr -> CastSpell ( plr , SPELL_RESURRECTION_VISUAL , true );
2008-10-02 16:23:55 -05:00
m_ResurrectQueue . push_back ( * itr2 );
}
( itr -> second ). clear ();
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_ReviveQueue . clear ();
m_LastResurrectTime = 0 ;
}
else
// queue is clear and time passed, just update last resurrection time
m_LastResurrectTime = 0 ;
}
else if ( m_LastResurrectTime > 500 ) // Resurrect players only half a second later, to see spirit heal effect on NPC
{
2009-10-17 16:20:24 -07:00
for ( std :: vector < uint64 >:: const_iterator itr = m_ResurrectQueue . begin (); itr != m_ResurrectQueue . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( * itr );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
continue ;
plr -> ResurrectPlayer ( 1.0f );
2009-10-06 22:41:37 +02:00
plr -> CastSpell ( plr , 6962 , true );
2008-10-02 16:23:55 -05:00
plr -> CastSpell ( plr , SPELL_SPIRIT_HEAL_MANA , true );
2010-06-25 00:18:01 +02:00
sObjectAccessor . ConvertCorpseForPlayer ( * itr );
2008-10-02 16:23:55 -05:00
}
m_ResurrectQueue . clear ();
}
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
/*********************************************************/
/*** BATTLEGROUND BALLANCE SYSTEM ***/
/*********************************************************/
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// if less then minimum players are in on one side, then start premature finish timer
2010-08-08 04:37:24 +02:00
if ( GetStatus () == STATUS_IN_PROGRESS && ! isArena () && sBattlegroundMgr . GetPrematureFinishTime () && ( GetPlayersCountByTeam ( ALLIANCE ) < GetMinPlayersPerTeam () || GetPlayersCountByTeam ( HORDE ) < GetMinPlayersPerTeam ()))
2008-10-05 08:48:32 -05:00
{
2009-04-08 16:33:46 -05:00
if ( ! m_PrematureCountDown )
2008-10-05 08:48:32 -05:00
{
m_PrematureCountDown = true ;
2010-08-08 04:37:24 +02:00
m_PrematureCountDownTimer = sBattlegroundMgr . GetPrematureFinishTime ();
2008-10-05 08:48:32 -05:00
}
2009-04-08 16:33:46 -05:00
else if ( m_PrematureCountDownTimer < diff )
2008-10-05 08:48:32 -05:00
{
// time's up!
2009-03-09 18:14:06 -06:00
uint32 winner = 0 ;
2009-04-08 16:33:46 -05:00
if ( GetPlayersCountByTeam ( ALLIANCE ) >= GetMinPlayersPerTeam ())
2009-03-09 18:14:06 -06:00
winner = ALLIANCE ;
2009-04-08 16:33:46 -05:00
else if ( GetPlayersCountByTeam ( HORDE ) >= GetMinPlayersPerTeam ())
2009-03-09 18:14:06 -06:00
winner = HORDE ;
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
EndBattleground ( winner );
2008-10-05 08:48:32 -05:00
m_PrematureCountDown = false ;
2008-12-19 16:05:13 -06:00
}
2010-08-08 04:37:24 +02:00
else if ( ! sBattlegroundMgr . isTesting ())
2008-10-05 08:48:32 -05:00
{
uint32 newtime = m_PrematureCountDownTimer - diff ;
// announce every minute
2010-07-12 00:30:17 +02:00
if ( newtime > ( MINUTE * IN_MILLISECONDS ))
2009-03-06 15:25:20 -06:00
{
2010-07-12 00:30:17 +02: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 )));
2009-03-06 15:25:20 -06:00
}
else
{
//announce every 15 seconds
2010-07-12 00:30:17 +02:00
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 ));
2009-03-06 15:25:20 -06:00
}
2008-10-05 08:48:32 -05:00
m_PrematureCountDownTimer = newtime ;
}
}
else if ( m_PrematureCountDown )
m_PrematureCountDown = false ;
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
/*********************************************************/
/*** BATTLEGROUND STARTING SYSTEM ***/
/*********************************************************/
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
if ( GetStatus () == STATUS_WAIT_JOIN && GetPlayersSize ())
{
ModifyStartDelayTime ( diff );
2009-10-17 15:51:44 -07:00
2010-12-02 22:50:30 +01:00
if ( m_ResetStatTimer <= 5000 )
{
m_ResetStatTimer = 0 ;
for ( BattlegroundPlayerMap :: const_iterator itr = GetPlayers (). begin (); itr != GetPlayers (). end (); ++ itr )
if ( Player * plr = sObjectMgr . GetPlayer ( itr -> first ))
plr -> ResetAllPowers ();
}
2009-03-07 12:05:30 -06:00
if ( ! ( m_Events & BG_STARTING_EVENT_1 ))
{
m_Events |= BG_STARTING_EVENT_1 ;
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
// setup here, only when at least one player has ported to the map
2010-08-08 04:37:24 +02:00
if ( ! SetupBattleground ())
2009-03-07 12:05:30 -06:00
{
EndNow ();
return ;
}
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
StartingEventCloseDoors ();
SetStartDelayTime ( m_StartDelayTimes [ BG_STARTING_EVENT_FIRST ]);
//first start warning - 2 or 1 minute
SendMessageToAll ( m_StartMessageIds [ BG_STARTING_EVENT_FIRST ], CHAT_MSG_BG_SYSTEM_NEUTRAL );
}
// After 1 minute or 30 seconds, warning is signalled
else if ( GetStartDelayTime () <= m_StartDelayTimes [ BG_STARTING_EVENT_SECOND ] && ! ( m_Events & BG_STARTING_EVENT_2 ))
{
m_Events |= BG_STARTING_EVENT_2 ;
SendMessageToAll ( m_StartMessageIds [ BG_STARTING_EVENT_SECOND ], CHAT_MSG_BG_SYSTEM_NEUTRAL );
}
// After 30 or 15 seconds, warning is signalled
else if ( GetStartDelayTime () <= m_StartDelayTimes [ BG_STARTING_EVENT_THIRD ] && ! ( m_Events & BG_STARTING_EVENT_3 ))
{
m_Events |= BG_STARTING_EVENT_3 ;
SendMessageToAll ( m_StartMessageIds [ BG_STARTING_EVENT_THIRD ], CHAT_MSG_BG_SYSTEM_NEUTRAL );
}
// delay expired (atfer 2 or 1 minute)
else if ( GetStartDelayTime () <= 0 && ! ( m_Events & BG_STARTING_EVENT_4 ))
{
m_Events |= BG_STARTING_EVENT_4 ;
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
StartingEventOpenDoors ();
2009-10-17 15:51:44 -07:00
2010-06-01 23:55:09 +02:00
SendWarningToAll ( m_StartMessageIds [ BG_STARTING_EVENT_FOURTH ]);
2009-03-07 12:05:30 -06:00
SetStatus ( STATUS_IN_PROGRESS );
SetStartDelayTime ( m_StartDelayTimes [ BG_STARTING_EVENT_FOURTH ]);
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
//remove preparation
2009-04-08 16:33:46 -05:00
if ( isArena ())
2009-03-07 12:05:30 -06:00
{
2009-03-09 16:36:58 -06:00
//TODO : add arena sound PlaySoundToAll(SOUND_ARENA_START);
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = GetPlayers (). begin (); itr != GetPlayers (). end (); ++ itr )
2010-08-08 05:25:45 +02:00
if ( Player * plr = sObjectMgr . GetPlayer ( itr -> first ))
2009-05-24 22:54:13 +02:00
{
2010-08-27 04:49:04 +03:00
// BG Status packet
WorldPacket status ;
2010-08-27 04:55:49 +03:00
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr . BGQueueTypeId ( m_TypeID , GetArenaType ());
2010-08-27 04:49:04 +03:00
uint32 queueSlot = plr -> GetBattlegroundQueueIndex ( bgQueueTypeId );
sBattlegroundMgr . BuildBattlegroundStatusPacket ( & status , this , queueSlot , STATUS_IN_PROGRESS , 0 , GetStartTime (), GetArenaType ());
plr -> GetSession () -> SendPacket ( & status );
2009-03-07 12:05:30 -06:00
plr -> RemoveAurasDueToSpell ( SPELL_ARENA_PREPARATION );
2010-12-02 22:50:30 +01:00
plr -> ResetAllPowers ();
2009-05-24 22:54:13 +02:00
// remove auras with duration lower than 30s
2010-01-10 20:09:44 +01:00
Unit :: AuraApplicationMap & auraMap = plr -> GetAppliedAuras ();
for ( Unit :: AuraApplicationMap :: iterator iter = auraMap . begin (); iter != auraMap . end ();)
2009-05-24 22:54:13 +02:00
{
2010-01-10 20:09:44 +01:00
AuraApplication * aurApp = iter -> second ;
Aura * aura = aurApp -> GetBase ();
2010-01-10 01:23:15 +01:00
if ( ! aura -> IsPermanent ()
2010-07-12 00:30:17 +02:00
&& aura -> GetDuration () <= 30 * IN_MILLISECONDS
2010-01-10 20:09:44 +01:00
&& aurApp -> IsPositive ()
2010-01-10 01:23:15 +01:00
&& ( ! ( aura -> GetSpellProto () -> Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY ))
&& ( ! aura -> HasEffectType ( SPELL_AURA_MOD_INVISIBILITY )))
2010-01-10 20:09:44 +01:00
plr -> RemoveAura ( iter );
2009-05-24 22:54:13 +02:00
else
++ iter ;
}
}
2009-10-17 15:51:44 -07:00
2009-03-09 16:36:58 -06:00
CheckArenaWinConditions ();
2009-03-07 12:05:30 -06:00
}
else
{
PlaySoundToAll ( SOUND_BG_START );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = GetPlayers (). begin (); itr != GetPlayers (). end (); ++ itr )
2010-08-08 05:25:45 +02:00
if ( Player * plr = sObjectMgr . GetPlayer ( itr -> first ))
2010-12-02 22:50:30 +01:00
{
2009-03-07 12:05:30 -06:00
plr -> RemoveAurasDueToSpell ( SPELL_PREPARATION );
2010-12-02 22:50:30 +01:00
plr -> ResetAllPowers ();
}
2009-03-09 16:36:58 -06:00
//Announce BG starting
2010-08-23 19:56:47 -07:00
if ( sWorld . getBoolConfig ( CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE ))
2009-03-07 12:05:30 -06:00
{
sWorld . SendWorldText ( LANG_BG_STARTED_ANNOUNCE_WORLD , GetName (), GetMinLevel (), GetMaxLevel ());
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-03-07 12:05:30 -06:00
/*********************************************************/
/*** BATTLEGROUND ENDING SYSTEM ***/
/*********************************************************/
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( GetStatus () == STATUS_WAIT_LEAVE )
2008-10-02 16:23:55 -05:00
{
// remove all players from battleground after 2 minutes
2009-03-13 18:06:36 -06:00
m_EndTime -= diff ;
2009-04-08 16:33:46 -05:00
if ( m_EndTime <= 0 )
2008-10-02 16:23:55 -05:00
{
2009-03-13 18:06:36 -06:00
m_EndTime = 0 ;
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: iterator itr , next ;
2009-10-17 16:20:24 -07:00
for ( itr = m_Players . begin (); itr != m_Players . end (); itr = next )
2009-03-09 17:58:04 -06:00
{
next = itr ;
++ next ;
//itr is erased here!
2009-03-09 17:07:40 -06:00
RemovePlayerAtLeave ( itr -> first , true , true ); // remove player from BG
2009-03-09 17:58:04 -06:00
// do not change any battleground's private variables
}
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-12-02 22:50:30 +01:00
// Update start time and reset stats timer
2009-03-13 18:06:36 -06:00
m_StartTime += diff ;
2010-12-02 22:50:30 +01:00
m_ResetStatTimer += diff ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SetTeamStartLoc ( uint32 TeamID , float X , float Y , float Z , float O )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundTeamId idx = GetTeamIndexByTeamId ( TeamID );
2008-10-02 16:23:55 -05:00
m_TeamStartLocX [ idx ] = X ;
m_TeamStartLocY [ idx ] = Y ;
m_TeamStartLocZ [ idx ] = Z ;
m_TeamStartLocO [ idx ] = O ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendPacketToAll ( WorldPacket * packet )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
continue ;
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-04-08 16:33:46 -05:00
if ( plr )
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( packet );
else
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:SendPacketToAll: Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendPacketToTeam ( uint32 TeamID , WorldPacket * packet , Player * sender , bool self )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
continue ;
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:SendPacketToTeam: Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2008-10-02 16:23:55 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! self && sender == plr )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
uint32 team = itr -> second . Team ;
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( team == TeamID )
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( packet );
}
}
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-08-08 04:37:24 +02: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 ;
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
{
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
continue ;
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:PlaySoundToTeam: Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2008-10-02 16:23:55 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
uint32 team = itr -> second . Team ;
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( team == TeamID )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildPlaySoundPacket ( & data , SoundID );
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( & data );
}
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
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 )
2008-10-02 16:23:55 -05:00
{
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
continue ;
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:CastSpellOnTeam: Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2008-10-02 16:23:55 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
uint32 team = itr -> second . Team ;
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( team == TeamID )
2008-10-02 16:23:55 -05:00
plr -> CastSpell ( plr , SpellID , true );
}
}
2009-10-17 15:51:44 -07: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
{
2010-08-08 04:37:24 +02:00
for ( std :: map < uint64 , BattlegroundPlayer >:: iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-11-21 19:45:49 -06:00
{
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2010-04-07 19:14:10 +02:00
if ( ! plr )
2008-11-21 19:45:49 -06:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground: Player " UI64FMTD " not found!" , itr -> first );
2008-11-21 19:45:49 -06:00
continue ;
}
creature -> BuildMonsterChat ( & data , CHAT_MSG_MONSTER_YELL , text , language , creature -> GetName (), itr -> first );
plr -> GetSession () -> SendPacket ( & data );
}
}
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 )
2008-10-02 16:23:55 -05:00
{
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
continue ;
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:RewardHonorToTeam: Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2008-10-02 16:23:55 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
uint32 team = itr -> second . Team ;
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( team == TeamID )
2008-10-02 16:23:55 -05:00
UpdatePlayerScore ( plr , SCORE_BONUS_HONOR , Honor );
}
}
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
{
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( faction_id );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! factionEntry )
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
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
continue ;
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:RewardReputationToTeam: Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2008-10-02 16:23:55 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
uint32 team = itr -> second . Team ;
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( team == TeamID )
2009-03-26 13:53:32 -06:00
plr -> 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-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildUpdateWorldStatePacket ( & data , Field , Value );
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 :: UpdateWorldStateForPlayer ( uint32 Field , uint32 Value , Player * Source )
2008-10-02 16:23:55 -05:00
{
WorldPacket data ;
2010-08-08 04:37:24 +02: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
{
2008-10-05 08:48:32 -05:00
this -> RemoveFromBGFreeSlotQueue ();
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
ArenaTeam * winner_arena_team = NULL ;
ArenaTeam * loser_arena_team = NULL ;
2010-08-27 18:18:26 +02:00
uint32 loser_team_rating = 0 ;
uint32 loser_matchmaker_rating = 0 ;
2010-09-10 23:08:49 +02:00
int32 loser_change = 0 ;
2010-08-27 18:18:26 +02:00
uint32 winner_team_rating = 0 ;
uint32 winner_matchmaker_rating = 0 ;
2010-09-10 23:08:49 +02:00
int32 winner_change = 0 ;
2008-10-02 16:23:55 -05:00
WorldPacket data ;
2009-03-09 17:00:31 -06:00
int32 winmsg_id = 0 ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( winner == ALLIANCE )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
winmsg_id = isBattleground () ? LANG_BG_A_WINS : LANG_ARENA_GOLD_WINS ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
PlaySoundToAll ( SOUND_ALLIANCE_WINS ); // alliance wins sound
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SetWinner ( WINNER_ALLIANCE );
}
2009-04-08 16:33:46 -05:00
else if ( winner == HORDE )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
winmsg_id = isBattleground () ? LANG_BG_H_WINS : LANG_ARENA_GREEN_WINS ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
PlaySoundToAll ( SOUND_HORDE_WINS ); // horde wins sound
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SetWinner ( WINNER_HORDE );
}
2008-10-05 08:48:32 -05:00
else
{
SetWinner ( 3 );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
SetStatus ( STATUS_WAIT_LEAVE );
2009-03-13 18:06:36 -06:00
//we must set it this way, because end time is sent in packet!
m_EndTime = TIME_TO_AUTOREMOVE ;
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// arena rating calculation
2009-04-08 16:33:46 -05:00
if ( isArena () && isRated ())
2008-10-05 08:48:32 -05:00
{
2010-08-08 05:25:45 +02:00
winner_arena_team = sObjectMgr . GetArenaTeamById ( GetArenaTeamIdForTeam ( winner ));
loser_arena_team = sObjectMgr . GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( winner )));
2010-12-03 23:14:38 +01:00
if ( winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2008-10-05 08:48:32 -05:00
{
2010-12-03 23:14:38 +01:00
if ( winner != WINNER_NONE )
{
loser_team_rating = loser_arena_team -> GetRating ();
loser_matchmaker_rating = GetArenaMatchmakerRating ( GetOtherTeam ( winner ));
winner_team_rating = winner_arena_team -> GetRating ();
winner_matchmaker_rating = GetArenaMatchmakerRating ( winner );
winner_change = winner_arena_team -> WonAgainst ( loser_matchmaker_rating );
loser_change = loser_arena_team -> LostAgainst ( winner_matchmaker_rating );
sLog . outDebug ( "--- Winner rating: %u, Loser rating: %u, Winner MMR: %u, Loser MMR: %u, Winner change: %u, Losser change: %u ---" , winner_team_rating , loser_team_rating ,
winner_matchmaker_rating , loser_matchmaker_rating , winner_change , loser_change );
SetArenaTeamRatingChangeForTeam ( winner , winner_change );
SetArenaTeamRatingChangeForTeam ( GetOtherTeam ( winner ), loser_change );
sLog . outArena ( "Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. 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 ))
for ( Battleground :: BattlegroundScoreMap :: const_iterator itr = GetPlayerScoresBegin (); itr != GetPlayerScoresEnd (); itr ++ )
if ( Player * player = sObjectMgr . GetPlayer ( itr -> first ))
sLog . outArena ( "Statistics for %s (GUID: " UI64FMTD ", Team: %d, IP: %s): %u damage, %u healing, %u killing blows" , player -> GetName (), itr -> first , player -> GetArenaTeamId ( m_ArenaType == 5 ? 2 : m_ArenaType == 3 ), player -> GetSession () -> GetRemoteAddress (). c_str (), itr -> second -> DamageDone , itr -> second -> HealingDone , itr -> second -> KillingBlows );
}
// Deduct 16 points from each teams arena-rating if there are no winners after 45+2 minutes
else
{
SetArenaTeamRatingChangeForTeam ( ALLIANCE , ARENA_TIMELIMIT_POINTS_LOSS );
SetArenaTeamRatingChangeForTeam ( HORDE , ARENA_TIMELIMIT_POINTS_LOSS );
winner_arena_team -> FinishGame ( ARENA_TIMELIMIT_POINTS_LOSS );
loser_arena_team -> FinishGame ( ARENA_TIMELIMIT_POINTS_LOSS );
}
2010-12-02 22:25:32 +01:00
}
2008-10-05 08:48:32 -05:00
else
{
SetArenaTeamRatingChangeForTeam ( ALLIANCE , 0 );
SetArenaTeamRatingChangeForTeam ( HORDE , 0 );
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
uint32 team = itr -> second . Team ;
2009-10-17 15:51:44 -07:00
2010-02-15 15:31:27 +01:00
if ( itr -> second . OfflineRemoveTime )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
//if rated arena match - make member lost!
2009-06-16 12:25:18 -05:00
if ( isArena () && isRated () && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2009-03-09 17:07:40 -06:00
{
2009-04-08 16:33:46 -05:00
if ( team == winner )
2010-09-10 23:08:49 +02:00
winner_arena_team -> OfflineMemberLost ( itr -> first , loser_matchmaker_rating , winner_change );
2009-03-09 17:07:40 -06:00
else
2010-09-10 23:08:49 +02:00
loser_arena_team -> OfflineMemberLost ( itr -> first , winner_matchmaker_rating , loser_change );
2009-03-09 17:07:40 -06:00
}
2008-10-02 16:23:55 -05:00
continue ;
}
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2010-02-15 15:31:27 +01:00
if ( ! plr )
2010-02-25 00:26:47 +01:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground:EndBattleground Player (GUID: %u) not found!" , GUID_LOPART ( itr -> first ));
2010-02-25 00:26:47 +01:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// should remove spirit of redemption
2010-04-07 19:14:10 +02:00
if ( plr -> HasAuraType ( SPELL_AURA_SPIRIT_OF_REDEMPTION ))
2009-04-06 13:31:14 +02:00
plr -> RemoveAurasByType ( SPELL_AURA_MOD_SHAPESHIFT );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr -> isAlive ())
2008-10-02 16:23:55 -05:00
{
plr -> ResurrectPlayer ( 1.0f );
plr -> SpawnCorpseBones ();
2010-02-25 00:26:47 +01:00
}
else
2009-08-14 22:09:06 +02:00
{
//needed cause else in av some creatures will kill the players at the end
plr -> CombatStop ();
2010-03-09 11:11:10 +01:00
plr -> getHostileRefManager (). deleteReferences ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:07:40 -06:00
//this line is obsolete - team is set ALWAYS
2010-04-07 19:14:10 +02:00
//if (!team) team = plr->GetTeam();
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// per player calculation
2009-06-16 12:25:18 -05:00
if ( isArena () && isRated () && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2008-10-05 08:48:32 -05:00
{
2009-04-08 16:33:46 -05:00
if ( team == winner )
2009-06-01 21:51:34 -05:00
{
// update achievement BEFORE personal rating update
2009-06-14 10:02:20 -05:00
ArenaTeamMember * member = winner_arena_team -> GetMember ( plr -> GetGUID ());
if ( member )
plr -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA , member -> personal_rating );
2009-10-17 15:51:44 -07:00
2010-09-10 23:08:49 +02:00
winner_arena_team -> MemberWon ( plr , loser_matchmaker_rating , winner_change );
2009-06-01 21:51:34 -05:00
}
2008-10-05 08:48:32 -05:00
else
2009-06-01 21:51:34 -05:00
{
2010-09-10 23:08:49 +02:00
loser_arena_team -> MemberLost ( plr , winner_matchmaker_rating , loser_change );
2009-10-17 15:51:44 -07:00
2010-11-14 23:46:34 +02:00
// Arena lost => reset the win_rated_arena having the "no_lose" condition
2010-09-28 08:21:51 +03:00
plr -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA , ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE );
2009-06-01 21:51:34 -05:00
}
2008-10-05 08:48:32 -05:00
}
2009-10-17 15:51:44 -07:00
2010-11-14 23:46:34 +02:00
uint32 winner_kills = plr -> GetRandomWinner () ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST ;
uint32 loser_kills = plr -> GetRandomWinner () ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST ;
uint32 winner_arena = plr -> GetRandomWinner () ? BG_REWARD_WINNER_ARENA_LAST : BG_REWARD_WINNER_ARENA_FIRST ;
2010-05-26 11:34:37 +02:00
2010-05-04 17:30:50 +02:00
// Reward winner team
2009-04-08 16:33:46 -05:00
if ( team == winner )
2010-05-26 11:34:37 +02:00
{
2010-08-08 04:37:24 +02:00
if ( IsRandom () || BattlegroundMgr :: IsBGWeekend ( GetTypeID ()))
2010-05-26 11:34:37 +02:00
{
2010-11-14 23:46:34 +02:00
UpdatePlayerScore ( plr , SCORE_BONUS_HONOR , GetBonusHonorFromKill ( winner_kills ));
2010-08-07 01:58:23 +06:00
if ( CanAwardArenaPoints ())
2010-11-14 23:46:34 +02:00
plr -> ModifyArenaPoints ( winner_arena );
2010-05-26 11:34:37 +02:00
if ( ! plr -> GetRandomWinner ())
plr -> SetRandomWinner ( true );
}
2009-07-22 23:51:39 +02:00
plr -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_WIN_BG , 1 );
2010-05-26 11:34:37 +02:00
}
else
{
2010-08-08 04:37:24 +02:00
if ( IsRandom () || BattlegroundMgr :: IsBGWeekend ( GetTypeID ()))
2010-11-14 23:46:34 +02:00
UpdatePlayerScore ( plr , SCORE_BONUS_HONOR , GetBonusHonorFromKill ( loser_kills ));
2010-08-08 19:45:53 +02:00
}
2010-05-26 11:34:37 +02:00
2009-10-17 15:51:44 -07:00
2010-12-02 22:50:30 +01:00
plr -> ResetAllPowers ();
2008-10-02 16:23:55 -05:00
plr -> CombatStopWithPets ( true );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
BlockMovement ( plr );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildPvpLogDataPacket ( & data , this );
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( & data );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr :: BGQueueTypeId ( GetTypeID (), GetArenaType ());
sBattlegroundMgr . BuildBattlegroundStatusPacket ( & data , this , plr -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_IN_PROGRESS , TIME_TO_AUTOREMOVE , GetStartTime (), GetArenaType ());
2008-10-02 16:23:55 -05:00
plr -> GetSession () -> SendPacket ( & data );
2008-12-24 09:58:26 -06:00
plr -> GetAchievementMgr (). UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND , 1 );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-16 12:25:18 -05:00
if ( isArena () && isRated () && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2008-10-05 08:48:32 -05:00
{
// update arena points only after increasing the player's match count!
2008-12-19 16:05:13 -06:00
//obsolete: winner_arena_team->UpdateArenaPointsHelper();
//obsolete: loser_arena_team->UpdateArenaPointsHelper();
2008-10-05 08:48:32 -05:00
// save the stat changes
winner_arena_team -> SaveToDB ();
loser_arena_team -> SaveToDB ();
// send updated arena team stats to players
// this way all arena team members will get notified, not only the ones who participated in this match
winner_arena_team -> NotifyStatsChanged ();
loser_arena_team -> NotifyStatsChanged ();
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( winmsg_id )
2009-03-09 18:14:06 -06:00
SendMessageToAll ( winmsg_id , CHAT_MSG_BG_SYSTEM_NEUTRAL );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetBonusHonorFromKill ( uint32 kills ) const
2009-03-09 18:14:06 -06:00
{
//variable kills means how many honorable kills you scored (so we need kills * honor_for_one_kill)
2010-06-25 15:58:27 +02:00
uint32 maxLevel = ( GetMaxLevel () < 80 ) ? GetMaxLevel () : 80 ;
2010-06-03 16:24:10 +02:00
return Trinity :: Honor :: hk_honor_at_level ( maxLevel , kills );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetBattlemasterEntry () const
2008-10-02 16:23:55 -05:00
{
2010-05-26 11:34:37 +02:00
switch ( GetTypeID ( true ))
2008-10-02 16:23:55 -05:00
{
case BATTLEGROUND_AV : return 15972 ;
case BATTLEGROUND_WS : return 14623 ;
case BATTLEGROUND_AB : return 14879 ;
case BATTLEGROUND_EY : return 22516 ;
case BATTLEGROUND_NA : return 20200 ;
default : return 0 ;
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: BlockMovement ( Player * plr )
2008-10-02 16:23:55 -05:00
{
plr -> SetClientControl ( plr , 0 ); // movement disabled NOTE: the effect will be automatically removed by client when the player is teleported from the battleground, so no need to send with uint8(1) in RemovePlayerAtLeave()
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +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 );
bool participant = false ;
2008-10-02 16:23:55 -05:00
// Remove from lists/maps
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: iterator itr = m_Players . find ( guid );
2009-04-08 16:33:46 -05:00
if ( itr != m_Players . end ())
2008-10-02 16:23:55 -05:00
{
2009-03-09 18:14:06 -06:00
UpdatePlayersCountByTeam ( team , true ); // -1 player
2008-10-02 16:23:55 -05:00
m_Players . erase ( itr );
2008-10-05 08:48:32 -05:00
// check if the player was a participant of the match, or only entered through gm command (goname)
participant = true ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundScoreMap :: iterator itr2 = m_PlayerScores . find ( guid );
2009-04-08 16:33:46 -05:00
if ( itr2 != m_PlayerScores . end ())
2008-10-02 16:23:55 -05:00
{
delete itr2 -> second ; // delete player's score
m_PlayerScores . erase ( itr2 );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
RemovePlayerFromResurrectQueue ( guid );
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( guid );
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// should remove spirit of redemption
2010-04-07 19:14:10 +02:00
if ( plr && plr -> HasAuraType ( SPELL_AURA_SPIRIT_OF_REDEMPTION ))
2009-04-06 13:31:14 +02:00
plr -> RemoveAurasByType ( SPELL_AURA_MOD_SHAPESHIFT );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( plr && ! plr -> isAlive ()) // resurrect on exit
2008-10-02 16:23:55 -05:00
{
plr -> ResurrectPlayer ( 1.0f );
plr -> SpawnCorpseBones ();
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
RemovePlayer ( plr , guid ); // BG subclass specific code
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( participant ) // if the player was a match participant, remove auras, calc rating, update queue
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
BattlegroundTypeId bgTypeId = GetTypeID ();
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr :: BGQueueTypeId ( GetTypeID (), GetArenaType ());
2009-04-08 16:33:46 -05:00
if ( plr )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
plr -> ClearAfkReports ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! team ) team = plr -> GetTeam ();
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// if arena, remove the specific arena auras
2009-04-08 16:33:46 -05:00
if ( isArena ())
2008-10-05 08:48:32 -05:00
{
2009-03-09 18:14:06 -06:00
plr -> RemoveArenaAuras ( true ); // removes debuffs / dots etc., we don't want the player to die after porting out
bgTypeId = BATTLEGROUND_AA ; // set the bg type to all arenas (it will be used for queue refreshing)
2009-10-17 15:51:44 -07:00
2009-04-11 14:47:38 -05:00
// unsummon current and summon old pet if there was one and there isn't a current pet
plr -> RemovePet ( NULL , PET_SAVE_NOT_IN_SLOT );
plr -> ResummonPetTemporaryUnSummonedIfAny ();
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( isRated () && GetStatus () == STATUS_IN_PROGRESS )
2008-10-05 08:48:32 -05:00
{
//left a rated match while the encounter was in progress, consider as loser
2010-08-08 05:25:45 +02:00
ArenaTeam * winner_arena_team = sObjectMgr . GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( team )));
ArenaTeam * loser_arena_team = sObjectMgr . GetArenaTeamById ( GetArenaTeamIdForTeam ( team ));
2009-06-16 12:25:18 -05:00
if ( winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team )
2010-09-12 18:41:47 +02:00
loser_arena_team -> MemberLost ( plr , GetArenaMatchmakerRating ( GetOtherTeam ( team )));
2008-10-05 08:48:32 -05:00
}
}
2009-04-08 16:33:46 -05:00
if ( SendPacket )
2008-10-05 08:48:32 -05:00
{
2009-03-09 17:07:40 -06:00
WorldPacket data ;
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildBattlegroundStatusPacket ( & data , this , plr -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_NONE , 0 , 0 , 0 );
2008-10-05 08:48:32 -05:00
plr -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2008-10-05 08:48:32 -05:00
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
2010-08-08 04:37:24 +02:00
plr -> RemoveBattlegroundQueueId ( bgQueueTypeId );
2009-03-09 17:07:40 -06:00
}
else
// removing offline participant
{
2009-04-08 16:33:46 -05:00
if ( isRated () && GetStatus () == STATUS_IN_PROGRESS )
2008-10-02 16:23:55 -05:00
{
2009-03-09 17:07:40 -06:00
//left a rated match while the encounter was in progress, consider as loser
2010-08-08 05:25:45 +02:00
ArenaTeam * others_arena_team = sObjectMgr . GetArenaTeamById ( GetArenaTeamIdForTeam ( GetOtherTeam ( team )));
ArenaTeam * players_arena_team = sObjectMgr . GetArenaTeamById ( GetArenaTeamIdForTeam ( team ));
2009-04-08 16:33:46 -05:00
if ( others_arena_team && players_arena_team )
2010-09-12 18:41:47 +02:00
players_arena_team -> OfflineMemberLost ( guid , GetArenaMatchmakerRating ( GetOtherTeam ( team )));
2008-10-02 16:23:55 -05:00
}
2009-03-09 17:07:40 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:07:40 -06:00
// remove from raid group if player is member
2009-04-08 16:33:46 -05:00
if ( Group * group = GetBgRaid ( team ))
2009-03-09 17:07:40 -06:00
{
2010-09-10 13:37:55 +02:00
if ( ! group -> RemoveMember ( guid )) // group was disbanded
2009-03-09 17:07:40 -06:00
{
SetBgRaid ( team , NULL );
delete group ;
}
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-08-08 04:37:24 +02: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-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildPlayerLeftBattlegroundPacket ( & data , guid );
2009-03-09 17:07:40 -06:00
SendPacketToTeam ( team , & data , plr , false );
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( plr )
2009-03-09 17:07:40 -06:00
{
2008-10-02 16:23:55 -05:00
// Do next only if found in battleground
2010-08-08 04:37:24 +02:00
plr -> SetBattlegroundId ( 0 , BATTLEGROUND_TYPE_NONE ); // We're not in BG.
2008-10-05 08:48:32 -05:00
// reset destination bg team
plr -> SetBGTeam ( 0 );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( Transport )
2009-08-12 20:27:00 -05:00
plr -> TeleportToBGEntryPoint ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
sLog . outDetail ( "BATTLEGROUND: Removed player %s from Battleground." , plr -> GetName ());
2010-08-07 18:31:06 +02:00
plr -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE , ACHIEVEMENT_CRITERIA_CONDITION_MAP , GetMapId (), true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
//battleground object will be deleted next Battleground::Update() call
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// this method is called when no players remains in battleground
2010-08-08 04:37:24 +02:00
void Battleground :: Reset ()
2008-10-02 16:23:55 -05:00
{
SetWinner ( WINNER_NONE );
SetStatus ( STATUS_WAIT_QUEUE );
SetStartTime ( 0 );
SetEndTime ( 0 );
SetLastResurrectTime ( 0 );
2008-10-05 08:48:32 -05:00
SetArenaType ( 0 );
SetRated ( false );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_Events = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
if ( m_InvitedAlliance > 0 || m_InvitedHorde > 0 )
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground system: bad counter, m_InvitedAlliance: %d, m_InvitedHorde: %d" , m_InvitedAlliance , m_InvitedHorde );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_InvitedAlliance = 0 ;
m_InvitedHorde = 0 ;
2008-10-05 08:48:32 -05:00
m_InBGFreeSlotQueue = false ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
m_Players . clear ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
for ( BattlegroundScoreMap :: const_iterator itr = m_PlayerScores . begin (); itr != m_PlayerScores . end (); ++ itr )
2009-08-06 17:45:37 -05:00
delete itr -> second ;
2008-10-02 16:23:55 -05:00
m_PlayerScores . clear ();
2009-10-17 15:51:44 -07:00
2009-08-04 23:16:44 +02:00
ResetBGSubclass ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: StartBattleground ()
2008-10-02 16:23:55 -05:00
{
SetStartTime ( 0 );
SetLastResurrectTime ( 0 );
2009-09-11 16:25:11 -07:00
// add BG to free slot queue
AddToBGFreeSlotQueue ();
2009-10-17 15:51:44 -07:00
2009-09-11 16:25:11 -07:00
// add bg to update list
// This must be done here, because we need to have already invited some players when first BG::Update() method is executed
2010-08-08 04:37:24 +02:00
// and it doesn't matter if we call StartBattleground() more times, because m_Battlegrounds is a map and instance id never changes
sBattlegroundMgr . AddBattleground ( GetInstanceID (), GetTypeID (), this );
2010-04-07 19:14:10 +02:00
if ( m_IsRated )
2009-06-01 20:44:23 +02: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
2010-08-08 04:37:24 +02:00
void Battleground :: AddPlayer ( Player * plr )
2008-10-02 16:23:55 -05:00
{
2009-08-27 20:28:28 -05:00
// remove afk from player
if ( plr -> HasFlag ( PLAYER_FLAGS , PLAYER_FLAGS_AFK ))
plr -> ToggleAFK ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// score struct must be created in inherited class
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint64 guid = plr -> GetGUID ();
uint32 team = plr -> GetBGTeam ();
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
BattlegroundPlayer bp ;
2009-03-09 17:07:12 -06:00
bp . OfflineRemoveTime = 0 ;
2008-10-02 16:23:55 -05:00
bp . Team = team ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// Add to list/maps
m_Players [ guid ] = bp ;
2009-10-17 15:51:44 -07:00
2008-12-19 16:05:13 -06:00
UpdatePlayersCountByTeam ( team , false ); // +1 player
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
WorldPacket data ;
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildPlayerJoinedBattlegroundPacket ( & data , plr );
2008-10-02 16:23:55 -05:00
SendPacketToTeam ( team , & data , plr , false );
2009-10-17 15:51:44 -07:00
2010-01-14 11:22:52 +01:00
// BG Status packet
WorldPacket status ;
2010-08-27 04:49:04 +03:00
BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr . BGQueueTypeId ( m_TypeID , GetArenaType ());
2010-08-08 04:37:24 +02:00
uint32 queueSlot = plr -> GetBattlegroundQueueIndex ( bgQueueTypeId );
2010-08-27 04:49:04 +03:00
sBattlegroundMgr . BuildBattlegroundStatusPacket ( & status , this , queueSlot , STATUS_IN_PROGRESS , 0 , GetStartTime (), GetArenaType (), isArena () ? 0 : 1 );
2010-01-14 11:22:52 +01:00
plr -> GetSession () -> SendPacket ( & status );
2010-06-03 16:24:10 +02:00
plr -> RemoveAurasByType ( SPELL_AURA_MOUNTED );
2008-10-05 08:48:32 -05:00
// add arena specific auras
2009-04-08 16:33:46 -05:00
if ( isArena ())
2008-10-02 16:23:55 -05:00
{
2009-05-24 22:54:13 +02:00
plr -> RemoveArenaEnchantments ( TEMP_ENCHANTMENT_SLOT );
2010-04-07 19:14:10 +02:00
if ( team == ALLIANCE ) // gold
2008-11-30 12:47:26 -06:00
{
2009-04-08 16:33:46 -05:00
if ( plr -> GetTeam () == HORDE )
2008-11-30 12:47:26 -06:00
plr -> CastSpell ( plr , SPELL_HORDE_GOLD_FLAG , true );
else
plr -> CastSpell ( plr , SPELL_ALLIANCE_GOLD_FLAG , true );
}
else // green
{
2009-04-08 16:33:46 -05:00
if ( plr -> GetTeam () == HORDE )
2008-11-30 12:47:26 -06:00
plr -> CastSpell ( plr , SPELL_HORDE_GREEN_FLAG , true );
else
plr -> CastSpell ( plr , SPELL_ALLIANCE_GREEN_FLAG , true );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
plr -> DestroyConjuredItems ( true );
2009-04-11 14:47:38 -05:00
plr -> UnsummonPetTemporaryIfAny ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetStatus () == STATUS_WAIT_JOIN ) // not started yet
2008-10-02 16:23:55 -05:00
{
2009-03-12 13:59:03 +01:00
plr -> CastSpell ( plr , SPELL_ARENA_PREPARATION , true );
2010-12-02 22:50:30 +01:00
plr -> ResetAllPowers ();
2008-10-02 16:23:55 -05:00
}
2010-08-27 04:49:04 +03:00
WorldPacket teammate ;
teammate . Initialize ( SMSG_ARENA_OPPONENT_UPDATE , 8 );
teammate << uint64 ( plr -> GetGUID ());
SendPacketToTeam ( team , & teammate , plr , false );
2008-10-02 16:23:55 -05:00
}
else
{
2010-04-07 19:14:10 +02:00
if ( GetStatus () == STATUS_WAIT_JOIN ) // not started yet
2008-10-02 16:23:55 -05:00
plr -> CastSpell ( plr , SPELL_PREPARATION , true ); // reduces all mana cost of spells.
}
2009-10-17 15:51:44 -07:00
2009-04-23 22:07:37 -05:00
plr -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE , ACHIEVEMENT_CRITERIA_CONDITION_MAP , GetMapId ());
plr -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE , ACHIEVEMENT_CRITERIA_CONDITION_MAP , GetMapId ());
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
// setup BG group membership
2009-03-09 17:07:12 -06:00
PlayerAddedToBGCheckIfBGIsRunning ( plr );
2009-02-13 20:10:14 -06:00
AddOrSetPlayerToCorrectBgGroup ( plr , guid , team );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// Log
sLog . outDetail ( "BATTLEGROUND: Player %s joined the battle." , plr -> GetName ());
}
2009-10-17 15:51:44 -07:00
2009-02-13 20:10:14 -06:00
/* this method adds player to his team's bg group, or sets his correct group if player is already in bg group */
2010-08-08 04:37:24 +02:00
void Battleground :: AddOrSetPlayerToCorrectBgGroup ( Player * plr , uint64 plr_guid , uint32 team )
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 );
group -> Create ( plr_guid , plr -> GetName ());
}
else // raid already exist
{
2009-04-08 16:33:46 -05:00
if ( group -> IsMember ( plr_guid ))
2009-02-13 20:10:14 -06:00
{
uint8 subgroup = group -> GetMemberGroup ( plr_guid );
2010-08-08 04:37:24 +02:00
plr -> SetBattlegroundRaid ( group , subgroup );
2009-02-13 20:10:14 -06:00
}
else
2009-03-14 20:06:00 -06:00
{
group -> AddMember ( plr_guid , plr -> GetName ());
2009-04-08 16:33:46 -05:00
if ( Group * originalGroup = plr -> GetOriginalGroup ())
if ( originalGroup -> IsLeader ( plr_guid ))
2009-03-14 20:06:00 -06:00
group -> ChangeLeader ( plr_guid );
}
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
2010-08-08 04:37:24 +02:00
void Battleground :: EventPlayerLoggedIn ( Player * player , uint64 plr_guid )
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
{
2009-04-08 16:33:46 -05:00
if ( * itr == plr_guid )
2009-03-09 17:07:12 -06:00
{
m_OfflineQueue . erase ( itr );
break ;
}
}
m_Players [ plr_guid ]. OfflineRemoveTime = 0 ;
PlayerAddedToBGCheckIfBGIsRunning ( player );
2009-03-09 17:07:40 -06:00
// if battleground is starting, then add preparation aura
// we don't have to do that, because preparation aura isn't removed when player logs out
2009-03-09 17:07:12 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 16:36:58 -06:00
// This method should be called when player logs out from running battleground
2010-08-08 04:37:24 +02:00
void Battleground :: EventPlayerLoggedOut ( Player * player )
2009-03-09 16:36:58 -06:00
{
2009-03-09 17:07:12 -06:00
// player is correct pointer, it is checked in WorldSession::LogoutPlayer()
m_OfflineQueue . push_back ( player -> GetGUID ());
2009-12-24 10:20:15 +01:00
m_Players [ player -> GetGUID ()]. OfflineRemoveTime = sWorld . GetGameTime () + MAX_OFFLINE_TIME ;
2009-04-08 16:33:46 -05:00
if ( GetStatus () == STATUS_IN_PROGRESS )
2009-03-09 16:36:58 -06:00
{
2010-02-15 15:31:27 +01:00
// drop flag and handle other cleanups
RemovePlayer ( player , player -> GetGUID ());
// 1 player is logging out, if it is the last, then end arena!
if ( isArena ())
2009-04-08 16:33:46 -05:00
if ( GetAlivePlayersCountByTeam ( player -> GetTeam ()) <= 1 && GetPlayersCountByTeam ( GetOtherTeam ( player -> GetTeam ())))
2010-08-08 04:37:24 +02:00
EndBattleground ( GetOtherTeam ( player -> GetTeam ()));
2009-03-09 16:36:58 -06:00
}
2010-02-15 15:31:27 +01:00
2009-12-17 10:43:12 +01:00
player -> LeaveBattleground ();
2009-03-09 16:36:58 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05: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-08-08 04:37:24 +02: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
2008-10-02 16:23:55 -05: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-08-08 04:37:24 +02: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-08-08 04:37:24 +02: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
{
2009-06-03 00:43:04 -05:00
//if BG is starting ... invite anyone
if ( GetStatus () == STATUS_WAIT_JOIN )
2008-10-05 08:48:32 -05:00
return ( GetInvitedCount ( Team ) < GetMaxPlayersPerTeam ()) ? GetMaxPlayersPerTeam () - GetInvitedCount ( Team ) : 0 ;
2009-06-03 00:43:04 -05:00
//if BG is already started .. do not allow to join too much players of one faction
uint32 otherTeam ;
uint32 otherIn ;
if ( Team == ALLIANCE )
{
otherTeam = GetInvitedCount ( HORDE );
otherIn = GetPlayersCountByTeam ( HORDE );
}
else
{
otherTeam = GetInvitedCount ( ALLIANCE );
otherIn = GetPlayersCountByTeam ( ALLIANCE );
}
if ( GetStatus () == STATUS_IN_PROGRESS )
{
// difference based on ppl invited (not necessarily entered battle)
// default: allow 0
uint32 diff = 0 ;
// allow join one person if the sides are equal (to fill up bg to minplayersperteam)
if ( otherTeam == GetInvitedCount ( Team ))
diff = 1 ;
// allow join more ppl if the other side has more players
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
diff = diff < diff2 ? diff : diff2 ;
// min of diff, diff2 and diff3
return diff < diff3 ? diff : diff3 ;
}
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
2010-08-08 04:37:24 +02:00
void Battleground :: UpdatePlayerScore ( Player * Source , uint32 type , uint32 value , bool doAddHonor )
2008-10-02 16:23:55 -05:00
{
//this procedure is called from virtual function implemented in bg subclass
2010-08-08 04:37:24 +02:00
BattlegroundScoreMap :: const_iterator itr = m_PlayerScores . find ( Source -> GetGUID ());
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( itr == m_PlayerScores . end ()) // player not found...
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
switch ( type )
{
case SCORE_KILLING_BLOWS : // Killing blows
itr -> second -> KillingBlows += value ;
break ;
case SCORE_DEATHS : // Deaths
itr -> second -> Deaths += value ;
2010-08-07 18:31:06 +02:00
Source -> GetAchievementMgr (). ResetAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE , ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH );
2008-10-02 16:23:55 -05:00
break ;
case SCORE_HONORABLE_KILLS : // Honorable kills
itr -> second -> HonorableKills += value ;
break ;
case SCORE_BONUS_HONOR : // Honor bonus
2008-10-05 08:48:32 -05:00
// do not add honor in arenas
2010-08-08 04:37:24 +02:00
if ( isBattleground ())
2008-10-05 08:48:32 -05:00
{
// reward honor instantly
2010-05-17 17:10:24 +02:00
if ( doAddHonor )
{
2010-05-17 23:29:13 +02:00
Source -> RewardHonor ( NULL , 1 , value ); //RewardHonor calls UpdatePlayerScore with doAddHonor = false
2010-05-17 17:10:24 +02:00
} else itr -> second -> BonusHonor += value ;
2008-10-05 08:48:32 -05:00
}
2008-10-02 16:23:55 -05:00
break ;
//used only in EY, but in MSG_PVP_LOG_DATA opcode
case SCORE_DAMAGE_DONE : // Damage Done
itr -> second -> DamageDone += value ;
break ;
case SCORE_HEALING_DONE : // Healing Done
itr -> second -> HealingDone += value ;
break ;
default :
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground: Unknown player score type %u" , type );
2008-10-02 16:23:55 -05:00
break ;
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +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
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( player_guid );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-09 15:33:45 -05:00
plr -> CastSpell ( plr , SPELL_WAITING_FOR_RESURRECT , true );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +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
{
2009-10-17 16:20:24 -07: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 );
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( player_guid );
2009-04-08 16:33:46 -05:00
if ( ! plr )
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
plr -> RemoveAurasDueToSpell ( SPELL_WAITING_FOR_RESURRECT );
2009-10-17 15:51:44 -07:00
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
{
2009-12-17 10:43:12 +01:00
Map * map = GetBgMap ();
2009-04-08 16:33:46 -05:00
if ( ! map )
2008-10-05 08:48:32 -05:00
return false ;
// must be created this way, adding to godatamap would add it to the base map of the instance
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
// so we must create it specific for this instance
GameObject * go = new GameObject ;
2010-08-08 05:25:45 +02:00
if ( ! go -> Create ( sObjectMgr . GenerateLowGuid ( HIGHGUID_GAMEOBJECT ), entry , GetBgMap (),
2009-04-27 18:36:10 -05:00
PHASEMASK_NORMAL , x , y , z , o , rotation0 , rotation1 , rotation2 , rotation3 , 100 , GO_STATE_READY ))
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outErrorDb ( "Gameobject template %u not found in database! Battleground not created!" , entry );
sLog . outError ( "Cannot create gameobject template %u! Battleground not created!" , entry );
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-08-08 05:25:45 +02: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
*/
// add to world, so it can be later looked up from HashMapHolder
2009-04-08 17:23:57 -05:00
map -> Add ( go );
2008-10-05 08:48:32 -05:00
m_BgObjects [ type ] = go -> GetGUID ();
2008-10-02 16:23:55 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05: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
{
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]);
2009-04-08 16:33:46 -05:00
if ( obj )
2008-10-02 16:23:55 -05: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
{
//change state to allow door to be closed
obj -> SetLootState ( GO_READY );
obj -> UseDoorOrButton ( RESPAWN_ONE_DAY );
}
}
else
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground: Door object not found (cannot close doors)" );
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
{
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]);
2009-04-08 16:33:46 -05:00
if ( obj )
2008-10-02 16:23:55 -05:00
{
//change state to be sure they will be opened
obj -> SetLootState ( GO_READY );
obj -> UseDoorOrButton ( RESPAWN_ONE_DAY );
}
else
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground: Door object not found! - doors will be closed." );
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
GameObject * Battleground :: GetBGObject ( uint32 type )
2008-11-21 19:45:49 -06:00
{
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]);
2010-04-07 19:14:10 +02:00
if ( ! obj )
2008-11-21 19:45:49 -06:00
sLog . outError ( "couldn't get gameobject %i" , type );
return obj ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Creature * Battleground :: GetBGCreature ( uint32 type )
2008-11-21 19:45:49 -06:00
{
2009-12-17 10:43:12 +01:00
Creature * creature = GetBgMap () -> GetCreature ( m_BgCreatures [ type ]);
2010-04-07 19:14:10 +02:00
if ( ! creature )
2008-11-21 19:45:49 -06:00
sLog . outError ( "couldn't get creature %i" , type );
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
{
2009-12-17 10:43:12 +01:00
Map * map = GetBgMap ();
2009-04-08 16:33:46 -05:00
if ( ! map )
2008-10-05 08:48:32 -05:00
return ;
2009-04-08 16:33:46 -05:00
if ( respawntime == 0 )
2008-10-02 16:23:55 -05:00
{
2009-12-17 10:43:12 +01:00
GameObject * obj = map -> GetGameObject ( m_BgObjects [ type ]);
2009-04-08 16:33:46 -05:00
if ( obj )
2008-10-02 16:23:55 -05:00
{
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
2009-04-08 16:33:46 -05:00
if ( obj -> getLootState () == GO_JUST_DEACTIVATED )
2008-10-02 16:23:55 -05:00
obj -> SetLootState ( GO_READY );
2008-10-05 08:48:32 -05:00
obj -> SetRespawnTime ( 0 );
map -> Add ( obj );
2008-10-02 16:23:55 -05:00
}
}
else
{
2009-12-17 10:43:12 +01:00
GameObject * obj = map -> GetGameObject ( m_BgObjects [ type ]);
2009-04-08 16:33:46 -05:00
if ( obj )
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
map -> Add ( obj );
2008-10-02 16:23:55 -05:00
obj -> SetRespawnTime ( respawntime );
obj -> SetLootState ( GO_JUST_DEACTIVATED );
}
}
}
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
{
2009-12-17 10:43:12 +01:00
Map * map = GetBgMap ();
2009-04-08 16:33:46 -05:00
if ( ! map )
2008-10-05 08:48:32 -05:00
return NULL ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Creature * pCreature = new Creature ;
2010-08-08 05:25:45 +02:00
if ( ! pCreature -> Create ( sObjectMgr . GenerateLowGuid ( HIGHGUID_UNIT ), map , PHASEMASK_NORMAL , entry , 0 , teamval , x , y , z , o ))
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "Can't create creature entry: %u" , entry );
delete pCreature ;
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-03-20 14:05:14 -06:00
pCreature -> SetHomePosition ( x , y , z , o );
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
CreatureInfo const * cinfo = sObjectMgr . GetCreatureTemplate ( entry );
2010-05-04 12:16:45 +02:00
if ( ! cinfo )
{
2010-08-08 04:37:24 +02:00
sLog . outErrorDb ( "Battleground::AddCreature: entry %u does not exist." , entry );
2010-05-04 12:16:45 +02:00
return NULL ;
}
//force using DB speeds
pCreature -> SetSpeed ( MOVE_WALK , cinfo -> speed_walk );
pCreature -> SetSpeed ( MOVE_RUN , cinfo -> speed_run );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
map -> Add ( pCreature );
m_BgCreatures [ type ] = pCreature -> GetGUID ();
2009-10-17 15:51:44 -07:00
2010-05-31 23:01:47 +02:00
if ( respawntime )
pCreature -> SetRespawnDelay ( respawntime );
2008-10-02 16:23:55 -05:00
return pCreature ;
}
2008-12-19 16:05:13 -06:00
/*
2010-08-08 04:37:24 +02:00
void Battleground::SpawnBGCreature(uint32 type, uint32 respawntime)
2008-12-19 16:05:13 -06:00
{
2010-06-25 00:18:01 +02:00
Map * map = sMapMgr.FindMap(GetMapId(),GetInstanceId());
2009-04-08 16:33:46 -05:00
if (!map)
2008-12-19 16:05:13 -06:00
return false;
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if (respawntime == 0)
2008-12-19 16:05:13 -06:00
{
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
2009-04-08 16:33:46 -05:00
if (obj)
2008-12-19 16:05:13 -06:00
{
//obj->Respawn(); // bugged
obj->SetRespawnTime(0);
2010-08-08 05:25:45 +02:00
sObjectMgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);
2008-12-19 16:05:13 -06:00
map->Add(obj);
}
}
else
{
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
2009-04-08 16:33:46 -05:00
if (obj)
2008-12-19 16:05:13 -06:00
{
obj->setDeathState(DEAD);
obj->SetRespawnTime(respawntime);
map->Add(obj);
}
}
}
*/
2010-08-08 04:37:24 +02:00
bool Battleground :: DelCreature ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2009-04-08 16:33:46 -05:00
if ( ! m_BgCreatures [ type ])
2009-02-10 09:55:16 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2009-12-17 10:43:12 +01:00
Creature * cr = GetBgMap () -> GetCreature ( m_BgCreatures [ type ]);
2009-04-08 16:33:46 -05:00
if ( ! cr )
2008-10-02 16:23:55 -05:00
{
2008-11-14 17:03:03 -06:00
sLog . outError ( "Can't find creature guid: %u" , GUID_LOPART ( m_BgCreatures [ type ]));
2008-10-02 16:23:55 -05:00
return false ;
}
cr -> AddObjectToRemoveList ();
m_BgCreatures [ type ] = 0 ;
return true ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: DelObject ( uint32 type )
2008-10-02 16:23:55 -05:00
{
2009-04-08 16:33:46 -05:00
if ( ! m_BgObjects [ type ])
2009-02-10 09:55:16 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( m_BgObjects [ type ]);
2009-04-08 16:33:46 -05:00
if ( ! obj )
2008-10-02 16:23:55 -05:00
{
2008-11-14 17:03:03 -06:00
sLog . outError ( "Can't find gobject guid: %u" , GUID_LOPART ( m_BgObjects [ type ]));
2008-10-02 16:23:55 -05:00
return false ;
}
obj -> SetRespawnTime ( 0 ); // not save respawn time
obj -> Delete ();
m_BgObjects [ type ] = 0 ;
return true ;
}
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
{
uint32 entry = 0 ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( team == ALLIANCE )
2009-08-14 22:09:06 +02:00
entry = BG_CREATURE_ENTRY_A_SPIRITGUIDE ;
2008-10-02 16:23:55 -05:00
else
2009-08-14 22:09:06 +02:00
entry = BG_CREATURE_ENTRY_H_SPIRITGUIDE ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Creature * pCreature = AddCreature ( entry , type , team , x , y , z , o );
2009-04-08 16:33:46 -05:00
if ( ! pCreature )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Can't create Spirit guide. Battleground not created!" );
2008-12-19 16:05:13 -06:00
EndNow ();
2008-10-02 16:23:55 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
pCreature -> setDeathState ( DEAD );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
pCreature -> SetUInt64Value ( UNIT_FIELD_CHANNEL_OBJECT , pCreature -> GetGUID ());
// aura
2009-02-06 19:42:03 +01:00
//TODO: Fix display here
//pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
2008-10-02 16:23:55 -05:00
// casting visual effect
pCreature -> SetUInt32Value ( UNIT_CHANNEL_SPELL , SPELL_SPIRIT_HEAL_CHANNEL );
// correct cast speed
pCreature -> SetFloatValue ( UNIT_MOD_CAST_SPEED , 1.0f );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
//pCreature->CastSpell(pCreature, SPELL_SPIRIT_HEAL_CHANNEL, true);
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendMessageToAll ( int32 entry , ChatMsg type , Player const * source )
2008-10-02 16:23:55 -05:00
{
2010-08-08 04:37:24 +02:00
Trinity :: BattlegroundChatBuilder bg_builder ( type , entry , source );
Trinity :: LocalizedPacketDo < Trinity :: BattlegroundChatBuilder > bg_do ( bg_builder );
2009-03-09 17:00:31 -06:00
BroadcastWorker ( bg_do );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: PSendMessageToAll ( int32 entry , ChatMsg type , Player const * source , ...)
2008-10-02 16:23:55 -05:00
{
2009-03-06 15:25:20 -06:00
va_list ap ;
2009-03-09 17:07:12 -06:00
va_start ( ap , source );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
Trinity :: BattlegroundChatBuilder bg_builder ( type , entry , source , & ap );
Trinity :: LocalizedPacketDo < Trinity :: BattlegroundChatBuilder > bg_do ( bg_builder );
2009-03-09 17:00:31 -06:00
BroadcastWorker ( bg_do );
2009-10-17 15:51:44 -07:00
2009-03-06 15:25:20 -06:00
va_end ( ap );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SendWarningToAll ( int32 entry , ...)
2010-06-01 23:55:09 +02:00
{
2010-08-08 05:25:45 +02:00
const char * format = sObjectMgr . GetTrinityStringForDBCLocale ( entry );
2010-06-01 23:55:09 +02:00
va_list ap ;
char str [ 1024 ];
va_start ( ap , entry );
vsnprintf ( str , 1024 , format , ap );
va_end ( ap );
std :: string msg = ( std :: string ) str ;
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
data << ( uint8 ) CHAT_MSG_RAID_BOSS_EMOTE ;
data << ( uint32 ) LANG_UNIVERSAL ;
data << ( uint64 ) 0 ;
data << ( uint32 ) 0 ; // 2.1.0
data << ( uint32 ) 1 ;
2010-08-08 19:45:53 +02:00
data << ( uint8 ) 0 ;
2010-06-01 23:55:09 +02:00
data << ( uint64 ) 0 ;
data << ( uint32 )( strlen ( msg . c_str ()) + 1 );
data << msg . c_str ();
data << ( uint8 ) 0 ;
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2010-06-01 23:55:09 +02:00
if ( Player * plr = ObjectAccessor :: FindPlayer ( MAKE_NEW_GUID ( itr -> first , 0 , HIGHGUID_PLAYER )))
if ( plr -> GetSession ())
plr -> GetSession () -> SendPacket ( & data );
}
2010-08-08 04:37:24 +02:00
void Battleground :: SendMessage2ToAll ( int32 entry , ChatMsg type , Player const * source , int32 arg1 , int32 arg2 )
2009-03-09 17:06:13 -06:00
{
2010-08-08 04:37:24 +02:00
Trinity :: Battleground2ChatBuilder bg_builder ( type , entry , source , arg1 , arg2 );
Trinity :: LocalizedPacketDo < Trinity :: Battleground2ChatBuilder > bg_do ( bg_builder );
2009-03-09 17:06:13 -06:00
BroadcastWorker ( bg_do );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: EndNow ()
2008-10-02 16:23:55 -05:00
{
2008-10-05 08:48:32 -05:00
RemoveFromBGFreeSlotQueue ();
2008-10-02 16:23:55 -05:00
SetStatus ( STATUS_WAIT_LEAVE );
2009-03-13 18:06:36 -06:00
SetEndTime ( 0 );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-09 17:06:13 -06:00
//to be removed
2010-08-08 04:37:24 +02:00
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-08-08 05:25:45 +02:00
return sObjectMgr . GetTrinityStringForDBCLocale ( entry );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/*
important notice:
buffs aren't spawned/despawned when players captures anything
buffs are in their positions when battleground starts
*/
2010-08-08 04:37:24 +02:00
void Battleground :: HandleTriggerBuff ( uint64 const & go_guid )
2008-10-02 16:23:55 -05:00
{
2009-12-17 10:43:12 +01:00
GameObject * obj = GetBgMap () -> GetGameObject ( go_guid );
2009-04-08 16:33:46 -05:00
if ( ! obj || obj -> GetGoType () != GAMEOBJECT_TYPE_TRAP || ! obj -> isSpawned ())
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
//change buff type, when buff is used:
int32 index = m_BgObjects . size () - 1 ;
while ( index >= 0 && m_BgObjects [ index ] != go_guid )
index -- ;
if ( index < 0 )
{
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground (Type: %u) has buff gameobject (Guid: %u Entry: %u Type:%u) but it hasn't that object in its internal data" , GetTypeID ( true ), GUID_LOPART ( go_guid ), obj -> GetEntry (), obj -> GetGoType ());
2008-10-02 16:23:55 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
//randomly select new buff
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
{
//despawn current buff
SpawnBGObject ( index , RESPAWN_ONE_DAY );
//set index for new one
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
2010-08-08 04:37:24 +02:00
void Battleground :: HandleKillPlayer ( Player * player , Player * killer )
2008-10-02 16:23:55 -05:00
{
//keep in mind that for arena this will have to be changed a bit
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// add +1 deaths
UpdatePlayerScore ( player , SCORE_DEATHS , 1 );
// 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
{
2010-08-08 05:25:45 +02:00
Player * plr = sObjectMgr . GetPlayer ( itr -> first );
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( ! plr || plr == killer )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:33:46 -05:00
if ( plr -> GetTeam () == killer -> GetTeam () && plr -> IsAtGroupRewardDistance ( player ))
2008-10-02 16:23:55 -05:00
UpdatePlayerScore ( plr , SCORE_HONORABLE_KILLS , 1 );
}
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
// to be able to remove insignia -- ONLY IN Battlegrounds
2010-08-08 19:45:53 +02:00
// give xp only in Battlegrounds
2009-04-08 16:33:46 -05:00
if ( ! isArena ())
2010-05-11 21:48:03 +02:00
{
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
2008-10-05 08:48:32 -05:00
// return the player's team based on battlegroundplayer info
// used in same faction arena matches mainly
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetPlayerTeam ( uint64 guid )
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-08-08 04:37:24 +02:00
uint32 Battleground :: GetOtherTeam ( uint32 teamId )
2009-03-09 17:07:40 -06:00
{
return ( teamId ) ? (( teamId == ALLIANCE ) ? HORDE : ALLIANCE ) : 0 ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
bool Battleground :: IsPlayerInBattleground ( uint64 guid )
2009-02-10 01:16:16 -06:00
{
2010-08-08 04:37:24 +02:00
BattlegroundPlayerMap :: const_iterator itr = m_Players . find ( guid );
2009-04-08 16:33:46 -05:00
if ( itr != m_Players . end ())
2009-02-10 01:16:16 -06:00
return true ;
return false ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: PlayerAddedToBGCheckIfBGIsRunning ( Player * plr )
2009-02-10 01:16:16 -06:00
{
2009-04-08 16:33:46 -05:00
if ( GetStatus () != STATUS_WAIT_LEAVE )
2009-02-10 01:16:16 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-02-10 01:16:16 -06:00
WorldPacket data ;
2010-08-08 04:37:24 +02:00
BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr :: BGQueueTypeId ( GetTypeID (), GetArenaType ());
2009-10-17 15:51:44 -07:00
2009-02-10 01:16:16 -06:00
BlockMovement ( plr );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildPvpLogDataPacket ( & data , this );
2009-02-10 01:16:16 -06:00
plr -> GetSession () -> SendPacket ( & data );
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
sBattlegroundMgr . BuildBattlegroundStatusPacket ( & data , this , plr -> GetBattlegroundQueueIndex ( bgQueueTypeId ), STATUS_IN_PROGRESS , GetEndTime (), GetStartTime (), GetArenaType ());
2009-02-10 01:16:16 -06:00
plr -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
uint32 Battleground :: GetAlivePlayersCountByTeam ( uint32 Team ) const
2008-10-05 08:48:32 -05:00
{
int count = 0 ;
2010-08-08 04:37:24 +02:00
for ( BattlegroundPlayerMap :: const_iterator itr = m_Players . begin (); itr != m_Players . end (); ++ itr )
2008-10-05 08:48:32 -05:00
{
2009-04-08 16:33:46 -05:00
if ( itr -> second . Team == Team )
2008-10-05 08:48:32 -05:00
{
2010-08-08 05:25:45 +02:00
Player * pl = sObjectMgr . GetPlayer ( itr -> first );
2009-05-12 10:01:09 -05:00
if ( pl && pl -> isAlive () && ! pl -> HasByteFlag ( UNIT_FIELD_BYTES_2 , 3 , FORM_SPIRITOFREDEMPTION ))
2008-10-05 08:48:32 -05:00
++ count ;
}
}
return count ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: SetHoliday ( bool is_holiday )
2008-10-17 16:36:07 -05:00
{
2010-04-07 19:14:10 +02:00
if ( is_holiday )
2008-10-17 16:36:07 -05:00
m_HonorMode = BG_HOLIDAY ;
else
m_HonorMode = BG_NORMAL ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
int32 Battleground :: GetObjectType ( uint64 guid )
2008-11-21 19:45:49 -06:00
{
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < m_BgObjects . size (); ++ i )
2010-04-07 19:14:10 +02:00
if ( m_BgObjects [ i ] == guid )
2008-11-21 19:45:49 -06:00
return i ;
2010-08-08 04:37:24 +02:00
sLog . outError ( "Battleground: cheating? a player used a gameobject which isnt supposed to be a usable object!" );
2008-11-21 19:45:49 -06:00
return - 1 ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: HandleKillUnit ( Creature * /*creature*/ , Player * /*killer*/ )
2008-11-21 19:45:49 -06:00
{
}
2009-10-17 15:51:44 -07:00
2010-12-02 22:25:32 +01:00
void Battleground :: CheckArenaAfterTimerConditions ()
{
EndBattleground ( WINNER_NONE );
}
2010-08-08 04:37:24 +02:00
void Battleground :: CheckArenaWinConditions ()
2009-03-09 16:36:58 -06:00
{
2009-04-08 16:33:46 -05:00
if ( ! GetAlivePlayersCountByTeam ( ALLIANCE ) && GetPlayersCountByTeam ( HORDE ))
2010-08-08 04:37:24 +02:00
EndBattleground ( HORDE );
2009-04-08 16:33:46 -05:00
else if ( GetPlayersCountByTeam ( ALLIANCE ) && ! GetAlivePlayersCountByTeam ( HORDE ))
2010-08-08 04:37:24 +02:00
EndBattleground ( ALLIANCE );
2009-03-09 16:36:58 -06:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 04:37:24 +02:00
void Battleground :: UpdateArenaWorldState ()
2009-12-16 23:23:42 +02:00
{
2009-12-17 10:43:12 +01:00
UpdateWorldState ( 0xe10 , GetAlivePlayersCountByTeam ( HORDE ));
UpdateWorldState ( 0xe11 , GetAlivePlayersCountByTeam ( ALLIANCE ));
2009-12-16 23:23:42 +02:00
}
2010-08-08 04:37:24 +02:00
void Battleground :: SetBgRaid ( uint32 TeamID , Group * bg_raid )
2009-02-09 22:08:06 -06:00
{
Group * & old_raid = TeamID == ALLIANCE ? m_BgRaids [ BG_TEAM_ALLIANCE ] : m_BgRaids [ BG_TEAM_HORDE ];
2010-04-07 19:14:10 +02:00
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-08-08 05:25:45 +02: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
{
2010-08-08 04:37:24 +02:00
BattlegroundTeamId team_idx = GetTeamIndexByTeamId ( team );
2009-09-18 14:10:37 -07:00
uint32 score = ( m_TeamScores [ team_idx ] < 0 ) ? 0 : uint32 ( m_TeamScores [ team_idx ]);
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 )
if ( Player * pPlayer = sObjectMgr . GetPlayer ( itr -> first ))
pPlayer -> GetAchievementMgr (). StartTimedAchievement ( type , entry );
}
2010-08-08 04:37:24 +02:00
void Battleground :: SetBracket ( PvPDifficultyEntry const * bracketEntry )
2010-02-15 15:31:27 +01:00
{
m_BracketId = bracketEntry -> GetBracketId ();
SetLevelRange ( bracketEntry -> minLevel , bracketEntry -> maxLevel );
}
2010-05-11 21:42:39 +02:00
2010-08-08 04:37:24 +02:00
void Battleground :: RewardXPAtKill ( Player * plr , Player * victim )
2010-05-11 21:42:39 +02:00
{
2010-08-23 19:56:47 -07:00
if ( ! sWorld . getBoolConfig ( CONFIG_BG_XP_FOR_KILL ) || ! plr || ! victim )
2010-05-11 21:42:39 +02:00
return ;
uint32 xp = 0 ;
uint32 count = 0 ;
uint32 sum_level = 0 ;
Player * member_with_max_level = NULL ;
Player * not_gray_member_with_max_level = NULL ;
if ( Group * pGroup = plr -> GetGroup ()) //should be always in a raid group while in any bg
{
for ( GroupReference * itr = pGroup -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
{
Player * member = itr -> getSource ();
if ( ! member || ! member -> isAlive ()) // only for alive
continue ;
if ( ! member -> IsAtGroupRewardDistance ( victim )) // at req. distance
continue ;
++ count ;
sum_level += member -> getLevel ();
if ( ! member_with_max_level || member_with_max_level -> getLevel () < member -> getLevel ())
member_with_max_level = member ;
uint32 gray_level = Trinity :: XP :: GetGrayLevel ( member -> getLevel ());
if ( victim -> getLevel () > gray_level && ( ! not_gray_member_with_max_level
|| not_gray_member_with_max_level -> getLevel () < member -> getLevel ()))
not_gray_member_with_max_level = member ;
2010-08-08 19:45:53 +02:00
}
2010-05-11 21:42:39 +02:00
if ( member_with_max_level )
{
xp = ! not_gray_member_with_max_level ? 0 : Trinity :: XP :: Gain ( not_gray_member_with_max_level , victim );
if ( ! xp )
return ;
float group_rate = 1.0f ;
for ( GroupReference * itr = pGroup -> GetFirstMember (); itr != NULL ; itr = itr -> next ())
{
Player * pGroupGuy = itr -> getSource ();
if ( ! pGroupGuy )
continue ;
if ( ! pGroupGuy -> IsAtGroupRewardDistance ( victim ))
continue ; // member (alive or dead) or his corpse at req. distance
float rate = group_rate * float ( pGroupGuy -> getLevel ()) / sum_level ;
// XP updated only for alive group member
if ( pGroupGuy -> isAlive () && not_gray_member_with_max_level && pGroupGuy -> getLevel () <= not_gray_member_with_max_level -> getLevel ())
{
uint32 itr_xp = ( member_with_max_level == not_gray_member_with_max_level ) ? uint32 ( xp * rate ) : uint32 (( xp * rate / 2 ) + 1 );
// handle SPELL_AURA_MOD_XP_PCT auras
Unit :: AuraEffectList const & ModXPPctAuras = plr -> GetAuraEffectsByType ( SPELL_AURA_MOD_XP_PCT );
for ( Unit :: AuraEffectList :: const_iterator i = ModXPPctAuras . begin (); i != ModXPPctAuras . end (); ++ i )
itr_xp = uint32 ( itr_xp * ( 1.0f + ( * i ) -> GetAmount () / 100.0f ));
pGroupGuy -> GiveXP ( itr_xp , victim );
if ( Pet * pet = pGroupGuy -> GetPet ())
pet -> GivePetXP ( itr_xp / 2 );
}
}
}
}
else //should be always in a raid group while in any BG, but you never know...
{
xp = Trinity :: XP :: Gain ( plr , victim );
if ( ! xp )
return ;
// handle SPELL_AURA_MOD_XP_PCT auras
Unit :: AuraEffectList const & ModXPPctAuras = plr -> GetAuraEffectsByType ( SPELL_AURA_MOD_XP_PCT );
for ( Unit :: AuraEffectList :: const_iterator i = ModXPPctAuras . begin (); i != ModXPPctAuras . end (); ++ i )
xp = uint32 ( xp * ( 1.0f + ( * i ) -> GetAmount () / 100.0f ));
plr -> GiveXP ( xp , victim );
if ( Pet * pet = plr -> GetPet ())
pet -> GivePetXP ( xp );
2010-08-08 19:45:53 +02:00
}
2010-06-07 12:08:15 -06:00
}