Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. // bot_npc.h
  3. // A NextBot non-player derived actor
  4. // Michael Booth, November 2010
  5. #ifndef BOT_NPC_H
  6. #define BOT_NPC_H
  7. #ifdef OBSOLETE_USE_BOSS_ALPHA
  8. #include "NextBot.h"
  9. #include "NextBotBehavior.h"
  10. #include "NextBotGroundLocomotion.h"
  11. #include "Path/NextBotPathFollow.h"
  12. #include "bot_npc_body.h"
  13. #include "bot/map_entities/tf_spawner_boss.h"
  14. class CTFPlayer;
  15. class CBotNPC;
  16. //----------------------------------------------------------------------------
  17. class CBotNPCLocomotion : public NextBotGroundLocomotion
  18. {
  19. public:
  20. CBotNPCLocomotion( INextBot *bot );
  21. virtual ~CBotNPCLocomotion() { }
  22. virtual float GetRunSpeed( void ) const; // get maximum running speed
  23. virtual float GetStepHeight( void ) const; // if delta Z is greater than this, we have to jump to get up
  24. virtual float GetMaxJumpHeight( void ) const; // return maximum height of a jump
  25. virtual float GetMaxAcceleration( void ) const
  26. {
  27. return 2500.0f;
  28. }
  29. private:
  30. float m_runSpeed;
  31. };
  32. //----------------------------------------------------------------------------
  33. class CBotNPCIntention : public IIntention
  34. {
  35. public:
  36. CBotNPCIntention( CBotNPC *me );
  37. virtual ~CBotNPCIntention();
  38. virtual void Reset( void );
  39. virtual void Update( void );
  40. virtual QueryResultType IsPositionAllowed( const INextBot *me, const Vector &pos ) const; // is the a place we can be?
  41. virtual INextBotEventResponder *FirstContainedResponder( void ) const { return m_behavior; }
  42. virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const { return NULL; }
  43. private:
  44. Behavior< CBotNPC > *m_behavior;
  45. };
  46. //----------------------------------------------------------------------------
  47. class CBotNPCVision : public IVision
  48. {
  49. public:
  50. CBotNPCVision( INextBot *bot ) : IVision( bot )
  51. {
  52. }
  53. virtual ~CBotNPCVision() { }
  54. virtual bool IsIgnored( CBaseEntity *subject ) const; // return true to completely ignore this entity (may not be in sight when this is called)
  55. };
  56. //----------------------------------------------------------------------------
  57. class CBotNPCWeapon : public CBaseAnimating
  58. {
  59. public:
  60. CBotNPCWeapon( CBotNPC *owner )
  61. {
  62. m_owner = owner;
  63. }
  64. virtual ~CBotNPCWeapon() { }
  65. virtual void StartAttack( void ) { }
  66. virtual void Update( void ) { }
  67. private:
  68. CHandle< CBotNPC > m_owner;
  69. };
  70. //----------------------------------------------------------------------------
  71. class CBotNPCWeapon_Axe : public CBotNPCWeapon
  72. {
  73. public:
  74. DECLARE_CLASS( CBotNPCWeapon_Axe, CBotNPCWeapon );
  75. CBotNPCWeapon_Axe( CBotNPC *owner );
  76. virtual ~CBotNPCWeapon_Axe() { }
  77. virtual void StartAttack( void );
  78. virtual void Update( void );
  79. };
  80. //----------------------------------------------------------------------------
  81. //----------------------------------------------------------------------------
  82. class CBotNPCGetOffMe : public Action< CBotNPC >
  83. {
  84. public:
  85. virtual ActionResult< CBotNPC > OnStart( CBotNPC *me, Action< CBotNPC > *priorAction );
  86. virtual ActionResult< CBotNPC > Update( CBotNPC *me, float interval );
  87. virtual void OnEnd( CBotNPC *me, Action< CBotNPC > *nextAction );
  88. virtual const char *GetName( void ) const { return "GetOffMe"; } // return name of this action
  89. private:
  90. CountdownTimer m_timer;
  91. };
  92. //----------------------------------------------------------------------------
  93. //----------------------------------------------------------------------------
  94. class CBotNPC : public NextBotCombatCharacter
  95. {
  96. public:
  97. DECLARE_CLASS( CBotNPC, NextBotCombatCharacter );
  98. DECLARE_SERVERCLASS();
  99. CBotNPC();
  100. virtual ~CBotNPC();
  101. virtual void Precache();
  102. virtual void Spawn( void );
  103. virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
  104. // INextBot
  105. virtual CBotNPCIntention *GetIntentionInterface( void ) const { return m_intention; }
  106. virtual CBotNPCLocomotion *GetLocomotionInterface( void ) const { return m_locomotor; }
  107. virtual CBotNPCBody *GetBodyInterface( void ) const { return m_body; }
  108. virtual CBotNPCVision *GetVisionInterface( void ) const { return m_vision; }
  109. virtual void Update( void );
  110. virtual bool IsPotentiallyChaseable( CTFPlayer *victim );
  111. void SetSpawner( CTFSpawnerBoss *spawner ); // remember the spawner that created us
  112. CTFSpawnerBoss *GetSpawner( void ) const; // return the spawner that created us
  113. void Break( void ); // bust into gibs
  114. struct AttackerInfo
  115. {
  116. CHandle< CBaseCombatCharacter > m_attacker;
  117. float m_timestamp;
  118. float m_damage;
  119. bool m_wasCritical;
  120. };
  121. const CUtlVector< AttackerInfo > &GetAttackerVector( void ) const;
  122. void RememberAttacker( CBaseCombatCharacter *attacker, float damage, bool wasCritical );
  123. struct ThreatInfo
  124. {
  125. CHandle< CBaseCombatCharacter > m_who;
  126. float m_threat;
  127. };
  128. const ThreatInfo *GetMaxThreat( void ) const;
  129. const ThreatInfo *GetThreat( CBaseCombatCharacter *who ) const;
  130. void SwingAxe( void );
  131. void UpdateAxeSwing( void );
  132. bool IsSwingingAxe( void ) const;
  133. //----------------------------------
  134. enum Ability
  135. {
  136. CAN_BE_STUNNED = 0x01,
  137. CAN_NUKE = 0x02,
  138. CAN_ENRAGE = 0x04,
  139. CAN_FIRE_ROCKETS = 0x08,
  140. CAN_LAUNCH_STICKIES = 0x10,
  141. CAN_LAUNCH_MINIONS = 0x20,
  142. };
  143. virtual bool HasAbility( Ability ability ) const;
  144. virtual bool IsMiniBoss( void ) const { return false; }
  145. virtual float GetMoveSpeed( void ) const { return 300.0f; }
  146. virtual int GetRocketLaunchCount( void ) const { return 5; }
  147. virtual float GetRocketDamage( void ) const { return 25.0f; }
  148. virtual float GetRocketAimError( void ) const { return 1.81f; }
  149. virtual float GetRocketInterval( void ) const { return 0.3f; }
  150. virtual const char *GetRocketSoundEffect( void ) const { return "Weapon_RPG.Single"; }
  151. virtual float GetGrenadeInterval( void ) const { return 10.0f; }
  152. virtual float GetBecomeStunnedDamage( void ) const { return 500.0f; }
  153. //----------------------------------
  154. enum Condition
  155. {
  156. SHIELDED = 0x01,
  157. CHARGING = 0x02,
  158. STUNNED = 0x04,
  159. INVULNERABLE = 0x08,
  160. VULNERABLE_TO_STUN = 0x10,
  161. BUSY = 0x20,
  162. ENRAGED = 0x40,
  163. };
  164. bool IsBusy( void ) const; // returns true if we're in a condition that means we can't start another action
  165. void AddCondition( Condition c );
  166. void RemoveCondition( Condition c );
  167. bool IsInCondition( Condition c ) const;
  168. bool IsAttackTarget( CBaseCombatCharacter *target ) const;
  169. bool HasAttackTarget( void ) const;
  170. void SetAttackTarget( CBaseCombatCharacter *target, float duration = 0.0f );
  171. CBaseCombatCharacter *GetAttackTarget( void ) const;
  172. void LockAttackTarget( void ); // don't allow target to change until it is unlocked or the target is destroyed
  173. void UnlockAttackTarget( void );
  174. CBaseCombatCharacter *GetNearestVisibleEnemy( void ) const;
  175. void SetHomePosition( const Vector &pos );
  176. const Vector &GetHomePosition( void ) const;
  177. CBaseAnimating *GetWeapon( void ) const;
  178. CBaseAnimating *GetShield( void ) const;
  179. CountdownTimer *GetNukeTimer( void );
  180. CountdownTimer *GetGrenadeTimer( void );
  181. float GetReceivedDamagePerSecond( void ) const;
  182. float GetReceivedDamagePerSecondDelta( void ) const;
  183. void SetLaserTarget( CBaseEntity *target );
  184. CBaseEntity *GetLaserTarget( void ) const;
  185. void ClearStunDamage( void );
  186. void AccumulateStunDamage( float damage );
  187. float GetStunDamage( void ) const;
  188. CTFPlayer *GetClosestMinionPrisoner( void );
  189. bool IsPrisonerOfMinion( CBaseCombatCharacter *victim );
  190. void StartNukeEffect( void );
  191. void StopNukeEffect( void );
  192. float GetAge( void ) const; // how long have we been alive
  193. void CollectPlayersStandingOnMe( CUtlVector< CTFPlayer * > *playerVector );
  194. // Entity I/O
  195. void InputSpawn( inputdata_t &inputdata );
  196. COutputEvent m_outputOnStunned; // fired the boss becomes stunned
  197. private:
  198. CBotNPCIntention *m_intention;
  199. CBotNPCLocomotion *m_locomotor;
  200. CBotNPCBody *m_body;
  201. CBotNPCVision *m_vision;
  202. CHandle< CTFSpawnerBoss > m_spawner;
  203. CBaseAnimating *m_axe;
  204. CBaseAnimating *m_shield;
  205. void PrecacheArmorParts( void );
  206. void InstallArmorParts( void );
  207. CUtlVector< CBaseAnimating * > m_armorPartVector;
  208. CountdownTimer m_axeSwingTimer;
  209. CountdownTimer m_attackTimer;
  210. CountdownTimer m_nukeTimer;
  211. CountdownTimer m_grenadeTimer;
  212. CountdownTimer m_ouchTimer;
  213. CountdownTimer m_hateTauntTimer;
  214. CNetworkHandle( CBaseEntity, m_laserTarget );
  215. CNetworkVar( bool, m_isNuking );
  216. CHandle< CBaseCombatCharacter > m_nearestVisibleEnemy;
  217. void UpdateNearestVisibleEnemy( void );
  218. CountdownTimer m_nearestVisibleEnemyTimer;
  219. CUtlVector< AttackerInfo > m_attackerVector; // list of everyone who injured me, and when
  220. CUtlVector< ThreatInfo > m_threatVector; // list of attackers and their current damage/second on me
  221. float m_currentDamagePerSecond;
  222. float m_lastDamagePerSecond;
  223. void UpdateDamagePerSecond( void );
  224. CHandle< CBaseCombatCharacter > m_attackTarget;
  225. CountdownTimer m_attackTargetTimer;
  226. bool m_isAttackTargetLocked;
  227. void UpdateAttackTarget( void );
  228. int m_damagePoseParameter;
  229. bool m_isShielded;
  230. Vector m_homePos;
  231. bool IsIgnored( CTFPlayer *player ) const;
  232. unsigned int m_conditionFlags;
  233. float m_stunDamage;
  234. IntervalTimer m_ageTimer;
  235. };
  236. inline bool CBotNPC::HasAbility( Ability ability ) const
  237. {
  238. const int myAbilities = CAN_BE_STUNNED | CAN_NUKE | CAN_ENRAGE | CAN_FIRE_ROCKETS | CAN_LAUNCH_STICKIES | CAN_LAUNCH_MINIONS;
  239. return myAbilities & ability ? true : false;
  240. }
  241. inline void CBotNPC::SetSpawner( CTFSpawnerBoss *spawner )
  242. {
  243. m_spawner = spawner;
  244. }
  245. inline CTFSpawnerBoss *CBotNPC::GetSpawner( void ) const
  246. {
  247. return m_spawner;
  248. }
  249. inline bool CBotNPC::IsAttackTarget( CBaseCombatCharacter *target ) const
  250. {
  251. if ( HasAttackTarget() )
  252. {
  253. return ( m_attackTarget == target ) ? true : false;
  254. }
  255. return false;
  256. }
  257. inline bool CBotNPC::HasAttackTarget( void ) const
  258. {
  259. return ( m_attackTarget == NULL || !m_attackTarget->IsAlive() ) ? false : true;
  260. }
  261. inline void CBotNPC::LockAttackTarget( void )
  262. {
  263. m_isAttackTargetLocked = HasAttackTarget();
  264. }
  265. inline void CBotNPC::UnlockAttackTarget( void )
  266. {
  267. m_isAttackTargetLocked = false;
  268. }
  269. inline float CBotNPC::GetAge( void ) const
  270. {
  271. return m_ageTimer.GetElapsedTime();
  272. }
  273. inline void CBotNPC::StartNukeEffect( void )
  274. {
  275. m_isNuking = true;
  276. }
  277. inline void CBotNPC::StopNukeEffect( void )
  278. {
  279. m_isNuking = false;
  280. }
  281. inline void CBotNPC::ClearStunDamage( void )
  282. {
  283. m_stunDamage = 0.0f;
  284. }
  285. inline void CBotNPC::AccumulateStunDamage( float damage )
  286. {
  287. m_stunDamage += damage;
  288. }
  289. inline float CBotNPC::GetStunDamage( void ) const
  290. {
  291. return m_stunDamage;
  292. }
  293. inline void CBotNPC::SetLaserTarget( CBaseEntity *target )
  294. {
  295. m_laserTarget = target;
  296. }
  297. inline CBaseEntity *CBotNPC::GetLaserTarget( void ) const
  298. {
  299. return m_laserTarget;
  300. }
  301. inline float CBotNPC::GetReceivedDamagePerSecond( void ) const
  302. {
  303. return m_currentDamagePerSecond;
  304. }
  305. inline float CBotNPC::GetReceivedDamagePerSecondDelta( void ) const
  306. {
  307. return m_currentDamagePerSecond - m_lastDamagePerSecond;
  308. }
  309. inline CountdownTimer *CBotNPC::GetNukeTimer( void )
  310. {
  311. return &m_nukeTimer;
  312. }
  313. inline CountdownTimer *CBotNPC::GetGrenadeTimer( void )
  314. {
  315. return &m_grenadeTimer;
  316. }
  317. inline CBaseAnimating *CBotNPC::GetWeapon( void ) const
  318. {
  319. return m_axe;
  320. }
  321. inline CBaseAnimating *CBotNPC::GetShield( void ) const
  322. {
  323. return m_shield;
  324. }
  325. inline void CBotNPC::SetHomePosition( const Vector &pos )
  326. {
  327. m_homePos = pos;
  328. }
  329. inline const Vector &CBotNPC::GetHomePosition( void ) const
  330. {
  331. return m_homePos;
  332. }
  333. inline CBaseCombatCharacter *CBotNPC::GetNearestVisibleEnemy( void ) const
  334. {
  335. return m_nearestVisibleEnemy;
  336. }
  337. inline void CBotNPC::AddCondition( Condition c )
  338. {
  339. m_conditionFlags |= c;
  340. }
  341. inline bool CBotNPC::IsInCondition( Condition c ) const
  342. {
  343. return ( m_conditionFlags & c ) ? true : false;
  344. }
  345. inline const CUtlVector< CBotNPC::AttackerInfo > &CBotNPC::GetAttackerVector( void ) const
  346. {
  347. return m_attackerVector;
  348. }
  349. //--------------------------------------------------------------------------------------------------------------
  350. class CBotNPCPathCost : public IPathCost
  351. {
  352. public:
  353. CBotNPCPathCost( CBotNPC *me )
  354. {
  355. m_me = me;
  356. }
  357. // return the cost (weighted distance between) of moving from "fromArea" to "area", or -1 if the move is not allowed
  358. virtual float operator()( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder, const CFuncElevator *elevator, float length ) const
  359. {
  360. if ( fromArea == NULL )
  361. {
  362. // first area in path, no cost
  363. return 0.0f;
  364. }
  365. else
  366. {
  367. if ( !m_me->GetLocomotionInterface()->IsAreaTraversable( area ) )
  368. {
  369. // our locomotor says we can't move here
  370. return -1.0f;
  371. }
  372. // compute distance traveled along path so far
  373. float dist;
  374. if ( ladder )
  375. {
  376. dist = ladder->m_length;
  377. }
  378. else if ( length > 0.0 )
  379. {
  380. // optimization to avoid recomputing length
  381. dist = length;
  382. }
  383. else
  384. {
  385. dist = ( area->GetCenter() - fromArea->GetCenter() ).Length();
  386. }
  387. float cost = dist + fromArea->GetCostSoFar();
  388. // check height change
  389. float deltaZ = fromArea->ComputeAdjacentConnectionHeightChange( area );
  390. if ( deltaZ >= m_me->GetLocomotionInterface()->GetStepHeight() )
  391. {
  392. if ( deltaZ >= m_me->GetLocomotionInterface()->GetMaxJumpHeight() )
  393. {
  394. // too high to reach
  395. return -1.0f;
  396. }
  397. // jumping is slower than flat ground
  398. const float jumpPenalty = 5.0f;
  399. cost += jumpPenalty * dist;
  400. }
  401. else if ( deltaZ < -m_me->GetLocomotionInterface()->GetDeathDropHeight() )
  402. {
  403. // too far to drop
  404. return -1.0f;
  405. }
  406. return cost;
  407. }
  408. }
  409. CBotNPC *m_me;
  410. };
  411. #endif // #ifdef OBSOLETE_USE_BOSS_ALPHA
  412. #endif // BOT_NPC_H