aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/bmodels.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/server/bmodels.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/server/bmodels.cpp')
-rw-r--r--mp/src/game/server/bmodels.cpp2930
1 files changed, 1465 insertions, 1465 deletions
diff --git a/mp/src/game/server/bmodels.cpp b/mp/src/game/server/bmodels.cpp
index f293d70b..71be7d39 100644
--- a/mp/src/game/server/bmodels.cpp
+++ b/mp/src/game/server/bmodels.cpp
@@ -1,1465 +1,1465 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Spawn, think, and use functions for common brush entities.
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "doors.h"
-#include "mathlib/mathlib.h"
-#include "physics.h"
-#include "ndebugoverlay.h"
-#include "engine/IEngineSound.h"
-#include "globals.h"
-#include "filters.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define SF_BRUSH_ACCDCC 16// brush should accelerate and decelerate when toggled
-#define SF_BRUSH_HURT 32// rotating brush that inflicts pain based on rotation speed
-#define SF_ROTATING_NOT_SOLID 64 // some special rotating objects are not solid.
-
-// =================== FUNC_WALL ==============================================
-class CFuncWall : public CBaseEntity
-{
-public:
- DECLARE_DATADESC();
- DECLARE_CLASS( CFuncWall, CBaseEntity );
- void Spawn( void );
- bool CreateVPhysics( void );
- void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
-
- int m_nState;
-};
-
-LINK_ENTITY_TO_CLASS( func_wall, CFuncWall );
-
-//---------------------------------------------------------
-// Save/Restore
-//---------------------------------------------------------
-BEGIN_DATADESC( CFuncWall )
-
- DEFINE_FIELD( m_nState, FIELD_INTEGER ),
-
-END_DATADESC()
-
-void CFuncWall::Spawn( void )
-{
- SetLocalAngles( vec3_angle );
- SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
- SetModel( STRING( GetModelName() ) );
-
- // If it can't move/go away, it's really part of the world
- AddFlag( FL_WORLDBRUSH );
-
- // set manual mode
- CreateVPhysics();
-}
-
-
-bool CFuncWall::CreateVPhysics( void )
-{
- SetSolid( SOLID_BSP );
- IPhysicsObject *pPhys = VPhysicsInitStatic();
- if ( pPhys )
- {
- int contents = modelinfo->GetModelContents( GetModelIndex() );
- if ( ! (contents & (MASK_SOLID|MASK_PLAYERSOLID|MASK_NPCSOLID)) )
- {
- // leave the physics shadow there in case it has crap constrained to it
- // but disable collisions with it
- pPhys->EnableCollisions( false );
- }
- }
-
- return true;
-}
-
-
-void CFuncWall::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- if ( ShouldToggle( useType, m_nState ) )
- {
- m_nState = 1 - m_nState;
- }
-}
-
-
-#define SF_WALL_START_OFF 0x0001
-
-class CFuncWallToggle : public CFuncWall
-{
-public:
- DECLARE_CLASS( CFuncWallToggle, CFuncWall );
-
- DECLARE_DATADESC();
-
- void Spawn( void );
- void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
-
- void InputToggle( inputdata_t &inputdata );
-
- void TurnOff( void );
- void TurnOn( void );
- bool IsOn( void );
-};
-
-BEGIN_DATADESC( CFuncWallToggle )
-
- DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
-
-END_DATADESC()
-
-
-LINK_ENTITY_TO_CLASS( func_wall_toggle, CFuncWallToggle );
-
-void CFuncWallToggle::Spawn( void )
-{
- BaseClass::Spawn();
- if ( HasSpawnFlags( SF_WALL_START_OFF ) )
- TurnOff();
-
- SetMoveType( MOVETYPE_PUSH );
-}
-
-
-void CFuncWallToggle::TurnOff( void )
-{
- IPhysicsObject *pPhys = VPhysicsGetObject();
- if ( pPhys )
- {
- pPhys->EnableCollisions( false );
- }
- AddSolidFlags( FSOLID_NOT_SOLID );
- AddEffects( EF_NODRAW );
-}
-
-
-void CFuncWallToggle::TurnOn( void )
-{
- IPhysicsObject *pPhys = VPhysicsGetObject();
- if ( pPhys )
- {
- pPhys->EnableCollisions( true );
- }
- RemoveSolidFlags( FSOLID_NOT_SOLID );
- RemoveEffects( EF_NODRAW );
-}
-
-
-bool CFuncWallToggle::IsOn( void )
-{
- if ( IsSolidFlagSet( FSOLID_NOT_SOLID ) )
- return false;
- return true;
-}
-
-void CFuncWallToggle::InputToggle( inputdata_t &inputdata )
-{
- int status = IsOn();
-
- if ( ShouldToggle( USE_TOGGLE, status ) )
- {
- if ( status )
- TurnOff();
- else
- TurnOn();
- }
-}
-
-//Adrian - Is this function needed at all?
-void CFuncWallToggle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- int status = IsOn();
-
- if ( ShouldToggle( useType, status ) )
- {
- if ( status )
- TurnOff();
- else
- TurnOn();
- }
-}
-
-//============================== FUNC_VEHICLECLIP =====================================
-class CFuncVehicleClip : public CBaseEntity
-{
-public:
- DECLARE_CLASS( CFuncVehicleClip, CBaseEntity );
- DECLARE_DATADESC();
-
- void Spawn();
- bool CreateVPhysics( void );
-
- void InputEnable( inputdata_t &data );
- void InputDisable( inputdata_t &data );
-
-private:
-};
-
-BEGIN_DATADESC( CFuncVehicleClip )
-
- DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
-
-END_DATADESC()
-
-LINK_ENTITY_TO_CLASS( func_vehicleclip, CFuncVehicleClip );
-
-void CFuncVehicleClip::Spawn()
-{
-
- SetLocalAngles( vec3_angle );
- SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
- SetModel( STRING( GetModelName() ) );
-
- // It's part of the world
- AddFlag( FL_WORLDBRUSH );
-
- CreateVPhysics();
-
- AddEffects( EF_NODRAW ); // make entity invisible
-
- SetCollisionGroup( COLLISION_GROUP_VEHICLE_CLIP );
-}
-
-bool CFuncVehicleClip::CreateVPhysics( void )
-{
- SetSolid( SOLID_BSP );
- VPhysicsInitStatic();
-
- return true;
-}
-
-void CFuncVehicleClip::InputEnable( inputdata_t &data )
-{
- IPhysicsObject *pPhys = VPhysicsGetObject();
- if ( pPhys )
- {
- pPhys->EnableCollisions( true );
- }
- RemoveSolidFlags( FSOLID_NOT_SOLID );
-}
-
-void CFuncVehicleClip::InputDisable( inputdata_t &data )
-{
- IPhysicsObject *pPhys = VPhysicsGetObject();
- if ( pPhys )
- {
- pPhys->EnableCollisions( false );
- }
- AddSolidFlags( FSOLID_NOT_SOLID );
-}
-
-//============================= FUNC_CONVEYOR =======================================
-
-#define SF_CONVEYOR_VISUAL 0x0001
-#define SF_CONVEYOR_NOTSOLID 0x0002
-
-class CFuncConveyor : public CFuncWall
-{
-public:
- DECLARE_CLASS( CFuncConveyor, CFuncWall );
- DECLARE_DATADESC();
- DECLARE_SERVERCLASS();
-
- CFuncConveyor();
-
- void Spawn( void );
- void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
- void UpdateSpeed( float flNewSpeed );
-
- void GetGroundVelocityToApply( Vector &vecGroundVel );
-
- // Input handlers.
- void InputToggleDirection( inputdata_t &inputdata );
- void InputSetSpeed( inputdata_t &inputdata );
-
-private:
-
- Vector m_vecMoveDir;
- CNetworkVar( float, m_flConveyorSpeed );
-};
-
-LINK_ENTITY_TO_CLASS( func_conveyor, CFuncConveyor );
-
-BEGIN_DATADESC( CFuncConveyor )
-
- DEFINE_INPUTFUNC( FIELD_VOID, "ToggleDirection", InputToggleDirection ),
- DEFINE_INPUTFUNC( FIELD_VOID, "SetSpeed", InputSetSpeed ),
-
- DEFINE_KEYFIELD( m_vecMoveDir, FIELD_VECTOR, "movedir" ),
- DEFINE_FIELD( m_flConveyorSpeed, FIELD_FLOAT ),
-
-END_DATADESC()
-
-
-IMPLEMENT_SERVERCLASS_ST(CFuncConveyor, DT_FuncConveyor)
- SendPropFloat( SENDINFO(m_flConveyorSpeed), 0, SPROP_NOSCALE ),
-END_SEND_TABLE()
-
-
-CFuncConveyor::CFuncConveyor()
-{
- m_flConveyorSpeed = 0.0;
-}
-
-void CFuncConveyor::Spawn( void )
-{
- // Convert movedir from angles to a vector
- QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z );
- AngleVectors( angMoveDir, &m_vecMoveDir );
-
- BaseClass::Spawn();
-
- if ( !HasSpawnFlags(SF_CONVEYOR_VISUAL) )
- AddFlag( FL_CONVEYOR );
-
- // HACKHACK - This is to allow for some special effects
- if ( HasSpawnFlags( SF_CONVEYOR_NOTSOLID ) )
- {
- AddSolidFlags( FSOLID_NOT_SOLID );
- }
-
- if ( m_flSpeed == 0 )
- m_flSpeed = 100;
-
- UpdateSpeed( m_flSpeed );
-}
-
-
-void CFuncConveyor::UpdateSpeed( float flNewSpeed )
-{
- m_flConveyorSpeed = flNewSpeed;
-}
-
-
-void CFuncConveyor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- m_flSpeed = -m_flSpeed;
- UpdateSpeed( m_flSpeed );
-}
-
-
-void CFuncConveyor::InputToggleDirection( inputdata_t &inputdata )
-{
- Use( inputdata.pActivator, inputdata.pCaller, USE_TOGGLE, 0 );
-}
-
-
-void CFuncConveyor::InputSetSpeed( inputdata_t &inputdata )
-{
- m_flSpeed = inputdata.value.Float();
- UpdateSpeed( m_flSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the velocity imparted to players standing on us.
-//-----------------------------------------------------------------------------
-void CFuncConveyor::GetGroundVelocityToApply( Vector &vecGroundVel )
-{
- vecGroundVel = m_vecMoveDir * m_flSpeed;
-}
-
-
-// =================== FUNC_ILLUSIONARY ==============================================
-// A simple entity that looks solid but lets you walk through it.
-class CFuncIllusionary : public CBaseEntity
-{
- DECLARE_CLASS( CFuncIllusionary, CBaseEntity );
-public:
- void Spawn( void );
-};
-
-LINK_ENTITY_TO_CLASS( func_illusionary, CFuncIllusionary );
-
-void CFuncIllusionary::Spawn( void )
-{
- SetLocalAngles( vec3_angle );
- SetMoveType( MOVETYPE_NONE );
- SetSolid( SOLID_NONE );
- SetModel( STRING( GetModelName() ) );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: A rotating brush entity.
-//
-// You need to have an origin brush as part of this entity. The
-// center of that brush will be the point around which it is rotated.
-//
-// It will rotate around the Z axis by default. Spawnflags can be set
-// to make it rotate around the X or Y axes.
-//
-// The direction of rotation is also controlled by a spawnflag.
-//-----------------------------------------------------------------------------
-class CFuncRotating : public CBaseEntity
-{
- DECLARE_CLASS( CFuncRotating, CBaseEntity );
-public:
- // basic functions
- void Spawn( void );
- void Precache( void );
- bool CreateVPhysics( void );
- void SpinUpMove( void );
- void SpinDownMove( void );
- bool KeyValue( const char *szKeyName, const char *szValue );
- void HurtTouch ( CBaseEntity *pOther );
- void RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
- void RotateMove( void );
- void ReverseMove( void );
- void RampPitchVol( void );
- void Blocked( CBaseEntity *pOther );
- void SetTargetSpeed( float flSpeed );
- void UpdateSpeed( float flNewSpeed );
-
- int DrawDebugTextOverlays(void);
-
- DECLARE_DATADESC();
- DECLARE_SERVERCLASS();
-
-protected:
- bool SpinDown( float flTargetSpeed );
- float GetMoveSpeed( float flSpeed );
-
- float GetNextMoveInterval() const;
-
- // Input handlers
- void InputSetSpeed( inputdata_t &inputdata );
- void InputStart( inputdata_t &inputdata );
- void InputStop( inputdata_t &inputdata );
- void InputStartForward( inputdata_t &inputdata );
- void InputStartBackward( inputdata_t &inputdata );
- void InputToggle( inputdata_t &inputdata );
- void InputReverse( inputdata_t &inputdata );
- void InputStopAtStartPos( inputdata_t &inputdata );
-
- QAngle m_vecMoveAng;
-
- float m_flFanFriction;
- float m_flAttenuation;
- float m_flVolume;
- float m_flTargetSpeed; // Target value for m_flSpeed, used for spinning up and down.
- float m_flMaxSpeed; // Maximum value for m_flSpeed, used for ramping sound effects.
- float m_flBlockDamage; // Damage inflicted when blocked.
- string_t m_NoiseRunning;
- bool m_bReversed;
-
- QAngle m_angStart;
- bool m_bStopAtStartPos;
-
- bool m_bSolidBsp; // Brush is SOLID_BSP
-
-public:
- Vector m_vecClientOrigin;
- QAngle m_vecClientAngles;
-};
-
-LINK_ENTITY_TO_CLASS( func_rotating, CFuncRotating );
-
-
-BEGIN_DATADESC( CFuncRotating )
-
- DEFINE_FIELD( m_vecMoveAng, FIELD_VECTOR ),
- DEFINE_FIELD( m_flFanFriction, FIELD_FLOAT ),
- DEFINE_FIELD( m_flAttenuation, FIELD_FLOAT ),
- DEFINE_FIELD( m_flVolume, FIELD_FLOAT ),
- DEFINE_FIELD( m_flTargetSpeed, FIELD_FLOAT ),
- DEFINE_KEYFIELD( m_flMaxSpeed, FIELD_FLOAT, "maxspeed" ),
- DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "dmg" ),
- DEFINE_KEYFIELD( m_NoiseRunning, FIELD_SOUNDNAME, "message" ),
- DEFINE_FIELD( m_bReversed, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_angStart, FIELD_VECTOR ),
- DEFINE_FIELD( m_bStopAtStartPos, FIELD_BOOLEAN ),
- DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ),
-
- // Function Pointers
- DEFINE_FUNCTION( SpinUpMove ),
- DEFINE_FUNCTION( SpinDownMove ),
- DEFINE_FUNCTION( HurtTouch ),
- DEFINE_FUNCTION( RotatingUse ),
- DEFINE_FUNCTION( RotateMove ),
- DEFINE_FUNCTION( ReverseMove ),
-
- // Inputs
- DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Reverse", InputReverse ),
- DEFINE_INPUTFUNC( FIELD_VOID, "StartForward", InputStartForward ),
- DEFINE_INPUTFUNC( FIELD_VOID, "StartBackward", InputStartBackward ),
- DEFINE_INPUTFUNC( FIELD_VOID, "StopAtStartPos", InputStopAtStartPos ),
-
-END_DATADESC()
-
-extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
-void SendProxy_FuncRotatingOrigin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID )
-{
-#ifdef TF_DLL
- CFuncRotating *entity = (CFuncRotating*)pStruct;
- Assert( entity );
-
- if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
- {
- const Vector *v = &entity->m_vecClientOrigin;
- pOut->m_Vector[ 0 ] = v->x;
- pOut->m_Vector[ 1 ] = v->y;
- pOut->m_Vector[ 2 ] = v->z;
- return;
- }
-#endif
-
- SendProxy_Origin( pProp, pStruct, pData, pOut, iElement, objectID );
-}
-
-/*
-extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
-void SendProxy_FuncRotatingAngles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID )
-{
- CFuncRotating *entity = (CFuncRotating*)pStruct;
- Assert( entity );
- if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
- {
- const QAngle *a = &entity->m_vecClientAngles;
- pOut->m_Vector[ 0 ] = anglemod( a->x );
- pOut->m_Vector[ 1 ] = anglemod( a->y );
- pOut->m_Vector[ 2 ] = anglemod( a->z );
- return;
- }
-
- SendProxy_Angles( pProp, pStruct, pData, pOut, iElement, objectID );
-}
-*/
-void SendProxy_FuncRotatingAngle( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID)
-{
- CFuncRotating *entity = (CFuncRotating*)pStruct;
- Assert( entity );
-
- vec_t const *qa = (vec_t *)pData;
- vec_t const *ea = entity->GetLocalAngles().Base();
- NOTE_UNUSED(ea);
- // Assert its actually an index into m_angRotation if not this won't work
-
- Assert( (uintp)qa >= (uintp)ea && (uintp)qa < (uintp)ea + sizeof( QAngle ));
-
-#ifdef TF_DLL
- if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
- {
- const QAngle *a = &entity->m_vecClientAngles;
-
- pOut->m_Float = anglemod( (*a)[ qa - ea ] );
- return;
- }
-#endif
-
- pOut->m_Float = anglemod( *qa );
-
- Assert( IsFinite( pOut->m_Float ) );
-}
-
-
-extern void SendProxy_SimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID );
-void SendProxy_FuncRotatingSimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID )
-{
-#ifdef TF_DLL
- CFuncRotating *entity = (CFuncRotating*)pStruct;
- Assert( entity );
-
- if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
- {
- pOut->m_Int = 0;
- return;
- }
-#endif
-
- SendProxy_SimulationTime( pProp, pStruct, pVarData, pOut, iElement, objectID );
-}
-
-IMPLEMENT_SERVERCLASS_ST(CFuncRotating, DT_FuncRotating)
- SendPropExclude( "DT_BaseEntity", "m_angRotation" ),
- SendPropExclude( "DT_BaseEntity", "m_vecOrigin" ),
- SendPropExclude( "DT_BaseEntity", "m_flSimulationTime" ),
-
- SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_FuncRotatingOrigin ),
- SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 0), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngle ),
- SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 1), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngle ),
- SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 2), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngle ),
-
- SendPropInt(SENDINFO(m_flSimulationTime), SIMULATION_TIME_WINDOW_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_FuncRotatingSimulationTime),
-END_SEND_TABLE()
-
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Handles keyvalues from the BSP. Called before spawning.
-//-----------------------------------------------------------------------------
-bool CFuncRotating::KeyValue( const char *szKeyName, const char *szValue )
-{
- if (FStrEq(szKeyName, "fanfriction"))
- {
- m_flFanFriction = atof(szValue)/100;
- }
- else if (FStrEq(szKeyName, "Volume"))
- {
- m_flVolume = atof(szValue) / 10.0;
- m_flVolume = clamp(m_flVolume, 0.0f, 1.0f);
- }
- else
- {
- return BaseClass::KeyValue( szKeyName, szValue );
- }
-
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Called when spawning, after keyvalues have been set.
-//-----------------------------------------------------------------------------
-void CFuncRotating::Spawn( )
-{
-#ifdef TF_DLL
- AddSpawnFlags( SF_BRUSH_ROTATE_CLIENTSIDE );
-#endif
-
- //
- // Maintain compatibility with previous maps.
- //
- if (m_flVolume == 0.0)
- {
- m_flVolume = 1.0;
- }
-
- //
- // If the designer didn't set a sound attenuation, default to one.
- //
- if ( HasSpawnFlags(SF_BRUSH_ROTATE_SMALLRADIUS) )
- {
- m_flAttenuation = ATTN_IDLE;
- }
- else if ( HasSpawnFlags(SF_BRUSH_ROTATE_MEDIUMRADIUS) )
- {
- m_flAttenuation = ATTN_STATIC;
- }
- else if ( HasSpawnFlags(SF_BRUSH_ROTATE_LARGERADIUS) )
- {
- m_flAttenuation = ATTN_NORM;
- }
- else
- {
- m_flAttenuation = ATTN_NORM;
- }
-
- //
- // Prevent divide by zero if level designer forgets friction!
- //
- if ( m_flFanFriction == 0 )
- {
- m_flFanFriction = 1;
- }
-
- //
- // Build the axis of rotation based on spawnflags.
- //
- if ( HasSpawnFlags(SF_BRUSH_ROTATE_Z_AXIS) )
- {
- m_vecMoveAng = QAngle(0,0,1);
- }
- else if ( HasSpawnFlags(SF_BRUSH_ROTATE_X_AXIS) )
- {
- m_vecMoveAng = QAngle(1,0,0);
- }
- else
- {
- m_vecMoveAng = QAngle(0,1,0); // y-axis
- }
-
- //
- // Check for reverse rotation.
- //
- if ( HasSpawnFlags(SF_BRUSH_ROTATE_BACKWARDS) )
- {
- m_vecMoveAng = m_vecMoveAng * -1;
- }
-
- SetSolid( SOLID_VPHYSICS );
-
- //
- // Some rotating objects like fake volumetric lights will not be solid.
- //
- if ( HasSpawnFlags(SF_ROTATING_NOT_SOLID) )
- {
- AddSolidFlags( FSOLID_NOT_SOLID );
- SetMoveType( MOVETYPE_PUSH );
- }
- else
- {
- RemoveSolidFlags( FSOLID_NOT_SOLID );
- SetMoveType( MOVETYPE_PUSH );
- }
-
- SetModel( STRING( GetModelName() ) );
-
- SetUse( &CFuncRotating::RotatingUse );
-
- //
- // Did level designer forget to assign a maximum speed? Prevent a divide by
- // zero in RampPitchVol as well as allowing the rotator to work.
- //
- m_flMaxSpeed = fabs( m_flMaxSpeed );
- if (m_flMaxSpeed == 0)
- {
- m_flMaxSpeed = 100;
- }
-
- //
- // If the brush should be initially rotating, use it in a little while.
- //
- if ( HasSpawnFlags(SF_BRUSH_ROTATE_START_ON) )
- {
- SetThink( &CFuncRotating::SUB_CallUseToggle );
- SetNextThink( gpGlobals->curtime + .2 ); // leave a magic delay for client to start up
- }
-
- //
- // Can this brush inflict pain?
- //
- if ( HasSpawnFlags(SF_BRUSH_HURT) )
- {
- SetTouch( &CFuncRotating::HurtTouch );
- }
-
- //
- // Set speed to 0 in case there's an old "speed" key lying around.
- //
- m_flSpeed = 0;
-
- Precache( );
- CreateVPhysics();
-
- m_angStart = GetLocalAngles();
-
- // Slam the object back to solid - if we really want it to be solid.
- if ( m_bSolidBsp )
- {
- SetSolid( SOLID_BSP );
- }
-
-#ifdef TF_DLL
- if ( HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
- {
- m_vecClientOrigin = GetLocalOrigin();
- m_vecClientAngles = GetLocalAngles();
- }
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CFuncRotating::CreateVPhysics( void )
-{
- if ( !IsSolidFlagSet( FSOLID_NOT_SOLID ))
- {
- VPhysicsInitShadow( false, false );
- }
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CFuncRotating::Precache( void )
-{
- //
- // Set up rotation sound.
- //
- char *szSoundFile = ( char * )STRING( m_NoiseRunning );
- if ( !m_NoiseRunning || strlen( szSoundFile ) == 0 )
- {
- // No sound set up, use the null sound.
- m_NoiseRunning = AllocPooledString("DoorSound.Null");
- }
- PrecacheScriptSound( STRING( m_NoiseRunning ) );
-
- if (GetLocalAngularVelocity() != vec3_angle )
- {
- //
- // If fan was spinning, and we went through transition or save/restore,
- // make sure we restart the sound. 1.5 sec delay is a magic number.
- //
- SetMoveDone( &CFuncRotating::SpinUpMove );
- SetMoveDoneTime( 1.5 );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Will hurt others based on how fast the brush is spinning.
-// Input : pOther -
-//-----------------------------------------------------------------------------
-void CFuncRotating::HurtTouch ( CBaseEntity *pOther )
-{
- // we can't hurt this thing, so we're not concerned with it
- if ( !pOther->m_takedamage )
- return;
-
- // calculate damage based on rotation speed
- m_flBlockDamage = GetLocalAngularVelocity().Length() / 10;
-
-#ifdef HL1_DLL
- if( m_flBlockDamage > 0 )
-#endif
- {
- pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) );
-
- Vector vecNewVelocity = pOther->GetAbsOrigin() - WorldSpaceCenter();
- VectorNormalize(vecNewVelocity);
- vecNewVelocity *= m_flBlockDamage;
- pOther->SetAbsVelocity( vecNewVelocity );
- }
-}
-
-
-#define FANPITCHMIN 30
-#define FANPITCHMAX 100
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Ramp pitch and volume up to maximum values, based on the difference
-// between how fast we're going vs how fast we can go.
-//-----------------------------------------------------------------------------
-void CFuncRotating::RampPitchVol( void )
-{
- //
- // Calc volume and pitch as % of maximum vol and pitch.
- //
- float fpct = fabs(m_flSpeed) / m_flMaxSpeed;
- float fvol = clamp(m_flVolume * fpct, 0.f, 1.f); // slowdown volume ramps down to 0
-
- float fpitch = FANPITCHMIN + (FANPITCHMAX - FANPITCHMIN) * fpct;
-
- int pitch = clamp(FastFloatToSmallInt(fpitch), 0, 255);
- if (pitch == PITCH_NORM)
- {
- pitch = PITCH_NORM - 1;
- }
-
- //
- // Update the fan's volume and pitch.
- //
- CPASAttenuationFilter filter( GetAbsOrigin(), m_flAttenuation );
- filter.MakeReliable();
-
- EmitSound_t ep;
- ep.m_nChannel = CHAN_STATIC;
- ep.m_pSoundName = STRING(m_NoiseRunning);
- ep.m_flVolume = fvol;
- ep.m_SoundLevel = ATTN_TO_SNDLVL( m_flAttenuation );
- ep.m_nFlags = SND_CHANGE_PITCH | SND_CHANGE_VOL;
- ep.m_nPitch = pitch;
-
- EmitSound( filter, entindex(), ep );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Output : float
-//-----------------------------------------------------------------------------
-float CFuncRotating::GetNextMoveInterval() const
-{
- if ( m_bStopAtStartPos )
- {
- return TICK_INTERVAL;
- }
- return 0.1f;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets the current speed to the given value and manages the sound effects.
-// Input : flNewSpeed - New speed in degrees per second.
-//-----------------------------------------------------------------------------
-void CFuncRotating::UpdateSpeed( float flNewSpeed )
-{
- float flOldSpeed = m_flSpeed;
- m_flSpeed = clamp( flNewSpeed, -m_flMaxSpeed, m_flMaxSpeed );
-
- if ( m_bStopAtStartPos )
- {
- int checkAxis = 2;
- // See if we got close to the starting orientation
- if ( m_vecMoveAng[0] != 0 )
- {
- checkAxis = 0;
- }
- else if ( m_vecMoveAng[1] != 0 )
- {
- checkAxis = 1;
- }
-
- float angDelta = anglemod( GetLocalAngles()[ checkAxis ] - m_angStart[ checkAxis ] );
- if ( angDelta > 180.0f )
- {
- angDelta -= 360.0f;
- }
-
- if ( flNewSpeed < 100 )
- {
- if ( flNewSpeed <= 25 && fabs( angDelta ) < 1.0f )
- {
- m_flTargetSpeed = 0;
- m_bStopAtStartPos = false;
- m_flSpeed = 0.0f;
-
- SetLocalAngles( m_angStart );
- }
- else if ( fabs( angDelta ) > 90.0f )
- {
- // Keep rotating at same speed for now
- m_flSpeed = flOldSpeed;
- }
- else
- {
- float minSpeed = fabs( angDelta );
- if ( minSpeed < 20 )
- minSpeed = 20;
-
- m_flSpeed = flOldSpeed > 0.0f ? minSpeed : -minSpeed;
- }
- }
- }
-
-
- if ( ( flOldSpeed == 0 ) && ( m_flSpeed != 0 ) )
- {
- // Starting to move - emit the sound.
- CPASAttenuationFilter filter( GetAbsOrigin(), m_flAttenuation );
- filter.MakeReliable();
-
- EmitSound_t ep;
- ep.m_nChannel = CHAN_STATIC;
- ep.m_pSoundName = STRING(m_NoiseRunning);
- ep.m_flVolume = 0.01;
- ep.m_SoundLevel = ATTN_TO_SNDLVL( m_flAttenuation );
- ep.m_nPitch = FANPITCHMIN;
-
- EmitSound( filter, entindex(), ep );
- RampPitchVol();
- }
- else if ( ( flOldSpeed != 0 ) && ( m_flSpeed == 0 ) )
- {
- // Stopping - stop the sound.
- StopSound( entindex(), CHAN_STATIC, STRING(m_NoiseRunning) );
-
- }
- else
- {
- // Changing speed - adjust the pitch and volume.
- RampPitchVol();
- }
-
- SetLocalAngularVelocity( m_vecMoveAng * m_flSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Think function. Accelerates a func_rotating to a higher angular velocity.
-//-----------------------------------------------------------------------------
-void CFuncRotating::SpinUpMove( void )
-{
- //
- // Calculate our new speed.
- //
- bool bSpinUpDone = false;
- float flNewSpeed = fabs( m_flSpeed ) + 0.2 * m_flMaxSpeed * m_flFanFriction;
- if ( fabs( flNewSpeed ) >= fabs( m_flTargetSpeed ) )
- {
- // Reached our target speed.
- flNewSpeed = m_flTargetSpeed;
- bSpinUpDone = !m_bStopAtStartPos;
- }
- else if ( m_flTargetSpeed < 0 )
- {
- // Spinning up in reverse - negate the speed.
- flNewSpeed *= -1;
- }
-
- //
- // Apply the new speed, adjust sound pitch and volume.
- //
- UpdateSpeed( flNewSpeed );
-
- //
- // If we've met or exceeded target speed, stop spinning up.
- //
- if ( bSpinUpDone )
- {
- SetMoveDone( &CFuncRotating::RotateMove );
- RotateMove();
- }
-
- SetMoveDoneTime( GetNextMoveInterval() );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Decelerates the rotator from a higher speed to a lower one.
-// Input : flTargetSpeed - Speed to spin down to.
-// Output : Returns true if we reached the target speed, false otherwise.
-//-----------------------------------------------------------------------------
-bool CFuncRotating::SpinDown( float flTargetSpeed )
-{
- //
- // Bleed off a little speed due to friction.
- //
- bool bSpinDownDone = false;
- float flNewSpeed = fabs( m_flSpeed ) - 0.1 * m_flMaxSpeed * m_flFanFriction;
- if ( flNewSpeed < 0 )
- {
- flNewSpeed = 0;
- }
-
- if ( fabs( flNewSpeed ) <= fabs( flTargetSpeed ) )
- {
- // Reached our target speed.
- flNewSpeed = flTargetSpeed;
- bSpinDownDone = !m_bStopAtStartPos;
- }
- else if ( m_flSpeed < 0 )
- {
- // Spinning down in reverse - negate the speed.
- flNewSpeed *= -1;
- }
-
- //
- // Apply the new speed, adjust sound pitch and volume.
- //
- UpdateSpeed( flNewSpeed );
-
- //
- // If we've met or exceeded target speed, stop spinning down.
- //
- return bSpinDownDone;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Think function. Decelerates a func_rotating to a lower angular velocity.
-//-----------------------------------------------------------------------------
-void CFuncRotating::SpinDownMove( void )
-{
- //
- // If we've met or exceeded target speed, stop spinning down.
- //
- if ( SpinDown( m_flTargetSpeed ) )
- {
- SetMoveDone( &CFuncRotating::RotateMove );
- RotateMove();
- }
- else
- {
- SetMoveDoneTime( GetNextMoveInterval() );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Think function for reversing directions. Spins down to zero, then
-// starts spinning up to the target speed.
-//-----------------------------------------------------------------------------
-void CFuncRotating::ReverseMove( void )
-{
- if ( SpinDown( 0 ) )
- {
- // We've reached zero - spin back up to the target speed.
- SetTargetSpeed( m_flTargetSpeed );
- }
- else
- {
- SetMoveDoneTime( GetNextMoveInterval() );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Think function. Called while rotating at a constant angular velocity.
-//-----------------------------------------------------------------------------
-void CFuncRotating::RotateMove( void )
-{
- SetMoveDoneTime( 10 );
-
- if ( m_bStopAtStartPos )
- {
- SetMoveDoneTime( GetNextMoveInterval() );
- int checkAxis = 2;
-
- // See if we got close to the starting orientation
- if ( m_vecMoveAng[0] != 0 )
- {
- checkAxis = 0;
- }
- else if ( m_vecMoveAng[1] != 0 )
- {
- checkAxis = 1;
- }
-
- float angDelta = anglemod( GetLocalAngles()[ checkAxis ] - m_angStart[ checkAxis ] );
- if ( angDelta > 180.0f )
- angDelta -= 360.0f;
-
- QAngle avel = GetLocalAngularVelocity();
- // Delta per tick
- QAngle avelpertick = avel * TICK_INTERVAL;
-
- if ( fabs( angDelta ) < fabs( avelpertick[ checkAxis ] ) )
- {
- SetTargetSpeed( 0 );
- SetLocalAngles( m_angStart );
- m_bStopAtStartPos = false;
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Used for debug output. Returns the given speed considering our current
-// direction of rotation, so that positive values are forward and negative
-// values are backward.
-// Input : flSpeed - Angular speed in degrees per second.
-//-----------------------------------------------------------------------------
-float CFuncRotating::GetMoveSpeed( float flSpeed )
-{
- if ( m_vecMoveAng[0] != 0 )
- {
- return flSpeed * m_vecMoveAng[0];
- }
-
- if ( m_vecMoveAng[1] != 0 )
- {
- return flSpeed * m_vecMoveAng[1];
- }
-
- return flSpeed * m_vecMoveAng[2];
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets a new angular velocity to achieve.
-// Input : flSpeed - Target angular velocity in degrees per second.
-//-----------------------------------------------------------------------------
-void CFuncRotating::SetTargetSpeed( float flSpeed )
-{
- //
- // Make sure the sign is correct - positive for forward rotation,
- // negative for reverse rotation.
- //
- flSpeed = fabs( flSpeed );
- if ( m_bReversed )
- {
- flSpeed *= -1;
- }
-
- m_flTargetSpeed = flSpeed;
-
- //
- // If we don't accelerate, change to the new speed instantly.
- //
- if ( !HasSpawnFlags(SF_BRUSH_ACCDCC ) )
- {
- UpdateSpeed( m_flTargetSpeed );
- SetMoveDone( &CFuncRotating::RotateMove );
- }
- //
- // Otherwise deal with acceleration/deceleration:
- //
- else
- {
- //
- // Check for reversing directions.
- //
- if ((( m_flSpeed > 0 ) && ( m_flTargetSpeed < 0 )) ||
- (( m_flSpeed < 0 ) && ( m_flTargetSpeed > 0 )))
- {
- SetMoveDone( &CFuncRotating::ReverseMove );
- }
- //
- // If we are below the new target speed, spin up to the target speed.
- //
- else if ( fabs( m_flSpeed ) < fabs( m_flTargetSpeed ) )
- {
- SetMoveDone( &CFuncRotating::SpinUpMove );
- }
- //
- // If we are above the new target speed, spin down to the target speed.
- //
- else if ( fabs( m_flSpeed ) > fabs( m_flTargetSpeed ) )
- {
- SetMoveDone( &CFuncRotating::SpinDownMove );
- }
- //
- // We are already at the new target speed. Just keep rotating.
- //
- else
- {
- SetMoveDone( &CFuncRotating::RotateMove );
- }
- }
-
- SetMoveDoneTime( GetNextMoveInterval() );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Called when a rotating brush is used by the player.
-// Input : pActivator -
-// pCaller -
-// useType -
-// value -
-//-----------------------------------------------------------------------------
-void CFuncRotating::RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- //
- // If the rotator is spinning, stop it.
- //
- if ( m_flSpeed != 0 )
- {
- SetTargetSpeed( 0 );
- }
- //
- // Rotator is not moving, so start it.
- //
- else
- {
- SetTargetSpeed( m_flMaxSpeed );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler that reverses the direction of rotation.
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputReverse( inputdata_t &inputdata )
-{
- m_bStopAtStartPos = false;
- m_bReversed = !m_bReversed;
- SetTargetSpeed( m_flSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler for setting the speed of the rotator.
-// Input : Float target angular velocity as a ratio of maximum speed [0, 1].
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputSetSpeed( inputdata_t &inputdata )
-{
- m_bStopAtStartPos = false;
- float flSpeed = inputdata.value.Float();
- m_bReversed = flSpeed < 0 ? true : false;
- flSpeed = fabs(flSpeed);
- SetTargetSpeed( clamp( flSpeed, 0.f, 1.f ) * m_flMaxSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler to start the rotator spinning.
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputStart( inputdata_t &inputdata )
-{
- m_bStopAtStartPos = false;
- SetTargetSpeed( m_flMaxSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler to start the rotator spinning.
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputStartForward( inputdata_t &inputdata )
-{
- m_bReversed = false;
- SetTargetSpeed( m_flMaxSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler to start the rotator spinning.
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputStartBackward( inputdata_t &inputdata )
-{
- m_bStopAtStartPos = false;
- m_bReversed = true;
- SetTargetSpeed( m_flMaxSpeed );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler to stop the rotator from spinning.
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputStop( inputdata_t &inputdata )
-{
- m_bStopAtStartPos = false;
- SetTargetSpeed( 0 );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &inputdata -
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputStopAtStartPos( inputdata_t &inputdata )
-{
- m_bStopAtStartPos = true;
- SetTargetSpeed( 0 );
- SetMoveDoneTime( GetNextMoveInterval() );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Starts the rotator if it is still, stops it if it is spinning.
-//-----------------------------------------------------------------------------
-void CFuncRotating::InputToggle( inputdata_t &inputdata )
-{
- if (m_flSpeed > 0)
- {
- SetTargetSpeed( 0 );
- }
- else
- {
- SetTargetSpeed( m_flMaxSpeed );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: An entity has blocked the brush.
-// Input : pOther -
-//-----------------------------------------------------------------------------
-void CFuncRotating::Blocked( CBaseEntity *pOther )
-{
-#ifdef HL1_DLL
- if( m_flBlockDamage > 0 )
-#endif
- pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Draw any debug text overlays
-// Input :
-// Output : Current text offset from the top
-//-----------------------------------------------------------------------------
-int CFuncRotating::DrawDebugTextOverlays(void)
-{
- int text_offset = BaseClass::DrawDebugTextOverlays();
-
- if (m_debugOverlays & OVERLAY_TEXT_BIT)
- {
- char tempstr[512];
- Q_snprintf( tempstr, sizeof( tempstr ),"Speed cur (target): %3.2f (%3.2f)", GetMoveSpeed( m_flSpeed ), GetMoveSpeed( m_flTargetSpeed ) );
- EntityText(text_offset,tempstr,0);
- text_offset++;
- }
- return text_offset;
-
-}
-
-
-class CFuncVPhysicsClip : public CBaseEntity
-{
- DECLARE_DATADESC();
- DECLARE_CLASS( CFuncVPhysicsClip, CBaseEntity );
-
-public:
- void Spawn();
- void Activate();
- bool CreateVPhysics( void );
-
- bool EntityPassesFilter( CBaseEntity *pOther );
- bool ForceVPhysicsCollide( CBaseEntity *pEntity );
-
- void InputEnable( inputdata_t &inputdata );
- void InputDisable( inputdata_t &inputdata );
-
-private:
-
- string_t m_iFilterName;
- CHandle<CBaseFilter> m_hFilter;
- bool m_bDisabled;
-};
-
-// Global Savedata for base trigger
-BEGIN_DATADESC( CFuncVPhysicsClip )
-
- // Keyfields
- DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ),
- DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ),
- DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ),
-
- DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
-
-END_DATADESC()
-
-
-LINK_ENTITY_TO_CLASS( func_clip_vphysics, CFuncVPhysicsClip );
-
-void CFuncVPhysicsClip::Spawn( void )
-{
- SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
- SetSolid( SOLID_VPHYSICS );
- AddSolidFlags( FSOLID_NOT_SOLID );
- SetModel( STRING( GetModelName() ) );
- AddEffects( EF_NODRAW );
- CreateVPhysics();
- VPhysicsGetObject()->EnableCollisions( !m_bDisabled );
-}
-
-
-bool CFuncVPhysicsClip::CreateVPhysics( void )
-{
- VPhysicsInitStatic();
- return true;
-}
-
-
-void CFuncVPhysicsClip::Activate( void )
-{
- // Get a handle to my filter entity if there is one
- if (m_iFilterName != NULL_STRING)
- {
- m_hFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iFilterName ));
- }
- BaseClass::Activate();
-}
-
-bool CFuncVPhysicsClip::EntityPassesFilter( CBaseEntity *pOther )
-{
- CBaseFilter* pFilter = (CBaseFilter*)(m_hFilter.Get());
-
- if ( pFilter )
- return pFilter->PassesFilter( this, pOther );
-
- if ( pOther->GetMoveType() == MOVETYPE_VPHYSICS && pOther->VPhysicsGetObject()->IsMoveable() )
- return true;
-
- return false;
-}
-
-
-bool CFuncVPhysicsClip::ForceVPhysicsCollide( CBaseEntity *pEntity )
-{
- return EntityPassesFilter(pEntity);
-}
-
-void CFuncVPhysicsClip::InputEnable( inputdata_t &inputdata )
-{
- VPhysicsGetObject()->EnableCollisions(true);
- m_bDisabled = false;
-}
-
-void CFuncVPhysicsClip::InputDisable( inputdata_t &inputdata )
-{
- VPhysicsGetObject()->EnableCollisions(false);
- m_bDisabled = true;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Spawn, think, and use functions for common brush entities.
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "doors.h"
+#include "mathlib/mathlib.h"
+#include "physics.h"
+#include "ndebugoverlay.h"
+#include "engine/IEngineSound.h"
+#include "globals.h"
+#include "filters.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define SF_BRUSH_ACCDCC 16// brush should accelerate and decelerate when toggled
+#define SF_BRUSH_HURT 32// rotating brush that inflicts pain based on rotation speed
+#define SF_ROTATING_NOT_SOLID 64 // some special rotating objects are not solid.
+
+// =================== FUNC_WALL ==============================================
+class CFuncWall : public CBaseEntity
+{
+public:
+ DECLARE_DATADESC();
+ DECLARE_CLASS( CFuncWall, CBaseEntity );
+ void Spawn( void );
+ bool CreateVPhysics( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+
+ int m_nState;
+};
+
+LINK_ENTITY_TO_CLASS( func_wall, CFuncWall );
+
+//---------------------------------------------------------
+// Save/Restore
+//---------------------------------------------------------
+BEGIN_DATADESC( CFuncWall )
+
+ DEFINE_FIELD( m_nState, FIELD_INTEGER ),
+
+END_DATADESC()
+
+void CFuncWall::Spawn( void )
+{
+ SetLocalAngles( vec3_angle );
+ SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
+ SetModel( STRING( GetModelName() ) );
+
+ // If it can't move/go away, it's really part of the world
+ AddFlag( FL_WORLDBRUSH );
+
+ // set manual mode
+ CreateVPhysics();
+}
+
+
+bool CFuncWall::CreateVPhysics( void )
+{
+ SetSolid( SOLID_BSP );
+ IPhysicsObject *pPhys = VPhysicsInitStatic();
+ if ( pPhys )
+ {
+ int contents = modelinfo->GetModelContents( GetModelIndex() );
+ if ( ! (contents & (MASK_SOLID|MASK_PLAYERSOLID|MASK_NPCSOLID)) )
+ {
+ // leave the physics shadow there in case it has crap constrained to it
+ // but disable collisions with it
+ pPhys->EnableCollisions( false );
+ }
+ }
+
+ return true;
+}
+
+
+void CFuncWall::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ if ( ShouldToggle( useType, m_nState ) )
+ {
+ m_nState = 1 - m_nState;
+ }
+}
+
+
+#define SF_WALL_START_OFF 0x0001
+
+class CFuncWallToggle : public CFuncWall
+{
+public:
+ DECLARE_CLASS( CFuncWallToggle, CFuncWall );
+
+ DECLARE_DATADESC();
+
+ void Spawn( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+
+ void InputToggle( inputdata_t &inputdata );
+
+ void TurnOff( void );
+ void TurnOn( void );
+ bool IsOn( void );
+};
+
+BEGIN_DATADESC( CFuncWallToggle )
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
+
+END_DATADESC()
+
+
+LINK_ENTITY_TO_CLASS( func_wall_toggle, CFuncWallToggle );
+
+void CFuncWallToggle::Spawn( void )
+{
+ BaseClass::Spawn();
+ if ( HasSpawnFlags( SF_WALL_START_OFF ) )
+ TurnOff();
+
+ SetMoveType( MOVETYPE_PUSH );
+}
+
+
+void CFuncWallToggle::TurnOff( void )
+{
+ IPhysicsObject *pPhys = VPhysicsGetObject();
+ if ( pPhys )
+ {
+ pPhys->EnableCollisions( false );
+ }
+ AddSolidFlags( FSOLID_NOT_SOLID );
+ AddEffects( EF_NODRAW );
+}
+
+
+void CFuncWallToggle::TurnOn( void )
+{
+ IPhysicsObject *pPhys = VPhysicsGetObject();
+ if ( pPhys )
+ {
+ pPhys->EnableCollisions( true );
+ }
+ RemoveSolidFlags( FSOLID_NOT_SOLID );
+ RemoveEffects( EF_NODRAW );
+}
+
+
+bool CFuncWallToggle::IsOn( void )
+{
+ if ( IsSolidFlagSet( FSOLID_NOT_SOLID ) )
+ return false;
+ return true;
+}
+
+void CFuncWallToggle::InputToggle( inputdata_t &inputdata )
+{
+ int status = IsOn();
+
+ if ( ShouldToggle( USE_TOGGLE, status ) )
+ {
+ if ( status )
+ TurnOff();
+ else
+ TurnOn();
+ }
+}
+
+//Adrian - Is this function needed at all?
+void CFuncWallToggle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ int status = IsOn();
+
+ if ( ShouldToggle( useType, status ) )
+ {
+ if ( status )
+ TurnOff();
+ else
+ TurnOn();
+ }
+}
+
+//============================== FUNC_VEHICLECLIP =====================================
+class CFuncVehicleClip : public CBaseEntity
+{
+public:
+ DECLARE_CLASS( CFuncVehicleClip, CBaseEntity );
+ DECLARE_DATADESC();
+
+ void Spawn();
+ bool CreateVPhysics( void );
+
+ void InputEnable( inputdata_t &data );
+ void InputDisable( inputdata_t &data );
+
+private:
+};
+
+BEGIN_DATADESC( CFuncVehicleClip )
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( func_vehicleclip, CFuncVehicleClip );
+
+void CFuncVehicleClip::Spawn()
+{
+
+ SetLocalAngles( vec3_angle );
+ SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
+ SetModel( STRING( GetModelName() ) );
+
+ // It's part of the world
+ AddFlag( FL_WORLDBRUSH );
+
+ CreateVPhysics();
+
+ AddEffects( EF_NODRAW ); // make entity invisible
+
+ SetCollisionGroup( COLLISION_GROUP_VEHICLE_CLIP );
+}
+
+bool CFuncVehicleClip::CreateVPhysics( void )
+{
+ SetSolid( SOLID_BSP );
+ VPhysicsInitStatic();
+
+ return true;
+}
+
+void CFuncVehicleClip::InputEnable( inputdata_t &data )
+{
+ IPhysicsObject *pPhys = VPhysicsGetObject();
+ if ( pPhys )
+ {
+ pPhys->EnableCollisions( true );
+ }
+ RemoveSolidFlags( FSOLID_NOT_SOLID );
+}
+
+void CFuncVehicleClip::InputDisable( inputdata_t &data )
+{
+ IPhysicsObject *pPhys = VPhysicsGetObject();
+ if ( pPhys )
+ {
+ pPhys->EnableCollisions( false );
+ }
+ AddSolidFlags( FSOLID_NOT_SOLID );
+}
+
+//============================= FUNC_CONVEYOR =======================================
+
+#define SF_CONVEYOR_VISUAL 0x0001
+#define SF_CONVEYOR_NOTSOLID 0x0002
+
+class CFuncConveyor : public CFuncWall
+{
+public:
+ DECLARE_CLASS( CFuncConveyor, CFuncWall );
+ DECLARE_DATADESC();
+ DECLARE_SERVERCLASS();
+
+ CFuncConveyor();
+
+ void Spawn( void );
+ void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+ void UpdateSpeed( float flNewSpeed );
+
+ void GetGroundVelocityToApply( Vector &vecGroundVel );
+
+ // Input handlers.
+ void InputToggleDirection( inputdata_t &inputdata );
+ void InputSetSpeed( inputdata_t &inputdata );
+
+private:
+
+ Vector m_vecMoveDir;
+ CNetworkVar( float, m_flConveyorSpeed );
+};
+
+LINK_ENTITY_TO_CLASS( func_conveyor, CFuncConveyor );
+
+BEGIN_DATADESC( CFuncConveyor )
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "ToggleDirection", InputToggleDirection ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "SetSpeed", InputSetSpeed ),
+
+ DEFINE_KEYFIELD( m_vecMoveDir, FIELD_VECTOR, "movedir" ),
+ DEFINE_FIELD( m_flConveyorSpeed, FIELD_FLOAT ),
+
+END_DATADESC()
+
+
+IMPLEMENT_SERVERCLASS_ST(CFuncConveyor, DT_FuncConveyor)
+ SendPropFloat( SENDINFO(m_flConveyorSpeed), 0, SPROP_NOSCALE ),
+END_SEND_TABLE()
+
+
+CFuncConveyor::CFuncConveyor()
+{
+ m_flConveyorSpeed = 0.0;
+}
+
+void CFuncConveyor::Spawn( void )
+{
+ // Convert movedir from angles to a vector
+ QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z );
+ AngleVectors( angMoveDir, &m_vecMoveDir );
+
+ BaseClass::Spawn();
+
+ if ( !HasSpawnFlags(SF_CONVEYOR_VISUAL) )
+ AddFlag( FL_CONVEYOR );
+
+ // HACKHACK - This is to allow for some special effects
+ if ( HasSpawnFlags( SF_CONVEYOR_NOTSOLID ) )
+ {
+ AddSolidFlags( FSOLID_NOT_SOLID );
+ }
+
+ if ( m_flSpeed == 0 )
+ m_flSpeed = 100;
+
+ UpdateSpeed( m_flSpeed );
+}
+
+
+void CFuncConveyor::UpdateSpeed( float flNewSpeed )
+{
+ m_flConveyorSpeed = flNewSpeed;
+}
+
+
+void CFuncConveyor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ m_flSpeed = -m_flSpeed;
+ UpdateSpeed( m_flSpeed );
+}
+
+
+void CFuncConveyor::InputToggleDirection( inputdata_t &inputdata )
+{
+ Use( inputdata.pActivator, inputdata.pCaller, USE_TOGGLE, 0 );
+}
+
+
+void CFuncConveyor::InputSetSpeed( inputdata_t &inputdata )
+{
+ m_flSpeed = inputdata.value.Float();
+ UpdateSpeed( m_flSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the velocity imparted to players standing on us.
+//-----------------------------------------------------------------------------
+void CFuncConveyor::GetGroundVelocityToApply( Vector &vecGroundVel )
+{
+ vecGroundVel = m_vecMoveDir * m_flSpeed;
+}
+
+
+// =================== FUNC_ILLUSIONARY ==============================================
+// A simple entity that looks solid but lets you walk through it.
+class CFuncIllusionary : public CBaseEntity
+{
+ DECLARE_CLASS( CFuncIllusionary, CBaseEntity );
+public:
+ void Spawn( void );
+};
+
+LINK_ENTITY_TO_CLASS( func_illusionary, CFuncIllusionary );
+
+void CFuncIllusionary::Spawn( void )
+{
+ SetLocalAngles( vec3_angle );
+ SetMoveType( MOVETYPE_NONE );
+ SetSolid( SOLID_NONE );
+ SetModel( STRING( GetModelName() ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: A rotating brush entity.
+//
+// You need to have an origin brush as part of this entity. The
+// center of that brush will be the point around which it is rotated.
+//
+// It will rotate around the Z axis by default. Spawnflags can be set
+// to make it rotate around the X or Y axes.
+//
+// The direction of rotation is also controlled by a spawnflag.
+//-----------------------------------------------------------------------------
+class CFuncRotating : public CBaseEntity
+{
+ DECLARE_CLASS( CFuncRotating, CBaseEntity );
+public:
+ // basic functions
+ void Spawn( void );
+ void Precache( void );
+ bool CreateVPhysics( void );
+ void SpinUpMove( void );
+ void SpinDownMove( void );
+ bool KeyValue( const char *szKeyName, const char *szValue );
+ void HurtTouch ( CBaseEntity *pOther );
+ void RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+ void RotateMove( void );
+ void ReverseMove( void );
+ void RampPitchVol( void );
+ void Blocked( CBaseEntity *pOther );
+ void SetTargetSpeed( float flSpeed );
+ void UpdateSpeed( float flNewSpeed );
+
+ int DrawDebugTextOverlays(void);
+
+ DECLARE_DATADESC();
+ DECLARE_SERVERCLASS();
+
+protected:
+ bool SpinDown( float flTargetSpeed );
+ float GetMoveSpeed( float flSpeed );
+
+ float GetNextMoveInterval() const;
+
+ // Input handlers
+ void InputSetSpeed( inputdata_t &inputdata );
+ void InputStart( inputdata_t &inputdata );
+ void InputStop( inputdata_t &inputdata );
+ void InputStartForward( inputdata_t &inputdata );
+ void InputStartBackward( inputdata_t &inputdata );
+ void InputToggle( inputdata_t &inputdata );
+ void InputReverse( inputdata_t &inputdata );
+ void InputStopAtStartPos( inputdata_t &inputdata );
+
+ QAngle m_vecMoveAng;
+
+ float m_flFanFriction;
+ float m_flAttenuation;
+ float m_flVolume;
+ float m_flTargetSpeed; // Target value for m_flSpeed, used for spinning up and down.
+ float m_flMaxSpeed; // Maximum value for m_flSpeed, used for ramping sound effects.
+ float m_flBlockDamage; // Damage inflicted when blocked.
+ string_t m_NoiseRunning;
+ bool m_bReversed;
+
+ QAngle m_angStart;
+ bool m_bStopAtStartPos;
+
+ bool m_bSolidBsp; // Brush is SOLID_BSP
+
+public:
+ Vector m_vecClientOrigin;
+ QAngle m_vecClientAngles;
+};
+
+LINK_ENTITY_TO_CLASS( func_rotating, CFuncRotating );
+
+
+BEGIN_DATADESC( CFuncRotating )
+
+ DEFINE_FIELD( m_vecMoveAng, FIELD_VECTOR ),
+ DEFINE_FIELD( m_flFanFriction, FIELD_FLOAT ),
+ DEFINE_FIELD( m_flAttenuation, FIELD_FLOAT ),
+ DEFINE_FIELD( m_flVolume, FIELD_FLOAT ),
+ DEFINE_FIELD( m_flTargetSpeed, FIELD_FLOAT ),
+ DEFINE_KEYFIELD( m_flMaxSpeed, FIELD_FLOAT, "maxspeed" ),
+ DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "dmg" ),
+ DEFINE_KEYFIELD( m_NoiseRunning, FIELD_SOUNDNAME, "message" ),
+ DEFINE_FIELD( m_bReversed, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_angStart, FIELD_VECTOR ),
+ DEFINE_FIELD( m_bStopAtStartPos, FIELD_BOOLEAN ),
+ DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ),
+
+ // Function Pointers
+ DEFINE_FUNCTION( SpinUpMove ),
+ DEFINE_FUNCTION( SpinDownMove ),
+ DEFINE_FUNCTION( HurtTouch ),
+ DEFINE_FUNCTION( RotatingUse ),
+ DEFINE_FUNCTION( RotateMove ),
+ DEFINE_FUNCTION( ReverseMove ),
+
+ // Inputs
+ DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Reverse", InputReverse ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "StartForward", InputStartForward ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "StartBackward", InputStartBackward ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "StopAtStartPos", InputStopAtStartPos ),
+
+END_DATADESC()
+
+extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
+void SendProxy_FuncRotatingOrigin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID )
+{
+#ifdef TF_DLL
+ CFuncRotating *entity = (CFuncRotating*)pStruct;
+ Assert( entity );
+
+ if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
+ {
+ const Vector *v = &entity->m_vecClientOrigin;
+ pOut->m_Vector[ 0 ] = v->x;
+ pOut->m_Vector[ 1 ] = v->y;
+ pOut->m_Vector[ 2 ] = v->z;
+ return;
+ }
+#endif
+
+ SendProxy_Origin( pProp, pStruct, pData, pOut, iElement, objectID );
+}
+
+/*
+extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
+void SendProxy_FuncRotatingAngles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID )
+{
+ CFuncRotating *entity = (CFuncRotating*)pStruct;
+ Assert( entity );
+ if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
+ {
+ const QAngle *a = &entity->m_vecClientAngles;
+ pOut->m_Vector[ 0 ] = anglemod( a->x );
+ pOut->m_Vector[ 1 ] = anglemod( a->y );
+ pOut->m_Vector[ 2 ] = anglemod( a->z );
+ return;
+ }
+
+ SendProxy_Angles( pProp, pStruct, pData, pOut, iElement, objectID );
+}
+*/
+void SendProxy_FuncRotatingAngle( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID)
+{
+ CFuncRotating *entity = (CFuncRotating*)pStruct;
+ Assert( entity );
+
+ vec_t const *qa = (vec_t *)pData;
+ vec_t const *ea = entity->GetLocalAngles().Base();
+ NOTE_UNUSED(ea);
+ // Assert its actually an index into m_angRotation if not this won't work
+
+ Assert( (uintp)qa >= (uintp)ea && (uintp)qa < (uintp)ea + sizeof( QAngle ));
+
+#ifdef TF_DLL
+ if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
+ {
+ const QAngle *a = &entity->m_vecClientAngles;
+
+ pOut->m_Float = anglemod( (*a)[ qa - ea ] );
+ return;
+ }
+#endif
+
+ pOut->m_Float = anglemod( *qa );
+
+ Assert( IsFinite( pOut->m_Float ) );
+}
+
+
+extern void SendProxy_SimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID );
+void SendProxy_FuncRotatingSimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID )
+{
+#ifdef TF_DLL
+ CFuncRotating *entity = (CFuncRotating*)pStruct;
+ Assert( entity );
+
+ if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
+ {
+ pOut->m_Int = 0;
+ return;
+ }
+#endif
+
+ SendProxy_SimulationTime( pProp, pStruct, pVarData, pOut, iElement, objectID );
+}
+
+IMPLEMENT_SERVERCLASS_ST(CFuncRotating, DT_FuncRotating)
+ SendPropExclude( "DT_BaseEntity", "m_angRotation" ),
+ SendPropExclude( "DT_BaseEntity", "m_vecOrigin" ),
+ SendPropExclude( "DT_BaseEntity", "m_flSimulationTime" ),
+
+ SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_FuncRotatingOrigin ),
+ SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 0), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngle ),
+ SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 1), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngle ),
+ SendPropAngle( SENDINFO_VECTORELEM(m_angRotation, 2), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngle ),
+
+ SendPropInt(SENDINFO(m_flSimulationTime), SIMULATION_TIME_WINDOW_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_FuncRotatingSimulationTime),
+END_SEND_TABLE()
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Handles keyvalues from the BSP. Called before spawning.
+//-----------------------------------------------------------------------------
+bool CFuncRotating::KeyValue( const char *szKeyName, const char *szValue )
+{
+ if (FStrEq(szKeyName, "fanfriction"))
+ {
+ m_flFanFriction = atof(szValue)/100;
+ }
+ else if (FStrEq(szKeyName, "Volume"))
+ {
+ m_flVolume = atof(szValue) / 10.0;
+ m_flVolume = clamp(m_flVolume, 0.0f, 1.0f);
+ }
+ else
+ {
+ return BaseClass::KeyValue( szKeyName, szValue );
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when spawning, after keyvalues have been set.
+//-----------------------------------------------------------------------------
+void CFuncRotating::Spawn( )
+{
+#ifdef TF_DLL
+ AddSpawnFlags( SF_BRUSH_ROTATE_CLIENTSIDE );
+#endif
+
+ //
+ // Maintain compatibility with previous maps.
+ //
+ if (m_flVolume == 0.0)
+ {
+ m_flVolume = 1.0;
+ }
+
+ //
+ // If the designer didn't set a sound attenuation, default to one.
+ //
+ if ( HasSpawnFlags(SF_BRUSH_ROTATE_SMALLRADIUS) )
+ {
+ m_flAttenuation = ATTN_IDLE;
+ }
+ else if ( HasSpawnFlags(SF_BRUSH_ROTATE_MEDIUMRADIUS) )
+ {
+ m_flAttenuation = ATTN_STATIC;
+ }
+ else if ( HasSpawnFlags(SF_BRUSH_ROTATE_LARGERADIUS) )
+ {
+ m_flAttenuation = ATTN_NORM;
+ }
+ else
+ {
+ m_flAttenuation = ATTN_NORM;
+ }
+
+ //
+ // Prevent divide by zero if level designer forgets friction!
+ //
+ if ( m_flFanFriction == 0 )
+ {
+ m_flFanFriction = 1;
+ }
+
+ //
+ // Build the axis of rotation based on spawnflags.
+ //
+ if ( HasSpawnFlags(SF_BRUSH_ROTATE_Z_AXIS) )
+ {
+ m_vecMoveAng = QAngle(0,0,1);
+ }
+ else if ( HasSpawnFlags(SF_BRUSH_ROTATE_X_AXIS) )
+ {
+ m_vecMoveAng = QAngle(1,0,0);
+ }
+ else
+ {
+ m_vecMoveAng = QAngle(0,1,0); // y-axis
+ }
+
+ //
+ // Check for reverse rotation.
+ //
+ if ( HasSpawnFlags(SF_BRUSH_ROTATE_BACKWARDS) )
+ {
+ m_vecMoveAng = m_vecMoveAng * -1;
+ }
+
+ SetSolid( SOLID_VPHYSICS );
+
+ //
+ // Some rotating objects like fake volumetric lights will not be solid.
+ //
+ if ( HasSpawnFlags(SF_ROTATING_NOT_SOLID) )
+ {
+ AddSolidFlags( FSOLID_NOT_SOLID );
+ SetMoveType( MOVETYPE_PUSH );
+ }
+ else
+ {
+ RemoveSolidFlags( FSOLID_NOT_SOLID );
+ SetMoveType( MOVETYPE_PUSH );
+ }
+
+ SetModel( STRING( GetModelName() ) );
+
+ SetUse( &CFuncRotating::RotatingUse );
+
+ //
+ // Did level designer forget to assign a maximum speed? Prevent a divide by
+ // zero in RampPitchVol as well as allowing the rotator to work.
+ //
+ m_flMaxSpeed = fabs( m_flMaxSpeed );
+ if (m_flMaxSpeed == 0)
+ {
+ m_flMaxSpeed = 100;
+ }
+
+ //
+ // If the brush should be initially rotating, use it in a little while.
+ //
+ if ( HasSpawnFlags(SF_BRUSH_ROTATE_START_ON) )
+ {
+ SetThink( &CFuncRotating::SUB_CallUseToggle );
+ SetNextThink( gpGlobals->curtime + .2 ); // leave a magic delay for client to start up
+ }
+
+ //
+ // Can this brush inflict pain?
+ //
+ if ( HasSpawnFlags(SF_BRUSH_HURT) )
+ {
+ SetTouch( &CFuncRotating::HurtTouch );
+ }
+
+ //
+ // Set speed to 0 in case there's an old "speed" key lying around.
+ //
+ m_flSpeed = 0;
+
+ Precache( );
+ CreateVPhysics();
+
+ m_angStart = GetLocalAngles();
+
+ // Slam the object back to solid - if we really want it to be solid.
+ if ( m_bSolidBsp )
+ {
+ SetSolid( SOLID_BSP );
+ }
+
+#ifdef TF_DLL
+ if ( HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) )
+ {
+ m_vecClientOrigin = GetLocalOrigin();
+ m_vecClientAngles = GetLocalAngles();
+ }
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CFuncRotating::CreateVPhysics( void )
+{
+ if ( !IsSolidFlagSet( FSOLID_NOT_SOLID ))
+ {
+ VPhysicsInitShadow( false, false );
+ }
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CFuncRotating::Precache( void )
+{
+ //
+ // Set up rotation sound.
+ //
+ char *szSoundFile = ( char * )STRING( m_NoiseRunning );
+ if ( !m_NoiseRunning || strlen( szSoundFile ) == 0 )
+ {
+ // No sound set up, use the null sound.
+ m_NoiseRunning = AllocPooledString("DoorSound.Null");
+ }
+ PrecacheScriptSound( STRING( m_NoiseRunning ) );
+
+ if (GetLocalAngularVelocity() != vec3_angle )
+ {
+ //
+ // If fan was spinning, and we went through transition or save/restore,
+ // make sure we restart the sound. 1.5 sec delay is a magic number.
+ //
+ SetMoveDone( &CFuncRotating::SpinUpMove );
+ SetMoveDoneTime( 1.5 );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Will hurt others based on how fast the brush is spinning.
+// Input : pOther -
+//-----------------------------------------------------------------------------
+void CFuncRotating::HurtTouch ( CBaseEntity *pOther )
+{
+ // we can't hurt this thing, so we're not concerned with it
+ if ( !pOther->m_takedamage )
+ return;
+
+ // calculate damage based on rotation speed
+ m_flBlockDamage = GetLocalAngularVelocity().Length() / 10;
+
+#ifdef HL1_DLL
+ if( m_flBlockDamage > 0 )
+#endif
+ {
+ pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) );
+
+ Vector vecNewVelocity = pOther->GetAbsOrigin() - WorldSpaceCenter();
+ VectorNormalize(vecNewVelocity);
+ vecNewVelocity *= m_flBlockDamage;
+ pOther->SetAbsVelocity( vecNewVelocity );
+ }
+}
+
+
+#define FANPITCHMIN 30
+#define FANPITCHMAX 100
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Ramp pitch and volume up to maximum values, based on the difference
+// between how fast we're going vs how fast we can go.
+//-----------------------------------------------------------------------------
+void CFuncRotating::RampPitchVol( void )
+{
+ //
+ // Calc volume and pitch as % of maximum vol and pitch.
+ //
+ float fpct = fabs(m_flSpeed) / m_flMaxSpeed;
+ float fvol = clamp(m_flVolume * fpct, 0.f, 1.f); // slowdown volume ramps down to 0
+
+ float fpitch = FANPITCHMIN + (FANPITCHMAX - FANPITCHMIN) * fpct;
+
+ int pitch = clamp(FastFloatToSmallInt(fpitch), 0, 255);
+ if (pitch == PITCH_NORM)
+ {
+ pitch = PITCH_NORM - 1;
+ }
+
+ //
+ // Update the fan's volume and pitch.
+ //
+ CPASAttenuationFilter filter( GetAbsOrigin(), m_flAttenuation );
+ filter.MakeReliable();
+
+ EmitSound_t ep;
+ ep.m_nChannel = CHAN_STATIC;
+ ep.m_pSoundName = STRING(m_NoiseRunning);
+ ep.m_flVolume = fvol;
+ ep.m_SoundLevel = ATTN_TO_SNDLVL( m_flAttenuation );
+ ep.m_nFlags = SND_CHANGE_PITCH | SND_CHANGE_VOL;
+ ep.m_nPitch = pitch;
+
+ EmitSound( filter, entindex(), ep );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : float
+//-----------------------------------------------------------------------------
+float CFuncRotating::GetNextMoveInterval() const
+{
+ if ( m_bStopAtStartPos )
+ {
+ return TICK_INTERVAL;
+ }
+ return 0.1f;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the current speed to the given value and manages the sound effects.
+// Input : flNewSpeed - New speed in degrees per second.
+//-----------------------------------------------------------------------------
+void CFuncRotating::UpdateSpeed( float flNewSpeed )
+{
+ float flOldSpeed = m_flSpeed;
+ m_flSpeed = clamp( flNewSpeed, -m_flMaxSpeed, m_flMaxSpeed );
+
+ if ( m_bStopAtStartPos )
+ {
+ int checkAxis = 2;
+ // See if we got close to the starting orientation
+ if ( m_vecMoveAng[0] != 0 )
+ {
+ checkAxis = 0;
+ }
+ else if ( m_vecMoveAng[1] != 0 )
+ {
+ checkAxis = 1;
+ }
+
+ float angDelta = anglemod( GetLocalAngles()[ checkAxis ] - m_angStart[ checkAxis ] );
+ if ( angDelta > 180.0f )
+ {
+ angDelta -= 360.0f;
+ }
+
+ if ( flNewSpeed < 100 )
+ {
+ if ( flNewSpeed <= 25 && fabs( angDelta ) < 1.0f )
+ {
+ m_flTargetSpeed = 0;
+ m_bStopAtStartPos = false;
+ m_flSpeed = 0.0f;
+
+ SetLocalAngles( m_angStart );
+ }
+ else if ( fabs( angDelta ) > 90.0f )
+ {
+ // Keep rotating at same speed for now
+ m_flSpeed = flOldSpeed;
+ }
+ else
+ {
+ float minSpeed = fabs( angDelta );
+ if ( minSpeed < 20 )
+ minSpeed = 20;
+
+ m_flSpeed = flOldSpeed > 0.0f ? minSpeed : -minSpeed;
+ }
+ }
+ }
+
+
+ if ( ( flOldSpeed == 0 ) && ( m_flSpeed != 0 ) )
+ {
+ // Starting to move - emit the sound.
+ CPASAttenuationFilter filter( GetAbsOrigin(), m_flAttenuation );
+ filter.MakeReliable();
+
+ EmitSound_t ep;
+ ep.m_nChannel = CHAN_STATIC;
+ ep.m_pSoundName = STRING(m_NoiseRunning);
+ ep.m_flVolume = 0.01;
+ ep.m_SoundLevel = ATTN_TO_SNDLVL( m_flAttenuation );
+ ep.m_nPitch = FANPITCHMIN;
+
+ EmitSound( filter, entindex(), ep );
+ RampPitchVol();
+ }
+ else if ( ( flOldSpeed != 0 ) && ( m_flSpeed == 0 ) )
+ {
+ // Stopping - stop the sound.
+ StopSound( entindex(), CHAN_STATIC, STRING(m_NoiseRunning) );
+
+ }
+ else
+ {
+ // Changing speed - adjust the pitch and volume.
+ RampPitchVol();
+ }
+
+ SetLocalAngularVelocity( m_vecMoveAng * m_flSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Think function. Accelerates a func_rotating to a higher angular velocity.
+//-----------------------------------------------------------------------------
+void CFuncRotating::SpinUpMove( void )
+{
+ //
+ // Calculate our new speed.
+ //
+ bool bSpinUpDone = false;
+ float flNewSpeed = fabs( m_flSpeed ) + 0.2 * m_flMaxSpeed * m_flFanFriction;
+ if ( fabs( flNewSpeed ) >= fabs( m_flTargetSpeed ) )
+ {
+ // Reached our target speed.
+ flNewSpeed = m_flTargetSpeed;
+ bSpinUpDone = !m_bStopAtStartPos;
+ }
+ else if ( m_flTargetSpeed < 0 )
+ {
+ // Spinning up in reverse - negate the speed.
+ flNewSpeed *= -1;
+ }
+
+ //
+ // Apply the new speed, adjust sound pitch and volume.
+ //
+ UpdateSpeed( flNewSpeed );
+
+ //
+ // If we've met or exceeded target speed, stop spinning up.
+ //
+ if ( bSpinUpDone )
+ {
+ SetMoveDone( &CFuncRotating::RotateMove );
+ RotateMove();
+ }
+
+ SetMoveDoneTime( GetNextMoveInterval() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Decelerates the rotator from a higher speed to a lower one.
+// Input : flTargetSpeed - Speed to spin down to.
+// Output : Returns true if we reached the target speed, false otherwise.
+//-----------------------------------------------------------------------------
+bool CFuncRotating::SpinDown( float flTargetSpeed )
+{
+ //
+ // Bleed off a little speed due to friction.
+ //
+ bool bSpinDownDone = false;
+ float flNewSpeed = fabs( m_flSpeed ) - 0.1 * m_flMaxSpeed * m_flFanFriction;
+ if ( flNewSpeed < 0 )
+ {
+ flNewSpeed = 0;
+ }
+
+ if ( fabs( flNewSpeed ) <= fabs( flTargetSpeed ) )
+ {
+ // Reached our target speed.
+ flNewSpeed = flTargetSpeed;
+ bSpinDownDone = !m_bStopAtStartPos;
+ }
+ else if ( m_flSpeed < 0 )
+ {
+ // Spinning down in reverse - negate the speed.
+ flNewSpeed *= -1;
+ }
+
+ //
+ // Apply the new speed, adjust sound pitch and volume.
+ //
+ UpdateSpeed( flNewSpeed );
+
+ //
+ // If we've met or exceeded target speed, stop spinning down.
+ //
+ return bSpinDownDone;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Think function. Decelerates a func_rotating to a lower angular velocity.
+//-----------------------------------------------------------------------------
+void CFuncRotating::SpinDownMove( void )
+{
+ //
+ // If we've met or exceeded target speed, stop spinning down.
+ //
+ if ( SpinDown( m_flTargetSpeed ) )
+ {
+ SetMoveDone( &CFuncRotating::RotateMove );
+ RotateMove();
+ }
+ else
+ {
+ SetMoveDoneTime( GetNextMoveInterval() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Think function for reversing directions. Spins down to zero, then
+// starts spinning up to the target speed.
+//-----------------------------------------------------------------------------
+void CFuncRotating::ReverseMove( void )
+{
+ if ( SpinDown( 0 ) )
+ {
+ // We've reached zero - spin back up to the target speed.
+ SetTargetSpeed( m_flTargetSpeed );
+ }
+ else
+ {
+ SetMoveDoneTime( GetNextMoveInterval() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Think function. Called while rotating at a constant angular velocity.
+//-----------------------------------------------------------------------------
+void CFuncRotating::RotateMove( void )
+{
+ SetMoveDoneTime( 10 );
+
+ if ( m_bStopAtStartPos )
+ {
+ SetMoveDoneTime( GetNextMoveInterval() );
+ int checkAxis = 2;
+
+ // See if we got close to the starting orientation
+ if ( m_vecMoveAng[0] != 0 )
+ {
+ checkAxis = 0;
+ }
+ else if ( m_vecMoveAng[1] != 0 )
+ {
+ checkAxis = 1;
+ }
+
+ float angDelta = anglemod( GetLocalAngles()[ checkAxis ] - m_angStart[ checkAxis ] );
+ if ( angDelta > 180.0f )
+ angDelta -= 360.0f;
+
+ QAngle avel = GetLocalAngularVelocity();
+ // Delta per tick
+ QAngle avelpertick = avel * TICK_INTERVAL;
+
+ if ( fabs( angDelta ) < fabs( avelpertick[ checkAxis ] ) )
+ {
+ SetTargetSpeed( 0 );
+ SetLocalAngles( m_angStart );
+ m_bStopAtStartPos = false;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Used for debug output. Returns the given speed considering our current
+// direction of rotation, so that positive values are forward and negative
+// values are backward.
+// Input : flSpeed - Angular speed in degrees per second.
+//-----------------------------------------------------------------------------
+float CFuncRotating::GetMoveSpeed( float flSpeed )
+{
+ if ( m_vecMoveAng[0] != 0 )
+ {
+ return flSpeed * m_vecMoveAng[0];
+ }
+
+ if ( m_vecMoveAng[1] != 0 )
+ {
+ return flSpeed * m_vecMoveAng[1];
+ }
+
+ return flSpeed * m_vecMoveAng[2];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets a new angular velocity to achieve.
+// Input : flSpeed - Target angular velocity in degrees per second.
+//-----------------------------------------------------------------------------
+void CFuncRotating::SetTargetSpeed( float flSpeed )
+{
+ //
+ // Make sure the sign is correct - positive for forward rotation,
+ // negative for reverse rotation.
+ //
+ flSpeed = fabs( flSpeed );
+ if ( m_bReversed )
+ {
+ flSpeed *= -1;
+ }
+
+ m_flTargetSpeed = flSpeed;
+
+ //
+ // If we don't accelerate, change to the new speed instantly.
+ //
+ if ( !HasSpawnFlags(SF_BRUSH_ACCDCC ) )
+ {
+ UpdateSpeed( m_flTargetSpeed );
+ SetMoveDone( &CFuncRotating::RotateMove );
+ }
+ //
+ // Otherwise deal with acceleration/deceleration:
+ //
+ else
+ {
+ //
+ // Check for reversing directions.
+ //
+ if ((( m_flSpeed > 0 ) && ( m_flTargetSpeed < 0 )) ||
+ (( m_flSpeed < 0 ) && ( m_flTargetSpeed > 0 )))
+ {
+ SetMoveDone( &CFuncRotating::ReverseMove );
+ }
+ //
+ // If we are below the new target speed, spin up to the target speed.
+ //
+ else if ( fabs( m_flSpeed ) < fabs( m_flTargetSpeed ) )
+ {
+ SetMoveDone( &CFuncRotating::SpinUpMove );
+ }
+ //
+ // If we are above the new target speed, spin down to the target speed.
+ //
+ else if ( fabs( m_flSpeed ) > fabs( m_flTargetSpeed ) )
+ {
+ SetMoveDone( &CFuncRotating::SpinDownMove );
+ }
+ //
+ // We are already at the new target speed. Just keep rotating.
+ //
+ else
+ {
+ SetMoveDone( &CFuncRotating::RotateMove );
+ }
+ }
+
+ SetMoveDoneTime( GetNextMoveInterval() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Called when a rotating brush is used by the player.
+// Input : pActivator -
+// pCaller -
+// useType -
+// value -
+//-----------------------------------------------------------------------------
+void CFuncRotating::RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ //
+ // If the rotator is spinning, stop it.
+ //
+ if ( m_flSpeed != 0 )
+ {
+ SetTargetSpeed( 0 );
+ }
+ //
+ // Rotator is not moving, so start it.
+ //
+ else
+ {
+ SetTargetSpeed( m_flMaxSpeed );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Input handler that reverses the direction of rotation.
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputReverse( inputdata_t &inputdata )
+{
+ m_bStopAtStartPos = false;
+ m_bReversed = !m_bReversed;
+ SetTargetSpeed( m_flSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Input handler for setting the speed of the rotator.
+// Input : Float target angular velocity as a ratio of maximum speed [0, 1].
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputSetSpeed( inputdata_t &inputdata )
+{
+ m_bStopAtStartPos = false;
+ float flSpeed = inputdata.value.Float();
+ m_bReversed = flSpeed < 0 ? true : false;
+ flSpeed = fabs(flSpeed);
+ SetTargetSpeed( clamp( flSpeed, 0.f, 1.f ) * m_flMaxSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Input handler to start the rotator spinning.
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputStart( inputdata_t &inputdata )
+{
+ m_bStopAtStartPos = false;
+ SetTargetSpeed( m_flMaxSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Input handler to start the rotator spinning.
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputStartForward( inputdata_t &inputdata )
+{
+ m_bReversed = false;
+ SetTargetSpeed( m_flMaxSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Input handler to start the rotator spinning.
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputStartBackward( inputdata_t &inputdata )
+{
+ m_bStopAtStartPos = false;
+ m_bReversed = true;
+ SetTargetSpeed( m_flMaxSpeed );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Input handler to stop the rotator from spinning.
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputStop( inputdata_t &inputdata )
+{
+ m_bStopAtStartPos = false;
+ SetTargetSpeed( 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &inputdata -
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputStopAtStartPos( inputdata_t &inputdata )
+{
+ m_bStopAtStartPos = true;
+ SetTargetSpeed( 0 );
+ SetMoveDoneTime( GetNextMoveInterval() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Starts the rotator if it is still, stops it if it is spinning.
+//-----------------------------------------------------------------------------
+void CFuncRotating::InputToggle( inputdata_t &inputdata )
+{
+ if (m_flSpeed > 0)
+ {
+ SetTargetSpeed( 0 );
+ }
+ else
+ {
+ SetTargetSpeed( m_flMaxSpeed );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: An entity has blocked the brush.
+// Input : pOther -
+//-----------------------------------------------------------------------------
+void CFuncRotating::Blocked( CBaseEntity *pOther )
+{
+#ifdef HL1_DLL
+ if( m_flBlockDamage > 0 )
+#endif
+ pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw any debug text overlays
+// Input :
+// Output : Current text offset from the top
+//-----------------------------------------------------------------------------
+int CFuncRotating::DrawDebugTextOverlays(void)
+{
+ int text_offset = BaseClass::DrawDebugTextOverlays();
+
+ if (m_debugOverlays & OVERLAY_TEXT_BIT)
+ {
+ char tempstr[512];
+ Q_snprintf( tempstr, sizeof( tempstr ),"Speed cur (target): %3.2f (%3.2f)", GetMoveSpeed( m_flSpeed ), GetMoveSpeed( m_flTargetSpeed ) );
+ EntityText(text_offset,tempstr,0);
+ text_offset++;
+ }
+ return text_offset;
+
+}
+
+
+class CFuncVPhysicsClip : public CBaseEntity
+{
+ DECLARE_DATADESC();
+ DECLARE_CLASS( CFuncVPhysicsClip, CBaseEntity );
+
+public:
+ void Spawn();
+ void Activate();
+ bool CreateVPhysics( void );
+
+ bool EntityPassesFilter( CBaseEntity *pOther );
+ bool ForceVPhysicsCollide( CBaseEntity *pEntity );
+
+ void InputEnable( inputdata_t &inputdata );
+ void InputDisable( inputdata_t &inputdata );
+
+private:
+
+ string_t m_iFilterName;
+ CHandle<CBaseFilter> m_hFilter;
+ bool m_bDisabled;
+};
+
+// Global Savedata for base trigger
+BEGIN_DATADESC( CFuncVPhysicsClip )
+
+ // Keyfields
+ DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ),
+ DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ),
+ DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
+
+END_DATADESC()
+
+
+LINK_ENTITY_TO_CLASS( func_clip_vphysics, CFuncVPhysicsClip );
+
+void CFuncVPhysicsClip::Spawn( void )
+{
+ SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything
+ SetSolid( SOLID_VPHYSICS );
+ AddSolidFlags( FSOLID_NOT_SOLID );
+ SetModel( STRING( GetModelName() ) );
+ AddEffects( EF_NODRAW );
+ CreateVPhysics();
+ VPhysicsGetObject()->EnableCollisions( !m_bDisabled );
+}
+
+
+bool CFuncVPhysicsClip::CreateVPhysics( void )
+{
+ VPhysicsInitStatic();
+ return true;
+}
+
+
+void CFuncVPhysicsClip::Activate( void )
+{
+ // Get a handle to my filter entity if there is one
+ if (m_iFilterName != NULL_STRING)
+ {
+ m_hFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iFilterName ));
+ }
+ BaseClass::Activate();
+}
+
+bool CFuncVPhysicsClip::EntityPassesFilter( CBaseEntity *pOther )
+{
+ CBaseFilter* pFilter = (CBaseFilter*)(m_hFilter.Get());
+
+ if ( pFilter )
+ return pFilter->PassesFilter( this, pOther );
+
+ if ( pOther->GetMoveType() == MOVETYPE_VPHYSICS && pOther->VPhysicsGetObject()->IsMoveable() )
+ return true;
+
+ return false;
+}
+
+
+bool CFuncVPhysicsClip::ForceVPhysicsCollide( CBaseEntity *pEntity )
+{
+ return EntityPassesFilter(pEntity);
+}
+
+void CFuncVPhysicsClip::InputEnable( inputdata_t &inputdata )
+{
+ VPhysicsGetObject()->EnableCollisions(true);
+ m_bDisabled = false;
+}
+
+void CFuncVPhysicsClip::InputDisable( inputdata_t &inputdata )
+{
+ VPhysicsGetObject()->EnableCollisions(false);
+ m_bDisabled = true;
+}