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.

437 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: The robots for use in the Robot Destruction TF2 game mode.
  4. //
  5. //=========================================================================//
  6. #ifndef ROBOT_DESTRUCTION_ROBOT_H
  7. #define ROBOT_DESTRUCTION_ROBOT_H
  8. #pragma once
  9. #include "cbase.h"
  10. #ifdef GAME_DLL
  11. #include "tf_shareddefs.h"
  12. #include "pathtrack.h"
  13. #include "NextBotGroundLocomotion.h"
  14. #include "NextBotIntentionInterface.h"
  15. #include "NextBotBehavior.h"
  16. #include "NextBot.h"
  17. #include "../server/NextBot/Path/NextBotPathFollow.h"
  18. #include "../server/NextBot/Path/NextBotPath.h"
  19. #include "../server/tf/halloween/headless_hatman_body.h"
  20. #include "tf_obj_dispenser.h"
  21. #else
  22. #include "c_obj_dispenser.h"
  23. #endif
  24. #ifdef CLIENT_DLL
  25. #define CTFRobotDestruction_Robot C_TFRobotDestruction_Robot
  26. #define CRobotDispenser C_RobotDispenser
  27. #endif
  28. #include "props_shared.h"
  29. enum eRobotType
  30. {
  31. ROBOT_TYPE_FRUSTUM = 0,
  32. ROBOT_TYPE_SPHERE,
  33. ROBOT_TYPE_KING,
  34. NUM_ROBOT_TYPES
  35. };
  36. enum eRobotUIState
  37. {
  38. ROBOT_STATE_INACIVE = 0,
  39. ROBOT_STATE_ACTIVE,
  40. ROBOT_STATE_DEAD,
  41. ROBOT_STATE_SHIELDED,
  42. NUM_ROBOT_STATES
  43. };
  44. struct RobotData_t
  45. {
  46. public:
  47. enum EStringDataKey_t
  48. {
  49. MODEL_KEY = 0,
  50. DAMAGED_MODEL_KEY,
  51. HURT_SOUND_KEY,
  52. DEATH_SOUND_KEY,
  53. COLLIDE_SOUND_KEY,
  54. IDLE_SOUND_KEY
  55. };
  56. enum EFloatDataKey_t
  57. {
  58. HEALTH_BAR_OFFSET_KEY
  59. };
  60. RobotData_t( const char* pszModelName
  61. , const char* pszDamagedModelName
  62. , const char *pszHurtSound
  63. , const char *pszDeathSound
  64. , const char *pszCollideSound
  65. , const char *pszIdleSound
  66. , float flHealthBarOffset )
  67. {
  68. m_stringMap.SetLessFunc( DefLessFunc(int) );
  69. m_floatMap.SetLessFunc( DefLessFunc(int) );
  70. m_stringMap.Insert( MODEL_KEY, pszModelName );
  71. m_stringMap.Insert( DAMAGED_MODEL_KEY, pszDamagedModelName );
  72. m_stringMap.Insert( HURT_SOUND_KEY, pszHurtSound );
  73. m_stringMap.Insert( DEATH_SOUND_KEY, pszDeathSound );
  74. m_stringMap.Insert( COLLIDE_SOUND_KEY, pszCollideSound );
  75. m_stringMap.Insert( IDLE_SOUND_KEY, pszIdleSound );
  76. m_floatMap.Insert( HEALTH_BAR_OFFSET_KEY, flHealthBarOffset );
  77. }
  78. const char* GetStringData( EStringDataKey_t key ) const
  79. {
  80. return GetData< const char * >( m_stringMap, (int)key );
  81. }
  82. float GetFloatData( EFloatDataKey_t key ) const
  83. {
  84. return GetData< float >( m_floatMap, (int)key );
  85. }
  86. void Precache();
  87. private:
  88. template< typename T >
  89. T GetData( const CUtlMap< int, T >& map, int nKey ) const
  90. {
  91. int nIndex = map.Find( nKey );
  92. if ( nIndex != map.InvalidIndex() )
  93. {
  94. return map.Element( nIndex );
  95. }
  96. AssertMsg1( 0, "No entry for key %d", nKey );
  97. return T(0);
  98. }
  99. CUtlMap< int, const char * > m_stringMap;
  100. CUtlMap< int, float > m_floatMap;
  101. };
  102. class CTFRobotDestruction_Robot;
  103. #ifdef GAME_DLL
  104. struct RobotSpawnData_t
  105. {
  106. RobotSpawnData_t()
  107. : m_eType( ROBOT_TYPE_FRUSTUM )
  108. , m_nRobotHealth( 100 )
  109. , m_nPoints( 0 )
  110. , m_nNumGibs( 0 )
  111. , m_pszPathName( NULL )
  112. , m_pszGroupName( NULL )
  113. {}
  114. RobotSpawnData_t &operator=( const RobotSpawnData_t& rhs )
  115. {
  116. m_eType = rhs.m_eType;
  117. m_nRobotHealth = rhs.m_nRobotHealth;
  118. m_nPoints = rhs.m_nPoints;
  119. m_nNumGibs = rhs.m_nNumGibs;
  120. m_pszPathName = rhs.m_pszPathName;
  121. m_pszGroupName = rhs.m_pszGroupName;
  122. return *this;
  123. }
  124. eRobotType m_eType;
  125. int m_nRobotHealth;
  126. int m_nPoints;
  127. int m_nNumGibs;
  128. const char *m_pszPathName;
  129. const char *m_pszGroupName;
  130. };
  131. //----------------------------------------------------------------------------
  132. class CRobotLocomotion : public NextBotGroundLocomotion
  133. {
  134. public:
  135. CRobotLocomotion( INextBot *bot ) : NextBotGroundLocomotion( bot ) { }
  136. virtual ~CRobotLocomotion() { }
  137. virtual float GetGroundSpeed() const OVERRIDE;
  138. virtual float GetRunSpeed( void ) const OVERRIDE; // get maximum running speed
  139. virtual float GetStepHeight( void ) const OVERRIDE; // if delta Z is greater than this, we have to jump to get up
  140. virtual float GetMaxJumpHeight( void ) const OVERRIDE; // return maximum height of a jump
  141. virtual bool ShouldCollideWith( const CBaseEntity *object ) const OVERRIDE;
  142. private:
  143. virtual float GetMaxYawRate( void ) const OVERRIDE; // return max rate of yaw rotation
  144. };
  145. //----------------------------------------------------------------------------
  146. class CRobotIntention : public IIntention
  147. {
  148. public:
  149. CRobotIntention( class CTFRobotDestruction_Robot *me );
  150. virtual ~CRobotIntention();
  151. virtual void Reset( void ) OVERRIDE;
  152. virtual void Update( void ) OVERRIDE;
  153. virtual QueryResultType IsPositionAllowed( const INextBot *me, const Vector &pos ) const OVERRIDE; // is the a place we can be?
  154. virtual INextBotEventResponder *FirstContainedResponder( void ) const OVERRIDE { return m_behavior; }
  155. virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const OVERRIDE { return NULL; }
  156. private:
  157. Behavior< CTFRobotDestruction_Robot > *m_behavior;
  158. };
  159. //---------------------------------------------------------------------------------------------
  160. class CRobotBehavior : public Action< CTFRobotDestruction_Robot >
  161. {
  162. public:
  163. virtual Action< CTFRobotDestruction_Robot > *InitialContainedAction( CTFRobotDestruction_Robot *me ) OVERRIDE;
  164. virtual ActionResult< CTFRobotDestruction_Robot > OnStart( CTFRobotDestruction_Robot *me, Action< CTFRobotDestruction_Robot > *priorAction ) OVERRIDE;
  165. virtual ActionResult< CTFRobotDestruction_Robot > Update( CTFRobotDestruction_Robot *me, float interval ) OVERRIDE;
  166. virtual EventDesiredResult< CTFRobotDestruction_Robot > OnInjured( CTFRobotDestruction_Robot *me, const CTakeDamageInfo &info );
  167. EventDesiredResult< CTFRobotDestruction_Robot > OnContact( CTFRobotDestruction_Robot *me, CBaseEntity *pOther, CGameTrace *result = NULL );
  168. virtual const char *GetName( void ) const { return "RobotBehavior"; } // return name of this action
  169. private:
  170. CountdownTimer m_SpeakTimer;
  171. CountdownTimer m_IdleSpeakTimer;
  172. };
  173. #endif
  174. class CRobotDispenser :
  175. #ifdef GAME_DLL
  176. public CObjectDispenser
  177. #else
  178. public C_ObjectDispenser
  179. #endif
  180. {
  181. #ifdef GAME_DLL
  182. DECLARE_CLASS( CRobotDispenser, CObjectDispenser )
  183. #else
  184. DECLARE_CLASS( CRobotDispenser, C_ObjectDispenser )
  185. #endif
  186. DECLARE_NETWORKCLASS();
  187. DECLARE_DATADESC();
  188. public:
  189. #ifdef GAME_DLL
  190. CRobotDispenser();
  191. virtual void Spawn( void ) OVERRIDE;
  192. virtual void OnGoActive( void ) OVERRIDE;
  193. virtual void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ) OVERRIDE;
  194. virtual void SetModel( const char *pModel ) OVERRIDE;
  195. virtual float GetDispenserRadius( void ) OVERRIDE { return 128; }
  196. virtual float GetHealRate() const OVERRIDE { return 5.f; }
  197. virtual int DispenseMetal( CTFPlayer * ) OVERRIDE { return 0; }
  198. virtual bool DispenseAmmo( CTFPlayer * ) OVERRIDE { return false; }
  199. private:
  200. virtual void PlayActiveSound() OVERRIDE { /*DO NOTHING*/ }
  201. #endif
  202. };
  203. class CTFRobotDestruction_RobotAnimController
  204. {
  205. public:
  206. CTFRobotDestruction_RobotAnimController( CTFRobotDestruction_Robot *pOuter );
  207. void Update();
  208. void Impulse( const Vector& vecImpulse );
  209. private:
  210. void Approach( Vector& vecIn, const Vector& vecTarget, float flRate );
  211. void GetPoseParams();
  212. Vector m_vecOldOrigin;
  213. Vector m_vecLean;
  214. Vector m_vecImpulse;
  215. CTFRobotDestruction_Robot *m_pOuter;
  216. struct PoseParams_t
  217. {
  218. int m_nMoveX;
  219. int m_nMoveY;
  220. } m_poseParams;
  221. };
  222. #ifdef GAME_DLL
  223. typedef NextBotCombatCharacter RobotBaseClass;
  224. #else
  225. typedef CBaseCombatCharacter RobotBaseClass;
  226. #endif
  227. class CTFRobotDestruction_Robot : public RobotBaseClass
  228. #ifdef CLIENT_DLL
  229. , public CGameEventListener
  230. #endif
  231. {
  232. DECLARE_DATADESC();
  233. DECLARE_CLASS( CTFRobotDestruction_Robot, RobotBaseClass )
  234. DECLARE_NETWORKCLASS();
  235. public:
  236. CTFRobotDestruction_Robot( void );
  237. virtual ~CTFRobotDestruction_Robot( void );
  238. static void StaticPrecache( void );
  239. virtual void Precache( void ) OVERRIDE;
  240. virtual void Spawn( void ) OVERRIDE;
  241. virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const OVERRIDE;
  242. #ifdef CLIENT_DLL
  243. virtual float GetHealthBarHeightOffset( void ) const OVERRIDE;
  244. virtual void OnDataChanged( DataUpdateType_t type ) OVERRIDE;
  245. virtual int GetHealth( void ) const OVERRIDE { return m_iHealth; }
  246. virtual int GetMaxHealth( void ) const OVERRIDE { return m_iMaxHealth; }
  247. virtual bool IsHealthBarVisible( void ) const OVERRIDE { return true; }
  248. virtual void UpdateClientSideAnimation( void ) OVERRIDE;
  249. virtual void FireGameEvent( IGameEvent *event ) OVERRIDE;
  250. virtual CStudioHdr* OnNewModel() OVERRIDE;
  251. virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ) OVERRIDE;
  252. void UpdateDamagedEffects( void );
  253. #else
  254. virtual void HandleAnimEvent( animevent_t *pEvent ) OVERRIDE;
  255. virtual bool IsRemovedOnReset( void ) const { return false; }
  256. virtual void UpdateOnRemove( void ) OVERRIDE;
  257. virtual void Event_Killed( const CTakeDamageInfo &info ) OVERRIDE;
  258. virtual int OnTakeDamage( const CTakeDamageInfo &info ) OVERRIDE;
  259. virtual void TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ) OVERRIDE;
  260. virtual void UpdateAnimsThink( void );
  261. void RepairSelfThink( void );
  262. bool GetShieldedState( void ) const { return m_bShielded; }
  263. CPathTrack *GetNextPath( void ) const { return m_hNextPath; }
  264. void ArriveAtPath( void );
  265. void SetRobotSpawnData( const RobotSpawnData_t& data ) { m_spawnData = data; m_eType = data.m_eType; }
  266. const RobotSpawnData_t &GetRobotSpawnData() const { return m_spawnData; }
  267. void SetGroup( class CTFRobotDestruction_RobotGroup* pGroup ) { m_hGroup.Set( pGroup ); }
  268. void SetSpawn( class CTFRobotDestruction_RobotSpawn* pSpawn ) { m_hSpawn.Set( pSpawn ); }
  269. void EnableUber( void );
  270. void DisableUber( void );
  271. // INextBot
  272. virtual CRobotIntention *GetIntentionInterface( void ) const { return m_intention; }
  273. virtual CRobotLocomotion *GetLocomotionInterface( void ) const { return m_locomotor; }
  274. virtual CHeadlessHatmanBody *GetBodyInterface( void ) const { return m_body; }
  275. void SetNewActivity( Activity activity );
  276. void SetIsPanicked( bool bPanicked ) { m_bIsPanicked = bPanicked; }
  277. bool GetIsPanicked( void ) const { return m_bIsPanicked; }
  278. //Inputs
  279. void InputStopAndUseComputer( inputdata_t &inputdata );
  280. private:
  281. void PlayDeathEffects( void );
  282. void ModifyDamage( CTakeDamageInfo *info ) const;
  283. void SpewBars( int nNumToSpew );
  284. void SpewBarsThink( void );
  285. void SelfDestructThink( void );
  286. void SpewGibs( void );
  287. #endif
  288. private:
  289. int m_iHealth;
  290. int m_iMaxHealth;
  291. CUtlVector<breakmodel_t> m_aGibs;
  292. CUtlVector<breakmodel_t> m_aSpawnProps;
  293. CTFRobotDestruction_RobotAnimController m_animController;
  294. CNetworkVar( bool, m_bShielded );
  295. CNetworkVar( eRobotType, m_eType );
  296. #ifdef CLIENT_DLL
  297. HPARTICLEFFECT m_hDamagedParticleEffect;
  298. #else
  299. CRobotDispenser *m_pDispenser;
  300. RobotSpawnData_t m_spawnData;
  301. CHandle< CPathTrack > m_hNextPath;
  302. int m_nPointsSpewed;
  303. IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_iHealth );
  304. CHandle< CTFRobotDestruction_RobotGroup > m_hGroup;
  305. CHandle< CTFRobotDestruction_RobotSpawn > m_hSpawn;
  306. CRobotIntention *m_intention;
  307. CRobotLocomotion *m_locomotor;
  308. CHeadlessHatmanBody *m_body;
  309. bool m_bIsPanicked;
  310. #endif
  311. };
  312. #ifdef GAME_DLL
  313. //--------------------------------------------------------------------------------------------------------------
  314. class CRobotPathCost : public IPathCost
  315. {
  316. public:
  317. CRobotPathCost( CTFRobotDestruction_Robot *me )
  318. {
  319. m_me = me;
  320. }
  321. // return the cost (weighted distance between) of moving from "fromArea" to "area", or -1 if the move is not allowed
  322. virtual float operator()( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder, const CFuncElevator *elevator, float length ) const
  323. {
  324. if ( fromArea == NULL )
  325. {
  326. // first area in path, no cost
  327. return 0.0f;
  328. }
  329. else
  330. {
  331. if ( !m_me->GetLocomotionInterface()->IsAreaTraversable( area ) )
  332. {
  333. // our locomotor says we can't move here
  334. return -1.0f;
  335. }
  336. // compute distance traveled along path so far
  337. float dist;
  338. if ( ladder )
  339. {
  340. dist = ladder->m_length;
  341. }
  342. else if ( length > 0.0 )
  343. {
  344. // optimization to avoid recomputing length
  345. dist = length;
  346. }
  347. else
  348. {
  349. dist = ( area->GetCenter() - fromArea->GetCenter() ).Length();
  350. }
  351. // check height change
  352. float deltaZ = fromArea->ComputeAdjacentConnectionHeightChange( area );
  353. if ( deltaZ >= m_me->GetLocomotionInterface()->GetStepHeight() )
  354. {
  355. if ( deltaZ >= m_me->GetLocomotionInterface()->GetMaxJumpHeight() )
  356. {
  357. // too high to reach
  358. return -1.0f;
  359. }
  360. // jumping is slower than flat ground
  361. const float jumpPenalty = 5.0f;
  362. dist += jumpPenalty * dist;
  363. }
  364. else if ( deltaZ < -m_me->GetLocomotionInterface()->GetDeathDropHeight() )
  365. {
  366. // too far to drop
  367. return -1.0f;
  368. }
  369. return dist + fromArea->GetCostSoFar();
  370. }
  371. }
  372. CTFRobotDestruction_Robot *m_me;
  373. };
  374. #endif // GAME_DLL
  375. #endif // ROBOT_DESTRUCTION_ROBOT_H