diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/obstacle_pushaway.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/shared/obstacle_pushaway.cpp')
| -rw-r--r-- | mp/src/game/shared/obstacle_pushaway.cpp | 670 |
1 files changed, 335 insertions, 335 deletions
diff --git a/mp/src/game/shared/obstacle_pushaway.cpp b/mp/src/game/shared/obstacle_pushaway.cpp index 043c1773..35fef4ad 100644 --- a/mp/src/game/shared/obstacle_pushaway.cpp +++ b/mp/src/game/shared/obstacle_pushaway.cpp @@ -1,335 +1,335 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "obstacle_pushaway.h"
-#include "props_shared.h"
-
-#if defined( CSTRIKE_DLL )
-#define SV_PUSH_CONVAR_FLAGS (FCVAR_REPLICATED)
-#else
-#define SV_PUSH_CONVAR_FLAGS (FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY)
-#endif // CSTRIKE_DLL
-
-//-----------------------------------------------------------------------------------------------------
-ConVar sv_pushaway_force( "sv_pushaway_force", "30000", SV_PUSH_CONVAR_FLAGS, "How hard physics objects are pushed away from the players on the server." );
-ConVar sv_pushaway_min_player_speed( "sv_pushaway_min_player_speed", "75", SV_PUSH_CONVAR_FLAGS, "If a player is moving slower than this, don't push away physics objects (enables ducking behind things)." );
-ConVar sv_pushaway_max_force( "sv_pushaway_max_force", "1000", SV_PUSH_CONVAR_FLAGS, "Maximum amount of force applied to physics objects by players." );
-ConVar sv_pushaway_clientside( "sv_pushaway_clientside", "0", SV_PUSH_CONVAR_FLAGS, "Clientside physics push away (0=off, 1=only localplayer, 1=all players)" );
-
-ConVar sv_pushaway_player_force( "sv_pushaway_player_force", "200000", SV_PUSH_CONVAR_FLAGS | FCVAR_CHEAT, "How hard the player is pushed away from physics objects (falls off with inverse square of distance)." );
-ConVar sv_pushaway_max_player_force( "sv_pushaway_max_player_force", "10000", SV_PUSH_CONVAR_FLAGS | FCVAR_CHEAT, "Maximum of how hard the player is pushed away from physics objects." );
-
-#ifdef CLIENT_DLL
-ConVar sv_turbophysics( "sv_turbophysics", "0", FCVAR_REPLICATED, "Turns on turbo physics" );
-#else
-extern ConVar sv_turbophysics;
-#endif
-
-//-----------------------------------------------------------------------------------------------------
-bool IsPushAwayEntity( CBaseEntity *pEnt )
-{
- if ( pEnt == NULL )
- return false;
-
- if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY )
- {
- // Try backing away from doors that are currently rotating, to prevent blocking them
-#ifndef CLIENT_DLL
- if ( FClassnameIs( pEnt, "func_door_rotating" ) )
- {
- CBaseDoor *door = dynamic_cast<CBaseDoor *>(pEnt);
- if ( !door )
- {
- return false;
- }
-
- if ( door->m_toggle_state != TS_GOING_UP && door->m_toggle_state != TS_GOING_DOWN )
- {
- return false;
- }
- }
- else if ( FClassnameIs( pEnt, "prop_door_rotating" ) )
- {
- CBasePropDoor *door = dynamic_cast<CBasePropDoor *>(pEnt);
- if ( !door )
- {
- return false;
- }
-
- if ( !door->IsDoorOpening() && !door->IsDoorClosing() )
- {
- return false;
- }
- }
- else
-#endif // !CLIENT_DLL
- {
- return false;
- }
- }
-
- return true;
-}
-
-//-----------------------------------------------------------------------------------------------------
-bool IsPushableEntity( CBaseEntity *pEnt )
-{
- if ( pEnt == NULL )
- return false;
-
- if ( sv_turbophysics.GetBool() )
- {
- if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_NONE )
- {
-#ifdef CLIENT_DLL
- if ( FClassnameIs( pEnt, "class CPhysicsPropMultiplayer" ) )
-#else
- if ( FClassnameIs( pEnt, "prop_physics_multiplayer" ) )
-#endif // CLIENT_DLL
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-//-----------------------------------------------------------------------------------------------------
-#ifndef CLIENT_DLL
-bool IsBreakableEntity( CBaseEntity *pEnt )
-{
- if ( pEnt == NULL )
- return false;
-
- // If we won't be able to break it, don't try
- if ( pEnt->m_takedamage != DAMAGE_YES )
- return false;
-
- if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY && pEnt->GetCollisionGroup() != COLLISION_GROUP_BREAKABLE_GLASS && pEnt->GetCollisionGroup() != COLLISION_GROUP_NONE )
- return false;
-
- if ( pEnt->m_iHealth > 200 )
- return false;
-
- IMultiplayerPhysics *pPhysicsInterface = dynamic_cast< IMultiplayerPhysics * >( pEnt );
- if ( pPhysicsInterface )
- {
- if ( pPhysicsInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID )
- return false;
- }
- else
- {
- if ((FClassnameIs( pEnt, "func_breakable" ) || FClassnameIs( pEnt, "func_breakable_surf" )))
- {
- if (FClassnameIs( pEnt, "func_breakable_surf" ))
- {
- // don't try to break it if it has already been broken
- CBreakableSurface *surf = static_cast< CBreakableSurface * >( pEnt );
-
- if ( surf->m_bIsBroken )
- return false;
- }
- }
- else if ( pEnt->PhysicsSolidMaskForEntity() & CONTENTS_PLAYERCLIP )
- {
- // hostages and players use CONTENTS_PLAYERCLIP, so we can use it to ignore them
- return false;
- }
- }
-
- IBreakableWithPropData *pBreakableInterface = dynamic_cast< IBreakableWithPropData * >( pEnt );
- if ( pBreakableInterface )
- {
- // Bullets don't damage it - ignore
- if ( pBreakableInterface->GetDmgModBullet() <= 0.0f )
- {
- return false;
- }
- }
-
- CBreakableProp *pProp = dynamic_cast< CBreakableProp * >( pEnt );
- if ( pProp )
- {
- // It takes a large amount of damage to even scratch it - ignore
- if ( pProp->m_iMinHealthDmg >= 50 )
- {
- return false;
- }
- }
-
- return true;
-}
-#endif // !CLIENT_DLL
-
-//-----------------------------------------------------------------------------------------------------
-int GetPushawayEnts( CBaseCombatCharacter *pPushingEntity, CBaseEntity **ents, int nMaxEnts, float flPlayerExpand, int PartitionMask, CPushAwayEnumerator *enumerator )
-{
-
- Vector vExpand( flPlayerExpand, flPlayerExpand, flPlayerExpand );
-
- Ray_t ray;
- ray.Init( pPushingEntity->GetAbsOrigin(), pPushingEntity->GetAbsOrigin(), pPushingEntity->GetCollideable()->OBBMins() - vExpand, pPushingEntity->GetCollideable()->OBBMaxs() + vExpand );
-
- CPushAwayEnumerator *physPropEnum = NULL;
- if ( !enumerator )
- {
- physPropEnum = new CPushAwayEnumerator( ents, nMaxEnts );
- enumerator = physPropEnum;
- }
-
- partition->EnumerateElementsAlongRay( PartitionMask, ray, false, enumerator );
-
- int numHit = enumerator->m_nAlreadyHit;
-
- if ( physPropEnum )
- delete physPropEnum;
-
- return numHit;
-}
-
-void AvoidPushawayProps( CBaseCombatCharacter *pPlayer, CUserCmd *pCmd )
-{
- // Figure out what direction we're moving and the extents of the box we're going to sweep
- // against physics objects.
- Vector currentdir;
- Vector rightdir;
- AngleVectors( pCmd->viewangles, ¤tdir, &rightdir, NULL );
-
- CBaseEntity *props[512];
-#ifdef CLIENT_DLL
- int nEnts = GetPushawayEnts( pPlayer, props, ARRAYSIZE( props ), 0.0f, PARTITION_CLIENT_SOLID_EDICTS, NULL );
-#else
- int nEnts = GetPushawayEnts( pPlayer, props, ARRAYSIZE( props ), 0.0f, PARTITION_ENGINE_SOLID_EDICTS, NULL );
-#endif
-
- const Vector & ourCenter = pPlayer->WorldSpaceCenter();
- Vector nearestPropPoint;
- Vector nearestPlayerPoint;
-
- for ( int i=0; i < nEnts; i++ )
- {
- // Don't respond to this entity on the client unless it has PHYSICS_MULTIPLAYER_FULL set.
- IMultiplayerPhysics *pInterface = dynamic_cast<IMultiplayerPhysics*>( props[i] );
- if ( pInterface && pInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID )
- continue;
-
- const float minMass = 10.0f; // minimum mass that can push a player back
- const float maxMass = 30.0f; // cap at a decently large value
- float mass = maxMass;
- if ( pInterface )
- {
- mass = pInterface->GetMass();
- }
- mass = clamp( mass, minMass, maxMass );
-
- mass = MAX( mass, 0 );
- mass /= maxMass; // bring into a 0..1 range
-
- // Push away from the collision point. The closer our center is to the collision point,
- // the harder we push away.
- props[i]->CollisionProp()->CalcNearestPoint( ourCenter, &nearestPropPoint );
- pPlayer->CollisionProp()->CalcNearestPoint( nearestPropPoint, &nearestPlayerPoint );
- Vector vPushAway = (nearestPlayerPoint - nearestPropPoint);
- float flDist = VectorNormalize( vPushAway );
-
- const float MaxPushawayDistance = 5.0f;
- if ( flDist > MaxPushawayDistance && !pPlayer->CollisionProp()->IsPointInBounds( nearestPropPoint ) )
- {
- continue;
- }
-
- // If we're not pushing, try from our center to the nearest edge of the prop
- if ( vPushAway.IsZero() )
- {
- vPushAway = (ourCenter - nearestPropPoint);
- flDist = VectorNormalize( vPushAway );
- }
-
- // If we're still not pushing, try from our center to the center of the prop
- if ( vPushAway.IsZero() )
- {
- vPushAway = (ourCenter - props[i]->WorldSpaceCenter());
- flDist = VectorNormalize( vPushAway );
- }
-
- flDist = MAX( flDist, 1 );
-
- float flForce = sv_pushaway_player_force.GetFloat() / flDist * mass;
- flForce = MIN( flForce, sv_pushaway_max_player_force.GetFloat() );
-
-#ifndef CLIENT_DLL
- pPlayer->PushawayTouch( props[i] );
-
- // We can get right up next to rotating doors before they start to move, so scale back our force so we don't go flying
- if ( FClassnameIs( props[i], "func_door_rotating" ) || FClassnameIs( props[i], "prop_door_rotating" ) )
-#endif
- {
- flForce *= 0.25f;
- }
-
- vPushAway *= flForce;
-
- pCmd->forwardmove += vPushAway.Dot( currentdir );
- pCmd->sidemove += vPushAway.Dot( rightdir );
- }
-}
-
-//-----------------------------------------------------------------------------------------------------
-void PerformObstaclePushaway( CBaseCombatCharacter *pPushingEntity )
-{
- if ( pPushingEntity->m_lifeState != LIFE_ALIVE )
- return;
-
- // Give a push to any barrels that we're touching.
- // The client handles adjusting our usercmd to push us away.
- CBaseEntity *props[256];
-
-#ifdef CLIENT_DLL
- // if sv_pushaway_clientside is disabled, clientside phys objects don't bounce away
- if ( sv_pushaway_clientside.GetInt() == 0 )
- return;
-
- // if sv_pushaway_clientside is 1, only local player can push them
- CBasePlayer *pPlayer = pPushingEntity->IsPlayer() ? (dynamic_cast< CBasePlayer * >(pPushingEntity)) : NULL;
- if ( (sv_pushaway_clientside.GetInt() == 1) && (!pPlayer || !pPlayer->IsLocalPlayer()) )
- return;
-
- int nEnts = GetPushawayEnts( pPushingEntity, props, ARRAYSIZE( props ), 3.0f, PARTITION_CLIENT_RESPONSIVE_EDICTS, NULL );
-#else
- int nEnts = GetPushawayEnts( pPushingEntity, props, ARRAYSIZE( props ), 3.0f, PARTITION_ENGINE_SOLID_EDICTS, NULL );
-#endif
-
- for ( int i=0; i < nEnts; i++ )
- {
- // If this entity uas PHYSICS_MULTIPLAYER_FULL set (ie: it's not just debris), and we're moving too slow, don't push it away.
- // Instead, let the client bounce off it. This allows players to get close to and duck behind things without knocking them over.
- IMultiplayerPhysics *pInterface = dynamic_cast<IMultiplayerPhysics*>( props[i] );
-
- if ( pInterface && pInterface->GetMultiplayerPhysicsMode() == PHYSICS_MULTIPLAYER_SOLID )
- {
- if ( pPushingEntity->GetAbsVelocity().Length2D() < sv_pushaway_min_player_speed.GetFloat() )
- continue;
- }
-
- IPhysicsObject *pObj = props[i]->VPhysicsGetObject();
-
- if ( pObj )
- {
- Vector vPushAway = (props[i]->WorldSpaceCenter() - pPushingEntity->WorldSpaceCenter());
- vPushAway.z = 0;
-
- float flDist = VectorNormalize( vPushAway );
- flDist = MAX( flDist, 1 );
-
- float flForce = sv_pushaway_force.GetFloat() / flDist;
- flForce = MIN( flForce, sv_pushaway_max_force.GetFloat() );
-
- pObj->ApplyForceOffset( vPushAway * flForce, pPushingEntity->WorldSpaceCenter() );
- }
- }
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "obstacle_pushaway.h" +#include "props_shared.h" + +#if defined( CSTRIKE_DLL ) +#define SV_PUSH_CONVAR_FLAGS (FCVAR_REPLICATED) +#else +#define SV_PUSH_CONVAR_FLAGS (FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY) +#endif // CSTRIKE_DLL + +//----------------------------------------------------------------------------------------------------- +ConVar sv_pushaway_force( "sv_pushaway_force", "30000", SV_PUSH_CONVAR_FLAGS, "How hard physics objects are pushed away from the players on the server." ); +ConVar sv_pushaway_min_player_speed( "sv_pushaway_min_player_speed", "75", SV_PUSH_CONVAR_FLAGS, "If a player is moving slower than this, don't push away physics objects (enables ducking behind things)." ); +ConVar sv_pushaway_max_force( "sv_pushaway_max_force", "1000", SV_PUSH_CONVAR_FLAGS, "Maximum amount of force applied to physics objects by players." ); +ConVar sv_pushaway_clientside( "sv_pushaway_clientside", "0", SV_PUSH_CONVAR_FLAGS, "Clientside physics push away (0=off, 1=only localplayer, 1=all players)" ); + +ConVar sv_pushaway_player_force( "sv_pushaway_player_force", "200000", SV_PUSH_CONVAR_FLAGS | FCVAR_CHEAT, "How hard the player is pushed away from physics objects (falls off with inverse square of distance)." ); +ConVar sv_pushaway_max_player_force( "sv_pushaway_max_player_force", "10000", SV_PUSH_CONVAR_FLAGS | FCVAR_CHEAT, "Maximum of how hard the player is pushed away from physics objects." ); + +#ifdef CLIENT_DLL +ConVar sv_turbophysics( "sv_turbophysics", "0", FCVAR_REPLICATED, "Turns on turbo physics" ); +#else +extern ConVar sv_turbophysics; +#endif + +//----------------------------------------------------------------------------------------------------- +bool IsPushAwayEntity( CBaseEntity *pEnt ) +{ + if ( pEnt == NULL ) + return false; + + if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY ) + { + // Try backing away from doors that are currently rotating, to prevent blocking them +#ifndef CLIENT_DLL + if ( FClassnameIs( pEnt, "func_door_rotating" ) ) + { + CBaseDoor *door = dynamic_cast<CBaseDoor *>(pEnt); + if ( !door ) + { + return false; + } + + if ( door->m_toggle_state != TS_GOING_UP && door->m_toggle_state != TS_GOING_DOWN ) + { + return false; + } + } + else if ( FClassnameIs( pEnt, "prop_door_rotating" ) ) + { + CBasePropDoor *door = dynamic_cast<CBasePropDoor *>(pEnt); + if ( !door ) + { + return false; + } + + if ( !door->IsDoorOpening() && !door->IsDoorClosing() ) + { + return false; + } + } + else +#endif // !CLIENT_DLL + { + return false; + } + } + + return true; +} + +//----------------------------------------------------------------------------------------------------- +bool IsPushableEntity( CBaseEntity *pEnt ) +{ + if ( pEnt == NULL ) + return false; + + if ( sv_turbophysics.GetBool() ) + { + if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_NONE ) + { +#ifdef CLIENT_DLL + if ( FClassnameIs( pEnt, "class CPhysicsPropMultiplayer" ) ) +#else + if ( FClassnameIs( pEnt, "prop_physics_multiplayer" ) ) +#endif // CLIENT_DLL + { + return true; + } + } + } + + return false; +} + +//----------------------------------------------------------------------------------------------------- +#ifndef CLIENT_DLL +bool IsBreakableEntity( CBaseEntity *pEnt ) +{ + if ( pEnt == NULL ) + return false; + + // If we won't be able to break it, don't try + if ( pEnt->m_takedamage != DAMAGE_YES ) + return false; + + if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY && pEnt->GetCollisionGroup() != COLLISION_GROUP_BREAKABLE_GLASS && pEnt->GetCollisionGroup() != COLLISION_GROUP_NONE ) + return false; + + if ( pEnt->m_iHealth > 200 ) + return false; + + IMultiplayerPhysics *pPhysicsInterface = dynamic_cast< IMultiplayerPhysics * >( pEnt ); + if ( pPhysicsInterface ) + { + if ( pPhysicsInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID ) + return false; + } + else + { + if ((FClassnameIs( pEnt, "func_breakable" ) || FClassnameIs( pEnt, "func_breakable_surf" ))) + { + if (FClassnameIs( pEnt, "func_breakable_surf" )) + { + // don't try to break it if it has already been broken + CBreakableSurface *surf = static_cast< CBreakableSurface * >( pEnt ); + + if ( surf->m_bIsBroken ) + return false; + } + } + else if ( pEnt->PhysicsSolidMaskForEntity() & CONTENTS_PLAYERCLIP ) + { + // hostages and players use CONTENTS_PLAYERCLIP, so we can use it to ignore them + return false; + } + } + + IBreakableWithPropData *pBreakableInterface = dynamic_cast< IBreakableWithPropData * >( pEnt ); + if ( pBreakableInterface ) + { + // Bullets don't damage it - ignore + if ( pBreakableInterface->GetDmgModBullet() <= 0.0f ) + { + return false; + } + } + + CBreakableProp *pProp = dynamic_cast< CBreakableProp * >( pEnt ); + if ( pProp ) + { + // It takes a large amount of damage to even scratch it - ignore + if ( pProp->m_iMinHealthDmg >= 50 ) + { + return false; + } + } + + return true; +} +#endif // !CLIENT_DLL + +//----------------------------------------------------------------------------------------------------- +int GetPushawayEnts( CBaseCombatCharacter *pPushingEntity, CBaseEntity **ents, int nMaxEnts, float flPlayerExpand, int PartitionMask, CPushAwayEnumerator *enumerator ) +{ + + Vector vExpand( flPlayerExpand, flPlayerExpand, flPlayerExpand ); + + Ray_t ray; + ray.Init( pPushingEntity->GetAbsOrigin(), pPushingEntity->GetAbsOrigin(), pPushingEntity->GetCollideable()->OBBMins() - vExpand, pPushingEntity->GetCollideable()->OBBMaxs() + vExpand ); + + CPushAwayEnumerator *physPropEnum = NULL; + if ( !enumerator ) + { + physPropEnum = new CPushAwayEnumerator( ents, nMaxEnts ); + enumerator = physPropEnum; + } + + partition->EnumerateElementsAlongRay( PartitionMask, ray, false, enumerator ); + + int numHit = enumerator->m_nAlreadyHit; + + if ( physPropEnum ) + delete physPropEnum; + + return numHit; +} + +void AvoidPushawayProps( CBaseCombatCharacter *pPlayer, CUserCmd *pCmd ) +{ + // Figure out what direction we're moving and the extents of the box we're going to sweep + // against physics objects. + Vector currentdir; + Vector rightdir; + AngleVectors( pCmd->viewangles, ¤tdir, &rightdir, NULL ); + + CBaseEntity *props[512]; +#ifdef CLIENT_DLL + int nEnts = GetPushawayEnts( pPlayer, props, ARRAYSIZE( props ), 0.0f, PARTITION_CLIENT_SOLID_EDICTS, NULL ); +#else + int nEnts = GetPushawayEnts( pPlayer, props, ARRAYSIZE( props ), 0.0f, PARTITION_ENGINE_SOLID_EDICTS, NULL ); +#endif + + const Vector & ourCenter = pPlayer->WorldSpaceCenter(); + Vector nearestPropPoint; + Vector nearestPlayerPoint; + + for ( int i=0; i < nEnts; i++ ) + { + // Don't respond to this entity on the client unless it has PHYSICS_MULTIPLAYER_FULL set. + IMultiplayerPhysics *pInterface = dynamic_cast<IMultiplayerPhysics*>( props[i] ); + if ( pInterface && pInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID ) + continue; + + const float minMass = 10.0f; // minimum mass that can push a player back + const float maxMass = 30.0f; // cap at a decently large value + float mass = maxMass; + if ( pInterface ) + { + mass = pInterface->GetMass(); + } + mass = clamp( mass, minMass, maxMass ); + + mass = MAX( mass, 0 ); + mass /= maxMass; // bring into a 0..1 range + + // Push away from the collision point. The closer our center is to the collision point, + // the harder we push away. + props[i]->CollisionProp()->CalcNearestPoint( ourCenter, &nearestPropPoint ); + pPlayer->CollisionProp()->CalcNearestPoint( nearestPropPoint, &nearestPlayerPoint ); + Vector vPushAway = (nearestPlayerPoint - nearestPropPoint); + float flDist = VectorNormalize( vPushAway ); + + const float MaxPushawayDistance = 5.0f; + if ( flDist > MaxPushawayDistance && !pPlayer->CollisionProp()->IsPointInBounds( nearestPropPoint ) ) + { + continue; + } + + // If we're not pushing, try from our center to the nearest edge of the prop + if ( vPushAway.IsZero() ) + { + vPushAway = (ourCenter - nearestPropPoint); + flDist = VectorNormalize( vPushAway ); + } + + // If we're still not pushing, try from our center to the center of the prop + if ( vPushAway.IsZero() ) + { + vPushAway = (ourCenter - props[i]->WorldSpaceCenter()); + flDist = VectorNormalize( vPushAway ); + } + + flDist = MAX( flDist, 1 ); + + float flForce = sv_pushaway_player_force.GetFloat() / flDist * mass; + flForce = MIN( flForce, sv_pushaway_max_player_force.GetFloat() ); + +#ifndef CLIENT_DLL + pPlayer->PushawayTouch( props[i] ); + + // We can get right up next to rotating doors before they start to move, so scale back our force so we don't go flying + if ( FClassnameIs( props[i], "func_door_rotating" ) || FClassnameIs( props[i], "prop_door_rotating" ) ) +#endif + { + flForce *= 0.25f; + } + + vPushAway *= flForce; + + pCmd->forwardmove += vPushAway.Dot( currentdir ); + pCmd->sidemove += vPushAway.Dot( rightdir ); + } +} + +//----------------------------------------------------------------------------------------------------- +void PerformObstaclePushaway( CBaseCombatCharacter *pPushingEntity ) +{ + if ( pPushingEntity->m_lifeState != LIFE_ALIVE ) + return; + + // Give a push to any barrels that we're touching. + // The client handles adjusting our usercmd to push us away. + CBaseEntity *props[256]; + +#ifdef CLIENT_DLL + // if sv_pushaway_clientside is disabled, clientside phys objects don't bounce away + if ( sv_pushaway_clientside.GetInt() == 0 ) + return; + + // if sv_pushaway_clientside is 1, only local player can push them + CBasePlayer *pPlayer = pPushingEntity->IsPlayer() ? (dynamic_cast< CBasePlayer * >(pPushingEntity)) : NULL; + if ( (sv_pushaway_clientside.GetInt() == 1) && (!pPlayer || !pPlayer->IsLocalPlayer()) ) + return; + + int nEnts = GetPushawayEnts( pPushingEntity, props, ARRAYSIZE( props ), 3.0f, PARTITION_CLIENT_RESPONSIVE_EDICTS, NULL ); +#else + int nEnts = GetPushawayEnts( pPushingEntity, props, ARRAYSIZE( props ), 3.0f, PARTITION_ENGINE_SOLID_EDICTS, NULL ); +#endif + + for ( int i=0; i < nEnts; i++ ) + { + // If this entity uas PHYSICS_MULTIPLAYER_FULL set (ie: it's not just debris), and we're moving too slow, don't push it away. + // Instead, let the client bounce off it. This allows players to get close to and duck behind things without knocking them over. + IMultiplayerPhysics *pInterface = dynamic_cast<IMultiplayerPhysics*>( props[i] ); + + if ( pInterface && pInterface->GetMultiplayerPhysicsMode() == PHYSICS_MULTIPLAYER_SOLID ) + { + if ( pPushingEntity->GetAbsVelocity().Length2D() < sv_pushaway_min_player_speed.GetFloat() ) + continue; + } + + IPhysicsObject *pObj = props[i]->VPhysicsGetObject(); + + if ( pObj ) + { + Vector vPushAway = (props[i]->WorldSpaceCenter() - pPushingEntity->WorldSpaceCenter()); + vPushAway.z = 0; + + float flDist = VectorNormalize( vPushAway ); + flDist = MAX( flDist, 1 ); + + float flForce = sv_pushaway_force.GetFloat() / flDist; + flForce = MIN( flForce, sv_pushaway_max_force.GetFloat() ); + + pObj->ApplyForceOffset( vPushAway * flForce, pPushingEntity->WorldSpaceCenter() ); + } + } +} |