summaryrefslogtreecommitdiff
path: root/game/shared/dod/dod_gamemovement.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/dod/dod_gamemovement.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/dod/dod_gamemovement.cpp')
-rw-r--r--game/shared/dod/dod_gamemovement.cpp1405
1 files changed, 1405 insertions, 0 deletions
diff --git a/game/shared/dod/dod_gamemovement.cpp b/game/shared/dod/dod_gamemovement.cpp
new file mode 100644
index 0000000..9582189
--- /dev/null
+++ b/game/shared/dod/dod_gamemovement.cpp
@@ -0,0 +1,1405 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+//========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+#include "cbase.h"
+#include "gamemovement.h"
+#include "dod_gamerules.h"
+#include "dod_shareddefs.h"
+#include "in_buttons.h"
+#include "movevars_shared.h"
+
+#include "weapon_dodsniper.h"
+#include "weapon_dodbaserpg.h"
+#include "weapon_dodsemiauto.h"
+
+
+#ifdef CLIENT_DLL
+ #include "c_dod_player.h"
+#else
+ #include "dod_player.h"
+#endif
+
+extern bool g_bMovementOptimizations;
+
+class CDODGameMovement : public CGameMovement
+{
+public:
+ DECLARE_CLASS( CDODGameMovement, CGameMovement );
+
+ CDODGameMovement();
+ virtual ~CDODGameMovement();
+
+ void SetPlayerSpeed( void );
+
+ virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMove );
+ virtual bool CanAccelerate();
+ virtual bool CheckJumpButton( void );
+ virtual void ReduceTimers( void );
+ virtual void WalkMove( void );
+ virtual void AirMove( void );
+ virtual void CheckParameters( void );
+ virtual void CheckFalling( void );
+
+ // Ducking
+ virtual void Duck( void );
+ virtual void FinishUnDuck( void );
+ virtual void FinishDuck( void );
+ virtual void HandleDuckingSpeedCrop();
+ void SetDODDuckedEyeOffset( float duckFraction );
+ void SetDeployedEyeOffset( void );
+
+ // Prone
+ void SetProneEyeOffset( float proneFraction );
+ void FinishProne( void );
+ void FinishUnProne( void );
+ bool CanUnprone();
+
+ virtual Vector GetPlayerMins( void ) const; // uses local player
+ virtual Vector GetPlayerMaxs( void ) const; // uses local player
+
+ // IGameMovement interface
+ virtual Vector GetPlayerMins( bool ducked ) const { return BaseClass::GetPlayerMins(ducked); }
+ virtual Vector GetPlayerMaxs( bool ducked ) const { return BaseClass::GetPlayerMaxs(ducked); }
+ virtual Vector GetPlayerViewOffset( bool ducked ) const { return BaseClass::GetPlayerViewOffset(ducked); }
+
+ void ViewOffsetAnimation( Vector vecDest, float flTime, ViewAnimationType type );
+
+ void SetViewOffset( Vector vecViewOffset );
+
+ virtual unsigned int PlayerSolidMask( bool brushOnly = false );
+
+protected:
+ virtual void PlayerMove();
+
+ void CheckForLadders( bool wasOnGround );
+ bool ResolveStanding( void );
+ void TracePlayerBBoxWithStep( const Vector &vStart, const Vector &vEnd, unsigned int fMask, int collisionGroup, trace_t &trace );
+
+public:
+ CDODPlayer *m_pDODPlayer;
+ bool m_bUnProneToDuck;
+};
+
+
+// Expose our interface.
+static CDODGameMovement g_GameMovement;
+IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement;
+
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameMovement, IGameMovement,INTERFACENAME_GAMEMOVEMENT, g_GameMovement );
+
+
+// ---------------------------------------------------------------------------------------- //
+// CDODGameMovement.
+// ---------------------------------------------------------------------------------------- //
+
+CDODGameMovement::CDODGameMovement()
+{
+ // Don't set any member variables here, or you'll get an access
+ // violation exception on LoadLibrary, and will have to stay up til
+ // 3 in the morning figuring out where you did bad things.
+
+ m_bUnProneToDuck = false;
+}
+
+CDODGameMovement::~CDODGameMovement()
+{
+}
+
+void CDODGameMovement::SetPlayerSpeed( void )
+{
+ if( DODGameRules()->State_Get() == STATE_PREROUND )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_FROZEN;
+ return;
+ }
+
+ if ( m_pDODPlayer->m_Shared.IsPlanting() ||
+ m_pDODPlayer->m_Shared.IsDefusing() )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_FROZEN;
+ return;
+ }
+
+ bool bZoomed = ( m_pDODPlayer->GetFOV() < m_pDODPlayer->GetDefaultFOV() );
+ bool bBazookaDeployed = false;
+ bool bZoomingIn = false;
+
+ CWeaponDODBase *pWpn = m_pDODPlayer->GetActiveDODWeapon();
+ if( pWpn )
+ {
+ if( pWpn->GetDODWpnData().m_WeaponType == WPN_TYPE_BAZOOKA )
+ {
+ CDODBaseRocketWeapon *pBazooka = (CDODBaseRocketWeapon *)pWpn;
+ bBazookaDeployed = pBazooka->ShouldPlayerBeSlow();
+ }
+
+ if ( pWpn->GetDODWpnData().m_WeaponType == WPN_TYPE_SNIPER )
+ {
+ CDODSniperWeapon *pSniper = dynamic_cast<CDODSniperWeapon *>( pWpn );
+ if ( pSniper )
+ {
+ bZoomingIn = !bZoomed && pSniper->IsZoomingIn();
+ }
+ }
+ }
+
+ // are we zooming?
+
+ if ( m_pDODPlayer->m_Shared.IsInMGDeploy() )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_FROZEN;
+ }
+ else if ( m_pDODPlayer->m_Shared.IsProne() &&
+ !m_pDODPlayer->m_Shared.IsGettingUpFromProne() &&
+ m_pDODPlayer->GetGroundEntity() != NULL )
+ {
+ if ( bZoomed )
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_PRONE_ZOOMED;
+ else if ( bBazookaDeployed )
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_PRONE_BAZOOKA_DEPLOYED;
+ else
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_PRONE; //Base prone speed
+ }
+ else //not prone, dead or deployed - standing or crouching and possibly moving
+ {
+ float stamina = m_pDODPlayer->m_Shared.GetStamina();
+
+ if ( bZoomed )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_ZOOMED;
+ }
+ else if ( bBazookaDeployed )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_BAZOOKA_DEPLOYED;
+ }
+ else if ( mv->m_nButtons & IN_DUCK )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_RUN; //gets cut in fraction later
+ }
+ // check for slowed from leg hit or firing a machine gun
+ else if ( m_pDODPlayer->m_Shared.GetSlowedTime() > gpGlobals->curtime )
+ {
+ mv->m_flClientMaxSpeed = PLAYER_SPEED_SLOWED;
+ }
+ else
+ {
+ float flMaxSpeed;
+
+ if ( ( mv->m_nButtons & IN_SPEED ) && ( stamina > 0 ) && ( mv->m_nButtons & IN_FORWARD ) && !bZoomingIn )
+ {
+ flMaxSpeed = PLAYER_SPEED_SPRINT; //sprinting
+ }
+ else
+ {
+ flMaxSpeed = PLAYER_SPEED_RUN; //jogging
+ }
+
+ mv->m_flClientMaxSpeed = flMaxSpeed - 100 + stamina;
+ }
+ }
+
+ if ( m_pDODPlayer->GetGroundEntity() != NULL )
+ {
+ if( m_pDODPlayer->m_Shared.IsGoingProne() )
+ {
+ float pronetime = m_pDODPlayer->m_Shared.m_flGoProneTime - gpGlobals->curtime;
+
+ //interp to prone speed
+ float flProneFraction = SimpleSpline( pronetime / TIME_TO_PRONE );
+
+ float maxSpeed = mv->m_flClientMaxSpeed;
+
+ if ( m_bUnProneToDuck )
+ maxSpeed *= 0.33;
+
+ mv->m_flClientMaxSpeed = ( ( 1 - flProneFraction ) * PLAYER_SPEED_PRONE ) + ( flProneFraction * maxSpeed );
+ }
+ else if( m_pDODPlayer->m_Shared.IsGettingUpFromProne() )
+ {
+ float pronetime = m_pDODPlayer->m_Shared.m_flUnProneTime - gpGlobals->curtime;
+
+ //interp to regular speed speed
+ float flProneFraction = SimpleSpline( pronetime / TIME_TO_PRONE );
+
+ float maxSpeed = mv->m_flClientMaxSpeed;
+
+ if ( m_bUnProneToDuck )
+ maxSpeed *= 0.33;
+
+ mv->m_flClientMaxSpeed = ( flProneFraction * PLAYER_SPEED_PRONE ) + ( ( 1 - flProneFraction ) * maxSpeed );
+ }
+ }
+}
+
+ConVar cl_show_speed( "cl_show_speed", "0", FCVAR_CHEAT | FCVAR_REPLICATED, "spam console with local player speed" );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODGameMovement::CheckParameters( void )
+{
+ QAngle v_angle;
+
+ SetPlayerSpeed();
+
+ if ( player->GetMoveType() != MOVETYPE_ISOMETRIC &&
+ player->GetMoveType() != MOVETYPE_NOCLIP &&
+ player->GetMoveType() != MOVETYPE_OBSERVER )
+ {
+ float spd;
+ float maxspeed;
+
+ spd = ( mv->m_flForwardMove * mv->m_flForwardMove ) +
+ ( mv->m_flSideMove * mv->m_flSideMove ) +
+ ( mv->m_flUpMove * mv->m_flUpMove );
+
+ maxspeed = mv->m_flClientMaxSpeed;
+ if ( maxspeed != 0.0 )
+ {
+ mv->m_flMaxSpeed = MIN( maxspeed, mv->m_flMaxSpeed );
+ }
+
+ // Slow down by the speed factor
+ float flSpeedFactor = 1.0f;
+ if ( player->GetSurfaceData() )
+ {
+ flSpeedFactor = player->GetSurfaceData()->game.maxSpeedFactor;
+ }
+
+ // If we have a constraint, slow down because of that too.
+ float flConstraintSpeedFactor = ComputeConstraintSpeedFactor();
+ if (flConstraintSpeedFactor < flSpeedFactor)
+ flSpeedFactor = flConstraintSpeedFactor;
+
+ mv->m_flMaxSpeed *= flSpeedFactor;
+
+ if ( g_bMovementOptimizations )
+ {
+ // Same thing but only do the sqrt if we have to.
+ if ( ( spd != 0.0 ) && ( spd > mv->m_flMaxSpeed*mv->m_flMaxSpeed ) )
+ {
+ float fRatio = mv->m_flMaxSpeed / sqrt( spd );
+ mv->m_flForwardMove *= fRatio;
+ mv->m_flSideMove *= fRatio;
+ mv->m_flUpMove *= fRatio;
+ }
+ }
+ else
+ {
+ spd = sqrt( spd );
+ if ( ( spd != 0.0 ) && ( spd > mv->m_flMaxSpeed ) )
+ {
+ float fRatio = mv->m_flMaxSpeed / spd;
+ mv->m_flForwardMove *= fRatio;
+ mv->m_flSideMove *= fRatio;
+ mv->m_flUpMove *= fRatio;
+ }
+ }
+ }
+
+
+ if ( player->GetFlags() & FL_FROZEN ||
+ player->GetFlags() & FL_ONTRAIN ||
+ IsDead() )
+ {
+ mv->m_flForwardMove = 0;
+ mv->m_flSideMove = 0;
+ mv->m_flUpMove = 0;
+ }
+
+ DecayPunchAngle();
+
+ // Take angles from command.
+ if ( !IsDead() )
+ {
+ v_angle = mv->m_vecAngles;
+ v_angle = v_angle + player->m_Local.m_vecPunchAngle;
+
+ // Now adjust roll angle
+ if ( player->GetMoveType() != MOVETYPE_ISOMETRIC &&
+ player->GetMoveType() != MOVETYPE_NOCLIP )
+ {
+ mv->m_vecAngles[ROLL] = CalcRoll( v_angle, mv->m_vecVelocity, sv_rollangle.GetFloat(), sv_rollspeed.GetFloat() );
+ }
+ else
+ {
+ mv->m_vecAngles[ROLL] = 0.0; // v_angle[ ROLL ];
+ }
+ mv->m_vecAngles[PITCH] = v_angle[PITCH];
+ mv->m_vecAngles[YAW] = v_angle[YAW];
+ }
+ else
+ {
+ mv->m_vecAngles = mv->m_vecOldAngles;
+ }
+
+ // Set dead player view_offset
+ if ( IsDead() )
+ {
+ SetViewOffset( VEC_DEAD_VIEWHEIGHT_SCALED( player ) );
+ }
+
+ // Adjust client view angles to match values used on server.
+ if ( mv->m_vecAngles[YAW] > 180.0f )
+ {
+ mv->m_vecAngles[YAW] -= 360.0f;
+ }
+
+ if ( cl_show_speed.GetBool() )
+ {
+ Vector vel = m_pDODPlayer->GetAbsVelocity();
+ float actual_speed = sqrt( vel.x * vel.x + vel.y * vel.y );
+ Msg( "player speed %.1f\n",actual_speed );
+ }
+}
+
+void CDODGameMovement::CheckFalling( void )
+{
+ // if we landed on the ground
+ if ( player->GetGroundEntity() != NULL && !IsDead() )
+ {
+ if ( player->m_Local.m_flFallVelocity >= 300 )
+ {
+ CPASFilter filter( player->GetAbsOrigin() );
+ filter.UsePredictionRules();
+ player->EmitSound( filter, player->entindex(), "Player.JumpLanding" );
+ }
+
+ // turn off the jumping flag if we're on ground after a jump
+ if ( m_pDODPlayer->m_Shared.IsJumping() )
+ {
+ m_pDODPlayer->m_Shared.SetJumping( false );
+
+ // if we landed from a jump, slow us
+ if ( player->m_Local.m_flFallVelocity > 50 )
+ m_pDODPlayer->m_Shared.SetSlowedTime( 0.5 );
+ }
+ }
+
+ BaseClass::CheckFalling();
+}
+
+
+void CDODGameMovement::ProcessMovement( CBasePlayer *pBasePlayer, CMoveData *pMove )
+{
+ //Store the player pointer
+ m_pDODPlayer = ToDODPlayer( pBasePlayer );
+ Assert( m_pDODPlayer );
+
+ m_pDODPlayer->m_Shared.ViewAnimThink();
+
+ BaseClass::ProcessMovement( pBasePlayer, pMove );
+}
+
+bool CDODGameMovement::CanAccelerate()
+{
+ // Only allow the player to accelerate when in certain states.
+ DODPlayerState curState = m_pDODPlayer->State_Get();
+ if ( curState == STATE_ACTIVE )
+ {
+ return player->GetWaterJumpTime() == 0;
+ }
+ else if ( player->IsObserver() )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void CDODGameMovement::PlayerMove()
+{
+ BaseClass::PlayerMove();
+
+ if ( player->GetMoveType() != MOVETYPE_ISOMETRIC &&
+ player->GetMoveType() != MOVETYPE_NOCLIP &&
+ player->GetMoveType() != MOVETYPE_OBSERVER )
+ {
+
+ // Cap actual player speed, fix wall running
+ float spd = mv->m_vecVelocity[0] * mv->m_vecVelocity[0] +
+ mv->m_vecVelocity[1] * mv->m_vecVelocity[1];
+
+ if( spd > 0.0 && spd > ( mv->m_flMaxSpeed * mv->m_flMaxSpeed ) )
+ {
+ float fRatio = mv->m_flMaxSpeed / sqrt( spd );
+ mv->m_vecVelocity[0] *= fRatio;
+ mv->m_vecVelocity[1] *= fRatio;
+ }
+ }
+}
+
+
+void CDODGameMovement::WalkMove( void )
+{
+ float flSpeed = m_pDODPlayer->GetAbsVelocity().Length2D();
+
+ bool bSprintButtonPressed = ( mv->m_nButtons & IN_SPEED ) > 0;
+
+ if( bSprintButtonPressed &&
+ ( mv->m_nButtons & IN_FORWARD ) &&
+ !m_pDODPlayer->m_Shared.IsProne() &&
+ !m_pDODPlayer->m_Shared.IsDucking() &&
+ flSpeed > 80 )
+ {
+ m_pDODPlayer->SetSprinting( true );
+ }
+ else
+ {
+ m_pDODPlayer->SetSprinting( false );
+ }
+
+ BaseClass::WalkMove();
+
+ //CheckForLadders( true );
+ //ResolveStanding();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Allow bots etc to use slightly different solid masks
+//-----------------------------------------------------------------------------
+unsigned int CDODGameMovement::PlayerSolidMask( bool brushOnly )
+{
+ int mask = 0;
+
+ switch ( m_pDODPlayer->GetTeamNumber() )
+ {
+ case TEAM_ALLIES:
+ mask = CONTENTS_TEAM1;
+ break;
+
+ case TEAM_AXIS:
+ mask = CONTENTS_TEAM2;
+ break;
+ }
+
+ return ( mask | BaseClass::PlayerSolidMask( brushOnly ) );
+}
+
+void CDODGameMovement::AirMove( void )
+{
+ BaseClass::AirMove();
+
+ //CheckForLadders( false );
+}
+
+void CDODGameMovement::CheckForLadders( bool wasOnGround )
+{
+ if ( !wasOnGround || !ResolveStanding() )
+ {
+ trace_t trace;
+ TracePlayerBBox( mv->GetAbsOrigin(), mv->GetAbsOrigin() + Vector( 0, 0, -5), MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
+ if ( trace.fraction == 1.0f )
+ {
+ Vector vel = -m_pDODPlayer->m_lastStandingPos + mv->GetAbsOrigin();
+ if ( !vel.x && !vel.y )
+ {
+ return;
+ }
+ vel.NormalizeInPlace();
+ vel *= 5.0f;
+ Vector vecStartPos( mv->GetAbsOrigin().x + vel.x, mv->GetAbsOrigin().y + vel.y, mv->GetAbsOrigin().z );
+ vel *= 5.0f;
+ Vector vecStandPos( mv->GetAbsOrigin().x - vel.x, mv->GetAbsOrigin().y - vel.y, mv->GetAbsOrigin().z - ( player->m_Local.m_flStepSize * 1.0f ) );
+
+ TracePlayerBBoxWithStep( vecStartPos, vecStandPos, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
+
+ if ( trace.fraction != 1.0f && OnLadder( trace ) && trace.plane.normal.z != 1.0f )
+ {
+ if ( trace.fraction > 0.6 )
+ {
+ vel.NormalizeInPlace();
+ Vector org = mv->GetAbsOrigin();
+ org -= vel*5;
+ mv->SetAbsOrigin( org );
+ }
+ player->SetMoveType( MOVETYPE_LADDER );
+ player->SetMoveCollide( MOVECOLLIDE_DEFAULT );
+
+ player->SetLadderNormal( trace.plane.normal );
+ mv->m_vecVelocity.Init();
+ }
+ }
+ }
+ else
+ {
+ m_pDODPlayer->m_lastStandingPos = mv->GetAbsOrigin();
+ }
+}
+
+inline void CDODGameMovement::TracePlayerBBoxWithStep( const Vector &vStart, const Vector &vEnd,
+ unsigned int fMask, int collisionGroup, trace_t &trace )
+{
+ VPROF( "CDODGameMovement::TracePlayerBBoxWithStep" );
+
+ Vector vHullMin = GetPlayerMins( player->m_Local.m_bDucked );
+ vHullMin.z += player->m_Local.m_flStepSize;
+ Vector vHullMax = GetPlayerMaxs( player->m_Local.m_bDucked );
+
+ Ray_t ray;
+ ray.Init( vStart, vEnd, vHullMin, vHullMax );
+ UTIL_TraceRay( ray, fMask, mv->m_nPlayerHandle.Get(), collisionGroup, &trace );
+}
+
+// Taken from TF2 to prevent bouncing down slopes
+bool CDODGameMovement::ResolveStanding( void )
+{
+ VPROF( "CDODGameMovement::ResolveStanding" );
+
+ //
+ // Attempt to move down twice your step height. Anything between 0.5 and 1.0
+ // is a valid "stand" value.
+ //
+
+ // Matt - don't move twice your step height, only check a little bit down
+ // this will keep us relatively glued to stairs without feeling too snappy
+ float flMaxStepDrop = 8.0f;
+
+ Vector vecStandPos( mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, mv->GetAbsOrigin().z - ( flMaxStepDrop ) );
+
+ trace_t trace;
+ TracePlayerBBoxWithStep( mv->GetAbsOrigin(), vecStandPos, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
+
+ // Anything between 0.5 and 1.0 is a valid stand value
+ if ( fabs( trace.fraction - 0.5 ) < 0.0004f )
+ {
+ return true;
+ }
+
+ if ( trace.fraction > 0.5f )
+ {
+ trace.fraction -= 0.5f;
+ Vector vecNewOrigin;
+ vecNewOrigin = mv->GetAbsOrigin() + trace.fraction * ( vecStandPos - mv->GetAbsOrigin() );
+ mv->SetAbsOrigin( vecNewOrigin );
+ return false;
+ }
+
+ // Less than 0.5 mean we need to attempt to push up the difference.
+ vecStandPos.z = ( mv->GetAbsOrigin().z + ( ( 0.5f - trace.fraction ) * ( player->m_Local.m_flStepSize * 2.0f ) ) );
+ TracePlayerBBoxWithStep( mv->GetAbsOrigin(), vecStandPos, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
+
+ // A fraction of 1.0 means we stood up fine - done.
+ if ( trace.fraction == 1.0f )
+ {
+ mv->SetAbsOrigin( trace.endpos );
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Recover stamina
+//-----------------------------------------------------------------------------
+void CDODGameMovement::ReduceTimers( void )
+{
+ Vector vecPlayerVelocity = m_pDODPlayer->GetAbsVelocity();
+ float flStamina = m_pDODPlayer->m_Shared.GetStamina();
+ float fl2DVelocitySquared = vecPlayerVelocity.x * vecPlayerVelocity.x +
+ vecPlayerVelocity.y * vecPlayerVelocity.y;
+
+ if ( !( mv->m_nButtons & IN_SPEED ) )
+ {
+ m_pDODPlayer->m_Shared.ResetSprintPenalty();
+ }
+
+ // Can only sprint in forward direction.
+ bool bSprinting = ( (mv->m_nButtons & IN_SPEED) && ( mv->m_nButtons & IN_FORWARD ) );
+
+ // If we're holding the sprint key and also actually moving, remove some stamina
+ Vector vel = m_pDODPlayer->GetAbsVelocity();
+ if ( bSprinting && fl2DVelocitySquared > 10000 ) //speed > 100
+ {
+ //flStamina -= 30 * gpGlobals->frametime; //reduction for sprinting
+ //flStamina += 10 * gpGlobals->frametime; //addition for recovering
+
+ flStamina -= 20 * gpGlobals->frametime;
+
+ m_pDODPlayer->m_Shared.SetStamina( flStamina );
+ }
+ else
+ {
+ //gain some back
+ if ( fl2DVelocitySquared <= 0 )
+ {
+ flStamina += 60 * gpGlobals->frametime;
+ }
+ else if ( ( m_pDODPlayer->GetFlags() & FL_ONGROUND ) &&
+ ( mv->m_nButtons & IN_DUCK ) &&
+ ( m_pDODPlayer->GetFlags() & FL_DUCKING ) )
+ {
+ flStamina += 50 * gpGlobals->frametime;
+ }
+ else
+ {
+ flStamina += 10 * gpGlobals->frametime;
+ }
+
+ m_pDODPlayer->m_Shared.SetStamina( flStamina );
+ }
+
+#ifdef CLIENT_DLL
+ if ( bSprinting && flStamina < 25 )
+ {
+ m_pDODPlayer->HintMessage( HINT_LOW_STAMINA );
+ }
+#endif
+
+ BaseClass::ReduceTimers();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CDODGameMovement::CheckJumpButton( void )
+{
+ if (m_pDODPlayer->pl.deadflag)
+ {
+ mv->m_nOldButtons |= IN_JUMP ; // don't jump again until released
+ return false;
+ }
+
+ if( m_pDODPlayer->m_Shared.IsProne() ||
+ m_pDODPlayer->m_Shared.IsGettingUpFromProne() ||
+ m_pDODPlayer->m_Shared.IsGoingProne() )
+ {
+ mv->m_nOldButtons |= IN_JUMP;
+ return false;
+ }
+
+ // See if we are waterjumping. If so, decrement count and return.
+ float flWaterJumpTime = player->GetWaterJumpTime();
+
+ if ( flWaterJumpTime > 0 )
+ {
+ flWaterJumpTime -= gpGlobals->frametime;
+ if (flWaterJumpTime < 0)
+ flWaterJumpTime = 0;
+
+ player->SetWaterJumpTime( flWaterJumpTime );
+
+ return false;
+ }
+
+ // If we are in the water most of the way...
+ if ( m_pDODPlayer->GetWaterLevel() >= 2 )
+ {
+ // swimming, not jumping
+ SetGroundEntity( NULL );
+
+ if(m_pDODPlayer->GetWaterType() == CONTENTS_WATER) // We move up a certain amount
+ mv->m_vecVelocity[2] = 100;
+ else if (m_pDODPlayer->GetWaterType() == CONTENTS_SLIME)
+ mv->m_vecVelocity[2] = 80;
+
+ // play swiming sound
+ if ( player->GetSwimSoundTime() <= 0 )
+ {
+ // Don't play sound again for 1 second
+ player->SetSwimSoundTime( 1000 );
+ PlaySwimSound();
+ }
+
+ return false;
+ }
+
+ // No more effect
+ if (m_pDODPlayer->GetGroundEntity() == NULL)
+ {
+ mv->m_nOldButtons |= IN_JUMP;
+ return false; // in air, so no effect
+ }
+
+ if ( mv->m_nOldButtons & IN_JUMP )
+ return false; // don't pogo stick
+
+ if( m_pDODPlayer->m_Shared.IsInMGDeploy() )
+ {
+ return false;
+ }
+
+ // In the air now.
+ SetGroundEntity( NULL );
+
+ m_pDODPlayer->PlayStepSound( (Vector &)mv->GetAbsOrigin(), player->GetSurfaceData(), 1.0, true );
+
+ m_pDODPlayer->DoAnimationEvent( PLAYERANIMEVENT_JUMP );
+
+ // make the jump sound
+ CPASFilter filter( m_pDODPlayer->GetAbsOrigin() );
+ filter.UsePredictionRules();
+ m_pDODPlayer->EmitSound( filter, m_pDODPlayer->entindex(), "Player.Jump" );
+
+ float flGroundFactor = 1.0f;
+ if ( player->GetSurfaceData() )
+ {
+ flGroundFactor = player->GetSurfaceData()->game.jumpFactor;
+ }
+
+ /*
+ // old and busted
+
+ float flStamina = m_pDODPlayer->m_Shared.GetStamina();
+
+ //15.0 is the base height. the player will always jump this high
+ //regardless of stamina. Also the player will be able to jump max height
+ //until he is below 60 stamina. Then the height will decrease proportionately
+
+ float flJumpSpeed = 15.0; //base jump height
+
+ if( flStamina >= 60.0f )
+ {
+ flJumpSpeed += 30.0;
+ }
+ else
+ {
+ flJumpSpeed += (30.0 * ( flStamina / 60.0f ) );
+ }
+
+ //Remove stamina for a successful jump
+ m_pDODPlayer->m_Shared.SetStamina( flStamina - 40 );
+
+ */
+
+ // new hotness - constant jumpspeed of 45
+ //m_pDODPlayer->m_Shared.SetSlowedTime( 1.0f );
+
+ Assert( GetCurrentGravity() == 800.0f );
+
+ // Accelerate upward
+ // If we are ducking...
+ float startz = mv->m_vecVelocity[2];
+ if ( ( m_pDODPlayer->m_Local.m_bDucking ) || ( m_pDODPlayer->GetFlags() & FL_DUCKING ) )
+ {
+ // d = 0.5 * g * t^2 - distance traveled with linear accel
+ // t = sqrt(2.0 * 45 / g) - how long to fall 45 units
+ // v = g * t - velocity at the end (just invert it to jump up that high)
+ // v = g * sqrt(2.0 * 45 / g )
+ // v^2 = g * g * 2.0 * 45 / g
+ // v = sqrt( g * 2.0 * 45 )
+
+ mv->m_vecVelocity[2] = flGroundFactor * 268.3281572999747f; // flJumpSpeed of 45
+ //mv->m_vecVelocity[2] = flGroundFactor * sqrt(2 * 800 * flJumpSpeed); // 2 * gravity * height
+ }
+ else
+ {
+ mv->m_vecVelocity[2] += flGroundFactor * 268.3281572999747f; // flJumpSpeed of 45
+ //mv->m_vecVelocity[2] += flGroundFactor * sqrt(2 * 800 * flJumpSpeed); // 2 * gravity * height
+ }
+
+ FinishGravity();
+
+ mv->m_outWishVel.z += mv->m_vecVelocity[2] - startz;
+ mv->m_outStepHeight += 0.1f;
+
+ // Flag that we jumped.
+ mv->m_nOldButtons |= IN_JUMP; // don't jump again until released
+
+ m_pDODPlayer->m_Shared.SetJumping( true );
+
+ return true;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Limit speed if we are ducking
+//-----------------------------------------------------------------------------
+void CDODGameMovement::HandleDuckingSpeedCrop()
+{
+ if ( !( m_iSpeedCropped & SPEED_CROPPED_DUCK ) )
+ {
+ if ( ( mv->m_nButtons & IN_DUCK ) || ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) )
+ {
+ float frac = 0.33333333f;
+ mv->m_flForwardMove *= frac;
+ mv->m_flSideMove *= frac;
+ mv->m_flUpMove *= frac;
+ m_iSpeedCropped |= SPEED_CROPPED_DUCK;
+ }
+ }
+}
+
+bool CDODGameMovement::CanUnprone()
+{
+ int i;
+ trace_t trace;
+ Vector newOrigin;
+
+ VectorCopy( mv->GetAbsOrigin(), newOrigin );
+
+ Vector vecMins, vecMaxs;
+
+ if ( mv->m_nButtons & IN_DUCK )
+ {
+ vecMins = VEC_DUCK_HULL_MIN_SCALED( player );
+ vecMaxs = VEC_DUCK_HULL_MAX_SCALED( player );
+ }
+ else
+ {
+ vecMins = VEC_HULL_MIN_SCALED( player );
+ vecMaxs = VEC_HULL_MAX_SCALED( player );
+ }
+
+ if ( player->GetGroundEntity() != NULL )
+ {
+ for ( i = 0; i < 3; i++ )
+ {
+ newOrigin[i] += ( VEC_PRONE_HULL_MIN_SCALED( player )[i] - vecMins[i] );
+ }
+ }
+ else
+ {
+ // If in air an letting go of crouch, make sure we can offset origin to make
+ // up for uncrouching
+
+ Vector hullSizeNormal = vecMaxs - vecMins;
+ Vector hullSizeProne = VEC_PRONE_HULL_MAX_SCALED( player ) - VEC_PRONE_HULL_MIN_SCALED( player );
+
+ Vector viewDelta = -0.5f * ( hullSizeNormal - hullSizeProne );
+
+ VectorAdd( newOrigin, viewDelta, newOrigin );
+ }
+
+ bool saveprone = m_pDODPlayer->m_Shared.IsProne();
+ bool saveducked = player->m_Local.m_bDucked;
+
+ // pretend we're not prone
+ m_pDODPlayer->m_Shared.SetProne( false );
+ if ( mv->m_nButtons & IN_DUCK )
+ player->m_Local.m_bDucked = true;
+
+ TracePlayerBBox( mv->GetAbsOrigin(), newOrigin, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, trace );
+
+ // revert to reality
+ m_pDODPlayer->m_Shared.SetProne( saveprone );
+ player->m_Local.m_bDucked = saveducked;
+
+ if ( trace.startsolid || ( trace.fraction != 1.0f ) )
+ return false;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Stop ducking
+//-----------------------------------------------------------------------------
+void CDODGameMovement::FinishUnDuck( void )
+{
+ int i;
+ trace_t trace;
+ Vector newOrigin;
+
+ VectorCopy( mv->GetAbsOrigin(), newOrigin );
+
+ if ( player->GetGroundEntity() != NULL )
+ {
+ for ( i = 0; i < 3; i++ )
+ {
+ newOrigin[i] += ( VEC_DUCK_HULL_MIN_SCALED( player )[i] - VEC_HULL_MIN_SCALED( player )[i] );
+ }
+ }
+ else
+ {
+ // If in air an letting go of crouch, make sure we can offset origin to make
+ // up for uncrouching
+ // orange box patch - made this match the check in CanUnduck()
+ Vector hullSizeNormal = VEC_HULL_MAX_SCALED( player ) - VEC_HULL_MIN_SCALED( player );
+ Vector hullSizeCrouch = VEC_DUCK_HULL_MAX_SCALED( player ) - VEC_DUCK_HULL_MIN_SCALED( player );
+ Vector viewDelta = ( hullSizeNormal - hullSizeCrouch );
+ viewDelta.Negate();
+ VectorAdd( newOrigin, viewDelta, newOrigin );
+ }
+
+ player->m_Local.m_bDucked = false;
+ player->RemoveFlag( FL_DUCKING );
+ player->m_Local.m_bDucking = false;
+ SetViewOffset( GetPlayerViewOffset( false ) );
+ player->m_Local.m_flDucktime = 0;
+
+ mv->SetAbsOrigin( newOrigin );
+
+ // Recategorize position since ducking can change origin
+ CategorizePosition();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Finish ducking
+//-----------------------------------------------------------------------------
+void CDODGameMovement::FinishDuck( void )
+{
+ Vector hullSizeNormal = VEC_HULL_MAX_SCALED( player ) - VEC_HULL_MIN_SCALED( player );
+ Vector hullSizeCrouch = VEC_DUCK_HULL_MAX_SCALED( player ) - VEC_DUCK_HULL_MIN_SCALED( player );
+
+ Vector viewDelta = 0.5f * ( hullSizeNormal - hullSizeCrouch );
+
+ SetViewOffset( GetPlayerViewOffset( true ) );
+ player->AddFlag( FL_DUCKING );
+ player->m_Local.m_bDucking = false;
+
+ if ( !player->m_Local.m_bDucked )
+ {
+ Vector org = mv->GetAbsOrigin();
+
+ if ( player->GetGroundEntity() != NULL )
+ {
+ org -= VEC_DUCK_HULL_MIN_SCALED( player ) - VEC_HULL_MIN_SCALED( player );
+ }
+ else
+ {
+ VectorAdd( org, viewDelta, org );
+ }
+ mv->SetAbsOrigin( org );
+
+ player->m_Local.m_bDucked = true;
+ }
+
+ // See if we are stuck?
+ FixPlayerCrouchStuck( true );
+
+ // Recategorize position since ducking can change origin
+ CategorizePosition();
+}
+
+// Being deployed or undeploying totally stomps the duck view offset
+void CDODGameMovement::SetDeployedEyeOffset( void )
+{
+ if ( m_pDODPlayer->m_Shared.IsProne() || m_pDODPlayer->m_Shared.IsGettingUpFromProne() )
+ return;
+
+ if ( !m_pDODPlayer->IsAlive() )
+ return;
+
+ float flTimeSinceDeployChange = gpGlobals->curtime - m_pDODPlayer->m_Shared.m_flDeployChangeTime;
+
+ if ( m_pDODPlayer->m_Shared.IsInMGDeploy() || flTimeSinceDeployChange < TIME_TO_DEPLOY )
+ {
+ if ( m_pDODPlayer->m_Shared.IsInMGDeploy() )
+ {
+ // anim to deployed
+ if ( m_pDODPlayer->m_Shared.GetLastViewAnimTime() < m_pDODPlayer->m_Shared.m_flDeployChangeTime.m_Value )
+ {
+ // Deployed height
+ float flViewOffset = clamp( m_pDODPlayer->m_Shared.GetDeployedHeight(),
+ CROUCHING_DEPLOY_HEIGHT,
+ STANDING_DEPLOY_HEIGHT );
+
+ Vector vecView = player->GetViewOffset();
+ vecView.z = flViewOffset;
+
+ ViewOffsetAnimation( vecView, TIME_TO_DEPLOY, VIEW_ANIM_LINEAR_Z_ONLY );
+ m_pDODPlayer->m_Shared.SetLastViewAnimTime( gpGlobals->curtime );
+ }
+ }
+ else
+ {
+ // anim to undeployed
+ if ( m_pDODPlayer->m_Shared.GetLastViewAnimTime() < m_pDODPlayer->m_Shared.m_flDeployChangeTime.m_Value )
+ {
+ ViewOffsetAnimation( GetPlayerViewOffset( player->m_Local.m_bDucked ), TIME_TO_DEPLOY, VIEW_ANIM_LINEAR_Z_ONLY );
+ m_pDODPlayer->m_Shared.SetLastViewAnimTime( gpGlobals->curtime );
+ }
+ }
+
+ if ( flTimeSinceDeployChange >= TIME_TO_DEPLOY )
+ {
+ player->m_Local.m_bDucked = false;
+ player->RemoveFlag( FL_DUCKING );
+ player->m_Local.m_bDucking = false;
+ player->m_Local.m_flDucktime = 0;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : duckFraction -
+//-----------------------------------------------------------------------------
+void CDODGameMovement::SetDODDuckedEyeOffset( float duckFraction )
+{
+ // Different from CGameMovement in that
+ Vector vDuckHullMin = GetPlayerMins( true );
+ Vector vStandHullMin = GetPlayerMins( false );
+
+ float fMore = ( vDuckHullMin.z - vStandHullMin.z );
+
+ Vector vecStandViewOffset = GetPlayerViewOffset( false );
+
+ Vector vecDuckViewOffset = GetPlayerViewOffset( true );
+ Vector temp = player->GetViewOffset();
+ temp.z = ( ( vecDuckViewOffset.z - fMore ) * duckFraction ) +
+ ( vecStandViewOffset.z * ( 1 - duckFraction ) );
+ SetViewOffset( temp );
+}
+
+void CDODGameMovement::SetProneEyeOffset( float proneFraction )
+{
+ Vector vecPropViewOffset = VEC_PRONE_VIEW;
+ Vector vecStandViewOffset = GetPlayerViewOffset( player->m_Local.m_bDucked );
+
+ Vector temp = player->GetViewOffset();
+ temp.z = SimpleSplineRemapVal( proneFraction, 1.0, 0.0, vecPropViewOffset.z, vecStandViewOffset.z );
+
+ SetViewOffset( temp );
+}
+
+void CDODGameMovement::FinishUnProne( void )
+{
+ m_pDODPlayer->m_Shared.m_flUnProneTime = 0.0f;
+
+ SetProneEyeOffset( 0.0 );
+
+ Vector vHullMin = GetPlayerMins( player->m_Local.m_bDucked );
+ Vector vHullMax = GetPlayerMaxs( player->m_Local.m_bDucked );
+
+ if ( m_bUnProneToDuck )
+ {
+ FinishDuck();
+ }
+ else
+ {
+ CategorizePosition();
+
+ if ( mv->m_nButtons & IN_DUCK && !( player->GetFlags() & FL_DUCKING ) )
+ {
+ // Use 1 second so super long jump will work
+ player->m_Local.m_flDucktime = 1000;
+ player->m_Local.m_bDucking = true;
+ }
+ }
+}
+
+void CDODGameMovement::FinishProne( void )
+{
+ m_pDODPlayer->m_Shared.SetProne( true );
+ m_pDODPlayer->m_Shared.m_flGoProneTime = 0.0f;
+
+#ifndef CLIENT_DLL
+ m_pDODPlayer->HintMessage( HINT_PRONE );
+#endif
+
+ FinishUnDuck(); // clear ducking
+
+ SetProneEyeOffset( 1.0 );
+
+ FixPlayerCrouchStuck(true);
+
+ CategorizePosition();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: See if duck button is pressed and do the appropriate things
+//-----------------------------------------------------------------------------
+void CDODGameMovement::Duck( void )
+{
+ int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame
+ int buttonsPressed = buttonsChanged & mv->m_nButtons; // The changed ones still down are "pressed"
+ int buttonsReleased = buttonsChanged & mv->m_nOldButtons; // The changed ones which were previously down are "released"
+
+ if ( mv->m_nButtons & IN_DUCK )
+ {
+ mv->m_nOldButtons |= IN_DUCK;
+ }
+ else
+ {
+ mv->m_nOldButtons &= ~IN_DUCK;
+ }
+
+ if ( !player->IsAlive() )
+ {
+ if( m_pDODPlayer->m_Shared.IsProne() )
+ {
+ FinishUnProne();
+ }
+
+ // Unduck
+ if ( player->m_Local.m_bDucking || player->m_Local.m_bDucked )
+ {
+ FinishUnDuck();
+ }
+ return;
+ }
+
+ static int iState = 0;
+
+ // Prone / UnProne - we don't duck or deploy if this is happening
+ if( m_pDODPlayer->m_Shared.m_flUnProneTime > 0.0f )
+ {
+ float pronetime = m_pDODPlayer->m_Shared.m_flUnProneTime - gpGlobals->curtime;
+
+ if( pronetime < 0 )
+ {
+ FinishUnProne();
+
+ if ( !m_bUnProneToDuck && ( mv->m_nButtons & IN_DUCK ) )
+ {
+ buttonsPressed |= IN_DUCK;
+ mv->m_nOldButtons &= ~IN_DUCK;
+ }
+ }
+
+ // Set these, so that as soon as we stop unproning, we don't pop to standing
+ // the information that we let go of the duck key has been lost by now.
+ if ( m_bUnProneToDuck )
+ {
+ player->m_Local.m_flDucktime = 1000;
+ player->m_Local.m_bDucking = true;
+ }
+
+ //don't deal with ducking while we're proning
+ return;
+ }
+ else if( m_pDODPlayer->m_Shared.m_flGoProneTime > 0.0f )
+ {
+ float pronetime = m_pDODPlayer->m_Shared.m_flGoProneTime - gpGlobals->curtime;
+
+ if( pronetime < 0 )
+ {
+ FinishProne();
+ }
+
+ //don't deal with ducking while we're proning
+ return;
+ }
+
+ if ( gpGlobals->curtime > m_pDODPlayer->m_Shared.m_flNextProneCheck )
+ {
+ if ( buttonsPressed & IN_ALT1 && m_pDODPlayer->m_Shared.CanChangePosition() )
+ {
+ if( m_pDODPlayer->m_Shared.IsProne() == false &&
+ m_pDODPlayer->m_Shared.IsGettingUpFromProne() == false )
+ {
+ m_pDODPlayer->m_Shared.StartGoingProne();
+
+ // do unprone anim
+ ViewOffsetAnimation( VEC_PRONE_VIEW, TIME_TO_PRONE, VIEW_ANIM_EXPONENTIAL_Z_ONLY );
+ }
+ else if( CanUnprone() )
+ {
+ m_pDODPlayer->m_Shared.SetProne( false );
+ m_pDODPlayer->m_Shared.StandUpFromProne();
+
+ // do unprone anim
+ ViewOffsetAnimation( GetPlayerViewOffset( m_bUnProneToDuck ),
+ TIME_TO_PRONE,
+ VIEW_ANIM_EXPONENTIAL_Z_ONLY );
+
+ m_bUnProneToDuck = ( mv->m_nButtons & IN_DUCK ) > 0;
+ }
+
+ m_pDODPlayer->m_Shared.m_flNextProneCheck = gpGlobals->curtime + 1.0f;
+ return;
+ }
+ }
+
+ SetDeployedEyeOffset();
+
+ if ( m_pDODPlayer->m_Shared.IsProne() &&
+ m_pDODPlayer->m_Shared.CanChangePosition() &&
+ !m_pDODPlayer->m_Shared.IsGettingUpFromProne() &&
+ ( buttonsPressed & IN_DUCK ) &&
+ CanUnprone() ) // BUGBUG - even calling this will unzoom snipers.
+ {
+ // If the player presses duck while prone,
+ // unprone them to the duck position
+ m_pDODPlayer->m_Shared.SetProne( false );
+ m_pDODPlayer->m_Shared.StandUpFromProne();
+
+ m_bUnProneToDuck = true;
+
+ // do unprone anim
+ ViewOffsetAnimation( GetPlayerViewOffset( m_bUnProneToDuck ),
+ TIME_TO_PRONE,
+ VIEW_ANIM_EXPONENTIAL_Z_ONLY );
+
+ // simulate a duck that was pressed while we were prone
+ player->AddFlag( FL_DUCKING );
+ player->m_Local.m_bDucked = true;
+ player->m_Local.m_flDucktime = 1000;
+ player->m_Local.m_bDucking = true;
+ }
+
+ // no ducking or unducking while deployed or prone
+ if( m_pDODPlayer->m_Shared.IsProne() ||
+ m_pDODPlayer->m_Shared.IsGettingUpFromProne() ||
+ !m_pDODPlayer->m_Shared.CanChangePosition() )
+ {
+ return;
+ }
+
+ HandleDuckingSpeedCrop();
+
+ if ( !( player->GetFlags() & FL_DUCKING ) && ( player->m_Local.m_bDucked ) )
+ {
+ player->m_Local.m_bDucked = false;
+ }
+
+ /*
+ Msg( "duck button %s ducking %s ducked %s duck flags %s\n",
+ ( mv->m_nButtons & IN_DUCK ) ? "down" : "up",
+ ( player->m_Local.m_bDucking ) ? "yes" : "no",
+ ( player->m_Local.m_bDucked ) ? "yes" : "no",
+ ( player->GetFlags() & FL_DUCKING ) ? "set" : "not set" );*/
+
+ // Holding duck, in process of ducking or fully ducked?
+ if ( ( mv->m_nButtons & IN_DUCK ) || ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) )
+ {
+ if ( mv->m_nButtons & IN_DUCK )
+ {
+ bool alreadyDucked = ( player->GetFlags() & FL_DUCKING ) ? true : false;
+
+ if ( (buttonsPressed & IN_DUCK ) && !( player->GetFlags() & FL_DUCKING ) )
+ {
+ // Use 1 second so super long jump will work
+ player->m_Local.m_flDucktime = 1000;
+ player->m_Local.m_bDucking = true;
+ }
+
+ float duckmilliseconds = MAX( 0.0f, 1000.0f - (float)player->m_Local.m_flDucktime );
+ float duckseconds = duckmilliseconds / 1000.0f;
+
+ //time = MAX( 0.0, ( 1.0 - (float)player->m_Local.m_flDucktime / 1000.0 ) );
+
+ if ( player->m_Local.m_bDucking )
+ {
+ // Finish ducking immediately if duck time is over or not on ground
+ if ( ( duckseconds > TIME_TO_DUCK ) ||
+ ( player->GetGroundEntity() == NULL ) ||
+ alreadyDucked)
+ {
+ FinishDuck();
+ }
+ else
+ {
+ // Calc parametric time
+ float flDuckFraction = SimpleSpline( duckseconds / TIME_TO_DUCK );
+ SetDODDuckedEyeOffset( flDuckFraction );
+ }
+ }
+ }
+ else
+ {
+ // Try to unduck unless automovement is not allowed
+ // NOTE: When not onground, you can always unduck
+ if ( player->m_Local.m_bAllowAutoMovement || player->GetGroundEntity() == NULL )
+ {
+ if ( (buttonsReleased & IN_DUCK ) && ( player->GetFlags() & FL_DUCKING ) )
+ {
+ // Use 1 second so super long jump will work
+ player->m_Local.m_flDucktime = 1000;
+ player->m_Local.m_bDucking = true; // or unducking
+ }
+
+ float duckmilliseconds = MAX( 0.0f, 1000.0f - (float)player->m_Local.m_flDucktime );
+ float duckseconds = duckmilliseconds / 1000.0f;
+
+ if ( CanUnduck() )
+ {
+ if ( player->m_Local.m_bDucking ||
+ player->m_Local.m_bDucked ) // or unducking
+ {
+ // Finish ducking immediately if duck time is over or not on ground
+ if ( ( duckseconds > TIME_TO_UNDUCK ) ||
+ ( player->GetGroundEntity() == NULL ) )
+ {
+ FinishUnDuck();
+ }
+ else
+ {
+ // Calc parametric time
+ float duckFraction = SimpleSpline( 1.0f - ( duckseconds / TIME_TO_UNDUCK ) );
+ SetDODDuckedEyeOffset( duckFraction );
+ }
+ }
+ }
+ else
+ {
+ // Still under something where we can't unduck, so make sure we reset this timer so
+ // that we'll unduck once we exit the tunnel, etc.
+ player->m_Local.m_flDucktime = 1000;
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output : const Vector
+//-----------------------------------------------------------------------------
+Vector CDODGameMovement::GetPlayerMins( void ) const
+{
+ if ( !player )
+ {
+ return vec3_origin;
+ }
+
+ if ( player->IsObserver() )
+ {
+ return VEC_OBS_HULL_MIN_SCALED( player );
+ }
+ else
+ {
+ if ( player->m_Local.m_bDucked )
+ return VEC_DUCK_HULL_MIN_SCALED( player );
+ else if ( m_pDODPlayer->m_Shared.IsProne() )
+ return VEC_PRONE_HULL_MIN_SCALED( player );
+ else
+ return VEC_HULL_MIN_SCALED( player );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output : const Vector
+//-----------------------------------------------------------------------------
+Vector CDODGameMovement::GetPlayerMaxs( void ) const
+{
+ if ( !player )
+ {
+ return vec3_origin;
+ }
+ if ( player->IsObserver() )
+ {
+ return VEC_OBS_HULL_MAX_SCALED( player );
+ }
+ else
+ {
+ if ( player->m_Local.m_bDucked )
+ return VEC_DUCK_HULL_MAX_SCALED( player );
+ else if ( m_pDODPlayer->m_Shared.IsProne() )
+ return VEC_PRONE_HULL_MAX_SCALED( player );
+ else
+ return VEC_HULL_MAX_SCALED( player );
+ }
+}
+
+void CDODGameMovement::SetViewOffset( Vector vecViewOffset )
+{
+ // call this instead of player->SetViewOffset directly, so we can cancel any
+ // animation in progress
+
+ m_pDODPlayer->m_Shared.ResetViewOffsetAnimation();
+
+ player->SetViewOffset( vecViewOffset );
+}
+
+void CDODGameMovement::ViewOffsetAnimation( Vector vecDest, float flTime, ViewAnimationType type )
+{
+ m_pDODPlayer->m_Shared.ViewOffsetAnimation( vecDest, flTime, type );
+} \ No newline at end of file