diff options
Diffstat (limited to 'game/server/tf/tf_hltvdirector.cpp')
| -rw-r--r-- | game/server/tf/tf_hltvdirector.cpp | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/game/server/tf/tf_hltvdirector.cpp b/game/server/tf/tf_hltvdirector.cpp new file mode 100644 index 0000000..454344e --- /dev/null +++ b/game/server/tf/tf_hltvdirector.cpp @@ -0,0 +1,231 @@ +//========= 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; +}
\ No newline at end of file |