aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/obstacle_pushaway.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/shared/obstacle_pushaway.cpp
parentMark some more files as text. (diff)
downloadsource-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.cpp670
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, &currentdir, &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, &currentdir, &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() );
+ }
+ }
+}