Skip to content

Commit cea38f0

Browse files
committed
Added support for ragdoll prop gibs + related ragdoll LRU forced fade from Alien Swarm SDK
1 parent 4bc56b2 commit cea38f0

File tree

5 files changed

+263
-7
lines changed

5 files changed

+263
-7
lines changed

sp/src/game/client/c_baseanimating.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ LINK_ENTITY_TO_CLASS( client_ragdoll, C_ClientRagdoll );
259259
BEGIN_DATADESC( C_ClientRagdoll )
260260
DEFINE_FIELD( m_bFadeOut, FIELD_BOOLEAN ),
261261
DEFINE_FIELD( m_bImportant, FIELD_BOOLEAN ),
262+
#ifdef MAPBASE
263+
DEFINE_FIELD( m_flForcedRetireTime, FIELD_FLOAT ),
264+
#endif
262265
DEFINE_FIELD( m_iCurrentFriction, FIELD_INTEGER ),
263266
DEFINE_FIELD( m_iMinFriction, FIELD_INTEGER ),
264267
DEFINE_FIELD( m_iMaxFriction, FIELD_INTEGER ),
@@ -377,6 +380,9 @@ C_ClientRagdoll::C_ClientRagdoll( bool bRestoring )
377380
m_bFadeOut = false;
378381
m_bFadingOut = false;
379382
m_bImportant = false;
383+
#ifdef MAPBASE
384+
m_flForcedRetireTime = 0.0f;
385+
#endif
380386
m_bNoModelParticles = false;
381387

382388
SetClassname("client_ragdoll");
@@ -457,7 +463,11 @@ void C_ClientRagdoll::OnRestore( void )
457463

458464
if ( m_bFadeOut == true )
459465
{
466+
#ifdef MAPBASE
467+
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant, m_flForcedRetireTime );
468+
#else
460469
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant );
470+
#endif
461471
}
462472

463473
NoteRagdollCreationTick( this );

sp/src/game/client/c_baseanimating.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,10 @@ class C_ClientRagdoll : public C_BaseAnimating, public IPVSNotify
737737

738738
bool m_bFadeOut;
739739
bool m_bImportant;
740+
#ifdef MAPBASE
741+
// Required to save/restore Alien Swarm SDK ragdoll LRU forced fade
742+
float m_flForcedRetireTime;
743+
#endif
740744
float m_flEffectTime;
741745

742746
private:

sp/src/game/client/physpropclientside.cpp

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,9 +704,157 @@ void C_PhysPropClientside::ParseAllEntities(const char *pMapData)
704704
}
705705
}
706706

