|
|
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef BASEANIMATING_H
#define BASEANIMATING_H
#ifdef _WIN32
#pragma once
#endif
#include "entityoutput.h"
#include "studio.h"
#include "bone_merge_cache.h"
#include "datacache/idatacache.h"
#include "tier0/threadtools.h"
struct animevent_t; struct matrix3x4_t; class CIKContext; class KeyValues; class CAnimationLayer; FORWARD_DECLARE_HANDLE( memhandle_t );
#define BCF_NO_ANIMATION_SKIP ( 1 << 0 ) // Do not allow PVS animation skipping (mostly for attachments being critical to an entity)
#define BCF_IS_IN_SPAWN ( 1 << 1 ) // Is currently inside of spawn, always evaluate animations
extern IDataCache *datacache;
class CBaseAnimating : public CBaseEntity { public: DECLARE_CLASS( CBaseAnimating, CBaseEntity );
CBaseAnimating(); ~CBaseAnimating();
DECLARE_PREDICTABLE();
enum { NUM_POSEPAREMETERS = 24, NUM_BONECTRLS = 4 };
DECLARE_DATADESC(); DECLARE_SERVERCLASS(); DECLARE_ENT_SCRIPTDESC();
virtual void SetModel( const char *szModelName ); virtual void Activate(); virtual void Spawn(); virtual void Precache(); virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
virtual int Restore( IRestore &restore ); virtual void OnRestore();
CStudioHdr *GetModelPtr( void ); virtual void InvalidateMdlCache() { UnlockStudioHdr(); delete m_pStudioHdr; m_pStudioHdr = NULL; }
virtual CBaseAnimating* GetBaseAnimating() { return this; }
// Cycle access
void ForceCycle( float flCycle ); void SetCycle( float flCycle ); float GetCycle() const;
float GetAnimTimeInterval( void ) const;
// Call this in your constructor to tell it that you will not use animtime. Then the
// interpolation will be done correctly on the client.
// This defaults to off.
void UseClientSideAnimation();
// Tells whether or not we're using client-side animation. Used for controlling
// the transmission of animtime.
bool IsUsingClientSideAnimation() { return m_bClientSideAnimation; }
// Basic NPC Animation functions
virtual float GetIdealSpeed( ) const; virtual float GetIdealAccel( ) const; virtual void StudioFrameAdvance(); // advance animation frame to some time in the future
void StudioFrameAdvanceManual( float flInterval ); bool IsValidSequence( int iSequence ); virtual void ReachedEndOfSequence() { return; }
inline float GetPlaybackRate() const; inline void SetPlaybackRate( float rate );
inline int GetSequence() { return m_nSequence; } // inline void SetSequence(int nSequence) { Assert( GetModelPtr( ) && nSequence >= 0 && nSequence < GetModelPtr( )->GetNumSeq() ); m_nSequence = nSequence; }
void SetSequence(int nSequence); virtual void OnSequenceSet( int nOldSequence ) {} /* inline */ void ResetSequence(int nSequence); // FIXME: push transitions support down into CBaseAnimating?
virtual bool IsActivityFinished( void ) { return m_bSequenceFinished; } inline bool IsSequenceFinished( void ) { return m_bSequenceFinished; } inline bool SequenceLoops( void ) { return m_bSequenceLoops; } bool IsSequenceLooping( CStudioHdr *pStudioHdr, int iSequence ); inline bool IsSequenceLooping( int iSequence ) { return IsSequenceLooping(GetModelPtr(),iSequence); } inline float SequenceDuration( void ) { return SequenceDuration( m_nSequence ); } float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence ); inline float SequenceDuration( int iSequence ) { return SequenceDuration(GetModelPtr(), iSequence); } float GetSequenceCycleRate( CStudioHdr *pStudioHdr, int iSequence ); inline float GetSequenceCycleRate( int iSequence ) { return GetSequenceCycleRate(GetModelPtr(),iSequence); } float GetLastVisibleCycle( CStudioHdr *pStudioHdr, int iSequence ); virtual float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence ); inline float GetSequenceGroundSpeed( int iSequence ) { return GetSequenceGroundSpeed(GetModelPtr(), iSequence); } virtual float GetLayerSequenceCycleRate( CAnimationLayer *pLayer, int iSequence ) { return GetSequenceCycleRate(GetModelPtr(),iSequence); } void ResetActivityIndexes ( void ); void ResetEventIndexes ( void ); int SelectWeightedSequence ( Activity activity ); int SelectWeightedSequence ( Activity activity, int curSequence ); int SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount ); int SelectHeaviestSequence ( Activity activity ); int LookupActivity( const char *label ); int LookupSequence ( const char *label ); int LookupSequence ( CStudioHdr* pHdr, const char *label ); float GetFirstSequenceAnimTag( int sequence, int nDesiredTag, float flStart = 0, float flEnd = 1 ); float GetAnySequenceAnimTag( int sequence, int nDesiredTag, float flDefault ); KeyValues *GetSequenceKeyValues( int iSequence );
float GetSequenceMoveYaw( int iSequence ); float GetSequenceMoveDist( CStudioHdr *pStudioHdr, int iSequence ); inline float GetSequenceMoveDist( int iSequence ) { return GetSequenceMoveDist(GetModelPtr(),iSequence);} void GetSequenceLinearMotion( int iSequence, Vector *pVec ); const char *GetSequenceName( int iSequence ); const char *GetSequenceActivityName( int iSequence ); Activity GetSequenceActivity( int iSequence );
void ResetSequenceInfo ( ); // This will stop animation until you call ResetSequenceInfo() at some point in the future
inline void StopAnimation( void ) { m_flPlaybackRate = 0; }
virtual void ClampRagdollForce( const Vector &vecForceIn, Vector *vecForceOut ) { *vecForceOut = vecForceIn; } // Base class does nothing.
virtual bool BecomeRagdollOnClient( const Vector &force ); virtual bool IsRagdoll(); virtual bool CanBecomeRagdoll( void ); //Check if this entity will ragdoll when dead.
virtual void GetSkeleton( CStudioHdr *pStudioHdr, BoneVector pos[], BoneQuaternionAligned q[], int boneMask );
virtual void GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld ); virtual void SetupBones( matrix3x4a_t *pBoneToWorld, int boneMask ); virtual void CalculateIKLocks( float currentTime ); virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity, bool bUseSlowHighAccuracyContacts = true );
bool HasAnimEvent( int nSequence, int nEvent ); virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future
virtual void HandleAnimEvent( animevent_t *pEvent ); virtual bool HandleScriptedAnimEvent( animevent_t *pEvent ) { return false; } virtual bool HandleBehaviorAnimEvent( animevent_t *pEvent ) { return false; }
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName ); inline int LookupPoseParameter( const char *szName ) { return LookupPoseParameter(GetModelPtr(), szName); }
float SetPoseParameter( CStudioHdr *pStudioHdr, const char *szName, float flValue ); inline float SetPoseParameter( const char *szName, float flValue ) { return SetPoseParameter( GetModelPtr(), szName, flValue ); } float SetPoseParameter( CStudioHdr *pStudioHdr, int iParameter, float flValue ); inline float SetPoseParameter( int iParameter, float flValue ) { return SetPoseParameter( GetModelPtr(), iParameter, flValue ); }
float GetPoseParameter( const char *szName ); float GetPoseParameter( int iParameter ); bool GetPoseParameterRange( int index, float &minValue, float &maxValue ); bool HasPoseParameter( int iSequence, const char *szName ); bool HasPoseParameter( int iSequence, int iParameter ); float EdgeLimitPoseParameter( int iParameter, float flValue, float flBase = 0.0f );
protected: // The modus operandi for pose parameters is that you should not use the const char * version of the functions
// in general code -- it causes many many string comparisons, which is slower than you think. Better is to
// save off your pose parameters in member variables in your derivation of this function:
virtual void PopulatePoseParameters( void );
private: CBoneMergeCache *m_pBoneMergeCache;
public:
CBaseAnimating* FindFollowedEntity();
int LookupBone( const char *szName ); void GetBonePosition( const char *szName, Vector &origin, QAngle &angles ); void GetBonePosition( int iBone, Vector &origin, QAngle &angles ); void GetHitboxBonePosition( int iBone, Vector &origin, QAngle &angles, QAngle hitboxOrientation ); void GetHitboxBoneTransform( int iBone, QAngle hitboxOrientation, matrix3x4_t &pOut );
int GetPhysicsBone( int boneIndex );
int GetNumBones ( void );
int FindTransitionSequence( int iCurrentSequence, int iGoalSequence, int *piDir ); bool GotoSequence( int iCurrentSequence, float flCurrentCycle, float flCurrentRate, int iGoalSequence, int &iNextSequence, float &flCycle, int &iDir ); int GetEntryNode( int iSequence ); int GetExitNode( int iSequence ); void GetEyeballs( Vector &origin, QAngle &angles ); // ?? remove ??
int LookupAttachment( const char *szName );
// These return the attachment in world space
bool GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles ); bool GetAttachment( int iAttachment, Vector &absOrigin, QAngle &absAngles ); int GetAttachmentBone( int iAttachment ); virtual bool GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld ); const Vector& ScriptGetAttachmentOrigin( int iAttachment ); const Vector& ScriptGetAttachmentAngles( int iAttachment );
// These return the attachment in the space of the entity
bool GetAttachmentLocal( const char *szName, Vector &origin, QAngle &angles ); bool GetAttachmentLocal( int iAttachment, Vector &origin, QAngle &angles ); bool GetAttachmentLocal( int iAttachment, matrix3x4_t &attachmentToLocal ); // Non-angle versions of the attachments in world space
bool GetAttachment( const char *szName, Vector &absOrigin, Vector *forward = NULL, Vector *right = NULL, Vector *up = NULL ); bool GetAttachment( int iAttachment, Vector &absOrigin, Vector *forward = NULL, Vector *right = NULL, Vector *up = NULL );
void SetBodygroup( int iGroup, int iValue ); int GetBodygroup( int iGroup ); void SetBodygroupPreset( char const *szName ); int GetSkin() { return m_nSkin; }
const char *GetBodygroupName( int iGroup ); int FindBodygroupByName( const char *name ); const char *GetBodygroupPartName( int iGroup, int iPart ); int GetBodygroupCount( int iGroup ); int GetNumBodyGroups( void ); int CountBodyGroupVariants( int group ); int FindBodyGroupVariant( int group, int variant ); ///< Find undamaged bodygroup part index
int FindDamagedBodyGroupVariant( int group ); ///< Find a damaged version of the current part for the given bodygroup
void RandomizeBodygroups( CUtlVector< const char * >& groups );
void SetHitboxSet( int setnum ); void SetHitboxSetByName( const char *setname ); int GetHitboxSet( void ); char const *GetHitboxSetName( void ); int GetHitboxSetCount( void ); int GetHitboxBone( int hitboxIndex ); bool LookupHitbox( const char *szName, int& outSet, int& outBox );
// Computes a box that surrounds all hitboxes
bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Computes a box that surrounds a single hitboxes
bool ComputeHitboxSurroundingBox( int iHitbox, Vector *pVecWorldMins, Vector *pVecWorldMaxs ); // Clone a CBaseAnimating from another (copies model & sequence data)
void CopyAnimationDataFrom( CBaseAnimating *pSource );
int ExtractBbox( int sequence, Vector& mins, Vector& maxs ); void SetSequenceBox( void ); int RegisterPrivateActivity( const char *pszActivityName );
void ResetClientsideFrame( void );
// Controllers.
virtual void InitBoneControllers ( void ); // Return's the controller's angle/position in bone space.
float GetBoneController ( int iController );
// Maps the angle/position value you specify into the bone's start/end and sets the specified controller to the value.
float SetBoneController ( int iController, float flValue ); void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity);
// these two need to move somewhere else
LocalFlexController_t GetNumFlexControllers( void ); const char *GetFlexDescFacs( int iFlexDesc ); const char *GetFlexControllerName( LocalFlexController_t iFlexController ); const char *GetFlexControllerType( LocalFlexController_t iFlexController );
virtual Vector GetGroundSpeedVelocity( void );
bool GetIntervalMovement( float flIntervalUsed, bool &bMoveSeqFinished, Vector &newPosition, QAngle &newAngles ); bool GetSequenceMovement( int nSequence, float fromCycle, float toCycle, Vector &deltaPosition, QAngle &deltaAngles ); float GetInstantaneousVelocity( float flInterval = 0.0 ); float GetEntryVelocity( int iSequence ); float GetExitVelocity( int iSequence ); float GetMovementFrame( float flDist ); bool HasMovement( int iSequence );
void ReportMissingActivity( int iActivity ); virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); class CBoneCache *GetBoneCache( void ); virtual void InvalidateBoneCache( void ); virtual int DrawDebugTextOverlays( void ); virtual bool IsViewModel() const { return false; } // See note in code re: bandwidth usage!!!
void DrawServerHitboxes( float duration = 0.0f, bool monocolor = false ); void DrawRawSkeleton( matrix3x4_t boneToWorld[], int boneMask, bool noDepthTest = true, float duration = 0.0f, bool monocolor = false );
void SetModelScale( float scale, float change_duration = 0.0f, ModelScaleType_t scaleType = HIERARCHICAL_MODEL_SCALE ); float GetModelScale() const; float GetModelHierarchyScale(); // Get the overall scale of the entire hierarchy (model scale can be local, per-bone)
ModelScaleType_t GetModelScaleType() const; void SetModelScaleType( ModelScaleType_t scaleType );
void UpdateModelScale(); // also calculate IK on server? (always done on client)
void EnableServerIK(); void DisableServerIK();
// for ragdoll vs. car
int GetHitboxesFrontside( int *boxList, int boxMax, const Vector &normal, float dist );
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
// Send a muzzle flash event to the client for this entity.
void DoMuzzleFlash();
// Fire
virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); virtual void IgniteLifetime( float flFlameLifetime ); virtual void IgniteUseCheapEffect( bool bUseCheapEffect ); virtual void Extinguish() { RemoveFlag( FL_ONFIRE ); } bool IsOnFire() { return ( (GetFlags() & FL_ONFIRE) != 0 ); } void Scorch( int rate, int floor ); void InputIgnite( inputdata_t &inputdata ); void InputIgniteLifetime( inputdata_t &inputdata ); void InputIgniteNumHitboxFires( inputdata_t &inputdata ); void InputIgniteHitboxFireScale( inputdata_t &inputdata ); void InputBecomeRagdoll( inputdata_t &inputdata );
// Ice
virtual bool IsFrozen( void ) { return m_flFrozen >= 1.0f; } float GetFrozenAmount( void ) const { return m_flFrozen; } float GetFrozenThawRate( void ) { return m_flFrozenThawRate; } void Thaw( float flThawAmount ); void ToggleFreeze(void); virtual void Freeze( float flFreezeAmount = -1.0f, CBaseEntity *pFreezer = NULL, Ray_t *pFreezeRay = NULL ); virtual void Unfreeze();
// Dissolve, returns true if the ragdoll has been created
virtual bool Dissolve( const char *pMaterialName, float flStartTime, bool bNPCOnly = true, int nDissolveType = 0, Vector vDissolverOrigin = vec3_origin, int iMagnitude = 0 ); bool IsDissolving() { return ( (GetFlags() & FL_DISSOLVING) != 0 ); } void TransferDissolveFrom( CBaseAnimating *pAnim );
// animation needs
float m_flGroundSpeed; // computed linear movement rate for current sequence
float m_flLastEventCheck; // cycle index of when events were last checked
virtual void SetLightingOriginRelative( CBaseEntity *pLightingOriginRelative ); void SetLightingOriginRelative( string_t strLightingOriginRelative ); CBaseEntity *GetLightingOriginRelative();
virtual void SetLightingOrigin( CBaseEntity *pLightingOrigin ); void SetLightingOrigin( string_t strLightingOrigin ); CBaseEntity *GetLightingOrigin();
const float* GetPoseParameterArray() { return m_flPoseParameter.Base(); } const float* GetEncodedControllerArray() { return m_flEncodedController.Base(); }
void SetFadeDistance( float minFadeDist, float maxFadeDist );
int GetBoneCacheFlags( void ) { return m_fBoneCacheFlags; } inline void SetBoneCacheFlags( unsigned short fFlag ) { m_fBoneCacheFlags |= fFlag; } inline void ClearBoneCacheFlags( unsigned short fFlag ) { m_fBoneCacheFlags &= ~fFlag; }
bool PrefetchSequence( int iSequence );
#ifdef PORTAL2
virtual void OnFizzled( void ); #endif // PORTAL2
private: void LockStudioHdr(); void UnlockStudioHdr();
void StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flInterval ); void InputSetLightingOriginRelative( inputdata_t &inputdata ); void InputSetLightingOrigin( inputdata_t &inputdata );
public: bool CanSkipAnimation( void );
#ifdef PORTAL2
public: void SetObjectScaleLevel( int nScaleLevel ) { m_nObjectScaleLevel = nScaleLevel; } int GetObjectScaleLevel( void ) { return m_nObjectScaleLevel; } protected: int m_nObjectScaleLevel; bool m_bCanBeCaptured; // Set true this prop allows capture by weapon_camera
#endif // PORTAL2
public:
CNetworkVar( int, m_nForceBone ); CNetworkVector( m_vecForce );
CNetworkVar( int, m_nSkin ); CNetworkVar( int, m_nBody ); CNetworkVar( int, m_nHitboxSet );
// For making things thin during barnacle swallowing, e.g.
CNetworkVar( float, m_flModelScale );
// was pev->framerate
CNetworkVar( float, m_flPlaybackRate );
private: CNetworkVar( ModelScaleType_t, m_ScaleType );
public: void InitStepHeightAdjust( void ); void SetIKGroundContactInfo( float minHeight, float maxHeight ); void UpdateStepOrigin( void );
protected: float m_flIKGroundContactTime; float m_flIKGroundMinHeight; float m_flIKGroundMaxHeight;
float m_flEstIkFloor; // debounced
float m_flEstIkOffset;
CIKContext *m_pIk; int m_iIKCounter;
public: Vector GetStepOrigin( void ) const; QAngle GetStepAngles( void ) const;
protected: bool m_bSequenceFinished;// flag set when StudioAdvanceFrame moves across a frame boundry
bool m_bSequenceLoops; // true if the sequence loops
float m_flDissolveStartTime;
IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_bClientSideRagdoll );
// was pev->frame
CNetworkVar( float, m_flCycle ); CNetworkVar( int, m_nSequence ); CNetworkArray( float, m_flPoseParameter, NUM_POSEPAREMETERS ); // must be private so manual mode works!
CNetworkArray( float, m_flEncodedController, NUM_BONECTRLS ); // bone controller setting (0..1)
// Client-side animation (useful for looping animation objects)
CNetworkVar( bool, m_bClientSideAnimation ); CNetworkVar( bool, m_bClientSideFrameReset );
CNetworkVar( int, m_nNewSequenceParity ); CNetworkVar( int, m_nResetEventsParity );
CNetworkVar( bool, m_bSuppressAnimSounds );
// Incremented each time the entity is told to do a muzzle flash.
// The client picks up the change and draws the flash.
CNetworkVar( unsigned char, m_nMuzzleFlashParity );
CNetworkHandle( CBaseEntity, m_hLightingOrigin ); CNetworkHandle( CBaseEntity, m_hLightingOriginRelative );
string_t m_iszLightingOriginRelative; // for reading from the file only
string_t m_iszLightingOrigin; // for reading from the file only
memhandle_t m_boneCacheHandle; unsigned short m_fBoneCacheFlags; // Used for bone cache state on model
CNetworkVar( float, m_flFrozen ); // 0 - 1 amount that the model is frozen
float m_flMovementFrozen; // How frozen are the movement parts
float m_flAttackFrozen; // How frozen are the attacking parts
float m_flFrozenThawRate; // amount it unfreezes per second
float m_flFrozenMax; // maximum amount this entitiy is allowed to freeze
public: COutputEvent m_OnIgnite;
#if defined ( PORTAL2 )
COutputEvent m_OnFizzled; // Fizzled by a fizzler
#endif // PORTAL2
private: CStudioHdr *m_pStudioHdr; CThreadFastMutex m_StudioHdrInitLock; CThreadFastMutex m_BoneSetupMutex;
// FIXME: necessary so that cyclers can hack m_bSequenceFinished
friend class CBaseAnimatingOverlay; friend class CFlexCycler; friend class CCycler; friend class CBlendingCycler; };
//-----------------------------------------------------------------------------
// Purpose: return a pointer to an updated studiomdl cache cache
//-----------------------------------------------------------------------------
inline CStudioHdr *CBaseAnimating::GetModelPtr( void ) { #ifdef _DEBUG
#ifndef _GAMECONSOLE
// Consoles don't need to lock the modeldata cache since it never flushes
// GetModelPtr() is often called before OnNewModel() so go ahead and set it up first chance.
static IDataCacheSection *pModelCache = g_pDataCache->FindSection( "ModelData" ); AssertOnce( pModelCache->IsFrameLocking() ); #endif
#endif
if ( !m_pStudioHdr && GetModel() ) { LockStudioHdr(); } return ( m_pStudioHdr && m_pStudioHdr->IsValid() ) ? m_pStudioHdr : NULL; }
//-----------------------------------------------------------------------------
// Purpose: Serves the 90% case of calling SetSequence / ResetSequenceInfo.
//-----------------------------------------------------------------------------
/*
inline void CBaseAnimating::ResetSequence(int nSequence) { if ( nSequence != m_nSequence ) { m_nSequence = nSequence; InvalidatePhysicsRecursive( SEQUENCE_CHANGED ); } ResetSequenceInfo(); } */
inline float CBaseAnimating::GetPlaybackRate() const { #if defined( PORTAL2 )
return m_flPlaybackRate * ( 1.0f / sqrt( GetModelScaleType() == HIERARCHICAL_MODEL_SCALE ? GetModelScale() : 1.0f ) ); #endif // PORTAL2or INFESTED
// Slow the animation while partially frozen
return m_flPlaybackRate * clamp( 1.0f - m_flFrozen, 0.0f, 1.0f ); }
inline void CBaseAnimating::SetPlaybackRate( float rate ) { // if we start going in a new direction, the current animation isn't finished anymore
m_bSequenceFinished = false; m_flPlaybackRate = rate; }
inline void CBaseAnimating::SetLightingOrigin( CBaseEntity *pLightingOrigin ) { m_hLightingOrigin = pLightingOrigin; }
inline CBaseEntity *CBaseAnimating::GetLightingOrigin() { return m_hLightingOrigin; }
inline void CBaseAnimating::SetLightingOriginRelative( CBaseEntity *pLightingOriginRelative ) { m_hLightingOriginRelative = pLightingOriginRelative; }
inline CBaseEntity *CBaseAnimating::GetLightingOriginRelative() { return m_hLightingOriginRelative; }
//-----------------------------------------------------------------------------
// Cycle access
//-----------------------------------------------------------------------------
inline float CBaseAnimating::GetCycle() const { return m_flCycle; }
inline void CBaseAnimating::SetCycle( float flCycle ) { m_flCycle = flCycle; }
inline void CBaseAnimating::ForceCycle( float flCycle ) { SetCycle( flCycle ); m_flLastEventCheck = flCycle; }
EXTERN_SEND_TABLE(DT_BaseAnimating);
#define ANIMATION_SEQUENCE_BITS 12 // 4096 sequences
#define ANIMATION_SKIN_BITS 10 // 1024 body skin selections FIXME: this seems way high
#define ANIMATION_BODY_BITS 32 // body combinations
#define ANIMATION_HITBOXSET_BITS 2 // hit box sets
#if defined( TF_DLL )
#define ANIMATION_POSEPARAMETER_BITS 8 // pose parameter resolution
#else
#define ANIMATION_POSEPARAMETER_BITS 11 // pose parameter resolution
#endif
#define ANIMATION_PLAYBACKRATE_BITS 8 // default playback rate, only used on leading edge detect sequence changes
#endif // BASEANIMATING_H
|