PDA

View Full Version : CSS Animations -> HL2MP code


StuD-tos
06-25-2007, 01:44 AM
I've worked on this before with no luck, but I think I can solve it now. So far I have modified HL2MP_weapon_parse

void CHL2MPSWeaponInfo::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
{
BaseClass::Parse( pKeyValuesData, szWeaponName );

m_iPlayerDamage = pKeyValuesData->GetInt( "damage", 0 );

//-----------------------------------------------------
// Taken from sdk_weapon_parse, Should allow weapons to
// use CSS animations - Keith
//-----------------------------------------------------
const char *pAnimEx = pKeyValuesData->GetString( "PlayerAnimationExtension", "mp5" );
Q_strncpy( m_szAnimExtension, pAnimEx, sizeof( m_szAnimExtension ) );
//-----------------------------------------------------
}

and in the header

char m_szAnimExtension[16]; // string used to //generate player animations with this weapon


I then went to my weapon class .cpp, and added under the constructor

const CHL2MPSWeaponInfo &CWeaponTOSBase::GetTOSWpnData() const
{
const FileWeaponInfo_t *pWeaponInfo = &GetWpnData();
const CHL2MPSWeaponInfo *pHL2MPSInfo;

#ifdef _DEBUG
pHL2MPSInfo = dynamic_cast< const CHL2MPSWeaponInfo* >( pWeaponInfo );
Assert( pHL2MPSInfo );
#else
pHL2MPSInfo = static_cast< const CHL2MPSWeaponInfo* >( pWeaponInfo );
#endif

return *pHL2MPSInfo;
}

Then declare this in the .h

// Get HL2MP weapon specific weapon data.
CHL2MPSWeaponInfo const &GetTOSWpnData() const;

Now I think all that is left is getting sdkplayeranimstate to work with the HL2MP code. If anyone else has any better ideas, pitch them in.

StuD-tos
06-25-2007, 01:48 AM
This is my modified sdkplayeranimstate.cpp

//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//================================================== ===========================//

#include "cbase.h"
#include "base_playeranimstate.h"
#include "tier0/vprof.h"
#include "animation.h"
#include "studio.h"
#include "apparent_velocity_helper.h"
#include "utldict.h"

#include "sdk_playeranimstate.h"
#include "weapon_tosbase.h"
//#include "weapon_basesdkgrenade.h"

#ifdef CLIENT_DLL
#include "c_hl2mp_player.h"
#include "bone_setup.h"
#include "interpolatedvar.h"
#else
#include "hl2mp_player.h"
#endif

#define ANIM_TOPSPEED_WALK 100
#define ANIM_TOPSPEED_RUN 250
#define ANIM_TOPSPEED_RUN_CROUCH 85

#define DEFAULT_IDLE_NAME "idle_upper_"
#define DEFAULT_CROUCH_IDLE_NAME "crouch_idle_upper_"
#define DEFAULT_CROUCH_WALK_NAME "crouch_walk_upper_"
#define DEFAULT_WALK_NAME "walk_upper_"
#define DEFAULT_RUN_NAME "run_upper_"

#define DEFAULT_FIRE_IDLE_NAME "idle_shoot_"
#define DEFAULT_FIRE_CROUCH_NAME "crouch_idle_shoot_"
#define DEFAULT_FIRE_CROUCH_WALK_NAME "crouch_walk_shoot_"
#define DEFAULT_FIRE_WALK_NAME "walk_shoot_"
#define DEFAULT_FIRE_RUN_NAME "run_shoot_"


#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS)
#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
#define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1)
#define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1)



// ------------------------------------------------------------------------------------------------ //
// CSDKPlayerAnimState declaration.
// ------------------------------------------------------------------------------------------------ //

class CSDKPlayerAnimState : public CBasePlayerAnimState, public ISDKPlayerAnimState
{
public:
DECLARE_CLASS( CSDKPlayerAnimState, CBasePlayerAnimState );
friend ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );

CSDKPlayerAnimState();

virtual void DoAnimationEvent( PlayerAnimEvent_t event );
virtual bool IsThrowingGrenade();
virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
virtual void ClearAnimationState();
virtual bool CanThePlayerMove();
virtual float GetCurrentMaxGroundSpeed();
virtual Activity CalcMainActivity();
virtual void DebugShowAnimState( int iStartLine );
virtual void ComputeSequences( CStudioHdr *pStudioHdr );
virtual void ClearAnimationLayers();


