diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/sdk/sdk_playeranimstate.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/shared/sdk/sdk_playeranimstate.cpp')
| -rw-r--r-- | mp/src/game/shared/sdk/sdk_playeranimstate.cpp | 1242 |
1 files changed, 621 insertions, 621 deletions
diff --git a/mp/src/game/shared/sdk/sdk_playeranimstate.cpp b/mp/src/game/shared/sdk/sdk_playeranimstate.cpp index 950c73ce..6effe3e4 100644 --- a/mp/src/game/shared/sdk/sdk_playeranimstate.cpp +++ b/mp/src/game/shared/sdk/sdk_playeranimstate.cpp @@ -1,621 +1,621 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "base_playeranimstate.h"
-#include "tier0/vprof.h"
-#include "animation.h"
-#include "studio.h"
-#include "apparent_velocity_helper.h"
-#include "utldict.h"
-
-#include "sdk_playeranimstate.h"
-#include "weapon_sdkbase.h"
-#include "weapon_basesdkgrenade.h"
-
-#ifdef CLIENT_DLL
- #include "c_sdk_player.h"
- #include "bone_setup.h"
- #include "interpolatedvar.h"
-#else
- #include "sdk_player.h"
-#endif
-
-#define ANIM_TOPSPEED_WALK 100
-#define ANIM_TOPSPEED_RUN 250
-#define ANIM_TOPSPEED_RUN_CROUCH 85
-
-#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_"
-
-
-#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS)
-#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
-#define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1)
-#define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1)
-
-
-
-// ------------------------------------------------------------------------------------------------ //
-// CSDKPlayerAnimState declaration.
-// ------------------------------------------------------------------------------------------------ //
-
-class CSDKPlayerAnimState : public CBasePlayerAnimState, public ISDKPlayerAnimState
-{
-public:
- DECLARE_CLASS( CSDKPlayerAnimState, CBasePlayerAnimState );
- friend ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
-
- CSDKPlayerAnimState();
-
- virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData );
- virtual bool IsThrowingGrenade();
- virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
- virtual void ClearAnimationState();
- virtual bool CanThePlayerMove();
- virtual float GetCurrentMaxGroundSpeed();
- virtual Activity CalcMainActivity();
- virtual void DebugShowAnimState( int iStartLine );
- virtual void ComputeSequences( CStudioHdr *pStudioHdr );
- virtual void ClearAnimationLayers();
-
-
- void InitSDK( CBaseAnimatingOverlay *pPlayer, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
-
-protected:
-
- int CalcFireLayerSequence(PlayerAnimEvent_t event);
- void ComputeFireSequence(CStudioHdr *pStudioHdr);
-
- void ComputeReloadSequence(CStudioHdr *pStudioHdr);
- int CalcReloadLayerSequence();
-
- bool IsOuterGrenadePrimed();
- void ComputeGrenadeSequence( CStudioHdr *pStudioHdr );
- int CalcGrenadePrimeSequence();
- int CalcGrenadeThrowSequence();
- int GetOuterGrenadeThrowCounter();
-
- const char* GetWeaponSuffix();
- bool HandleJumping();
-
- void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd );
-
-private:
-
- // Current state variables.
- bool m_bJumping; // Set on a jump event.
- float m_flJumpStartTime;
- bool m_bFirstJumpFrame;
-
- // Aim sequence plays reload while this is on.
- bool m_bReloading;
- float m_flReloadCycle;
- int m_iReloadSequence;
-
- // This is set to true if ANY animation is being played in the fire layer.
- bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
- // until it completes.
- int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
- float m_flFireCycle;
-
- // These control grenade animations.
- bool m_bThrowingGrenade;
- bool m_bPrimingGrenade;
- float m_flGrenadeCycle;
- int m_iGrenadeSequence;
- int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade.
-
- ISDKPlayerAnimStateHelpers *m_pHelpers;
-};
-
-
-ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
-{
- CSDKPlayerAnimState *pRet = new CSDKPlayerAnimState;
- pRet->InitSDK( pEntity, pHelpers, legAnimType, bUseAimSequences );
- return pRet;
-}
-
-// ------------------------------------------------------------------------------------------------ //
-// CSDKPlayerAnimState implementation.
-// ------------------------------------------------------------------------------------------------ //
-
-CSDKPlayerAnimState::CSDKPlayerAnimState()
-{
- m_pOuter = NULL;
- m_bReloading = false;
-}
-
-
-void CSDKPlayerAnimState::InitSDK( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
-{
- CModAnimConfig config;
- config.m_flMaxBodyYawDegrees = 90;
- config.m_LegAnimType = legAnimType;
- config.m_bUseAimSequences = bUseAimSequences;
-
- m_pHelpers = pHelpers;
-
- BaseClass::Init( pEntity, config );
-}
-
-
-void CSDKPlayerAnimState::ClearAnimationState()
-{
- m_bJumping = false;
- m_bFiring = false;
- m_bReloading = false;
- m_bThrowingGrenade = m_bPrimingGrenade = false;
- m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
-
- BaseClass::ClearAnimationState();
-}
-
-
-void CSDKPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
-{
- Assert( event != PLAYERANIMEVENT_THROW_GRENADE );
-
- if ( event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY ||
- event == PLAYERANIMEVENT_FIRE_GUN_SECONDARY )
- {
- // Regardless of what we're doing in the fire layer, restart it.
- m_flFireCycle = 0;
- m_iFireSequence = CalcFireLayerSequence( event );
- m_bFiring = m_iFireSequence != -1;
- }
- else if ( event == PLAYERANIMEVENT_JUMP )
- {
- // Play the jump animation.
- m_bJumping = true;
- m_bFirstJumpFrame = true;
- m_flJumpStartTime = gpGlobals->curtime;
- }
- else if ( event == PLAYERANIMEVENT_RELOAD )
- {
- m_iReloadSequence = CalcReloadLayerSequence();
- if ( m_iReloadSequence != -1 )
- {
- m_bReloading = true;
- m_flReloadCycle = 0;
- }
- }
- else
- {
- Assert( !"CSDKPlayerAnimState::DoAnimationEvent" );
- }
-}
-
-
-float g_flThrowGrenadeFraction = 0.25;
-bool CSDKPlayerAnimState::IsThrowingGrenade()
-{
- if ( m_bThrowingGrenade )
- {
- // An animation event would be more appropriate here.
- return m_flGrenadeCycle < g_flThrowGrenadeFraction;
- }
- else
- {
- bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
- return bThrowPending || IsOuterGrenadePrimed();
- }
-}
-
-
-int CSDKPlayerAnimState::CalcReloadLayerSequence()
-{
- const char *pSuffix = GetWeaponSuffix();
- if ( !pSuffix )
- return -1;
-
- CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
- if ( !pWeapon )
- return -1;
-
- // First, look for reload_<weapon name>.
- char szName[512];
- Q_snprintf( szName, sizeof( szName ), "reload_%s", pSuffix );
- int iReloadSequence = m_pOuter->LookupSequence( szName );
- if ( iReloadSequence != -1 )
- return iReloadSequence;
-
- //SDKTODO
-/*
- // Ok, look for generic categories.. pistol, shotgun, rifle, etc.
- if ( pWeapon->GetSDKWpnData().m_WeaponType == WEAPONTYPE_PISTOL )
- {
- Q_snprintf( szName, sizeof( szName ), "reload_pistol" );
- iReloadSequence = m_pOuter->LookupSequence( szName );
- if ( iReloadSequence != -1 )
- return iReloadSequence;
- }
- */
-
- // Fall back to reload_m4.
- iReloadSequence = CalcSequenceIndex( "reload_m4" );
- if ( iReloadSequence > 0 )
- return iReloadSequence;
-
- return -1;
-}
-
-
-#ifdef CLIENT_DLL
- void CSDKPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd )
- {
- if ( !bEnabled )
- return;
-
- // Increment the fire sequence's cycle.
- flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime;
- if ( flCurCycle > 1 )
- {
- if ( bWaitAtEnd )
- {
- flCurCycle = 1;
- }
- else
- {
- // Not firing anymore.
- bEnabled = false;
- iSequence = 0;
- return;
- }
- }
-
- // Now dump the state into its animation layer.
- C_AnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
-
- pLayer->m_flCycle = flCurCycle;
- pLayer->m_nSequence = iSequence;
-
- pLayer->m_flPlaybackRate = 1.0;
- pLayer->m_flWeight = 1.0f;
- pLayer->m_nOrder = iLayer;
- }
-#endif
-
-
-
-bool CSDKPlayerAnimState::IsOuterGrenadePrimed()
-{
- CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer();
- if ( pChar )
- {
- CBaseSDKGrenade *pGren = dynamic_cast<CBaseSDKGrenade*>( pChar->GetActiveWeapon() );
- return pGren && pGren->IsPinPulled();
- }
- else
- {
- return NULL;
- }
-}
-
-
-void CSDKPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr )
-{
-#ifdef CLIENT_DLL
- if ( m_bThrowingGrenade )
- {
- UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false );
- }
- else
- {
- // Priming the grenade isn't an event.. we just watch the player for it.
- // Also play the prime animation first if he wants to throw the grenade.
- bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
- if ( IsOuterGrenadePrimed() || bThrowPending )
- {
- if ( !m_bPrimingGrenade )
- {
- // If this guy just popped into our PVS, and he's got his grenade primed, then
- // let's assume that it's all the way primed rather than playing the prime
- // animation from the start.
- if ( TimeSinceLastAnimationStateClear() < 0.4f )
- m_flGrenadeCycle = 1;
- else
- m_flGrenadeCycle = 0;
-
- m_iGrenadeSequence = CalcGrenadePrimeSequence();
- }
-
- m_bPrimingGrenade = true;
- UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true );
-
- // If we're waiting to throw and we're done playing the prime animation...
- if ( bThrowPending && m_flGrenadeCycle == 1 )
- {
- m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
-
- // Now play the throw animation.
- m_iGrenadeSequence = CalcGrenadeThrowSequence();
- if ( m_iGrenadeSequence != -1 )
- {
- // Configure to start playing
- m_bThrowingGrenade = true;
- m_bPrimingGrenade = false;
- m_flGrenadeCycle = 0;
- }
- }
- }
- else
- {
- m_bPrimingGrenade = false;
- }
- }
-#endif
-}
-
-
-int CSDKPlayerAnimState::CalcGrenadePrimeSequence()
-{
- return CalcSequenceIndex( "idle_shoot_gren1" );
-}
-
-
-int CSDKPlayerAnimState::CalcGrenadeThrowSequence()
-{
- return CalcSequenceIndex( "idle_shoot_gren2" );
-}
-
-
-int CSDKPlayerAnimState::GetOuterGrenadeThrowCounter()
-{
- CSDKPlayer *pPlayer = dynamic_cast<CSDKPlayer*>( m_pOuter );
- if ( pPlayer )
- return pPlayer->m_iThrowGrenadeCounter;
- else
- return 0;
-}
-
-
-void CSDKPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr )
-{
-#ifdef CLIENT_DLL
- UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false );
-#else
- // Server doesn't bother with different fire sequences.
-#endif
-}
-
-
-int CSDKPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
-{
- const char *pSuffix = GetWeaponSuffix();
- if ( !pSuffix )
- return 0;
-
- if ( bForceIdle )
- {
- switch ( GetCurrentMainSequenceActivity() )
- {
- case ACT_CROUCHIDLE:
- return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
-
- default:
- return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
- }
- }
- else
- {
- switch ( GetCurrentMainSequenceActivity() )
- {
- case ACT_RUN:
- return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix );
-
- case ACT_WALK:
- case ACT_RUNTOIDLE:
- case ACT_IDLETORUN:
- return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix );
-
- case ACT_CROUCHIDLE:
- return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
-
- case ACT_RUN_CROUCH:
- return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix );
-
- case ACT_IDLE:
- default:
- return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
- }
- }
-}
-
-
-const char* CSDKPlayerAnimState::GetWeaponSuffix()
-{
- // Figure out the weapon suffix.
- CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
- if ( !pWeapon )
- return "Pistol";
-
- const char *pSuffix = pWeapon->GetSDKWpnData().m_szAnimExtension;
-
- return pSuffix;
-}
-
-
-int CSDKPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t event)
-{
- // Figure out the weapon suffix.
- CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
- if ( !pWeapon )
- return 0;
-
- const char *pSuffix = GetWeaponSuffix();
- if ( !pSuffix )
- return 0;
-
- // Don't rely on their weapon here because the player has usually switched to their
- // pistol or rifle by the time the PLAYERANIMEVENT_THROW_GRENADE message gets to the client.
- if ( event == PLAYERANIMEVENT_THROW_GRENADE )
- {
- pSuffix = "Gren";
- }
-
- switch ( GetCurrentMainSequenceActivity() )
- {
- case ACT_PLAYER_RUN_FIRE:
- case ACT_RUN:
- return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix );
-
- case ACT_PLAYER_WALK_FIRE:
- case ACT_WALK:
- return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix );
-
- case ACT_PLAYER_CROUCH_FIRE:
- case ACT_CROUCHIDLE:
- return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix );
-
- case ACT_PLAYER_CROUCH_WALK_FIRE:
- case ACT_RUN_CROUCH:
- return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix );
-
- default:
- case ACT_PLAYER_IDLE_FIRE:
- return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix );
- }
-}
-
-
-bool CSDKPlayerAnimState::CanThePlayerMove()
-{
- return m_pHelpers->SDKAnim_CanMove();
-}
-
-
-float CSDKPlayerAnimState::GetCurrentMaxGroundSpeed()
-{
- Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() );
- if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE )
- return ANIM_TOPSPEED_WALK;
- else if ( currentActivity == ACT_RUN )
- return ANIM_TOPSPEED_RUN;
- else if ( currentActivity == ACT_RUN_CROUCH )
- return ANIM_TOPSPEED_RUN_CROUCH;
- else
- return 0;
-}
-
-
-bool CSDKPlayerAnimState::HandleJumping()
-{
- if ( m_bJumping )
- {
- if ( m_bFirstJumpFrame )
- {
- m_bFirstJumpFrame = false;
- RestartMainSequence(); // Reset the animation.
- }
-
- // 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.
- if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
- {
- if ( m_pOuter->GetFlags() & FL_ONGROUND )
- {
- m_bJumping = false;
- RestartMainSequence(); // Reset the animation.
- }
- }
- }
-
- // Are we still jumping? If so, keep playing the jump animation.
- return m_bJumping;
-}
-
-
-Activity CSDKPlayerAnimState::CalcMainActivity()
-{
- float flOuterSpeed = GetOuterXYSpeed();
-
- if ( HandleJumping() )
- {
- return ACT_HOP;
- }
- else
- {
- Activity idealActivity = ACT_IDLE;
-
- if ( m_pOuter->GetFlags() & FL_DUCKING )
- {
- if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
- idealActivity = ACT_RUN_CROUCH;
- else
- idealActivity = ACT_CROUCHIDLE;
- }
- else
- {
- if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
- {
- if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
- idealActivity = ACT_RUN;
- else
- idealActivity = ACT_WALK;
- }
- else
- {
- idealActivity = ACT_IDLE;
- }
- }
-
- return idealActivity;
- }
-}
-
-
-void CSDKPlayerAnimState::DebugShowAnimState( int iStartLine )
-{
-#ifdef CLIENT_DLL
- engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle );
- engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle );
- BaseClass::DebugShowAnimState( iStartLine );
-#endif
-}
-
-
-void CSDKPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
-{
- BaseClass::ComputeSequences( pStudioHdr );
-
- ComputeFireSequence( pStudioHdr );
- ComputeReloadSequence( pStudioHdr );
- ComputeGrenadeSequence( pStudioHdr );
-}
-
-
-void CSDKPlayerAnimState::ClearAnimationLayers()
-{
- if ( !m_pOuter )
- return;
-
- m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
- for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
- {
- m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
- }
-}
-
-
-void CSDKPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr )
-{
-#ifdef CLIENT_DLL
- UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
-#else
- // Server doesn't bother with different fire sequences.
-#endif
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "base_playeranimstate.h" +#include "tier0/vprof.h" +#include "animation.h" +#include "studio.h" +#include "apparent_velocity_helper.h" +#include "utldict.h" + +#include "sdk_playeranimstate.h" +#include "weapon_sdkbase.h" +#include "weapon_basesdkgrenade.h" + +#ifdef CLIENT_DLL + #include "c_sdk_player.h" + #include "bone_setup.h" + #include "interpolatedvar.h" +#else + #include "sdk_player.h" +#endif + +#define ANIM_TOPSPEED_WALK 100 +#define ANIM_TOPSPEED_RUN 250 +#define ANIM_TOPSPEED_RUN_CROUCH 85 + +#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_" + + +#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS) +#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1) +#define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1) +#define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1) + + + +// ------------------------------------------------------------------------------------------------ // +// CSDKPlayerAnimState declaration. +// ------------------------------------------------------------------------------------------------ // + +class CSDKPlayerAnimState : public CBasePlayerAnimState, public ISDKPlayerAnimState +{ +public: + DECLARE_CLASS( CSDKPlayerAnimState, CBasePlayerAnimState ); + friend ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ); + + CSDKPlayerAnimState(); + + virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData ); + virtual bool IsThrowingGrenade(); + virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ); + virtual void ClearAnimationState(); + virtual bool CanThePlayerMove(); + virtual float GetCurrentMaxGroundSpeed(); + virtual Activity CalcMainActivity(); + virtual void DebugShowAnimState( int iStartLine ); + virtual void ComputeSequences( CStudioHdr *pStudioHdr ); + virtual void ClearAnimationLayers(); + + + void InitSDK( CBaseAnimatingOverlay *pPlayer, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ); + +protected: + + int CalcFireLayerSequence(PlayerAnimEvent_t event); + void ComputeFireSequence(CStudioHdr *pStudioHdr); + + void ComputeReloadSequence(CStudioHdr *pStudioHdr); + int CalcReloadLayerSequence(); + + bool IsOuterGrenadePrimed(); + void ComputeGrenadeSequence( CStudioHdr *pStudioHdr ); + int CalcGrenadePrimeSequence(); + int CalcGrenadeThrowSequence(); + int GetOuterGrenadeThrowCounter(); + + const char* GetWeaponSuffix(); + bool HandleJumping(); + + void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd ); + +private: + + // Current state variables. + bool m_bJumping; // Set on a jump event. + float m_flJumpStartTime; + bool m_bFirstJumpFrame; + + // Aim sequence plays reload while this is on. + bool m_bReloading; + float m_flReloadCycle; + int m_iReloadSequence; + + // This is set to true if ANY animation is being played in the fire layer. + bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer + // until it completes. + int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw). + float m_flFireCycle; + + // These control grenade animations. + bool m_bThrowingGrenade; + bool m_bPrimingGrenade; + float m_flGrenadeCycle; + int m_iGrenadeSequence; + int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade. + + ISDKPlayerAnimStateHelpers *m_pHelpers; +}; + + +ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ) +{ + CSDKPlayerAnimState *pRet = new CSDKPlayerAnimState; + pRet->InitSDK( pEntity, pHelpers, legAnimType, bUseAimSequences ); + return pRet; +} + +// ------------------------------------------------------------------------------------------------ // +// CSDKPlayerAnimState implementation. +// ------------------------------------------------------------------------------------------------ // + +CSDKPlayerAnimState::CSDKPlayerAnimState() +{ + m_pOuter = NULL; + m_bReloading = false; +} + + +void CSDKPlayerAnimState::InitSDK( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ) +{ + CModAnimConfig config; + config.m_flMaxBodyYawDegrees = 90; + config.m_LegAnimType = legAnimType; + config.m_bUseAimSequences = bUseAimSequences; + + m_pHelpers = pHelpers; + + BaseClass::Init( pEntity, config ); +} + + +void CSDKPlayerAnimState::ClearAnimationState() +{ + m_bJumping = false; + m_bFiring = false; + m_bReloading = false; + m_bThrowingGrenade = m_bPrimingGrenade = false; + m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter(); + + BaseClass::ClearAnimationState(); +} + + +void CSDKPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + Assert( event != PLAYERANIMEVENT_THROW_GRENADE ); + + if ( event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY || + event == PLAYERANIMEVENT_FIRE_GUN_SECONDARY ) + { + // Regardless of what we're doing in the fire layer, restart it. + m_flFireCycle = 0; + m_iFireSequence = CalcFireLayerSequence( event ); + m_bFiring = m_iFireSequence != -1; + } + else if ( event == PLAYERANIMEVENT_JUMP ) + { + // Play the jump animation. + m_bJumping = true; + m_bFirstJumpFrame = true; + m_flJumpStartTime = gpGlobals->curtime; + } + else if ( event == PLAYERANIMEVENT_RELOAD ) + { + m_iReloadSequence = CalcReloadLayerSequence(); + if ( m_iReloadSequence != -1 ) + { + m_bReloading = true; + m_flReloadCycle = 0; + } + } + else + { + Assert( !"CSDKPlayerAnimState::DoAnimationEvent" ); + } +} + + +float g_flThrowGrenadeFraction = 0.25; +bool CSDKPlayerAnimState::IsThrowingGrenade() +{ + if ( m_bThrowingGrenade ) + { + // An animation event would be more appropriate here. + return m_flGrenadeCycle < g_flThrowGrenadeFraction; + } + else + { + bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter()); + return bThrowPending || IsOuterGrenadePrimed(); + } +} + + +int CSDKPlayerAnimState::CalcReloadLayerSequence() +{ + const char *pSuffix = GetWeaponSuffix(); + if ( !pSuffix ) + return -1; + + CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon(); + if ( !pWeapon ) + return -1; + + // First, look for reload_<weapon name>. + char szName[512]; + Q_snprintf( szName, sizeof( szName ), "reload_%s", pSuffix ); + int iReloadSequence = m_pOuter->LookupSequence( szName ); + if ( iReloadSequence != -1 ) + return iReloadSequence; + + //SDKTODO +/* + // Ok, look for generic categories.. pistol, shotgun, rifle, etc. + if ( pWeapon->GetSDKWpnData().m_WeaponType == WEAPONTYPE_PISTOL ) + { + Q_snprintf( szName, sizeof( szName ), "reload_pistol" ); + iReloadSequence = m_pOuter->LookupSequence( szName ); + if ( iReloadSequence != -1 ) + return iReloadSequence; + } + */ + + // Fall back to reload_m4. + iReloadSequence = CalcSequenceIndex( "reload_m4" ); + if ( iReloadSequence > 0 ) + return iReloadSequence; + + return -1; +} + + +#ifdef CLIENT_DLL + void CSDKPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd ) + { + if ( !bEnabled ) + return; + + // Increment the fire sequence's cycle. + flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime; + if ( flCurCycle > 1 ) + { + if ( bWaitAtEnd ) + { + flCurCycle = 1; + } + else + { + // Not firing anymore. + bEnabled = false; + iSequence = 0; + return; + } + } + + // Now dump the state into its animation layer. + C_AnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer ); + + pLayer->m_flCycle = flCurCycle; + pLayer->m_nSequence = iSequence; + + pLayer->m_flPlaybackRate = 1.0; + pLayer->m_flWeight = 1.0f; + pLayer->m_nOrder = iLayer; + } +#endif + + + +bool CSDKPlayerAnimState::IsOuterGrenadePrimed() +{ + CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer(); + if ( pChar ) + { + CBaseSDKGrenade *pGren = dynamic_cast<CBaseSDKGrenade*>( pChar->GetActiveWeapon() ); + return pGren && pGren->IsPinPulled(); + } + else + { + return NULL; + } +} + + +void CSDKPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr ) +{ +#ifdef CLIENT_DLL + if ( m_bThrowingGrenade ) + { + UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false ); + } + else + { + // Priming the grenade isn't an event.. we just watch the player for it. + // Also play the prime animation first if he wants to throw the grenade. + bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter()); + if ( IsOuterGrenadePrimed() || bThrowPending ) + { + if ( !m_bPrimingGrenade ) + { + // If this guy just popped into our PVS, and he's got his grenade primed, then + // let's assume that it's all the way primed rather than playing the prime + // animation from the start. + if ( TimeSinceLastAnimationStateClear() < 0.4f ) + m_flGrenadeCycle = 1; + else + m_flGrenadeCycle = 0; + + m_iGrenadeSequence = CalcGrenadePrimeSequence(); + } + + m_bPrimingGrenade = true; + UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true ); + + // If we're waiting to throw and we're done playing the prime animation... + if ( bThrowPending && m_flGrenadeCycle == 1 ) + { + m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter(); + + // Now play the throw animation. + m_iGrenadeSequence = CalcGrenadeThrowSequence(); + if ( m_iGrenadeSequence != -1 ) + { + // Configure to start playing + m_bThrowingGrenade = true; + m_bPrimingGrenade = false; + m_flGrenadeCycle = 0; + } + } + } + else + { + m_bPrimingGrenade = false; + } + } +#endif +} + + +int CSDKPlayerAnimState::CalcGrenadePrimeSequence() +{ + return CalcSequenceIndex( "idle_shoot_gren1" ); +} + + +int CSDKPlayerAnimState::CalcGrenadeThrowSequence() +{ + return CalcSequenceIndex( "idle_shoot_gren2" ); +} + + +int CSDKPlayerAnimState::GetOuterGrenadeThrowCounter() +{ + CSDKPlayer *pPlayer = dynamic_cast<CSDKPlayer*>( m_pOuter ); + if ( pPlayer ) + return pPlayer->m_iThrowGrenadeCounter; + else + return 0; +} + + +void CSDKPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr ) +{ +#ifdef CLIENT_DLL + UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false ); +#else + // Server doesn't bother with different fire sequences. +#endif +} + + +int CSDKPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) +{ + const char *pSuffix = GetWeaponSuffix(); + if ( !pSuffix ) + return 0; + + if ( bForceIdle ) + { + switch ( GetCurrentMainSequenceActivity() ) + { + case ACT_CROUCHIDLE: + return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix ); + + default: + return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix ); + } + } + else + { + switch ( GetCurrentMainSequenceActivity() ) + { + case ACT_RUN: + return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix ); + + case ACT_WALK: + case ACT_RUNTOIDLE: + case ACT_IDLETORUN: + return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix ); + + case ACT_CROUCHIDLE: + return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix ); + + case ACT_RUN_CROUCH: + return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix ); + + case ACT_IDLE: + default: + return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix ); + } + } +} + + +const char* CSDKPlayerAnimState::GetWeaponSuffix() +{ + // Figure out the weapon suffix. + CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon(); + if ( !pWeapon ) + return "Pistol"; + + const char *pSuffix = pWeapon->GetSDKWpnData().m_szAnimExtension; + + return pSuffix; +} + + +int CSDKPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t event) +{ + // Figure out the weapon suffix. + CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon(); + if ( !pWeapon ) + return 0; + + const char *pSuffix = GetWeaponSuffix(); + if ( !pSuffix ) + return 0; + + // Don't rely on their weapon here because the player has usually switched to their + // pistol or rifle by the time the PLAYERANIMEVENT_THROW_GRENADE message gets to the client. + if ( event == PLAYERANIMEVENT_THROW_GRENADE ) + { + pSuffix = "Gren"; + } + + switch ( GetCurrentMainSequenceActivity() ) + { + case ACT_PLAYER_RUN_FIRE: + case ACT_RUN: + return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix ); + + case ACT_PLAYER_WALK_FIRE: + case ACT_WALK: + return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix ); + + case ACT_PLAYER_CROUCH_FIRE: + case ACT_CROUCHIDLE: + return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix ); + + case ACT_PLAYER_CROUCH_WALK_FIRE: + case ACT_RUN_CROUCH: + return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix ); + + default: + case ACT_PLAYER_IDLE_FIRE: + return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix ); + } +} + + +bool CSDKPlayerAnimState::CanThePlayerMove() +{ + return m_pHelpers->SDKAnim_CanMove(); +} + + +float CSDKPlayerAnimState::GetCurrentMaxGroundSpeed() +{ + Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() ); + if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE ) + return ANIM_TOPSPEED_WALK; + else if ( currentActivity == ACT_RUN ) + return ANIM_TOPSPEED_RUN; + else if ( currentActivity == ACT_RUN_CROUCH ) + return ANIM_TOPSPEED_RUN_CROUCH; + else + return 0; +} + + +bool CSDKPlayerAnimState::HandleJumping() +{ + if ( m_bJumping ) + { + if ( m_bFirstJumpFrame ) + { + m_bFirstJumpFrame = false; + RestartMainSequence(); // Reset the animation. + } + + // 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. + if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f ) + { + if ( m_pOuter->GetFlags() & FL_ONGROUND ) + { + m_bJumping = false; + RestartMainSequence(); // Reset the animation. + } + } + } + + // Are we still jumping? If so, keep playing the jump animation. + return m_bJumping; +} + + +Activity CSDKPlayerAnimState::CalcMainActivity() +{ + float flOuterSpeed = GetOuterXYSpeed(); + + if ( HandleJumping() ) + { + return ACT_HOP; + } + else + { + Activity idealActivity = ACT_IDLE; + + if ( m_pOuter->GetFlags() & FL_DUCKING ) + { + if ( flOuterSpeed > MOVING_MINIMUM_SPEED ) + idealActivity = ACT_RUN_CROUCH; + else + idealActivity = ACT_CROUCHIDLE; + } + else + { + if ( flOuterSpeed > MOVING_MINIMUM_SPEED ) + { + if ( flOuterSpeed > ARBITRARY_RUN_SPEED ) + idealActivity = ACT_RUN; + else + idealActivity = ACT_WALK; + } + else + { + idealActivity = ACT_IDLE; + } + } + + return idealActivity; + } +} + + +void CSDKPlayerAnimState::DebugShowAnimState( int iStartLine ) +{ +#ifdef CLIENT_DLL + engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle ); + engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle ); + BaseClass::DebugShowAnimState( iStartLine ); +#endif +} + + +void CSDKPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) +{ + BaseClass::ComputeSequences( pStudioHdr ); + + ComputeFireSequence( pStudioHdr ); + ComputeReloadSequence( pStudioHdr ); + ComputeGrenadeSequence( pStudioHdr ); +} + + +void CSDKPlayerAnimState::ClearAnimationLayers() +{ + if ( !m_pOuter ) + return; + + m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED ); + for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ ) + { + m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS ); + } +} + + +void CSDKPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr ) +{ +#ifdef CLIENT_DLL + UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false ); +#else + // Server doesn't bother with different fire sequences. +#endif +} |