From 8fa6f698467198b3fc1ed01db07c360273c7e37d Mon Sep 17 00:00:00 2001 From: Alan Shen Date: Wed, 14 Oct 2026 23:54:00 -0600 Subject: [PATCH 1/3] Animate players on the SDK base player anim state Move the player animation back onto CBasePlayerAnimState, the 2006 SDK base classic NEOTOKYO is built on, which neo compiles but did not use. CNEOPlayerAnimState replaces CHL2MPPlayerAnimState and takes CMultiPlayerAnimState out of the build (the files stay on disk). The base gives classic's torso blend by speed, constant leg ground speeds, the 3 s face-front timer and its feet rules. The new class adds the run legs only while sprinting, the jump held until a drawn landing, one gesture layer for fire, reload, grenade and detpack events, the lean rule, the #2108 transitioner reset, and a face-front timer counted from the last squared frame so server and client agree. Client-side animation and the network excludes from #653 are kept. --- src/game/client/CMakeLists.txt | 6 +- src/game/client/hl2mp/c_hl2mp_player.cpp | 2 +- src/game/client/hl2mp/c_hl2mp_player.h | 4 +- src/game/server/CMakeLists.txt | 6 +- src/game/server/hl2mp/hl2mp_player.cpp | 2 +- src/game/server/hl2mp/hl2mp_player.h | 4 +- src/game/shared/base_playeranimstate.cpp | 11 + src/game/shared/base_playeranimstate.h | 5 + .../shared/hl2mp/hl2mp_playeranimstate.cpp | 1015 ----------------- src/game/shared/hl2mp/hl2mp_playeranimstate.h | 80 -- src/game/shared/neo/neo_playeranimstate.cpp | 453 ++++++++ src/game/shared/neo/neo_playeranimstate.h | 76 ++ 12 files changed, 555 insertions(+), 1109 deletions(-) delete mode 100644 src/game/shared/hl2mp/hl2mp_playeranimstate.cpp delete mode 100644 src/game/shared/hl2mp/hl2mp_playeranimstate.h create mode 100644 src/game/shared/neo/neo_playeranimstate.cpp create mode 100644 src/game/shared/neo/neo_playeranimstate.h diff --git a/src/game/client/CMakeLists.txt b/src/game/client/CMakeLists.txt index 7b73417fdb..cfb32df6f0 100644 --- a/src/game/client/CMakeLists.txt +++ b/src/game/client/CMakeLists.txt @@ -1759,6 +1759,7 @@ set(UNITY_SOURCE_NEO_SHARED ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_spawnpoint.cpp + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_playeranimstate.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.cpp @@ -1789,6 +1790,7 @@ target_sources_grouped( ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_spawnpoint.h + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_playeranimstate.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.h @@ -1898,14 +1900,11 @@ target_sources_grouped( TARGET client NAME "Source Files\\Shared\\Multiplayer" FILES - ${CMAKE_SOURCE_DIR}/game/shared/Multiplayer/multiplayer_animstate.cpp - ${CMAKE_SOURCE_DIR}/game/shared/Multiplayer/multiplayer_animstate.h ) set(UNITY_SOURCE_HL2MP ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_gamerules.cpp ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_player_shared.cpp - ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_playeranimstate.cpp ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_weapon_parse.cpp hl2mp/c_hl2mp_player.cpp hl2mp/c_te_hl2mp_shotgun_shot.cpp @@ -1923,7 +1922,6 @@ target_sources_grouped( FILES ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_gamerules.h ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_player_shared.h - ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_playeranimstate.h ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_weapon_parse.h hl2mp/c_hl2mp_player.h hl2mp/clientmode_hl2mpnormal.h diff --git a/src/game/client/hl2mp/c_hl2mp_player.cpp b/src/game/client/hl2mp/c_hl2mp_player.cpp index f0e64c8bd8..6b3589bd60 100644 --- a/src/game/client/hl2mp/c_hl2mp_player.cpp +++ b/src/game/client/hl2mp/c_hl2mp_player.cpp @@ -188,7 +188,7 @@ C_HL2MP_Player::C_HL2MP_Player() : m_PlayerAnimState( this ), m_iv_angEyeAngles( m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK; #endif #ifdef NEO - m_PlayerAnimState = CreateHL2MPPlayerAnimState( this ); + m_PlayerAnimState = CreateNEOPlayerAnimState( this ); #endif m_blinkTimer.Invalidate(); diff --git a/src/game/client/hl2mp/c_hl2mp_player.h b/src/game/client/hl2mp/c_hl2mp_player.h index aaa99399c0..9e15e066dd 100644 --- a/src/game/client/hl2mp/c_hl2mp_player.h +++ b/src/game/client/hl2mp/c_hl2mp_player.h @@ -9,7 +9,7 @@ #define HL2MP_PLAYER_H #pragma once -#include "hl2mp_playeranimstate.h" +#include "neo_playeranimstate.h" #include "c_basehlplayer.h" #include "hl2mp_player_shared.h" #include "beamdraw.h" @@ -145,7 +145,7 @@ class C_HL2MP_Player : public C_BaseHLPlayer C_HL2MP_Player( const C_HL2MP_Player & ); #ifdef NEO - CHL2MPPlayerAnimState *m_PlayerAnimState; + CNEOPlayerAnimState *m_PlayerAnimState; #else CPlayerAnimState m_PlayerAnimState; #endif diff --git a/src/game/server/CMakeLists.txt b/src/game/server/CMakeLists.txt index fec1fd9998..20980013ca 100644 --- a/src/game/server/CMakeLists.txt +++ b/src/game/server/CMakeLists.txt @@ -1423,6 +1423,7 @@ set(UNITY_SOURCE_NEO_SHARED ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_spawnpoint.cpp + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_playeranimstate.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.cpp ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.cpp @@ -1480,6 +1481,7 @@ target_sources_grouped( ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_penetration_resistance.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_shared.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_player_spawnpoint.h + ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_playeranimstate.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_predicted_viewmodel_muzzleflash.h ${CMAKE_SOURCE_DIR}/game/shared/neo/neo_shot_manipulator.h @@ -1740,14 +1742,11 @@ target_sources_grouped( TARGET server NAME "Source Files\\Shared\\Multiplayer" FILES - ${CMAKE_SOURCE_DIR}/game/shared/Multiplayer/multiplayer_animstate.cpp - ${CMAKE_SOURCE_DIR}/game/shared/Multiplayer/multiplayer_animstate.h ) set(UNITY_SOURCE_HL2MP ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_gamerules.cpp ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_player_shared.cpp - ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_playeranimstate.cpp ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_weapon_parse.cpp hl2mp/hl2mp_client.cpp hl2mp/hl2mp_cvars.cpp @@ -1766,7 +1765,6 @@ target_sources_grouped( FILES ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_gamerules.h ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_player_shared.h - ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_playeranimstate.h ${CMAKE_SOURCE_DIR}/game/shared/hl2mp/hl2mp_weapon_parse.h hl2mp/hl2mp_gameinterface.h hl2mp/hl2mp_player.h diff --git a/src/game/server/hl2mp/hl2mp_player.cpp b/src/game/server/hl2mp/hl2mp_player.cpp index d9e8c9bcc5..d73f33a6af 100644 --- a/src/game/server/hl2mp/hl2mp_player.cpp +++ b/src/game/server/hl2mp/hl2mp_player.cpp @@ -193,7 +193,7 @@ CHL2MP_Player::CHL2MP_Player() : m_PlayerAnimState( this ) { #ifdef NEO //Tony; create our player animation state. - m_PlayerAnimState = CreateHL2MPPlayerAnimState( this ); + m_PlayerAnimState = CreateNEOPlayerAnimState( this ); #endif UseClientSideAnimation(); diff --git a/src/game/server/hl2mp/hl2mp_player.h b/src/game/server/hl2mp/hl2mp_player.h index e5e0b60a14..463d9d2374 100644 --- a/src/game/server/hl2mp/hl2mp_player.h +++ b/src/game/server/hl2mp/hl2mp_player.h @@ -16,7 +16,7 @@ class CHL2MP_Player; #include "hl2_player.h" #include "simtimer.h" #include "soundenvelope.h" -#include "hl2mp_playeranimstate.h" +#include "neo_playeranimstate.h" #include "hl2mp_player_shared.h" #include "hl2mp_gamerules.h" #include "utldict.h" @@ -177,7 +177,7 @@ class CHL2MP_Player : public CHL2_Player private: #ifdef NEO - CHL2MPPlayerAnimState *m_PlayerAnimState; + CNEOPlayerAnimState *m_PlayerAnimState; #else CPlayerAnimState m_PlayerAnimState; #endif diff --git a/src/game/shared/base_playeranimstate.cpp b/src/game/shared/base_playeranimstate.cpp index 0126f016ae..7f4950894c 100644 --- a/src/game/shared/base_playeranimstate.cpp +++ b/src/game/shared/base_playeranimstate.cpp @@ -234,6 +234,17 @@ void CBasePlayerAnimState::RestartMainSequence() } +#ifdef NEO +void CBasePlayerAnimState::OnNewModel() +{ + // the aim layer transitioners keep the previous sequences to blend out of them, + // and after a model swap those indices address a foreign sequence table + m_IdleSequenceTransitioner.RemoveAll(); + m_SequenceTransitioner.RemoveAll(); + ClearAnimationState(); +} +#endif + void CBasePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) { VPROF( "CBasePlayerAnimState::ComputeSequences" ); diff --git a/src/game/shared/base_playeranimstate.h b/src/game/shared/base_playeranimstate.h index 95e2c73a4f..de0a68be97 100644 --- a/src/game/shared/base_playeranimstate.h +++ b/src/game/shared/base_playeranimstate.h @@ -162,6 +162,11 @@ abstract_class CBasePlayerAnimState : virtual public IPlayerAnimState void RestartMainSequence(); +#ifdef NEO + // A sequence index is only meaningful for the model it was computed against + void OnNewModel(); +#endif + // Helpers for the derived classes to use. protected: diff --git a/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp b/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp deleted file mode 100644 index 9e441acd87..0000000000 --- a/src/game/shared/hl2mp/hl2mp_playeranimstate.cpp +++ /dev/null @@ -1,1015 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -#include "cbase.h" -#include "tier0/vprof.h" -#include "animation.h" -#include "studio.h" -#include "apparent_velocity_helper.h" -#include "utldict.h" - -#include "hl2mp_playeranimstate.h" -#include "base_playeranimstate.h" -#include "datacache/imdlcache.h" - -#ifdef CLIENT_DLL -#include "c_hl2mp_player.h" -#ifdef NEO -#include "c_neo_player.h" -#endif -#else -#include "hl2mp_player.h" -#ifdef NEO -#include "neo_player.h" -#endif -#endif - -#ifdef NEO -#include "shareddefs.h" - -#define DEFAULT_IDLE_NAME "Idle_Upper_" -#define DEFAULT_CROUCH_IDLE_NAME "Crouch_Idle_Upper_" -#define DEFAULT_CROUCH_WALK_NAME "Crouch_Walk_Upper_" -#define DEFAULT_WALK_NAME "Walk_Upper_" -#define DEFAULT_RUN_NAME "Run_Upper_" - -#define DEFAULT_FIRE_IDLE_NAME "Idle_Shoot_" -#define DEFAULT_FIRE_CROUCH_NAME "Crouch_Idle_Shoot_" -#define DEFAULT_FIRE_CROUCH_WALK_NAME "Crouch_Walk_Shoot_" -#define DEFAULT_FIRE_WALK_NAME "Walk_Shoot_" -#define DEFAULT_FIRE_RUN_NAME "Run_Shoot_" -#endif - -#include "filesystem.h" -#include "engine/ivdebugoverlay.h" - -#define HL2MP_RUN_SPEED 320.0f -#define HL2MP_WALK_SPEED 75.0f -#define HL2MP_CROUCHWALK_SPEED 110.0f - -extern ConVar sv_showanimstate; -extern ConVar showanimstate_log; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// Output : CMultiPlayerAnimState* -//----------------------------------------------------------------------------- -CHL2MPPlayerAnimState* CreateHL2MPPlayerAnimState( CHL2MP_Player *pPlayer ) -{ - MDLCACHE_CRITICAL_SECTION(); - - // Setup the movement data. - MultiPlayerMovementData_t movementData; - movementData.m_flBodyYawRate = 720.0f; - movementData.m_flRunSpeed = HL2MP_RUN_SPEED; - movementData.m_flWalkSpeed = HL2MP_WALK_SPEED; - movementData.m_flSprintSpeed = -1.0f; - - // Create animation state for this player. - CHL2MPPlayerAnimState *pRet = new CHL2MPPlayerAnimState( pPlayer, movementData ); - - // Specific HL2MP player initialization. - pRet->InitHL2MPAnimState( pPlayer ); - - return pRet; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -CHL2MPPlayerAnimState::CHL2MPPlayerAnimState() -{ - m_pHL2MPPlayer = NULL; - - // Don't initialize HL2MP specific variables here. Init them in InitHL2MPAnimState() -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// &movementData - -//----------------------------------------------------------------------------- -CHL2MPPlayerAnimState::CHL2MPPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ) -: CMultiPlayerAnimState( pPlayer, movementData ) -{ - m_pHL2MPPlayer = NULL; - - // Don't initialize HL2MP specific variables here. Init them in InitHL2MPAnimState() -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -CHL2MPPlayerAnimState::~CHL2MPPlayerAnimState() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize HL2MP specific animation state. -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::InitHL2MPAnimState( CHL2MP_Player *pPlayer ) -{ - m_pHL2MPPlayer = pPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::ClearAnimationState( void ) -{ - BaseClass::ClearAnimationState(); -} - -int CHL2MPPlayerAnimState::CalcSequenceIndex(const char* pBaseName, ...) -{ - char szFullName[512]; - va_list marker; - va_start(marker, pBaseName); - Q_vsnprintf(szFullName, sizeof(szFullName), pBaseName, marker); - va_end(marker); - CBaseAnimatingOverlay* pPlayer = GetBasePlayer(); - int iSequence = pPlayer->LookupSequence(szFullName); - - // Show warnings if we can't find anything here. - if (iSequence == -1) - { - static CUtlDict dict; - if (dict.Find(szFullName) == -1) - { - dict.Insert(szFullName, 0); - Warning("CalcSequenceIndex: can't find '%s'.\n", szFullName); - } - - iSequence = 0; - } - - //DevMsg("CalcSeqIdx: \"%s\": %d\n", szFullName, iSequence); - - return iSequence; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : actDesired - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CHL2MPPlayerAnimState::TranslateActivity( Activity actDesired ) -{ - // Hook into baseclass when / if hl2mp player models get swim animations. - Activity translateActivity = actDesired; //BaseClass::TranslateActivity( actDesired ); - if ( GetHL2MPPlayer()->GetActiveWeapon() ) - { - bool required = false; - translateActivity = GetHL2MPPlayer()->GetActiveWeapon()->ActivityOverride( translateActivity, &required); - } - return translateActivity; -} - -#ifdef NEO -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pStudioHdr - -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::ComputeSequences(CStudioHdr* pStudioHdr) -{ - VPROF("CBasePlayerAnimState::ComputeSequences"); - - // Lower body (walk/run/idle). - ComputeMainSequence(); - - // The groundspeed interpolator uses the main sequence info. - UpdateInterpolators(); - ComputeGestureSequence(pStudioHdr); -} - -#endif //NEO -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::Update( float eyeYaw, float eyePitch ) -{ - // Profile the animation update. - VPROF( "CHL2MPPlayerAnimState::Update" ); - - // Get the HL2MP player. - CHL2MP_Player *pHL2MPPlayer = GetHL2MPPlayer(); - if ( !pHL2MPPlayer ) - return; - - // Get the studio header for the player. - CStudioHdr *pStudioHdr = pHL2MPPlayer->GetModelPtr(); - if ( !pStudioHdr ) - return; - - // Check to see if we should be updating the animation state - dead, ragdolled? - if ( !ShouldUpdateAnimState() ) - { - ClearAnimationState(); - return; - } - - // Store the eye angles. - m_flEyeYaw = AngleNormalize( eyeYaw ); - m_flEyePitch = AngleNormalize( eyePitch ); - - // Compute the player sequences. - ComputeSequences( pStudioHdr ); - - if ( SetupPoseParameters( pStudioHdr ) ) - { - // Pose parameter - what direction are the player's legs running in. - ComputePoseParam_MoveYaw( pStudioHdr ); - - // Pose parameter - Torso aiming (up/down). - ComputePoseParam_AimPitch( pStudioHdr ); - - // Pose parameter - Torso aiming (rotation). - ComputePoseParam_AimYaw( pStudioHdr ); - } - -#ifdef CLIENT_DLL - if ( C_BasePlayer::ShouldDrawLocalPlayer() ) - { - m_pHL2MPPlayer->SetPlaybackRate( 1.0f ); - } -#endif - -#ifdef CLIENT_DLL - if (cl_showanimstate.GetInt() == m_pHL2MPPlayer->entindex()) - { - DebugShowAnimStateFull(5); - } - else if (cl_showanimstate.GetInt() == -2) - { - C_BasePlayer* targetPlayer = C_BasePlayer::GetLocalPlayer(); - - if (targetPlayer && (targetPlayer->GetObserverMode() == OBS_MODE_IN_EYE || targetPlayer->GetObserverMode() == OBS_MODE_CHASE)) - { - C_BaseEntity* target = targetPlayer->GetObserverTarget(); - - if (target && target->IsPlayer()) - { - targetPlayer = ToBasePlayer(target); - } - } - - if (m_pHL2MPPlayer == targetPlayer) - { - DebugShowAnimStateFull(6); - } - } -#else - if (sv_showanimstate.GetInt() == m_pHL2MPPlayer->entindex()) - { - DebugShowAnimState(20); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : event - -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) -{ - Activity iGestureActivity = ACT_INVALID; - - switch( event ) - { - case PLAYERANIMEVENT_ATTACK_PRIMARY: - { -#ifdef NEO - AddToGestureSlot(GESTURE_SLOT_ATTACK_AND_RELOAD, CalcFireSequence(), true); -#else - // Weapon primary fire. - if ( m_pHL2MPPlayer->GetFlags() & FL_DUCKING ) - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ); - else - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE ); - - iGestureActivity = ACT_VM_PRIMARYATTACK; -#endif - break; - } - - case PLAYERANIMEVENT_VOICE_COMMAND_GESTURE: - { - if ( !IsGestureSlotActive( GESTURE_SLOT_ATTACK_AND_RELOAD ) ) - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, (Activity)nData ); - - break; - } - case PLAYERANIMEVENT_ATTACK_SECONDARY: - { -#ifdef NEO - AddToGestureSlot(GESTURE_SLOT_ATTACK_AND_RELOAD, CalcFireSequence(), true); -#else - // Weapon secondary fire. - if ( m_pHL2MPPlayer->GetFlags() & FL_DUCKING ) - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_SECONDARYFIRE ); - else - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_SECONDARYFIRE ); - - iGestureActivity = ACT_VM_PRIMARYATTACK; -#endif - break; - } - case PLAYERANIMEVENT_ATTACK_PRE: - { - if ( m_pHL2MPPlayer->GetFlags() & FL_DUCKING ) - { - // Weapon pre-fire. Used for minigun windup, sniper aiming start, etc in crouch. - iGestureActivity = ACT_MP_ATTACK_CROUCH_PREFIRE; - } - else - { - // Weapon pre-fire. Used for minigun windup, sniper aiming start, etc. - iGestureActivity = ACT_MP_ATTACK_STAND_PREFIRE; - } - - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, iGestureActivity, false ); - - break; - } - case PLAYERANIMEVENT_ATTACK_POST: - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_POSTFIRE ); - break; - } - - case PLAYERANIMEVENT_RELOAD: - { -#ifdef NEO - AddToGestureSlot(GESTURE_SLOT_ATTACK_AND_RELOAD, CalcReloadSequence(), true); -#else - // Weapon reload. - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH ); - else - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND ); -#endif - break; - } - case PLAYERANIMEVENT_RELOAD_LOOP: - { - // Weapon reload. - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH_LOOP ); - else - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND_LOOP ); - break; - } - case PLAYERANIMEVENT_RELOAD_END: - { - // Weapon reload. - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH_END ); - else - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND_END ); - break; - } - default: - { - BaseClass::DoAnimationEvent( event, nData ); - break; - } - } - -#ifdef CLIENT_DLL - // Make the weapon play the animation as well - if ( iGestureActivity != ACT_INVALID ) - { - CBaseCombatWeapon *pWeapon = GetHL2MPPlayer()->GetActiveWeapon(); - if ( pWeapon ) - { -// pWeapon->EnsureCorrectRenderingModel(); - pWeapon->SendWeaponAnim( iGestureActivity ); -// // Force animation events! -// pWeapon->ResetEventsParity(); // reset event parity so the animation events will occur on the weapon. - pWeapon->DoAnimationEvents( pWeapon->GetModelPtr() ); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -//----------------------------------------------------------------------------- -bool CHL2MPPlayerAnimState::HandleSwimming( Activity &idealActivity ) -{ - bool bInWater = BaseClass::HandleSwimming( idealActivity ); - - return bInWater; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2MPPlayerAnimState::HandleMoving( Activity &idealActivity ) -{ -#ifdef NEO - if (m_pHL2MPPlayer->IsSprinting()) - { - idealActivity = ACT_RUN; - } - else - { - Vector vecVelocity; - GetOuterAbsVelocity(vecVelocity); - if (vecVelocity.Length() > 0.5) - { - idealActivity = ACT_WALK; - } - } - - return true; -#else - return BaseClass::HandleMoving( idealActivity ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2MPPlayerAnimState::HandleDucking( Activity &idealActivity ) -{ - if ( m_pHL2MPPlayer->GetFlags() & FL_DUCKING ) - { - if ( GetOuterXYSpeed() < MOVING_MINIMUM_SPEED ) - { -#ifdef NEO - idealActivity = ACT_CROUCHIDLE; -#else - idealActivity = ACT_MP_CROUCH_IDLE; -#endif - } - else - { -#ifdef NEO - idealActivity = ACT_RUN_CROUCH; -#else - idealActivity = ACT_MP_CROUCHWALK; -#endif - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -bool CHL2MPPlayerAnimState::HandleJumping( Activity &idealActivity ) -{ - Vector vecVelocity; - GetOuterAbsVelocity( vecVelocity ); - - if ( m_bJumping ) - { - static bool bNewJump = false; //Tony; hl2mp players only have a 'hop' - - if ( m_bFirstJumpFrame ) - { - m_bFirstJumpFrame = false; - RestartMainSequence(); // Reset the animation. - } - - // Reset if we hit water and start swimming. - if ( m_pHL2MPPlayer->GetWaterLevel() >= WL_Waist ) - { - m_bJumping = false; - RestartMainSequence(); - } - // Don't check if he's on the ground for a sec.. sometimes the client still has the - // on-ground flag set right when the message comes in. - else if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f ) - { - if ( m_pHL2MPPlayer->GetFlags() & FL_ONGROUND ) - { - m_bJumping = false; - RestartMainSequence(); - - if ( bNewJump ) - { -#ifdef NEO - RestartGesture(GESTURE_SLOT_JUMP, ACT_HOP); -#else - RestartGesture( GESTURE_SLOT_JUMP, ACT_MP_JUMP_LAND ); -#endif - } - } - } - - // if we're still jumping - if ( m_bJumping ) - { -#ifdef NEO - idealActivity = ACT_HOP; -#else - if ( bNewJump ) - { - if ( gpGlobals->curtime - m_flJumpStartTime > 0.5 ) - { - idealActivity = ACT_MP_JUMP_FLOAT; - } - else - { - idealActivity = ACT_MP_JUMP_START; - } - } - else - { - idealActivity = ACT_MP_JUMP; - } -#endif - } - } - - if ( m_bJumping ) - return true; - - return false; -} - -bool CHL2MPPlayerAnimState::SetupPoseParameters( CStudioHdr *pStudioHdr ) -{ -#ifdef NEO - BaseClass::SetupPoseParameters(pStudioHdr); -#endif - // Check to see if this has already been done. - if ( m_bPoseParameterInit ) - return true; - - // Save off the pose parameter indices. - if ( !pStudioHdr ) - return false; - - // Tony; just set them both to the same for now. - m_PoseParameterData.m_iMoveX = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_yaw" ); - m_PoseParameterData.m_iMoveY = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_yaw" ); - if ( ( m_PoseParameterData.m_iMoveX < 0 ) || ( m_PoseParameterData.m_iMoveY < 0 ) ) - return false; - - // Look for the aim pitch blender. - m_PoseParameterData.m_iAimPitch = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "body_pitch" ); - if ( m_PoseParameterData.m_iAimPitch < 0 ) - return false; - - // Look for aim yaw blender. - m_PoseParameterData.m_iAimYaw = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "body_yaw" ); - if ( m_PoseParameterData.m_iAimYaw < 0 ) - return false; - - m_bPoseParameterInit = true; - - return true; -} -float SnapYawTo( float flValue ); -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::EstimateYaw( void ) -{ - // Get the frame time. - float flDeltaTime = gpGlobals->frametime; - if ( flDeltaTime == 0.0f ) - return; - -#if 0 // 9way - // Get the player's velocity and angles. - Vector vecEstVelocity; - GetOuterAbsVelocity( vecEstVelocity ); - QAngle angles = GetBasePlayer()->GetLocalAngles(); - - // If we are not moving, sync up the feet and eyes slowly. - if ( vecEstVelocity.x == 0.0f && vecEstVelocity.y == 0.0f ) - { - float flYawDelta = angles[YAW] - m_PoseParameterData.m_flEstimateYaw; - flYawDelta = AngleNormalize( flYawDelta ); - - if ( flDeltaTime < 0.25f ) - { - flYawDelta *= ( flDeltaTime * 4.0f ); - } - else - { - flYawDelta *= flDeltaTime; - } - - m_PoseParameterData.m_flEstimateYaw += flYawDelta; - AngleNormalize( m_PoseParameterData.m_flEstimateYaw ); - } - else - { - m_PoseParameterData.m_flEstimateYaw = ( atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0f / M_PI ); - m_PoseParameterData.m_flEstimateYaw = clamp( m_PoseParameterData.m_flEstimateYaw, -180.0f, 180.0f ); - } -#else - float dt = gpGlobals->frametime; - - // Get the player's velocity and angles. - Vector vecEstVelocity; - GetOuterAbsVelocity( vecEstVelocity ); - QAngle angles = GetBasePlayer()->GetLocalAngles(); - - if ( vecEstVelocity.y == 0 && vecEstVelocity.x == 0 ) - { - float flYawDiff = angles[YAW] - m_PoseParameterData.m_flEstimateYaw; - flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; - if (flYawDiff > 180) - flYawDiff -= 360; - if (flYawDiff < -180) - flYawDiff += 360; - - if (dt < 0.25) - flYawDiff *= dt * 4; - else - flYawDiff *= dt; - - m_PoseParameterData.m_flEstimateYaw += flYawDiff; - m_PoseParameterData.m_flEstimateYaw = m_PoseParameterData.m_flEstimateYaw - (int)(m_PoseParameterData.m_flEstimateYaw / 360) * 360; - } - else - { - m_PoseParameterData.m_flEstimateYaw = (atan2(vecEstVelocity.y, vecEstVelocity.x) * 180 / M_PI); - - if (m_PoseParameterData.m_flEstimateYaw > 180) - m_PoseParameterData.m_flEstimateYaw = 180; - else if (m_PoseParameterData.m_flEstimateYaw < -180) - m_PoseParameterData.m_flEstimateYaw = -180; - } -#endif -} -//----------------------------------------------------------------------------- -// Purpose: Override for backpeddling -// Input : dt - -//----------------------------------------------------------------------------- -float SnapYawTo( float flValue ); -void CHL2MPPlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ) -{ -#ifdef NEO - BaseClass::ComputePoseParam_MoveYaw(pStudioHdr); -#endif - // Get the estimated movement yaw. - EstimateYaw(); - -#if 1 // 9way - ConVarRef mp_slammoveyaw("mp_slammoveyaw"); - - // Get the view yaw. - float flAngle = AngleNormalize( m_flEyeYaw ); - - // Calc side to side turning - the view vs. movement yaw. - float flYaw = flAngle - m_PoseParameterData.m_flEstimateYaw; - flYaw = AngleNormalize( -flYaw ); - - // Get the current speed the character is running. - bool bIsMoving; - float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving ); - - // Setup the 9-way blend parameters based on our speed and direction. - Vector2D vecCurrentMoveYaw( 0.0f, 0.0f ); - if ( bIsMoving ) - { - if ( mp_slammoveyaw.GetBool() ) - flYaw = SnapYawTo( flYaw ); - - vecCurrentMoveYaw.x = cos( DEG2RAD( flYaw ) ) * flPlaybackRate; - vecCurrentMoveYaw.y = -sin( DEG2RAD( flYaw ) ) * flPlaybackRate; - } - - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, vecCurrentMoveYaw.x ); - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, vecCurrentMoveYaw.y ); - - m_DebugAnimData.m_vecMoveYaw = vecCurrentMoveYaw; -#else - // view direction relative to movement - float flYaw; - - QAngle angles = GetBasePlayer()->GetLocalAngles(); - float ang = angles[ YAW ]; - if ( ang > 180.0f ) - { - ang -= 360.0f; - } - else if ( ang < -180.0f ) - { - ang += 360.0f; - } - - // calc side to side turning - flYaw = ang - m_PoseParameterData.m_flEstimateYaw; - // Invert for mapping into 8way blend - flYaw = -flYaw; - flYaw = flYaw - (int)(flYaw / 360) * 360; - - if (flYaw < -180) - { - flYaw = flYaw + 360; - } - else if (flYaw > 180) - { - flYaw = flYaw - 360; - } - - //Tony; oops, i inverted this previously above. - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, flYaw ); - -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr ) -{ - // Get the view pitch. - float flAimPitch = m_flEyePitch; - - // Set the aim pitch pose parameter and save. - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimPitch, flAimPitch ); - m_DebugAnimData.m_flAimPitch = flAimPitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ) -{ - // Get the movement velocity. - Vector vecVelocity; - GetOuterAbsVelocity( vecVelocity ); - - // Check to see if we are moving. - bool bMoving = ( vecVelocity.Length() > 1.0f ) ? true : false; - -#ifdef NEO - // If we are moving or leaning or are prone and undeployed. - if ( bMoving || m_bForceAimYaw || IsLeaning(pStudioHdr) ) -#else - // If we are moving or are prone and undeployed. - if ( bMoving || m_bForceAimYaw ) -#endif // NEO - { - // The feet match the eye direction when moving - the move yaw takes care of the rest. - m_flGoalFeetYaw = m_flEyeYaw; - } - // Else if we are not moving. - else - { - // Initialize the feet. - if ( m_PoseParameterData.m_flLastAimTurnTime <= 0.0f ) - { - m_flGoalFeetYaw = m_flEyeYaw; - m_flCurrentFeetYaw = m_flEyeYaw; - m_PoseParameterData.m_flLastAimTurnTime = gpGlobals->curtime; - } - // Make sure the feet yaw isn't too far out of sync with the eye yaw. - // TODO: Do something better here! - else - { - float flYawDelta = AngleNormalize( m_flGoalFeetYaw - m_flEyeYaw ); - -#ifdef NEO - if (fabs(flYawDelta) > 90.f /*NEO_ANIMSTATE_MAX_BODY_YAW_DEGREES*/) -#else - if ( fabs( flYawDelta ) > 45.0f ) -#endif - { - float flSide = ( flYawDelta > 0.0f ) ? -1.0f : 1.0f; - -#ifdef NEO - m_flGoalFeetYaw += (90.f/*NEO_ANIMSTATE_MAX_BODY_YAW_DEGREES*/ * flSide); -#else - m_flGoalFeetYaw += ( 45.0f * flSide ); -#endif - } - } - } - - // Fix up the feet yaw. - m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw ); - if ( m_flGoalFeetYaw != m_flCurrentFeetYaw ) - { - if ( m_bForceAimYaw ) - { - m_flCurrentFeetYaw = m_flGoalFeetYaw; - } - else - { - ConvergeYawAngles( m_flGoalFeetYaw, 720.0f, gpGlobals->frametime, m_flCurrentFeetYaw ); - m_flLastAimTurnTime = gpGlobals->curtime; - } - } - - // Rotate the body into position. - m_angRender[YAW] = m_flCurrentFeetYaw; - - // Find the aim(torso) yaw base on the eye and feet yaws. - float flAimYaw = m_flEyeYaw - m_flCurrentFeetYaw; - flAimYaw = AngleNormalize( flAimYaw ); - - // Set the aim yaw and save. - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimYaw, flAimYaw ); - m_DebugAnimData.m_flAimYaw = flAimYaw; - - // Turn off a force aim yaw - either we have already updated or we don't need to. - m_bForceAimYaw = false; - -#ifndef CLIENT_DLL - QAngle angle = GetBasePlayer()->GetAbsAngles(); - angle[YAW] = m_flCurrentFeetYaw; - - GetBasePlayer()->SetAbsAngles( angle ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Override the default, because hl2mp models don't use moveX -// Input : - -// Output : float -//----------------------------------------------------------------------------- -float CHL2MPPlayerAnimState::GetCurrentMaxGroundSpeed() -{ -#ifdef NEO - return BaseClass::GetCurrentMaxGroundSpeed(); -#endif - CStudioHdr *pStudioHdr = GetBasePlayer()->GetModelPtr(); - - if ( pStudioHdr == NULL ) - return 1.0f; - -// float prevX = GetBasePlayer()->GetPoseParameter( m_PoseParameterData.m_iMoveX ); - float prevY = GetBasePlayer()->GetPoseParameter( m_PoseParameterData.m_iMoveY ); - - float d = sqrt( /*prevX * prevX + */prevY * prevY ); - float newY;//, newX; - if ( d == 0.0 ) - { -// newX = 1.0; - newY = 0.0; - } - else - { -// newX = prevX / d; - newY = prevY / d; - } - -// GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, newX ); - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, newY ); - - float speed = GetBasePlayer()->GetSequenceGroundSpeed( GetBasePlayer()->GetSequence() ); - -// GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, prevX ); - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, prevY ); - - return speed; -} - -#ifdef NEO -bool CHL2MPPlayerAnimState::IsLeaning(CStudioHdr *pStudioHdr) -{ - if (CBaseAnimating* pBaseAnimating = GetBasePlayer()->GetBaseAnimating()) - { - constexpr int LEAN_BONE_CONTROLLER = 0; -#ifdef CLIENT_DLL - constexpr float BONE_CONTROLLER_VALUE_NOT_LEANING = 0.5f; -#else - constexpr int BONE_CONTROLLER_VALUE_NOT_LEANING = 0; -#endif // CLIENT_DLL - return pBaseAnimating->GetBoneController(LEAN_BONE_CONTROLLER) != BONE_CONTROLLER_VALUE_NOT_LEANING; - } - return false; -} -#endif // NEO - -// ----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::AnimStateLog(const char* pMsg, ...) -{ - // Format the string. - char str[4096]; - va_list marker; - va_start(marker, pMsg); - Q_vsnprintf(str, sizeof(str), pMsg, marker); - va_end(marker); - - // Log it? - if (showanimstate_log.GetInt() == 1 || showanimstate_log.GetInt() == 3) - { - Msg("%s", str); - } - - if (showanimstate_log.GetInt() > 1) - { -#ifdef CLIENT_DLL - const char* fname = "AnimStateClient.log"; -#else - const char* fname = "AnimStateServer.log"; -#endif - static FileHandle_t hFile = filesystem->Open(fname, "wt"); - filesystem->FPrintf(hFile, "%s", str); - filesystem->Flush(hFile); - } -} - -// ----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::AnimStatePrintf(int iLine, const char* pMsg, ...) -{ - // Format the string. - char str[4096]; - va_list marker; - va_start(marker, pMsg); - Q_vsnprintf(str, sizeof(str), pMsg, marker); - va_end(marker); - - // Show it with Con_NPrintf. - engine->Con_NPrintf(iLine, "%s", str); - - // Log it. - AnimStateLog("%s\n", str); -} - - -// ----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::DebugShowAnimState(int iStartLine) -{ - Vector vOuterVel; - GetOuterAbsVelocity(vOuterVel); - - int iLine = iStartLine; - AnimStatePrintf(iLine++, "main: %s(%d), cycle: %.2f cyclerate: %.2f playbackrate: %.2f\n", - GetSequenceName(m_pHL2MPPlayer->GetModelPtr(), m_pHL2MPPlayer->GetSequence()), - m_pHL2MPPlayer->GetSequence(), - m_pHL2MPPlayer->GetCycle(), - m_pHL2MPPlayer->GetSequenceCycleRate(m_pHL2MPPlayer->GetModelPtr(), m_pHL2MPPlayer->GetSequence()), - m_pHL2MPPlayer->GetPlaybackRate() - ); - - for (int i = 0; i < m_pHL2MPPlayer->GetNumAnimOverlays() - 1; i++) - { - CAnimationLayer* pLayer = m_pHL2MPPlayer->GetAnimOverlay(AIMSEQUENCE_LAYER + i); -#ifdef CLIENT_DLL - AnimStatePrintf(iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)", - !pLayer->IsActive() ? "-- " : (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName(m_pHL2MPPlayer->GetModelPtr(), pLayer->m_nSequence)), - !pLayer->IsActive() ? 0 : (int)pLayer->m_nSequence, - !pLayer->IsActive() ? 0 : (float)pLayer->m_flWeight, - !pLayer->IsActive() ? 0 : (float)pLayer->m_flCycle, - !pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder, - i - ); -#else - AnimStatePrintf(iLine++, "%s(%d), flags (%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)", - !pLayer->IsActive() ? "-- " : (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName(m_pHL2MPPlayer->GetModelPtr(), pLayer->m_nSequence)), - !pLayer->IsActive() ? 0 : (int)pLayer->m_nSequence, - !pLayer->IsActive() ? 0 : (int)pLayer->m_fFlags,// Doesn't exist on client - !pLayer->IsActive() ? 0 : (float)pLayer->m_flWeight, - !pLayer->IsActive() ? 0 : (float)pLayer->m_flCycle, - !pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder, - i - ); -#endif - } - - AnimStatePrintf(iLine++, "vel: %.2f, time: %.2f, max: %.2f, animspeed: %.2f", - vOuterVel.Length2D(), gpGlobals->curtime, GetInterpolatedGroundSpeed(), m_pHL2MPPlayer->GetSequenceGroundSpeed(m_pHL2MPPlayer->GetSequence())); - - { - AnimStatePrintf(iLine++, "ent yaw: %.2f, body_yaw: %.2f, body_pitch: %.2f, move_x: %.2f, move_y: %.2f", - m_angRender[YAW], g_flLastBodyYaw, g_flLastBodyPitch, m_DebugAnimData.m_vecMoveYaw.x, m_DebugAnimData.m_vecMoveYaw.y); - } - - // Draw a red triangle on the ground for the eye yaw. - float flBaseSize = 10; - float flHeight = 80; - Vector vBasePos = m_pHL2MPPlayer->GetAbsOrigin() + Vector(0, 0, 3); - QAngle angles(0, 0, 0); - angles[YAW] = m_flEyeYaw; - Vector vForward, vRight, vUp; - AngleVectors(angles, &vForward, &vRight, &vUp); - debugoverlay->AddTriangleOverlay(vBasePos + vRight * flBaseSize / 2, vBasePos - vRight * flBaseSize / 2, vBasePos + vForward * flHeight, 255, 0, 0, 255, false, 0.01); - - // Draw a blue triangle on the ground for the body yaw. - angles[YAW] = m_angRender[YAW]; - AngleVectors(angles, &vForward, &vRight, &vUp); - debugoverlay->AddTriangleOverlay(vBasePos + vRight * flBaseSize / 2, vBasePos - vRight * flBaseSize / 2, vBasePos + vForward * flHeight, 0, 0, 255, 255, false, 0.01); - -} - -// ----------------------------------------------------------------------------- -void CHL2MPPlayerAnimState::DebugShowAnimStateFull(int iStartLine) -{ - AnimStateLog("----------------- frame %d -----------------\n", gpGlobals->framecount); - - DebugShowAnimState(iStartLine); - - AnimStateLog("--------------------------------------------\n\n"); -} diff --git a/src/game/shared/hl2mp/hl2mp_playeranimstate.h b/src/game/shared/hl2mp/hl2mp_playeranimstate.h deleted file mode 100644 index 9a05125539..0000000000 --- a/src/game/shared/hl2mp/hl2mp_playeranimstate.h +++ /dev/null @@ -1,80 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -#ifndef HL2MP_PLAYERANIMSTATE_H -#define HL2MP_PLAYERANIMSTATE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "convar.h" -#include "multiplayer_animstate.h" - -#if defined( CLIENT_DLL ) -class C_HL2MP_Player; -#define CHL2MP_Player C_HL2MP_Player -#else -class CHL2MP_Player; -#endif - -// ------------------------------------------------------------------------------------------------ // -// CPlayerAnimState declaration. -// ------------------------------------------------------------------------------------------------ // -class CHL2MPPlayerAnimState : public CMultiPlayerAnimState -{ -public: - - DECLARE_CLASS( CHL2MPPlayerAnimState, CMultiPlayerAnimState ); - - CHL2MPPlayerAnimState(); - CHL2MPPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ); - ~CHL2MPPlayerAnimState(); - - void InitHL2MPAnimState( CHL2MP_Player *pPlayer ); - CHL2MP_Player *GetHL2MPPlayer( void ) { return m_pHL2MPPlayer; } - - virtual void ClearAnimationState(); - int CalcSequenceIndex(const char* pBaseName, ...); - virtual Activity TranslateActivity( Activity actDesired ); - virtual void Update( float eyeYaw, float eyePitch ); - - void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ); - - bool HandleMoving( Activity &idealActivity ); - bool HandleJumping( Activity &idealActivity ); - bool HandleDucking( Activity &idealActivity ); - bool HandleSwimming( Activity &idealActivity ); - - virtual float GetCurrentMaxGroundSpeed(); -#ifdef NEO - virtual void ComputeSequences(CStudioHdr* pStudioHdr); -#endif - - void DebugShowAnimStateFull(int iStartLine); - virtual void DebugShowAnimState(int iStartLine); - void AnimStatePrintf(int iLine, PRINTF_FORMAT_STRING const char* pMsg, ...); - void AnimStateLog(PRINTF_FORMAT_STRING const char* pMsg, ...); - -private: - - bool SetupPoseParameters( CStudioHdr *pStudioHdr ); - virtual void EstimateYaw( void ); - virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ); - -#ifdef NEO - bool IsLeaning(CStudioHdr *pStudioHdr); -#endif // NEO - - CHL2MP_Player *m_pHL2MPPlayer; -#ifndef NEO - bool m_bInAirWalk; - float m_flHoldDeployedPoseUntilTime; -#endif -}; - -CHL2MPPlayerAnimState *CreateHL2MPPlayerAnimState( CHL2MP_Player *pPlayer ); - - - -#endif // HL2MP_PLAYERANIMSTATE_H diff --git a/src/game/shared/neo/neo_playeranimstate.cpp b/src/game/shared/neo/neo_playeranimstate.cpp new file mode 100644 index 0000000000..7a16ca7139 --- /dev/null +++ b/src/game/shared/neo/neo_playeranimstate.cpp @@ -0,0 +1,453 @@ +#include "cbase.h" +#include "neo_playeranimstate.h" +#include "datacache/imdlcache.h" +#include "weapon_detpack.h" + +#ifdef CLIENT_DLL +#include "c_neo_player.h" +#else +#include "neo_player.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// Upper body sequence names, each followed by the weapon's animation suffix +static constexpr const char *AIM_IDLE_NAME = "idle_upper_"; +static constexpr const char *AIM_CROUCH_IDLE_NAME = "crouch_idle_upper_"; +static constexpr const char *AIM_CROUCH_WALK_NAME = "crouch_walk_upper_"; +static constexpr const char *AIM_WALK_NAME = "walk_upper_"; +static constexpr const char *AIM_RUN_NAME = "run_upper_"; + +static constexpr const char *FIRE_IDLE_NAME = "idle_shoot_"; +static constexpr const char *FIRE_CROUCH_NAME = "crouch_idle_shoot_"; +static constexpr const char *FIRE_CROUCH_WALK_NAME = "crouch_walk_shoot_"; +static constexpr const char *FIRE_WALK_NAME = "walk_shoot_"; +static constexpr const char *FIRE_RUN_NAME = "run_shoot_"; + +// The fire, reload and throw sequences play on the layer above the base's aim layers +static constexpr int GESTURE_LAYER = AIMSEQUENCE_LAYER + NUM_AIMSEQUENCE_LAYERS; +static constexpr int NUM_LAYERS = GESTURE_LAYER + 1; + +// The legs play at the rate of the player's speed over the speed the walk, run and crouch walk sequences cover, +// which is constant as in classic NEOTOKYO: two of the original models' forward walk and run animations carry no movement +static constexpr float ANIM_TOPSPEED_WALK = 100.0f; +static constexpr float ANIM_TOPSPEED_RUN = 250.0f; +static constexpr float ANIM_TOPSPEED_RUN_CROUCH = 85.0f; + +// A sprinting player plays the run legs only above this speed: neo's slowest sprint is 185, +// and bots sprint through turns at 100-180 +static constexpr float SPRINT_LEGS_MIN_SPEED = 100.0f; + +// The feet face the eyes when they are this close (degrees) +static constexpr float FEET_FACE_EYES_TOLERANCE = 1.0f; + +// Don't check if a jumping player is on the ground for this long: +// sometimes the client still has the on-ground flag set right when the jump event comes in +static constexpr float JUMP_MIN_TIME = 0.2f; + +// The remote of a thrown detpack fires the remote's sequence only this long after the detpack is ready to trigger +static constexpr float DET_REMOTE_FIRE_DELAY = 0.005f; + +#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 + +CNEOPlayerAnimState *CreateNEOPlayerAnimState( CHL2MP_Player *pPlayer ) +{ + MDLCACHE_CRITICAL_SECTION(); + return new CNEOPlayerAnimState( pPlayer ); +} + +CNEOPlayerAnimState::CNEOPlayerAnimState( CHL2MP_Player *pPlayer ) +{ + m_pPlayer = pPlayer; + m_bJumping = false; + m_bFirstJumpFrame = false; + m_flJumpStartTime = 0.0f; +#ifdef CLIENT_DLL + m_flJumpGroundFlagTime = 0.0f; +#endif + m_iGestureSequence = 0; + m_flGestureCycle = 0.0f; + + CModAnimConfig config; + config.m_flMaxBodyYawDegrees = NEO_ANIMSTATE_MAX_BODY_YAW_DEGREES; + config.m_LegAnimType = LEGANIM_9WAY; + config.m_bUseAimSequences = true; + Init( pPlayer, config ); +} + +void CNEOPlayerAnimState::ClearAnimationState() +{ + m_bJumping = false; + m_iGestureSequence = 0; + BaseClass::ClearAnimationState(); +} + +void CNEOPlayerAnimState::ClearAnimationLayers() +{ + if ( !m_pOuter ) + { + return; + } + + m_pOuter->SetNumAnimOverlays( NUM_LAYERS ); + for ( int i = 0; i < m_pOuter->GetNumAnimOverlays(); i++ ) + { + m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS ); +#ifndef CLIENT_DLL + m_pOuter->GetAnimOverlay( i )->m_fFlags = 0; +#endif + } +} + +void CNEOPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + switch ( event ) + { + case PLAYERANIMEVENT_ATTACK_PRIMARY: + StartGesture( CalcFireSequence() ); + break; + + case PLAYERANIMEVENT_RELOAD: + StartGesture( CalcReloadSequence() ); + break; + + case PLAYERANIMEVENT_JUMP: + m_bJumping = true; + m_bFirstJumpFrame = true; + m_flJumpStartTime = gpGlobals->curtime; + break; + + case PLAYERANIMEVENT_SPAWN: + ClearAnimationState(); + break; + + default: + break; + } +} + +void CNEOPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) +{ + BaseClass::ComputeSequences( pStudioHdr ); + ComputeGestureSequence( pStudioHdr ); +} + +void CNEOPlayerAnimState::StartGesture( int iSequence ) +{ + if ( iSequence <= 0 ) + { + return; + } + + m_iGestureSequence = iSequence; + m_flGestureCycle = 0.0f; + m_hGestureWeapon = m_pPlayer->GetActiveWeapon(); +} + +void CNEOPlayerAnimState::ComputeGestureSequence( CStudioHdr *pStudioHdr ) +{ + if ( m_iGestureSequence <= 0 ) + { + return; + } + + // a weapon switch ends the gesture of the previous weapon + if ( m_pPlayer->GetActiveWeapon() != m_hGestureWeapon.Get() ) + { + m_iGestureSequence = 0; + return; + } + + m_flGestureCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, m_iGestureSequence ) * gpGlobals->frametime; + if ( m_flGestureCycle >= 1.0f ) + { + m_iGestureSequence = 0; + return; + } + + CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( GESTURE_LAYER ); + pLayer->m_nSequence = m_iGestureSequence; + pLayer->m_flCycle = m_flGestureCycle; + pLayer->m_flPlaybackRate = 1.0f; + pLayer->m_flWeight = 1.0f; + pLayer->m_nOrder = GESTURE_LAYER; +#ifndef CLIENT_DLL + pLayer->m_fFlags |= ANIM_LAYER_ACTIVE; +#endif +} + +Activity CNEOPlayerAnimState::CalcMainActivity() +{ + if ( HandleJumping() ) + { + return ACT_HOP; + } + + if ( m_pPlayer->GetWaterLevel() >= WL_Waist ) + { + return ACT_SWIM; + } + + const float flSpeed = GetOuterXYSpeed(); + if ( m_pPlayer->GetFlags() & FL_DUCKING ) + { + return ( flSpeed > MOVING_MINIMUM_SPEED ) ? ACT_RUN_CROUCH : ACT_CROUCHIDLE; + } + + if ( flSpeed <= MOVING_MINIMUM_SPEED ) + { + return ACT_IDLE; + } + + return ( m_pPlayer->IsSprinting() && flSpeed > SPRINT_LEGS_MIN_SPEED ) ? ACT_RUN : ACT_WALK; +} + +bool CNEOPlayerAnimState::HandleJumping() +{ + if ( !m_bJumping ) + { + return false; + } + + if ( m_bFirstJumpFrame ) + { + m_bFirstJumpFrame = false; + RestartMainSequence(); +#ifdef CLIENT_DLL + m_flJumpGroundFlagTime = 0.0f; +#endif + } + + const bool bInWater = m_pPlayer->GetWaterLevel() >= WL_Waist; + if ( bInWater || ( gpGlobals->curtime - m_flJumpStartTime > JUMP_MIN_TIME && HasLandedFromJump() ) ) + { + m_bJumping = false; + RestartMainSequence(); + } + + return m_bJumping; +} + +//----------------------------------------------------------------------------- +// 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 CNEOPlayerAnimState::HasLandedFromJump() +{ + if ( !( m_pPlayer->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_pPlayer->GetAbsOrigin(); + trace_t tr; + UTIL_TraceHull( vecOrigin, vecOrigin - Vector( 0, 0, JUMP_LAND_GROUND_DIST ), + m_pPlayer->GetPlayerMins(), m_pPlayer->GetPlayerMaxs(), + MASK_PLAYERSOLID, m_pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); + + return tr.fraction < 1.0f || tr.startsolid; +#else + return true; +#endif // CLIENT_DLL +} + +float CNEOPlayerAnimState::GetCurrentMaxGroundSpeed() +{ + switch ( m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() ) ) + { + case ACT_IDLE: + case ACT_WALK: + return ANIM_TOPSPEED_WALK; + case ACT_RUN: + return ANIM_TOPSPEED_RUN; + case ACT_RUN_CROUCH: + return ANIM_TOPSPEED_RUN_CROUCH; + default: + return 0.0f; + } +} + +void CNEOPlayerAnimState::ComputePoseParam_BodyYaw() +{ + // a leaning player's feet turn to the eyes, as the base turns a new player's (no turn yet), + const bool bLeaning = IsLeaning(); + if ( bLeaning ) + { + m_flLastTurnTime = 0.0f; + } + + BaseClass::ComputePoseParam_BodyYaw(); + + // and the face-front time counts from the lean or the last frame the feet faced the eyes: + // the base counts from the feet's last turn, so after standing still it squared the feet up on the next turn at once + if ( bLeaning || fabsf( AngleDiff( m_flEyeYaw, m_flCurrentFeetYaw ) ) < FEET_FACE_EYES_TOLERANCE ) + { + m_flLastTurnTime = gpGlobals->curtime; + } +} + +bool CNEOPlayerAnimState::IsLeaning() const +{ + constexpr int LEAN_BONE_CONTROLLER = 0; + // the client reads the lean controller encoded 0-1 (0.5 is upright), the server reads it in degrees +#ifdef CLIENT_DLL + constexpr float BONE_CONTROLLER_VALUE_NOT_LEANING = 0.5f; +#else + constexpr float BONE_CONTROLLER_VALUE_NOT_LEANING = 0.0f; +#endif // CLIENT_DLL + return m_pPlayer->GetBoneController( LEAN_BONE_CONTROLLER ) != BONE_CONTROLLER_VALUE_NOT_LEANING; +} + +//----------------------------------------------------------------------------- +// Purpose: Whether a remote detpack shows its remote: triggered, or thrown and ready to trigger +//----------------------------------------------------------------------------- +static bool IsDetRemoteOut( CBaseCombatWeapon *pWeapon, float flReadyDelay ) +{ + auto pDetpack = static_cast( pWeapon ); + return pDetpack->m_bRemoteHasBeenTriggered || + ( pDetpack->m_bThisDetpackHasBeenThrown && gpGlobals->curtime > pDetpack->m_flNextPrimaryAttack + flReadyDelay ); +} + +static bool IsRemoteDet( CBaseCombatWeapon *pWeapon ) +{ + return !Q_strcmp( pWeapon->GetClassname(), "weapon_remotedet" ); +} + +//----------------------------------------------------------------------------- +// Purpose: The weapon's animation name suffix, with the substitutions for the classes that lack the weapon's animations +//----------------------------------------------------------------------------- +const char *CNEOPlayerAnimState::GetAimSuffix() const +{ + auto pWeapon = m_pPlayer->GetActiveWeapon(); + if ( !pWeapon ) + { + return nullptr; + } + + const int iClass = ToNEOPlayer( m_pPlayer )->m_iNeoClass; + if ( IsRemoteDet( pWeapon ) ) + { + // only recon has the detpack animations, the other classes hold it like a grenade + if ( iClass != NEO_CLASS_RECON ) + { + return "Grenade"; + } + + return IsDetRemoteOut( pWeapon, 0.0f ) ? "detremote" : "detpack"; + } + + const char *pSuffix = pWeapon->GetWpnData().szAnimationPrefix; + if ( iClass != NEO_CLASS_VIP && !Q_strcmp( pSuffix, "smac" ) ) + { + return "srm"; + } + + if ( iClass == NEO_CLASS_VIP && !Q_strcmp( pSuffix, "ZR68C" ) ) + { + return "m4"; + } + + return pSuffix; +} + +int CNEOPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) +{ + const char *pSuffix = GetAimSuffix(); + if ( !pSuffix ) + { + return 0; + } + + const Activity act = GetCurrentMainSequenceActivity(); + if ( bForceIdle ) + { + return CalcSequenceIndex( "%s%s", ( act == ACT_CROUCHIDLE ) ? AIM_CROUCH_IDLE_NAME : AIM_IDLE_NAME, pSuffix ); + } + + switch ( act ) + { + case ACT_RUN: + return CalcSequenceIndex( "%s%s", AIM_RUN_NAME, pSuffix ); + case ACT_WALK: + return CalcSequenceIndex( "%s%s", AIM_WALK_NAME, pSuffix ); + case ACT_CROUCHIDLE: + return CalcSequenceIndex( "%s%s", AIM_CROUCH_IDLE_NAME, pSuffix ); + case ACT_RUN_CROUCH: + return CalcSequenceIndex( "%s%s", AIM_CROUCH_WALK_NAME, pSuffix ); + default: + return CalcSequenceIndex( "%s%s", AIM_IDLE_NAME, pSuffix ); + } +} + +int CNEOPlayerAnimState::CalcFireSequence() +{ + const char *pSuffix = GetAimSuffix(); + if ( !pSuffix ) + { + return 0; + } + + auto pWeapon = m_pPlayer->GetActiveWeapon(); + if ( IsRemoteDet( pWeapon ) ) + { + // a class without the detpack animations throws it like a grenade and does not swing the remote + const bool bRemote = IsDetRemoteOut( pWeapon, DET_REMOTE_FIRE_DELAY ); + if ( ToNEOPlayer( m_pPlayer )->m_iNeoClass == NEO_CLASS_RECON ) + { + pSuffix = bRemote ? "detremote" : "detpack"; + } + else + { + pSuffix = bRemote ? "SRM" : "Gren1"; + } + } + else if ( !Q_strcmp( pSuffix, "Grenade" ) ) + { + pSuffix = "Gren1"; + } + + switch ( GetCurrentMainSequenceActivity() ) + { + case ACT_RUN: + return CalcSequenceIndex( "%s%s", FIRE_RUN_NAME, pSuffix ); + case ACT_WALK: + return CalcSequenceIndex( "%s%s", FIRE_WALK_NAME, pSuffix ); + case ACT_CROUCHIDLE: + return CalcSequenceIndex( "%s%s", FIRE_CROUCH_NAME, pSuffix ); + case ACT_RUN_CROUCH: + return CalcSequenceIndex( "%s%s", FIRE_CROUCH_WALK_NAME, pSuffix ); + default: + return CalcSequenceIndex( "%s%s", FIRE_IDLE_NAME, pSuffix ); + } +} + +int CNEOPlayerAnimState::CalcReloadSequence() +{ + auto pWeapon = m_pPlayer->GetActiveWeapon(); + if ( !pWeapon ) + { + return 0; + } + + return CalcSequenceIndex( "Reload_%s", pWeapon->GetWpnData().szAnimationPrefix ); +} diff --git a/src/game/shared/neo/neo_playeranimstate.h b/src/game/shared/neo/neo_playeranimstate.h new file mode 100644 index 0000000000..4c03be195d --- /dev/null +++ b/src/game/shared/neo/neo_playeranimstate.h @@ -0,0 +1,76 @@ +#ifndef NEO_PLAYERANIMSTATE_H +#define NEO_PLAYERANIMSTATE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "base_playeranimstate.h" + +#ifdef CLIENT_DLL +class C_HL2MP_Player; +#define CHL2MP_Player C_HL2MP_Player +#else +class CHL2MP_Player; +#endif + +enum PlayerAnimEvent_t +{ + PLAYERANIMEVENT_ATTACK_PRIMARY, + PLAYERANIMEVENT_RELOAD, + PLAYERANIMEVENT_JUMP, + PLAYERANIMEVENT_SPAWN, + + PLAYERANIMEVENT_COUNT +}; + +// The player animation of classic NEOTOKYO: the 2006 SDK base (9-way legs, upper body aim layers blended by speed) +// plus one gesture layer for firing, reloading and throwing. +class CNEOPlayerAnimState : public CBasePlayerAnimState +{ +public: + DECLARE_CLASS( CNEOPlayerAnimState, CBasePlayerAnimState ); + + CNEOPlayerAnimState( CHL2MP_Player *pPlayer ); + + void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ); + + virtual void ClearAnimationState() override; + virtual void ClearAnimationLayers() override; + virtual void ComputeSequences( CStudioHdr *pStudioHdr ) override; + virtual Activity CalcMainActivity() override; + virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) override; + virtual float GetCurrentMaxGroundSpeed() override; + +protected: + virtual void ComputePoseParam_BodyYaw() override; + +private: + const char *GetAimSuffix() const; + int CalcFireSequence(); + int CalcReloadSequence(); + void StartGesture( int iSequence ); + void ComputeGestureSequence( CStudioHdr *pStudioHdr ); + + bool HandleJumping(); + bool HasLandedFromJump(); + bool IsLeaning() const; + + CHL2MP_Player *m_pPlayer; + + // the jump pose plays from the jump event until the player lands + bool m_bJumping; + bool m_bFirstJumpFrame; + float m_flJumpStartTime; +#ifdef CLIENT_DLL + float m_flJumpGroundFlagTime; // when the client first saw the ground flag during a jump, 0 while in the air +#endif + + // fire, reload and throw sequences share one layer above the aim layers, and a new one restarts it + int m_iGestureSequence; + float m_flGestureCycle; + EHANDLE m_hGestureWeapon; +}; + +CNEOPlayerAnimState *CreateNEOPlayerAnimState( CHL2MP_Player *pPlayer ); + +#endif // NEO_PLAYERANIMSTATE_H From bcef3626a57b4ba98b90587f37019ed0abd4acc8 Mon Sep 17 00:00:00 2001 From: Alan Shen <1976941+sunzenshen@users.noreply.github.com> Date: Fri, 16 Oct 2026 00:57:23 -0600 Subject: [PATCH 2/3] No idea where 2006 SDK Base came from --- src/game/shared/neo/neo_playeranimstate.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/shared/neo/neo_playeranimstate.h b/src/game/shared/neo/neo_playeranimstate.h index 4c03be195d..f5b30acd69 100644 --- a/src/game/shared/neo/neo_playeranimstate.h +++ b/src/game/shared/neo/neo_playeranimstate.h @@ -23,8 +23,6 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_COUNT }; -// The player animation of classic NEOTOKYO: the 2006 SDK base (9-way legs, upper body aim layers blended by speed) -// plus one gesture layer for firing, reloading and throwing. class CNEOPlayerAnimState : public CBasePlayerAnimState { public: From 70d19d271b88846af6895c4197b2e4b676d12f27 Mon Sep 17 00:00:00 2001 From: Alan Shen Date: Sun, 25 Oct 2026 21:19:05 -0600 Subject: [PATCH 3/3] Address anim-sdk-base review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrap neo_playeranimstate.h includes in #ifdef NEO blocks in the HL2MP player headers, following review feedback. Remove HasLandedFromJump() — jump animation tampering is out of scope for this PR. The jump pose now ends when the player has been in the air at least JUMP_MIN_TIME and FL_ONGROUND is set. Also removes the JUMP_LAND_* constants and m_flJumpGroundFlagTime member that were only used by that function. --- src/game/client/hl2mp/c_hl2mp_player.h | 2 + src/game/server/hl2mp/hl2mp_player.h | 2 + src/game/shared/neo/neo_playeranimstate.cpp | 52 +-------------------- src/game/shared/neo/neo_playeranimstate.h | 4 -- 4 files changed, 5 insertions(+), 55 deletions(-) diff --git a/src/game/client/hl2mp/c_hl2mp_player.h b/src/game/client/hl2mp/c_hl2mp_player.h index 9e15e066dd..7e94bf2633 100644 --- a/src/game/client/hl2mp/c_hl2mp_player.h +++ b/src/game/client/hl2mp/c_hl2mp_player.h @@ -9,7 +9,9 @@ #define HL2MP_PLAYER_H #pragma once +#ifdef NEO #include "neo_playeranimstate.h" +#endif #include "c_basehlplayer.h" #include "hl2mp_player_shared.h" #include "beamdraw.h" diff --git a/src/game/server/hl2mp/hl2mp_player.h b/src/game/server/hl2mp/hl2mp_player.h index 463d9d2374..81e18d76d7 100644 --- a/src/game/server/hl2mp/hl2mp_player.h +++ b/src/game/server/hl2mp/hl2mp_player.h @@ -16,7 +16,9 @@ class CHL2MP_Player; #include "hl2_player.h" #include "simtimer.h" #include "soundenvelope.h" +#ifdef NEO #include "neo_playeranimstate.h" +#endif #include "hl2mp_player_shared.h" #include "hl2mp_gamerules.h" #include "utldict.h" diff --git a/src/game/shared/neo/neo_playeranimstate.cpp b/src/game/shared/neo/neo_playeranimstate.cpp index 7a16ca7139..9a8ebfe18a 100644 --- a/src/game/shared/neo/neo_playeranimstate.cpp +++ b/src/game/shared/neo/neo_playeranimstate.cpp @@ -49,13 +49,6 @@ static constexpr float JUMP_MIN_TIME = 0.2f; // The remote of a thrown detpack fires the remote's sequence only this long after the detpack is ready to trigger static constexpr float DET_REMOTE_FIRE_DELAY = 0.005f; -#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 - CNEOPlayerAnimState *CreateNEOPlayerAnimState( CHL2MP_Player *pPlayer ) { MDLCACHE_CRITICAL_SECTION(); @@ -68,9 +61,6 @@ CNEOPlayerAnimState::CNEOPlayerAnimState( CHL2MP_Player *pPlayer ) m_bJumping = false; m_bFirstJumpFrame = false; m_flJumpStartTime = 0.0f; -#ifdef CLIENT_DLL - m_flJumpGroundFlagTime = 0.0f; -#endif m_iGestureSequence = 0; m_flGestureCycle = 0.0f; @@ -219,13 +209,10 @@ bool CNEOPlayerAnimState::HandleJumping() { m_bFirstJumpFrame = false; RestartMainSequence(); -#ifdef CLIENT_DLL - m_flJumpGroundFlagTime = 0.0f; -#endif } const bool bInWater = m_pPlayer->GetWaterLevel() >= WL_Waist; - if ( bInWater || ( gpGlobals->curtime - m_flJumpStartTime > JUMP_MIN_TIME && HasLandedFromJump() ) ) + if ( bInWater || ( gpGlobals->curtime - m_flJumpStartTime > JUMP_MIN_TIME && (m_pPlayer->GetFlags() & FL_ONGROUND) ) ) { m_bJumping = false; RestartMainSequence(); @@ -234,43 +221,6 @@ bool CNEOPlayerAnimState::HandleJumping() return m_bJumping; } -//----------------------------------------------------------------------------- -// 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 CNEOPlayerAnimState::HasLandedFromJump() -{ - if ( !( m_pPlayer->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_pPlayer->GetAbsOrigin(); - trace_t tr; - UTIL_TraceHull( vecOrigin, vecOrigin - Vector( 0, 0, JUMP_LAND_GROUND_DIST ), - m_pPlayer->GetPlayerMins(), m_pPlayer->GetPlayerMaxs(), - MASK_PLAYERSOLID, m_pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - - return tr.fraction < 1.0f || tr.startsolid; -#else - return true; -#endif // CLIENT_DLL -} - float CNEOPlayerAnimState::GetCurrentMaxGroundSpeed() { switch ( m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() ) ) diff --git a/src/game/shared/neo/neo_playeranimstate.h b/src/game/shared/neo/neo_playeranimstate.h index f5b30acd69..dc39974155 100644 --- a/src/game/shared/neo/neo_playeranimstate.h +++ b/src/game/shared/neo/neo_playeranimstate.h @@ -50,7 +50,6 @@ class CNEOPlayerAnimState : public CBasePlayerAnimState void ComputeGestureSequence( CStudioHdr *pStudioHdr ); bool HandleJumping(); - bool HasLandedFromJump(); bool IsLeaning() const; CHL2MP_Player *m_pPlayer; @@ -59,9 +58,6 @@ class CNEOPlayerAnimState : public CBasePlayerAnimState bool m_bJumping; bool m_bFirstJumpFrame; float m_flJumpStartTime; -#ifdef CLIENT_DLL - float m_flJumpGroundFlagTime; // when the client first saw the ground flag during a jump, 0 while in the air -#endif // fire, reload and throw sequences share one layer above the aim layers, and a new one restarts it int m_iGestureSequence;