mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-29 17:43:01 +00:00
258 lines
8.2 KiB
C++
258 lines
8.2 KiB
C++
|
//========= 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();
|
||
|
}
|