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.

452 lines
9.4 KiB

  1. // FunctorUtils.h
  2. // Useful functors
  3. // Author: Michael Booth, August 2005, Copyright 2005 Turtle Rock Studios, Inc.
  4. #ifndef _FUNCTOR_UTILS_H_
  5. #define _FUNCTOR_UTILS_H_
  6. #ifdef SERVER_NEXT_BOTS
  7. #include "NextBotInterface.h"
  8. #include "NextBotManager.h"
  9. #else
  10. class INextBot;
  11. #endif
  12. //--------------------------------------------------------------------------------------------------------
  13. /**
  14. * NOTE: The functors in this file should ideally be game-independent,
  15. * and work for any Source based game
  16. */
  17. //--------------------------------------------------------------------------------------------------------
  18. //--------------------------------------------------------------------------------------------------------
  19. /**
  20. * Count the number of living players on a given team (or TEAM_ANY)
  21. */
  22. class LivePlayerCounter
  23. {
  24. public:
  25. static const bool EXCLUDE_BOTS = false;
  26. LivePlayerCounter( int team, bool includeBots = true )
  27. {
  28. m_team = team;
  29. m_includeBots = includeBots;
  30. m_count = 0;
  31. }
  32. bool operator() ( CBasePlayer *player )
  33. {
  34. if (player->IsAlive() && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
  35. {
  36. if (m_includeBots || !player->IsBot())
  37. {
  38. ++m_count;
  39. }
  40. }
  41. return true;
  42. }
  43. int GetCount( void ) const
  44. {
  45. return m_count;
  46. }
  47. int m_team;
  48. bool m_includeBots;
  49. int m_count;
  50. };
  51. //--------------------------------------------------------------------------------------------------------
  52. /**
  53. * Count the number of dead players on a given team (or TEAM_ANY)
  54. */
  55. class DeadPlayerCounter
  56. {
  57. public:
  58. static const bool EXCLUDE_BOTS = false;
  59. DeadPlayerCounter( int team, bool includeBots = true )
  60. {
  61. m_team = team;
  62. m_includeBots = includeBots;
  63. m_count = 0;
  64. }
  65. bool operator() ( CBasePlayer *player )
  66. {
  67. if (!player->IsAlive() && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
  68. {
  69. if (m_includeBots || !player->IsBot())
  70. {
  71. ++m_count;
  72. }
  73. }
  74. return true;
  75. }
  76. int GetCount( void ) const
  77. {
  78. return m_count;
  79. }
  80. int m_team;
  81. bool m_includeBots;
  82. int m_count;
  83. };
  84. //--------------------------------------------------------------------------------------------------------
  85. /**
  86. * Count the number of players on a given team (or TEAM_ANY)
  87. */
  88. class PlayerCounter
  89. {
  90. public:
  91. static const bool EXCLUDE_BOTS = false;
  92. PlayerCounter( int team, int lifeState = -1, bool includeBots = true )
  93. {
  94. m_team = team;
  95. m_includeBots = includeBots;
  96. m_count = 0;
  97. m_lifeState = lifeState;
  98. }
  99. bool operator() ( CBasePlayer *player )
  100. {
  101. if ((player->m_lifeState == m_lifeState || m_lifeState == -1) && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
  102. {
  103. if (m_includeBots || !player->IsBot())
  104. {
  105. ++m_count;
  106. }
  107. }
  108. return true;
  109. }
  110. int GetCount( void ) const
  111. {
  112. return m_count;
  113. }
  114. int m_lifeState;
  115. int m_team;
  116. bool m_includeBots;
  117. int m_count;
  118. };
  119. //--------------------------------------------------------------------------------------------------------
  120. /**
  121. * Return the closest living player on the given team (or TEAM_ANY)
  122. */
  123. class ClosestPlayerScan
  124. {
  125. public:
  126. static const bool EXCLUDE_BOTS = false;
  127. ClosestPlayerScan( const Vector &spot, int team, float maxRange = 0.0f, CBasePlayer *ignore = NULL, bool includeBots = true )
  128. {
  129. m_spot = spot;
  130. m_team = team;
  131. m_includeBots = includeBots;
  132. m_close = NULL;
  133. if ( maxRange > 0.0f )
  134. {
  135. m_closeRangeSq = maxRange * maxRange;
  136. }
  137. else
  138. {
  139. m_closeRangeSq = 999999999.9f;
  140. }
  141. m_ignore = ignore;
  142. }
  143. bool operator() ( CBasePlayer *player )
  144. {
  145. if (player == m_ignore)
  146. return true;
  147. if (player->IsAlive() && (m_team == TEAM_ANY || player->GetTeamNumber() == m_team))
  148. {
  149. if ( !m_includeBots && player->IsBot() )
  150. return true;
  151. Vector to = player->WorldSpaceCenter() - m_spot;
  152. float rangeSq = to.LengthSqr();
  153. if (rangeSq < m_closeRangeSq)
  154. {
  155. m_closeRangeSq = rangeSq;
  156. m_close = player;
  157. }
  158. }
  159. return true;
  160. }
  161. CBasePlayer *GetPlayer( void ) const
  162. {
  163. return m_close;
  164. }
  165. bool IsCloserThan( float range )
  166. {
  167. return (m_closeRangeSq < (range * range));
  168. }
  169. bool IsFartherThan( float range )
  170. {
  171. return (m_closeRangeSq > (range * range));
  172. }
  173. Vector m_spot;
  174. int m_team;
  175. bool m_includeBots;
  176. CBasePlayer *m_close;
  177. float m_closeRangeSq;
  178. CBasePlayer *m_ignore;
  179. };
  180. //--------------------------------------------------------------------------------------------------------
  181. /**
  182. * Return the closest living BaseCombatCharacter on the given team (or TEAM_ANY)
  183. */
  184. class ClosestActorScan
  185. {
  186. public:
  187. ClosestActorScan( const Vector &spot, int team, float maxRange = 0.0f, CBaseCombatCharacter *ignore = NULL )
  188. {
  189. m_spot = spot;
  190. m_team = team;
  191. m_close = NULL;
  192. if ( maxRange > 0.0f )
  193. {
  194. m_closeRangeSq = maxRange * maxRange;
  195. }
  196. else
  197. {
  198. m_closeRangeSq = 999999999.9f;
  199. }
  200. m_ignore = ignore;
  201. }
  202. bool operator() ( CBaseCombatCharacter *actor )
  203. {
  204. if (actor == m_ignore)
  205. return true;
  206. if (actor->IsAlive() && (m_team == TEAM_ANY || actor->GetTeamNumber() == m_team))
  207. {
  208. Vector to = actor->WorldSpaceCenter() - m_spot;
  209. float rangeSq = to.LengthSqr();
  210. if (rangeSq < m_closeRangeSq)
  211. {
  212. m_closeRangeSq = rangeSq;
  213. m_close = actor;
  214. }
  215. }
  216. return true;
  217. }
  218. CBaseCombatCharacter *GetClosestActor( void ) const
  219. {
  220. return m_close;
  221. }
  222. bool IsClosestActorCloserThan( float range )
  223. {
  224. return (m_closeRangeSq < (range * range));
  225. }
  226. bool IsClosestActorFartherThan( float range )
  227. {
  228. return (m_closeRangeSq > (range * range));
  229. }
  230. Vector m_spot;
  231. int m_team;
  232. CBaseCombatCharacter *m_close;
  233. float m_closeRangeSq;
  234. CBaseCombatCharacter *m_ignore;
  235. };
  236. //--------------------------------------------------------------------------------------------------------
  237. class CShowViewportPanel
  238. {
  239. int m_team;
  240. const char *m_panelName;
  241. bool m_show;
  242. KeyValues *m_data;
  243. public:
  244. CShowViewportPanel( int team, const char *panelName, bool show, KeyValues *data = NULL )
  245. {
  246. m_team = team;
  247. m_panelName = panelName;
  248. m_show = show;
  249. m_data = data;
  250. }
  251. bool operator() ( CBasePlayer *player )
  252. {
  253. if ( m_team != TEAM_ANY && m_team != player->GetTeamNumber() )
  254. return true;
  255. player->ShowViewPortPanel( m_panelName, m_show, m_data );
  256. return true;
  257. }
  258. };
  259. //--------------------------------------------------------------------------------------------------------------
  260. /**
  261. * Iterate each "actor" in the game, where an actor is a Player or NextBot
  262. */
  263. template < typename Functor >
  264. inline bool ForEachActor( Functor &func )
  265. {
  266. // iterate all non-bot players
  267. for( int i=1; i<=gpGlobals->maxClients; ++i )
  268. {
  269. CBasePlayer *player = UTIL_PlayerByIndex( i );
  270. if ( player == NULL )
  271. continue;
  272. if ( FNullEnt( player->edict() ) )
  273. continue;
  274. if ( !player->IsPlayer() )
  275. continue;
  276. if ( !player->IsConnected() )
  277. continue;
  278. #ifdef SERVER_NEXT_BOTS
  279. // skip bots - ForEachCombatCharacter will catch them
  280. INextBot *bot = player->MyNextBotPointer();
  281. if ( bot )
  282. {
  283. continue;
  284. }
  285. #endif
  286. if ( func( player ) == false )
  287. {
  288. return false;
  289. }
  290. }
  291. #ifdef SERVER_NEXT_BOTS
  292. // iterate all NextBots
  293. return TheNextBots().ForEachCombatCharacter( func );
  294. #else
  295. return true;
  296. #endif
  297. }
  298. //--------------------------------------------------------------------------------------------------------------
  299. /**
  300. * The interface for functors for use with ForEachActor() that
  301. * want notification before iteration starts and after interation
  302. * is complete (successful or not).
  303. */
  304. class IActorFunctor
  305. {
  306. public:
  307. virtual void OnBeginIteration( void ) { } // invoked once before iteration begins
  308. virtual bool operator() ( CBaseCombatCharacter *them ) = 0;
  309. virtual void OnEndIteration( bool allElementsIterated ) { } // invoked once after iteration is complete whether successful or not
  310. };
  311. //--------------------------------------------------------------------------------------------------------------
  312. /**
  313. * Iterate each "actor" in the game, where an actor is a Player or NextBot
  314. * Template specialization for IActorFunctors.
  315. */
  316. template <>
  317. inline bool ForEachActor( IActorFunctor &func )
  318. {
  319. func.OnBeginIteration();
  320. bool isComplete = true;
  321. // iterate all non-bot players
  322. for( int i=1; i<=gpGlobals->maxClients; ++i )
  323. {
  324. CBasePlayer *player = UTIL_PlayerByIndex( i );
  325. if ( player == NULL )
  326. continue;
  327. if ( FNullEnt( player->edict() ) )
  328. continue;
  329. if ( !player->IsPlayer() )
  330. continue;
  331. if ( !player->IsConnected() )
  332. continue;
  333. #ifdef SERVER_NEXT_BOTS
  334. // skip bots - ForEachCombatCharacter will catch them
  335. INextBot *bot = dynamic_cast< INextBot * >( player );
  336. if ( bot )
  337. {
  338. continue;
  339. }
  340. #endif
  341. if ( func( player ) == false )
  342. {
  343. isComplete = false;
  344. break;
  345. }
  346. }
  347. #ifdef SERVER_NEXT_BOTS
  348. if ( !isComplete )
  349. {
  350. // iterate all NextBots
  351. isComplete = TheNextBots().ForEachCombatCharacter( func );
  352. }
  353. #endif
  354. func.OnEndIteration( isComplete );
  355. return isComplete;
  356. }
  357. //--------------------------------------------------------------------------------------------------------
  358. class CTraceFilterOnlyClassname : public CTraceFilterSimple
  359. {
  360. public:
  361. CTraceFilterOnlyClassname( const IHandleEntity *passentity, const char *pchClassname, int collisionGroup ) :
  362. CTraceFilterSimple( passentity, collisionGroup ), m_pchClassname( pchClassname )
  363. {
  364. }
  365. virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
  366. {
  367. CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
  368. if ( !pEntity )
  369. return false;
  370. return FClassnameIs( pEntity, m_pchClassname ) && CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
  371. }
  372. private:
  373. const char *m_pchClassname;
  374. };
  375. #endif // _FUNCTOR_UTILS_H_