source-sdk-2013-mapbase/sp/src/game/server/logic_measure_movement.cpp

897 lines
29 KiB
C++
Raw Normal View History

2013-12-02 19:31:46 -08:00
//========= 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"
#ifdef MAPBASE
#include "filters.h"
#include "ai_basenpc.h"
#endif
2013-12-02 19:31:46 -08:00
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef MAPBASE
// These spawnflags were originally only on logic_measure_direction.
#define SF_LOGIC_MEASURE_MOVEMENT_IGNORE_X ( 1 << 0 )
#define SF_LOGIC_MEASURE_MOVEMENT_IGNORE_Y ( 1 << 1 )
#define SF_LOGIC_MEASURE_MOVEMENT_IGNORE_Z ( 1 << 2 )
// Uses the "Ignore X/Y/Z" flags for the origin instead of the angles.
// logic_measure_direction uses this flag to control trace direction.
#define SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN ( 1 << 3 )
// Uses "Teleport" instead of "SetAbsOrigin" for smoother movement
#define SF_LOGIC_MEASURE_MOVEMENT_TELEPORT ( 1 << 4 )
#endif
2013-12-02 19:31:46 -08:00
//-----------------------------------------------------------------------------
// 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();
#ifdef MAPBASE
public:
#else
2013-12-02 19:31:46 -08:00
private:
#endif
2013-12-02 19:31:46 -08:00
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 );
#ifdef MAPBASE
// Allows for derived class trickery
void MeasureThink(); //{ DoMeasure(); }
// Allows for InputGetPosition(), etc.
virtual void DoMeasure(Vector &vecOrigin, QAngle &angAngles);
void HandleIgnoreFlags( float *vec );
void InputSetMeasureAttachment( inputdata_t &inputdata );
void InputSetMeasureType( inputdata_t &inputdata ) { m_nMeasureType = inputdata.value.Int(); }
void InputGetPosition( inputdata_t &inputdata );
#else
2013-12-02 19:31:46 -08:00
void MeasureThink();
private:
#endif
2013-12-02 19:31:46 -08:00
enum
{
MEASURE_POSITION = 0,
MEASURE_EYE_POSITION,
#ifdef MAPBASE
MEASURE_ATTACHMENT,
//MEASURE_BARREL_POSITION,
#endif
2013-12-02 19:31:46 -08:00
};
string_t m_strMeasureTarget;
string_t m_strMeasureReference;
string_t m_strTargetReference;
EHANDLE m_hMeasureTarget;
EHANDLE m_hMeasureReference;
EHANDLE m_hTarget;
EHANDLE m_hTargetReference;
#ifdef MAPBASE
string_t m_strAttachment;
int m_iAttachment;
bool m_bOutputPosition;
COutputVector m_OutPosition;
COutputVector m_OutAngles;
#endif
2013-12-02 19:31:46 -08:00
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" ),
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMeasureType", InputSetMeasureType ),
DEFINE_KEYFIELD( m_strAttachment, FIELD_STRING, "MeasureAttachment" ),
DEFINE_FIELD( m_iAttachment, FIELD_EHANDLE ),
DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureAttachment", InputSetMeasureAttachment ),
DEFINE_INPUT( m_bOutputPosition, FIELD_BOOLEAN, "ShouldOutputPosition" ),
DEFINE_INPUTFUNC( FIELD_VOID, "GetPosition", InputGetPosition ),
#endif
2013-12-02 19:31:46 -08:00
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 ),
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_STRING, "Target", InputSetTarget ), // For legacy support...even though that name was broken before.
#endif
2013-12-02 19:31:46 -08:00
DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetReference", InputSetTargetReference ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTargetScale", InputSetTargetScale ),
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
#ifdef MAPBASE
DEFINE_OUTPUT( m_OutPosition, "OutPosition" ),
DEFINE_OUTPUT( m_OutAngles, "OutAngles" ),
#endif
2013-12-02 19:31:46 -08:00
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 )
{
#ifdef MAPBASE
m_hMeasureTarget = gEntList.FindEntityByName( NULL, pName, this );
#else
2013-12-02 19:31:46 -08:00
m_hMeasureTarget = gEntList.FindEntityByName( NULL, pName );
#endif
2013-12-02 19:31:46 -08:00
if ( !m_hMeasureTarget )
{
if ( Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) )
{
#ifdef MAPBASE
Warning( "%s: Unable to find measure target entity %s\n", GetDebugName(), pName );
#else
2013-12-02 19:31:46 -08:00
Warning("logic_measure_movement: Unable to find measure target entity %s\n", pName );
#endif
2013-12-02 19:31:46 -08:00
}
}
#ifdef MAPBASE
m_iAttachment = 0;
#endif
2013-12-02 19:31:46 -08:00
}
void CLogicMeasureMovement::SetMeasureReference( const char *pName )
{
#ifdef MAPBASE
m_hMeasureReference = gEntList.FindEntityByName( NULL, pName, this );
#else
2013-12-02 19:31:46 -08:00
m_hMeasureReference = gEntList.FindEntityByName( NULL, pName );
#endif
2013-12-02 19:31:46 -08:00
if ( !m_hMeasureReference )
{
#ifdef MAPBASE
Warning( "%s: Unable to find measure reference entity %s\n", GetDebugName(), pName );
#else
2013-12-02 19:31:46 -08:00
Warning("logic_measure_movement: Unable to find measure reference entity %s\n", pName );
#endif
2013-12-02 19:31:46 -08:00
}
}
void CLogicMeasureMovement::SetTarget( const char *pName )
{
#ifdef MAPBASE
m_hTarget = gEntList.FindEntityByName( NULL, pName, this );
#else
2013-12-02 19:31:46 -08:00
m_hTarget = gEntList.FindEntityByName( NULL, pName );
#endif
2013-12-02 19:31:46 -08:00
if ( !m_hTarget )
{
#ifdef MAPBASE
Warning( "%s: Unable to find movement target entity %s\n", GetDebugName(), pName );
#else
2013-12-02 19:31:46 -08:00
Warning("logic_measure_movement: Unable to find movement target entity %s\n", pName );
#endif
2013-12-02 19:31:46 -08:00
}
}
void CLogicMeasureMovement::SetTargetReference( const char *pName )
{
#ifdef MAPBASE
m_hTargetReference = gEntList.FindEntityByName( NULL, pName, this );
#else
2013-12-02 19:31:46 -08:00
m_hTargetReference = gEntList.FindEntityByName( NULL, pName );
#endif
2013-12-02 19:31:46 -08:00
if ( !m_hTargetReference )
{
#ifdef MAPBASE
Warning( "%s: Unable to find movement reference entity %s\n", GetDebugName(), pName );
#else
2013-12-02 19:31:46 -08:00
Warning("logic_measure_movement: Unable to find movement reference entity %s\n", pName );
#endif
2013-12-02 19:31:46 -08:00
}
}
//-----------------------------------------------------------------------------
// 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() )
{
#ifdef MAPBASE
Vector vecNewOrigin;
QAngle vecNewAngles;
DoMeasure(vecNewOrigin, vecNewAngles);
if (m_bOutputPosition)
{
m_OutPosition.Set(vecNewOrigin, m_hTarget.Get(), this);
m_OutAngles.Set(*(reinterpret_cast<Vector*>(vecNewAngles.Base())), m_hTarget.Get(), this);
}
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_TELEPORT ))
{
m_hTarget->Teleport( &vecNewOrigin, &vecNewAngles, NULL );
}
else
{
m_hTarget->SetAbsOrigin( vecNewOrigin );
m_hTarget->SetAbsAngles( vecNewAngles );
}
#else
2013-12-02 19:31:46 -08:00
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 );
#endif
2013-12-02 19:31:46 -08:00
}
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Moves logic_measure_movement's movement measurements to its own function,
// primarily to allow for the GetPosition input without any hacks.
// Also helps with derivative entities that would otherwise have to find a way to re-define the think function.
// Warning: Doesn't account for whether these handles are null!
//-----------------------------------------------------------------------------
void CLogicMeasureMovement::DoMeasure( Vector &vecOrigin, QAngle &angAngles )
{
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;
case MEASURE_ATTACHMENT:
if (CBaseAnimating *pAnimating = m_hMeasureTarget->GetBaseAnimating())
{
if (m_iAttachment <= 0)
m_iAttachment = m_hMeasureTarget->GetBaseAnimating()->LookupAttachment(STRING(m_strAttachment));
if (m_iAttachment == -1)
Warning("WARNING: %s requesting invalid attachment %s on %s!\n", GetDebugName(), STRING(m_strAttachment), m_hMeasureTarget->GetDebugName());
else
pAnimating->GetAttachment(m_iAttachment, matWorldToMeasure);
}
else
{
Warning("WARNING: %s requesting attachment point on non-animating entity %s!\n", GetDebugName(), m_hMeasureTarget->GetDebugName());
}
break;
}
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 );
// Handle origin ignorance
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN ))
{
// Get the position from the matrix's column directly and re-assign it
Vector vecPosition;
MatrixGetColumn( matRefToMeasure, 3, vecPosition );
HandleIgnoreFlags( vecPosition.Base() );
MatrixSetColumn( vecPosition, 3, matRefToMeasure );
}
ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld );
MatrixAngles( matNewTargetToWorld, angAngles, vecOrigin );
// If our spawnflags are greater than 0 (and don't just contain our default "TELEPORT" flag), we might need to ignore one of our angles.
if (GetSpawnFlags() && GetSpawnFlags() != SF_LOGIC_MEASURE_MOVEMENT_TELEPORT && !HasSpawnFlags(SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN))
{
HandleIgnoreFlags( angAngles.Base() );
}
}
//-----------------------------------------------------------------------------
// Purpose: Handles logic_measure_movement's ignore flags on the specified Vector/QAngle
//-----------------------------------------------------------------------------
FORCEINLINE void CLogicMeasureMovement::HandleIgnoreFlags( float *vec )
{
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_IGNORE_X ))
vec[0] = 0.0f;
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_IGNORE_Y ))
vec[1] = 0.0f;
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_IGNORE_Z ))
vec[2] = 0.0f;
}
#endif
2013-12-02 19:31:46 -08:00
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
#ifdef MAPBASE
//
// Inputs work differently now so they could take !activator, etc.
//
void CLogicMeasureMovement::InputSetMeasureTarget( inputdata_t &inputdata )
{
m_strMeasureTarget = inputdata.value.StringID();
m_hMeasureTarget = gEntList.FindEntityByName( NULL, STRING(m_strMeasureTarget), this, inputdata.pActivator, inputdata.pCaller );
if ( !m_hMeasureTarget )
{
if ( Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) )
{
Warning( "%s: Unable to find measure target entity %s\n", GetDebugName(), STRING(m_strMeasureTarget) );
}
}
m_iAttachment = 0;
if (!m_hTarget)
SetTarget( STRING(m_target) );
if (!m_hTargetReference)
SetTargetReference( STRING(m_strTargetReference) );
}
void CLogicMeasureMovement::InputSetMeasureReference( inputdata_t &inputdata )
{
m_strMeasureReference = inputdata.value.StringID();
m_hMeasureReference = gEntList.FindEntityByName( NULL, STRING(m_strMeasureReference), this, inputdata.pActivator, inputdata.pCaller );
if ( !m_hMeasureReference )
{
Warning( "%s: Unable to find measure reference entity %s\n", GetDebugName(), STRING(m_strMeasureReference) );
}
}
void CLogicMeasureMovement::InputSetTarget( inputdata_t &inputdata )
{
m_target = inputdata.value.StringID();
m_hTarget = gEntList.FindEntityByName( NULL, STRING(m_target), this, inputdata.pActivator, inputdata.pCaller );
if ( !m_hTarget )
{
Warning( "%s: Unable to find movement target entity %s\n", GetDebugName(), STRING(m_target) );
}
}
void CLogicMeasureMovement::InputSetTargetReference( inputdata_t &inputdata )
{
m_strTargetReference = inputdata.value.StringID();
m_hTargetReference = gEntList.FindEntityByName( NULL, STRING(m_strTargetReference), this, inputdata.pActivator, inputdata.pCaller );
if ( !m_hTargetReference )
{
Warning( "%s: Unable to find movement reference entity %s\n", GetDebugName(), STRING(m_strTargetReference) );
}
}
void CLogicMeasureMovement::InputSetMeasureAttachment( inputdata_t &inputdata )
{
m_strAttachment = inputdata.value.StringID();
m_iAttachment = 0;
}
// Just gets the position once and fires outputs without moving anything.
// We don't even need a target for this.
void CLogicMeasureMovement::InputGetPosition( inputdata_t &inputdata )
{
if ( !m_hMeasureTarget.Get() || !m_hMeasureReference.Get() || !m_hTargetReference.Get() )
return;
Vector vecNewOrigin;
QAngle vecNewAngles;
DoMeasure(vecNewOrigin, vecNewAngles);
// m_bOutputPosition has been repurposed here to toggle between using the target or the input activator as the activator.
m_OutPosition.Set(vecNewOrigin, m_bOutputPosition ? m_hTarget.Get() : inputdata.pActivator, this);
m_OutAngles.Set(Vector(vecNewAngles.x, vecNewAngles.y, vecNewAngles.z), m_bOutputPosition ? m_hTarget.Get() : inputdata.pActivator, this);
}
#else
2013-12-02 19:31:46 -08:00
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() );
}
#endif
2013-12-02 19:31:46 -08:00
void CLogicMeasureMovement::InputSetTargetScale( inputdata_t &inputdata )
{
m_flScale = inputdata.value.Float();
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// This will measure the direction of a target entity and move
// another entity to where the target entity is facing.
//
// m_hMeasureTarget; // Whose direction is measured
// m_hMeasureReference; // Position where direction is measured
// m_hTarget; // Target whose origin is applied
// m_hTargetReference; // From where the target's origin is applied
//-----------------------------------------------------------------------------
class CLogicMeasureDirection : public CLogicMeasureMovement
{
DECLARE_DATADESC();
DECLARE_CLASS( CLogicMeasureDirection, CLogicMeasureMovement );
public:
virtual void DoMeasure(Vector &vecOrigin, QAngle &angAngles);
CBaseFilter *GetTraceFilter();
//void InputSetTraceFilter( inputdata_t &inputdata ) { InputSetDamageFilter(inputdata); }
private:
float m_flTraceDistance;
int m_iMask;
int m_iCollisionGroup;
bool m_bHitIfPassed;
//string_t m_iszTraceFilter;
//CHandle<CBaseFilter*> m_hTraceFilter;
bool m_bTraceTargetReference;
};
LINK_ENTITY_TO_CLASS( logic_measure_direction, CLogicMeasureDirection );
BEGIN_DATADESC( CLogicMeasureDirection )
DEFINE_KEYFIELD( m_flTraceDistance, FIELD_FLOAT, "TraceDistance" ),
DEFINE_KEYFIELD( m_iMask, FIELD_INTEGER, "Mask" ),
DEFINE_KEYFIELD( m_iCollisionGroup, FIELD_INTEGER, "CollisionGroup" ),
DEFINE_KEYFIELD( m_bHitIfPassed, FIELD_BOOLEAN, "HitIfPassed" ),
DEFINE_KEYFIELD( m_bTraceTargetReference, FIELD_BOOLEAN, "TraceTargetReference" ),
DEFINE_INPUTFUNC( FIELD_STRING, "SetTraceFilter", InputSetDamageFilter ),
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose: Gets our "trace filter".
//-----------------------------------------------------------------------------
inline CBaseFilter *CLogicMeasureDirection::GetTraceFilter()
{
return static_cast<CBaseFilter*>(m_hDamageFilter.Get()); // pranked
}
//-----------------------------------------------------------------------------
// Purpose: Does measure.
//-----------------------------------------------------------------------------
void CLogicMeasureDirection::DoMeasure( Vector &vecOrigin, QAngle &angAngles )
{
trace_t tr;
Vector vecStart, vecDir;
QAngle angStart;
switch( m_nMeasureType )
{
case MEASURE_POSITION:
vecStart = m_hMeasureReference->GetAbsOrigin();
angStart = m_hMeasureTarget->GetAbsAngles();
break;
case MEASURE_EYE_POSITION:
vecStart = m_hMeasureReference->EyePosition();
angStart = m_hMeasureTarget->EyeAngles();
break;
case MEASURE_ATTACHMENT:
CBaseAnimating *pAnimating = m_hMeasureTarget->GetBaseAnimating();
if (pAnimating)
{
if (m_iAttachment <= 0)
m_iAttachment = m_hMeasureTarget->GetBaseAnimating()->LookupAttachment(STRING(m_strAttachment));
if (m_iAttachment == -1)
Warning("WARNING: %s requesting invalid attachment %s on %s!\n", GetDebugName(), STRING(m_strAttachment), m_hMeasureTarget->GetDebugName());
else
{
pAnimating->GetAttachment(m_iAttachment, vecStart, angStart);
}
}
else
{
Warning("WARNING: %s requesting attachment point on non-animating entity %s!\n", GetDebugName(), m_hMeasureTarget->GetDebugName());
}
break;
}
// If we have spawn flags, we might be supposed to ignore something
if (GetSpawnFlags() > 0)
{
if (!HasSpawnFlags(SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN))
AngleVectors(angStart, &vecDir);
HandleIgnoreFlags( angStart.Base() );
if (HasSpawnFlags(SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN))
AngleVectors(angStart, &vecDir);
}
else
{
AngleVectors(angStart, &vecDir);
}
CTraceFilterEntityFilter traceFilter(m_hMeasureReference, m_iCollisionGroup);
traceFilter.m_pFilter = GetTraceFilter();
traceFilter.m_bHitIfPassed = m_bHitIfPassed;
UTIL_TraceLine( vecStart, vecStart + vecDir * (m_flTraceDistance != 0 ? m_flTraceDistance : MAX_TRACE_LENGTH), m_iMask, &traceFilter, &tr ); //MASK_BLOCKLOS_AND_NPCS
Vector vecEnd = tr.endpos;
// Apply the scale factor
float flScale = m_flScale;
if ( ( flScale != 0.0f ) && ( flScale != 1.0f ) )
{
vecEnd = (vecStart + ((vecEnd - vecStart) / flScale));
}
Vector refPos = m_hTargetReference->GetAbsOrigin();
Vector vecPos = refPos + (vecEnd - vecStart);
if (m_bTraceTargetReference)
{
// Make sure we can go the whole distance there
UTIL_TraceLine( refPos, vecPos, m_iMask, &traceFilter, &tr );
vecPos = tr.endpos;
}
vecOrigin = vecPos;
angAngles = angStart;
}
//-----------------------------------------------------------------------------
// The unused, "forgotten" entity brought back to life.
// Mirrors an entity's movement across a reference.
// It derives from logic_measure_movement now so it could use its features.
// This is unfinished and I'm still figuring out how it works.
//
// m_hMeasureTarget; // Whose position is mirrored (m_hRemoteTarget)
// m_hMeasureReference; // Position where position is mirrored (m_hMirrorRelative)
// m_hTarget; // Target whose origin is mirrored (m_hMovementTarget)
// m_hTargetReference; // From where the target's origin is mirrored (m_hMirrorTarget)
//-----------------------------------------------------------------------------
class CLogicMirrorMovement : public CLogicMeasureMovement
{
DECLARE_DATADESC();
DECLARE_CLASS( CLogicMirrorMovement, CLogicMeasureMovement );
public:
virtual void DoMeasure(Vector &vecOrigin, QAngle &angAngles);
};
LINK_ENTITY_TO_CLASS( logic_mirror_movement, CLogicMirrorMovement );
BEGIN_DATADESC( CLogicMirrorMovement )
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose: Does measure.
//-----------------------------------------------------------------------------
void CLogicMirrorMovement::DoMeasure( Vector &vecOrigin, QAngle &angAngles )
{
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
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;
case MEASURE_ATTACHMENT:
if (CBaseAnimating *pAnimating = m_hMeasureTarget->GetBaseAnimating())
{
if (m_iAttachment <= 0)
m_iAttachment = m_hMeasureTarget->GetBaseAnimating()->LookupAttachment(STRING(m_strAttachment));
if (m_iAttachment == -1)
Warning("WARNING: %s requesting invalid attachment %s on %s!\n", GetDebugName(), STRING(m_strAttachment), m_hMeasureTarget->GetDebugName());
else
pAnimating->GetAttachment(m_iAttachment, matWorldToMeasure);
}
else
{
Warning("WARNING: %s requesting attachment point on non-animating entity %s!\n", GetDebugName(), m_hMeasureTarget->GetDebugName());
}
break;
}
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 );
}
MatrixScaleBy( -1.0f, matRefToMeasure );
QAngle angRot;
Vector vecPos;
MatrixAngles( matRefToMeasure, angRot );
MatrixPosition( matRefToMeasure, vecPos );
angRot.z *= -1.0f;
vecPos.z *= -1.0f;
AngleMatrix( angRot, vecPos, matWorldToMeasure );
// Now apply the new matrix to the new reference point
matrix3x4_t matMeasureToRef, matNewTargetToWorld;
MatrixInvert( matRefToMeasure, matMeasureToRef );
// Handle origin ignorance
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN ))
{
// Get the position from the matrix's column directly and re-assign it
Vector vecPosition;
MatrixGetColumn( matRefToMeasure, 3, vecPosition );
HandleIgnoreFlags( vecPosition.Base() );
MatrixSetColumn( vecPosition, 3, matRefToMeasure );
}
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld );
MatrixAngles( matNewTargetToWorld, angAngles, vecOrigin );
// If our spawnflags are greater than 0 (and don't just contain our default "TELEPORT" flag), we might need to ignore one of our angles.
if (GetSpawnFlags() && GetSpawnFlags() != SF_LOGIC_MEASURE_MOVEMENT_TELEPORT && !HasSpawnFlags(SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN))
{
HandleIgnoreFlags( angAngles.Base() );
}
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
/*
VMatrix matPortal1ToWorldInv, matPortal2ToWorld;
MatrixInverseGeneral( m_hMeasureReference->EntityToWorldTransform(), matPortal1ToWorldInv );
switch( m_nMeasureType )
{
case MEASURE_POSITION:
matPortal2ToWorld = m_hMeasureTarget->EntityToWorldTransform();
break;
case MEASURE_EYE_POSITION:
matPortal2ToWorld.SetupMatrixOrgAngles( m_hMeasureTarget->EyePosition(), m_hMeasureTarget->EyeAngles() );
break;
case MEASURE_ATTACHMENT:
CBaseAnimating *pAnimating = m_hMeasureTarget->GetBaseAnimating();
if (pAnimating)
{
if (m_iAttachment <= 0)
m_iAttachment = m_hMeasureTarget->GetBaseAnimating()->LookupAttachment(STRING(m_strAttachment));
if (m_iAttachment == -1)
Warning("WARNING: %s requesting invalid attachment %s on %s!\n", GetDebugName(), STRING(m_strAttachment), m_hMeasureTarget->GetDebugName());
else
{
pAnimating->GetAttachment( m_iAttachment, matPortal2ToWorld.As3x4() );
}
}
else
{
Warning("WARNING: %s requesting attachment point on non-animating entity %s!\n", GetDebugName(), m_hMeasureTarget->GetDebugName());
}
break;
}
// If we have spawn flags, we might be supposed to ignore something
if (GetSpawnFlags() > 0)
{
if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_USE_IGNORE_FLAGS_FOR_ORIGIN ))
{
// Get the position from the matrix's column directly and re-assign it
Vector vecPosition;
MatrixGetColumn( matPortal2ToWorld, 3, &vecPosition );
HandleIgnoreFlags( vecPosition.Base() );
MatrixSetColumn( matPortal2ToWorld, 3, vecPosition );
}
else
{
// Get the angles from the matrix and re-assign it
QAngle angAngles;
MatrixToAngles( matPortal2ToWorld, angAngles );
HandleIgnoreFlags( angAngles.Base() );
matPortal2ToWorld.SetupMatrixAngles( angAngles );
}
}
// Apply the scale factor
if ( ( m_flScale != 0.0f ) && ( m_flScale != 1.0f ) )
{
Vector vecTranslation;
MatrixGetColumn( matPortal2ToWorld.As3x4(), 3, vecTranslation );
vecTranslation /= m_flScale;
MatrixSetColumn( vecTranslation, 3, matPortal2ToWorld.As3x4() );
}
// Get our scene camera's current orientation
Vector ptCameraPosition, vCameraLook, vCameraRight, vCameraUp;
ptCameraPosition = m_hTargetReference->EyePosition();
m_hTargetReference->GetVectors( &vCameraLook, &vCameraRight, &vCameraUp );
// map this position and orientation to the remote portal, mirrored (invert the result)
Vector ptNewPosition, vNewLook;
ptNewPosition = matPortal1ToWorldInv * ptCameraPosition;
ptNewPosition = matPortal2ToWorld*(Vector( -ptNewPosition.x, -ptNewPosition.y, ptNewPosition.z ));
vNewLook = matPortal1ToWorldInv.ApplyRotation( vCameraLook );
vNewLook = matPortal2ToWorld.ApplyRotation( Vector( -vNewLook.x, -vNewLook.y, vNewLook.z ) );
// Set the point camera to the new location/orientation
QAngle qNewAngles;
VectorAngles( vNewLook, qNewAngles );
vecOrigin = ptNewPosition;
angAngles = qNewAngles;
Merged dev changes 9/28/2019 - Experimental RPC stuff for the future - Fixed players running over allies with vehicles (kind of) - Modified redirect filter infrastructure to support when there's no target filter (meaning it will just make sure the entity exists) - Fixed SDK_EyeRefract - Fixed env_beam SetStart/EndEntity - New "OnStateChange" output on NPCs - scripted_face removed (use generic facing VCDs instead) - Fixed RPC - View ID nodraw keyvalue + reflective glass view ID fix - CopyAnimationDataFrom expansion (more variables copied) - Fixed pre-Mapbase env_projectedtextures not updating after loading a save - Fixed(?) player companion grenade throwing being interrupted - Added convars for secondary and NPC shotgun pellet amounts - NPC fade distance/scale transfers to its ragdoll - Made node graph rebuild occur sooner after map load - Added option to disable "node graph out of date" message - Fixed ent_fire delay (decimals discarded before) - "SetFilter" on func_clip_vphysics - Fixed func_tank zero barrel (untested) - Fixed npc_turret_ground parenting fix - Added toggle-able weapon_crossbow experimental hit location code - Fixed ally grenades being considered Combine grenades - Added SDK_MonitorScreen and SDK_UnlitTwoTexture - Updated README - Added !activator/!caller support to logic_collision_pair - Fixed ortho not working in script_intro - Added Nbc66's closed captioning language fix - Applied fade fix to server ragdolls - Added combine_mine friend/foe filters - Fixed env_starfield pausing - Reworked PickupWeapon/Item inputs - Fixed context response system $ usage - Fixed env_break_shooter velocity/speed - Made func_breakable "Spawn on break" support other entities - Fixed OnThrowGrenade > point_entity_replace blip - Added mapname to logic_externaldata - Added "Random Template" to point_template - Added "Use LOS" to trigger_look - Added flags based on L4D(2) to trigger_playermovement - Added npc_combine_s "Alternate Capable" keyvalue that enables both grenades and alt-fire at the same time regardless of elite status - Fixed npc_combine_s DropGrenade input - Miscellaneous code and comment changes
2019-09-28 22:56:52 +00:00
*/
}
#endif