From e754d217939824b0d3d7635cc02cb6f53fa6fe49 Mon Sep 17 00:00:00 2001 From: Alan Shen Date: Wed, 14 Oct 2026 22:50:35 -0600 Subject: [PATCH 1/2] Use horizontal speed for the player moving test The legs and feet decided "moving" on 3D speed, so a player rising or falling (a jump, a drop off a ledge, a lift) played the walk animation in the air. Classic NEOTOKYO and the 2006 SDK use horizontal speed. Ladders keep the 3D test, so climbing keeps the walk animation it has today. --- .../shared/hl2mp/hl2mp_playeranimstate.cpp | 32 +++++++++++++++---- src/game/shared/hl2mp/hl2mp_playeranimstate.h | 1 + 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp b/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp index 9e441acd87..b85647f58a 100644 --- a/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp +++ b/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp @@ -417,14 +417,9 @@ bool CHL2MPPlayerAnimState::HandleMoving( Activity &idealActivity ) { idealActivity = ACT_RUN; } - else + else if (GetMovingSpeed() > 0.5) { - Vector vecVelocity; - GetOuterAbsVelocity(vecVelocity); - if (vecVelocity.Length() > 0.5) - { - idealActivity = ACT_WALK; - } + idealActivity = ACT_WALK; } return true; @@ -433,6 +428,24 @@ bool CHL2MPPlayerAnimState::HandleMoving( Activity &idealActivity ) #endif } +#ifdef NEO +//----------------------------------------------------------------------------- +// Purpose: The speed that counts as moving for the legs and feet: rising or falling is not walking, +// as in classic NEOTOKYO, but climbing a ladder keeps the walk animation it has always had. +//----------------------------------------------------------------------------- +float CHL2MPPlayerAnimState::GetMovingSpeed() +{ + if ( m_pHL2MPPlayer->GetMoveType() == MOVETYPE_LADDER ) + { + Vector vecVelocity; + GetOuterAbsVelocity( vecVelocity ); + return vecVelocity.Length(); + } + + return GetOuterXYSpeed(); +} +#endif // NEO + //----------------------------------------------------------------------------- // Purpose: // Input : *idealActivity - @@ -745,12 +758,17 @@ void CHL2MPPlayerAnimState::ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr ) //----------------------------------------------------------------------------- void CHL2MPPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ) { +#ifdef NEO + // Check to see if we are moving. + bool bMoving = GetMovingSpeed() > 1.0f; +#else // Get the movement velocity. Vector vecVelocity; GetOuterAbsVelocity( vecVelocity ); // Check to see if we are moving. bool bMoving = ( vecVelocity.Length() > 1.0f ) ? true : false; +#endif #ifdef NEO // If we are moving or leaning or are prone and undeployed. diff --git a/src/game/shared/hl2mp/hl2mp_playeranimstate.h b/src/game/shared/hl2mp/hl2mp_playeranimstate.h index 9a05125539..43b2174c50 100644 --- a/src/game/shared/hl2mp/hl2mp_playeranimstate.h +++ b/src/game/shared/hl2mp/hl2mp_playeranimstate.h @@ -64,6 +64,7 @@ class CHL2MPPlayerAnimState : public CMultiPlayerAnimState #ifdef NEO bool IsLeaning(CStudioHdr *pStudioHdr); + float GetMovingSpeed(); #endif // NEO CHL2MP_Player *m_pHL2MPPlayer; From e93610330bb1f57f63581b793e7c499c0e56dc44 Mon Sep 17 00:00:00 2001 From: Alan Shen Date: Wed, 14 Oct 2026 22:51:43 -0600 Subject: [PATCH 2/2] End a drawn player's jump when the body lands The jump pose ended when the client saw the ground flag, 0.2 s or more after take-off. The flag is networked as received, but other players are drawn at an interpolated position that trails it by a few tenths of a second, so the pose ended near the top of the jump and the body came down in the walk pose. On the client, the jump now lasts until a short hull trace finds ground under the drawn body, or until the flag has been set for 0.5 s. The server and the flag test are unchanged. --- .../shared/hl2mp/hl2mp_playeranimstate.cpp | 56 +++++++++++++++++++ src/game/shared/hl2mp/hl2mp_playeranimstate.h | 4 ++ 2 files changed, 60 insertions(+) diff --git a/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp b/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp index b85647f58a..a89f6d9612 100644 --- a/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp +++ b/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp @@ -112,6 +112,9 @@ CHL2MPPlayerAnimState::~CHL2MPPlayerAnimState() void CHL2MPPlayerAnimState::InitHL2MPAnimState( CHL2MP_Player *pPlayer ) { m_pHL2MPPlayer = pPlayer; +#if defined( NEO ) && defined( CLIENT_DLL ) + m_flJumpGroundFlagTime = 0.0f; +#endif } //----------------------------------------------------------------------------- @@ -493,6 +496,9 @@ bool CHL2MPPlayerAnimState::HandleJumping( Activity &idealActivity ) { m_bFirstJumpFrame = false; RestartMainSequence(); // Reset the animation. +#if defined( NEO ) && defined( CLIENT_DLL ) + m_flJumpGroundFlagTime = 0.0f; +#endif } // Reset if we hit water and start swimming. @@ -505,7 +511,11 @@ bool CHL2MPPlayerAnimState::HandleJumping( Activity &idealActivity ) // on-ground flag set right when the message comes in. else if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f ) { +#ifdef NEO + if ( HasLandedFromJump() ) +#else if ( m_pHL2MPPlayer->GetFlags() & FL_ONGROUND ) +#endif { m_bJumping = false; RestartMainSequence(); @@ -552,6 +562,52 @@ bool CHL2MPPlayerAnimState::HandleJumping( Activity &idealActivity ) return false; } +#ifdef NEO +#ifdef CLIENT_DLL +// A jump has landed when the drawn body is this close above the ground (the ground check of player movement), +static constexpr float JUMP_LAND_GROUND_DIST = 2.0f; +// or when the ground flag has been set this long and the trace still finds no ground under the drawn body +static constexpr float JUMP_LAND_MAX_FLAG_LEAD = 0.5f; +#endif + +//----------------------------------------------------------------------------- +// Purpose: Whether a jumping player has landed. The client draws other players a few tenths of a second behind +// their networked ground flag, so there the jump lasts until the drawn body reaches the ground. +//----------------------------------------------------------------------------- +bool CHL2MPPlayerAnimState::HasLandedFromJump() +{ + if ( !( m_pHL2MPPlayer->GetFlags() & FL_ONGROUND ) ) + { +#ifdef CLIENT_DLL + m_flJumpGroundFlagTime = 0.0f; +#endif + return false; + } + +#ifdef CLIENT_DLL + if ( m_flJumpGroundFlagTime <= 0.0f ) + { + m_flJumpGroundFlagTime = gpGlobals->curtime; + } + + if ( gpGlobals->curtime - m_flJumpGroundFlagTime > JUMP_LAND_MAX_FLAG_LEAD ) + { + return true; + } + + const Vector &vecOrigin = m_pHL2MPPlayer->GetAbsOrigin(); + trace_t tr; + UTIL_TraceHull( vecOrigin, vecOrigin - Vector( 0, 0, JUMP_LAND_GROUND_DIST ), + m_pHL2MPPlayer->GetPlayerMins(), m_pHL2MPPlayer->GetPlayerMaxs(), + MASK_PLAYERSOLID, m_pHL2MPPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); + + return tr.fraction < 1.0f || tr.startsolid; +#else + return true; +#endif // CLIENT_DLL +} +#endif // NEO + bool CHL2MPPlayerAnimState::SetupPoseParameters( CStudioHdr *pStudioHdr ) { #ifdef NEO diff --git a/src/game/shared/hl2mp/hl2mp_playeranimstate.h b/src/game/shared/hl2mp/hl2mp_playeranimstate.h index 43b2174c50..4abf7842a6 100644 --- a/src/game/shared/hl2mp/hl2mp_playeranimstate.h +++ b/src/game/shared/hl2mp/hl2mp_playeranimstate.h @@ -65,9 +65,13 @@ class CHL2MPPlayerAnimState : public CMultiPlayerAnimState #ifdef NEO bool IsLeaning(CStudioHdr *pStudioHdr); float GetMovingSpeed(); + bool HasLandedFromJump(); #endif // NEO CHL2MP_Player *m_pHL2MPPlayer; +#if defined( NEO ) && defined( CLIENT_DLL ) + float m_flJumpGroundFlagTime; // when the client first saw the ground flag during a jump, 0 while in the air +#endif #ifndef NEO bool m_bInAirWalk; float m_flHoldDeployedPoseUntilTime;