Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
8.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: This will measure the movement of a target entity and move
  4. // another entity to match the movement of the first.
  5. //
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "baseentity.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. //-----------------------------------------------------------------------------
  12. // This will measure the movement of a target entity and move
  13. // another entity to match the movement of the first.
  14. //-----------------------------------------------------------------------------
  15. class CLogicMeasureMovement : public CLogicalEntity
  16. {
  17. DECLARE_DATADESC();
  18. DECLARE_CLASS( CLogicMeasureMovement, CLogicalEntity );
  19. public:
  20. virtual void Activate();
  21. private:
  22. void SetMeasureTarget( const char *pName );
  23. void SetMeasureReference( const char *pName );
  24. void SetTarget( const char *pName );
  25. void SetTargetReference( const char *pName );
  26. void InputSetMeasureTarget( inputdata_t &inputdata );
  27. void InputSetMeasureReference( inputdata_t &inputdata );
  28. void InputSetTarget( inputdata_t &inputdata );
  29. void InputSetTargetReference( inputdata_t &inputdata );
  30. void InputSetTargetScale( inputdata_t &inputdata );
  31. void InputEnable( inputdata_t &inputdata );
  32. void InputDisable( inputdata_t &inputdata );
  33. void MeasureThink();
  34. private:
  35. enum
  36. {
  37. MEASURE_POSITION = 0,
  38. MEASURE_EYE_POSITION,
  39. };
  40. string_t m_strMeasureTarget;
  41. string_t m_strMeasureReference;
  42. string_t m_strTargetReference;
  43. EHANDLE m_hMeasureTarget;
  44. EHANDLE m_hMeasureReference;
  45. EHANDLE m_hTarget;
  46. EHANDLE m_hTargetReference;
  47. float m_flScale;
  48. int m_nMeasureType;
  49. };
  50. LINK_ENTITY_TO_CLASS( logic_measure_movement, CLogicMeasureMovement );
  51. BEGIN_DATADESC( CLogicMeasureMovement )
  52. DEFINE_KEYFIELD( m_strMeasureTarget, FIELD_STRING, "MeasureTarget" ),
  53. DEFINE_KEYFIELD( m_strMeasureReference, FIELD_STRING, "MeasureReference" ),
  54. DEFINE_KEYFIELD( m_strTargetReference, FIELD_STRING, "TargetReference" ),
  55. DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "TargetScale" ),
  56. DEFINE_KEYFIELD( m_nMeasureType, FIELD_INTEGER, "MeasureType" ),
  57. DEFINE_FIELD( m_hMeasureTarget, FIELD_EHANDLE ),
  58. DEFINE_FIELD( m_hMeasureReference, FIELD_EHANDLE ),
  59. DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ),
  60. DEFINE_FIELD( m_hTargetReference, FIELD_EHANDLE ),
  61. DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureTarget", InputSetMeasureTarget ),
  62. DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureReference", InputSetMeasureReference ),
  63. DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ),
  64. DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetReference", InputSetTargetReference ),
  65. DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTargetScale", InputSetTargetScale ),
  66. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  67. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  68. DEFINE_THINKFUNC( MeasureThink ),
  69. END_DATADESC()
  70. //-----------------------------------------------------------------------------
  71. // Methods to change various targets
  72. //-----------------------------------------------------------------------------
  73. void CLogicMeasureMovement::Activate()
  74. {
  75. BaseClass::Activate();
  76. SetMeasureTarget( STRING(m_strMeasureTarget) );
  77. SetMeasureReference( STRING(m_strMeasureReference) );
  78. SetTarget( STRING(m_target) );
  79. SetTargetReference( STRING(m_strTargetReference) );
  80. SetThink( &CLogicMeasureMovement::MeasureThink );
  81. SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Sets the name
  85. //-----------------------------------------------------------------------------
  86. void CLogicMeasureMovement::SetMeasureTarget( const char *pName )
  87. {
  88. m_hMeasureTarget = gEntList.FindEntityByName( NULL, pName );
  89. if ( !m_hMeasureTarget )
  90. {
  91. if ( Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) )
  92. {
  93. Warning("logic_measure_movement: Unable to find measure target entity %s\n", pName );
  94. }
  95. }
  96. }
  97. void CLogicMeasureMovement::SetMeasureReference( const char *pName )
  98. {
  99. m_hMeasureReference = gEntList.FindEntityByName( NULL, pName );
  100. if ( !m_hMeasureReference )
  101. {
  102. Warning("logic_measure_movement: Unable to find measure reference entity %s\n", pName );
  103. }
  104. }
  105. void CLogicMeasureMovement::SetTarget( const char *pName )
  106. {
  107. m_hTarget = gEntList.FindEntityByName( NULL, pName );
  108. if ( !m_hTarget )
  109. {
  110. Warning("logic_measure_movement: Unable to find movement target entity %s\n", pName );
  111. }
  112. }
  113. void CLogicMeasureMovement::SetTargetReference( const char *pName )
  114. {
  115. m_hTargetReference = gEntList.FindEntityByName( NULL, pName );
  116. if ( !m_hTargetReference )
  117. {
  118. Warning("logic_measure_movement: Unable to find movement reference entity %s\n", pName );
  119. }
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Apply movement
  123. //-----------------------------------------------------------------------------
  124. void CLogicMeasureMovement::MeasureThink( )
  125. {
  126. // FIXME: This is a hack to make measuring !player simpler. The player isn't
  127. // created at Activate time, so m_hMeasureTarget may be NULL because of that.
  128. if ( !m_hMeasureTarget.Get() && !Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) )
  129. {
  130. SetMeasureTarget( STRING(m_strMeasureTarget) );
  131. }
  132. // Make sure all entities are valid
  133. if ( m_hMeasureTarget.Get() && m_hMeasureReference.Get() && m_hTarget.Get() && m_hTargetReference.Get() )
  134. {
  135. matrix3x4_t matRefToMeasure, matWorldToMeasure;
  136. switch( m_nMeasureType )
  137. {
  138. case MEASURE_POSITION:
  139. MatrixInvert( m_hMeasureTarget->EntityToWorldTransform(), matWorldToMeasure );
  140. break;
  141. case MEASURE_EYE_POSITION:
  142. AngleIMatrix( m_hMeasureTarget->EyeAngles(), m_hMeasureTarget->EyePosition(), matWorldToMeasure );
  143. break;
  144. // FIXME: Could add attachment point measurement here easily
  145. }
  146. ConcatTransforms( matWorldToMeasure, m_hMeasureReference->EntityToWorldTransform(), matRefToMeasure );
  147. // Apply the scale factor
  148. if ( ( m_flScale != 0.0f ) && ( m_flScale != 1.0f ) )
  149. {
  150. Vector vecTranslation;
  151. MatrixGetColumn( matRefToMeasure, 3, vecTranslation );
  152. vecTranslation /= m_flScale;
  153. MatrixSetColumn( vecTranslation, 3, matRefToMeasure );
  154. }
  155. // Now apply the new matrix to the new reference point
  156. matrix3x4_t matMeasureToRef, matNewTargetToWorld;
  157. MatrixInvert( matRefToMeasure, matMeasureToRef );
  158. ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld );
  159. Vector vecNewOrigin;
  160. QAngle vecNewAngles;
  161. MatrixAngles( matNewTargetToWorld, vecNewAngles, vecNewOrigin );
  162. m_hTarget->SetAbsOrigin( vecNewOrigin );
  163. m_hTarget->SetAbsAngles( vecNewAngles );
  164. }
  165. SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Enable, disable
  169. //-----------------------------------------------------------------------------
  170. void CLogicMeasureMovement::InputEnable( inputdata_t &inputdata )
  171. {
  172. SetThink( &CLogicMeasureMovement::MeasureThink );
  173. SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
  174. }
  175. void CLogicMeasureMovement::InputDisable( inputdata_t &inputdata )
  176. {
  177. SetThink( NULL );
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Methods to change various targets
  181. //-----------------------------------------------------------------------------
  182. void CLogicMeasureMovement::InputSetMeasureTarget( inputdata_t &inputdata )
  183. {
  184. m_strMeasureTarget = MAKE_STRING( inputdata.value.String() );
  185. SetMeasureTarget( inputdata.value.String() );
  186. SetTarget( STRING(m_target) );
  187. SetTargetReference( STRING(m_strTargetReference) );
  188. }
  189. void CLogicMeasureMovement::InputSetMeasureReference( inputdata_t &inputdata )
  190. {
  191. m_strMeasureReference = MAKE_STRING( inputdata.value.String() );
  192. SetMeasureReference( inputdata.value.String() );
  193. }
  194. void CLogicMeasureMovement::InputSetTarget( inputdata_t &inputdata )
  195. {
  196. m_target = MAKE_STRING( inputdata.value.String() );
  197. SetTarget( inputdata.value.String() );
  198. }
  199. void CLogicMeasureMovement::InputSetTargetReference( inputdata_t &inputdata )
  200. {
  201. m_strTargetReference = MAKE_STRING( inputdata.value.String() );
  202. SetTargetReference( inputdata.value.String() );
  203. }
  204. void CLogicMeasureMovement::InputSetTargetScale( inputdata_t &inputdata )
  205. {
  206. m_flScale = inputdata.value.Float();
  207. }