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.

346 lines
9.6 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "c_baseentity.h"
  9. #ifdef WIN32
  10. #include <typeinfo.h>
  11. #endif
  12. #include "tier0/vprof.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. //-----------------------------------------------------------------------------
  16. // helper method for trace hull as used by physics...
  17. //-----------------------------------------------------------------------------
  18. static void Physics_TraceHull( C_BaseEntity* pBaseEntity, const Vector &vecStart,
  19. const Vector &vecEnd, const Vector &hullMin, const Vector &hullMax,
  20. unsigned int mask, trace_t *ptr )
  21. {
  22. // FIXME: I really am not sure the best way of doing this
  23. // The TraceHull code below for shots will make sure the object passes
  24. // through shields which do not block that damage type. It will also
  25. // send messages to the shields that they've been hit.
  26. #if 0
  27. if (pBaseEntity->GetDamageType() != DMG_GENERIC)
  28. {
  29. GameRules()->WeaponTraceHull( vecStart, vecEnd, hullMin, hullMax,
  30. mask, pBaseEntity, pBaseEntity->GetCollisionGroup(),
  31. pBaseEntity, ptr );
  32. }
  33. else
  34. #endif
  35. {
  36. UTIL_TraceHull( vecStart, vecEnd, hullMin, hullMax, mask,
  37. pBaseEntity, pBaseEntity->GetCollisionGroup(), ptr );
  38. }
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose: Does not change the entities velocity at all
  42. // Input : push -
  43. // Output : trace_t
  44. //-----------------------------------------------------------------------------
  45. void C_BaseEntity::PhysicsCheckSweep( const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace )
  46. {
  47. unsigned int mask = PhysicsSolidMaskForEntity();
  48. Vector vecAbsEnd;
  49. VectorAdd( vecAbsStart, vecAbsDelta, vecAbsEnd );
  50. // Set collision type
  51. if ( !IsSolid() || IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) )
  52. {
  53. // don't collide with monsters
  54. mask &= ~CONTENTS_MONSTER;
  55. }
  56. Physics_TraceHull( this, vecAbsStart, vecAbsEnd, WorldAlignMins(), WorldAlignMaxs(), mask, pTrace );
  57. }
  58. //-----------------------------------------------------------------------------
  59. // Purpose:
  60. // Input : push -
  61. // Output : trace_t
  62. //-----------------------------------------------------------------------------
  63. void C_BaseEntity::PhysicsPushEntity( const Vector& push, trace_t *pTrace )
  64. {
  65. /*
  66. if ( m_pMoveParent )
  67. {
  68. Warning( "pushing entity (%s) that has m_pMoveParent!\n", STRING( pev->classname ) );
  69. Assert(0);
  70. }
  71. */
  72. // NOTE: absorigin and origin must be equal because there is no moveparent
  73. Vector prevOrigin;
  74. VectorCopy( GetAbsOrigin(), prevOrigin );
  75. trace_t trace;
  76. PhysicsCheckSweep( prevOrigin, push, pTrace );
  77. if ( pTrace->fraction )
  78. {
  79. SetAbsOrigin( pTrace->endpos );
  80. }
  81. // CLIENT DLL HACKS
  82. m_vecNetworkOrigin = GetLocalOrigin();
  83. m_angNetworkAngles = GetLocalAngles();
  84. // InvalidatePhysicsRecursive( POSITION_CHANGED | ANGLES_CHANGED );
  85. if ( pTrace->m_pEnt )
  86. {
  87. PhysicsImpact( pTrace->m_pEnt, *pTrace );
  88. }
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose:
  92. // Input : *pNewPosition -
  93. // *pNewVelocity -
  94. // *pNewAngles -
  95. // *pNewAngVelocity -
  96. //-----------------------------------------------------------------------------
  97. void C_BaseEntity::PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity )
  98. {
  99. // If you're going to use custom physics, you need to implement this!
  100. Assert(0);
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose:
  104. //-----------------------------------------------------------------------------
  105. void C_BaseEntity::PhysicsCustom()
  106. {
  107. PhysicsCheckWater();
  108. // regular thinking
  109. if ( !PhysicsRunThink() )
  110. return;
  111. // Moving upward, off the ground, or resting on something that isn't ground
  112. if ( m_vecVelocity[2] > 0 || !GetGroundEntity() || !GetGroundEntity()->IsStandable() )
  113. {
  114. SetGroundEntity( NULL );
  115. }
  116. // NOTE: The entity must set the position, angles, velocity in its custom movement
  117. Vector vecNewPosition = GetAbsOrigin();
  118. if ( vecNewPosition == vec3_origin )
  119. {
  120. // Shouldn't be at world origin
  121. Assert( 0 );
  122. }
  123. Vector vecNewVelocity = m_vecVelocity;
  124. QAngle angNewAngles = GetAbsAngles();
  125. QAngle angNewAngVelocity = m_vecAngVelocity;
  126. PerformCustomPhysics( &vecNewPosition, &vecNewVelocity, &angNewAngles, &angNewAngVelocity );
  127. // Store off all of the new state information...
  128. m_vecVelocity = vecNewVelocity;
  129. SetAbsAngles( angNewAngles );
  130. m_vecAngVelocity = angNewAngVelocity;
  131. Vector move;
  132. VectorSubtract( vecNewPosition, GetAbsOrigin(), move );
  133. // move origin
  134. trace_t trace;
  135. PhysicsPushEntity( move, &trace );
  136. PhysicsCheckVelocity();
  137. if (trace.allsolid)
  138. {
  139. // entity is trapped in another solid
  140. // UNDONE: does this entity needs to be removed?
  141. VectorCopy (vec3_origin, m_vecVelocity);
  142. VectorCopy (vec3_angle, m_vecAngVelocity);
  143. return;
  144. }
  145. #if !defined( CLIENT_DLL )
  146. if (pev->free)
  147. return;
  148. #endif
  149. // check for in water
  150. PhysicsCheckWaterTransition();
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose:
  154. //-----------------------------------------------------------------------------
  155. void C_BaseEntity::PhysicsStep()
  156. {
  157. // Run all but the base think function
  158. PhysicsRunThink( THINK_FIRE_ALL_BUT_BASE );
  159. PhysicsRunThink( THINK_FIRE_BASE_ONLY );
  160. }
  161. //-----------------------------------------------------------------------------
  162. // Purpose:
  163. //-----------------------------------------------------------------------------
  164. void C_BaseEntity::PhysicsNoclip( void )
  165. {
  166. PhysicsRunThink();
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Purpose:
  170. //-----------------------------------------------------------------------------
  171. void C_BaseEntity::PhysicsNone( void )
  172. {
  173. PhysicsRunThink();
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose:
  177. //-----------------------------------------------------------------------------
  178. void C_BaseEntity::PhysicsPusher( void )
  179. {
  180. PhysicsRunThink();
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose:
  184. //-----------------------------------------------------------------------------
  185. void C_BaseEntity::PhysicsParent( void )
  186. {
  187. PhysicsRunThink();
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose: Not yet supported on client .dll
  191. // Input : *pOther -
  192. //-----------------------------------------------------------------------------
  193. void C_BaseEntity::StartTouch( C_BaseEntity *pOther )
  194. {
  195. // notify parent
  196. // if ( m_pParent != NULL )
  197. // m_pParent->StartTouch( pOther );
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose: Call touch function if one is set
  201. // Input : *pOther -
  202. //-----------------------------------------------------------------------------
  203. void C_BaseEntity::Touch( C_BaseEntity *pOther )
  204. {
  205. if ( m_pfnTouch )
  206. (this->*m_pfnTouch)( pOther );
  207. // notify parent of touch
  208. // if ( m_pParent != NULL )
  209. // m_pParent->Touch( pOther );
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Purpose: Call end touch
  213. // Input : *pOther -
  214. //-----------------------------------------------------------------------------
  215. void C_BaseEntity::EndTouch( C_BaseEntity *pOther )
  216. {
  217. // notify parent
  218. // if ( m_pParent != NULL )
  219. // {
  220. // m_pParent->EndTouch( pOther );
  221. // }
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose:
  225. // Input : check -
  226. //-----------------------------------------------------------------------------
  227. void C_BaseEntity::SetCheckUntouch( bool check )
  228. {
  229. // Invalidate touchstamp
  230. if ( check )
  231. {
  232. touchStamp++;
  233. if ( !IsEFlagSet( EFL_CHECK_UNTOUCH ) )
  234. {
  235. AddEFlags( EFL_CHECK_UNTOUCH );
  236. }
  237. }
  238. else
  239. {
  240. RemoveEFlags( EFL_CHECK_UNTOUCH );
  241. }
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose:
  245. // Output : Returns true on success, false on failure.
  246. //-----------------------------------------------------------------------------
  247. bool C_BaseEntity::GetCheckUntouch() const
  248. {
  249. return IsEFlagSet( EFL_CHECK_UNTOUCH );
  250. }
  251. extern ConVar think_limit;
  252. //-----------------------------------------------------------------------------
  253. // Purpose: Called when it's time for a physically moved objects (plats, doors, etc)
  254. // to run it's game code.
  255. // All other entity thinking is done during worldspawn's think
  256. //-----------------------------------------------------------------------------
  257. void C_BaseEntity::PhysicsDispatchThink( BASEPTR thinkFunc )
  258. {
  259. float thinkLimit = think_limit.GetFloat();
  260. double startTime = 0.0;
  261. /*
  262. // This doesn't apply on the client, really
  263. if ( IsDormant() )
  264. {
  265. Warning( "Dormant entity %s is thinking!!\n", GetClassname() );
  266. Assert(0);
  267. }
  268. */
  269. if ( thinkLimit )
  270. {
  271. startTime = Plat_FloatTime();
  272. }
  273. if ( thinkFunc )
  274. {
  275. (this->*thinkFunc)();
  276. }
  277. if ( thinkLimit )
  278. {
  279. // calculate running time of the AI in milliseconds
  280. float time = ( Plat_FloatTime() - startTime ) * 1000.0f;
  281. if ( time > thinkLimit )
  282. {
  283. #if 0
  284. // If its an NPC print out the shedule/task that took so long
  285. CAI_BaseNPC *pNPC = MyNPCPointer();
  286. if (pNPC && pNPC->GetCurSchedule())
  287. {
  288. pNPC->ReportOverThinkLimit( time );
  289. }
  290. else
  291. #endif
  292. {
  293. #ifdef WIN32
  294. Msg( "CLIENT: %s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).raw_name(), time );
  295. #else
  296. Msg( "CLIENT: %s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).name(), time );
  297. #endif
  298. }
  299. }
  300. }
  301. }