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.

312 lines
8.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: "Force-field" obstacle avoidance & steering
  4. //
  5. // @Note (toml 06-18-02): Currently only controls direction. Ultimately could
  6. // also incorporate body facing (yaw), speed, and translational/rotational
  7. // acceleration.
  8. //
  9. // $NoKeywords: $
  10. //=============================================================================//
  11. #ifndef AI_MOVESOLVER_H
  12. #define AI_MOVESOLVER_H
  13. #if defined( _WIN32 )
  14. #pragma once
  15. #endif
  16. #include "utlvector.h"
  17. #include "ai_obstacle_type.h"
  18. //-----------------------------------------------------------------------------
  19. inline float NormalizeAngle( float angle )
  20. {
  21. if ( angle < 0.0 )
  22. angle += 360.0;
  23. else if ( angle >= 360.0 )
  24. angle -= 360.0;
  25. return angle;
  26. }
  27. //-----------------------------------------------------------------------------
  28. // ENUMERATIONS
  29. //-----------------------------------------------------------------------------
  30. //-----------------------------------------------------------------------------
  31. // STRUCTURES
  32. //-----------------------------------------------------------------------------
  33. //-------------------------------------
  34. // AI_Arc_t
  35. //
  36. // Purpose: Represents an arc.
  37. //
  38. //-------------------------------------
  39. struct AI_Arc_t
  40. {
  41. AI_Arc_t()
  42. : center( 0 ),
  43. span( 0 )
  44. {
  45. }
  46. // Set by center and span
  47. void Set( float newCenter, float newSpan );
  48. // Set by the right and left extremes (coordinates run counter clockwise)
  49. void SetByLimits( float yawRight, float yawLeft );
  50. // Center of the arc (as "yaw")
  51. float center;
  52. // Span of the arc (in degrees)
  53. float span;
  54. };
  55. //-------------------------------------
  56. // AI_MoveSuggestion_t
  57. //
  58. // Purpose: Suggests a possible move/avoidance, with a range of acceptable alternatives
  59. //
  60. // @Note (toml 06-20-02): this probably will eventually want to incorporate facing and
  61. // destination of the motivating goal.
  62. //
  63. //-------------------------------------
  64. enum AI_MoveSuggestionFlags_t
  65. {
  66. AIMS_FAVOR_LEFT = 0x01,
  67. AIMS_FAVOR_RIGHT = 0x02
  68. };
  69. //-----------------
  70. struct AI_MoveSuggestion_t
  71. {
  72. AI_MoveSuggestion_t();
  73. AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity = NULL );
  74. AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity = NULL );
  75. void Set( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity = NULL );
  76. void Set( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity = NULL );
  77. //---------------------------------
  78. // The kind of suggestion
  79. AI_MoveSuggType_t type;
  80. // The unadjusted weight of the suggestion [0..1], although [-1..1] within the solver
  81. float weight;
  82. // The desired direction to move/avoid
  83. AI_Arc_t arc;
  84. // The causing entity, if any
  85. EHANDLE hObstacleEntity;
  86. // Flags
  87. unsigned flags;
  88. };
  89. //-----------------
  90. typedef CUtlVector<AI_MoveSuggestion_t> CAI_MoveSuggestions;
  91. //-------------------------------------
  92. // AI_MoveSolution_t
  93. //
  94. // Purpose: The result of resolving suggestions
  95. //
  96. // @Note (toml 06-18-02): Currently, this is a very dopey little structure.
  97. // However, it will probably eventually incorporate much of the info
  98. // passed or calculated piecemeal between Move...() and Move...Execute()
  99. // functions. Once suggestions incorprate more information, the solution
  100. // may want to include a copy of the winning suggestion, so that the
  101. // caller need retain less state. If this is not the case, reduce it to just
  102. // a yaw.
  103. //
  104. //-------------------------------------
  105. struct AI_MoveSolution_t
  106. {
  107. AI_MoveSolution_t()
  108. : dir(0)
  109. {
  110. }
  111. // The direction to move
  112. float dir;
  113. };
  114. //-----------------------------------------------------------------------------
  115. // class CAI_MoveSolver
  116. //
  117. // Purpose: Given a set of precalculated "regulations" (typically negative),
  118. // and a set of instantaneous suggestions (usually positive)
  119. //-----------------------------------------------------------------------------
  120. class CAI_MoveSolver
  121. {
  122. public:
  123. CAI_MoveSolver();
  124. //---------------------------------
  125. // Purpose: A regulation is a suggestion that is kept around as a rule until
  126. // cleared. They are generally negative suggestions.
  127. //---------------------------------
  128. void AddRegulation( const AI_MoveSuggestion_t &suggestion );
  129. void AddRegulations( const AI_MoveSuggestion_t *pSuggestion, int nSuggestions );
  130. bool HaveRegulations() const;
  131. void ClearRegulations();
  132. //---------------------------------
  133. // Purpose: Solve the move, picking the best direction from a set of suggestions,
  134. // after applying the regulations
  135. //---------------------------------
  136. bool Solve( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions, AI_MoveSolution_t *pResult );
  137. bool Solve( const AI_MoveSuggestion_t &suggestion, AI_MoveSolution_t *pResult );
  138. //---------------------------------
  139. bool HaveRegulationForObstacle( CBaseEntity *pEntity);
  140. //---------------------------------
  141. // Visualization
  142. void VisualizeRegulations( const Vector& origin );
  143. private:
  144. enum
  145. {
  146. REGS_RESERVE = 8,
  147. };
  148. //---------------------------------
  149. void NormalizeSuggestions( AI_MoveSuggestion_t *pBegin, AI_MoveSuggestion_t *pEnd );
  150. //---------------------------------
  151. CAI_MoveSuggestions m_Regulations;
  152. };
  153. //-----------------------------------------------------------------------------
  154. // AI_Arc_t inline methods
  155. //-----------------------------------------------------------------------------
  156. inline void AI_Arc_t::Set( float newCenter, float newSpan )
  157. {
  158. center = NormalizeAngle( newCenter );
  159. span = NormalizeAngle( newSpan );
  160. }
  161. //-------------------------------------
  162. inline void AI_Arc_t::SetByLimits( float yawRight, float yawLeft )
  163. {
  164. // Yaw runs counter-clockwise
  165. span = yawLeft - yawRight;
  166. if ( span < 0 )
  167. span += 360;
  168. center = yawRight + span * 0.5;
  169. if ( center >= 360 )
  170. center -= 360;
  171. }
  172. //-----------------------------------------------------------------------------
  173. // AI_MoveSuggestion_t inline methods
  174. //-----------------------------------------------------------------------------
  175. inline void AI_MoveSuggestion_t::Set( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity )
  176. {
  177. type = newType;
  178. weight = newWeight;
  179. hObstacleEntity = pEntity;
  180. flags = 0;
  181. arc.Set( newDir, newSpan );
  182. }
  183. //-------------------------------------
  184. inline AI_MoveSuggestion_t::AI_MoveSuggestion_t()
  185. : type( AIMS_INVALID ),
  186. weight( 0 ),
  187. flags( 0 )
  188. {
  189. }
  190. //-------------------------------------
  191. inline AI_MoveSuggestion_t::AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity )
  192. {
  193. Set( newType, newWeight, newDir, newSpan, pEntity );
  194. }
  195. //-------------------------------------
  196. inline AI_MoveSuggestion_t::AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity )
  197. {
  198. Set( newType, newWeight, arc.center, arc.span, pEntity );
  199. }
  200. //-------------------------------------
  201. inline void AI_MoveSuggestion_t::Set( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity )
  202. {
  203. Set( newType, newWeight, arc.center, arc.span, pEntity );
  204. }
  205. //-----------------------------------------------------------------------------
  206. // CAI_MoveSolver inline methods
  207. //-----------------------------------------------------------------------------
  208. inline CAI_MoveSolver::CAI_MoveSolver()
  209. {
  210. m_Regulations.EnsureCapacity( REGS_RESERVE );
  211. }
  212. //-------------------------------------
  213. inline void CAI_MoveSolver::AddRegulation( const AI_MoveSuggestion_t &suggestion )
  214. {
  215. m_Regulations.AddToTail( suggestion );
  216. }
  217. //-------------------------------------
  218. inline void CAI_MoveSolver::AddRegulations( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions )
  219. {
  220. for (int i = 0; i < nSuggestions; ++i)
  221. {
  222. m_Regulations.AddToTail( pSuggestions[i] );
  223. }
  224. }
  225. //-------------------------------------
  226. inline bool CAI_MoveSolver::HaveRegulations() const
  227. {
  228. return (m_Regulations.Count() > 0);
  229. }
  230. //-------------------------------------
  231. inline void CAI_MoveSolver::ClearRegulations()
  232. {
  233. m_Regulations.RemoveAll();
  234. }
  235. //-------------------------------------
  236. inline bool CAI_MoveSolver::Solve( const AI_MoveSuggestion_t &suggestion, AI_MoveSolution_t *pResult)
  237. {
  238. return Solve( &suggestion, 1, pResult);
  239. }
  240. //=============================================================================
  241. #endif // AI_MOVESOLVER_H