diff options
Diffstat (limited to 'game/shared/hl1/hl1_player_shared.cpp')
| -rw-r--r-- | game/shared/hl1/hl1_player_shared.cpp | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/game/shared/hl1/hl1_player_shared.cpp b/game/shared/hl1/hl1_player_shared.cpp new file mode 100644 index 0000000..2d74018 --- /dev/null +++ b/game/shared/hl1/hl1_player_shared.cpp @@ -0,0 +1,373 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include "cbase.h" +#include "tier0/vprof.h" + +#ifdef CLIENT_DLL +#include "hl1_player_shared.h" +#include "hl1/c_hl1mp_player.h" +//#define CRecipientFilter C_RecipientFilter +#else +#include "hl1mp_player.h" +#endif + +// When moving this fast, he plays run anim. +#define ARBITRARY_RUN_SPEED 175.0f + +#define MAX_STANDING_RUN_SPEED 320 +#define MAX_CROUCHED_RUN_SPEED 110 + + +// ------------------------------------------------------------------------------------------------ // +// CPlayerAnimState declaration. +// ------------------------------------------------------------------------------------------------ // + +class CPlayerAnimState : public IHL1MPPlayerAnimState, public CBasePlayerAnimState +{ +public: + + DECLARE_CLASS( CPlayerAnimState, CBasePlayerAnimState ); + + CPlayerAnimState(); + void Init( CHL1MP_Player *pPlayer ); + + // This is called by both the client and the server in the same way to trigger events for + // players firing, jumping, throwing grenades, etc. + virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData ); + virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ); + virtual float SetOuterBodyYaw( float flValue ); + virtual Activity CalcMainActivity(); + virtual float GetCurrentMaxGroundSpeed(); + virtual void ClearAnimationState(); + virtual bool ShouldUpdateAnimState(); + virtual int SelectWeightedSequence( Activity activity ) ; + + float CalcMovementPlaybackRate( bool *bIsMoving ); + + virtual void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ); + + +private: + + const char* GetWeaponSuffix(); + bool HandleJumping(); + bool HandleDeath( Activity *deathActivity ); + + +private: + + CHL1MP_Player *m_pOuter; + + bool m_bJumping; + bool m_bFirstJumpFrame; + float m_flJumpStartTime; + + bool m_bFiring; + float m_flFireStartTime; + + bool m_bDying; + Activity m_DeathActivity; +}; + + +IHL1MPPlayerAnimState* CreatePlayerAnimState( CHL1MP_Player *pPlayer ) +{ + CPlayerAnimState *pRet = new CPlayerAnimState; + pRet->Init( pPlayer ); + return pRet; +} + + +// ----------------------------------------------------------------------------- // +// CPlayerAnimState implementation. +// ----------------------------------------------------------------------------- // + +CPlayerAnimState::CPlayerAnimState() +{ + m_pOuter = NULL; + m_bJumping = false; + m_bFirstJumpFrame = false; + m_bFiring = false; +} + + +void CPlayerAnimState::Init( CHL1MP_Player *pPlayer ) +{ + m_pOuter = pPlayer; + + CModAnimConfig config; + config.m_flMaxBodyYawDegrees = 90; + config.m_LegAnimType = LEGANIM_GOLDSRC; + config.m_bUseAimSequences = true; + + BaseClass::Init( pPlayer, config ); +} + + +const char* CPlayerAnimState::GetWeaponSuffix() +{ + CBaseCombatWeapon *pWeapon = m_pOuter->GetActiveWeapon(); + if ( pWeapon ) + return pWeapon->GetWpnData().szAnimationPrefix; + else + return "shotgun"; +} + + +int CPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) +{ + const char *pWeaponSuffix = GetWeaponSuffix(); + if ( !pWeaponSuffix ) + return 0; + + if ( strcmp( pWeaponSuffix, "glock" ) == 0 ) + pWeaponSuffix = "onehanded"; + + // Are we aiming or firing? + const char *pAimOrShoot = "aim"; + if ( m_bFiring ) + pAimOrShoot = "shoot"; + + // Are we standing or crouching? + int iSequence = 0; + const char *pPrefix = "ref"; + if ( m_bDying ) + { + // While dying, only play the main sequence.. don't layer this one on top. + *flAimSequenceWeight = 0; + } + else + { + switch ( GetCurrentMainSequenceActivity() ) + { + case ACT_CROUCHIDLE: + case ACT_RUN_CROUCH: + pPrefix = "crouch"; + break; + } + } + + iSequence = CalcSequenceIndex( "%s_%s_%s", pPrefix, pAimOrShoot, pWeaponSuffix ); + + // Check if we're done firing. + if ( m_bFiring ) + { + float dur = m_pOuter->SequenceDuration( iSequence ); + *flCycle = (gpGlobals->curtime - m_flFireStartTime) / dur; + if ( *flCycle >= 1 ) + { + *flCycle = 1; + m_bFiring = false; + } + } + + return iSequence; +} + + +void CPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) +{ + if ( event == PLAYERANIMEVENT_JUMP ) + { + // Main animation goes to ACT_HOP. + m_bJumping = true; + m_bFirstJumpFrame = true; + m_flJumpStartTime = gpGlobals->curtime; + } + else if ( event == PLAYERANIMEVENT_FIRE_GUN ) + { + // The middle part of the aim layer sequence becomes "shoot" until that animation is complete. + m_bFiring = true; + m_flFireStartTime = gpGlobals->curtime; + } +} + + +float CPlayerAnimState::SetOuterBodyYaw( float flValue ) +{ +// m_pOuter->SetBoneController( 0, flValue ); + + float fAcc = flValue / 4; + + for ( int i = 0; i < 4; i++ ) + { + m_pOuter->SetBoneController( i, fAcc ); + } + + return flValue; +} + + +bool CPlayerAnimState::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; +} + +int CPlayerAnimState::SelectWeightedSequence( Activity activity ) +{ + return m_pOuter->m_iRealSequence; +} + +bool CPlayerAnimState::HandleDeath( Activity *deathActivity ) +{ + if ( m_bDying ) + { + if ( m_pOuter->IsAlive() ) + { + m_bDying = false; + } + else + { + *deathActivity = m_DeathActivity; + } + } + return m_bDying; +} + + +Activity CPlayerAnimState::CalcMainActivity() +{ + Activity deathActivity = ACT_IDLE; + if ( HandleDeath( &deathActivity ) ) + { + return deathActivity; + } + else if ( HandleJumping() ) + { + return ACT_HOP; + } + else + { + Activity idealActivity = ACT_IDLE; + float flOuterSpeed = GetOuterXYSpeed(); + + if ( m_pOuter->GetFlags() & FL_DUCKING ) + { + if ( flOuterSpeed > 0.1f ) + idealActivity = ACT_RUN_CROUCH; + else + idealActivity = ACT_CROUCHIDLE; + } + else + { + if ( flOuterSpeed > 0.1f ) + { + if ( flOuterSpeed > ARBITRARY_RUN_SPEED ) + idealActivity = ACT_RUN; + else + idealActivity = ACT_WALK; + } + else + { + idealActivity = ACT_IDLE; + } + } + + return idealActivity ; + } +} + + +float CPlayerAnimState::GetCurrentMaxGroundSpeed() +{ + Activity act = GetCurrentMainSequenceActivity(); + if ( act == ACT_CROUCHIDLE || act == ACT_RUN_CROUCH ) + return MAX_CROUCHED_RUN_SPEED; + else + return MAX_STANDING_RUN_SPEED; +} + + +void CPlayerAnimState::ClearAnimationState() +{ + m_bJumping = false; + m_bFiring = false; + m_bDying = false; + + BaseClass::ClearAnimationState(); +} + + +bool CPlayerAnimState::ShouldUpdateAnimState() +{ + return true; +} + +float CPlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving ) +{ + // Determine ideal playback rate + Vector vel; + GetOuterAbsVelocity( vel ); + + float flReturnValue = BaseClass::CalcMovementPlaybackRate( bIsMoving ); + + Activity eActivity = GetOuter()->GetSequenceActivity( GetOuter()->GetSequence() ) ; + + if ( eActivity == ACT_RUN || eActivity == ACT_WALK || eActivity == ACT_CROUCH ) + { + VectorNormalize( vel ); + + Vector vForward; + AngleVectors( GetOuter()->EyeAngles(), &vForward ); + + float flDot = DotProduct( vel, vForward ); + + if ( flDot < 0 ) + { + flReturnValue *= -1; + } + } + + return flReturnValue; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ) +{ + VPROF( "CBasePlayerAnimState::ComputePoseParam_BodyPitch" ); + + // Get pitch from v_angle + float flPitch = -m_flEyePitch; + if ( flPitch > 180.0f ) + { + flPitch -= 360.0f; + } + flPitch = clamp( flPitch, -50, 45 ); + + // See if we have a blender for pitch + int pitch = GetOuter()->LookupPoseParameter( pStudioHdr, "XR" ); + if ( pitch < 0 ) + return; + + GetOuter()->SetPoseParameter( pStudioHdr, pitch, flPitch ); + g_flLastBodyPitch = flPitch; +} + |