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..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 -#include "hl2mp_playeranimstate.h" +#ifdef NEO +#include "neo_playeranimstate.h" +#endif #include "c_basehlplayer.h" #include "hl2mp_player_shared.h" #include "beamdraw.h" @@ -145,7 +147,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..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" -#include "hl2mp_playeranimstate.h" +#ifdef NEO +#include "neo_playeranimstate.h" +#endif #include "hl2mp_player_shared.h" #include "hl2mp_gamerules.h" #include "utldict.h" @@ -177,7 +179,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..9a8ebfe18a --- /dev/null +++ b/src/game/shared/neo/neo_playeranimstate.cpp @@ -0,0 +1,403 @@ +#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; + +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; + 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(); + } + + const bool bInWater = m_pPlayer->GetWaterLevel() >= WL_Waist; + if ( bInWater || ( gpGlobals->curtime - m_flJumpStartTime > JUMP_MIN_TIME && (m_pPlayer->GetFlags() & FL_ONGROUND) ) ) + { + m_bJumping = false; + RestartMainSequence(); + } + + return m_bJumping; +} + +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..dc39974155 --- /dev/null +++ b/src/game/shared/neo/neo_playeranimstate.h @@ -0,0 +1,70 @@ +#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 +}; + +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 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; + + // 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