2011-07-27 04:07:46 +07: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/>.
*/
#include "Battlefield.h"
#include "BattlefieldMgr.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Map.h"
#include "MapManager.h"
#include "Group.h"
#include "WorldPacket.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "CreatureTextMgr.h"
#include "GroupMgr.h"
Battlefield :: Battlefield ()
{
m_Timer = 0 ;
2012-03-21 18:52:07 +01:00
m_IsEnabled = true ;
m_isActive = false ;
2011-07-27 04:07:46 +07:00
m_DefenderTeam = TEAM_NEUTRAL ;
m_TypeId = 0 ;
m_BattleId = 0 ;
m_ZoneId = 0 ;
m_MapId = 0 ;
m_MaxPlayer = 0 ;
m_MinPlayer = 0 ;
m_BattleTime = 0 ;
m_NoWarBattleTime = 0 ;
m_TimeForAcceptInvite = 20 ;
m_uiKickDontAcceptTimer = 1000 ;
2012-03-21 18:52:07 +01:00
m_uiKickAfkPlayersTimer = 1000 ;
2011-07-27 04:07:46 +07:00
m_LastResurectTimer = 30 * IN_MILLISECONDS ;
m_StartGroupingTimer = 0 ;
m_StartGrouping = false ;
StalkerGuid = 0 ;
}
Battlefield ::~ Battlefield ()
{
}
2012-03-21 18:52:07 +01:00
// Called when a player enters the zone
void Battlefield :: HandlePlayerEnterZone ( Player * player , uint32 /*zone*/ )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
// If battle is started,
// If not full of players > invite player to join the war
// If full of players > announce to player that BF is full and kick him after a few second if he desn't leave
2011-07-27 04:07:46 +07:00
if ( IsWarTime ())
{
2012-03-21 18:52:07 +01:00
if ( m_PlayersInWar [ player -> GetTeamId ()]. size () + m_InvitedPlayers [ player -> GetTeamId ()]. size () < m_MaxPlayer ) // Vacant spaces
2012-03-12 15:07:27 +01:00
InvitePlayerToWar ( player );
2012-03-21 18:52:07 +01:00
else // No more vacant places
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
// TODO: Send a packet to announce it to player
2012-03-12 15:07:27 +01:00
m_PlayersWillBeKick [ player -> GetTeamId ()][ player -> GetGUID ()] = time ( NULL ) + 10 ;
InvitePlayerToQueue ( player );
2011-07-27 04:07:46 +07:00
}
}
else
{
2012-03-21 18:52:07 +01:00
// If time left is < 15 minutes invite player to join queue
2011-07-27 04:07:46 +07:00
if ( m_Timer <= m_StartGroupingTimer )
2012-03-12 15:07:27 +01:00
InvitePlayerToQueue ( player );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
// Add player in the list of player in zone
2012-03-12 15:07:27 +01:00
m_players [ player -> GetTeamId ()]. insert ( player -> GetGUID ());
2012-03-21 18:52:07 +01:00
OnPlayerEnterZone ( player );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
// Called when a player leave the zone
void Battlefield :: HandlePlayerLeaveZone ( Player * player , uint32 /*zone*/ )
2011-07-27 04:07:46 +07:00
{
if ( IsWarTime ())
{
2012-03-21 18:52:07 +01:00
// If the player is participating to the battle
2012-03-12 15:07:27 +01:00
if ( m_PlayersInWar [ player -> GetTeamId ()]. find ( player -> GetGUID ()) != m_PlayersInWar [ player -> GetTeamId ()]. end ())
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
m_PlayersInWar [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
player -> GetSession () -> SendBfLeaveMessage ( m_BattleId );
2012-03-21 18:52:07 +01:00
if ( Group * group = player -> GetGroup ()) // Remove the player from the raid group
2012-03-12 15:07:27 +01:00
group -> RemoveMember ( player -> GetGUID ());
2012-02-22 16:32:51 -05:00
2012-03-21 18:52:07 +01:00
OnPlayerLeaveWar ( player );
2011-07-27 04:07:46 +07:00
}
}
for ( BfCapturePointMap :: iterator itr = m_capturePoints . begin (); itr != m_capturePoints . end (); ++ itr )
2012-03-12 15:07:27 +01:00
itr -> second -> HandlePlayerLeave ( player );
m_InvitedPlayers [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
m_PlayersWillBeKick [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
m_players [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
SendRemoveWorldStates ( player );
RemovePlayerFromResurrectQueue ( player -> GetGUID ());
2012-03-21 18:52:07 +01:00
OnPlayerLeaveZone ( player );
2011-07-27 04:07:46 +07:00
}
bool Battlefield :: Update ( uint32 diff )
{
if ( m_Timer <= diff )
{
2012-03-21 18:52:07 +01:00
// Battlefield ends on time
2011-07-27 04:07:46 +07:00
if ( IsWarTime ())
EndBattle ( true );
2012-03-21 18:52:07 +01:00
else // Time to start a new battle!
2011-07-27 04:07:46 +07:00
StartBattle ();
}
else
m_Timer -= diff ;
2012-03-21 18:52:07 +01:00
// Invite players a few minutes before the battle's beginning
2011-07-27 04:07:46 +07:00
if ( ! m_StartGrouping && m_Timer <= m_StartGroupingTimer )
{
m_StartGrouping = true ;
2012-03-21 18:52:07 +01:00
InvitePlayersInZoneToQueue ();
OnStartGrouping ();
2011-07-27 04:07:46 +07:00
}
bool objective_changed = false ;
if ( IsWarTime ())
{
2012-03-21 18:52:07 +01:00
if ( m_uiKickAfkPlayersTimer <= diff )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_uiKickAfkPlayersTimer = 1000 ;
KickAfkPlayers ();
2011-07-27 04:07:46 +07:00
}
else
2012-03-21 18:52:07 +01:00
m_uiKickAfkPlayersTimer -= diff ;
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
// Kick players who chose not to accept invitation to the battle
2011-07-27 04:07:46 +07:00
if ( m_uiKickDontAcceptTimer <= diff )
{
for ( int team = 0 ; team < 2 ; team ++ )
for ( PlayerTimerMap :: iterator itr = m_InvitedPlayers [ team ]. begin (); itr != m_InvitedPlayers [ team ]. end (); itr ++ )
if (( * itr ). second <= time ( NULL ))
2012-03-21 18:52:07 +01:00
KickPlayerFromBattlefield (( * itr ). first );
InvitePlayersInZoneToWar ();
2011-07-27 04:07:46 +07:00
for ( int team = 0 ; team < 2 ; team ++ )
for ( PlayerTimerMap :: iterator itr = m_PlayersWillBeKick [ team ]. begin (); itr != m_PlayersWillBeKick [ team ]. end (); itr ++ )
if (( * itr ). second <= time ( NULL ))
2012-03-21 18:52:07 +01:00
KickPlayerFromBattlefield (( * itr ). first );
2011-07-27 04:07:46 +07:00
m_uiKickDontAcceptTimer = 1000 ;
}
else
m_uiKickDontAcceptTimer -= diff ;
for ( BfCapturePointMap :: iterator itr = m_capturePoints . begin (); itr != m_capturePoints . end (); ++ itr )
if ( itr -> second -> Update ( diff ))
objective_changed = true ;
}
if ( m_LastResurectTimer <= diff )
{
2012-03-21 18:52:07 +01:00
for ( uint8 i = 0 ; i < m_GraveyardList . size (); i ++ )
if ( GetGraveyardById ( i ))
m_GraveyardList [ i ] -> Resurrect ();
2011-07-27 04:07:46 +07:00
m_LastResurectTimer = RESURRECTION_INTERVAL ;
}
else
m_LastResurectTimer -= diff ;
return objective_changed ;
}
2012-03-21 18:52:07 +01:00
void Battlefield :: InvitePlayersInZoneToQueue ()
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < 2 ; ++ team )
for ( GuidSet :: const_iterator itr = m_players [ team ]. begin (); itr != m_players [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
InvitePlayerToQueue ( player );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: InvitePlayerToQueue ( Player * player )
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( m_PlayersInQueue [ player -> GetTeamId ()]. count ( player -> GetGUID ()))
2011-07-27 04:07:46 +07:00
return ;
2012-08-08 09:29:43 -04:00
if ( m_PlayersInQueue [ player -> GetTeamId ()]. size () <= m_MinPlayer || m_PlayersInQueue [ GetOtherTeam ( player -> GetTeamId ())]. size () >= m_MinPlayer )
2012-03-12 15:07:27 +01:00
player -> GetSession () -> SendBfInvitePlayerToQueue ( m_BattleId );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: InvitePlayersInQueueToWar ()
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < BG_TEAMS_COUNT ; ++ team )
{
for ( GuidSet :: const_iterator itr = m_PlayersInQueue [ team ]. begin (); itr != m_PlayersInQueue [ team ]. end (); ++ itr )
{
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( m_PlayersInWar [ player -> GetTeamId ()]. size () + m_InvitedPlayers [ player -> GetTeamId ()]. size () < m_MaxPlayer )
InvitePlayerToWar ( player );
2011-07-27 04:07:46 +07:00
else
{
//Full
}
}
}
m_PlayersInQueue [ team ]. clear ();
}
}
2012-03-21 18:52:07 +01:00
void Battlefield :: InvitePlayersInZoneToWar ()
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < BG_TEAMS_COUNT ; ++ team )
for ( GuidSet :: const_iterator itr = m_players [ team ]. begin (); itr != m_players [ team ]. end (); ++ itr )
{
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( m_PlayersInWar [ player -> GetTeamId ()]. count ( player -> GetGUID ()) || m_InvitedPlayers [ player -> GetTeamId ()]. count ( player -> GetGUID ()))
2011-07-27 04:07:46 +07:00
continue ;
2012-03-12 15:07:27 +01:00
if ( m_PlayersInWar [ player -> GetTeamId ()]. size () + m_InvitedPlayers [ player -> GetTeamId ()]. size () < m_MaxPlayer )
InvitePlayerToWar ( player );
2012-03-21 18:52:07 +01:00
else // Battlefield is full of players
2012-03-12 15:07:27 +01:00
m_PlayersWillBeKick [ player -> GetTeamId ()][ player -> GetGUID ()] = time ( NULL ) + 10 ;
2011-07-27 04:07:46 +07:00
}
}
}
2012-03-21 18:52:07 +01:00
void Battlefield :: InvitePlayerToWar ( Player * player )
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( ! player )
2011-07-27 04:07:46 +07:00
return ;
// TODO : needed ?
2012-03-12 15:07:27 +01:00
if ( player -> isInFlight ())
2011-07-27 04:07:46 +07:00
return ;
2012-03-12 15:07:27 +01:00
if ( player -> InArena () || player -> GetBattleground ())
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
m_PlayersInQueue [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
2011-07-27 04:07:46 +07:00
return ;
}
2012-03-21 18:52:07 +01:00
// If the player does not match minimal level requirements for the battlefield, kick him
2012-03-12 15:07:27 +01:00
if ( player -> getLevel () < m_MinLevel )
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( m_PlayersWillBeKick [ player -> GetTeamId ()]. count ( player -> GetGUID ()) == 0 )
m_PlayersWillBeKick [ player -> GetTeamId ()][ player -> GetGUID ()] = time ( NULL ) + 10 ;
2012-08-21 19:40:21 +02:00
return ;
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
// Check if player is not already in war
2012-03-12 15:07:27 +01:00
if ( m_PlayersInWar [ player -> GetTeamId ()]. count ( player -> GetGUID ()) || m_InvitedPlayers [ player -> GetTeamId ()]. count ( player -> GetGUID ()))
2011-07-27 04:07:46 +07:00
return ;
2012-03-12 15:07:27 +01:00
m_PlayersWillBeKick [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
m_InvitedPlayers [ player -> GetTeamId ()][ player -> GetGUID ()] = time ( NULL ) + m_TimeForAcceptInvite ;
player -> GetSession () -> SendBfInvitePlayerToWar ( m_BattleId , m_ZoneId , m_TimeForAcceptInvite );
2011-07-27 04:07:46 +07:00
}
void Battlefield :: InitStalker ( uint32 entry , float x , float y , float z , float o )
{
if ( Creature * creature = SpawnCreature ( entry , x , y , z , o , TEAM_NEUTRAL ))
StalkerGuid = creature -> GetGUID ();
else
2012-08-21 19:40:21 +02:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::InitStalker: could not spawn Stalker (Creature entry %u), zone messeges will be un-available" , entry );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: KickAfkPlayers ()
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < BG_TEAMS_COUNT ; ++ team )
for ( GuidSet :: const_iterator itr = m_PlayersInWar [ team ]. begin (); itr != m_PlayersInWar [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
if ( player -> isAFK ())
2012-03-21 18:52:07 +01:00
KickPlayerFromBattlefield ( * itr );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: KickPlayerFromBattlefield ( uint64 guid )
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( guid ))
if ( player -> GetZoneId () == GetZoneId ())
player -> TeleportTo ( KickPosition );
2011-07-27 04:07:46 +07:00
}
void Battlefield :: StartBattle ()
{
2012-03-21 18:52:07 +01:00
if ( m_isActive )
2011-07-27 04:07:46 +07:00
return ;
for ( int team = 0 ; team < BG_TEAMS_COUNT ; team ++ )
{
m_PlayersInWar [ team ]. clear ();
m_Groups [ team ]. clear ();
}
m_Timer = m_BattleTime ;
2012-03-21 18:52:07 +01:00
m_isActive = true ;
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
InvitePlayersInZoneToWar ();
InvitePlayersInQueueToWar ();
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
DoPlaySoundToAll ( BF_START );
2011-07-27 04:07:46 +07:00
OnBattleStart ();
}
2012-03-21 18:52:07 +01:00
void Battlefield :: EndBattle ( bool endByTimer )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( ! m_isActive )
2012-03-09 09:45:44 -05:00
return ;
2012-03-21 18:52:07 +01:00
m_isActive = false ;
2011-07-27 04:07:46 +07:00
m_StartGrouping = false ;
2012-03-21 18:52:07 +01:00
if ( ! endByTimer )
2011-07-27 04:07:46 +07:00
SetDefenderTeam ( GetAttackerTeam ());
if ( GetDefenderTeam () == TEAM_ALLIANCE )
2012-03-21 18:52:07 +01:00
DoPlaySoundToAll ( BF_ALLIANCE_WINS );
2011-07-27 04:07:46 +07:00
else
2012-03-21 18:52:07 +01:00
DoPlaySoundToAll ( BF_HORDE_WINS );
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
OnBattleEnd ( endByTimer );
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
// Reset battlefield timer
2011-07-27 04:07:46 +07:00
m_Timer = m_NoWarBattleTime ;
SendInitWorldStatesToAll ();
}
2012-03-21 18:52:07 +01:00
void Battlefield :: DoPlaySoundToAll ( uint32 SoundID )
2011-07-27 04:07:46 +07:00
{
WorldPacket data ;
data . Initialize ( SMSG_PLAY_SOUND , 4 );
data << uint32 ( SoundID );
for ( int team = 0 ; team < BG_TEAMS_COUNT ; team ++ )
for ( GuidSet :: const_iterator itr = m_PlayersInWar [ team ]. begin (); itr != m_PlayersInWar [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> GetSession () -> SendPacket ( & data );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
bool Battlefield :: HasPlayer ( Player * player ) const
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
return m_players [ player -> GetTeamId ()]. find ( player -> GetGUID ()) != m_players [ player -> GetTeamId ()]. end ();
2011-07-27 04:07:46 +07:00
}
// Called in WorldSession::HandleBfQueueInviteResponse
2012-03-21 18:52:07 +01:00
void Battlefield :: PlayerAcceptInviteToQueue ( Player * player )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
// Add player in queue
2012-03-12 15:07:27 +01:00
m_PlayersInQueue [ player -> GetTeamId ()]. insert ( player -> GetGUID ());
2011-07-27 04:07:46 +07:00
// Send notification
2012-03-21 18:52:07 +01:00
player -> GetSession () -> SendBfQueueInviteResponse ( m_BattleId , m_ZoneId );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
2011-07-27 04:07:46 +07:00
// Called in WorldSession::HandleBfExitRequest
2012-03-21 18:52:07 +01:00
void Battlefield :: AskToLeaveQueue ( Player * player )
2011-07-27 04:07:46 +07:00
{
// Remove player from queue
2012-03-12 15:07:27 +01:00
m_PlayersInQueue [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
2011-07-27 04:07:46 +07:00
}
// Called in WorldSession::HandleBfEntryInviteResponse
2012-03-21 18:52:07 +01:00
void Battlefield :: PlayerAcceptInviteToWar ( Player * player )
2011-07-27 04:07:46 +07:00
{
if ( ! IsWarTime ())
return ;
2012-03-12 15:07:27 +01:00
if ( AddOrSetPlayerToCorrectBfGroup ( player ))
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
player -> GetSession () -> SendBfEntered ( m_BattleId );
m_PlayersInWar [ player -> GetTeamId ()]. insert ( player -> GetGUID ());
m_InvitedPlayers [ player -> GetTeamId ()]. erase ( player -> GetGUID ());
2012-03-21 18:52:07 +01:00
2012-03-12 15:07:27 +01:00
if ( player -> isAFK ())
player -> ToggleAFK ();
2011-07-27 04:07:46 +07:00
2012-03-12 15:07:27 +01:00
OnPlayerJoinWar ( player ); //for scripting
2011-07-27 04:07:46 +07:00
}
}
void Battlefield :: TeamCastSpell ( TeamId team , int32 spellId )
{
if ( spellId > 0 )
for ( GuidSet :: const_iterator itr = m_PlayersInWar [ team ]. begin (); itr != m_PlayersInWar [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
2012-03-21 18:52:07 +01:00
player -> CastSpell ( player , uint32 ( spellId ), true );
2011-07-27 04:07:46 +07:00
else
for ( GuidSet :: const_iterator itr = m_PlayersInWar [ team ]. begin (); itr != m_PlayersInWar [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
2012-03-21 18:52:07 +01:00
player -> RemoveAuraFromStack ( uint32 ( - spellId ));
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: BroadcastPacketToZone ( WorldPacket & data ) const
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < BG_TEAMS_COUNT ; ++ team )
for ( GuidSet :: const_iterator itr = m_players [ team ]. begin (); itr != m_players [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> GetSession () -> SendPacket ( & data );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: BroadcastPacketToQueue ( WorldPacket & data ) const
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < BG_TEAMS_COUNT ; ++ team )
for ( GuidSet :: const_iterator itr = m_PlayersInQueue [ team ]. begin (); itr != m_PlayersInQueue [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> GetSession () -> SendPacket ( & data );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: BroadcastPacketToWar ( WorldPacket & data ) const
2011-07-27 04:07:46 +07:00
{
for ( uint8 team = 0 ; team < BG_TEAMS_COUNT ; ++ team )
for ( GuidSet :: const_iterator itr = m_PlayersInWar [ team ]. begin (); itr != m_PlayersInWar [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> GetSession () -> SendPacket ( & data );
2011-07-27 04:07:46 +07:00
}
WorldPacket Battlefield :: BuildWarningAnnPacket ( std :: string msg )
{
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 );
data << uint8 ( 0 );
data << uint64 ( 0 );
data << uint32 ( strlen ( msg . c_str ()) + 1 );
data << msg . c_str ();
data << uint8 ( 0 );
return data ;
}
void Battlefield :: SendWarningToAllInZone ( uint32 entry )
{
if ( Unit * unit = sObjectAccessor -> FindUnit ( StalkerGuid ))
if ( Creature * stalker = unit -> ToCreature ())
// FIXME: replaced CHAT_TYPE_END with CHAT_MSG_BG_SYSTEM_NEUTRAL to fix compile, it's a guessed change :/
sCreatureTextMgr -> SendChat ( stalker , ( uint8 ) entry , NULL , CHAT_MSG_BG_SYSTEM_NEUTRAL , LANG_ADDON , TEXT_RANGE_ZONE );
}
/*void Battlefield::SendWarningToAllInWar(int32 entry,...)
{
const char *format = sObjectMgr->GetTrinityStringForDBCLocale(entry);
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 = BuildWarningAnnPacket(msg);
BroadcastPacketWar(data);
}*/
2012-03-21 18:52:07 +01:00
void Battlefield :: SendWarningToPlayer ( Player * player , uint32 entry )
{
if ( player )
if ( Unit * unit = sObjectAccessor -> FindUnit ( StalkerGuid ))
if ( Creature * stalker = unit -> ToCreature ())
sCreatureTextMgr -> SendChat ( stalker , ( uint8 ) entry , player -> GetGUID ());
2011-07-27 04:07:46 +07:00
}
void Battlefield :: SendUpdateWorldState ( uint32 field , uint32 value )
{
for ( uint8 i = 0 ; i < BG_TEAMS_COUNT ; ++ i )
for ( GuidSet :: iterator itr = m_players [ i ]. begin (); itr != m_players [ i ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> SendUpdateWorldState ( field , value );
2011-07-27 04:07:46 +07:00
}
void Battlefield :: RegisterZone ( uint32 zoneId )
{
2012-03-02 22:00:26 -03:00
sBattlefieldMgr -> AddZone ( zoneId , this );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: HideNpc ( Creature * creature )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
creature -> CombatStop ();
creature -> SetReactState ( REACT_PASSIVE );
creature -> SetFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE );
creature -> SetPhaseMask ( 2 , true );
creature -> DisappearAndDie ();
creature -> SetVisible ( false );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void Battlefield :: ShowNpc ( Creature * creature , bool aggressive )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
creature -> SetPhaseMask ( 1 , true );
creature -> SetVisible ( true );
creature -> RemoveFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE );
if ( ! creature -> isAlive ())
creature -> Respawn ( true );
if ( aggressive )
creature -> SetReactState ( REACT_AGGRESSIVE );
2011-07-27 04:07:46 +07:00
else
{
2012-03-21 18:52:07 +01:00
creature -> SetFlag ( UNIT_FIELD_FLAGS , UNIT_FLAG_NON_ATTACKABLE );
creature -> SetReactState ( REACT_PASSIVE );
2011-07-27 04:07:46 +07:00
}
}
2012-03-21 18:52:07 +01:00
// ****************************************************
// ******************* Group System *******************
// ****************************************************
Group * Battlefield :: GetFreeBfRaid ( TeamId TeamId )
2011-07-27 04:07:46 +07:00
{
for ( GuidSet :: const_iterator itr = m_Groups [ TeamId ]. begin (); itr != m_Groups [ TeamId ]. end (); ++ itr )
if ( Group * group = sGroupMgr -> GetGroupByGUID ( * itr ))
if ( ! group -> IsFull ())
return group ;
return NULL ;
}
2012-03-21 18:52:07 +01:00
Group * Battlefield :: GetGroupPlayer ( uint64 guid , TeamId TeamId )
2011-07-27 04:07:46 +07:00
{
for ( GuidSet :: const_iterator itr = m_Groups [ TeamId ]. begin (); itr != m_Groups [ TeamId ]. end (); ++ itr )
if ( Group * group = sGroupMgr -> GetGroupByGUID ( * itr ))
if ( group -> IsMember ( guid ))
return group ;
return NULL ;
}
2012-03-21 18:52:07 +01:00
bool Battlefield :: AddOrSetPlayerToCorrectBfGroup ( Player * player )
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
if ( ! player -> IsInWorld ())
2011-07-27 04:07:46 +07:00
return false ;
2012-03-12 15:07:27 +01:00
if ( Group * group = player -> GetGroup ())
group -> RemoveMember ( player -> GetGUID ());
2011-07-27 04:07:46 +07:00
2012-03-12 15:07:27 +01:00
Group * group = GetFreeBfRaid ( player -> GetTeamId ());
2011-07-27 04:07:46 +07:00
if ( ! group )
{
group = new Group ;
group -> SetBattlefieldGroup ( this );
2012-03-12 15:07:27 +01:00
group -> Create ( player );
2011-07-27 04:07:46 +07:00
sGroupMgr -> AddGroup ( group );
2012-03-12 15:07:27 +01:00
m_Groups [ player -> GetTeamId ()]. insert ( group -> GetGUID ());
2011-07-27 04:07:46 +07:00
}
2012-03-12 15:07:27 +01:00
else if ( group -> IsMember ( player -> GetGUID ()))
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
uint8 subgroup = group -> GetMemberGroup ( player -> GetGUID ());
2012-08-20 16:23:24 -04:00
player -> SetBattlegroundRaid ( group , subgroup );
2011-07-27 04:07:46 +07:00
}
else
2012-03-12 15:07:27 +01:00
group -> AddMember ( player );
2011-07-27 04:07:46 +07:00
return true ;
}
//***************End of Group System*******************
//*****************************************************
//***************Spirit Guide System*******************
//*****************************************************
2012-03-21 18:52:07 +01:00
2011-07-27 04:07:46 +07:00
//--------------------
//-Battlefield Method-
//--------------------
2012-03-21 18:52:07 +01:00
BfGraveyard * Battlefield :: GetGraveyardById ( uint32 id )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( id < m_GraveyardList . size ())
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( m_GraveyardList [ id ])
return m_GraveyardList [ id ];
2011-07-27 04:07:46 +07:00
else
2012-08-21 19:40:21 +02:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::GetGraveyardById Id:%u not existed" , id );
2011-07-27 04:07:46 +07:00
}
else
2012-08-21 19:40:21 +02:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::GetGraveyardById Id:%u cant be found" , id );
2011-07-27 04:07:46 +07:00
return NULL ;
}
2012-03-21 18:52:07 +01:00
WorldSafeLocsEntry const * Battlefield :: GetClosestGraveYard ( Player * player )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
BfGraveyard * closestGY = NULL ;
2011-07-27 04:07:46 +07:00
float maxdist = - 1 ;
2012-03-21 18:52:07 +01:00
for ( uint8 i = 0 ; i < m_GraveyardList . size (); i ++ )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( m_GraveyardList [ i ])
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( m_GraveyardList [ i ] -> GetControlTeamId () != player -> GetTeamId ())
2011-07-27 04:07:46 +07:00
continue ;
2012-03-21 18:52:07 +01:00
float dist = m_GraveyardList [ i ] -> GetDistance ( player );
2011-07-27 04:07:46 +07:00
if ( dist < maxdist || maxdist < 0 )
{
2012-03-21 18:52:07 +01:00
closestGY = m_GraveyardList [ i ];
2011-07-27 04:07:46 +07:00
maxdist = dist ;
}
}
}
if ( closestGY )
2012-03-21 18:52:07 +01:00
return sWorldSafeLocsStore . LookupEntry ( closestGY -> GetGraveyardId ());
2011-07-27 04:07:46 +07:00
return NULL ;
}
2012-03-21 18:52:07 +01:00
void Battlefield :: AddPlayerToResurrectQueue ( uint64 npcGuid , uint64 playerGuid )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
for ( uint8 i = 0 ; i < m_GraveyardList . size (); i ++ )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( ! m_GraveyardList [ i ])
2011-07-27 04:07:46 +07:00
continue ;
2012-03-21 18:52:07 +01:00
if ( m_GraveyardList [ i ] -> HasNpc ( npcGuid ))
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_GraveyardList [ i ] -> AddPlayer ( playerGuid );
2011-07-27 04:07:46 +07:00
break ;
}
}
}
2012-03-21 18:52:07 +01:00
void Battlefield :: RemovePlayerFromResurrectQueue ( uint64 playerGuid )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
for ( uint8 i = 0 ; i < m_GraveyardList . size (); i ++ )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( ! m_GraveyardList [ i ])
2011-07-27 04:07:46 +07:00
continue ;
2012-03-21 18:52:07 +01:00
if ( m_GraveyardList [ i ] -> HasPlayer ( playerGuid ))
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_GraveyardList [ i ] -> RemovePlayer ( playerGuid );
2011-07-27 04:07:46 +07:00
break ;
}
}
}
2012-03-21 18:52:07 +01:00
void Battlefield :: SendAreaSpiritHealerQueryOpcode ( Player * player , const uint64 & guid )
2011-07-27 04:07:46 +07:00
{
WorldPacket data ( SMSG_AREA_SPIRIT_HEALER_TIME , 12 );
uint32 time = m_LastResurectTimer ; // resurrect every 30 seconds
data << guid << time ;
2012-03-21 18:52:07 +01:00
ASSERT ( player && player -> GetSession ());
player -> GetSession () -> SendPacket ( & data );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
// ----------------------
// - BfGraveyard Method -
// ----------------------
BfGraveyard :: BfGraveyard ( Battlefield * battlefield )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_Bf = battlefield ;
2011-07-27 04:07:46 +07:00
m_GraveyardId = 0 ;
m_ControlTeam = TEAM_NEUTRAL ;
m_SpiritGuide [ 0 ] = NULL ;
m_SpiritGuide [ 1 ] = NULL ;
m_ResurrectQueue . clear ();
}
2012-03-21 18:52:07 +01:00
void BfGraveyard :: Initialize ( TeamId startControl , uint32 graveyardId )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_ControlTeam = startControl ;
m_GraveyardId = graveyardId ;
2012-03-01 02:03:52 -03:00
}
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
void BfGraveyard :: SetSpirit ( Creature * spirit , TeamId team )
2012-03-01 02:03:52 -03:00
{
if ( ! spirit )
2011-07-27 04:07:46 +07:00
{
2012-08-21 19:40:21 +02:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "BfGraveyard::SetSpirit: Invalid Spirit." );
2012-03-01 02:03:52 -03:00
return ;
2011-07-27 04:07:46 +07:00
}
2012-03-01 02:03:52 -03:00
m_SpiritGuide [ team ] = spirit -> GetGUID ();
spirit -> SetReactState ( REACT_PASSIVE );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
float BfGraveyard :: GetDistance ( Player * player )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
const WorldSafeLocsEntry * safeLoc = sWorldSafeLocsStore . LookupEntry ( m_GraveyardId );
return player -> GetDistance2d ( safeLoc -> x , safeLoc -> y );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void BfGraveyard :: AddPlayer ( uint64 playerGuid )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
if ( ! m_ResurrectQueue . count ( playerGuid ))
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_ResurrectQueue . insert ( playerGuid );
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( playerGuid ))
2012-03-12 15:07:27 +01:00
player -> CastSpell ( player , SPELL_WAITING_FOR_RESURRECT , true );
2011-07-27 04:07:46 +07:00
}
}
2012-03-21 18:52:07 +01:00
void BfGraveyard :: RemovePlayer ( uint64 playerGuid )
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
m_ResurrectQueue . erase ( m_ResurrectQueue . find ( playerGuid ));
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( playerGuid ))
2012-03-12 15:07:27 +01:00
player -> RemoveAurasDueToSpell ( SPELL_WAITING_FOR_RESURRECT );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
void BfGraveyard :: Resurrect ()
2011-07-27 04:07:46 +07:00
{
if ( m_ResurrectQueue . empty ())
return ;
for ( GuidSet :: const_iterator itr = m_ResurrectQueue . begin (); itr != m_ResurrectQueue . end (); ++ itr )
{
// Get player object from his guid
2012-03-12 15:07:27 +01:00
Player * player = sObjectAccessor -> FindPlayer ( * itr );
if ( ! player )
2011-07-27 04:07:46 +07:00
continue ;
2012-03-21 18:52:07 +01:00
// Check if the player is in world and on the good graveyard
2012-03-12 15:07:27 +01:00
if ( player -> IsInWorld ())
2012-03-01 02:03:52 -03:00
if ( Unit * spirit = sObjectAccessor -> FindUnit ( m_SpiritGuide [ m_ControlTeam ]))
spirit -> CastSpell ( spirit , SPELL_SPIRIT_HEAL , true );
2011-07-27 04:07:46 +07:00
// Resurect player
2012-03-12 15:07:27 +01:00
player -> CastSpell ( player , SPELL_RESURRECTION_VISUAL , true );
player -> ResurrectPlayer ( 1.0f );
player -> CastSpell ( player , 6962 , true );
player -> CastSpell ( player , SPELL_SPIRIT_HEAL_MANA , true );
2011-07-27 04:07:46 +07:00
2012-03-12 15:07:27 +01:00
sObjectAccessor -> ConvertCorpseForPlayer ( player -> GetGUID ());
2011-07-27 04:07:46 +07:00
}
m_ResurrectQueue . clear ();
}
// For changing graveyard control
2012-03-21 18:52:07 +01:00
void BfGraveyard :: GiveControlTo ( TeamId team )
2011-07-27 04:07:46 +07:00
{
// Guide switching
2012-03-01 02:03:52 -03:00
// Note: Visiblity changes are made by phasing
/*if (m_SpiritGuide[1 - team])
2011-07-27 04:07:46 +07:00
m_SpiritGuide[1 - team]->SetVisible(false);
if (m_SpiritGuide[team])
2012-03-01 02:03:52 -03:00
m_SpiritGuide[team]->SetVisible(true);*/
2011-07-27 04:07:46 +07:00
m_ControlTeam = team ;
// Teleport to other graveyard, player witch were on this graveyard
RelocateDeadPlayers ();
}
2012-03-21 18:52:07 +01:00
void BfGraveyard :: RelocateDeadPlayers ()
2011-07-27 04:07:46 +07:00
{
2012-03-21 18:52:07 +01:00
WorldSafeLocsEntry const * closestGrave = NULL ;
2011-07-27 04:07:46 +07:00
for ( GuidSet :: const_iterator itr = m_ResurrectQueue . begin (); itr != m_ResurrectQueue . end (); ++ itr )
{
2012-03-12 15:07:27 +01:00
Player * player = sObjectAccessor -> FindPlayer ( * itr );
if ( ! player )
2011-07-27 04:07:46 +07:00
continue ;
2012-03-21 18:52:07 +01:00
if ( closestGrave )
player -> TeleportTo ( player -> GetMapId (), closestGrave -> x , closestGrave -> y , closestGrave -> z , player -> GetOrientation ());
2011-07-27 04:07:46 +07:00
else
{
2012-03-21 18:52:07 +01:00
closestGrave = m_Bf -> GetClosestGraveYard ( player );
if ( closestGrave )
player -> TeleportTo ( player -> GetMapId (), closestGrave -> x , closestGrave -> y , closestGrave -> z , player -> GetOrientation ());
2011-07-27 04:07:46 +07:00
}
}
}
2012-03-21 18:52:07 +01:00
// *******************************************************
// *************** End Spirit Guide system ***************
// *******************************************************
// ********************** Misc ***************************
// *******************************************************
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
Creature * Battlefield :: SpawnCreature ( uint32 entry , Position pos , TeamId team )
2011-07-27 04:07:46 +07:00
{
return SpawnCreature ( entry , pos . m_positionX , pos . m_positionY , pos . m_positionZ , pos . m_orientation , team );
}
2012-03-21 18:52:07 +01:00
Creature * Battlefield :: SpawnCreature ( uint32 entry , float x , float y , float z , float o , TeamId team )
2011-07-27 04:07:46 +07:00
{
//Get map object
Map * map = const_cast < Map * > ( sMapMgr -> CreateBaseMap ( m_MapId ));
if ( ! map )
{
2012-08-21 19:40:21 +02:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::SpawnCreature: Can't create creature entry: %u map not found" , entry );
2011-07-27 04:07:46 +07:00
return 0 ;
}
2012-03-14 00:04:34 +01:00
Creature * creature = new Creature ;
if ( ! creature -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_UNIT ), map , PHASEMASK_NORMAL , entry , 0 , team , x , y , z , o ))
2011-07-27 04:07:46 +07:00
{
2012-08-21 19:40:21 +02:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::SpawnCreature: Can't create creature entry: %u" , entry );
2012-03-14 00:04:34 +01:00
delete creature ;
2011-07-27 04:07:46 +07:00
return NULL ;
}
2012-03-14 00:04:34 +01:00
creature -> SetHomePosition ( x , y , z , o );
2011-07-27 04:07:46 +07:00
CreatureTemplate const * cinfo = sObjectMgr -> GetCreatureTemplate ( entry );
if ( ! cinfo )
{
2012-08-06 13:12:30 -04:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::SpawnCreature: entry %u does not exist." , entry );
2011-07-27 04:07:46 +07:00
return NULL ;
}
// force using DB speeds -- do we really need this?
2012-03-14 00:04:34 +01:00
creature -> SetSpeed ( MOVE_WALK , cinfo -> speed_walk );
creature -> SetSpeed ( MOVE_RUN , cinfo -> speed_run );
2011-07-27 04:07:46 +07:00
// Set creature in world
2012-03-14 00:04:34 +01:00
map -> AddToMap ( creature );
creature -> setActive ( true );
2011-07-27 04:07:46 +07:00
2012-03-14 00:04:34 +01:00
return creature ;
2011-07-27 04:07:46 +07:00
}
// Method for spawning gameobject on map
2012-03-21 18:52:07 +01:00
GameObject * Battlefield :: SpawnGameObject ( uint32 entry , float x , float y , float z , float o )
2011-07-27 04:07:46 +07:00
{
// Get map object
2012-03-21 18:52:07 +01:00
Map * map = const_cast < Map *> ( sMapMgr -> CreateBaseMap ( 571 )); // *vomits*
2011-07-27 04:07:46 +07:00
if ( ! map )
return 0 ;
// Create gameobject
GameObject * go = new GameObject ;
if ( ! go -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_GAMEOBJECT ), entry , map , PHASEMASK_NORMAL , x , y , z , o , 0 , 0 , 0 , 0 , 100 , GO_STATE_READY ))
{
2012-08-06 13:12:30 -04:00
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::SpawnGameObject: Gameobject template %u not found in database! Battlefield not created!" , entry );
sLog -> outError ( LOG_FILTER_BATTLEFIELD , "Battlefield::SpawnGameObject: Cannot create gameobject template %u! Battlefield not created!" , entry );
2011-07-27 04:07:46 +07:00
delete go ;
return NULL ;
}
2012-03-21 18:52:07 +01:00
// Add to world
2012-02-21 11:33:49 -05:00
map -> AddToMap ( go );
2011-07-27 04:07:46 +07:00
go -> setActive ( true );
2012-03-21 18:52:07 +01:00
2011-07-27 04:07:46 +07:00
return go ;
}
2012-03-21 18:52:07 +01:00
// *******************************************************
// ******************* CapturePoint **********************
// *******************************************************
2011-07-27 04:07:46 +07:00
2012-03-21 18:52:07 +01:00
BfCapturePoint :: BfCapturePoint ( Battlefield * battlefield ) : m_Bf ( battlefield ), m_capturePoint ( NULL )
2011-07-27 04:07:46 +07:00
{
m_team = TEAM_NEUTRAL ;
m_value = 0 ;
m_maxValue = 0 ;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL ;
m_OldState = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL ;
m_capturePointEntry = 0 ;
m_neutralValuePct = 0 ;
m_maxSpeed = 0 ;
}
2012-03-21 18:52:07 +01:00
bool BfCapturePoint :: HandlePlayerEnter ( Player * player )
2011-07-27 04:07:46 +07:00
{
if ( m_capturePoint )
{
2012-03-12 15:07:27 +01:00
player -> SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldState1 , 1 );
2012-03-21 18:52:07 +01:00
player -> SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldstate2 , uint32 ( ceil (( m_value + m_maxValue ) / ( 2 * m_maxValue ) * 100.0f )));
2012-03-12 15:07:27 +01:00
player -> SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldstate3 , m_neutralValuePct );
2011-07-27 04:07:46 +07:00
}
2012-03-12 15:07:27 +01:00
return m_activePlayers [ player -> GetTeamId ()]. insert ( player -> GetGUID ()). second ;
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
GuidSet :: iterator BfCapturePoint :: HandlePlayerLeave ( Player * player )
2011-07-27 04:07:46 +07:00
{
if ( m_capturePoint )
2012-03-21 18:52:07 +01:00
player -> SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldState1 , 0 );
2012-03-17 20:52:31 -05:00
2012-03-21 18:52:07 +01:00
GuidSet :: iterator current = m_activePlayers [ player -> GetTeamId ()]. find ( player -> GetGUID ());
2012-03-17 20:52:31 -05:00
2012-03-21 18:52:07 +01:00
if ( current == m_activePlayers [ player -> GetTeamId ()]. end ())
2012-03-17 20:52:31 -05:00
return current ; // return end()
2012-03-21 18:52:07 +01:00
m_activePlayers [ player -> GetTeamId ()]. erase ( current ++ );
2012-03-17 20:52:31 -05:00
return current ;
2011-07-27 04:07:46 +07:00
}
void BfCapturePoint :: SendChangePhase ()
{
if ( ! m_capturePoint )
return ;
// send this too, sometimes the slider disappears, dunno why :(
SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldState1 , 1 );
// send these updates to only the ones in this objective
SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldstate2 , ( uint32 ) ceil (( m_value + m_maxValue ) / ( 2 * m_maxValue ) * 100.0f ));
// send this too, sometimes it resets :S
SendUpdateWorldState ( m_capturePoint -> GetGOInfo () -> capturePoint . worldstate3 , m_neutralValuePct );
}
2012-03-04 01:24:00 -03:00
bool BfCapturePoint :: SetCapturePointData ( GameObject * capturePoint )
2011-07-27 04:07:46 +07:00
{
2012-03-04 01:24:00 -03:00
ASSERT ( capturePoint );
sLog -> outDebug ( LOG_FILTER_BATTLEFIELD , "Creating capture point %u" , capturePoint -> GetEntry ());
m_capturePoint = capturePoint ;
2011-07-27 04:07:46 +07:00
// check info existence
2012-03-04 13:29:05 -03:00
GameObjectTemplate const * goinfo = capturePoint -> GetGOInfo ();
if ( goinfo -> type != GAMEOBJECT_TYPE_CAPTURE_POINT )
2011-07-27 04:07:46 +07:00
{
2012-08-06 13:12:30 -04:00
sLog -> outError ( LOG_FILTER_GENERAL , "OutdoorPvP: GO %u is not capture point!" , capturePoint -> GetEntry ());
2011-07-27 04:07:46 +07:00
return false ;
}
2012-03-04 01:24:00 -03:00
// get the needed values from goinfo
m_maxValue = goinfo -> capturePoint . maxTime ;
m_maxSpeed = m_maxValue / ( goinfo -> capturePoint . minTime ? goinfo -> capturePoint . minTime : 60 );
m_neutralValuePct = goinfo -> capturePoint . neutralPercent ;
m_minValue = m_maxValue * goinfo -> capturePoint . neutralPercent / 100 ;
m_capturePointEntry = capturePoint -> GetEntry ();
if ( m_team == TEAM_ALLIANCE )
2011-07-27 04:07:46 +07:00
{
2012-03-04 01:24:00 -03:00
m_value = m_maxValue ;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE ;
}
else
{
m_value = - m_maxValue ;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE ;
2011-07-27 04:07:46 +07:00
}
2012-03-04 01:24:00 -03:00
return true ;
2011-07-27 04:07:46 +07:00
}
bool BfCapturePoint :: DelCapturePoint ()
{
if ( m_capturePoint )
{
m_capturePoint -> SetRespawnTime ( 0 ); // not save respawn time
m_capturePoint -> Delete ();
m_capturePoint = NULL ;
}
return true ;
}
bool BfCapturePoint :: Update ( uint32 diff )
{
if ( ! m_capturePoint )
return false ;
float radius = m_capturePoint -> GetGOInfo () -> capturePoint . radius ;
for ( uint8 team = 0 ; team < 2 ; ++ team )
2012-03-17 20:52:31 -05:00
{
for ( GuidSet :: iterator itr = m_activePlayers [ team ]. begin (); itr != m_activePlayers [ team ]. end ();)
{
2012-03-21 18:52:07 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
2012-03-17 20:52:31 -05:00
{
2012-03-21 18:52:07 +01:00
if ( ! m_capturePoint -> IsWithinDistInMap ( player , radius ) || ! player -> IsOutdoorPvPActive ())
itr = HandlePlayerLeave ( player );
2012-03-17 20:52:31 -05:00
else
++ itr ;
}
else
++ itr ;
}
}
2011-07-27 04:07:46 +07:00
2012-03-17 20:52:31 -05:00
std :: list < Player *> players ;
2011-07-27 04:07:46 +07:00
Trinity :: AnyPlayerInObjectRangeCheck checker ( m_capturePoint , radius );
2012-03-17 20:52:31 -05:00
Trinity :: PlayerListSearcher < Trinity :: AnyPlayerInObjectRangeCheck > searcher ( m_capturePoint , players , checker );
2011-07-27 04:07:46 +07:00
m_capturePoint -> VisitNearbyWorldObject ( radius , searcher );
2012-03-17 20:52:31 -05:00
for ( std :: list < Player *>:: iterator itr = players . begin (); itr != players . end (); ++ itr )
2011-07-27 04:07:46 +07:00
if (( * itr ) -> IsOutdoorPvPActive ())
if ( m_activePlayers [( * itr ) -> GetTeamId ()]. insert (( * itr ) -> GetGUID ()). second )
HandlePlayerEnter ( * itr );
// get the difference of numbers
float fact_diff = (( float ) m_activePlayers [ 0 ]. size () - ( float ) m_activePlayers [ 1 ]. size ()) * diff / BATTLEFIELD_OBJECTIVE_UPDATE_INTERVAL ;
if ( ! fact_diff )
return false ;
uint32 Challenger = 0 ;
float maxDiff = m_maxSpeed * diff ;
if ( fact_diff < 0 )
{
// horde is in majority, but it's already horde-controlled -> no change
if ( m_State == BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE && m_value <= - m_maxValue )
return false ;
if ( fact_diff < - maxDiff )
fact_diff = - maxDiff ;
Challenger = HORDE ;
}
else
{
// ally is in majority, but it's already ally-controlled -> no change
if ( m_State == BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE && m_value >= m_maxValue )
return false ;
if ( fact_diff > maxDiff )
fact_diff = maxDiff ;
Challenger = ALLIANCE ;
}
float oldValue = m_value ;
TeamId oldTeam = m_team ;
m_OldState = m_State ;
m_value += fact_diff ;
if ( m_value < - m_minValue ) // red
{
if ( m_value < - m_maxValue )
m_value = - m_maxValue ;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE ;
m_team = TEAM_HORDE ;
}
else if ( m_value > m_minValue ) // blue
{
if ( m_value > m_maxValue )
m_value = m_maxValue ;
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE ;
m_team = TEAM_ALLIANCE ;
}
else if ( oldValue * m_value <= 0 ) // grey, go through mid point
{
// if challenger is ally, then n->a challenge
if ( Challenger == ALLIANCE )
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE ;
// if challenger is horde, then n->h challenge
else if ( Challenger == HORDE )
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE ;
m_team = TEAM_NEUTRAL ;
}
else // grey, did not go through mid point
{
// old phase and current are on the same side, so one team challenges the other
if ( Challenger == ALLIANCE && ( m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE || m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE ))
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE ;
else if ( Challenger == HORDE && ( m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE || m_OldState == BF_CAPTUREPOINT_OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE ))
m_State = BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE ;
m_team = TEAM_NEUTRAL ;
}
if ( m_value != oldValue )
SendChangePhase ();
if ( m_OldState != m_State )
{
2012-08-21 19:40:21 +02:00
//sLog->outError(LOG_FILTER_BATTLEFIELD, "%u->%u", m_OldState, m_State);
2011-07-27 04:07:46 +07:00
if ( oldTeam != m_team )
ChangeTeam ( oldTeam );
return true ;
}
return false ;
}
void BfCapturePoint :: SendUpdateWorldState ( uint32 field , uint32 value )
{
for ( uint8 team = 0 ; team < 2 ; ++ team )
for ( GuidSet :: iterator itr = m_activePlayers [ team ]. begin (); itr != m_activePlayers [ team ]. end (); ++ itr ) // send to all players present in the area
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> SendUpdateWorldState ( field , value );
2011-07-27 04:07:46 +07:00
}
void BfCapturePoint :: SendObjectiveComplete ( uint32 id , uint64 guid )
{
uint8 team ;
switch ( m_State )
{
case BF_CAPTUREPOINT_OBJECTIVESTATE_ALLIANCE :
team = 0 ;
break ;
case BF_CAPTUREPOINT_OBJECTIVESTATE_HORDE :
team = 1 ;
break ;
default :
return ;
}
// send to all players present in the area
for ( GuidSet :: iterator itr = m_activePlayers [ team ]. begin (); itr != m_activePlayers [ team ]. end (); ++ itr )
2012-03-12 15:07:27 +01:00
if ( Player * player = sObjectAccessor -> FindPlayer ( * itr ))
player -> KilledMonsterCredit ( id , guid );
2011-07-27 04:07:46 +07:00
}
2012-03-21 18:52:07 +01:00
bool BfCapturePoint :: IsInsideObjective ( Player * player ) const
2011-07-27 04:07:46 +07:00
{
2012-03-12 15:07:27 +01:00
return m_activePlayers [ player -> GetTeamId ()]. find ( player -> GetGUID ()) != m_activePlayers [ player -> GetTeamId ()]. end ();
2011-07-27 04:07:46 +07:00
}