diff options
Diffstat (limited to 'game/shared/base_playeranimstate.h')
| -rw-r--r-- | game/shared/base_playeranimstate.h | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/game/shared/base_playeranimstate.h b/game/shared/base_playeranimstate.h new file mode 100644 index 0000000..5c84755 --- /dev/null +++ b/game/shared/base_playeranimstate.h @@ -0,0 +1,288 @@ +//========= 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 |