You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
6.7 KiB
324 lines
6.7 KiB
![]()
4 years ago
|
//========= 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;
|
||
|
}
|
||
|
|