aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/ai_basenpc.h
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/ai_basenpc.h
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/ai_basenpc.h')
-rw-r--r--mp/src/game/server/ai_basenpc.h6250
1 files changed, 3125 insertions, 3125 deletions
diff --git a/mp/src/game/server/ai_basenpc.h b/mp/src/game/server/ai_basenpc.h
index f5224f15..2131a0f4 100644
--- a/mp/src/game/server/ai_basenpc.h
+++ b/mp/src/game/server/ai_basenpc.h
@@ -1,3125 +1,3125 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Base NPC character with AI
-//
-//=============================================================================//
-
-#ifndef AI_BASENPC_H
-#define AI_BASENPC_H
-
-#ifdef _WIN32
-#pragma once
-#endif
-
-#include "simtimer.h"
-#include "basecombatcharacter.h"
-#include "ai_debug.h"
-#include "ai_default.h"
-#include "ai_schedule.h"
-#include "ai_condition.h"
-#include "ai_component.h"
-#include "ai_task.h"
-#include "ai_movetypes.h"
-#include "ai_navtype.h"
-#include "ai_namespaces.h"
-#include "ai_npcstate.h"
-#include "ai_hull.h"
-#include "ai_utils.h"
-#include "ai_moveshoot.h"
-#include "entityoutput.h"
-#include "utlvector.h"
-#include "activitylist.h"
-#include "bitstring.h"
-#include "ai_basenpc.h"
-#include "ai_navgoaltype.h" //GoalType_t enum
-#include "eventlist.h"
-#include "soundent.h"
-#include "ai_navigator.h"
-#include "tier1/functors.h"
-
-
-#define PLAYER_SQUADNAME "player_squad"
-
-class CAI_Schedule;
-class CAI_Network;
-class CAI_Route;
-class CAI_Hint;
-class CAI_Node;
-class CAI_Navigator;
-class CAI_Pathfinder;
-class CAI_Senses;
-class CAI_Enemies;
-class CAI_Squad;
-class CAI_Expresser;
-class CAI_BehaviorBase;
-class CAI_GoalEntity;
-class CAI_Motor;
-class CAI_MoveProbe;
-class CAI_LocalNavigator;
-class CAI_TacticalServices;
-class CVarBitVec;
-class CAI_ScriptedSequence;
-class CSceneEntity;
-class CBaseGrenade;
-class CBaseDoor;
-class CBasePropDoor;
-struct AI_Waypoint_t;
-class AI_Response;
-class CBaseFilter;
-
-typedef CBitVec<MAX_CONDITIONS> CAI_ScheduleBits;
-
-// Used to control optimizations mostly dealing with pathfinding for NPCs
-extern ConVar ai_strong_optimizations;
-
-extern bool AIStrongOpt( void );
-
-// AI_MONITOR_FOR_OSCILLATION defaults to OFF. If you build with this ON, you can flag
-// NPC's and monitor them to detect oscillations in their schedule (circular logic and conditions bugs)
-// DO NOT SHIP WITH THIS ON!
-#undef AI_MONITOR_FOR_OSCILLATION
-
-//=============================================================================
-//
-// Constants & enumerations
-//
-//=============================================================================
-#define TURRET_CLOSE_RANGE 200
-#define TURRET_MEDIUM_RANGE 500
-
-#define COMMAND_GOAL_TOLERANCE 48 // 48 inches.
-#define TIME_CARE_ABOUT_DAMAGE 3.0
-
-#define ITEM_PICKUP_TOLERANCE 48.0f
-
-// Max's of the box used to search for a weapon to pick up. 45x45x~8 ft.
-#define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 )
-
-enum Interruptability_t
-{
- GENERAL_INTERRUPTABILITY,
- DAMAGEORDEATH_INTERRUPTABILITY,
- DEATH_INTERRUPTABILITY
-};
-
-//-------------------------------------
-// Memory
-//-------------------------------------
-
-#define MEMORY_CLEAR 0
-#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes.
-#define bits_MEMORY_INCOVER ( 1 << 1 )// npc knows it is in a covered position.
-#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily
-#define bits_MEMORY_TASK_EXPENSIVE ( 1 << 3 )// NPC has completed a task which is considered costly, so don't do another task this frame
-//#define bits_MEMORY_ ( 1 << 4 )
-#define bits_MEMORY_PATH_FAILED ( 1 << 5 )// Failed to find a path
-#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
-//#define bits_MEMORY_ ( 1 << 7 )
-#define bits_MEMORY_TOURGUIDE ( 1 << 8 )// I have been acting as a tourguide.
-//#define bits_MEMORY_ ( 1 << 9 )//
-#define bits_MEMORY_LOCKED_HINT ( 1 << 10 )//
-//#define bits_MEMORY_ ( 1 << 12 )
-
-#define bits_MEMORY_TURNING ( 1 << 13 )// Turning, don't interrupt me.
-#define bits_MEMORY_TURNHACK ( 1 << 14 )
-
-#define bits_MEMORY_HAD_ENEMY ( 1 << 15 )// Had an enemy
-#define bits_MEMORY_HAD_PLAYER ( 1 << 16 )// Had player
-#define bits_MEMORY_HAD_LOS ( 1 << 17 )// Had LOS to enemy
-
-#define bits_MEMORY_MOVED_FROM_SPAWN ( 1 << 18 )// Has moved since spawning.
-
-#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // NPC-specific memory
-#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // NPC-specific memory
-#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // NPC-specific memory
-#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // NPC-specific memory
-
-//-------------------------------------
-// Spawn flags
-//-------------------------------------
-#define SF_NPC_WAIT_TILL_SEEN ( 1 << 0 ) // spawnflag that makes npcs wait until player can see them before attacking.
-#define SF_NPC_GAG ( 1 << 1 ) // no idle noises from this npc
-#define SF_NPC_FALL_TO_GROUND ( 1 << 2 ) // used my NPC_Maker
-#define SF_NPC_DROP_HEALTHKIT ( 1 << 3 ) // Drop a healthkit upon death
-#define SF_NPC_START_EFFICIENT ( 1 << 4 ) // Set into efficiency mode from spawn
-// ( 1 << 5 )
-// ( 1 << 6 )
-#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
-#define SF_NPC_LONG_RANGE ( 1 << 8 ) // makes npcs look far and relaxes weapon range limit
-#define SF_NPC_FADE_CORPSE ( 1 << 9 ) // Fade out corpse after death
-#define SF_NPC_ALWAYSTHINK ( 1 << 10 ) // Simulate even when player isn't in PVS.
-#define SF_NPC_TEMPLATE ( 1 << 11 ) // This NPC will be used as a template by an npc_maker -- do not spawn.
-#define SF_NPC_ALTCOLLISION ( 1 << 12 )
-#define SF_NPC_NO_WEAPON_DROP ( 1 << 13 ) // This NPC will not actually drop a weapon that can be picked up
-#define SF_NPC_NO_PLAYER_PUSHAWAY ( 1 << 14 )
-// ( 1 << 15 )
-// !! Flags above ( 1 << 15 ) are reserved for NPC sub-classes
-
-//-------------------------------------
-//
-// Return codes from CanPlaySequence.
-//
-//-------------------------------------
-
-enum CanPlaySequence_t
-{
- CANNOT_PLAY = 0, // Can't play for any number of reasons.
- CAN_PLAY_NOW, // Can play the script immediately.
- CAN_PLAY_ENQUEUED, // Can play the script after I finish playing my current script.
-};
-
-//-------------------------------------
-// Weapon holstering
-//-------------------------------------
-enum DesiredWeaponState_t
-{
- DESIREDWEAPONSTATE_IGNORE = 0,
- DESIREDWEAPONSTATE_HOLSTERED,
- DESIREDWEAPONSTATE_HOLSTERED_DESTROYED, // Put the weapon away, then destroy it.
- DESIREDWEAPONSTATE_UNHOLSTERED,
- DESIREDWEAPONSTATE_CHANGING,
- DESIREDWEAPONSTATE_CHANGING_DESTROY, // Destroy the weapon when this change is complete.
-};
-
-//-------------------------------------
-//
-// Efficiency modes
-//
-//-------------------------------------
-
-enum AI_Efficiency_t
-{
- // Run at full tilt
- AIE_NORMAL,
-
- // Run decision process less often
- AIE_EFFICIENT,
-
- // Run decision process even less often, ignore other NPCs
- AIE_VERY_EFFICIENT,
-
- // Run decision process even less often, ignore other NPCs
- AIE_SUPER_EFFICIENT,
-
- // Don't run at all
- AIE_DORMANT,
-};
-
-enum AI_MoveEfficiency_t
-{
- AIME_NORMAL,
- AIME_EFFICIENT,
-};
-
-//-------------------------------------
-//
-// Sleep state
-//
-//-------------------------------------
-
-enum AI_SleepState_t
-{
- AISS_AWAKE,
- AISS_WAITING_FOR_THREAT,
- AISS_WAITING_FOR_PVS,
- AISS_WAITING_FOR_INPUT,
- AISS_AUTO_PVS,
- AISS_AUTO_PVS_AFTER_PVS, // Same as AUTO_PVS, except doesn't activate until/unless the NPC is IN the player's PVS.
-};
-
-#define AI_SLEEP_FLAGS_NONE 0x00000000
-#define AI_SLEEP_FLAG_AUTO_PVS 0x00000001
-#define AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS 0x00000002
-
-
-//-------------------------------------
-//
-// Debug bits
-//
-//-------------------------------------
-
-enum DebugBaseNPCBits_e
-{
- bits_debugDisableAI = 0x00000001, // disable AI
- bits_debugStepAI = 0x00000002, // step AI
-
-};
-
-//-------------------------------------
-//
-// Base Sentence index for behaviors
-//
-//-------------------------------------
-enum SentenceIndex_t
-{
- SENTENCE_BASE_BEHAVIOR_INDEX = 1000,
-};
-
-#ifdef AI_MONITOR_FOR_OSCILLATION
-struct AIScheduleChoice_t
-{
- float m_flTimeSelected;
- CAI_Schedule *m_pScheduleSelected;
-};
-#endif//AI_MONITOR_FOR_OSCILLATION
-
-#define MARK_TASK_EXPENSIVE() \
- if ( GetOuter() ) \
- { \
- GetOuter()->Remember( bits_MEMORY_TASK_EXPENSIVE ); \
- }
-
-//=============================================================================
-//
-// Types used by CAI_BaseNPC
-//
-//=============================================================================
-
-struct AIScheduleState_t
-{
- int iCurTask;
- TaskStatus_e fTaskStatus;
- float timeStarted;
- float timeCurTaskStarted;
- AI_TaskFailureCode_t taskFailureCode;
- int iTaskInterrupt;
- bool bTaskRanAutomovement;
- bool bTaskUpdatedYaw;
- bool bScheduleWasInterrupted;
-
- DECLARE_SIMPLE_DATADESC();
-};
-
-// -----------------------------------------
-// An entity that this NPC can't reach
-// -----------------------------------------
-
-struct UnreachableEnt_t
-{
- EHANDLE hUnreachableEnt; // Entity that's unreachable
- float fExpireTime; // Time to forget this information
- Vector vLocationWhenUnreachable;
-
- DECLARE_SIMPLE_DATADESC();
-};
-
-//=============================================================================
-// SCRIPTED NPC INTERACTIONS
-//=============================================================================
-// -----------------------------------------
-// Scripted NPC interaction flags
-// -----------------------------------------
-#define SCNPC_FLAG_TEST_OTHER_ANGLES ( 1 << 1 )
-#define SCNPC_FLAG_TEST_OTHER_VELOCITY ( 1 << 2 )
-#define SCNPC_FLAG_LOOP_IN_ACTION ( 1 << 3 )
-#define SCNPC_FLAG_NEEDS_WEAPON_ME ( 1 << 4 )
-#define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 )
-#define SCNPC_FLAG_DONT_TELEPORT_AT_END_ME ( 1 << 6 )
-#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )
-
-// -----------------------------------------
-// Scripted NPC interaction trigger methods
-// -----------------------------------------
-enum
-{
- SNPCINT_CODE = 0,
- SNPCINT_AUTOMATIC_IN_COMBAT = 1,
-};
-
-// -----------------------------------------
-// Scripted NPC interaction loop breaking trigger methods
-// -----------------------------------------
-#define SNPCINT_LOOPBREAK_ON_DAMAGE ( 1 << 1 )
-#define SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ( 1 << 2 )
-
-// -----------------------------------------
-// Scripted NPC interaction anim phases
-// -----------------------------------------
-enum
-{
- SNPCINT_ENTRY = 0,
- SNPCINT_SEQUENCE,
- SNPCINT_EXIT,
-
- SNPCINT_NUM_PHASES
-};
-
-struct ScriptedNPCInteraction_Phases_t
-{
- string_t iszSequence;
- int iActivity;
-
- DECLARE_SIMPLE_DATADESC();
-};
-
-// Allowable delta from the desired dynamic scripted sequence point
-#define DSS_MAX_DIST 6
-#define DSS_MAX_ANGLE_DIFF 4
-
-// Interaction Logic States
-enum
-{
- NPCINT_NOT_RUNNING = 0,
- NPCINT_RUNNING_ACTIVE, // I'm in an interaction that I initiated
- NPCINT_RUNNING_PARTNER, // I'm in an interaction that was initiated by the other NPC
- NPCINT_MOVING_TO_MARK, // I'm moving to a position to do an interaction
-};
-
-#define NPCINT_NONE -1
-
-#define MAXTACLAT_IGNORE -1
-
-// -----------------------------------------
-// A scripted interaction between NPCs
-// -----------------------------------------
-struct ScriptedNPCInteraction_t
-{
- ScriptedNPCInteraction_t()
- {
- iszInteractionName = NULL_STRING;
- iFlags = 0;
- iTriggerMethod = SNPCINT_CODE;
- iLoopBreakTriggerMethod = 0;
- vecRelativeOrigin = vec3_origin;
- bValidOnCurrentEnemy = false;
- flDelay = 5.0;
- flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST);
- flNextAttemptTime = 0;
- iszMyWeapon = NULL_STRING;
- iszTheirWeapon = NULL_STRING;
-
- for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
- {
- sPhases[i].iszSequence = NULL_STRING;
- sPhases[i].iActivity = ACT_INVALID;
- }
- }
-
- // Fill out these when passing to AddScriptedNPCInteraction
- string_t iszInteractionName;
- int iFlags;
- int iTriggerMethod;
- int iLoopBreakTriggerMethod;
- Vector vecRelativeOrigin; // (forward, right, up)
- QAngle angRelativeAngles;
- Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
- float flDelay; // Delay before interaction can be used again
- float flDistSqr; // Max distance sqr from the relative origin the NPC is allowed to be to trigger
- string_t iszMyWeapon; // Classname of the weapon I'm holding, if any
- string_t iszTheirWeapon; // Classname of the weapon my interaction partner is holding, if any
- ScriptedNPCInteraction_Phases_t sPhases[SNPCINT_NUM_PHASES];
-
- // These will be filled out for you in AddScriptedNPCInteraction
- VMatrix matDesiredLocalToWorld; // Desired relative position / angles of the other NPC
- bool bValidOnCurrentEnemy;
-
- float flNextAttemptTime;
-
- DECLARE_SIMPLE_DATADESC();
-};
-
-//=============================================================================
-//
-// Utility functions
-//
-//=============================================================================
-
-Vector VecCheckToss ( CBaseEntity *pEdict, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
-Vector VecCheckToss ( CBaseEntity *pEntity, ITraceFilter *pFilter, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
-Vector VecCheckThrow( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0f, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
-
-extern Vector g_vecAttackDir;
-
-bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget );
-bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize = 0.0 );
-
-// FIXME: move to utils?
-float DeltaV( float v0, float v1, float d );
-float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVelocity, float flCurVelocity, float flIdealVelocity, float flAccelRate, float &flNewDistance, float &flNewVelocity );
-
-//=============================================================================
-//
-// class CAI_Manager
-//
-// Central location for components of the AI to operate across all AIs without
-// iterating over the global list of entities.
-//
-//=============================================================================
-
-class CAI_Manager
-{
-public:
- CAI_Manager();
-
- CAI_BaseNPC ** AccessAIs();
- int NumAIs();
-
- void AddAI( CAI_BaseNPC *pAI );
- void RemoveAI( CAI_BaseNPC *pAI );
-
- bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); }
-
-private:
- enum
- {
- MAX_AIS = 256
- };
-
- typedef CUtlVector<CAI_BaseNPC *> CAIArray;
-
- CAIArray m_AIs;
-
-};
-
-//-------------------------------------
-
-extern CAI_Manager g_AI_Manager;
-
-//=============================================================================
-//
-// class CAI_BaseNPC
-//
-//=============================================================================
-
-class CAI_BaseNPC : public CBaseCombatCharacter,
- public CAI_DefMovementSink
-{
- DECLARE_CLASS( CAI_BaseNPC, CBaseCombatCharacter );
-
-public:
- //-----------------------------------------------------
- //
- // Initialization, cleanup, serialization, identity
- //
-
- CAI_BaseNPC();
- ~CAI_BaseNPC();
-
- //---------------------------------
-
- DECLARE_DATADESC();
- DECLARE_SERVERCLASS();
-
- virtual int Save( ISave &save );
- virtual int Restore( IRestore &restore );
- virtual void OnRestore();
- void SaveConditions( ISave &save, const CAI_ScheduleBits &conditions );
- void RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions );
-
- bool ShouldSavePhysics() { return false; }
- virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
-
- virtual bool KeyValue( const char *szKeyName, const char *szValue );
-
- //---------------------------------
-
- virtual void PostConstructor( const char *szClassname );
- virtual void Activate( void );
- virtual void Precache( void ); // derived calls at start of Spawn()
- virtual bool CreateVPhysics();
- virtual void NPCInit( void ); // derived calls after Spawn()
- void NPCInitThink( void );
- virtual void PostNPCInit() {};// called after NPC_InitThink
- virtual void StartNPC( void );
- virtual bool IsTemplate( void );
-
- virtual void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
- virtual void UpdateOnRemove( void );
-
- virtual int UpdateTransmitState();
-
- //---------------------------------
- // Component creation factories
- //
-
- // The master call, override if you introduce new component types. Call base first
- virtual bool CreateComponents();
-
- // Components defined by the base AI class
- virtual CAI_Senses * CreateSenses();
- virtual CAI_MoveProbe * CreateMoveProbe();
- virtual CAI_Motor * CreateMotor();
- virtual CAI_LocalNavigator *CreateLocalNavigator();
- virtual CAI_Navigator * CreateNavigator();
- virtual CAI_Pathfinder *CreatePathfinder();
- virtual CAI_TacticalServices *CreateTacticalServices();
-
- //---------------------------------
-
- virtual bool IsNPC( void ) const { return true; }
-
- //---------------------------------
-
- void TestPlayerPushing( CBaseEntity *pPlayer );
- void CascadePlayerPush( const Vector &push, const Vector &pushOrigin );
- void NotifyPushMove();
-
-public:
- //-----------------------------------------------------
- //
- // AI processing - thinking, schedule selection and task running
- //
- //-----------------------------------------------------
- void CallNPCThink( void );
-
- // Thinking, including core thinking, movement, animation
- virtual void NPCThink( void );
-
- // Core thinking (schedules & tasks)
- virtual void RunAI( void );// core ai function!
-
- // Called to gather up all relevant conditons
- virtual void GatherConditions( void );
-
- // Called immediately prior to schedule processing
- virtual void PrescheduleThink( void );
-
- // Called immediately after schedule processing
- virtual void PostscheduleThink( void ) { return; };
-
- // Notification that the current schedule, if any, is ending and a new one is being selected
- virtual void OnScheduleChange( void );
-
- // Notification that a new schedule is about to run its first task
- virtual void OnStartSchedule( int scheduleType ) {};
-
- // This function implements a decision tree for the NPC. It is responsible for choosing the next behavior (schedule)
- // based on the current conditions and state.
- virtual int SelectSchedule( void );
- virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
-
- // After the schedule has been selected, it will be processed by this function so child NPC classes can
- // remap base schedules into child-specific behaviors
- virtual int TranslateSchedule( int scheduleType );
-
- virtual void StartTask( const Task_t *pTask );
- virtual void RunTask( const Task_t *pTask );
-
- void ClearTransientConditions();
-
- virtual void HandleAnimEvent( animevent_t *pEvent );
-
- virtual bool IsInterruptable();
- virtual void OnStartScene( void ) {} // Called when an NPC begins a cine scene (useful for clean-up)
- virtual bool ShouldPlayerAvoid( void );
- virtual void SetPlayerAvoidState( void );
- virtual void PlayerPenetratingVPhysics( void );
-
- virtual bool ShouldAlwaysThink();
- void ForceGatherConditions() { m_bForceConditionsGather = true; SetEfficiency( AIE_NORMAL ); } // Force an NPC out of PVS to call GatherConditions on next think
-
- virtual float LineOfSightDist( const Vector &vecDir = vec3_invalid, float zEye = FLT_MAX );
-
- virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
- virtual const char *GetTracerType( void );
- virtual void DoImpactEffect( trace_t &tr, int nDamageType );
-
- enum
- {
- NEXT_SCHEDULE = LAST_SHARED_SCHEDULE,
- NEXT_TASK = LAST_SHARED_TASK,
- NEXT_CONDITION = LAST_SHARED_CONDITION,
- };
-
-protected:
- // Used by derived classes to chain a task to a task that might not be the
- // one they are currently handling:
- void ChainStartTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; StartTask( (const Task_t *)&tempTask ); }
- void ChainRunTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; RunTask( (const Task_t *) &tempTask ); }
-
- void StartTaskOverlay();
- void RunTaskOverlay();
- void EndTaskOverlay();
-
- virtual void PostRunStopMoving();
-
- bool CheckPVSCondition();
-
-private:
- bool CanThinkRebalance();
- void RebalanceThinks();
-
- bool PreNPCThink();
- void PostNPCThink();
-
- bool PreThink( void );
- void PerformSensing();
- void CheckOnGround( void );
- void MaintainSchedule( void );
- void RunAnimation( void );
- void PostRun( void );
- void PerformMovement();
- void PostMovement();
-
- 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
- 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
-
-public:
- //-----------------------------------------------------
- //
- // Schedules & tasks
- //
- //-----------------------------------------------------
-
- void SetSchedule( CAI_Schedule *pNewSchedule );
- bool SetSchedule( int localScheduleID );
-
- void SetDefaultFailSchedule( int failSchedule ) { m_failSchedule = failSchedule; }
-
- void ClearSchedule( const char *szReason );
-
- CAI_Schedule * GetCurSchedule() { return m_pSchedule; }
- bool IsCurSchedule( int schedId, bool fIdeal = true );
- virtual CAI_Schedule *GetSchedule(int localScheduleID);
- virtual int GetLocalScheduleId( int globalScheduleID ) { return AI_IdIsLocal( globalScheduleID ) ? globalScheduleID : GetClassScheduleIdSpace()->ScheduleGlobalToLocal( globalScheduleID ); }
- virtual int GetGlobalScheduleId( int localScheduleID ) { return AI_IdIsGlobal( localScheduleID ) ? localScheduleID : GetClassScheduleIdSpace()->ScheduleLocalToGlobal( localScheduleID ); }
-
- float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; }
-
- //---------------------------------
-
- const Task_t* GetTask( void );
- int TaskIsRunning( void );
-
- virtual void TaskFail( AI_TaskFailureCode_t );
- void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); }
- void TaskComplete( bool fIgnoreSetFailedCondition = false );
-
- void TaskInterrupt() { m_ScheduleState.iTaskInterrupt++; }
- void ClearTaskInterrupt() { m_ScheduleState.iTaskInterrupt = 0; }
- int GetTaskInterrupt() const { return m_ScheduleState.iTaskInterrupt; }
-
- void TaskMovementComplete( void );
- inline int TaskIsComplete( void ) { return (GetTaskStatus() == TASKSTATUS_COMPLETE); }
-
- virtual const char *TaskName(int taskID);
-
- float GetTimeTaskStarted() const { return m_ScheduleState.timeCurTaskStarted; }
- virtual int GetLocalTaskId( int globalTaskId) { return GetClassScheduleIdSpace()->TaskGlobalToLocal( globalTaskId ); }
-
- virtual const char *GetSchedulingErrorName() { return "CAI_BaseNPC"; }
-
-protected:
- static bool LoadSchedules(void);
- virtual bool LoadedSchedules(void);
- virtual void BuildScheduleTestBits( void );
-
- //---------------------------------
-
- // This is the main call to select/translate a schedule
- virtual CAI_Schedule *GetNewSchedule( void );
- virtual CAI_Schedule *GetFailSchedule( void );
-
- //---------------------------------
-
- virtual bool CanFlinch( void );
- virtual void CheckFlinches( void );
- virtual void PlayFlinchGesture( void );
- int SelectFlinchSchedule( void );
-
- virtual bool IsAllowedToDodge( void );
-
- bool IsInChoreo() const;
-
-private:
- // This function maps the type through TranslateSchedule() and then retrieves the pointer
- // to the actual CAI_Schedule from the database of schedules available to this class.
- CAI_Schedule * GetScheduleOfType( int scheduleType );
-
- bool FHaveSchedule( void );
- bool FScheduleDone ( void );
- CAI_Schedule * ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount );
-
- int GetScheduleCurTaskIndex() const { return m_ScheduleState.iCurTask; }
- inline int IncScheduleCurTaskIndex();
- inline void ResetScheduleCurTaskIndex();
- void NextScheduledTask ( void );
- bool IsScheduleValid ( void );
- bool ShouldSelectIdealState( void );
-
- // Selecting the ideal state
- NPC_STATE SelectIdleIdealState();
- NPC_STATE SelectAlertIdealState();
- NPC_STATE SelectScriptIdealState();
-
- // Various schedule selections based on NPC_STATE
- int SelectIdleSchedule();
- int SelectAlertSchedule();
- int SelectCombatSchedule();
- virtual int SelectDeadSchedule();
- int SelectScriptSchedule();
- int SelectInteractionSchedule();
-
- void OnStartTask( void ) { SetTaskStatus( TASKSTATUS_RUN_MOVE_AND_TASK ); }
- void SetTaskStatus( TaskStatus_e status ) { m_ScheduleState.fTaskStatus = status; }
- TaskStatus_e GetTaskStatus() const { return m_ScheduleState.fTaskStatus; }
-
- void DiscardScheduleState();
-
- //---------------------------------
-
- CAI_Schedule * m_pSchedule;
- int m_IdealSchedule;
- AIScheduleState_t m_ScheduleState;
- int m_failSchedule; // Schedule type to choose if current schedule fails
- bool m_bDoPostRestoreRefindPath;
-
- bool m_bUsingStandardThinkTime;
- float m_flLastRealThinkTime;
- int m_iFrameBlocked;
- bool m_bInChoreo;
-
- static int gm_iNextThinkRebalanceTick;
- static float gm_flTimeLastSpawn;
- static int gm_nSpawnedThisFrame;
-
-protected: // pose parameters
- int m_poseAim_Pitch;
- int m_poseAim_Yaw;
- int m_poseMove_Yaw;
- virtual void PopulatePoseParameters( void );
-
-public:
- inline bool HasPoseMoveYaw() { return ( m_poseMove_Yaw >= 0 ); }
-
- // Return the stored pose parameter for "move_yaw"
- inline int LookupPoseMoveYaw() { return m_poseMove_Yaw; }
-
-
- //-----------------------------------------------------
- //
- // Hooks for CAI_Behaviors, *if* derived class supports them
- //
- //-----------------------------------------------------
- template <class BEHAVIOR_TYPE>
- bool GetBehavior( BEHAVIOR_TYPE **ppBehavior )
- {
- CAI_BehaviorBase **ppBehaviors = AccessBehaviors();
-
- *ppBehavior = NULL;
- for ( int i = 0; i < NumBehaviors(); i++ )
- {
- *ppBehavior = dynamic_cast<BEHAVIOR_TYPE *>(ppBehaviors[i]);
- if ( *ppBehavior )
- return true;
- }
- return false;
- }
-
- virtual CAI_BehaviorBase *GetRunningBehavior() { return NULL; }
-
- virtual bool ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) { return true; }
- virtual void OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) {}
-
- // Notification that the status behavior ability to select schedules has changed.
- // Return "true" to signal a schedule interrupt is desired
- virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ) { return false; }
-
-private:
- virtual CAI_BehaviorBase ** AccessBehaviors() { return NULL; }
- virtual int NumBehaviors() { return 0; }
-
-public:
- //-----------------------------------------------------
- //
- // Conditions
- //
- //-----------------------------------------------------
-
- virtual const char* ConditionName(int conditionID);
-
- virtual void RemoveIgnoredConditions ( void );
- void SetCondition( int iCondition /*, bool state = true*/ );
- bool HasCondition( int iCondition );
- bool HasCondition( int iCondition, bool bUseIgnoreConditions );
- bool HasInterruptCondition( int iCondition );
- bool HasConditionsToInterruptSchedule( int nLocalScheduleID );
-
- void ClearCondition( int iCondition );
- void ClearConditions( int *pConditions, int nConditions );
- void SetIgnoreConditions( int *pConditions, int nConditions );
- void ClearIgnoreConditions( int *pConditions, int nConditions );
- bool ConditionInterruptsCurSchedule( int iCondition );
- bool ConditionInterruptsSchedule( int schedule, int iCondition );
-
- void SetCustomInterruptCondition( int nCondition );
- bool IsCustomInterruptConditionSet( int nCondition );
- void ClearCustomInterruptCondition( int nCondition );
- void ClearCustomInterruptConditions( void );
-
- bool ConditionsGathered() const { return m_bConditionsGathered; }
- const CAI_ScheduleBits &AccessConditionBits() const { return m_Conditions; }
- CAI_ScheduleBits & AccessConditionBits() { return m_Conditions; }
-
- bool DidChooseEnemy() const { return !m_bSkippedChooseEnemy; }
-
-private:
- CAI_ScheduleBits m_Conditions;
- CAI_ScheduleBits m_CustomInterruptConditions; //Bit string assembled by the schedule running, then
- //modified by leaf classes to suit their needs
- CAI_ScheduleBits m_ConditionsPreIgnore;
- CAI_ScheduleBits m_InverseIgnoreConditions;
-
- bool m_bForceConditionsGather;
- bool m_bConditionsGathered;
- bool m_bSkippedChooseEnemy;
-
-public:
- //-----------------------------------------------------
- //
- // NPC State
- //
- //-----------------------------------------------------
- inline void SetIdealState( NPC_STATE eIdealState );
- inline NPC_STATE GetIdealState();
- virtual NPC_STATE SelectIdealState( void );
-
- void SetState( NPC_STATE State );
- virtual bool ShouldGoToIdleState( void ) { return ( false ); }
- virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) {/*Base class doesn't care*/};
-
- NPC_STATE GetState( void ) { return m_NPCState; }
-
- AI_Efficiency_t GetEfficiency() const { return m_Efficiency; }
- void SetEfficiency( AI_Efficiency_t efficiency ) { m_Efficiency = efficiency; }
- AI_MoveEfficiency_t GetMoveEfficiency() const { return m_MoveEfficiency; }
- void SetMoveEfficiency( AI_MoveEfficiency_t efficiency ) { m_MoveEfficiency = efficiency; }
- virtual void UpdateEfficiency( bool bInPVS );
- void ForceDecisionThink() { m_flNextDecisionTime = 0; SetEfficiency( AIE_NORMAL ); }
-
- bool IsFlaggedEfficient() const { return HasSpawnFlags( SF_NPC_START_EFFICIENT ); }
-
- AI_SleepState_t GetSleepState() const { return m_SleepState; }
- void SetSleepState( AI_SleepState_t sleepState ) { m_SleepState = sleepState; }
- void AddSleepFlags( int flags ) { m_SleepFlags |= flags; }
- void RemoveSleepFlags( int flags ) { m_SleepFlags &= ~flags; }
- bool HasSleepFlags( int flags ) { return (m_SleepFlags & flags) == flags; }
-
- void UpdateSleepState( bool bInPVS );
- virtual void Wake( bool bFireOutput = true );
- void Sleep();
- bool WokeThisTick() const;
-
- //---------------------------------
-
- NPC_STATE m_NPCState; // npc's current state
- float m_flLastStateChangeTime;
-
-private:
- NPC_STATE m_IdealNPCState; // npc should change to this state
- AI_Efficiency_t m_Efficiency;
- AI_MoveEfficiency_t m_MoveEfficiency;
- float m_flNextDecisionTime;
-
- AI_SleepState_t m_SleepState;
- int m_SleepFlags;
- float m_flWakeRadius;
- bool m_bWakeSquad;
- int m_nWakeTick;
-
-public:
- //-----------------------------------------------------
- //
- // Activities
- //
- //-----------------------------------------------------
-
- Activity TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity = NULL );
- Activity NPC_TranslateActivity( Activity eNewActivity );
- Activity GetActivity( void ) { return m_Activity; }
- virtual void SetActivity( Activity NewActivity );
- Activity GetIdealActivity( void ) { return m_IdealActivity; }
- void SetIdealActivity( Activity NewActivity );
- void ResetIdealActivity( Activity newIdealActivity );
- void SetSequenceByName( const char *szSequence );
- void SetSequenceById( int iSequence );
- Activity GetScriptCustomMoveActivity( void );
- int GetScriptCustomMoveSequence( void );
- Activity GetStoppedActivity( void );
- inline bool HaveSequenceForActivity( Activity activity );
- inline bool IsActivityStarted(void);
- virtual bool IsActivityFinished( void );
- virtual bool IsActivityMovementPhased( Activity activity );
- virtual void OnChangeActivity( Activity eNewActivity );
- void MaintainActivity(void);
- void ResetActivity(void) { m_Activity = ACT_RESET; }
-
- void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity);
-
-private:
-
- void AdvanceToIdealActivity(void);
- void ResolveActivityToSequence(Activity NewActivity, int &iSequence, Activity &translatedActivity, Activity &weaponActivity);
-
- Activity m_Activity; // Current animation state
- Activity m_translatedActivity; // Current actual translated animation
-
- Activity m_IdealActivity; // Desired animation state
- int m_nIdealSequence; // Desired animation sequence
- Activity m_IdealTranslatedActivity; // Desired actual translated animation state
- Activity m_IdealWeaponActivity; // Desired weapon animation state
-
- CNetworkVar(int, m_iDeathPose );
- CNetworkVar(int, m_iDeathFrame );
-
-public:
- //-----------------------------------------------------
- //
- // Senses
- //
- //-----------------------------------------------------
-
- CAI_Senses * GetSenses() { return m_pSenses; }
- const CAI_Senses * GetSenses() const { return m_pSenses; }
-
- void SetDistLook( float flDistLook );
-
- virtual bool QueryHearSound( CSound *pSound );
- virtual bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );
-
- virtual void OnLooked( int iDistance );
- virtual void OnListened();
-
- virtual void OnSeeEntity( CBaseEntity *pEntity ) {}
-
- // If true, AI will try to see this entity regardless of distance.
- virtual bool ShouldNotDistanceCull() { return false; }
-
- virtual int GetSoundInterests( void );
- virtual int GetSoundPriority( CSound *pSound );
-
- CSound * GetLoudestSoundOfType( int iType );
- virtual CSound * GetBestSound( int validTypes = ALL_SOUNDS );
- virtual CSound * GetBestScent( void );
- virtual float HearingSensitivity( void ) { return 1.0; }
- virtual bool ShouldIgnoreSound( CSound * ) { return false; }
- bool SoundIsVisible( CSound *pSound );
-
-protected:
- virtual void ClearSenseConditions( void );
-
-private:
- void LockBestSound();
- void UnlockBestSound();
-
- CAI_Senses * m_pSenses;
- CSound * m_pLockedBestSound;
-
-public:
- //-----------------------------------------------------
- //
- // Enemy and target
- //
- //-----------------------------------------------------
-
- Vector GetSmoothedVelocity( void );
-
- CBaseEntity* GetEnemy() { return m_hEnemy.Get(); }
- CBaseEntity* GetEnemy() const { return m_hEnemy.Get(); }
- float GetTimeEnemyAcquired() { return m_flTimeEnemyAcquired; }
- void SetEnemy( CBaseEntity *pEnemy, bool bSetCondNewEnemy = true );
-
- const Vector & GetEnemyLKP() const;
- float GetEnemyLastTimeSeen() const;
- void MarkEnemyAsEluded();
- void ClearEnemyMemory();
- bool EnemyHasEludedMe() const;
-
- virtual CBaseEntity *BestEnemy(); // returns best enemy in memory list
- virtual bool IsValidEnemy( CBaseEntity *pEnemy );
- virtual bool CanBeAnEnemyOf( CBaseEntity *pEnemy );
-
- void ForceChooseNewEnemy() { m_EnemiesSerialNumber = -1; }
-
- bool ChooseEnemy();
- virtual bool ShouldChooseNewEnemy();
- virtual void GatherEnemyConditions( CBaseEntity *pEnemy );
- virtual float EnemyDistTolerance() { return 0; } // Enemy distances within this tolerance of each other are considered equivalent.
-
- float EnemyDistance( CBaseEntity *pEnemy );
- CBaseCombatCharacter *GetEnemyCombatCharacterPointer();
- void SetEnemyOccluder(CBaseEntity *pBlocker);
- CBaseEntity *GetEnemyOccluder(void);
-
- virtual void StartTargetHandling( CBaseEntity *pTargetEnt );
-
- //---------------------------------
-
- CBaseEntity* GetTarget() { return m_hTargetEnt.Get(); }
- void SetTarget( CBaseEntity *pTarget );
- void CheckTarget( CBaseEntity *pTarget );
- float GetAcceptableTimeSeenEnemy( void ) { return m_flAcceptableTimeSeenEnemy; }
- virtual CAI_BaseNPC *CreateCustomTarget( const Vector &vecOrigin, float duration = -1 );
-
- void SetDeathPose( const int &iDeathPose ) { m_iDeathPose = iDeathPose; }
- void SetDeathPoseFrame( const int &iDeathPoseFrame ) { m_iDeathFrame = iDeathPoseFrame; }
-
- void SelectDeathPose( const CTakeDamageInfo &info );
- virtual bool ShouldPickADeathPose( void ) { return true; }
-
- virtual bool AllowedToIgnite( void ) { return false; }
-
-protected:
- virtual float GetGoalRepathTolerance( CBaseEntity *pGoalEnt, GoalType_t type, const Vector &curGoal, const Vector &curTargetPos );
-
-private:
- void * CheckEnemy( CBaseEntity *pEnemy ) { return NULL; } // OBSOLETE, replaced by GatherEnemyConditions(), left here to make derived code not compile
-
- // Updates the goal position in case of GOALTYPE_ENEMY
- void UpdateEnemyPos();
-
- // Updates the goal position in case of GOALTYPE_TARGETENT
- void UpdateTargetPos();
-
- //---------------------------------
-
- EHANDLE m_hEnemy; // the entity that the npc is fighting.
- float m_flTimeEnemyAcquired; // The time at which the entity the NPC is fighting became the NPC's enemy.
- EHANDLE m_hTargetEnt; // the entity that the npc is trying to reach
-
- CRandStopwatch m_GiveUpOnDeadEnemyTimer;
- CSimpleSimTimer m_FailChooseEnemyTimer;
- int m_EnemiesSerialNumber;
-
- float m_flAcceptableTimeSeenEnemy;
-
- CSimpleSimTimer m_UpdateEnemyPosTimer;
- static CSimpleSimTimer m_AnyUpdateEnemyPosTimer;
-
-public:
- //-----------------------------------------------------
- //
- // Commander mode stuff.
- //
- //-----------------------------------------------------
- virtual bool IsCommandable() { return false; }
- virtual bool IsPlayerAlly( CBasePlayer *pPlayer = NULL );
- virtual bool IsMedic() { return false; }
- virtual bool IsCommandMoving() { return false; }
- virtual bool ShouldAutoSummon() { return false; }
- virtual void SetCommandGoal( const Vector &vecGoal );
- virtual void ClearCommandGoal();
- virtual void OnTargetOrder() {}
- virtual void OnMoveOrder() {}
- virtual bool IsValidCommandTarget( CBaseEntity *pTarget ) { return false; }
- const Vector &GetCommandGoal() const { return m_vecCommandGoal; }
- virtual void OnMoveToCommandGoalFailed() {}
- string_t GetPlayerSquadName() const { Assert( gm_iszPlayerSquad != NULL_STRING ); return gm_iszPlayerSquad; }
- bool IsInPlayerSquad() const;
- virtual CAI_BaseNPC *GetSquadCommandRepresentative() { return NULL; }
-
- virtual bool TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ) { OnTargetOrder(); return true; }
- virtual void MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ) { SetCommandGoal( vecDest ); SetCondition( COND_RECEIVED_ORDERS ); OnMoveOrder(); }
-
- // Return true if you're willing to be idly talked to by other friends.
- virtual bool CanBeUsedAsAFriend( void );
-
-
-private:
- Vector m_vecCommandGoal;
- static string_t gm_iszPlayerSquad;
-
-public:
- CAI_MoveMonitor m_CommandMoveMonitor;
-
- //-----------------------------------------------------
- // Dynamic scripted NPC interactions
- //-----------------------------------------------------
-public:
- float GetInteractionYaw( void ) const { return m_flInteractionYaw; }
-
-protected:
- void ParseScriptedNPCInteractions( void );
- void AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction );
- const char *GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase );
- void StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive );
- void StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles );
- void CheckForScriptedNPCInteractions( void );
- void CalculateValidEnemyInteractions( void );
- void CheckForcedNPCInteractions( void );
- bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
- virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
- bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
- bool IsActiveDynamicInteraction( void ) { return (m_iInteractionState == NPCINT_RUNNING_ACTIVE && (m_hCine != NULL)); }
- ScriptedNPCInteraction_t *GetRunningDynamicInteraction( void ) { return &(m_ScriptedInteractions[m_iInteractionPlaying]); }
- void SetInteractionCantDie( bool bCantDie ) { m_bCannotDieDuringInteraction = bCantDie; }
- bool HasInteractionCantDie( void );
-
- void InputForceInteractionWithNPC( inputdata_t &inputdata );
- void StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction );
- void CleanupForcedInteraction( void );
- void CalculateForcedInteractionPosition( void );
- CAI_BaseNPC *GetInteractionPartner( void );
-
-private:
- // Forced interactions
- CHandle<CAI_BaseNPC> m_hForcedInteractionPartner;
- Vector m_vecForcedWorldPosition;
- float m_flForcedInteractionTimeout; // Abort the interaction if it hasn't started by this time.
-
- CHandle<CAI_BaseNPC> m_hInteractionPartner;
- EHANDLE m_hLastInteractionTestTarget;
- bool m_bCannotDieDuringInteraction;
- int m_iInteractionState;
- int m_iInteractionPlaying;
- CUtlVector<ScriptedNPCInteraction_t> m_ScriptedInteractions;
-
- float m_flInteractionYaw;
-
-
-public:
- //-----------------------------------------------------
- //
- // Sounds
- //
- //-----------------------------------------------------
- virtual CanPlaySequence_t CanPlaySequence( bool fDisregardState, int interruptLevel );
-
- virtual bool CanPlaySentence( bool fDisregardState ) { return IsAlive(); }
- virtual int PlaySentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener = NULL );
- virtual int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener );
-
- virtual bool FOkToMakeSound( int soundPriority = 0 );
- virtual void JustMadeSound( int soundPriority = 0, float flSoundLength = 0.0f );
-
- virtual void DeathSound( const CTakeDamageInfo &info ) { return; };
- virtual void AlertSound( void ) { return; };
- virtual void IdleSound( void ) { return; };
- virtual void PainSound( const CTakeDamageInfo &info ) { return; };
- virtual void FearSound( void ) { return; };
- virtual void LostEnemySound( void ) { return; };
- virtual void FoundEnemySound( void ) { return; };
- virtual void BarnacleDeathSound( void ) { CTakeDamageInfo info; PainSound( info ); }
-
- virtual void SpeakSentence( int sentenceType ) { return; };
- virtual bool ShouldPlayIdleSound( void );
-
- virtual void MakeAIFootstepSound( float volume, float duration = 0.5f );
-
- //---------------------------------
-
- virtual CAI_Expresser *GetExpresser() { return NULL; }
- const CAI_Expresser *GetExpresser() const { return const_cast<CAI_BaseNPC *>(this)->GetExpresser(); }
-
- //---------------------------------
- // NPC Event Response System
- virtual bool CanRespondToEvent( const char *ResponseConcept ) { return false; }
- virtual bool RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene ) { return false; }
-
- virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
-
- virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
-
-protected:
- float SoundWaitTime() const { return m_flSoundWaitTime; }
-
-public:
- //-----------------------------------------------------
- //
- // Capabilities report (from CBaseCombatCharacter)
- //
- //-----------------------------------------------------
- virtual int CapabilitiesGet( void ) const;
-
- // local capabilities access
- int CapabilitiesAdd( int capabilities );
- int CapabilitiesRemove( int capabilities );
- void CapabilitiesClear( void );
-
-private:
- int m_afCapability; // tells us what a npc can/can't do.
-
-public:
- //-----------------------------------------------------
- //
- // Pathfinding, navigation & movement
- //
- //-----------------------------------------------------
-
- CAI_Navigator * GetNavigator() { return m_pNavigator; }
- const CAI_Navigator *GetNavigator() const { return m_pNavigator; }
-
- CAI_LocalNavigator *GetLocalNavigator() { return m_pLocalNavigator; }
- const CAI_LocalNavigator *GetLocalNavigator() const { return m_pLocalNavigator; }
-
- CAI_Pathfinder * GetPathfinder() { return m_pPathfinder; }
- const CAI_Pathfinder *GetPathfinder() const { return m_pPathfinder; }
-
- CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; }
- const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; }
-
- CAI_Motor * GetMotor() { return m_pMotor; }
- const CAI_Motor * GetMotor() const { return m_pMotor; }
-
- //---------------------------------
-
- static bool FindSpotForNPCInRadius( Vector *pResult, const Vector &vStartPos, CAI_BaseNPC *pNPC, float radius, bool bOutOfPlayerViewcone = false );
-
- //---------------------------------
-
- virtual bool IsNavigationUrgent();
- virtual bool ShouldFailNav( bool bMovementFailed );
- virtual bool ShouldBruteForceFailedNav() { return false; }
-
- // The current navigation (movement) mode (e.g. fly, swim, locomote, etc)
- Navigation_t GetNavType() const;
- void SetNavType( Navigation_t navType );
-
- CBaseEntity * GetNavTargetEntity(void);
-
- bool IsMoving( void );
- virtual float GetTimeToNavGoal();
-
- // NPCs can override this to tweak with how costly particular movements are
- virtual bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
-
- // Turns a directional vector into a yaw value that points down that vector.
- float VecToYaw( const Vector &vecDir );
-
- // Turning
- virtual float CalcIdealYaw( const Vector &vecTarget );
- virtual float MaxYawSpeed( void ); // Get max yaw speed
- bool FacingIdeal( void );
- void SetUpdatedYaw() { m_ScheduleState.bTaskUpdatedYaw = true; }
-
- // Add multiple facing goals while moving/standing still.
- virtual void AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 );
- virtual void AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
- virtual void AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
- virtual float GetFacingDirection( Vector &vecDir );
-
- // ------------
- // Methods used by motor to query properties/preferences/move-related state
- // ------------
- virtual bool CanStandOn( CBaseEntity *pSurface ) const;
-
- virtual bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; // Override for specific creature types
- bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const;
- bool ShouldMoveWait();
- virtual float StepHeight() const { return 18.0f; }
- float GetStepDownMultiplier() const;
- virtual float GetMaxJumpSpeed() const { return 350.0f; }
- virtual float GetJumpGravity() const { return 1.0f; }
-
- //---------------------------------
-
- virtual bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so)
- virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval );
-
- //---------------------------------
-
- virtual bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior
- virtual bool ValidateNavGoal();
- virtual bool IsCurTaskContinuousMove();
- virtual bool IsValidMoveAwayDest( const Vector &vecDest ) { return true; }
-
- //---------------------------------
- //
- // Notifications from navigator
- //
- virtual void OnMovementFailed() {};
- virtual void OnMovementComplete() {};
-
- //---------------------------------
-
- bool FindNearestValidGoalPos( const Vector &vTestPoint, Vector *pResult );
-
- void RememberUnreachable( CBaseEntity* pEntity, float duration = -1 ); // Remember that entity is unreachable
- virtual bool IsUnreachable( CBaseEntity* pEntity ); // Is entity is unreachable?
-
- //---------------------------------
- // Inherited from IAI_MotorMovementServices
- virtual float CalcYawSpeed( void );
-
- virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal,
- float distClear,
- AIMoveResult_t *pResult );
-
- virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal,
- float distClear,
- AIMoveResult_t *pResult );
-
- // Translations of the above into some useful game terms
- virtual bool OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal,
- CBaseDoor *pDoor,
- float distClear,
- AIMoveResult_t *pResult );
-
- virtual bool OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
- CBasePropDoor *pDoor,
- float distClear,
- AIMoveResult_t *pResult );
-
- void OpenPropDoorBegin( CBasePropDoor *pDoor );
- void OpenPropDoorNow( CBasePropDoor *pDoor );
-
- //---------------------------------
-
- void DelayMoveStart( float delay ) { m_flMoveWaitFinished = gpGlobals->curtime + delay; }
-
- float m_flMoveWaitFinished;
-
-
- //
- // Stuff for opening doors.
- //
- void OnDoorFullyOpen(CBasePropDoor *pDoor);
- void OnDoorBlocked(CBasePropDoor *pDoor);
- CHandle<CBasePropDoor> m_hOpeningDoor; // The CBasePropDoor that we are in the midst of opening for navigation.
-
-protected:
- // BRJ 4/11
- // Semi-obsolete-looking Lars code I moved out of the engine and into here
- int FlyMove( const Vector& vecPosition, unsigned int mask );
- int WalkMove( const Vector& vecPosition, unsigned int mask );
-
- // Unreachable Entities
- CUtlVector<UnreachableEnt_t> m_UnreachableEnts; // Array of unreachable entities
-
-private:
- CAI_Navigator * m_pNavigator;
- CAI_LocalNavigator *m_pLocalNavigator;
- CAI_Pathfinder * m_pPathfinder;
- CAI_MoveProbe * m_pMoveProbe;
- CAI_Motor * m_pMotor;
-
- EHANDLE m_hGoalEnt; // path corner we are heading towards
-
- float m_flTimeLastMovement;
-
-
- CSimpleSimTimer m_CheckOnGroundTimer;
-
-public:
- //-----------------------------------------------------
- //
- // Eye position, view offset, head direction, eye direction
- //
- //-----------------------------------------------------
-
- void SetDefaultEyeOffset ( void );
- const Vector & GetDefaultEyeOffset( void ) { return m_vDefaultEyeOffset; }
- virtual Vector GetNodeViewOffset() { return GetViewOffset(); }
-
- virtual Vector EyeOffset( Activity nActivity );
- virtual Vector EyePosition( void );
-
- //---------------------------------
-
- virtual Vector HeadDirection2D( void );
- virtual Vector HeadDirection3D( void );
- virtual Vector EyeDirection2D( void );
- virtual Vector EyeDirection3D( void );
-
- virtual CBaseEntity *EyeLookTarget( void ); // Overridden by subclass to force look at an entity
- virtual void AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ) { };
- virtual void AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ) { };
- virtual void SetHeadDirection( const Vector &vTargetPos, float flInterval );
- virtual void MaintainLookTargets( float flInterval );
- virtual bool ValidEyeTarget(const Vector &lookTargetPos);
-
- virtual Vector FacingPosition( void ) { return EyePosition(); }; // position that other npc's use when facing you
-
- virtual void MaintainTurnActivity( void );
-
- virtual bool FInAimCone( const Vector &vecSpot );
- virtual void AimGun();
- virtual void SetAim( const Vector &aimDir );
- virtual void RelaxAim( void );
- virtual CBaseEntity *GetAlternateMoveShootTarget() { return NULL; }
-
-protected:
- Vector m_vDefaultEyeOffset;
- float m_flNextEyeLookTime; // Next time a pick a new place to look
-
- float m_flEyeIntegRate; // How fast does eye move to target
-
-private:
- Vector m_vEyeLookTarget; // Where I want to be looking
- Vector m_vCurEyeTarget; // Direction I'm looking at
- EHANDLE m_hEyeLookTarget; // What I want to be looking at
- float m_flHeadYaw; // Current head yaw
- float m_flHeadPitch; // Current head pitch
-protected:
- float m_flOriginalYaw; // This is the direction facing when the level designer placed the NPC in the level.
-
-public:
- //-----------------------------------------------------
- // Mapmaker Scripting
- //
- // Set when the NPC is being scripted by a mapmaker, and
- // shouldn't be responding to external stimuli that would
- // break him out of his "script". NOT a scripted sequence.
- //-----------------------------------------------------
- inline bool IsInAScript( void ) { return m_bInAScript; }
- inline void SetInAScript( bool bScript ) { m_bInAScript = bScript; }
- void InputStartScripting( inputdata_t &inputdata ) { m_bInAScript = true; }
- void InputStopScripting( inputdata_t &inputdata ) { m_bInAScript = false; }
-
- void InputGagEnable( inputdata_t &inputdata ) { AddSpawnFlags(SF_NPC_GAG); }
- void InputGagDisable( inputdata_t &inputdata ) { RemoveSpawnFlags(SF_NPC_GAG); }
-
- bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt);
-
- virtual void InputOutsideTransition( inputdata_t &inputdata );
- virtual void InputInsideTransition( inputdata_t &inputdata );
-
- void CleanupScriptsOnTeleport( bool bEnrouteAsWell );
-
- virtual void SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt );
-
-private:
- bool m_bInAScript;
-
-public:
- //-----------------------------------------------------
- //
- // Scripting
- //
- //-----------------------------------------------------
-
- // Scripted sequence Info
- enum SCRIPTSTATE
- {
- SCRIPT_PLAYING = 0, // Playing the action animation.
- SCRIPT_WAIT, // Waiting on everyone in the script to be ready. Plays the pre idle animation if there is one.
- SCRIPT_POST_IDLE, // Playing the post idle animation after playing the action animation.
- SCRIPT_CLEANUP, // Cancelling the script / cleaning up.
- SCRIPT_WALK_TO_MARK, // Walking to the scripted sequence position.
- SCRIPT_RUN_TO_MARK, // Running to the scripted sequence position.
- SCRIPT_CUSTOM_MOVE_TO_MARK, // Moving to the scripted sequence position while playing a custom movement animation.
- };
-
- bool ExitScriptedSequence();
- bool CineCleanup();
-
- virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
-
- // forces movement and sets a new schedule
- virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
- virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
-
- static void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun);
- static void ForceSelectedGoRandom(void);
-
- bool AutoMovement( CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL );
- bool AutoMovement( float flInterval, CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL );
- bool TaskRanAutomovement( void ) { return m_ScheduleState.bTaskRanAutomovement; }
-
- SCRIPTSTATE m_scriptState; // internal cinematic state
- CHandle<CAI_ScriptedSequence> m_hCine;
- Activity m_ScriptArrivalActivity;
- string_t m_strScriptArrivalSequence;
-
- //-----------------------------------------------------
- //
- // Scenes
- //
- //-----------------------------------------------------
-
- void AddSceneLock( float flDuration = 0.2f ) { m_flSceneTime = MAX( gpGlobals->curtime + flDuration, m_flSceneTime ); };
- void ClearSceneLock( float flDuration = 0.2f ) { m_flSceneTime = gpGlobals->curtime + flDuration; };
- bool IsInLockedScene( void ) { return m_flSceneTime > gpGlobals->curtime; };
- float m_flSceneTime;
- string_t m_iszSceneCustomMoveSeq;
-
-public:
- //-----------------------------------------------------
- //
- // Memory
- //
- //-----------------------------------------------------
-
- inline void Remember( int iMemory ) { m_afMemory |= iMemory; }
- inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; }
- inline bool HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; }
- inline bool HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; }
-
- virtual CAI_Enemies *GetEnemies( void );
- virtual void RemoveMemory( void );
-
- virtual bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL );
- virtual float GetReactionDelay( CBaseEntity *pEnemy );
-
- void SetLastAttackTime( float time) { m_flLastAttackTime = time; }
-
- float GetLastAttackTime() const { return m_flLastAttackTime; }
- float GetLastDamageTime() const { return m_flLastDamageTime; }
- float GetLastPlayerDamageTime() const { return m_flLastPlayerDamageTime; }
- float GetLastEnemyTime() const { return m_flLastEnemyTime; }
-
- // Set up the shot regulator based on the equipped weapon
- virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
-
- // Weapon holstering
- virtual bool CanHolsterWeapon( void );
- virtual int HolsterWeapon( void );
- virtual int UnholsterWeapon( void );
- void InputHolsterWeapon( inputdata_t &inputdata );
- void InputHolsterAndDestroyWeapon( inputdata_t &inputdata );
- void InputUnholsterWeapon( inputdata_t &inputdata );
- bool IsWeaponHolstered( void );
- bool IsWeaponStateChanging( void );
- void SetDesiredWeaponState( DesiredWeaponState_t iState ) { m_iDesiredWeaponState = iState; }
-
- // NOTE: The Shot Regulator is used to manage the RangeAttack1 weapon.
- inline CAI_ShotRegulator* GetShotRegulator() { return &m_ShotRegulator; }
- virtual void OnRangeAttack1();
-
-protected:
- // Shot regulator code
- virtual void OnUpdateShotRegulator( );
-
-protected:
- CAI_Enemies * m_pEnemies; // Holds information about enemies / danger positions / shared between sqaud members
- int m_afMemory;
- EHANDLE m_hEnemyOccluder; // The entity my enemy is hiding behind.
-
- float m_flSumDamage; // How much consecutive damage I've received
- float m_flLastDamageTime; // Last time I received damage
- float m_flLastPlayerDamageTime; // Last time I received damage from the player
- float m_flLastSawPlayerTime; // Last time I saw the player
- float m_flLastAttackTime; // Last time that I attacked my current enemy
- float m_flLastEnemyTime;
- float m_flNextWeaponSearchTime; // next time to search for a better weapon
- string_t m_iszPendingWeapon; // THe NPC should create and equip this weapon.
- bool m_bIgnoreUnseenEnemies;
-
-private:
- CAI_ShotRegulator m_ShotRegulator; // When should I shoot next?
-
- DesiredWeaponState_t m_iDesiredWeaponState;
-
-public:
- //-----------------------------------------------------
- //
- // Squads & tactics
- //
- //-----------------------------------------------------
-
- virtual bool InitSquad( void );
-
- virtual const char* SquadSlotName(int slotID) { return gm_SquadSlotNamespace.IdToSymbol(slotID); }
- bool OccupyStrategySlot( int squadSlotID );
- bool OccupyStrategySlotRange( int slotIDStart, int slotIDEnd );
- bool HasStrategySlot( int squadSlotID );
- bool HasStrategySlotRange( int slotIDStart, int slotIDEnd );
- int GetMyStrategySlot() { return m_iMySquadSlot; }
- void VacateStrategySlot( void );
- bool IsStrategySlotRangeOccupied( int slotIDStart, int slotIDEnd ); // Returns true if all in the range are occupied
-
- CAI_Squad * GetSquad() { return m_pSquad; }
- virtual void SetSquad( CAI_Squad *pSquad );
- void AddToSquad( string_t name );
- void RemoveFromSquad();
- void CheckSquad();
- void SetSquadName( string_t name ) { m_SquadName = name; }
- bool IsInSquad() const { return m_pSquad != NULL; }
- virtual bool IsSilentSquadMember() const { return false; }
-
- int NumWeaponsInSquad( const char *pszWeaponClassname );
-
- string_t GetHintGroup( void ) { return m_strHintGroup; }
- void ClearHintGroup( void ) { SetHintGroup( NULL_STRING ); }
- void SetHintGroup( string_t name, bool bHintGroupNavLimiting = false );
- bool IsLimitingHintGroups( void ) { return m_bHintGroupNavLimiting; }
-
- //---------------------------------
-
- CAI_TacticalServices *GetTacticalServices() { return m_pTacticalServices; }
- const CAI_TacticalServices *GetTacticalServices() const { return m_pTacticalServices; }
-
- //---------------------------------
- // Cover
-
- virtual bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult );
- virtual bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult );
- virtual bool FindCoverPos( CSound *pSound, Vector *pResult );
- virtual bool IsValidCover ( const Vector &vecCoverLocation, CAI_Hint const *pHint );
- virtual bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint );
- virtual bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ) { return WeaponLOSCondition( vecShootPos, targetPos, false ); }
- virtual bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
- virtual float CoverRadius( void ) { return 1024; } // Default cover radius
- virtual float GetMaxTacticalLateralMovement( void ) { return MAXTACLAT_IGNORE; }
-
-protected:
- virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {}
-
- CAI_Squad * m_pSquad; // The squad that I'm on
- string_t m_SquadName;
-
- int m_iMySquadSlot; // this is the behaviour slot that the npc currently holds in the squad.
-
-private:
- string_t m_strHintGroup;
- bool m_bHintGroupNavLimiting;
- CAI_TacticalServices *m_pTacticalServices;
-
-public:
- //-----------------------------------------------------
- //
- // Base schedule & task support; Miscellaneous
- //
- //-----------------------------------------------------
-
- void InitRelationshipTable( void );
- void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator );
-
- virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
- virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority );
-
- void NPCUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
-
- CBaseGrenade* IncomingGrenade(void);
-
- virtual bool ShouldFadeOnDeath( void );
-
- void NPCInitDead( void ); // Call after animation/pose is set up
- void CorpseFallThink( void );
-
- float ThrowLimit( const Vector &vecStart, const Vector &vecEnd, float fGravity, float fArcSize, const Vector &mins, const Vector &maxs, CBaseEntity *pTarget, Vector *jumpVel, CBaseEntity **pBlocker);
-
- // these functions will survey conditions and set appropriate conditions bits for attack types.
- virtual int RangeAttack1Conditions( float flDot, float flDist );
- virtual int RangeAttack2Conditions( float flDot, float flDist );
- virtual int MeleeAttack1Conditions( float flDot, float flDist );
- virtual int MeleeAttack2Conditions( float flDot, float flDist );
-
- virtual float InnateRange1MinRange( void ) { return 0.0f; }
- virtual float InnateRange1MaxRange( void ) { return FLT_MAX; }
-
- virtual bool OnBeginMoveAndShoot( void ) { return true; }
- virtual void OnEndMoveAndShoot( void ) {}
-
- virtual bool UseAttackSquadSlots() { return false; }
-
- //---------------------------------
-
- virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
-
- //---------------------------------
- // States
- //---------------------------------
-
- virtual void ClearAttackConditions( void );
- void GatherAttackConditions( CBaseEntity *pTarget, float flDist );
- virtual bool ShouldLookForBetterWeapon();
- bool Weapon_IsBetterAvailable ( void ) ;
- virtual Vector Weapon_ShootPosition( void );
- virtual void GiveWeapon( string_t iszWeaponName );
- virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) { }
- bool IsMovingToPickupWeapon();
- virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
- virtual bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions) { return WeaponLOSCondition( GetAbsOrigin(), targetPos, bSetConditions ); }
- virtual bool IsWaitingToRappel( void ) { return false; }
- virtual void BeginRappel() {}
-
- // override to change the chase location of an enemy
- // This is where your origin should go when you are chasing pEnemy when his origin is at chasePosition
- // by default, leave this alone to make your origin coincide with his.
- virtual void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition);
- virtual float GetDefaultNavGoalTolerance() { return (GetHullWidth() * 2.0); }
-
- virtual bool FCanCheckAttacks ( void );
- virtual void CheckAmmo( void ) {}
-
- virtual bool FValidateHintType( CAI_Hint *pHint );
- virtual Activity GetHintActivity( short sHintType, Activity HintsActivity );
- virtual float GetHintDelay( short sHintType );
- virtual Activity GetCoverActivity( CAI_Hint* pHint );
- virtual Activity GetReloadActivity( CAI_Hint* pHint );
-
- virtual void SetTurnActivity( void );
- bool UpdateTurnGesture( void );
-
- // Returns the time when the door will be open
- float OpenDoorAndWait( CBaseEntity *pDoor );
-
- bool BBoxFlat( void );
-
- //---------------------------------
-
- virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
- virtual bool PassesDamageFilter( const CTakeDamageInfo &info );
-
- //---------------------------------
-
- void MakeDamageBloodDecal( int cCount, float flNoise, trace_t *ptr, Vector vecDir );
- virtual float GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info );
- void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
- void DecalTrace( trace_t *pTrace, char const *decalName );
- void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName );
- virtual bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers = true );
- CBaseEntity * PlayerInRange( const Vector &vecLocation, float flDist );
- bool PointInSpread( CBaseCombatCharacter *pCheckEntity, const Vector &sourcePos, const Vector &targetPos, const Vector &testPoint, float flSpread, float maxDistOffCenter );
- bool IsSquadmateInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter );
-
- //---------------------------------
- // combat functions
- //---------------------------------
- virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions );
-
- virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
-
- virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class
- virtual bool Event_Gibbed( const CTakeDamageInfo &info );
- virtual void Event_Killed( const CTakeDamageInfo &info );
-
- virtual Vector GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy = true );
-#ifdef HL2_DLL
- virtual Vector GetActualShootPosition( const Vector &shootOrigin );
- virtual Vector GetActualShootTrajectory( const Vector &shootOrigin );
- virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL );
- virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget );
-#endif //HL2_DLL
- virtual void CollectShotStats( const Vector &vecShootOrigin, const Vector &vecShootDir );
- virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
- virtual Vector GetAutoAimCenter() { return BodyTarget(vec3_origin, false); }
- virtual void FireBullets( const FireBulletsInfo_t &info );
-
- // OLD VERSION! Use the struct version
- void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting,
- const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4,
- int firingEntID = -1, int attachmentID = -1, int iDamage = 0,
- CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false );
-
- virtual bool ShouldMoveAndShoot( void );
-
- //---------------------------------
- // Damage
- //---------------------------------
- virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
- virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info );
- virtual int OnTakeDamage_Dead( const CTakeDamageInfo &info );
-
- virtual void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity );
- virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
-
- virtual bool IsLightDamage( const CTakeDamageInfo &info );
- virtual bool IsHeavyDamage( const CTakeDamageInfo &info );
-
- void DoRadiusDamage( const CTakeDamageInfo &info, int iClassIgnore, CBaseEntity *pEntityIgnore );
- void DoRadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, int iClassIgnore, CBaseEntity *pEntityIgnore );
-
- //---------------------------------
-
- virtual void PickupWeapon( CBaseCombatWeapon *pWeapon );
- virtual void PickupItem( CBaseEntity *pItem ) { };
- CBaseEntity* DropItem( const char *pszItemName, Vector vecPos, QAngle vecAng );// drop an item.
-
-
- //---------------------------------
- // Inputs
- //---------------------------------
- void InputSetRelationship( inputdata_t &inputdata );
- void InputSetEnemyFilter( inputdata_t &inputdata );
- void InputSetHealth( inputdata_t &inputdata );
- void InputBeginRappel( inputdata_t &inputdata );
- void InputSetSquad( inputdata_t &inputdata );
- void InputWake( inputdata_t &inputdata );
- void InputForgetEntity( inputdata_t &inputdata );
- void InputIgnoreDangerSounds( inputdata_t &inputdata );
- void InputUpdateEnemyMemory( inputdata_t &inputdata );
-
- //---------------------------------
-
- virtual void NotifyDeadFriend( CBaseEntity *pFriend ) { return; }
-
- //---------------------------------
- // Utility methods
- static Vector CalcThrowVelocity(const Vector &startPos, const Vector &endPos, float fGravity, float fArcSize);
-
- //---------------------------------
-
- float SetWait( float minWait, float maxWait = 0.0 );
- void ClearWait();
- float GetWaitFinishTime() { return m_flWaitFinished; }
- bool IsWaitFinished();
- bool IsWaitSet();
-
- CBaseEntity* GetGoalEnt() { return m_hGoalEnt; }
- void SetGoalEnt( CBaseEntity *pGoalEnt ) { m_hGoalEnt.Set( pGoalEnt ); }
-
- CAI_Hint *GetHintNode() { return m_pHintNode; }
- const CAI_Hint *GetHintNode() const { return m_pHintNode; }
- void SetHintNode( CAI_Hint *pHintNode );
- void ClearHintNode( float reuseDelay = 0.0 );
-
- float m_flWaitFinished; // if we're told to wait, this is the time that the wait will be over.
-
- float m_flNextFlinchTime; // Time at which we'll flinch fully again (as opposed to just doing gesture flinches)
- float m_flNextDodgeTime; // Time at which I can dodge again. Used so that the behavior doesn't happen over and over.
-
- CAI_MoveAndShootOverlay m_MoveAndShootOverlay;
-
- Vector m_vecLastPosition; // npc sometimes wants to return to where it started after an operation.
- Vector m_vSavePosition; // position stored by code that called this schedules
- Vector m_vInterruptSavePosition; // position stored by a task that was interrupted
-
-private:
- CHandle<CAI_Hint> m_pHintNode; // this is the hint that the npc is moving towards or performing active idle on.
-
-public:
- int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences)
- float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in GatherEnemyConditions
- string_t m_spawnEquipment;
-
- bool m_fNoDamageDecal;
-
- EHANDLE m_hStoredPathTarget; // For TASK_SET_GOAL
- Vector m_vecStoredPathGoal; //
- GoalType_t m_nStoredPathType; //
- int m_fStoredPathFlags; //
-
- CHandle<CBaseFilter> m_hEnemyFilter;
- string_t m_iszEnemyFilterName;
-
- bool m_bDidDeathCleanup;
-
-
- IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_lifeState );
-
- //---------------------------------
- // Outputs
- //---------------------------------
- COutputEvent m_OnDamaged;
- COutputEvent m_OnDeath;
- COutputEvent m_OnHalfHealth;
- COutputEHANDLE m_OnFoundEnemy;
- COutputEvent m_OnLostEnemyLOS;
- COutputEvent m_OnLostEnemy;
- COutputEHANDLE m_OnFoundPlayer;
- COutputEvent m_OnLostPlayerLOS;
- COutputEvent m_OnLostPlayer;
- COutputEvent m_OnHearWorld;
- COutputEvent m_OnHearPlayer;
- COutputEvent m_OnHearCombat;
- COutputEvent m_OnDamagedByPlayer;
- COutputEvent m_OnDamagedByPlayerSquad;
- COutputEvent m_OnDenyCommanderUse;
- COutputEvent m_OnRappelTouchdown;
- COutputEvent m_OnSleep;
- COutputEvent m_OnWake;
- COutputEvent m_OnForcedInteractionStarted;
- COutputEvent m_OnForcedInteractionAborted;
- COutputEvent m_OnForcedInteractionFinished;
-
-public:
- // use this to shrink the bbox temporarily
- void SetHullSizeNormal( bool force = false );
- bool SetHullSizeSmall( bool force = false );
-
- bool IsUsingSmallHull() const { return m_fIsUsingSmallHull; }
-
- const Vector & GetHullMins() const { return NAI_Hull::Mins(GetHullType()); }
- const Vector & GetHullMaxs() const { return NAI_Hull::Maxs(GetHullType()); }
- float GetHullWidth() const { return NAI_Hull::Width(GetHullType()); }
- float GetHullHeight() const { return NAI_Hull::Height(GetHullType()); }
-
- void SetupVPhysicsHull();
- virtual void StartTouch( CBaseEntity *pOther );
- void CheckPhysicsContacts();
-
-private:
- void TryRestoreHull( void );
- bool m_fIsUsingSmallHull;
- bool m_bCheckContacts;
-
-private:
- // Task implementation helpers
- void StartTurn( float flDeltaYaw );
- bool FindCoverFromEnemy( bool bNodesOnly = false, float flMinDistance = 0, float flMaxDistance = FLT_MAX );
- bool FindCoverFromBestSound( Vector *pCoverPos );
- void StartScriptMoveToTargetTask( int task );
-
- void RunDieTask();
- void RunAttackTask( int task );
-
-protected:
- virtual float CalcReasonableFacing( bool bIgnoreOriginalFacing = false );
- virtual bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ) { return true; }
- virtual float GetReasonableFacingDist( void );
-
-public:
- inline int UsableNPCObjectCaps( int baseCaps )
- {
- if ( IsAlive() )
- baseCaps |= FCAP_IMPULSE_USE;
- return baseCaps;
- }
-
- virtual int ObjectCaps() { return (BaseClass::ObjectCaps() | FCAP_NOTIFY_ON_TRANSITION); }
-
- //-----------------------------------------------------
- //
- // Core mapped data structures
- //
- // String Registries for default AI Shared by all CBaseNPCs
- // These are used only during initialization and in debug
- //-----------------------------------------------------
-
- static void InitSchedulingTables();
-
- static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return &gm_SchedulingSymbols; }
- static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; }
- virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; }
-
- static int GetScheduleID (const char* schedName);
- static int GetActivityID (const char* actName);
- static int GetConditionID (const char* condName);
- static int GetTaskID (const char* taskName);
- static int GetSquadSlotID (const char* slotName);
- virtual const char* GetSquadSlotDebugName( int iSquadSlot );
- static const char* GetActivityName (int actID);
-
- static void AddActivityToSR(const char *actName, int conID);
-
- static void AddEventToSR(const char *eventName, int conID);
- static const char* GetEventName (int actID);
- static int GetEventID (const char* actName);
-
-public:
- //-----------------------------------------------------
- // Crouch handling
- //-----------------------------------------------------
- bool CrouchIsDesired( void ) const;
- virtual bool IsCrouching( void );
- inline void ForceCrouch( void );
- inline void ClearForceCrouch( void );
-
-protected:
- virtual bool Crouch( void );
- virtual bool Stand( void );
- virtual void DesireCrouch( void );
- inline void DesireStand( void );
- bool CouldShootIfCrouching( CBaseEntity *pTarget );
- virtual bool IsCrouchedActivity( Activity activity );
-
-protected:
- // Override these in your derived NPC class
- virtual Vector GetCrouchEyeOffset( void ) { return Vector(0,0,40); }
- virtual Vector GetCrouchGunOffset( void ) { return Vector(0,0,36); }
-
-private:
- bool m_bCrouchDesired;
- bool m_bForceCrouch;
- bool m_bIsCrouching;
- //-----------------------------------------------------
-
- //-----------------------------------------------------
- // ai_post_frame_navigation
- //-----------------------------------------------------
-
-private:
- bool m_bDeferredNavigation; // This NPCs has a navigation query that's being deferred until later in the frame
-
-public:
- void SetNavigationDeferred( bool bState ) { m_bDeferredNavigation = bState; }
- bool IsNavigationDeferred( void ) { return m_bDeferredNavigation; }
-
- //-----------------------------------------------------
-protected:
- static CAI_GlobalNamespace gm_SquadSlotNamespace;
- static CAI_LocalIdSpace gm_SquadSlotIdSpace;
-
-private:
- // Checks to see that the nav hull is valid for the NPC
- bool IsNavHullValid() const;
-
- friend class CAI_SystemHook;
- friend class CAI_SchedulesManager;
-
- static bool LoadDefaultSchedules(void);
-
- static void InitDefaultScheduleSR(void);
- static void InitDefaultTaskSR(void);
- static void InitDefaultConditionSR(void);
- static void InitDefaultActivitySR(void);
- static void InitDefaultSquadSlotSR(void);
-
- static CStringRegistry* m_pActivitySR;
- static int m_iNumActivities;
-
- static CStringRegistry* m_pEventSR;
- static int m_iNumEvents;
-
- static CAI_GlobalScheduleNamespace gm_SchedulingSymbols;
- static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace;
-
-public:
- //----------------------------------------------------
- // Debugging tools
- //
-
- // -----------------------------
- // Debuging Fields and Methods
- // -----------------------------
- const char* m_failText; // Text of why it failed
- const char* m_interruptText; // Text of why schedule interrupted
- CAI_Schedule* m_failedSchedule; // The schedule that failed last
- CAI_Schedule* m_interuptSchedule; // The schedule that was interrupted last
- int m_nDebugCurIndex; // Index used for stepping through AI
- virtual void ReportAIState( void );
- virtual void ReportOverThinkLimit( float time );
- void DumpTaskTimings();
- void DrawDebugGeometryOverlays(void);
- virtual int DrawDebugTextOverlays(void);
- void ToggleFreeze(void);
-
- static void ClearAllSchedules(void);
-
- static int m_nDebugBits;
-
- static CAI_BaseNPC* m_pDebugNPC;
- static int m_nDebugPauseIndex; // Current step
- static inline void SetDebugNPC( CAI_BaseNPC *pNPC ) { m_pDebugNPC = pNPC; }
- static inline bool IsDebugNPC( CAI_BaseNPC *pNPC ) { return( pNPC == m_pDebugNPC ); }
-
- float m_LastShootAccuracy;
- int m_TotalShots;
- int m_TotalHits;
-#ifdef _DEBUG
- bool m_bSelected;
-#endif
-
- float m_flSoundWaitTime; // Time when I'm allowed to make another sound
- int m_nSoundPriority;
- float m_flIgnoreDangerSoundsUntil;
-
-#ifdef AI_MONITOR_FOR_OSCILLATION
- CUtlVector<AIScheduleChoice_t> m_ScheduleHistory;
-#endif//AI_MONITOR_FOR_OSCILLATION
-
-private:
-
- // Break into pieces!
- void Break( CBaseEntity *pBreaker );
- void InputBreak( inputdata_t &inputdata );
-
- friend void CC_NPC_Go();
- friend void CC_NPC_GoRandom();
- friend void CC_NPC_Freeze( const CCommand &args );
-
-public:
-
- CNetworkVar( bool, m_bPerformAvoidance );
- CNetworkVar( bool, m_bIsMoving );
- CNetworkVar( bool, m_bFadeCorpse );
- CNetworkVar( bool, m_bImportanRagdoll );
-
- CNetworkVar( bool, m_bSpeedModActive );
- CNetworkVar( int, m_iSpeedModRadius );
- CNetworkVar( int, m_iSpeedModSpeed );
- CNetworkVar( float, m_flTimePingEffect ); // Display the pinged effect until this time
-
- void InputActivateSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = true; }
- void InputDisableSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = false; }
- void InputSetSpeedModifierRadius( inputdata_t &inputdata );
- void InputSetSpeedModifierSpeed( inputdata_t &inputdata );
-
- virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity );
-
- bool m_bPlayerAvoidState;
- void GetPlayerAvoidBounds( Vector *pMins, Vector *pMaxs );
-
- void StartPingEffect( void ) { m_flTimePingEffect = gpGlobals->curtime + 2.0f; DispatchUpdateTransmitState(); }
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns whether our ideal activity has started. If not, we are in
-// a transition sequence.
-//-----------------------------------------------------------------------------
-inline bool CAI_BaseNPC::IsActivityStarted(void)
-{
- return (GetSequence() == m_nIdealSequence);
-}
-
-//-----------------------------------------------------------------------------
-// Bullet firing (legacy)...
-//-----------------------------------------------------------------------------
-inline void CAI_BaseNPC::FireBullets( int cShots, const Vector &vecSrc,
- const Vector &vecDirShooting, const Vector &vecSpread, float flDistance,
- int iAmmoType, int iTracerFreq, int firingEntID, int attachmentID,
- int iDamage, CBaseEntity *pAttacker, bool bFirstShotAccurate )
-{
- FireBulletsInfo_t info;
- info.m_iShots = cShots;
- info.m_vecSrc = vecSrc;
- info.m_vecDirShooting = vecDirShooting;
- info.m_vecSpread = vecSpread;
- info.m_flDistance = flDistance;
- info.m_iAmmoType = iAmmoType;
- info.m_iTracerFreq = iTracerFreq;
- info.m_flDamage = iDamage;
- info.m_pAttacker = pAttacker;
- info.m_nFlags = bFirstShotAccurate ? FIRE_BULLETS_FIRST_SHOT_ACCURATE : 0;
-
- FireBullets( info );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Sets the ideal state of this NPC.
-//-----------------------------------------------------------------------------
-inline void CAI_BaseNPC::SetIdealState( NPC_STATE eIdealState )
-{
- if (eIdealState != m_IdealNPCState)
- {
- /*switch (eIdealState)
- {
- case NPC_STATE_NONE:
- Msg("%s.SetIdealState: NPC_STATE_NONE\n", GetDebugName());
- break;
-
- case NPC_STATE_IDLE:
- Msg("%s.SetIdealState: NPC_STATE_IDLE\n", GetDebugName());
- break;
-
- case NPC_STATE_ALERT:
- Msg("%s.SetIdealState: NPC_STATE_ALERT\n", GetDebugName());
- break;
-
- case NPC_STATE_COMBAT:
- Msg("%s.SetIdealState: NPC_STATE_COMBAT\n", GetDebugName());
- break;
-
- case NPC_STATE_SCRIPT:
- Msg("%s.SetIdealState: NPC_STATE_SCRIPT\n", GetDebugName());
- break;
-
- case NPC_STATE_PLAYDEAD:
- Msg("%s.SetIdealState: NPC_STATE_PLAYDEAD\n", GetDebugName());
- break;
-
- case NPC_STATE_PRONE:
- Msg("%s.SetIdealState: NPC_STATE_PRONE\n", GetDebugName());
- break;
-
- case NPC_STATE_DEAD:
- Msg("%s.SetIdealState: NPC_STATE_DEAD\n", GetDebugName());
- break;
-
- default:
- Msg("%s.SetIdealState: <Unknown>\n", GetDebugName());
- break;
- }*/
-
- m_IdealNPCState = eIdealState;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns the current ideal state the NPC will try to achieve.
-//-----------------------------------------------------------------------------
-inline NPC_STATE CAI_BaseNPC::GetIdealState()
-{
- return m_IdealNPCState;
-}
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-inline int CAI_BaseNPC::IncScheduleCurTaskIndex()
-{
- m_ScheduleState.iTaskInterrupt = 0;
- m_ScheduleState.bTaskRanAutomovement = false;
- m_ScheduleState.bTaskUpdatedYaw = false;
- return ++m_ScheduleState.iCurTask;
-}
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-inline void CAI_BaseNPC::ResetScheduleCurTaskIndex()
-{
- m_ScheduleState.iCurTask = 0;
- m_ScheduleState.iTaskInterrupt = 0;
- m_ScheduleState.bTaskRanAutomovement = false;
- m_ScheduleState.bTaskUpdatedYaw = false;
-}
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-inline bool CAI_BaseNPC::CrouchIsDesired( void ) const
-{
- return ( (CapabilitiesGet() & bits_CAP_DUCK) && (m_bCrouchDesired | m_bForceCrouch) );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-inline void CAI_BaseNPC::DesireStand( void )
-{
- m_bCrouchDesired = false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-inline void CAI_BaseNPC::ForceCrouch( void )
-{
- m_bForceCrouch = true;
- Crouch();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-inline void CAI_BaseNPC::ClearForceCrouch( void )
-{
- m_bForceCrouch = false;
-
- if ( IsCrouching() )
- {
- Stand();
- }
-}
-
-inline bool CAI_BaseNPC::HaveSequenceForActivity( Activity activity )
-{
-#if STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW
- return ( (GetModelPtr()) ? (SelectWeightedSequence( activity ) != ACTIVITY_NOT_AVAILABLE) : false );
-#else
- return ( (GetModelPtr()) ? GetModelPtr()->HaveSequenceForActivity(activity) : false );
-#endif
-}
-
-typedef CHandle<CAI_BaseNPC> AIHANDLE;
-
-
-// ============================================================================
-// Macros for introducing new schedules in sub-classes
-//
-// Strings registries and schedules use unique ID's for each item, but
-// sub-class enumerations are non-unique, so we translate between the
-// enumerations and unique ID's
-// ============================================================================
-
-#define AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( derivedClass ) \
- IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass ) \
- void derivedClass::InitCustomSchedules( void ) \
- { \
- typedef derivedClass CNpc; \
- const char *pszClassName = #derivedClass; \
- \
- CUtlVector<const char *> schedulesToLoad; \
- CUtlVector<AIScheduleLoadFunc_t> reqiredOthers; \
- CAI_NamespaceInfos scheduleIds; \
- CAI_NamespaceInfos taskIds; \
- CAI_NamespaceInfos conditionIds;
-
-
-//-----------------
-
-#define AI_BEGIN_CUSTOM_NPC( className, derivedClass ) \
- IMPLEMENT_CUSTOM_AI(className, derivedClass ) \
- void derivedClass::InitCustomSchedules( void ) \
- { \
- typedef derivedClass CNpc; \
- const char *pszClassName = #derivedClass; \
- \
- CUtlVector<const char *> schedulesToLoad; \
- CUtlVector<AIScheduleLoadFunc_t> reqiredOthers; \
- CAI_NamespaceInfos scheduleIds; \
- CAI_NamespaceInfos taskIds; \
- CAI_NamespaceInfos conditionIds; \
- CAI_NamespaceInfos squadSlotIds;
-
-//-----------------
-
-#define EXTERN_SCHEDULE( id ) \
- scheduleIds.PushBack( #id, id ); \
- extern const char * g_psz##id; \
- schedulesToLoad.AddToTail( g_psz##id );
-
-//-----------------
-
-#define DEFINE_SCHEDULE( id, text ) \
- scheduleIds.PushBack( #id, id ); \
- const char * g_psz##id = \
- "\n Schedule" \
- "\n " #id \
- text \
- "\n"; \
- schedulesToLoad.AddToTail( g_psz##id );
-
-//-----------------
-
-#define DECLARE_CONDITION( id ) \
- conditionIds.PushBack( #id, id );
-
-//-----------------
-
-#define DECLARE_TASK( id ) \
- taskIds.PushBack( #id, id );
-
-//-----------------
-
-#define DECLARE_ACTIVITY( id ) \
- ADD_CUSTOM_ACTIVITY( CNpc, id );
-
-//-----------------
-
-#define DECLARE_SQUADSLOT( id ) \
- squadSlotIds.PushBack( #id, id );
-
-//-----------------
-
-#define DECLARE_INTERACTION( interaction ) \
- ADD_CUSTOM_INTERACTION( interaction );
-
-//-----------------
-
-#define DECLARE_ANIMEVENT( id ) \
- ADD_CUSTOM_ANIMEVENT( CNpc, id );
-
-//-----------------
-
-#define DECLARE_USES_SCHEDULE_PROVIDER( classname ) reqiredOthers.AddToTail( ScheduleLoadHelper(classname) );
-
-//-----------------
-
-// IDs are stored and then added in order due to constraints in the namespace implementation
-#define AI_END_CUSTOM_SCHEDULE_PROVIDER() \
- \
- int i; \
- \
- CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
- \
- scheduleIds.Sort(); \
- taskIds.Sort(); \
- conditionIds.Sort(); \
- \
- for ( i = 0; i < scheduleIds.Count(); i++ ) \
- { \
- ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \
- } \
- \
- for ( i = 0; i < taskIds.Count(); i++ ) \
- { \
- ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \
- } \
- \
- for ( i = 0; i < conditionIds.Count(); i++ ) \
- { \
- if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \
- { \
- ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \
- } \
- } \
- \
- for ( i = 0; i < reqiredOthers.Count(); i++ ) \
- { \
- (*reqiredOthers[i])(); \
- } \
- \
- for ( i = 0; i < schedulesToLoad.Count(); i++ ) \
- { \
- if ( CNpc::gm_SchedLoadStatus.fValid ) \
- { \
- CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect() ); \
- } \
- else \
- break; \
- } \
- }
-
-inline bool ValidateConditionLimits( const char *pszNewCondition )
-{
- int nGlobalConditions = CAI_BaseNPC::GetSchedulingSymbols()->NumConditions();
- if ( nGlobalConditions >= MAX_CONDITIONS )
- {
- AssertMsg2( 0, "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition );
- DevWarning( "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition );
- return false;
- }
- return true;
-}
-
-
-//-------------------------------------
-
-// IDs are stored and then added in order due to constraints in the namespace implementation
-#define AI_END_CUSTOM_NPC() \
- \
- int i; \
- \
- CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
- CNpc::gm_SquadSlotIdSpace.Init( &BaseClass::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace); \
- \
- scheduleIds.Sort(); \
- taskIds.Sort(); \
- conditionIds.Sort(); \
- squadSlotIds.Sort(); \
- \
- for ( i = 0; i < scheduleIds.Count(); i++ ) \
- { \
- ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \
- } \
- \
- for ( i = 0; i < taskIds.Count(); i++ ) \
- { \
- ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \
- } \
- \
- for ( i = 0; i < conditionIds.Count(); i++ ) \
- { \
- if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \
- { \
- ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \
- } \
- } \
- \
- for ( i = 0; i < squadSlotIds.Count(); i++ ) \
- { \
- ADD_CUSTOM_SQUADSLOT_NAMED( CNpc, squadSlotIds[i].pszName, squadSlotIds[i].localId ); \
- } \
- \
- for ( i = 0; i < reqiredOthers.Count(); i++ ) \
- { \
- (*reqiredOthers[i])(); \
- } \
- \
- for ( i = 0; i < schedulesToLoad.Count(); i++ ) \
- { \
- if ( CNpc::gm_SchedLoadStatus.fValid ) \
- { \
- CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect() ); \
- } \
- else \
- break; \
- } \
- }
-
-//-------------------------------------
-
-struct AI_NamespaceAddInfo_t
-{
- AI_NamespaceAddInfo_t( const char *pszName, int localId )
- : pszName( pszName ),
- localId( localId )
- {
- }
-
- const char *pszName;
- int localId;
-};
-
-class CAI_NamespaceInfos : public CUtlVector<AI_NamespaceAddInfo_t>
-{
-public:
- void PushBack( const char *pszName, int localId )
- {
- AddToTail( AI_NamespaceAddInfo_t( pszName, localId ) );
- }
-
- void Sort()
- {
- CUtlVector<AI_NamespaceAddInfo_t>::Sort( Compare );
- }
-
-private:
- static int __cdecl Compare(const AI_NamespaceAddInfo_t *pLeft, const AI_NamespaceAddInfo_t *pRight )
- {
- return pLeft->localId - pRight->localId;
- }
-
-};
-
-//-------------------------------------
-
-// Declares the static variables that hold the string registry offset for the new subclass
-// as well as the initialization in schedule load functions
-
-struct AI_SchedLoadStatus_t
-{
- bool fValid;
- int signature;
-};
-
-// Load schedules pulled out to support stepping through with debugger
-inline bool AI_DoLoadSchedules( bool (*pfnBaseLoad)(), void (*pfnInitCustomSchedules)(),
- AI_SchedLoadStatus_t *pLoadStatus )
-{
- (*pfnBaseLoad)();
-
- if (pLoadStatus->signature != g_AI_SchedulesManager.GetScheduleLoadSignature())
- {
- (*pfnInitCustomSchedules)();
- pLoadStatus->fValid = true;
- pLoadStatus->signature = g_AI_SchedulesManager.GetScheduleLoadSignature();
- }
- return pLoadStatus->fValid;
-}
-
-//-------------------------------------
-
-typedef bool (*AIScheduleLoadFunc_t)();
-
-// @Note (toml 02-16-03): The following class exists to allow us to establish an anonymous friendship
-// in DEFINE_CUSTOM_SCHEDULE_PROVIDER. The particulars of this implementation is almost entirely
-// defined by bugs in MSVC 6.0
-class ScheduleLoadHelperImpl
-{
-public:
- template <typename T>
- static AIScheduleLoadFunc_t AccessScheduleLoadFunc(T *)
- {
- return (&T::LoadSchedules);
- }
-};
-
-#define ScheduleLoadHelper( type ) (ScheduleLoadHelperImpl::AccessScheduleLoadFunc((type *)0))
-
-//-------------------------------------
-
-#define DEFINE_CUSTOM_SCHEDULE_PROVIDER\
- static AI_SchedLoadStatus_t gm_SchedLoadStatus; \
- static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace; \
- static const char * gm_pszErrorClassName;\
- \
- static CAI_ClassScheduleIdSpace & AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; } \
- virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; } \
- virtual const char * GetSchedulingErrorName() { return gm_pszErrorClassName; } \
- \
- static void InitCustomSchedules(void);\
- \
- static bool LoadSchedules(void);\
- virtual bool LoadedSchedules(void); \
- \
- friend class ScheduleLoadHelperImpl; \
- \
- class CScheduleLoader \
- { \
- public: \
- CScheduleLoader(); \
- } m_ScheduleLoader; \
- \
- friend class CScheduleLoader;
-
-//-------------------------------------
-
-#define DEFINE_CUSTOM_AI\
- DEFINE_CUSTOM_SCHEDULE_PROVIDER \
- \
- static CAI_LocalIdSpace gm_SquadSlotIdSpace; \
- \
- const char* SquadSlotName (int squadSlotID);
-
-//-------------------------------------
-
-#define IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\
- AI_SchedLoadStatus_t derivedClass::gm_SchedLoadStatus = { true, -1 }; \
- CAI_ClassScheduleIdSpace derivedClass::gm_ClassScheduleIdSpace; \
- const char * derivedClass::gm_pszErrorClassName = #derivedClass; \
- \
- derivedClass::CScheduleLoader::CScheduleLoader()\
- { \
- derivedClass::LoadSchedules(); \
- } \
- \
- /* --------------------------------------------- */ \
- /* Load schedules for this type of NPC */ \
- /* --------------------------------------------- */ \
- bool derivedClass::LoadSchedules(void)\
- {\
- return AI_DoLoadSchedules( derivedClass::BaseClass::LoadSchedules, \
- derivedClass::InitCustomSchedules, \
- &derivedClass::gm_SchedLoadStatus ); \
- }\
- \
- bool derivedClass::LoadedSchedules(void) \
- { \
- return derivedClass::gm_SchedLoadStatus.fValid;\
- }
-
-
-//-------------------------------------
-
-// Initialize offsets and implement methods for loading and getting squad info for the subclass
-#define IMPLEMENT_CUSTOM_AI(className, derivedClass)\
- IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\
- \
- CAI_LocalIdSpace derivedClass::gm_SquadSlotIdSpace; \
- \
- /* -------------------------------------------------- */ \
- /* Given squadSlot enumeration return squadSlot name */ \
- /* -------------------------------------------------- */ \
- const char* derivedClass::SquadSlotName(int slotEN)\
- {\
- return gm_SquadSlotNamespace.IdToSymbol( derivedClass::gm_SquadSlotIdSpace.LocalToGlobal(slotEN) );\
- }
-
-
-//-------------------------------------
-
-#define ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,schedName,schedEN)\
- if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddSchedule( schedName, schedEN, derivedClass::gm_pszErrorClassName ) ) return;
-
-#define ADD_CUSTOM_SCHEDULE(derivedClass,schedEN) ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,#schedEN,schedEN)
-
-#define ADD_CUSTOM_TASK_NAMED(derivedClass,taskName,taskEN)\
- if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddTask( taskName, taskEN, derivedClass::gm_pszErrorClassName ) ) return;
-
-#define ADD_CUSTOM_TASK(derivedClass,taskEN) ADD_CUSTOM_TASK_NAMED(derivedClass,#taskEN,taskEN)
-
-#define ADD_CUSTOM_CONDITION_NAMED(derivedClass,condName,condEN)\
- if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddCondition( condName, condEN, derivedClass::gm_pszErrorClassName ) ) return;
-
-#define ADD_CUSTOM_CONDITION(derivedClass,condEN) ADD_CUSTOM_CONDITION_NAMED(derivedClass,#condEN,condEN)
-
-//-------------------------------------
-
-#define INIT_CUSTOM_AI(derivedClass)\
- derivedClass::AccessClassScheduleIdSpaceDirect().Init( #derivedClass, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
- derivedClass::gm_SquadSlotIdSpace.Init( &CAI_BaseNPC::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace);
-
-#define ADD_CUSTOM_INTERACTION( interaction ) { interaction = CBaseCombatCharacter::GetInteractionID(); }
-
-#define ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,squadSlotName,squadSlotEN)\
- if ( !derivedClass::gm_SquadSlotIdSpace.AddSymbol( squadSlotName, squadSlotEN, "squadslot", derivedClass::gm_pszErrorClassName ) ) return;
-
-#define ADD_CUSTOM_SQUADSLOT(derivedClass,squadSlotEN) ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,#squadSlotEN,squadSlotEN)
-
-#define ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,activityName,activityEnum)\
- REGISTER_PRIVATE_ACTIVITY(activityEnum);\
- CAI_BaseNPC::AddActivityToSR(activityName,activityEnum);
-
-#define ADD_CUSTOM_ACTIVITY(derivedClass,activityEnum) ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,#activityEnum,activityEnum)
-
-
-#define ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,eventName,eventEnum)\
- REGISTER_PRIVATE_ANIMEVENT(eventEnum);\
- CAI_BaseNPC::AddEventToSR(eventName,eventEnum);
-
-#define ADD_CUSTOM_ANIMEVENT(derivedClass,eventEnum) ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,#eventEnum,eventEnum)
-
-
-//=============================================================================
-// class CAI_Component
-//=============================================================================
-
-inline const Vector &CAI_Component::GetLocalOrigin() const
-{
- return GetOuter()->GetLocalOrigin();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetLocalOrigin(const Vector &origin)
-{
- GetOuter()->SetLocalOrigin(origin);
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Vector &CAI_Component::GetAbsOrigin() const
-{
- return GetOuter()->GetAbsOrigin();
-}
-
-//-----------------------------------------------------------------------------
-
-inline const QAngle &CAI_Component::GetAbsAngles() const
-{
- return GetOuter()->GetAbsAngles();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetSolid( SolidType_t val )
-{
- GetOuter()->SetSolid(val);
-}
-
-//-----------------------------------------------------------------------------
-
-inline SolidType_t CAI_Component::GetSolid() const
-{
- return GetOuter()->GetSolid();
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Vector &CAI_Component::WorldAlignMins() const
-{
- return GetOuter()->WorldAlignMins();
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Vector &CAI_Component::WorldAlignMaxs() const
-{
- return GetOuter()->WorldAlignMaxs();
-}
-
-//-----------------------------------------------------------------------------
-
-inline Hull_t CAI_Component::GetHullType() const
-{
- return GetOuter()->GetHullType();
-}
-
-//-----------------------------------------------------------------------------
-
-inline Vector CAI_Component::WorldSpaceCenter() const
-{
- return GetOuter()->WorldSpaceCenter();
-}
-
-//-----------------------------------------------------------------------------
-
-inline float CAI_Component::GetGravity() const
-{
- return GetOuter()->GetGravity();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetGravity( float flGravity )
-{
- GetOuter()->SetGravity( flGravity );
-}
-
-//-----------------------------------------------------------------------------
-
-inline float CAI_Component::GetHullWidth() const
-{
- return NAI_Hull::Width(GetOuter()->GetHullType());
-}
-
-//-----------------------------------------------------------------------------
-
-inline float CAI_Component::GetHullHeight() const
-{
- return NAI_Hull::Height(GetOuter()->GetHullType());
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Vector &CAI_Component::GetHullMins() const
-{
- return NAI_Hull::Mins(GetOuter()->GetHullType());
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Vector &CAI_Component::GetHullMaxs() const
-{
- return NAI_Hull::Maxs(GetOuter()->GetHullType());
-}
-
-//-----------------------------------------------------------------------------
-
-inline int CAI_Component::GetCollisionGroup() const
-{
- return GetOuter()->GetCollisionGroup();
-}
-
-//-----------------------------------------------------------------------------
-
-inline CBaseEntity *CAI_Component::GetEnemy()
-{
- return GetOuter()->GetEnemy();
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Vector &CAI_Component::GetEnemyLKP() const
-{
- return GetOuter()->GetEnemyLKP();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition )
-{
- GetOuter()->TranslateNavGoal( pEnemy, chasePosition );
-}
-
-//-----------------------------------------------------------------------------
-
-inline CBaseEntity *CAI_Component::GetTarget()
-{
- return GetOuter()->GetTarget();
-}
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetTarget( CBaseEntity *pTarget )
-{
- GetOuter()->SetTarget( pTarget );
-}
-
-//-----------------------------------------------------------------------------
-
-inline const Task_t *CAI_Component::GetCurTask()
-{
- return GetOuter()->GetTask();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::TaskFail( AI_TaskFailureCode_t code )
-{
- GetOuter()->TaskFail( code );
-}
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::TaskFail( const char *pszGeneralFailText )
-{
- GetOuter()->TaskFail( pszGeneralFailText );
-}
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::TaskComplete( bool fIgnoreSetFailedCondition )
-{
- GetOuter()->TaskComplete( fIgnoreSetFailedCondition );
-}
-//-----------------------------------------------------------------------------
-
-inline int CAI_Component::TaskIsRunning()
-{
- return GetOuter()->TaskIsRunning();
-}
-//-----------------------------------------------------------------------------
-
-inline int CAI_Component::TaskIsComplete()
-{
- return GetOuter()->TaskIsComplete();
-}
-
-//-----------------------------------------------------------------------------
-
-inline Activity CAI_Component::GetActivity()
-{
- return GetOuter()->GetActivity();
-}
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetActivity( Activity NewActivity )
-{
- GetOuter()->SetActivity( NewActivity );
-}
-//-----------------------------------------------------------------------------
-
-inline float CAI_Component::GetIdealSpeed() const
-{
- return GetOuter()->GetIdealSpeed();
-}
-
-//-----------------------------------------------------------------------------
-
-inline float CAI_Component::GetIdealAccel() const
-{
- return GetOuter()->GetIdealAccel();
-}
-
-//-----------------------------------------------------------------------------
-
-inline int CAI_Component::GetSequence()
-{
- return GetOuter()->GetSequence();
-}
-
-//-----------------------------------------------------------------------------
-
-inline int CAI_Component::GetEntFlags() const
-{
- return GetOuter()->GetFlags();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::AddEntFlag( int flags )
-{
- GetOuter()->AddFlag( flags );
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::RemoveEntFlag( int flagsToRemove )
-{
- GetOuter()->RemoveFlag( flagsToRemove );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Change the ground entity for the outer
-// Input : *ground -
-// Output : inline void
-//-----------------------------------------------------------------------------
-inline void CAI_Component::SetGroundEntity( CBaseEntity *ground )
-{
- GetOuter()->SetGroundEntity( ground );
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::ToggleEntFlag( int flagToToggle )
-{
- GetOuter()->ToggleFlag( flagToToggle );
-}
-
-//-----------------------------------------------------------------------------
-
-inline CBaseEntity* CAI_Component::GetGoalEnt()
-{
- return GetOuter()->GetGoalEnt();
-}
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetGoalEnt( CBaseEntity *pGoalEnt )
-{
- GetOuter()->SetGoalEnt( pGoalEnt );
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::Remember( int iMemory )
-{
- GetOuter()->Remember( iMemory );
-}
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::Forget( int iMemory )
-{
- GetOuter()->Forget( iMemory );
-}
-//-----------------------------------------------------------------------------
-
-inline bool CAI_Component::HasMemory( int iMemory )
-{
- return GetOuter()->HasMemory( iMemory );
-}
-
-//-----------------------------------------------------------------------------
-
-inline CAI_Enemies *CAI_Component::GetEnemies()
-{
- return GetOuter()->GetEnemies();
-}
-
-//-----------------------------------------------------------------------------
-
-inline const char *CAI_Component::GetEntClassname()
-{
- return GetOuter()->GetClassname();
-}
-
-//-----------------------------------------------------------------------------
-
-inline int CAI_Component::CapabilitiesGet()
-{
- return GetOuter()->CapabilitiesGet();
-}
-
-//-----------------------------------------------------------------------------
-
-inline void CAI_Component::SetLocalAngles( const QAngle& angles )
-{
- GetOuter()->SetLocalAngles( angles );
-}
-
-//-----------------------------------------------------------------------------
-
-inline const QAngle &CAI_Component::GetLocalAngles( void ) const
-{
- return GetOuter()->GetLocalAngles();
-}
-
-//-----------------------------------------------------------------------------
-
-inline edict_t *CAI_Component::GetEdict()
-{
- return GetOuter()->NetworkProp()->edict();
-}
-
-//-----------------------------------------------------------------------------
-
-inline float CAI_Component::GetLastThink( const char *szContext )
-{
- return GetOuter()->GetLastThink( szContext );
-}
-
-// ============================================================================
-abstract_class INPCInteractive
-{
-public:
- virtual bool CanInteractWith( CAI_BaseNPC *pUser ) = 0;
- virtual bool HasBeenInteractedWith() = 0;
- virtual void NotifyInteraction( CAI_BaseNPC *pUser ) = 0;
-
- // Alyx specific interactions
- virtual void AlyxStartedInteraction( void ) = 0;
- virtual void AlyxFinishedInteraction( void ) = 0;
-};
-
-// Base Class for any NPC that wants to be interactable by other NPCS (i.e. Alyx Hackable)
-// NOTE: YOU MUST DEFINE THE OUTPUTS IN YOUR CLASS'S DATADESC!
-// THE DO SO, INSERT THE FOLLOWING MACRO INTO YOUR CLASS'S DATADESC.
-//
-#define DEFINE_BASENPCINTERACTABLE_DATADESC() \
- DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \
- DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \
- DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown )
-
-template <class NPC_CLASS>
-class CNPCBaseInteractive : public NPC_CLASS, public INPCInteractive
-{
- DECLARE_CLASS( CNPCBaseInteractive, NPC_CLASS );
-public:
- virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; };
- virtual bool HasBeenInteractedWith() { return false; };
- virtual void NotifyInteraction( CAI_BaseNPC *pUser ) { return; };
-
- virtual void InputPowerdown( inputdata_t &inputdata )
- {
-
- }
-
- // Alyx specific interactions
- virtual void AlyxStartedInteraction( void )
- {
- m_OnAlyxStartedInteraction.FireOutput( this, this );
- }
- virtual void AlyxFinishedInteraction( void )
- {
- m_OnAlyxFinishedInteraction.FireOutput( this, this );
- }
-
-public:
- // Outputs
- // Alyx specific interactions
- COutputEvent m_OnAlyxStartedInteraction;
- COutputEvent m_OnAlyxFinishedInteraction;
-};
-
-//
-// Deferred Navigation calls go here
-//
-
-extern ConVar ai_post_frame_navigation;
-
-class CPostFrameNavigationHook : public CBaseGameSystemPerFrame
-{
-public:
- virtual const char *Name( void ) { return "CPostFrameNavigationHook"; }
-
- virtual bool Init( void );
- virtual void FrameUpdatePostEntityThink( void );
- virtual void FrameUpdatePreEntityThink( void );
-
- bool IsGameFrameRunning( void ) { return m_bGameFrameRunning; }
- void SetGrameFrameRunning( bool bState ) { m_bGameFrameRunning = bState; }
-
- void EnqueueEntityNavigationQuery( CAI_BaseNPC *pNPC, CFunctor *functor );
-
-private:
- CUtlVector<CFunctor *> m_Functors;
- bool m_bGameFrameRunning;
-};
-
-extern CPostFrameNavigationHook *PostFrameNavigationSystem( void );
-
-#endif // AI_BASENPC_H
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Base NPC character with AI
+//
+//=============================================================================//
+
+#ifndef AI_BASENPC_H
+#define AI_BASENPC_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "simtimer.h"
+#include "basecombatcharacter.h"
+#include "ai_debug.h"
+#include "ai_default.h"
+#include "ai_schedule.h"
+#include "ai_condition.h"
+#include "ai_component.h"
+#include "ai_task.h"
+#include "ai_movetypes.h"
+#include "ai_navtype.h"
+#include "ai_namespaces.h"
+#include "ai_npcstate.h"
+#include "ai_hull.h"
+#include "ai_utils.h"
+#include "ai_moveshoot.h"
+#include "entityoutput.h"
+#include "utlvector.h"
+#include "activitylist.h"
+#include "bitstring.h"
+#include "ai_basenpc.h"
+#include "ai_navgoaltype.h" //GoalType_t enum
+#include "eventlist.h"
+#include "soundent.h"
+#include "ai_navigator.h"
+#include "tier1/functors.h"
+
+
+#define PLAYER_SQUADNAME "player_squad"
+
+class CAI_Schedule;
+class CAI_Network;
+class CAI_Route;
+class CAI_Hint;
+class CAI_Node;
+class CAI_Navigator;
+class CAI_Pathfinder;
+class CAI_Senses;
+class CAI_Enemies;
+class CAI_Squad;
+class CAI_Expresser;
+class CAI_BehaviorBase;
+class CAI_GoalEntity;
+class CAI_Motor;
+class CAI_MoveProbe;
+class CAI_LocalNavigator;
+class CAI_TacticalServices;
+class CVarBitVec;
+class CAI_ScriptedSequence;
+class CSceneEntity;
+class CBaseGrenade;
+class CBaseDoor;
+class CBasePropDoor;
+struct AI_Waypoint_t;
+class AI_Response;
+class CBaseFilter;
+
+typedef CBitVec<MAX_CONDITIONS> CAI_ScheduleBits;
+
+// Used to control optimizations mostly dealing with pathfinding for NPCs
+extern ConVar ai_strong_optimizations;
+
+extern bool AIStrongOpt( void );
+
+// AI_MONITOR_FOR_OSCILLATION defaults to OFF. If you build with this ON, you can flag
+// NPC's and monitor them to detect oscillations in their schedule (circular logic and conditions bugs)
+// DO NOT SHIP WITH THIS ON!
+#undef AI_MONITOR_FOR_OSCILLATION
+
+//=============================================================================
+//
+// Constants & enumerations
+//
+//=============================================================================
+#define TURRET_CLOSE_RANGE 200
+#define TURRET_MEDIUM_RANGE 500
+
+#define COMMAND_GOAL_TOLERANCE 48 // 48 inches.
+#define TIME_CARE_ABOUT_DAMAGE 3.0
+
+#define ITEM_PICKUP_TOLERANCE 48.0f
+
+// Max's of the box used to search for a weapon to pick up. 45x45x~8 ft.
+#define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 )
+
+enum Interruptability_t
+{
+ GENERAL_INTERRUPTABILITY,
+ DAMAGEORDEATH_INTERRUPTABILITY,
+ DEATH_INTERRUPTABILITY
+};
+
+//-------------------------------------
+// Memory
+//-------------------------------------
+
+#define MEMORY_CLEAR 0
+#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes.
+#define bits_MEMORY_INCOVER ( 1 << 1 )// npc knows it is in a covered position.
+#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily
+#define bits_MEMORY_TASK_EXPENSIVE ( 1 << 3 )// NPC has completed a task which is considered costly, so don't do another task this frame
+//#define bits_MEMORY_ ( 1 << 4 )
+#define bits_MEMORY_PATH_FAILED ( 1 << 5 )// Failed to find a path
+#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
+//#define bits_MEMORY_ ( 1 << 7 )
+#define bits_MEMORY_TOURGUIDE ( 1 << 8 )// I have been acting as a tourguide.
+//#define bits_MEMORY_ ( 1 << 9 )//
+#define bits_MEMORY_LOCKED_HINT ( 1 << 10 )//
+//#define bits_MEMORY_ ( 1 << 12 )
+
+#define bits_MEMORY_TURNING ( 1 << 13 )// Turning, don't interrupt me.
+#define bits_MEMORY_TURNHACK ( 1 << 14 )
+
+#define bits_MEMORY_HAD_ENEMY ( 1 << 15 )// Had an enemy
+#define bits_MEMORY_HAD_PLAYER ( 1 << 16 )// Had player
+#define bits_MEMORY_HAD_LOS ( 1 << 17 )// Had LOS to enemy
+
+#define bits_MEMORY_MOVED_FROM_SPAWN ( 1 << 18 )// Has moved since spawning.
+
+#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // NPC-specific memory
+#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // NPC-specific memory
+#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // NPC-specific memory
+#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // NPC-specific memory
+
+//-------------------------------------
+// Spawn flags
+//-------------------------------------
+#define SF_NPC_WAIT_TILL_SEEN ( 1 << 0 ) // spawnflag that makes npcs wait until player can see them before attacking.
+#define SF_NPC_GAG ( 1 << 1 ) // no idle noises from this npc
+#define SF_NPC_FALL_TO_GROUND ( 1 << 2 ) // used my NPC_Maker
+#define SF_NPC_DROP_HEALTHKIT ( 1 << 3 ) // Drop a healthkit upon death
+#define SF_NPC_START_EFFICIENT ( 1 << 4 ) // Set into efficiency mode from spawn
+// ( 1 << 5 )
+// ( 1 << 6 )
+#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
+#define SF_NPC_LONG_RANGE ( 1 << 8 ) // makes npcs look far and relaxes weapon range limit
+#define SF_NPC_FADE_CORPSE ( 1 << 9 ) // Fade out corpse after death
+#define SF_NPC_ALWAYSTHINK ( 1 << 10 ) // Simulate even when player isn't in PVS.
+#define SF_NPC_TEMPLATE ( 1 << 11 ) // This NPC will be used as a template by an npc_maker -- do not spawn.
+#define SF_NPC_ALTCOLLISION ( 1 << 12 )
+#define SF_NPC_NO_WEAPON_DROP ( 1 << 13 ) // This NPC will not actually drop a weapon that can be picked up
+#define SF_NPC_NO_PLAYER_PUSHAWAY ( 1 << 14 )
+// ( 1 << 15 )
+// !! Flags above ( 1 << 15 ) are reserved for NPC sub-classes
+
+//-------------------------------------
+//
+// Return codes from CanPlaySequence.
+//
+//-------------------------------------
+
+enum CanPlaySequence_t
+{
+ CANNOT_PLAY = 0, // Can't play for any number of reasons.
+ CAN_PLAY_NOW, // Can play the script immediately.
+ CAN_PLAY_ENQUEUED, // Can play the script after I finish playing my current script.
+};
+
+//-------------------------------------
+// Weapon holstering
+//-------------------------------------
+enum DesiredWeaponState_t
+{
+ DESIREDWEAPONSTATE_IGNORE = 0,
+ DESIREDWEAPONSTATE_HOLSTERED,
+ DESIREDWEAPONSTATE_HOLSTERED_DESTROYED, // Put the weapon away, then destroy it.
+ DESIREDWEAPONSTATE_UNHOLSTERED,
+ DESIREDWEAPONSTATE_CHANGING,
+ DESIREDWEAPONSTATE_CHANGING_DESTROY, // Destroy the weapon when this change is complete.
+};
+
+//-------------------------------------
+//
+// Efficiency modes
+//
+//-------------------------------------
+
+enum AI_Efficiency_t
+{
+ // Run at full tilt
+ AIE_NORMAL,
+
+ // Run decision process less often
+ AIE_EFFICIENT,
+
+ // Run decision process even less often, ignore other NPCs
+ AIE_VERY_EFFICIENT,
+
+ // Run decision process even less often, ignore other NPCs
+ AIE_SUPER_EFFICIENT,
+
+ // Don't run at all
+ AIE_DORMANT,
+};
+
+enum AI_MoveEfficiency_t
+{
+ AIME_NORMAL,
+ AIME_EFFICIENT,
+};
+
+//-------------------------------------
+//
+// Sleep state
+//
+//-------------------------------------
+
+enum AI_SleepState_t
+{
+ AISS_AWAKE,
+ AISS_WAITING_FOR_THREAT,
+ AISS_WAITING_FOR_PVS,
+ AISS_WAITING_FOR_INPUT,
+ AISS_AUTO_PVS,
+ AISS_AUTO_PVS_AFTER_PVS, // Same as AUTO_PVS, except doesn't activate until/unless the NPC is IN the player's PVS.
+};
+
+#define AI_SLEEP_FLAGS_NONE 0x00000000
+#define AI_SLEEP_FLAG_AUTO_PVS 0x00000001
+#define AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS 0x00000002
+
+
+//-------------------------------------
+//
+// Debug bits
+//
+//-------------------------------------
+
+enum DebugBaseNPCBits_e
+{
+ bits_debugDisableAI = 0x00000001, // disable AI
+ bits_debugStepAI = 0x00000002, // step AI
+
+};
+
+//-------------------------------------
+//
+// Base Sentence index for behaviors
+//
+//-------------------------------------
+enum SentenceIndex_t
+{
+ SENTENCE_BASE_BEHAVIOR_INDEX = 1000,
+};
+
+#ifdef AI_MONITOR_FOR_OSCILLATION
+struct AIScheduleChoice_t
+{
+ float m_flTimeSelected;
+ CAI_Schedule *m_pScheduleSelected;
+};
+#endif//AI_MONITOR_FOR_OSCILLATION
+
+#define MARK_TASK_EXPENSIVE() \
+ if ( GetOuter() ) \
+ { \
+ GetOuter()->Remember( bits_MEMORY_TASK_EXPENSIVE ); \
+ }
+
+//=============================================================================
+//
+// Types used by CAI_BaseNPC
+//
+//=============================================================================
+
+struct AIScheduleState_t
+{
+ int iCurTask;
+ TaskStatus_e fTaskStatus;
+ float timeStarted;
+ float timeCurTaskStarted;
+ AI_TaskFailureCode_t taskFailureCode;
+ int iTaskInterrupt;
+ bool bTaskRanAutomovement;
+ bool bTaskUpdatedYaw;
+ bool bScheduleWasInterrupted;
+
+ DECLARE_SIMPLE_DATADESC();
+};
+
+// -----------------------------------------
+// An entity that this NPC can't reach
+// -----------------------------------------
+
+struct UnreachableEnt_t
+{
+ EHANDLE hUnreachableEnt; // Entity that's unreachable
+ float fExpireTime; // Time to forget this information
+ Vector vLocationWhenUnreachable;
+
+ DECLARE_SIMPLE_DATADESC();
+};
+
+//=============================================================================
+// SCRIPTED NPC INTERACTIONS
+//=============================================================================
+// -----------------------------------------
+// Scripted NPC interaction flags
+// -----------------------------------------
+#define SCNPC_FLAG_TEST_OTHER_ANGLES ( 1 << 1 )
+#define SCNPC_FLAG_TEST_OTHER_VELOCITY ( 1 << 2 )
+#define SCNPC_FLAG_LOOP_IN_ACTION ( 1 << 3 )
+#define SCNPC_FLAG_NEEDS_WEAPON_ME ( 1 << 4 )
+#define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 )
+#define SCNPC_FLAG_DONT_TELEPORT_AT_END_ME ( 1 << 6 )
+#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )
+
+// -----------------------------------------
+// Scripted NPC interaction trigger methods
+// -----------------------------------------
+enum
+{
+ SNPCINT_CODE = 0,
+ SNPCINT_AUTOMATIC_IN_COMBAT = 1,
+};
+
+// -----------------------------------------
+// Scripted NPC interaction loop breaking trigger methods
+// -----------------------------------------
+#define SNPCINT_LOOPBREAK_ON_DAMAGE ( 1 << 1 )
+#define SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ( 1 << 2 )
+
+// -----------------------------------------
+// Scripted NPC interaction anim phases
+// -----------------------------------------
+enum
+{
+ SNPCINT_ENTRY = 0,
+ SNPCINT_SEQUENCE,
+ SNPCINT_EXIT,
+
+ SNPCINT_NUM_PHASES
+};
+
+struct ScriptedNPCInteraction_Phases_t
+{
+ string_t iszSequence;
+ int iActivity;
+
+ DECLARE_SIMPLE_DATADESC();
+};
+
+// Allowable delta from the desired dynamic scripted sequence point
+#define DSS_MAX_DIST 6
+#define DSS_MAX_ANGLE_DIFF 4
+
+// Interaction Logic States
+enum
+{
+ NPCINT_NOT_RUNNING = 0,
+ NPCINT_RUNNING_ACTIVE, // I'm in an interaction that I initiated
+ NPCINT_RUNNING_PARTNER, // I'm in an interaction that was initiated by the other NPC
+ NPCINT_MOVING_TO_MARK, // I'm moving to a position to do an interaction
+};
+
+#define NPCINT_NONE -1
+
+#define MAXTACLAT_IGNORE -1
+
+// -----------------------------------------
+// A scripted interaction between NPCs
+// -----------------------------------------
+struct ScriptedNPCInteraction_t
+{
+ ScriptedNPCInteraction_t()
+ {
+ iszInteractionName = NULL_STRING;
+ iFlags = 0;
+ iTriggerMethod = SNPCINT_CODE;
+ iLoopBreakTriggerMethod = 0;
+ vecRelativeOrigin = vec3_origin;
+ bValidOnCurrentEnemy = false;
+ flDelay = 5.0;
+ flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST);
+ flNextAttemptTime = 0;
+ iszMyWeapon = NULL_STRING;
+ iszTheirWeapon = NULL_STRING;
+
+ for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
+ {
+ sPhases[i].iszSequence = NULL_STRING;
+ sPhases[i].iActivity = ACT_INVALID;
+ }
+ }
+
+ // Fill out these when passing to AddScriptedNPCInteraction
+ string_t iszInteractionName;
+ int iFlags;
+ int iTriggerMethod;
+ int iLoopBreakTriggerMethod;
+ Vector vecRelativeOrigin; // (forward, right, up)
+ QAngle angRelativeAngles;
+ Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
+ float flDelay; // Delay before interaction can be used again
+ float flDistSqr; // Max distance sqr from the relative origin the NPC is allowed to be to trigger
+ string_t iszMyWeapon; // Classname of the weapon I'm holding, if any
+ string_t iszTheirWeapon; // Classname of the weapon my interaction partner is holding, if any
+ ScriptedNPCInteraction_Phases_t sPhases[SNPCINT_NUM_PHASES];
+
+ // These will be filled out for you in AddScriptedNPCInteraction
+ VMatrix matDesiredLocalToWorld; // Desired relative position / angles of the other NPC
+ bool bValidOnCurrentEnemy;
+
+ float flNextAttemptTime;
+
+ DECLARE_SIMPLE_DATADESC();
+};
+
+//=============================================================================
+//
+// Utility functions
+//
+//=============================================================================
+
+Vector VecCheckToss ( CBaseEntity *pEdict, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
+Vector VecCheckToss ( CBaseEntity *pEntity, ITraceFilter *pFilter, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
+Vector VecCheckThrow( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0f, Vector *vecMins = NULL, Vector *vecMaxs = NULL );
+
+extern Vector g_vecAttackDir;
+
+bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget );
+bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize = 0.0 );
+
+// FIXME: move to utils?
+float DeltaV( float v0, float v1, float d );
+float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVelocity, float flCurVelocity, float flIdealVelocity, float flAccelRate, float &flNewDistance, float &flNewVelocity );
+
+//=============================================================================
+//
+// class CAI_Manager
+//
+// Central location for components of the AI to operate across all AIs without
+// iterating over the global list of entities.
+//
+//=============================================================================
+
+class CAI_Manager
+{
+public:
+ CAI_Manager();
+
+ CAI_BaseNPC ** AccessAIs();
+ int NumAIs();
+
+ void AddAI( CAI_BaseNPC *pAI );
+ void RemoveAI( CAI_BaseNPC *pAI );
+
+ bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); }
+
+private:
+ enum
+ {
+ MAX_AIS = 256
+ };
+
+ typedef CUtlVector<CAI_BaseNPC *> CAIArray;
+
+ CAIArray m_AIs;
+
+};
+
+//-------------------------------------
+
+extern CAI_Manager g_AI_Manager;
+
+//=============================================================================
+//
+// class CAI_BaseNPC
+//
+//=============================================================================
+
+class CAI_BaseNPC : public CBaseCombatCharacter,
+ public CAI_DefMovementSink
+{
+ DECLARE_CLASS( CAI_BaseNPC, CBaseCombatCharacter );
+
+public:
+ //-----------------------------------------------------
+ //
+ // Initialization, cleanup, serialization, identity
+ //
+
+ CAI_BaseNPC();
+ ~CAI_BaseNPC();
+
+ //---------------------------------
+
+ DECLARE_DATADESC();
+ DECLARE_SERVERCLASS();
+
+ virtual int Save( ISave &save );
+ virtual int Restore( IRestore &restore );
+ virtual void OnRestore();
+ void SaveConditions( ISave &save, const CAI_ScheduleBits &conditions );
+ void RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions );
+
+ bool ShouldSavePhysics() { return false; }
+ virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
+
+ virtual bool KeyValue( const char *szKeyName, const char *szValue );
+
+ //---------------------------------
+
+ virtual void PostConstructor( const char *szClassname );
+ virtual void Activate( void );
+ virtual void Precache( void ); // derived calls at start of Spawn()
+ virtual bool CreateVPhysics();
+ virtual void NPCInit( void ); // derived calls after Spawn()
+ void NPCInitThink( void );
+ virtual void PostNPCInit() {};// called after NPC_InitThink
+ virtual void StartNPC( void );
+ virtual bool IsTemplate( void );
+
+ virtual void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
+ virtual void UpdateOnRemove( void );
+
+ virtual int UpdateTransmitState();
+
+ //---------------------------------
+ // Component creation factories
+ //
+
+ // The master call, override if you introduce new component types. Call base first
+ virtual bool CreateComponents();
+
+ // Components defined by the base AI class
+ virtual CAI_Senses * CreateSenses();
+ virtual CAI_MoveProbe * CreateMoveProbe();
+ virtual CAI_Motor * CreateMotor();
+ virtual CAI_LocalNavigator *CreateLocalNavigator();
+ virtual CAI_Navigator * CreateNavigator();
+ virtual CAI_Pathfinder *CreatePathfinder();
+ virtual CAI_TacticalServices *CreateTacticalServices();
+
+ //---------------------------------
+
+ virtual bool IsNPC( void ) const { return true; }
+
+ //---------------------------------
+
+ void TestPlayerPushing( CBaseEntity *pPlayer );
+ void CascadePlayerPush( const Vector &push, const Vector &pushOrigin );
+ void NotifyPushMove();
+
+public:
+ //-----------------------------------------------------
+ //
+ // AI processing - thinking, schedule selection and task running
+ //
+ //-----------------------------------------------------
+ void CallNPCThink( void );
+
+ // Thinking, including core thinking, movement, animation
+ virtual void NPCThink( void );
+
+ // Core thinking (schedules & tasks)
+ virtual void RunAI( void );// core ai function!
+
+ // Called to gather up all relevant conditons
+ virtual void GatherConditions( void );
+
+ // Called immediately prior to schedule processing
+ virtual void PrescheduleThink( void );
+
+ // Called immediately after schedule processing
+ virtual void PostscheduleThink( void ) { return; };
+
+ // Notification that the current schedule, if any, is ending and a new one is being selected
+ virtual void OnScheduleChange( void );
+
+ // Notification that a new schedule is about to run its first task
+ virtual void OnStartSchedule( int scheduleType ) {};
+
+ // This function implements a decision tree for the NPC. It is responsible for choosing the next behavior (schedule)
+ // based on the current conditions and state.
+ virtual int SelectSchedule( void );
+ virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
+
+ // After the schedule has been selected, it will be processed by this function so child NPC classes can
+ // remap base schedules into child-specific behaviors
+ virtual int TranslateSchedule( int scheduleType );
+
+ virtual void StartTask( const Task_t *pTask );
+ virtual void RunTask( const Task_t *pTask );
+
+ void ClearTransientConditions();
+
+ virtual void HandleAnimEvent( animevent_t *pEvent );
+
+ virtual bool IsInterruptable();
+ virtual void OnStartScene( void ) {} // Called when an NPC begins a cine scene (useful for clean-up)
+ virtual bool ShouldPlayerAvoid( void );
+ virtual void SetPlayerAvoidState( void );
+ virtual void PlayerPenetratingVPhysics( void );
+
+ virtual bool ShouldAlwaysThink();
+ void ForceGatherConditions() { m_bForceConditionsGather = true; SetEfficiency( AIE_NORMAL ); } // Force an NPC out of PVS to call GatherConditions on next think
+
+ virtual float LineOfSightDist( const Vector &vecDir = vec3_invalid, float zEye = FLT_MAX );
+
+ virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
+ virtual const char *GetTracerType( void );
+ virtual void DoImpactEffect( trace_t &tr, int nDamageType );
+
+ enum
+ {
+ NEXT_SCHEDULE = LAST_SHARED_SCHEDULE,
+ NEXT_TASK = LAST_SHARED_TASK,
+ NEXT_CONDITION = LAST_SHARED_CONDITION,
+ };
+
+protected:
+ // Used by derived classes to chain a task to a task that might not be the
+ // one they are currently handling:
+ void ChainStartTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; StartTask( (const Task_t *)&tempTask ); }
+ void ChainRunTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; RunTask( (const Task_t *) &tempTask ); }
+
+ void StartTaskOverlay();
+ void RunTaskOverlay();
+ void EndTaskOverlay();
+
+ virtual void PostRunStopMoving();
+
+ bool CheckPVSCondition();
+
+private:
+ bool CanThinkRebalance();
+ void RebalanceThinks();
+
+ bool PreNPCThink();
+ void PostNPCThink();
+
+ bool PreThink( void );
+ void PerformSensing();
+ void CheckOnGround( void );
+ void MaintainSchedule( void );
+ void RunAnimation( void );
+ void PostRun( void );
+ void PerformMovement();
+ void PostMovement();
+
+ 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
+ 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
+
+public:
+ //-----------------------------------------------------
+ //
+ // Schedules & tasks
+ //
+ //-----------------------------------------------------
+
+ void SetSchedule( CAI_Schedule *pNewSchedule );
+ bool SetSchedule( int localScheduleID );
+
+ void SetDefaultFailSchedule( int failSchedule ) { m_failSchedule = failSchedule; }
+
+ void ClearSchedule( const char *szReason );
+
+ CAI_Schedule * GetCurSchedule() { return m_pSchedule; }
+ bool IsCurSchedule( int schedId, bool fIdeal = true );
+ virtual CAI_Schedule *GetSchedule(int localScheduleID);
+ virtual int GetLocalScheduleId( int globalScheduleID ) { return AI_IdIsLocal( globalScheduleID ) ? globalScheduleID : GetClassScheduleIdSpace()->ScheduleGlobalToLocal( globalScheduleID ); }
+ virtual int GetGlobalScheduleId( int localScheduleID ) { return AI_IdIsGlobal( localScheduleID ) ? localScheduleID : GetClassScheduleIdSpace()->ScheduleLocalToGlobal( localScheduleID ); }
+
+ float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; }
+
+ //---------------------------------
+
+ const Task_t* GetTask( void );
+ int TaskIsRunning( void );
+
+ virtual void TaskFail( AI_TaskFailureCode_t );
+ void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); }
+ void TaskComplete( bool fIgnoreSetFailedCondition = false );
+
+ void TaskInterrupt() { m_ScheduleState.iTaskInterrupt++; }
+ void ClearTaskInterrupt() { m_ScheduleState.iTaskInterrupt = 0; }
+ int GetTaskInterrupt() const { return m_ScheduleState.iTaskInterrupt; }
+
+ void TaskMovementComplete( void );
+ inline int TaskIsComplete( void ) { return (GetTaskStatus() == TASKSTATUS_COMPLETE); }
+
+ virtual const char *TaskName(int taskID);
+
+ float GetTimeTaskStarted() const { return m_ScheduleState.timeCurTaskStarted; }
+ virtual int GetLocalTaskId( int globalTaskId) { return GetClassScheduleIdSpace()->TaskGlobalToLocal( globalTaskId ); }
+
+ virtual const char *GetSchedulingErrorName() { return "CAI_BaseNPC"; }
+
+protected:
+ static bool LoadSchedules(void);
+ virtual bool LoadedSchedules(void);
+ virtual void BuildScheduleTestBits( void );
+
+ //---------------------------------
+
+ // This is the main call to select/translate a schedule
+ virtual CAI_Schedule *GetNewSchedule( void );
+ virtual CAI_Schedule *GetFailSchedule( void );
+
+ //---------------------------------
+
+ virtual bool CanFlinch( void );
+ virtual void CheckFlinches( void );
+ virtual void PlayFlinchGesture( void );
+ int SelectFlinchSchedule( void );
+
+ virtual bool IsAllowedToDodge( void );
+
+ bool IsInChoreo() const;
+
+private:
+ // This function maps the type through TranslateSchedule() and then retrieves the pointer
+ // to the actual CAI_Schedule from the database of schedules available to this class.
+ CAI_Schedule * GetScheduleOfType( int scheduleType );
+
+ bool FHaveSchedule( void );
+ bool FScheduleDone ( void );
+ CAI_Schedule * ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount );
+
+ int GetScheduleCurTaskIndex() const { return m_ScheduleState.iCurTask; }
+ inline int IncScheduleCurTaskIndex();
+ inline void ResetScheduleCurTaskIndex();
+ void NextScheduledTask ( void );
+ bool IsScheduleValid ( void );
+ bool ShouldSelectIdealState( void );
+
+ // Selecting the ideal state
+ NPC_STATE SelectIdleIdealState();
+ NPC_STATE SelectAlertIdealState();
+ NPC_STATE SelectScriptIdealState();
+
+ // Various schedule selections based on NPC_STATE
+ int SelectIdleSchedule();
+ int SelectAlertSchedule();
+ int SelectCombatSchedule();
+ virtual int SelectDeadSchedule();
+ int SelectScriptSchedule();
+ int SelectInteractionSchedule();
+
+ void OnStartTask( void ) { SetTaskStatus( TASKSTATUS_RUN_MOVE_AND_TASK ); }
+ void SetTaskStatus( TaskStatus_e status ) { m_ScheduleState.fTaskStatus = status; }
+ TaskStatus_e GetTaskStatus() const { return m_ScheduleState.fTaskStatus; }
+
+ void DiscardScheduleState();
+
+ //---------------------------------
+
+ CAI_Schedule * m_pSchedule;
+ int m_IdealSchedule;
+ AIScheduleState_t m_ScheduleState;
+ int m_failSchedule; // Schedule type to choose if current schedule fails
+ bool m_bDoPostRestoreRefindPath;
+
+ bool m_bUsingStandardThinkTime;
+ float m_flLastRealThinkTime;
+ int m_iFrameBlocked;
+ bool m_bInChoreo;
+
+ static int gm_iNextThinkRebalanceTick;
+ static float gm_flTimeLastSpawn;
+ static int gm_nSpawnedThisFrame;
+
+protected: // pose parameters
+ int m_poseAim_Pitch;
+ int m_poseAim_Yaw;
+ int m_poseMove_Yaw;
+ virtual void PopulatePoseParameters( void );
+
+public:
+ inline bool HasPoseMoveYaw() { return ( m_poseMove_Yaw >= 0 ); }
+
+ // Return the stored pose parameter for "move_yaw"
+ inline int LookupPoseMoveYaw() { return m_poseMove_Yaw; }
+
+
+ //-----------------------------------------------------
+ //
+ // Hooks for CAI_Behaviors, *if* derived class supports them
+ //
+ //-----------------------------------------------------
+ template <class BEHAVIOR_TYPE>
+ bool GetBehavior( BEHAVIOR_TYPE **ppBehavior )
+ {
+ CAI_BehaviorBase **ppBehaviors = AccessBehaviors();
+
+ *ppBehavior = NULL;
+ for ( int i = 0; i < NumBehaviors(); i++ )
+ {
+ *ppBehavior = dynamic_cast<BEHAVIOR_TYPE *>(ppBehaviors[i]);
+ if ( *ppBehavior )
+ return true;
+ }
+ return false;
+ }
+
+ virtual CAI_BehaviorBase *GetRunningBehavior() { return NULL; }
+
+ virtual bool ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) { return true; }
+ virtual void OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) {}
+
+ // Notification that the status behavior ability to select schedules has changed.
+ // Return "true" to signal a schedule interrupt is desired
+ virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ) { return false; }
+
+private:
+ virtual CAI_BehaviorBase ** AccessBehaviors() { return NULL; }
+ virtual int NumBehaviors() { return 0; }
+
+public:
+ //-----------------------------------------------------
+ //
+ // Conditions
+ //
+ //-----------------------------------------------------
+
+ virtual const char* ConditionName(int conditionID);
+
+ virtual void RemoveIgnoredConditions ( void );
+ void SetCondition( int iCondition /*, bool state = true*/ );
+ bool HasCondition( int iCondition );
+ bool HasCondition( int iCondition, bool bUseIgnoreConditions );
+ bool HasInterruptCondition( int iCondition );
+ bool HasConditionsToInterruptSchedule( int nLocalScheduleID );
+
+ void ClearCondition( int iCondition );
+ void ClearConditions( int *pConditions, int nConditions );
+ void SetIgnoreConditions( int *pConditions, int nConditions );
+ void ClearIgnoreConditions( int *pConditions, int nConditions );
+ bool ConditionInterruptsCurSchedule( int iCondition );
+ bool ConditionInterruptsSchedule( int schedule, int iCondition );
+
+ void SetCustomInterruptCondition( int nCondition );
+ bool IsCustomInterruptConditionSet( int nCondition );
+ void ClearCustomInterruptCondition( int nCondition );
+ void ClearCustomInterruptConditions( void );
+
+ bool ConditionsGathered() const { return m_bConditionsGathered; }
+ const CAI_ScheduleBits &AccessConditionBits() const { return m_Conditions; }
+ CAI_ScheduleBits & AccessConditionBits() { return m_Conditions; }
+
+ bool DidChooseEnemy() const { return !m_bSkippedChooseEnemy; }
+
+private:
+ CAI_ScheduleBits m_Conditions;
+ CAI_ScheduleBits m_CustomInterruptConditions; //Bit string assembled by the schedule running, then
+ //modified by leaf classes to suit their needs
+ CAI_ScheduleBits m_ConditionsPreIgnore;
+ CAI_ScheduleBits m_InverseIgnoreConditions;
+
+ bool m_bForceConditionsGather;
+ bool m_bConditionsGathered;
+ bool m_bSkippedChooseEnemy;
+
+public:
+ //-----------------------------------------------------
+ //
+ // NPC State
+ //
+ //-----------------------------------------------------
+ inline void SetIdealState( NPC_STATE eIdealState );
+ inline NPC_STATE GetIdealState();
+ virtual NPC_STATE SelectIdealState( void );
+
+ void SetState( NPC_STATE State );
+ virtual bool ShouldGoToIdleState( void ) { return ( false ); }
+ virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) {/*Base class doesn't care*/};
+
+ NPC_STATE GetState( void ) { return m_NPCState; }
+
+ AI_Efficiency_t GetEfficiency() const { return m_Efficiency; }
+ void SetEfficiency( AI_Efficiency_t efficiency ) { m_Efficiency = efficiency; }
+ AI_MoveEfficiency_t GetMoveEfficiency() const { return m_MoveEfficiency; }
+ void SetMoveEfficiency( AI_MoveEfficiency_t efficiency ) { m_MoveEfficiency = efficiency; }
+ virtual void UpdateEfficiency( bool bInPVS );
+ void ForceDecisionThink() { m_flNextDecisionTime = 0; SetEfficiency( AIE_NORMAL ); }
+
+ bool IsFlaggedEfficient() const { return HasSpawnFlags( SF_NPC_START_EFFICIENT ); }
+
+ AI_SleepState_t GetSleepState() const { return m_SleepState; }
+ void SetSleepState( AI_SleepState_t sleepState ) { m_SleepState = sleepState; }
+ void AddSleepFlags( int flags ) { m_SleepFlags |= flags; }
+ void RemoveSleepFlags( int flags ) { m_SleepFlags &= ~flags; }
+ bool HasSleepFlags( int flags ) { return (m_SleepFlags & flags) == flags; }
+
+ void UpdateSleepState( bool bInPVS );
+ virtual void Wake( bool bFireOutput = true );
+ void Sleep();
+ bool WokeThisTick() const;
+
+ //---------------------------------
+
+ NPC_STATE m_NPCState; // npc's current state
+ float m_flLastStateChangeTime;
+
+private:
+ NPC_STATE m_IdealNPCState; // npc should change to this state
+ AI_Efficiency_t m_Efficiency;
+ AI_MoveEfficiency_t m_MoveEfficiency;
+ float m_flNextDecisionTime;
+
+ AI_SleepState_t m_SleepState;
+ int m_SleepFlags;
+ float m_flWakeRadius;
+ bool m_bWakeSquad;
+ int m_nWakeTick;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Activities
+ //
+ //-----------------------------------------------------
+
+ Activity TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity = NULL );
+ Activity NPC_TranslateActivity( Activity eNewActivity );
+ Activity GetActivity( void ) { return m_Activity; }
+ virtual void SetActivity( Activity NewActivity );
+ Activity GetIdealActivity( void ) { return m_IdealActivity; }
+ void SetIdealActivity( Activity NewActivity );
+ void ResetIdealActivity( Activity newIdealActivity );
+ void SetSequenceByName( const char *szSequence );
+ void SetSequenceById( int iSequence );
+ Activity GetScriptCustomMoveActivity( void );
+ int GetScriptCustomMoveSequence( void );
+ Activity GetStoppedActivity( void );
+ inline bool HaveSequenceForActivity( Activity activity );
+ inline bool IsActivityStarted(void);
+ virtual bool IsActivityFinished( void );
+ virtual bool IsActivityMovementPhased( Activity activity );
+ virtual void OnChangeActivity( Activity eNewActivity );
+ void MaintainActivity(void);
+ void ResetActivity(void) { m_Activity = ACT_RESET; }
+
+ void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity);
+
+private:
+
+ void AdvanceToIdealActivity(void);
+ void ResolveActivityToSequence(Activity NewActivity, int &iSequence, Activity &translatedActivity, Activity &weaponActivity);
+
+ Activity m_Activity; // Current animation state
+ Activity m_translatedActivity; // Current actual translated animation
+
+ Activity m_IdealActivity; // Desired animation state
+ int m_nIdealSequence; // Desired animation sequence
+ Activity m_IdealTranslatedActivity; // Desired actual translated animation state
+ Activity m_IdealWeaponActivity; // Desired weapon animation state
+
+ CNetworkVar(int, m_iDeathPose );
+ CNetworkVar(int, m_iDeathFrame );
+
+public:
+ //-----------------------------------------------------
+ //
+ // Senses
+ //
+ //-----------------------------------------------------
+
+ CAI_Senses * GetSenses() { return m_pSenses; }
+ const CAI_Senses * GetSenses() const { return m_pSenses; }
+
+ void SetDistLook( float flDistLook );
+
+ virtual bool QueryHearSound( CSound *pSound );
+ virtual bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false );
+
+ virtual void OnLooked( int iDistance );
+ virtual void OnListened();
+
+ virtual void OnSeeEntity( CBaseEntity *pEntity ) {}
+
+ // If true, AI will try to see this entity regardless of distance.
+ virtual bool ShouldNotDistanceCull() { return false; }
+
+ virtual int GetSoundInterests( void );
+ virtual int GetSoundPriority( CSound *pSound );
+
+ CSound * GetLoudestSoundOfType( int iType );
+ virtual CSound * GetBestSound( int validTypes = ALL_SOUNDS );
+ virtual CSound * GetBestScent( void );
+ virtual float HearingSensitivity( void ) { return 1.0; }
+ virtual bool ShouldIgnoreSound( CSound * ) { return false; }
+ bool SoundIsVisible( CSound *pSound );
+
+protected:
+ virtual void ClearSenseConditions( void );
+
+private:
+ void LockBestSound();
+ void UnlockBestSound();
+
+ CAI_Senses * m_pSenses;
+ CSound * m_pLockedBestSound;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Enemy and target
+ //
+ //-----------------------------------------------------
+
+ Vector GetSmoothedVelocity( void );
+
+ CBaseEntity* GetEnemy() { return m_hEnemy.Get(); }
+ CBaseEntity* GetEnemy() const { return m_hEnemy.Get(); }
+ float GetTimeEnemyAcquired() { return m_flTimeEnemyAcquired; }
+ void SetEnemy( CBaseEntity *pEnemy, bool bSetCondNewEnemy = true );
+
+ const Vector & GetEnemyLKP() const;
+ float GetEnemyLastTimeSeen() const;
+ void MarkEnemyAsEluded();
+ void ClearEnemyMemory();
+ bool EnemyHasEludedMe() const;
+
+ virtual CBaseEntity *BestEnemy(); // returns best enemy in memory list
+ virtual bool IsValidEnemy( CBaseEntity *pEnemy );
+ virtual bool CanBeAnEnemyOf( CBaseEntity *pEnemy );
+
+ void ForceChooseNewEnemy() { m_EnemiesSerialNumber = -1; }
+
+ bool ChooseEnemy();
+ virtual bool ShouldChooseNewEnemy();
+ virtual void GatherEnemyConditions( CBaseEntity *pEnemy );
+ virtual float EnemyDistTolerance() { return 0; } // Enemy distances within this tolerance of each other are considered equivalent.
+
+ float EnemyDistance( CBaseEntity *pEnemy );
+ CBaseCombatCharacter *GetEnemyCombatCharacterPointer();
+ void SetEnemyOccluder(CBaseEntity *pBlocker);
+ CBaseEntity *GetEnemyOccluder(void);
+
+ virtual void StartTargetHandling( CBaseEntity *pTargetEnt );
+
+ //---------------------------------
+
+ CBaseEntity* GetTarget() { return m_hTargetEnt.Get(); }
+ void SetTarget( CBaseEntity *pTarget );
+ void CheckTarget( CBaseEntity *pTarget );
+ float GetAcceptableTimeSeenEnemy( void ) { return m_flAcceptableTimeSeenEnemy; }
+ virtual CAI_BaseNPC *CreateCustomTarget( const Vector &vecOrigin, float duration = -1 );
+
+ void SetDeathPose( const int &iDeathPose ) { m_iDeathPose = iDeathPose; }
+ void SetDeathPoseFrame( const int &iDeathPoseFrame ) { m_iDeathFrame = iDeathPoseFrame; }
+
+ void SelectDeathPose( const CTakeDamageInfo &info );
+ virtual bool ShouldPickADeathPose( void ) { return true; }
+
+ virtual bool AllowedToIgnite( void ) { return false; }
+
+protected:
+ virtual float GetGoalRepathTolerance( CBaseEntity *pGoalEnt, GoalType_t type, const Vector &curGoal, const Vector &curTargetPos );
+
+private:
+ void * CheckEnemy( CBaseEntity *pEnemy ) { return NULL; } // OBSOLETE, replaced by GatherEnemyConditions(), left here to make derived code not compile
+
+ // Updates the goal position in case of GOALTYPE_ENEMY
+ void UpdateEnemyPos();
+
+ // Updates the goal position in case of GOALTYPE_TARGETENT
+ void UpdateTargetPos();
+
+ //---------------------------------
+
+ EHANDLE m_hEnemy; // the entity that the npc is fighting.
+ float m_flTimeEnemyAcquired; // The time at which the entity the NPC is fighting became the NPC's enemy.
+ EHANDLE m_hTargetEnt; // the entity that the npc is trying to reach
+
+ CRandStopwatch m_GiveUpOnDeadEnemyTimer;
+ CSimpleSimTimer m_FailChooseEnemyTimer;
+ int m_EnemiesSerialNumber;
+
+ float m_flAcceptableTimeSeenEnemy;
+
+ CSimpleSimTimer m_UpdateEnemyPosTimer;
+ static CSimpleSimTimer m_AnyUpdateEnemyPosTimer;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Commander mode stuff.
+ //
+ //-----------------------------------------------------
+ virtual bool IsCommandable() { return false; }
+ virtual bool IsPlayerAlly( CBasePlayer *pPlayer = NULL );
+ virtual bool IsMedic() { return false; }
+ virtual bool IsCommandMoving() { return false; }
+ virtual bool ShouldAutoSummon() { return false; }
+ virtual void SetCommandGoal( const Vector &vecGoal );
+ virtual void ClearCommandGoal();
+ virtual void OnTargetOrder() {}
+ virtual void OnMoveOrder() {}
+ virtual bool IsValidCommandTarget( CBaseEntity *pTarget ) { return false; }
+ const Vector &GetCommandGoal() const { return m_vecCommandGoal; }
+ virtual void OnMoveToCommandGoalFailed() {}
+ string_t GetPlayerSquadName() const { Assert( gm_iszPlayerSquad != NULL_STRING ); return gm_iszPlayerSquad; }
+ bool IsInPlayerSquad() const;
+ virtual CAI_BaseNPC *GetSquadCommandRepresentative() { return NULL; }
+
+ virtual bool TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ) { OnTargetOrder(); return true; }
+ virtual void MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ) { SetCommandGoal( vecDest ); SetCondition( COND_RECEIVED_ORDERS ); OnMoveOrder(); }
+
+ // Return true if you're willing to be idly talked to by other friends.
+ virtual bool CanBeUsedAsAFriend( void );
+
+
+private:
+ Vector m_vecCommandGoal;
+ static string_t gm_iszPlayerSquad;
+
+public:
+ CAI_MoveMonitor m_CommandMoveMonitor;
+
+ //-----------------------------------------------------
+ // Dynamic scripted NPC interactions
+ //-----------------------------------------------------
+public:
+ float GetInteractionYaw( void ) const { return m_flInteractionYaw; }
+
+protected:
+ void ParseScriptedNPCInteractions( void );
+ void AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction );
+ const char *GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase );
+ void StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive );
+ void StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles );
+ void CheckForScriptedNPCInteractions( void );
+ void CalculateValidEnemyInteractions( void );
+ void CheckForcedNPCInteractions( void );
+ bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
+ virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
+ bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
+ bool IsActiveDynamicInteraction( void ) { return (m_iInteractionState == NPCINT_RUNNING_ACTIVE && (m_hCine != NULL)); }
+ ScriptedNPCInteraction_t *GetRunningDynamicInteraction( void ) { return &(m_ScriptedInteractions[m_iInteractionPlaying]); }
+ void SetInteractionCantDie( bool bCantDie ) { m_bCannotDieDuringInteraction = bCantDie; }
+ bool HasInteractionCantDie( void );
+
+ void InputForceInteractionWithNPC( inputdata_t &inputdata );
+ void StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction );
+ void CleanupForcedInteraction( void );
+ void CalculateForcedInteractionPosition( void );
+ CAI_BaseNPC *GetInteractionPartner( void );
+
+private:
+ // Forced interactions
+ CHandle<CAI_BaseNPC> m_hForcedInteractionPartner;
+ Vector m_vecForcedWorldPosition;
+ float m_flForcedInteractionTimeout; // Abort the interaction if it hasn't started by this time.
+
+ CHandle<CAI_BaseNPC> m_hInteractionPartner;
+ EHANDLE m_hLastInteractionTestTarget;
+ bool m_bCannotDieDuringInteraction;
+ int m_iInteractionState;
+ int m_iInteractionPlaying;
+ CUtlVector<ScriptedNPCInteraction_t> m_ScriptedInteractions;
+
+ float m_flInteractionYaw;
+
+
+public:
+ //-----------------------------------------------------
+ //
+ // Sounds
+ //
+ //-----------------------------------------------------
+ virtual CanPlaySequence_t CanPlaySequence( bool fDisregardState, int interruptLevel );
+
+ virtual bool CanPlaySentence( bool fDisregardState ) { return IsAlive(); }
+ virtual int PlaySentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener = NULL );
+ virtual int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener );
+
+ virtual bool FOkToMakeSound( int soundPriority = 0 );
+ virtual void JustMadeSound( int soundPriority = 0, float flSoundLength = 0.0f );
+
+ virtual void DeathSound( const CTakeDamageInfo &info ) { return; };
+ virtual void AlertSound( void ) { return; };
+ virtual void IdleSound( void ) { return; };
+ virtual void PainSound( const CTakeDamageInfo &info ) { return; };
+ virtual void FearSound( void ) { return; };
+ virtual void LostEnemySound( void ) { return; };
+ virtual void FoundEnemySound( void ) { return; };
+ virtual void BarnacleDeathSound( void ) { CTakeDamageInfo info; PainSound( info ); }
+
+ virtual void SpeakSentence( int sentenceType ) { return; };
+ virtual bool ShouldPlayIdleSound( void );
+
+ virtual void MakeAIFootstepSound( float volume, float duration = 0.5f );
+
+ //---------------------------------
+
+ virtual CAI_Expresser *GetExpresser() { return NULL; }
+ const CAI_Expresser *GetExpresser() const { return const_cast<CAI_BaseNPC *>(this)->GetExpresser(); }
+
+ //---------------------------------
+ // NPC Event Response System
+ virtual bool CanRespondToEvent( const char *ResponseConcept ) { return false; }
+ virtual bool RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene ) { return false; }
+
+ virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
+
+ virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
+
+protected:
+ float SoundWaitTime() const { return m_flSoundWaitTime; }
+
+public:
+ //-----------------------------------------------------
+ //
+ // Capabilities report (from CBaseCombatCharacter)
+ //
+ //-----------------------------------------------------
+ virtual int CapabilitiesGet( void ) const;
+
+ // local capabilities access
+ int CapabilitiesAdd( int capabilities );
+ int CapabilitiesRemove( int capabilities );
+ void CapabilitiesClear( void );
+
+private:
+ int m_afCapability; // tells us what a npc can/can't do.
+
+public:
+ //-----------------------------------------------------
+ //
+ // Pathfinding, navigation & movement
+ //
+ //-----------------------------------------------------
+
+ CAI_Navigator * GetNavigator() { return m_pNavigator; }
+ const CAI_Navigator *GetNavigator() const { return m_pNavigator; }
+
+ CAI_LocalNavigator *GetLocalNavigator() { return m_pLocalNavigator; }
+ const CAI_LocalNavigator *GetLocalNavigator() const { return m_pLocalNavigator; }
+
+ CAI_Pathfinder * GetPathfinder() { return m_pPathfinder; }
+ const CAI_Pathfinder *GetPathfinder() const { return m_pPathfinder; }
+
+ CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; }
+ const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; }
+
+ CAI_Motor * GetMotor() { return m_pMotor; }
+ const CAI_Motor * GetMotor() const { return m_pMotor; }
+
+ //---------------------------------
+
+ static bool FindSpotForNPCInRadius( Vector *pResult, const Vector &vStartPos, CAI_BaseNPC *pNPC, float radius, bool bOutOfPlayerViewcone = false );
+
+ //---------------------------------
+
+ virtual bool IsNavigationUrgent();
+ virtual bool ShouldFailNav( bool bMovementFailed );
+ virtual bool ShouldBruteForceFailedNav() { return false; }
+
+ // The current navigation (movement) mode (e.g. fly, swim, locomote, etc)
+ Navigation_t GetNavType() const;
+ void SetNavType( Navigation_t navType );
+
+ CBaseEntity * GetNavTargetEntity(void);
+
+ bool IsMoving( void );
+ virtual float GetTimeToNavGoal();
+
+ // NPCs can override this to tweak with how costly particular movements are
+ virtual bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost );
+
+ // Turns a directional vector into a yaw value that points down that vector.
+ float VecToYaw( const Vector &vecDir );
+
+ // Turning
+ virtual float CalcIdealYaw( const Vector &vecTarget );
+ virtual float MaxYawSpeed( void ); // Get max yaw speed
+ bool FacingIdeal( void );
+ void SetUpdatedYaw() { m_ScheduleState.bTaskUpdatedYaw = true; }
+
+ // Add multiple facing goals while moving/standing still.
+ virtual void AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 );
+ virtual void AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
+ virtual void AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
+ virtual float GetFacingDirection( Vector &vecDir );
+
+ // ------------
+ // Methods used by motor to query properties/preferences/move-related state
+ // ------------
+ virtual bool CanStandOn( CBaseEntity *pSurface ) const;
+
+ virtual bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; // Override for specific creature types
+ bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const;
+ bool ShouldMoveWait();
+ virtual float StepHeight() const { return 18.0f; }
+ float GetStepDownMultiplier() const;
+ virtual float GetMaxJumpSpeed() const { return 350.0f; }
+ virtual float GetJumpGravity() const { return 1.0f; }
+
+ //---------------------------------
+
+ virtual bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so)
+ virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval );
+
+ //---------------------------------
+
+ virtual bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior
+ virtual bool ValidateNavGoal();
+ virtual bool IsCurTaskContinuousMove();
+ virtual bool IsValidMoveAwayDest( const Vector &vecDest ) { return true; }
+
+ //---------------------------------
+ //
+ // Notifications from navigator
+ //
+ virtual void OnMovementFailed() {};
+ virtual void OnMovementComplete() {};
+
+ //---------------------------------
+
+ bool FindNearestValidGoalPos( const Vector &vTestPoint, Vector *pResult );
+
+ void RememberUnreachable( CBaseEntity* pEntity, float duration = -1 ); // Remember that entity is unreachable
+ virtual bool IsUnreachable( CBaseEntity* pEntity ); // Is entity is unreachable?
+
+ //---------------------------------
+ // Inherited from IAI_MotorMovementServices
+ virtual float CalcYawSpeed( void );
+
+ virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal,
+ float distClear,
+ AIMoveResult_t *pResult );
+
+ virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal,
+ float distClear,
+ AIMoveResult_t *pResult );
+
+ // Translations of the above into some useful game terms
+ virtual bool OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal,
+ CBaseDoor *pDoor,
+ float distClear,
+ AIMoveResult_t *pResult );
+
+ virtual bool OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal,
+ CBasePropDoor *pDoor,
+ float distClear,
+ AIMoveResult_t *pResult );
+
+ void OpenPropDoorBegin( CBasePropDoor *pDoor );
+ void OpenPropDoorNow( CBasePropDoor *pDoor );
+
+ //---------------------------------
+
+ void DelayMoveStart( float delay ) { m_flMoveWaitFinished = gpGlobals->curtime + delay; }
+
+ float m_flMoveWaitFinished;
+
+
+ //
+ // Stuff for opening doors.
+ //
+ void OnDoorFullyOpen(CBasePropDoor *pDoor);
+ void OnDoorBlocked(CBasePropDoor *pDoor);
+ CHandle<CBasePropDoor> m_hOpeningDoor; // The CBasePropDoor that we are in the midst of opening for navigation.
+
+protected:
+ // BRJ 4/11
+ // Semi-obsolete-looking Lars code I moved out of the engine and into here
+ int FlyMove( const Vector& vecPosition, unsigned int mask );
+ int WalkMove( const Vector& vecPosition, unsigned int mask );
+
+ // Unreachable Entities
+ CUtlVector<UnreachableEnt_t> m_UnreachableEnts; // Array of unreachable entities
+
+private:
+ CAI_Navigator * m_pNavigator;
+ CAI_LocalNavigator *m_pLocalNavigator;
+ CAI_Pathfinder * m_pPathfinder;
+ CAI_MoveProbe * m_pMoveProbe;
+ CAI_Motor * m_pMotor;
+
+ EHANDLE m_hGoalEnt; // path corner we are heading towards
+
+ float m_flTimeLastMovement;
+
+
+ CSimpleSimTimer m_CheckOnGroundTimer;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Eye position, view offset, head direction, eye direction
+ //
+ //-----------------------------------------------------
+
+ void SetDefaultEyeOffset ( void );
+ const Vector & GetDefaultEyeOffset( void ) { return m_vDefaultEyeOffset; }
+ virtual Vector GetNodeViewOffset() { return GetViewOffset(); }
+
+ virtual Vector EyeOffset( Activity nActivity );
+ virtual Vector EyePosition( void );
+
+ //---------------------------------
+
+ virtual Vector HeadDirection2D( void );
+ virtual Vector HeadDirection3D( void );
+ virtual Vector EyeDirection2D( void );
+ virtual Vector EyeDirection3D( void );
+
+ virtual CBaseEntity *EyeLookTarget( void ); // Overridden by subclass to force look at an entity
+ virtual void AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ) { };
+ virtual void AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ) { };
+ virtual void SetHeadDirection( const Vector &vTargetPos, float flInterval );
+ virtual void MaintainLookTargets( float flInterval );
+ virtual bool ValidEyeTarget(const Vector &lookTargetPos);
+
+ virtual Vector FacingPosition( void ) { return EyePosition(); }; // position that other npc's use when facing you
+
+ virtual void MaintainTurnActivity( void );
+
+ virtual bool FInAimCone( const Vector &vecSpot );
+ virtual void AimGun();
+ virtual void SetAim( const Vector &aimDir );
+ virtual void RelaxAim( void );
+ virtual CBaseEntity *GetAlternateMoveShootTarget() { return NULL; }
+
+protected:
+ Vector m_vDefaultEyeOffset;
+ float m_flNextEyeLookTime; // Next time a pick a new place to look
+
+ float m_flEyeIntegRate; // How fast does eye move to target
+
+private:
+ Vector m_vEyeLookTarget; // Where I want to be looking
+ Vector m_vCurEyeTarget; // Direction I'm looking at
+ EHANDLE m_hEyeLookTarget; // What I want to be looking at
+ float m_flHeadYaw; // Current head yaw
+ float m_flHeadPitch; // Current head pitch
+protected:
+ float m_flOriginalYaw; // This is the direction facing when the level designer placed the NPC in the level.
+
+public:
+ //-----------------------------------------------------
+ // Mapmaker Scripting
+ //
+ // Set when the NPC is being scripted by a mapmaker, and
+ // shouldn't be responding to external stimuli that would
+ // break him out of his "script". NOT a scripted sequence.
+ //-----------------------------------------------------
+ inline bool IsInAScript( void ) { return m_bInAScript; }
+ inline void SetInAScript( bool bScript ) { m_bInAScript = bScript; }
+ void InputStartScripting( inputdata_t &inputdata ) { m_bInAScript = true; }
+ void InputStopScripting( inputdata_t &inputdata ) { m_bInAScript = false; }
+
+ void InputGagEnable( inputdata_t &inputdata ) { AddSpawnFlags(SF_NPC_GAG); }
+ void InputGagDisable( inputdata_t &inputdata ) { RemoveSpawnFlags(SF_NPC_GAG); }
+
+ bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt);
+
+ virtual void InputOutsideTransition( inputdata_t &inputdata );
+ virtual void InputInsideTransition( inputdata_t &inputdata );
+
+ void CleanupScriptsOnTeleport( bool bEnrouteAsWell );
+
+ virtual void SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt );
+
+private:
+ bool m_bInAScript;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Scripting
+ //
+ //-----------------------------------------------------
+
+ // Scripted sequence Info
+ enum SCRIPTSTATE
+ {
+ SCRIPT_PLAYING = 0, // Playing the action animation.
+ SCRIPT_WAIT, // Waiting on everyone in the script to be ready. Plays the pre idle animation if there is one.
+ SCRIPT_POST_IDLE, // Playing the post idle animation after playing the action animation.
+ SCRIPT_CLEANUP, // Cancelling the script / cleaning up.
+ SCRIPT_WALK_TO_MARK, // Walking to the scripted sequence position.
+ SCRIPT_RUN_TO_MARK, // Running to the scripted sequence position.
+ SCRIPT_CUSTOM_MOVE_TO_MARK, // Moving to the scripted sequence position while playing a custom movement animation.
+ };
+
+ bool ExitScriptedSequence();
+ bool CineCleanup();
+
+ virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
+
+ // forces movement and sets a new schedule
+ virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
+ virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
+
+ static void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun);
+ static void ForceSelectedGoRandom(void);
+
+ bool AutoMovement( CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL );
+ bool AutoMovement( float flInterval, CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL );
+ bool TaskRanAutomovement( void ) { return m_ScheduleState.bTaskRanAutomovement; }
+
+ SCRIPTSTATE m_scriptState; // internal cinematic state
+ CHandle<CAI_ScriptedSequence> m_hCine;
+ Activity m_ScriptArrivalActivity;
+ string_t m_strScriptArrivalSequence;
+
+ //-----------------------------------------------------
+ //
+ // Scenes
+ //
+ //-----------------------------------------------------
+
+ void AddSceneLock( float flDuration = 0.2f ) { m_flSceneTime = MAX( gpGlobals->curtime + flDuration, m_flSceneTime ); };
+ void ClearSceneLock( float flDuration = 0.2f ) { m_flSceneTime = gpGlobals->curtime + flDuration; };
+ bool IsInLockedScene( void ) { return m_flSceneTime > gpGlobals->curtime; };
+ float m_flSceneTime;
+ string_t m_iszSceneCustomMoveSeq;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Memory
+ //
+ //-----------------------------------------------------
+
+ inline void Remember( int iMemory ) { m_afMemory |= iMemory; }
+ inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; }
+ inline bool HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; }
+ inline bool HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; }
+
+ virtual CAI_Enemies *GetEnemies( void );
+ virtual void RemoveMemory( void );
+
+ virtual bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL );
+ virtual float GetReactionDelay( CBaseEntity *pEnemy );
+
+ void SetLastAttackTime( float time) { m_flLastAttackTime = time; }
+
+ float GetLastAttackTime() const { return m_flLastAttackTime; }
+ float GetLastDamageTime() const { return m_flLastDamageTime; }
+ float GetLastPlayerDamageTime() const { return m_flLastPlayerDamageTime; }
+ float GetLastEnemyTime() const { return m_flLastEnemyTime; }
+
+ // Set up the shot regulator based on the equipped weapon
+ virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon );
+
+ // Weapon holstering
+ virtual bool CanHolsterWeapon( void );
+ virtual int HolsterWeapon( void );
+ virtual int UnholsterWeapon( void );
+ void InputHolsterWeapon( inputdata_t &inputdata );
+ void InputHolsterAndDestroyWeapon( inputdata_t &inputdata );
+ void InputUnholsterWeapon( inputdata_t &inputdata );
+ bool IsWeaponHolstered( void );
+ bool IsWeaponStateChanging( void );
+ void SetDesiredWeaponState( DesiredWeaponState_t iState ) { m_iDesiredWeaponState = iState; }
+
+ // NOTE: The Shot Regulator is used to manage the RangeAttack1 weapon.
+ inline CAI_ShotRegulator* GetShotRegulator() { return &m_ShotRegulator; }
+ virtual void OnRangeAttack1();
+
+protected:
+ // Shot regulator code
+ virtual void OnUpdateShotRegulator( );
+
+protected:
+ CAI_Enemies * m_pEnemies; // Holds information about enemies / danger positions / shared between sqaud members
+ int m_afMemory;
+ EHANDLE m_hEnemyOccluder; // The entity my enemy is hiding behind.
+
+ float m_flSumDamage; // How much consecutive damage I've received
+ float m_flLastDamageTime; // Last time I received damage
+ float m_flLastPlayerDamageTime; // Last time I received damage from the player
+ float m_flLastSawPlayerTime; // Last time I saw the player
+ float m_flLastAttackTime; // Last time that I attacked my current enemy
+ float m_flLastEnemyTime;
+ float m_flNextWeaponSearchTime; // next time to search for a better weapon
+ string_t m_iszPendingWeapon; // THe NPC should create and equip this weapon.
+ bool m_bIgnoreUnseenEnemies;
+
+private:
+ CAI_ShotRegulator m_ShotRegulator; // When should I shoot next?
+
+ DesiredWeaponState_t m_iDesiredWeaponState;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Squads & tactics
+ //
+ //-----------------------------------------------------
+
+ virtual bool InitSquad( void );
+
+ virtual const char* SquadSlotName(int slotID) { return gm_SquadSlotNamespace.IdToSymbol(slotID); }
+ bool OccupyStrategySlot( int squadSlotID );
+ bool OccupyStrategySlotRange( int slotIDStart, int slotIDEnd );
+ bool HasStrategySlot( int squadSlotID );
+ bool HasStrategySlotRange( int slotIDStart, int slotIDEnd );
+ int GetMyStrategySlot() { return m_iMySquadSlot; }
+ void VacateStrategySlot( void );
+ bool IsStrategySlotRangeOccupied( int slotIDStart, int slotIDEnd ); // Returns true if all in the range are occupied
+
+ CAI_Squad * GetSquad() { return m_pSquad; }
+ virtual void SetSquad( CAI_Squad *pSquad );
+ void AddToSquad( string_t name );
+ void RemoveFromSquad();
+ void CheckSquad();
+ void SetSquadName( string_t name ) { m_SquadName = name; }
+ bool IsInSquad() const { return m_pSquad != NULL; }
+ virtual bool IsSilentSquadMember() const { return false; }
+
+ int NumWeaponsInSquad( const char *pszWeaponClassname );
+
+ string_t GetHintGroup( void ) { return m_strHintGroup; }
+ void ClearHintGroup( void ) { SetHintGroup( NULL_STRING ); }
+ void SetHintGroup( string_t name, bool bHintGroupNavLimiting = false );
+ bool IsLimitingHintGroups( void ) { return m_bHintGroupNavLimiting; }
+
+ //---------------------------------
+
+ CAI_TacticalServices *GetTacticalServices() { return m_pTacticalServices; }
+ const CAI_TacticalServices *GetTacticalServices() const { return m_pTacticalServices; }
+
+ //---------------------------------
+ // Cover
+
+ virtual bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult );
+ virtual bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult );
+ virtual bool FindCoverPos( CSound *pSound, Vector *pResult );
+ virtual bool IsValidCover ( const Vector &vecCoverLocation, CAI_Hint const *pHint );
+ virtual bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint );
+ virtual bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ) { return WeaponLOSCondition( vecShootPos, targetPos, false ); }
+ virtual bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition );
+ virtual float CoverRadius( void ) { return 1024; } // Default cover radius
+ virtual float GetMaxTacticalLateralMovement( void ) { return MAXTACLAT_IGNORE; }
+
+protected:
+ virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {}
+
+ CAI_Squad * m_pSquad; // The squad that I'm on
+ string_t m_SquadName;
+
+ int m_iMySquadSlot; // this is the behaviour slot that the npc currently holds in the squad.
+
+private:
+ string_t m_strHintGroup;
+ bool m_bHintGroupNavLimiting;
+ CAI_TacticalServices *m_pTacticalServices;
+
+public:
+ //-----------------------------------------------------
+ //
+ // Base schedule & task support; Miscellaneous
+ //
+ //-----------------------------------------------------
+
+ void InitRelationshipTable( void );
+ void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator );
+
+ virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
+ virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority );
+
+ void NPCUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+
+ CBaseGrenade* IncomingGrenade(void);
+
+ virtual bool ShouldFadeOnDeath( void );
+
+ void NPCInitDead( void ); // Call after animation/pose is set up
+ void CorpseFallThink( void );
+
+ float ThrowLimit( const Vector &vecStart, const Vector &vecEnd, float fGravity, float fArcSize, const Vector &mins, const Vector &maxs, CBaseEntity *pTarget, Vector *jumpVel, CBaseEntity **pBlocker);
+
+ // these functions will survey conditions and set appropriate conditions bits for attack types.
+ virtual int RangeAttack1Conditions( float flDot, float flDist );
+ virtual int RangeAttack2Conditions( float flDot, float flDist );
+ virtual int MeleeAttack1Conditions( float flDot, float flDist );
+ virtual int MeleeAttack2Conditions( float flDot, float flDist );
+
+ virtual float InnateRange1MinRange( void ) { return 0.0f; }
+ virtual float InnateRange1MaxRange( void ) { return FLT_MAX; }
+
+ virtual bool OnBeginMoveAndShoot( void ) { return true; }
+ virtual void OnEndMoveAndShoot( void ) {}
+
+ virtual bool UseAttackSquadSlots() { return false; }
+
+ //---------------------------------
+
+ virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
+
+ //---------------------------------
+ // States
+ //---------------------------------
+
+ virtual void ClearAttackConditions( void );
+ void GatherAttackConditions( CBaseEntity *pTarget, float flDist );
+ virtual bool ShouldLookForBetterWeapon();
+ bool Weapon_IsBetterAvailable ( void ) ;
+ virtual Vector Weapon_ShootPosition( void );
+ virtual void GiveWeapon( string_t iszWeaponName );
+ virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) { }
+ bool IsMovingToPickupWeapon();
+ virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
+ virtual bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions) { return WeaponLOSCondition( GetAbsOrigin(), targetPos, bSetConditions ); }
+ virtual bool IsWaitingToRappel( void ) { return false; }
+ virtual void BeginRappel() {}
+
+ // override to change the chase location of an enemy
+ // This is where your origin should go when you are chasing pEnemy when his origin is at chasePosition
+ // by default, leave this alone to make your origin coincide with his.
+ virtual void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition);
+ virtual float GetDefaultNavGoalTolerance() { return (GetHullWidth() * 2.0); }
+
+ virtual bool FCanCheckAttacks ( void );
+ virtual void CheckAmmo( void ) {}
+
+ virtual bool FValidateHintType( CAI_Hint *pHint );
+ virtual Activity GetHintActivity( short sHintType, Activity HintsActivity );
+ virtual float GetHintDelay( short sHintType );
+ virtual Activity GetCoverActivity( CAI_Hint* pHint );
+ virtual Activity GetReloadActivity( CAI_Hint* pHint );
+
+ virtual void SetTurnActivity( void );
+ bool UpdateTurnGesture( void );
+
+ // Returns the time when the door will be open
+ float OpenDoorAndWait( CBaseEntity *pDoor );
+
+ bool BBoxFlat( void );
+
+ //---------------------------------
+
+ virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
+ virtual bool PassesDamageFilter( const CTakeDamageInfo &info );
+
+ //---------------------------------
+
+ void MakeDamageBloodDecal( int cCount, float flNoise, trace_t *ptr, Vector vecDir );
+ virtual float GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info );
+ void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
+ void DecalTrace( trace_t *pTrace, char const *decalName );
+ void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName );
+ virtual bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers = true );
+ CBaseEntity * PlayerInRange( const Vector &vecLocation, float flDist );
+ bool PointInSpread( CBaseCombatCharacter *pCheckEntity, const Vector &sourcePos, const Vector &targetPos, const Vector &testPoint, float flSpread, float maxDistOffCenter );
+ bool IsSquadmateInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter );
+
+ //---------------------------------
+ // combat functions
+ //---------------------------------
+ virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions );
+
+ virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
+
+ virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class
+ virtual bool Event_Gibbed( const CTakeDamageInfo &info );
+ virtual void Event_Killed( const CTakeDamageInfo &info );
+
+ virtual Vector GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy = true );
+#ifdef HL2_DLL
+ virtual Vector GetActualShootPosition( const Vector &shootOrigin );
+ virtual Vector GetActualShootTrajectory( const Vector &shootOrigin );
+ virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL );
+ virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget );
+#endif //HL2_DLL
+ virtual void CollectShotStats( const Vector &vecShootOrigin, const Vector &vecShootDir );
+ virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
+ virtual Vector GetAutoAimCenter() { return BodyTarget(vec3_origin, false); }
+ virtual void FireBullets( const FireBulletsInfo_t &info );
+
+ // OLD VERSION! Use the struct version
+ void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting,
+ const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4,
+ int firingEntID = -1, int attachmentID = -1, int iDamage = 0,
+ CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false );
+
+ virtual bool ShouldMoveAndShoot( void );
+
+ //---------------------------------
+ // Damage
+ //---------------------------------
+ virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info );
+ virtual int OnTakeDamage_Dead( const CTakeDamageInfo &info );
+
+ virtual void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity );
+ virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker );
+
+ virtual bool IsLightDamage( const CTakeDamageInfo &info );
+ virtual bool IsHeavyDamage( const CTakeDamageInfo &info );
+
+ void DoRadiusDamage( const CTakeDamageInfo &info, int iClassIgnore, CBaseEntity *pEntityIgnore );
+ void DoRadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, int iClassIgnore, CBaseEntity *pEntityIgnore );
+
+ //---------------------------------
+
+ virtual void PickupWeapon( CBaseCombatWeapon *pWeapon );
+ virtual void PickupItem( CBaseEntity *pItem ) { };
+ CBaseEntity* DropItem( const char *pszItemName, Vector vecPos, QAngle vecAng );// drop an item.
+
+
+ //---------------------------------
+ // Inputs
+ //---------------------------------
+ void InputSetRelationship( inputdata_t &inputdata );
+ void InputSetEnemyFilter( inputdata_t &inputdata );
+ void InputSetHealth( inputdata_t &inputdata );
+ void InputBeginRappel( inputdata_t &inputdata );
+ void InputSetSquad( inputdata_t &inputdata );
+ void InputWake( inputdata_t &inputdata );
+ void InputForgetEntity( inputdata_t &inputdata );
+ void InputIgnoreDangerSounds( inputdata_t &inputdata );
+ void InputUpdateEnemyMemory( inputdata_t &inputdata );
+
+ //---------------------------------
+
+ virtual void NotifyDeadFriend( CBaseEntity *pFriend ) { return; }
+
+ //---------------------------------
+ // Utility methods
+ static Vector CalcThrowVelocity(const Vector &startPos, const Vector &endPos, float fGravity, float fArcSize);
+
+ //---------------------------------
+
+ float SetWait( float minWait, float maxWait = 0.0 );
+ void ClearWait();
+ float GetWaitFinishTime() { return m_flWaitFinished; }
+ bool IsWaitFinished();
+ bool IsWaitSet();
+
+ CBaseEntity* GetGoalEnt() { return m_hGoalEnt; }
+ void SetGoalEnt( CBaseEntity *pGoalEnt ) { m_hGoalEnt.Set( pGoalEnt ); }
+
+ CAI_Hint *GetHintNode() { return m_pHintNode; }
+ const CAI_Hint *GetHintNode() const { return m_pHintNode; }
+ void SetHintNode( CAI_Hint *pHintNode );
+ void ClearHintNode( float reuseDelay = 0.0 );
+
+ float m_flWaitFinished; // if we're told to wait, this is the time that the wait will be over.
+
+ float m_flNextFlinchTime; // Time at which we'll flinch fully again (as opposed to just doing gesture flinches)
+ float m_flNextDodgeTime; // Time at which I can dodge again. Used so that the behavior doesn't happen over and over.
+
+ CAI_MoveAndShootOverlay m_MoveAndShootOverlay;
+
+ Vector m_vecLastPosition; // npc sometimes wants to return to where it started after an operation.
+ Vector m_vSavePosition; // position stored by code that called this schedules
+ Vector m_vInterruptSavePosition; // position stored by a task that was interrupted
+
+private:
+ CHandle<CAI_Hint> m_pHintNode; // this is the hint that the npc is moving towards or performing active idle on.
+
+public:
+ int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences)
+ float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in GatherEnemyConditions
+ string_t m_spawnEquipment;
+
+ bool m_fNoDamageDecal;
+
+ EHANDLE m_hStoredPathTarget; // For TASK_SET_GOAL
+ Vector m_vecStoredPathGoal; //
+ GoalType_t m_nStoredPathType; //
+ int m_fStoredPathFlags; //
+
+ CHandle<CBaseFilter> m_hEnemyFilter;
+ string_t m_iszEnemyFilterName;
+
+ bool m_bDidDeathCleanup;
+
+
+ IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_lifeState );
+
+ //---------------------------------
+ // Outputs
+ //---------------------------------
+ COutputEvent m_OnDamaged;
+ COutputEvent m_OnDeath;
+ COutputEvent m_OnHalfHealth;
+ COutputEHANDLE m_OnFoundEnemy;
+ COutputEvent m_OnLostEnemyLOS;
+ COutputEvent m_OnLostEnemy;
+ COutputEHANDLE m_OnFoundPlayer;
+ COutputEvent m_OnLostPlayerLOS;
+ COutputEvent m_OnLostPlayer;
+ COutputEvent m_OnHearWorld;
+ COutputEvent m_OnHearPlayer;
+ COutputEvent m_OnHearCombat;
+ COutputEvent m_OnDamagedByPlayer;
+ COutputEvent m_OnDamagedByPlayerSquad;
+ COutputEvent m_OnDenyCommanderUse;
+ COutputEvent m_OnRappelTouchdown;
+ COutputEvent m_OnSleep;
+ COutputEvent m_OnWake;
+ COutputEvent m_OnForcedInteractionStarted;
+ COutputEvent m_OnForcedInteractionAborted;
+ COutputEvent m_OnForcedInteractionFinished;
+
+public:
+ // use this to shrink the bbox temporarily
+ void SetHullSizeNormal( bool force = false );
+ bool SetHullSizeSmall( bool force = false );
+
+ bool IsUsingSmallHull() const { return m_fIsUsingSmallHull; }
+
+ const Vector & GetHullMins() const { return NAI_Hull::Mins(GetHullType()); }
+ const Vector & GetHullMaxs() const { return NAI_Hull::Maxs(GetHullType()); }
+ float GetHullWidth() const { return NAI_Hull::Width(GetHullType()); }
+ float GetHullHeight() const { return NAI_Hull::Height(GetHullType()); }
+
+ void SetupVPhysicsHull();
+ virtual void StartTouch( CBaseEntity *pOther );
+ void CheckPhysicsContacts();
+
+private:
+ void TryRestoreHull( void );
+ bool m_fIsUsingSmallHull;
+ bool m_bCheckContacts;
+
+private:
+ // Task implementation helpers
+ void StartTurn( float flDeltaYaw );
+ bool FindCoverFromEnemy( bool bNodesOnly = false, float flMinDistance = 0, float flMaxDistance = FLT_MAX );
+ bool FindCoverFromBestSound( Vector *pCoverPos );
+ void StartScriptMoveToTargetTask( int task );
+
+ void RunDieTask();
+ void RunAttackTask( int task );
+
+protected:
+ virtual float CalcReasonableFacing( bool bIgnoreOriginalFacing = false );
+ virtual bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ) { return true; }
+ virtual float GetReasonableFacingDist( void );
+
+public:
+ inline int UsableNPCObjectCaps( int baseCaps )
+ {
+ if ( IsAlive() )
+ baseCaps |= FCAP_IMPULSE_USE;
+ return baseCaps;
+ }
+
+ virtual int ObjectCaps() { return (BaseClass::ObjectCaps() | FCAP_NOTIFY_ON_TRANSITION); }
+
+ //-----------------------------------------------------
+ //
+ // Core mapped data structures
+ //
+ // String Registries for default AI Shared by all CBaseNPCs
+ // These are used only during initialization and in debug
+ //-----------------------------------------------------
+
+ static void InitSchedulingTables();
+
+ static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return &gm_SchedulingSymbols; }
+ static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; }
+ virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; }
+
+ static int GetScheduleID (const char* schedName);
+ static int GetActivityID (const char* actName);
+ static int GetConditionID (const char* condName);
+ static int GetTaskID (const char* taskName);
+ static int GetSquadSlotID (const char* slotName);
+ virtual const char* GetSquadSlotDebugName( int iSquadSlot );
+ static const char* GetActivityName (int actID);
+
+ static void AddActivityToSR(const char *actName, int conID);
+
+ static void AddEventToSR(const char *eventName, int conID);
+ static const char* GetEventName (int actID);
+ static int GetEventID (const char* actName);
+
+public:
+ //-----------------------------------------------------
+ // Crouch handling
+ //-----------------------------------------------------
+ bool CrouchIsDesired( void ) const;
+ virtual bool IsCrouching( void );
+ inline void ForceCrouch( void );
+ inline void ClearForceCrouch( void );
+
+protected:
+ virtual bool Crouch( void );
+ virtual bool Stand( void );
+ virtual void DesireCrouch( void );
+ inline void DesireStand( void );
+ bool CouldShootIfCrouching( CBaseEntity *pTarget );
+ virtual bool IsCrouchedActivity( Activity activity );
+
+protected:
+ // Override these in your derived NPC class
+ virtual Vector GetCrouchEyeOffset( void ) { return Vector(0,0,40); }
+ virtual Vector GetCrouchGunOffset( void ) { return Vector(0,0,36); }
+
+private:
+ bool m_bCrouchDesired;
+ bool m_bForceCrouch;
+ bool m_bIsCrouching;
+ //-----------------------------------------------------
+
+ //-----------------------------------------------------
+ // ai_post_frame_navigation
+ //-----------------------------------------------------
+
+private:
+ bool m_bDeferredNavigation; // This NPCs has a navigation query that's being deferred until later in the frame
+
+public:
+ void SetNavigationDeferred( bool bState ) { m_bDeferredNavigation = bState; }
+ bool IsNavigationDeferred( void ) { return m_bDeferredNavigation; }
+
+ //-----------------------------------------------------
+protected:
+ static CAI_GlobalNamespace gm_SquadSlotNamespace;
+ static CAI_LocalIdSpace gm_SquadSlotIdSpace;
+
+private:
+ // Checks to see that the nav hull is valid for the NPC
+ bool IsNavHullValid() const;
+
+ friend class CAI_SystemHook;
+ friend class CAI_SchedulesManager;
+
+ static bool LoadDefaultSchedules(void);
+
+ static void InitDefaultScheduleSR(void);
+ static void InitDefaultTaskSR(void);
+ static void InitDefaultConditionSR(void);
+ static void InitDefaultActivitySR(void);
+ static void InitDefaultSquadSlotSR(void);
+
+ static CStringRegistry* m_pActivitySR;
+ static int m_iNumActivities;
+
+ static CStringRegistry* m_pEventSR;
+ static int m_iNumEvents;
+
+ static CAI_GlobalScheduleNamespace gm_SchedulingSymbols;
+ static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace;
+
+public:
+ //----------------------------------------------------
+ // Debugging tools
+ //
+
+ // -----------------------------
+ // Debuging Fields and Methods
+ // -----------------------------
+ const char* m_failText; // Text of why it failed
+ const char* m_interruptText; // Text of why schedule interrupted
+ CAI_Schedule* m_failedSchedule; // The schedule that failed last
+ CAI_Schedule* m_interuptSchedule; // The schedule that was interrupted last
+ int m_nDebugCurIndex; // Index used for stepping through AI
+ virtual void ReportAIState( void );
+ virtual void ReportOverThinkLimit( float time );
+ void DumpTaskTimings();
+ void DrawDebugGeometryOverlays(void);
+ virtual int DrawDebugTextOverlays(void);
+ void ToggleFreeze(void);
+
+ static void ClearAllSchedules(void);
+
+ static int m_nDebugBits;
+
+ static CAI_BaseNPC* m_pDebugNPC;
+ static int m_nDebugPauseIndex; // Current step
+ static inline void SetDebugNPC( CAI_BaseNPC *pNPC ) { m_pDebugNPC = pNPC; }
+ static inline bool IsDebugNPC( CAI_BaseNPC *pNPC ) { return( pNPC == m_pDebugNPC ); }
+
+ float m_LastShootAccuracy;
+ int m_TotalShots;
+ int m_TotalHits;
+#ifdef _DEBUG
+ bool m_bSelected;
+#endif
+
+ float m_flSoundWaitTime; // Time when I'm allowed to make another sound
+ int m_nSoundPriority;
+ float m_flIgnoreDangerSoundsUntil;
+
+#ifdef AI_MONITOR_FOR_OSCILLATION
+ CUtlVector<AIScheduleChoice_t> m_ScheduleHistory;
+#endif//AI_MONITOR_FOR_OSCILLATION
+
+private:
+
+ // Break into pieces!
+ void Break( CBaseEntity *pBreaker );
+ void InputBreak( inputdata_t &inputdata );
+
+ friend void CC_NPC_Go();
+ friend void CC_NPC_GoRandom();
+ friend void CC_NPC_Freeze( const CCommand &args );
+
+public:
+
+ CNetworkVar( bool, m_bPerformAvoidance );
+ CNetworkVar( bool, m_bIsMoving );
+ CNetworkVar( bool, m_bFadeCorpse );
+ CNetworkVar( bool, m_bImportanRagdoll );
+
+ CNetworkVar( bool, m_bSpeedModActive );
+ CNetworkVar( int, m_iSpeedModRadius );
+ CNetworkVar( int, m_iSpeedModSpeed );
+ CNetworkVar( float, m_flTimePingEffect ); // Display the pinged effect until this time
+
+ void InputActivateSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = true; }
+ void InputDisableSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = false; }
+ void InputSetSpeedModifierRadius( inputdata_t &inputdata );
+ void InputSetSpeedModifierSpeed( inputdata_t &inputdata );
+
+ virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity );
+
+ bool m_bPlayerAvoidState;
+ void GetPlayerAvoidBounds( Vector *pMins, Vector *pMaxs );
+
+ void StartPingEffect( void ) { m_flTimePingEffect = gpGlobals->curtime + 2.0f; DispatchUpdateTransmitState(); }
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns whether our ideal activity has started. If not, we are in
+// a transition sequence.
+//-----------------------------------------------------------------------------
+inline bool CAI_BaseNPC::IsActivityStarted(void)
+{
+ return (GetSequence() == m_nIdealSequence);
+}
+
+//-----------------------------------------------------------------------------
+// Bullet firing (legacy)...
+//-----------------------------------------------------------------------------
+inline void CAI_BaseNPC::FireBullets( int cShots, const Vector &vecSrc,
+ const Vector &vecDirShooting, const Vector &vecSpread, float flDistance,
+ int iAmmoType, int iTracerFreq, int firingEntID, int attachmentID,
+ int iDamage, CBaseEntity *pAttacker, bool bFirstShotAccurate )
+{
+ FireBulletsInfo_t info;
+ info.m_iShots = cShots;
+ info.m_vecSrc = vecSrc;
+ info.m_vecDirShooting = vecDirShooting;
+ info.m_vecSpread = vecSpread;
+ info.m_flDistance = flDistance;
+ info.m_iAmmoType = iAmmoType;
+ info.m_iTracerFreq = iTracerFreq;
+ info.m_flDamage = iDamage;
+ info.m_pAttacker = pAttacker;
+ info.m_nFlags = bFirstShotAccurate ? FIRE_BULLETS_FIRST_SHOT_ACCURATE : 0;
+
+ FireBullets( info );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the ideal state of this NPC.
+//-----------------------------------------------------------------------------
+inline void CAI_BaseNPC::SetIdealState( NPC_STATE eIdealState )
+{
+ if (eIdealState != m_IdealNPCState)
+ {
+ /*switch (eIdealState)
+ {
+ case NPC_STATE_NONE:
+ Msg("%s.SetIdealState: NPC_STATE_NONE\n", GetDebugName());
+ break;
+
+ case NPC_STATE_IDLE:
+ Msg("%s.SetIdealState: NPC_STATE_IDLE\n", GetDebugName());
+ break;
+
+ case NPC_STATE_ALERT:
+ Msg("%s.SetIdealState: NPC_STATE_ALERT\n", GetDebugName());
+ break;
+
+ case NPC_STATE_COMBAT:
+ Msg("%s.SetIdealState: NPC_STATE_COMBAT\n", GetDebugName());
+ break;
+
+ case NPC_STATE_SCRIPT:
+ Msg("%s.SetIdealState: NPC_STATE_SCRIPT\n", GetDebugName());
+ break;
+
+ case NPC_STATE_PLAYDEAD:
+ Msg("%s.SetIdealState: NPC_STATE_PLAYDEAD\n", GetDebugName());
+ break;
+
+ case NPC_STATE_PRONE:
+ Msg("%s.SetIdealState: NPC_STATE_PRONE\n", GetDebugName());
+ break;
+
+ case NPC_STATE_DEAD:
+ Msg("%s.SetIdealState: NPC_STATE_DEAD\n", GetDebugName());
+ break;
+
+ default:
+ Msg("%s.SetIdealState: <Unknown>\n", GetDebugName());
+ break;
+ }*/
+
+ m_IdealNPCState = eIdealState;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the current ideal state the NPC will try to achieve.
+//-----------------------------------------------------------------------------
+inline NPC_STATE CAI_BaseNPC::GetIdealState()
+{
+ return m_IdealNPCState;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline int CAI_BaseNPC::IncScheduleCurTaskIndex()
+{
+ m_ScheduleState.iTaskInterrupt = 0;
+ m_ScheduleState.bTaskRanAutomovement = false;
+ m_ScheduleState.bTaskUpdatedYaw = false;
+ return ++m_ScheduleState.iCurTask;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline void CAI_BaseNPC::ResetScheduleCurTaskIndex()
+{
+ m_ScheduleState.iCurTask = 0;
+ m_ScheduleState.iTaskInterrupt = 0;
+ m_ScheduleState.bTaskRanAutomovement = false;
+ m_ScheduleState.bTaskUpdatedYaw = false;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+inline bool CAI_BaseNPC::CrouchIsDesired( void ) const
+{
+ return ( (CapabilitiesGet() & bits_CAP_DUCK) && (m_bCrouchDesired | m_bForceCrouch) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+inline void CAI_BaseNPC::DesireStand( void )
+{
+ m_bCrouchDesired = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+inline void CAI_BaseNPC::ForceCrouch( void )
+{
+ m_bForceCrouch = true;
+ Crouch();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+inline void CAI_BaseNPC::ClearForceCrouch( void )
+{
+ m_bForceCrouch = false;
+
+ if ( IsCrouching() )
+ {
+ Stand();
+ }
+}
+
+inline bool CAI_BaseNPC::HaveSequenceForActivity( Activity activity )
+{
+#if STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW
+ return ( (GetModelPtr()) ? (SelectWeightedSequence( activity ) != ACTIVITY_NOT_AVAILABLE) : false );
+#else
+ return ( (GetModelPtr()) ? GetModelPtr()->HaveSequenceForActivity(activity) : false );
+#endif
+}
+
+typedef CHandle<CAI_BaseNPC> AIHANDLE;
+
+
+// ============================================================================
+// Macros for introducing new schedules in sub-classes
+//
+// Strings registries and schedules use unique ID's for each item, but
+// sub-class enumerations are non-unique, so we translate between the
+// enumerations and unique ID's
+// ============================================================================
+
+#define AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( derivedClass ) \
+ IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass ) \
+ void derivedClass::InitCustomSchedules( void ) \
+ { \
+ typedef derivedClass CNpc; \
+ const char *pszClassName = #derivedClass; \
+ \
+ CUtlVector<const char *> schedulesToLoad; \
+ CUtlVector<AIScheduleLoadFunc_t> reqiredOthers; \
+ CAI_NamespaceInfos scheduleIds; \
+ CAI_NamespaceInfos taskIds; \
+ CAI_NamespaceInfos conditionIds;
+
+
+//-----------------
+
+#define AI_BEGIN_CUSTOM_NPC( className, derivedClass ) \
+ IMPLEMENT_CUSTOM_AI(className, derivedClass ) \
+ void derivedClass::InitCustomSchedules( void ) \
+ { \
+ typedef derivedClass CNpc; \
+ const char *pszClassName = #derivedClass; \
+ \
+ CUtlVector<const char *> schedulesToLoad; \
+ CUtlVector<AIScheduleLoadFunc_t> reqiredOthers; \
+ CAI_NamespaceInfos scheduleIds; \
+ CAI_NamespaceInfos taskIds; \
+ CAI_NamespaceInfos conditionIds; \
+ CAI_NamespaceInfos squadSlotIds;
+
+//-----------------
+
+#define EXTERN_SCHEDULE( id ) \
+ scheduleIds.PushBack( #id, id ); \
+ extern const char * g_psz##id; \
+ schedulesToLoad.AddToTail( g_psz##id );
+
+//-----------------
+
+#define DEFINE_SCHEDULE( id, text ) \
+ scheduleIds.PushBack( #id, id ); \
+ const char * g_psz##id = \
+ "\n Schedule" \
+ "\n " #id \
+ text \
+ "\n"; \
+ schedulesToLoad.AddToTail( g_psz##id );
+
+//-----------------
+
+#define DECLARE_CONDITION( id ) \
+ conditionIds.PushBack( #id, id );
+
+//-----------------
+
+#define DECLARE_TASK( id ) \
+ taskIds.PushBack( #id, id );
+
+//-----------------
+
+#define DECLARE_ACTIVITY( id ) \
+ ADD_CUSTOM_ACTIVITY( CNpc, id );
+
+//-----------------
+
+#define DECLARE_SQUADSLOT( id ) \
+ squadSlotIds.PushBack( #id, id );
+
+//-----------------
+
+#define DECLARE_INTERACTION( interaction ) \
+ ADD_CUSTOM_INTERACTION( interaction );
+
+//-----------------
+
+#define DECLARE_ANIMEVENT( id ) \
+ ADD_CUSTOM_ANIMEVENT( CNpc, id );
+
+//-----------------
+
+#define DECLARE_USES_SCHEDULE_PROVIDER( classname ) reqiredOthers.AddToTail( ScheduleLoadHelper(classname) );
+
+//-----------------
+
+// IDs are stored and then added in order due to constraints in the namespace implementation
+#define AI_END_CUSTOM_SCHEDULE_PROVIDER() \
+ \
+ int i; \
+ \
+ CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
+ \
+ scheduleIds.Sort(); \
+ taskIds.Sort(); \
+ conditionIds.Sort(); \
+ \
+ for ( i = 0; i < scheduleIds.Count(); i++ ) \
+ { \
+ ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \
+ } \
+ \
+ for ( i = 0; i < taskIds.Count(); i++ ) \
+ { \
+ ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \
+ } \
+ \
+ for ( i = 0; i < conditionIds.Count(); i++ ) \
+ { \
+ if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \
+ { \
+ ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \
+ } \
+ } \
+ \
+ for ( i = 0; i < reqiredOthers.Count(); i++ ) \
+ { \
+ (*reqiredOthers[i])(); \
+ } \
+ \
+ for ( i = 0; i < schedulesToLoad.Count(); i++ ) \
+ { \
+ if ( CNpc::gm_SchedLoadStatus.fValid ) \
+ { \
+ CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect() ); \
+ } \
+ else \
+ break; \
+ } \
+ }
+
+inline bool ValidateConditionLimits( const char *pszNewCondition )
+{
+ int nGlobalConditions = CAI_BaseNPC::GetSchedulingSymbols()->NumConditions();
+ if ( nGlobalConditions >= MAX_CONDITIONS )
+ {
+ AssertMsg2( 0, "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition );
+ DevWarning( "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition );
+ return false;
+ }
+ return true;
+}
+
+
+//-------------------------------------
+
+// IDs are stored and then added in order due to constraints in the namespace implementation
+#define AI_END_CUSTOM_NPC() \
+ \
+ int i; \
+ \
+ CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
+ CNpc::gm_SquadSlotIdSpace.Init( &BaseClass::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace); \
+ \
+ scheduleIds.Sort(); \
+ taskIds.Sort(); \
+ conditionIds.Sort(); \
+ squadSlotIds.Sort(); \
+ \
+ for ( i = 0; i < scheduleIds.Count(); i++ ) \
+ { \
+ ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \
+ } \
+ \
+ for ( i = 0; i < taskIds.Count(); i++ ) \
+ { \
+ ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \
+ } \
+ \
+ for ( i = 0; i < conditionIds.Count(); i++ ) \
+ { \
+ if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \
+ { \
+ ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \
+ } \
+ } \
+ \
+ for ( i = 0; i < squadSlotIds.Count(); i++ ) \
+ { \
+ ADD_CUSTOM_SQUADSLOT_NAMED( CNpc, squadSlotIds[i].pszName, squadSlotIds[i].localId ); \
+ } \
+ \
+ for ( i = 0; i < reqiredOthers.Count(); i++ ) \
+ { \
+ (*reqiredOthers[i])(); \
+ } \
+ \
+ for ( i = 0; i < schedulesToLoad.Count(); i++ ) \
+ { \
+ if ( CNpc::gm_SchedLoadStatus.fValid ) \
+ { \
+ CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect() ); \
+ } \
+ else \
+ break; \
+ } \
+ }
+
+//-------------------------------------
+
+struct AI_NamespaceAddInfo_t
+{
+ AI_NamespaceAddInfo_t( const char *pszName, int localId )
+ : pszName( pszName ),
+ localId( localId )
+ {
+ }
+
+ const char *pszName;
+ int localId;
+};
+
+class CAI_NamespaceInfos : public CUtlVector<AI_NamespaceAddInfo_t>
+{
+public:
+ void PushBack( const char *pszName, int localId )
+ {
+ AddToTail( AI_NamespaceAddInfo_t( pszName, localId ) );
+ }
+
+ void Sort()
+ {
+ CUtlVector<AI_NamespaceAddInfo_t>::Sort( Compare );
+ }
+
+private:
+ static int __cdecl Compare(const AI_NamespaceAddInfo_t *pLeft, const AI_NamespaceAddInfo_t *pRight )
+ {
+ return pLeft->localId - pRight->localId;
+ }
+
+};
+
+//-------------------------------------
+
+// Declares the static variables that hold the string registry offset for the new subclass
+// as well as the initialization in schedule load functions
+
+struct AI_SchedLoadStatus_t
+{
+ bool fValid;
+ int signature;
+};
+
+// Load schedules pulled out to support stepping through with debugger
+inline bool AI_DoLoadSchedules( bool (*pfnBaseLoad)(), void (*pfnInitCustomSchedules)(),
+ AI_SchedLoadStatus_t *pLoadStatus )
+{
+ (*pfnBaseLoad)();
+
+ if (pLoadStatus->signature != g_AI_SchedulesManager.GetScheduleLoadSignature())
+ {
+ (*pfnInitCustomSchedules)();
+ pLoadStatus->fValid = true;
+ pLoadStatus->signature = g_AI_SchedulesManager.GetScheduleLoadSignature();
+ }
+ return pLoadStatus->fValid;
+}
+
+//-------------------------------------
+
+typedef bool (*AIScheduleLoadFunc_t)();
+
+// @Note (toml 02-16-03): The following class exists to allow us to establish an anonymous friendship
+// in DEFINE_CUSTOM_SCHEDULE_PROVIDER. The particulars of this implementation is almost entirely
+// defined by bugs in MSVC 6.0
+class ScheduleLoadHelperImpl
+{
+public:
+ template <typename T>
+ static AIScheduleLoadFunc_t AccessScheduleLoadFunc(T *)
+ {
+ return (&T::LoadSchedules);
+ }
+};
+
+#define ScheduleLoadHelper( type ) (ScheduleLoadHelperImpl::AccessScheduleLoadFunc((type *)0))
+
+//-------------------------------------
+
+#define DEFINE_CUSTOM_SCHEDULE_PROVIDER\
+ static AI_SchedLoadStatus_t gm_SchedLoadStatus; \
+ static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace; \
+ static const char * gm_pszErrorClassName;\
+ \
+ static CAI_ClassScheduleIdSpace & AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; } \
+ virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; } \
+ virtual const char * GetSchedulingErrorName() { return gm_pszErrorClassName; } \
+ \
+ static void InitCustomSchedules(void);\
+ \
+ static bool LoadSchedules(void);\
+ virtual bool LoadedSchedules(void); \
+ \
+ friend class ScheduleLoadHelperImpl; \
+ \
+ class CScheduleLoader \
+ { \
+ public: \
+ CScheduleLoader(); \
+ } m_ScheduleLoader; \
+ \
+ friend class CScheduleLoader;
+
+//-------------------------------------
+
+#define DEFINE_CUSTOM_AI\
+ DEFINE_CUSTOM_SCHEDULE_PROVIDER \
+ \
+ static CAI_LocalIdSpace gm_SquadSlotIdSpace; \
+ \
+ const char* SquadSlotName (int squadSlotID);
+
+//-------------------------------------
+
+#define IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\
+ AI_SchedLoadStatus_t derivedClass::gm_SchedLoadStatus = { true, -1 }; \
+ CAI_ClassScheduleIdSpace derivedClass::gm_ClassScheduleIdSpace; \
+ const char * derivedClass::gm_pszErrorClassName = #derivedClass; \
+ \
+ derivedClass::CScheduleLoader::CScheduleLoader()\
+ { \
+ derivedClass::LoadSchedules(); \
+ } \
+ \
+ /* --------------------------------------------- */ \
+ /* Load schedules for this type of NPC */ \
+ /* --------------------------------------------- */ \
+ bool derivedClass::LoadSchedules(void)\
+ {\
+ return AI_DoLoadSchedules( derivedClass::BaseClass::LoadSchedules, \
+ derivedClass::InitCustomSchedules, \
+ &derivedClass::gm_SchedLoadStatus ); \
+ }\
+ \
+ bool derivedClass::LoadedSchedules(void) \
+ { \
+ return derivedClass::gm_SchedLoadStatus.fValid;\
+ }
+
+
+//-------------------------------------
+
+// Initialize offsets and implement methods for loading and getting squad info for the subclass
+#define IMPLEMENT_CUSTOM_AI(className, derivedClass)\
+ IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\
+ \
+ CAI_LocalIdSpace derivedClass::gm_SquadSlotIdSpace; \
+ \
+ /* -------------------------------------------------- */ \
+ /* Given squadSlot enumeration return squadSlot name */ \
+ /* -------------------------------------------------- */ \
+ const char* derivedClass::SquadSlotName(int slotEN)\
+ {\
+ return gm_SquadSlotNamespace.IdToSymbol( derivedClass::gm_SquadSlotIdSpace.LocalToGlobal(slotEN) );\
+ }
+
+
+//-------------------------------------
+
+#define ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,schedName,schedEN)\
+ if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddSchedule( schedName, schedEN, derivedClass::gm_pszErrorClassName ) ) return;
+
+#define ADD_CUSTOM_SCHEDULE(derivedClass,schedEN) ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,#schedEN,schedEN)
+
+#define ADD_CUSTOM_TASK_NAMED(derivedClass,taskName,taskEN)\
+ if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddTask( taskName, taskEN, derivedClass::gm_pszErrorClassName ) ) return;
+
+#define ADD_CUSTOM_TASK(derivedClass,taskEN) ADD_CUSTOM_TASK_NAMED(derivedClass,#taskEN,taskEN)
+
+#define ADD_CUSTOM_CONDITION_NAMED(derivedClass,condName,condEN)\
+ if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddCondition( condName, condEN, derivedClass::gm_pszErrorClassName ) ) return;
+
+#define ADD_CUSTOM_CONDITION(derivedClass,condEN) ADD_CUSTOM_CONDITION_NAMED(derivedClass,#condEN,condEN)
+
+//-------------------------------------
+
+#define INIT_CUSTOM_AI(derivedClass)\
+ derivedClass::AccessClassScheduleIdSpaceDirect().Init( #derivedClass, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \
+ derivedClass::gm_SquadSlotIdSpace.Init( &CAI_BaseNPC::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace);
+
+#define ADD_CUSTOM_INTERACTION( interaction ) { interaction = CBaseCombatCharacter::GetInteractionID(); }
+
+#define ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,squadSlotName,squadSlotEN)\
+ if ( !derivedClass::gm_SquadSlotIdSpace.AddSymbol( squadSlotName, squadSlotEN, "squadslot", derivedClass::gm_pszErrorClassName ) ) return;
+
+#define ADD_CUSTOM_SQUADSLOT(derivedClass,squadSlotEN) ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,#squadSlotEN,squadSlotEN)
+
+#define ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,activityName,activityEnum)\
+ REGISTER_PRIVATE_ACTIVITY(activityEnum);\
+ CAI_BaseNPC::AddActivityToSR(activityName,activityEnum);
+
+#define ADD_CUSTOM_ACTIVITY(derivedClass,activityEnum) ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,#activityEnum,activityEnum)
+
+
+#define ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,eventName,eventEnum)\
+ REGISTER_PRIVATE_ANIMEVENT(eventEnum);\
+ CAI_BaseNPC::AddEventToSR(eventName,eventEnum);
+
+#define ADD_CUSTOM_ANIMEVENT(derivedClass,eventEnum) ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,#eventEnum,eventEnum)
+
+
+//=============================================================================
+// class CAI_Component
+//=============================================================================
+
+inline const Vector &CAI_Component::GetLocalOrigin() const
+{
+ return GetOuter()->GetLocalOrigin();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetLocalOrigin(const Vector &origin)
+{
+ GetOuter()->SetLocalOrigin(origin);
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Vector &CAI_Component::GetAbsOrigin() const
+{
+ return GetOuter()->GetAbsOrigin();
+}
+
+//-----------------------------------------------------------------------------
+
+inline const QAngle &CAI_Component::GetAbsAngles() const
+{
+ return GetOuter()->GetAbsAngles();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetSolid( SolidType_t val )
+{
+ GetOuter()->SetSolid(val);
+}
+
+//-----------------------------------------------------------------------------
+
+inline SolidType_t CAI_Component::GetSolid() const
+{
+ return GetOuter()->GetSolid();
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Vector &CAI_Component::WorldAlignMins() const
+{
+ return GetOuter()->WorldAlignMins();
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Vector &CAI_Component::WorldAlignMaxs() const
+{
+ return GetOuter()->WorldAlignMaxs();
+}
+
+//-----------------------------------------------------------------------------
+
+inline Hull_t CAI_Component::GetHullType() const
+{
+ return GetOuter()->GetHullType();
+}
+
+//-----------------------------------------------------------------------------
+
+inline Vector CAI_Component::WorldSpaceCenter() const
+{
+ return GetOuter()->WorldSpaceCenter();
+}
+
+//-----------------------------------------------------------------------------
+
+inline float CAI_Component::GetGravity() const
+{
+ return GetOuter()->GetGravity();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetGravity( float flGravity )
+{
+ GetOuter()->SetGravity( flGravity );
+}
+
+//-----------------------------------------------------------------------------
+
+inline float CAI_Component::GetHullWidth() const
+{
+ return NAI_Hull::Width(GetOuter()->GetHullType());
+}
+
+//-----------------------------------------------------------------------------
+
+inline float CAI_Component::GetHullHeight() const
+{
+ return NAI_Hull::Height(GetOuter()->GetHullType());
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Vector &CAI_Component::GetHullMins() const
+{
+ return NAI_Hull::Mins(GetOuter()->GetHullType());
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Vector &CAI_Component::GetHullMaxs() const
+{
+ return NAI_Hull::Maxs(GetOuter()->GetHullType());
+}
+
+//-----------------------------------------------------------------------------
+
+inline int CAI_Component::GetCollisionGroup() const
+{
+ return GetOuter()->GetCollisionGroup();
+}
+
+//-----------------------------------------------------------------------------
+
+inline CBaseEntity *CAI_Component::GetEnemy()
+{
+ return GetOuter()->GetEnemy();
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Vector &CAI_Component::GetEnemyLKP() const
+{
+ return GetOuter()->GetEnemyLKP();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition )
+{
+ GetOuter()->TranslateNavGoal( pEnemy, chasePosition );
+}
+
+//-----------------------------------------------------------------------------
+
+inline CBaseEntity *CAI_Component::GetTarget()
+{
+ return GetOuter()->GetTarget();
+}
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetTarget( CBaseEntity *pTarget )
+{
+ GetOuter()->SetTarget( pTarget );
+}
+
+//-----------------------------------------------------------------------------
+
+inline const Task_t *CAI_Component::GetCurTask()
+{
+ return GetOuter()->GetTask();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::TaskFail( AI_TaskFailureCode_t code )
+{
+ GetOuter()->TaskFail( code );
+}
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::TaskFail( const char *pszGeneralFailText )
+{
+ GetOuter()->TaskFail( pszGeneralFailText );
+}
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::TaskComplete( bool fIgnoreSetFailedCondition )
+{
+ GetOuter()->TaskComplete( fIgnoreSetFailedCondition );
+}
+//-----------------------------------------------------------------------------
+
+inline int CAI_Component::TaskIsRunning()
+{
+ return GetOuter()->TaskIsRunning();
+}
+//-----------------------------------------------------------------------------
+
+inline int CAI_Component::TaskIsComplete()
+{
+ return GetOuter()->TaskIsComplete();
+}
+
+//-----------------------------------------------------------------------------
+
+inline Activity CAI_Component::GetActivity()
+{
+ return GetOuter()->GetActivity();
+}
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetActivity( Activity NewActivity )
+{
+ GetOuter()->SetActivity( NewActivity );
+}
+//-----------------------------------------------------------------------------
+
+inline float CAI_Component::GetIdealSpeed() const
+{
+ return GetOuter()->GetIdealSpeed();
+}
+
+//-----------------------------------------------------------------------------
+
+inline float CAI_Component::GetIdealAccel() const
+{
+ return GetOuter()->GetIdealAccel();
+}
+
+//-----------------------------------------------------------------------------
+
+inline int CAI_Component::GetSequence()
+{
+ return GetOuter()->GetSequence();
+}
+
+//-----------------------------------------------------------------------------
+
+inline int CAI_Component::GetEntFlags() const
+{
+ return GetOuter()->GetFlags();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::AddEntFlag( int flags )
+{
+ GetOuter()->AddFlag( flags );
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::RemoveEntFlag( int flagsToRemove )
+{
+ GetOuter()->RemoveFlag( flagsToRemove );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Change the ground entity for the outer
+// Input : *ground -
+// Output : inline void
+//-----------------------------------------------------------------------------
+inline void CAI_Component::SetGroundEntity( CBaseEntity *ground )
+{
+ GetOuter()->SetGroundEntity( ground );
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::ToggleEntFlag( int flagToToggle )
+{
+ GetOuter()->ToggleFlag( flagToToggle );
+}
+
+//-----------------------------------------------------------------------------
+
+inline CBaseEntity* CAI_Component::GetGoalEnt()
+{
+ return GetOuter()->GetGoalEnt();
+}
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetGoalEnt( CBaseEntity *pGoalEnt )
+{
+ GetOuter()->SetGoalEnt( pGoalEnt );
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::Remember( int iMemory )
+{
+ GetOuter()->Remember( iMemory );
+}
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::Forget( int iMemory )
+{
+ GetOuter()->Forget( iMemory );
+}
+//-----------------------------------------------------------------------------
+
+inline bool CAI_Component::HasMemory( int iMemory )
+{
+ return GetOuter()->HasMemory( iMemory );
+}
+
+//-----------------------------------------------------------------------------
+
+inline CAI_Enemies *CAI_Component::GetEnemies()
+{
+ return GetOuter()->GetEnemies();
+}
+
+//-----------------------------------------------------------------------------
+
+inline const char *CAI_Component::GetEntClassname()
+{
+ return GetOuter()->GetClassname();
+}
+
+//-----------------------------------------------------------------------------
+
+inline int CAI_Component::CapabilitiesGet()
+{
+ return GetOuter()->CapabilitiesGet();
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CAI_Component::SetLocalAngles( const QAngle& angles )
+{
+ GetOuter()->SetLocalAngles( angles );
+}
+
+//-----------------------------------------------------------------------------
+
+inline const QAngle &CAI_Component::GetLocalAngles( void ) const
+{
+ return GetOuter()->GetLocalAngles();
+}
+
+//-----------------------------------------------------------------------------
+
+inline edict_t *CAI_Component::GetEdict()
+{
+ return GetOuter()->NetworkProp()->edict();
+}
+
+//-----------------------------------------------------------------------------
+
+inline float CAI_Component::GetLastThink( const char *szContext )
+{
+ return GetOuter()->GetLastThink( szContext );
+}
+
+// ============================================================================
+abstract_class INPCInteractive
+{
+public:
+ virtual bool CanInteractWith( CAI_BaseNPC *pUser ) = 0;
+ virtual bool HasBeenInteractedWith() = 0;
+ virtual void NotifyInteraction( CAI_BaseNPC *pUser ) = 0;
+
+ // Alyx specific interactions
+ virtual void AlyxStartedInteraction( void ) = 0;
+ virtual void AlyxFinishedInteraction( void ) = 0;
+};
+
+// Base Class for any NPC that wants to be interactable by other NPCS (i.e. Alyx Hackable)
+// NOTE: YOU MUST DEFINE THE OUTPUTS IN YOUR CLASS'S DATADESC!
+// THE DO SO, INSERT THE FOLLOWING MACRO INTO YOUR CLASS'S DATADESC.
+//
+#define DEFINE_BASENPCINTERACTABLE_DATADESC() \
+ DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \
+ DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \
+ DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown )
+
+template <class NPC_CLASS>
+class CNPCBaseInteractive : public NPC_CLASS, public INPCInteractive
+{
+ DECLARE_CLASS( CNPCBaseInteractive, NPC_CLASS );
+public:
+ virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; };
+ virtual bool HasBeenInteractedWith() { return false; };
+ virtual void NotifyInteraction( CAI_BaseNPC *pUser ) { return; };
+
+ virtual void InputPowerdown( inputdata_t &inputdata )
+ {
+
+ }
+
+ // Alyx specific interactions
+ virtual void AlyxStartedInteraction( void )
+ {
+ m_OnAlyxStartedInteraction.FireOutput( this, this );
+ }
+ virtual void AlyxFinishedInteraction( void )
+ {
+ m_OnAlyxFinishedInteraction.FireOutput( this, this );
+ }
+
+public:
+ // Outputs
+ // Alyx specific interactions
+ COutputEvent m_OnAlyxStartedInteraction;
+ COutputEvent m_OnAlyxFinishedInteraction;
+};
+
+//
+// Deferred Navigation calls go here
+//
+
+extern ConVar ai_post_frame_navigation;
+
+class CPostFrameNavigationHook : public CBaseGameSystemPerFrame
+{
+public:
+ virtual const char *Name( void ) { return "CPostFrameNavigationHook"; }
+
+ virtual bool Init( void );
+ virtual void FrameUpdatePostEntityThink( void );
+ virtual void FrameUpdatePreEntityThink( void );
+
+ bool IsGameFrameRunning( void ) { return m_bGameFrameRunning; }
+ void SetGrameFrameRunning( bool bState ) { m_bGameFrameRunning = bState; }
+
+ void EnqueueEntityNavigationQuery( CAI_BaseNPC *pNPC, CFunctor *functor );
+
+private:
+ CUtlVector<CFunctor *> m_Functors;
+ bool m_bGameFrameRunning;
+};
+
+extern CPostFrameNavigationHook *PostFrameNavigationSystem( void );
+
+#endif // AI_BASENPC_H