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.
288 lines
9.4 KiB
288 lines
9.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef BASE_PLAYERANIMSTATE_H |
|
#define BASE_PLAYERANIMSTATE_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
|
|
#include "iplayeranimstate.h" |
|
#include "studio.h" |
|
#include "sequence_Transitioner.h" |
|
|
|
#ifdef CLIENT_DLL |
|
class C_BaseAnimatingOverlay; |
|
#define CBaseAnimatingOverlay C_BaseAnimatingOverlay |
|
#else |
|
class CBaseAnimatingOverlay; |
|
#endif |
|
|
|
// If a guy is moving slower than this, then he's considered to not be moving |
|
// (so he goes to his idle animation at full playback rate rather than his walk |
|
// animation at low playback rate). |
|
#define MOVING_MINIMUM_SPEED 0.5f |
|
|
|
|
|
#define MAIN_IDLE_SEQUENCE_LAYER 0 // For 8-way blended models, this layer blends an idle on top of the run/walk animation to simulate a 9-way blend. |
|
// For 9-way blended models, we don't use this layer. |
|
|
|
#define AIMSEQUENCE_LAYER 1 // Aim sequence uses layers 0 and 1 for the weapon idle animation (needs 2 layers so it can blend). |
|
#define NUM_AIMSEQUENCE_LAYERS 4 // Then it uses layers 2 and 3 to blend in the weapon run/walk/crouchwalk animation. |
|
|
|
|
|
// Everyone who derives from CBasePlayerAnimState gets to fill in this info |
|
// to drive how the animation state is generated. |
|
class CModAnimConfig |
|
{ |
|
public: |
|
// This tells how far the upper body can rotate left and right. If he begins to rotate |
|
// past this, it'll turn his feet to face his upper body. |
|
float m_flMaxBodyYawDegrees; |
|
|
|
// How do the legs animate? |
|
LegAnimType_t m_LegAnimType; |
|
|
|
// Use aim sequences? (CS hostages don't). |
|
bool m_bUseAimSequences; |
|
}; |
|
|
|
|
|
// ------------------------------------------------------------------------------------------------ // |
|
// CBasePlayerAnimState declaration. |
|
// ------------------------------------------------------------------------------------------------ // |
|
|
|
abstract_class CBasePlayerAnimState : virtual public IPlayerAnimState |
|
{ |
|
public: |
|
DECLARE_CLASS_NOBASE( CBasePlayerAnimState ); |
|
|
|
enum |
|
{ |
|
TURN_NONE = 0, |
|
TURN_LEFT, |
|
TURN_RIGHT |
|
}; |
|
|
|
CBasePlayerAnimState(); |
|
virtual ~CBasePlayerAnimState(); |
|
|
|
void Init( CBaseAnimatingOverlay *pPlayer, const CModAnimConfig &config ); |
|
virtual void Release(); |
|
|
|
// Update() and DoAnimationEvent() together maintain the entire player's animation state. |
|
// |
|
// Update() maintains the the lower body animation (the player's m_nSequence) |
|
// and the upper body overlay based on the player's velocity and look direction. |
|
// |
|
// It also modulates these based on events triggered by DoAnimationEvent. |
|
virtual void Update( float eyeYaw, float eyePitch ); |
|
|
|
// This is called by the client when a new player enters the PVS to clear any events |
|
// the dormant version of the entity may have been playing. |
|
virtual void ClearAnimationState(); |
|
|
|
// This is called every frame to prepare the animation layers to be filled with data |
|
// since we reconstruct them every frame (in case they get stomped by the networking |
|
// or anything else). |
|
virtual void ClearAnimationLayers(); |
|
|
|
// The client uses this to figure out what angles to render the entity with (since as the guy turns, |
|
// it will change his body_yaw pose parameter before changing his rendered angle). |
|
virtual const QAngle& GetRenderAngles(); |
|
|
|
|
|
// Overrideables. |
|
public: |
|
|
|
virtual bool ShouldUpdateAnimState(); |
|
|
|
// This is called near the start of each frame. |
|
// The base class figures out the main sequence and the aim sequence, and derived |
|
// classes can overlay whatever other animations they want. |
|
virtual void ComputeSequences( CStudioHdr *pStudioHdr ); |
|
|
|
// This is called to figure out what the main activity is. The mod-specific class |
|
// overrides this to handle events like jumping, firing, etc. |
|
virtual Activity CalcMainActivity() = 0; |
|
|
|
// This is called to calculate the aim layer sequence. It usually figures out the |
|
// animation prefixes and suffixes and calls CalcSequenceIndex(). |
|
virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) = 0; |
|
|
|
// This lets server-controlled idle sequences to play unchanged on the client |
|
virtual bool ShouldChangeSequences( void ) const; |
|
|
|
// If this returns true, then it will blend the current aim layer sequence with an idle aim layer |
|
// sequence based on how fast the character is moving, so it doesn't play the upper-body run at |
|
// full speed if he's moving really slowly. |
|
// |
|
// We return false on this for animations that don't have blends, like reloads. |
|
virtual bool ShouldBlendAimSequenceToIdle(); |
|
|
|
// For the body left/right rotation, some models use a pose parameter and some use a bone controller. |
|
virtual float SetOuterBodyYaw( float flValue ); |
|
|
|
// Return true if the player is allowed to move. |
|
virtual bool CanThePlayerMove(); |
|
|
|
// This is called every frame to see what the maximum speed the player can move is. |
|
// It is used to determine where to put the move_x/move_y pose parameters or to |
|
// determine the animation playback rate, based on the player's movement speed. |
|
// The return value from here is interpolated so the playback rate or pose params don't move sharply. |
|
virtual float GetCurrentMaxGroundSpeed() = 0; |
|
|
|
// Display Con_NPrint output about the animation state. This is called if |
|
// we're on the client and if cl_showanimstate holds the current entity's index. |
|
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, ... ); |
|
|
|
// Calculate the playback rate for movement layer |
|
virtual float CalcMovementPlaybackRate( bool *bIsMoving ); |
|
|
|
// Allow inheriting classes to translate their desired activity, while keeping all |
|
// internal ACT comparisons using the base activity |
|
virtual Activity TranslateActivity( Activity actDesired ) { return actDesired; } |
|
|
|
// Allow inheriting classes to override SelectWeightedSequence |
|
virtual int SelectWeightedSequence( Activity activity ); |
|
|
|
public: |
|
|
|
void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] ); |
|
|
|
CBaseAnimatingOverlay *GetOuter() const; |
|
|
|
void RestartMainSequence(); |
|
|
|
|
|
// Helpers for the derived classes to use. |
|
protected: |
|
|
|
// Sets up the string you specify, looks for that sequence and returns the index. |
|
// Complains in the console and returns 0 if it can't find it. |
|
virtual int CalcSequenceIndex( PRINTF_FORMAT_STRING const char *pBaseName, ... ); |
|
|
|
Activity GetCurrentMainSequenceActivity() const; |
|
|
|
void GetOuterAbsVelocity( Vector& vel ) const; |
|
float GetOuterXYSpeed() const; |
|
|
|
// How long has it been since we cleared the animation state? |
|
float TimeSinceLastAnimationStateClear() const; |
|
|
|
float GetEyeYaw() const { return m_flEyeYaw; } |
|
|
|
protected: |
|
|
|
CModAnimConfig m_AnimConfig; |
|
CBaseAnimatingOverlay *m_pOuter; |
|
|
|
protected: |
|
int ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current ); |
|
virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ); |
|
virtual void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ); |
|
virtual void ComputePoseParam_BodyYaw(); |
|
|
|
virtual void ResetGroundSpeed( void ); |
|
|
|
protected: |
|
// The player's eye yaw and pitch angles. |
|
float m_flEyeYaw; |
|
float m_flEyePitch; |
|
|
|
// The following variables are used for tweaking the yaw of the upper body when standing still and |
|
// making sure that it smoothly blends in and out once the player starts moving |
|
// Direction feet were facing when we stopped moving |
|
float m_flGoalFeetYaw; |
|
|
|
float m_flCurrentFeetYaw; |
|
bool m_bCurrentFeetYawInitialized; |
|
|
|
float m_flCurrentTorsoYaw; |
|
|
|
// To check if they are rotating in place |
|
float m_flLastYaw; |
|
|
|
// Time when we stopped moving |
|
float m_flLastTurnTime; |
|
|
|
// One of the above enums |
|
int m_nTurningInPlace; |
|
|
|
QAngle m_angRender; |
|
|
|
private: |
|
|
|
// Update the prone state machine. |
|
void UpdateProneState(); |
|
|
|
// Get the string that's appended to animation names for the player's current weapon. |
|
const char* GetWeaponSuffix(); |
|
|
|
Activity BodyYawTranslateActivity( Activity activity ); |
|
|
|
void SetOuterPoseParameter( int iParam, float flValue ); |
|
|
|
|
|
void EstimateYaw(); |
|
|
|
virtual bool ShouldResetMainSequence( int iCurrentSequence, int iNewSequence ); |
|
void ComputeMainSequence(); |
|
void ComputeAimSequence(); |
|
|
|
void ComputePlaybackRate(); |
|
|
|
void UpdateInterpolators(); |
|
float GetInterpolatedGroundSpeed(); |
|
|
|
private: |
|
|
|
float m_flMaxGroundSpeed; |
|
|
|
float m_flLastAnimationStateClearTime; |
|
|
|
// If he's using 8-way blending, then we blend to this idle |
|
int m_iCurrent8WayIdleSequence; |
|
int m_iCurrent8WayCrouchIdleSequence; |
|
|
|
// Last activity we've used on the lower body. Used to determine if animations should restart. |
|
Activity m_eCurrentMainSequenceActivity; |
|
|
|
float m_flGaitYaw; |
|
float m_flStoredCycle; |
|
|
|
Vector2D m_vLastMovePose; |
|
|
|
void UpdateAimSequenceLayers( |
|
float flCycle, |
|
int iFirstLayer, |
|
bool bForceIdle, |
|
CSequenceTransitioner *pTransitioner, |
|
float flWeightScale |
|
); |
|
|
|
void OptimizeLayerWeights( int iFirstLayer, int nLayers ); |
|
|
|
// This gives us smooth transitions between aim anim sequences on the client. |
|
CSequenceTransitioner m_IdleSequenceTransitioner; |
|
CSequenceTransitioner m_SequenceTransitioner; |
|
}; |
|
|
|
extern float g_flLastBodyPitch, g_flLastBodyYaw, m_flLastMoveYaw; |
|
|
|
|
|
inline Activity CBasePlayerAnimState::GetCurrentMainSequenceActivity() const |
|
{ |
|
return m_eCurrentMainSequenceActivity; |
|
} |
|
|
|
|
|
#endif // BASE_PLAYERANIMSTATE_H
|
|
|