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.

2152 lines
79 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. //
  8. // Author: Michael S. Booth ([email protected]), 2003
  9. //
  10. // NOTE: The CS Bot code uses Doxygen-style comments. If you run Doxygen over this code, it will
  11. // auto-generate documentation. Visit www.doxygen.org to download the system for free.
  12. //
  13. #ifndef _CS_BOT_H_
  14. #define _CS_BOT_H_
  15. #ifdef _GAMECONSOLE
  16. #define OPT_VIS_CSGO
  17. #endif
  18. #include "bot/bot.h"
  19. #include "bot/cs_bot_manager.h"
  20. #include "bot/cs_bot_chatter.h"
  21. #include "cs_gamestate.h"
  22. #include "cs_player.h"
  23. #include "weapon_csbase.h"
  24. #include "cs_nav_pathfind.h"
  25. #include "cs_nav_area.h"
  26. class CBaseDoor;
  27. class CBasePropDoor;
  28. class CCSBot;
  29. class CPushAwayEnumerator;
  30. //--------------------------------------------------------------------------------------------------------------
  31. /**
  32. * For use with player->m_rgpPlayerItems[]
  33. */
  34. enum InventorySlotType
  35. {
  36. PRIMARY_WEAPON_SLOT = 1,
  37. PISTOL_SLOT,
  38. KNIFE_SLOT,
  39. GRENADE_SLOT,
  40. C4_SLOT
  41. };
  42. //--------------------------------------------------------------------------------------------------------------
  43. /**
  44. * The definition of a bot's behavior state. One or more finite state machines
  45. * using these states implement a bot's behaviors.
  46. */
  47. class BotState
  48. {
  49. public:
  50. virtual void OnEnter( CCSBot *bot ) { } ///< when state is entered
  51. virtual void OnUpdate( CCSBot *bot ) { } ///< state behavior
  52. virtual void OnExit( CCSBot *bot ) { } ///< when state exited
  53. virtual const char *GetName( void ) const = 0; ///< return state name
  54. };
  55. //--------------------------------------------------------------------------------------------------------------
  56. /**
  57. * The state is invoked when a bot has nothing to do, or has finished what it was doing.
  58. * A bot never stays in this state - it is the main action selection mechanism.
  59. */
  60. class IdleState : public BotState
  61. {
  62. public:
  63. virtual void OnEnter( CCSBot *bot );
  64. virtual void OnUpdate( CCSBot *bot );
  65. virtual const char *GetName( void ) const { return "Idle"; }
  66. void UpdateCoop( CCSBot *bot );
  67. };
  68. //--------------------------------------------------------------------------------------------------------------
  69. /**
  70. * When a bot is actively searching for an enemy.
  71. */
  72. class HuntState : public BotState
  73. {
  74. public:
  75. virtual void OnEnter( CCSBot *bot );
  76. virtual void OnUpdate( CCSBot *bot );
  77. virtual void OnExit( CCSBot *bot );
  78. virtual const char *GetName( void ) const { return "Hunt"; }
  79. void ClearHuntArea( void ) { m_huntArea = NULL; }
  80. private:
  81. CNavArea *m_huntArea; ///< "far away" area we are moving to
  82. };
  83. //--------------------------------------------------------------------------------------------------------------
  84. /**
  85. * When a bot has an enemy and is attempting to kill it
  86. */
  87. class AttackState : public BotState
  88. {
  89. public:
  90. virtual void OnEnter( CCSBot *bot );
  91. virtual void OnUpdate( CCSBot *bot );
  92. virtual void OnExit( CCSBot *bot );
  93. virtual const char *GetName( void ) const { return "Attack"; }
  94. void SetCrouchAndHold( bool crouch ) { m_crouchAndHold = crouch; }
  95. protected:
  96. enum DodgeStateType
  97. {
  98. STEADY_ON,
  99. SLIDE_LEFT,
  100. SLIDE_RIGHT,
  101. JUMP,
  102. NUM_ATTACK_STATES
  103. };
  104. DodgeStateType m_dodgeState;
  105. float m_nextDodgeStateTimestamp;
  106. CountdownTimer m_repathTimer;
  107. float m_scopeTimestamp;
  108. bool m_haveSeenEnemy; ///< false if we haven't yet seen the enemy since we started this attack (told by a friend, etc)
  109. bool m_isEnemyHidden; ///< true we if we have lost line-of-sight to our enemy
  110. float m_reacquireTimestamp; ///< time when we can fire again, after losing enemy behind cover
  111. float m_shieldToggleTimestamp; ///< time to toggle shield deploy state
  112. bool m_shieldForceOpen; ///< if true, open up and shoot even if in danger
  113. float m_pinnedDownTimestamp; ///< time when we'll consider ourselves "pinned down" by the enemy
  114. bool m_crouchAndHold;
  115. bool m_didAmbushCheck;
  116. bool m_shouldDodge;
  117. bool m_firstDodge;
  118. bool m_isCoward; ///< if true, we'll retreat if outnumbered during this fight
  119. CountdownTimer m_retreatTimer;
  120. void StopAttacking( CCSBot *bot );
  121. void Dodge( CCSBot *bot ); ///< do dodge behavior
  122. };
  123. //--------------------------------------------------------------------------------------------------------------
  124. /**
  125. * When a bot has heard an enemy noise and is moving to find out what it was.
  126. */
  127. class InvestigateNoiseState : public BotState
  128. {
  129. public:
  130. virtual void OnEnter( CCSBot *bot );
  131. virtual void OnUpdate( CCSBot *bot );
  132. virtual void OnExit( CCSBot *bot );
  133. virtual const char *GetName( void ) const { return "InvestigateNoise"; }
  134. private:
  135. void AttendCurrentNoise( CCSBot *bot ); ///< move towards currently heard noise
  136. Vector m_checkNoisePosition; ///< the position of the noise we're investigating
  137. CountdownTimer m_minTimer; ///< minimum time we will investigate our current noise
  138. };
  139. //--------------------------------------------------------------------------------------------------------------
  140. /**
  141. * When a bot is buying equipment at the start of a round.
  142. */
  143. class BuyState : public BotState
  144. {
  145. public:
  146. virtual void OnEnter( CCSBot *bot );
  147. virtual void OnUpdate( CCSBot *bot );
  148. virtual void OnExit( CCSBot *bot );
  149. virtual const char *GetName( void ) const { return "Buy"; }
  150. private:
  151. bool m_isInitialDelay;
  152. int m_prefRetries; ///< for retrying buying preferred weapon at current index
  153. int m_prefIndex; ///< where are we in our list of preferred weapons
  154. int m_retries;
  155. bool m_doneBuying;
  156. bool m_buyDefuseKit;
  157. bool m_buyGrenade;
  158. bool m_buyShield;
  159. bool m_buyPistol;
  160. };
  161. //--------------------------------------------------------------------------------------------------------------
  162. /**
  163. * When a bot is moving to a potentially far away position in the world.
  164. */
  165. class MoveToState : public BotState
  166. {
  167. public:
  168. virtual void OnEnter( CCSBot *bot );
  169. virtual void OnUpdate( CCSBot *bot );
  170. virtual void OnExit( CCSBot *bot );
  171. virtual const char *GetName( void ) const { return "MoveTo"; }
  172. void SetGoalPosition( const Vector &pos ) { m_goalPosition = pos; }
  173. void SetRouteType( RouteType route ) { m_routeType = route; }
  174. private:
  175. Vector m_goalPosition; ///< goal position of move
  176. RouteType m_routeType; ///< the kind of route to build
  177. bool m_radioedPlan;
  178. bool m_askedForCover;
  179. };
  180. //--------------------------------------------------------------------------------------------------------------
  181. /**
  182. * When a Terrorist bot is moving to pick up a dropped bomb.
  183. */
  184. class FetchBombState : public BotState
  185. {
  186. public:
  187. virtual void OnEnter( CCSBot *bot );
  188. virtual void OnUpdate( CCSBot *bot );
  189. virtual const char *GetName( void ) const { return "FetchBomb"; }
  190. };
  191. //--------------------------------------------------------------------------------------------------------------
  192. /**
  193. * When a Terrorist bot is actually planting the bomb.
  194. */
  195. class PlantBombState : public BotState
  196. {
  197. public:
  198. virtual void OnEnter( CCSBot *bot );
  199. virtual void OnUpdate( CCSBot *bot );
  200. virtual void OnExit( CCSBot *bot );
  201. virtual const char *GetName( void ) const { return "PlantBomb"; }
  202. };
  203. //--------------------------------------------------------------------------------------------------------------
  204. /**
  205. * When a CT bot is actually defusing a live bomb.
  206. */
  207. class DefuseBombState : public BotState
  208. {
  209. public:
  210. virtual void OnEnter( CCSBot *bot );
  211. virtual void OnUpdate( CCSBot *bot );
  212. virtual void OnExit( CCSBot *bot );
  213. virtual const char *GetName( void ) const { return "DefuseBomb"; }
  214. };
  215. //--------------------------------------------------------------------------------------------------------------
  216. /**
  217. * When a CT bot is picking up a hostage
  218. */
  219. class PickupHostageState : public BotState
  220. {
  221. public:
  222. virtual void OnEnter( CCSBot *bot );
  223. virtual void OnUpdate( CCSBot *bot );
  224. virtual void OnExit( CCSBot *bot );
  225. virtual const char *GetName( void ) const { return "PickupHostage"; }
  226. void SetEntity( CBaseEntity *entity ) { m_entity = entity; }
  227. private:
  228. EHANDLE m_entity;
  229. };
  230. //--------------------------------------------------------------------------------------------------------------
  231. /**
  232. * When a bot is hiding in a corner.
  233. * NOTE: This state also includes MOVING TO that hiding spot, which may be all the way
  234. * across the map!
  235. */
  236. class HideState : public BotState
  237. {
  238. public:
  239. virtual void OnEnter( CCSBot *bot );
  240. virtual void OnUpdate( CCSBot *bot );
  241. virtual void OnExit( CCSBot *bot );
  242. virtual const char *GetName( void ) const { return "Hide"; }
  243. void SetHidingSpot( const Vector &pos ) { m_hidingSpot = pos; }
  244. const Vector &GetHidingSpot( void ) const { return m_hidingSpot; }
  245. void SetSearchArea( CNavArea *area ) { m_searchFromArea = area; }
  246. void SetSearchRange( float range ) { m_range = range; }
  247. void SetDuration( float time ) { m_duration = time; }
  248. void SetHoldPosition( bool hold ) { m_isHoldingPosition = hold; }
  249. bool IsAtSpot( void ) const { return m_isAtSpot; }
  250. float GetHideTime( void ) const
  251. {
  252. if (IsAtSpot())
  253. {
  254. return m_duration - m_hideTimer.GetRemainingTime();
  255. }
  256. return 0.0f;
  257. }
  258. private:
  259. CNavArea *m_searchFromArea;
  260. float m_range;
  261. Vector m_hidingSpot;
  262. bool m_isLookingOutward;
  263. bool m_isAtSpot;
  264. float m_duration;
  265. CountdownTimer m_hideTimer; ///< how long to hide
  266. bool m_isHoldingPosition;
  267. float m_holdPositionTime; ///< how long to hold our position after we hear nearby enemy noise
  268. bool m_heardEnemy; ///< set to true when we first hear an enemy
  269. float m_firstHeardEnemyTime; ///< when we first heard the enemy
  270. int m_retry; ///< counter for retrying hiding spot
  271. Vector m_leaderAnchorPos; ///< the position of our follow leader when we decided to hide
  272. bool m_isPaused; ///< if true, we have paused in our retreat for a moment
  273. CountdownTimer m_pauseTimer; ///< for stoppping and starting our pauses while we retreat
  274. };
  275. //--------------------------------------------------------------------------------------------------------------
  276. /**
  277. * When a bot is attempting to flee from a bomb that is about to explode.
  278. */
  279. class EscapeFromBombState : public BotState
  280. {
  281. public:
  282. virtual void OnEnter( CCSBot *bot );
  283. virtual void OnUpdate( CCSBot *bot );
  284. virtual void OnExit( CCSBot *bot );
  285. virtual const char *GetName( void ) const { return "EscapeFromBomb"; }
  286. };
  287. //--------------------------------------------------------------------------------------------------------------
  288. /**
  289. * When a bot is following another player.
  290. */
  291. class FollowState : public BotState
  292. {
  293. public:
  294. virtual void OnEnter( CCSBot *bot );
  295. virtual void OnUpdate( CCSBot *bot );
  296. virtual void OnExit( CCSBot *bot );
  297. virtual const char *GetName( void ) const { return "Follow"; }
  298. void SetLeader( CCSPlayer *player ) { m_leader = player; }
  299. private:
  300. CHandle< CCSPlayer > m_leader; ///< the player we are following
  301. Vector m_lastLeaderPos; ///< where the leader was when we computed our follow path
  302. bool m_isStopped;
  303. float m_stoppedTimestamp;
  304. enum LeaderMotionStateType
  305. {
  306. INVALID,
  307. STOPPED,
  308. WALKING,
  309. RUNNING
  310. };
  311. LeaderMotionStateType m_leaderMotionState;
  312. IntervalTimer m_leaderMotionStateTime;
  313. bool m_isSneaking;
  314. float m_lastSawLeaderTime;
  315. CountdownTimer m_repathInterval;
  316. IntervalTimer m_walkTime;
  317. bool m_isAtWalkSpeed;
  318. float m_waitTime;
  319. CountdownTimer m_idleTimer;
  320. void ComputeLeaderMotionState( float leaderSpeed );
  321. };
  322. //--------------------------------------------------------------------------------------------------------------
  323. /**
  324. * When a bot is actually using another entity (ie: facing towards it and pressing the use key)
  325. */
  326. class UseEntityState : public BotState
  327. {
  328. public:
  329. virtual void OnEnter( CCSBot *bot );
  330. virtual void OnUpdate( CCSBot *bot );
  331. virtual void OnExit( CCSBot *bot );
  332. virtual const char *GetName( void ) const { return "UseEntity"; }
  333. void SetEntity( CBaseEntity *entity ) { m_entity = entity; }
  334. private:
  335. EHANDLE m_entity; ///< the entity we will use
  336. };
  337. //--------------------------------------------------------------------------------------------------------------
  338. /**
  339. * When a bot is opening a door
  340. */
  341. class OpenDoorState : public BotState
  342. {
  343. public:
  344. virtual void OnEnter( CCSBot *bot );
  345. virtual void OnUpdate( CCSBot *bot );
  346. virtual void OnExit( CCSBot *bot );
  347. virtual const char *GetName( void ) const { return "OpenDoor"; }
  348. void SetDoor( CBaseEntity *door );
  349. bool IsDone( void ) const { return m_isDone; } ///< return true if behavior is done
  350. private:
  351. CHandle< CBaseDoor > m_funcDoor; ///< the func_door we are opening
  352. CHandle< CBasePropDoor > m_propDoor; ///< the prop_door we are opening
  353. bool m_isDone;
  354. CountdownTimer m_timeout;
  355. };
  356. //--------------------------------------------------------------------------------------------------------------
  357. /**
  358. * When a bot is attempting to escape from a field of flames (probably from a Molotov)
  359. */
  360. class EscapeFromFlamesState : public BotState
  361. {
  362. public:
  363. virtual void OnEnter( CCSBot *bot );
  364. virtual void OnUpdate( CCSBot *bot );
  365. virtual void OnExit( CCSBot *bot );
  366. virtual const char *GetName( void ) const { return "EscapeFromFlames"; }
  367. private:
  368. CNavArea *FindNearestNonDamagingArea( CCSBot *bot ) const;
  369. CountdownTimer m_searchTimer;
  370. CNavArea *m_safeArea;
  371. };
  372. //--------------------------------------------------------------------------------------------------------------
  373. //--------------------------------------------------------------------------------------------------------------
  374. /**
  375. * The Counter-strike Bot
  376. */
  377. class CCSBot : public CBot< CCSPlayer >
  378. {
  379. public:
  380. DECLARE_CLASS( CCSBot, CBot< CCSPlayer > );
  381. DECLARE_DATADESC();
  382. CCSBot( void ); ///< constructor initializes all values to zero
  383. virtual ~CCSBot();
  384. virtual bool Initialize( const BotProfile *profile, int team ); ///< (EXTEND) prepare bot for action
  385. virtual void CoopInitialize( void ); // initialize for Coop missions
  386. virtual void Spawn( void ); ///< (EXTEND) spawn the bot into the game
  387. virtual void Touch( CBaseEntity *other ); ///< (EXTEND) when touched by another entity
  388. virtual void Upkeep( void ); ///< lightweight maintenance, invoked frequently
  389. virtual void Update( void ); ///< heavyweight algorithms, invoked less often
  390. virtual void BuildUserCmd( CUserCmd& cmd, const QAngle& viewangles, float forwardmove, float sidemove, float upmove, int buttons, byte impulse );
  391. virtual void AvoidPlayers( CUserCmd *pCmd ); ///< some game types allow players to pass through each other, this method pushes them apart
  392. virtual float GetMoveSpeed( void ); ///< returns current movement speed (for walk/run)
  393. virtual void Walk( void );
  394. virtual bool Jump( bool mustJump = false ); ///< returns true if jump was started
  395. //- behavior properties ------------------------------------------------------------------------------------------
  396. float GetCombatRange( void ) const;
  397. bool IsRogue( void ) const; ///< return true if we dont listen to teammates or pursue scenario goals
  398. void SetRogue( bool rogue );
  399. bool IsHurrying( void ) const; ///< return true if we are in a hurry
  400. void Hurry( float duration ); ///< force bot to hurry
  401. bool IsSafe( void ) const; ///< return true if we are in a safe region
  402. bool IsWellPastSafe( void ) const; ///< return true if it is well past the early, "safe", part of the round
  403. bool IsEndOfSafeTime( void ) const; ///< return true if we were in the safe time last update, but not now
  404. float GetSafeTimeRemaining( void ) const; ///< return the amount of "safe time" we have left
  405. float GetSafeTime( void ) const; ///< return what we think the total "safe time" for this map is
  406. virtual void Blind( float holdTime, float fadeTime, float startingAlpha = 255 ); // player blinded by a flashbang
  407. bool IsUnhealthy( void ) const; ///< returns true if bot is low on health
  408. bool IsAlert( void ) const; ///< return true if bot is in heightened "alert" mode
  409. void BecomeAlert( void ); ///< bot becomes "alert" for immediately nearby enemies
  410. bool IsSneaking( void ) const; ///< return true if bot is sneaking
  411. void Sneak( float duration ); ///< sneak for given duration
  412. //- behaviors ---------------------------------------------------------------------------------------------------
  413. void Idle( void );
  414. bool IsIdling( void ) const;
  415. void Hide( CNavArea *searchFromArea = NULL, float duration = -1.0f, float hideRange = 750.0f, bool holdPosition = false ); ///< DEPRECATED: Use TryToHide() instead
  416. #define USE_NEAREST true
  417. bool TryToHide( CNavArea *searchFromArea = NULL, float duration = -1.0f, float hideRange = 750.0f, bool holdPosition = false, bool useNearest = false, const Vector *pStartPosOverride = NULL ); ///< try to hide nearby, return false if cannot
  418. void Hide( const Vector &hidingSpot, float duration = -1.0f, bool holdPosition = false ); ///< move to the given hiding place
  419. bool IsHiding( void ) const; ///< returns true if bot is currently hiding
  420. bool IsAtHidingSpot( void ) const; ///< return true if we are hiding and at our hiding spot
  421. float GetHidingTime( void ) const; ///< return number of seconds we have been at our current hiding spot
  422. bool MoveToInitialEncounter( void ); ///< move to a hiding spot and wait for initial encounter with enemy team (return false if no spots are available)
  423. bool TryToRetreat( float maxRange = 1000.0f, float duration = -1.0f ); ///< retreat to a nearby hiding spot, away from enemies
  424. void Hunt( void );
  425. bool IsHunting( void ) const; ///< returns true if bot is currently hunting
  426. void Attack( CCSPlayer *victim );
  427. void FireWeaponAtEnemy( void ); ///< fire our active weapon towards our current enemy
  428. void StopAttacking( void );
  429. bool IsAttacking( void ) const; ///< returns true if bot is currently engaging a target
  430. void MoveTo( const Vector &pos, RouteType route = SAFEST_ROUTE ); ///< move to potentially distant position
  431. bool IsMovingTo( void ) const; ///< return true if we are in the MoveTo state
  432. void PlantBomb( void );
  433. void FetchBomb( void ); ///< bomb has been dropped - go get it
  434. bool NoticeLooseBomb( void ) const; ///< return true if we noticed the bomb on the ground or on radar
  435. bool CanSeeLooseBomb( void ) const; ///< return true if we directly see the loose bomb
  436. void DefuseBomb( void );
  437. void PickupHostage( CBaseEntity *entity );
  438. bool IsPickingupHostage( void ) const;
  439. bool IsDefusingBomb( void ) const; ///< returns true if bot is currently defusing the bomb
  440. bool CanSeePlantedBomb( void ) const; ///< return true if we directly see the planted bomb
  441. void EscapeFromBomb( void );
  442. bool IsEscapingFromBomb( void ) const; ///< return true if we are escaping from the bomb
  443. void EscapeFromFlames( void );
  444. bool IsEscapingFromFlames( void ) const; ///< return true if we are escaping from a field of flames
  445. void RescueHostages( void ); ///< begin process of rescuing hostages
  446. void UseEntity( CBaseEntity *entity ); ///< use the entity
  447. void OpenDoor( CBaseEntity *door ); ///< open the door (assumes we are right in front of it)
  448. bool IsOpeningDoor( void ) const; ///< return true if we are in the process of opening a door
  449. void Buy( void ); ///< enter the buy state
  450. bool IsBuying( void ) const;
  451. void Panic( void ); ///< look around in panic
  452. bool IsPanicking( void ) const; ///< return true if bot is panicked
  453. void StopPanicking( void ); ///< end our panic
  454. void UpdatePanicLookAround( void ); ///< do panic behavior
  455. void TryToJoinTeam( int team ); ///< try to join the given team
  456. void Follow( CCSPlayer *player ); ///< begin following given Player
  457. void ContinueFollowing( void ); ///< continue following our leader after finishing what we were doing
  458. void StopFollowing( void ); ///< stop following
  459. bool IsFollowing( void ) const; ///< return true if we are following someone (not necessarily in the follow state)
  460. CCSPlayer *GetFollowLeader( void ) const; ///< return the leader we are following
  461. float GetFollowDuration( void ) const; ///< return how long we've been following our leader
  462. bool CanAutoFollow( void ) const; ///< return true if we can auto-follow
  463. bool IsNotMoving( float minDuration = 0.0f ) const; ///< return true if we are currently standing still and have been for minDuration
  464. void AimAtEnemy( void ); ///< point our weapon towards our enemy
  465. void StopAiming( void ); ///< stop aiming at enemy
  466. bool IsAimingAtEnemy( void ) const; ///< returns true if we are trying to aim at an enemy
  467. float GetStateTimestamp( void ) const; ///< get time current state was entered
  468. bool IsDoingScenario( void ) const; ///< return true if we will do scenario-related tasks
  469. //- scenario / gamestate -----------------------------------------------------------------------------------------
  470. CSGameState *GetGameState( void ); ///< return an interface to this bot's gamestate
  471. const CSGameState *GetGameState( void ) const; ///< return an interface to this bot's gamestate
  472. bool IsAtBombsite( void ); ///< return true if we are in a bomb planting zone
  473. bool GuardRandomZone( float range = 500.0f ); ///< pick a random zone and hide near it
  474. bool IsBusy( void ) const; ///< return true if we are busy doing something important
  475. //- high-level tasks ---------------------------------------------------------------------------------------------
  476. enum TaskType
  477. {
  478. SEEK_AND_DESTROY,
  479. PLANT_BOMB,
  480. FIND_TICKING_BOMB,
  481. DEFUSE_BOMB,
  482. GUARD_TICKING_BOMB,
  483. GUARD_BOMB_DEFUSER,
  484. GUARD_LOOSE_BOMB,
  485. GUARD_BOMB_ZONE,
  486. GUARD_INITIAL_ENCOUNTER,
  487. ESCAPE_FROM_BOMB,
  488. HOLD_POSITION,
  489. FOLLOW,
  490. VIP_ESCAPE,
  491. GUARD_VIP_ESCAPE_ZONE,
  492. COLLECT_HOSTAGES,
  493. RESCUE_HOSTAGES,
  494. GUARD_HOSTAGES,
  495. GUARD_HOSTAGE_RESCUE_ZONE,
  496. MOVE_TO_LAST_KNOWN_ENEMY_POSITION,
  497. MOVE_TO_SNIPER_SPOT,
  498. SNIPING,
  499. ESCAPE_FROM_FLAMES,
  500. NUM_TASKS
  501. };
  502. void SetTask( TaskType task, CBaseEntity *entity = NULL ); ///< set our current "task"
  503. TaskType GetTask( void ) const;
  504. CBaseEntity *GetTaskEntity( void );
  505. const char *GetTaskName( void ) const; ///< return string describing current task
  506. // You probably never want to call these on CS bots.
  507. virtual CBaseEntity *GetEnemy( void ) OVERRIDE { Assert( 0 ); return NULL; }
  508. virtual CBaseEntity *GetEnemy( void ) const OVERRIDE { Assert( 0 ); return NULL; }
  509. //- behavior modifiers ------------------------------------------------------------------------------------------
  510. enum DispositionType
  511. {
  512. ENGAGE_AND_INVESTIGATE, ///< engage enemies on sight and investigate enemy noises
  513. OPPORTUNITY_FIRE, ///< engage enemies on sight, but only look towards enemy noises, dont investigate
  514. SELF_DEFENSE, ///< only engage if fired on, or very close to enemy
  515. IGNORE_ENEMIES, ///< ignore all enemies - useful for ducking around corners, running away, etc
  516. NUM_DISPOSITIONS
  517. };
  518. void SetDisposition( DispositionType disposition ); ///< define how we react to enemies
  519. DispositionType GetDisposition( void ) const;
  520. const char *GetDispositionName( void ) const; ///< return string describing current disposition
  521. void IgnoreEnemies( float duration ); ///< ignore enemies for a short duration
  522. enum MoraleType
  523. {
  524. TERRIBLE = -3,
  525. BAD = -2,
  526. NEGATIVE = -1,
  527. NEUTRAL = 0,
  528. POSITIVE = 1,
  529. GOOD = 2,
  530. EXCELLENT = 3,
  531. };
  532. MoraleType GetMorale( void ) const;
  533. const char *GetMoraleName( void ) const; ///< return string describing current morale
  534. void IncreaseMorale( void );
  535. void DecreaseMorale( void );
  536. void Surprise( float duration ); ///< become "surprised" - can't attack
  537. bool IsSurprised( void ) const; ///< return true if we are "surprised"
  538. //- listening for noises ----------------------------------------------------------------------------------------
  539. bool IsNoiseHeard( void ) const; ///< return true if we have heard a noise
  540. bool HeardInterestingNoise( void ); ///< return true if we heard an enemy noise worth checking in to
  541. float GetNoiseInvestigateChance( void ) const;
  542. void InvestigateNoise( void ); ///< investigate recent enemy noise
  543. bool IsInvestigatingNoise( void ) const; ///< return true if we are investigating a noise
  544. const Vector *GetNoisePosition( void ) const; ///< return position of last heard noise, or NULL if none heard
  545. CNavArea *GetNoiseArea( void ) const; ///< return area where noise was heard
  546. void ForgetNoise( void ); ///< clear the last heard noise
  547. bool CanSeeNoisePosition( void ) const; ///< return true if we directly see where we think the noise came from
  548. float GetNoiseRange( void ) const; ///< return approximate distance to last noise heard
  549. bool CanHearNearbyEnemyGunfire( float range = -1.0f ) const;///< return true if we hear nearby threatening enemy gunfire within given range (-1 == infinite)
  550. PriorityType GetNoisePriority( void ) const; ///< return priority of last heard noise
  551. //- radio and chatter--------------------------------------------------------------------------------------------
  552. void SendRadioMessage( RadioType event ); ///< send a radio message
  553. void SpeakAudio( const char *voiceFilename, float duration, int pitch ); ///< send voice chatter
  554. bool SpeakAudioResponseRules( const char *pConcept, AI_CriteriaSet *criteria, float duration ); ///< send voice chatter through response rules system
  555. BotChatterInterface *GetChatter( void ); ///< return an interface to this bot's chatter system
  556. bool RespondToHelpRequest( CCSPlayer *player, Place place, float maxRange = -1.0f ); ///< decide if we should move to help the player, return true if we will
  557. bool IsUsingVoice() const; ///< new-style "voice" chatter gets voice feedback
  558. //- enemies ------------------------------------------------------------------------------------------------------
  559. // BOTPORT: GetEnemy() collides with GetEnemy() in CBaseEntity - need to use different nomenclature
  560. void SetBotEnemy( CCSPlayer *enemy ); ///< set given player as our current enemy
  561. CCSPlayer *GetBotEnemy( void ) const;
  562. int GetNearbyEnemyCount( void ) const; ///< return max number of nearby enemies we've seen recently
  563. unsigned int GetEnemyPlace( void ) const; ///< return location where we see the majority of our enemies
  564. bool CanSeeBomber( void ) const; ///< return true if we can see the bomb carrier
  565. CCSPlayer *GetBomber( void ) const;
  566. int GetNearbyFriendCount( void ) const; ///< return number of nearby teammates
  567. CCSPlayer *GetClosestVisibleFriend( void ) const; ///< return the closest friend that we can see
  568. CCSPlayer *GetClosestVisibleHumanFriend( void ) const; ///< return the closest human friend that we can see
  569. bool IsOutnumbered( void ) const; ///< return true if we are outnumbered by enemies
  570. int OutnumberedCount( void ) const; ///< return number of enemies we are outnumbered by
  571. #define ONLY_VISIBLE_ENEMIES true
  572. CCSPlayer *GetImportantEnemy( bool checkVisibility = false ) const; ///< return the closest "important" enemy for the given scenario (bomb carrier, VIP, hostage escorter)
  573. void UpdateReactionQueue( void ); ///< update our reaction time queue
  574. CCSPlayer *GetRecognizedEnemy( void ); ///< return the most dangerous threat we are "conscious" of
  575. bool IsRecognizedEnemyReloading( void ); ///< return true if the enemy we are "conscious" of is reloading
  576. bool IsRecognizedEnemyProtectedByShield( void ); ///< return true if the enemy we are "conscious" of is hiding behind a shield
  577. float GetRangeToNearestRecognizedEnemy( void ); ///< return distance to closest enemy we are "conscious" of
  578. CCSPlayer *GetAttacker( void ) const; ///< return last enemy that hurt us
  579. float GetTimeSinceAttacked( void ) const; ///< return duration since we were last injured by an attacker
  580. float GetFirstSawEnemyTimestamp( void ) const; ///< time since we saw any enemies
  581. float GetLastSawEnemyTimestamp( void ) const;
  582. float GetTimeSinceLastSawEnemy( void ) const;
  583. float GetTimeSinceAcquiredCurrentEnemy( void ) const;
  584. float GetTimeSinceBurnedByFlames( void ) const;
  585. bool HasNotSeenEnemyForLongTime( void ) const; ///< return true if we haven't seen an enemy for "a long time"
  586. const Vector &GetLastKnownEnemyPosition( void ) const;
  587. bool IsEnemyVisible( void ) const; ///< is our current enemy visible
  588. float GetEnemyDeathTimestamp( void ) const;
  589. bool IsFriendInLineOfFire( void ); ///< return true if a friend is in our weapon's way
  590. bool IsAwareOfEnemyDeath( void ) const; ///< return true if we *noticed* that our enemy died
  591. int GetLastVictimID( void ) const; ///< return the ID (entindex) of the last victim we killed, or zero
  592. bool CanSeeSniper( void ) const; ///< return true if we can see an enemy sniper
  593. bool HasSeenSniperRecently( void ) const; ///< return true if we have seen a sniper recently
  594. float GetTravelDistanceToPlayer( CCSPlayer *player ) const; ///< return shortest path travel distance to this player
  595. bool DidPlayerJustFireWeapon( const CCSPlayer *player ) const; ///< return true if the given player just fired their weapon
  596. //- navigation --------------------------------------------------------------------------------------------------
  597. bool HasPath( void ) const;
  598. void DestroyPath( void );
  599. float GetFeetZ( void ) const; ///< return Z of bottom of feet
  600. enum PathResult
  601. {
  602. PROGRESSING, ///< we are moving along the path
  603. END_OF_PATH, ///< we reached the end of the path
  604. PATH_FAILURE ///< we failed to reach the end of the path
  605. };
  606. #define NO_SPEED_CHANGE false
  607. PathResult UpdatePathMovement( bool allowSpeedChange = true ); ///< move along our computed path - if allowSpeedChange is true, bot will walk when near goal to ensure accuracy
  608. //bool AStarSearch( CNavArea *startArea, CNavArea *goalArea ); ///< find shortest path from startArea to goalArea - don't actually buid the path
  609. bool ComputePath( const Vector &goal, RouteType route = SAFEST_ROUTE ); ///< compute path to goal position
  610. bool StayOnNavMesh( void );
  611. const Vector &GetPathEndpoint( void ) const; ///< return final position of our current path
  612. float GetPathDistanceRemaining( void ) const; ///< return estimated distance left to travel along path
  613. void ResetStuckMonitor( void );
  614. bool IsAreaVisible( const CNavArea *area ) const; ///< is any portion of the area visible to this bot
  615. const Vector &GetPathPosition( int index ) const;
  616. bool GetSimpleGroundHeightWithFloor( const Vector &pos, float *height, Vector *normal = NULL ); ///< find "simple" ground height, treating current nav area as part of the floor
  617. void BreakablesCheck( void );
  618. void DoorCheck( void ); ///< Check for any doors along our path that need opening
  619. virtual void PushawayTouch( CBaseEntity *pOther );
  620. Place GetPlace( void ) const; ///< get our current radio chatter place
  621. bool IsUsingLadder( void ) const; ///< returns true if we are in the process of negotiating a ladder
  622. void GetOffLadder( void ); ///< immediately jump off of our ladder, if we're on one
  623. void SetGoalEntity( CBaseEntity *entity );
  624. CBaseEntity *GetGoalEntity( void );
  625. bool IsNearJump( void ) const; ///< return true if nearing a jump in the path
  626. float GetApproximateFallDamage( float height ) const; ///< return how much damage will will take from the given fall height
  627. void ForceRun( float duration ); ///< force the bot to run if it moves for the given duration
  628. virtual bool IsRunning( void ) const;
  629. void Wait( float duration ); ///< wait where we are for the given duration
  630. bool IsWaiting( void ) const; ///< return true if we are waiting
  631. void StopWaiting( void ); ///< stop waiting
  632. void Wiggle( void ); ///< random movement, for getting un-stuck
  633. bool IsFriendInTheWay( const Vector &goalPos ); ///< return true if a friend is between us and the given position
  634. void FeelerReflexAdjustment( Vector *goalPosition ); ///< do reflex avoidance movements if our "feelers" are touched
  635. bool HasVisitedEnemySpawn( void ) const; ///< return true if we have visited enemy spawn at least once
  636. bool IsAtEnemySpawn( void ) const; ///< return true if we are at the/an enemy spawn right now
  637. //- looking around ----------------------------------------------------------------------------------------------
  638. // BOTPORT: EVIL VILE HACK - why is EyePosition() not const?!?!?
  639. const Vector &EyePositionConst( void ) const;
  640. void SetLookAngles( float yaw, float pitch ); ///< set our desired look angles
  641. void UpdateLookAngles( void ); ///< move actual view angles towards desired ones
  642. void UpdateLookAround( bool updateNow = false ); ///< update "looking around" mechanism
  643. void InhibitLookAround( float duration ); ///< block all "look at" and "looking around" behavior for given duration - just look ahead
  644. /// @todo Clean up notion of "forward angle" and "look ahead angle"
  645. void SetForwardAngle( float angle ); ///< define our forward facing
  646. void SetLookAheadAngle( float angle ); ///< define default look ahead angle
  647. /// look at the given point in space for the given duration (-1 means forever)
  648. void SetLookAt( const char *desc, const Vector &pos, PriorityType pri, float duration = -1.0f, bool clearIfClose = false, float angleTolerance = 5.0f, bool attack = false );
  649. void ClearLookAt( void ); ///< stop looking at a point in space and just look ahead
  650. bool IsLookingAtSpot( PriorityType pri = PRIORITY_LOW ) const; ///< return true if we are looking at spot with equal or higher priority
  651. bool IsViewMoving( float angleVelThreshold = 1.0f ) const; ///< returns true if bot's view angles are rotating (not still)
  652. bool HasViewBeenSteady( float duration ) const; ///< how long has our view been "steady" (ie: not moving) for given duration
  653. bool HasLookAtTarget( void ) const; ///< return true if we are in the process of looking at a target
  654. enum VisiblePartType
  655. {
  656. NONE = 0x00,
  657. GUT = 0x01,
  658. HEAD = 0x02,
  659. LEFT_SIDE = 0x04, ///< the left side of the object from our point of view (not their left side)
  660. RIGHT_SIDE = 0x08, ///< the right side of the object from our point of view (not their right side)
  661. FEET = 0x10
  662. };
  663. #define CHECK_FOV true
  664. bool IsVisible( const Vector &pos, bool testFOV = false, const CBaseEntity *ignore = NULL ) const; ///< return true if we can see the point
  665. bool IsVisible( CCSPlayer *player, bool testFOV = false, unsigned char *visParts = NULL ) const; ///< return true if we can see any part of the player
  666. bool IsBeyondBotMaxVisionDistance( const Vector &vecTargetPosition ) const;
  667. bool IsNoticable( const CCSPlayer *player, unsigned char visibleParts ) const; ///< return true if we "notice" given player
  668. bool IsEnemyPartVisible( VisiblePartType part ) const; ///< if enemy is visible, return the part we see for our current enemy
  669. const Vector &GetPartPosition( CCSPlayer *player, VisiblePartType part ) const; ///< return world space position of given part on player
  670. float ComputeWeaponSightRange( void ); ///< return line-of-sight distance to obstacle along weapon fire ray
  671. bool IsAnyVisibleEnemyLookingAtMe( bool testFOV = false ) const;///< return true if any enemy I have LOS to is looking directly at me
  672. bool IsSignificantlyCloser( const CCSPlayer *testPlayer, const CCSPlayer *referencePlayer ) const; ///< return true if testPlayer is significantly closer than referencePlayer
  673. //- approach points ---------------------------------------------------------------------------------------------
  674. void ComputeApproachPoints( void ); ///< determine the set of "approach points" representing where the enemy can enter this region
  675. void UpdateApproachPoints( void ); ///< recompute the approach point set if we have moved far enough to invalidate the current ones
  676. void ClearApproachPoints( void );
  677. void DrawApproachPoints( void ) const; ///< for debugging
  678. float GetHidingSpotCheckTimestamp( HidingSpot *spot ) const; ///< return time when given spot was last checked
  679. void SetHidingSpotCheckTimestamp( HidingSpot *spot ); ///< set the timestamp of the given spot to now
  680. const CNavArea *GetInitialEncounterArea( void ) const; ///< return area where we think we will first meet the enemy
  681. void SetInitialEncounterArea( const CNavArea *area );
  682. //- weapon query and equip --------------------------------------------------------------------------------------
  683. #define MUST_EQUIP true
  684. void EquipBestWeapon( bool mustEquip = false ); ///< equip the best weapon we are carrying that has ammo
  685. void EquipPistol( void ); ///< equip our pistol
  686. void EquipKnife( void ); ///< equip the knife
  687. #define DONT_USE_SMOKE_GRENADE true
  688. bool EquipGrenade( bool noSmoke = false ); ///< equip a grenade, return false if we cant
  689. bool IsUsingKnife( void ) const; ///< returns true if we have knife equipped
  690. bool IsUsingPistol( void ) const; ///< returns true if we have pistol equipped
  691. bool IsUsingGrenade( void ) const; ///< returns true if we have grenade equipped
  692. bool IsUsingSniperRifle( void ) const; ///< returns true if using a "sniper" rifle
  693. bool IsUsing( CSWeaponID weapon ) const; ///< returns true if using the specific weapon
  694. bool IsSniper( void ) const; ///< return true if we have a sniper rifle in our inventory
  695. bool IsSniping( void ) const; ///< return true if we are actively sniping (moving to sniper spot or settled in)
  696. bool IsUsingShotgun( void ) const; ///< returns true if using a shotgun
  697. bool IsUsingMachinegun( void ) const; ///< returns true if using the big 'ol machinegun
  698. void ThrowGrenade( const Vector &target ); ///< begin the process of throwing the grenade
  699. bool IsThrowingGrenade( void ) const; ///< return true if we are in the process of throwing a grenade
  700. bool HasGrenade( void ) const; ///< return true if we have a grenade in our inventory
  701. void AvoidEnemyGrenades( void ); ///< react to enemy grenades we see
  702. bool IsAvoidingGrenade( void ) const; ///< return true if we are in the act of avoiding a grenade
  703. bool DoesActiveWeaponHaveRemoveableSilencer( void ) const; ///< returns true if we are using a weapon with a removable silencer
  704. bool CanActiveWeaponFire( void ) const; ///< returns true if our current weapon can attack
  705. CWeaponCSBase *GetActiveCSWeapon( void ) const; ///< get our current Counter-Strike weapon
  706. void GiveWeapon( const char *weaponAlias ); ///< Debug command to give a named weapon
  707. virtual void PrimaryAttack( void ); ///< presses the fire button, unless we're holding a pistol that can't fire yet (so we can just always call PrimaryAttack())
  708. enum ZoomType { NO_ZOOM, LOW_ZOOM, HIGH_ZOOM };
  709. ZoomType GetZoomLevel( void ); ///< return the current zoom level of our weapon
  710. bool AdjustZoom( float range ); ///< change our zoom level to be appropriate for the given range
  711. bool IsWaitingForZoom( void ) const; ///< return true if we are reacquiring after our zoom
  712. bool IsPrimaryWeaponEmpty( void ) const; ///< return true if primary weapon doesn't exist or is totally out of ammo
  713. bool IsPistolEmpty( void ) const; ///< return true if pistol doesn't exist or is totally out of ammo
  714. int GetHostageEscortCount( void ) const; ///< return the number of hostages following me
  715. void IncreaseHostageEscortCount( void );
  716. float GetRangeToFarthestEscortedHostage( void ) const; ///< return euclidean distance to farthest escorted hostage
  717. void ResetWaitForHostagePatience( void );
  718. //------------------------------------------------------------------------------------
  719. // Event hooks
  720. //
  721. /// invoked when injured by something (EXTEND) - returns the amount of damage inflicted
  722. virtual int OnTakeDamage( const CTakeDamageInfo &info );
  723. /// invoked when killed (EXTEND)
  724. virtual void Event_Killed( const CTakeDamageInfo &info );
  725. virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); ///< invoked when in contact with a CWeaponBox
  726. /// invoked when event occurs in the game (some events have NULL entity)
  727. void OnPlayerFootstep( IGameEvent *event );
  728. void OnPlayerRadio( IGameEvent *event );
  729. void OnPlayerDeath( IGameEvent *event );
  730. void OnPlayerFallDamage( IGameEvent *event );
  731. void OnBombPickedUp( IGameEvent *event );
  732. void OnBombPlanted( IGameEvent *event );
  733. void OnBombBeep( IGameEvent *event );
  734. void OnBombDefuseBegin( IGameEvent *event );
  735. void OnBombDefused( IGameEvent *event );
  736. void OnBombDefuseAbort( IGameEvent *event );
  737. void OnBombExploded( IGameEvent *event );
  738. void OnRoundEnd( IGameEvent *event );
  739. void OnRoundStart( IGameEvent *event );
  740. void OnDoorMoving( IGameEvent *event );
  741. void OnBreakProp( IGameEvent *event );
  742. void OnBreakBreakable( IGameEvent *event );
  743. void OnHostageFollows( IGameEvent *event );
  744. void OnHostageRescuedAll( IGameEvent *event );
  745. void OnWeaponFire( IGameEvent *event );
  746. void OnWeaponFireOnEmpty( IGameEvent *event );
  747. void OnWeaponReload( IGameEvent *event );
  748. void OnWeaponZoom( IGameEvent *event );
  749. void OnBulletImpact( IGameEvent *event );
  750. void OnHEGrenadeDetonate( IGameEvent *event );
  751. void OnFlashbangDetonate( IGameEvent *event );
  752. void OnSmokeGrenadeDetonate( IGameEvent *event );
  753. void OnMolotovDetonate( IGameEvent *event );
  754. void OnDecoyDetonate( IGameEvent *event );
  755. void OnDecoyFiring( IGameEvent *event );
  756. void OnGrenadeBounce( IGameEvent *event );
  757. void OnNavBlocked( IGameEvent *event );
  758. void OnEnteredNavArea( CNavArea *newArea ); ///< invoked when bot enters a nav area
  759. #define IS_FOOTSTEP true
  760. void OnAudibleEvent( IGameEvent *event, CBasePlayer *player, float range, PriorityType priority, bool isHostile, bool isFootstep = false, const Vector *actualOrigin = NULL ); ///< Checks if the bot can hear the event
  761. void SetLastCoopSpawnPoint( SpawnPointCoopEnemy *spawn );
  762. SpawnPointCoopEnemy *GetLastCoopSpawnPoint( void ) const;
  763. CHandle< SpawnPointCoopEnemy > m_lastCoopSpawnPoint; /// the last spawn point entity that we spawned from
  764. protected:
  765. float SlowNoise( float fTau ) const;
  766. BotProfile *m_pLocalProfile; ///< local profile of the bot - can change over time due to dynamic bot difficulty changes
  767. private:
  768. friend class CCSBotManager;
  769. /// @todo Get rid of these
  770. friend class AttackState;
  771. friend class BuyState;
  772. // BOTPORT: Remove this vile hack
  773. Vector m_eyePosition;
  774. void ResetValues( void ); ///< reset internal data to initial state
  775. void BotDeathThink( void );
  776. char m_name[64]; ///< copied from STRING(pev->netname) for debugging
  777. void DebugDisplay( void ) const; ///< render bot debug info
  778. //- behavior properties ------------------------------------------------------------------------------------------
  779. float m_combatRange; ///< desired distance between us and them during gunplay
  780. mutable bool m_isRogue; ///< if true, the bot is a "rogue" and listens to no-one
  781. mutable CountdownTimer m_rogueTimer;
  782. MoraleType m_morale; ///< our current morale, based on our win/loss history
  783. bool m_diedLastRound; ///< true if we died last round
  784. float m_safeTime; ///< duration at the beginning of the round where we feel "safe"
  785. bool m_wasSafe; ///< true if we were in the safe time last update
  786. void AdjustSafeTime( void ); ///< called when enemy seen to adjust safe time for this round
  787. NavRelativeDirType m_blindMoveDir; ///< which way to move when we're blind
  788. bool m_blindFire; ///< if true, fire weapon while blinded
  789. CountdownTimer m_surpriseTimer; ///< when we were surprised
  790. bool m_isFollowing; ///< true if we are following someone
  791. CHandle< CCSPlayer > m_leader; ///< the ID of who we are following
  792. float m_followTimestamp; ///< when we started following
  793. float m_allowAutoFollowTime; ///< time when we can auto follow
  794. CountdownTimer m_hurryTimer; ///< if valid, bot is in a hurry
  795. CountdownTimer m_alertTimer; ///< if valid, bot is alert
  796. CountdownTimer m_sneakTimer; ///< if valid, bot is sneaking
  797. CountdownTimer m_panicTimer; ///< if valid, bot is panicking
  798. // instances of each possible behavior state, to avoid dynamic memory allocation during runtime
  799. IdleState m_idleState;
  800. HuntState m_huntState;
  801. AttackState m_attackState;
  802. InvestigateNoiseState m_investigateNoiseState;
  803. BuyState m_buyState;
  804. MoveToState m_moveToState;
  805. FetchBombState m_fetchBombState;
  806. PlantBombState m_plantBombState;
  807. DefuseBombState m_defuseBombState;
  808. PickupHostageState m_pickupHostageState;
  809. HideState m_hideState;
  810. EscapeFromBombState m_escapeFromBombState;
  811. FollowState m_followState;
  812. UseEntityState m_useEntityState;
  813. OpenDoorState m_openDoorState;
  814. EscapeFromFlamesState m_escapeFromFlamesState;
  815. /// @todo Allow multiple simultaneous state machines (look around, etc)
  816. void SetState( BotState *state ); ///< set the current behavior state
  817. BotState *m_state; ///< current behavior state
  818. float m_stateTimestamp; ///< time state was entered
  819. bool m_isAttacking; ///< if true, special Attack state is overriding the state machine
  820. bool m_isOpeningDoor; ///< if true, special OpenDoor state is overriding the state machine
  821. TaskType m_task; ///< our current task
  822. EHANDLE m_taskEntity; ///< an entity used for our task
  823. //- navigation ---------------------------------------------------------------------------------------------------
  824. Vector m_goalPosition;
  825. EHANDLE m_goalEntity;
  826. void MoveTowardsPosition( const Vector &pos ); ///< move towards position, independant of view angle
  827. void MoveAwayFromPosition( const Vector &pos ); ///< move away from position, independant of view angle
  828. void StrafeAwayFromPosition( const Vector &pos ); ///< strafe (sidestep) away from position, independant of view angle
  829. void StuckCheck( void ); ///< check if we have become stuck
  830. CCSNavArea *m_currentArea; ///< the nav area we are standing on
  831. CCSNavArea *m_lastKnownArea; ///< the last area we were in
  832. EHANDLE m_avoid; ///< higher priority player we need to make way for
  833. float m_avoidTimestamp;
  834. bool m_isStopping; ///< true if we're trying to stop because we entered a 'stop' nav area
  835. bool m_hasVisitedEnemySpawn; ///< true if we have been at the enemy spawn
  836. IntervalTimer m_stillTimer; ///< how long we have been not moving
  837. void CoopUpdateChecks( void ); ///< checks needed for coop
  838. //- path navigation data ----------------------------------------------------------------------------------------
  839. enum { MAX_PATH_LENGTH = 256 };
  840. struct ConnectInfo
  841. {
  842. CNavArea *area; ///< the area along the path
  843. NavTraverseType how; ///< how to enter this area from the previous one
  844. Vector pos; ///< our movement goal position at this point in the path
  845. const CNavLadder *ladder; ///< if "how" refers to a ladder, this is it
  846. }
  847. m_path[ MAX_PATH_LENGTH ];
  848. int m_pathLength;
  849. int m_pathIndex; ///< index of next area on path
  850. float m_areaEnteredTimestamp;
  851. void BuildTrivialPath( const Vector &goal ); ///< build trivial path to goal, assuming we are already in the same area
  852. CountdownTimer m_repathTimer; ///< must have elapsed before bot can pathfind again
  853. bool ComputePathPositions( void ); ///< determine actual path positions bot will move between along the path
  854. void SetupLadderMovement( void );
  855. void SetPathIndex( int index ); ///< set the current index along the path
  856. void DrawPath( void );
  857. int FindOurPositionOnPath( Vector *close, bool local = false ) const; ///< compute the closest point to our current position on our path
  858. int FindPathPoint( float aheadRange, Vector *point, int *prevIndex = NULL ); ///< compute a point a fixed distance ahead along our path.
  859. bool FindClosestPointOnPath( const Vector &pos, int startIndex, int endIndex, Vector *close ) const; ///< compute closest point on path to given point
  860. bool IsStraightLinePathWalkable( const Vector &goal ) const; ///< test for un-jumpable height change, or unrecoverable fall
  861. void ComputeLadderAngles( float *yaw, float *pitch ); ///< computes ideal yaw/pitch for traversing the current ladder on our path
  862. mutable CountdownTimer m_avoidFriendTimer; ///< used to throttle how often we check for friends in our path
  863. mutable bool m_isFriendInTheWay; ///< true if a friend is blocking our path
  864. CountdownTimer m_politeTimer; ///< we'll wait for friend to move until this runs out
  865. bool m_isWaitingBehindFriend; ///< true if we are waiting for a friend to move
  866. #define ONLY_JUMP_DOWN true
  867. bool DiscontinuityJump( float ground, bool onlyJumpDown = false, bool mustJump = false ); ///< check if we need to jump due to height change
  868. enum LadderNavState
  869. {
  870. APPROACH_ASCENDING_LADDER, ///< prepare to scale a ladder
  871. APPROACH_DESCENDING_LADDER, ///< prepare to go down ladder
  872. FACE_ASCENDING_LADDER,
  873. FACE_DESCENDING_LADDER,
  874. MOUNT_ASCENDING_LADDER, ///< move toward ladder until "on" it
  875. MOUNT_DESCENDING_LADDER, ///< move toward ladder until "on" it
  876. ASCEND_LADDER, ///< go up the ladder
  877. DESCEND_LADDER, ///< go down the ladder
  878. DISMOUNT_ASCENDING_LADDER, ///< get off of the ladder
  879. DISMOUNT_DESCENDING_LADDER, ///< get off of the ladder
  880. MOVE_TO_DESTINATION, ///< dismount ladder and move to destination area
  881. }
  882. m_pathLadderState;
  883. bool m_pathLadderFaceIn; ///< if true, face towards ladder, otherwise face away
  884. const CNavLadder *m_pathLadder; ///< the ladder we need to use to reach the next area
  885. bool UpdateLadderMovement( void ); ///< called by UpdatePathMovement()
  886. NavRelativeDirType m_pathLadderDismountDir; ///< which way to dismount
  887. float m_pathLadderDismountTimestamp; ///< time when dismount started
  888. float m_pathLadderEnd; ///< if ascending, z of top, if descending z of bottom
  889. void ComputeLadderEndpoint( bool ascending );
  890. float m_pathLadderTimestamp; ///< time when we started using ladder - for timeout check
  891. CountdownTimer m_mustRunTimer; ///< if nonzero, bot cannot walk
  892. CountdownTimer m_waitTimer; ///< if nonzero, we are waiting where we are
  893. void UpdateTravelDistanceToAllPlayers( void ); ///< periodically compute shortest path distance to each player
  894. CountdownTimer m_updateTravelDistanceTimer; ///< for throttling travel distance computations
  895. float m_playerTravelDistance[ MAX_PLAYERS ]; ///< current distance from this bot to each player
  896. unsigned char m_travelDistancePhase; ///< a counter for optimizing when to compute travel distance
  897. //- game scenario mechanisms -------------------------------------------------------------------------------------
  898. CSGameState m_gameState; ///< our current knowledge about the state of the scenario
  899. byte m_hostageEscortCount; ///< the number of hostages we're currently escorting
  900. void UpdateHostageEscortCount( void ); ///< periodic check of hostage count in case we lost some
  901. float m_hostageEscortCountTimestamp;
  902. int m_desiredTeam; ///< the team we want to be on
  903. bool m_hasJoined; ///< true if bot has actually joined the game
  904. bool m_isWaitingForHostage;
  905. CountdownTimer m_inhibitWaitingForHostageTimer; ///< if active, inhibits us waiting for lagging hostages
  906. CountdownTimer m_waitForHostageTimer; ///< stops us waiting too long
  907. //- listening mechanism ------------------------------------------------------------------------------------------
  908. Vector m_noisePosition; ///< position we last heard non-friendly noise
  909. float m_noiseTravelDistance; ///< the travel distance to the noise
  910. float m_noiseTimestamp; ///< when we heard it (can get zeroed)
  911. CNavArea *m_noiseArea; ///< the nav area containing the noise
  912. PriorityType m_noisePriority; ///< priority of currently heard noise
  913. bool UpdateLookAtNoise( void ); ///< return true if we decided to look towards the most recent noise source
  914. CountdownTimer m_noiseBendTimer; ///< for throttling how often we bend our line of sight to the noise location
  915. Vector m_bentNoisePosition; ///< the last computed bent line of sight
  916. bool m_bendNoisePositionValid;
  917. //- "looking around" mechanism -----------------------------------------------------------------------------------
  918. float m_lookAroundStateTimestamp; ///< time of next state change
  919. float m_lookAheadAngle; ///< our desired forward look angle
  920. float m_forwardAngle; ///< our current forward facing direction
  921. float m_inhibitLookAroundTimestamp; ///< time when we can look around again
  922. enum LookAtSpotState
  923. {
  924. NOT_LOOKING_AT_SPOT, ///< not currently looking at a point in space
  925. LOOK_TOWARDS_SPOT, ///< in the process of aiming at m_lookAtSpot
  926. LOOK_AT_SPOT, ///< looking at m_lookAtSpot
  927. NUM_LOOK_AT_SPOT_STATES
  928. }
  929. m_lookAtSpotState;
  930. Vector m_lookAtSpot; ///< the spot we're currently looking at
  931. PriorityType m_lookAtSpotPriority;
  932. float m_lookAtSpotDuration; ///< how long we need to look at the spot
  933. float m_lookAtSpotTimestamp; ///< when we actually began looking at the spot
  934. float m_lookAtSpotAngleTolerance; ///< how exactly we must look at the spot
  935. bool m_lookAtSpotClearIfClose; ///< if true, the look at spot is cleared if it gets close to us
  936. bool m_lookAtSpotAttack; ///< if true, the look at spot should be attacked
  937. const char *m_lookAtDesc; ///< for debugging
  938. void UpdateLookAt( void );
  939. void UpdatePeripheralVision(); ///< update enounter spot timestamps, etc
  940. float m_peripheralTimestamp;
  941. enum { MAX_APPROACH_POINTS = 16 };
  942. struct ApproachPoint
  943. {
  944. Vector m_pos;
  945. CNavArea *m_area;
  946. };
  947. ApproachPoint m_approachPoint[ MAX_APPROACH_POINTS ];
  948. unsigned char m_approachPointCount;
  949. Vector m_approachPointViewPosition; ///< the position used when computing current approachPoint set
  950. CBaseEntity * FindEntitiesOnPath( float distance, CPushAwayEnumerator *enumerator, bool checkStuck );
  951. IntervalTimer m_viewSteadyTimer; ///< how long has our view been "steady" (ie: not moving)
  952. bool BendLineOfSight( const Vector &eye, const Vector &target, Vector *bend, float angleLimit = 135.0f ) const; ///< "bend" our line of sight until we can see the target point. Return bend point, false if cant bend.
  953. bool FindApproachPointNearestPath( Vector *pos ); ///< find the approach point that is nearest to our current path, ahead of us
  954. bool FindGrenadeTossPathTarget( Vector *pos ); ///< find spot to throw grenade ahead of us and "around the corner" along our path
  955. enum GrenadeTossState
  956. {
  957. NOT_THROWING, ///< not yet throwing
  958. START_THROW, ///< lining up throw
  959. THROW_LINED_UP, ///< pause for a moment when on-line
  960. FINISH_THROW, ///< throwing
  961. };
  962. GrenadeTossState m_grenadeTossState;
  963. CountdownTimer m_tossGrenadeTimer; ///< timeout timer for grenade tossing
  964. const CNavArea *m_initialEncounterArea; ///< area where we think we will initially encounter the enemy
  965. void LookForGrenadeTargets( void ); ///< look for grenade throw targets and throw our grenade at them
  966. void UpdateGrenadeThrow( void ); ///< process grenade throwing
  967. CountdownTimer m_isAvoidingGrenade; ///< if nonzero we are in the act of avoiding a grenade
  968. SpotEncounter *m_spotEncounter; ///< the spots we will encounter as we move thru our current area
  969. float m_spotCheckTimestamp; ///< when to check next encounter spot
  970. /// @todo Add timestamp for each possible client to hiding spots
  971. enum { MAX_CHECKED_SPOTS = 64 };
  972. struct HidingSpotCheckInfo
  973. {
  974. HidingSpot *spot;
  975. float timestamp;
  976. }
  977. m_checkedHidingSpot[ MAX_CHECKED_SPOTS ];
  978. int m_checkedHidingSpotCount;
  979. //- view angle mechanism -----------------------------------------------------------------------------------------
  980. float m_lookPitch; ///< our desired look pitch angle
  981. float m_lookPitchVel;
  982. float m_lookYaw; ///< our desired look yaw angle
  983. float m_lookYawVel;
  984. //- aim angle mechanism -----------------------------------------------------------------------------------------
  985. void PickNewAimSpot(); ///< set the current aim offset
  986. void UpdateAimPrediction( void ); ///< wiggle aim based on aim error term
  987. Vector m_targetSpot; ///< the spot we currently wish to fire at
  988. Vector m_targetSpotVelocity; ///< the spot we currently wish to fire at
  989. Vector m_targetSpotPredicted; ///< the spot we currently wish to fire at
  990. QAngle m_aimError;
  991. QAngle m_aimGoal;
  992. float m_targetSpotTime;
  993. float m_aimFocus; ///< radius of aim focus
  994. float m_aimFocusInterval; ///< time interval of current offset adjustment (can be random)
  995. float m_aimFocusNextUpdate; ///< time of next offset adjustment
  996. struct PartInfo
  997. {
  998. Vector m_headPos; ///< current head position
  999. Vector m_gutPos; ///< current gut position
  1000. Vector m_feetPos; ///< current feet position
  1001. Vector m_leftSidePos; ///< current left side position
  1002. Vector m_rightSidePos; ///< current right side position
  1003. int m_validFrame; ///< frame of last computation (for lazy evaluation)
  1004. };
  1005. static PartInfo m_partInfo[ MAX_PLAYERS ]; ///< part positions for each player
  1006. void ComputePartPositions( CCSPlayer *player ); ///< compute part positions from bone location
  1007. //- attack state data --------------------------------------------------------------------------------------------
  1008. DispositionType m_disposition; ///< how we will react to enemies
  1009. CountdownTimer m_ignoreEnemiesTimer; ///< how long will we ignore enemies
  1010. mutable CHandle< CCSPlayer > m_enemy; ///< our current enemy
  1011. bool m_isEnemyVisible; ///< result of last visibility test on enemy
  1012. unsigned char m_visibleEnemyParts; ///< which parts of the visible enemy do we see
  1013. Vector m_lastEnemyPosition; ///< last place we saw the enemy
  1014. float m_lastSawEnemyTimestamp;
  1015. float m_firstSawEnemyTimestamp;
  1016. float m_currentEnemyAcquireTimestamp;
  1017. float m_enemyDeathTimestamp; ///< if m_enemy is dead, this is when he died
  1018. float m_friendDeathTimestamp; ///< time since we saw a friend die
  1019. bool m_isLastEnemyDead; ///< true if we killed or saw our last enemy die
  1020. int m_nearbyEnemyCount; ///< max number of enemies we've seen recently
  1021. unsigned int m_enemyPlace; ///< the location where we saw most of our enemies
  1022. struct WatchInfo
  1023. {
  1024. float timestamp; ///< time we last saw this player, zero if never seen
  1025. bool isEnemy;
  1026. }
  1027. m_watchInfo[ MAX_PLAYERS ];
  1028. mutable CHandle< CCSPlayer > m_bomber; ///< points to bomber if we can see him
  1029. int m_nearbyFriendCount; ///< number of nearby teammates
  1030. mutable CHandle< CCSPlayer > m_closestVisibleFriend; ///< the closest friend we can see
  1031. mutable CHandle< CCSPlayer > m_closestVisibleHumanFriend; ///< the closest human friend we can see
  1032. IntervalTimer m_attentionInterval; ///< time between attention checks
  1033. mutable CHandle< CCSPlayer > m_attacker; ///< last enemy that hurt us (may not be same as m_enemy)
  1034. float m_attackedTimestamp; ///< when we were hurt by the m_attacker
  1035. IntervalTimer m_burnedByFlamesTimer;
  1036. int m_lastVictimID; ///< the entindex of the last victim we killed, or zero
  1037. bool m_isAimingAtEnemy; ///< if true, we are trying to aim at our enemy
  1038. bool m_isRapidFiring; ///< if true, RunUpkeep() will toggle our primary attack as fast as it can
  1039. IntervalTimer m_equipTimer; ///< how long have we had our current weapon equipped
  1040. CountdownTimer m_zoomTimer; ///< for delaying firing immediately after zoom
  1041. bool DoEquip( CWeaponCSBase *gun ); ///< equip the given item
  1042. void ReloadCheck( void ); ///< reload our weapon if we must
  1043. void SilencerCheck( void ); ///< use silencer
  1044. float m_fireWeaponTimestamp;
  1045. // sleeping
  1046. bool m_bIsSleeping;
  1047. bool m_isEnemySniperVisible; ///< do we see an enemy sniper right now
  1048. CountdownTimer m_sawEnemySniperTimer; ///< tracking time since saw enemy sniper
  1049. //- reaction time system -----------------------------------------------------------------------------------------
  1050. enum { MAX_ENEMY_QUEUE = 20 };
  1051. struct ReactionState
  1052. {
  1053. // NOTE: player position & orientation is not currently stored separately
  1054. CHandle<CCSPlayer> player;
  1055. bool isReloading;
  1056. bool isProtectedByShield;
  1057. }
  1058. m_enemyQueue[ MAX_ENEMY_QUEUE ]; ///< round-robin queue for simulating reaction times
  1059. byte m_enemyQueueIndex;
  1060. byte m_enemyQueueCount;
  1061. byte m_enemyQueueAttendIndex; ///< index of the timeframe we are "conscious" of
  1062. CCSPlayer *FindMostDangerousThreat( void ); ///< return most dangerous threat in my field of view (feeds into reaction time queue)
  1063. //- stuck detection ---------------------------------------------------------------------------------------------
  1064. bool m_isStuck;
  1065. float m_stuckTimestamp; ///< time when we got stuck
  1066. Vector m_stuckSpot; ///< the location where we became stuck
  1067. NavRelativeDirType m_wiggleDirection;
  1068. CountdownTimer m_wiggleTimer;
  1069. CountdownTimer m_stuckJumpTimer; ///< time for next jump when stuck
  1070. float m_nextCleanupCheckTimestamp;
  1071. enum { MAX_VEL_SAMPLES = 10 };
  1072. float m_avgVel[ MAX_VEL_SAMPLES ];
  1073. int m_avgVelIndex;
  1074. int m_avgVelCount;
  1075. Vector m_lastOrigin;
  1076. //- radio --------------------------------------------------------------------------------------------------------
  1077. RadioType m_lastRadioCommand; ///< last radio command we recieved
  1078. float m_lastRadioRecievedTimestamp; ///< time we recieved a radio message
  1079. float m_lastRadioSentTimestamp; ///< time when we send a radio message
  1080. CHandle< CCSPlayer > m_radioSubject; ///< who issued the radio message
  1081. Vector m_radioPosition; ///< position referred to in radio message
  1082. void RespondToRadioCommands( void );
  1083. bool IsRadioCommand( RadioType event ) const; ///< returns true if the radio message is an order to do something
  1084. /// new-style "voice" chatter gets voice feedback
  1085. float m_voiceEndTimestamp;
  1086. BotChatterInterface *m_pChatter; ///< chatter mechanism
  1087. int ObjectCaps( void ) { return ( BaseClass::ObjectCaps() | FCAP_IMPULSE_USE ); } //allow +use
  1088. #ifdef OPT_VIS_CSGO
  1089. //--------------------------------------------------------------------------------------------------
  1090. // PS3 vis cache
  1091. //--------------------------------------------------------------------------------------------------
  1092. bool m_bVis[5];
  1093. char m_aVisParts[5];
  1094. #endif
  1095. };
  1096. //
  1097. // Inlines
  1098. //
  1099. inline float CCSBot::GetFeetZ( void ) const
  1100. {
  1101. return GetAbsOrigin().z;
  1102. }
  1103. inline const Vector *CCSBot::GetNoisePosition( void ) const
  1104. {
  1105. if (m_noiseTimestamp > 0.0f)
  1106. return &m_noisePosition;
  1107. return NULL;
  1108. }
  1109. inline bool CCSBot::IsAwareOfEnemyDeath( void ) const
  1110. {
  1111. if (GetEnemyDeathTimestamp() == 0.0f)
  1112. return false;
  1113. if (m_enemy == NULL)
  1114. return true;
  1115. if (!m_enemy->IsAlive() && gpGlobals->curtime - GetEnemyDeathTimestamp() > (1.0f - 0.8f * GetProfile()->GetSkill()))
  1116. return true;
  1117. return false;
  1118. }
  1119. inline void CCSBot::Panic( void )
  1120. {
  1121. // we are stunned for a moment
  1122. Surprise( RandomFloat( 0.2f, 0.3f ) );
  1123. const float panicTime = 3.0f;
  1124. m_panicTimer.Start( panicTime );
  1125. const float panicRetreatRange = 300.0f;
  1126. TryToRetreat( panicRetreatRange, 0.0f );
  1127. PrintIfWatched( "*** PANIC ***\n" );
  1128. }
  1129. inline bool CCSBot::IsPanicking( void ) const
  1130. {
  1131. return !m_panicTimer.IsElapsed();
  1132. }
  1133. inline void CCSBot::StopPanicking( void )
  1134. {
  1135. m_panicTimer.Invalidate();
  1136. }
  1137. inline bool CCSBot::IsNotMoving( float minDuration ) const
  1138. {
  1139. return (m_stillTimer.HasStarted() && m_stillTimer.GetElapsedTime() >= minDuration);
  1140. }
  1141. inline CWeaponCSBase *CCSBot::GetActiveCSWeapon( void ) const
  1142. {
  1143. return reinterpret_cast<CWeaponCSBase *>( GetActiveWeapon() );
  1144. }
  1145. inline void CCSBot::SetLastCoopSpawnPoint( SpawnPointCoopEnemy *spawn )
  1146. {
  1147. m_lastCoopSpawnPoint = spawn;
  1148. }
  1149. inline SpawnPointCoopEnemy *CCSBot::GetLastCoopSpawnPoint( void ) const
  1150. {
  1151. return m_lastCoopSpawnPoint;
  1152. }
  1153. inline float CCSBot::GetCombatRange( void ) const
  1154. {
  1155. return m_combatRange;
  1156. }
  1157. inline void CCSBot::SetRogue( bool rogue )
  1158. {
  1159. m_isRogue = rogue;
  1160. }
  1161. inline void CCSBot::Hurry( float duration )
  1162. {
  1163. m_hurryTimer.Start( duration );
  1164. }
  1165. inline float CCSBot::GetSafeTime( void ) const
  1166. {
  1167. return m_safeTime;
  1168. }
  1169. inline bool CCSBot::IsUnhealthy( void ) const
  1170. {
  1171. return (GetHealth() <= 40);
  1172. }
  1173. inline bool CCSBot::IsAlert( void ) const
  1174. {
  1175. return !m_alertTimer.IsElapsed();
  1176. }
  1177. inline void CCSBot::BecomeAlert( void )
  1178. {
  1179. const float alertCooldownTime = 10.0f;
  1180. m_alertTimer.Start( alertCooldownTime );
  1181. }
  1182. inline bool CCSBot::IsSneaking( void ) const
  1183. {
  1184. return !m_sneakTimer.IsElapsed();
  1185. }
  1186. inline void CCSBot::Sneak( float duration )
  1187. {
  1188. m_sneakTimer.Start( duration );
  1189. }
  1190. inline bool CCSBot::IsFollowing( void ) const
  1191. {
  1192. return m_isFollowing;
  1193. }
  1194. inline CCSPlayer *CCSBot::GetFollowLeader( void ) const
  1195. {
  1196. return m_leader;
  1197. }
  1198. inline float CCSBot::GetFollowDuration( void ) const
  1199. {
  1200. return gpGlobals->curtime - m_followTimestamp;
  1201. }
  1202. inline bool CCSBot::CanAutoFollow( void ) const
  1203. {
  1204. return (gpGlobals->curtime > m_allowAutoFollowTime);
  1205. }
  1206. inline void CCSBot::AimAtEnemy( void )
  1207. {
  1208. m_isAimingAtEnemy = true;
  1209. }
  1210. inline void CCSBot::StopAiming( void )
  1211. {
  1212. m_isAimingAtEnemy = false;
  1213. }
  1214. inline bool CCSBot::IsAimingAtEnemy( void ) const
  1215. {
  1216. return m_isAimingAtEnemy;
  1217. }
  1218. inline float CCSBot::GetStateTimestamp( void ) const
  1219. {
  1220. return m_stateTimestamp;
  1221. }
  1222. inline CSGameState *CCSBot::GetGameState( void )
  1223. {
  1224. return &m_gameState;
  1225. }
  1226. inline const CSGameState *CCSBot::GetGameState( void ) const
  1227. {
  1228. return &m_gameState;
  1229. }
  1230. inline bool CCSBot::IsAtBombsite( void )
  1231. {
  1232. return m_bInBombZone;
  1233. }
  1234. inline void CCSBot::SetTask( TaskType task, CBaseEntity *entity )
  1235. {
  1236. m_task = task;
  1237. m_taskEntity = entity;
  1238. if ( task == CCSBot::PLANT_BOMB )
  1239. {
  1240. // don't stop to attack - get the bomb there
  1241. SetDisposition( CCSBot::SELF_DEFENSE );
  1242. }
  1243. }
  1244. inline CCSBot::TaskType CCSBot::GetTask( void ) const
  1245. {
  1246. return m_task;
  1247. }
  1248. inline CBaseEntity *CCSBot::GetTaskEntity( void )
  1249. {
  1250. return static_cast<CBaseEntity *>( m_taskEntity );
  1251. }
  1252. inline CCSBot::MoraleType CCSBot::GetMorale( void ) const
  1253. {
  1254. return m_morale;
  1255. }
  1256. inline void CCSBot::Surprise( float duration )
  1257. {
  1258. m_surpriseTimer.Start( duration );
  1259. }
  1260. inline bool CCSBot::IsSurprised( void ) const
  1261. {
  1262. return !m_surpriseTimer.IsElapsed();
  1263. }
  1264. inline CNavArea *CCSBot::GetNoiseArea( void ) const
  1265. {
  1266. return m_noiseArea;
  1267. }
  1268. inline void CCSBot::ForgetNoise( void )
  1269. {
  1270. m_noiseTimestamp = 0.0f;
  1271. }
  1272. inline float CCSBot::GetNoiseRange( void ) const
  1273. {
  1274. if (IsNoiseHeard())
  1275. return m_noiseTravelDistance;
  1276. return 999999999.9f;
  1277. }
  1278. inline PriorityType CCSBot::GetNoisePriority( void ) const
  1279. {
  1280. return m_noisePriority;
  1281. }
  1282. inline BotChatterInterface *CCSBot::GetChatter( void )
  1283. {
  1284. return m_pChatter;
  1285. }
  1286. inline CCSPlayer *CCSBot::GetBotEnemy( void ) const
  1287. {
  1288. return m_enemy;
  1289. }
  1290. inline int CCSBot::GetNearbyEnemyCount( void ) const
  1291. {
  1292. return MIN( GetEnemiesRemaining(), m_nearbyEnemyCount );
  1293. }
  1294. inline unsigned int CCSBot::GetEnemyPlace( void ) const
  1295. {
  1296. return m_enemyPlace;
  1297. }
  1298. inline bool CCSBot::CanSeeBomber( void ) const
  1299. {
  1300. return (m_bomber == NULL) ? false : true;
  1301. }
  1302. inline CCSPlayer *CCSBot::GetBomber( void ) const
  1303. {
  1304. return m_bomber;
  1305. }
  1306. inline int CCSBot::GetNearbyFriendCount( void ) const
  1307. {
  1308. return MIN( GetFriendsRemaining(), m_nearbyFriendCount );
  1309. }
  1310. inline CCSPlayer *CCSBot::GetClosestVisibleFriend( void ) const
  1311. {
  1312. return m_closestVisibleFriend;
  1313. }
  1314. inline CCSPlayer *CCSBot::GetClosestVisibleHumanFriend( void ) const
  1315. {
  1316. return m_closestVisibleHumanFriend;
  1317. }
  1318. inline float CCSBot::GetTimeSinceAttacked( void ) const
  1319. {
  1320. return gpGlobals->curtime - m_attackedTimestamp;
  1321. }
  1322. inline float CCSBot::GetFirstSawEnemyTimestamp( void ) const
  1323. {
  1324. return m_firstSawEnemyTimestamp;
  1325. }
  1326. inline float CCSBot::GetLastSawEnemyTimestamp( void ) const
  1327. {
  1328. return m_lastSawEnemyTimestamp;
  1329. }
  1330. inline float CCSBot::GetTimeSinceLastSawEnemy( void ) const
  1331. {
  1332. return gpGlobals->curtime - m_lastSawEnemyTimestamp;
  1333. }
  1334. inline float CCSBot::GetTimeSinceAcquiredCurrentEnemy( void ) const
  1335. {
  1336. return gpGlobals->curtime - m_currentEnemyAcquireTimestamp;
  1337. }
  1338. inline float CCSBot::GetTimeSinceBurnedByFlames( void ) const
  1339. {
  1340. return m_burnedByFlamesTimer.GetElapsedTime();
  1341. }
  1342. inline const Vector &CCSBot::GetLastKnownEnemyPosition( void ) const
  1343. {
  1344. return m_lastEnemyPosition;
  1345. }
  1346. inline bool CCSBot::IsEnemyVisible( void ) const
  1347. {
  1348. return m_isEnemyVisible;
  1349. }
  1350. inline float CCSBot::GetEnemyDeathTimestamp( void ) const
  1351. {
  1352. return m_enemyDeathTimestamp;
  1353. }
  1354. inline int CCSBot::GetLastVictimID( void ) const
  1355. {
  1356. return m_lastVictimID;
  1357. }
  1358. inline bool CCSBot::CanSeeSniper( void ) const
  1359. {
  1360. return m_isEnemySniperVisible;
  1361. }
  1362. inline bool CCSBot::HasSeenSniperRecently( void ) const
  1363. {
  1364. return !m_sawEnemySniperTimer.IsElapsed();
  1365. }
  1366. inline float CCSBot::GetTravelDistanceToPlayer( CCSPlayer *player ) const
  1367. {
  1368. if (player == NULL)
  1369. return -1.0f;
  1370. if (!player->IsAlive())
  1371. return -1.0f;
  1372. return m_playerTravelDistance[ player->entindex() % MAX_PLAYERS ];
  1373. }
  1374. inline bool CCSBot::HasPath( void ) const
  1375. {
  1376. return (m_pathLength) ? true : false;
  1377. }
  1378. inline void CCSBot::DestroyPath( void )
  1379. {
  1380. m_isStopping = false;
  1381. m_pathLength = 0;
  1382. m_pathLadder = NULL;
  1383. }
  1384. inline const Vector &CCSBot::GetPathEndpoint( void ) const
  1385. {
  1386. return m_path[ m_pathLength-1 ].pos;
  1387. }
  1388. inline const Vector &CCSBot::GetPathPosition( int index ) const
  1389. {
  1390. return m_path[ index ].pos;
  1391. }
  1392. inline bool CCSBot::IsUsingLadder( void ) const
  1393. {
  1394. return (m_pathLadder) ? true : false;
  1395. }
  1396. inline void CCSBot::SetGoalEntity( CBaseEntity *entity )
  1397. {
  1398. m_goalEntity = entity;
  1399. }
  1400. inline CBaseEntity *CCSBot::GetGoalEntity( void )
  1401. {
  1402. return m_goalEntity;
  1403. }
  1404. inline void CCSBot::ForceRun( float duration )
  1405. {
  1406. Run();
  1407. m_mustRunTimer.Start( duration );
  1408. }
  1409. inline void CCSBot::Wait( float duration )
  1410. {
  1411. m_waitTimer.Start( duration );
  1412. }
  1413. inline bool CCSBot::IsWaiting( void ) const
  1414. {
  1415. return !m_waitTimer.IsElapsed();
  1416. }
  1417. inline void CCSBot::StopWaiting( void )
  1418. {
  1419. m_waitTimer.Invalidate();
  1420. }
  1421. inline bool CCSBot::HasVisitedEnemySpawn( void ) const
  1422. {
  1423. return m_hasVisitedEnemySpawn;
  1424. }
  1425. inline const Vector &CCSBot::EyePositionConst( void ) const
  1426. {
  1427. return m_eyePosition;
  1428. }
  1429. inline void CCSBot::SetLookAngles( float yaw, float pitch )
  1430. {
  1431. m_lookYaw = yaw;
  1432. m_lookPitch = pitch;
  1433. }
  1434. inline void CCSBot::SetForwardAngle( float angle )
  1435. {
  1436. m_forwardAngle = angle;
  1437. }
  1438. inline void CCSBot::SetLookAheadAngle( float angle )
  1439. {
  1440. m_lookAheadAngle = angle;
  1441. }
  1442. inline void CCSBot::ClearLookAt( void )
  1443. {
  1444. //PrintIfWatched( "ClearLookAt()\n" );
  1445. m_lookAtSpotState = NOT_LOOKING_AT_SPOT;
  1446. m_lookAtDesc = NULL;
  1447. }
  1448. inline bool CCSBot::IsLookingAtSpot( PriorityType pri ) const
  1449. {
  1450. if (m_lookAtSpotState != NOT_LOOKING_AT_SPOT && m_lookAtSpotPriority >= pri)
  1451. return true;
  1452. return false;
  1453. }
  1454. inline bool CCSBot::IsViewMoving( float angleVelThreshold ) const
  1455. {
  1456. if (m_lookYawVel < angleVelThreshold && m_lookYawVel > -angleVelThreshold &&
  1457. m_lookPitchVel < angleVelThreshold && m_lookPitchVel > -angleVelThreshold)
  1458. {
  1459. return false;
  1460. }
  1461. return true;
  1462. }
  1463. inline bool CCSBot::HasViewBeenSteady( float duration ) const
  1464. {
  1465. return (m_viewSteadyTimer.GetElapsedTime() > duration);
  1466. }
  1467. inline bool CCSBot::HasLookAtTarget( void ) const
  1468. {
  1469. return (m_lookAtSpotState != NOT_LOOKING_AT_SPOT);
  1470. }
  1471. inline bool CCSBot::IsEnemyPartVisible( VisiblePartType part ) const
  1472. {
  1473. VPROF_BUDGET( "CCSBot::IsEnemyPartVisible", VPROF_BUDGETGROUP_NPCS );
  1474. if (!IsEnemyVisible())
  1475. return false;
  1476. return (m_visibleEnemyParts & part) ? true : false;
  1477. }
  1478. inline bool CCSBot::IsSignificantlyCloser( const CCSPlayer *testPlayer, const CCSPlayer *referencePlayer ) const
  1479. {
  1480. if ( !referencePlayer )
  1481. return true;
  1482. if ( !testPlayer )
  1483. return false;
  1484. float testDist = ( GetAbsOrigin() - testPlayer->GetAbsOrigin() ).Length();
  1485. float referenceDist = ( GetAbsOrigin() - referencePlayer->GetAbsOrigin() ).Length();
  1486. const float significantRangeFraction = 0.7f;
  1487. if ( testDist < referenceDist * significantRangeFraction )
  1488. return true;
  1489. return false;
  1490. }
  1491. inline void CCSBot::ClearApproachPoints( void )
  1492. {
  1493. m_approachPointCount = 0;
  1494. }
  1495. inline const CNavArea *CCSBot::GetInitialEncounterArea( void ) const
  1496. {
  1497. return m_initialEncounterArea;
  1498. }
  1499. inline void CCSBot::SetInitialEncounterArea( const CNavArea *area )
  1500. {
  1501. m_initialEncounterArea = area;
  1502. }
  1503. inline bool CCSBot::IsThrowingGrenade( void ) const
  1504. {
  1505. return m_grenadeTossState != NOT_THROWING;
  1506. }
  1507. inline bool CCSBot::IsAvoidingGrenade( void ) const
  1508. {
  1509. return !m_isAvoidingGrenade.IsElapsed();
  1510. }
  1511. inline void CCSBot::PrimaryAttack( void )
  1512. {
  1513. // for now the bots only secondary attack with the revolver until I teach them to hold the fire button
  1514. CWeaponCSBase *weapon = GetActiveCSWeapon();
  1515. if ( weapon && weapon->IsRevolver() && CanActiveWeaponFire() )
  1516. {
  1517. BaseClass::SecondaryAttack();
  1518. return;
  1519. }
  1520. if ( IsUsingPistol() && !CanActiveWeaponFire() )
  1521. return;
  1522. BaseClass::PrimaryAttack();
  1523. }
  1524. inline CCSBot::ZoomType CCSBot::GetZoomLevel( void )
  1525. {
  1526. if (GetFOV() > 60.0f)
  1527. return NO_ZOOM;
  1528. if (GetFOV() > 25.0f)
  1529. return LOW_ZOOM;
  1530. return HIGH_ZOOM;
  1531. }
  1532. inline bool CCSBot::IsWaitingForZoom( void ) const
  1533. {
  1534. return !m_zoomTimer.IsElapsed();
  1535. }
  1536. inline int CCSBot::GetHostageEscortCount( void ) const
  1537. {
  1538. return m_hostageEscortCount;
  1539. }
  1540. inline void CCSBot::IncreaseHostageEscortCount( void )
  1541. {
  1542. ++m_hostageEscortCount;
  1543. }
  1544. inline void CCSBot::ResetWaitForHostagePatience( void )
  1545. {
  1546. m_isWaitingForHostage = false;
  1547. m_inhibitWaitingForHostageTimer.Invalidate();
  1548. }
  1549. inline bool CCSBot::IsUsingVoice() const
  1550. {
  1551. return m_voiceEndTimestamp > gpGlobals->curtime;
  1552. }
  1553. inline bool CCSBot::IsOpeningDoor( void ) const
  1554. {
  1555. return m_isOpeningDoor;
  1556. }
  1557. //--------------------------------------------------------------------------------------------------------------
  1558. /**
  1559. * Return true if the given weapon is a sniper rifle
  1560. */
  1561. inline bool IsSniperRifle( CWeaponCSBase *weapon )
  1562. {
  1563. if (weapon == NULL)
  1564. return false;
  1565. return weapon->IsKindOf(WEAPONTYPE_SNIPER_RIFLE);
  1566. }
  1567. //--------------------------------------------------------------------------------------------------------------
  1568. /**
  1569. * Functor used with NavAreaBuildPath()
  1570. */
  1571. class PathCost
  1572. {
  1573. public:
  1574. PathCost( CCSBot *bot, RouteType route = SAFEST_ROUTE )
  1575. {
  1576. m_bot = bot;
  1577. m_route = route;
  1578. float baseDangerFactor = CSGameRules()->IsPlayingGunGameTRBomb() ? 0.25f : 100.0f;
  1579. m_dangerFactor = (1.0f - (0.95f * m_bot->GetProfile()->GetAggression( ))) * baseDangerFactor;
  1580. }
  1581. // HPE_TODO[pmf]: check that these new parameters are okay to be ignored
  1582. float operator() ( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder, const CFuncElevator *elevator, float length )
  1583. {
  1584. float dangerFactor = m_dangerFactor;
  1585. if (fromArea == NULL)
  1586. {
  1587. if (m_route == FASTEST_ROUTE)
  1588. return 0.0f;
  1589. // first area in path, cost is just danger
  1590. return dangerFactor * area->GetDanger( m_bot->GetTeamNumber() );
  1591. }
  1592. else if ((fromArea->GetAttributes() & NAV_MESH_JUMP) && (area->GetAttributes() & NAV_MESH_JUMP))
  1593. {
  1594. // cannot actually walk in jump areas - disallow moving from jump area to jump area
  1595. return -1.0f;
  1596. }
  1597. if ( area->GetAttributes() & NAV_MESH_NO_HOSTAGES && m_bot->GetHostageEscortCount() )
  1598. {
  1599. // if we're leading hostages, don't try to go where they can't
  1600. return -1.0f;
  1601. }
  1602. else
  1603. {
  1604. // compute distance from previous area to this area
  1605. float dist;
  1606. if (ladder)
  1607. {
  1608. // ladders are slow to use
  1609. const float ladderPenalty = 1.0f; // 3.0f;
  1610. dist = ladderPenalty * ladder->m_length;
  1611. // if we are currently escorting hostages, avoid ladders (hostages are confused by them)
  1612. //if (m_bot->GetHostageEscortCount())
  1613. // dist *= 100.0f;
  1614. }
  1615. else
  1616. {
  1617. dist = (area->GetCenter() - fromArea->GetCenter()).Length();
  1618. }
  1619. // compute distance travelled along path so far
  1620. float cost = dist + fromArea->GetCostSoFar();
  1621. // add cost of "jump down" pain unless we're jumping into water
  1622. if (!area->IsUnderwater() && area->IsConnected( fromArea, NUM_DIRECTIONS ) == false)
  1623. {
  1624. // this is a "jump down" (one way drop) transition - estimate damage we will take to traverse it
  1625. float fallDistance = -fromArea->ComputeGroundHeightChange( area );
  1626. // if it's a drop-down ladder, estimate height from the bottom of the ladder to the lower area
  1627. if ( ladder && ladder->m_bottom.z < fromArea->GetCenter().z && ladder->m_bottom.z > area->GetCenter().z )
  1628. {
  1629. fallDistance = ladder->m_bottom.z - area->GetCenter().z;
  1630. }
  1631. float fallDamage = m_bot->GetApproximateFallDamage( fallDistance );
  1632. if (fallDamage > 0.0f)
  1633. {
  1634. // if the fall would kill us, don't use it
  1635. const float deathFallMargin = 10.0f;
  1636. if (fallDamage + deathFallMargin >= m_bot->GetHealth())
  1637. return -1.0f;
  1638. // if we need to get there in a hurry, ignore minor pain
  1639. const float painTolerance = 15.0f * m_bot->GetProfile()->GetAggression() + 10.0f;
  1640. if (m_route != FASTEST_ROUTE || fallDamage > painTolerance)
  1641. {
  1642. // cost is proportional to how much it hurts when we fall
  1643. // 10 points - not a big deal, 50 points - ouch!
  1644. cost += 100.0f * fallDamage * fallDamage;
  1645. }
  1646. }
  1647. }
  1648. // if this is a "crouch" or "walk" area, add penalty
  1649. if (area->GetAttributes() & (NAV_MESH_CROUCH | NAV_MESH_WALK))
  1650. {
  1651. // these areas are very slow to move through
  1652. float penalty = (m_route == FASTEST_ROUTE) ? 20.0f : 5.0f;
  1653. // avoid crouch areas if we are rescuing hostages
  1654. if ((area->GetAttributes() & NAV_MESH_CROUCH) && m_bot->GetHostageEscortCount())
  1655. {
  1656. penalty *= 3.0f;
  1657. }
  1658. cost += penalty * dist;
  1659. }
  1660. // if this is a "jump" area, add penalty
  1661. if (area->GetAttributes() & NAV_MESH_JUMP)
  1662. {
  1663. // jumping can slow you down
  1664. //const float jumpPenalty = (m_route == FASTEST_ROUTE) ? 100.0f : 0.5f;
  1665. const float jumpPenalty = 1.0f;
  1666. cost += jumpPenalty * dist;
  1667. }
  1668. // if this is an area to avoid, add penalty
  1669. if ( area->IsDamaging() )
  1670. {
  1671. const float damagingPenalty = 100.0f;
  1672. cost += damagingPenalty * dist;
  1673. }
  1674. // if this is an area to avoid, add penalty
  1675. if (area->GetAttributes() & NAV_MESH_AVOID)
  1676. {
  1677. const float avoidPenalty = 20.0f;
  1678. cost += avoidPenalty * dist;
  1679. }
  1680. if (m_route == SAFEST_ROUTE)
  1681. {
  1682. // add in the danger of this path - danger is per unit length traveled
  1683. cost += dist + ( dist * dangerFactor * area->GetDanger( m_bot->GetTeamNumber() ) );
  1684. }
  1685. // this term causes the same bot to choose different routes over time,
  1686. // but keep the same route for a period in case of repaths
  1687. int timeMod = (int)( gpGlobals->curtime / 10.0f ) + 1;
  1688. int uniqueID = ((size_t)area) >> 7; // areas are 128-byte aligned, so shift address over
  1689. // We just need a unique number approximately between 1 and 300, so take the mod 293 because it's prime
  1690. unsigned int nRandomCost = ( unsigned int )( m_bot->entindex() * uniqueID * timeMod ) % 293;
  1691. cost += 1.0f + (float)nRandomCost;
  1692. if (!m_bot->IsAttacking())
  1693. {
  1694. // add in cost of teammates in the way
  1695. // approximate density of teammates based on area
  1696. float size = (area->GetSizeX() + area->GetSizeY())/2.0f;
  1697. // degenerate check
  1698. if (size >= 1.0f)
  1699. {
  1700. // cost is proportional to the density of teammates in this area
  1701. const float costPerFriendPerUnit = 50000.0f;
  1702. cost += costPerFriendPerUnit * (float)area->GetPlayerCount( m_bot->GetTeamNumber() ) / size;
  1703. }
  1704. }
  1705. return cost;
  1706. }
  1707. }
  1708. private:
  1709. CCSBot * m_bot;
  1710. RouteType m_route;
  1711. float m_dangerFactor;
  1712. };
  1713. inline CCSBot *ToCSBot( CBaseEntity *pEntity )
  1714. {
  1715. CCSPlayer* pPlayer = ToCSPlayer( pEntity );
  1716. if ( !pPlayer || !pPlayer->IsBot() )
  1717. return NULL;
  1718. return dynamic_cast<CCSBot*>( pPlayer );
  1719. }
  1720. //--------------------------------------------------------------------------------------------------------------
  1721. //
  1722. // Prototypes
  1723. //
  1724. extern int GetBotFollowCount( CCSPlayer *leader );
  1725. extern const Vector *FindNearbyRetreatSpot( CCSBot *me, float maxRange = 250.0f );
  1726. extern const HidingSpot *FindInitialEncounterSpot( CBaseEntity *me, const Vector &searchOrigin, float enemyArriveTime, float maxRange, bool isSniper );
  1727. #endif // _CS_BOT_H_