diff options
Diffstat (limited to 'game/server/logic_measure_movement.cpp')
| -rw-r--r-- | game/server/logic_measure_movement.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/game/server/logic_measure_movement.cpp b/game/server/logic_measure_movement.cpp new file mode 100644 index 0000000..bf074bd --- /dev/null +++ b/game/server/logic_measure_movement.cpp @@ -0,0 +1,257 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This will measure the movement of a target entity and move +// another entity to match the movement of the first. +// +//=============================================================================// + +#include "cbase.h" +#include "baseentity.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// This will measure the movement of a target entity and move +// another entity to match the movement of the first. +//----------------------------------------------------------------------------- +class CLogicMeasureMovement : public CLogicalEntity +{ + DECLARE_DATADESC(); + DECLARE_CLASS( CLogicMeasureMovement, CLogicalEntity ); + +public: + virtual void Activate(); + +private: + void SetMeasureTarget( const char *pName ); + void SetMeasureReference( const char *pName ); + void SetTarget( const char *pName ); + void SetTargetReference( const char *pName ); + + void InputSetMeasureTarget( inputdata_t &inputdata ); + void InputSetMeasureReference( inputdata_t &inputdata ); + void InputSetTarget( inputdata_t &inputdata ); + void InputSetTargetReference( inputdata_t &inputdata ); + void InputSetTargetScale( inputdata_t &inputdata ); + void InputEnable( inputdata_t &inputdata ); + void InputDisable( inputdata_t &inputdata ); + + void MeasureThink(); + +private: + enum + { + MEASURE_POSITION = 0, + MEASURE_EYE_POSITION, + }; + + string_t m_strMeasureTarget; + string_t m_strMeasureReference; + string_t m_strTargetReference; + + EHANDLE m_hMeasureTarget; + EHANDLE m_hMeasureReference; + EHANDLE m_hTarget; + EHANDLE m_hTargetReference; + + float m_flScale; + int m_nMeasureType; +}; + + +LINK_ENTITY_TO_CLASS( logic_measure_movement, CLogicMeasureMovement ); + + +BEGIN_DATADESC( CLogicMeasureMovement ) + + DEFINE_KEYFIELD( m_strMeasureTarget, FIELD_STRING, "MeasureTarget" ), + DEFINE_KEYFIELD( m_strMeasureReference, FIELD_STRING, "MeasureReference" ), + DEFINE_KEYFIELD( m_strTargetReference, FIELD_STRING, "TargetReference" ), + DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "TargetScale" ), + DEFINE_KEYFIELD( m_nMeasureType, FIELD_INTEGER, "MeasureType" ), + + DEFINE_FIELD( m_hMeasureTarget, FIELD_EHANDLE ), + DEFINE_FIELD( m_hMeasureReference, FIELD_EHANDLE ), + DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), + DEFINE_FIELD( m_hTargetReference, FIELD_EHANDLE ), + + DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureTarget", InputSetMeasureTarget ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureReference", InputSetMeasureReference ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetReference", InputSetTargetReference ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTargetScale", InputSetTargetScale ), + + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + + DEFINE_THINKFUNC( MeasureThink ), + +END_DATADESC() + + +//----------------------------------------------------------------------------- +// Methods to change various targets +//----------------------------------------------------------------------------- +void CLogicMeasureMovement::Activate() +{ + BaseClass::Activate(); + + SetMeasureTarget( STRING(m_strMeasureTarget) ); + SetMeasureReference( STRING(m_strMeasureReference) ); + SetTarget( STRING(m_target) ); + SetTargetReference( STRING(m_strTargetReference) ); + + SetThink( &CLogicMeasureMovement::MeasureThink ); + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); +} + + +//----------------------------------------------------------------------------- +// Sets the name +//----------------------------------------------------------------------------- +void CLogicMeasureMovement::SetMeasureTarget( const char *pName ) +{ + m_hMeasureTarget = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hMeasureTarget ) + { + if ( Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) ) + { + Warning("logic_measure_movement: Unable to find measure target entity %s\n", pName ); + } + } +} + +void CLogicMeasureMovement::SetMeasureReference( const char *pName ) +{ + m_hMeasureReference = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hMeasureReference ) + { + Warning("logic_measure_movement: Unable to find measure reference entity %s\n", pName ); + } +} + +void CLogicMeasureMovement::SetTarget( const char *pName ) +{ + m_hTarget = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hTarget ) + { + Warning("logic_measure_movement: Unable to find movement target entity %s\n", pName ); + } +} + +void CLogicMeasureMovement::SetTargetReference( const char *pName ) +{ + m_hTargetReference = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hTargetReference ) + { + Warning("logic_measure_movement: Unable to find movement reference entity %s\n", pName ); + } +} + + +//----------------------------------------------------------------------------- +// Apply movement +//----------------------------------------------------------------------------- +void CLogicMeasureMovement::MeasureThink( ) +{ + // FIXME: This is a hack to make measuring !player simpler. The player isn't + // created at Activate time, so m_hMeasureTarget may be NULL because of that. + if ( !m_hMeasureTarget.Get() && !Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) ) + { + SetMeasureTarget( STRING(m_strMeasureTarget) ); + } + + // Make sure all entities are valid + if ( m_hMeasureTarget.Get() && m_hMeasureReference.Get() && m_hTarget.Get() && m_hTargetReference.Get() ) + { + matrix3x4_t matRefToMeasure, matWorldToMeasure; + switch( m_nMeasureType ) + { + case MEASURE_POSITION: + MatrixInvert( m_hMeasureTarget->EntityToWorldTransform(), matWorldToMeasure ); + break; + + case MEASURE_EYE_POSITION: + AngleIMatrix( m_hMeasureTarget->EyeAngles(), m_hMeasureTarget->EyePosition(), matWorldToMeasure ); + break; + + // FIXME: Could add attachment point measurement here easily + } + + ConcatTransforms( matWorldToMeasure, m_hMeasureReference->EntityToWorldTransform(), matRefToMeasure ); + + // Apply the scale factor + if ( ( m_flScale != 0.0f ) && ( m_flScale != 1.0f ) ) + { + Vector vecTranslation; + MatrixGetColumn( matRefToMeasure, 3, vecTranslation ); + vecTranslation /= m_flScale; + MatrixSetColumn( vecTranslation, 3, matRefToMeasure ); + } + + // Now apply the new matrix to the new reference point + matrix3x4_t matMeasureToRef, matNewTargetToWorld; + MatrixInvert( matRefToMeasure, matMeasureToRef ); + + ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld ); + + Vector vecNewOrigin; + QAngle vecNewAngles; + MatrixAngles( matNewTargetToWorld, vecNewAngles, vecNewOrigin ); + m_hTarget->SetAbsOrigin( vecNewOrigin ); + m_hTarget->SetAbsAngles( vecNewAngles ); + } + + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); +} + + +//----------------------------------------------------------------------------- +// Enable, disable +//----------------------------------------------------------------------------- +void CLogicMeasureMovement::InputEnable( inputdata_t &inputdata ) +{ + SetThink( &CLogicMeasureMovement::MeasureThink ); + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); +} + +void CLogicMeasureMovement::InputDisable( inputdata_t &inputdata ) +{ + SetThink( NULL ); +} + + +//----------------------------------------------------------------------------- +// Methods to change various targets +//----------------------------------------------------------------------------- +void CLogicMeasureMovement::InputSetMeasureTarget( inputdata_t &inputdata ) +{ + m_strMeasureTarget = MAKE_STRING( inputdata.value.String() ); + SetMeasureTarget( inputdata.value.String() ); + SetTarget( STRING(m_target) ); + SetTargetReference( STRING(m_strTargetReference) ); +} + +void CLogicMeasureMovement::InputSetMeasureReference( inputdata_t &inputdata ) +{ + m_strMeasureReference = MAKE_STRING( inputdata.value.String() ); + SetMeasureReference( inputdata.value.String() ); +} + +void CLogicMeasureMovement::InputSetTarget( inputdata_t &inputdata ) +{ + m_target = MAKE_STRING( inputdata.value.String() ); + SetTarget( inputdata.value.String() ); +} + +void CLogicMeasureMovement::InputSetTargetReference( inputdata_t &inputdata ) +{ + m_strTargetReference = MAKE_STRING( inputdata.value.String() ); + SetTargetReference( inputdata.value.String() ); +} + +void CLogicMeasureMovement::InputSetTargetScale( inputdata_t &inputdata ) +{ + m_flScale = inputdata.value.Float(); +} |