void InitSDK( CBaseAnimatingOverlay *pPlayer, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );

protected:

int CalcFireLayerSequence(PlayerAnimEvent_t event);
void ComputeFireSequence(CStudioHdr *pStudioHdr);

void ComputeReloadSequence(CStudioHdr *pStudioHdr);
int CalcReloadLayerSequence();

bool IsOuterGrenadePrimed();
void ComputeGrenadeSequence( CStudioHdr *pStudioHdr );
int CalcGrenadePrimeSequence();
int CalcGrenadeThrowSequence();
int GetOuterGrenadeThrowCounter();

const char* GetWeaponSuffix();
bool HandleJumping();

void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd );

private:

// Current state variables.
bool m_bJumping; // Set on a jump event.
float m_flJumpStartTime;
bool m_bFirstJumpFrame;

// Aim sequence plays reload while this is on.
bool m_bReloading;
float m_flReloadCycle;
int m_iReloadSequence;

// This is set to true if ANY animation is being played in the fire layer.
bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
// until it completes.
int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
float m_flFireCycle;

// These control grenade animations.
bool m_bThrowingGrenade;
bool m_bPrimingGrenade;
float m_flGrenadeCycle;
int m_iGrenadeSequence;
int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade.

ISDKPlayerAnimStateHelpers *m_pHelpers;
};


ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
{
CSDKPlayerAnimState *pRet = new CSDKPlayerAnimState;
pRet->InitSDK( pEntity, pHelpers, legAnimType, bUseAimSequences );
return pRet;
}

// ------------------------------------------------------------------------------------------------ //
// CSDKPlayerAnimState implementation.
// ------------------------------------------------------------------------------------------------ //

CSDKPlayerAnimState::CSDKPlayerAnimState()
{
m_pOuter = NULL;
m_bReloading = false;
}


void CSDKPlayerAnimState::InitSDK( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
{
CModAnimConfig config;
config.m_flMaxBodyYawDegrees = 90;
config.m_LegAnimType = legAnimType;
config.m_bUseAimSequences = bUseAimSequences;

m_pHelpers = pHelpers;

BaseClass::Init( pEntity, config );
}


void CSDKPlayerAnimState::ClearAnimationState()
{
m_bJumping = false;
m_bFiring = false;
m_bReloading = false;
m_bThrowingGrenade = m_bPrimingGrenade = false;
m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();

BaseClass::ClearAnimationState();
}


void CSDKPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event )
{
Assert( event != PLAYERANIMEVENT_THROW_GRENADE );

if ( event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY ||
event == PLAYERANIMEVENT_FIRE_GUN_SECONDARY )
{
// Regardless of what we're doing in the fire layer, restart it.
m_flFireCycle = 0;
m_iFireSequence = CalcFireLayerSequence( event );
m_bFiring = m_iFireSequence != -1;
}
else if ( event == PLAYERANIMEVENT_JUMP )
{
// Play the jump animation.
m_bJumping = true;
m_bFirstJumpFrame = true;
m_flJumpStartTime = gpGlobals->curtime;
}
else if ( event == PLAYERANIMEVENT_RELOAD )
{
m_iReloadSequence = CalcReloadLayerSequence();
if ( m_iReloadSequence != -1 )
{
m_bReloading = true;
m_flReloadCycle = 0;
}
}
else
{
Assert( !"CSDKPlayerAnimState::DoAnimationEvent" );
}
}


float g_flThrowGrenadeFraction = 0.25;
bool CSDKPlayerAnimState::IsThrowingGrenade()
{
if ( m_bThrowingGrenade )
{
// An animation event would be more appropriate here.
return m_flGrenadeCycle < g_flThrowGrenadeFraction;
}
else
{
bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
return bThrowPending || IsOuterGrenadePrimed();
}
}


