2023-10-03 14:23:56 +00:00
|
|
|
|
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
2020-04-22 16:56:21 +00:00
|
|
|
|
//
|
|
|
|
|
// Purpose:
|
|
|
|
|
//
|
|
|
|
|
//=============================================================================//
|
|
|
|
|
|
|
|
|
|
#ifndef RAGDOLL_SHARED_H
|
|
|
|
|
#define RAGDOLL_SHARED_H
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#pragma once
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
class IPhysicsObject;
|
|
|
|
|
class IPhysicsConstraint;
|
|
|
|
|
class IPhysicsConstraintGroup;
|
|
|
|
|
class IPhysicsCollision;
|
|
|
|
|
class IPhysicsEnvironment;
|
|
|
|
|
class IPhysicsSurfaceProps;
|
|
|
|
|
struct matrix3x4_t;
|
|
|
|
|
|
|
|
|
|
struct vcollide_t;
|
|
|
|
|
struct studiohdr_t;
|
|
|
|
|
class CStudioHdr;
|
|
|
|
|
class CBoneAccessor;
|
|
|
|
|
|
|
|
|
|
#include "mathlib/vector.h"
|
|
|
|
|
#include "bone_accessor.h"
|
2023-10-03 14:23:56 +00:00
|
|
|
|
#include "vcollide_parse.h"
|
2020-04-22 16:56:21 +00:00
|
|
|
|
|
|
|
|
|
// UNDONE: Remove and make dynamic?
|
2023-10-03 14:23:56 +00:00
|
|
|
|
#define RAGDOLL_MAX_ELEMENTS 32
|
2020-04-22 16:56:21 +00:00
|
|
|
|
#define RAGDOLL_INDEX_BITS 5 // NOTE 1<<RAGDOLL_INDEX_BITS >= RAGDOLL_MAX_ELEMENTS
|
|
|
|
|
|
|
|
|
|
#define CORE_DISSOLVE_FADE_START 0.2f
|
|
|
|
|
#define CORE_DISSOLVE_MODEL_FADE_START 0.1f
|
|
|
|
|
#define CORE_DISSOLVE_MODEL_FADE_LENGTH 0.05f
|
|
|
|
|
#define CORE_DISSOLVE_FADEIN_LENGTH 0.1f
|
|
|
|
|
|
|
|
|
|
struct ragdollelement_t
|
|
|
|
|
{
|
|
|
|
|
Vector originParentSpace;
|
|
|
|
|
IPhysicsObject *pObject; // all valid elements have an object
|
|
|
|
|
IPhysicsConstraint *pConstraint; // all valid elements have a constraint (except the root)
|
|
|
|
|
int parentIndex;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ragdoll_t
|
|
|
|
|
{
|
2022-03-01 20:00:42 +00:00
|
|
|
|
int listCount;
|
2020-04-22 16:56:21 +00:00
|
|
|
|
bool allowStretch;
|
|
|
|
|
bool unused;
|
|
|
|
|
IPhysicsConstraintGroup *pGroup;
|
|
|
|
|
// store these in separate arrays for save/load
|
|
|
|
|
ragdollelement_t list[RAGDOLL_MAX_ELEMENTS];
|
|
|
|
|
int boneIndex[RAGDOLL_MAX_ELEMENTS];
|
|
|
|
|
ragdollanimatedfriction_t animfriction;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ragdollparams_t
|
|
|
|
|
{
|
|
|
|
|
void *pGameData;
|
|
|
|
|
vcollide_t *pCollide;
|
|
|
|
|
CStudioHdr *pStudioHdr;
|
|
|
|
|
int modelIndex;
|
|
|
|
|
Vector forcePosition;
|
|
|
|
|
Vector forceVector;
|
|
|
|
|
int forceBoneIndex;
|
|
|
|
|
const matrix3x4_t *pCurrentBones;
|
|
|
|
|
float jointFrictionScale;
|
|
|
|
|
bool allowStretch;
|
2023-10-03 14:23:56 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CRagdollEntry
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
CRagdollEntry( CBaseAnimating *pRagdoll, float flForcedRetireTime ) : m_hRagdoll( pRagdoll ), m_flForcedRetireTime( flForcedRetireTime )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
CBaseAnimating* Get() { return m_hRagdoll.Get(); }
|
|
|
|
|
float GetForcedRetireTime() { return m_flForcedRetireTime; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
CHandle<CBaseAnimating> m_hRagdoll;
|
|
|
|
|
float m_flForcedRetireTime;
|
2020-04-22 16:56:21 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// This hooks the main game systems callbacks to allow the AI system to manage memory
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
class CRagdollLRURetirement : public CAutoGameSystemPerFrame
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
CRagdollLRURetirement( char const *name ) : CAutoGameSystemPerFrame( name )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Methods of IGameSystem
|
|
|
|
|
virtual void Update( float frametime );
|
|
|
|
|
virtual void FrameUpdatePostEntityThink( void );
|
|
|
|
|
|
|
|
|
|
// Move it to the top of the LRU
|
2023-10-03 14:23:56 +00:00
|
|
|
|
void MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant = false, float flForcedRetireTime = 0.0f );
|
2020-04-22 16:56:21 +00:00
|
|
|
|
void SetMaxRagdollCount( int iMaxCount ){ m_iMaxRagdolls = iMaxCount; }
|
|
|
|
|
|
|
|
|
|
virtual void LevelInitPreEntity( void );
|
|
|
|
|
int CountRagdolls( bool bOnlySimulatingRagdolls ) { return bOnlySimulatingRagdolls ? m_iSimulatedRagdollCount : m_iRagdollCount; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
typedef CHandle<CBaseAnimating> CRagdollHandle;
|
2023-10-03 14:23:56 +00:00
|
|
|
|
CUtlLinkedList< CRagdollEntry > m_LRU;
|
|
|
|
|
CUtlLinkedList< CRagdollEntry > m_LRUImportantRagdolls;
|
2020-04-22 16:56:21 +00:00
|
|
|
|
|
|
|
|
|
int m_iMaxRagdolls;
|
|
|
|
|
int m_iSimulatedRagdollCount;
|
|
|
|
|
int m_iRagdollCount;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern CRagdollLRURetirement s_RagdollLRU;
|
|
|
|
|
|
|
|
|
|
// Manages ragdolls fading for the low violence versions
|
|
|
|
|
class CRagdollLowViolenceManager
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
CRagdollLowViolenceManager(){ m_bLowViolence = false; }
|
|
|
|
|
// Turn the low violence ragdoll stuff off if we're in the HL2 Citadel maps because
|
|
|
|
|
// the player has the super gravity gun and fading ragdolls will break things.
|
|
|
|
|
void SetLowViolence( const char *pMapName );
|
|
|
|
|
bool IsLowViolence( void ){ return m_bLowViolence; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool m_bLowViolence;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern CRagdollLowViolenceManager g_RagdollLVManager;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool RagdollCreate( ragdoll_t &ragdoll, const ragdollparams_t ¶ms, IPhysicsEnvironment *pPhysEnv );
|
|
|
|
|
|
|
|
|
|
void RagdollActivate( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex, bool bForceWake = true );
|
|
|
|
|
void RagdollSetupCollisions( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex );
|
|
|
|
|
void RagdollDestroy( ragdoll_t &ragdoll );
|
|
|
|
|
|
|
|
|
|
// Gets the bone matrix for a ragdoll object
|
|
|
|
|
// NOTE: This is different than the object's position because it is
|
|
|
|
|
// forced to be rigidly attached in parent space
|
|
|
|
|
bool RagdollGetBoneMatrix( const ragdoll_t &ragdoll, CBoneAccessor &pBoneToWorld, int objectIndex );
|
|
|
|
|
|
|
|
|
|
// Parse the ragdoll and obtain the mapping from each physics element index to a bone index
|
|
|
|
|
// returns num phys elements
|
|
|
|
|
int RagdollExtractBoneIndices( int *boneIndexOut, CStudioHdr *pStudioHdr, vcollide_t *pCollide );
|
|
|
|
|
|
|
|
|
|
// computes an exact bbox of the ragdoll's physics objects
|
|
|
|
|
void RagdollComputeExactBbox( const ragdoll_t &ragdoll, const Vector &origin, Vector &outMins, Vector &outMaxs );
|
2023-10-03 14:23:56 +00:00
|
|
|
|
void RagdollComputeApproximateBbox( const ragdoll_t &ragdoll, const Vector &origin, Vector &outMins, Vector &outMaxs );
|
2020-04-22 16:56:21 +00:00
|
|
|
|
bool RagdollIsAsleep( const ragdoll_t &ragdoll );
|
|
|
|
|
void RagdollSetupAnimatedFriction( IPhysicsEnvironment *pPhysEnv, ragdoll_t *ragdoll, int iModelIndex );
|
|
|
|
|
|
|
|
|
|
void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, const matrix3x4_t *pBoneToWorld );
|
|
|
|
|
void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, const matrix3x4_t *pPrevBones, const matrix3x4_t *pCurrentBones, float dt );
|
|
|
|
|
|
|
|
|
|
void RagdollSolveSeparation( ragdoll_t &ragdoll, CBaseEntity *pEntity );
|
|
|
|
|
|
|
|
|
|
#endif // RAGDOLL_SHARED_H
|