You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
5.8 KiB
231 lines
5.8 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "hltvdirector.h" |
|
#include "team_control_point.h" |
|
|
|
|
|
CBaseEntity* GetCapturePointByIndex( int iCaptureIndex ) |
|
{ |
|
CTeamControlPoint *pTeamControlPoint = (CTeamControlPoint *)gEntList.FindEntityByClassname( NULL, "team_control_point" ); |
|
|
|
while ( pTeamControlPoint ) |
|
{ |
|
if ( pTeamControlPoint->GetPointIndex() == iCaptureIndex ) |
|
{ |
|
return pTeamControlPoint; |
|
} |
|
|
|
pTeamControlPoint = (CTeamControlPoint *)gEntList.FindEntityByClassname( pTeamControlPoint, "team_control_point" ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
class CTFHLTVDirector : public CHLTVDirector |
|
{ |
|
public: |
|
DECLARE_CLASS( CTFHLTVDirector, CHLTVDirector ); |
|
|
|
const char** GetModEvents(); |
|
void SetHLTVServer( IHLTVServer *hltv ); |
|
void CreateShotFromEvent( CHLTVGameEvent *event ); |
|
|
|
virtual char *GetFixedCameraEntityName( void ) { return "info_observer_point"; } |
|
}; |
|
|
|
void CTFHLTVDirector::SetHLTVServer( IHLTVServer *hltv ) |
|
{ |
|
BaseClass::SetHLTVServer( hltv ); |
|
|
|
if ( m_pHLTVServer ) |
|
{ |
|
// mod specific events the director uses to find interesting shots |
|
ListenForGameEvent( "teamplay_point_captured" ); |
|
ListenForGameEvent( "teamplay_capture_blocked" ); |
|
ListenForGameEvent( "teamplay_point_startcapture" ); |
|
ListenForGameEvent( "teamplay_flag_event" ); |
|
ListenForGameEvent( "ctf_flag_captured" ); |
|
} |
|
} |
|
|
|
void CTFHLTVDirector::CreateShotFromEvent( CHLTVGameEvent *event ) |
|
{ |
|
// show event at least for 2 more seconds after it occured |
|
const char *name = event->m_Event->GetName(); |
|
|
|
int thera = RandomFloat()>0.5?20:-20; |
|
|
|
if ( !Q_strcmp( "teamplay_point_startcapture", name ) || |
|
!Q_strcmp( "teamplay_point_captured", name ) || |
|
!Q_strcmp( "teamplay_capture_blocked", name ) ) |
|
{ |
|
CBaseEntity *pCapturePoint = GetCapturePointByIndex( event->m_Event->GetInt( "cp" ) ); |
|
|
|
int iCameraIndex = -1; |
|
float flClosest = 99999.9f; |
|
|
|
if ( pCapturePoint ) |
|
{ |
|
// Does it have an associated viewpoint? |
|
for ( int i = 0; i<m_nNumFixedCameras; i++ ) |
|
{ |
|
CBaseEntity *pCamera = m_pFixedCameras[ i ]; |
|
|
|
if ( pCamera ) |
|
{ |
|
byte pvs[MAX_MAP_CLUSTERS/8]; |
|
int clusterIndex = engine->GetClusterForOrigin( pCamera->GetAbsOrigin() ); |
|
engine->GetPVSForCluster( clusterIndex, sizeof(pvs), pvs ); |
|
bool bCameraInPVS = engine->CheckOriginInPVS( pCapturePoint->GetAbsOrigin(), pvs, sizeof( pvs ) ); |
|
|
|
if ( bCameraInPVS == true ) |
|
{ |
|
float flDistance = (pCapturePoint->GetAbsOrigin() - pCamera->GetAbsOrigin()).Length(); |
|
if ( flDistance <= flClosest ) |
|
{ |
|
iCameraIndex = i; |
|
flClosest = flDistance; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
CBasePlayer *pPlayer = NULL; |
|
|
|
if ( !Q_strcmp( "teamplay_point_captured", name ) ) |
|
{ |
|
const char *pszCappers = event->m_Event->GetString("cappers"); |
|
int nLength = Q_strlen(pszCappers); |
|
|
|
if ( nLength > 0 ) |
|
{ |
|
int iRandomCapper = pszCappers[ RandomInt(0,nLength-1) ]; |
|
pPlayer = UTIL_PlayerByIndex( iRandomCapper ); |
|
} |
|
} |
|
else if ( !Q_strcmp( "teamplay_capture_blocked", name ) ) |
|
{ |
|
int iBlocker = event->m_Event->GetInt("blocker"); |
|
pPlayer = UTIL_PlayerByIndex( iBlocker ); |
|
} |
|
|
|
if ( pPlayer ) |
|
{ |
|
if ( iCameraIndex >= 0 && RandomFloat() > 0.66f ) |
|
{ |
|
StartFixedCameraShot( iCameraIndex, pPlayer->entindex() ); |
|
} |
|
else if ( pCapturePoint ) |
|
{ |
|
StartChaseCameraShot( pPlayer->entindex(), pCapturePoint->entindex(), 96, 20, thera, false ); |
|
} |
|
else |
|
{ |
|
StartChaseCameraShot( pPlayer->entindex(), 0, 96, 20, 0, false ); |
|
} |
|
} |
|
else if ( iCameraIndex >= 0 && pCapturePoint ) |
|
{ |
|
// no player known for this event |
|
StartFixedCameraShot( iCameraIndex, pCapturePoint->entindex() ); |
|
} |
|
|
|
// shot 2 seconds after event |
|
m_nNextShotTick = MIN( m_nNextShotTick, (event->m_Tick+TIME_TO_TICKS(1.0)) ); |
|
} |
|
else if ( !Q_strcmp( "object_destroyed", name ) ) |
|
{ |
|
CBasePlayer *attacker = UTIL_PlayerByUserId( event->m_Event->GetInt("attacker") ); |
|
if ( attacker ) |
|
{ |
|
int iObjectIndex = event->m_Event->GetInt("index"); |
|
StartChaseCameraShot( attacker->entindex(), iObjectIndex, 96, 20, thera, false ); |
|
} |
|
} |
|
else if ( !Q_strcmp( "ctf_flag_captured", name ) ) |
|
{ |
|
CBasePlayer *capper = UTIL_PlayerByUserId( event->m_Event->GetInt("capper") ); |
|
if ( capper ) |
|
{ |
|
StartChaseCameraShot( capper->entindex(), 0, 96, 20, 0, false ); |
|
} |
|
} |
|
else if ( !Q_strcmp( "teamplay_flag_event", name ) ) |
|
{ |
|
StartChaseCameraShot( event->m_Event->GetInt("player"), 0, 96, 20, 0, false ); |
|
} |
|
else |
|
{ |
|
|
|
// let baseclass create a shot |
|
BaseClass::CreateShotFromEvent( event ); |
|
} |
|
} |
|
|
|
const char** CTFHLTVDirector::GetModEvents() |
|
{ |
|
// game events relayed to spectator clients |
|
static const char *s_modevents[] = |
|
{ |
|
"game_newmap", |
|
"hltv_status", |
|
"hltv_chat", |
|
"player_connect", |
|
"player_disconnect", |
|
"player_changeclass", |
|
"player_team", |
|
"player_info", |
|
"player_death", |
|
"player_chat", |
|
"player_spawn", |
|
"round_start", |
|
"round_end", |
|
"server_cvar", |
|
"server_spawn", |
|
|
|
// additional TF events: |
|
"controlpoint_starttouch", |
|
"controlpoint_endtouch", |
|
"ctf_flag_captured", |
|
"teamplay_broadcast_audio", |
|
"teamplay_capture_blocked", |
|
"teamplay_flag_event", |
|
"teamplay_game_over", |
|
"teamplay_point_captured", |
|
"teamplay_round_stalemate", |
|
"teamplay_round_start", |
|
"teamplay_round_win", |
|
"teamplay_timer_time_added", |
|
"teamplay_update_timer", |
|
"teamplay_win_panel", |
|
"training_complete", |
|
"tf_game_over", |
|
"object_destroyed", |
|
|
|
NULL |
|
}; |
|
|
|
return s_modevents; |
|
} |
|
|
|
static CTFHLTVDirector s_HLTVDirector; // singleton |
|
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLTVDirector, IHLTVDirector, INTERFACEVERSION_HLTVDIRECTOR, s_HLTVDirector ); |
|
|
|
CHLTVDirector* HLTVDirector() |
|
{ |
|
return &s_HLTVDirector; |
|
} |
|
|
|
IGameSystem* HLTVDirectorSystem() |
|
{ |
|
return &s_HLTVDirector; |
|
} |