Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1404 lines
38 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. //========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============
  8. //
  9. // Purpose:
  10. //
  11. // $NoKeywords: $
  12. //=============================================================================
  13. #include "cbase.h"
  14. #include "gamemovement.h"
  15. #include "dod_gamerules.h"
  16. #include "dod_shareddefs.h"
  17. #include "in_buttons.h"
  18. #include "movevars_shared.h"
  19. #include "weapon_dodsniper.h"
  20. #include "weapon_dodbaserpg.h"
  21. #include "weapon_dodsemiauto.h"
  22. #ifdef CLIENT_DLL
  23. #include "c_dod_player.h"
  24. #else
  25. #include "dod_player.h"
  26. #endif
  27. extern bool g_bMovementOptimizations;
  28. class CDODGameMovement : public CGameMovement
  29. {
  30. public:
  31. DECLARE_CLASS( CDODGameMovement, CGameMovement );
  32. CDODGameMovement();
  33. virtual ~CDODGameMovement();
  34. void SetPlayerSpeed( void );
  35. virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMove );
  36. virtual bool CanAccelerate();
  37. virtual bool CheckJumpButton( void );
  38. virtual void ReduceTimers( void );
  39. virtual void WalkMove( void );
  40. virtual void AirMove( void );
  41. virtual void CheckParameters( void );
  42. virtual void CheckFalling( void );
  43. // Ducking
  44. virtual void Duck( void );
  45. virtual void FinishUnDuck( void );
  46. virtual void FinishDuck( void );
  47. virtual void HandleDuckingSpeedCrop();
  48. void SetDODDuckedEyeOffset( float duckFraction );
  49. void SetDeployedEyeOffset( void );
  50. // Prone
  51. void SetProneEyeOffset( float proneFraction );
  52. void FinishProne( void );
  53. void FinishUnProne( void );
  54. bool CanUnprone();
  55. virtual Vector GetPlayerMins( void ) const; // uses local player
  56. virtual Vector GetPlayerMaxs( void ) const; // uses local player
  57. // IGameMovement interface
  58. virtual Vector GetPlayerMins( bool ducked ) const { return BaseClass::GetPlayerMins(ducked); }
  59. virtual Vector GetPlayerMaxs( bool ducked ) const { return BaseClass::GetPlayerMaxs(ducked); }
  60. virtual Vector GetPlayerViewOffset( bool ducked ) const { return BaseClass::GetPlayerViewOffset(ducked); }
  61. void ViewOffsetAnimation( Vector vecDest, float flTime, ViewAnimationType type );
  62. void SetViewOffset( Vector vecViewOffset );
  63. virtual unsigned int PlayerSolidMask( bool brushOnly = false );
  64. protected:
  65. virtual void PlayerMove();
  66. void CheckForLadders( bool wasOnGround );
  67. bool ResolveStanding( void );
  68. void TracePlayerBBoxWithStep( const Vector &vStart, const Vector &vEnd, unsigned int fMask, int collisionGroup, trace_t &trace );
  69. public:
  70. CDODPlayer *m_pDODPlayer;
  71. bool m_bUnProneToDuck;
  72. };
  73. // Expose our interface.
  74. static CDODGameMovement g_GameMovement;
  75. IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement;
  76. EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameMovement, IGameMovement,INTERFACENAME_GAMEMOVEMENT, g_GameMovement );
  77. // ---------------------------------------------------------------------------------------- //
  78. // CDODGameMovement.
  79. // ---------------------------------------------------------------------------------------- //
  80. CDODGameMovement::CDODGameMovement()
  81. {
  82. // Don't set any member variables here, or you'll get an access
  83. // violation exception on LoadLibrary, and will have to stay up til
  84. // 3 in the morning figuring out where you did bad things.
  85. m_bUnProneToDuck = false;
  86. }
  87. CDODGameMovement::~CDODGameMovement()
  88. {
  89. }
  90. void CDODGameMovement::SetPlayerSpeed( void )
  91. {
  92. if( DODGameRules()->State_Get() == STATE_PREROUND )
  93. {
  94. mv->m_flClientMaxSpeed = PLAYER_SPEED_FROZEN;
  95. return;
  96. }
  97. if ( m_pDODPlayer->m_Shared.IsPlanting() ||
  98. m_pDODPlayer->m_Shared.IsDefusing() )
  99. {
  100. mv->m_flClientMaxSpeed = PLAYER_SPEED_FROZEN;
  101. return;
  102. }
  103. bool bZoomed = ( m_pDODPlayer->GetFOV() < m_pDODPlayer->GetDefaultFOV() );
  104. bool bBazookaDeployed = false;
  105. bool bZoomingIn = false;
  106. CWeaponDODBase *pWpn = m_pDODPlayer->GetActiveDODWeapon();
  107. if( pWpn )
  108. {
  109. if( pWpn->GetDODWpnData().m_WeaponType == WPN_TYPE_BAZOOKA )
  110. {
  111. CDODBaseRocketWeapon *pBazooka = (CDODBaseRocketWeapon *)pWpn;
  112. bBazookaDeployed = pBazooka->ShouldPlayerBeSlow();
  113. }
  114. if ( pWpn->GetDODWpnData().m_WeaponType == WPN_TYPE_SNIPER )
  115. {
  116. CDODSniperWeapon *pSniper = dynamic_cast<CDODSniperWeapon *>( pWpn );
  117. if ( pSniper )
  118. {
  119. bZoomingIn = !bZoomed && pSniper->IsZoomingIn();
  120. }
  121. }
  122. }
  123. // are we zooming?
  124. if ( m_pDODPlayer->m_Shared.IsInMGDeploy() )
  125. {
  126. mv->m_flClientMaxSpeed = PLAYER_SPEED_FROZEN;
  127. }
  128. else if ( m_pDODPlayer->m_Shared.IsProne() &&
  129. !m_pDODPlayer->m_Shared.IsGettingUpFromProne() &&
  130. m_pDODPlayer->GetGroundEntity() != NULL )
  131. {
  132. if ( bZoomed )
  133. mv->m_flClientMaxSpeed = PLAYER_SPEED_PRONE_ZOOMED;
  134. else if ( bBazookaDeployed )
  135. mv->m_flClientMaxSpeed = PLAYER_SPEED_PRONE_BAZOOKA_DEPLOYED;
  136. else
  137. mv->m_flClientMaxSpeed = PLAYER_SPEED_PRONE; //Base prone speed
  138. }
  139. else //not prone, dead or deployed - standing or crouching and possibly moving
  140. {
  141. float stamina = m_pDODPlayer->m_Shared.GetStamina();
  142. if ( bZoomed )
  143. {
  144. mv->m_flClientMaxSpeed = PLAYER_SPEED_ZOOMED;
  145. }
  146. else if ( bBazookaDeployed )
  147. {
  148. mv->m_flClientMaxSpeed = PLAYER_SPEED_BAZOOKA_DEPLOYED;
  149. }
  150. else if ( mv->m_nButtons & IN_DUCK )
  151. {
  152. mv->m_flClientMaxSpeed = PLAYER_SPEED_RUN; //gets cut in fraction later
  153. }
  154. // check for slowed from leg hit or firing a machine gun
  155. else if ( m_pDODPlayer->m_Shared.GetSlowedTime() > gpGlobals->curtime )
  156. {
  157. mv->m_flClientMaxSpeed = PLAYER_SPEED_SLOWED;
  158. }
  159. else
  160. {
  161. float flMaxSpeed;
  162. if ( ( mv->m_nButtons & IN_SPEED ) && ( stamina > 0 ) && ( mv->m_nButtons & IN_FORWARD ) && !bZoomingIn )
  163. {
  164. flMaxSpeed = PLAYER_SPEED_SPRINT; //sprinting
  165. }
  166. else
  167. {
  168. flMaxSpeed = PLAYER_SPEED_RUN; //jogging
  169. }
  170. mv->m_flClientMaxSpeed = flMaxSpeed - 100 + stamina;
  171. }
  172. }
  173. if ( m_pDODPlayer->GetGroundEntity() != NULL )
  174. {
  175. if( m_pDODPlayer->m_Shared.IsGoingProne() )
  176. {
  177. float pronetime = m_pDODPlayer->m_Shared.m_flGoProneTime - gpGlobals->curtime;
  178. //interp to prone speed
  179. float flProneFraction = SimpleSpline( pronetime / TIME_TO_PRONE );
  180. float maxSpeed = mv->m_flClientMaxSpeed;
  181. if ( m_bUnProneToDuck )
  182. maxSpeed *= 0.33;
  183. mv->m_flClientMaxSpeed = ( ( 1 - flProneFraction ) * PLAYER_SPEED_PRONE ) + ( flProneFraction * maxSpeed );
  184. }
  185. else if( m_pDODPlayer->m_Shared.IsGettingUpFromProne() )
  186. {
  187. float pronetime = m_pDODPlayer->m_Shared.m_flUnProneTime - gpGlobals->curtime;
  188. //interp to regular speed speed
  189. float flProneFraction = SimpleSpline( pronetime / TIME_TO_PRONE );
  190. float maxSpeed = mv->m_flClientMaxSpeed;
  191. if ( m_bUnProneToDuck )
  192. maxSpeed *= 0.33;
  193. mv->m_flClientMaxSpeed = ( flProneFraction * PLAYER_SPEED_PRONE ) + ( ( 1 - flProneFraction ) * maxSpeed );
  194. }
  195. }
  196. }
  197. ConVar cl_show_speed( "cl_show_speed", "0", FCVAR_CHEAT | FCVAR_REPLICATED, "spam console with local player speed" );
  198. //-----------------------------------------------------------------------------
  199. // Purpose:
  200. //-----------------------------------------------------------------------------
  201. void CDODGameMovement::CheckParameters( void )
  202. {
  203. QAngle v_angle;
  204. SetPlayerSpeed();
  205. if ( player->GetMoveType() != MOVETYPE_ISOMETRIC &&
  206. player->GetMoveType() != MOVETYPE_NOCLIP &&
  207. player->GetMoveType() != MOVETYPE_OBSERVER )
  208. {
  209. float spd;
  210. float maxspeed;
  211. spd = ( mv->m_flForwardMove * mv->m_flForwardMove ) +
  212. ( mv->m_flSideMove * mv->m_flSideMove ) +
  213. ( mv->m_flUpMove * mv->m_flUpMove );
  214. maxspeed = mv->m_flClientMaxSpeed;
  215. if ( maxspeed != 0.0 )
  216. {
  217. mv->m_flMaxSpeed = MIN( maxspeed, mv->m_flMaxSpeed );
  218. }
  219. // Slow down by the speed factor
  220. float flSpeedFactor = 1.0f;
  221. if ( player->GetSurfaceData() )
  222. {
  223. flSpeedFactor = player->GetSurfaceData()->game.maxSpeedFactor;
  224. }
  225. // If we have a constraint, slow down because of that too.
  226. float flConstraintSpeedFactor = ComputeConstraintSpeedFactor();
  227. if (flConstraintSpeedFactor < flSpeedFactor)
  228. flSpeedFactor = flConstraintSpeedFactor;
  229. mv->m_flMaxSpeed *= flSpeedFactor;
  230. if ( g_bMovementOptimizations )
  231. {
  232. // Same thing but only do the sqrt if we have to.
  233. if ( ( spd != 0.0 ) && ( spd > mv->m_flMaxSpeed*mv->m_flMaxSpeed ) )
  234. {
  235. float fRatio = mv->m_flMaxSpeed / sqrt( spd );
  236. mv->m_flForwardMove *= fRatio;
  237. mv->m_flSideMove *= fRatio;
  238. mv->m_flUpMove *= fRatio;
  239. }
  240. }
  241. else
  242. {
  243. spd = sqrt( spd );
  244. if ( ( spd != 0.0 ) && ( spd > mv->m_flMaxSpeed ) )
  245. {
  246. float fRatio = mv->m_flMaxSpeed / spd;
  247. mv->m_flForwardMove *= fRatio;
  248. mv->m_flSideMove *= fRatio;
  249. mv->m_flUpMove *= fRatio;
  250. }
  251. }
  252. }
  253. if ( player->GetFlags() & FL_FROZEN ||
  254. player->GetFlags() & FL_ONTRAIN ||
  255. IsDead() )
  256. {
  257. mv->m_flForwardMove = 0;
  258. mv->m_flSideMove = 0;
  259. mv->m_flUpMove = 0;
  260. }
  261. DecayPunchAngle();
  262. // Take angles from command.
  263. if ( !IsDead() )
  264. {
  265. v_angle = mv->m_vecAngles;
  266. v_angle = v_angle + player->m_Local.m_vecPunchAngle;
  267. // Now adjust roll angle
  268. if ( player->GetMoveType() != MOVETYPE_ISOMETRIC &&
  269. player->GetMoveType() != MOVETYPE_NOCLIP )
  270. {
  271. mv->m_vecAngles[ROLL] = CalcRoll( v_angle, mv->m_vecVelocity, sv_rollangle.GetFloat(), sv_rollspeed.GetFloat() );
  272. }
  273. else
  274. {
  275. mv->m_vecAngles[ROLL] = 0.0; // v_angle[ ROLL ];
  276. }
  277. mv->m_vecAngles[PITCH] = v_angle[PITCH];
  278. mv->m_vecAngles[YAW] = v_angle[YAW];
  279. }
  280. else
  281. {
  282. mv->m_vecAngles = mv->m_vecOldAngles;
  283. }
  284. // Set dead player view_offset
  285. if ( IsDead() )
  286. {
  287. SetViewOffset( VEC_DEAD_VIEWHEIGHT_SCALED( player ) );
  288. }
  289. // Adjust client view angles to match values used on server.
  290. if ( mv->m_vecAngles[YAW] > 180.0f )
  291. {
  292. mv->m_vecAngles[YAW] -= 360.0f;
  293. }
  294. if ( cl_show_speed.GetBool() )
  295. {
  296. Vector vel = m_pDODPlayer->GetAbsVelocity();
  297. float actual_speed = sqrt( vel.x * vel.x + vel.y * vel.y );
  298. Msg( "player speed %.1f\n",actual_speed );
  299. }
  300. }
  301. void CDODGameMovement::CheckFalling( void )
  302. {
  303. // if we landed on the ground
  304. if ( player->GetGroundEntity() != NULL && !IsDead() )
  305. {
  306. if ( player->m_Local.m_flFallVelocity >= 300 )
  307. {
  308. CPASFilter filter( player->GetAbsOrigin() );
  309. filter.UsePredictionRules();
  310. player->EmitSound( filter, player->entindex(), "Player.JumpLanding" );
  311. }
  312. // turn off the jumping flag if we're on ground after a jump
  313. if ( m_pDODPlayer->m_Shared.IsJumping() )
  314. {
  315. m_pDODPlayer->m_Shared.SetJumping( false );
  316. // if we landed from a jump, slow us
  317. if ( player->m_Local.m_flFallVelocity > 50 )
  318. m_pDODPlayer->m_Shared.SetSlowedTime( 0.5 );
  319. }
  320. }
  321. BaseClass::CheckFalling();
  322. }
  323. void CDODGameMovement::ProcessMovement( CBasePlayer *pBasePlayer, CMoveData *pMove )
  324. {
  325. //Store the player pointer
  326. m_pDODPlayer = ToDODPlayer( pBasePlayer );
  327. Assert( m_pDODPlayer );
  328. m_pDODPlayer->m_Shared.ViewAnimThink();
  329. BaseClass::ProcessMovement( pBasePlayer, pMove );
  330. }
  331. bool CDODGameMovement::CanAccelerate()
  332. {
  333. // Only allow the player to accelerate when in certain states.
  334. DODPlayerState curState = m_pDODPlayer->State_Get();
  335. if ( curState == STATE_ACTIVE )
  336. {
  337. return player->GetWaterJumpTime() == 0;
  338. }
  339. else if ( player->IsObserver() )
  340. {
  341. return true;
  342. }
  343. else
  344. {
  345. return false;
  346. }
  347. }
  348. void CDODGameMovement::PlayerMove()
  349. {
  350. BaseClass::PlayerMove();
  351. if ( player->GetMoveType() != MOVETYPE_ISOMETRIC &&
  352. player->GetMoveType() != MOVETYPE_NOCLIP &&
  353. player->GetMoveType() != MOVETYPE_OBSERVER )
  354. {
  355. // Cap actual player speed, fix wall running
  356. float spd = mv->m_vecVelocity[0] * mv->m_vecVelocity[0] +
  357. mv->m_vecVelocity[1] * mv->m_vecVelocity[1];
  358. if( spd > 0.0 && spd > ( mv->m_flMaxSpeed * mv->m_flMaxSpeed ) )
  359. {
  360. float fRatio = mv->m_flMaxSpeed / sqrt( spd );
  361. mv->m_vecVelocity[0] *= fRatio;
  362. mv->m_vecVelocity[1] *= fRatio;
  363. }
  364. }
  365. }
  366. void CDODGameMovement::WalkMove( void )
  367. {
  368. float flSpeed = m_pDODPlayer->GetAbsVelocity().Length2D();
  369. bool bSprintButtonPressed = ( mv->m_nButtons & IN_SPEED ) > 0;
  370. if( bSprintButtonPressed &&
  371. ( mv->m_nButtons & IN_FORWARD ) &&
  372. !m_pDODPlayer->m_Shared.IsProne() &&
  373. !m_pDODPlayer->m_Shared.IsDucking() &&
  374. flSpeed > 80 )
  375. {
  376. m_pDODPlayer->SetSprinting( true );
  377. }
  378. else
  379. {
  380. m_pDODPlayer->SetSprinting( false );
  381. }
  382. BaseClass::WalkMove();
  383. //CheckForLadders( true );
  384. //ResolveStanding();
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Purpose: Allow bots etc to use slightly different solid masks
  388. //-----------------------------------------------------------------------------
  389. unsigned int CDODGameMovement::PlayerSolidMask( bool brushOnly )
  390. {
  391. int mask = 0;
  392. switch ( m_pDODPlayer->GetTeamNumber() )
  393. {
  394. case TEAM_ALLIES:
  395. mask = CONTENTS_TEAM1;
  396. break;
  397. case TEAM_AXIS:
  398. mask = CONTENTS_TEAM2;
  399. break;
  400. }
  401. return ( mask | BaseClass::PlayerSolidMask( brushOnly ) );
  402. }
  403. void CDODGameMovement::AirMove( void )
  404. {
  405. BaseClass::AirMove();
  406. //CheckForLadders( false );
  407. }
  408. void CDODGameMovement::CheckForLadders( bool wasOnGround )
  409. {
  410. if ( !wasOnGround || !ResolveStanding() )
  411. {
  412. trace_t trace;
  413. TracePlayerBBox( mv->GetAbsOrigin(), mv->GetAbsOrigin() + Vector( 0, 0, -5), MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
  414. if ( trace.fraction == 1.0f )
  415. {
  416. Vector vel = -m_pDODPlayer->m_lastStandingPos + mv->GetAbsOrigin();
  417. if ( !vel.x && !vel.y )
  418. {
  419. return;
  420. }
  421. vel.NormalizeInPlace();
  422. vel *= 5.0f;
  423. Vector vecStartPos( mv->GetAbsOrigin().x + vel.x, mv->GetAbsOrigin().y + vel.y, mv->GetAbsOrigin().z );
  424. vel *= 5.0f;
  425. Vector vecStandPos( mv->GetAbsOrigin().x - vel.x, mv->GetAbsOrigin().y - vel.y, mv->GetAbsOrigin().z - ( player->m_Local.m_flStepSize * 1.0f ) );
  426. TracePlayerBBoxWithStep( vecStartPos, vecStandPos, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
  427. if ( trace.fraction != 1.0f && OnLadder( trace ) && trace.plane.normal.z != 1.0f )
  428. {
  429. if ( trace.fraction > 0.6 )
  430. {
  431. vel.NormalizeInPlace();
  432. Vector org = mv->GetAbsOrigin();
  433. org -= vel*5;
  434. mv->SetAbsOrigin( org );
  435. }
  436. player->SetMoveType( MOVETYPE_LADDER );
  437. player->SetMoveCollide( MOVECOLLIDE_DEFAULT );
  438. player->SetLadderNormal( trace.plane.normal );
  439. mv->m_vecVelocity.Init();
  440. }
  441. }
  442. }
  443. else
  444. {
  445. m_pDODPlayer->m_lastStandingPos = mv->GetAbsOrigin();
  446. }
  447. }
  448. inline void CDODGameMovement::TracePlayerBBoxWithStep( const Vector &vStart, const Vector &vEnd,
  449. unsigned int fMask, int collisionGroup, trace_t &trace )
  450. {
  451. VPROF( "CDODGameMovement::TracePlayerBBoxWithStep" );
  452. Vector vHullMin = GetPlayerMins( player->m_Local.m_bDucked );
  453. vHullMin.z += player->m_Local.m_flStepSize;
  454. Vector vHullMax = GetPlayerMaxs( player->m_Local.m_bDucked );
  455. Ray_t ray;
  456. ray.Init( vStart, vEnd, vHullMin, vHullMax );
  457. UTIL_TraceRay( ray, fMask, mv->m_nPlayerHandle.Get(), collisionGroup, &trace );
  458. }
  459. // Taken from TF2 to prevent bouncing down slopes
  460. bool CDODGameMovement::ResolveStanding( void )
  461. {
  462. VPROF( "CDODGameMovement::ResolveStanding" );
  463. //
  464. // Attempt to move down twice your step height. Anything between 0.5 and 1.0
  465. // is a valid "stand" value.
  466. //
  467. // Matt - don't move twice your step height, only check a little bit down
  468. // this will keep us relatively glued to stairs without feeling too snappy
  469. float flMaxStepDrop = 8.0f;
  470. Vector vecStandPos( mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, mv->GetAbsOrigin().z - ( flMaxStepDrop ) );
  471. trace_t trace;
  472. TracePlayerBBoxWithStep( mv->GetAbsOrigin(), vecStandPos, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
  473. // Anything between 0.5 and 1.0 is a valid stand value
  474. if ( fabs( trace.fraction - 0.5 ) < 0.0004f )
  475. {
  476. return true;
  477. }
  478. if ( trace.fraction > 0.5f )
  479. {
  480. trace.fraction -= 0.5f;
  481. Vector vecNewOrigin;
  482. vecNewOrigin = mv->GetAbsOrigin() + trace.fraction * ( vecStandPos - mv->GetAbsOrigin() );
  483. mv->SetAbsOrigin( vecNewOrigin );
  484. return false;
  485. }
  486. // Less than 0.5 mean we need to attempt to push up the difference.
  487. vecStandPos.z = ( mv->GetAbsOrigin().z + ( ( 0.5f - trace.fraction ) * ( player->m_Local.m_flStepSize * 2.0f ) ) );
  488. TracePlayerBBoxWithStep( mv->GetAbsOrigin(), vecStandPos, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
  489. // A fraction of 1.0 means we stood up fine - done.
  490. if ( trace.fraction == 1.0f )
  491. {
  492. mv->SetAbsOrigin( trace.endpos );
  493. return true;
  494. }
  495. return false;
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose: Recover stamina
  499. //-----------------------------------------------------------------------------
  500. void CDODGameMovement::ReduceTimers( void )
  501. {
  502. Vector vecPlayerVelocity = m_pDODPlayer->GetAbsVelocity();
  503. float flStamina = m_pDODPlayer->m_Shared.GetStamina();
  504. float fl2DVelocitySquared = vecPlayerVelocity.x * vecPlayerVelocity.x +
  505. vecPlayerVelocity.y * vecPlayerVelocity.y;
  506. if ( !( mv->m_nButtons & IN_SPEED ) )
  507. {
  508. m_pDODPlayer->m_Shared.ResetSprintPenalty();
  509. }
  510. // Can only sprint in forward direction.
  511. bool bSprinting = ( (mv->m_nButtons & IN_SPEED) && ( mv->m_nButtons & IN_FORWARD ) );
  512. // If we're holding the sprint key and also actually moving, remove some stamina
  513. Vector vel = m_pDODPlayer->GetAbsVelocity();
  514. if ( bSprinting && fl2DVelocitySquared > 10000 ) //speed > 100
  515. {
  516. //flStamina -= 30 * gpGlobals->frametime; //reduction for sprinting
  517. //flStamina += 10 * gpGlobals->frametime; //addition for recovering
  518. flStamina -= 20 * gpGlobals->frametime;
  519. m_pDODPlayer->m_Shared.SetStamina( flStamina );
  520. }
  521. else
  522. {
  523. //gain some back
  524. if ( fl2DVelocitySquared <= 0 )
  525. {
  526. flStamina += 60 * gpGlobals->frametime;
  527. }
  528. else if ( ( m_pDODPlayer->GetFlags() & FL_ONGROUND ) &&
  529. ( mv->m_nButtons & IN_DUCK ) &&
  530. ( m_pDODPlayer->GetFlags() & FL_DUCKING ) )
  531. {
  532. flStamina += 50 * gpGlobals->frametime;
  533. }
  534. else
  535. {
  536. flStamina += 10 * gpGlobals->frametime;
  537. }
  538. m_pDODPlayer->m_Shared.SetStamina( flStamina );
  539. }
  540. #ifdef CLIENT_DLL
  541. if ( bSprinting && flStamina < 25 )
  542. {
  543. m_pDODPlayer->HintMessage( HINT_LOW_STAMINA );
  544. }
  545. #endif
  546. BaseClass::ReduceTimers();
  547. }
  548. //-----------------------------------------------------------------------------
  549. // Purpose:
  550. //-----------------------------------------------------------------------------
  551. bool CDODGameMovement::CheckJumpButton( void )
  552. {
  553. if (m_pDODPlayer->pl.deadflag)
  554. {
  555. mv->m_nOldButtons |= IN_JUMP ; // don't jump again until released
  556. return false;
  557. }
  558. if( m_pDODPlayer->m_Shared.IsProne() ||
  559. m_pDODPlayer->m_Shared.IsGettingUpFromProne() ||
  560. m_pDODPlayer->m_Shared.IsGoingProne() )
  561. {
  562. mv->m_nOldButtons |= IN_JUMP;
  563. return false;
  564. }
  565. // See if we are waterjumping. If so, decrement count and return.
  566. float flWaterJumpTime = player->GetWaterJumpTime();
  567. if ( flWaterJumpTime > 0 )
  568. {
  569. flWaterJumpTime -= gpGlobals->frametime;
  570. if (flWaterJumpTime < 0)
  571. flWaterJumpTime = 0;
  572. player->SetWaterJumpTime( flWaterJumpTime );
  573. return false;
  574. }
  575. // If we are in the water most of the way...
  576. if ( m_pDODPlayer->GetWaterLevel() >= 2 )
  577. {
  578. // swimming, not jumping
  579. SetGroundEntity( NULL );
  580. if(m_pDODPlayer->GetWaterType() == CONTENTS_WATER) // We move up a certain amount
  581. mv->m_vecVelocity[2] = 100;
  582. else if (m_pDODPlayer->GetWaterType() == CONTENTS_SLIME)
  583. mv->m_vecVelocity[2] = 80;
  584. // play swiming sound
  585. if ( player->GetSwimSoundTime() <= 0 )
  586. {
  587. // Don't play sound again for 1 second
  588. player->SetSwimSoundTime( 1000 );
  589. PlaySwimSound();
  590. }
  591. return false;
  592. }
  593. // No more effect
  594. if (m_pDODPlayer->GetGroundEntity() == NULL)
  595. {
  596. mv->m_nOldButtons |= IN_JUMP;
  597. return false; // in air, so no effect
  598. }
  599. if ( mv->m_nOldButtons & IN_JUMP )
  600. return false; // don't pogo stick
  601. if( m_pDODPlayer->m_Shared.IsInMGDeploy() )
  602. {
  603. return false;
  604. }
  605. // In the air now.
  606. SetGroundEntity( NULL );
  607. m_pDODPlayer->PlayStepSound( (Vector &)mv->GetAbsOrigin(), player->GetSurfaceData(), 1.0, true );
  608. m_pDODPlayer->DoAnimationEvent( PLAYERANIMEVENT_JUMP );
  609. // make the jump sound
  610. CPASFilter filter( m_pDODPlayer->GetAbsOrigin() );
  611. filter.UsePredictionRules();
  612. m_pDODPlayer->EmitSound( filter, m_pDODPlayer->entindex(), "Player.Jump" );
  613. float flGroundFactor = 1.0f;
  614. if ( player->GetSurfaceData() )
  615. {
  616. flGroundFactor = player->GetSurfaceData()->game.jumpFactor;
  617. }
  618. /*
  619. // old and busted
  620. float flStamina = m_pDODPlayer->m_Shared.GetStamina();
  621. //15.0 is the base height. the player will always jump this high
  622. //regardless of stamina. Also the player will be able to jump max height
  623. //until he is below 60 stamina. Then the height will decrease proportionately
  624. float flJumpSpeed = 15.0; //base jump height
  625. if( flStamina >= 60.0f )
  626. {
  627. flJumpSpeed += 30.0;
  628. }
  629. else
  630. {
  631. flJumpSpeed += (30.0 * ( flStamina / 60.0f ) );
  632. }
  633. //Remove stamina for a successful jump
  634. m_pDODPlayer->m_Shared.SetStamina( flStamina - 40 );
  635. */
  636. // new hotness - constant jumpspeed of 45
  637. //m_pDODPlayer->m_Shared.SetSlowedTime( 1.0f );
  638. Assert( GetCurrentGravity() == 800.0f );
  639. // Accelerate upward
  640. // If we are ducking...
  641. float startz = mv->m_vecVelocity[2];
  642. if ( ( m_pDODPlayer->m_Local.m_bDucking ) || ( m_pDODPlayer->GetFlags() & FL_DUCKING ) )
  643. {
  644. // d = 0.5 * g * t^2 - distance traveled with linear accel
  645. // t = sqrt(2.0 * 45 / g) - how long to fall 45 units
  646. // v = g * t - velocity at the end (just invert it to jump up that high)
  647. // v = g * sqrt(2.0 * 45 / g )
  648. // v^2 = g * g * 2.0 * 45 / g
  649. // v = sqrt( g * 2.0 * 45 )
  650. mv->m_vecVelocity[2] = flGroundFactor * 268.3281572999747f; // flJumpSpeed of 45
  651. //mv->m_vecVelocity[2] = flGroundFactor * sqrt(2 * 800 * flJumpSpeed); // 2 * gravity * height
  652. }
  653. else
  654. {
  655. mv->m_vecVelocity[2] += flGroundFactor * 268.3281572999747f; // flJumpSpeed of 45
  656. //mv->m_vecVelocity[2] += flGroundFactor * sqrt(2 * 800 * flJumpSpeed); // 2 * gravity * height
  657. }
  658. FinishGravity();
  659. mv->m_outWishVel.z += mv->m_vecVelocity[2] - startz;
  660. mv->m_outStepHeight += 0.1f;
  661. // Flag that we jumped.
  662. mv->m_nOldButtons |= IN_JUMP; // don't jump again until released
  663. m_pDODPlayer->m_Shared.SetJumping( true );
  664. return true;
  665. }
  666. //-----------------------------------------------------------------------------
  667. // Purpose: Limit speed if we are ducking
  668. //-----------------------------------------------------------------------------
  669. void CDODGameMovement::HandleDuckingSpeedCrop()
  670. {
  671. if ( !( m_iSpeedCropped & SPEED_CROPPED_DUCK ) )
  672. {
  673. if ( ( mv->m_nButtons & IN_DUCK ) || ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) )
  674. {
  675. float frac = 0.33333333f;
  676. mv->m_flForwardMove *= frac;
  677. mv->m_flSideMove *= frac;
  678. mv->m_flUpMove *= frac;
  679. m_iSpeedCropped |= SPEED_CROPPED_DUCK;
  680. }
  681. }
  682. }
  683. bool CDODGameMovement::CanUnprone()
  684. {
  685. int i;
  686. trace_t trace;
  687. Vector newOrigin;
  688. VectorCopy( mv->GetAbsOrigin(), newOrigin );
  689. Vector vecMins, vecMaxs;
  690. if ( mv->m_nButtons & IN_DUCK )
  691. {
  692. vecMins = VEC_DUCK_HULL_MIN_SCALED( player );
  693. vecMaxs = VEC_DUCK_HULL_MAX_SCALED( player );
  694. }
  695. else
  696. {
  697. vecMins = VEC_HULL_MIN_SCALED( player );
  698. vecMaxs = VEC_HULL_MAX_SCALED( player );
  699. }
  700. if ( player->GetGroundEntity() != NULL )
  701. {
  702. for ( i = 0; i < 3; i++ )
  703. {
  704. newOrigin[i] += ( VEC_PRONE_HULL_MIN_SCALED( player )[i] - vecMins[i] );
  705. }
  706. }
  707. else
  708. {
  709. // If in air an letting go of crouch, make sure we can offset origin to make
  710. // up for uncrouching
  711. Vector hullSizeNormal = vecMaxs - vecMins;
  712. Vector hullSizeProne = VEC_PRONE_HULL_MAX_SCALED( player ) - VEC_PRONE_HULL_MIN_SCALED( player );
  713. Vector viewDelta = -0.5f * ( hullSizeNormal - hullSizeProne );
  714. VectorAdd( newOrigin, viewDelta, newOrigin );
  715. }
  716. bool saveprone = m_pDODPlayer->m_Shared.IsProne();
  717. bool saveducked = player->m_Local.m_bDucked;
  718. // pretend we're not prone
  719. m_pDODPlayer->m_Shared.SetProne( false );
  720. if ( mv->m_nButtons & IN_DUCK )
  721. player->m_Local.m_bDucked = true;
  722. TracePlayerBBox( mv->GetAbsOrigin(), newOrigin, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
  723. // revert to reality
  724. m_pDODPlayer->m_Shared.SetProne( saveprone );
  725. player->m_Local.m_bDucked = saveducked;
  726. if ( trace.startsolid || ( trace.fraction != 1.0f ) )
  727. return false;
  728. return true;
  729. }
  730. //-----------------------------------------------------------------------------
  731. // Purpose: Stop ducking
  732. //-----------------------------------------------------------------------------
  733. void CDODGameMovement::FinishUnDuck( void )
  734. {
  735. int i;
  736. trace_t trace;
  737. Vector newOrigin;
  738. VectorCopy( mv->GetAbsOrigin(), newOrigin );
  739. if ( player->GetGroundEntity() != NULL )
  740. {
  741. for ( i = 0; i < 3; i++ )
  742. {
  743. newOrigin[i] += ( VEC_DUCK_HULL_MIN_SCALED( player )[i] - VEC_HULL_MIN_SCALED( player )[i] );
  744. }
  745. }
  746. else
  747. {
  748. // If in air an letting go of crouch, make sure we can offset origin to make
  749. // up for uncrouching
  750. // orange box patch - made this match the check in CanUnduck()
  751. Vector hullSizeNormal = VEC_HULL_MAX_SCALED( player ) - VEC_HULL_MIN_SCALED( player );
  752. Vector hullSizeCrouch = VEC_DUCK_HULL_MAX_SCALED( player ) - VEC_DUCK_HULL_MIN_SCALED( player );
  753. Vector viewDelta = ( hullSizeNormal - hullSizeCrouch );
  754. viewDelta.Negate();
  755. VectorAdd( newOrigin, viewDelta, newOrigin );
  756. }
  757. player->m_Local.m_bDucked = false;
  758. player->RemoveFlag( FL_DUCKING );
  759. player->m_Local.m_bDucking = false;
  760. SetViewOffset( GetPlayerViewOffset( false ) );
  761. player->m_Local.m_flDucktime = 0;
  762. mv->SetAbsOrigin( newOrigin );
  763. // Recategorize position since ducking can change origin
  764. CategorizePosition();
  765. }
  766. //-----------------------------------------------------------------------------
  767. // Purpose: Finish ducking
  768. //-----------------------------------------------------------------------------
  769. void CDODGameMovement::FinishDuck( void )
  770. {
  771. Vector hullSizeNormal = VEC_HULL_MAX_SCALED( player ) - VEC_HULL_MIN_SCALED( player );
  772. Vector hullSizeCrouch = VEC_DUCK_HULL_MAX_SCALED( player ) - VEC_DUCK_HULL_MIN_SCALED( player );
  773. Vector viewDelta = 0.5f * ( hullSizeNormal - hullSizeCrouch );
  774. SetViewOffset( GetPlayerViewOffset( true ) );
  775. player->AddFlag( FL_DUCKING );
  776. player->m_Local.m_bDucking = false;
  777. if ( !player->m_Local.m_bDucked )
  778. {
  779. Vector org = mv->GetAbsOrigin();
  780. if ( player->GetGroundEntity() != NULL )
  781. {
  782. org -= VEC_DUCK_HULL_MIN_SCALED( player ) - VEC_HULL_MIN_SCALED( player );
  783. }
  784. else
  785. {
  786. VectorAdd( org, viewDelta, org );
  787. }
  788. mv->SetAbsOrigin( org );
  789. player->m_Local.m_bDucked = true;
  790. }
  791. // See if we are stuck?
  792. FixPlayerCrouchStuck( true );
  793. // Recategorize position since ducking can change origin
  794. CategorizePosition();
  795. }
  796. // Being deployed or undeploying totally stomps the duck view offset
  797. void CDODGameMovement::SetDeployedEyeOffset( void )
  798. {
  799. if ( m_pDODPlayer->m_Shared.IsProne() || m_pDODPlayer->m_Shared.IsGettingUpFromProne() )
  800. return;
  801. if ( !m_pDODPlayer->IsAlive() )
  802. return;
  803. float flTimeSinceDeployChange = gpGlobals->curtime - m_pDODPlayer->m_Shared.m_flDeployChangeTime;
  804. if ( m_pDODPlayer->m_Shared.IsInMGDeploy() || flTimeSinceDeployChange < TIME_TO_DEPLOY )
  805. {
  806. if ( m_pDODPlayer->m_Shared.IsInMGDeploy() )
  807. {
  808. // anim to deployed
  809. if ( m_pDODPlayer->m_Shared.GetLastViewAnimTime() < m_pDODPlayer->m_Shared.m_flDeployChangeTime.m_Value )
  810. {
  811. // Deployed height
  812. float flViewOffset = clamp( m_pDODPlayer->m_Shared.GetDeployedHeight(),
  813. CROUCHING_DEPLOY_HEIGHT,
  814. STANDING_DEPLOY_HEIGHT );
  815. Vector vecView = player->GetViewOffset();
  816. vecView.z = flViewOffset;
  817. ViewOffsetAnimation( vecView, TIME_TO_DEPLOY, VIEW_ANIM_LINEAR_Z_ONLY );
  818. m_pDODPlayer->m_Shared.SetLastViewAnimTime( gpGlobals->curtime );
  819. }
  820. }
  821. else
  822. {
  823. // anim to undeployed
  824. if ( m_pDODPlayer->m_Shared.GetLastViewAnimTime() < m_pDODPlayer->m_Shared.m_flDeployChangeTime.m_Value )
  825. {
  826. ViewOffsetAnimation( GetPlayerViewOffset( player->m_Local.m_bDucked ), TIME_TO_DEPLOY, VIEW_ANIM_LINEAR_Z_ONLY );
  827. m_pDODPlayer->m_Shared.SetLastViewAnimTime( gpGlobals->curtime );
  828. }
  829. }
  830. if ( flTimeSinceDeployChange >= TIME_TO_DEPLOY )
  831. {
  832. player->m_Local.m_bDucked = false;
  833. player->RemoveFlag( FL_DUCKING );
  834. player->m_Local.m_bDucking = false;
  835. player->m_Local.m_flDucktime = 0;
  836. }
  837. }
  838. }
  839. //-----------------------------------------------------------------------------
  840. // Purpose:
  841. // Input : duckFraction -
  842. //-----------------------------------------------------------------------------
  843. void CDODGameMovement::SetDODDuckedEyeOffset( float duckFraction )
  844. {
  845. // Different from CGameMovement in that
  846. Vector vDuckHullMin = GetPlayerMins( true );
  847. Vector vStandHullMin = GetPlayerMins( false );
  848. float fMore = ( vDuckHullMin.z - vStandHullMin.z );
  849. Vector vecStandViewOffset = GetPlayerViewOffset( false );
  850. Vector vecDuckViewOffset = GetPlayerViewOffset( true );
  851. Vector temp = player->GetViewOffset();
  852. temp.z = ( ( vecDuckViewOffset.z - fMore ) * duckFraction ) +
  853. ( vecStandViewOffset.z * ( 1 - duckFraction ) );
  854. SetViewOffset( temp );
  855. }
  856. void CDODGameMovement::SetProneEyeOffset( float proneFraction )
  857. {
  858. Vector vecPropViewOffset = VEC_PRONE_VIEW;
  859. Vector vecStandViewOffset = GetPlayerViewOffset( player->m_Local.m_bDucked );
  860. Vector temp = player->GetViewOffset();
  861. temp.z = SimpleSplineRemapVal( proneFraction, 1.0, 0.0, vecPropViewOffset.z, vecStandViewOffset.z );
  862. SetViewOffset( temp );
  863. }
  864. void CDODGameMovement::FinishUnProne( void )
  865. {
  866. m_pDODPlayer->m_Shared.m_flUnProneTime = 0.0f;
  867. SetProneEyeOffset( 0.0 );
  868. Vector vHullMin = GetPlayerMins( player->m_Local.m_bDucked );
  869. Vector vHullMax = GetPlayerMaxs( player->m_Local.m_bDucked );
  870. if ( m_bUnProneToDuck )
  871. {
  872. FinishDuck();
  873. }
  874. else
  875. {
  876. CategorizePosition();
  877. if ( mv->m_nButtons & IN_DUCK && !( player->GetFlags() & FL_DUCKING ) )
  878. {
  879. // Use 1 second so super long jump will work
  880. player->m_Local.m_flDucktime = 1000;
  881. player->m_Local.m_bDucking = true;
  882. }
  883. }
  884. }
  885. void CDODGameMovement::FinishProne( void )
  886. {
  887. m_pDODPlayer->m_Shared.SetProne( true );
  888. m_pDODPlayer->m_Shared.m_flGoProneTime = 0.0f;
  889. #ifndef CLIENT_DLL
  890. m_pDODPlayer->HintMessage( HINT_PRONE );
  891. #endif
  892. FinishUnDuck(); // clear ducking
  893. SetProneEyeOffset( 1.0 );
  894. FixPlayerCrouchStuck(true);
  895. CategorizePosition();
  896. }
  897. //-----------------------------------------------------------------------------
  898. // Purpose: See if duck button is pressed and do the appropriate things
  899. //-----------------------------------------------------------------------------
  900. void CDODGameMovement::Duck( void )
  901. {
  902. int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame
  903. int buttonsPressed = buttonsChanged & mv->m_nButtons; // The changed ones still down are "pressed"
  904. int buttonsReleased = buttonsChanged & mv->m_nOldButtons; // The changed ones which were previously down are "released"
  905. if ( mv->m_nButtons & IN_DUCK )
  906. {
  907. mv->m_nOldButtons |= IN_DUCK;
  908. }
  909. else
  910. {
  911. mv->m_nOldButtons &= ~IN_DUCK;
  912. }
  913. if ( !player->IsAlive() )
  914. {
  915. if( m_pDODPlayer->m_Shared.IsProne() )
  916. {
  917. FinishUnProne();
  918. }
  919. // Unduck
  920. if ( player->m_Local.m_bDucking || player->m_Local.m_bDucked )
  921. {
  922. FinishUnDuck();
  923. }
  924. return;
  925. }
  926. static int iState = 0;
  927. // Prone / UnProne - we don't duck or deploy if this is happening
  928. if( m_pDODPlayer->m_Shared.m_flUnProneTime > 0.0f )
  929. {
  930. float pronetime = m_pDODPlayer->m_Shared.m_flUnProneTime - gpGlobals->curtime;
  931. if( pronetime < 0 )
  932. {
  933. FinishUnProne();
  934. if ( !m_bUnProneToDuck && ( mv->m_nButtons & IN_DUCK ) )
  935. {
  936. buttonsPressed |= IN_DUCK;
  937. mv->m_nOldButtons &= ~IN_DUCK;
  938. }
  939. }
  940. // Set these, so that as soon as we stop unproning, we don't pop to standing
  941. // the information that we let go of the duck key has been lost by now.
  942. if ( m_bUnProneToDuck )
  943. {
  944. player->m_Local.m_flDucktime = 1000;
  945. player->m_Local.m_bDucking = true;
  946. }
  947. //don't deal with ducking while we're proning
  948. return;
  949. }
  950. else if( m_pDODPlayer->m_Shared.m_flGoProneTime > 0.0f )
  951. {
  952. float pronetime = m_pDODPlayer->m_Shared.m_flGoProneTime - gpGlobals->curtime;
  953. if( pronetime < 0 )
  954. {
  955. FinishProne();
  956. }
  957. //don't deal with ducking while we're proning
  958. return;
  959. }
  960. if ( gpGlobals->curtime > m_pDODPlayer->m_Shared.m_flNextProneCheck )
  961. {
  962. if ( buttonsPressed & IN_ALT1 && m_pDODPlayer->m_Shared.CanChangePosition() )
  963. {
  964. if( m_pDODPlayer->m_Shared.IsProne() == false &&
  965. m_pDODPlayer->m_Shared.IsGettingUpFromProne() == false )
  966. {
  967. m_pDODPlayer->m_Shared.StartGoingProne();
  968. // do unprone anim
  969. ViewOffsetAnimation( VEC_PRONE_VIEW, TIME_TO_PRONE, VIEW_ANIM_EXPONENTIAL_Z_ONLY );
  970. }
  971. else if( CanUnprone() )
  972. {
  973. m_pDODPlayer->m_Shared.SetProne( false );
  974. m_pDODPlayer->m_Shared.StandUpFromProne();
  975. // do unprone anim
  976. ViewOffsetAnimation( GetPlayerViewOffset( m_bUnProneToDuck ),
  977. TIME_TO_PRONE,
  978. VIEW_ANIM_EXPONENTIAL_Z_ONLY );
  979. m_bUnProneToDuck = ( mv->m_nButtons & IN_DUCK ) > 0;
  980. }
  981. m_pDODPlayer->m_Shared.m_flNextProneCheck = gpGlobals->curtime + 1.0f;
  982. return;
  983. }
  984. }
  985. SetDeployedEyeOffset();
  986. if ( m_pDODPlayer->m_Shared.IsProne() &&
  987. m_pDODPlayer->m_Shared.CanChangePosition() &&
  988. !m_pDODPlayer->m_Shared.IsGettingUpFromProne() &&
  989. ( buttonsPressed & IN_DUCK ) &&
  990. CanUnprone() ) // BUGBUG - even calling this will unzoom snipers.
  991. {
  992. // If the player presses duck while prone,
  993. // unprone them to the duck position
  994. m_pDODPlayer->m_Shared.SetProne( false );
  995. m_pDODPlayer->m_Shared.StandUpFromProne();
  996. m_bUnProneToDuck = true;
  997. // do unprone anim
  998. ViewOffsetAnimation( GetPlayerViewOffset( m_bUnProneToDuck ),
  999. TIME_TO_PRONE,
  1000. VIEW_ANIM_EXPONENTIAL_Z_ONLY );
  1001. // simulate a duck that was pressed while we were prone
  1002. player->AddFlag( FL_DUCKING );
  1003. player->m_Local.m_bDucked = true;
  1004. player->m_Local.m_flDucktime = 1000;
  1005. player->m_Local.m_bDucking = true;
  1006. }
  1007. // no ducking or unducking while deployed or prone
  1008. if( m_pDODPlayer->m_Shared.IsProne() ||
  1009. m_pDODPlayer->m_Shared.IsGettingUpFromProne() ||
  1010. !m_pDODPlayer->m_Shared.CanChangePosition() )
  1011. {
  1012. return;
  1013. }
  1014. HandleDuckingSpeedCrop();
  1015. if ( !( player->GetFlags() & FL_DUCKING ) && ( player->m_Local.m_bDucked ) )
  1016. {
  1017. player->m_Local.m_bDucked = false;
  1018. }
  1019. /*
  1020. Msg( "duck button %s ducking %s ducked %s duck flags %s\n",
  1021. ( mv->m_nButtons & IN_DUCK ) ? "down" : "up",
  1022. ( player->m_Local.m_bDucking ) ? "yes" : "no",
  1023. ( player->m_Local.m_bDucked ) ? "yes" : "no",
  1024. ( player->GetFlags() & FL_DUCKING ) ? "set" : "not set" );*/
  1025. // Holding duck, in process of ducking or fully ducked?
  1026. if ( ( mv->m_nButtons & IN_DUCK ) || ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) )
  1027. {
  1028. if ( mv->m_nButtons & IN_DUCK )
  1029. {
  1030. bool alreadyDucked = ( player->GetFlags() & FL_DUCKING ) ? true : false;
  1031. if ( (buttonsPressed & IN_DUCK ) && !( player->GetFlags() & FL_DUCKING ) )
  1032. {
  1033. // Use 1 second so super long jump will work
  1034. player->m_Local.m_flDucktime = 1000;
  1035. player->m_Local.m_bDucking = true;
  1036. }
  1037. float duckmilliseconds = MAX( 0.0f, 1000.0f - (float)player->m_Local.m_flDucktime );
  1038. float duckseconds = duckmilliseconds / 1000.0f;
  1039. //time = MAX( 0.0, ( 1.0 - (float)player->m_Local.m_flDucktime / 1000.0 ) );
  1040. if ( player->m_Local.m_bDucking )
  1041. {
  1042. // Finish ducking immediately if duck time is over or not on ground
  1043. if ( ( duckseconds > TIME_TO_DUCK ) ||
  1044. ( player->GetGroundEntity() == NULL ) ||
  1045. alreadyDucked)
  1046. {
  1047. FinishDuck();
  1048. }
  1049. else
  1050. {
  1051. // Calc parametric time
  1052. float flDuckFraction = SimpleSpline( duckseconds / TIME_TO_DUCK );
  1053. SetDODDuckedEyeOffset( flDuckFraction );
  1054. }
  1055. }
  1056. }
  1057. else
  1058. {
  1059. // Try to unduck unless automovement is not allowed
  1060. // NOTE: When not onground, you can always unduck
  1061. if ( player->m_Local.m_bAllowAutoMovement || player->GetGroundEntity() == NULL )
  1062. {
  1063. if ( (buttonsReleased & IN_DUCK ) && ( player->GetFlags() & FL_DUCKING ) )
  1064. {
  1065. // Use 1 second so super long jump will work
  1066. player->m_Local.m_flDucktime = 1000;
  1067. player->m_Local.m_bDucking = true; // or unducking
  1068. }
  1069. float duckmilliseconds = MAX( 0.0f, 1000.0f - (float)player->m_Local.m_flDucktime );
  1070. float duckseconds = duckmilliseconds / 1000.0f;
  1071. if ( CanUnduck() )
  1072. {
  1073. if ( player->m_Local.m_bDucking ||
  1074. player->m_Local.m_bDucked ) // or unducking
  1075. {
  1076. // Finish ducking immediately if duck time is over or not on ground
  1077. if ( ( duckseconds > TIME_TO_UNDUCK ) ||
  1078. ( player->GetGroundEntity() == NULL ) )
  1079. {
  1080. FinishUnDuck();
  1081. }
  1082. else
  1083. {
  1084. // Calc parametric time
  1085. float duckFraction = SimpleSpline( 1.0f - ( duckseconds / TIME_TO_UNDUCK ) );
  1086. SetDODDuckedEyeOffset( duckFraction );
  1087. }
  1088. }
  1089. }
  1090. else
  1091. {
  1092. // Still under something where we can't unduck, so make sure we reset this timer so
  1093. // that we'll unduck once we exit the tunnel, etc.
  1094. player->m_Local.m_flDucktime = 1000;
  1095. }
  1096. }
  1097. }
  1098. }
  1099. }
  1100. //-----------------------------------------------------------------------------
  1101. // Purpose:
  1102. // Input :
  1103. // Output : const Vector
  1104. //-----------------------------------------------------------------------------
  1105. Vector CDODGameMovement::GetPlayerMins( void ) const
  1106. {
  1107. if ( !player )
  1108. {
  1109. return vec3_origin;
  1110. }
  1111. if ( player->IsObserver() )
  1112. {
  1113. return VEC_OBS_HULL_MIN_SCALED( player );
  1114. }
  1115. else
  1116. {
  1117. if ( player->m_Local.m_bDucked )
  1118. return VEC_DUCK_HULL_MIN_SCALED( player );
  1119. else if ( m_pDODPlayer->m_Shared.IsProne() )
  1120. return VEC_PRONE_HULL_MIN_SCALED( player );
  1121. else
  1122. return VEC_HULL_MIN_SCALED( player );
  1123. }
  1124. }
  1125. //-----------------------------------------------------------------------------
  1126. // Purpose:
  1127. // Input :
  1128. // Output : const Vector
  1129. //-----------------------------------------------------------------------------
  1130. Vector CDODGameMovement::GetPlayerMaxs( void ) const
  1131. {
  1132. if ( !player )
  1133. {
  1134. return vec3_origin;
  1135. }
  1136. if ( player->IsObserver() )
  1137. {
  1138. return VEC_OBS_HULL_MAX_SCALED( player );
  1139. }
  1140. else
  1141. {
  1142. if ( player->m_Local.m_bDucked )
  1143. return VEC_DUCK_HULL_MAX_SCALED( player );
  1144. else if ( m_pDODPlayer->m_Shared.IsProne() )
  1145. return VEC_PRONE_HULL_MAX_SCALED( player );
  1146. else
  1147. return VEC_HULL_MAX_SCALED( player );
  1148. }
  1149. }
  1150. void CDODGameMovement::SetViewOffset( Vector vecViewOffset )
  1151. {
  1152. // call this instead of player->SetViewOffset directly, so we can cancel any
  1153. // animation in progress
  1154. m_pDODPlayer->m_Shared.ResetViewOffsetAnimation();
  1155. player->SetViewOffset( vecViewOffset );
  1156. }
  1157. void CDODGameMovement::ViewOffsetAnimation( Vector vecDest, float flTime, ViewAnimationType type )
  1158. {
  1159. m_pDODPlayer->m_Shared.ViewOffsetAnimation( vecDest, flTime, type );
  1160. }