m_PlayerAnimState

From Valve Developer Community
Jump to navigation Jump to search

The m_PlayerAnimState object maintains a player's animation state. It is shared code.

There are two versions: CBasePlayerAnimState and CMultiPlayerAnimState.

Note.pngNote:Your player must be using a model set up with the appropriate blend sequences for any of this to work. Unfortunately there are several different schemes floating around: Ep1, OB and Counter-Strike players are all driven by different sequences! Check m_PlayerAnimState->SetupPoseParameters() to see what your code is looking for.

Usage

Update( float eyeYaw, float eyePitch )
Manages ambient, looping animations (running/swimming, aiming, breathing) based on player velocity and look direction every frame. Typically called from:
  • CBasePlayer::PostThink()
  • C_BasePlayer::UpdateClientSideAnimation()
DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 )
Begins a discrete, event-based animation (crouching, shooting, reloading) whenever called. PlayerAnimEvent_t is an enum value that defines what type of animation event this is; it is translated into an activity elsewhere depending on the status of the player (weapon held, swimming, etc).

Implementation

You must define m_PlayerAnimState in both your client and server classes:

class CMyPlayer : public CBasePlayer // and on client!
{
	// ...
	CMultiPlayerAnimState* m_PlayerAnimState;
	// ...
};

And then initialise it in shared code:

inline void CMyPlayer::Spawn_Shared()
{
	MultiPlayerMovementData_t mv;
	mv.m_flSprintSpeed = -1;
	mv.m_flRunSpeed = 200;
	mv.m_flWalkSpeed = 80;
	mv.m_flBodyYawRate = 180;
	m_PlayerAnimState = new CMultiPlayerAnimState( this,mv );

	UseClientSideAnimation();
}

Now you need to hook things up. On the server:

void CMyPlayer::PostThink()
{
	BaseClass::PostThink();

	// Keep the model upright; pose params will handle pitch aiming.
	QAngle angles = GetLocalAngles();
	angles[PITCH] = 0;
	SetLocalAngles( angles );

	m_PlayerAnimState->Update( EyeAngles()[YAW], EyeAngles()[PITCH] );
}

void CMyPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
{
	m_PlayerAnimState->DoAnimationEvent( event, nData );
	TE_PlayerAnimEvent( this, event, nData );	// Transmit to other clients. Comment this out in SP.
}

And on the client:

#include "prediction.h"
#include "c_basetempentity.h"

void C_MyPlayer::UpdateClientSideAnimation()
{
	m_PlayerAnimState->Update( EyeAngles()[YAW], EyeAngles()[PITCH] );
}

void C_MyPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
{
	if ( IsLocalPlayer() && prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) )
		return;
 
	MDLCACHE_CRITICAL_SECTION();
	m_PlayerAnimState->DoAnimationEvent( event, nData );
}

Dispatching to clients

In multiplayer you must dispatch animation events to all onlooking clients, a job which is not performed by CBasePlayer. See m_PlayerAnimState/TempEnt for the temporary entity used by Valve.