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.

278 lines
8.0 KiB

  1. // NextBotUtil.h
  2. // Utilities for the NextBot system
  3. // Author: Michael Booth, May 2006
  4. //========= Copyright Valve Corporation, All rights reserved. ============//
  5. #ifndef _NEXT_BOT_UTIL_H_
  6. #define _NEXT_BOT_UTIL_H_
  7. #include "NextBotLocomotionInterface.h"
  8. #include "nav_area.h"
  9. #include "nav_mesh.h"
  10. #include "nav_pathfind.h"
  11. //--------------------------------------------------------------------------------------------
  12. /**
  13. * A simple filter interface for various NextBot queries
  14. */
  15. class INextBotEntityFilter
  16. {
  17. public:
  18. // return true if the given entity passes this filter
  19. virtual bool IsAllowed( CBaseEntity *entity ) const = 0;
  20. };
  21. // trace filter callback functions. needed for use with the querycache/optimization functionality
  22. bool VisionTraceFilterFunction( IHandleEntity *pServerEntity, int contentsMask );
  23. bool IgnoreActorsTraceFilterFunction( IHandleEntity *pServerEntity, int contentsMask );
  24. //--------------------------------------------------------------------------------------------
  25. /**
  26. * Trace filter that skips all players and NextBots
  27. */
  28. class NextBotTraceFilterIgnoreActors : public CTraceFilterSimple
  29. {
  30. public:
  31. NextBotTraceFilterIgnoreActors( const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple( passentity, collisionGroup, IgnoreActorsTraceFilterFunction )
  32. {
  33. }
  34. };
  35. //--------------------------------------------------------------------------------------------
  36. /**
  37. * Trace filter that skips all players, NextBots, and non-LOS blockers
  38. */
  39. class NextBotVisionTraceFilter : public CTraceFilterSimple
  40. {
  41. public:
  42. NextBotVisionTraceFilter( const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple( passentity, collisionGroup, VisionTraceFilterFunction )
  43. {
  44. }
  45. };
  46. //--------------------------------------------------------------------------------------------
  47. /**
  48. * Trace filter that skips all NextBots, but includes Players
  49. */
  50. class NextBotTraceFilterIgnoreNextBots : public CTraceFilterSimple
  51. {
  52. public:
  53. NextBotTraceFilterIgnoreNextBots( const IHandleEntity *passentity, int collisionGroup )
  54. : CTraceFilterSimple( passentity, collisionGroup )
  55. {
  56. }
  57. virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
  58. {
  59. if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
  60. {
  61. CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
  62. #ifdef TERROR
  63. CBasePlayer *player = ToBasePlayer( entity );
  64. if ( player && player->IsGhost() )
  65. return false;
  66. #endif // TERROR
  67. return ( entity->MyNextBotPointer() == NULL );
  68. }
  69. return false;
  70. }
  71. };
  72. //--------------------------------------------------------------------------------------------
  73. /**
  74. * Trace filter that obeys INextBot::IsAbleToBlockMovementOf()
  75. */
  76. class NextBotTraceFilter : public CTraceFilterSimple
  77. {
  78. public:
  79. NextBotTraceFilter( const IHandleEntity *passentity, int collisionGroup )
  80. : CTraceFilterSimple( passentity, collisionGroup )
  81. {
  82. CBaseEntity *entity = const_cast<CBaseEntity *>(EntityFromEntityHandle( passentity ));
  83. m_passBot = entity->MyNextBotPointer();
  84. }
  85. virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
  86. {
  87. if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
  88. {
  89. CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
  90. #ifdef TERROR
  91. CBasePlayer *player = ToBasePlayer( entity );
  92. if ( player && player->IsGhost() )
  93. return false;
  94. #endif // TERROR
  95. // Skip players on the same team - they're not solid to us, and we'll avoid them
  96. if ( entity->IsPlayer() && m_passBot && m_passBot->GetEntity() &&
  97. m_passBot->GetEntity()->GetTeamNumber() == entity->GetTeamNumber() )
  98. return false;
  99. INextBot *bot = entity->MyNextBotPointer();
  100. return ( !bot || bot->IsAbleToBlockMovementOf( m_passBot ) );
  101. }
  102. return false;
  103. }
  104. const INextBot *m_passBot;
  105. };
  106. //--------------------------------------------------------------------------------------------
  107. /**
  108. * Trace filter that only hits players and NextBots
  109. */
  110. class NextBotTraceFilterOnlyActors : public CTraceFilterSimple
  111. {
  112. public:
  113. NextBotTraceFilterOnlyActors( const IHandleEntity *passentity, int collisionGroup )
  114. : CTraceFilterSimple( passentity, collisionGroup )
  115. {
  116. }
  117. virtual TraceType_t GetTraceType() const
  118. {
  119. return TRACE_ENTITIES_ONLY;
  120. }
  121. virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
  122. {
  123. if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
  124. {
  125. CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
  126. #ifdef TERROR
  127. CBasePlayer *player = ToBasePlayer( entity );
  128. if ( player && player->IsGhost() )
  129. return false;
  130. #endif // TERROR
  131. return ( entity->MyNextBotPointer() || entity->IsPlayer() );
  132. }
  133. return false;
  134. }
  135. };
  136. //--------------------------------------------------------------------------------------------
  137. /**
  138. * Trace filter that skips "traversable" entities. The "when" argument creates
  139. * a temporal context for asking if an entity is IMMEDIATELY traversable (like thin
  140. * glass that just breaks as we walk through it) or EVENTUALLY traversable (like a
  141. * breakable object that will take some time to break through)
  142. */
  143. class NextBotTraversableTraceFilter : public CTraceFilterSimple
  144. {
  145. public:
  146. NextBotTraversableTraceFilter( INextBot *bot, ILocomotion::TraverseWhenType when = ILocomotion::EVENTUALLY ) : CTraceFilterSimple( bot->GetEntity(), COLLISION_GROUP_NONE )
  147. {
  148. m_bot = bot;
  149. m_when = when;
  150. }
  151. virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
  152. {
  153. CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
  154. if ( m_bot->IsSelf( entity ) )
  155. {
  156. return false;
  157. }
  158. if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
  159. {
  160. return !m_bot->GetLocomotionInterface()->IsEntityTraversable( entity, m_when );
  161. }
  162. return false;
  163. }
  164. private:
  165. INextBot *m_bot;
  166. ILocomotion::TraverseWhenType m_when;
  167. };
  168. //---------------------------------------------------------------------------------------------
  169. /**
  170. * Given a vector of entities, a nav area, and a max travel distance, return
  171. * the entity that has the shortest travel distance.
  172. */
  173. inline CBaseEntity *SelectClosestEntityByTravelDistance( INextBot *me, const CUtlVector< CBaseEntity * > &candidateEntities, CNavArea *startArea, float travelRange )
  174. {
  175. // collect nearby walkable areas within travelRange
  176. CUtlVector< CNavArea * > nearbyAreaVector;
  177. CollectSurroundingAreas( &nearbyAreaVector, startArea, travelRange, me->GetLocomotionInterface()->GetStepHeight(), me->GetLocomotionInterface()->GetDeathDropHeight() );
  178. // find closest entity in the collected area set
  179. CBaseEntity *closeEntity = NULL;
  180. float closeTravelRange = FLT_MAX;
  181. for( int i=0; i<candidateEntities.Count(); ++i )
  182. {
  183. CBaseEntity *candidate = candidateEntities[i];
  184. CNavArea *area = TheNavMesh->GetNearestNavArea( candidate, GETNAVAREA_CHECK_LOS, 500.0f );
  185. if ( area && area->IsMarked() && area->GetCostSoFar() < closeTravelRange )
  186. {
  187. closeEntity = candidate;
  188. closeTravelRange = area->GetCostSoFar();
  189. }
  190. }
  191. return closeEntity;
  192. }
  193. #ifdef OBSOLETE
  194. //--------------------------------------------------------------------------------------------
  195. /**
  196. * Trace filter that skips "traversable" entities, but hits other Actors.
  197. * Used for obstacle avoidance.
  198. */
  199. class NextBotMovementAvoidanceTraceFilter : public CTraceFilterSimple
  200. {
  201. public:
  202. NextBotMovementAvoidanceTraceFilter( INextBot *bot ) : CTraceFilterSimple( bot->GetEntity(), COLLISION_GROUP_NONE )
  203. {
  204. m_bot = bot;
  205. }
  206. virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
  207. {
  208. CBaseEntity *entity = EntityFromEntityHandle( pServerEntity );
  209. #ifdef TERROR
  210. CBasePlayer *player = ToBasePlayer( entity );
  211. if ( player && player->IsGhost() )
  212. return false;
  213. #endif // TERROR
  214. if ( m_bot->IsSelf( entity ) )
  215. {
  216. return false;
  217. }
  218. if ( CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ) )
  219. {
  220. return !m_bot->GetLocomotionInterface()->IsEntityTraversable( entity, ILocomotion::IMMEDIATELY );
  221. }
  222. return false;
  223. }
  224. private:
  225. INextBot *m_bot;
  226. };
  227. #endif
  228. #endif // _NEXT_BOT_UTIL_H_