summaryrefslogtreecommitdiff
path: root/game/server/tf/tf_hltvdirector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/tf/tf_hltvdirector.cpp')
-rw-r--r--game/server/tf/tf_hltvdirector.cpp231
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