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.

289 lines
9.5 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Base combat character with no AI
  4. //
  5. //=====================================================================================//
  6. #include "ai_baseactor.h"
  7. #include "npc_playercompanion.h"
  8. #include "ai_behavior_holster.h"
  9. #include "ai_behavior_functank.h"
  10. #include "soundenvelope.h"
  11. extern ConVar npc_alyx_readiness;
  12. class CNPC_Alyx : public CNPC_PlayerCompanion
  13. {
  14. public:
  15. DECLARE_CLASS( CNPC_Alyx, CNPC_PlayerCompanion );
  16. // fast class list
  17. CNPC_Alyx *m_pNext;
  18. virtual void ModifyOrAppendCriteria( AI_CriteriaSet &set );
  19. bool ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther );
  20. CNPC_Alyx( );
  21. ~CNPC_Alyx( );
  22. static CNPC_Alyx *GetAlyx( void );
  23. bool CreateBehaviors();
  24. void Spawn( void );
  25. void Activate( void );
  26. void StopLoopingSounds( void );
  27. void SelectModel();
  28. void Precache( void );
  29. void SetupAlyxWithoutParent( void );
  30. void CreateEmpTool( void );
  31. void PrescheduleThink( void );
  32. void GatherConditions();
  33. bool ShouldPlayerAvoid( void );
  34. void AnalyzeGunfireSound( CSound *pSound );
  35. bool IsValidEnemy( CBaseEntity *pEnemy );
  36. void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
  37. void Event_Killed( const CTakeDamageInfo &info );
  38. void EnemyIgnited( CAI_BaseNPC *pVictim );
  39. void CombineBallSocketed( int iNumBounces );
  40. void AimGun( void );
  41. Vector GetActualShootPosition( const Vector &shootOrigin );
  42. float MaxYawSpeed( void );
  43. void OnUpdateShotRegulator();
  44. bool IsCrouchedActivity( Activity activity );
  45. bool OnBeginMoveAndShoot();
  46. void SpeakAttacking( void );
  47. virtual float GetJumpGravity() const { return 1.8f; }
  48. // Crouching
  49. Vector GetCrouchEyeOffset( void ) { return Vector(0,0,50); }
  50. Vector GetCrouchGunOffset( void ) { return Vector(0,0,40); }
  51. bool EnemyIsValidCrouchTarget( CBaseEntity *pEnemy );
  52. bool Stand( void );
  53. bool Crouch( void );
  54. void DesireCrouch( void );
  55. // Custom AI
  56. void DoCustomCombatAI( void );
  57. void DoMobbedCombatAI( void );
  58. void DoCustomSpeechAI( void );
  59. Disposition_t IRelationType( CBaseEntity *pTarget );
  60. int IRelationPriority( CBaseEntity *pTarget );
  61. CAI_FollowBehavior &GetFollowBehavior( void );
  62. Class_T Classify ( void );
  63. bool FValidateHintType( CAI_Hint *pHint );
  64. int ObjectCaps();
  65. void HandleAnimEvent( animevent_t *pEvent );
  66. bool FInViewCone( CBaseEntity *pEntity );
  67. bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );
  68. bool CanSeeEntityInDarkness( CBaseEntity *pEntity );
  69. bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
  70. Activity NPC_TranslateActivity ( Activity activity );
  71. bool ShouldDeferToFollowBehavior();
  72. void BuildScheduleTestBits();
  73. bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior );
  74. int SelectSchedule( void );
  75. int SelectScheduleDanger( void );
  76. int TranslateSchedule( int scheduleType );
  77. void StartTask( const Task_t *pTask );
  78. void RunTask( const Task_t *pTask );
  79. void OnStateChange( NPC_STATE OldState, NPC_STATE NewState );
  80. float LengthOfLastCombat( void ) const;
  81. // bool IsNavigationUrgent();
  82. void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
  83. bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker );
  84. int OnTakeDamage_Alive( const CTakeDamageInfo &info );
  85. bool FCanCheckAttacks();
  86. float GetAttackDamageScale( CBaseEntity *pVictim );
  87. bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt);
  88. virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
  89. void HolsterPistol();
  90. void DrawPistol();
  91. void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL );
  92. void SetEMPHolstered( bool bHolstered ) { m_bIsEMPHolstered = bHolstered; }
  93. bool IsEMPHolstered() { return (!m_hEmpTool || m_hEmpTool->GetParent() != this || m_bIsEMPHolstered); }
  94. float GetReadinessDecay() { return 60.0f; }
  95. virtual bool IsAllowedToAim();
  96. virtual void PainSound( const CTakeDamageInfo &info );
  97. virtual void DeathSound( const CTakeDamageInfo &info );
  98. // Hacking and object interaction
  99. void SearchForInteractTargets();
  100. bool IsValidInteractTarget( CBaseEntity *pTarget );
  101. bool CanInteractWithTarget( CBaseEntity *pTarget );
  102. void SetInteractTarget( CBaseEntity *pTarget );
  103. bool HasInteractTarget() { return m_hHackTarget != NULL; }
  104. CBaseEntity *GetInteractTarget() { return m_hHackTarget; }
  105. void EmpZapTarget( CBaseEntity *pTarget );
  106. virtual void OnSeeEntity( CBaseEntity *pEntity );
  107. void InputAllowInteraction( inputdata_t &inputdata )
  108. {
  109. m_bInteractionAllowed = true;
  110. }
  111. void InputDisallowInteraction( inputdata_t &inputdata )
  112. {
  113. m_bInteractionAllowed = false;
  114. }
  115. void InputAllowDarknessSpeech( inputdata_t &inputdata )
  116. {
  117. m_bDarknessSpeechAllowed = inputdata.value.Bool();
  118. }
  119. void InputGiveEMP( inputdata_t &inputdata );
  120. void InputVehiclePunted( inputdata_t &inputdata );
  121. void InputOutsideTransition( inputdata_t &inputdata );
  122. virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon );
  123. virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
  124. virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon );
  125. virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon );
  126. // Blinding
  127. virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
  128. void CheckBlindedByFlare( void );
  129. bool CanBeBlindedByFlashlight( bool bCheckLightSources );
  130. bool PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer );
  131. bool BlindedByFlare( void );
  132. bool CanReload( void );
  133. virtual bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs );
  134. virtual void OnSelectedLookTarget( AILookTargetArgs_t *pArgs );
  135. virtual bool IsReadinessCapable( void );
  136. virtual void ReadinessLevelChanged( int iPriorLevel );
  137. bool IsAllowedToInteract();
  138. virtual void BarnacleDeathSound( void );
  139. virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALYXDEAD"; }
  140. PassengerState_e GetPassengerState( void );
  141. void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  142. bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers );
  143. private:
  144. EHANDLE m_hEmpTool;
  145. EHANDLE m_hHackTarget;
  146. CHandle<CAI_Hint> m_hStealthLookTarget;
  147. bool m_bInteractionAllowed;
  148. float m_fTimeNextSearchForInteractTargets;
  149. bool m_bDarknessSpeechAllowed;
  150. bool m_bIsEMPHolstered;
  151. bool m_bIsFlashlightBlind;
  152. float m_fStayBlindUntil;
  153. float m_flDontBlindUntil;
  154. bool m_bSpokeLostPlayerInDarkness;
  155. bool m_bPlayerFlashlightState;
  156. bool m_bHadCondSeeEnemy;
  157. string_t m_iszCurrentBlindScene;
  158. float m_fTimeUntilNextDarknessFoundPlayer;
  159. float m_fCombatStartTime;
  160. float m_fCombatEndTime;
  161. float m_flNextCrouchTime;
  162. CSoundPatch *m_sndDarknessBreathing;
  163. // Speech timers
  164. // Theoretically, these shouldn't be needed. Instead, each response
  165. // should prevent the concept being spoken for the desired time. But
  166. // until the responses exists, Alyx will spam the response rules forever,
  167. // so these timers stop that.
  168. CRandStopwatch m_SpeechWatch_LostPlayer;
  169. CSimpleSimTimer m_SpeechTimer_HeardSound;
  170. CRandStopwatch m_SpeechWatch_SoundDelay;
  171. CRandStopwatch m_SpeechWatch_BreathingRamp;
  172. CRandStopwatch m_SpeechWatch_FoundPlayer;
  173. CAI_MoveMonitor m_MoveMonitor;
  174. enum WeaponType_t
  175. {
  176. WT_NONE,
  177. WT_ALYXGUN,
  178. WT_SMG1,
  179. WT_SHOTGUN,
  180. WT_AR2,
  181. WT_OTHER,
  182. };
  183. int m_WeaponType;
  184. bool m_bShouldHaveEMP;
  185. CAI_FuncTankBehavior m_FuncTankBehavior;
  186. COutputEvent m_OnFinishInteractWithObject;
  187. COutputEvent m_OnPlayerUse;
  188. bool RunningPassengerBehavior( void );
  189. WeaponType_t ComputeWeaponType( CBaseEntity *pWeapon = NULL );
  190. WeaponType_t GetWeaponType() { return (WeaponType_t)m_WeaponType; }
  191. bool HasShotgun() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_SHOTGUN ); }
  192. bool HasAlyxgun() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_ALYXGUN ); }
  193. bool HasAR2() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_AR2 ); }
  194. private:
  195. enum
  196. {
  197. COND_ALYX_HAS_INTERACT_TARGET = BaseClass::NEXT_CONDITION,
  198. COND_ALYX_NO_INTERACT_TARGET,
  199. COND_ALYX_CAN_INTERACT_WITH_TARGET, // Hack target is in a suitable state and location to hack
  200. COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET,
  201. COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT,
  202. COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT,
  203. COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED,
  204. COND_ALYX_IN_DARK, // lights are out and she can't see
  205. };
  206. enum
  207. {
  208. SCHED_ALYX_PREPARE_TO_INTERACT_WITH_TARGET = BaseClass::NEXT_SCHEDULE,
  209. SCHED_ALYX_WAIT_TO_INTERACT_WITH_TARGET,
  210. SCHED_ALYX_INTERACT_WITH_TARGET,
  211. SCHED_ALYX_INTERACTION_INTERRUPTED,
  212. SCHED_ALYX_FINISH_INTERACTING_WITH_TARGET,
  213. SCHED_ALYX_HOLSTER_EMP,
  214. SCHED_ALYX_ALERT_FACE_AWAYFROM_BESTSOUND,
  215. SCHED_ALYX_RANGE_ATTACK1,
  216. SCHED_ALYX_ALERT_REACT_TO_COMBAT_SOUND,
  217. SCHED_ALYX_COMBAT_FACE,
  218. SCHED_ALYX_WAKE_ANGRY,
  219. SCHED_ALYX_NEW_WEAPON,
  220. SCHED_ALYX_IDLE_STAND,
  221. SCHED_ALYX_ALERT_FACE_BESTSOUND,
  222. SCHED_ALYX_FALL_TO_GROUND,
  223. };
  224. enum
  225. {
  226. TASK_ALYX_BEGIN_INTERACTION = BaseClass::NEXT_TASK,
  227. TASK_ALYX_COMPLETE_INTERACTION,
  228. TASK_ALYX_ANNOUNCE_HACK,
  229. TASK_ALYX_GET_PATH_TO_INTERACT_TARGET,
  230. TASK_ALYX_WAIT_HACKING,
  231. TASK_ALYX_HOLSTER_PISTOL,
  232. TASK_ALYX_DRAW_PISTOL,
  233. TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL,
  234. TASK_ALYX_BUILD_COMBAT_FACE_PATH,
  235. TASK_ALYX_SET_IDLE_ACTIVITY,
  236. TASK_ALYX_FALL_TO_GROUND,
  237. };
  238. DECLARE_DATADESC();
  239. DEFINE_CUSTOM_AI;
  240. };