Counter Strike : Global Offensive Source Code
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.

365 lines
9.7 KiB

  1. //========= Copyright � 1996-2005, 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. IMPLEMENT_SERVERCLASS_ST(CBaseToggle, DT_BaseToggle)
  120. SendPropVector( SENDINFO( m_vecFinalDest ) ),
  121. SendPropInt( SENDINFO( m_movementType ) ),
  122. SendPropFloat( SENDINFO( m_flMoveTargetTime ) ),
  123. END_SEND_TABLE()
  124. CBaseToggle::CBaseToggle()
  125. {
  126. #ifdef _DEBUG
  127. // necessary since in debug, we initialize vectors to NAN for debugging
  128. m_vecPosition1.Init();
  129. m_vecPosition2.Init();
  130. m_vecAngle1.Init();
  131. m_vecAngle2.Init();
  132. m_vecFinalDest.Init();
  133. m_vecFinalAngle.Init();
  134. #endif
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Returns the velocity imparted to players standing on us.
  138. //-----------------------------------------------------------------------------
  139. void CBaseToggle::GetGroundVelocityToApply( Vector &vecGroundVel )
  140. {
  141. vecGroundVel = GetLocalVelocity();
  142. }
  143. bool CBaseToggle::KeyValue( const char *szKeyName, const char *szValue )
  144. {
  145. if (FStrEq(szKeyName, "lip"))
  146. {
  147. m_flLip = atof(szValue);
  148. }
  149. else if (FStrEq(szKeyName, "wait"))
  150. {
  151. m_flWait = atof(szValue);
  152. }
  153. else if (FStrEq(szKeyName, "master"))
  154. {
  155. m_sMaster = AllocPooledString(szValue);
  156. }
  157. else if (FStrEq(szKeyName, "distance"))
  158. {
  159. m_flMoveDistance = atof(szValue);
  160. }
  161. else
  162. return BaseClass::KeyValue( szKeyName, szValue );
  163. return true;
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from
  167. // GetOrigin() traveling at flSpeed.
  168. // Input : Vector vecDest -
  169. // flSpeed -
  170. //-----------------------------------------------------------------------------
  171. void CBaseToggle::LinearMove( const Vector &vecDest, float flSpeed )
  172. {
  173. ASSERTSZ(flSpeed != 0, "LinearMove: no speed is defined!");
  174. m_vecFinalDest = vecDest;
  175. m_movementType = MOVE_TOGGLE_LINEAR;
  176. // Already there?
  177. if (vecDest == GetLocalOrigin())
  178. {
  179. MoveDone();
  180. return;
  181. }
  182. // set destdelta to the vector needed to move
  183. Vector vecDestDelta = vecDest - GetLocalOrigin();
  184. // divide vector length by speed to get time to reach dest
  185. float flTravelTime = vecDestDelta.Length() / flSpeed;
  186. // set m_flNextThink to trigger a call to LinearMoveDone when dest is reached
  187. SetMoveDoneTime( flTravelTime );
  188. m_flMoveTargetTime = gpGlobals->curtime + flTravelTime;
  189. // scale the destdelta vector by the time spent traveling to get velocity
  190. SetLocalVelocity( vecDestDelta / flTravelTime );
  191. }
  192. void CBaseToggle::MoveDone( void )
  193. {
  194. switch ( m_movementType )
  195. {
  196. case MOVE_TOGGLE_LINEAR:
  197. LinearMoveDone();
  198. break;
  199. case MOVE_TOGGLE_ANGULAR:
  200. AngularMoveDone();
  201. break;
  202. }
  203. m_movementType = MOVE_TOGGLE_NONE;
  204. BaseClass::MoveDone();
  205. }
  206. //-----------------------------------------------------------------------------
  207. // Purpose: After moving, set origin to exact final destination, call "move done" function.
  208. //-----------------------------------------------------------------------------
  209. void CBaseToggle::LinearMoveDone( void )
  210. {
  211. UTIL_SetOrigin( this, m_vecFinalDest);
  212. SetAbsVelocity( vec3_origin );
  213. SetMoveDoneTime( -1 );
  214. }
  215. // DVS TODO: obselete, remove?
  216. bool CBaseToggle::IsLockedByMaster( void )
  217. {
  218. if (m_sMaster != NULL_STRING && !UTIL_IsMasterTriggered(m_sMaster, m_hActivator))
  219. return true;
  220. else
  221. return false;
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from
  225. // GetLocalOrigin() traveling at flSpeed. Just like LinearMove, but rotational.
  226. // Input : vecDestAngle -
  227. // flSpeed -
  228. //-----------------------------------------------------------------------------
  229. void CBaseToggle::AngularMove( const QAngle &vecDestAngle, float flSpeed )
  230. {
  231. ASSERTSZ(flSpeed != 0, "AngularMove: no speed is defined!");
  232. m_vecFinalAngle = vecDestAngle;
  233. m_movementType = MOVE_TOGGLE_ANGULAR;
  234. // Already there?
  235. if (vecDestAngle == GetLocalAngles())
  236. {
  237. MoveDone();
  238. return;
  239. }
  240. // set destdelta to the vector needed to move
  241. QAngle vecDestDelta = vecDestAngle - GetLocalAngles();
  242. // divide by speed to get time to reach dest
  243. float flTravelTime = vecDestDelta.Length() / flSpeed;
  244. const float MinTravelTime = 0.01f;
  245. if ( flTravelTime < MinTravelTime )
  246. {
  247. // If we only travel for a short time, we can fail WillSimulateGamePhysics()
  248. flTravelTime = MinTravelTime;
  249. flSpeed = vecDestDelta.Length() / flTravelTime;
  250. }
  251. // set m_flNextThink to trigger a call to AngularMoveDone when dest is reached
  252. SetMoveDoneTime( flTravelTime );
  253. // scale the destdelta vector by the time spent traveling to get velocity
  254. SetLocalAngularVelocity( vecDestDelta * (1.0 / flTravelTime) );
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Purpose: After rotating, set angle to exact final angle, call "move done" function.
  258. //-----------------------------------------------------------------------------
  259. void CBaseToggle::AngularMoveDone( void )
  260. {
  261. SetLocalAngles( m_vecFinalAngle );
  262. SetLocalAngularVelocity( vec3_angle );
  263. SetMoveDoneTime( -1 );
  264. }
  265. float CBaseToggle::AxisValue( int flags, const QAngle &angles )
  266. {
  267. if ( FBitSet(flags, SF_DOOR_ROTATE_ROLL) )
  268. return angles.z;
  269. if ( FBitSet(flags, SF_DOOR_ROTATE_PITCH) )
  270. return angles.x;
  271. return angles.y;
  272. }
  273. void CBaseToggle::AxisDir( void )
  274. {
  275. if ( m_spawnflags & SF_DOOR_ROTATE_ROLL )
  276. m_vecMoveAng = QAngle( 0, 0, 1 ); // angles are roll
  277. else if ( m_spawnflags & SF_DOOR_ROTATE_PITCH )
  278. m_vecMoveAng = QAngle( 1, 0, 0 ); // angles are pitch
  279. else
  280. m_vecMoveAng = QAngle( 0, 1, 0 ); // angles are yaw
  281. }
  282. float CBaseToggle::AxisDelta( int flags, const QAngle &angle1, const QAngle &angle2 )
  283. {
  284. // UNDONE: Use AngleDistance() here?
  285. if ( FBitSet (flags, SF_DOOR_ROTATE_ROLL) )
  286. return angle1.z - angle2.z;
  287. if ( FBitSet (flags, SF_DOOR_ROTATE_PITCH) )
  288. return angle1.x - angle2.x;
  289. return angle1.y - angle2.y;
  290. }