diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/dod/dod_gamemovement.cpp | |
| download | archived-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.cpp | 1405 |
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 |