diff --git a/sp/src/game/server/hl2/weapon_physcannon.cpp b/sp/src/game/server/hl2/weapon_physcannon.cpp index 8a246a2d..2947e291 100644 --- a/sp/src/game/server/hl2/weapon_physcannon.cpp +++ b/sp/src/game/server/hl2/weapon_physcannon.cpp @@ -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( 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)); diff --git a/sp/src/game/server/physics_prop_ragdoll.cpp b/sp/src/game/server/physics_prop_ragdoll.cpp index cc788fc6..e208e620 100644 --- a/sp/src/game/server/physics_prop_ragdoll.cpp +++ b/sp/src/game/server/physics_prop_ragdoll.cpp @@ -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 ) diff --git a/sp/src/game/server/physics_prop_ragdoll.h b/sp/src/game/server/physics_prop_ragdoll.h index 46e527c3..82a3d77a 100644 --- a/sp/src/game/server/physics_prop_ragdoll.h +++ b/sp/src/game/server/physics_prop_ragdoll.h @@ -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 ); diff --git a/sp/src/game/shared/ragdoll_shared.cpp b/sp/src/game/shared/ragdoll_shared.cpp index a9da2613..494c9ebe 100644 --- a/sp/src/game/shared/ragdoll_shared.cpp +++ b/sp/src/game/shared/ragdoll_shared.cpp @@ -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 diff --git a/sp/src/game/shared/ragdoll_shared.h b/sp/src/game/shared/ragdoll_shared.h index 5f4f7058..db2bd7b2 100644 --- a/sp/src/game/shared/ragdoll_shared.h +++ b/sp/src/game/shared/ragdoll_shared.h @@ -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