Merge pull request #297 from Blixibon/mapbase/feature/useable-ragdolls

Add capability to +USE serverside ragdolls and toggle cleanup of individual ragdolls
This commit is contained in:
Blixibon 2025-01-02 08:31:09 -06:00 committed by GitHub
commit da44d97951
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 139 additions and 9 deletions

View File

@ -490,6 +490,9 @@ public:
float GetLoadWeight( void ) const { return m_flLoadWeight; }
void SetAngleAlignment( float alignAngleCosine ) { m_angleAlignment = alignAngleCosine; }
void SetIgnorePitch( bool bIgnore ) { m_bIgnoreRelativePitch = bIgnore; }
#ifdef MAPBASE
void SetDontUseListMass( bool bDontUse ) { m_bDontUseListMass = bDontUse; }
#endif
QAngle TransformAnglesToPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer );
QAngle TransformAnglesFromPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer );
@ -531,6 +534,12 @@ private:
// NVNT player controlling this grab controller
CBasePlayer* m_pControllingPlayer;
#ifdef MAPBASE
// Prevents using the added mass of every part of the object
// (not saved due to only being used upon attach)
bool m_bDontUseListMass;
#endif
friend class CWeaponPhysCannon;
};
@ -581,6 +590,9 @@ CGrabController::CGrabController( void )
m_flDistanceOffset = 0;
// NVNT constructing m_pControllingPlayer to NULL
m_pControllingPlayer = NULL;
#ifdef MAPBASE
m_bDontUseListMass = false;
#endif
}
CGrabController::~CGrabController( void )
@ -783,12 +795,18 @@ void CGrabController::AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity,
{
float mass = pList[i]->GetMass();
pList[i]->GetDamping( NULL, &m_savedRotDamping[i] );
m_flLoadWeight += mass;
m_savedMass[i] = mass;
// reduce the mass to prevent the player from adding crazy amounts of energy to the system
pList[i]->SetMass( REDUCED_CARRY_MASS / flFactor );
pList[i]->SetDamping( NULL, &damping );
#ifdef MAPBASE
if (!m_bDontUseListMass || pList[i] == pPhys)
#endif
{
m_flLoadWeight += mass;
// reduce the mass to prevent the player from adding crazy amounts of energy to the system
pList[i]->SetMass( REDUCED_CARRY_MASS / flFactor );
pList[i]->SetDamping( NULL, &damping );
}
}
// NVNT setting m_pControllingPlayer to the player attached
@ -1077,7 +1095,24 @@ void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject )
Pickup_OnPhysGunPickup( pObject, m_pPlayer, PICKED_UP_BY_PLAYER );
#ifdef MAPBASE
bool bUseGrabPos = false;
Vector vecGrabPos;
if ( dynamic_cast<CRagdollProp*>( pObject ) )
{
m_grabController.SetDontUseListMass( true );
// Approximate where we're grabbing from
vecGrabPos = pPlayer->EyePosition() + (pPlayer->EyeDirection3D() * 16.0f);
bUseGrabPos = true;
}
else
m_grabController.SetDontUseListMass( false );
m_grabController.AttachEntity( pPlayer, pObject, pPhysics, false, vecGrabPos, bUseGrabPos );
#else
m_grabController.AttachEntity( pPlayer, pObject, pPhysics, false, vec3_origin, false );
#endif
// NVNT apply a downward force to simulate the mass of the held object.
#if defined( WIN32 ) && !defined( _X360 )
HapticSetConstantForce(m_pPlayer,clamp(m_grabController.GetLoadWeight()*0.1,1,6)*Vector(0,-1,0));

View File

