mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-12 23:07:55 +03:00
Added support for ragdoll prop gibs + related ragdoll LRU forced fade from Alien Swarm SDK
This commit is contained in:
parent
4bc56b214b
commit
cea38f03ec
@ -259,6 +259,9 @@ LINK_ENTITY_TO_CLASS( client_ragdoll, C_ClientRagdoll );
|
||||
BEGIN_DATADESC( C_ClientRagdoll )
|
||||
DEFINE_FIELD( m_bFadeOut, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_bImportant, FIELD_BOOLEAN ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_FIELD( m_flForcedRetireTime, FIELD_FLOAT ),
|
||||
#endif
|
||||
DEFINE_FIELD( m_iCurrentFriction, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_iMinFriction, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_iMaxFriction, FIELD_INTEGER ),
|
||||
@ -377,6 +380,9 @@ C_ClientRagdoll::C_ClientRagdoll( bool bRestoring )
|
||||
m_bFadeOut = false;
|
||||
m_bFadingOut = false;
|
||||
m_bImportant = false;
|
||||
#ifdef MAPBASE
|
||||
m_flForcedRetireTime = 0.0f;
|
||||
#endif
|
||||
m_bNoModelParticles = false;
|
||||
|
||||
SetClassname("client_ragdoll");
|
||||
@ -457,7 +463,11 @@ void C_ClientRagdoll::OnRestore( void )
|
||||
|
||||
if ( m_bFadeOut == true )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant, m_flForcedRetireTime );
|
||||
#else
|
||||
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant );
|
||||
#endif
|
||||
}
|
||||
|
||||
NoteRagdollCreationTick( this );
|
||||
|
@ -737,6 +737,10 @@ public:
|
||||
|
||||
bool m_bFadeOut;
|
||||
bool m_bImportant;
|
||||
#ifdef MAPBASE
|
||||
// Required to save/restore Alien Swarm SDK ragdoll LRU forced fade
|
||||
float m_flForcedRetireTime;
|
||||
#endif
|
||||
float m_flEffectTime;
|
||||
|
||||
private:
|
||||
|
@ -704,9 +704,157 @@ void C_PhysPropClientside::ParseAllEntities(const char *pMapData)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
CBaseAnimating *BreakModelCreate_Ragdoll( CBaseEntity *pOwnerEnt, breakmodel_t *pModel, const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity )
|
||||
{
|
||||
C_BaseAnimating *pOwner = dynamic_cast<C_BaseAnimating *>( pOwnerEnt );
|
||||
if ( !pOwner )
|
||||
return NULL;
|
||||
|
||||
C_ClientRagdoll *pRagdoll = new C_ClientRagdoll( false );
|
||||
if ( pRagdoll == NULL )
|
||||
return NULL;
|
||||
|
||||
const char *pModelName = pModel->modelName;
|
||||
if ( pRagdoll->InitializeAsClientEntity( pModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
|
||||
{
|
||||
pRagdoll->Release();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pRagdoll->SetAbsOrigin( position );
|
||||
pRagdoll->SetAbsAngles( angles );
|
||||
|
||||
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
|
||||
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
|
||||
matrix3x4_t currentBones[MAXSTUDIOBONES];
|
||||
const float boneDt = 0.1f;
|
||||
|
||||
pRagdoll->SetParent( pOwner );
|
||||
pRagdoll->ForceSetupBonesAtTime( boneDelta0, gpGlobals->curtime - boneDt );
|
||||
pRagdoll->ForceSetupBonesAtTime( boneDelta1, gpGlobals->curtime );
|
||||
pRagdoll->ForceSetupBonesAtTime( currentBones, gpGlobals->curtime );
|
||||
pRagdoll->SetParent( NULL );
|
||||
|
||||
// We need to take these from the entity
|
||||
//pRagdoll->SetAbsOrigin( position );
|
||||
//pRagdoll->SetAbsAngles( angles );
|
||||
|
||||
pRagdoll->IgniteRagdoll( pOwner );
|
||||
pRagdoll->TransferDissolveFrom( pOwner );
|
||||
pRagdoll->InitModelEffects();
|
||||
|
||||
if ( pOwner->IsEffectActive( EF_NOSHADOW ) )
|
||||
{
|
||||
pRagdoll->AddEffects( EF_NOSHADOW );
|
||||
}
|
||||
|
||||
pRagdoll->m_nRenderFX = kRenderFxRagdoll;
|
||||
pRagdoll->SetRenderMode( pOwner->GetRenderMode() );
|
||||
pRagdoll->SetRenderColor( pOwner->GetRenderColor().r, pOwner->GetRenderColor().g, pOwner->GetRenderColor().b, pOwner->GetRenderColor().a );
|
||||
//pRagdoll->SetGlobalFadeScale( pOwner->GetGlobalFadeScale() );
|
||||
|
||||
pRagdoll->SetSkin( pOwner->GetSkin() );
|
||||
//pRagdoll->m_vecForce = pOwner->m_vecForce;
|
||||
//pRagdoll->m_nForceBone = 0; //pOwner->m_nForceBone;
|
||||
pRagdoll->SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
|
||||
pRagdoll->SetModelName( AllocPooledString( pModelName ) );
|
||||
pRagdoll->ResetSequence( 0 );
|
||||
pRagdoll->SetModelScale( pOwner->GetModelScale() );
|
||||
pRagdoll->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
|
||||
//pRagdoll->m_builtRagdoll = true;
|
||||
|
||||
CStudioHdr *hdr = pRagdoll->GetModelPtr();
|
||||
if ( !hdr )
|
||||
{
|
||||
pRagdoll->Release();
|
||||
Warning( "Couldn't create ragdoll gib for %s (no model pointer)\n", pModel->modelName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pRagdoll->m_pRagdoll = CreateRagdoll(
|
||||
pRagdoll,
|
||||
hdr,
|
||||
vec3_origin,
|
||||
0,
|
||||
boneDelta0,
|
||||
boneDelta1,
|
||||
currentBones,
|
||||
boneDt );
|
||||
|
||||
if ( !pRagdoll->m_pRagdoll )
|
||||
{
|
||||
pRagdoll->Release();
|
||||
Warning( "Couldn't create ragdoll gib for %s\n", pModel->modelName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IPhysicsObject *pPhysicsObject = pRagdoll->VPhysicsGetObject();
|
||||
if ( pPhysicsObject )
|
||||
{
|
||||
// randomize velocity by 5%
|
||||
float rndf = RandomFloat( -0.025, 0.025 );
|
||||
Vector rndVel = velocity + rndf*velocity;
|
||||
|
||||
pPhysicsObject->AddVelocity( &rndVel, &angVelocity );
|
||||
}
|
||||
pRagdoll->ApplyLocalAngularVelocityImpulse( angVelocity );
|
||||
|
||||
if ( pRagdoll->m_pRagdoll )
|
||||
{
|
||||
pRagdoll->m_bImportant = false;
|
||||
pRagdoll->m_flForcedRetireTime = pModel->fadeTime > 0.0f ? gpGlobals->curtime + pModel->fadeTime : 0.0f;
|
||||
s_RagdollLRU.MoveToTopOfLRU( pRagdoll, pRagdoll->m_bImportant, pRagdoll->m_flForcedRetireTime );
|
||||
pRagdoll->m_bFadeOut = true;
|
||||
}
|
||||
|
||||
// Cause the entity to recompute its shadow type and make a
|
||||
// version which only updates when physics state changes
|
||||
// NOTE: We have to do this after m_pRagdoll is assigned above
|
||||
// because that's what ShadowCastType uses to figure out which type of shadow to use.
|
||||
pRagdoll->DestroyShadow();
|
||||
pRagdoll->CreateShadow();
|
||||
|
||||
pRagdoll->SetAbsOrigin( position );
|
||||
pRagdoll->SetAbsAngles( angles );
|
||||
|
||||
pRagdoll->SetPlaybackRate( 0 );
|
||||
pRagdoll->SetCycle( 0 );
|
||||
|
||||
// put into ACT_DIERAGDOLL if it exists, otherwise use sequence 0
|
||||
int nSequence = pRagdoll->SelectWeightedSequence( ACT_DIERAGDOLL );
|
||||
if ( nSequence < 0 )
|
||||
{
|
||||
pRagdoll->ResetSequence( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
pRagdoll->ResetSequence( nSequence );
|
||||
}
|
||||
|
||||
pRagdoll->UpdatePartitionListEntry();
|
||||
pRagdoll->MarkRenderHandleDirty();
|
||||
|
||||
NoteRagdollCreationTick( pRagdoll );
|
||||
|
||||
//pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
|
||||
return pRagdoll;
|
||||
}
|
||||
#endif
|
||||
|
||||
CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position,
|
||||
const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, int nSkin, const breakablepropparams_t ¶ms )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if ( pModel->isRagdoll )
|
||||
{
|
||||
CBaseEntity *pEntity = BreakModelCreate_Ragdoll( pOwner, pModel, position, angles, velocity, angVelocity );
|
||||
return pEntity;
|
||||
}
|
||||
#endif
|
||||
|
||||
C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew();
|
||||
|
||||
if ( !pEntity )
|
||||
@ -778,10 +926,12 @@ CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel,
|
||||
pEntity->SetFadeMinMax( pModel->fadeMinDist, pModel->fadeMaxDist );
|
||||
}
|
||||
|
||||
#ifndef MAPBASE
|
||||
if ( pModel->isRagdoll )
|
||||
{
|
||||
DevMsg( "BreakModelCreateSingle: clientside doesn't support ragdoll breakmodels.\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();
|
||||
|
@ -830,6 +830,33 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
|
||||
m_iRagdollCount = 0;
|
||||
m_iSimulatedRagdollCount = 0;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
// remove ragdolls with a forced retire time
|
||||
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
|
||||
{
|
||||
next = m_LRU.Next(i);
|
||||
|
||||
CBaseAnimating *pRagdoll = m_LRU[i].Get();
|
||||
|
||||
//Just ignore it until we're done burning/dissolving.
|
||||
if ( pRagdoll && pRagdoll->GetEffectEntity() )
|
||||
continue;
|
||||
|
||||
// ignore if it's not time to force retire this ragdoll
|
||||
if ( m_LRU[i].GetForcedRetireTime() == 0.0f || gpGlobals->curtime < m_LRU[i].GetForcedRetireTime() )
|
||||
continue;
|
||||
|
||||
//Msg(" Removing ragdoll %s due to forced retire time of %f (now = %f)\n", pRagdoll->GetModelName(), m_LRU[i].GetForcedRetireTime(), gpGlobals->curtime );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
pRagdoll->SUB_Remove();
|
||||
#else
|
||||
pRagdoll->SUB_StartFadeOut( 0 );
|
||||
#endif
|
||||
m_LRU.Remove(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
// First, find ragdolls that are good candidates for deletion because they are not
|
||||
// visible at all, or are in a culled visibility box
|
||||
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
|
||||
@ -847,12 +874,12 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
|
||||
if ( m_LRU.Count() > iMaxRagdollCount )
|
||||
{
|
||||
//Found one, we're done.
|
||||
if ( ShouldRemoveThisRagdoll( m_LRU[i] ) == true )
|
||||
if ( ShouldRemoveThisRagdoll( pRagdoll ) == true )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
m_LRU[ i ]->SUB_Remove();
|
||||
pRagdoll->SUB_Remove();
|
||||
#else
|
||||
m_LRU[ i ]->SUB_StartFadeOut( 0 );
|
||||
pRagdoll->SUB_StartFadeOut( 0 );
|
||||
#endif
|
||||
|
||||
m_LRU.Remove(i);
|
||||
@ -933,10 +960,11 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
|
||||
}
|
||||
}
|
||||
|
||||
CBaseAnimating *pRemoveRagdoll = m_LRU[ furthestOne ].Get();
|
||||
#ifdef CLIENT_DLL
|
||||
m_LRU[ furthestOne ]->SUB_Remove();
|
||||
pRemoveRagdoll->SUB_Remove();
|
||||
#else
|
||||
m_LRU[ furthestOne ]->SUB_StartFadeOut( 0 );
|
||||
pRemoveRagdoll->SUB_StartFadeOut( 0 );
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -957,9 +985,9 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
|
||||
continue;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
m_LRU[ i ]->SUB_Remove();
|
||||
pRagdoll->SUB_Remove();
|
||||
#else
|
||||
m_LRU[ i ]->SUB_StartFadeOut( 0 );
|
||||
pRagdoll->SUB_StartFadeOut( 0 );
|
||||
#endif
|
||||
m_LRU.Remove(i);
|
||||
}
|
||||
@ -989,6 +1017,33 @@ void CRagdollLRURetirement::Update( float frametime ) // Non-episodic version
|
||||
m_iRagdollCount = 0;
|
||||
m_iSimulatedRagdollCount = 0;
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
// remove ragdolls with a forced retire time
|
||||
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
|
||||
{
|
||||
next = m_LRU.Next(i);
|
||||
|
||||
CBaseAnimating *pRagdoll = m_LRU[i].Get();
|
||||
|
||||
//Just ignore it until we're done burning/dissolving.
|
||||
if ( pRagdoll && pRagdoll->GetEffectEntity() )
|
||||
continue;
|
||||
|
||||
// ignore if it's not time to force retire this ragdoll
|
||||
if ( m_LRU[i].GetForcedRetireTime() == 0.0f || gpGlobals->curtime < m_LRU[i].GetForcedRetireTime() )
|
||||
continue;
|
||||
|
||||
//Msg(" Removing ragdoll %s due to forced retire time of %f (now = %f)\n", pRagdoll->GetModelName(), m_LRU[i].GetForcedRetireTime(), gpGlobals->curtime );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
pRagdoll->SUB_Remove();
|
||||
#else
|
||||
pRagdoll->SUB_StartFadeOut( 0 );
|
||||
#endif
|
||||
m_LRU.Remove(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
|
||||
{
|
||||
next = m_LRU.Next(i);
|
||||
@ -1074,11 +1129,19 @@ ConVar g_ragdoll_important_maxcount( "g_ragdoll_important_maxcount", "2", FCVAR_
|
||||
//-----------------------------------------------------------------------------
|
||||
// Move it to the top of the LRU
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant, float flForcedRetireTime )
|
||||
#else
|
||||
void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant )
|
||||
#endif
|
||||
{
|
||||
if ( bImportant )
|
||||
{
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_LRUImportantRagdolls.AddToTail( CRagdollEntry( pRagdoll, flForcedRetireTime ) );
|
||||
#else
|
||||
m_LRUImportantRagdolls.AddToTail( pRagdoll );
|
||||
#endif
|
||||
|
||||
if ( m_LRUImportantRagdolls.Count() > g_ragdoll_important_maxcount.GetInt() )
|
||||
{
|
||||
@ -1108,7 +1171,11 @@ void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImpo
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
m_LRU.AddToTail( CRagdollEntry( pRagdoll, flForcedRetireTime ) );
|
||||
#else
|
||||
m_LRU.AddToTail( pRagdoll );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,6 +83,22 @@ struct ragdollparams_t
|
||||
bool fixedConstraints;
|
||||
};
|
||||
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
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;
|
||||
};
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This hooks the main game systems callbacks to allow the AI system to manage memory
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -98,7 +114,11 @@ public:
|
||||
virtual void FrameUpdatePostEntityThink( void );
|
||||
|
||||
// Move it to the top of the LRU
|
||||
#ifdef MAPBASE // From Alien Swarm SDK
|
||||
void MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant = false, float flForcedRetireTime = 0.0f );
|
||||
#else
|
||||
void MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant = false );
|
||||
#endif
|
||||
void SetMaxRagdollCount( int iMaxCount ){ m_iMaxRagdolls = iMaxCount; }
|
||||
|
||||
virtual void LevelInitPreEntity( void );
|
||||
@ -106,8 +126,13 @@ public:
|
||||
|
||||
private:
|
||||
typedef CHandle<CBaseAnimating> CRagdollHandle;
|
||||
#ifdef MAPBASE
|
||||
CUtlLinkedList< CRagdollEntry > m_LRU;
|
||||
CUtlLinkedList< CRagdollEntry > m_LRUImportantRagdolls;
|
||||
#else
|
||||
CUtlLinkedList< CRagdollHandle > m_LRU;
|
||||
CUtlLinkedList< CRagdollHandle > m_LRUImportantRagdolls;
|
||||
#endif
|
||||
|
||||
int m_iMaxRagdolls;
|
||||
int m_iSimulatedRagdollCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user