Counter Strike : Global Offensive Source Code
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.

1088 lines
34 KiB

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