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.
1405 lines
38 KiB
1405 lines
38 KiB
//========= 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 );
|
|
}
|