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.

439 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Base class for humanoid NPCs intended to fight along side player in close
  4. // environments
  5. //
  6. //=============================================================================//
  7. #ifndef NPC_PLAYERCOMPANION_H
  8. #define NPC_PLAYERCOMPANION_H
  9. #include "ai_playerally.h"
  10. #include "ai_behavior_follow.h"
  11. #include "ai_behavior_standoff.h"
  12. #include "ai_behavior_assault.h"
  13. #include "ai_behavior_lead.h"
  14. #include "ai_behavior_actbusy.h"
  15. #include "ai_behavior_fear.h"
  16. #ifdef HL2_EPISODIC
  17. #include "ai_behavior_operator.h"
  18. #include "ai_behavior_passenger_companion.h"
  19. #endif
  20. #if defined( _WIN32 )
  21. #pragma once
  22. #endif
  23. enum AIReadiness_t
  24. {
  25. AIRL_PANIC = -2,
  26. AIRL_STEALTH = -1,
  27. AIRL_RELAXED = 0,
  28. AIRL_STIMULATED,
  29. AIRL_AGITATED,
  30. };
  31. enum AIReadinessUse_t
  32. {
  33. AIRU_NEVER,
  34. AIRU_ALWAYS,
  35. AIRU_ONLY_PLAYER_SQUADMATES,
  36. };
  37. class CCompanionActivityRemap : public CActivityRemap
  38. {
  39. public:
  40. CCompanionActivityRemap( void ) :
  41. m_fUsageBits( 0 ),
  42. m_readiness( AIRL_RELAXED ),
  43. m_bAiming( false ),
  44. m_bWeaponRequired( false ),
  45. m_bInVehicle( false ) {}
  46. // This bitfield maps which bits of data are being utilized by this data structure, since not all criteria
  47. // in the parsed file are essential. You must add corresponding bits to the definitions below and maintain
  48. // their state in the parsing of the file, as well as check the bitfield before accessing the data. This
  49. // could be encapsulated into this class, but we'll probably move away from this model and closer to something
  50. // more akin to the response rules -- jdw
  51. int m_fUsageBits;
  52. AIReadiness_t m_readiness;
  53. bool m_bAiming;
  54. bool m_bWeaponRequired;
  55. bool m_bInVehicle; // For future expansion, this needs to speak more to the exact seat, role, and vehicle
  56. };
  57. // Usage bits for remap "extra" parsing - if these bits are set, the associated data has changed
  58. #define bits_REMAP_READINESS (1<<0)
  59. #define bits_REMAP_AIMING (1<<1)
  60. #define bits_REMAP_WEAPON_REQUIRED (1<<2)
  61. #define bits_REMAP_IN_VEHICLE (1<<3)
  62. // Readiness modes that only change due to mapmaker scripts
  63. #define READINESS_MIN_VALUE -2
  64. #define READINESS_MODE_PANIC -2
  65. #define READINESS_MODE_STEALTH -1
  66. // Readiness modes that change normally
  67. #define READINESS_VALUE_RELAXED 0.1f
  68. #define READINESS_VALUE_STIMULATED 0.95f
  69. #define READINESS_VALUE_AGITATED 1.0f
  70. class CPhysicsProp;
  71. //-----------------------------------------------------------------------------
  72. //
  73. // CLASS: CNPC_PlayerCompanion
  74. //
  75. //-----------------------------------------------------------------------------
  76. class CNPC_PlayerCompanion : public CAI_PlayerAlly
  77. {
  78. DECLARE_CLASS( CNPC_PlayerCompanion, CAI_PlayerAlly );
  79. public:
  80. //---------------------------------
  81. bool CreateBehaviors();
  82. void Precache();
  83. void Spawn();
  84. virtual void SelectModel() {};
  85. virtual int Restore( IRestore &restore );
  86. virtual void DoCustomSpeechAI( void );
  87. //---------------------------------
  88. int ObjectCaps();
  89. bool ShouldAlwaysThink();
  90. Disposition_t IRelationType( CBaseEntity *pTarget );
  91. bool IsSilentSquadMember() const;
  92. //---------------------------------
  93. // Behavior
  94. //---------------------------------
  95. void GatherConditions();
  96. virtual void PredictPlayerPush();
  97. void BuildScheduleTestBits();
  98. CSound *GetBestSound( int validTypes = ALL_SOUNDS );
  99. bool QueryHearSound( CSound *pSound );
  100. bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );
  101. bool ShouldIgnoreSound( CSound * );
  102. int SelectSchedule();
  103. virtual int SelectScheduleDanger();
  104. virtual int SelectSchedulePriorityAction();
  105. virtual int SelectScheduleNonCombat() { return SCHED_NONE; }
  106. virtual int SelectScheduleCombat();
  107. int SelectSchedulePlayerPush();
  108. virtual bool CanReload( void );
  109. virtual bool ShouldDeferToFollowBehavior();
  110. bool ShouldDeferToPassengerBehavior( void );
  111. bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist );
  112. int TranslateSchedule( int scheduleType );
  113. void StartTask( const Task_t *pTask );
  114. void RunTask( const Task_t *pTask );
  115. Activity TranslateActivityReadiness( Activity activity );
  116. Activity NPC_TranslateActivity( Activity eNewActivity );
  117. void HandleAnimEvent( animevent_t *pEvent );
  118. bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt);
  119. int GetSoundInterests();
  120. void Touch( CBaseEntity *pOther );
  121. virtual bool IgnorePlayerPushing( void );
  122. void ModifyOrAppendCriteria( AI_CriteriaSet& set );
  123. void Activate( void );
  124. void PrepareReadinessRemap( void );
  125. virtual bool IsNavigationUrgent( void );
  126. //---------------------------------
  127. // Readiness
  128. //---------------------------------
  129. protected:
  130. virtual bool IsReadinessCapable();
  131. bool IsReadinessLocked() { return gpGlobals->curtime < m_flReadinessLockedUntil; }
  132. void AddReadiness( float flAdd, bool bOverrideLock = false );
  133. void SubtractReadiness( float flAdd, bool bOverrideLock = false );
  134. void SetReadinessValue( float flSet );
  135. void SetReadinessSensitivity( float flSensitivity ) { m_flReadinessSensitivity = flSensitivity; }
  136. virtual void UpdateReadiness();
  137. virtual float GetReadinessDecay();
  138. bool IsInScriptedReadinessState( void ) { return (m_flReadiness < 0 ); }
  139. CUtlVector< CCompanionActivityRemap > m_activityMappings;
  140. public:
  141. float GetReadinessValue() { return m_flReadiness; }
  142. int GetReadinessLevel();
  143. void SetReadinessLevel( int iLevel, bool bOverrideLock, bool bSlam );
  144. void LockReadiness( float duration = -1.0f ); // Defaults to indefinitely locked
  145. void UnlockReadiness( void );
  146. virtual void ReadinessLevelChanged( int iPriorLevel ) { }
  147. void InputGiveWeapon( inputdata_t &inputdata );
  148. #ifdef HL2_EPISODIC
  149. //---------------------------------
  150. // Vehicle passenger
  151. //---------------------------------
  152. void InputEnterVehicle( inputdata_t &inputdata );
  153. void InputEnterVehicleImmediately( inputdata_t &inputdata );
  154. void InputCancelEnterVehicle( inputdata_t &inputdata );
  155. void InputExitVehicle( inputdata_t &inputdata );
  156. bool CanEnterVehicle( void );
  157. bool CanExitVehicle( void );
  158. void EnterVehicle( CBaseEntity *pEntityVehicle, bool bImmediately );
  159. virtual bool ExitVehicle( void );
  160. virtual void UpdateEfficiency( bool bInPVS );
  161. virtual bool IsInAVehicle( void ) const;
  162. virtual IServerVehicle *GetVehicle( void );
  163. virtual CBaseEntity *GetVehicleEntity( void );
  164. virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
  165. virtual bool IsAllowedToDodge( void );
  166. #endif // HL2_EPISODIC
  167. public:
  168. virtual void OnPlayerKilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
  169. //---------------------------------
  170. //---------------------------------
  171. bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs );
  172. //---------------------------------
  173. // Aiming
  174. //---------------------------------
  175. CBaseEntity *GetAimTarget() { return m_hAimTarget; }
  176. void SetAimTarget( CBaseEntity *pTarget );
  177. void StopAiming( char *pszReason = NULL );
  178. bool FindNewAimTarget();
  179. void OnNewLookTarget();
  180. bool ShouldBeAiming();
  181. virtual bool IsAllowedToAim();
  182. bool HasAimLOS( CBaseEntity *pAimTarget );
  183. void AimGun();
  184. CBaseEntity *GetAlternateMoveShootTarget();
  185. //---------------------------------
  186. // Combat
  187. //---------------------------------
  188. virtual void LocateEnemySound() {};
  189. bool IsValidEnemy( CBaseEntity *pEnemy );
  190. bool IsSafeFromFloorTurret( const Vector &vecLocation, CBaseEntity *pTurret );
  191. bool ShouldMoveAndShoot( void );
  192. void OnUpdateShotRegulator();
  193. void DecalTrace( trace_t *pTrace, char const *decalName );
  194. bool FCanCheckAttacks();
  195. Vector GetActualShootPosition( const Vector &shootOrigin );
  196. WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon );
  197. bool ShouldLookForBetterWeapon();
  198. bool Weapon_CanUse( CBaseCombatWeapon *pWeapon );
  199. void Weapon_Equip( CBaseCombatWeapon *pWeapon );
  200. void PickupWeapon( CBaseCombatWeapon *pWeapon );
  201. bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult);
  202. bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult );
  203. bool FindCoverPos( CSound *pSound, Vector *pResult );
  204. bool FindMortarCoverPos( CSound *pSound, Vector *pResult );
  205. bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
  206. bool IsEnemyTurret() { return ( GetEnemy() && IsTurret(GetEnemy()) ); }
  207. static bool IsMortar( CBaseEntity *pEntity );
  208. static bool IsSniper( CBaseEntity *pEntity );
  209. static bool IsTurret( CBaseEntity *pEntity );
  210. static bool IsGunship( CBaseEntity *pEntity );
  211. //---------------------------------
  212. // Damage handling
  213. //---------------------------------
  214. int OnTakeDamage_Alive( const CTakeDamageInfo &info );
  215. void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
  216. //---------------------------------
  217. // Hints
  218. //---------------------------------
  219. bool FValidateHintType ( CAI_Hint *pHint );
  220. //---------------------------------
  221. // Navigation
  222. //---------------------------------
  223. bool IsValidMoveAwayDest( const Vector &vecDest );
  224. bool ValidateNavGoal();
  225. bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so)
  226. bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
  227. float GetIdealSpeed() const;
  228. float GetIdealAccel() const;
  229. bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
  230. //---------------------------------
  231. // Inputs
  232. //---------------------------------
  233. void InputOutsideTransition( inputdata_t &inputdata );
  234. void InputSetReadinessPanic( inputdata_t &inputdata );
  235. void InputSetReadinessStealth( inputdata_t &inputdata );
  236. void InputSetReadinessLow( inputdata_t &inputdata );
  237. void InputSetReadinessMedium( inputdata_t &inputdata );
  238. void InputSetReadinessHigh( inputdata_t &inputdata );
  239. void InputLockReadiness( inputdata_t &inputdata );
  240. #if HL2_EPISODIC
  241. void InputClearAllOuputs( inputdata_t &inputdata ); ///< annihilate every output on this npc
  242. #endif
  243. bool AllowReadinessValueChange( void );
  244. protected:
  245. //-----------------------------------------------------
  246. // Conditions, Schedules, Tasks
  247. //-----------------------------------------------------
  248. enum
  249. {
  250. COND_PC_HURTBYFIRE = BaseClass::NEXT_CONDITION,
  251. COND_PC_SAFE_FROM_MORTAR,
  252. COND_PC_BECOMING_PASSENGER,
  253. NEXT_CONDITION,
  254. SCHED_PC_COWER = BaseClass::NEXT_SCHEDULE,
  255. SCHED_PC_MOVE_TOWARDS_COVER_FROM_BEST_SOUND,
  256. SCHED_PC_TAKE_COVER_FROM_BEST_SOUND,
  257. SCHED_PC_FLEE_FROM_BEST_SOUND,
  258. SCHED_PC_FAIL_TAKE_COVER_TURRET,
  259. SCHED_PC_FAKEOUT_MORTAR,
  260. SCHED_PC_GET_OFF_COMPANION,
  261. NEXT_SCHEDULE,
  262. TASK_PC_WAITOUT_MORTAR = BaseClass::NEXT_TASK,
  263. TASK_PC_GET_PATH_OFF_COMPANION,
  264. NEXT_TASK,
  265. };
  266. private:
  267. void SetupCoverSearch( CBaseEntity *pEntity );
  268. void CleanupCoverSearch();
  269. //-----------------------------------------------------
  270. bool m_bMovingAwayFromPlayer;
  271. bool m_bWeightPathsInCover;
  272. enum eCoverType
  273. {
  274. CT_NORMAL,
  275. CT_TURRET,
  276. CT_MORTAR
  277. };
  278. static eCoverType gm_fCoverSearchType;
  279. static bool gm_bFindingCoverFromAllEnemies;
  280. CSimpleSimTimer m_FakeOutMortarTimer;
  281. // Derived classes should not use the expresser directly
  282. virtual CAI_Expresser *GetExpresser() { return BaseClass::GetExpresser(); }
  283. protected:
  284. //-----------------------------------------------------
  285. virtual CAI_FollowBehavior &GetFollowBehavior( void ) { return m_FollowBehavior; }
  286. CAI_AssaultBehavior m_AssaultBehavior;
  287. CAI_FollowBehavior m_FollowBehavior;
  288. CAI_StandoffBehavior m_StandoffBehavior;
  289. CAI_LeadBehavior m_LeadBehavior;
  290. CAI_ActBusyBehavior m_ActBusyBehavior;
  291. #ifdef HL2_EPISODIC
  292. CAI_OperatorBehavior m_OperatorBehavior;
  293. CAI_PassengerBehaviorCompanion m_PassengerBehavior;
  294. CAI_FearBehavior m_FearBehavior;
  295. #endif
  296. //-----------------------------------------------------
  297. bool ShouldAlwaysTransition( void );
  298. // Readiness is a value that's fed by various events in the NPC's AI. It is used
  299. // to make decisions about what type of posture the NPC should be in (relaxed, agitated).
  300. // It is not used to make decisions about what to do in the AI.
  301. float m_flReadiness;
  302. float m_flReadinessSensitivity;
  303. bool m_bReadinessCapable;
  304. float m_flReadinessLockedUntil;
  305. float m_fLastBarrelExploded;
  306. float m_fLastPlayerKill;
  307. int m_iNumConsecutiveBarrelsExploded; // Companions keep track of the # of consecutive barrels exploded by the player and speaks a response as it increases
  308. int m_iNumConsecutivePlayerKills; // Alyx keeps track of the # of consecutive kills by the player and speaks a response as it increases
  309. //-----------------------------------------------------
  310. float m_flBoostSpeed;
  311. //-----------------------------------------------------
  312. CSimpleSimTimer m_AnnounceAttackTimer;
  313. //-----------------------------------------------------
  314. EHANDLE m_hAimTarget;
  315. #ifdef HL2_EPISODIC
  316. CHandle<CPhysicsProp> m_hFlare;
  317. #endif // HL2_EPISODIC
  318. //-----------------------------------------------------
  319. static string_t gm_iszMortarClassname;
  320. static string_t gm_iszFloorTurretClassname;
  321. static string_t gm_iszGroundTurretClassname;
  322. static string_t gm_iszShotgunClassname;
  323. static string_t gm_iszRollerMineClassname;
  324. //-----------------------------------------------------
  325. void InputEnableAlwaysTransition( inputdata_t &inputdata );
  326. void InputDisableAlwaysTransition( inputdata_t &inputdata );
  327. bool m_bAlwaysTransition;
  328. bool m_bDontPickupWeapons;
  329. void InputEnableWeaponPickup( inputdata_t &inputdata );
  330. void InputDisableWeaponPickup( inputdata_t &inputdata );
  331. COutputEvent m_OnWeaponPickup;
  332. CStopwatch m_SpeechWatch_PlayerLooking;
  333. DECLARE_DATADESC();
  334. DEFINE_CUSTOM_AI;
  335. };
  336. // Used for quick override move searches against certain types of entities
  337. void OverrideMoveCache_ForceRepopulateList( void );
  338. CBaseEntity *OverrideMoveCache_FindTargetsInRadius( CBaseEntity *pFirstEntity, const Vector &vecOrigin, float flRadius );
  339. void OverrideMoveCache_LevelInitPreEntity( void );
  340. void OverrideMoveCache_LevelShutdownPostEntity( void );
  341. #endif // NPC_PLAYERCOMPANION_H