Team Fortress 2 Source Code as on 22/4/2020
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.

230 lines
5.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "hltvdirector.h"
  10. #include "team_control_point.h"
  11. CBaseEntity* GetCapturePointByIndex( int iCaptureIndex )
  12. {
  13. CTeamControlPoint *pTeamControlPoint = (CTeamControlPoint *)gEntList.FindEntityByClassname( NULL, "team_control_point" );
  14. while ( pTeamControlPoint )
  15. {
  16. if ( pTeamControlPoint->GetPointIndex() == iCaptureIndex )
  17. {
  18. return pTeamControlPoint;
  19. }
  20. pTeamControlPoint = (CTeamControlPoint *)gEntList.FindEntityByClassname( pTeamControlPoint, "team_control_point" );
  21. }
  22. return NULL;
  23. }
  24. class CTFHLTVDirector : public CHLTVDirector
  25. {
  26. public:
  27. DECLARE_CLASS( CTFHLTVDirector, CHLTVDirector );
  28. const char** GetModEvents();
  29. void SetHLTVServer( IHLTVServer *hltv );
  30. void CreateShotFromEvent( CHLTVGameEvent *event );
  31. virtual char *GetFixedCameraEntityName( void ) { return "info_observer_point"; }
  32. };
  33. void CTFHLTVDirector::SetHLTVServer( IHLTVServer *hltv )
  34. {
  35. BaseClass::SetHLTVServer( hltv );
  36. if ( m_pHLTVServer )
  37. {
  38. // mod specific events the director uses to find interesting shots
  39. ListenForGameEvent( "teamplay_point_captured" );
  40. ListenForGameEvent( "teamplay_capture_blocked" );
  41. ListenForGameEvent( "teamplay_point_startcapture" );
  42. ListenForGameEvent( "teamplay_flag_event" );
  43. ListenForGameEvent( "ctf_flag_captured" );
  44. }
  45. }
  46. void CTFHLTVDirector::CreateShotFromEvent( CHLTVGameEvent *event )
  47. {
  48. // show event at least for 2 more seconds after it occured
  49. const char *name = event->m_Event->GetName();
  50. int thera = RandomFloat()>0.5?20:-20;
  51. if ( !Q_strcmp( "teamplay_point_startcapture", name ) ||
  52. !Q_strcmp( "teamplay_point_captured", name ) ||
  53. !Q_strcmp( "teamplay_capture_blocked", name ) )
  54. {
  55. CBaseEntity *pCapturePoint = GetCapturePointByIndex( event->m_Event->GetInt( "cp" ) );
  56. int iCameraIndex = -1;
  57. float flClosest = 99999.9f;
  58. if ( pCapturePoint )
  59. {
  60. // Does it have an associated viewpoint?
  61. for ( int i = 0; i<m_nNumFixedCameras; i++ )
  62. {
  63. CBaseEntity *pCamera = m_pFixedCameras[ i ];
  64. if ( pCamera )
  65. {
  66. byte pvs[MAX_MAP_CLUSTERS/8];
  67. int clusterIndex = engine->GetClusterForOrigin( pCamera->GetAbsOrigin() );
  68. engine->GetPVSForCluster( clusterIndex, sizeof(pvs), pvs );
  69. bool bCameraInPVS = engine->CheckOriginInPVS( pCapturePoint->GetAbsOrigin(), pvs, sizeof( pvs ) );
  70. if ( bCameraInPVS == true )
  71. {
  72. float flDistance = (pCapturePoint->GetAbsOrigin() - pCamera->GetAbsOrigin()).Length();
  73. if ( flDistance <= flClosest )
  74. {
  75. iCameraIndex = i;
  76. flClosest = flDistance;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. CBasePlayer *pPlayer = NULL;
  83. if ( !Q_strcmp( "teamplay_point_captured", name ) )
  84. {
  85. const char *pszCappers = event->m_Event->GetString("cappers");
  86. int nLength = Q_strlen(pszCappers);
  87. if ( nLength > 0 )
  88. {
  89. int iRandomCapper = pszCappers[ RandomInt(0,nLength-1) ];
  90. pPlayer = UTIL_PlayerByIndex( iRandomCapper );
  91. }
  92. }
  93. else if ( !Q_strcmp( "teamplay_capture_blocked", name ) )
  94. {
  95. int iBlocker = event->m_Event->GetInt("blocker");
  96. pPlayer = UTIL_PlayerByIndex( iBlocker );
  97. }
  98. if ( pPlayer )
  99. {
  100. if ( iCameraIndex >= 0 && RandomFloat() > 0.66f )
  101. {
  102. StartFixedCameraShot( iCameraIndex, pPlayer->entindex() );
  103. }
  104. else if ( pCapturePoint )
  105. {
  106. StartChaseCameraShot( pPlayer->entindex(), pCapturePoint->entindex(), 96, 20, thera, false );
  107. }
  108. else
  109. {
  110. StartChaseCameraShot( pPlayer->entindex(), 0, 96, 20, 0, false );
  111. }
  112. }
  113. else if ( iCameraIndex >= 0 && pCapturePoint )
  114. {
  115. // no player known for this event
  116. StartFixedCameraShot( iCameraIndex, pCapturePoint->entindex() );
  117. }
  118. // shot 2 seconds after event
  119. m_nNextShotTick = MIN( m_nNextShotTick, (event->m_Tick+TIME_TO_TICKS(1.0)) );
  120. }
  121. else if ( !Q_strcmp( "object_destroyed", name ) )
  122. {
  123. CBasePlayer *attacker = UTIL_PlayerByUserId( event->m_Event->GetInt("attacker") );
  124. if ( attacker )
  125. {
  126. int iObjectIndex = event->m_Event->GetInt("index");
  127. StartChaseCameraShot( attacker->entindex(), iObjectIndex, 96, 20, thera, false );
  128. }
  129. }
  130. else if ( !Q_strcmp( "ctf_flag_captured", name ) )
  131. {
  132. CBasePlayer *capper = UTIL_PlayerByUserId( event->m_Event->GetInt("capper") );
  133. if ( capper )
  134. {
  135. StartChaseCameraShot( capper->entindex(), 0, 96, 20, 0, false );
  136. }
  137. }
  138. else if ( !Q_strcmp( "teamplay_flag_event", name ) )
  139. {
  140. StartChaseCameraShot( event->m_Event->GetInt("player"), 0, 96, 20, 0, false );
  141. }
  142. else
  143. {
  144. // let baseclass create a shot
  145. BaseClass::CreateShotFromEvent( event );
  146. }
  147. }
  148. const char** CTFHLTVDirector::GetModEvents()
  149. {
  150. // game events relayed to spectator clients
  151. static const char *s_modevents[] =
  152. {
  153. "game_newmap",
  154. "hltv_status",
  155. "hltv_chat",
  156. "player_connect",
  157. "player_disconnect",
  158. "player_changeclass",
  159. "player_team",
  160. "player_info",
  161. "player_death",
  162. "player_chat",
  163. "player_spawn",
  164. "round_start",
  165. "round_end",
  166. "server_cvar",
  167. "server_spawn",
  168. // additional TF events:
  169. "controlpoint_starttouch",
  170. "controlpoint_endtouch",
  171. "ctf_flag_captured",
  172. "teamplay_broadcast_audio",
  173. "teamplay_capture_blocked",
  174. "teamplay_flag_event",
  175. "teamplay_game_over",
  176. "teamplay_point_captured",
  177. "teamplay_round_stalemate",
  178. "teamplay_round_start",
  179. "teamplay_round_win",
  180. "teamplay_timer_time_added",
  181. "teamplay_update_timer",
  182. "teamplay_win_panel",
  183. "training_complete",
  184. "tf_game_over",
  185. "object_destroyed",
  186. NULL
  187. };
  188. return s_modevents;
  189. }
  190. static CTFHLTVDirector s_HLTVDirector; // singleton
  191. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLTVDirector, IHLTVDirector, INTERFACEVERSION_HLTVDIRECTOR, s_HLTVDirector );
  192. CHLTVDirector* HLTVDirector()
  193. {
  194. return &s_HLTVDirector;
  195. }
  196. IGameSystem* HLTVDirectorSystem()
  197. {
  198. return &s_HLTVDirector;
  199. }