290 lines
9.9 KiB
C++
290 lines
9.9 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#ifndef BASE_PLAYERANIMSTATE_H
|
|
#define BASE_PLAYERANIMSTATE_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "iplayeranimstate.h"
|
|
#include "sequence_Transitioner.h"
|
|
#include "studio.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 ¤t);
|
|
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
|