int CSDKPlayerAnimState::CalcReloadLayerSequence()
{
const char *pSuffix = GetWeaponSuffix();
if ( !pSuffix )
return -1;

CWeaponTOSBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
if ( !pWeapon )
return -1;

// First, look for reload_<weapon name>.
char szName[512];
Q_snprintf( szName, sizeof( szName ), "reload_%s", pSuffix );
int iReloadSequence = m_pOuter->LookupSequence( szName );
if ( iReloadSequence != -1 )
return iReloadSequence;

//SDKTODO
/*
// Ok, look for generic categories.. pistol, shotgun, rifle, etc.
if ( pWeapon->GetSDKWpnData().m_WeaponType == WEAPONTYPE_PISTOL )
{
Q_snprintf( szName, sizeof( szName ), "reload_pistol" );
iReloadSequence = m_pOuter->LookupSequence( szName );
if ( iReloadSequence != -1 )
return iReloadSequence;
}
*/

// Fall back to reload_m4.
iReloadSequence = CalcSequenceIndex( "reload_m4" );
if ( iReloadSequence > 0 )
return iReloadSequence;

return -1;
}


#ifdef CLIENT_DLL
void CSDKPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd )
{
if ( !bEnabled )
return;

// Increment the fire sequence's cycle.
flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime;
if ( flCurCycle > 1 )
{
if ( bWaitAtEnd )
{
flCurCycle = 1;
}
else
{
// Not firing anymore.
bEnabled = false;
iSequence = 0;
return;
}
}

// Now dump the state into its animation layer.
C_AnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );

pLayer->m_flCycle = flCurCycle;
pLayer->m_nSequence = iSequence;

pLayer->m_flPlaybackRate = 1.0;
pLayer->m_flWeight = 1.0f;
pLayer->m_nOrder = iLayer;
}
#endif



/*bool CSDKPlayerAnimState::IsOuterGrenadePrimed()
{
CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer();
if ( pChar )
{
CBaseSDKGrenade *pGren = dynamic_cast<CBaseSDKGrenade*>( pChar->GetActiveWeapon() );
return pGren && pGren->IsPinPulled();
}
else
{
return NULL;
}
}*/

/*
void CSDKPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr )
{
#ifdef CLIENT_DLL
if ( m_bThrowingGrenade )
{
UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false );
}
else
{
// Priming the grenade isn't an event.. we just watch the player for it.
// Also play the prime animation first if he wants to throw the grenade.
bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
if ( IsOuterGrenadePrimed() || bThrowPending )
{
if ( !m_bPrimingGrenade )
{
// If this guy just popped into our PVS, and he's got his grenade primed, then
// let's assume that it's all the way primed rather than playing the prime
// animation from the start.
if ( TimeSinceLastAnimationStateClear() < 0.4f )
m_flGrenadeCycle = 1;
else
m_flGrenadeCycle = 0;

m_iGrenadeSequence = CalcGrenadePrimeSequence();
}

m_bPrimingGrenade = true;
UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true );

// If we're waiting to throw and we're done playing the prime animation...
if ( bThrowPending && m_flGrenadeCycle == 1 )
{
m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();

// Now play the throw animation.
m_iGrenadeSequence = CalcGrenadeThrowSequence();
if ( m_iGrenadeSequence != -1 )
{
// Configure to start playing
m_bThrowingGrenade = true;
m_bPrimingGrenade = false;
m_flGrenadeCycle = 0;
}
}
}
else
{
m_bPrimingGrenade = false;
}
}
#endif
}
*/
/*
int CSDKPlayerAnimState::CalcGrenadePrimeSequence()
{
return CalcSequenceIndex( "idle_shoot_gren1" );
}


int CSDKPlayerAnimState::CalcGrenadeThrowSequence()
{
return CalcSequenceIndex( "idle_shoot_gren2" );
}


int CSDKPlayerAnimState::GetOuterGrenadeThrowCounter()
{
CHL2MP_Player *pPlayer = dynamic_cast<CHL2MP_Player*>( m_pOuter );
if ( pPlayer )
return pPlayer->m_iThrowGrenadeCounter;
else
return 0;
}
*/

void CSDKPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr )
{
#ifdef CLIENT_DLL
UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false );
#else
// Server doesn't bother with different fire sequences.
#endif
}


int CSDKPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
{
const char *pSuffix = GetWeaponSuffix();
if ( !pSuffix )
return 0;

if ( bForceIdle )
{
switch ( GetCurrentMainSequenceActivity() )
{
case ACT_CROUCHIDLE:
return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );

default:
return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
}
}
else
{
switch ( GetCurrentMainSequenceActivity() )
{
case ACT_RUN:
return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix );

case ACT_WALK:
case ACT_RUNTOIDLE:
case ACT_IDLETORUN:
return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix );

