//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef MULTIPLAYERANIMSTATE_H #define MULTIPLAYERANIMSTATE_H #ifdef _WIN32 #pragma once #endif #include "convar.h" #include "basecombatweapon_shared.h" #include "iplayeranimstate.h" #if defined( CLIENT_DLL ) class C_BasePlayer; #define CPlayer C_BasePlayer #else class CBasePlayer; #endif enum PlayerAnimEvent_t { PLAYERANIMEVENT_ATTACK_PRIMARY, PLAYERANIMEVENT_ATTACK_SECONDARY, PLAYERANIMEVENT_ATTACK_GRENADE, PLAYERANIMEVENT_RELOAD, PLAYERANIMEVENT_RELOAD_LOOP, PLAYERANIMEVENT_RELOAD_END, PLAYERANIMEVENT_JUMP, PLAYERANIMEVENT_SWIM, PLAYERANIMEVENT_DIE, PLAYERANIMEVENT_FLINCH_CHEST, PLAYERANIMEVENT_FLINCH_HEAD, PLAYERANIMEVENT_FLINCH_LEFTARM, PLAYERANIMEVENT_FLINCH_RIGHTARM, PLAYERANIMEVENT_FLINCH_LEFTLEG, PLAYERANIMEVENT_FLINCH_RIGHTLEG, PLAYERANIMEVENT_DOUBLEJUMP, // Cancel. PLAYERANIMEVENT_CANCEL, PLAYERANIMEVENT_SPAWN, // Snap to current yaw exactly PLAYERANIMEVENT_SNAP_YAW, PLAYERANIMEVENT_CUSTOM, // Used to play specific activities PLAYERANIMEVENT_CUSTOM_GESTURE, PLAYERANIMEVENT_CUSTOM_SEQUENCE, // Used to play specific sequences PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE, // TF Specific. Here until there's a derived game solution to this. PLAYERANIMEVENT_ATTACK_PRE, PLAYERANIMEVENT_ATTACK_POST, PLAYERANIMEVENT_GRENADE1_DRAW, PLAYERANIMEVENT_GRENADE2_DRAW, PLAYERANIMEVENT_GRENADE1_THROW, PLAYERANIMEVENT_GRENADE2_THROW, PLAYERANIMEVENT_VOICE_COMMAND_GESTURE, PLAYERANIMEVENT_DOUBLEJUMP_CROUCH, PLAYERANIMEVENT_STUN_BEGIN, PLAYERANIMEVENT_STUN_MIDDLE, PLAYERANIMEVENT_STUN_END, PLAYERANIMEVENT_PASSTIME_THROW_BEGIN, PLAYERANIMEVENT_PASSTIME_THROW_MIDDLE, PLAYERANIMEVENT_PASSTIME_THROW_END, PLAYERANIMEVENT_PASSTIME_THROW_CANCEL, PLAYERANIMEVENT_ATTACK_PRIMARY_SUPER, PLAYERANIMEVENT_COUNT }; // Gesture Slots. enum { GESTURE_SLOT_ATTACK_AND_RELOAD, GESTURE_SLOT_GRENADE, GESTURE_SLOT_JUMP, GESTURE_SLOT_SWIM, GESTURE_SLOT_FLINCH, GESTURE_SLOT_VCD, GESTURE_SLOT_CUSTOM, GESTURE_SLOT_COUNT, }; #define GESTURE_SLOT_INVALID -1 struct GestureSlot_t { int m_iGestureSlot; Activity m_iActivity; bool m_bAutoKill; bool m_bActive; CAnimationLayer *m_pAnimLayer; }; inline bool IsCustomPlayerAnimEvent( PlayerAnimEvent_t event ) { return ( event == PLAYERANIMEVENT_CUSTOM ) || ( event == PLAYERANIMEVENT_CUSTOM_GESTURE ) || ( event == PLAYERANIMEVENT_CUSTOM_SEQUENCE ) || ( event == PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE ); } struct MultiPlayerPoseData_t { int m_iMoveX; int m_iMoveY; int m_iAimYaw; int m_iAimPitch; int m_iBodyHeight; int m_iMoveYaw; int m_iMoveScale; float m_flEstimateYaw; float m_flLastAimTurnTime; void Init() { m_iMoveX = 0; m_iMoveY = 0; m_iAimYaw = 0; m_iAimPitch = 0; m_iBodyHeight = 0; m_iMoveYaw = 0; m_iMoveScale = 0; m_flEstimateYaw = 0.0f; m_flLastAimTurnTime = 0.0f; } }; struct DebugPlayerAnimData_t { float m_flSpeed; float m_flAimPitch; float m_flAimYaw; float m_flBodyHeight; Vector2D m_vecMoveYaw; void Init() { m_flSpeed = 0.0f; m_flAimPitch = 0.0f; m_flAimYaw = 0.0f; m_flBodyHeight = 0.0f; m_vecMoveYaw.Init(); } }; struct MultiPlayerMovementData_t { // Set speeds to -1 if they are not used. float m_flWalkSpeed; float m_flRunSpeed; float m_flSprintSpeed; float m_flBodyYawRate; }; //============================================================================= // // Multi-Player Animation State // class CMultiPlayerAnimState { public: DECLARE_CLASS_NOBASE( CMultiPlayerAnimState ); // Creation/Destruction CMultiPlayerAnimState() {} CMultiPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ); virtual ~CMultiPlayerAnimState(); // 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 ClearAnimationState(); virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ); virtual Activity CalcMainActivity(); virtual void Update( float eyeYaw, float eyePitch ); virtual void Release( void ); const QAngle &GetRenderAngles(); virtual Activity TranslateActivity( Activity actDesired ); virtual void SetRunSpeed( float flSpeed ) { m_MovementData.m_flRunSpeed = flSpeed; } virtual void SetWalkSpeed( float flSpeed ) { m_MovementData.m_flWalkSpeed = flSpeed; } virtual void SetSprintSpeed( float flSpeed ) { m_MovementData.m_flSprintSpeed = flSpeed; } // Debug virtual void ShowDebugInfo( void ); virtual void DebugShowAnimState( int iStartLine ); Activity GetCurrentMainActivity( void ) { return m_eCurrentMainSequenceActivity; } void OnNewModel( void ); // Gestures. void ResetGestureSlots( void ); void ResetGestureSlot( int iGestureSlot ); void AddVCDSequenceToGestureSlot( int iGestureSlot, int iGestureSequence, float flCycle = 0.0f, bool bAutoKill = true ); CAnimationLayer* GetGestureSlotLayer( int iGestureSlot ); bool IsGestureSlotActive( int iGestureSlot ); bool VerifyAnimLayerInSlot( int iGestureSlot ); // Feet. // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window, // and the fact that m_flEyeYaw is never propogated from the server to the client. // TODO: Fix this after Halloween 2014. bool m_bForceAimYaw; protected: virtual void Init( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ); CBasePlayer *GetBasePlayer( void ) { return m_pPlayer; } // Allow inheriting classes to override SelectWeightedSequence virtual int SelectWeightedSequence( Activity activity ) { return GetBasePlayer()->SelectWeightedSequence( activity ); } virtual void RestartMainSequence(); virtual void GetOuterAbsVelocity( Vector& vel ); float GetOuterXYSpeed(); virtual bool HandleJumping( Activity &idealActivity ); virtual bool HandleDucking( Activity &idealActivity ); virtual bool HandleMoving( Activity &idealActivity ); virtual bool HandleSwimming( Activity &idealActivity ); virtual bool HandleDying( Activity &idealActivity ); // Gesture Slots CUtlVector m_aGestureSlots; bool InitGestureSlots( void ); void ShutdownGestureSlots( void ); bool IsGestureSlotPlaying( int iGestureSlot, Activity iGestureActivity ); void AddToGestureSlot( int iGestureSlot, Activity iGestureActivity, bool bAutoKill ); virtual void RestartGesture( int iGestureSlot, Activity iGestureActivity, bool bAutoKill = true ); void ComputeGestureSequence( CStudioHdr *pStudioHdr ); void UpdateGestureLayer( CStudioHdr *pStudioHdr, GestureSlot_t *pGesture ); void DebugGestureInfo( void ); virtual float GetGesturePlaybackRate( void ) { return 1.0f; } #ifdef CLIENT_DLL void RunGestureSlotAnimEventsToCompletion( GestureSlot_t *pGesture ); #endif virtual void PlayFlinchGesture( Activity iActivity ); virtual float CalcMovementSpeed( bool *bIsMoving ); virtual float CalcMovementPlaybackRate( bool *bIsMoving ); void DoMovementTest( CStudioHdr *pStudioHdr, float flX, float flY ); void DoMovementTest( CStudioHdr *pStudioHdr ); void GetMovementFlags( CStudioHdr *pStudioHdr ); // Pose parameters. bool SetupPoseParameters( CStudioHdr *pStudioHdr ); virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ); virtual void ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr ); virtual void ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ); void ComputePoseParam_BodyHeight( CStudioHdr *pStudioHdr ); virtual void EstimateYaw( void ); void ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw ); virtual float GetCurrentMaxGroundSpeed(); virtual void ComputeSequences( CStudioHdr *pStudioHdr ); void ComputeMainSequence(); void UpdateInterpolators(); void ResetGroundSpeed( void ); float GetInterpolatedGroundSpeed( void ); void ComputeFireSequence(); void ComputeDeployedSequence(); virtual bool ShouldUpdateAnimState(); void DebugShowAnimStateForPlayer( bool bIsServer ); void DebugShowEyeYaw( void ); // Client specific. #ifdef CLIENT_DLL // Debug. void DebugShowActivity( Activity activity ); #endif protected: CBasePlayer *m_pPlayer; QAngle m_angRender; // Pose parameters. bool m_bPoseParameterInit; MultiPlayerPoseData_t m_PoseParameterData; DebugPlayerAnimData_t m_DebugAnimData; bool m_bCurrentFeetYawInitialized; float m_flLastAnimationStateClearTime; float m_flEyeYaw; float m_flEyePitch; float m_flGoalFeetYaw; float m_flCurrentFeetYaw; float m_flLastAimTurnTime; MultiPlayerMovementData_t m_MovementData; // Jumping. bool m_bJumping; float m_flJumpStartTime; bool m_bFirstJumpFrame; // Swimming. bool m_bInSwim; bool m_bFirstSwimFrame; // Dying bool m_bDying; bool m_bFirstDyingFrame; // Last activity we've used on the lower body. Used to determine if animations should restart. Activity m_eCurrentMainSequenceActivity; // Specific full-body sequence to play int m_nSpecificMainSequence; // Weapon data. CHandle m_hActiveWeapon; // Ground speed interpolators. #ifdef CLIENT_DLL float m_flLastGroundSpeedUpdateTime; CInterpolatedVar m_iv_flMaxGroundSpeed; #endif float m_flMaxGroundSpeed; // movement playback options int m_nMovementSequence; LegAnimType_t m_LegAnimType; }; // If this is set, then the game code needs to make sure to send player animation events // to the local player if he's the one being watched. extern ConVar cl_showanimstate; #endif // DOD_PLAYERANIMSTATE_H