mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-02-05 02:00:34 +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_nPrevSequence = -1;
|
||||||
m_nRestoreSequence = -1;
|
m_nRestoreSequence = -1;
|
||||||
m_pRagdoll = NULL;
|
m_pRagdoll = NULL;
|
||||||
|
m_pClientsideRagdoll = NULL;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_pServerRagdoll = NULL;
|
||||||
|
#endif
|
||||||
m_builtRagdoll = false;
|
m_builtRagdoll = false;
|
||||||
m_hitboxBoneCacheHandle = 0;
|
m_hitboxBoneCacheHandle = 0;
|
||||||
int i;
|
int i;
|
||||||
@ -4948,26 +4952,26 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
|
|||||||
{
|
{
|
||||||
MoveToLastReceivedPosition( true );
|
MoveToLastReceivedPosition( true );
|
||||||
GetAbsOrigin();
|
GetAbsOrigin();
|
||||||
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
|
m_pClientsideRagdoll = CreateRagdollCopy();
|
||||||
|
|
||||||
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
|
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
|
||||||
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
|
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
|
||||||
matrix3x4_t currentBones[MAXSTUDIOBONES];
|
matrix3x4_t currentBones[MAXSTUDIOBONES];
|
||||||
const float boneDt = 0.1f;
|
const float boneDt = 0.1f;
|
||||||
GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
|
GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||||
pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
m_pClientsideRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
// Hook for ragdolling
|
// Hook for ragdolling
|
||||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
|
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
|
||||||
{
|
{
|
||||||
// ragdoll
|
// ragdoll
|
||||||
ScriptVariant_t args[] = { ScriptVariant_t( pRagdoll->GetScriptInstance() ) };
|
ScriptVariant_t args[] = { ScriptVariant_t( m_pClientsideRagdoll->GetScriptInstance() ) };
|
||||||
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
|
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
|
||||||
}
|
}
|
||||||
#endif
|
#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 )
|
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:
|
public:
|
||||||
CRagdoll *m_pRagdoll;
|
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
|
// Texture group to use
|
||||||
int m_nSkin;
|
int m_nSkin;
|
||||||
|
@ -25,6 +25,13 @@ extern ConVar r_drawmodeldecals;
|
|||||||
|
|
||||||
ImpactSoundRouteFn g_pImpactSoundRouteFn = NULL;
|
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
|
// RAGDOLL ENUMERATOR
|
||||||
//==========================================================================================================================
|
//==========================================================================================================================
|
||||||
@ -32,7 +39,11 @@ CRagdollEnumerator::CRagdollEnumerator( Ray_t& shot, int iDamageType )
|
|||||||
{
|
{
|
||||||
m_rayShot = shot;
|
m_rayShot = shot;
|
||||||
m_iDamageType = iDamageType;
|
m_iDamageType = iDamageType;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_pHitEnt = NULL;
|
||||||
|
#else
|
||||||
m_bHit = false;
|
m_bHit = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity )
|
IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity )
|
||||||
@ -57,7 +68,11 @@ IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity
|
|||||||
if ( tr.fraction < 1.0 )
|
if ( tr.fraction < 1.0 )
|
||||||
{
|
{
|
||||||
pModel->ImpactTrace( &tr, m_iDamageType, NULL );
|
pModel->ImpactTrace( &tr, m_iDamageType, NULL );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_pHitEnt = pModel;
|
||||||
|
#else
|
||||||
m_bHit = true;
|
m_bHit = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
//FIXME: Yes? No?
|
//FIXME: Yes? No?
|
||||||
return ITERATION_STOP;
|
return ITERATION_STOP;
|
||||||
@ -84,6 +99,22 @@ bool FX_AffectRagdolls( Vector vecOrigin, Vector vecStart, int iDamageType )
|
|||||||
return ragdollEnum.Hit();
|
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:
|
// Purpose:
|
||||||
// Input : &data -
|
// Input : &data -
|
||||||
@ -104,6 +135,22 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
|
|||||||
|
|
||||||
Assert ( pEntity );
|
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
|
// Clear out the trace
|
||||||
memset( &tr, 0, sizeof(trace_t));
|
memset( &tr, 0, sizeof(trace_t));
|
||||||
tr.fraction = 1.0f;
|
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 );
|
VectorMA( vecStart, flLength + 8.0f, shotDir, traceExt );
|
||||||
|
|
||||||
// Attempt to hit ragdolls
|
// Attempt to hit ragdolls
|
||||||
|
|
||||||
bool bHitRagdoll = false;
|
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() )
|
if ( !pEntity->IsClientCreated() )
|
||||||
{
|
{
|
||||||
bHitRagdoll = FX_AffectRagdolls( vecOrigin, vecStart, iDamageType );
|
bHitRagdoll = FX_AffectRagdolls( vecOrigin, vecStart, iDamageType );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( (nFlags & IMPACT_NODECAL) == 0 )
|
if ( (nFlags & IMPACT_NODECAL) == 0 )
|
||||||
{
|
{
|
||||||
|
@ -58,12 +58,21 @@ public:
|
|||||||
// Actual work code
|
// Actual work code
|
||||||
virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
|
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; }
|
bool Hit( void ) const { return m_bHit; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ray_t m_rayShot;
|
Ray_t m_rayShot;
|
||||||
int m_iDamageType;
|
int m_iDamageType;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
C_BaseAnimating *m_pHitEnt;
|
||||||
|
#else
|
||||||
bool m_bHit;
|
bool m_bHit;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FX_IMPACT_H
|
#endif // FX_IMPACT_H
|
||||||
|
@ -487,6 +487,9 @@ int C_ServerRagdoll::InternalDrawModel( int flags )
|
|||||||
return ret;
|
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 )
|
CStudioHdr *C_ServerRagdoll::OnNewModel( void )
|
||||||
{
|
{
|
||||||
@ -509,6 +512,26 @@ CStudioHdr *C_ServerRagdoll::OnNewModel( void )
|
|||||||
m_iv_ragAngles.SetMaxCount( m_elementCount );
|
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;
|
return hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user