707+
#ifdef MAPBASE
708+
CBaseAnimating *BreakModelCreate_Ragdoll( CBaseEntity *pOwnerEnt, breakmodel_t *pModel, const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity )
709+
{
710+
C_BaseAnimating *pOwner = dynamic_cast<C_BaseAnimating *>( pOwnerEnt );
711+
if ( !pOwner )
712+
return NULL;
713+
714+
C_ClientRagdoll *pRagdoll = new C_ClientRagdoll( false );
715+
if ( pRagdoll == NULL )
716+
return NULL;
717+
718+
const char *pModelName = pModel->modelName;
719+
if ( pRagdoll->InitializeAsClientEntity( pModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
720+
{
721+
pRagdoll->Release();
722+
return NULL;
723+
}
724+
725+
pRagdoll->SetAbsOrigin( position );
726+
pRagdoll->SetAbsAngles( angles );
727+
728+
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
729+
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
730+
matrix3x4_t currentBones[MAXSTUDIOBONES];
731+
const float boneDt = 0.1f;
732+
733+
pRagdoll->SetParent( pOwner );
734+
pRagdoll->ForceSetupBonesAtTime( boneDelta0, gpGlobals->curtime - boneDt );
735+
pRagdoll->ForceSetupBonesAtTime( boneDelta1, gpGlobals->curtime );
736+
pRagdoll->ForceSetupBonesAtTime( currentBones, gpGlobals->curtime );
737+
pRagdoll->SetParent( NULL );
738+
739+
// We need to take these from the entity
740+
//pRagdoll->SetAbsOrigin( position );
741+
//pRagdoll->SetAbsAngles( angles );
742+
743+
pRagdoll->IgniteRagdoll( pOwner );
744+
pRagdoll->TransferDissolveFrom( pOwner );
745+
pRagdoll->InitModelEffects();
746+
747+
if ( pOwner->IsEffectActive( EF_NOSHADOW ) )
748+
{
749+
pRagdoll->AddEffects( EF_NOSHADOW );
750+
}
751+
752+
pRagdoll->m_nRenderFX = kRenderFxRagdoll;
753+
pRagdoll->SetRenderMode( pOwner->GetRenderMode() );
754+
pRagdoll->SetRenderColor( pOwner->GetRenderColor().r, pOwner->GetRenderColor().g, pOwner->GetRenderColor().b, pOwner->GetRenderColor().a );
755+
//pRagdoll->SetGlobalFadeScale( pOwner->GetGlobalFadeScale() );
756+
757+
pRagdoll->SetSkin( pOwner->GetSkin() );
758+
//pRagdoll->m_vecForce = pOwner->m_vecForce;
759+
//pRagdoll->m_nForceBone = 0; //pOwner->m_nForceBone;
760+
pRagdoll->SetNextClientThink( CLIENT_THINK_ALWAYS );
761+
762+
pRagdoll->SetModelName( AllocPooledString( pModelName ) );
763+
pRagdoll->ResetSequence( 0 );
764+
pRagdoll->SetModelScale( pOwner->GetModelScale() );
765+
pRagdoll->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
766+
//pRagdoll->m_builtRagdoll = true;
767+
768+
CStudioHdr *hdr = pRagdoll->GetModelPtr();
769+
if ( !hdr )
770+
{
771+
pRagdoll->Release();
772+
Warning( "Couldn't create ragdoll gib for %s (no model pointer)\n", pModel->modelName );
773+
return NULL;
774+
}
775+
776+
pRagdoll->m_pRagdoll = CreateRagdoll(
777+
pRagdoll,
778+
hdr,
779+
vec3_origin,
780+
0,
781+
boneDelta0,
782+
boneDelta1,
783+
currentBones,
784+
boneDt );
785+
786+
if ( !pRagdoll->m_pRagdoll )
787+
{
788+
pRagdoll->Release();
789+
Warning( "Couldn't create ragdoll gib for %s\n", pModel->modelName );
790+
return NULL;
791+
}
792+
793+
IPhysicsObject *pPhysicsObject = pRagdoll->VPhysicsGetObject();
794+
if ( pPhysicsObject )
795+
{
796+
// randomize velocity by 5%
797+
float rndf = RandomFloat( -0.025, 0.025 );
798+
Vector rndVel = velocity + rndf*velocity;
799+
800+
pPhysicsObject->AddVelocity( &rndVel, &angVelocity );
801+
}
802+
pRagdoll->ApplyLocalAngularVelocityImpulse( angVelocity );
803+
804+
if ( pRagdoll->m_pRagdoll )
805+
{
806+
pRagdoll->m_bImportant = false;
807+
pRagdoll->m_flForcedRetireTime = pModel->fadeTime > 0.0f ? gpGlobals->curtime + pModel->fadeTime : 0.0f;
808+
s_RagdollLRU.MoveToTopOfLRU( pRagdoll, pRagdoll->m_bImportant, pRagdoll->m_flForcedRetireTime );
809+
pRagdoll->m_bFadeOut = true;
810+
}
811+
812+
// Cause the entity to recompute its shadow type and make a
813+
// version which only updates when physics state changes
814+
// NOTE: We have to do this after m_pRagdoll is assigned above
815+
// because that's what ShadowCastType uses to figure out which type of shadow to use.
816+
pRagdoll->DestroyShadow();
817+
pRagdoll->CreateShadow();
818+
819+
pRagdoll->SetAbsOrigin( position );
820+
pRagdoll->SetAbsAngles( angles );
821+
822+
pRagdoll->SetPlaybackRate( 0 );
823+
pRagdoll->SetCycle( 0 );
824+
825+
// put into ACT_DIERAGDOLL if it exists, otherwise use sequence 0
826+
int nSequence = pRagdoll->SelectWeightedSequence( ACT_DIERAGDOLL );
827+
if ( nSequence < 0 )
828+
{
829+
pRagdoll->ResetSequence( 0 );
830+
}
831+
else
832+
{
833+
pRagdoll->ResetSequence( nSequence );
834+
}
835+
836+
pRagdoll->UpdatePartitionListEntry();
837+
pRagdoll->MarkRenderHandleDirty();
838+
839+
NoteRagdollCreationTick( pRagdoll );
840+
841+
//pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
842+
843+
return pRagdoll;
844+
}
845+
#endif
846+
707847
CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position,
708848
const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, int nSkin, const breakablepropparams_t &params )
709849
{
850+
#ifdef MAPBASE
851+
if ( pModel->isRagdoll )
852+
{
853+
CBaseEntity *pEntity = BreakModelCreate_Ragdoll( pOwner, pModel, position, angles, velocity, angVelocity );
854+
return pEntity;
855+
}
856+
#endif
857+
710858
C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew();
711859

712860
if ( !pEntity )
@@ -778,10 +926,12 @@ CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel,
778926
pEntity->SetFadeMinMax( pModel->fadeMinDist, pModel->fadeMaxDist );
779927
}
780928

929+
#ifndef MAPBASE
781930
if ( pModel->isRagdoll )
782931
{
783932
DevMsg( "BreakModelCreateSingle: clientside doesn't support ragdoll breakmodels.\n" );
784933
}
934+
#endif
785935

786936

787937
IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();

sp/src/game/shared/ragdoll_shared.cpp

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,33 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
830830
m_iRagdollCount = 0;
831831
m_iSimulatedRagdollCount = 0;
832832

833+
#ifdef MAPBASE // From Alien Swarm SDK
834+
// remove ragdolls with a forced retire time
835+
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
836+
{
837+
next = m_LRU.Next(i);
838+
839+
CBaseAnimating *pRagdoll = m_LRU[i].Get();
840+
841+
//Just ignore it until we're done burning/dissolving.
842+
if ( pRagdoll && pRagdoll->GetEffectEntity() )
843+
continue;
844+
845+
// ignore if it's not time to force retire this ragdoll
846+
if ( m_LRU[i].GetForcedRetireTime() == 0.0f || gpGlobals->curtime < m_LRU[i].GetForcedRetireTime() )
847+
continue;
848+
849+
//Msg(" Removing ragdoll %s due to forced retire time of %f (now = %f)\n", pRagdoll->GetModelName(), m_LRU[i].GetForcedRetireTime(), gpGlobals->curtime );
850+
851+
#ifdef CLIENT_DLL
852+
pRagdoll->SUB_Remove();
853+
#else
854+
pRagdoll->SUB_StartFadeOut( 0 );
855+
#endif
856+
m_LRU.Remove(i);
857+
}
858+
#endif
859+
833860
// First, find ragdolls that are good candidates for deletion because they are not
834861
// visible at all, or are in a culled visibility box
835862
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
@@ -847,12 +874,12 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
847874
if ( m_LRU.Count() > iMaxRagdollCount )
848875
{
849876
//Found one, we're done.
850-
if ( ShouldRemoveThisRagdoll( m_LRU[i] ) == true )
877+
if ( ShouldRemoveThisRagdoll( pRagdoll ) == true )
851878
{
852879
#ifdef CLIENT_DLL
853-
m_LRU[ i ]->SUB_Remove();
880+
pRagdoll->SUB_Remove();
854881
#else
855-
m_LRU[ i ]->SUB_StartFadeOut( 0 );
882+
pRagdoll->SUB_StartFadeOut( 0 );
856883
#endif
857884

858885
m_LRU.Remove(i);
@@ -933,10 +960,11 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
933960
}
934961
}
935962

963+
CBaseAnimating *pRemoveRagdoll = m_LRU[ furthestOne ].Get();
936964
#ifdef CLIENT_DLL
937-
m_LRU[ furthestOne ]->SUB_Remove();
965+
pRemoveRagdoll->SUB_Remove();
938966
#else
939-
m_LRU[ furthestOne ]->SUB_StartFadeOut( 0 );
967+
pRemoveRagdoll->SUB_StartFadeOut( 0 );
940968
#endif
941969

942970
}
@@ -957,9 +985,9 @@ void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION
957985
continue;
958986

