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.

349 lines
9.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Frequently used global functions.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "doors.h"
  9. #include "entitylist.h"
  10. #include "globals.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. // Landmark class
  14. void CPointEntity::Spawn( void )
  15. {
  16. SetSolid( SOLID_NONE );
  17. // UTIL_SetSize(this, vec3_origin, vec3_origin);
  18. }
  19. class CNullEntity : public CBaseEntity
  20. {
  21. public:
  22. DECLARE_CLASS( CNullEntity, CBaseEntity );
  23. void Spawn( void );
  24. };
  25. // Null Entity, remove on startup
  26. void CNullEntity::Spawn( void )
  27. {
  28. UTIL_Remove( this );
  29. }
  30. LINK_ENTITY_TO_CLASS(info_null,CNullEntity);
  31. class CBaseDMStart : public CPointEntity
  32. {
  33. public:
  34. DECLARE_CLASS( CBaseDMStart, CPointEntity );
  35. bool IsTriggered( CBaseEntity *pEntity );
  36. DECLARE_DATADESC();
  37. string_t m_Master;
  38. private:
  39. };
  40. BEGIN_DATADESC( CBaseDMStart )
  41. DEFINE_KEYFIELD( m_Master, FIELD_STRING, "master" ),
  42. END_DATADESC()
  43. // These are the new entry points to entities.
  44. LINK_ENTITY_TO_CLASS(info_player_deathmatch,CBaseDMStart);
  45. LINK_ENTITY_TO_CLASS(info_player_start,CPointEntity);
  46. LINK_ENTITY_TO_CLASS(info_landmark,CPointEntity);
  47. bool CBaseDMStart::IsTriggered( CBaseEntity *pEntity )
  48. {
  49. bool master = UTIL_IsMasterTriggered( m_Master, pEntity );
  50. return master;
  51. }
  52. // Convenient way to delay removing oneself
  53. void CBaseEntity::SUB_Remove( void )
  54. {
  55. if (m_iHealth > 0)
  56. {
  57. // this situation can screw up NPCs who can't tell their entity pointers are invalid.
  58. m_iHealth = 0;
  59. DevWarning( 2, "SUB_Remove called on entity with health > 0\n");
  60. }
  61. UTIL_Remove( this );
  62. }
  63. // Convenient way to explicitly do nothing (passed to functions that require a method)
  64. void CBaseEntity::SUB_DoNothing( void )
  65. {
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Purpose: Finds all active entities with the given targetname and calls their
  69. // 'Use' function.
  70. // Input : targetName - Target name to search for.
  71. // pActivator -
  72. // pCaller -
  73. // useType -
  74. // value -
  75. //-----------------------------------------------------------------------------
  76. void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  77. {
  78. CBaseEntity *pTarget = NULL;
  79. if ( !targetName || !targetName[0] )
  80. return;
  81. DevMsg( 2, "Firing: (%s)\n", targetName );
  82. for (;;)
  83. {
  84. CBaseEntity *pSearchingEntity = pActivator;
  85. pTarget = gEntList.FindEntityByName( pTarget, targetName, pSearchingEntity, pActivator, pCaller );
  86. if ( !pTarget )
  87. break;
  88. if (!pTarget->IsMarkedForDeletion() ) // Don't use dying ents
  89. {
  90. DevMsg( 2, "[%03d] Found: %s, firing (%s)\n", gpGlobals->tickcount%1000, pTarget->GetDebugName(), targetName );
  91. pTarget->Use( pActivator, pCaller, useType, value );
  92. }
  93. }
  94. }
  95. enum togglemovetypes_t
  96. {
  97. MOVE_TOGGLE_NONE = 0,
  98. MOVE_TOGGLE_LINEAR = 1,
  99. MOVE_TOGGLE_ANGULAR = 2,
  100. };
  101. // Global Savedata for Toggle
  102. BEGIN_DATADESC( CBaseToggle )
  103. DEFINE_FIELD( m_toggle_state, FIELD_INTEGER ),
  104. DEFINE_FIELD( m_flMoveDistance, FIELD_FLOAT ),
  105. DEFINE_FIELD( m_flWait, FIELD_FLOAT ),
  106. DEFINE_FIELD( m_flLip, FIELD_FLOAT ),
  107. DEFINE_FIELD( m_vecPosition1, FIELD_POSITION_VECTOR ),
  108. DEFINE_FIELD( m_vecPosition2, FIELD_POSITION_VECTOR ),
  109. DEFINE_FIELD( m_vecMoveAng, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
  110. DEFINE_FIELD( m_vecAngle1, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
  111. DEFINE_FIELD( m_vecAngle2, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
  112. DEFINE_FIELD( m_flHeight, FIELD_FLOAT ),
  113. DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ),
  114. DEFINE_FIELD( m_vecFinalDest, FIELD_POSITION_VECTOR ),
  115. DEFINE_FIELD( m_vecFinalAngle, FIELD_VECTOR ),
  116. DEFINE_FIELD( m_sMaster, FIELD_STRING),
  117. DEFINE_FIELD( m_movementType, FIELD_INTEGER ), // Linear or angular movement? (togglemovetypes_t)
  118. END_DATADESC()
  119. CBaseToggle::CBaseToggle()
  120. {
  121. #ifdef _DEBUG
  122. // necessary since in debug, we initialize vectors to NAN for debugging
  123. m_vecPosition1.Init();
  124. m_vecPosition2.Init();
  125. m_vecAngle1.Init();
  126. m_vecAngle2.Init();
  127. m_vecFinalDest.Init();
  128. m_vecFinalAngle.Init();
  129. #endif
  130. }
  131. bool CBaseToggle::KeyValue( const char *szKeyName, const char *szValue )
  132. {
  133. if (FStrEq(szKeyName, "lip"))
  134. {
  135. m_flLip = atof(szValue);
  136. }
  137. else if (FStrEq(szKeyName, "wait"))
  138. {
  139. m_flWait = atof(szValue);
  140. }
  141. else if (FStrEq(szKeyName, "master"))
  142. {
  143. m_sMaster = AllocPooledString(szValue);
  144. }
  145. else if (FStrEq(szKeyName, "distance"))
  146. {
  147. m_flMoveDistance = atof(szValue);
  148. }
  149. else
  150. return BaseClass::KeyValue( szKeyName, szValue );
  151. return true;
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from
  155. // GetOrigin() traveling at flSpeed.
  156. // Input : Vector vecDest -
  157. // flSpeed -
  158. //-----------------------------------------------------------------------------
  159. void CBaseToggle::LinearMove( const Vector &vecDest, float flSpeed )
  160. {
  161. ASSERTSZ(flSpeed != 0, "LinearMove: no speed is defined!");
  162. m_vecFinalDest = vecDest;
  163. m_movementType = MOVE_TOGGLE_LINEAR;
  164. // Already there?
  165. if (vecDest == GetLocalOrigin())
  166. {
  167. MoveDone();
  168. return;
  169. }
  170. // set destdelta to the vector needed to move
  171. Vector vecDestDelta = vecDest - GetLocalOrigin();
  172. // divide vector length by speed to get time to reach dest
  173. float flTravelTime = vecDestDelta.Length() / flSpeed;
  174. // set m_flNextThink to trigger a call to LinearMoveDone when dest is reached
  175. SetMoveDoneTime( flTravelTime );
  176. // scale the destdelta vector by the time spent traveling to get velocity
  177. SetLocalVelocity( vecDestDelta / flTravelTime );
  178. }
  179. void CBaseToggle::MoveDone( void )
  180. {
  181. switch ( m_movementType )
  182. {
  183. case MOVE_TOGGLE_LINEAR:
  184. LinearMoveDone();
  185. break;
  186. case MOVE_TOGGLE_ANGULAR:
  187. AngularMoveDone();
  188. break;
  189. }
  190. m_movementType = MOVE_TOGGLE_NONE;
  191. BaseClass::MoveDone();
  192. }
  193. //-----------------------------------------------------------------------------
  194. // Purpose: After moving, set origin to exact final destination, call "move done" function.
  195. //-----------------------------------------------------------------------------
  196. void CBaseToggle::LinearMoveDone( void )
  197. {
  198. UTIL_SetOrigin( this, m_vecFinalDest);
  199. SetAbsVelocity( vec3_origin );
  200. SetMoveDoneTime( -1 );
  201. }
  202. // DVS TODO: obselete, remove?
  203. bool CBaseToggle::IsLockedByMaster( void )
  204. {
  205. if (m_sMaster != NULL_STRING && !UTIL_IsMasterTriggered(m_sMaster, m_hActivator))
  206. return true;
  207. else
  208. return false;
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from
  212. // GetLocalOrigin() traveling at flSpeed. Just like LinearMove, but rotational.
  213. // Input : vecDestAngle -
  214. // flSpeed -
  215. //-----------------------------------------------------------------------------
  216. void CBaseToggle::AngularMove( const QAngle &vecDestAngle, float flSpeed )
  217. {
  218. ASSERTSZ(flSpeed != 0, "AngularMove: no speed is defined!");
  219. m_vecFinalAngle = vecDestAngle;
  220. m_movementType = MOVE_TOGGLE_ANGULAR;
  221. // Already there?
  222. if (vecDestAngle == GetLocalAngles())
  223. {
  224. MoveDone();
  225. return;
  226. }
  227. // set destdelta to the vector needed to move
  228. QAngle vecDestDelta = vecDestAngle - GetLocalAngles();
  229. // divide by speed to get time to reach dest
  230. float flTravelTime = vecDestDelta.Length() / flSpeed;
  231. const float MinTravelTime = 0.01f;
  232. if ( flTravelTime < MinTravelTime )
  233. {
  234. // If we only travel for a short time, we can fail WillSimulateGamePhysics()
  235. flTravelTime = MinTravelTime;
  236. flSpeed = vecDestDelta.Length() / flTravelTime;
  237. }
  238. // set m_flNextThink to trigger a call to AngularMoveDone when dest is reached
  239. SetMoveDoneTime( flTravelTime );
  240. // scale the destdelta vector by the time spent traveling to get velocity
  241. SetLocalAngularVelocity( vecDestDelta * (1.0 / flTravelTime) );
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose: After rotating, set angle to exact final angle, call "move done" function.
  245. //-----------------------------------------------------------------------------
  246. void CBaseToggle::AngularMoveDone( void )
  247. {
  248. SetLocalAngles( m_vecFinalAngle );
  249. SetLocalAngularVelocity( vec3_angle );
  250. SetMoveDoneTime( -1 );
  251. }
  252. float CBaseToggle::AxisValue( int flags, const QAngle &angles )
  253. {
  254. if ( FBitSet(flags, SF_DOOR_ROTATE_ROLL) )
  255. return angles.z;
  256. if ( FBitSet(flags, SF_DOOR_ROTATE_PITCH) )
  257. return angles.x;
  258. return angles.y;
  259. }
  260. void CBaseToggle::AxisDir( void )
  261. {
  262. if ( m_spawnflags & SF_DOOR_ROTATE_ROLL )
  263. m_vecMoveAng = QAngle( 0, 0, 1 ); // angles are roll
  264. else if ( m_spawnflags & SF_DOOR_ROTATE_PITCH )
  265. m_vecMoveAng = QAngle( 1, 0, 0 ); // angles are pitch
  266. else
  267. m_vecMoveAng = QAngle( 0, 1, 0 ); // angles are yaw
  268. }
  269. float CBaseToggle::AxisDelta( int flags, const QAngle &angle1, const QAngle &angle2 )
  270. {
  271. // UNDONE: Use AngleDistance() here?
  272. if ( FBitSet (flags, SF_DOOR_ROTATE_ROLL) )
  273. return angle1.z - angle2.z;
  274. if ( FBitSet (flags, SF_DOOR_ROTATE_PITCH) )
  275. return angle1.x - angle2.x;
  276. return angle1.y - angle2.y;
  277. }