|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "tfc_playeranimstate.h"
#include "base_playeranimstate.h"
#include "tier0/vprof.h"
#include "animation.h"
#include "studio.h"
#include "apparent_velocity_helper.h"
#include "utldict.h"
#ifdef CLIENT_DLL
#include "c_tfc_player.h"
#else
#include "tfc_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 CTFCPlayerAnimState : public ITFCPlayerAnimState, public CBasePlayerAnimState { public: DECLARE_CLASS( CTFCPlayerAnimState, CBasePlayerAnimState );
CTFCPlayerAnimState(); void InitTFC( CTFCPlayer *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 ); virtual float SetOuterBodyYaw( float flValue ); virtual Activity CalcMainActivity(); virtual float GetCurrentMaxGroundSpeed(); virtual void ClearAnimationState(); virtual bool ShouldUpdateAnimState();
private: const char* GetWeaponSuffix(); bool HandleJumping(); bool HandleDeath( Activity *deathActivity );
private: CTFCPlayer *m_pOuterTFC; bool m_bJumping; bool m_bFirstJumpFrame; float m_flJumpStartTime;
bool m_bFiring; float m_flFireStartTime;
bool m_bDying; Activity m_DeathActivity; };
ITFCPlayerAnimState* CreatePlayerAnimState( CTFCPlayer *pPlayer ) { CTFCPlayerAnimState *pRet = new CTFCPlayerAnimState; pRet->InitTFC( pPlayer ); return pRet; }
// ----------------------------------------------------------------------------- //
// CTFCPlayerAnimState implementation.
// ----------------------------------------------------------------------------- //
CTFCPlayerAnimState::CTFCPlayerAnimState() { m_pOuterTFC = NULL; m_bJumping = false; m_bFirstJumpFrame = false; m_bFiring = false; }
void CTFCPlayerAnimState::InitTFC( CTFCPlayer *pPlayer ) { m_pOuterTFC = pPlayer; CModAnimConfig config; config.m_flMaxBodyYawDegrees = 30; config.m_LegAnimType = LEGANIM_GOLDSRC; config.m_bUseAimSequences = true;
BaseClass::Init( pPlayer, config ); }
const char* CTFCPlayerAnimState::GetWeaponSuffix() { CBaseCombatWeapon *pWeapon = m_pOuterTFC->GetActiveWeapon(); if ( pWeapon ) return pWeapon->GetWpnData().szAnimationPrefix; else return "shotgun"; }
int CTFCPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight ) { const char *pWeaponSuffix = GetWeaponSuffix(); if ( !pWeaponSuffix ) return 0;
// 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_pOuterTFC->SequenceDuration( iSequence ); *flCycle = (gpGlobals->curtime - m_flFireStartTime) / dur; if ( *flCycle >= 1 ) { *flCycle = 1; m_bFiring = false; } }
return iSequence; }
void CTFCPlayerAnimState::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; } else if ( event == PLAYERANIMEVENT_DIE ) { m_bFiring = m_bJumping = false; m_bDying = true; Activity acts[] = { ACT_DIESIMPLE, ACT_DIEBACKWARD, ACT_DIEFORWARD, ACT_DIE_HEADSHOT, ACT_DIE_GUTSHOT };
m_DeathActivity = acts[ RandomInt( 0, ARRAYSIZE( acts ) - 1 ) ]; RestartMainSequence(); // Play a death animation.
} }
float CTFCPlayerAnimState::SetOuterBodyYaw( float flValue ) { m_pOuterTFC->SetBoneController( 0, flValue ); return flValue; }
bool CTFCPlayerAnimState::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_pOuterTFC->GetFlags() & FL_ONGROUND ) { m_bJumping = false; RestartMainSequence(); // Reset the animation.
} } }
// Are we still jumping? If so, keep playing the jump animation.
return m_bJumping; }
bool CTFCPlayerAnimState::HandleDeath( Activity *deathActivity ) { if ( m_bDying ) { if ( m_pOuterTFC->IsAlive() ) { m_bDying = false; } else { *deathActivity = m_DeathActivity; } } return m_bDying; }
Activity CTFCPlayerAnimState::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_pOuterTFC->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 CTFCPlayerAnimState::GetCurrentMaxGroundSpeed() { Activity act = GetCurrentMainSequenceActivity(); if ( act == ACT_CROUCHIDLE || act == ACT_RUN_CROUCH ) return MAX_CROUCHED_RUN_SPEED; else return MAX_STANDING_RUN_SPEED; }
void CTFCPlayerAnimState::ClearAnimationState() { m_bJumping = false; m_bFiring = false; m_bDying = false;
BaseClass::ClearAnimationState(); }
bool CTFCPlayerAnimState::ShouldUpdateAnimState() { return true; }
|