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.

862 lines
26 KiB

  1. // NextBotPlayer.h
  2. // A CBasePlayer bot based on the NextBot technology
  3. // Author: Michael Booth, November 2005
  4. // Copyright (c) 2007 Turtle Rock Studios, Inc. - All Rights Reserved
  5. #ifndef _NEXT_BOT_PLAYER_H_
  6. #define _NEXT_BOT_PLAYER_H_
  7. #include "cbase.h"
  8. #include "gameinterface.h"
  9. #include "NextBot.h"
  10. #include "Path/NextBotPathFollow.h"
  11. //#include "NextBotPlayerBody.h"
  12. #include "NextBotBehavior.h"
  13. #include "in_buttons.h"
  14. extern ConVar NextBotPlayerStop;
  15. extern ConVar NextBotPlayerWalk;
  16. extern ConVar NextBotPlayerCrouch;
  17. extern ConVar NextBotPlayerMove;
  18. //--------------------------------------------------------------------------------------------------
  19. /**
  20. * Instantiate a NextBot derived from CBasePlayer and spawn it into the environment.
  21. * Assumes class T is derived from CBasePlayer, and has the following method that
  22. * creates a new entity of type T and returns it:
  23. *
  24. * static CBasePlayer *T::AllocatePlayerEntity( edict_t *pEdict, const char *playerName )
  25. *
  26. */
  27. template < typename T >
  28. T * NextBotCreatePlayerBot( const char *name )
  29. {
  30. /*
  31. if ( UTIL_ClientsInGame() >= gpGlobals->maxClients )
  32. {
  33. Msg( "CreatePlayerBot: Failed - server is full (%d/%d clients).\n", UTIL_ClientsInGame(), gpGlobals->maxClients );
  34. return NULL;
  35. }
  36. */
  37. // This is a "back door" for allocating a custom player bot entity when
  38. // the engine calls ClientPutInServer (from CreateFakeClient)
  39. ClientPutInServerOverride( T::AllocatePlayerEntity );
  40. // create the bot and spawn it into the environment
  41. edict_t *botEdict = engine->CreateFakeClient( name );
  42. // close the "back door"
  43. ClientPutInServerOverride( NULL );
  44. if ( botEdict == NULL )
  45. {
  46. Msg( "CreatePlayerBot: Unable to create bot %s - CreateFakeClient() returned NULL.\n", name );
  47. return NULL;
  48. }
  49. // create an instance of the bot's class and bind it to the edict
  50. T *bot = dynamic_cast< T * >( CBaseEntity::Instance( botEdict ) );
  51. if ( bot == NULL )
  52. {
  53. Assert( false );
  54. Error( "CreatePlayerBot: Could not Instance() from the bot edict.\n" );
  55. return NULL;
  56. }
  57. // set the fakeclient's name
  58. // char trimmedName[ MAX_PLAYER_NAME_LENGTH ];
  59. // Q_strncpy( trimmedName, name, sizeof( trimmedName ) );
  60. // bot->PlayerData()->netname = AllocPooledString( trimmedName );
  61. bot->SetPlayerName( name );
  62. // flag this as a fakeclient (bot)
  63. bot->ClearFlags();
  64. bot->AddFlag( FL_CLIENT | FL_FAKECLIENT );
  65. return bot;
  66. }
  67. //--------------------------------------------------------------------------------------------------
  68. /**
  69. * Interface to access player input buttons.
  70. * Unless a duration is given, each button is released at the start of the next frame.
  71. * The release methods allow releasing a button before its duration has elapsed.
  72. */
  73. class INextBotPlayerInput
  74. {
  75. public:
  76. virtual void PressFireButton( float duration = -1.0f ) = 0;
  77. virtual void ReleaseFireButton( void ) = 0;
  78. virtual void PressAltFireButton( float duration = -1.0f ) = 0;
  79. virtual void ReleaseAltFireButton( void ) = 0;
  80. virtual void PressMeleeButton( float duration = -1.0f ) = 0;
  81. virtual void ReleaseMeleeButton( void ) = 0;
  82. virtual void PressUseButton( float duration = -1.0f ) = 0;
  83. virtual void ReleaseUseButton( void ) = 0;
  84. virtual void PressReloadButton( float duration = -1.0f ) = 0;
  85. virtual void ReleaseReloadButton( void ) = 0;
  86. virtual void PressForwardButton( float duration = -1.0f ) = 0;
  87. virtual void ReleaseForwardButton( void ) = 0;
  88. virtual void PressBackwardButton( float duration = -1.0f ) = 0;
  89. virtual void ReleaseBackwardButton( void ) = 0;
  90. virtual void PressLeftButton( float duration = -1.0f ) = 0;
  91. virtual void ReleaseLeftButton( void ) = 0;
  92. virtual void PressRightButton( float duration = -1.0f ) = 0;
  93. virtual void ReleaseRightButton( void ) = 0;
  94. virtual void PressJumpButton( float duration = -1.0f ) = 0;
  95. virtual void ReleaseJumpButton( void ) = 0;
  96. virtual void PressCrouchButton( float duration = -1.0f ) = 0;
  97. virtual void ReleaseCrouchButton( void ) = 0;
  98. virtual void PressWalkButton( float duration = -1.0f ) = 0;
  99. virtual void ReleaseWalkButton( void ) = 0;
  100. virtual void SetButtonScale( float forward, float right ) = 0;
  101. };
  102. //--------------------------------------------------------------------------------------------------
  103. /**
  104. * Drive a CBasePlayer-derived entity via NextBot logic
  105. */
  106. template < typename PlayerType >
  107. class NextBotPlayer : public PlayerType, public INextBot, public INextBotPlayerInput
  108. {
  109. public:
  110. DECLARE_CLASS( NextBotPlayer, PlayerType );
  111. NextBotPlayer( void );
  112. virtual ~NextBotPlayer();
  113. virtual void Spawn( void );
  114. virtual void PhysicsSimulate( void );
  115. virtual bool IsNetClient( void ) const { return false; } // Bots should return FALSE for this, they can't receive NET messages
  116. virtual bool IsFakeClient( void ) const { return true; }
  117. virtual bool IsBot( void ) const { return true; }
  118. virtual INextBot *MyNextBotPointer( void ) { return this; }
  119. // this is valid because the templatized PlayerType must be derived from CBasePlayer, which is derived from CBaseCombatCharacter
  120. virtual CBaseCombatCharacter *GetEntity( void ) const { return ( PlayerType * )this; }
  121. virtual bool IsRemovedOnReset( void ) const { return false; } // remove this bot when the NextBot manager calls Reset
  122. virtual bool IsDormantWhenDead( void ) const { return true; } // should this player-bot continue to update itself when dead (respawn logic, etc)
  123. // allocate a bot and bind it to the edict
  124. static CBasePlayer *AllocatePlayerEntity( edict_t *edict, const char *playerName );
  125. //------------------------------------------------------------------------
  126. // utility methods
  127. float GetDistanceBetween( CBaseEntity *other ) const; // return distance between us and the given entity
  128. bool IsDistanceBetweenLessThan( CBaseEntity *other, float range ) const; // return true if distance between is less than the given value
  129. bool IsDistanceBetweenGreaterThan( CBaseEntity *other, float range ) const; // return true if distance between is greater than the given value
  130. float GetDistanceBetween( const Vector &target ) const; // return distance between us and the given entity
  131. bool IsDistanceBetweenLessThan( const Vector &target, float range ) const; // return true if distance between is less than the given value
  132. bool IsDistanceBetweenGreaterThan( const Vector &target, float range ) const; // return true if distance between is greater than the given value
  133. //------------------------------------------------------------------------
  134. // INextBotPlayerInput
  135. virtual void PressFireButton( float duration = -1.0f );
  136. virtual void ReleaseFireButton( void );
  137. virtual void PressAltFireButton( float duration = -1.0f );
  138. virtual void ReleaseAltFireButton( void );
  139. virtual void PressMeleeButton( float duration = -1.0f );
  140. virtual void ReleaseMeleeButton( void );
  141. virtual void PressUseButton( float duration = -1.0f );
  142. virtual void ReleaseUseButton( void );
  143. virtual void PressReloadButton( float duration = -1.0f );
  144. virtual void ReleaseReloadButton( void );
  145. virtual void PressForwardButton( float duration = -1.0f );
  146. virtual void ReleaseForwardButton( void );
  147. virtual void PressBackwardButton( float duration = -1.0f );
  148. virtual void ReleaseBackwardButton( void );
  149. virtual void PressLeftButton( float duration = -1.0f );
  150. virtual void ReleaseLeftButton( void );
  151. virtual void PressRightButton( float duration = -1.0f );
  152. virtual void ReleaseRightButton( void );
  153. virtual void PressJumpButton( float duration = -1.0f );
  154. virtual void ReleaseJumpButton( void );
  155. virtual void PressCrouchButton( float duration = -1.0f );
  156. virtual void ReleaseCrouchButton( void );
  157. virtual void PressWalkButton( float duration = -1.0f );
  158. virtual void ReleaseWalkButton( void );
  159. virtual void SetButtonScale( float forward, float right );
  160. //------------------------------------------------------------------------
  161. // Event hooks into NextBot system
  162. virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
  163. virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info );
  164. virtual void Event_Killed( const CTakeDamageInfo &info );
  165. virtual void HandleAnimEvent( animevent_t *event );
  166. virtual void OnNavAreaChanged( CNavArea *enteredArea, CNavArea *leftArea ); // invoked (by UpdateLastKnownArea) when we enter a new nav area (or it is reset to NULL)
  167. virtual void Touch( CBaseEntity *other );
  168. virtual void Weapon_Equip( CBaseCombatWeapon *weapon ); // for OnPickUp
  169. virtual void Weapon_Drop( CBaseCombatWeapon *weapon, const Vector *target, const Vector *velocity ); // for OnDrop
  170. virtual void OnMainActivityComplete( Activity newActivity, Activity oldActivity );
  171. virtual void OnMainActivityInterrupted( Activity newActivity, Activity oldActivity );
  172. //------------------------------------------------------------------------
  173. bool IsAbleToAutoCenterOnLadders( void ) const;
  174. public:
  175. // begin INextBot ------------------------------------------------------------------------------------------------------------------
  176. virtual void Update( void ); // (EXTEND) update internal state
  177. protected:
  178. int m_inputButtons; // this is still needed to guarantee each button press is captured at least once
  179. int m_prevInputButtons;
  180. CountdownTimer m_fireButtonTimer;
  181. CountdownTimer m_meleeButtonTimer;
  182. CountdownTimer m_useButtonTimer;
  183. CountdownTimer m_reloadButtonTimer;
  184. CountdownTimer m_forwardButtonTimer;
  185. CountdownTimer m_backwardButtonTimer;
  186. CountdownTimer m_leftButtonTimer;
  187. CountdownTimer m_rightButtonTimer;
  188. CountdownTimer m_jumpButtonTimer;
  189. CountdownTimer m_crouchButtonTimer;
  190. CountdownTimer m_walkButtonTimer;
  191. CountdownTimer m_buttonScaleTimer;
  192. IntervalTimer m_burningTimer; // how long since we were last burning
  193. float m_forwardScale;
  194. float m_rightScale;
  195. };
  196. template < typename PlayerType >
  197. inline float NextBotPlayer< PlayerType >::GetDistanceBetween( CBaseEntity *other ) const
  198. {
  199. return (this->GetAbsOrigin() - other->GetAbsOrigin()).Length();
  200. }
  201. template < typename PlayerType >
  202. inline bool NextBotPlayer< PlayerType >::IsDistanceBetweenLessThan( CBaseEntity *other, float range ) const
  203. {
  204. return (this->GetAbsOrigin() - other->GetAbsOrigin()).IsLengthLessThan( range );
  205. }
  206. template < typename PlayerType >
  207. inline bool NextBotPlayer< PlayerType >::IsDistanceBetweenGreaterThan( CBaseEntity *other, float range ) const
  208. {
  209. return (this->GetAbsOrigin() - other->GetAbsOrigin()).IsLengthGreaterThan( range );
  210. }
  211. template < typename PlayerType >
  212. inline float NextBotPlayer< PlayerType >::GetDistanceBetween( const Vector &target ) const
  213. {
  214. return (this->GetAbsOrigin() - target).Length();
  215. }
  216. template < typename PlayerType >
  217. inline bool NextBotPlayer< PlayerType >::IsDistanceBetweenLessThan( const Vector &target, float range ) const
  218. {
  219. return (this->GetAbsOrigin() - target).IsLengthLessThan( range );
  220. }
  221. template < typename PlayerType >
  222. inline bool NextBotPlayer< PlayerType >::IsDistanceBetweenGreaterThan( const Vector &target, float range ) const
  223. {
  224. return (this->GetAbsOrigin() - target).IsLengthGreaterThan( range );
  225. }
  226. template < typename PlayerType >
  227. inline void NextBotPlayer< PlayerType >::PressFireButton( float duration )
  228. {
  229. m_inputButtons |= IN_ATTACK;
  230. m_fireButtonTimer.Start( duration );
  231. }
  232. template < typename PlayerType >
  233. inline void NextBotPlayer< PlayerType >::ReleaseFireButton( void )
  234. {
  235. m_inputButtons &= ~IN_ATTACK;
  236. m_fireButtonTimer.Invalidate();
  237. }
  238. template < typename PlayerType >
  239. inline void NextBotPlayer< PlayerType >::PressAltFireButton( float duration )
  240. {
  241. PressMeleeButton( duration );
  242. }
  243. template < typename PlayerType >
  244. inline void NextBotPlayer< PlayerType >::ReleaseAltFireButton( void )
  245. {
  246. ReleaseMeleeButton();
  247. }
  248. template < typename PlayerType >
  249. inline void NextBotPlayer< PlayerType >::PressMeleeButton( float duration )
  250. {
  251. m_inputButtons |= IN_ATTACK2;
  252. m_meleeButtonTimer.Start( duration );
  253. }
  254. template < typename PlayerType >
  255. inline void NextBotPlayer< PlayerType >::ReleaseMeleeButton( void )
  256. {
  257. m_inputButtons &= ~IN_ATTACK2;
  258. m_meleeButtonTimer.Invalidate();
  259. }
  260. template < typename PlayerType >
  261. inline void NextBotPlayer< PlayerType >::PressUseButton( float duration )
  262. {
  263. m_inputButtons |= IN_USE;
  264. m_useButtonTimer.Start( duration );
  265. }
  266. template < typename PlayerType >
  267. inline void NextBotPlayer< PlayerType >::ReleaseUseButton( void )
  268. {
  269. m_inputButtons &= ~IN_USE;
  270. m_useButtonTimer.Invalidate();
  271. }
  272. template < typename PlayerType >
  273. inline void NextBotPlayer< PlayerType >::PressReloadButton( float duration )
  274. {
  275. m_inputButtons |= IN_RELOAD;
  276. m_reloadButtonTimer.Start( duration );
  277. }
  278. template < typename PlayerType >
  279. inline void NextBotPlayer< PlayerType >::ReleaseReloadButton( void )
  280. {
  281. m_inputButtons &= ~IN_RELOAD;
  282. m_reloadButtonTimer.Invalidate();
  283. }
  284. template < typename PlayerType >
  285. inline void NextBotPlayer< PlayerType >::PressJumpButton( float duration )
  286. {
  287. m_inputButtons |= IN_JUMP;
  288. m_jumpButtonTimer.Start( duration );
  289. }
  290. template < typename PlayerType >
  291. inline void NextBotPlayer< PlayerType >::ReleaseJumpButton( void )
  292. {
  293. m_inputButtons &= ~IN_JUMP;
  294. m_jumpButtonTimer.Invalidate();
  295. }
  296. template < typename PlayerType >
  297. inline void NextBotPlayer< PlayerType >::PressCrouchButton( float duration )
  298. {
  299. m_inputButtons |= IN_DUCK;
  300. m_crouchButtonTimer.Start( duration );
  301. }
  302. template < typename PlayerType >
  303. inline void NextBotPlayer< PlayerType >::ReleaseCrouchButton( void )
  304. {
  305. m_inputButtons &= ~IN_DUCK;
  306. m_crouchButtonTimer.Invalidate();
  307. }
  308. template < typename PlayerType >
  309. inline void NextBotPlayer< PlayerType >::PressWalkButton( float duration )
  310. {
  311. m_inputButtons |= IN_SPEED;
  312. m_walkButtonTimer.Start( duration );
  313. }
  314. template < typename PlayerType >
  315. inline void NextBotPlayer< PlayerType >::ReleaseWalkButton( void )
  316. {
  317. m_inputButtons &= ~IN_SPEED;
  318. m_walkButtonTimer.Invalidate();
  319. }
  320. template < typename PlayerType >
  321. inline void NextBotPlayer< PlayerType >::PressForwardButton( float duration )
  322. {
  323. m_inputButtons |= IN_FORWARD;
  324. m_forwardButtonTimer.Start( duration );
  325. }
  326. template < typename PlayerType >
  327. inline void NextBotPlayer< PlayerType >::ReleaseForwardButton( void )
  328. {
  329. m_inputButtons &= ~IN_FORWARD;
  330. m_forwardButtonTimer.Invalidate();
  331. }
  332. template < typename PlayerType >
  333. inline void NextBotPlayer< PlayerType >::PressBackwardButton( float duration )
  334. {
  335. m_inputButtons |= IN_BACK;
  336. m_backwardButtonTimer.Start( duration );
  337. }
  338. template < typename PlayerType >
  339. inline void NextBotPlayer< PlayerType >::ReleaseBackwardButton( void )
  340. {
  341. m_inputButtons &= ~IN_BACK;
  342. m_backwardButtonTimer.Invalidate();
  343. }
  344. template < typename PlayerType >
  345. inline void NextBotPlayer< PlayerType >::PressLeftButton( float duration )
  346. {
  347. m_inputButtons |= IN_MOVELEFT;
  348. m_leftButtonTimer.Start( duration );
  349. }
  350. template < typename PlayerType >
  351. inline void NextBotPlayer< PlayerType >::ReleaseLeftButton( void )
  352. {
  353. m_inputButtons &= ~IN_MOVELEFT;
  354. m_leftButtonTimer.Invalidate();
  355. }
  356. template < typename PlayerType >
  357. inline void NextBotPlayer< PlayerType >::PressRightButton( float duration )
  358. {
  359. m_inputButtons |= IN_MOVERIGHT;
  360. m_rightButtonTimer.Start( duration );
  361. }
  362. template < typename PlayerType >
  363. inline void NextBotPlayer< PlayerType >::ReleaseRightButton( void )
  364. {
  365. m_inputButtons &= ~IN_MOVERIGHT;
  366. m_rightButtonTimer.Invalidate();
  367. }
  368. template < typename PlayerType >
  369. inline void NextBotPlayer< PlayerType >::SetButtonScale( float forward, float right )
  370. {
  371. m_forwardScale = forward;
  372. m_rightScale = right;
  373. m_buttonScaleTimer.Start( 0.01 );
  374. }
  375. //-----------------------------------------------------------------------------------------------------
  376. template < typename PlayerType >
  377. inline NextBotPlayer< PlayerType >::NextBotPlayer( void )
  378. {
  379. m_prevInputButtons = 0;
  380. m_inputButtons = 0;
  381. m_burningTimer.Invalidate();
  382. }
  383. //-----------------------------------------------------------------------------------------------------
  384. template < typename PlayerType >
  385. inline NextBotPlayer< PlayerType >::~NextBotPlayer()
  386. {
  387. }
  388. //-----------------------------------------------------------------------------------------------------
  389. template < typename PlayerType >
  390. inline void NextBotPlayer< PlayerType >::Spawn( void )
  391. {
  392. engine->SetFakeClientConVarValue( this->edict(), "cl_autohelp", "0" );
  393. m_prevInputButtons = m_inputButtons = 0;
  394. m_fireButtonTimer.Invalidate();
  395. m_meleeButtonTimer.Invalidate();
  396. m_useButtonTimer.Invalidate();
  397. m_reloadButtonTimer.Invalidate();
  398. m_forwardButtonTimer.Invalidate();
  399. m_backwardButtonTimer.Invalidate();
  400. m_leftButtonTimer.Invalidate();
  401. m_rightButtonTimer.Invalidate();
  402. m_jumpButtonTimer.Invalidate();
  403. m_crouchButtonTimer.Invalidate();
  404. m_walkButtonTimer.Invalidate();
  405. m_buttonScaleTimer.Invalidate();
  406. m_forwardScale = m_rightScale = 0.04;
  407. m_burningTimer.Invalidate();
  408. // reset first, because Spawn() may access various interfaces
  409. INextBot::Reset();
  410. BaseClass::Spawn();
  411. }
  412. //-----------------------------------------------------------------------------------------------------
  413. inline void _NextBot_BuildUserCommand( CUserCmd *cmd, const QAngle &viewangles, float forwardmove, float sidemove, float upmove, int buttons, byte impulse )
  414. {
  415. Q_memset( cmd, 0, sizeof( CUserCmd ) );
  416. cmd->command_number = gpGlobals->tickcount;
  417. cmd->forwardmove = forwardmove;
  418. cmd->sidemove = sidemove;
  419. cmd->upmove = upmove;
  420. cmd->buttons = buttons;
  421. cmd->impulse = impulse;
  422. VectorCopy( viewangles, cmd->viewangles );
  423. cmd->random_seed = random->RandomInt( 0, 0x7fffffff );
  424. }
  425. //-----------------------------------------------------------------------------------------------------
  426. template < typename PlayerType >
  427. inline void NextBotPlayer< PlayerType >::PhysicsSimulate( void )
  428. {
  429. VPROF( "NextBotPlayer::PhysicsSimulate" );
  430. if ( engine->IsPaused() )
  431. {
  432. // We're paused - don't add new commands
  433. PlayerType::PhysicsSimulate();
  434. return;
  435. }
  436. if ( ( IsDormantWhenDead() && PlayerType::m_lifeState == LIFE_DEAD ) || NextBotStop.GetBool() )
  437. {
  438. // death animation complete - nothing left to do except let PhysicsSimulate run PreThink etc
  439. PlayerType::PhysicsSimulate();
  440. return;
  441. }
  442. int inputButtons;
  443. //
  444. // Update bot behavior
  445. //
  446. if ( BeginUpdate() )
  447. {
  448. Update();
  449. // build button bits
  450. if ( !m_fireButtonTimer.IsElapsed() )
  451. m_inputButtons |= IN_ATTACK;
  452. if ( !m_meleeButtonTimer.IsElapsed() )
  453. m_inputButtons |= IN_ATTACK2;
  454. if ( !m_useButtonTimer.IsElapsed() )
  455. m_inputButtons |= IN_USE;
  456. if ( !m_reloadButtonTimer.IsElapsed() )
  457. m_inputButtons |= IN_RELOAD;
  458. if ( !m_forwardButtonTimer.IsElapsed() )
  459. m_inputButtons |= IN_FORWARD;
  460. if ( !m_backwardButtonTimer.IsElapsed() )
  461. m_inputButtons |= IN_BACK;
  462. if ( !m_leftButtonTimer.IsElapsed() )
  463. m_inputButtons |= IN_MOVELEFT;
  464. if ( !m_rightButtonTimer.IsElapsed() )
  465. m_inputButtons |= IN_MOVERIGHT;
  466. if ( !m_jumpButtonTimer.IsElapsed() )
  467. m_inputButtons |= IN_JUMP;
  468. if ( !m_crouchButtonTimer.IsElapsed() )
  469. m_inputButtons |= IN_DUCK;
  470. if ( !m_walkButtonTimer.IsElapsed() )
  471. m_inputButtons |= IN_SPEED;
  472. m_prevInputButtons = m_inputButtons;
  473. inputButtons = m_inputButtons;
  474. EndUpdate();
  475. }
  476. else
  477. {
  478. // HACK: Smooth out body animations
  479. GetBodyInterface()->Update();
  480. // keep buttons pressed between Update() calls (m_prevInputButtons),
  481. // and include any button presses that occurred this tick (m_inputButtons).
  482. inputButtons = m_prevInputButtons | m_inputButtons;
  483. }
  484. //
  485. // Convert NextBot locomotion and posture into
  486. // player commands
  487. //
  488. IBody *body = GetBodyInterface();
  489. ILocomotion *mover = GetLocomotionInterface();
  490. if ( body->IsActualPosture( IBody::CROUCH ) )
  491. {
  492. inputButtons |= IN_DUCK;
  493. }
  494. float forwardSpeed = 0.0f;
  495. float strafeSpeed = 0.0f;
  496. float verticalSpeed = ( m_inputButtons & IN_JUMP ) ? mover->GetRunSpeed() : 0.0f;
  497. if ( inputButtons & IN_FORWARD )
  498. {
  499. forwardSpeed = mover->GetRunSpeed();
  500. }
  501. else if ( inputButtons & IN_BACK )
  502. {
  503. forwardSpeed = -mover->GetRunSpeed();
  504. }
  505. if ( inputButtons & IN_MOVELEFT )
  506. {
  507. strafeSpeed = -mover->GetRunSpeed();
  508. }
  509. else if ( inputButtons & IN_MOVERIGHT )
  510. {
  511. strafeSpeed = mover->GetRunSpeed();
  512. }
  513. if ( NextBotPlayerWalk.GetBool() )
  514. {
  515. inputButtons |= IN_SPEED;
  516. }
  517. if ( NextBotPlayerCrouch.GetBool() )
  518. {
  519. inputButtons |= IN_DUCK;
  520. }
  521. if ( !m_buttonScaleTimer.IsElapsed() )
  522. {
  523. forwardSpeed = mover->GetRunSpeed() * m_forwardScale;
  524. strafeSpeed = mover->GetRunSpeed() * m_rightScale;
  525. }
  526. if ( !NextBotPlayerMove.GetBool() )
  527. {
  528. inputButtons &= ~(IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT | IN_JUMP );
  529. forwardSpeed = 0.0f;
  530. strafeSpeed = 0.0f;
  531. verticalSpeed = 0.0f;
  532. }
  533. QAngle angles = this->EyeAngles();
  534. #ifdef TERROR
  535. if ( IsStunned() )
  536. {
  537. inputButtons &= ~(IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT | IN_JUMP | IN_DUCK );
  538. }
  539. // "Look" in the direction we're climbing/stumbling etc. We can't do anything anyway, and it
  540. // keeps motion extraction working.
  541. if ( IsRenderYawOverridden() && IsMotionControlledXY( GetMainActivity() ) )
  542. {
  543. angles[YAW] = GetOverriddenRenderYaw();
  544. }
  545. #endif
  546. // construct a "command" to move the player
  547. CUserCmd userCmd;
  548. _NextBot_BuildUserCommand( &userCmd, angles, forwardSpeed, strafeSpeed, verticalSpeed, inputButtons, 0 );
  549. #ifdef TERROR
  550. AvoidPlayers( &userCmd );
  551. #endif
  552. // allocate a new command and add it to the player's list of command to process
  553. this->ProcessUsercmds( &userCmd, 1, 1, 0, false );
  554. m_inputButtons = 0;
  555. // actually execute player commands and do player physics
  556. PlayerType::PhysicsSimulate();
  557. }
  558. //----------------------------------------------------------------------------------------------------------
  559. template < typename PlayerType >
  560. inline void NextBotPlayer< PlayerType >::OnNavAreaChanged( CNavArea *enteredArea, CNavArea *leftArea )
  561. {
  562. // propagate into NextBot responders
  563. INextBotEventResponder::OnNavAreaChanged( enteredArea, leftArea );
  564. BaseClass::OnNavAreaChanged( enteredArea, leftArea );
  565. }
  566. //----------------------------------------------------------------------------------------------------------
  567. template < typename PlayerType >
  568. inline void NextBotPlayer< PlayerType >::Touch( CBaseEntity *other )
  569. {
  570. if ( ShouldTouch( other ) )
  571. {
  572. // propagate touch into NextBot event responders
  573. trace_t result;
  574. result = this->GetTouchTrace();
  575. OnContact( other, &result );
  576. }
  577. BaseClass::Touch( other );
  578. }
  579. //----------------------------------------------------------------------------------------------------------
  580. template < typename PlayerType >
  581. inline void NextBotPlayer< PlayerType >::Weapon_Equip( CBaseCombatWeapon *weapon )
  582. {
  583. #ifdef TERROR
  584. // TODO: Reimplement GetDroppingPlayer() into GetLastOwner()
  585. OnPickUp( weapon, weapon->GetDroppingPlayer() );
  586. #else
  587. OnPickUp( weapon, NULL );
  588. #endif
  589. BaseClass::Weapon_Equip( weapon );
  590. }
  591. //----------------------------------------------------------------------------------------------------------
  592. template < typename PlayerType >
  593. inline void NextBotPlayer< PlayerType >::Weapon_Drop( CBaseCombatWeapon *weapon, const Vector *target, const Vector *velocity )
  594. {
  595. OnDrop( weapon );
  596. BaseClass::Weapon_Drop( weapon, target, velocity );
  597. }
  598. //--------------------------------------------------------------------------------------------------------
  599. template < typename PlayerType >
  600. inline void NextBotPlayer< PlayerType >::OnMainActivityComplete( Activity newActivity, Activity oldActivity )
  601. {
  602. #ifdef TERROR
  603. BaseClass::OnMainActivityComplete( newActivity, oldActivity );
  604. #endif
  605. OnAnimationActivityComplete( oldActivity );
  606. }
  607. //--------------------------------------------------------------------------------------------------------
  608. template < typename PlayerType >
  609. inline void NextBotPlayer< PlayerType >::OnMainActivityInterrupted( Activity newActivity, Activity oldActivity )
  610. {
  611. #ifdef TERROR
  612. BaseClass::OnMainActivityInterrupted( newActivity, oldActivity );
  613. #endif
  614. OnAnimationActivityInterrupted( oldActivity );
  615. }
  616. //----------------------------------------------------------------------------------------------------------
  617. template < typename PlayerType >
  618. inline void NextBotPlayer< PlayerType >::Update( void )
  619. {
  620. // don't spend CPU updating if this Survivor is dead
  621. if ( ( this->IsAlive() || !IsDormantWhenDead() ) && !NextBotPlayerStop.GetBool() )
  622. {
  623. INextBot::Update();
  624. }
  625. }
  626. //----------------------------------------------------------------------------------------------------------
  627. template < typename PlayerType >
  628. inline bool NextBotPlayer< PlayerType >::IsAbleToAutoCenterOnLadders( void ) const
  629. {
  630. const ILocomotion *locomotion = GetLocomotionInterface();
  631. return locomotion && locomotion->IsAbleToAutoCenterOnLadder();
  632. }
  633. //----------------------------------------------------------------------------------------------------------
  634. template < typename PlayerType >
  635. inline int NextBotPlayer< PlayerType >::OnTakeDamage_Alive( const CTakeDamageInfo &info )
  636. {
  637. if ( info.GetDamageType() & DMG_BURN )
  638. {
  639. if ( !m_burningTimer.HasStarted() || m_burningTimer.IsGreaterThen( 1.0f ) )
  640. {
  641. // emit ignite event periodically as long as we are burning
  642. OnIgnite();
  643. m_burningTimer.Start();
  644. }
  645. }
  646. // propagate event to components
  647. OnInjured( info );
  648. return BaseClass::OnTakeDamage_Alive( info );
  649. }
  650. //----------------------------------------------------------------------------------------------------------
  651. template < typename PlayerType >
  652. inline int NextBotPlayer< PlayerType >::OnTakeDamage_Dying( const CTakeDamageInfo &info )
  653. {
  654. if ( info.GetDamageType() & DMG_BURN )
  655. {
  656. if ( !m_burningTimer.HasStarted() || m_burningTimer.IsGreaterThen( 1.0f ) )
  657. {
  658. // emit ignite event periodically as long as we are burning
  659. OnIgnite();
  660. m_burningTimer.Start();
  661. }
  662. }
  663. // propagate event to components
  664. OnInjured( info );
  665. return BaseClass::OnTakeDamage_Dying( info );
  666. }
  667. //----------------------------------------------------------------------------------------------------------
  668. template < typename PlayerType >
  669. inline void NextBotPlayer< PlayerType >::Event_Killed( const CTakeDamageInfo &info )
  670. {
  671. // propagate event to my components
  672. OnKilled( info );
  673. BaseClass::Event_Killed( info );
  674. }
  675. //----------------------------------------------------------------------------------------------------------
  676. template < typename PlayerType >
  677. inline void NextBotPlayer< PlayerType >::HandleAnimEvent( animevent_t *event )
  678. {
  679. // propagate event to components
  680. OnAnimationEvent( event );
  681. BaseClass::HandleAnimEvent( event );
  682. }
  683. #endif // _NEXT_BOT_PLAYER_H_