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.

735 lines
22 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. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. #define VEHICLE_HITBOX_DRIVER 1
  22. //
  23. // Anim events.
  24. //
  25. enum
  26. {
  27. AE_POD_OPEN = 1, // The pod is now open and can be entered or exited.
  28. AE_POD_CLOSE = 2, // The pod is now closed and cannot be entered or exited.
  29. };
  30. extern ConVar g_debug_vehicledriver;
  31. class CPropVehiclePrisonerPod;
  32. // Pod bones that have physics followers
  33. static const char *pPodFollowerBoneNames[] =
  34. {
  35. "base",
  36. };
  37. //-----------------------------------------------------------------------------
  38. // Purpose:
  39. //-----------------------------------------------------------------------------
  40. class CPrisonerPodServerVehicle : public CBaseServerVehicle
  41. {
  42. typedef CBaseServerVehicle BaseClass;
  43. // IServerVehicle
  44. public:
  45. void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL );
  46. virtual void ItemPostFrame( CBasePlayer *pPlayer );
  47. virtual bool IsPassengerEntering( void ) { return false; } // NOTE: This mimics the scenario HL2 would have seen
  48. virtual bool IsPassengerExiting( void ) { return false; }
  49. protected:
  50. CPropVehiclePrisonerPod *GetPod( void );
  51. };
  52. //-----------------------------------------------------------------------------
  53. // Purpose:
  54. //-----------------------------------------------------------------------------
  55. class CPropVehiclePrisonerPod : public CPhysicsProp, public IDrivableVehicle
  56. {
  57. DECLARE_CLASS( CPropVehiclePrisonerPod, CPhysicsProp );
  58. public:
  59. DECLARE_DATADESC();
  60. DECLARE_SERVERCLASS();
  61. CPropVehiclePrisonerPod( void )
  62. {
  63. m_ServerVehicle.SetVehicle( this );
  64. }
  65. ~CPropVehiclePrisonerPod( void )
  66. {
  67. }
  68. // CBaseEntity
  69. virtual void Precache( void );
  70. void Spawn( void );
  71. void Think(void);
  72. virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; };
  73. virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  74. virtual void DrawDebugGeometryOverlays( void );
  75. virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
  76. virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
  77. virtual int OnTakeDamage( const CTakeDamageInfo &info );
  78. void PlayerControlInit( CBasePlayer *pPlayer );
  79. void PlayerControlShutdown( void );
  80. void ResetUseKey( CBasePlayer *pPlayer );
  81. virtual bool OverridePropdata() { return true; }
  82. void GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const;
  83. bool ShouldForceExit() { return m_bForcedExit; }
  84. void ClearForcedExit() { m_bForcedExit = false; }
  85. // CBaseAnimating
  86. void HandleAnimEvent( animevent_t *pEvent );
  87. // Inputs
  88. void InputEnterVehicleImmediate( inputdata_t &inputdata );
  89. void InputEnterVehicle( inputdata_t &inputdata );
  90. void InputExitVehicle( inputdata_t &inputdata );
  91. void InputLock( inputdata_t &inputdata );
  92. void InputUnlock( inputdata_t &inputdata );
  93. void InputOpen( inputdata_t &inputdata );
  94. void InputClose( inputdata_t &inputdata );
  95. CNetworkHandle( CBasePlayer, m_hPlayer );
  96. // IDrivableVehicle
  97. public:
  98. virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info )
  99. {
  100. if ( info.GetDamageType() & DMG_VEHICLE )
  101. return true;
  102. return (info.GetDamageType() & (DMG_RADIATION|DMG_BLAST) ) == 0;
  103. }
  104. virtual CBaseEntity *GetDriver( void );
  105. virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; }
  106. virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; }
  107. virtual bool CanEnterVehicle( CBaseEntity *pEntity );
  108. virtual bool CanExitVehicle( CBaseEntity *pEntity );
  109. virtual void SetVehicleEntryAnim( bool bOn );
  110. virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; }
  111. virtual void EnterVehicle( CBaseCombatCharacter *pPassenger );
  112. virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; }
  113. virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; }
  114. virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {}
  115. virtual void ExitVehicle( int nRole );
  116. virtual void ItemPostFrame( CBasePlayer *pPlayer ) {}
  117. virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {}
  118. virtual string_t GetVehicleScriptName() { return m_vehicleScript; }
  119. // If this is a vehicle, returns the vehicle interface
  120. virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; }
  121. protected:
  122. // Contained IServerVehicle
  123. CPrisonerPodServerVehicle m_ServerVehicle;
  124. private:
  125. // Entering / Exiting
  126. bool m_bLocked;
  127. CNetworkVar( bool, m_bEnterAnimOn );
  128. CNetworkVar( bool, m_bExitAnimOn );
  129. CNetworkVector( m_vecEyeExitEndpoint );
  130. bool m_bForcedExit;
  131. // Vehicle script filename
  132. string_t m_vehicleScript;
  133. COutputEvent m_playerOn;
  134. COutputEvent m_playerOff;
  135. COutputEvent m_OnOpen;
  136. COutputEvent m_OnClose;
  137. };
  138. LINK_ENTITY_TO_CLASS( prop_vehicle_prisoner_pod, CPropVehiclePrisonerPod );
  139. BEGIN_DATADESC( CPropVehiclePrisonerPod )
  140. // Inputs
  141. DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ),
  142. DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ),
  143. DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicle", InputEnterVehicle ),
  144. DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicleImmediate", InputEnterVehicleImmediate ),
  145. DEFINE_INPUTFUNC( FIELD_VOID, "ExitVehicle", InputExitVehicle ),
  146. DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ),
  147. DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ),
  148. // Keys
  149. DEFINE_EMBEDDED( m_ServerVehicle ),
  150. DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ),
  151. DEFINE_FIELD( m_bEnterAnimOn, FIELD_BOOLEAN ),
  152. DEFINE_FIELD( m_bExitAnimOn, FIELD_BOOLEAN ),
  153. DEFINE_FIELD( m_bForcedExit, FIELD_BOOLEAN ),
  154. DEFINE_FIELD( m_vecEyeExitEndpoint, FIELD_POSITION_VECTOR ),
  155. DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ),
  156. DEFINE_KEYFIELD( m_bLocked, FIELD_BOOLEAN, "vehiclelocked" ),
  157. DEFINE_OUTPUT( m_playerOn, "PlayerOn" ),
  158. DEFINE_OUTPUT( m_playerOff, "PlayerOff" ),
  159. DEFINE_OUTPUT( m_OnOpen, "OnOpen" ),
  160. DEFINE_OUTPUT( m_OnClose, "OnClose" ),
  161. END_DATADESC()
  162. IMPLEMENT_SERVERCLASS_ST(CPropVehiclePrisonerPod, DT_PropVehiclePrisonerPod)
  163. SendPropEHandle(SENDINFO(m_hPlayer)),
  164. SendPropBool(SENDINFO(m_bEnterAnimOn)),
  165. SendPropBool(SENDINFO(m_bExitAnimOn)),
  166. SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD),
  167. END_SEND_TABLE();
  168. //------------------------------------------------
  169. // Precache
  170. //------------------------------------------------
  171. void CPropVehiclePrisonerPod::Precache( void )
  172. {
  173. BaseClass::Precache();
  174. PrecacheScriptSound( "d3_citadel.pod_open" );
  175. PrecacheScriptSound( "d3_citadel.pod_close" );
  176. m_ServerVehicle.Initialize( STRING(m_vehicleScript) );
  177. }
  178. //------------------------------------------------
  179. // Spawn
  180. //------------------------------------------------
  181. void CPropVehiclePrisonerPod::Spawn( void )
  182. {
  183. Precache();
  184. SetModel( STRING( GetModelName() ) );
  185. SetCollisionGroup( COLLISION_GROUP_VEHICLE );
  186. BaseClass::Spawn();
  187. m_takedamage = DAMAGE_EVENTS_ONLY;
  188. SetNextThink( gpGlobals->curtime );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose:
  192. //-----------------------------------------------------------------------------
  193. void CPropVehiclePrisonerPod::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
  194. {
  195. if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER )
  196. {
  197. if ( m_hPlayer != NULL )
  198. {
  199. m_hPlayer->TakeDamage( info );
  200. }
  201. }
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Purpose:
  205. //-----------------------------------------------------------------------------
  206. int CPropVehiclePrisonerPod::OnTakeDamage( const CTakeDamageInfo &inputInfo )
  207. {
  208. // Do scaled up physics damage to the pod
  209. CTakeDamageInfo info = inputInfo;
  210. info.ScaleDamage( 25 );
  211. // reset the damage
  212. info.SetDamage( inputInfo.GetDamage() );
  213. // Check to do damage to prisoner
  214. if ( m_hPlayer != NULL )
  215. {
  216. // Take no damage from physics damages
  217. if ( info.GetDamageType() & DMG_CRUSH )
  218. return 0;
  219. // Take the damage
  220. m_hPlayer->TakeDamage( info );
  221. }
  222. return 0;
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose:
  226. //-----------------------------------------------------------------------------
  227. Vector CPropVehiclePrisonerPod::BodyTarget( const Vector &posSrc, bool bNoisy )
  228. {
  229. Vector shotPos;
  230. matrix3x4_t matrix;
  231. int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes");
  232. GetAttachment( eyeAttachmentIndex, matrix );
  233. MatrixGetColumn( matrix, 3, shotPos );
  234. if ( bNoisy )
  235. {
  236. shotPos[0] += random->RandomFloat( -8.0f, 8.0f );
  237. shotPos[1] += random->RandomFloat( -8.0f, 8.0f );
  238. shotPos[2] += random->RandomFloat( -8.0f, 8.0f );
  239. }
  240. return shotPos;
  241. }
  242. //-----------------------------------------------------------------------------
  243. // Purpose:
  244. //-----------------------------------------------------------------------------
  245. void CPropVehiclePrisonerPod::Think(void)
  246. {
  247. SetNextThink( gpGlobals->curtime + 0.1 );
  248. if ( GetDriver() )
  249. {
  250. BaseClass::Think();
  251. // If the enter or exit animation has finished, tell the server vehicle
  252. if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) )
  253. {
  254. GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true );
  255. }
  256. }
  257. StudioFrameAdvance();
  258. DispatchAnimEvents( this );
  259. }
  260. //------------------------------------------------------------------------------
  261. // Purpose:
  262. //------------------------------------------------------------------------------
  263. void CPropVehiclePrisonerPod::InputOpen( inputdata_t &inputdata )
  264. {
  265. int nSequence = LookupSequence( "open" );
  266. // Set to the desired anim, or default anim if the desired is not present
  267. if ( nSequence > ACTIVITY_NOT_AVAILABLE )
  268. {
  269. SetCycle( 0 );
  270. m_flAnimTime = gpGlobals->curtime;
  271. ResetSequence( nSequence );
  272. ResetClientsideFrame();
  273. EmitSound( "d3_citadel.pod_open" );
  274. }
  275. else
  276. {
  277. // Not available try to get default anim
  278. Msg( "Prisoner pod %s: missing open sequence\n", GetDebugName() );
  279. SetSequence( 0 );
  280. }
  281. }
  282. //------------------------------------------------------------------------------
  283. // Purpose:
  284. //------------------------------------------------------------------------------
  285. void CPropVehiclePrisonerPod::InputClose( inputdata_t &inputdata )
  286. {
  287. // The enter anim closes the pod, so don't do this redundantly!
  288. if ( m_bLocked || m_bEnterAnimOn )
  289. return;
  290. int nSequence = LookupSequence( "close" );
  291. // Set to the desired anim, or default anim if the desired is not present
  292. if ( nSequence > ACTIVITY_NOT_AVAILABLE )
  293. {
  294. SetCycle( 0 );
  295. m_flAnimTime = gpGlobals->curtime;
  296. ResetSequence( nSequence );
  297. ResetClientsideFrame();
  298. EmitSound( "d3_citadel.pod_close" );
  299. }
  300. else
  301. {
  302. // Not available try to get default anim
  303. Msg( "Prisoner pod %s: missing close sequence\n", GetDebugName() );
  304. SetSequence( 0 );
  305. }
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose:
  309. //-----------------------------------------------------------------------------
  310. void CPropVehiclePrisonerPod::HandleAnimEvent( animevent_t *pEvent )
  311. {
  312. if ( pEvent->event == AE_POD_OPEN )
  313. {
  314. m_OnOpen.FireOutput( this, this );
  315. m_bLocked = false;
  316. }
  317. else if ( pEvent->event == AE_POD_CLOSE )
  318. {
  319. m_OnClose.FireOutput( this, this );
  320. m_bLocked = true;
  321. }
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Purpose:
  325. //-----------------------------------------------------------------------------
  326. void CPropVehiclePrisonerPod::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  327. {
  328. CBasePlayer *pPlayer = ToBasePlayer( pActivator );
  329. if ( !pPlayer )
  330. return;
  331. ResetUseKey( pPlayer );
  332. GetServerVehicle()->HandlePassengerEntry( pPlayer, (value > 0) );
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose: Return true of the player's allowed to enter / exit the vehicle
  336. //-----------------------------------------------------------------------------
  337. bool CPropVehiclePrisonerPod::CanEnterVehicle( CBaseEntity *pEntity )
  338. {
  339. // Prevent entering if the vehicle's being driven by an NPC
  340. if ( GetDriver() && GetDriver() != pEntity )
  341. return false;
  342. // Prevent entering if the vehicle's locked
  343. return !m_bLocked;
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Purpose: Return true of the player is allowed to exit the vehicle.
  347. //-----------------------------------------------------------------------------
  348. bool CPropVehiclePrisonerPod::CanExitVehicle( CBaseEntity *pEntity )
  349. {
  350. // Prevent exiting if the vehicle's locked, rotating, or playing an entry/exit anim.
  351. return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && !m_bEnterAnimOn && !m_bExitAnimOn );
  352. }
  353. //-----------------------------------------------------------------------------
  354. // Purpose: Override base class to add display
  355. //-----------------------------------------------------------------------------
  356. void CPropVehiclePrisonerPod::DrawDebugGeometryOverlays(void)
  357. {
  358. // Draw if BBOX is on
  359. if ( m_debugOverlays & OVERLAY_BBOX_BIT )
  360. {
  361. }
  362. BaseClass::DrawDebugGeometryOverlays();
  363. }
  364. //-----------------------------------------------------------------------------
  365. // Purpose:
  366. //-----------------------------------------------------------------------------
  367. void CPropVehiclePrisonerPod::EnterVehicle( CBaseCombatCharacter *pPassenger )
  368. {
  369. if ( pPassenger == NULL )
  370. return;
  371. CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
  372. if ( pPlayer != NULL )
  373. {
  374. // Remove any player who may be in the vehicle at the moment
  375. if ( m_hPlayer )
  376. {
  377. ExitVehicle( VEHICLE_ROLE_DRIVER );
  378. }
  379. m_hPlayer = pPlayer;
  380. m_playerOn.FireOutput( pPlayer, this, 0 );
  381. m_ServerVehicle.SoundStart();
  382. }
  383. else
  384. {
  385. // NPCs are not supported yet - jdw
  386. Assert( 0 );
  387. }
  388. }
  389. //-----------------------------------------------------------------------------
  390. // Purpose:
  391. //-----------------------------------------------------------------------------
  392. void CPropVehiclePrisonerPod::SetVehicleEntryAnim( bool bOn )
  393. {
  394. m_bEnterAnimOn = bOn;
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Purpose:
  398. //-----------------------------------------------------------------------------
  399. void CPropVehiclePrisonerPod::ExitVehicle( int nRole )
  400. {
  401. CBasePlayer *pPlayer = m_hPlayer;
  402. if ( !pPlayer )
  403. return;
  404. m_hPlayer = NULL;
  405. ResetUseKey( pPlayer );
  406. m_playerOff.FireOutput( pPlayer, this, 0 );
  407. m_bEnterAnimOn = false;
  408. m_ServerVehicle.SoundShutdown( 1.0 );
  409. }
  410. //-----------------------------------------------------------------------------
  411. // Purpose:
  412. //-----------------------------------------------------------------------------
  413. void CPropVehiclePrisonerPod::ResetUseKey( CBasePlayer *pPlayer )
  414. {
  415. pPlayer->m_afButtonPressed &= ~IN_USE;
  416. }
  417. //-----------------------------------------------------------------------------
  418. // Purpose: Vehicles are permanently oriented off angle for vphysics.
  419. //-----------------------------------------------------------------------------
  420. void CPropVehiclePrisonerPod::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const
  421. {
  422. // This call is necessary to cause m_rgflCoordinateFrame to be recomputed
  423. const matrix3x4_t &entityToWorld = EntityToWorldTransform();
  424. if (pForward != NULL)
  425. {
  426. MatrixGetColumn( entityToWorld, 1, *pForward );
  427. }
  428. if (pRight != NULL)
  429. {
  430. MatrixGetColumn( entityToWorld, 0, *pRight );
  431. }
  432. if (pUp != NULL)
  433. {
  434. MatrixGetColumn( entityToWorld, 2, *pUp );
  435. }
  436. }
  437. //-----------------------------------------------------------------------------
  438. // Purpose:
  439. //-----------------------------------------------------------------------------
  440. CBaseEntity *CPropVehiclePrisonerPod::GetDriver( void )
  441. {
  442. return m_hPlayer;
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Purpose: Prevent the player from entering / exiting the vehicle
  446. //-----------------------------------------------------------------------------
  447. void CPropVehiclePrisonerPod::InputLock( inputdata_t &inputdata )
  448. {
  449. m_bLocked = true;
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Purpose: Allow the player to enter / exit the vehicle
  453. //-----------------------------------------------------------------------------
  454. void CPropVehiclePrisonerPod::InputUnlock( inputdata_t &inputdata )
  455. {
  456. m_bLocked = false;
  457. }
  458. //-----------------------------------------------------------------------------
  459. // Purpose: Force the player to enter the vehicle.
  460. //-----------------------------------------------------------------------------
  461. void CPropVehiclePrisonerPod::InputEnterVehicle( inputdata_t &inputdata )
  462. {
  463. if ( m_bEnterAnimOn )
  464. return;
  465. // Try the activator first & use them if they are a player.
  466. CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator );
  467. if ( pPassenger == NULL )
  468. {
  469. // Activator was not a player, just grab the singleplayer player.
  470. pPassenger = UTIL_PlayerByIndex( 1 );
  471. if ( pPassenger == NULL )
  472. return;
  473. }
  474. // FIXME: I hate code like this. I should really add a parameter to HandlePassengerEntry
  475. // to allow entry into locked vehicles
  476. bool bWasLocked = m_bLocked;
  477. m_bLocked = false;
  478. GetServerVehicle()->HandlePassengerEntry( pPassenger, true );
  479. m_bLocked = bWasLocked;
  480. }
  481. //-----------------------------------------------------------------------------
  482. // Purpose:
  483. // Input : &inputdata -
  484. //-----------------------------------------------------------------------------
  485. void CPropVehiclePrisonerPod::InputEnterVehicleImmediate( inputdata_t &inputdata )
  486. {
  487. if ( m_bEnterAnimOn )
  488. return;
  489. // Try the activator first & use them if they are a player.
  490. CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator );
  491. if ( pPassenger == NULL )
  492. {
  493. // Activator was not a player, just grab the singleplayer player.
  494. pPassenger = UTIL_PlayerByIndex( 1 );
  495. if ( pPassenger == NULL )
  496. return;
  497. }
  498. CBasePlayer *pPlayer = ToBasePlayer( pPassenger );
  499. if ( pPlayer != NULL )
  500. {
  501. if ( pPlayer->IsInAVehicle() )
  502. {
  503. // Force the player out of whatever vehicle they are in.
  504. pPlayer->LeaveVehicle();
  505. }
  506. pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER );
  507. }
  508. else
  509. {
  510. // NPCs are not currently supported - jdw
  511. Assert( 0 );
  512. }
  513. }
  514. //-----------------------------------------------------------------------------
  515. // Purpose: Force the player to exit the vehicle.
  516. //-----------------------------------------------------------------------------
  517. void CPropVehiclePrisonerPod::InputExitVehicle( inputdata_t &inputdata )
  518. {
  519. m_bForcedExit = true;
  520. }
  521. //========================================================================================================================================
  522. // CRANE VEHICLE SERVER VEHICLE
  523. //========================================================================================================================================
  524. CPropVehiclePrisonerPod *CPrisonerPodServerVehicle::GetPod( void )
  525. {
  526. return (CPropVehiclePrisonerPod *)GetDrivableVehicle();
  527. }
  528. //-----------------------------------------------------------------------------
  529. // Purpose:
  530. // Input : pPlayer -
  531. //-----------------------------------------------------------------------------
  532. void CPrisonerPodServerVehicle::ItemPostFrame( CBasePlayer *player )
  533. {
  534. Assert( player == GetDriver() );
  535. GetDrivableVehicle()->ItemPostFrame( player );
  536. if (( player->m_afButtonPressed & IN_USE ) || GetPod()->ShouldForceExit() )
  537. {
  538. GetPod()->ClearForcedExit();
  539. if ( GetDrivableVehicle()->CanExitVehicle(player) )
  540. {
  541. // Let the vehicle try to play the exit animation
  542. if ( !HandlePassengerExit( player ) && ( player != NULL ) )
  543. {
  544. player->PlayUseDenySound();
  545. }
  546. }
  547. }
  548. }
  549. //-----------------------------------------------------------------------------
  550. // Purpose:
  551. //-----------------------------------------------------------------------------
  552. void CPrisonerPodServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ )
  553. {
  554. // FIXME: This needs to be reconciled with the other versions of this function!
  555. Assert( nRole == VEHICLE_ROLE_DRIVER );
  556. CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() );
  557. Assert( pPlayer );
  558. *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter.
  559. float flPitchFactor = 1.0;
  560. matrix3x4_t vehicleEyePosToWorld;
  561. Vector vehicleEyeOrigin;
  562. QAngle vehicleEyeAngles;
  563. GetPod()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles );
  564. AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld );
  565. // Compute the relative rotation between the unperterbed eye attachment + the eye angles
  566. matrix3x4_t cameraToWorld;
  567. AngleMatrix( *pAbsAngles, cameraToWorld );
  568. matrix3x4_t worldToEyePos;
  569. MatrixInvert( vehicleEyePosToWorld, worldToEyePos );
  570. matrix3x4_t vehicleCameraToEyePos;
  571. ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos );
  572. // Now perterb the attachment point
  573. vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x );
  574. vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z );
  575. AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld );
  576. // Now treat the relative eye angles as being relative to this new, perterbed view position...
  577. matrix3x4_t newCameraToWorld;
  578. ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld );
  579. // output new view abs angles
  580. MatrixAngles( newCameraToWorld, *pAbsAngles );
  581. // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics
  582. MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin );
  583. }