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.

237 lines
5.7 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Implements doors that move when you look at them.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "basecombatcharacter.h"
  9. #include "entitylist.h"
  10. #include "func_movelinear.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. #define SF_LDOOR_THRESHOLD 8192
  14. #define SF_LDOOR_INVERT 16384
  15. #define SF_LDOOR_FROM_OPEN 32768
  16. class CLookDoor : public CFuncMoveLinear
  17. {
  18. public:
  19. DECLARE_CLASS( CLookDoor, CFuncMoveLinear );
  20. void Spawn( void );
  21. void MoveThink( void );
  22. // Inputs
  23. void InputInvertOn( inputdata_t &inputdata );
  24. void InputInvertOff( inputdata_t &inputdata );
  25. float m_flProximityDistance; // How far before I start reacting
  26. float m_flProximityOffset;
  27. float m_flFieldOfView;
  28. EHANDLE m_hLooker; // Who is looking
  29. DECLARE_DATADESC();
  30. };
  31. class CLookDoorThinker : public CLogicalEntity
  32. {
  33. public:
  34. DECLARE_CLASS( CLookDoorThinker, CLogicalEntity );
  35. void LookThink( void );
  36. EHANDLE m_hLookDoor; // Who owns me
  37. DECLARE_DATADESC();
  38. };
  39. BEGIN_DATADESC( CLookDoorThinker )
  40. DEFINE_FIELD( m_hLookDoor, FIELD_EHANDLE ),
  41. // Function Pointers
  42. DEFINE_FUNCTION(LookThink),
  43. END_DATADESC()
  44. LINK_ENTITY_TO_CLASS( lookdoorthinker, CLookDoorThinker );
  45. //------------------------------------------------------------------------------
  46. // Purpose :
  47. //------------------------------------------------------------------------------
  48. void CLookDoorThinker::LookThink(void)
  49. {
  50. if (m_hLookDoor)
  51. {
  52. ((CLookDoor*)(CBaseEntity*)m_hLookDoor)->MoveThink();
  53. SetNextThink( gpGlobals->curtime + 0.01f );
  54. }
  55. else
  56. {
  57. UTIL_Remove(this);
  58. }
  59. }
  60. BEGIN_DATADESC( CLookDoor )
  61. DEFINE_KEYFIELD( m_flProximityDistance, FIELD_FLOAT, "ProximityDistance"),
  62. DEFINE_KEYFIELD( m_flProximityOffset, FIELD_FLOAT, "ProximityOffset"),
  63. DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ),
  64. DEFINE_FIELD(m_hLooker, FIELD_EHANDLE),
  65. // Inputs
  66. DEFINE_INPUTFUNC( FIELD_VOID, "InvertOn", InputInvertOn ),
  67. DEFINE_INPUTFUNC( FIELD_VOID, "InvertOff", InputInvertOff ),
  68. // Function Pointers
  69. DEFINE_FUNCTION(MoveThink),
  70. END_DATADESC()
  71. LINK_ENTITY_TO_CLASS( func_lookdoor, CLookDoor );
  72. //------------------------------------------------------------------------------
  73. // Purpose : Input handlers.
  74. //------------------------------------------------------------------------------
  75. void CLookDoor::InputInvertOn( inputdata_t &inputdata )
  76. {
  77. m_spawnflags |= SF_LDOOR_INVERT;
  78. }
  79. void CLookDoor::InputInvertOff( inputdata_t &inputdata )
  80. {
  81. m_spawnflags &= ~SF_LDOOR_INVERT;
  82. }
  83. //------------------------------------------------------------------------------
  84. // Purpose :
  85. //------------------------------------------------------------------------------
  86. void CLookDoor::Spawn(void)
  87. {
  88. BaseClass::Spawn();
  89. if (m_target == NULL_STRING)
  90. {
  91. Warning( "ERROR: DoorLook (%s) given no target. Rejecting spawn.\n",GetDebugName());
  92. return;
  93. }
  94. CLookDoorThinker* pLookThinker = (CLookDoorThinker*)CreateEntityByName("lookdoorthinker");
  95. if (pLookThinker)
  96. {
  97. pLookThinker->SetThink(&CLookDoorThinker::LookThink);
  98. pLookThinker->m_hLookDoor = this;
  99. pLookThinker->SetNextThink( gpGlobals->curtime + 0.1f );
  100. }
  101. }
  102. //------------------------------------------------------------------------------
  103. // Purpose :
  104. //------------------------------------------------------------------------------
  105. void CLookDoor::MoveThink(void)
  106. {
  107. // --------------------------------
  108. // Make sure we have a looker
  109. // --------------------------------
  110. if (m_hLooker == NULL)
  111. {
  112. m_hLooker = (CBaseEntity*)gEntList.FindEntityByName( NULL, m_target );
  113. if (m_hLooker == NULL)
  114. {
  115. return;
  116. }
  117. }
  118. //--------------------------------------
  119. // Calculate an orgin for the door
  120. //--------------------------------------
  121. Vector vOrigin = WorldSpaceCenter() - GetAbsOrigin();
  122. // If FROM_OPEN flag is set, door proximity is measured
  123. // from the open and not the closed position
  124. if (FBitSet (m_spawnflags, SF_LDOOR_FROM_OPEN))
  125. {
  126. vOrigin += m_vecPosition2;
  127. }
  128. // ------------------------------------------------------
  129. // First add movement based on proximity
  130. // ------------------------------------------------------
  131. float flProxMove = 0;
  132. if (m_flProximityDistance > 0)
  133. {
  134. float flDist = (m_hLooker->GetAbsOrigin() - vOrigin).Length()-m_flProximityOffset;
  135. if (flDist < 0) flDist = 0;
  136. if (flDist < m_flProximityDistance)
  137. {
  138. if (FBitSet (m_spawnflags, SF_LDOOR_THRESHOLD))
  139. {
  140. flProxMove = 1.0;
  141. }
  142. else
  143. {
  144. flProxMove = 1-flDist/m_flProximityDistance;
  145. }
  146. }
  147. }
  148. // ------------------------------------------------------
  149. // Then add movement based on view angle
  150. // ------------------------------------------------------
  151. float flViewMove = 0;
  152. if (m_flFieldOfView > 0)
  153. {
  154. // ----------------------------------------
  155. // Check that toucher is facing the target
  156. // ----------------------------------------
  157. Assert( dynamic_cast< CBaseCombatCharacter* >( m_hLooker.Get() ) );
  158. CBaseCombatCharacter* pBCC = (CBaseCombatCharacter*)m_hLooker.Get();
  159. Vector vTouchDir = pBCC->EyeDirection3D( );
  160. Vector vTargetDir = vOrigin - pBCC->EyePosition();
  161. VectorNormalize(vTargetDir);
  162. float flDotPr = DotProduct(vTouchDir,vTargetDir);
  163. if (flDotPr < m_flFieldOfView)
  164. {
  165. flViewMove = 0.0;
  166. }
  167. else
  168. {
  169. flViewMove = (flDotPr-m_flFieldOfView)/(1.0 - m_flFieldOfView);
  170. }
  171. }
  172. //---------------------------------------
  173. // Summate the two moves
  174. //---------------------------------------
  175. float flMove = flProxMove + flViewMove;
  176. if (flMove > 1.0)
  177. {
  178. flMove = 1.0;
  179. }
  180. // If behavior is inverted do the reverse
  181. if (FBitSet (m_spawnflags, SF_LDOOR_INVERT))
  182. {
  183. flMove = 1-flMove;
  184. }
  185. // Move the door
  186. SetPosition( flMove );
  187. }