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.

983 lines
30 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "npcevent.h"
  8. #include "vehicle_base.h"
  9. #include "engine/IEngineSound.h"
  10. #include "in_buttons.h"
  11. #include "soundenvelope.h"
  12. #include "soundent.h"
  13. #include "physics_saverestore.h"
  14. #include "vphysics/constraints.h"
  15. #include "vcollide_parse.h"
  16. #include "ndebugoverlay.h"
  17. #include "hl2_player.h"
  18. #include "props.h"
  19. #include "vehicle_choreo_generic_shared.h"
  20. #include "ai_utils.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. #define VEHICLE_HITBOX_DRIVER 1
  24. #define CHOREO_VEHICLE_VIEW_FOV 90
  25. #define CHOREO_VEHICLE_VIEW_YAW_MIN -60
  26. #define CHOREO_VEHICLE_VIEW_YAW_MAX 60
  27. #define CHOREO_VEHICLE_VIEW_PITCH_MIN -90
  28. #define CHOREO_VEHICLE_VIEW_PITCH_MAX 38
  29. BEGIN_DATADESC_NO_BASE( vehicleview_t )
  30. DEFINE_FIELD( bClampEyeAngles, FIELD_BOOLEAN ),
  31. DEFINE_FIELD( flPitchCurveZero, FIELD_FLOAT ),
  32. DEFINE_FIELD( flPitchCurveLinear, FIELD_FLOAT ),
  33. DEFINE_FIELD( flRollCurveZero, FIELD_FLOAT ),
  34. DEFINE_FIELD( flRollCurveLinear, FIELD_FLOAT ),
  35. DEFINE_FIELD( flFOV, FIELD_FLOAT ),
  36. DEFINE_FIELD( flYawMin, FIELD_FLOAT ),
  37. DEFINE_FIELD( flYawMax, FIELD_FLOAT ),
  38. DEFINE_FIELD( flPitchMin, FIELD_FLOAT ),
  39. DEFINE_FIELD( flPitchMax, FIELD_FLOAT ),
  40. END_DATADESC()
  41. //
  42. // Anim events.
  43. //
  44. enum
  45. {
  46. AE_CHOREO_VEHICLE_OPEN = 1,
  47. AE_CHOREO_VEHICLE_CLOSE = 2,
  48. };
  49. extern ConVar g_debug_vehicledriver;
  50. class CPropVehicleChoreoGeneric;
  51. static const char *pChoreoGenericFollowerBoneNames[] =
  52. {
  53. "base",
  54. };
  55. //-----------------------------------------------------------------------------
  56. // Purpose: A KeyValues parse for vehicle sound blocks
  57. //-----------------------------------------------------------------------------
  58. class CVehicleChoreoViewParser : public IVPhysicsKeyHandler
  59. {
  60. public:
  61. CVehicleChoreoViewParser( void );
  62. private:
  63. virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue );
  64. virtual void SetDefaults( void *pData );
  65. };
  66. //-----------------------------------------------------------------------------
  67. // Purpose:
  68. //-----------------------------------------------------------------------------
  69. class CChoreoGenericServerVehicle : public CBaseServerVehicle
  70. {
  71. typedef CBaseServerVehicle BaseClass;
  72. // IServerVehicle
  73. public:
  74. void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL );
  75. virtual void ItemPostFrame( CBasePlayer *pPlayer );
  76. protected:
  77. CPropVehicleChoreoGeneric *GetVehicle( void );
  78. };
  79. //-----------------------------------------------------------------------------
  80. // Purpose:
  81. //-----------------------------------------------------------------------------
  82. class CPropVehicleChoreoGeneric : public CDynamicProp, public IDrivableVehicle
  83. {
  84. DECLARE_CLASS( CPropVehicleChoreoGeneric, CDynamicProp );
  85. public:
  86. DECLARE_DATADESC();
  87. DECLARE_SERVERCLASS();
  88. CPropVehicleChoreoGeneric( void )
  89. {
  90. m_ServerVehicle.SetVehicle( this );
  91. m_bIgnoreMoveParent = false;
  92. m_bForcePlayerEyePoint = false;
  93. }
  94. ~CPropVehicleChoreoGeneric( void )
  95. {
  96. }
  97. // CBaseEntity
  98. virtual void Precache( void );
  99. void Spawn( void );
  100. void Think(void);
  101. virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; };
  102. virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  103. virtual void DrawDebugGeometryOverlays( void );
  104. virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
  105. virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
  106. virtual int OnTakeDamage( const CTakeDamageInfo &info );
  107. void PlayerControlInit( CBasePlayer *pPlayer );
  108. void PlayerControlShutdown( void );
  109. void ResetUseKey( CBasePlayer *pPlayer );
  110. virtual bool OverridePropdata() { return true; }
  111. bool ParseViewParams( const char *pScriptName );
  112. void GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const;
  113. bool CreateVPhysics()
  114. {
  115. SetSolid(SOLID_VPHYSICS);
  116. SetMoveType(MOVETYPE_NONE);
  117. return true;
  118. }
  119. bool ShouldForceExit() { return m_bForcedExit; }
  120. void ClearForcedExit() { m_bForcedExit = false; }
  121. // CBaseAnimating
  122. void HandleAnimEvent( animevent_t *pEvent );
  123. // Inputs
  124. void InputEnterVehicleImmediate( inputdata_t &inputdata );
  125. void InputEnterVehicle( inputdata_t &inputdata );
  126. void InputExitVehicle( inputdata_t &inputdata );
  127. void InputLock( inputdata_t &inputdata );
  128. void InputUnlock( inputdata_t &inputdata );
  129. void InputOpen( inputdata_t &inputdata );
  130. void InputClose( inputdata_t &inputdata );
  131. void InputViewlock( inputdata_t &inputdata );
  132. bool ShouldIgnoreParent( void ) { return m_bIgnoreMoveParent; }
  133. // Tuned to match HL2s definition, but this should probably return false in all cases
  134. virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) { return (info.GetDamageType() & (DMG_BLAST|DMG_RADIATION)) == 0; }
  135. CNetworkHandle( CBasePlayer, m_hPlayer );
  136. CNetworkVarEmbedded( vehicleview_t, m_vehicleView );
  137. private:
  138. vehicleview_t m_savedVehicleView; // gets saved out for viewlock/unlock input
  139. // IDrivableVehicle
  140. public:
  141. virtual CBaseEntity *GetDriver( void );
  142. virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; }
  143. virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; }
  144. virtual bool CanEnterVehicle( CBaseEntity *pEntity );
  145. virtual bool CanExitVehicle( CBaseEntity *pEntity );
  146. virtual void SetVehicleEntryAnim( bool bOn );
  147. virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; }
  148. virtual void EnterVehicle( CBaseCombatCharacter *pPassenger );
  149. virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; }
  150. virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; }
  151. virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {}
  152. virtual void ExitVehicle( int nRole );
  153. virtual void ItemPostFrame( CBasePlayer *pPlayer ) {}
  154. virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {}
  155. virtual string_t GetVehicleScriptName() { return m_vehicleScript; }
  156. // If this is a vehicle, returns the vehicle interface
  157. virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; }
  158. bool ShouldCollide( int collisionGroup, int contentsMask ) const;
  159. bool m_bForcePlayerEyePoint; // Uses player's eyepoint instead of 'vehicle_driver_eyes' attachment
  160. protected:
  161. // Contained IServerVehicle
  162. CChoreoGenericServerVehicle m_ServerVehicle;
  163. private:
  164. // Entering / Exiting
  165. bool m_bLocked;
  166. CNetworkVar( bool, m_bEnterAnimOn );
  167. CNetworkVar( bool, m_bExitAnimOn );
  168. CNetworkVector( m_vecEyeExitEndpoint );
  169. bool m_bForcedExit;
  170. bool m_bIgnoreMoveParent;
  171. bool m_bIgnorePlayerCollisions;
  172. // Vehicle script filename
  173. string_t m_vehicleScript;
  174. COutputEvent m_playerOn;
  175. COutputEvent m_playerOff;
  176. COutputEvent m_OnOpen;
  177. COutputEvent m_OnClose;
  178. };
  179. LINK_ENTITY_TO_CLASS( prop_vehicle_choreo_generic, CPropVehicleChoreoGeneric );
  180. BEGIN_DATADESC( CPropVehicleChoreoGeneric )
  181. // Inputs
  182. DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ),
  183. DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ),
  184. DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicle", InputEnterVehicle ),
  185. DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicleImmediate", InputEnterVehicleImmediate ),
  186. DEFINE_INPUTFUNC( FIELD_VOID, "ExitVehicle", InputExitVehicle ),
  187. DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ),
  188. DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ),
  189. DEFINE_INPUTFUNC( FIELD_BOOLEAN, "Viewlock", InputViewlock ),
  190. // Keys
  191. DEFINE_EMBEDDED( m_ServerVehicle ),
  192. DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ),
  193. DEFINE_FIELD( m_bEnterAnimOn, FIELD_BOOLEAN ),
  194. DEFINE_FIELD( m_bExitAnimOn, FIELD_BOOLEAN ),
  195. DEFINE_FIELD( m_bForcedExit, FIELD_BOOLEAN ),
  196. DEFINE_FIELD( m_vecEyeExitEndpoint, FIELD_POSITION_VECTOR ),
  197. DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ),
  198. DEFINE_KEYFIELD( m_bLocked, FIELD_BOOLEAN, "vehiclelocked" ),
  199. DEFINE_KEYFIELD( m_bIgnoreMoveParent, FIELD_BOOLEAN, "ignoremoveparent" ),
  200. DEFINE_KEYFIELD( m_bIgnorePlayerCollisions, FIELD_BOOLEAN, "ignoreplayer" ),
  201. DEFINE_KEYFIELD( m_bForcePlayerEyePoint, FIELD_BOOLEAN, "useplayereyes" ),
  202. DEFINE_OUTPUT( m_playerOn, "PlayerOn" ),
  203. DEFINE_OUTPUT( m_playerOff, "PlayerOff" ),
  204. DEFINE_OUTPUT( m_OnOpen, "OnOpen" ),
  205. DEFINE_OUTPUT( m_OnClose, "OnClose" ),
  206. DEFINE_EMBEDDED( m_vehicleView ),
  207. DEFINE_EMBEDDED( m_savedVehicleView ),
  208. END_DATADESC()
  209. IMPLEMENT_SERVERCLASS_ST(CPropVehicleChoreoGeneric, DT_PropVehicleChoreoGeneric)
  210. SendPropEHandle(SENDINFO(m_hPlayer)),
  211. SendPropBool(SENDINFO(m_bEnterAnimOn)),
  212. SendPropBool(SENDINFO(m_bExitAnimOn)),
  213. SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD),
  214. SendPropBool( SENDINFO_STRUCTELEM( m_vehicleView.bClampEyeAngles ) ),
  215. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchCurveZero ) ),
  216. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchCurveLinear ) ),
  217. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flRollCurveZero ) ),
  218. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flRollCurveLinear ) ),
  219. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flFOV ) ),
  220. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flYawMin ) ),
  221. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flYawMax ) ),
  222. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchMin ) ),
  223. SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchMax ) ),
  224. END_SEND_TABLE();
  225. bool ShouldVehicleIgnoreEntity( CBaseEntity *pVehicle, CBaseEntity *pCollide )
  226. {
  227. if ( pCollide->GetParent() == pVehicle )
  228. return true;
  229. CPropVehicleChoreoGeneric *pChoreoVehicle = dynamic_cast <CPropVehicleChoreoGeneric *>( pVehicle );
  230. if ( pChoreoVehicle == NULL )
  231. return false;
  232. if ( pCollide == NULL )
  233. return false;
  234. if ( pChoreoVehicle->ShouldIgnoreParent() == false )
  235. return false;
  236. if ( pChoreoVehicle->GetMoveParent() == pCollide )
  237. return true;
  238. return false;
  239. }
  240. //------------------------------------------------
  241. // Precache
  242. //------------------------------------------------
  243. void CPropVehicleChoreoGeneric::Precache( void )
  244. {
  245. BaseClass::Precache();
  246. m_ServerVehicle.Initialize( STRING(m_vehicleScript) );
  247. m_ServerVehicle.UseLegacyExitChecks( true );
  248. }
  249. //------------------------------------------------
  250. // Spawn
  251. //------------------------------------------------
  252. void CPropVehicleChoreoGeneric::Spawn( void )
  253. {
  254. Precache();
  255. SetModel( STRING( GetModelName() ) );
  256. SetCollisionGroup( COLLISION_GROUP_VEHICLE );
  257. if ( GetSolid() != SOLID_NONE )
  258. {
  259. BaseClass::Spawn();
  260. }
  261. m_takedamage = DAMAGE_EVENTS_ONLY;
  262. SetNextThink( gpGlobals->curtime );
  263. ParseViewParams( STRING(m_vehicleScript) );
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Purpose:
  267. //-----------------------------------------------------------------------------
  268. void CPropVehicleChoreoGeneric::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
  269. {
  270. if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER )
  271. {
  272. if ( m_hPlayer != NULL )
  273. {
  274. m_hPlayer->TakeDamage( info );
  275. }
  276. }
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Purpose:
  280. //-----------------------------------------------------------------------------
  281. int CPropVehicleChoreoGeneric::OnTakeDamage( const CTakeDamageInfo &inputInfo )
  282. {
  283. CTakeDamageInfo info = inputInfo;
  284. info.ScaleDamage( 25 );
  285. // reset the damage
  286. info.SetDamage( inputInfo.GetDamage() );
  287. // Check to do damage to prisoner
  288. if ( m_hPlayer != NULL )
  289. {
  290. // Take no damage from physics damages
  291. if ( info.GetDamageType() & DMG_CRUSH )
  292. return 0;
  293. // Take the damage
  294. m_hPlayer->TakeDamage( info );
  295. }
  296. return 0;
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Purpose:
  300. //-----------------------------------------------------------------------------
  301. Vector CPropVehicleChoreoGeneric::BodyTarget( const Vector &posSrc, bool bNoisy )
  302. {
  303. Vector shotPos;
  304. int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes");
  305. GetAttachment( eyeAttachmentIndex, shotPos );
  306. if ( bNoisy )
  307. {
  308. shotPos[0] += random->RandomFloat( -8.0f, 8.0f );
  309. shotPos[1] += random->RandomFloat( -8.0f, 8.0f );
  310. shotPos[2] += random->RandomFloat( -8.0f, 8.0f );
  311. }
  312. return shotPos;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Purpose:
  316. //-----------------------------------------------------------------------------
  317. void CPropVehicleChoreoGeneric::Think(void)
  318. {
  319. SetNextThink( gpGlobals->curtime + 0.1 );
  320. if ( GetDriver() )
  321. {
  322. BaseClass::Think();
  323. // If the enter or exit animation has finished, tell the server vehicle
  324. if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) )
  325. {
  326. GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true );
  327. }
  328. }
  329. StudioFrameAdvance();
  330. DispatchAnimEvents( this );
  331. }
  332. //------------------------------------------------------------------------------
  333. // Purpose:
  334. //------------------------------------------------------------------------------
  335. void CPropVehicleChoreoGeneric::InputOpen( inputdata_t &inputdata )
  336. {
  337. int nSequence = LookupSequence( "open" );
  338. // Set to the desired anim, or default anim if the desired is not present
  339. if ( nSequence > ACTIVITY_NOT_AVAILABLE )
  340. {
  341. SetCycle( 0 );
  342. m_flAnimTime = gpGlobals->curtime;
  343. ResetSequence( nSequence );
  344. ResetClientsideFrame();
  345. }
  346. else
  347. {
  348. // Not available try to get default anim
  349. Msg( "Choreo Generic Vehicle %s: missing open sequence\n", GetDebugName() );
  350. SetSequence( 0 );
  351. }
  352. }
  353. //------------------------------------------------------------------------------
  354. // Purpose:
  355. //------------------------------------------------------------------------------
  356. void CPropVehicleChoreoGeneric::InputClose( inputdata_t &inputdata )
  357. {
  358. if ( m_bLocked || m_bEnterAnimOn )
  359. return;
  360. int nSequence = LookupSequence( "close" );
  361. // Set to the desired anim, or default anim if the desired is not present
  362. if ( nSequence > ACTIVITY_NOT_AVAILABLE )
  363. {
  364. SetCycle( 0 );
  365. m_flAnimTime = gpGlobals->curtime;
  366. ResetSequence( nSequence );
  367. ResetClientsideFrame();
  368. }
  369. else
  370. {
  371. // Not available try to get default anim
  372. Msg( "Choreo Generic Vehicle %s: missing close sequence\n", GetDebugName() );
  373. SetSequence( 0 );
  374. }
  375. }
  376. //------------------------------------------------------------------------------
  377. // Purpose:
  378. //------------------------------------------------------------------------------
  379. void CPropVehicleChoreoGeneric::InputViewlock( inputdata_t &inputdata )
  380. {
  381. if (inputdata.value.Bool()) // lock
  382. {
  383. if (m_savedVehicleView.flFOV == 0) // not already locked
  384. {
  385. m_savedVehicleView = m_vehicleView;
  386. m_vehicleView.flYawMax = m_vehicleView.flYawMin = m_vehicleView.flPitchMin = m_vehicleView.flPitchMax = 0.0f;
  387. }
  388. }
  389. else
  390. { //unlock
  391. Assert(m_savedVehicleView.flFOV); // is nonzero if something is saved, is zero if nothing was saved.
  392. if (m_savedVehicleView.flFOV)
  393. {
  394. // m_vehicleView = m_savedVehicleView;
  395. m_savedVehicleView.flFOV = 0;
  396. m_vehicleView.flYawMax.Set( m_savedVehicleView.flYawMax);
  397. m_vehicleView.flYawMin.Set( m_savedVehicleView.flYawMin);
  398. m_vehicleView.flPitchMin.Set(m_savedVehicleView.flPitchMin);
  399. m_vehicleView.flPitchMax.Set(m_savedVehicleView.flPitchMax);
  400. /* // note: the straight assignments, as in the lower two lines below, do not call the = overload and thus are never transmitted!
  401. m_vehicleView.flYawMax = 50; // m_savedVehicleView.flYawMax;
  402. m_vehicleView.flYawMin = -50; // m_savedVehicleView.flYawMin;
  403. m_vehicleView.flPitchMin = m_savedVehicleView.flPitchMin;
  404. m_vehicleView.flPitchMax = m_savedVehicleView.flPitchMax;
  405. */
  406. }
  407. }
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Purpose:
  411. //-----------------------------------------------------------------------------
  412. void CPropVehicleChoreoGeneric::HandleAnimEvent( animevent_t *pEvent )
  413. {
  414. if ( pEvent->event == AE_CHOREO_VEHICLE_OPEN )
  415. {
  416. m_OnOpen.FireOutput( this, this );
  417. m_bLocked = false;
  418. }
  419. else if ( pEvent->event == AE_CHOREO_VEHICLE_CLOSE )
  420. {
  421. m_OnClose.FireOutput( this, this );
  422. m_bLocked = true;
  423. }
  424. }
  425. //-----------------------------------------------------------------------------
  426. // Purpose:
  427. //-----------------------------------------------------------------------------
  428. void CPropVehicleChoreoGeneric::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  429. {
  430. CBasePlayer *pPlayer = ToBasePlayer( pActivator );
  431. if ( !pPlayer )
  432. return;
  433. ResetUseKey( pPlayer );
  434. GetServerVehicle()->HandlePassengerEntry( pPlayer, (value > 0) );
  435. }
  436. //-----------------------------------------------------------------------------
  437. // Purpose: Return true of the player's allowed to enter / exit the vehicle
  438. //-----------------------------------------------------------------------------
  439. bool CPropVehicleChoreoGeneric::CanEnterVehicle( CBaseEntity *pEntity )
  440. {
  441. // Prevent entering if the vehicle's being driven by an NPC
  442. if ( GetDriver() && GetDriver() != pEntity )
  443. return false;
  444. // Prevent entering if the vehicle's locked
  445. return !m_bLocked;
  446. }
  447. //-----------------------------------------------------------------------------
  448. // Purpose: Return true of the player is allowed to exit the vehicle.
  449. //-----------------------------------------------------------------------------
  450. bool CPropVehicleChoreoGeneric::CanExitVehicle( CBaseEntity *pEntity )
  451. {
  452. // Prevent exiting if the vehicle's locked, rotating, or playing an entry/exit anim.
  453. return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && !m_bEnterAnimOn && !m_bExitAnimOn );
  454. }
  455. //-----------------------------------------------------------------------------
  456. // Purpose: Override base class to add display
  457. //-----------------------------------------------------------------------------
  458. void CPropVehicleChoreoGeneric::DrawDebugGeometryOverlays(void)
  459. {
  460. // Draw if BBOX is on
  461. if ( m_debugOverlays & OVERLAY_BBOX_BIT )
  462. {
  463. }
  464. BaseClass::DrawDebugGeometryOverlays();
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Purpose:
  468. //-----------------------------------------------------------------------------
  469. void CPropVehicleChoreoGeneric::EnterVehicle( CBaseCombatCharacter *pPassenger )
  470. {
  471. if ( pPassenger == NULL )
  472. return;
  473. CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
  474. if ( pPlayer != NULL )
  475. {
  476. // Remove any player who may be in the vehicle at the moment
  477. if ( m_hPlayer )
  478. {
  479. ExitVehicle( VEHICLE_ROLE_DRIVER );
  480. }
  481. m_hPlayer = pPlayer;
  482. m_playerOn.FireOutput( pPlayer, this, 0 );
  483. m_ServerVehicle.SoundStart();
  484. }
  485. else
  486. {
  487. // NPCs not supported yet - jdw
  488. Assert( 0 );
  489. }
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Purpose:
  493. //-----------------------------------------------------------------------------
  494. void CPropVehicleChoreoGeneric::SetVehicleEntryAnim( bool bOn )
  495. {
  496. m_bEnterAnimOn = bOn;
  497. }
  498. //-----------------------------------------------------------------------------
  499. // Purpose:
  500. //-----------------------------------------------------------------------------
  501. void CPropVehicleChoreoGeneric::ExitVehicle( int nRole )
  502. {
  503. CBasePlayer *pPlayer = m_hPlayer;
  504. if ( !pPlayer )
  505. return;
  506. m_hPlayer = NULL;
  507. ResetUseKey( pPlayer );
  508. m_playerOff.FireOutput( pPlayer, this, 0 );
  509. m_bEnterAnimOn = false;
  510. m_ServerVehicle.SoundShutdown( 1.0 );
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Purpose:
  514. //-----------------------------------------------------------------------------
  515. void CPropVehicleChoreoGeneric::ResetUseKey( CBasePlayer *pPlayer )
  516. {
  517. pPlayer->m_afButtonPressed &= ~IN_USE;
  518. }
  519. //-----------------------------------------------------------------------------
  520. // Purpose: Vehicles are permanently oriented off angle for vphysics.
  521. //-----------------------------------------------------------------------------
  522. void CPropVehicleChoreoGeneric::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const
  523. {
  524. // This call is necessary to cause m_rgflCoordinateFrame to be recomputed
  525. const matrix3x4_t &entityToWorld = EntityToWorldTransform();
  526. if (pForward != NULL)
  527. {
  528. MatrixGetColumn( entityToWorld, 1, *pForward );
  529. }
  530. if (pRight != NULL)
  531. {
  532. MatrixGetColumn( entityToWorld, 0, *pRight );
  533. }
  534. if (pUp != NULL)
  535. {
  536. MatrixGetColumn( entityToWorld, 2, *pUp );
  537. }
  538. }
  539. //-----------------------------------------------------------------------------
  540. // Purpose:
  541. //-----------------------------------------------------------------------------
  542. CBaseEntity *CPropVehicleChoreoGeneric::GetDriver( void )
  543. {
  544. return m_hPlayer;
  545. }
  546. //-----------------------------------------------------------------------------
  547. // Purpose: Prevent the player from entering / exiting the vehicle
  548. //-----------------------------------------------------------------------------
  549. void CPropVehicleChoreoGeneric::InputLock( inputdata_t &inputdata )
  550. {
  551. m_bLocked = true;
  552. }
  553. //-----------------------------------------------------------------------------
  554. // Purpose: Allow the player to enter / exit the vehicle
  555. //-----------------------------------------------------------------------------
  556. void CPropVehicleChoreoGeneric::InputUnlock( inputdata_t &inputdata )
  557. {
  558. m_bLocked = false;
  559. }
  560. //-----------------------------------------------------------------------------
  561. // Purpose: Force the player to enter the vehicle.
  562. //-----------------------------------------------------------------------------
  563. void CPropVehicleChoreoGeneric::InputEnterVehicle( inputdata_t &inputdata )
  564. {
  565. if ( m_bEnterAnimOn )
  566. return;
  567. // Try the activator first & use them if they are a player.
  568. CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator );
  569. if ( pPlayer == NULL )
  570. {
  571. // Activator was not a player, just grab the single-player player.
  572. pPlayer = AI_GetSinglePlayer();
  573. if ( pPlayer == NULL )
  574. return;
  575. }
  576. // Force us to drop anything we're holding
  577. pPlayer->ForceDropOfCarriedPhysObjects();
  578. // FIXME: I hate code like this. I should really add a parameter to HandlePassengerEntry
  579. // to allow entry into locked vehicles
  580. bool bWasLocked = m_bLocked;
  581. m_bLocked = false;
  582. GetServerVehicle()->HandlePassengerEntry( pPlayer, true );
  583. m_bLocked = bWasLocked;
  584. }
  585. //-----------------------------------------------------------------------------
  586. // Purpose:
  587. // Input : &inputdata -
  588. //-----------------------------------------------------------------------------
  589. void CPropVehicleChoreoGeneric::InputEnterVehicleImmediate( inputdata_t &inputdata )
  590. {
  591. if ( m_bEnterAnimOn )
  592. return;
  593. // Try the activator first & use them if they are a player.
  594. CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator );
  595. if ( pPlayer == NULL )
  596. {
  597. // Activator was not a player, just grab the singleplayer player.
  598. pPlayer = AI_GetSinglePlayer();
  599. if ( pPlayer == NULL )
  600. return;
  601. }
  602. if ( pPlayer->IsInAVehicle() )
  603. {
  604. // Force the player out of whatever vehicle they are in.
  605. pPlayer->LeaveVehicle();
  606. }
  607. // Force us to drop anything we're holding
  608. pPlayer->ForceDropOfCarriedPhysObjects();
  609. pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER );
  610. }
  611. //-----------------------------------------------------------------------------
  612. // Purpose: Force the player to exit the vehicle.
  613. //-----------------------------------------------------------------------------
  614. void CPropVehicleChoreoGeneric::InputExitVehicle( inputdata_t &inputdata )
  615. {
  616. m_bForcedExit = true;
  617. }
  618. //-----------------------------------------------------------------------------
  619. // Purpose: Parses the vehicle's script for the vehicle view parameters
  620. //-----------------------------------------------------------------------------
  621. bool CPropVehicleChoreoGeneric::ParseViewParams( const char *pScriptName )
  622. {
  623. byte *pFile = UTIL_LoadFileForMe( pScriptName, NULL );
  624. if ( !pFile )
  625. return false;
  626. IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( (char *)pFile );
  627. CVehicleChoreoViewParser viewParser;
  628. while ( !pParse->Finished() )
  629. {
  630. const char *pBlock = pParse->GetCurrentBlockName();
  631. if ( !strcmpi( pBlock, "vehicle_view" ) )
  632. {
  633. pParse->ParseCustom( &m_vehicleView, &viewParser );
  634. }
  635. else
  636. {
  637. pParse->SkipBlock();
  638. }
  639. }
  640. physcollision->VPhysicsKeyParserDestroy( pParse );
  641. UTIL_FreeFile( pFile );
  642. Precache();
  643. return true;
  644. }
  645. //========================================================================================================================================
  646. // CRANE VEHICLE SERVER VEHICLE
  647. //========================================================================================================================================
  648. CPropVehicleChoreoGeneric *CChoreoGenericServerVehicle::GetVehicle( void )
  649. {
  650. return (CPropVehicleChoreoGeneric *)GetDrivableVehicle();
  651. }
  652. //-----------------------------------------------------------------------------
  653. // Purpose:
  654. // Input : pPlayer -
  655. //-----------------------------------------------------------------------------
  656. void CChoreoGenericServerVehicle::ItemPostFrame( CBasePlayer *player )
  657. {
  658. Assert( player == GetDriver() );
  659. GetDrivableVehicle()->ItemPostFrame( player );
  660. if (( player->m_afButtonPressed & IN_USE ) || GetVehicle()->ShouldForceExit() )
  661. {
  662. GetVehicle()->ClearForcedExit();
  663. if ( GetDrivableVehicle()->CanExitVehicle(player) )
  664. {
  665. // Let the vehicle try to play the exit animation
  666. if ( !HandlePassengerExit( player ) && ( player != NULL ) )
  667. {
  668. player->PlayUseDenySound();
  669. }
  670. }
  671. }
  672. }
  673. //-----------------------------------------------------------------------------
  674. // Purpose:
  675. //-----------------------------------------------------------------------------
  676. void CChoreoGenericServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ )
  677. {
  678. // FIXME: This needs to be reconciled with the other versions of this function!
  679. Assert( nRole == VEHICLE_ROLE_DRIVER );
  680. CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() );
  681. Assert( pPlayer );
  682. // Use the player's eyes instead of the attachment point
  683. if ( GetVehicle()->m_bForcePlayerEyePoint )
  684. {
  685. // Call to BaseClass because CBasePlayer::EyePosition calls this function.
  686. *pAbsOrigin = pPlayer->CBaseCombatCharacter::EyePosition();
  687. *pAbsAngles = pPlayer->CBaseCombatCharacter::EyeAngles();
  688. return;
  689. }
  690. *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter.
  691. float flPitchFactor = 1.0;
  692. matrix3x4_t vehicleEyePosToWorld;
  693. Vector vehicleEyeOrigin;
  694. QAngle vehicleEyeAngles;
  695. GetVehicle()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles );
  696. AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld );
  697. // Compute the relative rotation between the unperterbed eye attachment + the eye angles
  698. matrix3x4_t cameraToWorld;
  699. AngleMatrix( *pAbsAngles, cameraToWorld );
  700. matrix3x4_t worldToEyePos;
  701. MatrixInvert( vehicleEyePosToWorld, worldToEyePos );
  702. matrix3x4_t vehicleCameraToEyePos;
  703. ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos );
  704. // Now perterb the attachment point
  705. vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x );
  706. vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z );
  707. AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld );
  708. // Now treat the relative eye angles as being relative to this new, perterbed view position...
  709. matrix3x4_t newCameraToWorld;
  710. ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld );
  711. // output new view abs angles
  712. MatrixAngles( newCameraToWorld, *pAbsAngles );
  713. // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics
  714. MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin );
  715. }
  716. bool CPropVehicleChoreoGeneric::ShouldCollide( int collisionGroup, int contentsMask ) const
  717. {
  718. if ( m_bIgnorePlayerCollisions == true )
  719. {
  720. if ( collisionGroup == COLLISION_GROUP_PLAYER || collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT )
  721. return false;
  722. }
  723. return BaseClass::ShouldCollide( collisionGroup, contentsMask );
  724. }
  725. CVehicleChoreoViewParser::CVehicleChoreoViewParser( void )
  726. {
  727. }
  728. //-----------------------------------------------------------------------------
  729. // Purpose:
  730. //-----------------------------------------------------------------------------
  731. void CVehicleChoreoViewParser::ParseKeyValue( void *pData, const char *pKey, const char *pValue )
  732. {
  733. vehicleview_t *pView = (vehicleview_t *)pData;
  734. // New gear?
  735. if ( !strcmpi( pKey, "clamp" ) )
  736. {
  737. pView->bClampEyeAngles = !!atoi( pValue );
  738. }
  739. else if ( !strcmpi( pKey, "pitchcurvezero" ) )
  740. {
  741. pView->flPitchCurveZero = atof( pValue );
  742. }
  743. else if ( !strcmpi( pKey, "pitchcurvelinear" ) )
  744. {
  745. pView->flPitchCurveLinear = atof( pValue );
  746. }
  747. else if ( !strcmpi( pKey, "rollcurvezero" ) )
  748. {
  749. pView->flRollCurveZero = atof( pValue );
  750. }
  751. else if ( !strcmpi( pKey, "rollcurvelinear" ) )
  752. {
  753. pView->flRollCurveLinear = atof( pValue );
  754. }
  755. else if ( !strcmpi( pKey, "yawmin" ) )
  756. {
  757. pView->flYawMin = atof( pValue );
  758. }
  759. else if ( !strcmpi( pKey, "yawmax" ) )
  760. {
  761. pView->flYawMax = atof( pValue );
  762. }
  763. else if ( !strcmpi( pKey, "pitchmin" ) )
  764. {
  765. pView->flPitchMin = atof( pValue );
  766. }
  767. else if ( !strcmpi( pKey, "pitchmax" ) )
  768. {
  769. pView->flPitchMax = atof( pValue );
  770. }
  771. else if ( !strcmpi( pKey, "fov" ) )
  772. {
  773. pView->flFOV = atof( pValue );
  774. }
  775. }
  776. //-----------------------------------------------------------------------------
  777. // Purpose:
  778. //-----------------------------------------------------------------------------
  779. void CVehicleChoreoViewParser::SetDefaults( void *pData )
  780. {
  781. vehicleview_t *pView = (vehicleview_t *)pData;
  782. pView->bClampEyeAngles = true;
  783. pView->flPitchCurveZero = PITCH_CURVE_ZERO;
  784. pView->flPitchCurveLinear = PITCH_CURVE_LINEAR;
  785. pView->flRollCurveZero = ROLL_CURVE_ZERO;
  786. pView->flRollCurveLinear = ROLL_CURVE_LINEAR;
  787. pView->flFOV = CHOREO_VEHICLE_VIEW_FOV;
  788. pView->flYawMin = CHOREO_VEHICLE_VIEW_YAW_MIN;
  789. pView->flYawMax = CHOREO_VEHICLE_VIEW_YAW_MAX;
  790. pView->flPitchMin = CHOREO_VEHICLE_VIEW_PITCH_MIN;
  791. pView->flPitchMax = CHOREO_VEHICLE_VIEW_PITCH_MAX;
  792. }