@ -30,6 +30,8 @@
#ifdef MAPBASE
ConVar ragdoll_autointeractions("ragdoll_autointeractions", "1", FCVAR_NONE, "Controls whether we should rely on hardcoded keyvalues or automatic flesh checks for ragdoll physgun interactions.");
#define IsBody() VPhysicsIsFlesh()
ConVar ragdoll_always_allow_use( "ragdoll_always_allow_use", "0", FCVAR_NONE, "Allows all ragdolls to be used and, if they aren't explicitly set to prevent pickup, picked up." );
#endif
//-----------------------------------------------------------------------------
@ -58,6 +60,8 @@ const float ATTACHED_DAMPING_SCALE = 50.0f;
#define SF_RAGDOLLPROP_STARTASLEEP 0x10000
#ifdef MAPBASE
#define SF_RAGDOLLPROP_FIXED_CONSTRAINTS 0x20000
#define SF_RAGDOLLPROP_ALLOW_USE 0x40000
#define SF_RAGDOLLPROP_PREVENT_PICKUP 0x80000
#endif
//-----------------------------------------------------------------------------
@ -104,6 +108,8 @@ BEGIN_DATADESC(CRagdollProp)
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_VOID, "Wake", InputWake ),
DEFINE_INPUTFUNC( FIELD_VOID, "Sleep", InputSleep ),
DEFINE_INPUTFUNC( FIELD_VOID, "AddToLRU", InputAddToLRU ),
DEFINE_INPUTFUNC( FIELD_VOID, "RemoveFromLRU", InputRemoveFromLRU ),
#endif
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputTurnOn ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputTurnOff ),
@ -125,6 +131,10 @@ BEGIN_DATADESC(CRagdollProp)
DEFINE_FIELD( m_strSourceClassName, FIELD_STRING ),
DEFINE_FIELD( m_bHasBeenPhysgunned, FIELD_BOOLEAN ),
#ifdef MAPBASE
DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ),
#endif
// think functions
DEFINE_THINKFUNC( SetDebrisThink ),
DEFINE_THINKFUNC( ClearFlagsThink ),
@ -334,9 +344,39 @@ void CRagdollProp::Precache( void )
int CRagdollProp::ObjectCaps()
{
return BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION;
int caps = FCAP_WCEDIT_POSITION;
#ifdef MAPBASE
if (HasSpawnFlags( SF_RAGDOLLPROP_ALLOW_USE ) || ragdoll_always_allow_use.GetBool())
caps |= FCAP_IMPULSE_USE;
#endif
return BaseClass::ObjectCaps() | caps;
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pActivator -
// *pCaller -
// useType -
// value -
//-----------------------------------------------------------------------------
void CRagdollProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBasePlayer *pPlayer = ToBasePlayer( pActivator );
if (pPlayer)
{
m_OnPlayerUse.FireOutput( pActivator, this );
if (!HasSpawnFlags( SF_RAGDOLLPROP_PREVENT_PICKUP ))
{
pPlayer->PickupObject( this, false );
}
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -405,7 +445,7 @@ void CRagdollProp::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t r
m_bHasBeenPhysgunned = true;
#ifdef MAPBASE
if( (ragdoll_autointeractions.GetBool() == true && IsBody()) || HasPhysgunInteraction( "onpickup", "boogie" ) )
if( ((ragdoll_autointeractions.GetBool() == true && IsBody()) || HasPhysgunInteraction( "onpickup", "boogie" )) && reason != PICKED_UP_BY_PLAYER )
#else
if( HasPhysgunInteraction( "onpickup", "boogie" ) )
#endif
@ -447,7 +487,7 @@ void CRagdollProp::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reaso
m_flLastPhysicsInfluenceTime = gpGlobals->curtime;
#ifdef MAPBASE
if( (ragdoll_autointeractions.GetBool() == true && IsBody()) || HasPhysgunInteraction( "onpickup", "boogie" ) )
if( ((ragdoll_autointeractions.GetBool() == true && IsBody()) || HasPhysgunInteraction( "onpickup", "boogie" )) && (Reason != DROPPED_BY_PLAYER && Reason != THROWN_BY_PLAYER) )
#else
if( HasPhysgunInteraction( "onpickup", "boogie" ) )
#endif
@ -1844,6 +1884,24 @@ void CRagdollProp::InputSleep( inputdata_t &inputdata )
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Adds ragdoll to LRU.
//-----------------------------------------------------------------------------
void CRagdollProp::InputAddToLRU( inputdata_t &inputdata )
{
AddSpawnFlags( SF_RAGDOLLPROP_USE_LRU_RETIREMENT );
s_RagdollLRU.MoveToTopOfLRU( this );
}
//-----------------------------------------------------------------------------
// Purpose: Removes ragdoll from LRU.
//-----------------------------------------------------------------------------
void CRagdollProp::InputRemoveFromLRU( inputdata_t &inputdata )
{
RemoveSpawnFlags( SF_RAGDOLLPROP_USE_LRU_RETIREMENT );
s_RagdollLRU.RemoveFromLRU( this );
}
#endif
void CRagdollProp::InputTurnOn( inputdata_t &inputdata )

View File

@ -42,6 +42,10 @@ public:
int ObjectCaps();
#ifdef MAPBASE
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
#endif
DECLARE_SERVERCLASS();
// Don't treat as a live target
virtual bool IsAlive( void ) { return false; }
@ -113,6 +117,8 @@ public:
#ifdef MAPBASE
void InputWake( inputdata_t &inputdata );
void InputSleep( inputdata_t &inputdata );
void InputAddToLRU( inputdata_t &inputdata );
void InputRemoveFromLRU( inputdata_t &inputdata );
#endif
void InputTurnOn( inputdata_t &inputdata );
void InputTurnOff( inputdata_t &inputdata );
@ -158,6 +164,10 @@ private:
string_t m_strSourceClassName;
bool m_bHasBeenPhysgunned;
#ifdef MAPBASE
COutputEvent m_OnPlayerUse;
#endif
// If not 1, then allow underlying sequence to blend in with simulated bone positions
CNetworkVar( float, m_flBlendWeight );
CNetworkVar( int, m_nOverlaySequence );

View File

@ -1178,6 +1178,32 @@ void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImpo
#endif
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Remove it from the LRU
//-----------------------------------------------------------------------------
void CRagdollLRURetirement::RemoveFromLRU( CBaseAnimating *pRagdoll )
{
for (int i = 0; i < m_LRU.Count(); i++)
{
if (m_LRU[i].Get() == pRagdoll)
{
m_LRU.Remove( i );
return;
}
}
for (int i = 0; i < m_LRUImportantRagdolls.Count(); i++)
{
if (m_LRUImportantRagdolls[i].Get() == pRagdoll)
{
m_LRUImportantRagdolls.Remove( i );
return;
}
}
}
#endif
//EFFECT/ENTITY TRANSFERS

View File

@ -114,8 +114,9 @@ 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 );
#ifdef MAPBASE
void MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant = false, float flForcedRetireTime = 0.0f ); // From Alien Swarm SDK
void RemoveFromLRU( CBaseAnimating *pRagdoll );
#else
void MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant = false );
#endif