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.

400 lines
10 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // nav_entities.cpp
  9. // AI Navigation entities
  10. // Author: Michael S. Booth ([email protected]), January 2003
  11. #include "cbase.h"
  12. #include "nav_mesh.h"
  13. #include "nav_node.h"
  14. #include "nav_pathfind.h"
  15. #include "nav_colors.h"
  16. #include "fmtstr.h"
  17. #include "props_shared.h"
  18. #include "func_breakablesurf.h"
  19. #ifdef TERROR
  20. #include "func_elevator.h"
  21. #include "AmbientLight.h"
  22. #endif
  23. #include "color.h"
  24. #include "collisionutils.h"
  25. #include "functorutils.h"
  26. #include "team.h"
  27. #include "nav_entities.h"
  28. // memdbgon must be the last include file in a .cpp file!!!
  29. #include "tier0/memdbgon.h"
  30. //--------------------------------------------------------------------------------------------------------
  31. BEGIN_DATADESC( CFuncNavBlocker )
  32. // Inputs
  33. DEFINE_INPUTFUNC( FIELD_VOID, "BlockNav", InputBlockNav ),
  34. DEFINE_INPUTFUNC( FIELD_VOID, "UnblockNav", InputUnblockNav ),
  35. DEFINE_KEYFIELD( m_blockedTeamNumber, FIELD_INTEGER, "teamToBlock" ),
  36. DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
  37. END_DATADESC()
  38. LINK_ENTITY_TO_CLASS( func_nav_blocker, CFuncNavBlocker );
  39. CUtlLinkedList<CFuncNavBlocker *> CFuncNavBlocker::gm_NavBlockers;
  40. //-----------------------------------------------------------------------------------------------------
  41. int CFuncNavBlocker::DrawDebugTextOverlays( void )
  42. {
  43. int offset = BaseClass::DrawDebugTextOverlays();
  44. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  45. {
  46. CFmtStr str;
  47. // FIRST_GAME_TEAM skips TEAM_SPECTATOR and TEAM_UNASSIGNED, so we can print
  48. // useful team names in a non-game-specific fashion.
  49. for ( int i=FIRST_GAME_TEAM; i<FIRST_GAME_TEAM + MAX_NAV_TEAMS; ++i )
  50. {
  51. if ( IsBlockingNav( i ) )
  52. {
  53. CTeam *team = GetGlobalTeam( i );
  54. if ( team )
  55. {
  56. EntityText( offset++, str.sprintf( "blocking team %s", team->GetName() ), 0 );
  57. }
  58. else
  59. {
  60. EntityText( offset++, str.sprintf( "blocking team %d", i ), 0 );
  61. }
  62. }
  63. }
  64. NavAreaCollector collector( true );
  65. Extent extent;
  66. extent.Init( this );
  67. TheNavMesh->ForAllAreasOverlappingExtent( collector, extent );
  68. for ( int i=0; i<collector.m_area.Count(); ++i )
  69. {
  70. CNavArea *area = collector.m_area[i];
  71. Extent areaExtent;
  72. area->GetExtent( &areaExtent );
  73. debugoverlay->AddBoxOverlay( vec3_origin, areaExtent.lo, areaExtent.hi, vec3_angle, 0, 255, 0, 10, NDEBUG_PERSIST_TILL_NEXT_SERVER );
  74. }
  75. }
  76. return offset;
  77. }
  78. //--------------------------------------------------------------------------------------------------------
  79. void CFuncNavBlocker::UpdateBlocked()
  80. {
  81. NavAreaCollector collector( true );
  82. Extent extent;
  83. extent.Init( this );
  84. TheNavMesh->ForAllAreasOverlappingExtent( collector, extent );
  85. for ( int i=0; i<collector.m_area.Count(); ++i )
  86. {
  87. CNavArea *area = collector.m_area[i];
  88. area->UpdateBlocked( true );
  89. }
  90. }
  91. //--------------------------------------------------------------------------------------------------------
  92. // Forces nav areas to unblock when the nav blocker is deleted (round restart) so flow can compute properly
  93. void CFuncNavBlocker::UpdateOnRemove( void )
  94. {
  95. UnblockNav();
  96. gm_NavBlockers.FindAndRemove( this );
  97. BaseClass::UpdateOnRemove();
  98. }
  99. //--------------------------------------------------------------------------------------------------------
  100. void CFuncNavBlocker::Spawn( void )
  101. {
  102. gm_NavBlockers.AddToTail( this );
  103. if ( !m_blockedTeamNumber )
  104. m_blockedTeamNumber = TEAM_ANY;
  105. SetMoveType( MOVETYPE_NONE );
  106. SetModel( STRING( GetModelName() ) );
  107. AddEffects( EF_NODRAW );
  108. SetCollisionGroup( COLLISION_GROUP_NONE );
  109. SetSolid( SOLID_NONE );
  110. AddSolidFlags( FSOLID_NOT_SOLID );
  111. CollisionProp()->WorldSpaceAABB( &m_CachedMins, &m_CachedMaxs );
  112. if ( m_bDisabled )
  113. {
  114. UnblockNav();
  115. }
  116. else
  117. {
  118. BlockNav();
  119. }
  120. }
  121. //--------------------------------------------------------------------------------------------------------
  122. void CFuncNavBlocker::InputBlockNav( inputdata_t &inputdata )
  123. {
  124. BlockNav();
  125. }
  126. //--------------------------------------------------------------------------------------------------------
  127. void CFuncNavBlocker::InputUnblockNav( inputdata_t &inputdata )
  128. {
  129. UnblockNav();
  130. }
  131. //--------------------------------------------------------------------------------------------------------
  132. void CFuncNavBlocker::BlockNav( void )
  133. {
  134. if ( m_blockedTeamNumber == TEAM_ANY )
  135. {
  136. for ( int i=0; i<MAX_NAV_TEAMS; ++i )
  137. {
  138. m_isBlockingNav[ i ] = true;
  139. }
  140. }
  141. else
  142. {
  143. int teamNumber = m_blockedTeamNumber % MAX_NAV_TEAMS;
  144. m_isBlockingNav[ teamNumber ] = true;
  145. }
  146. Extent extent;
  147. extent.Init( this );
  148. TheNavMesh->ForAllAreasOverlappingExtent( *this, extent );
  149. UpdateBlocked();
  150. }
  151. //--------------------------------------------------------------------------------------------------------
  152. void CFuncNavBlocker::UnblockNav( void )
  153. {
  154. if ( m_blockedTeamNumber == TEAM_ANY )
  155. {
  156. for ( int i=0; i<MAX_NAV_TEAMS; ++i )
  157. {
  158. m_isBlockingNav[ i ] = false;
  159. }
  160. }
  161. else
  162. {
  163. int teamNumber = m_blockedTeamNumber % MAX_NAV_TEAMS;
  164. m_isBlockingNav[ teamNumber ] = false;
  165. }
  166. UpdateBlocked();
  167. }
  168. //--------------------------------------------------------------------------------------------------------
  169. // functor that blocks areas in our extent
  170. bool CFuncNavBlocker::operator()( CNavArea *area )
  171. {
  172. area->MarkAsBlocked( m_blockedTeamNumber, this );
  173. return true;
  174. }
  175. //--------------------------------------------------------------------------------------------------------
  176. bool CFuncNavBlocker::CalculateBlocked( bool *pResultByTeam, const Vector &vecMins, const Vector &vecMaxs )
  177. {
  178. int nTeamsBlocked = 0;
  179. int i;
  180. bool bBlocked = false;
  181. for ( i=0; i<MAX_NAV_TEAMS; ++i )
  182. {
  183. pResultByTeam[i] = false;
  184. }
  185. FOR_EACH_LL( gm_NavBlockers, iBlocker )
  186. {
  187. CFuncNavBlocker *pBlocker = gm_NavBlockers[iBlocker];
  188. bool bIsIntersecting = false;
  189. for ( i=0; i<MAX_NAV_TEAMS; ++i )
  190. {
  191. if ( pBlocker->m_isBlockingNav[i] )
  192. {
  193. if ( !pResultByTeam[i] )
  194. {
  195. if ( bIsIntersecting || ( bIsIntersecting = IsBoxIntersectingBox( pBlocker->m_CachedMins, pBlocker->m_CachedMaxs, vecMins, vecMaxs ) ) != false )
  196. {
  197. bBlocked = true;
  198. pResultByTeam[i] = true;
  199. nTeamsBlocked++;
  200. }
  201. else
  202. {
  203. continue;
  204. }
  205. }
  206. }
  207. }
  208. if ( nTeamsBlocked == MAX_NAV_TEAMS )
  209. {
  210. break;
  211. }
  212. }
  213. return bBlocked;
  214. }
  215. //-----------------------------------------------------------------------------------------------------
  216. /**
  217. * An entity that can obstruct nav areas. This is meant for semi-transient areas that obstruct
  218. * pathfinding but can be ignored for longer-term queries like computing L4D flow distances and
  219. * escape routes.
  220. */
  221. class CFuncNavObstruction : public CBaseEntity, public INavAvoidanceObstacle
  222. {
  223. DECLARE_DATADESC();
  224. DECLARE_CLASS( CFuncNavObstruction, CBaseEntity );
  225. public:
  226. void Spawn();
  227. virtual void UpdateOnRemove( void );
  228. void InputEnable( inputdata_t &inputdata );
  229. void InputDisable( inputdata_t &inputdata );
  230. virtual bool IsPotentiallyAbleToObstructNavAreas( void ) const { return true; } // could we at some future time obstruct nav?
  231. virtual float GetNavObstructionHeight( void ) const { return JumpCrouchHeight; } // height at which to obstruct nav areas
  232. virtual bool CanObstructNavAreas( void ) const { return !m_bDisabled; } // can we obstruct nav right this instant?
  233. virtual CBaseEntity *GetObstructingEntity( void ) { return this; }
  234. virtual void OnNavMeshLoaded( void )
  235. {
  236. if ( !m_bDisabled )
  237. {
  238. ObstructNavAreas();
  239. }
  240. }
  241. int DrawDebugTextOverlays( void );
  242. bool operator()( CNavArea *area ); // functor that obstructs areas in our extent
  243. private:
  244. void ObstructNavAreas( void );
  245. bool m_bDisabled;
  246. };
  247. //--------------------------------------------------------------------------------------------------------
  248. BEGIN_DATADESC( CFuncNavObstruction )
  249. DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
  250. END_DATADESC()
  251. LINK_ENTITY_TO_CLASS( func_nav_avoidance_obstacle, CFuncNavObstruction );
  252. //-----------------------------------------------------------------------------------------------------
  253. int CFuncNavObstruction::DrawDebugTextOverlays( void )
  254. {
  255. int offset = BaseClass::DrawDebugTextOverlays();
  256. if (m_debugOverlays & OVERLAY_TEXT_BIT)
  257. {
  258. if ( CanObstructNavAreas() )
  259. {
  260. EntityText( offset++, "Obstructing nav", NDEBUG_PERSIST_TILL_NEXT_SERVER );
  261. }
  262. else
  263. {
  264. EntityText( offset++, "Not obstructing nav", NDEBUG_PERSIST_TILL_NEXT_SERVER );
  265. }
  266. }
  267. return offset;
  268. }
  269. //--------------------------------------------------------------------------------------------------------
  270. void CFuncNavObstruction::UpdateOnRemove( void )
  271. {
  272. TheNavMesh->UnregisterAvoidanceObstacle( this );
  273. BaseClass::UpdateOnRemove();
  274. }
  275. //--------------------------------------------------------------------------------------------------------
  276. void CFuncNavObstruction::Spawn( void )
  277. {
  278. SetMoveType( MOVETYPE_NONE );
  279. SetModel( STRING( GetModelName() ) );
  280. AddEffects( EF_NODRAW );
  281. SetCollisionGroup( COLLISION_GROUP_NONE );
  282. SetSolid( SOLID_NONE );
  283. AddSolidFlags( FSOLID_NOT_SOLID );
  284. if ( !m_bDisabled )
  285. {
  286. ObstructNavAreas();
  287. TheNavMesh->RegisterAvoidanceObstacle( this );
  288. }
  289. }
  290. //--------------------------------------------------------------------------------------------------------
  291. void CFuncNavObstruction::InputEnable( inputdata_t &inputdata )
  292. {
  293. m_bDisabled = false;
  294. ObstructNavAreas();
  295. TheNavMesh->RegisterAvoidanceObstacle( this );
  296. }
  297. //--------------------------------------------------------------------------------------------------------
  298. void CFuncNavObstruction::InputDisable( inputdata_t &inputdata )
  299. {
  300. m_bDisabled = true;
  301. TheNavMesh->UnregisterAvoidanceObstacle( this );
  302. }
  303. //--------------------------------------------------------------------------------------------------------
  304. void CFuncNavObstruction::ObstructNavAreas( void )
  305. {
  306. Extent extent;
  307. extent.Init( this );
  308. TheNavMesh->ForAllAreasOverlappingExtent( *this, extent );
  309. }
  310. //--------------------------------------------------------------------------------------------------------
  311. // functor that blocks areas in our extent
  312. bool CFuncNavObstruction::operator()( CNavArea *area )
  313. {
  314. area->MarkObstacleToAvoid( GetNavObstructionHeight() );
  315. return true;
  316. }
  317. //--------------------------------------------------------------------------------------------------------------