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.

3239 lines
112 KiB

  1. //========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Base NPC character with AI
  4. //
  5. //=============================================================================//
  6. #ifndef AI_BASENPC_H
  7. #define AI_BASENPC_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "simtimer.h"
  12. #include "basecombatcharacter.h"
  13. #include "ai_debug.h"
  14. #include "ai_default.h"
  15. #include "ai_schedule.h"
  16. #include "ai_condition.h"
  17. #include "ai_component.h"
  18. #include "ai_task.h"
  19. #include "ai_movetypes.h"
  20. #include "ai_navtype.h"
  21. #include "ai_namespaces.h"
  22. #include "ai_npcstate.h"
  23. #include "ai_hull.h"
  24. #include "ai_utils.h"
  25. #include "ai_moveshoot.h"
  26. #include "entityoutput.h"
  27. #include "utlvector.h"
  28. #include "activitylist.h"
  29. #include "bitstring.h"
  30. #include "ai_navgoaltype.h" //GoalType_t enum
  31. #include "eventlist.h"
  32. #include "soundent.h"
  33. #include "ai_navigator.h"
  34. #include "tier1/functors.h"
  35. #define PLAYER_SQUADNAME "player_squad"
  36. class CAI_Schedule;
  37. class CAI_Network;
  38. class CAI_Route;
  39. class CAI_Hint;
  40. class CAI_Node;
  41. class CAI_Navigator;
  42. class CAI_Pathfinder;
  43. class CAI_Senses;
  44. class CAI_Enemies;
  45. class CAI_Squad;
  46. class CAI_Expresser;
  47. class CAI_BehaviorBase;
  48. class CAI_GoalEntity;
  49. class CAI_Motor;
  50. class CAI_MoveProbe;
  51. class CAI_LocalNavigator;
  52. class CAI_TacticalServices;
  53. class CVarBitVec;
  54. class CAI_ScriptedSequence;
  55. class CSceneEntity;
  56. class CBaseGrenade;
  57. class CBaseDoor;
  58. class CBasePropDoor;
  59. struct AI_Waypoint_t;
  60. //class AI_Response;
  61. class CBaseFilter;
  62. class CGlobalEvent;
  63. typedef CBitVec<MAX_CONDITIONS> CAI_ScheduleBits;
  64. // Used to control optimizations mostly dealing with pathfinding for NPCs
  65. extern ConVar ai_strong_optimizations;
  66. extern bool AIStrongOpt( void );
  67. // AI_MONITOR_FOR_OSCILLATION defaults to OFF. If you build with this ON, you can flag
  68. // NPC's and monitor them to detect oscillations in their schedule (circular logic and conditions bugs)
  69. // DO NOT SHIP WITH THIS ON!
  70. #undef AI_MONITOR_FOR_OSCILLATION
  71. //=============================================================================
  72. //
  73. // Constants & enumerations
  74. //
  75. //=============================================================================
  76. #define TURRET_CLOSE_RANGE 200
  77. #define TURRET_MEDIUM_RANGE 500
  78. #define COMMAND_GOAL_TOLERANCE 48 // 48 inches.
  79. #define TIME_CARE_ABOUT_DAMAGE 3.0
  80. #define ITEM_PICKUP_TOLERANCE 48.0f
  81. // Max's of the box used to search for a weapon to pick up. 45x45x~8 ft.
  82. #define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 )
  83. enum Interruptability_t
  84. {
  85. GENERAL_INTERRUPTABILITY,
  86. DAMAGEORDEATH_INTERRUPTABILITY,
  87. DEATH_INTERRUPTABILITY
  88. };
  89. //-------------------------------------
  90. // Memory
  91. //-------------------------------------
  92. #define MEMORY_CLEAR 0
  93. #define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes.
  94. #define bits_MEMORY_INCOVER ( 1 << 1 )// npc knows it is in a covered position.
  95. #define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily
  96. #define bits_MEMORY_TASK_EXPENSIVE ( 1 << 3 )// NPC has completed a task which is considered costly, so don't do another task this frame
  97. //#define bits_MEMORY_ ( 1 << 4 )
  98. #define bits_MEMORY_PATH_FAILED ( 1 << 5 )// Failed to find a path
  99. #define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
  100. //#define bits_MEMORY_ ( 1 << 7 )
  101. #define bits_MEMORY_TOURGUIDE ( 1 << 8 )// I have been acting as a tourguide.
  102. //#define bits_MEMORY_ ( 1 << 9 )//
  103. #define bits_MEMORY_LOCKED_HINT ( 1 << 10 )//
  104. //#define bits_MEMORY_ ( 1 << 12 )
  105. #define bits_MEMORY_TURNING ( 1 << 13 )// Turning, don't interrupt me.
  106. #define bits_MEMORY_TURNHACK ( 1 << 14 )
  107. #define bits_MEMORY_HAD_ENEMY ( 1 << 15 )// Had an enemy
  108. #define bits_MEMORY_HAD_PLAYER ( 1 << 16 )// Had player
  109. #define bits_MEMORY_HAD_LOS ( 1 << 17 )// Had LOS to enemy
  110. #define bits_MEMORY_MOVED_FROM_SPAWN ( 1 << 18 )// Has moved since spawning.
  111. #define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // NPC-specific memory
  112. #define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // NPC-specific memory
  113. #define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // NPC-specific memory
  114. #define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // NPC-specific memory
  115. //-------------------------------------
  116. // Spawn flags
  117. //-------------------------------------
  118. #define SF_NPC_WAIT_TILL_SEEN ( 1 << 0 ) // spawnflag that makes npcs wait until player can see them before attacking.
  119. #define SF_NPC_GAG ( 1 << 1 ) // no idle noises from this npc
  120. #define SF_NPC_FALL_TO_GROUND ( 1 << 2 ) // used my NPC_Maker
  121. #define SF_NPC_DROP_HEALTHKIT ( 1 << 3 ) // Drop a healthkit upon death
  122. #define SF_NPC_START_EFFICIENT ( 1 << 4 ) // Set into efficiency mode from spawn
  123. // ( 1 << 5 )
  124. // ( 1 << 6 )
  125. #define SF_NPC_WAIT_FOR_SCRIPT ( 1 << 7 ) // spawnflag that makes npcs wait to check for attacking until the script is done or they've been attacked
  126. #define SF_NPC_LONG_RANGE ( 1 << 8 ) // makes npcs look far and relaxes weapon range limit
  127. #define SF_NPC_FADE_CORPSE ( 1 << 9 ) // Fade out corpse after death
  128. #define SF_NPC_ALWAYSTHINK ( 1 << 10 ) // Simulate even when player isn't in PVS.
  129. #define SF_NPC_TEMPLATE ( 1 << 11 ) // This NPC will be used as a template by an npc_maker -- do not spawn.
  130. #define SF_NPC_ALTCOLLISION ( 1 << 12 )
  131. #define SF_NPC_NO_WEAPON_DROP ( 1 << 13 ) // This NPC will not actually drop a weapon that can be picked up
  132. #define SF_NPC_NO_PLAYER_PUSHAWAY ( 1 << 14 )
  133. // ( 1 << 15 )
  134. // !! Flags above ( 1 << 15 ) are reserved for NPC sub-classes
  135. //-------------------------------------
  136. //
  137. // Return codes from CanPlaySequence.
  138. //
  139. //-------------------------------------
  140. enum CanPlaySequence_t
  141. {
  142. CANNOT_PLAY = 0, // Can't play for any number of reasons.
  143. CAN_PLAY_NOW, // Can play the script immediately.
  144. CAN_PLAY_ENQUEUED, // Can play the script after I finish playing my current script.
  145. };
  146. //-------------------------------------
  147. // Weapon holstering
  148. //-------------------------------------
  149. enum DesiredWeaponState_t
  150. {
  151. DESIREDWEAPONSTATE_IGNORE = 0,
  152. DESIREDWEAPONSTATE_HOLSTERED,
  153. DESIREDWEAPONSTATE_HOLSTERED_DESTROYED, // Put the weapon away, then destroy it.
  154. DESIREDWEAPONSTATE_UNHOLSTERED,
  155. DESIREDWEAPONSTATE_CHANGING,
  156. DESIREDWEAPONSTATE_CHANGING_DESTROY, // Destroy the weapon when this change is complete.
  157. };
  158. //-------------------------------------
  159. //
  160. // Efficiency modes
  161. //
  162. //-------------------------------------
  163. enum AI_Efficiency_t
  164. {
  165. // Run at full tilt
  166. AIE_NORMAL,
  167. // Run decision process less often
  168. AIE_EFFICIENT,
  169. // Run decision process even less often, ignore other NPCs
  170. AIE_VERY_EFFICIENT,
  171. // Run decision process even less often, ignore other NPCs
  172. AIE_SUPER_EFFICIENT,
  173. // Don't run at all
  174. AIE_DORMANT,
  175. };
  176. enum AI_MoveEfficiency_t
  177. {
  178. AIME_NORMAL,
  179. AIME_EFFICIENT,
  180. };
  181. //-------------------------------------
  182. //
  183. // Sleep state
  184. //
  185. //-------------------------------------
  186. enum AI_SleepState_t
  187. {
  188. AISS_AWAKE,
  189. AISS_WAITING_FOR_THREAT,
  190. AISS_WAITING_FOR_PVS,
  191. AISS_WAITING_FOR_INPUT,
  192. AISS_AUTO_PVS,
  193. AISS_AUTO_PVS_AFTER_PVS, // Same as AUTO_PVS, except doesn't activate until/unless the NPC is IN the player's PVS.
  194. };
  195. #define AI_SLEEP_FLAGS_NONE 0x00000000
  196. #define AI_SLEEP_FLAG_AUTO_PVS 0x00000001
  197. #define AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS 0x00000002
  198. //-------------------------------------
  199. //
  200. // Debug bits
  201. //
  202. //-------------------------------------
  203. enum DebugBaseNPCBits_e
  204. {
  205. bits_debugDisableAI = 0x00000001, // disable AI
  206. bits_debugStepAI = 0x00000002, // step AI
  207. };
  208. //-------------------------------------
  209. //
  210. // Base Sentence index for behaviors
  211. //
  212. //-------------------------------------
  213. enum SentenceIndex_t
  214. {
  215. SENTENCE_BASE_BEHAVIOR_INDEX = 1000,
  216. };
  217. #ifdef AI_MONITOR_FOR_OSCILLATION
  218. struct AIScheduleChoice_t
  219. {
  220. float m_flTimeSelected;
  221. CAI_Schedule *m_pScheduleSelected;
  222. };
  223. #endif//AI_MONITOR_FOR_OSCILLATION
  224. #define MARK_TASK_EXPENSIVE() \
  225. if ( GetOuter() ) \
  226. { \
  227. GetOuter()->Remember( bits_MEMORY_TASK_EXPENSIVE ); \
  228. }
  229. //=============================================================================
  230. //
  231. // Types used by CAI_BaseNPC
  232. //
  233. //=============================================================================
  234. struct AIScheduleState_t
  235. {
  236. int iCurTask;
  237. TaskStatus_e fTaskStatus;
  238. float timeStarted;
  239. float timeCurTaskStarted;
  240. AI_TaskFailureCode_t taskFailureCode;
  241. int iTaskInterrupt;
  242. bool bTaskRanAutomovement;
  243. bool bTaskUpdatedYaw;
  244. bool bScheduleWasInterrupted;
  245. DECLARE_SIMPLE_DATADESC();
  246. };
  247. // -----------------------------------------
  248. // An entity that this NPC can't reach
  249. // -----------------------------------------
  250. struct UnreachableEnt_t
  251. {
  252. EHANDLE hUnreachableEnt; // Entity that's unreachable
  253. float fExpireTime; // Time to forget this information
  254. Vector vLocationWhenUnreachable;
  255. DECLARE_SIMPLE_DATADESC();
  256. };
  257. //=============================================================================
  258. // SCRIPTED NPC INTERACTIONS
  259. //=============================================================================
  260. // -----------------------------------------
  261. // Scripted NPC interaction flags
  262. // -----------------------------------------
  263. #define SCNPC_FLAG_TEST_OTHER_ANGLES ( 1 << 1 )
  264. #define SCNPC_FLAG_TEST_OTHER_VELOCITY ( 1 << 2 )
  265. #define SCNPC_FLAG_LOOP_IN_ACTION ( 1 << 3 )
  266. #define SCNPC_FLAG_NEEDS_WEAPON_ME ( 1 << 4 )
  267. #define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 )
  268. #define SCNPC_FLAG_DONT_TELEPORT_AT_END_ME ( 1 << 6 )
  269. #define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )
  270. // -----------------------------------------
  271. // Scripted NPC interaction trigger methods
  272. // -----------------------------------------
  273. enum
  274. {
  275. SNPCINT_CODE = 0,
  276. SNPCINT_AUTOMATIC_IN_COMBAT = 1,
  277. };
  278. // -----------------------------------------
  279. // Scripted NPC interaction loop breaking trigger methods
  280. // -----------------------------------------
  281. #define SNPCINT_LOOPBREAK_ON_DAMAGE ( 1 << 1 )
  282. #define SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ( 1 << 2 )
  283. // -----------------------------------------
  284. // Scripted NPC interaction anim phases
  285. // -----------------------------------------
  286. enum
  287. {
  288. SNPCINT_ENTRY = 0,
  289. SNPCINT_SEQUENCE,
  290. SNPCINT_EXIT,
  291. SNPCINT_NUM_PHASES
  292. };
  293. struct ScriptedNPCInteraction_Phases_t
  294. {
  295. string_t iszSequence;
  296. int iActivity;
  297. DECLARE_SIMPLE_DATADESC();
  298. };
  299. // Allowable delta from the desired dynamic scripted sequence point
  300. #define DSS_MAX_DIST 6
  301. #define DSS_MAX_ANGLE_DIFF 4
  302. // Interaction Logic States
  303. enum
  304. {
  305. NPCINT_NOT_RUNNING = 0,
  306. NPCINT_RUNNING_ACTIVE, // I'm in an interaction that I initiated
  307. NPCINT_RUNNING_PARTNER, // I'm in an interaction that was initiated by the other NPC
  308. NPCINT_MOVING_TO_MARK, // I'm moving to a position to do an interaction
  309. };
  310. #define NPCINT_NONE -1
  311. #define MAXTACLAT_IGNORE -1
  312. // -----------------------------------------
  313. // A scripted interaction between NPCs
  314. // -----------------------------------------
  315. struct ScriptedNPCInteraction_t
  316. {
  317. ScriptedNPCInteraction_t()
  318. {
  319. iszInteractionName = NULL_STRING;
  320. iFlags = 0;
  321. iTriggerMethod = SNPCINT_CODE;
  322. iLoopBreakTriggerMethod = 0;
  323. vecRelativeOrigin = vec3_origin;
  324. bValidOnCurrentEnemy = false;
  325. flDelay = 5.0;
  326. flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST);
  327. flNextAttemptTime = 0;
  328. iszMyWeapon = NULL_STRING;
  329. iszTheirWeapon = NULL_STRING;
  330. for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
  331. {
  332. sPhases[i].iszSequence = NULL_STRING;
  333. sPhases[i].iActivity = ACT_INVALID;
  334. }
  335. }
  336. // Fill out these when passing to AddScriptedNPCInteraction
  337. string_t iszInteractionName;
  338. int iFlags;
  339. int iTriggerMethod;
  340. int iLoopBreakTriggerMethod;
  341. Vector vecRelativeOrigin; // (forward, right, up)
  342. QAngle angRelativeAngles;
  343. Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
  344. float flCameraDistance;
  345. QAngle angCameraAngles;
  346. float flDelay; // Delay before interaction can be used again
  347. float flDistSqr; // Max distance sqr from the relative origin the NPC is allowed to be to trigger
  348. string_t iszMyWeapon; // Classname of the weapon I'm holding, if any
  349. string_t iszTheirWeapon; // Classname of the weapon my interaction partner is holding, if any
  350. ScriptedNPCInteraction_Phases_t sPhases[SNPCINT_NUM_PHASES];
  351. // These will be filled out for you in AddScriptedNPCInteraction
  352. VMatrix matDesiredLocalToWorld; // Desired relative position / angles of the other NPC
  353. bool bValidOnCurrentEnemy;
  354. float flNextAttemptTime;
  355. DECLARE_SIMPLE_DATADESC();
  356. };
  357. //=============================================================================
  358. //
  359. // Utility functions
  360. //
  361. //=============================================================================
  362. Vector VecCheckToss ( CBaseEntity *pEdict, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
  363. Vector VecCheckToss ( CBaseEntity *pEntity, ITraceFilter *pFilter, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
  364. Vector VecCheckThrow( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0f, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
  365. extern Vector g_vecAttackDir;
  366. bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget );
  367. bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize = 0.0 );
  368. // FIXME: move to utils?
  369. float DeltaV( float v0, float v1, float d );
  370. float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVelocity, float flCurVelocity, float flIdealVelocity, float flAccelRate, float &flNewDistance, float &flNewVelocity );
  371. //=============================================================================
  372. //
  373. // class CAI_Manager
  374. //
  375. // Central location for components of the AI to operate across all AIs without
  376. // iterating over the global list of entities.
  377. //
  378. //=============================================================================
  379. class CAI_Manager
  380. {
  381. public:
  382. CAI_Manager();
  383. CAI_BaseNPC ** AccessAIs();
  384. int NumAIs();
  385. void AddAI( CAI_BaseNPC *pAI );
  386. void RemoveAI( CAI_BaseNPC *pAI );
  387. bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); }
  388. private:
  389. enum
  390. {
  391. MAX_AIS = 256
  392. };
  393. typedef CUtlVector<CAI_BaseNPC *> CAIArray;
  394. CAIArray m_AIs;
  395. };
  396. //-------------------------------------
  397. extern CAI_Manager g_AI_Manager;
  398. //=============================================================================
  399. // Purpose: Some bridges a little more complicated to allow behavior to see
  400. // what base class would do or control order in which it's done
  401. //=============================================================================
  402. abstract_class IAI_BehaviorBridge
  403. {
  404. public:
  405. #define AI_GENERATE_BRIDGE_INTERFACE
  406. #include "ai_behavior_template.h"
  407. // Non-standard bridge methods
  408. virtual void BehaviorBridge_GatherConditions() {}
  409. virtual int BehaviorBridge_SelectSchedule() { return 0; }
  410. virtual int BehaviorBridge_TranslateSchedule( int scheduleType ) { return 0; }
  411. virtual float BehaviorBridge_GetJumpGravity() const { return 0; }
  412. virtual bool BehaviorBridge_IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const { return 0; }
  413. virtual bool BehaviorBridge_MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ) { return 0; }
  414. };
  415. //=============================================================================
  416. //
  417. // class CAI_BaseNPC
  418. //
  419. //=============================================================================
  420. class CAI_BaseNPC : public CBaseCombatCharacter,
  421. public CAI_DefMovementSink,
  422. public IAI_BehaviorBridge
  423. {
  424. DECLARE_CLASS( CAI_BaseNPC, CBaseCombatCharacter );
  425. public:
  426. //-----------------------------------------------------
  427. //
  428. // Initialization, cleanup, serialization, identity
  429. //
  430. CAI_BaseNPC();
  431. ~CAI_BaseNPC();
  432. //---------------------------------
  433. DECLARE_DATADESC();
  434. DECLARE_SERVERCLASS();
  435. virtual int Save( ISave &save );
  436. virtual int Restore( IRestore &restore );
  437. virtual void OnRestore();
  438. void SaveConditions( ISave &save, const CAI_ScheduleBits &conditions );
  439. void RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions );
  440. bool ShouldSavePhysics() { return false; }
  441. virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
  442. virtual bool KeyValue( const char *szKeyName, const char *szValue );
  443. //---------------------------------
  444. virtual void PostConstructor( const char *szClassname );
  445. virtual void Activate( void );
  446. virtual void Precache( void ); // derived calls at start of Spawn()
  447. virtual bool CreateVPhysics();
  448. virtual void NPCInit( void ); // derived calls after Spawn()
  449. void NPCInitThink( void );
  450. virtual void PostNPCInit() {};// called after NPC_InitThink
  451. virtual void StartNPC( void );
  452. virtual bool IsTemplate( void );
  453. virtual void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
  454. virtual void UpdateOnRemove( void );
  455. virtual int UpdateTransmitState();
  456. //---------------------------------
  457. // Component creation factories
  458. //
  459. // The master call, override if you introduce new component types. Call base first
  460. virtual bool CreateComponents();
  461. // Components defined by the base AI class
  462. virtual CAI_Senses * CreateSenses();
  463. virtual CAI_MoveProbe * CreateMoveProbe();
  464. virtual CAI_Motor * CreateMotor();
  465. virtual CAI_LocalNavigator *CreateLocalNavigator();
  466. virtual CAI_Navigator * CreateNavigator();
  467. virtual CAI_Pathfinder *CreatePathfinder();
  468. virtual CAI_TacticalServices *CreateTacticalServices();
  469. //---------------------------------
  470. virtual bool IsNPC( void ) const { return true; }
  471. //---------------------------------
  472. void TestPlayerPushing( CBaseEntity *pPlayer );
  473. void CascadePlayerPush( const Vector &push, const Vector &pushOrigin );
  474. void NotifyPushMove();
  475. public:
  476. //-----------------------------------------------------
  477. //
  478. // AI processing - thinking, schedule selection and task running
  479. //
  480. //-----------------------------------------------------
  481. void CallNPCThink( void );
  482. // Thinking, including core thinking, movement, animation
  483. virtual void NPCThink( void );
  484. // Core thinking (schedules & tasks)
  485. virtual void RunAI( void );// core ai function!
  486. // Called to gather up all relevant conditons
  487. virtual void GatherConditions( void );
  488. // Called immediately prior to schedule processing
  489. virtual void PrescheduleThink( void );
  490. // Called immediately after schedule processing
  491. virtual void PostscheduleThink( void ) { return; };
  492. // Notification that the current schedule, if any, is ending and a new one is being selected
  493. virtual void OnScheduleChange( void );
  494. virtual void OnSetSchedule( void ){};
  495. // Notification that a new schedule is about to run its first task
  496. virtual void OnStartSchedule( int scheduleType ) {};
  497. // This function implements a decision tree for the NPC. It is responsible for choosing the next behavior (schedule)
  498. // based on the current conditions and state.
  499. virtual int SelectSchedule( void );
  500. virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
  501. // After the schedule has been selected, it will be processed by this function so child NPC classes can
  502. // remap base schedules into child-specific behaviors
  503. virtual int TranslateSchedule( int scheduleType );
  504. virtual void StartTask( const Task_t *pTask );
  505. virtual void RunTask( const Task_t *pTask );
  506. void ClearTransientConditions();
  507. virtual void HandleAnimEvent( animevent_t *pEvent );
  508. virtual void TranslateAddOnAttachment( char *pchAttachmentName, int iCount );
  509. virtual bool IsInterruptable();
  510. virtual void OnStartScene( void ) {} // Called when an NPC begins a cine scene (useful for clean-up)
  511. virtual bool ShouldPlayerAvoid( void );
  512. virtual void SetPlayerAvoidState( void );
  513. virtual void PlayerPenetratingVPhysics( void );
  514. virtual bool ShouldAlwaysThink();
  515. void ForceGatherConditions() { m_bForceConditionsGather = true; SetEfficiency( AIE_NORMAL ); } // Force an NPC out of PVS to call GatherConditions on next think
  516. bool IsForceGatherConditionsSet() { return m_bForceConditionsGather; }
  517. virtual float LineOfSightDist( const Vector &vecDir = vec3_invalid, float zEye = FLT_MAX );
  518. virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
  519. virtual const char *GetTracerType( void );
  520. virtual void DoImpactEffect( trace_t &tr, int nDamageType );
  521. enum
  522. {
  523. NEXT_SCHEDULE = LAST_SHARED_SCHEDULE,
  524. NEXT_TASK = LAST_SHARED_TASK,
  525. NEXT_CONDITION = LAST_SHARED_CONDITION,
  526. };
  527. protected:
  528. // Used by derived classes to chain a task to a task that might not be the
  529. // one they are currently handling:
  530. void ChainStartTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; StartTask( (const Task_t *)&tempTask ); }
  531. void ChainRunTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; RunTask( (const Task_t *) &tempTask ); }
  532. void StartTaskOverlay();
  533. virtual void RunTaskOverlay();
  534. virtual bool ModifyAutoMovement( Vector &vecNewPos ) { return false; } // allow NPCs to adjust automovement
  535. void EndTaskOverlay();
  536. virtual void PostRunStopMoving();
  537. virtual bool CheckPVSCondition();
  538. private:
  539. bool CanThinkRebalance();
  540. void RebalanceThinks();
  541. bool PreNPCThink();
  542. void PostNPCThink();
  543. bool PreThink( void );
  544. void PerformSensing();
  545. void CheckOnGround( void );
  546. void MaintainSchedule( void );
  547. void RunAnimation( void );
  548. void PostRun( void );
  549. void PerformMovement();
  550. void PostMovement();
  551. virtual int StartTask ( Task_t *pTask ) { DevMsg( "Called wrong StartTask()\n" ); StartTask( (const Task_t *)pTask ); return 0; } // to ensure correct signature in derived classes
  552. virtual int RunTask ( Task_t *pTask ) { DevMsg( "Called wrong RunTask()\n" ); RunTask( (const Task_t *)pTask ); return 0; } // to ensure correct signature in derived classes
  553. public:
  554. //-----------------------------------------------------
  555. //
  556. // Schedules & tasks
  557. //
  558. //-----------------------------------------------------
  559. void SetSchedule( CAI_Schedule *pNewSchedule );
  560. bool SetSchedule( int localScheduleID );
  561. void SetDefaultFailSchedule( int failSchedule ) { m_failSchedule = failSchedule; }
  562. void ClearSchedule( const char *szReason );
  563. inline CAI_Schedule *GetCurSchedule() const { return m_pSchedule; }
  564. bool IsCurSchedule( int schedId, bool fIdeal = true );
  565. virtual CAI_Schedule *GetSchedule(int localScheduleID);
  566. virtual int GetLocalScheduleId( int globalScheduleID ) { return AI_IdIsLocal( globalScheduleID ) ? globalScheduleID : GetClassScheduleIdSpace()->ScheduleGlobalToLocal( globalScheduleID ); }
  567. virtual int GetGlobalScheduleId( int localScheduleID ) { return AI_IdIsGlobal( localScheduleID ) ? localScheduleID : GetClassScheduleIdSpace()->ScheduleLocalToGlobal( localScheduleID ); }
  568. float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; }
  569. //---------------------------------
  570. const Task_t* GetTask( void );
  571. int TaskIsRunning( void );
  572. virtual void TaskFail( AI_TaskFailureCode_t );
  573. void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); }
  574. void TaskComplete( bool fIgnoreSetFailedCondition = false );
  575. void TaskInterrupt() { m_ScheduleState.iTaskInterrupt++; }
  576. void ClearTaskInterrupt() { m_ScheduleState.iTaskInterrupt = 0; }
  577. int GetTaskInterrupt() const { return m_ScheduleState.iTaskInterrupt; }
  578. void TaskMovementComplete( void );
  579. inline int TaskIsComplete( void ) { return (GetTaskStatus() == TASKSTATUS_COMPLETE); }
  580. virtual const char *TaskName(int taskID);
  581. float GetTimeTaskStarted() const { return m_ScheduleState.timeCurTaskStarted; }
  582. virtual int GetLocalTaskId( int globalTaskId) { return GetClassScheduleIdSpace()->TaskGlobalToLocal( globalTaskId ); }
  583. virtual const char *GetSchedulingErrorName() { return "CAI_BaseNPC"; }
  584. protected:
  585. static bool LoadSchedules(void);
  586. virtual bool LoadedSchedules(void);
  587. virtual void BuildScheduleTestBits( void );
  588. //---------------------------------
  589. // This is the main call to select/translate a schedule
  590. virtual CAI_Schedule *GetNewSchedule( void );
  591. virtual CAI_Schedule *GetFailSchedule( void );
  592. //---------------------------------
  593. virtual bool CanFlinch( void );
  594. virtual void CheckFlinches( void );
  595. virtual void PlayFlinchGesture( void );
  596. int SelectFlinchSchedule( void );
  597. virtual bool IsAllowedToDodge( void );
  598. protected:
  599. bool IsInChoreo() const;
  600. // Choreo state is reset each time UpdateEfficiency() is called. Setting it in leaf code
  601. // outside UpdateEfficiency() will result in your changes being lost.
  602. bool m_bInChoreo;
  603. protected:
  604. // This function maps the type through TranslateSchedule() and then retrieves the pointer
  605. // to the actual CAI_Schedule from the database of schedules available to this class.
  606. CAI_Schedule * GetScheduleOfType( int scheduleType );
  607. bool FHaveSchedule( void );
  608. bool FScheduleDone ( void );
  609. CAI_Schedule * ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount );
  610. int GetScheduleCurTaskIndex() const { return m_ScheduleState.iCurTask; }
  611. inline int IncScheduleCurTaskIndex();
  612. inline void ResetScheduleCurTaskIndex();
  613. void NextScheduledTask ( void );
  614. bool IsScheduleValid ( void );
  615. bool ShouldSelectIdealState( void );
  616. // Selecting the ideal state
  617. NPC_STATE SelectIdleIdealState();
  618. NPC_STATE SelectAlertIdealState();
  619. NPC_STATE SelectScriptIdealState();
  620. // Various schedule selections based on NPC_STATE
  621. int SelectIdleSchedule();
  622. int SelectAlertSchedule();
  623. int SelectCombatSchedule();
  624. virtual int SelectDeadSchedule();
  625. virtual int SelectScriptSchedule();
  626. int SelectInteractionSchedule();
  627. void OnStartTask( void ) { SetTaskStatus( TASKSTATUS_RUN_MOVE_AND_TASK ); }
  628. void SetTaskStatus( TaskStatus_e status ) { m_ScheduleState.fTaskStatus = status; }
  629. TaskStatus_e GetTaskStatus() const { return m_ScheduleState.fTaskStatus; }
  630. void DiscardScheduleState();
  631. //---------------------------------
  632. CAI_Schedule * m_pSchedule;
  633. int m_IdealSchedule;
  634. AIScheduleState_t m_ScheduleState;
  635. int m_failSchedule; // Schedule type to choose if current schedule fails
  636. bool m_bDoPostRestoreRefindPath;
  637. bool m_bUsingStandardThinkTime;
  638. float m_flLastRealThinkTime;
  639. int m_iFrameBlocked;
  640. static int gm_iNextThinkRebalanceTick;
  641. static float gm_flTimeLastSpawn;
  642. static int gm_nSpawnedThisFrame;
  643. CGlobalEvent *m_pScheduleEvent;
  644. protected: // pose parameters
  645. int m_poseAim_Pitch;
  646. int m_poseAim_Yaw;
  647. int m_poseMove_Yaw;
  648. virtual void PopulatePoseParameters( void );
  649. public:
  650. inline bool HasPoseMoveYaw() { return ( m_poseMove_Yaw >= 0 ); }
  651. // Return the stored pose parameter for "move_yaw"
  652. inline int LookupPoseMoveYaw() { return m_poseMove_Yaw; }
  653. //-----------------------------------------------------
  654. //
  655. // Hooks for CAI_Behaviors
  656. //
  657. //-----------------------------------------------------
  658. void AddBehavior( CAI_BehaviorBase *pBehavior );
  659. void RemoveAndDestroyBehavior( CAI_BehaviorBase *pBehavior );
  660. template <class BEHAVIOR_TYPE>
  661. bool GetBehavior( BEHAVIOR_TYPE **ppBehavior )
  662. {
  663. CAI_BehaviorBase **ppBehaviors = AccessBehaviors();
  664. *ppBehavior = NULL;
  665. for ( int i = 0; i < NumBehaviors(); i++ )
  666. {
  667. *ppBehavior = dynamic_cast<BEHAVIOR_TYPE *>(ppBehaviors[i]);
  668. if ( *ppBehavior )
  669. return true;
  670. }
  671. return false;
  672. }
  673. virtual bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ) { return true; }
  674. bool BehaviorSelectSchedule();
  675. bool IsRunningBehavior() const;
  676. CAI_BehaviorBase *GetPrimaryBehavior();
  677. CAI_BehaviorBase *DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior );
  678. void SetPrimaryBehavior( CAI_BehaviorBase *pNewBehavior );
  679. virtual bool ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) { return true; }
  680. virtual void OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) {}
  681. // Notification that the status behavior ability to select schedules has changed.
  682. // Return "true" to signal a schedule interrupt is desired
  683. virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule );
  684. virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) {}
  685. virtual CAI_BehaviorBase ** AccessBehaviors()
  686. {
  687. if (m_Behaviors.Count())
  688. return m_Behaviors.Base();
  689. return NULL;
  690. }
  691. virtual int NumBehaviors()
  692. {
  693. return m_Behaviors.Count();
  694. }
  695. // Automatically called during entity construction, derived class calls AddBehavior()
  696. virtual bool CreateBehaviors() { return true; }
  697. protected:
  698. CAI_BehaviorBase * m_pPrimaryBehavior;
  699. CUtlVector<CAI_BehaviorBase *> m_Behaviors;
  700. public:
  701. //-----------------------------------------------------
  702. //
  703. // Conditions
  704. //
  705. //-----------------------------------------------------
  706. virtual const char* ConditionName(int conditionID);
  707. virtual void RemoveIgnoredConditions ( void );
  708. void SetCondition( int iCondition /*, bool state = true*/ );
  709. bool HasCondition( int iCondition );
  710. bool HasCondition( int iCondition, bool bUseIgnoreConditions );
  711. bool HasInterruptCondition( int iCondition );
  712. bool HasConditionsToInterruptSchedule( int nLocalScheduleID );
  713. void ClearCondition( int iCondition );
  714. void ClearConditions( int *pConditions, int nConditions );
  715. void SetIgnoreConditions( int *pConditions, int nConditions );
  716. void ClearIgnoreConditions( int *pConditions, int nConditions );
  717. bool ConditionInterruptsCurSchedule( int iCondition );
  718. bool ConditionInterruptsSchedule( int schedule, int iCondition );
  719. void SetCustomInterruptCondition( int nCondition );
  720. bool IsCustomInterruptConditionSet( int nCondition );
  721. void ClearCustomInterruptCondition( int nCondition );
  722. void ClearCustomInterruptConditions( void );
  723. virtual void OnConditionSet( int nCondition ) { };
  724. virtual void OnConditionCleared( int nCondition ) { };
  725. bool ConditionsGathered() const { return m_bConditionsGathered; }
  726. const CAI_ScheduleBits &AccessConditionBits() const { return m_Conditions; }
  727. CAI_ScheduleBits & AccessConditionBits() { return m_Conditions; }
  728. bool DidChooseEnemy() const { return !m_bSkippedChooseEnemy; }
  729. private:
  730. CAI_ScheduleBits m_Conditions;
  731. CAI_ScheduleBits m_CustomInterruptConditions; //Bit string assembled by the schedule running, then
  732. //modified by leaf classes to suit their needs
  733. CAI_ScheduleBits m_ConditionsPreIgnore;
  734. CAI_ScheduleBits m_InverseIgnoreConditions;
  735. bool m_bForceConditionsGather;
  736. bool m_bConditionsGathered;
  737. bool m_bSkippedChooseEnemy;
  738. public:
  739. //-----------------------------------------------------
  740. //
  741. // NPC State
  742. //
  743. //-----------------------------------------------------
  744. inline void SetIdealState( NPC_STATE eIdealState );
  745. inline NPC_STATE GetIdealState();
  746. virtual NPC_STATE SelectIdealState( void );
  747. void SetState( NPC_STATE State );
  748. virtual bool ShouldGoToIdleState( void ) { return ( false ); }
  749. virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) {/*Base class doesn't care*/};
  750. NPC_STATE GetState( void ) { return m_NPCState; }
  751. AI_Efficiency_t GetEfficiency() const { return m_Efficiency; }
  752. void SetEfficiency( AI_Efficiency_t efficiency ) { m_Efficiency = efficiency; }
  753. AI_MoveEfficiency_t GetMoveEfficiency() const { return m_MoveEfficiency; }
  754. void SetMoveEfficiency( AI_MoveEfficiency_t efficiency ) { m_MoveEfficiency = efficiency; }
  755. virtual void UpdateEfficiency( bool bInPVS );
  756. void ForceDecisionThink() { m_flNextDecisionTime = 0; SetEfficiency( AIE_NORMAL ); }
  757. bool IsFlaggedEfficient() const { return HasSpawnFlags( SF_NPC_START_EFFICIENT ); }
  758. AI_SleepState_t GetSleepState() const { return m_SleepState; }
  759. void SetSleepState( AI_SleepState_t sleepState ) { m_SleepState = sleepState; }
  760. void AddSleepFlags( int flags ) { m_SleepFlags |= flags; }
  761. void RemoveSleepFlags( int flags ) { m_SleepFlags &= ~flags; }
  762. bool HasSleepFlags( int flags ) { return (m_SleepFlags & flags) == flags; }
  763. virtual void UpdateSleepState( bool bInPVS );
  764. virtual void Wake( bool bFireOutput = true );
  765. void Sleep();
  766. bool WokeThisTick() const;
  767. //---------------------------------
  768. NPC_STATE m_NPCState; // npc's current state
  769. float m_flLastStateChangeTime;
  770. private:
  771. NPC_STATE m_IdealNPCState; // npc should change to this state
  772. AI_Efficiency_t m_Efficiency;
  773. AI_MoveEfficiency_t m_MoveEfficiency;
  774. float m_flNextDecisionTime;
  775. AI_SleepState_t m_SleepState;
  776. int m_SleepFlags;
  777. float m_flWakeRadius;
  778. bool m_bWakeSquad;
  779. int m_nWakeTick;
  780. public:
  781. //-----------------------------------------------------
  782. //
  783. // Activities
  784. //
  785. //-----------------------------------------------------
  786. Activity TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity = NULL );
  787. Activity NPC_TranslateActivity( Activity eNewActivity );
  788. Activity GetActivity( void ) { return m_Activity; }
  789. virtual void SetActivity( Activity NewActivity );
  790. Activity GetIdealActivity( void ) { return m_IdealActivity; }
  791. void SetIdealActivity( Activity NewActivity );
  792. void SetIdealSequence( int iSequence, bool bReset = false ) { if ( bReset ) ResetIdealActivity( ACT_SPECIFIC_SEQUENCE ); else SetIdealActivity( ACT_SPECIFIC_SEQUENCE ); m_nIdealSequence = iSequence; }
  793. void ResetIdealActivity( Activity newIdealActivity );
  794. void SetSequenceByName( char *szSequence );
  795. void SetSequenceById( int iSequence );
  796. Activity GetScriptCustomMoveActivity( void );
  797. int GetScriptCustomMoveSequence( void );
  798. Activity GetStoppedActivity( void );
  799. inline bool HaveSequenceForActivity( Activity activity );
  800. inline bool IsActivityStarted(void);
  801. virtual bool IsActivityFinished( void );
  802. virtual bool IsActivityMovementPhased( Activity activity );
  803. virtual void OnChangeActivity( Activity eNewActivity );
  804. void MaintainActivity(void);
  805. void ResetActivity(void) { m_Activity = ACT_RESET; }
  806. void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity);
  807. private:
  808. void AdvanceToIdealActivity(void);
  809. void ResolveActivityToSequence(Activity NewActivity, int &iSequence, Activity &translatedActivity, Activity &weaponActivity);
  810. Activity m_Activity; // Current animation state
  811. Activity m_translatedActivity; // Current actual translated animation
  812. Activity m_IdealActivity; // Desired animation state
  813. int m_nIdealSequence; // Desired animation sequence
  814. Activity m_IdealTranslatedActivity; // Desired actual translated animation state
  815. Activity m_IdealWeaponActivity; // Desired weapon animation state
  816. CNetworkVar(int, m_iDeathPose );
  817. CNetworkVar(int, m_iDeathFrame );
  818. public:
  819. //-----------------------------------------------------
  820. //
  821. // Senses
  822. //
  823. //-----------------------------------------------------
  824. CAI_Senses * GetSenses() { return m_pSenses; }
  825. const CAI_Senses * GetSenses() const { return m_pSenses; }
  826. void SetDistLook( float flDistLook );
  827. virtual bool QueryHearSound( CSound *pSound );
  828. virtual bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );
  829. virtual void OnLooked( int iDistance );
  830. virtual void OnListened();
  831. virtual void OnSeeEntity( CBaseEntity *pEntity ) {}
  832. // If true, AI will try to see this entity regardless of distance.
  833. virtual bool ShouldNotDistanceCull() { return false; }
  834. virtual int GetSoundInterests( void );
  835. virtual int GetSoundPriority( CSound *pSound );
  836. CSound * GetLoudestSoundOfType( int iType );
  837. virtual CSound * GetBestSound( int validTypes = ALL_SOUNDS );
  838. virtual CSound * GetBestScent( void );
  839. virtual float HearingSensitivity( void ) { return 1.0; }
  840. virtual bool ShouldIgnoreSound( CSound * ) { return false; }
  841. bool SoundIsVisible( CSound *pSound );
  842. protected:
  843. virtual void ClearSenseConditions( void );
  844. private:
  845. void LockBestSound();
  846. void UnlockBestSound();
  847. CAI_Senses * m_pSenses;
  848. CSound * m_pLockedBestSound;
  849. public:
  850. //-----------------------------------------------------
  851. //
  852. // Enemy and target
  853. //
  854. //-----------------------------------------------------
  855. Vector GetSmoothedVelocity( void );
  856. CBaseEntity* GetEnemy() { return m_hEnemy.Get(); }
  857. CBaseEntity* GetEnemy() const { return m_hEnemy.Get(); }
  858. float GetTimeEnemyAcquired() { return m_flTimeEnemyAcquired; }
  859. void SetEnemy( CBaseEntity *pEnemy, bool bSetCondNewEnemy = true );
  860. virtual void OnEnemyChanged( CBaseEntity *pOldEnemy, CBaseEntity *pNewEnemy ) { }
  861. virtual const Vector & GetEnemyLKP() const;
  862. float GetEnemyLastTimeSeen() const;
  863. void MarkEnemyAsEluded();
  864. void ClearEnemyMemory();
  865. bool EnemyHasEludedMe() const;
  866. virtual CBaseEntity *BestEnemy(); // returns best enemy in memory list
  867. virtual bool IsValidEnemy( CBaseEntity *pEnemy );
  868. virtual bool CanBeAnEnemyOf( CBaseEntity *pEnemy );
  869. void ForceChooseNewEnemy() { m_EnemiesSerialNumber = -1; }
  870. bool ChooseEnemy();
  871. virtual bool ShouldChooseNewEnemy();
  872. virtual void GatherEnemyConditions( CBaseEntity *pEnemy );
  873. virtual float EnemyDistTolerance() { return 0; } // Enemy distances within this tolerance of each other are considered equivalent.
  874. float EnemyDistance( CBaseEntity *pEnemy );
  875. CBaseCombatCharacter *GetEnemyCombatCharacterPointer();
  876. void SetEnemyOccluder(CBaseEntity *pBlocker);
  877. CBaseEntity *GetEnemyOccluder(void);
  878. virtual void StartTargetHandling( CBaseEntity *pTargetEnt );
  879. //---------------------------------
  880. CBaseEntity* GetTarget() { return m_hTargetEnt.Get(); }
  881. void SetTarget( CBaseEntity *pTarget );
  882. void CheckTarget( CBaseEntity *pTarget );
  883. float GetAcceptableTimeSeenEnemy( void ) { return m_flAcceptableTimeSeenEnemy; }
  884. virtual CAI_BaseNPC *CreateCustomTarget( const Vector &vecOrigin, float duration = -1 );
  885. void SetDeathPose( const int &iDeathPose ) { m_iDeathPose = iDeathPose; }
  886. void SetDeathPoseFrame( const int &iDeathPoseFrame ) { m_iDeathFrame = iDeathPoseFrame; }
  887. void SelectDeathPose( const CTakeDamageInfo &info );
  888. virtual bool ShouldPickADeathPose( void ) { return true; }
  889. virtual bool AllowedToIgnite( void ) { return false; }
  890. protected:
  891. virtual float GetGoalRepathTolerance( CBaseEntity *pGoalEnt, GoalType_t type, const Vector &curGoal, const Vector &curTargetPos );
  892. private:
  893. void * CheckEnemy( CBaseEntity *pEnemy ) { return NULL; } // OBSOLETE, replaced by GatherEnemyConditions(), left here to make derived code not compile
  894. // Updates the goal position in case of GOALTYPE_ENEMY
  895. void UpdateEnemyPos();
  896. // Updates the goal position in case of GOALTYPE_TARGETENT
  897. void UpdateTargetPos();
  898. //---------------------------------
  899. EHANDLE m_hEnemy; // the entity that the npc is fighting.
  900. float m_flTimeEnemyAcquired; // The time at which the entity the NPC is fighting became the NPC's enemy.
  901. EHANDLE m_hTargetEnt; // the entity that the npc is trying to reach
  902. CRandStopwatch m_GiveUpOnDeadEnemyTimer;
  903. CSimpleSimTimer m_FailChooseEnemyTimer;
  904. int m_EnemiesSerialNumber;
  905. float m_flAcceptableTimeSeenEnemy;
  906. CSimpleSimTimer m_UpdateEnemyPosTimer;
  907. static CSimpleSimTimer m_AnyUpdateEnemyPosTimer;
  908. public:
  909. //-----------------------------------------------------
  910. //
  911. // Commander mode stuff.
  912. //
  913. //-----------------------------------------------------
  914. virtual bool IsCommandable() { return false; }
  915. virtual bool IsPlayerAlly( CBasePlayer *pPlayer = NULL );
  916. virtual bool IsMedic() { return false; }
  917. virtual bool IsCommandMoving() { return false; }
  918. virtual bool ShouldAutoSummon() { return false; }
  919. virtual void SetCommandGoal( const Vector &vecGoal );
  920. virtual void ClearCommandGoal();
  921. virtual void OnTargetOrder() {}
  922. virtual void OnMoveOrder() {}
  923. virtual bool IsValidCommandTarget( CBaseEntity *pTarget ) { return false; }
  924. const Vector &GetCommandGoal() const { return m_vecCommandGoal; }
  925. virtual void OnMoveToCommandGoalFailed() {}
  926. string_t GetPlayerSquadName() const { Assert( gm_iszPlayerSquad != NULL_STRING ); return gm_iszPlayerSquad; }
  927. bool IsInPlayerSquad() const;
  928. virtual CAI_BaseNPC *GetSquadCommandRepresentative() { return NULL; }
  929. virtual bool TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ) { OnTargetOrder(); return true; }
  930. virtual void MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ) { SetCommandGoal( vecDest ); SetCondition( COND_RECEIVED_ORDERS ); OnMoveOrder(); }
  931. // Return true if you're willing to be idly talked to by other friends.
  932. virtual bool CanBeUsedAsAFriend( void );
  933. private:
  934. Vector m_vecCommandGoal;
  935. static string_t gm_iszPlayerSquad;
  936. public:
  937. CAI_MoveMonitor m_CommandMoveMonitor;
  938. //-----------------------------------------------------
  939. // Dynamic scripted NPC interactions
  940. //-----------------------------------------------------
  941. public:
  942. float GetInteractionYaw( void ) const { return m_flInteractionYaw; }
  943. protected:
  944. void ParseScriptedNPCInteractions( void );
  945. void AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction );
  946. const char *GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase );
  947. void StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive );
  948. void StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles );
  949. void CheckForScriptedNPCInteractions( void );
  950. void CalculateValidEnemyInteractions( void );
  951. void CheckForcedNPCInteractions( void );
  952. bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
  953. virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
  954. bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
  955. bool IsActiveDynamicInteraction( void ) { return (m_iInteractionState == NPCINT_RUNNING_ACTIVE && (m_hCine != NULL)); }
  956. ScriptedNPCInteraction_t *GetRunningDynamicInteraction( void ) { return &(m_ScriptedInteractions[m_iInteractionPlaying]); }
  957. void SetInteractionCantDie( bool bCantDie ) { m_bCannotDieDuringInteraction = bCantDie; }
  958. bool HasInteractionCantDie( void );
  959. void InputForceInteractionWithNPC( inputdata_t &inputdata );
  960. void StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction );
  961. void CleanupForcedInteraction( void );
  962. void CalculateForcedInteractionPosition( void );
  963. CAI_BaseNPC *GetInteractionPartner( void );
  964. private:
  965. // Forced interactions
  966. CHandle<CAI_BaseNPC> m_hForcedInteractionPartner;
  967. Vector m_vecForcedWorldPosition;
  968. float m_flForcedInteractionTimeout; // Abort the interaction if it hasn't started by this time.
  969. CHandle<CAI_BaseNPC> m_hInteractionPartner;
  970. EHANDLE m_hLastInteractionTestTarget;
  971. bool m_bCannotDieDuringInteraction;
  972. int m_iInteractionState;
  973. int m_iInteractionPlaying;
  974. CUtlVector<ScriptedNPCInteraction_t> m_ScriptedInteractions;
  975. float m_flInteractionYaw;
  976. public:
  977. //-----------------------------------------------------
  978. //
  979. // Sounds
  980. //
  981. //-----------------------------------------------------
  982. virtual CanPlaySequence_t CanPlaySequence( bool fDisregardState, int interruptLevel );
  983. virtual bool CanPlaySentence( bool fDisregardState ) { return IsAlive(); }
  984. virtual int PlaySentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener = NULL );
  985. virtual int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener );
  986. virtual bool FOkToMakeSound( int soundPriority = 0 );
  987. virtual void JustMadeSound( int soundPriority = 0, float flSoundLength = 0.0f );
  988. virtual void DeathSound( const CTakeDamageInfo &info ) { return; };
  989. virtual void AlertSound( void ) { return; };
  990. virtual void IdleSound( void ) { return; };
  991. virtual void PainSound( const CTakeDamageInfo &info ) { return; };
  992. virtual void FearSound( void ) { return; };
  993. virtual void LostEnemySound( void ) { return; };
  994. virtual void FoundEnemySound( void ) { return; };
  995. virtual void BarnacleDeathSound( void ) { CTakeDamageInfo info; PainSound( info ); }
  996. virtual void SpeakSentence( int sentenceType ) { return; };
  997. virtual bool ShouldPlayIdleSound( void );
  998. virtual void MakeAIFootstepSound( float volume, float duration = 0.5f );
  999. //---------------------------------
  1000. virtual CAI_Expresser *GetExpresser() { AssertMsg(false, "Called GetExpresser() on something that has no expresser!\n"); return NULL; }
  1001. const CAI_Expresser *GetExpresser() const { return const_cast<CAI_BaseNPC *>(this)->GetExpresser(); }
  1002. //---------------------------------
  1003. // NPC Event Response System
  1004. virtual bool CanRespondToEvent( const char *ResponseConcept ) { return false; }
  1005. virtual bool RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene ) { return false; }
  1006. virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
  1007. virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
  1008. protected:
  1009. float SoundWaitTime() const { return m_flSoundWaitTime; }
  1010. public:
  1011. //-----------------------------------------------------
  1012. //
  1013. // Capabilities report (from CBaseCombatCharacter)
  1014. //
  1015. //-----------------------------------------------------
  1016. virtual int CapabilitiesGet( void ) const;
  1017. // local capabilities access
  1018. int CapabilitiesAdd( int capabilities );
  1019. int CapabilitiesRemove( int capabilities );
  1020. void CapabilitiesClear( void );
  1021. private:
  1022. int m_afCapability; // tells us what a npc can/can't do.
  1023. public:
  1024. //-----------------------------------------------------
  1025. //
  1026. // Pathfinding, navigation & movement
  1027. //
  1028. //-----------------------------------------------------
  1029. CAI_Navigator * GetNavigator() { return m_pNavigator; }
  1030. const CAI_Navigator *GetNavigator() const { return m_pNavigator; }
  1031. CAI_LocalNavigator *GetLocalNavigator() { return m_pLocalNavigator; }
  1032. const CAI_LocalNavigator *GetLocalNavigator() const { return m_pLocalNavigator; }
  1033. CAI_Pathfinder * GetPathfinder() { return m_pPathfinder; }
  1034. const CAI_Pathfinder *GetPathfinder() const { return m_pPathfinder; }
  1035. CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; }
  1036. const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; }
  1037. CAI_Motor * GetMotor() { return m_pMotor; }
  1038. const CAI_Motor * GetMotor() const { return m_pMotor; }
  1039. //---------------------------------
  1040. static bool FindSpotForNPCInRadius( Vector *pResult, const Vector &vStartPos, CAI_BaseNPC *pNPC, float radius, bool bOutOfPlayerViewcone = false );
  1041. //---------------------------------
  1042. virtual bool IsNavigationUrgent();
  1043. virtual bool ShouldFailNav( bool bMovementFailed );
  1044. virtual bool ShouldBruteForceFailedNav() { return false; }
  1045. // The current navigation (movement) mode (e.g. fly, swim, locomote, etc)
  1046. Navigation_t GetNavType() const;
  1047. void SetNavType( Navigation_t navType );
  1048. CBaseEntity * GetNavTargetEntity(void);
  1049. bool IsMoving( void );
  1050. virtual float GetTimeToNavGoal();
  1051. // NPCs can override this to tweak with how costly particular movements are
  1052. virtual bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
  1053. // Turns a directional vector into a yaw value that points down that vector.
  1054. float VecToYaw( const Vector &vecDir );
  1055. // Turning
  1056. virtual float CalcIdealYaw( const Vector &vecTarget );
  1057. virtual float MaxYawSpeed( void ); // Get max yaw speed
  1058. bool FacingIdeal( float flTolerance = 0.0f );
  1059. void SetUpdatedYaw() { m_ScheduleState.bTaskUpdatedYaw = true; }
  1060. // Add multiple facing goals while moving/standing still.
  1061. virtual void AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 );
  1062. virtual void AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
  1063. virtual void AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
  1064. virtual float GetFacingDirection( Vector &vecDir );
  1065. // ------------
  1066. // Methods used by motor to query properties/preferences/move-related state
  1067. // ------------
  1068. virtual bool CanStandOn( CBaseEntity *pSurface ) const;
  1069. virtual bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; // Override for specific creature types
  1070. virtual bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const;
  1071. bool ShouldMoveWait();
  1072. #ifdef INFESTED_DLL
  1073. virtual float StepHeight() const { return 24.0f; } // NOTE: Have to set this here rather than in the Infested derived AI classes, as this value is used by the AI node network generation
  1074. #else
  1075. virtual float StepHeight() const { return 18.0f; }
  1076. #endif
  1077. float GetStepDownMultiplier() const;
  1078. virtual float GetMaxJumpSpeed() const { return 350.0f; }
  1079. virtual float GetJumpGravity() const { return GetDefaultJumpGravity(); }
  1080. virtual float GetDefaultJumpGravity() const { return 1.0f; }
  1081. virtual float GetMinJumpHeight() const { return 0; }
  1082. //---------------------------------
  1083. virtual bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so)
  1084. virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval );
  1085. //---------------------------------
  1086. virtual bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior
  1087. virtual bool ValidateNavGoal();
  1088. virtual bool IsCurTaskContinuousMove();
  1089. virtual bool IsValidMoveAwayDest( const Vector &vecDest ) { return true; }
  1090. //---------------------------------
  1091. //
  1092. // Notifications from navigator
  1093. //
  1094. virtual void OnMovementFailed() {};
  1095. virtual void OnMovementComplete() {};
  1096. //---------------------------------
  1097. virtual bool FindNearestValidGoalPos( const Vector &vTestPoint, Vector *pResult );
  1098. void RememberUnreachable( CBaseEntity* pEntity, float duration = -1 ); // Remember that entity is unreachable
  1099. virtual bool IsUnreachable( CBaseEntity* pEntity ); // Is entity is unreachable?
  1100. //---------------------------------
  1101. // Inherited from IAI_MotorMovementServices
  1102. virtual float CalcYawSpeed( void );
  1103. virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal,
  1104. float distClear,
  1105. AIMoveResult_t *pResult );
  1106. virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal,
  1107. float distClear,
  1108. AIMoveResult_t *pResult );
  1109. // Translations of the above into some useful game terms
  1110. virtual bool OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal,
  1111. CBaseDoor *pDoor,
  1112. float distClear,
  1113. AIMoveResult_t *pResult );
  1114. virtual bool OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
  1115. CBasePropDoor *pDoor,
  1116. float distClear,
  1117. AIMoveResult_t *pResult );
  1118. void OpenPropDoorBegin( CBasePropDoor *pDoor );
  1119. void OpenPropDoorNow( CBasePropDoor *pDoor );
  1120. //---------------------------------
  1121. void DelayMoveStart( float delay ) { m_flMoveWaitFinished = gpGlobals->curtime + delay; }
  1122. float m_flMoveWaitFinished;
  1123. //
  1124. // Stuff for opening doors.
  1125. //
  1126. void OnDoorFullyOpen(CBasePropDoor *pDoor);
  1127. void OnDoorBlocked(CBasePropDoor *pDoor);
  1128. CHandle<CBasePropDoor> m_hOpeningDoor; // The CBasePropDoor that we are in the midst of opening for navigation.
  1129. protected:
  1130. // BRJ 4/11
  1131. // Semi-obsolete-looking Lars code I moved out of the engine and into here
  1132. int FlyMove( const Vector& vecPosition, unsigned int mask );
  1133. int WalkMove( const Vector& vecPosition, unsigned int mask );
  1134. // Unreachable Entities
  1135. CUtlVector<UnreachableEnt_t> m_UnreachableEnts; // Array of unreachable entities
  1136. private:
  1137. CAI_Navigator * m_pNavigator;
  1138. CAI_LocalNavigator *m_pLocalNavigator;
  1139. CAI_Pathfinder * m_pPathfinder;
  1140. CAI_MoveProbe * m_pMoveProbe;
  1141. CAI_Motor * m_pMotor;
  1142. EHANDLE m_hGoalEnt; // path corner we are heading towards
  1143. float m_flTimeLastMovement;
  1144. CSimpleSimTimer m_CheckOnGroundTimer;
  1145. public:
  1146. //-----------------------------------------------------
  1147. //
  1148. // Eye position, view offset, head direction, eye direction
  1149. //
  1150. //-----------------------------------------------------
  1151. void SetDefaultEyeOffset ( void );
  1152. const Vector & GetDefaultEyeOffset( void ) { return m_vDefaultEyeOffset; }
  1153. virtual Vector GetNodeViewOffset() { return GetViewOffset(); }
  1154. virtual Vector EyeOffset( Activity nActivity );
  1155. virtual Vector EyePosition( void );
  1156. //---------------------------------
  1157. virtual Vector HeadDirection2D( void );
  1158. virtual Vector HeadDirection3D( void );
  1159. virtual Vector EyeDirection2D( void );
  1160. virtual Vector EyeDirection3D( void );
  1161. virtual CBaseEntity *EyeLookTarget( void ); // Overridden by subclass to force look at an entity
  1162. virtual void AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ) { };
  1163. virtual void AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ) { };
  1164. virtual void SetHeadDirection( const Vector &vTargetPos, float flInterval );
  1165. virtual void MaintainLookTargets( float flInterval );
  1166. virtual bool ValidEyeTarget(const Vector &lookTargetPos);
  1167. virtual Vector FacingPosition( void ) { return EyePosition(); }; // position that other npc's use when facing you
  1168. virtual void MaintainTurnActivity( void );
  1169. virtual bool FInAimCone( const Vector &vecSpot );
  1170. virtual void AimGun();
  1171. virtual void SetAim( const Vector &aimDir );
  1172. virtual void RelaxAim( void );
  1173. virtual CBaseEntity *GetAlternateMoveShootTarget() { return NULL; }
  1174. protected:
  1175. Vector m_vDefaultEyeOffset;
  1176. float m_flNextEyeLookTime; // Next time a pick a new place to look
  1177. float m_flEyeIntegRate; // How fast does eye move to target
  1178. private:
  1179. Vector m_vEyeLookTarget; // Where I want to be looking
  1180. Vector m_vCurEyeTarget; // Direction I'm looking at
  1181. EHANDLE m_hEyeLookTarget; // What I want to be looking at
  1182. float m_flHeadYaw; // Current head yaw
  1183. float m_flHeadPitch; // Current head pitch
  1184. protected:
  1185. float m_flOriginalYaw; // This is the direction facing when the level designer placed the NPC in the level.
  1186. float m_flFaceEnemyTolerance; // min. angle difference required when running TASK_FACE_ENEMY
  1187. public:
  1188. //-----------------------------------------------------
  1189. // Mapmaker Scripting
  1190. //
  1191. // Set when the NPC is being scripted by a mapmaker, and
  1192. // shouldn't be responding to external stimuli that would
  1193. // break him out of his "script". NOT a scripted sequence.
  1194. //-----------------------------------------------------
  1195. inline bool IsInAScript( void ) { return m_bInAScript; }
  1196. inline void SetInAScript( bool bScript ) { m_bInAScript = bScript; }
  1197. void InputStartScripting( inputdata_t &inputdata ) { m_bInAScript = true; }
  1198. void InputStopScripting( inputdata_t &inputdata ) { m_bInAScript = false; }
  1199. void InputGagEnable( inputdata_t &inputdata ) { AddSpawnFlags(SF_NPC_GAG); }
  1200. void InputGagDisable( inputdata_t &inputdata ) { RemoveSpawnFlags(SF_NPC_GAG); }
  1201. bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt);
  1202. virtual void InputOutsideTransition( inputdata_t &inputdata );
  1203. virtual void InputInsideTransition( inputdata_t &inputdata );
  1204. void CleanupScriptsOnTeleport( bool bEnrouteAsWell );
  1205. virtual void SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt );
  1206. private:
  1207. bool m_bInAScript;
  1208. public:
  1209. //-----------------------------------------------------
  1210. //
  1211. // Scripting
  1212. //
  1213. //-----------------------------------------------------
  1214. // Scripted sequence Info
  1215. enum SCRIPTSTATE
  1216. {
  1217. SCRIPT_PLAYING = 0, // Playing the action animation.
  1218. SCRIPT_WAIT, // Waiting on everyone in the script to be ready. Plays the pre idle animation if there is one.
  1219. SCRIPT_POST_IDLE, // Playing the post idle animation after playing the action animation.
  1220. SCRIPT_CLEANUP, // Cancelling the script / cleaning up.
  1221. SCRIPT_WALK_TO_MARK, // Walking to the scripted sequence position.
  1222. SCRIPT_RUN_TO_MARK, // Running to the scripted sequence position.
  1223. SCRIPT_CUSTOM_MOVE_TO_MARK, // Moving to the scripted sequence position while playing a custom movement animation.
  1224. };
  1225. bool ExitScriptedSequence();
  1226. bool CineCleanup();
  1227. virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity, bool bUseSlowHighAccuracyContacts = true );
  1228. // forces movement and sets a new schedule
  1229. virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
  1230. virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
  1231. static void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun);
  1232. static void ForceSelectedGoRandom(void);
  1233. bool AutoMovement( CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL );
  1234. bool AutoMovement( float flInterval, CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL );
  1235. bool TaskRanAutomovement( void ) { return m_ScheduleState.bTaskRanAutomovement; }
  1236. SCRIPTSTATE m_scriptState; // internal cinematic state
  1237. CHandle<CAI_ScriptedSequence> m_hCine;
  1238. Activity m_ScriptArrivalActivity;
  1239. string_t m_strScriptArrivalSequence;
  1240. //-----------------------------------------------------
  1241. //
  1242. // Scenes
  1243. //
  1244. //-----------------------------------------------------
  1245. void AddSceneLock( float flDuration = 0.2f ) { m_flSceneTime = MAX( gpGlobals->curtime + flDuration, m_flSceneTime ); };
  1246. void ClearSceneLock( float flDuration = 0.2f ) { m_flSceneTime = gpGlobals->curtime + flDuration; };
  1247. bool IsInLockedScene( void ) { return m_flSceneTime > gpGlobals->curtime; };
  1248. float m_flSceneTime;
  1249. string_t m_iszSceneCustomMoveSeq;
  1250. public:
  1251. //-----------------------------------------------------
  1252. //
  1253. // Memory
  1254. //
  1255. //-----------------------------------------------------
  1256. inline void Remember( int iMemory ) { m_afMemory |= iMemory; }
  1257. inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; }
  1258. inline bool HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; }
  1259. inline bool HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; }
  1260. virtual CAI_Enemies *GetEnemies( void );
  1261. virtual void RemoveMemory( void );
  1262. virtual void ChangeFaction( int nNewFaction );
  1263. virtual bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL );
  1264. virtual float GetReactionDelay( CBaseEntity *pEnemy );
  1265. void SetLastAttackTime( float time) { m_flLastAttackTime = time; }
  1266. float GetLastAttackTime() const { return m_flLastAttackTime; }
  1267. float GetLastDamageTime() const { return m_flLastDamageTime; }
  1268. float GetLastPlayerDamageTime() const { return m_flLastPlayerDamageTime; }
  1269. float GetLastEnemyTime() const { return m_flLastEnemyTime; }
  1270. // Set up the shot regulator based on the equipped weapon
  1271. virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
  1272. // Weapon holstering
  1273. virtual bool CanHolsterWeapon( void );
  1274. virtual int HolsterWeapon( void );
  1275. virtual int UnholsterWeapon( void );
  1276. void InputHolsterWeapon( inputdata_t &inputdata );
  1277. void InputHolsterAndDestroyWeapon( inputdata_t &inputdata );
  1278. void InputUnholsterWeapon( inputdata_t &inputdata );
  1279. bool IsWeaponHolstered( void );
  1280. bool IsWeaponStateChanging( void );
  1281. void SetDesiredWeaponState( DesiredWeaponState_t iState ) { m_iDesiredWeaponState = iState; }
  1282. // NOTE: The Shot Regulator is used to manage the RangeAttack1 weapon.
  1283. inline CAI_ShotRegulator* GetShotRegulator() { return &m_ShotRegulator; }
  1284. virtual void OnRangeAttack1();
  1285. protected:
  1286. // Shot regulator code
  1287. virtual void OnUpdateShotRegulator( );
  1288. protected:
  1289. CAI_Enemies * m_pEnemies; // Holds information about enemies / danger positions / shared between sqaud members
  1290. int m_afMemory;
  1291. EHANDLE m_hEnemyOccluder; // The entity my enemy is hiding behind.
  1292. float m_flSumDamage; // How much consecutive damage I've received
  1293. float m_flLastDamageTime; // Last time I received damage
  1294. float m_flLastPlayerDamageTime; // Last time I received damage from the player
  1295. float m_flLastSawPlayerTime; // Last time I saw the player
  1296. float m_flLastAttackTime; // Last time that I attacked my current enemy
  1297. float m_flLastEnemyTime;
  1298. float m_flNextWeaponSearchTime; // next time to search for a better weapon
  1299. string_t m_iszPendingWeapon; // THe NPC should create and equip this weapon.
  1300. bool m_bIgnoreUnseenEnemies;
  1301. private:
  1302. CAI_ShotRegulator m_ShotRegulator; // When should I shoot next?
  1303. DesiredWeaponState_t m_iDesiredWeaponState;
  1304. public:
  1305. //-----------------------------------------------------
  1306. //
  1307. // Squads & tactics
  1308. //
  1309. //-----------------------------------------------------
  1310. virtual bool InitSquad( void );
  1311. virtual const char* SquadSlotName(int slotID) { return gm_SquadSlotNamespace.IdToSymbol(slotID); }
  1312. bool OccupyStrategySlot( int squadSlotID );
  1313. bool OccupyStrategySlotRange( int slotIDStart, int slotIDEnd );
  1314. bool HasStrategySlot( int squadSlotID );
  1315. bool HasStrategySlotRange( int slotIDStart, int slotIDEnd );
  1316. int GetMyStrategySlot() { return m_iMySquadSlot; }
  1317. void VacateStrategySlot( void );
  1318. bool IsStrategySlotRangeOccupied( int slotIDStart, int slotIDEnd ); // Returns true if all in the range are occupied
  1319. CAI_Squad * GetSquad() { return m_pSquad; }
  1320. virtual void SetSquad( CAI_Squad *pSquad );
  1321. void AddToSquad( string_t name );
  1322. void RemoveFromSquad();
  1323. void CheckSquad();
  1324. void SetSquadName( string_t name ) { m_SquadName = name; }
  1325. bool IsInSquad() const { return m_pSquad != NULL; }
  1326. virtual bool IsSilentSquadMember() const { return false; }
  1327. int NumWeaponsInSquad( const char *pszWeaponClassname );
  1328. string_t GetHintGroup( void ) { return m_strHintGroup; }
  1329. void ClearHintGroup( void ) { SetHintGroup( NULL_STRING ); }
  1330. void SetHintGroup( string_t name, bool bHintGroupNavLimiting = false );
  1331. bool IsLimitingHintGroups( void ) { return m_bHintGroupNavLimiting; }
  1332. //---------------------------------
  1333. CAI_TacticalServices *GetTacticalServices() { return m_pTacticalServices; }
  1334. const CAI_TacticalServices *GetTacticalServices() const { return m_pTacticalServices; }
  1335. //---------------------------------
  1336. // Cover
  1337. virtual bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult );
  1338. virtual bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult );
  1339. virtual bool FindCoverPos( CSound *pSound, Vector *pResult );
  1340. virtual bool IsValidCover ( const Vector &vecCoverLocation, CAI_Hint const *pHint );
  1341. virtual bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint );
  1342. virtual bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ) { return WeaponLOSCondition( vecShootPos, targetPos, false ); }
  1343. virtual bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
  1344. virtual float CoverRadius( void ) { return 1024; } // Default cover radius
  1345. virtual float GetMaxTacticalLateralMovement( void ) { return MAXTACLAT_IGNORE; }
  1346. bool FindCoverFromEnemy( bool bNodesOnly = false, float flMinDistance = 0, float flMaxDistance = FLT_MAX );
  1347. protected:
  1348. virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {}
  1349. CAI_Squad * m_pSquad; // The squad that I'm on
  1350. string_t m_SquadName;
  1351. int m_iMySquadSlot; // this is the behaviour slot that the npc currently holds in the squad.
  1352. private:
  1353. string_t m_strHintGroup;
  1354. bool m_bHintGroupNavLimiting;
  1355. CAI_TacticalServices *m_pTacticalServices;
  1356. public:
  1357. //-----------------------------------------------------
  1358. //
  1359. // Base schedule & task support; Miscellaneous
  1360. //
  1361. //-----------------------------------------------------
  1362. void InitRelationshipTable( void );
  1363. void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator );
  1364. virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
  1365. virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority );
  1366. void NPCUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
  1367. CBaseGrenade* IncomingGrenade(void);
  1368. virtual bool ShouldFadeOnDeath( void );
  1369. void NPCInitDead( void ); // Call after animation/pose is set up
  1370. void CorpseFallThink( void );
  1371. float ThrowLimit( const Vector &vecStart, const Vector &vecEnd, float fGravity, float fArcSize, const Vector &mins, const Vector &maxs, CBaseEntity *pTarget, Vector *jumpVel, CBaseEntity **pBlocker);
  1372. // these functions will survey conditions and set appropriate conditions bits for attack types.
  1373. virtual int RangeAttack1Conditions( float flDot, float flDist );
  1374. virtual int RangeAttack2Conditions( float flDot, float flDist );
  1375. virtual int MeleeAttack1Conditions( float flDot, float flDist );
  1376. virtual int MeleeAttack2Conditions( float flDot, float flDist );
  1377. virtual float InnateRange1MinRange( void ) { return 0.0f; }
  1378. virtual float InnateRange1MaxRange( void ) { return FLT_MAX; }
  1379. virtual bool OnBeginMoveAndShoot( void ) { return true; }
  1380. virtual void OnEndMoveAndShoot( void ) {}
  1381. virtual bool UseAttackSquadSlots() { return false; }
  1382. //---------------------------------
  1383. virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
  1384. //---------------------------------
  1385. // States
  1386. //---------------------------------
  1387. virtual void ClearAttackConditions( void );
  1388. void GatherAttackConditions( CBaseEntity *pTarget, float flDist );
  1389. virtual bool ShouldLookForBetterWeapon();
  1390. bool Weapon_IsBetterAvailable ( void ) ;
  1391. virtual Vector Weapon_ShootPosition( void );
  1392. virtual void GiveWeapon( string_t iszWeaponName );
  1393. virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) { }
  1394. bool IsMovingToPickupWeapon();
  1395. virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
  1396. virtual bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions) { return WeaponLOSCondition( GetAbsOrigin(), targetPos, bSetConditions ); }
  1397. virtual bool IsWaitingToRappel( void ) { return false; }
  1398. virtual void BeginRappel() {}
  1399. // override to change the chase location of an enemy
  1400. // This is where your origin should go when you are chasing pEnemy when his origin is at chasePosition
  1401. // by default, leave this alone to make your origin coincide with his.
  1402. virtual void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition);
  1403. virtual float GetDefaultNavGoalTolerance() { return (GetHullWidth() * 2.0); }
  1404. virtual bool FCanCheckAttacks ( void );
  1405. virtual void CheckAmmo( void ) {}
  1406. virtual bool FValidateHintType( CAI_Hint *pHint );
  1407. virtual Activity GetHintActivity( short sHintType, Activity HintsActivity );
  1408. virtual float GetHintDelay( short sHintType );
  1409. virtual Activity GetCoverActivity( CAI_Hint* pHint );
  1410. virtual Activity GetReloadActivity( CAI_Hint* pHint );
  1411. virtual void SetTurnActivity( void );
  1412. bool UpdateTurnGesture( void );
  1413. // Returns the time when the door will be open
  1414. float OpenDoorAndWait( CBaseEntity *pDoor );
  1415. bool BBoxFlat( void );
  1416. //---------------------------------
  1417. virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
  1418. virtual bool PassesDamageFilter( const CTakeDamageInfo &info );
  1419. //---------------------------------
  1420. void MakeDamageBloodDecal( int cCount, float flNoise, trace_t *ptr, Vector vecDir );
  1421. virtual float GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info );
  1422. void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
  1423. void DecalTrace( trace_t *pTrace, char const *decalName );
  1424. void ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName );
  1425. virtual bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers = true );
  1426. CBaseEntity * PlayerInRange( const Vector &vecLocation, float flDist );
  1427. bool PointInSpread( CBaseCombatCharacter *pCheckEntity, const Vector &sourcePos, const Vector &targetPos, const Vector &testPoint, float flSpread, float maxDistOffCenter );
  1428. bool IsSquadmateInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter );
  1429. //---------------------------------
  1430. // combat functions
  1431. //---------------------------------
  1432. virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions );
  1433. virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
  1434. virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class
  1435. virtual bool Event_Gibbed( const CTakeDamageInfo &info );
  1436. virtual void Event_Killed( const CTakeDamageInfo &info );
  1437. virtual Vector GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy = true );
  1438. virtual Vector GetActualShootPosition( const Vector &shootOrigin );
  1439. virtual Vector GetActualShootTrajectory( const Vector &shootOrigin );
  1440. virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL );
  1441. virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget );
  1442. virtual void CollectShotStats( const Vector &vecShootOrigin, const Vector &vecShootDir );
  1443. virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
  1444. virtual Vector GetAutoAimCenter() { return BodyTarget(vec3_origin, false); }
  1445. virtual void FireBullets( const FireBulletsInfo_t &info );
  1446. // OLD VERSION! Use the struct version
  1447. void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting,
  1448. const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4,
  1449. int firingEntID = -1, int attachmentID = -1, float flDamage = 0,
  1450. CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false );
  1451. virtual bool ShouldMoveAndShoot( void );
  1452. //---------------------------------
  1453. // Damage
  1454. //---------------------------------
  1455. virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
  1456. virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info );
  1457. virtual int OnTakeDamage_Dead( const CTakeDamageInfo &info );
  1458. virtual void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity );
  1459. virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
  1460. virtual bool IsLightDamage( const CTakeDamageInfo &info );
  1461. virtual bool IsHeavyDamage( const CTakeDamageInfo &info );
  1462. void DoRadiusDamage( const CTakeDamageInfo &info, int iClassIgnore, CBaseEntity *pEntityIgnore );
  1463. void DoRadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, int iClassIgnore, CBaseEntity *pEntityIgnore );
  1464. //---------------------------------
  1465. virtual void PickupWeapon( CBaseCombatWeapon *pWeapon );
  1466. virtual void PickupItem( CBaseEntity *pItem ) { };
  1467. CBaseEntity* DropItem( char *pszItemName, Vector vecPos, QAngle vecAng );// drop an item.
  1468. //---------------------------------
  1469. // Inputs
  1470. //---------------------------------
  1471. void InputSetRelationship( inputdata_t &inputdata );
  1472. void InputSetEnemyFilter( inputdata_t &inputdata );
  1473. void InputSetHealth( inputdata_t &inputdata );
  1474. void InputBeginRappel( inputdata_t &inputdata );
  1475. void InputSetSquad( inputdata_t &inputdata );
  1476. void InputWake( inputdata_t &inputdata );
  1477. void InputForgetEntity( inputdata_t &inputdata );
  1478. void InputIgnoreDangerSounds( inputdata_t &inputdata );
  1479. void InputUpdateEnemyMemory( inputdata_t &inputdata );
  1480. void InputCreateAddon( inputdata_t &inputdata );
  1481. //---------------------------------
  1482. virtual void NotifyDeadFriend( CBaseEntity *pFriend ) { return; }
  1483. //---------------------------------
  1484. // Utility methods
  1485. static Vector CalcThrowVelocity(const Vector &startPos, const Vector &endPos, float fGravity, float fArcSize);
  1486. //---------------------------------
  1487. float SetWait( float minWait, float maxWait = 0.0 );
  1488. void ClearWait();
  1489. float GetWaitFinishTime() { return m_flWaitFinished; }
  1490. bool IsWaitFinished();
  1491. bool IsWaitSet();
  1492. CBaseEntity* GetGoalEnt() { return m_hGoalEnt; }
  1493. void SetGoalEnt( CBaseEntity *pGoalEnt ) { m_hGoalEnt.Set( pGoalEnt ); }
  1494. CAI_Hint *GetHintNode() { return m_pHintNode; }
  1495. const CAI_Hint *GetHintNode() const { return m_pHintNode; }
  1496. void SetHintNode( CAI_Hint *pHintNode );
  1497. void ClearHintNode( float reuseDelay = 0.0 );
  1498. float m_flWaitFinished; // if we're told to wait, this is the time that the wait will be over.
  1499. float m_flNextFlinchTime; // Time at which we'll flinch fully again (as opposed to just doing gesture flinches)
  1500. float m_flNextDodgeTime; // Time at which I can dodge again. Used so that the behavior doesn't happen over and over.
  1501. CAI_MoveAndShootOverlay m_MoveAndShootOverlay;
  1502. Vector m_vecLastPosition; // npc sometimes wants to return to where it started after an operation.
  1503. Vector m_vSavePosition; // position stored by code that called this schedules
  1504. Vector m_vInterruptSavePosition; // position stored by a task that was interrupted
  1505. private:
  1506. CHandle<CAI_Hint> m_pHintNode; // this is the hint that the npc is moving towards or performing active idle on.
  1507. public:
  1508. int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences)
  1509. float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in GatherEnemyConditions
  1510. string_t m_spawnEquipment;
  1511. bool m_fNoDamageDecal;
  1512. EHANDLE m_hStoredPathTarget; // For TASK_SET_GOAL
  1513. Vector m_vecStoredPathGoal; //
  1514. GoalType_t m_nStoredPathType; //
  1515. int m_fStoredPathFlags; //
  1516. CHandle<CBaseFilter> m_hEnemyFilter;
  1517. string_t m_iszEnemyFilterName;
  1518. bool m_bDidDeathCleanup;
  1519. IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_lifeState );
  1520. //---------------------------------
  1521. // Outputs
  1522. //---------------------------------
  1523. COutputEvent m_OnDamaged;
  1524. COutputEvent m_OnDeath;
  1525. COutputEvent m_OnHalfHealth;
  1526. COutputEHANDLE m_OnFoundEnemy;
  1527. COutputEvent m_OnLostEnemyLOS;
  1528. COutputEvent m_OnLostEnemy;
  1529. COutputEHANDLE m_OnFoundPlayer;
  1530. COutputEvent m_OnLostPlayerLOS;
  1531. COutputEvent m_OnLostPlayer;
  1532. COutputEvent m_OnHearWorld;
  1533. COutputEvent m_OnHearPlayer;
  1534. COutputEvent m_OnHearCombat;
  1535. COutputEvent m_OnDamagedByPlayer;
  1536. COutputEvent m_OnDamagedByPlayerSquad;
  1537. COutputEvent m_OnDenyCommanderUse;
  1538. COutputEvent m_OnRappelTouchdown;
  1539. COutputEvent m_OnSleep;
  1540. COutputEvent m_OnWake;
  1541. COutputEvent m_OnForcedInteractionStarted;
  1542. COutputEvent m_OnForcedInteractionAborted;
  1543. COutputEvent m_OnForcedInteractionFinished;
  1544. public:
  1545. // use this to shrink the bbox temporarily
  1546. void SetHullSizeNormal( bool force = false );
  1547. bool SetHullSizeSmall( bool force = false );
  1548. bool IsUsingSmallHull() const { return m_fIsUsingSmallHull; }
  1549. const Vector & GetHullMins() const { return NAI_Hull::Mins(GetHullType()); }
  1550. const Vector & GetHullMaxs() const { return NAI_Hull::Maxs(GetHullType()); }
  1551. float GetHullWidth() const { return NAI_Hull::Width(GetHullType()); }
  1552. float GetHullHeight() const { return NAI_Hull::Height(GetHullType()); }
  1553. unsigned int GetHullTraceMask() const { return NAI_Hull::TraceMask(GetHullType()); }
  1554. void SetupVPhysicsHull();
  1555. virtual void StartTouch( CBaseEntity *pOther );
  1556. void CheckPhysicsContacts();
  1557. virtual bool ShouldCheckPhysicsContacts( void ) { return ( GetMoveType() == MOVETYPE_STEP && VPhysicsGetObject() ); }
  1558. private:
  1559. void TryRestoreHull( void );
  1560. bool m_fIsUsingSmallHull;
  1561. protected:
  1562. bool m_bCheckContacts;
  1563. private:
  1564. // Task implementation helpers
  1565. void StartTurn( float flDeltaYaw );
  1566. bool FindCoverFromBestSound( Vector *pCoverPos );
  1567. void StartScriptMoveToTargetTask( int task );
  1568. void RunAttackTask( int task );
  1569. protected:
  1570. virtual float CalcReasonableFacing( bool bIgnoreOriginalFacing = false );
  1571. virtual bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ) { return true; }
  1572. virtual float GetReasonableFacingDist( void );
  1573. virtual void RunDieTask();
  1574. public:
  1575. inline int UsableNPCObjectCaps( int baseCaps )
  1576. {
  1577. if ( IsAlive() )
  1578. baseCaps |= FCAP_IMPULSE_USE;
  1579. return baseCaps;
  1580. }
  1581. virtual int ObjectCaps() { return (BaseClass::ObjectCaps() | FCAP_NOTIFY_ON_TRANSITION); }
  1582. //-----------------------------------------------------
  1583. //
  1584. // Core mapped data structures
  1585. //
  1586. // String Registries for default AI Shared by all CBaseNPCs
  1587. // These are used only during initialization and in debug
  1588. //-----------------------------------------------------
  1589. static void InitSchedulingTables();
  1590. static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return &gm_SchedulingSymbols; }
  1591. static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; }
  1592. virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; }
  1593. static int GetScheduleID (const char* schedName);
  1594. static int GetActivityID (const char* actName);
  1595. static int GetConditionID (const char* condName);
  1596. static int GetTaskID (const char* taskName);
  1597. static int GetSquadSlotID (const char* slotName);
  1598. virtual const char* GetSquadSlotDebugName( int iSquadSlot );
  1599. static const char* GetActivityName (int actID);
  1600. static void AddActivityToSR(const char *actName, int conID);
  1601. static void AddEventToSR(const char *eventName, int conID);
  1602. static const char* GetEventName (int actID);
  1603. static int GetEventID (const char* actName);
  1604. public:
  1605. //-----------------------------------------------------
  1606. // Crouch handling
  1607. //-----------------------------------------------------
  1608. bool CrouchIsDesired( void ) const;
  1609. virtual bool IsCrouching( void );
  1610. inline void ForceCrouch( void );
  1611. inline void ClearForceCrouch( void );
  1612. protected:
  1613. virtual bool Crouch( void );
  1614. virtual bool Stand( void );
  1615. virtual void DesireCrouch( void );
  1616. inline void DesireStand( void );
  1617. bool CouldShootIfCrouching( CBaseEntity *pTarget );
  1618. virtual bool IsCrouchedActivity( Activity activity );
  1619. protected:
  1620. // Override these in your derived NPC class
  1621. virtual Vector GetCrouchEyeOffset( void ) { return Vector(0,0,40); }
  1622. virtual Vector GetCrouchGunOffset( void ) { return Vector(0,0,36); }
  1623. private:
  1624. bool m_bCrouchDesired;
  1625. bool m_bForceCrouch;
  1626. bool m_bIsCrouching;
  1627. //-----------------------------------------------------
  1628. //-----------------------------------------------------
  1629. // ai_post_frame_navigation
  1630. //-----------------------------------------------------
  1631. private:
  1632. bool m_bDeferredNavigation; // This NPCs has a navigation query that's being deferred until later in the frame
  1633. public:
  1634. void SetNavigationDeferred( bool bState ) { m_bDeferredNavigation = bState; }
  1635. bool IsNavigationDeferred( void ) { return m_bDeferredNavigation; }
  1636. //-----------------------------------------------------
  1637. protected:
  1638. static CAI_GlobalNamespace gm_SquadSlotNamespace;
  1639. static CAI_LocalIdSpace gm_SquadSlotIdSpace;
  1640. private:
  1641. // Checks to see that the nav hull is valid for the NPC
  1642. bool IsNavHullValid() const;
  1643. friend class CAI_SystemHook;
  1644. friend class CAI_SchedulesManager;
  1645. static bool LoadDefaultSchedules(void);
  1646. static void InitDefaultScheduleSR(void);
  1647. static void InitDefaultTaskSR(void);
  1648. static void InitDefaultConditionSR(void);
  1649. static void InitDefaultActivitySR(void);
  1650. static void InitDefaultSquadSlotSR(void);
  1651. static CStringRegistry* m_pActivitySR;
  1652. static int m_iNumActivities;
  1653. static CStringRegistry* m_pEventSR;
  1654. static int m_iNumEvents;
  1655. static CAI_GlobalScheduleNamespace gm_SchedulingSymbols;
  1656. static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace;
  1657. public:
  1658. //----------------------------------------------------
  1659. // Debugging tools
  1660. //
  1661. // -----------------------------
  1662. // Debuging Fields and Methods
  1663. // -----------------------------
  1664. const char* m_failText; // Text of why it failed
  1665. const char* m_interruptText; // Text of why schedule interrupted
  1666. CAI_Schedule* m_failedSchedule; // The schedule that failed last
  1667. CAI_Schedule* m_interuptSchedule; // The schedule that was interrupted last
  1668. int m_nDebugCurIndex; // Index used for stepping through AI
  1669. virtual void ReportAIState( void );
  1670. virtual void ReportOverThinkLimit( float time );
  1671. void DumpTaskTimings();
  1672. void DrawDebugGeometryOverlays(void);
  1673. virtual int DrawDebugTextOverlays(void);
  1674. void ToggleFreeze(void);
  1675. virtual void Freeze( float flFreezeAmount = -1.0f, CBaseEntity *pFreezer = NULL, Ray_t *pFreezeRay = NULL );
  1676. virtual bool ShouldBecomeStatue();
  1677. virtual bool IsMovementFrozen( void ) { return m_flMovementFrozen > m_flFrozenMoveBlock; }
  1678. virtual bool IsAttackFrozen( void ) { return m_flAttackFrozen > 0.0f; }
  1679. virtual void Unfreeze();
  1680. static void ClearAllSchedules(void);
  1681. static int m_nDebugBits;
  1682. static CAI_BaseNPC* m_pDebugNPC;
  1683. static int m_nDebugPauseIndex; // Current step
  1684. static inline void SetDebugNPC( CAI_BaseNPC *pNPC ) { m_pDebugNPC = pNPC; }
  1685. static inline bool IsDebugNPC( CAI_BaseNPC *pNPC ) { return( pNPC == m_pDebugNPC ); }
  1686. float m_LastShootAccuracy;
  1687. int m_TotalShots;
  1688. int m_TotalHits;
  1689. #ifdef _DEBUG
  1690. bool m_bSelected;
  1691. #endif
  1692. float m_flSoundWaitTime; // Time when I'm allowed to make another sound
  1693. int m_nSoundPriority;
  1694. float m_flIgnoreDangerSoundsUntil;
  1695. #ifdef AI_MONITOR_FOR_OSCILLATION
  1696. CUtlVector<AIScheduleChoice_t> m_ScheduleHistory;
  1697. #endif//AI_MONITOR_FOR_OSCILLATION
  1698. private:
  1699. // Break into pieces!
  1700. void Break( CBaseEntity *pBreaker );
  1701. void InputBreak( inputdata_t &inputdata );
  1702. friend void CC_NPC_Go();
  1703. friend void CC_NPC_GoRandom();
  1704. friend void CC_NPC_Freeze( const CCommand &args );
  1705. public:
  1706. CNetworkVar( bool, m_bPerformAvoidance );
  1707. CNetworkVar( bool, m_bIsMoving );
  1708. CNetworkVar( bool, m_bFadeCorpse );
  1709. CNetworkVar( bool, m_bImportanRagdoll );
  1710. CNetworkVar( bool, m_bSpeedModActive );
  1711. CNetworkVar( int, m_iSpeedModRadius );
  1712. CNetworkVar( int, m_iSpeedModSpeed );
  1713. CNetworkVar( float, m_flTimePingEffect ); // Display the pinged effect until this time
  1714. float m_flFrozenMoveBlock; // entity can't move after it's frozen past this amount
  1715. void InputActivateSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = true; }
  1716. void InputDisableSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = false; }
  1717. void InputSetSpeedModifierRadius( inputdata_t &inputdata );
  1718. void InputSetSpeedModifierSpeed( inputdata_t &inputdata );
  1719. virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity );
  1720. bool m_bPlayerAvoidState;
  1721. void GetPlayerAvoidBounds( Vector *pMins, Vector *pMaxs );
  1722. void StartPingEffect( void ) { m_flTimePingEffect = gpGlobals->curtime + 2.0f; DispatchUpdateTransmitState(); }
  1723. protected:
  1724. unsigned int m_nAITraceMask;
  1725. public:
  1726. inline unsigned int GetAITraceMask( void ) const { return m_nAITraceMask; }
  1727. inline unsigned int GetAITraceMask_BrushOnly( void ) const { return (m_nAITraceMask & ~CONTENTS_MONSTER); }
  1728. virtual bool OnlySeeAliveEntities( void ) { return true; }
  1729. };
  1730. //-------------------------------------
  1731. inline bool CAI_BaseNPC::IsRunningBehavior() const
  1732. {
  1733. return ( m_pPrimaryBehavior != NULL );
  1734. }
  1735. //-------------------------------------
  1736. inline CAI_BehaviorBase *CAI_BaseNPC::GetPrimaryBehavior()
  1737. {
  1738. return m_pPrimaryBehavior;
  1739. }
  1740. //-----------------------------------------------------------------------------
  1741. // Purpose: Returns whether our ideal activity has started. If not, we are in
  1742. // a transition sequence.
  1743. //-----------------------------------------------------------------------------
  1744. inline bool CAI_BaseNPC::IsActivityStarted(void)
  1745. {
  1746. return (GetSequence() == m_nIdealSequence);
  1747. }
  1748. //-----------------------------------------------------------------------------
  1749. // Bullet firing (legacy)...
  1750. //-----------------------------------------------------------------------------
  1751. inline void CAI_BaseNPC::FireBullets( int cShots, const Vector &vecSrc,
  1752. const Vector &vecDirShooting, const Vector &vecSpread, float flDistance,
  1753. int iAmmoType, int iTracerFreq, int firingEntID, int attachmentID,
  1754. float flDamage, CBaseEntity *pAttacker, bool bFirstShotAccurate )
  1755. {
  1756. FireBulletsInfo_t info;
  1757. info.m_iShots = cShots;
  1758. info.m_vecSrc = vecSrc;
  1759. info.m_vecDirShooting = vecDirShooting;
  1760. info.m_vecSpread = vecSpread;
  1761. info.m_flDistance = flDistance;
  1762. info.m_iAmmoType = iAmmoType;
  1763. info.m_iTracerFreq = iTracerFreq;
  1764. info.m_flDamage = flDamage;
  1765. info.m_pAttacker = pAttacker;
  1766. info.m_nFlags = bFirstShotAccurate ? FIRE_BULLETS_FIRST_SHOT_ACCURATE : 0;
  1767. FireBullets( info );
  1768. }
  1769. //-----------------------------------------------------------------------------
  1770. // Purpose: Sets the ideal state of this NPC.
  1771. //-----------------------------------------------------------------------------
  1772. inline void CAI_BaseNPC::SetIdealState( NPC_STATE eIdealState )
  1773. {
  1774. if (eIdealState != m_IdealNPCState)
  1775. {
  1776. /*switch (eIdealState)
  1777. {
  1778. case NPC_STATE_NONE:
  1779. Msg("%s.SetIdealState: NPC_STATE_NONE\n", GetDebugName());
  1780. break;
  1781. case NPC_STATE_IDLE:
  1782. Msg("%s.SetIdealState: NPC_STATE_IDLE\n", GetDebugName());
  1783. break;
  1784. case NPC_STATE_ALERT:
  1785. Msg("%s.SetIdealState: NPC_STATE_ALERT\n", GetDebugName());
  1786. break;
  1787. case NPC_STATE_COMBAT:
  1788. Msg("%s.SetIdealState: NPC_STATE_COMBAT\n", GetDebugName());
  1789. break;
  1790. case NPC_STATE_SCRIPT:
  1791. Msg("%s.SetIdealState: NPC_STATE_SCRIPT\n", GetDebugName());
  1792. break;
  1793. case NPC_STATE_PLAYDEAD:
  1794. Msg("%s.SetIdealState: NPC_STATE_PLAYDEAD\n", GetDebugName());
  1795. break;
  1796. case NPC_STATE_PRONE:
  1797. Msg("%s.SetIdealState: NPC_STATE_PRONE\n", GetDebugName());
  1798. break;
  1799. case NPC_STATE_DEAD:
  1800. Msg("%s.SetIdealState: NPC_STATE_DEAD\n", GetDebugName());
  1801. break;
  1802. default:
  1803. Msg("%s.SetIdealState: <Unknown>\n", GetDebugName());
  1804. break;
  1805. }*/
  1806. m_IdealNPCState = eIdealState;
  1807. }
  1808. }
  1809. //-----------------------------------------------------------------------------
  1810. // Purpose: Returns the current ideal state the NPC will try to achieve.
  1811. //-----------------------------------------------------------------------------
  1812. inline NPC_STATE CAI_BaseNPC::GetIdealState()
  1813. {
  1814. return m_IdealNPCState;
  1815. }
  1816. //-----------------------------------------------------------------------------
  1817. //-----------------------------------------------------------------------------
  1818. inline int CAI_BaseNPC::IncScheduleCurTaskIndex()
  1819. {
  1820. m_ScheduleState.iTaskInterrupt = 0;
  1821. m_ScheduleState.bTaskRanAutomovement = false;
  1822. m_ScheduleState.bTaskUpdatedYaw = false;
  1823. return ++m_ScheduleState.iCurTask;
  1824. }
  1825. //-----------------------------------------------------------------------------
  1826. //-----------------------------------------------------------------------------
  1827. inline void CAI_BaseNPC::ResetScheduleCurTaskIndex()
  1828. {
  1829. m_ScheduleState.iCurTask = 0;
  1830. m_ScheduleState.iTaskInterrupt = 0;
  1831. m_ScheduleState.bTaskRanAutomovement = false;
  1832. m_ScheduleState.bTaskUpdatedYaw = false;
  1833. }
  1834. //-----------------------------------------------------------------------------
  1835. //-----------------------------------------------------------------------------
  1836. inline bool CAI_BaseNPC::CrouchIsDesired( void ) const
  1837. {
  1838. return ( (CapabilitiesGet() & bits_CAP_DUCK) && (m_bCrouchDesired | m_bForceCrouch) );
  1839. }
  1840. //-----------------------------------------------------------------------------
  1841. // Purpose:
  1842. //-----------------------------------------------------------------------------
  1843. inline void CAI_BaseNPC::DesireStand( void )
  1844. {
  1845. m_bCrouchDesired = false;
  1846. }
  1847. //-----------------------------------------------------------------------------
  1848. // Purpose:
  1849. //-----------------------------------------------------------------------------
  1850. inline void CAI_BaseNPC::ForceCrouch( void )
  1851. {
  1852. m_bForceCrouch = true;
  1853. Crouch();
  1854. }
  1855. //-----------------------------------------------------------------------------
  1856. // Purpose:
  1857. //-----------------------------------------------------------------------------
  1858. inline void CAI_BaseNPC::ClearForceCrouch( void )
  1859. {
  1860. m_bForceCrouch = false;
  1861. if ( IsCrouching() )
  1862. {
  1863. Stand();
  1864. }
  1865. }
  1866. inline bool CAI_BaseNPC::HaveSequenceForActivity( Activity activity )
  1867. {
  1868. #if STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW
  1869. return ( (GetModelPtr()) ? (SelectWeightedSequence( activity ) != ACTIVITY_NOT_AVAILABLE) : false );
  1870. #else
  1871. return ( (GetModelPtr()) ? GetModelPtr()->HaveSequenceForActivity(activity) : false );
  1872. #endif
  1873. }
  1874. typedef CHandle<CAI_BaseNPC> AIHANDLE;
  1875. // ============================================================================
  1876. // Macros for introducing new schedules in sub-classes
  1877. //
  1878. // Strings registries and schedules use unique ID's for each item, but
  1879. // sub-class enumerations are non-unique, so we translate between the
  1880. // enumerations and unique ID's
  1881. // ============================================================================
  1882. #define AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( derivedClass ) \
  1883. IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass ) \
  1884. void derivedClass::InitCustomSchedules( void ) \
  1885. { \
  1886. typedef derivedClass CNpc; \
  1887. const char *pszClassName = #derivedClass; \
  1888. \
  1889. CUtlVector<char *> schedulesToLoad; \
  1890. CUtlVector<AIScheduleLoadFunc_t> reqiredOthers; \
  1891. CAI_NamespaceInfos scheduleIds; \
  1892. CAI_NamespaceInfos taskIds; \
  1893. CAI_NamespaceInfos conditionIds;
  1894. //-----------------
  1895. #define AI_BEGIN_CUSTOM_NPC( className, derivedClass ) \
  1896. IMPLEMENT_CUSTOM_AI(className, derivedClass ) \
  1897. void derivedClass::InitCustomSchedules( void ) \
  1898. { \
  1899. typedef derivedClass CNpc; \
  1900. const char *pszClassName = #derivedClass; \
  1901. \
  1902. CUtlVector<char *> schedulesToLoad; \
  1903. CUtlVector<AIScheduleLoadFunc_t> reqiredOthers; \
  1904. CAI_NamespaceInfos scheduleIds; \
  1905. CAI_NamespaceInfos taskIds; \
  1906. CAI_NamespaceInfos conditionIds; \
  1907. CAI_NamespaceInfos squadSlotIds;
  1908. //-----------------
  1909. #define EXTERN_SCHEDULE( id ) \
  1910. scheduleIds.PushBack( #id, id ); \
  1911. extern const char * g_psz##id; \
  1912. schedulesToLoad.AddToTail( (char *)g_psz##id );
  1913. //-----------------
  1914. #define DEFINE_SCHEDULE( id, text ) \
  1915. scheduleIds.PushBack( #id, id ); \
  1916. char * g_psz##id = \
  1917. "\n Schedule" \
  1918. "\n " #id \
  1919. text \
  1920. "\n"; \
  1921. schedulesToLoad.AddToTail( (char *)g_psz##id );
  1922. //-----------------
  1923. #define DECLARE_CONDITION( id ) \
  1924. conditionIds.PushBack( #id, id );
  1925. //-----------------
  1926. #define DECLARE_TASK( id ) \
  1927. taskIds.PushBack( #id, id );
  1928. //-----------------
  1929. #define DECLARE_ACTIVITY( id ) \
  1930. ADD_CUSTOM_ACTIVITY( CNpc, id );
  1931. //-----------------
  1932. #define DECLARE_SQUADSLOT( id ) \
  1933. squadSlotIds.PushBack( #id, id );
  1934. //-----------------
  1935. #define DECLARE_INTERACTION( interaction ) \
  1936. ADD_CUSTOM_INTERACTION( interaction );
  1937. //-----------------
  1938. #define DECLARE_ANIMEVENT( id ) \
  1939. ADD_CUSTOM_ANIMEVENT( CNpc, id );
  1940. //-----------------
  1941. #define DECLARE_USES_SCHEDULE_PROVIDER( classname ) reqiredOthers.AddToTail( ScheduleLoadHelper(classname) );
  1942. //-----------------
  1943. // IDs are stored and then added in order due to constraints in the namespace implementation
  1944. #define AI_END_CUSTOM_SCHEDULE_PROVIDER() \
  1945. \
  1946. int i; \
  1947. \
  1948. CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
  1949. \
  1950. scheduleIds.Sort(); \
  1951. taskIds.Sort(); \
  1952. conditionIds.Sort(); \
  1953. \
  1954. for ( i = 0; i < scheduleIds.Count(); i++ ) \
  1955. { \
  1956. ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \
  1957. } \
  1958. \
  1959. for ( i = 0; i < taskIds.Count(); i++ ) \
  1960. { \
  1961. ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \
  1962. } \
  1963. \
  1964. for ( i = 0; i < conditionIds.Count(); i++ ) \
  1965. { \
  1966. if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \
  1967. { \
  1968. ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \
  1969. } \
  1970. } \
  1971. \
  1972. for ( i = 0; i < reqiredOthers.Count(); i++ ) \
  1973. { \
  1974. (*reqiredOthers[i])(); \
  1975. } \
  1976. \
  1977. for ( i = 0; i < schedulesToLoad.Count(); i++ ) \
  1978. { \
  1979. if ( CNpc::gm_SchedLoadStatus.fValid ) \
  1980. { \
  1981. CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect(), GetSchedulingSymbols() ); \
  1982. } \
  1983. else \
  1984. break; \
  1985. } \
  1986. }
  1987. inline bool ValidateConditionLimits( const char *pszNewCondition )
  1988. {
  1989. int nGlobalConditions = CAI_BaseNPC::GetSchedulingSymbols()->NumConditions();
  1990. if ( nGlobalConditions >= MAX_CONDITIONS )
  1991. {
  1992. AssertMsg2( 0, "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition );
  1993. DevWarning( "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition );
  1994. return false;
  1995. }
  1996. return true;
  1997. }
  1998. //-------------------------------------
  1999. // IDs are stored and then added in order due to constraints in the namespace implementation
  2000. #define AI_END_CUSTOM_NPC() \
  2001. \
  2002. int i; \
  2003. \
  2004. CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
  2005. CNpc::gm_SquadSlotIdSpace.Init( &BaseClass::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace); \
  2006. \
  2007. scheduleIds.Sort(); \
  2008. taskIds.Sort(); \
  2009. conditionIds.Sort(); \
  2010. squadSlotIds.Sort(); \
  2011. \
  2012. for ( i = 0; i < scheduleIds.Count(); i++ ) \
  2013. { \
  2014. ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \
  2015. } \
  2016. \
  2017. for ( i = 0; i < taskIds.Count(); i++ ) \
  2018. { \
  2019. ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \
  2020. } \
  2021. \
  2022. for ( i = 0; i < conditionIds.Count(); i++ ) \
  2023. { \
  2024. if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \
  2025. { \
  2026. ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \
  2027. } \
  2028. } \
  2029. \
  2030. for ( i = 0; i < squadSlotIds.Count(); i++ ) \
  2031. { \
  2032. ADD_CUSTOM_SQUADSLOT_NAMED( CNpc, squadSlotIds[i].pszName, squadSlotIds[i].localId ); \
  2033. } \
  2034. \
  2035. for ( i = 0; i < reqiredOthers.Count(); i++ ) \
  2036. { \
  2037. (*reqiredOthers[i])(); \
  2038. } \
  2039. \
  2040. for ( i = 0; i < schedulesToLoad.Count(); i++ ) \
  2041. { \
  2042. if ( CNpc::gm_SchedLoadStatus.fValid ) \
  2043. { \
  2044. CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect(), GetSchedulingSymbols() ); \
  2045. } \
  2046. else \
  2047. break; \
  2048. } \
  2049. }
  2050. //-------------------------------------
  2051. struct AI_NamespaceAddInfo_t
  2052. {
  2053. AI_NamespaceAddInfo_t( const char *pszName, int localId )
  2054. : pszName( pszName ),
  2055. localId( localId )
  2056. {
  2057. }
  2058. const char *pszName;
  2059. int localId;
  2060. };
  2061. class CAI_NamespaceInfos : public CUtlVector<AI_NamespaceAddInfo_t>
  2062. {
  2063. public:
  2064. void PushBack( const char *pszName, int localId )
  2065. {
  2066. AddToTail( AI_NamespaceAddInfo_t( pszName, localId ) );
  2067. }
  2068. void Sort()
  2069. {
  2070. CUtlVector<AI_NamespaceAddInfo_t>::Sort( Compare );
  2071. }
  2072. private:
  2073. static int __cdecl Compare(const AI_NamespaceAddInfo_t *pLeft, const AI_NamespaceAddInfo_t *pRight )
  2074. {
  2075. return pLeft->localId - pRight->localId;
  2076. }
  2077. };
  2078. //-------------------------------------
  2079. // Declares the static variables that hold the string registry offset for the new subclass
  2080. // as well as the initialization in schedule load functions
  2081. struct AI_SchedLoadStatus_t
  2082. {
  2083. bool fValid;
  2084. int signature;
  2085. };
  2086. // Load schedules pulled out to support stepping through with debugger
  2087. inline bool AI_DoLoadSchedules( bool (*pfnBaseLoad)(), void (*pfnInitCustomSchedules)(),
  2088. AI_SchedLoadStatus_t *pLoadStatus )
  2089. {
  2090. (*pfnBaseLoad)();
  2091. if (pLoadStatus->signature != g_AI_SchedulesManager.GetScheduleLoadSignature())
  2092. {
  2093. (*pfnInitCustomSchedules)();
  2094. pLoadStatus->fValid = true;
  2095. pLoadStatus->signature = g_AI_SchedulesManager.GetScheduleLoadSignature();
  2096. }
  2097. return pLoadStatus->fValid;
  2098. }
  2099. //-------------------------------------
  2100. typedef bool (*AIScheduleLoadFunc_t)();
  2101. // @Note (toml 02-16-03): The following class exists to allow us to establish an anonymous friendship
  2102. // in DEFINE_CUSTOM_SCHEDULE_PROVIDER. The particulars of this implementation is almost entirely
  2103. // defined by bugs in MSVC 6.0
  2104. class ScheduleLoadHelperImpl
  2105. {
  2106. public:
  2107. template <typename T>
  2108. static AIScheduleLoadFunc_t AccessScheduleLoadFunc(T *)
  2109. {
  2110. return (&T::LoadSchedules);
  2111. }
  2112. };
  2113. #define ScheduleLoadHelper( type ) (ScheduleLoadHelperImpl::AccessScheduleLoadFunc((type *)0))
  2114. //-------------------------------------
  2115. #define DEFINE_CUSTOM_SCHEDULE_PROVIDER\
  2116. static AI_SchedLoadStatus_t gm_SchedLoadStatus; \
  2117. static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace; \
  2118. static const char * gm_pszErrorClassName;\
  2119. \
  2120. static CAI_ClassScheduleIdSpace & AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; } \
  2121. virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; } \
  2122. virtual const char * GetSchedulingErrorName() { return gm_pszErrorClassName; } \
  2123. \
  2124. static void InitCustomSchedules(void);\
  2125. \
  2126. static bool LoadSchedules(void);\
  2127. virtual bool LoadedSchedules(void); \
  2128. \
  2129. friend class ScheduleLoadHelperImpl; \
  2130. \
  2131. class CScheduleLoader \
  2132. { \
  2133. public: \
  2134. CScheduleLoader(); \
  2135. } m_ScheduleLoader; \
  2136. \
  2137. friend class CScheduleLoader;
  2138. //-------------------------------------
  2139. #define DEFINE_CUSTOM_AI\
  2140. DEFINE_CUSTOM_SCHEDULE_PROVIDER \
  2141. \
  2142. static CAI_LocalIdSpace gm_SquadSlotIdSpace; \
  2143. \
  2144. const char* SquadSlotName (int squadSlotID);
  2145. //-------------------------------------
  2146. #define IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\
  2147. AI_SchedLoadStatus_t derivedClass::gm_SchedLoadStatus = { true, -1 }; \
  2148. CAI_ClassScheduleIdSpace derivedClass::gm_ClassScheduleIdSpace; \
  2149. const char * derivedClass::gm_pszErrorClassName = #derivedClass; \
  2150. \
  2151. derivedClass::CScheduleLoader::CScheduleLoader()\
  2152. { \
  2153. derivedClass::LoadSchedules(); \
  2154. } \
  2155. \
  2156. /* --------------------------------------------- */ \
  2157. /* Load schedules for this type of NPC */ \
  2158. /* --------------------------------------------- */ \
  2159. bool derivedClass::LoadSchedules(void)\
  2160. {\
  2161. return AI_DoLoadSchedules( derivedClass::BaseClass::LoadSchedules, \
  2162. derivedClass::InitCustomSchedules, \
  2163. &derivedClass::gm_SchedLoadStatus ); \
  2164. }\
  2165. \
  2166. bool derivedClass::LoadedSchedules(void) \
  2167. { \
  2168. return derivedClass::gm_SchedLoadStatus.fValid;\
  2169. }
  2170. //-------------------------------------
  2171. // Initialize offsets and implement methods for loading and getting squad info for the subclass
  2172. #define IMPLEMENT_CUSTOM_AI(className, derivedClass)\
  2173. IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\
  2174. \
  2175. CAI_LocalIdSpace derivedClass::gm_SquadSlotIdSpace; \
  2176. \
  2177. /* -------------------------------------------------- */ \
  2178. /* Given squadSlot enumeration return squadSlot name */ \
  2179. /* -------------------------------------------------- */ \
  2180. const char* derivedClass::SquadSlotName(int slotEN)\
  2181. {\
  2182. return gm_SquadSlotNamespace.IdToSymbol( derivedClass::gm_SquadSlotIdSpace.LocalToGlobal(slotEN) );\
  2183. }
  2184. //-------------------------------------
  2185. #define ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,schedName,schedEN)\
  2186. if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddSchedule( schedName, schedEN, derivedClass::gm_pszErrorClassName ) ) return;
  2187. #define ADD_CUSTOM_SCHEDULE(derivedClass,schedEN) ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,#schedEN,schedEN)
  2188. #define ADD_CUSTOM_TASK_NAMED(derivedClass,taskName,taskEN)\
  2189. if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddTask( taskName, taskEN, derivedClass::gm_pszErrorClassName ) ) return;
  2190. #define ADD_CUSTOM_TASK(derivedClass,taskEN) ADD_CUSTOM_TASK_NAMED(derivedClass,#taskEN,taskEN)
  2191. #define ADD_CUSTOM_CONDITION_NAMED(derivedClass,condName,condEN)\
  2192. if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddCondition( condName, condEN, derivedClass::gm_pszErrorClassName ) ) return;
  2193. #define ADD_CUSTOM_CONDITION(derivedClass,condEN) ADD_CUSTOM_CONDITION_NAMED(derivedClass,#condEN,condEN)
  2194. //-------------------------------------
  2195. #define INIT_CUSTOM_AI(derivedClass)\
  2196. derivedClass::AccessClassScheduleIdSpaceDirect().Init( #derivedClass, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
  2197. derivedClass::gm_SquadSlotIdSpace.Init( &CAI_BaseNPC::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace);
  2198. #define ADD_CUSTOM_INTERACTION( interaction ) { interaction = CBaseCombatCharacter::GetInteractionID(); }
  2199. #define ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,squadSlotName,squadSlotEN)\
  2200. if ( !derivedClass::gm_SquadSlotIdSpace.AddSymbol( squadSlotName, squadSlotEN, "squadslot", derivedClass::gm_pszErrorClassName ) ) return;
  2201. #define ADD_CUSTOM_SQUADSLOT(derivedClass,squadSlotEN) ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,#squadSlotEN,squadSlotEN)
  2202. #define ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,activityName,activityEnum)\
  2203. REGISTER_PRIVATE_ACTIVITY(activityEnum);\
  2204. CAI_BaseNPC::AddActivityToSR(activityName,activityEnum);
  2205. #define ADD_CUSTOM_ACTIVITY(derivedClass,activityEnum) ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,#activityEnum,activityEnum)
  2206. #define ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,eventName,eventEnum)\
  2207. REGISTER_PRIVATE_ANIMEVENT(eventEnum);\
  2208. CAI_BaseNPC::AddEventToSR(eventName,eventEnum);
  2209. #define ADD_CUSTOM_ANIMEVENT(derivedClass,eventEnum) ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,#eventEnum,eventEnum)
  2210. //=============================================================================
  2211. // class CAI_Component
  2212. //=============================================================================
  2213. inline const Vector &CAI_Component::GetLocalOrigin() const
  2214. {
  2215. return GetOuter()->GetLocalOrigin();
  2216. }
  2217. //-----------------------------------------------------------------------------
  2218. inline void CAI_Component::SetLocalOrigin(const Vector &origin)
  2219. {
  2220. GetOuter()->SetLocalOrigin(origin);
  2221. }
  2222. //-----------------------------------------------------------------------------
  2223. inline const Vector &CAI_Component::GetAbsOrigin() const
  2224. {
  2225. return GetOuter()->GetAbsOrigin();
  2226. }
  2227. //-----------------------------------------------------------------------------
  2228. inline const QAngle &CAI_Component::GetAbsAngles() const
  2229. {
  2230. return GetOuter()->GetAbsAngles();
  2231. }
  2232. //-----------------------------------------------------------------------------
  2233. inline void CAI_Component::SetSolid( SolidType_t val )
  2234. {
  2235. GetOuter()->SetSolid(val);
  2236. }
  2237. //-----------------------------------------------------------------------------
  2238. inline SolidType_t CAI_Component::GetSolid() const
  2239. {
  2240. return GetOuter()->GetSolid();
  2241. }
  2242. //-----------------------------------------------------------------------------
  2243. inline const Vector &CAI_Component::WorldAlignMins() const
  2244. {
  2245. return GetOuter()->WorldAlignMins();
  2246. }
  2247. //-----------------------------------------------------------------------------
  2248. inline const Vector &CAI_Component::WorldAlignMaxs() const
  2249. {
  2250. return GetOuter()->WorldAlignMaxs();
  2251. }
  2252. //-----------------------------------------------------------------------------
  2253. inline Hull_t CAI_Component::GetHullType() const
  2254. {
  2255. return GetOuter()->GetHullType();
  2256. }
  2257. //-----------------------------------------------------------------------------
  2258. inline Vector CAI_Component::WorldSpaceCenter() const
  2259. {
  2260. return GetOuter()->WorldSpaceCenter();
  2261. }
  2262. //-----------------------------------------------------------------------------
  2263. inline float CAI_Component::GetGravity() const
  2264. {
  2265. return GetOuter()->GetGravity();
  2266. }
  2267. //-----------------------------------------------------------------------------
  2268. inline void CAI_Component::SetGravity( float flGravity )
  2269. {
  2270. GetOuter()->SetGravity( flGravity );
  2271. }
  2272. //-----------------------------------------------------------------------------
  2273. inline float CAI_Component::GetHullWidth() const
  2274. {
  2275. return NAI_Hull::Width(GetOuter()->GetHullType());
  2276. }
  2277. //-----------------------------------------------------------------------------
  2278. inline float CAI_Component::GetHullHeight() const
  2279. {
  2280. return NAI_Hull::Height(GetOuter()->GetHullType());
  2281. }
  2282. //-----------------------------------------------------------------------------
  2283. inline const Vector &CAI_Component::GetHullMins() const
  2284. {
  2285. return NAI_Hull::Mins(GetOuter()->GetHullType());
  2286. }
  2287. //-----------------------------------------------------------------------------
  2288. inline const Vector &CAI_Component::GetHullMaxs() const
  2289. {
  2290. return NAI_Hull::Maxs(GetOuter()->GetHullType());
  2291. }
  2292. inline int CAI_Component::GetHullTraceMask() const
  2293. {
  2294. return NAI_Hull::TraceMask(GetOuter()->GetHullType());
  2295. }
  2296. //-----------------------------------------------------------------------------
  2297. inline int CAI_Component::GetCollisionGroup() const
  2298. {
  2299. return GetOuter()->GetCollisionGroup();
  2300. }
  2301. //-----------------------------------------------------------------------------
  2302. inline CBaseEntity *CAI_Component::GetEnemy()
  2303. {
  2304. return GetOuter()->GetEnemy();
  2305. }
  2306. //-----------------------------------------------------------------------------
  2307. inline const Vector &CAI_Component::GetEnemyLKP() const
  2308. {
  2309. return GetOuter()->GetEnemyLKP();
  2310. }
  2311. //-----------------------------------------------------------------------------
  2312. inline void CAI_Component::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition )
  2313. {
  2314. GetOuter()->TranslateNavGoal( pEnemy, chasePosition );
  2315. }
  2316. //-----------------------------------------------------------------------------
  2317. inline CBaseEntity *CAI_Component::GetTarget()
  2318. {
  2319. return GetOuter()->GetTarget();
  2320. }
  2321. //-----------------------------------------------------------------------------
  2322. inline void CAI_Component::SetTarget( CBaseEntity *pTarget )
  2323. {
  2324. GetOuter()->SetTarget( pTarget );
  2325. }
  2326. //-----------------------------------------------------------------------------
  2327. inline const Task_t *CAI_Component::GetCurTask()
  2328. {
  2329. return GetOuter()->GetTask();
  2330. }
  2331. //-----------------------------------------------------------------------------
  2332. inline void CAI_Component::TaskFail( AI_TaskFailureCode_t code )
  2333. {
  2334. GetOuter()->TaskFail( code );
  2335. }
  2336. //-----------------------------------------------------------------------------
  2337. inline void CAI_Component::TaskFail( const char *pszGeneralFailText )
  2338. {
  2339. GetOuter()->TaskFail( pszGeneralFailText );
  2340. }
  2341. //-----------------------------------------------------------------------------
  2342. inline void CAI_Component::TaskComplete( bool fIgnoreSetFailedCondition )
  2343. {
  2344. GetOuter()->TaskComplete( fIgnoreSetFailedCondition );
  2345. }
  2346. //-----------------------------------------------------------------------------
  2347. inline int CAI_Component::TaskIsRunning()
  2348. {
  2349. return GetOuter()->TaskIsRunning();
  2350. }
  2351. //-----------------------------------------------------------------------------
  2352. inline int CAI_Component::TaskIsComplete()
  2353. {
  2354. return GetOuter()->TaskIsComplete();
  2355. }
  2356. //-----------------------------------------------------------------------------
  2357. inline Activity CAI_Component::GetActivity()
  2358. {
  2359. return GetOuter()->GetActivity();
  2360. }
  2361. //-----------------------------------------------------------------------------
  2362. inline void CAI_Component::SetActivity( Activity NewActivity )
  2363. {
  2364. GetOuter()->SetActivity( NewActivity );
  2365. }
  2366. //-----------------------------------------------------------------------------
  2367. inline float CAI_Component::GetIdealSpeed() const
  2368. {
  2369. return GetOuter()->GetIdealSpeed();
  2370. }
  2371. //-----------------------------------------------------------------------------
  2372. inline float CAI_Component::GetIdealAccel() const
  2373. {
  2374. return GetOuter()->GetIdealAccel();
  2375. }
  2376. //-----------------------------------------------------------------------------
  2377. inline int CAI_Component::GetSequence()
  2378. {
  2379. return GetOuter()->GetSequence();
  2380. }
  2381. //-----------------------------------------------------------------------------
  2382. inline int CAI_Component::GetEntFlags() const
  2383. {
  2384. return GetOuter()->GetFlags();
  2385. }
  2386. //-----------------------------------------------------------------------------
  2387. inline void CAI_Component::AddEntFlag( int flags )
  2388. {
  2389. GetOuter()->AddFlag( flags );
  2390. }
  2391. //-----------------------------------------------------------------------------
  2392. inline void CAI_Component::RemoveEntFlag( int flagsToRemove )
  2393. {
  2394. GetOuter()->RemoveFlag( flagsToRemove );
  2395. }
  2396. //-----------------------------------------------------------------------------
  2397. // Purpose: Change the ground entity for the outer
  2398. // Input : *ground -
  2399. // Output : inline void
  2400. //-----------------------------------------------------------------------------
  2401. inline void CAI_Component::SetGroundEntity( CBaseEntity *ground )
  2402. {
  2403. GetOuter()->SetGroundEntity( ground );
  2404. }
  2405. //-----------------------------------------------------------------------------
  2406. inline void CAI_Component::ToggleEntFlag( int flagToToggle )
  2407. {
  2408. GetOuter()->ToggleFlag( flagToToggle );
  2409. }
  2410. //-----------------------------------------------------------------------------
  2411. inline CBaseEntity* CAI_Component::GetGoalEnt()
  2412. {
  2413. return GetOuter()->GetGoalEnt();
  2414. }
  2415. //-----------------------------------------------------------------------------
  2416. inline void CAI_Component::SetGoalEnt( CBaseEntity *pGoalEnt )
  2417. {
  2418. GetOuter()->SetGoalEnt( pGoalEnt );
  2419. }
  2420. //-----------------------------------------------------------------------------
  2421. inline void CAI_Component::Remember( int iMemory )
  2422. {
  2423. GetOuter()->Remember( iMemory );
  2424. }
  2425. //-----------------------------------------------------------------------------
  2426. inline void CAI_Component::Forget( int iMemory )
  2427. {
  2428. GetOuter()->Forget( iMemory );
  2429. }
  2430. //-----------------------------------------------------------------------------
  2431. inline bool CAI_Component::HasMemory( int iMemory )
  2432. {
  2433. return GetOuter()->HasMemory( iMemory );
  2434. }
  2435. //-----------------------------------------------------------------------------
  2436. inline CAI_Enemies *CAI_Component::GetEnemies()
  2437. {
  2438. return GetOuter()->GetEnemies();
  2439. }
  2440. //-----------------------------------------------------------------------------
  2441. inline const char *CAI_Component::GetEntClassname()
  2442. {
  2443. return GetOuter()->GetClassname();
  2444. }
  2445. //-----------------------------------------------------------------------------
  2446. inline int CAI_Component::CapabilitiesGet()
  2447. {
  2448. return GetOuter()->CapabilitiesGet();
  2449. }
  2450. //-----------------------------------------------------------------------------
  2451. inline void CAI_Component::SetLocalAngles( const QAngle& angles )
  2452. {
  2453. GetOuter()->SetLocalAngles( angles );
  2454. }
  2455. //-----------------------------------------------------------------------------
  2456. inline const QAngle &CAI_Component::GetLocalAngles( void ) const
  2457. {
  2458. return GetOuter()->GetLocalAngles();
  2459. }
  2460. //-----------------------------------------------------------------------------
  2461. inline edict_t *CAI_Component::GetEdict()
  2462. {
  2463. return GetOuter()->NetworkProp()->edict();
  2464. }
  2465. //-----------------------------------------------------------------------------
  2466. inline float CAI_Component::GetLastThink( const char *szContext )
  2467. {
  2468. return GetOuter()->GetLastThink( szContext );
  2469. }
  2470. // ============================================================================
  2471. abstract_class INPCInteractive
  2472. {
  2473. public:
  2474. virtual bool CanInteractWith( CAI_BaseNPC *pUser ) = 0;
  2475. virtual bool HasBeenInteractedWith() = 0;
  2476. virtual void NotifyInteraction( CAI_BaseNPC *pUser ) = 0;
  2477. // Alyx specific interactions
  2478. virtual void AlyxStartedInteraction( void ) = 0;
  2479. virtual void AlyxFinishedInteraction( void ) = 0;
  2480. };
  2481. // Base Class for any NPC that wants to be interactable by other NPCS (i.e. Alyx Hackable)
  2482. // NOTE: YOU MUST DEFINE THE OUTPUTS IN YOUR CLASS'S DATADESC!
  2483. // THE DO SO, INSERT THE FOLLOWING MACRO INTO YOUR CLASS'S DATADESC.
  2484. //
  2485. #define DEFINE_BASENPCINTERACTABLE_DATADESC() \
  2486. DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \
  2487. DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \
  2488. DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown )
  2489. template <class NPC_CLASS>
  2490. class CNPCBaseInteractive : public NPC_CLASS, public INPCInteractive
  2491. {
  2492. DECLARE_CLASS( CNPCBaseInteractive, NPC_CLASS );
  2493. public:
  2494. virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; };
  2495. virtual bool HasBeenInteractedWith() { return false; };
  2496. virtual void NotifyInteraction( CAI_BaseNPC *pUser ) { return; };
  2497. virtual void InputPowerdown( inputdata_t &inputdata )
  2498. {
  2499. }
  2500. // Alyx specific interactions
  2501. virtual void AlyxStartedInteraction( void )
  2502. {
  2503. m_OnAlyxStartedInteraction.FireOutput( this, this );
  2504. }
  2505. virtual void AlyxFinishedInteraction( void )
  2506. {
  2507. m_OnAlyxFinishedInteraction.FireOutput( this, this );
  2508. }
  2509. public:
  2510. // Outputs
  2511. // Alyx specific interactions
  2512. COutputEvent m_OnAlyxStartedInteraction;
  2513. COutputEvent m_OnAlyxFinishedInteraction;
  2514. };
  2515. //
  2516. // Deferred Navigation calls go here
  2517. //
  2518. extern ConVar ai_post_frame_navigation;
  2519. class CPostFrameNavigationHook : public CBaseGameSystemPerFrame
  2520. {
  2521. public:
  2522. virtual const char *Name( void ) { return "CPostFrameNavigationHook"; }
  2523. virtual bool Init( void );
  2524. virtual void FrameUpdatePostEntityThink( void );
  2525. virtual void FrameUpdatePreEntityThink( void );
  2526. bool IsGameFrameRunning( void ) { return m_bGameFrameRunning; }
  2527. void SetGrameFrameRunning( bool bState ) { m_bGameFrameRunning = bState; }
  2528. void EnqueueEntityNavigationQuery( CAI_BaseNPC *pNPC, CFunctor *functor );
  2529. private:
  2530. CUtlVector<CFunctor *> m_Functors;
  2531. bool m_bGameFrameRunning;
  2532. };
  2533. extern CPostFrameNavigationHook *PostFrameNavigationSystem( void );
  2534. #endif // AI_BASENPC_H