mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-26 13:47:56 +03:00
Merge pull request #147 from mapbase-source/feature/ragdoll-decal-fixes
Ragdoll decal fixes
This commit is contained in:
commit
6c8e54b31e
@ -784,6 +784,10 @@ C_BaseAnimating::C_BaseAnimating() :
|
||||
m_nPrevSequence = -1;
|
||||
m_nRestoreSequence = -1;
|
||||
m_pRagdoll = NULL;
|
||||
m_pClientsideRagdoll = NULL;
|
||||
#ifdef MAPBASE
|
||||
m_pServerRagdoll = NULL;
|
||||
#endif
|
||||
m_builtRagdoll = false;
|
||||
m_hitboxBoneCacheHandle = 0;
|
||||
int i;
|
||||
@ -4948,26 +4952,26 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
|
||||
{
|
||||
MoveToLastReceivedPosition( true );
|
||||
GetAbsOrigin();
|
||||
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
|
||||
m_pClientsideRagdoll = CreateRagdollCopy();
|
||||
|
||||
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
|
||||
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
|
||||
matrix3x4_t currentBones[MAXSTUDIOBONES];
|
||||
const float boneDt = 0.1f;
|
||||
GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
m_pClientsideRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// Hook for ragdolling
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// ragdoll
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( pRagdoll->GetScriptInstance() ) };
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( m_pClientsideRagdoll->GetScriptInstance() ) };
|
||||
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
|
||||
}
|
||||
#endif
|
||||
|
||||
return pRagdoll;
|
||||
return m_pClientsideRagdoll;
|
||||
}
|
||||
|
||||
bool C_BaseAnimating::InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints )
|
||||
|
@ -531,6 +531,10 @@ private:
|
||||
|
||||
public:
|
||||
CRagdoll *m_pRagdoll;
|
||||
C_BaseAnimating *m_pClientsideRagdoll; // From Alien Swarm SDK
|
||||
#ifdef MAPBASE
|
||||
C_BaseAnimating *m_pServerRagdoll; // Not from Alien Swarm SDK (note that this can exist without the entity having died)
|
||||
#endif
|
||||
|
||||
// Texture group to use
|
||||
int m_nSkin;
|
||||
|
@ -25,6 +25,13 @@ extern ConVar r_drawmodeldecals;
|
||||
|
||||
ImpactSoundRouteFn g_pImpactSoundRouteFn = NULL;
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_ragdoll_steal_impacts_client( "g_ragdoll_steal_impacts_client", "1", FCVAR_NONE, "Allows clientside death ragdolls to \"steal\" impacts from their source entities. This fixes issues with NPCs dying before decals are applied." );
|
||||
ConVar g_ragdoll_steal_impacts_server( "g_ragdoll_steal_impacts_server", "1", FCVAR_NONE, "Allows serverside death ragdolls to \"steal\" impacts from their source entities. This fixes issues with NPCs dying before decals are applied." );
|
||||
|
||||
ConVar g_ragdoll_client_impact_decals( "g_ragdoll_client_impact_decals", "1", FCVAR_NONE, "Applies decals to clientside ragdolls when they are hit." );
|
||||
#endif
|
||||
|
||||
//==========================================================================================================================
|
||||
// RAGDOLL ENUMERATOR
|
||||
//==========================================================================================================================
|
||||
@ -32,7 +39,11 @@ CRagdollEnumerator::CRagdollEnumerator( Ray_t& shot, int iDamageType )
|
||||
{
|
||||
m_rayShot = shot;
|
||||
m_iDamageType = iDamageType;
|
||||
#ifdef MAPBASE
|
||||
m_pHitEnt = NULL;
|
||||
#else
|
||||
m_bHit = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity )
|
||||
@ -57,7 +68,11 @@ IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity
|
||||
if ( tr.fraction < 1.0 )
|
||||
{
|
||||
pModel->ImpactTrace( &tr, m_iDamageType, NULL );
|
||||
#ifdef MAPBASE
|
||||
m_pHitEnt = pModel;
|
||||
#else
|
||||
m_bHit = true;
|
||||
#endif
|
||||
|
||||
//FIXME: Yes? No?
|
||||
return ITERATION_STOP;
|
||||
@ -84,6 +99,22 @@ bool FX_AffectRagdolls( Vector vecOrigin, Vector vecStart, int iDamageType )
|
||||
return ragdollEnum.Hit();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
C_BaseAnimating *FX_AffectRagdolls_GetHit( Vector vecOrigin, Vector vecStart, int iDamageType )
|
||||
{
|
||||
// don't do this when lots of ragdolls are simulating
|
||||
if ( s_RagdollLRU.CountRagdolls(true) > 1 )
|
||||
return false;
|
||||
Ray_t shotRay;
|
||||
shotRay.Init( vecStart, vecOrigin );
|
||||
|
||||
CRagdollEnumerator ragdollEnum( shotRay, iDamageType );
|
||||
partition->EnumerateElementsAlongRay( PARTITION_CLIENT_RESPONSIVE_EDICTS, shotRay, false, &ragdollEnum );
|
||||
|
||||
return ragdollEnum.GetHit();
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
@ -104,6 +135,22 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
|
||||
|
||||
Assert ( pEntity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// If the entity already has a ragdoll that was created on the current tick, use that ragdoll instead.
|
||||
// This allows the killing damage's decals to show up on the ragdoll.
|
||||
if (C_BaseAnimating *pAnimating = pEntity->GetBaseAnimating())
|
||||
{
|
||||
if (pAnimating->m_pClientsideRagdoll && WasRagdollCreatedOnCurrentTick( pAnimating->m_pClientsideRagdoll ) && g_ragdoll_steal_impacts_client.GetBool())
|
||||
{
|
||||
pEntity = pAnimating->m_pClientsideRagdoll;
|
||||
}
|
||||
else if (pAnimating->m_pServerRagdoll && WasRagdollCreatedOnCurrentTick( pAnimating->m_pServerRagdoll ) && g_ragdoll_steal_impacts_server.GetBool())
|
||||
{
|
||||
pEntity = pAnimating->m_pServerRagdoll;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clear out the trace
|
||||
memset( &tr, 0, sizeof(trace_t));
|
||||
tr.fraction = 1.0f;
|
||||
@ -115,13 +162,52 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
|
||||
VectorMA( vecStart, flLength + 8.0f, shotDir, traceExt );
|
||||
|
||||
// Attempt to hit ragdolls
|
||||
|
||||
|
||||
bool bHitRagdoll = false;
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !pEntity->IsClientCreated() )
|
||||
{
|
||||
C_BaseAnimating *pRagdoll = FX_AffectRagdolls_GetHit( vecOrigin, vecStart, iDamageType );
|
||||
if (pRagdoll)
|
||||
{
|
||||
bHitRagdoll = true;
|
||||
|
||||
if (g_ragdoll_client_impact_decals.GetBool())
|
||||
{
|
||||
pEntity = pRagdoll;
|
||||
|
||||
// HACKHACK: Get the ragdoll's nearest bone for its material
|
||||
int iNearestMaterial = 0;
|
||||
float flNearestDistSqr = FLT_MAX;
|
||||
|
||||
IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
|
||||
int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) );
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
Vector vecPosition;
|
||||
QAngle angAngles;
|
||||
pList[i]->GetPosition( &vecPosition, &angAngles );
|
||||
float flDistSqr = (vecStart - vecPosition).LengthSqr();
|
||||
if (flDistSqr < flNearestDistSqr)
|
||||
{
|
||||
iNearestMaterial = pList[i]->GetMaterialIndex();
|
||||
flNearestDistSqr = flDistSqr;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the material from the surfaceprop
|
||||
surfacedata_t *psurfaceData = physprops->GetSurfaceData( iNearestMaterial );
|
||||
iMaterial = psurfaceData->game.material;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ( !pEntity->IsClientCreated() )
|
||||
{
|
||||
bHitRagdoll = FX_AffectRagdolls( vecOrigin, vecStart, iDamageType );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( (nFlags & IMPACT_NODECAL) == 0 )
|
||||
{
|
||||
|
@ -58,12 +58,21 @@ public:
|
||||
// Actual work code
|
||||
virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool Hit( void ) const { return m_pHitEnt != NULL; }
|
||||
C_BaseAnimating *GetHit( void ) { return m_pHitEnt; }
|
||||
#else
|
||||
bool Hit( void ) const { return m_bHit; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
Ray_t m_rayShot;
|
||||
int m_iDamageType;
|
||||
#ifdef MAPBASE
|
||||
C_BaseAnimating *m_pHitEnt;
|
||||
#else
|
||||
bool m_bHit;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FX_IMPACT_H
|
||||
|
@ -487,6 +487,9 @@ int C_ServerRagdoll::InternalDrawModel( int flags )
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
static ConVar g_ragdoll_server_snatch_instance( "g_ragdoll_server_snatch_instance", "1", FCVAR_NONE, "Allows serverside ragdolls to snatch their source entities' model instances in the same way clientside ragdolls do, thereby retaining decals." );
|
||||
#endif
|
||||
|
||||
CStudioHdr *C_ServerRagdoll::OnNewModel( void )
|
||||
{
|
||||
@ -509,6 +512,26 @@ CStudioHdr *C_ServerRagdoll::OnNewModel( void )
|
||||
m_iv_ragAngles.SetMaxCount( m_elementCount );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetOwnerEntity() )
|
||||
{
|
||||
if (GetOwnerEntity()->GetModelName() == GetModelName())
|
||||
{
|
||||
// TODO: Is there a better place for this?
|
||||
if (GetOwnerEntity()->GetBaseAnimating())
|
||||
GetOwnerEntity()->GetBaseAnimating()->m_pServerRagdoll = this;
|
||||
|
||||
if (g_ragdoll_server_snatch_instance.GetBool())
|
||||
{
|
||||
GetOwnerEntity()->SnatchModelInstance( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add server ragdolls to the creation tick list
|
||||
NoteRagdollCreationTick( this );
|
||||
#endif
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user