959987
#ifdef CLIENT_DLL
960-
m_LRU[ i ]->SUB_Remove();
988+
pRagdoll->SUB_Remove();
961989
#else
962-
m_LRU[ i ]->SUB_StartFadeOut( 0 );
990+
pRagdoll->SUB_StartFadeOut( 0 );
963991
#endif
964992
m_LRU.Remove(i);
965993
}
@@ -989,6 +1017,33 @@ void CRagdollLRURetirement::Update( float frametime ) // Non-episodic version
9891017
m_iRagdollCount = 0;
9901018
m_iSimulatedRagdollCount = 0;
9911019

1020+
#ifdef MAPBASE // From Alien Swarm SDK
1021+
// remove ragdolls with a forced retire time
1022+
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
1023+
{
1024+
next = m_LRU.Next(i);
1025+
1026+
CBaseAnimating *pRagdoll = m_LRU[i].Get();
1027+
1028+
//Just ignore it until we're done burning/dissolving.
1029+
if ( pRagdoll && pRagdoll->GetEffectEntity() )
1030+
continue;
1031+
1032+
// ignore if it's not time to force retire this ragdoll
1033+
if ( m_LRU[i].GetForcedRetireTime() == 0.0f || gpGlobals->curtime < m_LRU[i].GetForcedRetireTime() )
1034+
continue;
1035+
1036+
//Msg(" Removing ragdoll %s due to forced retire time of %f (now = %f)\n", pRagdoll->GetModelName(), m_LRU[i].GetForcedRetireTime(), gpGlobals->curtime );
1037+
1038+
#ifdef CLIENT_DLL
1039+
pRagdoll->SUB_Remove();
1040+
#else
1041+
pRagdoll->SUB_StartFadeOut( 0 );
1042+
#endif
1043+
m_LRU.Remove(i);
1044+
}
1045+
#endif
1046+
9921047
for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next )
9931048
{
9941049
next = m_LRU.Next(i);
@@ -1074,11 +1129,19 @@ ConVar g_ragdoll_important_maxcount( "g_ragdoll_important_maxcount", "2", FCVAR_
10741129
//-----------------------------------------------------------------------------
10751130
// Move it to the top of the LRU
10761131
//-----------------------------------------------------------------------------
1132+
#ifdef MAPBASE // From Alien Swarm SDK
1133+
void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant, float flForcedRetireTime )
1134+
#else
10771135
void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant )
1136+
#endif
10781137
{
10791138
if ( bImportant )
10801139
{
1140+
#ifdef MAPBASE // From Alien Swarm SDK
1141+
m_LRUImportantRagdolls.AddToTail( CRagdollEntry( pRagdoll, flForcedRetireTime ) );
1142+
#else
10811143
m_LRUImportantRagdolls.AddToTail( pRagdoll );
1144+
#endif
10821145

10831146
if ( m_LRUImportantRagdolls.Count() > g_ragdoll_important_maxcount.GetInt() )
10841147
{
@@ -1108,7 +1171,11 @@ void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImpo
11081171
}
11091172
}
11101173

1174+
#ifdef MAPBASE // From Alien Swarm SDK
1175+
m_LRU.AddToTail( CRagdollEntry( pRagdoll, flForcedRetireTime ) );
1176+
#else
11111177
m_LRU.AddToTail( pRagdoll );
1178+
#endif
11121179
}
11131180

11141181

0 commit comments

Comments
 (0)