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.

1570 lines
48 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "vehicle_base.h"
  9. #include "engine/IEngineSound.h"
  10. #include "in_buttons.h"
  11. #include "ammodef.h"
  12. #include "IEffects.h"
  13. #include "beam_shared.h"
  14. #include "soundenvelope.h"
  15. #include "decals.h"
  16. #include "soundent.h"
  17. #include "te_effect_dispatch.h"
  18. #include "ndebugoverlay.h"
  19. #include "movevars_shared.h"
  20. #include "bone_setup.h"
  21. #include "ai_basenpc.h"
  22. #include "ai_hint.h"
  23. #include "globalstate.h"
  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 LOCK_SPEED 10
  28. #define JEEP_GUN_YAW "vehicle_weapon_yaw"
  29. #define JEEP_GUN_PITCH "vehicle_weapon_pitch"
  30. #define JEEP_GUN_SPIN "gun_spin"
  31. #define JEEP_GUN_SPIN_RATE 20
  32. #define CANNON_MAX_UP_PITCH 20
  33. #define CANNON_MAX_DOWN_PITCH 20
  34. #define CANNON_MAX_LEFT_YAW 90
  35. #define CANNON_MAX_RIGHT_YAW 90
  36. #define OVERTURNED_EXIT_WAITTIME 2.0f
  37. #define JEEP_AMMOCRATE_HITGROUP 5
  38. #define JEEP_WHEEL_COUNT 4
  39. #define JEEP_AMMO_CRATE_CLOSE_DELAY 2.0f
  40. #define JEEP_DELTA_LENGTH_MAX 12.0f // 1 foot
  41. #define JEEP_FRAMETIME_MIN 1e-6
  42. ConVar hud_jeephint_numentries( "hud_jeephint_numentries", "10", FCVAR_NONE );
  43. ConVar g_jeepexitspeed( "g_jeepexitspeed", "100", FCVAR_CHEAT );
  44. //=============================================================================
  45. //
  46. // Jeep water data.
  47. //
  48. struct JeepWaterData_t
  49. {
  50. bool m_bWheelInWater[JEEP_WHEEL_COUNT];
  51. bool m_bWheelWasInWater[JEEP_WHEEL_COUNT];
  52. Vector m_vecWheelContactPoints[JEEP_WHEEL_COUNT];
  53. float m_flNextRippleTime[JEEP_WHEEL_COUNT];
  54. bool m_bBodyInWater;
  55. bool m_bBodyWasInWater;
  56. DECLARE_SIMPLE_DATADESC();
  57. };
  58. BEGIN_SIMPLE_DATADESC( JeepWaterData_t )
  59. DEFINE_ARRAY( m_bWheelInWater, FIELD_BOOLEAN, JEEP_WHEEL_COUNT ),
  60. DEFINE_ARRAY( m_bWheelWasInWater, FIELD_BOOLEAN, JEEP_WHEEL_COUNT ),
  61. DEFINE_ARRAY( m_vecWheelContactPoints, FIELD_VECTOR, JEEP_WHEEL_COUNT ),
  62. DEFINE_ARRAY( m_flNextRippleTime, FIELD_TIME, JEEP_WHEEL_COUNT ),
  63. DEFINE_FIELD( m_bBodyInWater, FIELD_BOOLEAN ),
  64. DEFINE_FIELD( m_bBodyWasInWater, FIELD_BOOLEAN ),
  65. END_DATADESC()
  66. //-----------------------------------------------------------------------------
  67. // Purpose: Four wheel physics vehicle server vehicle with weaponry
  68. //-----------------------------------------------------------------------------
  69. class CJeepFourWheelServerVehicle : public CFourWheelServerVehicle
  70. {
  71. typedef CFourWheelServerVehicle BaseClass;
  72. // IServerVehicle
  73. public:
  74. bool NPC_HasPrimaryWeapon( void ) { return true; }
  75. void NPC_AimPrimaryWeapon( Vector vecTarget );
  76. int GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked );
  77. };
  78. //-----------------------------------------------------------------------------
  79. // Purpose:
  80. //-----------------------------------------------------------------------------
  81. class CPropJeep : public CPropVehicleDriveable
  82. {
  83. DECLARE_CLASS( CPropJeep, CPropVehicleDriveable );
  84. public:
  85. DECLARE_SERVERCLASS();
  86. DECLARE_DATADESC();
  87. CPropJeep( void );
  88. // CPropVehicle
  89. virtual void OnRestore( void );
  90. virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData );
  91. virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased );
  92. virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move );
  93. virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  94. virtual void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles );
  95. virtual bool AllowBlockedExit( CBasePlayer *pPlayer, int nRole ) { return false; }
  96. virtual bool CanExitVehicle( CBaseEntity *pEntity );
  97. virtual bool IsVehicleBodyInWater() { return m_WaterData.m_bBodyInWater; }
  98. // CBaseEntity
  99. void Think(void);
  100. void Precache( void );
  101. void Spawn( void );
  102. virtual void CreateServerVehicle( void );
  103. virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
  104. virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
  105. virtual int OnTakeDamage( const CTakeDamageInfo &info );
  106. virtual void EnterVehicle( CBasePlayer *pPlayer );
  107. virtual void ExitVehicle( int nRole );
  108. void AimGunAt( Vector *endPos, float flInterval );
  109. bool TauCannonHasBeenCutOff( void ) { return m_bGunHasBeenCutOff; }
  110. // NPC Driving
  111. bool NPC_HasPrimaryWeapon( void ) { return true; }
  112. void NPC_AimPrimaryWeapon( Vector vecTarget );
  113. const char *GetTracerType( void ) { return "AR2Tracer"; }
  114. void DoImpactEffect( trace_t &tr, int nDamageType );
  115. bool HeadlightIsOn( void ) { return m_bHeadlightIsOn; }
  116. void HeadlightTurnOn( void ) { m_bHeadlightIsOn = true; }
  117. void HeadlightTurnOff( void ) { m_bHeadlightIsOn = false; }
  118. private:
  119. void FireCannon( void );
  120. void ChargeCannon( void );
  121. void FireChargedCannon( void );
  122. void DrawBeam( const Vector &startPos, const Vector &endPos, float width );
  123. void StopChargeSound( void );
  124. void GetCannonAim( Vector *resultDir );
  125. void InitWaterData( void );
  126. void HandleWater( void );
  127. bool CheckWater( void );
  128. void CheckWaterLevel( void );
  129. void CreateSplash( const Vector &vecPosition );
  130. void CreateRipple( const Vector &vecPosition );
  131. void UpdateSteeringAngle( void );
  132. void CreateDangerSounds( void );
  133. void ComputePDControllerCoefficients( float *pCoefficientsOut, float flFrequency, float flDampening, float flDeltaTime );
  134. void DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime );
  135. void DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime );
  136. void InputStartRemoveTauCannon( inputdata_t &inputdata );
  137. void InputFinishRemoveTauCannon( inputdata_t &inputdata );
  138. private:
  139. bool m_bGunHasBeenCutOff;
  140. float m_flDangerSoundTime;
  141. int m_nBulletType;
  142. bool m_bCannonCharging;
  143. float m_flCannonTime;
  144. float m_flCannonChargeStartTime;
  145. Vector m_vecGunOrigin;
  146. CSoundPatch *m_sndCannonCharge;
  147. int m_nSpinPos;
  148. float m_aimYaw;
  149. float m_aimPitch;
  150. float m_throttleDisableTime;
  151. float m_flAmmoCrateCloseTime;
  152. // handbrake after the fact to keep vehicles from rolling
  153. float m_flHandbrakeTime;
  154. bool m_bInitialHandbrake;
  155. float m_flOverturnedTime;
  156. Vector m_vecLastEyePos;
  157. Vector m_vecLastEyeTarget;
  158. Vector m_vecEyeSpeed;
  159. Vector m_vecTargetSpeed;
  160. JeepWaterData_t m_WaterData;
  161. int m_iNumberOfEntries;
  162. int m_nAmmoType;
  163. // Seagull perching
  164. float m_flPlayerExitedTime; // Time at which the player last left this vehicle
  165. float m_flLastSawPlayerAt; // Time at which we last saw the player
  166. EHANDLE m_hLastPlayerInVehicle;
  167. bool m_bHasPoop;
  168. CNetworkVar( bool, m_bHeadlightIsOn );
  169. };
  170. BEGIN_DATADESC( CPropJeep )
  171. DEFINE_FIELD( m_bGunHasBeenCutOff, FIELD_BOOLEAN ),
  172. DEFINE_FIELD( m_flDangerSoundTime, FIELD_TIME ),
  173. DEFINE_FIELD( m_nBulletType, FIELD_INTEGER ),
  174. DEFINE_FIELD( m_bCannonCharging, FIELD_BOOLEAN ),
  175. DEFINE_FIELD( m_flCannonTime, FIELD_TIME ),
  176. DEFINE_FIELD( m_flCannonChargeStartTime, FIELD_TIME ),
  177. DEFINE_FIELD( m_vecGunOrigin, FIELD_POSITION_VECTOR ),
  178. DEFINE_SOUNDPATCH( m_sndCannonCharge ),
  179. DEFINE_FIELD( m_nSpinPos, FIELD_INTEGER ),
  180. DEFINE_FIELD( m_aimYaw, FIELD_FLOAT ),
  181. DEFINE_FIELD( m_aimPitch, FIELD_FLOAT ),
  182. DEFINE_FIELD( m_throttleDisableTime, FIELD_TIME ),
  183. DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ),
  184. DEFINE_FIELD( m_bInitialHandbrake, FIELD_BOOLEAN ),
  185. DEFINE_FIELD( m_flOverturnedTime, FIELD_TIME ),
  186. DEFINE_FIELD( m_flAmmoCrateCloseTime, FIELD_FLOAT ),
  187. DEFINE_FIELD( m_vecLastEyePos, FIELD_POSITION_VECTOR ),
  188. DEFINE_FIELD( m_vecLastEyeTarget, FIELD_POSITION_VECTOR ),
  189. DEFINE_FIELD( m_vecEyeSpeed, FIELD_POSITION_VECTOR ),
  190. DEFINE_FIELD( m_vecTargetSpeed, FIELD_POSITION_VECTOR ),
  191. DEFINE_FIELD( m_bHeadlightIsOn, FIELD_BOOLEAN ),
  192. DEFINE_EMBEDDED( m_WaterData ),
  193. DEFINE_FIELD( m_iNumberOfEntries, FIELD_INTEGER ),
  194. DEFINE_FIELD( m_nAmmoType, FIELD_INTEGER ),
  195. DEFINE_FIELD( m_flPlayerExitedTime, FIELD_TIME ),
  196. DEFINE_FIELD( m_flLastSawPlayerAt, FIELD_TIME ),
  197. DEFINE_FIELD( m_hLastPlayerInVehicle, FIELD_EHANDLE ),
  198. DEFINE_FIELD( m_bHasPoop, FIELD_BOOLEAN ),
  199. DEFINE_INPUTFUNC( FIELD_VOID, "StartRemoveTauCannon", InputStartRemoveTauCannon ),
  200. DEFINE_INPUTFUNC( FIELD_VOID, "FinishRemoveTauCannon", InputFinishRemoveTauCannon ),
  201. END_DATADESC()
  202. IMPLEMENT_SERVERCLASS_ST( CPropJeep, DT_PropJeep )
  203. SendPropBool( SENDINFO( m_bHeadlightIsOn ) ),
  204. END_SEND_TABLE();
  205. //LINK_ENTITY_TO_CLASS( prop_vehicle_jeep, CPropJeep );
  206. //-----------------------------------------------------------------------------
  207. // Purpose:
  208. //-----------------------------------------------------------------------------
  209. CPropJeep::CPropJeep( void )
  210. {
  211. m_bHasGun = true;
  212. m_bGunHasBeenCutOff = false;
  213. m_bCannonCharging = false;
  214. m_flCannonChargeStartTime = 0;
  215. m_flCannonTime = 0;
  216. m_nBulletType = -1;
  217. m_flOverturnedTime = 0.0f;
  218. m_iNumberOfEntries = 0;
  219. m_vecEyeSpeed.Init();
  220. InitWaterData();
  221. m_bUnableToFire = true;
  222. m_flAmmoCrateCloseTime = 0;
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose:
  226. //-----------------------------------------------------------------------------
  227. void CPropJeep::CreateServerVehicle( void )
  228. {
  229. // Create our armed server vehicle
  230. m_pServerVehicle = new CJeepFourWheelServerVehicle();
  231. m_pServerVehicle->SetVehicle( this );
  232. }
  233. //-----------------------------------------------------------------------------
  234. // Purpose:
  235. //-----------------------------------------------------------------------------
  236. void CPropJeep::Precache( void )
  237. {
  238. UTIL_PrecacheOther( "npc_seagull" );
  239. PrecacheScriptSound( "PropJeep.AmmoClose" );
  240. PrecacheScriptSound( "PropJeep.FireCannon" );
  241. PrecacheScriptSound( "PropJeep.FireChargedCannon" );
  242. PrecacheScriptSound( "PropJeep.AmmoOpen" );
  243. PrecacheScriptSound( "Jeep.GaussCharge" );
  244. PrecacheEffect( "ImpactJeep" );
  245. PrecacheEffect( "watersplash" );
  246. PrecacheEffect( "waterripple" );
  247. // PrecacheModel( GAUSS_BEAM_SPRITE );
  248. BaseClass::Precache();
  249. }
  250. //------------------------------------------------
  251. // Spawn
  252. //------------------------------------------------
  253. void CPropJeep::Spawn( void )
  254. {
  255. // Setup vehicle as a real-wheels car.
  256. SetVehicleType( VEHICLE_TYPE_CAR_WHEELS );
  257. BaseClass::Spawn();
  258. m_flHandbrakeTime = gpGlobals->curtime + 0.1;
  259. m_bInitialHandbrake = false;
  260. m_VehiclePhysics.SetHasBrakePedal( false );
  261. m_flMinimumSpeedToEnterExit = LOCK_SPEED;
  262. m_nBulletType = GetAmmoDef()->Index("GaussEnergy");
  263. if ( m_bHasGun )
  264. {
  265. SetBodygroup( 1, true );
  266. }
  267. else
  268. {
  269. SetBodygroup( 1, false );
  270. }
  271. // Initialize pose parameters
  272. SetPoseParameter( JEEP_GUN_YAW, 0 );
  273. SetPoseParameter( JEEP_GUN_PITCH, 0 );
  274. m_nSpinPos = 0;
  275. SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos );
  276. m_aimYaw = 0;
  277. m_aimPitch = 0;
  278. AddSolidFlags( FSOLID_NOT_STANDABLE );
  279. CAmmoDef *pAmmoDef = GetAmmoDef();
  280. m_nAmmoType = pAmmoDef->Index("GaussEnergy");
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Purpose:
  284. // Input : &tr -
  285. // nDamageType -
  286. //-----------------------------------------------------------------------------
  287. void CPropJeep::DoImpactEffect( trace_t &tr, int nDamageType )
  288. {
  289. //Draw our beam
  290. DrawBeam( tr.startpos, tr.endpos, 2.4 );
  291. if ( (tr.surface.flags & SURF_SKY) == false )
  292. {
  293. CPVSFilter filter( tr.endpos );
  294. te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
  295. UTIL_ImpactTrace( &tr, m_nBulletType );
  296. }
  297. }
  298. //-----------------------------------------------------------------------------
  299. // Purpose:
  300. //-----------------------------------------------------------------------------
  301. void CPropJeep::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr )
  302. {
  303. CTakeDamageInfo info = inputInfo;
  304. if ( ptr->hitbox != VEHICLE_HITBOX_DRIVER )
  305. {
  306. if ( inputInfo.GetDamageType() & DMG_BULLET )
  307. {
  308. info.ScaleDamage( 0.0001 );
  309. }
  310. }
  311. BaseClass::TraceAttack( info, vecDir, ptr );
  312. }
  313. //-----------------------------------------------------------------------------
  314. // Purpose:
  315. //-----------------------------------------------------------------------------
  316. int CPropJeep::OnTakeDamage( const CTakeDamageInfo &inputInfo )
  317. {
  318. //Do scaled up physics damage to the car
  319. CTakeDamageInfo info = inputInfo;
  320. info.ScaleDamage( 25 );
  321. // HACKHACK: Scale up grenades until we get a better explosion/pressure damage system
  322. if ( inputInfo.GetDamageType() & DMG_BLAST )
  323. {
  324. info.SetDamageForce( inputInfo.GetDamageForce() * 10 );
  325. }
  326. VPhysicsTakeDamage( info );
  327. // reset the damage
  328. info.SetDamage( inputInfo.GetDamage() );
  329. // small amounts of shock damage disrupt the car, but aren't transferred to the player
  330. if ( info.GetDamageType() == DMG_SHOCK )
  331. {
  332. if ( info.GetDamage() <= 10 )
  333. {
  334. // take 10% damage and make the engine stall
  335. info.ScaleDamage( 0.1 );
  336. m_throttleDisableTime = gpGlobals->curtime + 2;
  337. }
  338. }
  339. //Check to do damage to driver
  340. if ( GetDriver() )
  341. {
  342. //Take no damage from physics damages
  343. if ( info.GetDamageType() & DMG_CRUSH )
  344. return 0;
  345. // Take the damage (strip out the DMG_BLAST)
  346. info.SetDamageType( info.GetDamageType() & (~DMG_BLAST) );
  347. GetDriver()->TakeDamage( info );
  348. }
  349. return 0;
  350. }
  351. //-----------------------------------------------------------------------------
  352. // Purpose:
  353. //-----------------------------------------------------------------------------
  354. Vector CPropJeep::BodyTarget( const Vector &posSrc, bool bNoisy )
  355. {
  356. Vector shotPos;
  357. matrix3x4_t matrix;
  358. int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes");
  359. GetAttachment( eyeAttachmentIndex, matrix );
  360. MatrixGetColumn( matrix, 3, shotPos );
  361. if ( bNoisy )
  362. {
  363. shotPos[0] += random->RandomFloat( -8.0f, 8.0f );
  364. shotPos[1] += random->RandomFloat( -8.0f, 8.0f );
  365. shotPos[2] += random->RandomFloat( -8.0f, 8.0f );
  366. }
  367. return shotPos;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Purpose: Aim Gun at a target
  371. //-----------------------------------------------------------------------------
  372. void CPropJeep::AimGunAt( Vector *endPos, float flInterval )
  373. {
  374. Vector aimPos = *endPos;
  375. // See if the gun should be allowed to aim
  376. if ( IsOverturned() || m_bEngineLocked )
  377. {
  378. SetPoseParameter( JEEP_GUN_YAW, 0 );
  379. SetPoseParameter( JEEP_GUN_PITCH, 0 );
  380. SetPoseParameter( JEEP_GUN_SPIN, 0 );
  381. return;
  382. // Make the gun go limp and look "down"
  383. Vector v_forward, v_up;
  384. AngleVectors( GetLocalAngles(), NULL, &v_forward, &v_up );
  385. aimPos = WorldSpaceCenter() + ( v_forward * -32.0f ) - Vector( 0, 0, 128.0f );
  386. }
  387. matrix3x4_t gunMatrix;
  388. GetAttachment( LookupAttachment("gun_ref"), gunMatrix );
  389. // transform the enemy into gun space
  390. Vector localEnemyPosition;
  391. VectorITransform( aimPos, gunMatrix, localEnemyPosition );
  392. // do a look at in gun space (essentially a delta-lookat)
  393. QAngle localEnemyAngles;
  394. VectorAngles( localEnemyPosition, localEnemyAngles );
  395. // convert to +/- 180 degrees
  396. localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 );
  397. localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 );
  398. float targetYaw = m_aimYaw + localEnemyAngles.y;
  399. float targetPitch = m_aimPitch + localEnemyAngles.x;
  400. // Constrain our angles
  401. float newTargetYaw = clamp( targetYaw, -CANNON_MAX_LEFT_YAW, CANNON_MAX_RIGHT_YAW );
  402. float newTargetPitch = clamp( targetPitch, -CANNON_MAX_DOWN_PITCH, CANNON_MAX_UP_PITCH );
  403. // If the angles have been clamped, we're looking outside of our valid range
  404. if ( fabs(newTargetYaw-targetYaw) > 1e-4 || fabs(newTargetPitch-targetPitch) > 1e-4 )
  405. {
  406. m_bUnableToFire = true;
  407. }
  408. targetYaw = newTargetYaw;
  409. targetPitch = newTargetPitch;
  410. // Exponentially approach the target
  411. float yawSpeed = 8;
  412. float pitchSpeed = 8;
  413. m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed );
  414. m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed );
  415. SetPoseParameter( JEEP_GUN_YAW, -m_aimYaw);
  416. SetPoseParameter( JEEP_GUN_PITCH, -m_aimPitch );
  417. InvalidateBoneCache();
  418. // read back to avoid drift when hitting limits
  419. // as long as the velocity is less than the delta between the limit and 180, this is fine.
  420. m_aimPitch = -GetPoseParameter( JEEP_GUN_PITCH );
  421. m_aimYaw = -GetPoseParameter( JEEP_GUN_YAW );
  422. // Now draw crosshair for actual aiming point
  423. Vector vecMuzzle, vecMuzzleDir;
  424. QAngle vecMuzzleAng;
  425. GetAttachment( "Muzzle", vecMuzzle, vecMuzzleAng );
  426. AngleVectors( vecMuzzleAng, &vecMuzzleDir );
  427. trace_t tr;
  428. UTIL_TraceLine( vecMuzzle, vecMuzzle + (vecMuzzleDir * MAX_TRACE_LENGTH), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  429. // see if we hit something, if so, adjust endPos to hit location
  430. if ( tr.fraction < 1.0 )
  431. {
  432. m_vecGunCrosshair = vecMuzzle + ( vecMuzzleDir * MAX_TRACE_LENGTH * tr.fraction );
  433. }
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Purpose:
  437. //-----------------------------------------------------------------------------
  438. void CPropJeep::InitWaterData( void )
  439. {
  440. m_WaterData.m_bBodyInWater = false;
  441. m_WaterData.m_bBodyWasInWater = false;
  442. for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel )
  443. {
  444. m_WaterData.m_bWheelInWater[iWheel] = false;
  445. m_WaterData.m_bWheelWasInWater[iWheel] = false;
  446. m_WaterData.m_vecWheelContactPoints[iWheel].Init();
  447. m_WaterData.m_flNextRippleTime[iWheel] = 0;
  448. }
  449. }
  450. //-----------------------------------------------------------------------------
  451. // Purpose:
  452. //-----------------------------------------------------------------------------
  453. void CPropJeep::HandleWater( void )
  454. {
  455. // Only check the wheels and engine in water if we have a driver (player).
  456. if ( !GetDriver() )
  457. return;
  458. // Check to see if we are in water.
  459. if ( CheckWater() )
  460. {
  461. for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel )
  462. {
  463. // Create an entry/exit splash!
  464. if ( m_WaterData.m_bWheelInWater[iWheel] != m_WaterData.m_bWheelWasInWater[iWheel] )
  465. {
  466. CreateSplash( m_WaterData.m_vecWheelContactPoints[iWheel] );
  467. CreateRipple( m_WaterData.m_vecWheelContactPoints[iWheel] );
  468. }
  469. // Create ripples.
  470. if ( m_WaterData.m_bWheelInWater[iWheel] && m_WaterData.m_bWheelWasInWater[iWheel] )
  471. {
  472. if ( m_WaterData.m_flNextRippleTime[iWheel] < gpGlobals->curtime )
  473. {
  474. // Stagger ripple times
  475. m_WaterData.m_flNextRippleTime[iWheel] = gpGlobals->curtime + RandomFloat( 0.1, 0.3 );
  476. CreateRipple( m_WaterData.m_vecWheelContactPoints[iWheel] );
  477. }
  478. }
  479. }
  480. }
  481. // Save of data from last think.
  482. for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel )
  483. {
  484. m_WaterData.m_bWheelWasInWater[iWheel] = m_WaterData.m_bWheelInWater[iWheel];
  485. }
  486. }
  487. //-----------------------------------------------------------------------------
  488. // Purpose:
  489. //-----------------------------------------------------------------------------
  490. bool CPropJeep::CheckWater( void )
  491. {
  492. bool bInWater = false;
  493. // Check all four wheels.
  494. for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel )
  495. {
  496. // Get the current wheel and get its contact point.
  497. IPhysicsObject *pWheel = m_VehiclePhysics.GetWheel( iWheel );
  498. if ( !pWheel )
  499. continue;
  500. // Check to see if we hit water.
  501. if ( pWheel->GetContactPoint( &m_WaterData.m_vecWheelContactPoints[iWheel], NULL ) )
  502. {
  503. m_WaterData.m_bWheelInWater[iWheel] = ( UTIL_PointContents( m_WaterData.m_vecWheelContactPoints[iWheel], MASK_WATER ) & MASK_WATER ) ? true : false;
  504. if ( m_WaterData.m_bWheelInWater[iWheel] )
  505. {
  506. bInWater = true;
  507. }
  508. }
  509. }
  510. // Check the body and the BONNET.
  511. int iEngine = LookupAttachment( "vehicle_engine" );
  512. Vector vecEnginePoint;
  513. QAngle vecEngineAngles;
  514. GetAttachment( iEngine, vecEnginePoint, vecEngineAngles );
  515. m_WaterData.m_bBodyInWater = ( UTIL_PointContents( vecEnginePoint, MASK_WATER ) & MASK_WATER ) ? true : false;
  516. if ( m_WaterData.m_bBodyInWater )
  517. {
  518. if ( m_bHasPoop )
  519. {
  520. RemoveAllDecals();
  521. m_bHasPoop = false;
  522. }
  523. if ( !m_VehiclePhysics.IsEngineDisabled() )
  524. {
  525. m_VehiclePhysics.SetDisableEngine( true );
  526. }
  527. }
  528. else
  529. {
  530. if ( m_VehiclePhysics.IsEngineDisabled() )
  531. {
  532. m_VehiclePhysics.SetDisableEngine( false );
  533. }
  534. }
  535. if ( bInWater )
  536. {
  537. // Check the player's water level.
  538. CheckWaterLevel();
  539. }
  540. return bInWater;
  541. }
  542. //-----------------------------------------------------------------------------
  543. // Purpose:
  544. //-----------------------------------------------------------------------------
  545. void CPropJeep::CheckWaterLevel( void )
  546. {
  547. CBaseEntity *pEntity = GetDriver();
  548. if ( pEntity && pEntity->IsPlayer() )
  549. {
  550. CBasePlayer *pPlayer = static_cast<CBasePlayer*>( pEntity );
  551. Vector vecAttachPoint;
  552. QAngle vecAttachAngles;
  553. // Check eyes. (vehicle_driver_eyes point)
  554. int iAttachment = LookupAttachment( "vehicle_driver_eyes" );
  555. GetAttachment( iAttachment, vecAttachPoint, vecAttachAngles );
  556. // Add the jeep's Z view offset
  557. Vector vecUp;
  558. AngleVectors( vecAttachAngles, NULL, NULL, &vecUp );
  559. vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z );
  560. vecAttachPoint.z += r_JeepViewZHeight.GetFloat() * vecUp.z;
  561. bool bEyes = ( UTIL_PointContents( vecAttachPoint, MASK_WATER ) & MASK_WATER ) ? true : false;
  562. if ( bEyes )
  563. {
  564. pPlayer->SetWaterLevel( WL_Eyes );
  565. return;
  566. }
  567. // Check waist. (vehicle_engine point -- see parent function).
  568. if ( m_WaterData.m_bBodyInWater )
  569. {
  570. pPlayer->SetWaterLevel( WL_Waist );
  571. return;
  572. }
  573. // Check feet. (vehicle_feet_passenger0 point)
  574. iAttachment = LookupAttachment( "vehicle_feet_passenger0" );
  575. GetAttachment( iAttachment, vecAttachPoint, vecAttachAngles );
  576. bool bFeet = ( UTIL_PointContents( vecAttachPoint, MASK_WATER ) & MASK_WATER ) ? true : false;
  577. if ( bFeet )
  578. {
  579. pPlayer->SetWaterLevel( WL_Feet );
  580. return;
  581. }
  582. // Not in water.
  583. pPlayer->SetWaterLevel( WL_NotInWater );
  584. }
  585. }
  586. //-----------------------------------------------------------------------------
  587. // Purpose:
  588. //-----------------------------------------------------------------------------
  589. void CPropJeep::CreateSplash( const Vector &vecPosition )
  590. {
  591. // Splash data.
  592. CEffectData data;
  593. data.m_fFlags = 0;
  594. data.m_vOrigin = vecPosition;
  595. data.m_vNormal.Init( 0.0f, 0.0f, 1.0f );
  596. VectorAngles( data.m_vNormal, data.m_vAngles );
  597. data.m_flScale = 10.0f + random->RandomFloat( 0, 2 );
  598. // Create the splash..
  599. DispatchEffect( "watersplash", data );
  600. }
  601. //-----------------------------------------------------------------------------
  602. // Purpose:
  603. //-----------------------------------------------------------------------------
  604. void CPropJeep::CreateRipple( const Vector &vecPosition )
  605. {
  606. // Ripple data.
  607. CEffectData data;
  608. data.m_fFlags = 0;
  609. data.m_vOrigin = vecPosition;
  610. data.m_vNormal.Init( 0.0f, 0.0f, 1.0f );
  611. VectorAngles( data.m_vNormal, data.m_vAngles );
  612. data.m_flScale = 10.0f + random->RandomFloat( 0, 2 );
  613. if ( GetWaterType() & CONTENTS_SLIME )
  614. {
  615. data.m_fFlags |= FX_WATER_IN_SLIME;
  616. }
  617. // Create the ripple.
  618. DispatchEffect( "waterripple", data );
  619. }
  620. //-----------------------------------------------------------------------------
  621. // Purpose:
  622. //-----------------------------------------------------------------------------
  623. void CPropJeep::Think(void)
  624. {
  625. BaseClass::Think();
  626. /*
  627. CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
  628. if ( m_bEngineLocked )
  629. {
  630. m_bUnableToFire = true;
  631. if ( pPlayer != NULL )
  632. {
  633. pPlayer->m_Local.m_iHideHUD |= HIDEHUD_VEHICLE_CROSSHAIR;
  634. }
  635. }
  636. else
  637. {
  638. // Start this as false and update it again each frame
  639. m_bUnableToFire = false;
  640. if ( pPlayer != NULL )
  641. {
  642. pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_VEHICLE_CROSSHAIR;
  643. }
  644. }
  645. */
  646. // Water!?
  647. HandleWater();
  648. SetSimulationTime( gpGlobals->curtime );
  649. SetNextThink( gpGlobals->curtime );
  650. SetAnimatedEveryTick( true );
  651. if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake
  652. {
  653. m_bInitialHandbrake = true;
  654. m_VehiclePhysics.SetHandbrake( true );
  655. m_VehiclePhysics.Think();
  656. }
  657. // Check overturned status.
  658. if ( !IsOverturned() )
  659. {
  660. m_flOverturnedTime = 0.0f;
  661. }
  662. else
  663. {
  664. m_flOverturnedTime += gpGlobals->frametime;
  665. }
  666. // spin gun if charging cannon
  667. //FIXME: Don't bother for E3
  668. if ( m_bCannonCharging )
  669. {
  670. m_nSpinPos += JEEP_GUN_SPIN_RATE;
  671. SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos );
  672. }
  673. // Aim gun based on the player view direction.
  674. if ( m_hPlayer && !m_bExitAnimOn && !m_bEnterAnimOn )
  675. {
  676. Vector vecEyeDir, vecEyePos;
  677. m_hPlayer->EyePositionAndVectors( &vecEyePos, &vecEyeDir, NULL, NULL );
  678. // Trace out from the player's eye point.
  679. Vector vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH );
  680. trace_t trace;
  681. UTIL_TraceLine( vecEyePos, vecEndPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &trace );
  682. // See if we hit something, if so, adjust end position to hit location.
  683. if ( trace.fraction < 1.0 )
  684. {
  685. vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH * trace.fraction );
  686. }
  687. //m_vecLookCrosshair = vecEndPos;
  688. AimGunAt( &vecEndPos, 0.1f );
  689. }
  690. StudioFrameAdvance();
  691. // If the enter or exit animation has finished, tell the server vehicle
  692. if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) )
  693. {
  694. if ( m_bEnterAnimOn )
  695. {
  696. m_VehiclePhysics.ReleaseHandbrake();
  697. StartEngine();
  698. // HACKHACK: This forces the jeep to play a sound when it gets entered underwater
  699. if ( m_VehiclePhysics.IsEngineDisabled() )
  700. {
  701. CBaseServerVehicle *pServerVehicle = dynamic_cast<CBaseServerVehicle *>(GetServerVehicle());
  702. if ( pServerVehicle )
  703. {
  704. pServerVehicle->SoundStartDisabled();
  705. }
  706. }
  707. // The first few time we get into the jeep, print the jeep help
  708. if ( m_iNumberOfEntries < hud_jeephint_numentries.GetInt() )
  709. {
  710. UTIL_HudHintText( m_hPlayer, "#Valve_Hint_JeepKeys" );
  711. m_iNumberOfEntries++;
  712. }
  713. }
  714. // If we're exiting and have had the tau cannon removed, we don't want to reset the animation
  715. GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, !(m_bExitAnimOn && TauCannonHasBeenCutOff()) );
  716. }
  717. // See if the ammo crate needs to close
  718. if ( ( m_flAmmoCrateCloseTime < gpGlobals->curtime ) && ( GetSequence() == LookupSequence( "ammo_open" ) ) )
  719. {
  720. m_flAnimTime = gpGlobals->curtime;
  721. m_flPlaybackRate = 0.0;
  722. SetCycle( 0 );
  723. ResetSequence( LookupSequence( "ammo_close" ) );
  724. }
  725. else if ( ( GetSequence() == LookupSequence( "ammo_close" ) ) && IsSequenceFinished() )
  726. {
  727. m_flAnimTime = gpGlobals->curtime;
  728. m_flPlaybackRate = 0.0;
  729. SetCycle( 0 );
  730. ResetSequence( LookupSequence( "idle" ) );
  731. CBroadcastRecipientFilter sndFilter;
  732. EmitSound( sndFilter, entindex(), "PropJeep.AmmoClose" );
  733. }
  734. }
  735. //-----------------------------------------------------------------------------
  736. // Purpose:
  737. // Input : &startPos -
  738. // &endPos -
  739. // width -
  740. // useMuzzle -
  741. //-----------------------------------------------------------------------------
  742. void CPropJeep::DrawBeam( const Vector &startPos, const Vector &endPos, float width )
  743. {
  744. /*
  745. //Tracer down the middle
  746. UTIL_Tracer( startPos, endPos, 0, TRACER_DONT_USE_ATTACHMENT, 6500, false, "GaussTracer" );
  747. //Draw the main beam shaft
  748. CBeam *pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, 0.5 );
  749. pBeam->SetStartPos( startPos );
  750. pBeam->PointEntInit( endPos, this );
  751. pBeam->SetEndAttachment( LookupAttachment("Muzzle") );
  752. pBeam->SetWidth( width );
  753. pBeam->SetEndWidth( 0.05f );
  754. pBeam->SetBrightness( 255 );
  755. pBeam->SetColor( 255, 185+random->RandomInt( -16, 16 ), 40 );
  756. pBeam->RelinkBeam();
  757. pBeam->LiveForTime( 0.1f );
  758. //Draw electric bolts along shaft
  759. pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, 3.0f );
  760. pBeam->SetStartPos( startPos );
  761. pBeam->PointEntInit( endPos, this );
  762. pBeam->SetEndAttachment( LookupAttachment("Muzzle") );
  763. pBeam->SetBrightness( random->RandomInt( 64, 255 ) );
  764. pBeam->SetColor( 255, 255, 150+random->RandomInt( 0, 64 ) );
  765. pBeam->RelinkBeam();
  766. pBeam->LiveForTime( 0.1f );
  767. pBeam->SetNoise( 1.6f );
  768. pBeam->SetEndWidth( 0.1f ); */
  769. }
  770. //-----------------------------------------------------------------------------
  771. // Purpose:
  772. //-----------------------------------------------------------------------------
  773. void CPropJeep::FireCannon( void )
  774. {
  775. //Don't fire again if it's been too soon
  776. if ( m_flCannonTime > gpGlobals->curtime )
  777. return;
  778. if ( m_bUnableToFire )
  779. return;
  780. m_flCannonTime = gpGlobals->curtime + 0.2f;
  781. m_bCannonCharging = false;
  782. //Find the direction the gun is pointing in
  783. Vector aimDir;
  784. GetCannonAim( &aimDir );
  785. FireBulletsInfo_t info( 1, m_vecGunOrigin, aimDir, VECTOR_CONE_1DEGREES, MAX_TRACE_LENGTH, m_nAmmoType );
  786. info.m_nFlags = FIRE_BULLETS_ALLOW_WATER_SURFACE_IMPACTS;
  787. info.m_pAttacker = m_hPlayer;
  788. FireBullets( info );
  789. // Register a muzzleflash for the AI
  790. if ( m_hPlayer )
  791. {
  792. m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
  793. }
  794. CBroadcastRecipientFilter sndFilter;
  795. EmitSound( sndFilter, entindex(), "PropJeep.FireCannon" );
  796. // make cylinders of gun spin a bit
  797. m_nSpinPos += JEEP_GUN_SPIN_RATE;
  798. //SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); //FIXME: Don't bother with this for E3, won't look right
  799. }
  800. //-----------------------------------------------------------------------------
  801. // Purpose:
  802. //-----------------------------------------------------------------------------
  803. void CPropJeep::FireChargedCannon( void )
  804. {
  805. /* bool penetrated = false;
  806. m_bCannonCharging = false;
  807. m_flCannonTime = gpGlobals->curtime + 0.5f;
  808. StopChargeSound();
  809. CPASAttenuationFilter sndFilter( this, "PropJeep.FireChargedCannon" );
  810. EmitSound( sndFilter, entindex(), "PropJeep.FireChargedCannon" );
  811. //Find the direction the gun is pointing in
  812. Vector aimDir;
  813. GetCannonAim( &aimDir );
  814. Vector endPos = m_vecGunOrigin + ( aimDir * MAX_TRACE_LENGTH );
  815. //Shoot a shot straight out
  816. trace_t tr;
  817. UTIL_TraceLine( m_vecGunOrigin, endPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  818. ClearMultiDamage();
  819. //Find how much damage to do
  820. float flChargeAmount = ( gpGlobals->curtime - m_flCannonChargeStartTime ) / MAX_GAUSS_CHARGE_TIME;
  821. //Clamp this
  822. if ( flChargeAmount > 1.0f )
  823. {
  824. flChargeAmount = 1.0f;
  825. }
  826. //Determine the damage amount
  827. //FIXME: Use ConVars!
  828. float flDamage = 15 + ( ( 250 - 15 ) * flChargeAmount );
  829. CBaseEntity *pHit = tr.m_pEnt;
  830. //Look for wall penetration
  831. if ( tr.DidHitWorld() && !(tr.surface.flags & SURF_SKY) )
  832. {
  833. //Try wall penetration
  834. UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" );
  835. UTIL_DecalTrace( &tr, "RedGlowFade" );
  836. CPVSFilter filter( tr.endpos );
  837. te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
  838. Vector testPos = tr.endpos + ( aimDir * 48.0f );
  839. UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, GetDriver(), COLLISION_GROUP_NONE, &tr );
  840. if ( tr.allsolid == false )
  841. {
  842. UTIL_DecalTrace( &tr, "RedGlowFade" );
  843. penetrated = true;
  844. }
  845. }
  846. else if ( pHit != NULL )
  847. {
  848. CTakeDamageInfo dmgInfo( this, GetDriver(), flDamage, DMG_SHOCK );
  849. CalculateBulletDamageForce( &dmgInfo, GetAmmoDef()->Index("GaussEnergy"), aimDir, tr.endpos, 1.0f + flChargeAmount * 4.0f );
  850. //Do direct damage to anything in our path
  851. pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr );
  852. }
  853. ApplyMultiDamage();
  854. //Kick up an effect
  855. if ( !(tr.surface.flags & SURF_SKY) )
  856. {
  857. UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" );
  858. //Do a gauss explosion
  859. CPVSFilter filter( tr.endpos );
  860. te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 );
  861. }
  862. //Show the effect
  863. DrawBeam( m_vecGunOrigin, tr.endpos, 9.6 );
  864. // Register a muzzleflash for the AI
  865. if ( m_hPlayer )
  866. {
  867. m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5f );
  868. }
  869. //Rock the car
  870. IPhysicsObject *pObj = VPhysicsGetObject();
  871. if ( pObj != NULL )
  872. {
  873. Vector shoveDir = aimDir * -( flDamage * 500.0f );
  874. pObj->ApplyForceOffset( shoveDir, m_vecGunOrigin );
  875. }
  876. //Do radius damage if we didn't penetrate the wall
  877. if ( penetrated == true )
  878. {
  879. RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL );
  880. } */
  881. }
  882. //-----------------------------------------------------------------------------
  883. // Purpose:
  884. //-----------------------------------------------------------------------------
  885. void CPropJeep::ChargeCannon( void )
  886. {
  887. //Don't fire again if it's been too soon
  888. if ( m_flCannonTime > gpGlobals->curtime )
  889. return;
  890. //See if we're starting a charge
  891. if ( m_bCannonCharging == false )
  892. {
  893. m_flCannonChargeStartTime = gpGlobals->curtime;
  894. m_bCannonCharging = true;
  895. //Start charging sound
  896. CBroadcastRecipientFilter filter;
  897. m_sndCannonCharge = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "Jeep.GaussCharge", ATTN_NORM );
  898. assert(m_sndCannonCharge!=NULL);
  899. if ( m_sndCannonCharge != NULL )
  900. {
  901. (CSoundEnvelopeController::GetController()).Play( m_sndCannonCharge, 1.0f, 50 );
  902. (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndCannonCharge, 250, 3.0f );
  903. }
  904. return;
  905. }
  906. //TODO: Add muzzle effect?
  907. //TODO: Check for overcharge and have the weapon simply fire or instead "decharge"?
  908. }
  909. //-----------------------------------------------------------------------------
  910. // Purpose:
  911. //-----------------------------------------------------------------------------
  912. void CPropJeep::StopChargeSound( void )
  913. {
  914. if ( m_sndCannonCharge != NULL )
  915. {
  916. (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndCannonCharge, 0.1f );
  917. }
  918. }
  919. //-----------------------------------------------------------------------------
  920. // Purpose: Finds the true aiming position of the gun (looks at what player
  921. // is looking at and adjusts)
  922. // Input : &resultDir - direction to be calculated
  923. //-----------------------------------------------------------------------------
  924. void CPropJeep::GetCannonAim( Vector *resultDir )
  925. {
  926. Vector muzzleOrigin;
  927. QAngle muzzleAngles;
  928. GetAttachment( LookupAttachment("gun_ref"), muzzleOrigin, muzzleAngles );
  929. AngleVectors( muzzleAngles, resultDir );
  930. }
  931. //-----------------------------------------------------------------------------
  932. // Purpose: If the player uses the jeep while at the back, he gets ammo from the crate instead
  933. //-----------------------------------------------------------------------------
  934. void CPropJeep::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  935. {
  936. CBasePlayer *pPlayer = ToBasePlayer( pActivator );
  937. if ( pPlayer == NULL)
  938. return;
  939. // Find out if the player's looking at our ammocrate hitbox
  940. Vector vecForward;
  941. pPlayer->EyeVectors( &vecForward, NULL, NULL );
  942. trace_t tr;
  943. Vector vecStart = pPlayer->EyePosition();
  944. UTIL_TraceLine( vecStart, vecStart + vecForward * 1024, MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_HITBOX, pPlayer, COLLISION_GROUP_NONE, &tr );
  945. if ( tr.m_pEnt == this && tr.hitgroup == JEEP_AMMOCRATE_HITGROUP )
  946. {
  947. // Player's using the crate.
  948. // Fill up his SMG ammo.
  949. pPlayer->GiveAmmo( 300, "SMG1");
  950. if ( ( GetSequence() != LookupSequence( "ammo_open" ) ) && ( GetSequence() != LookupSequence( "ammo_close" ) ) )
  951. {
  952. // Open the crate
  953. m_flAnimTime = gpGlobals->curtime;
  954. m_flPlaybackRate = 0.0;
  955. SetCycle( 0 );
  956. ResetSequence( LookupSequence( "ammo_open" ) );
  957. CBroadcastRecipientFilter sndFilter;
  958. EmitSound( sndFilter, entindex(), "PropJeep.AmmoOpen" );
  959. }
  960. m_flAmmoCrateCloseTime = gpGlobals->curtime + JEEP_AMMO_CRATE_CLOSE_DELAY;
  961. return;
  962. }
  963. // Fall back and get in the vehicle instead
  964. BaseClass::Use( pActivator, pCaller, useType, value );
  965. }
  966. //-----------------------------------------------------------------------------
  967. // Purpose:
  968. //-----------------------------------------------------------------------------
  969. bool CPropJeep::CanExitVehicle( CBaseEntity *pEntity )
  970. {
  971. return ( !m_bEnterAnimOn && !m_bExitAnimOn && !m_bLocked && (m_nSpeed <= g_jeepexitspeed.GetFloat() ) );
  972. }
  973. //-----------------------------------------------------------------------------
  974. // Purpose:
  975. //-----------------------------------------------------------------------------
  976. void CPropJeep::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles )
  977. {
  978. // Get the frametime. (Check to see if enough time has passed to warrent dampening).
  979. float flFrameTime = gpGlobals->frametime;
  980. if ( flFrameTime < JEEP_FRAMETIME_MIN )
  981. {
  982. vecVehicleEyePos = m_vecLastEyePos;
  983. DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f );
  984. return;
  985. }
  986. // Keep static the sideways motion.
  987. // Dampen forward/backward motion.
  988. DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
  989. // Blend up/down motion.
  990. DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
  991. }
  992. //-----------------------------------------------------------------------------
  993. // Use the controller as follows:
  994. // speed += ( pCoefficientsOut[0] * ( targetPos - currentPos ) + pCoefficientsOut[1] * ( targetSpeed - currentSpeed ) ) * flDeltaTime;
  995. //-----------------------------------------------------------------------------
  996. void CPropJeep::ComputePDControllerCoefficients( float *pCoefficientsOut,
  997. float flFrequency, float flDampening,
  998. float flDeltaTime )
  999. {
  1000. float flKs = 9.0f * flFrequency * flFrequency;
  1001. float flKd = 4.5f * flFrequency * flDampening;
  1002. float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime );
  1003. pCoefficientsOut[0] = flKs * flScale;
  1004. pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale;
  1005. }
  1006. //-----------------------------------------------------------------------------
  1007. // Purpose:
  1008. //-----------------------------------------------------------------------------
  1009. void CPropJeep::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
  1010. {
  1011. // Get forward vector.
  1012. Vector vecForward;
  1013. AngleVectors( vecVehicleEyeAngles, &vecForward);
  1014. // Simulate the eye position forward based on the data from last frame
  1015. // (assumes no acceleration - it will get that from the "spring").
  1016. Vector vecCurrentEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime;
  1017. // Calculate target speed based on the current vehicle eye position and the last vehicle eye position and frametime.
  1018. Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime;
  1019. m_vecLastEyeTarget = vecVehicleEyePos;
  1020. // Calculate the speed and position deltas.
  1021. Vector vecDeltaSpeed = vecVehicleEyeSpeed - m_vecEyeSpeed;
  1022. Vector vecDeltaPos = vecVehicleEyePos - vecCurrentEyePos;
  1023. // Clamp.
  1024. if ( vecDeltaPos.Length() > JEEP_DELTA_LENGTH_MAX )
  1025. {
  1026. float flSign = vecForward.Dot( vecVehicleEyeSpeed ) >= 0.0f ? -1.0f : 1.0f;
  1027. vecVehicleEyePos += flSign * ( vecForward * JEEP_DELTA_LENGTH_MAX );
  1028. m_vecLastEyePos = vecVehicleEyePos;
  1029. m_vecEyeSpeed = vecVehicleEyeSpeed;
  1030. return;
  1031. }
  1032. // Generate an updated (dampening) speed for use in next frames position extrapolation.
  1033. float flCoefficients[2];
  1034. ComputePDControllerCoefficients( flCoefficients, r_JeepViewDampenFreq.GetFloat(), r_JeepViewDampenDamp.GetFloat(), flFrameTime );
  1035. m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
  1036. // Save off data for next frame.
  1037. m_vecLastEyePos = vecCurrentEyePos;
  1038. // Move eye forward/backward.
  1039. Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
  1040. vecVehicleEyePos -= vecForwardOffset;
  1041. }
  1042. //-----------------------------------------------------------------------------
  1043. // Purpose:
  1044. //-----------------------------------------------------------------------------
  1045. void CPropJeep::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
  1046. {
  1047. // Get up vector.
  1048. Vector vecUp;
  1049. AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp );
  1050. vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z );
  1051. vecVehicleEyePos.z += r_JeepViewZHeight.GetFloat() * vecUp.z;
  1052. // NOTE: Should probably use some damped equation here.
  1053. }
  1054. //-----------------------------------------------------------------------------
  1055. // Purpose:
  1056. //-----------------------------------------------------------------------------
  1057. void CPropJeep::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
  1058. {
  1059. // If we are overturned and hit any key - leave the vehicle (IN_USE is already handled!).
  1060. if ( m_flOverturnedTime > OVERTURNED_EXIT_WAITTIME )
  1061. {
  1062. if ( (ucmd->buttons & (IN_FORWARD|IN_BACK|IN_MOVELEFT|IN_MOVERIGHT|IN_SPEED|IN_JUMP|IN_ATTACK|IN_ATTACK2) ) && !m_bExitAnimOn )
  1063. {
  1064. // Can't exit yet? We're probably still moving. Swallow the keys.
  1065. if ( !CanExitVehicle(player) )
  1066. return;
  1067. if ( !GetServerVehicle()->HandlePassengerExit( m_hPlayer ) && ( m_hPlayer != NULL ) )
  1068. {
  1069. m_hPlayer->PlayUseDenySound();
  1070. }
  1071. return;
  1072. }
  1073. }
  1074. // If the throttle is disabled or we're upside-down, don't allow throttling (including turbo)
  1075. CUserCmd tmp;
  1076. if ( ( m_throttleDisableTime > gpGlobals->curtime ) || ( IsOverturned() ) )
  1077. {
  1078. m_bUnableToFire = true;
  1079. tmp = (*ucmd);
  1080. tmp.buttons &= ~(IN_FORWARD|IN_BACK|IN_SPEED);
  1081. ucmd = &tmp;
  1082. }
  1083. BaseClass::SetupMove( player, ucmd, pHelper, move );
  1084. }
  1085. //-----------------------------------------------------------------------------
  1086. // Purpose:
  1087. //-----------------------------------------------------------------------------
  1088. void CPropJeep::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased )
  1089. {
  1090. int iButtons = ucmd->buttons;
  1091. //Adrian: No headlights on Superfly.
  1092. /* if ( ucmd->impulse == 100 )
  1093. {
  1094. if (HeadlightIsOn())
  1095. {
  1096. HeadlightTurnOff();
  1097. }
  1098. else
  1099. {
  1100. HeadlightTurnOn();
  1101. }
  1102. }*/
  1103. // If we're holding down an attack button, update our state
  1104. if ( IsOverturned() == false )
  1105. {
  1106. if ( iButtons & IN_ATTACK )
  1107. {
  1108. if ( m_bCannonCharging )
  1109. {
  1110. FireChargedCannon();
  1111. }
  1112. else
  1113. {
  1114. FireCannon();
  1115. }
  1116. }
  1117. else if ( iButtons & IN_ATTACK2 )
  1118. {
  1119. ChargeCannon();
  1120. }
  1121. }
  1122. // If we've released our secondary button, fire off our cannon
  1123. if ( ( iButtonsReleased & IN_ATTACK2 ) && ( m_bCannonCharging ) )
  1124. {
  1125. FireChargedCannon();
  1126. }
  1127. BaseClass::DriveVehicle( flFrameTime, ucmd, iButtonsDown, iButtonsReleased );
  1128. }
  1129. //-----------------------------------------------------------------------------
  1130. // Purpose:
  1131. // Input : *pPlayer -
  1132. // *pMoveData -
  1133. //-----------------------------------------------------------------------------
  1134. void CPropJeep::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData )
  1135. {
  1136. BaseClass::ProcessMovement( pPlayer, pMoveData );
  1137. // Create dangers sounds in front of the vehicle.
  1138. CreateDangerSounds();
  1139. }
  1140. //-----------------------------------------------------------------------------
  1141. // Purpose: Create danger sounds in front of the vehicle.
  1142. //-----------------------------------------------------------------------------
  1143. void CPropJeep::CreateDangerSounds( void )
  1144. {
  1145. QAngle dummy;
  1146. GetAttachment( "Muzzle", m_vecGunOrigin, dummy );
  1147. if ( m_flDangerSoundTime > gpGlobals->curtime )
  1148. return;
  1149. QAngle vehicleAngles = GetLocalAngles();
  1150. Vector vecStart = GetAbsOrigin();
  1151. Vector vecDir, vecRight;
  1152. GetVectors( &vecDir, &vecRight, NULL );
  1153. const float soundDuration = 0.25;
  1154. float speed = m_VehiclePhysics.GetHLSpeed();
  1155. // Make danger sounds ahead of the jeep
  1156. if ( fabs(speed) > 120 )
  1157. {
  1158. Vector vecSpot;
  1159. float steering = m_VehiclePhysics.GetSteering();
  1160. if ( steering != 0 )
  1161. {
  1162. if ( speed > 0 )
  1163. {
  1164. vecDir += vecRight * steering * 0.5;
  1165. }
  1166. else
  1167. {
  1168. vecDir -= vecRight * steering * 0.5;
  1169. }
  1170. VectorNormalize(vecDir);
  1171. }
  1172. const float radius = speed * 0.4;
  1173. // 0.3 seconds ahead of the jeep
  1174. vecSpot = vecStart + vecDir * (speed * 0.3f);
  1175. CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, radius, soundDuration, this, 0 );
  1176. CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, vecSpot, radius, soundDuration, this, 1 );
  1177. //NDebugOverlay::Box(vecSpot, Vector(-radius,-radius,-radius),Vector(radius,radius,radius), 255, 0, 255, 0, soundDuration);
  1178. #if 0
  1179. trace_t tr;
  1180. // put sounds a bit to left and right but slightly closer to Jeep to make a "cone" of sound
  1181. // in front of it
  1182. vecSpot = vecStart + vecDir * (speed * 0.5f) - vecRight * speed * 0.5;
  1183. UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  1184. CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 1 );
  1185. vecSpot = vecStart + vecDir * (speed * 0.5f) + vecRight * speed * 0.5;
  1186. UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  1187. CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 2);
  1188. #endif
  1189. }
  1190. m_flDangerSoundTime = gpGlobals->curtime + 0.1;
  1191. }
  1192. //-----------------------------------------------------------------------------
  1193. // Purpose:
  1194. //-----------------------------------------------------------------------------
  1195. void CPropJeep::EnterVehicle( CBasePlayer *pPlayer )
  1196. {
  1197. if ( !pPlayer )
  1198. return;
  1199. CheckWater();
  1200. BaseClass::EnterVehicle( pPlayer );
  1201. // Start looking for seagulls to land
  1202. m_hLastPlayerInVehicle = m_hPlayer;
  1203. }
  1204. //-----------------------------------------------------------------------------
  1205. // Purpose:
  1206. //-----------------------------------------------------------------------------
  1207. void CPropJeep::ExitVehicle( int nRole )
  1208. {
  1209. HeadlightTurnOff();
  1210. BaseClass::ExitVehicle( nRole );
  1211. //If the player has exited, stop charging
  1212. StopChargeSound();
  1213. m_bCannonCharging = false;
  1214. // Remember when we last saw the player
  1215. m_flPlayerExitedTime = gpGlobals->curtime;
  1216. m_flLastSawPlayerAt = gpGlobals->curtime;
  1217. }
  1218. //-----------------------------------------------------------------------------
  1219. // Purpose:
  1220. //-----------------------------------------------------------------------------
  1221. void CPropJeep::InputStartRemoveTauCannon( inputdata_t &inputdata )
  1222. {
  1223. // Start the gun removal animation
  1224. m_flAnimTime = gpGlobals->curtime;
  1225. m_flPlaybackRate = 0.0;
  1226. SetCycle( 0 );
  1227. ResetSequence( LookupSequence( "tau_levitate" ) );
  1228. m_bGunHasBeenCutOff = true;
  1229. }
  1230. //-----------------------------------------------------------------------------
  1231. // Purpose:
  1232. //-----------------------------------------------------------------------------
  1233. void CPropJeep::InputFinishRemoveTauCannon( inputdata_t &inputdata )
  1234. {
  1235. // Remove & hide the gun
  1236. SetBodygroup( 1, false );
  1237. m_bHasGun = false;
  1238. }
  1239. //-----------------------------------------------------------------------------
  1240. // Purpose:
  1241. //-----------------------------------------------------------------------------
  1242. void CPropJeep::OnRestore( void )
  1243. {
  1244. IServerVehicle *pServerVehicle = GetServerVehicle();
  1245. if ( pServerVehicle != NULL )
  1246. {
  1247. // Restore the passenger information we're holding on to
  1248. pServerVehicle->RestorePassengerInfo();
  1249. }
  1250. }
  1251. //========================================================================================================================================
  1252. // JEEP FOUR WHEEL PHYSICS VEHICLE SERVER VEHICLE
  1253. //========================================================================================================================================
  1254. //-----------------------------------------------------------------------------
  1255. // Purpose:
  1256. //-----------------------------------------------------------------------------
  1257. void CJeepFourWheelServerVehicle::NPC_AimPrimaryWeapon( Vector vecTarget )
  1258. {
  1259. ((CPropJeep*)m_pVehicle)->AimGunAt( &vecTarget, 0.1f );
  1260. }
  1261. //-----------------------------------------------------------------------------
  1262. // Purpose:
  1263. // Input : &vecEyeExitEndpoint -
  1264. // Output : int
  1265. //-----------------------------------------------------------------------------
  1266. int CJeepFourWheelServerVehicle::GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked )
  1267. {
  1268. bAllPointsBlocked = false;
  1269. if ( !m_bParsedAnimations )
  1270. {
  1271. // Load the entry/exit animations from the vehicle
  1272. ParseEntryExitAnims();
  1273. m_bParsedAnimations = true;
  1274. }
  1275. CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating *>(m_pVehicle);
  1276. // If we don't have the gun anymore, we want to get out using the "gun-less" animation
  1277. if ( pAnimating && ((CPropJeep*)m_pVehicle)->TauCannonHasBeenCutOff() )
  1278. {
  1279. // HACK: We know the tau-cannon removed exit anim uses the first upright anim's exit details
  1280. trace_t tr;
  1281. // Convert our offset points to worldspace ones
  1282. Vector vehicleExitOrigin = m_ExitAnimations[0].vecExitPointLocal;
  1283. QAngle vehicleExitAngles = m_ExitAnimations[0].vecExitAnglesLocal;
  1284. UTIL_ParentToWorldSpace( pAnimating, vehicleExitOrigin, vehicleExitAngles );
  1285. // Ensure the endpoint is clear by dropping a point down from above
  1286. vehicleExitOrigin -= VEC_VIEW;
  1287. Vector vecMove = Vector(0,0,64);
  1288. Vector vecStart = vehicleExitOrigin + vecMove;
  1289. Vector vecEnd = vehicleExitOrigin - vecMove;
  1290. UTIL_TraceHull( vecStart, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr );
  1291. Assert( !tr.startsolid && tr.fraction < 1.0 );
  1292. m_vecCurrentExitEndPoint = vecStart + ((vecEnd - vecStart) * tr.fraction);
  1293. vecEyeExitEndpoint = m_vecCurrentExitEndPoint + VEC_VIEW;
  1294. m_iCurrentExitAnim = 0;
  1295. return pAnimating->LookupSequence( "exit_tauremoved" );
  1296. }
  1297. return BaseClass::GetExitAnimToUse( vecEyeExitEndpoint, bAllPointsBlocked );
  1298. }