case ACT_CROUCHIDLE:
return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );

case ACT_RUN_CROUCH:
return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix );

case ACT_IDLE:
default:
return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
}
}
}


const char* CSDKPlayerAnimState::GetWeaponSuffix()
{
// Figure out the weapon suffix.
CWeaponTOSBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
if ( !pWeapon )
return "Pistol";

const char *pSuffix = pWeapon->GetTOSWpnData().m_szAnimExtension;

return pSuffix;
}


int CSDKPlayerAnimState::CalcFireLayerSequence(PlayerA nimEvent_t event)
{
// Figure out the weapon suffix.
CWeaponTOSBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
if ( !pWeapon )
return 0;

const char *pSuffix = GetWeaponSuffix();
if ( !pSuffix )
return 0;

// Don't rely on their weapon here because the player has usually switched to their
// pistol or rifle by the time the PLAYERANIMEVENT_THROW_GRENADE message gets to the client.
if ( event == PLAYERANIMEVENT_THROW_GRENADE )
{
pSuffix = "Gren";
}

switch ( GetCurrentMainSequenceActivity() )
{
case ACT_PLAYER_RUN_FIRE:
case ACT_RUN:
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix );

case ACT_PLAYER_WALK_FIRE:
case ACT_WALK:
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix );

case ACT_PLAYER_CROUCH_FIRE:
case ACT_CROUCHIDLE:
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix );

case ACT_PLAYER_CROUCH_WALK_FIRE:
case ACT_RUN_CROUCH:
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix );

default:
case ACT_PLAYER_IDLE_FIRE:
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix );
}
}


bool CSDKPlayerAnimState::CanThePlayerMove()
{
return m_pHelpers->SDKAnim_CanMove();
}


float CSDKPlayerAnimState::GetCurrentMaxGroundSpeed()
{
Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() );
if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE )
return ANIM_TOPSPEED_WALK;
else if ( currentActivity == ACT_RUN )
return ANIM_TOPSPEED_RUN;
else if ( currentActivity == ACT_RUN_CROUCH )
return ANIM_TOPSPEED_RUN_CROUCH;
else
return 0;
}


bool CSDKPlayerAnimState::HandleJumping()
{
if ( m_bJumping )
{
if ( m_bFirstJumpFrame )
{
m_bFirstJumpFrame = false;
RestartMainSequence(); // Reset the animation.
}

// Don't check if he's on the ground for a sec.. sometimes the client still has the
// on-ground flag set right when the message comes in.
if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
{
if ( m_pOuter->GetFlags() & FL_ONGROUND )
{
m_bJumping = false;
RestartMainSequence(); // Reset the animation.
}
}
}

// Are we still jumping? If so, keep playing the jump animation.
return m_bJumping;
}


Activity CSDKPlayerAnimState::CalcMainActivity()
{
float flOuterSpeed = GetOuterXYSpeed();

if ( HandleJumping() )
{
return ACT_HOP;
}
else
{
Activity idealActivity = ACT_IDLE;

if ( m_pOuter->GetFlags() & FL_DUCKING )
{
if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
idealActivity = ACT_RUN_CROUCH;
else
idealActivity = ACT_CROUCHIDLE;
}
else
{
if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
{
if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
idealActivity = ACT_RUN;
else
idealActivity = ACT_WALK;
}
else
{
idealActivity = ACT_IDLE;
}
}

return idealActivity;
}
}


void CSDKPlayerAnimState::DebugShowAnimState( int iStartLine )
{
#ifdef CLIENT_DLL
engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle );
engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle );
BaseClass::DebugShowAnimState( iStartLine );
#endif
}


void CSDKPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
{
BaseClass::ComputeSequences( pStudioHdr );

ComputeFireSequence( pStudioHdr );
ComputeReloadSequence( pStudioHdr );
ComputeGrenadeSequence( pStudioHdr );
}


void CSDKPlayerAnimState::ClearAnimationLayers()
{
if ( !m_pOuter )
return;

m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
{
m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
}
}


void CSDKPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr )
{
#ifdef CLIENT_DLL
UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
#else
// Server doesn't bother with different fire sequences.
#endif
}

here is the .h

//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//================================================== ===========================//

#ifndef SDK_PLAYERANIMSTATE_H
#define SDK_PLAYERANIMSTATE_H
#ifdef _WIN32
#pragma once
#endif


