diff options
Diffstat (limited to 'game/server/logic_mirror_movement.cpp')
| -rw-r--r-- | game/server/logic_mirror_movement.cpp | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/game/server/logic_mirror_movement.cpp b/game/server/logic_mirror_movement.cpp new file mode 100644 index 0000000..d2be00c --- /dev/null +++ b/game/server/logic_mirror_movement.cpp @@ -0,0 +1,198 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Mirrors the movement of a camera about a given point. +// +//=============================================================================// + +#include "cbase.h" +#include "baseentity.h" +#include "modelentities.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +////////////////////////////////////////////////////////////////////////// +// CLogicMirrorMovement +// This will record the vector offset of an entity's center from a given reference point +// (most likely the center of a mirror or portal) and place an entity (most likely a point camera) +// at a the same offset, mirrored about the reference point and orientation. +////////////////////////////////////////////////////////////////////////// +class CLogicMirrorMovement : public CLogicalEntity +{ + DECLARE_DATADESC(); + DECLARE_CLASS( CLogicMirrorMovement, CLogicalEntity ); + +private: + void SetMirrorTarget( const char *pName ); // Set entity to watch and mirror (ex. the player) + void SetTarget( const char *pName ); // Set entity to move based on the Mirror Target entity (ex. a point_camera) + void SetMirrorRelative( const char* pName ); // Set the point about which to measure an offset to orient based upon (ex. portal 1) + void SetRemoteTarget ( const char *pName ); // Entity's orientation/location from which to offset the movement target (ex. portal 2) + void SetDrawingSurface ( const char *pName ); + + void InputSetMirrorTarget( inputdata_t &inputdata ); + void InputSetTarget( inputdata_t &inputdata ); + void InputSetRemoteTarget ( inputdata_t &inputdata ); + void InputSetMirrorRelative ( inputdata_t &inputdata ); + + void Think(); + virtual void Activate(); + + string_t m_strMirrorTarget; + string_t m_strRemoteTarget; + string_t m_strMirrorRelative; + + EHANDLE m_hRemoteTarget; + EHANDLE m_hMirrorTarget; + EHANDLE m_hMovementTarget; + EHANDLE m_hMirrorRelative; + +}; + +LINK_ENTITY_TO_CLASS( logic_mirror_movement, CLogicMirrorMovement ); + + +BEGIN_DATADESC( CLogicMirrorMovement ) + +DEFINE_KEYFIELD( m_strMirrorTarget, FIELD_STRING, "MirrorTarget" ), +DEFINE_KEYFIELD( m_strRemoteTarget, FIELD_STRING, "RemoteTarget" ), +DEFINE_KEYFIELD( m_strMirrorRelative, FIELD_STRING, "MirrorRelative" ), + +DEFINE_FIELD( m_hMirrorTarget, FIELD_EHANDLE ), +DEFINE_FIELD( m_hMovementTarget, FIELD_EHANDLE ), +DEFINE_FIELD( m_hRemoteTarget, FIELD_EHANDLE ), +DEFINE_FIELD( m_hMirrorRelative, FIELD_EHANDLE ), + +DEFINE_INPUTFUNC( FIELD_STRING, "SetMirrorTarget", InputSetMirrorTarget ), +DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ), +DEFINE_INPUTFUNC( FIELD_STRING, "SetRemoteTarget", InputSetRemoteTarget ), +DEFINE_INPUTFUNC( FIELD_STRING, "SetMirrorRelative", InputSetMirrorRelative ), + +DEFINE_THINKFUNC( Think ), + +END_DATADESC() + + +void CLogicMirrorMovement::Activate() +{ + BaseClass::Activate(); + + SetMirrorTarget( STRING(m_strMirrorTarget) ); + SetTarget( STRING(m_target) ); + SetRemoteTarget( STRING(m_strRemoteTarget ) ); + SetMirrorRelative( STRING( m_strMirrorRelative) ); + + SetThink( &CLogicMirrorMovement::Think ); + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); +} + + +void CLogicMirrorMovement::SetMirrorTarget( const char *pName ) +{ + m_hMirrorTarget = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hMirrorTarget ) + { + if ( Q_strnicmp( STRING(m_strMirrorTarget), "!player", 8 ) ) + { + Warning("logic_mirror_movement: Unable to find mirror target entity %s\n", pName ); + } + } +} + +void CLogicMirrorMovement::SetTarget( const char *pName ) +{ + m_hMovementTarget = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hMovementTarget ) + { + Warning("logic_mirror_movement: Unable to find movement target entity %s\n", pName ); + } +} + +void CLogicMirrorMovement::SetRemoteTarget(const char *pName ) +{ + m_hRemoteTarget = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hRemoteTarget ) + { + Warning("logic_mirror_movement: Unable to find remote target entity %s\n", pName ); + } +} + +void CLogicMirrorMovement::SetMirrorRelative(const char* pName ) +{ + m_hMirrorRelative = gEntList.FindEntityByName( NULL, pName ); + if ( !m_hMirrorRelative ) + { + Warning("logic_mirror_movement: Unable to find mirror relative entity %s\n", pName ); + } +} + +void CLogicMirrorMovement::InputSetMirrorTarget( inputdata_t &inputdata ) +{ + m_strMirrorTarget = AllocPooledString( inputdata.value.String() ); + SetMirrorTarget( inputdata.value.String() ); +} + +void CLogicMirrorMovement::InputSetTarget( inputdata_t &inputdata ) +{ + m_target = AllocPooledString( inputdata.value.String() ); + SetTarget( inputdata.value.String() ); +} + +void CLogicMirrorMovement::InputSetRemoteTarget(inputdata_t &inputdata ) +{ + m_strRemoteTarget = AllocPooledString( inputdata.value.String() ); + SetRemoteTarget( inputdata.value.String() ); +} + +void CLogicMirrorMovement::InputSetMirrorRelative(inputdata_t &inputdata ) +{ + m_strMirrorRelative = AllocPooledString ( inputdata.value.String() ); + SetMirrorRelative( inputdata.value.String() ); +} + + +void CLogicMirrorMovement::Think() +{ + // Attempt to get the player's handle because it didn't exist at Activate time + if ( !m_hMirrorTarget.Get() ) + { + // If we will never find a target, we don't have a use... shutdown + if ( m_strMirrorTarget == NULL_STRING ) + SetNextThink ( NULL ); + + //BUGBUG: If m_strSetMirrorTarget doesn't exist in ent list, we get per-think searches with no results ever... + SetMirrorTarget ( STRING(m_strMirrorTarget) ); + } + + // Make sure all entities are valid + if ( m_hMirrorTarget.Get() && m_hMovementTarget.Get() && m_hRemoteTarget.Get() && m_hMirrorRelative.Get() ) + { + // Get our two portal's world transforms transforms + VMatrix matPortal1ToWorldInv, matPortal2ToWorld; + MatrixInverseGeneral( m_hMirrorRelative->EntityToWorldTransform(), matPortal1ToWorldInv ); + matPortal2ToWorld = m_hRemoteTarget->EntityToWorldTransform(); + + VMatrix matTransformToRemotePortal = matPortal1ToWorldInv * matPortal2ToWorld; + + // Get our scene camera's current orientation + Vector ptCameraPosition, vCameraLook, vCameraRight, vCameraUp; + ptCameraPosition = m_hMirrorTarget->EyePosition(); + m_hMirrorTarget->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 ); + m_hMovementTarget->Teleport( &ptNewPosition, &qNewAngles, NULL ); + } + + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); +} + + |