diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /sp/src/game/server/PointAngularVelocitySensor.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/game/server/PointAngularVelocitySensor.cpp')
| -rw-r--r-- | sp/src/game/server/PointAngularVelocitySensor.cpp | 1058 |
1 files changed, 529 insertions, 529 deletions
diff --git a/sp/src/game/server/PointAngularVelocitySensor.cpp b/sp/src/game/server/PointAngularVelocitySensor.cpp index 355b3f5d..03e6a45c 100644 --- a/sp/src/game/server/PointAngularVelocitySensor.cpp +++ b/sp/src/game/server/PointAngularVelocitySensor.cpp @@ -1,529 +1,529 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Used to fire events based on the orientation of a given entity.
-//
-// Looks at its target's anglular velocity every frame and fires outputs
-// as the angular velocity passes a given threshold value.
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "entityinput.h"
-#include "entityoutput.h"
-#include "eventqueue.h"
-#include "mathlib/mathlib.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-enum
-{
- AVELOCITY_SENSOR_NO_LAST_RESULT = -2
-};
-
-ConVar g_debug_angularsensor( "g_debug_angularsensor", "0", FCVAR_CHEAT );
-
-class CPointAngularVelocitySensor : public CPointEntity
-{
- DECLARE_CLASS( CPointAngularVelocitySensor, CPointEntity );
-
-public:
-
- CPointAngularVelocitySensor();
- void Activate(void);
- void Spawn(void);
- void Think(void);
-
-private:
-
- float SampleAngularVelocity(CBaseEntity *pEntity);
- int CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput);
- void FireCompareOutput(int nCompareResult, CBaseEntity *pActivator);
- void DrawDebugLines( void );
-
- // Input handlers
- void InputTest( inputdata_t &inputdata );
- void InputTestWithInterval( inputdata_t &inputdata );
-
- EHANDLE m_hTargetEntity; // Entity whose angles are being monitored.
- float m_flThreshold; // The threshold angular velocity that we are looking for.
- int m_nLastCompareResult; // The comparison result from our last measurement, expressed as -1, 0, or 1
- int m_nLastFireResult; // The last result for which we fire the output.
-
- float m_flFireTime;
- float m_flFireInterval;
- float m_flLastAngVelocity;
-
- QAngle m_lastOrientation;
-
- Vector m_vecAxis;
- bool m_bUseHelper;
-
- // Outputs
- COutputFloat m_AngularVelocity;
-
- // Compare the target's angular velocity to the threshold velocity and fire the appropriate output.
- // These outputs are filtered by m_flFireInterval to ignore excessive oscillations.
- COutputEvent m_OnLessThan;
- COutputEvent m_OnLessThanOrEqualTo;
- COutputEvent m_OnGreaterThan;
- COutputEvent m_OnGreaterThanOrEqualTo;
- COutputEvent m_OnEqualTo;
-
- DECLARE_DATADESC();
-};
-
-LINK_ENTITY_TO_CLASS(point_angularvelocitysensor, CPointAngularVelocitySensor);
-
-
-BEGIN_DATADESC( CPointAngularVelocitySensor )
-
- // Fields
- DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ),
- DEFINE_KEYFIELD(m_flThreshold, FIELD_FLOAT, "threshold"),
- DEFINE_FIELD(m_nLastCompareResult, FIELD_INTEGER),
- DEFINE_FIELD( m_nLastFireResult, FIELD_INTEGER ),
- DEFINE_FIELD( m_flFireTime, FIELD_TIME ),
- DEFINE_KEYFIELD( m_flFireInterval, FIELD_FLOAT, "fireinterval" ),
- DEFINE_FIELD( m_flLastAngVelocity, FIELD_FLOAT ),
- DEFINE_FIELD( m_lastOrientation, FIELD_VECTOR ),
-
- // Inputs
- DEFINE_INPUTFUNC(FIELD_VOID, "Test", InputTest),
- DEFINE_INPUTFUNC(FIELD_VOID, "TestWithInterval", InputTestWithInterval),
-
- // Outputs
- DEFINE_OUTPUT(m_OnLessThan, "OnLessThan"),
- DEFINE_OUTPUT(m_OnLessThanOrEqualTo, "OnLessThanOrEqualTo"),
- DEFINE_OUTPUT(m_OnGreaterThan, "OnGreaterThan"),
- DEFINE_OUTPUT(m_OnGreaterThanOrEqualTo, "OnGreaterThanOrEqualTo"),
- DEFINE_OUTPUT(m_OnEqualTo, "OnEqualTo"),
- DEFINE_OUTPUT(m_AngularVelocity, "AngularVelocity"),
-
- DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ),
- DEFINE_KEYFIELD( m_bUseHelper, FIELD_BOOLEAN, "usehelper" ),
-
-END_DATADESC()
-
-
-
-//-----------------------------------------------------------------------------
-// Purpose: constructor provides default values
-//-----------------------------------------------------------------------------
-CPointAngularVelocitySensor::CPointAngularVelocitySensor()
-{
- m_flFireInterval = 0.2f;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called when spawning after parsing keyvalues.
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::Spawn(void)
-{
- m_flThreshold = fabs(m_flThreshold);
- m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT;
- m_nLastCompareResult = AVELOCITY_SENSOR_NO_LAST_RESULT;
- // m_flFireInterval = 0.2;
- m_lastOrientation = vec3_angle;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Called after all entities in the map have spawned.
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::Activate(void)
-{
- BaseClass::Activate();
-
- m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target );
-
- if (m_hTargetEntity)
- {
- SetNextThink( gpGlobals->curtime );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Draws magic lines...
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::DrawDebugLines( void )
-{
- if ( m_hTargetEntity )
- {
- Vector vForward, vRight, vUp;
- AngleVectors( m_hTargetEntity->GetAbsAngles(), &vForward, &vRight, &vUp );
-
- NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vForward * 64, 255, 0, 0, false, 0 );
- NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vRight * 64, 0, 255, 0, false, 0 );
- NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vUp * 64, 0, 0, 255, false, 0 );
- }
-
- if ( m_bUseHelper == true )
- {
- QAngle Angles;
- Vector vAxisForward, vAxisRight, vAxisUp;
-
- Vector vLine = m_vecAxis - GetAbsOrigin();
-
- VectorNormalize( vLine );
-
- VectorAngles( vLine, Angles );
- AngleVectors( Angles, &vAxisForward, &vAxisRight, &vAxisUp );
-
- NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisForward * 64, 255, 0, 0, false, 0 );
- NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisRight * 64, 0, 255, 0, false, 0 );
- NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisUp * 64, 0, 0, 255, false, 0 );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the magnitude of the entity's angular velocity.
-//-----------------------------------------------------------------------------
-float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity)
-{
- if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS)
- {
- IPhysicsObject *pPhys = pEntity->VPhysicsGetObject();
- if (pPhys != NULL)
- {
- Vector vecVelocity;
- AngularImpulse vecAngVelocity;
- pPhys->GetVelocity(&vecVelocity, &vecAngVelocity);
-
- QAngle angles;
- pPhys->GetPosition( NULL, &angles );
-
- float dt = gpGlobals->curtime - GetLastThink();
- if ( dt == 0 )
- dt = 0.1;
-
- // HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing
- // is trying to move, but failing.
- QAngle delta = angles - m_lastOrientation;
-
- if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) )
- {
- return 0.0f;
- }
- m_lastOrientation = angles;
-
- if ( m_bUseHelper == false )
- {
- return vecAngVelocity.Length();
- }
- else
- {
- Vector vLine = m_vecAxis - GetAbsOrigin();
- VectorNormalize( vLine );
-
- Vector vecWorldAngVelocity;
- pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity );
- float flDot = DotProduct( vecWorldAngVelocity, vLine );
-
- return flDot;
- }
- }
- }
- else
- {
- QAngle vecAngVel = pEntity->GetLocalAngularVelocity();
- float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW]));
-
- return MAX(flMax, fabs(vecAngVel[ROLL]));
- }
-
- return 0;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Compares the given entity's angular velocity to the threshold velocity.
-// Input : pEntity - Entity whose angular velocity is being measured.
-// flThreshold -
-// Output : Returns -1 if less than, 0 if equal to, or 1 if greater than the threshold.
-//-----------------------------------------------------------------------------
-int CPointAngularVelocitySensor::CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput)
-{
- if (pEntity == NULL)
- {
- return 0;
- }
-
- float flAngVelocity = SampleAngularVelocity(pEntity);
-
- if ( g_debug_angularsensor.GetBool() )
- {
- DrawDebugLines();
- }
-
- if (bFireVelocityOutput && (flAngVelocity != m_flLastAngVelocity))
- {
- m_AngularVelocity.Set(flAngVelocity, pEntity, this);
- m_flLastAngVelocity = flAngVelocity;
- }
-
- if (flAngVelocity > flThreshold)
- {
- return 1;
- }
-
- if (flAngVelocity == flThreshold)
- {
- return 0;
- }
-
- return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// Called every frame to sense the angular velocity of the target entity.
-// Output is filtered by m_flFireInterval to ignore excessive oscillations.
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::Think(void)
-{
- if (m_hTargetEntity != NULL)
- {
- //
- // Check to see if the measure entity's angular velocity has been within
- // tolerance of the threshold for the given period of time.
- //
- int nCompare = CompareToThreshold(m_hTargetEntity, m_flThreshold, true);
- if (nCompare != m_nLastCompareResult)
- {
- // If we've oscillated back to where we last fired the output, don't
- // fire the same output again.
- if (nCompare == m_nLastFireResult)
- {
- m_flFireTime = 0;
- }
- else if (m_nLastCompareResult != AVELOCITY_SENSOR_NO_LAST_RESULT)
- {
- //
- // The value has changed -- reset the timer. We'll fire the output if
- // it stays at this value until the interval expires.
- //
- m_flFireTime = gpGlobals->curtime + m_flFireInterval;
- }
-
- m_nLastCompareResult = nCompare;
- }
- else if ((m_flFireTime != 0) && (gpGlobals->curtime >= m_flFireTime))
- {
- //
- // The compare result has held steady long enough -- time to
- // fire the output.
- //
- FireCompareOutput(nCompare, this);
- m_nLastFireResult = nCompare;
- m_flFireTime = 0;
- }
-
- SetNextThink( gpGlobals->curtime );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Fires the output after the fire interval if the velocity is stable.
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::InputTestWithInterval( inputdata_t &inputdata )
-{
- if (m_hTargetEntity != NULL)
- {
- m_flFireTime = gpGlobals->curtime + m_flFireInterval;
- m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT;
- m_nLastCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, true);
-
- SetNextThink( gpGlobals->curtime );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Input handler for forcing an instantaneous test of the condition.
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::InputTest( inputdata_t &inputdata )
-{
- int nCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, false);
- FireCompareOutput(nCompareResult, inputdata.pActivator);
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Fires the appropriate output based on the given comparison result.
-// Input : nCompareResult -
-// pActivator -
-//-----------------------------------------------------------------------------
-void CPointAngularVelocitySensor::FireCompareOutput( int nCompareResult, CBaseEntity *pActivator )
-{
- if (nCompareResult == -1)
- {
- m_OnLessThan.FireOutput(pActivator, this);
- m_OnLessThanOrEqualTo.FireOutput(pActivator, this);
- }
- else if (nCompareResult == 1)
- {
- m_OnGreaterThan.FireOutput(pActivator, this);
- m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this);
- }
- else
- {
- m_OnEqualTo.FireOutput(pActivator, this);
- m_OnLessThanOrEqualTo.FireOutput(pActivator, this);
- m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this);
- }
-}
-
-// ============================================================================
-//
-// Simple velocity sensor
-//
-// ============================================================================
-
-class CPointVelocitySensor : public CPointEntity
-{
- DECLARE_CLASS( CPointVelocitySensor, CPointEntity );
-
-public:
-
- void Spawn();
- void Activate( void );
- void Think( void );
-
-private:
-
- void SampleVelocity( void );
-
- EHANDLE m_hTargetEntity; // Entity whose angles are being monitored.
- Vector m_vecAxis; // Axis along which to measure the speed.
- bool m_bEnabled; // Whether we're measuring or not
-
- // Outputs
- float m_fPrevVelocity; // stores velocity from last frame, so we only write the output if it has changed
- COutputFloat m_Velocity;
-
- void InputEnable( inputdata_t &inputdata );
- void InputDisable( inputdata_t &inputdata );
-
- DECLARE_DATADESC();
-};
-
-LINK_ENTITY_TO_CLASS( point_velocitysensor, CPointVelocitySensor );
-
-BEGIN_DATADESC( CPointVelocitySensor )
-
- // Fields
- DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ),
- DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ),
- DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
- DEFINE_FIELD( m_fPrevVelocity, FIELD_FLOAT ),
-
- // Outputs
- DEFINE_OUTPUT( m_Velocity, "Velocity" ),
-
- DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
-
-END_DATADESC()
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void CPointVelocitySensor::Spawn()
-{
- Vector vLine = m_vecAxis - GetAbsOrigin();
- VectorNormalize( vLine );
- m_vecAxis = vLine;
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CPointVelocitySensor::Activate( void )
-{
- BaseClass::Activate();
-
- m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target );
-
- if ( m_bEnabled && m_hTargetEntity )
- {
- SetNextThink( gpGlobals->curtime );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CPointVelocitySensor::InputEnable( inputdata_t &inputdata )
-{
- // Don't interrupt us if we're already enabled
- if ( m_bEnabled )
- return;
-
- m_bEnabled = true;
-
- if ( m_hTargetEntity )
- {
- SetNextThink( gpGlobals->curtime );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CPointVelocitySensor::InputDisable( inputdata_t &inputdata )
-{
- m_bEnabled = false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Called every frame
-//-----------------------------------------------------------------------------
-void CPointVelocitySensor::Think( void )
-{
- if ( m_hTargetEntity != NULL && m_bEnabled )
- {
- SampleVelocity();
- SetNextThink( gpGlobals->curtime );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the magnitude of the entity's angular velocity.
-//-----------------------------------------------------------------------------
-void CPointVelocitySensor::SampleVelocity( void )
-{
- if ( m_hTargetEntity == NULL )
- return;
-
- Vector vecVelocity;
-
- if ( m_hTargetEntity->GetMoveType() == MOVETYPE_VPHYSICS )
- {
- IPhysicsObject *pPhys = m_hTargetEntity->VPhysicsGetObject();
- if ( pPhys != NULL )
- {
- pPhys->GetVelocity( &vecVelocity, NULL );
- }
- }
- else
- {
- vecVelocity = m_hTargetEntity->GetAbsVelocity();
- }
-
- /*
- float flSpeed = VectorNormalize( vecVelocity );
- float flDot = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f;
- */
- // We want the component of the velocity vector in the direction of the axis, which since the
- // axis is normalized is simply their dot product (eg V . A = |V|*|A|*cos(theta) )
- m_fPrevVelocity = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f;
-
- // if it's changed since the last frame, poke the output
- if ( m_fPrevVelocity != m_Velocity.Get() )
- {
- m_Velocity.Set( m_fPrevVelocity, NULL, NULL );
- }
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Used to fire events based on the orientation of a given entity. +// +// Looks at its target's anglular velocity every frame and fires outputs +// as the angular velocity passes a given threshold value. +// +//=============================================================================// + +#include "cbase.h" +#include "entityinput.h" +#include "entityoutput.h" +#include "eventqueue.h" +#include "mathlib/mathlib.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +enum +{ + AVELOCITY_SENSOR_NO_LAST_RESULT = -2 +}; + +ConVar g_debug_angularsensor( "g_debug_angularsensor", "0", FCVAR_CHEAT ); + +class CPointAngularVelocitySensor : public CPointEntity +{ + DECLARE_CLASS( CPointAngularVelocitySensor, CPointEntity ); + +public: + + CPointAngularVelocitySensor(); + void Activate(void); + void Spawn(void); + void Think(void); + +private: + + float SampleAngularVelocity(CBaseEntity *pEntity); + int CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput); + void FireCompareOutput(int nCompareResult, CBaseEntity *pActivator); + void DrawDebugLines( void ); + + // Input handlers + void InputTest( inputdata_t &inputdata ); + void InputTestWithInterval( inputdata_t &inputdata ); + + EHANDLE m_hTargetEntity; // Entity whose angles are being monitored. + float m_flThreshold; // The threshold angular velocity that we are looking for. + int m_nLastCompareResult; // The comparison result from our last measurement, expressed as -1, 0, or 1 + int m_nLastFireResult; // The last result for which we fire the output. + + float m_flFireTime; + float m_flFireInterval; + float m_flLastAngVelocity; + + QAngle m_lastOrientation; + + Vector m_vecAxis; + bool m_bUseHelper; + + // Outputs + COutputFloat m_AngularVelocity; + + // Compare the target's angular velocity to the threshold velocity and fire the appropriate output. + // These outputs are filtered by m_flFireInterval to ignore excessive oscillations. + COutputEvent m_OnLessThan; + COutputEvent m_OnLessThanOrEqualTo; + COutputEvent m_OnGreaterThan; + COutputEvent m_OnGreaterThanOrEqualTo; + COutputEvent m_OnEqualTo; + + DECLARE_DATADESC(); +}; + +LINK_ENTITY_TO_CLASS(point_angularvelocitysensor, CPointAngularVelocitySensor); + + +BEGIN_DATADESC( CPointAngularVelocitySensor ) + + // Fields + DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), + DEFINE_KEYFIELD(m_flThreshold, FIELD_FLOAT, "threshold"), + DEFINE_FIELD(m_nLastCompareResult, FIELD_INTEGER), + DEFINE_FIELD( m_nLastFireResult, FIELD_INTEGER ), + DEFINE_FIELD( m_flFireTime, FIELD_TIME ), + DEFINE_KEYFIELD( m_flFireInterval, FIELD_FLOAT, "fireinterval" ), + DEFINE_FIELD( m_flLastAngVelocity, FIELD_FLOAT ), + DEFINE_FIELD( m_lastOrientation, FIELD_VECTOR ), + + // Inputs + DEFINE_INPUTFUNC(FIELD_VOID, "Test", InputTest), + DEFINE_INPUTFUNC(FIELD_VOID, "TestWithInterval", InputTestWithInterval), + + // Outputs + DEFINE_OUTPUT(m_OnLessThan, "OnLessThan"), + DEFINE_OUTPUT(m_OnLessThanOrEqualTo, "OnLessThanOrEqualTo"), + DEFINE_OUTPUT(m_OnGreaterThan, "OnGreaterThan"), + DEFINE_OUTPUT(m_OnGreaterThanOrEqualTo, "OnGreaterThanOrEqualTo"), + DEFINE_OUTPUT(m_OnEqualTo, "OnEqualTo"), + DEFINE_OUTPUT(m_AngularVelocity, "AngularVelocity"), + + DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ), + DEFINE_KEYFIELD( m_bUseHelper, FIELD_BOOLEAN, "usehelper" ), + +END_DATADESC() + + + +//----------------------------------------------------------------------------- +// Purpose: constructor provides default values +//----------------------------------------------------------------------------- +CPointAngularVelocitySensor::CPointAngularVelocitySensor() +{ + m_flFireInterval = 0.2f; +} + +//----------------------------------------------------------------------------- +// Purpose: Called when spawning after parsing keyvalues. +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::Spawn(void) +{ + m_flThreshold = fabs(m_flThreshold); + m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT; + m_nLastCompareResult = AVELOCITY_SENSOR_NO_LAST_RESULT; + // m_flFireInterval = 0.2; + m_lastOrientation = vec3_angle; +} + + +//----------------------------------------------------------------------------- +// Purpose: Called after all entities in the map have spawned. +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::Activate(void) +{ + BaseClass::Activate(); + + m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); + + if (m_hTargetEntity) + { + SetNextThink( gpGlobals->curtime ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Draws magic lines... +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::DrawDebugLines( void ) +{ + if ( m_hTargetEntity ) + { + Vector vForward, vRight, vUp; + AngleVectors( m_hTargetEntity->GetAbsAngles(), &vForward, &vRight, &vUp ); + + NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vForward * 64, 255, 0, 0, false, 0 ); + NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vRight * 64, 0, 255, 0, false, 0 ); + NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vUp * 64, 0, 0, 255, false, 0 ); + } + + if ( m_bUseHelper == true ) + { + QAngle Angles; + Vector vAxisForward, vAxisRight, vAxisUp; + + Vector vLine = m_vecAxis - GetAbsOrigin(); + + VectorNormalize( vLine ); + + VectorAngles( vLine, Angles ); + AngleVectors( Angles, &vAxisForward, &vAxisRight, &vAxisUp ); + + NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisForward * 64, 255, 0, 0, false, 0 ); + NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisRight * 64, 0, 255, 0, false, 0 ); + NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisUp * 64, 0, 0, 255, false, 0 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the magnitude of the entity's angular velocity. +//----------------------------------------------------------------------------- +float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity) +{ + if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS) + { + IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); + if (pPhys != NULL) + { + Vector vecVelocity; + AngularImpulse vecAngVelocity; + pPhys->GetVelocity(&vecVelocity, &vecAngVelocity); + + QAngle angles; + pPhys->GetPosition( NULL, &angles ); + + float dt = gpGlobals->curtime - GetLastThink(); + if ( dt == 0 ) + dt = 0.1; + + // HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing + // is trying to move, but failing. + QAngle delta = angles - m_lastOrientation; + + if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) ) + { + return 0.0f; + } + m_lastOrientation = angles; + + if ( m_bUseHelper == false ) + { + return vecAngVelocity.Length(); + } + else + { + Vector vLine = m_vecAxis - GetAbsOrigin(); + VectorNormalize( vLine ); + + Vector vecWorldAngVelocity; + pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity ); + float flDot = DotProduct( vecWorldAngVelocity, vLine ); + + return flDot; + } + } + } + else + { + QAngle vecAngVel = pEntity->GetLocalAngularVelocity(); + float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW])); + + return MAX(flMax, fabs(vecAngVel[ROLL])); + } + + return 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Compares the given entity's angular velocity to the threshold velocity. +// Input : pEntity - Entity whose angular velocity is being measured. +// flThreshold - +// Output : Returns -1 if less than, 0 if equal to, or 1 if greater than the threshold. +//----------------------------------------------------------------------------- +int CPointAngularVelocitySensor::CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput) +{ + if (pEntity == NULL) + { + return 0; + } + + float flAngVelocity = SampleAngularVelocity(pEntity); + + if ( g_debug_angularsensor.GetBool() ) + { + DrawDebugLines(); + } + + if (bFireVelocityOutput && (flAngVelocity != m_flLastAngVelocity)) + { + m_AngularVelocity.Set(flAngVelocity, pEntity, this); + m_flLastAngVelocity = flAngVelocity; + } + + if (flAngVelocity > flThreshold) + { + return 1; + } + + if (flAngVelocity == flThreshold) + { + return 0; + } + + return -1; +} + + +//----------------------------------------------------------------------------- +// Called every frame to sense the angular velocity of the target entity. +// Output is filtered by m_flFireInterval to ignore excessive oscillations. +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::Think(void) +{ + if (m_hTargetEntity != NULL) + { + // + // Check to see if the measure entity's angular velocity has been within + // tolerance of the threshold for the given period of time. + // + int nCompare = CompareToThreshold(m_hTargetEntity, m_flThreshold, true); + if (nCompare != m_nLastCompareResult) + { + // If we've oscillated back to where we last fired the output, don't + // fire the same output again. + if (nCompare == m_nLastFireResult) + { + m_flFireTime = 0; + } + else if (m_nLastCompareResult != AVELOCITY_SENSOR_NO_LAST_RESULT) + { + // + // The value has changed -- reset the timer. We'll fire the output if + // it stays at this value until the interval expires. + // + m_flFireTime = gpGlobals->curtime + m_flFireInterval; + } + + m_nLastCompareResult = nCompare; + } + else if ((m_flFireTime != 0) && (gpGlobals->curtime >= m_flFireTime)) + { + // + // The compare result has held steady long enough -- time to + // fire the output. + // + FireCompareOutput(nCompare, this); + m_nLastFireResult = nCompare; + m_flFireTime = 0; + } + + SetNextThink( gpGlobals->curtime ); + } +} + + +//----------------------------------------------------------------------------- +// Fires the output after the fire interval if the velocity is stable. +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::InputTestWithInterval( inputdata_t &inputdata ) +{ + if (m_hTargetEntity != NULL) + { + m_flFireTime = gpGlobals->curtime + m_flFireInterval; + m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT; + m_nLastCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, true); + + SetNextThink( gpGlobals->curtime ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Input handler for forcing an instantaneous test of the condition. +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::InputTest( inputdata_t &inputdata ) +{ + int nCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, false); + FireCompareOutput(nCompareResult, inputdata.pActivator); +} + + +//----------------------------------------------------------------------------- +// Purpose: Fires the appropriate output based on the given comparison result. +// Input : nCompareResult - +// pActivator - +//----------------------------------------------------------------------------- +void CPointAngularVelocitySensor::FireCompareOutput( int nCompareResult, CBaseEntity *pActivator ) +{ + if (nCompareResult == -1) + { + m_OnLessThan.FireOutput(pActivator, this); + m_OnLessThanOrEqualTo.FireOutput(pActivator, this); + } + else if (nCompareResult == 1) + { + m_OnGreaterThan.FireOutput(pActivator, this); + m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this); + } + else + { + m_OnEqualTo.FireOutput(pActivator, this); + m_OnLessThanOrEqualTo.FireOutput(pActivator, this); + m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this); + } +} + +// ============================================================================ +// +// Simple velocity sensor +// +// ============================================================================ + +class CPointVelocitySensor : public CPointEntity +{ + DECLARE_CLASS( CPointVelocitySensor, CPointEntity ); + +public: + + void Spawn(); + void Activate( void ); + void Think( void ); + +private: + + void SampleVelocity( void ); + + EHANDLE m_hTargetEntity; // Entity whose angles are being monitored. + Vector m_vecAxis; // Axis along which to measure the speed. + bool m_bEnabled; // Whether we're measuring or not + + // Outputs + float m_fPrevVelocity; // stores velocity from last frame, so we only write the output if it has changed + COutputFloat m_Velocity; + + void InputEnable( inputdata_t &inputdata ); + void InputDisable( inputdata_t &inputdata ); + + DECLARE_DATADESC(); +}; + +LINK_ENTITY_TO_CLASS( point_velocitysensor, CPointVelocitySensor ); + +BEGIN_DATADESC( CPointVelocitySensor ) + + // Fields + DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), + DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ), + DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ), + DEFINE_FIELD( m_fPrevVelocity, FIELD_FLOAT ), + + // Outputs + DEFINE_OUTPUT( m_Velocity, "Velocity" ), + + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + +END_DATADESC() + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CPointVelocitySensor::Spawn() +{ + Vector vLine = m_vecAxis - GetAbsOrigin(); + VectorNormalize( vLine ); + m_vecAxis = vLine; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPointVelocitySensor::Activate( void ) +{ + BaseClass::Activate(); + + m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); + + if ( m_bEnabled && m_hTargetEntity ) + { + SetNextThink( gpGlobals->curtime ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPointVelocitySensor::InputEnable( inputdata_t &inputdata ) +{ + // Don't interrupt us if we're already enabled + if ( m_bEnabled ) + return; + + m_bEnabled = true; + + if ( m_hTargetEntity ) + { + SetNextThink( gpGlobals->curtime ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPointVelocitySensor::InputDisable( inputdata_t &inputdata ) +{ + m_bEnabled = false; +} + +//----------------------------------------------------------------------------- +// Purpose: Called every frame +//----------------------------------------------------------------------------- +void CPointVelocitySensor::Think( void ) +{ + if ( m_hTargetEntity != NULL && m_bEnabled ) + { + SampleVelocity(); + SetNextThink( gpGlobals->curtime ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Returns the magnitude of the entity's angular velocity. +//----------------------------------------------------------------------------- +void CPointVelocitySensor::SampleVelocity( void ) +{ + if ( m_hTargetEntity == NULL ) + return; + + Vector vecVelocity; + + if ( m_hTargetEntity->GetMoveType() == MOVETYPE_VPHYSICS ) + { + IPhysicsObject *pPhys = m_hTargetEntity->VPhysicsGetObject(); + if ( pPhys != NULL ) + { + pPhys->GetVelocity( &vecVelocity, NULL ); + } + } + else + { + vecVelocity = m_hTargetEntity->GetAbsVelocity(); + } + + /* + float flSpeed = VectorNormalize( vecVelocity ); + float flDot = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f; + */ + // We want the component of the velocity vector in the direction of the axis, which since the + // axis is normalized is simply their dot product (eg V . A = |V|*|A|*cos(theta) ) + m_fPrevVelocity = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f; + + // if it's changed since the last frame, poke the output + if ( m_fPrevVelocity != m_Velocity.Get() ) + { + m_Velocity.Set( m_fPrevVelocity, NULL, NULL ); + } +} |