#include "convar.h"
#include "iplayeranimstate.h"
#include "base_playeranimstate.h"


#ifdef CLIENT_DLL
class C_BaseAnimatingOverlay;
class C_WeaponTOSBase;
#define CBaseAnimatingOverlay C_BaseAnimatingOverlay
#define CWeaponTOSBase C_WeaponTOSBase
#define CHL2MP_Player C_HL2MP_Player
#else
class CBaseAnimatingOverlay;
class CWeaponTOSBase;
class CHL2MP_Player;
#endif


// When moving this fast, he plays run anim.
#define ARBITRARY_RUN_SPEED 175.0f


enum PlayerAnimEvent_t
{
PLAYERANIMEVENT_FIRE_GUN_PRIMARY=0,
PLAYERANIMEVENT_FIRE_GUN_SECONDARY,
PLAYERANIMEVENT_THROW_GRENADE,
PLAYERANIMEVENT_JUMP,
PLAYERANIMEVENT_RELOAD,

PLAYERANIMEVENT_COUNT
};


class ISDKPlayerAnimState : virtual public IPlayerAnimState
{
public:
// 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 DoAnimationEvent( PlayerAnimEvent_t event ) = 0;

// Returns true if we're playing the grenade prime or throw animation.
//virtual bool IsThrowingGrenade() = 0;
};


// This abstracts the differences between SDK players and hostages.
class ISDKPlayerAnimStateHelpers
{
public:
virtual CWeaponTOSBase* SDKAnim_GetActiveWeapon() = 0;
virtual bool SDKAnim_CanMove() = 0;
};


ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );

// 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 // SDK_PLAYERANIMSTATE_H


I haven't yet got to test this, but "sdk_playeranimstate.h"
is only included in sdk_player and weapon_sdkbase. So shouldn't be long till this work. I did remove the nade animation code for now. I'll get that later.

StuD-tos
06-25-2007, 02:18 AM
On to my next step. I noticed sdk_player has multiple inheritance. I tried to make hl2mp_player inherit public ISDKPlayerAnimStateHelpers. Didn't work. I go to hl2_player
add

#include "tos_playeranimstate.h"

and

class CHL2_Player : public CBasePlayer, public ISDKPlayerAnimStateHelpers

It compiled, but now we have multiple inheritance for hl2_player.
In sdk_player.h i see

// This passes the event to the client's and server's CPlayerAnimState.
void DoAnimationEvent( PlayerAnimEvent_t event );

and

// ISDKPlayerAnimState overrides.
virtual CWeaponSDKBase* SDKAnim_GetActiveWeapon();
virtual bool SDKAnim_CanMove();

The last thing I see that I think is relevant is under private:

ISDKPlayerAnimState *m_PlayerAnimState;

Next I'm gonna check these out and see if I can get them into hl2_player.cpp and compile. Looks like I'm getting closer.

StuD-tos
06-27-2007, 06:35 AM
Okay.. I have modified hl2mp_player, c_hl2mp_player, hl2mp_player_shared, added weapon_sdkbase, added sdk_playeranimstate, modified hl2mp_weapon parse to have
"PlayerAnimationExtension". Now, when I create the object

CreatePlayerAnimState( this, this, LEGANIM_9WAY, true );
}

in the hl2mp_player.cpp and c_hl2mp_player.cpp the game crashes. I get an assert

void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len )
{

Assert( pVec->Count() == pVecIV->Count() );

and here

void C_BaseEntity::RemoveVar( void *data, bool bAssert )
{
if ( bAssert )
{
Assert( !"RemoveVar" );
}

here

void CUtlVector<T, A>::RemoveMultiple( int elem, int num )
{
Assert( elem + num <= Count() );

here

inline T& CUtlVector<T, A>::Element( int i )
{
Assert( IsValidIndex(i) );

and then the game finally crashes here

inline void Destruct( T* pMemory )
{
pMemory->~T();

#ifdef _DEBUG
memset( pMemory, 0xDD, sizeof(T) );
#endif
}

I see something about "C_AnimationLayer*" and "expression cannot be evaluated" - CInterpolatedVarArrayBase<C_AnimationLayer> {m_pValue=??? m_VarHistory={m_pFirst=??? m_nElems=??? } m_LastNetworkedValue=??? ...} CInterpolatedVarArrayBase<C_AnimationLayer>

Any ideas?