Untitled diff

Created Diff never expires
0 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
765 lines
0 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
765 lines
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
// Purpose: Base NPC character with AI
// Purpose: Base NPC character with AI
//
//
//=============================================================================//
//=============================================================================//


#ifndef AI_BASENPC_H
#ifndef AI_BASENPC_H
#define AI_BASENPC_H
#define AI_BASENPC_H


#ifdef _WIN32
#ifdef _WIN32
#pragma once
#pragma once
#endif
#endif


#include "simtimer.h"
#include "simtimer.h"
#include "basecombatcharacter.h"
#include "basecombatcharacter.h"
#include "ai_debug.h"
#include "ai_debug.h"
#include "ai_default.h"
#include "ai_default.h"
#include "ai_schedule.h"
#include "ai_schedule.h"
#include "ai_condition.h"
#include "ai_condition.h"
#include "ai_component.h"
#include "ai_component.h"
#include "ai_task.h"
#include "ai_task.h"
#include "ai_movetypes.h"
#include "ai_movetypes.h"
#include "ai_navtype.h"
#include "ai_navtype.h"
#include "ai_namespaces.h"
#include "ai_namespaces.h"
#include "ai_npcstate.h"
#include "ai_npcstate.h"
#include "ai_hull.h"
#include "ai_hull.h"
#include "ai_utils.h"
#include "ai_utils.h"
#include "ai_moveshoot.h"
#include "ai_moveshoot.h"
#include "entityoutput.h"
#include "entityoutput.h"
#include "utlvector.h"
#include "utlvector.h"
#include "activitylist.h"
#include "activitylist.h"
#include "bitstring.h"
#include "bitstring.h"
#include "ai_basenpc.h"
#include "ai_basenpc.h"
#include "ai_navgoaltype.h" //GoalType_t enum
#include "ai_navgoaltype.h" //GoalType_t enum
#include "eventlist.h"
#include "eventlist.h"
#include "soundent.h"
#include "soundent.h"
#include "ai_navigator.h"
#include "ai_navigator.h"
#include "tier1/functors.h"
#include "tier1/functors.h"




#define PLAYER_SQUADNAME "player_squad"
#define PLAYER_SQUADNAME "player_squad"


class CAI_Schedule;
class CAI_Schedule;
class CAI_Network;
class CAI_Network;
class CAI_Route;
class CAI_Route;
class CAI_Hint;
class CAI_Hint;
class CAI_Node;
class CAI_Node;
class CAI_Navigator;
class CAI_Navigator;
class CAI_Pathfinder;
class CAI_Pathfinder;
class CAI_Senses;
class CAI_Senses;
class CAI_Enemies;
class CAI_Enemies;
class CAI_Squad;
class CAI_Squad;
class CAI_Expresser;
class CAI_Expresser;
class CAI_BehaviorBase;
class CAI_BehaviorBase;
class CAI_GoalEntity;
class CAI_GoalEntity;
class CAI_Motor;
class CAI_Motor;
class CAI_MoveProbe;
class CAI_MoveProbe;
class CAI_LocalNavigator;
class CAI_LocalNavigator;
class CAI_TacticalServices;
class CAI_TacticalServices;
class CVarBitVec;
class CVarBitVec;
class CAI_ScriptedSequence;
class CAI_ScriptedSequence;
class CSceneEntity;
class CSceneEntity;
class CBaseGrenade;
class CBaseGrenade;
class CBaseDoor;
class CBaseDoor;
class CBasePropDoor;
class CBasePropDoor;
struct AI_Waypoint_t;
struct AI_Waypoint_t;
class AI_Response;
class AI_Response;
class CBaseFilter;
class CBaseFilter;


typedef CBitVec<MAX_CONDITIONS> CAI_ScheduleBits;
typedef CBitVec<MAX_CONDITIONS> CAI_ScheduleBits;


// Used to control optimizations mostly dealing with pathfinding for NPCs
// Used to control optimizations mostly dealing with pathfinding for NPCs
extern ConVar ai_strong_optimizations;
extern ConVar ai_strong_optimizations;


extern bool AIStrongOpt( void );
extern bool AIStrongOpt( void );


// AI_MONITOR_FOR_OSCILLATION defaults to OFF. If you build with this ON, you can flag
// 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)
// NPC's and monitor them to detect oscillations in their schedule (circular logic and conditions bugs)
// DO NOT SHIP WITH THIS ON!
// DO NOT SHIP WITH THIS ON!
#undef AI_MONITOR_FOR_OSCILLATION
#undef AI_MONITOR_FOR_OSCILLATION


//=============================================================================
//=============================================================================
//
//
// Constants & enumerations
// Constants & enumerations
//
//
//=============================================================================
//=============================================================================
#define TURRET_CLOSE_RANGE 200
#define TURRET_CLOSE_RANGE 200
#define TURRET_MEDIUM_RANGE 500
#define TURRET_MEDIUM_RANGE 500


#define COMMAND_GOAL_TOLERANCE 48 // 48 inches.
#define COMMAND_GOAL_TOLERANCE 48 // 48 inches.
#define TIME_CARE_ABOUT_DAMAGE 3.0
#define TIME_CARE_ABOUT_DAMAGE 3.0


#define ITEM_PICKUP_TOLERANCE 48.0f
#define ITEM_PICKUP_TOLERANCE 48.0f


// Max's of the box used to search for a weapon to pick up. 45x45x~8 ft.
// 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 )
#define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 )


enum Interruptability_t
enum Interruptability_t
{
{
GENERAL_INTERRUPTABILITY,
GENERAL_INTERRUPTABILITY,
DAMAGEORDEATH_INTERRUPTABILITY,
DAMAGEORDEATH_INTERRUPTABILITY,
DEATH_INTERRUPTABILITY
DEATH_INTERRUPTABILITY
};
};


//-------------------------------------
//-------------------------------------
// Memory
// Memory
//-------------------------------------
//-------------------------------------


#define MEMORY_CLEAR 0
#define MEMORY_CLEAR 0
#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes.
#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_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_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_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_ ( 1 << 4 )
#define bits_MEMORY_PATH_FAILED ( 1 << 5 )// Failed to find a path
#define bits_MEMORY_PATH_FAILED ( 1 << 5 )// Failed to find a path
#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched
//#define bits_MEMORY_ ( 1 << 7 )
//#define bits_MEMORY_ ( 1 << 7 )
#define bits_MEMORY_TOURGUIDE ( 1 << 8 )// I have been acting as a tourguide.
#define bits_MEMORY_TOURGUIDE ( 1 << 8 )// I have been acting as a tourguide.
//#define bits_MEMORY_ ( 1 << 9 )//
//#define bits_MEMORY_ ( 1 << 9 )//
#define bits_MEMORY_LOCKED_HINT ( 1 << 10 )//
#define bits_MEMORY_LOCKED_HINT ( 1 << 10 )//
//#define bits_MEMORY_ ( 1 << 12 )
//#define bits_MEMORY_ ( 1 << 12 )


#define bits_MEMORY_TURNING ( 1 << 13 )// Turning, don't interrupt me.
#define bits_MEMORY_TURNING ( 1 << 13 )// Turning, don't interrupt me.
#define bits_MEMORY_TURNHACK ( 1 << 14 )
#define bits_MEMORY_TURNHACK ( 1 << 14 )


#define bits_MEMORY_HAD_ENEMY ( 1 << 15 )// Had an enemy
#define bits_MEMORY_HAD_ENEMY ( 1 << 15 )// Had an enemy
#define bits_MEMORY_HAD_PLAYER ( 1 << 16 )// Had player
#define bits_MEMORY_HAD_PLAYER ( 1 << 16 )// Had player
#define bits_MEMORY_HAD_LOS ( 1 << 17 )// Had LOS to enemy
#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_MOVED_FROM_SPAWN ( 1 << 18 )// Has moved since spawning.


#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // NPC-specific memory
#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // NPC-specific memory


//-------------------------------------
//-------------------------------------
// Spawn flags
// 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_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_GAG ( 1 << 1 ) // no idle noises from this npc
#define SF_NPC_FALL_TO_GROUND ( 1 << 2 ) // used my NPC_Maker
#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_DROP_HEALTHKIT ( 1 << 3 ) // Drop a healthkit upon death
#define SF_NPC_START_EFFICIENT ( 1 << 4 ) // Set into efficiency mode from spawn
#define SF_NPC_START_EFFICIENT ( 1 << 4 ) // Set into efficiency mode from spawn
// ( 1 << 5 )
// ( 1 << 5 )
// ( 1 << 6 )
// ( 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_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_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_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_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_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_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_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 )
#define SF_NPC_NO_PLAYER_PUSHAWAY ( 1 << 14 )
// ( 1 << 15 )
// ( 1 << 15 )
// !! Flags above ( 1 << 15 ) are reserved for NPC sub-classes
// !! Flags above ( 1 << 15 ) are reserved for NPC sub-classes


//-------------------------------------
//-------------------------------------
//
//
// Return codes from CanPlaySequence.
// Return codes from CanPlaySequence.
//
//
//-------------------------------------
//-------------------------------------


enum CanPlaySequence_t
enum CanPlaySequence_t
{
{
CANNOT_PLAY = 0, // Can't play for any number of reasons.
CANNOT_PLAY = 0, // Can't play for any number of reasons.
CAN_PLAY_NOW, // Can play the script immediately.
CAN_PLAY_NOW, // Can play the script immediately.
CAN_PLAY_ENQUEUED, // Can play the script after I finish playing my current script.
CAN_PLAY_ENQUEUED, // Can play the script after I finish playing my current script.
};
};


//-------------------------------------
//-------------------------------------
// Weapon holstering
// Weapon holstering
//-------------------------------------
//-------------------------------------
enum DesiredWeaponState_t
enum DesiredWeaponState_t
{
{
DESIREDWEAPONSTATE_IGNORE = 0,
DESIREDWEAPONSTATE_IGNORE = 0,
DESIREDWEAPONSTATE_HOLSTERED,
DESIREDWEAPONSTATE_HOLSTERED,
DESIREDWEAPONSTATE_HOLSTERED_DESTROYED, // Put the weapon away, then destroy it.
DESIREDWEAPONSTATE_HOLSTERED_DESTROYED, // Put the weapon away, then destroy it.
DESIREDWEAPONSTATE_UNHOLSTERED,
DESIREDWEAPONSTATE_UNHOLSTERED,
DESIREDWEAPONSTATE_CHANGING,
DESIREDWEAPONSTATE_CHANGING,
DESIREDWEAPONSTATE_CHANGING_DESTROY, // Destroy the weapon when this change is complete.
DESIREDWEAPONSTATE_CHANGING_DESTROY, // Destroy the weapon when this change is complete.
};
};


//-------------------------------------
//-------------------------------------
//
//
// Efficiency modes
// Efficiency modes
//
//
//-------------------------------------
//-------------------------------------


enum AI_Efficiency_t
enum AI_Efficiency_t
{
{
// Run at full tilt
// Run at full tilt
AIE_NORMAL,
AIE_NORMAL,


// Run decision process less often
// Run decision process less often
AIE_EFFICIENT,
AIE_EFFICIENT,


// Run decision process even less often, ignore other NPCs
// Run decision process even less often, ignore other NPCs
AIE_VERY_EFFICIENT,
AIE_VERY_EFFICIENT,


// Run decision process even less often, ignore other NPCs
// Run decision process even less often, ignore other NPCs
AIE_SUPER_EFFICIENT,
AIE_SUPER_EFFICIENT,


// Don't run at all
// Don't run at all
AIE_DORMANT,
AIE_DORMANT,
};
};


enum AI_MoveEfficiency_t
enum AI_MoveEfficiency_t
{
{
AIME_NORMAL,
AIME_NORMAL,
AIME_EFFICIENT,
AIME_EFFICIENT,
};
};


//-------------------------------------
//-------------------------------------
//
//
// Sleep state
// Sleep state
//
//
//-------------------------------------
//-------------------------------------


enum AI_SleepState_t
enum AI_SleepState_t
{
{
AISS_AWAKE,
AISS_AWAKE,
AISS_WAITING_FOR_THREAT,
AISS_WAITING_FOR_THREAT,
AISS_WAITING_FOR_PVS,
AISS_WAITING_FOR_PVS,
AISS_WAITING_FOR_INPUT,
AISS_WAITING_FOR_INPUT,
AISS_AUTO_PVS,
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.
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_FLAGS_NONE 0x00000000
#define AI_SLEEP_FLAG_AUTO_PVS 0x00000001
#define AI_SLEEP_FLAG_AUTO_PVS 0x00000001
#define AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS 0x00000002
#define AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS 0x00000002




//-------------------------------------
//-------------------------------------
//
//
// Debug bits
// Debug bits
//
//
//-------------------------------------
//-------------------------------------


enum DebugBaseNPCBits_e
enum DebugBaseNPCBits_e
{
{
bits_debugDisableAI = 0x00000001, // disable AI
bits_debugDisableAI = 0x00000001, // disable AI
bits_debugStepAI = 0x00000002, // step AI
bits_debugStepAI = 0x00000002, // step AI


};
};


//-------------------------------------
//-------------------------------------
//
//
// Base Sentence index for behaviors
// Base Sentence index for behaviors
//
//
//-------------------------------------
//-------------------------------------
enum SentenceIndex_t
enum SentenceIndex_t
{
{
SENTENCE_BASE_BEHAVIOR_INDEX = 1000,
SENTENCE_BASE_BEHAVIOR_INDEX = 1000,
};
};


#ifdef AI_MONITOR_FOR_OSCILLATION
#ifdef AI_MONITOR_FOR_OSCILLATION
struct AIScheduleChoice_t
struct AIScheduleChoice_t
{
{
float m_flTimeSelected;
float m_flTimeSelected;
CAI_Schedule *m_pScheduleSelected;
CAI_Schedule *m_pScheduleSelected;
};
};
#endif//AI_MONITOR_FOR_OSCILLATION
#endif//AI_MONITOR_FOR_OSCILLATION


#define MARK_TASK_EXPENSIVE() \
#define MARK_TASK_EXPENSIVE() \
if ( GetOuter() ) \
if ( GetOuter() ) \
{ \
{ \
GetOuter()->Remember( bits_MEMORY_TASK_EXPENSIVE ); \
GetOuter()->Remember( bits_MEMORY_TASK_EXPENSIVE ); \
}
}


//=============================================================================
//=============================================================================
//
//
// Types used by CAI_BaseNPC
// Types used by CAI_BaseNPC
//
//
//=============================================================================
//=============================================================================


struct AIScheduleState_t
struct AIScheduleState_t
{
{
int iCurTask;
int iCurTask;
TaskStatus_e fTaskStatus;
TaskStatus_e fTaskStatus;
float timeStarted;
float timeStarted;
float timeCurTaskStarted;
float timeCurTaskStarted;
AI_TaskFailureCode_t taskFailureCode;
AI_TaskFailureCode_t taskFailureCode;
int iTaskInterrupt;
int iTaskInterrupt;
bool bTaskRanAutomovement;
bool bTaskRanAutomovement;
bool bTaskUpdatedYaw;
bool bTaskUpdatedYaw;
bool bScheduleWasInterrupted;
bool bScheduleWasInterrupted;


DECLARE_SIMPLE_DATADESC();
DECLARE_SIMPLE_DATADESC();
};
};


// -----------------------------------------
// -----------------------------------------
// An entity that this NPC can't reach
// An entity that this NPC can't reach
// -----------------------------------------
// -----------------------------------------


struct UnreachableEnt_t
struct UnreachableEnt_t
{
{
EHANDLE hUnreachableEnt; // Entity that's unreachable
EHANDLE hUnreachableEnt; // Entity that's unreachable
float fExpireTime; // Time to forget this information
float fExpireTime; // Time to forget this information
Vector vLocationWhenUnreachable;
Vector vLocationWhenUnreachable;
DECLARE_SIMPLE_DATADESC();
DECLARE_SIMPLE_DATADESC();
};
};


//=============================================================================
//=============================================================================
// SCRIPTED NPC INTERACTIONS
// SCRIPTED NPC INTERACTIONS
//=============================================================================
//=============================================================================
// -----------------------------------------
// -----------------------------------------
// Scripted NPC interaction flags
// Scripted NPC interaction flags
// -----------------------------------------
// -----------------------------------------
#define SCNPC_FLAG_TEST_OTHER_ANGLES ( 1 << 1 )
#define SCNPC_FLAG_TEST_OTHER_ANGLES ( 1 << 1 )
#define SCNPC_FLAG_TEST_OTHER_VELOCITY ( 1 << 2 )
#define SCNPC_FLAG_TEST_OTHER_VELOCITY ( 1 << 2 )
#define SCNPC_FLAG_LOOP_IN_ACTION ( 1 << 3 )
#define SCNPC_FLAG_LOOP_IN_ACTION ( 1 << 3 )
#define SCNPC_FLAG_NEEDS_WEAPON_ME ( 1 << 4 )
#define SCNPC_FLAG_NEEDS_WEAPON_ME ( 1 << 4 )
#define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 )
#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_ME ( 1 << 6 )
#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )
#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )


// -----------------------------------------
// -----------------------------------------
// Scripted NPC interaction trigger methods
// Scripted NPC interaction trigger methods
// -----------------------------------------
// -----------------------------------------
enum
enum
{
{
SNPCINT_CODE = 0,
SNPCINT_CODE = 0,
SNPCINT_AUTOMATIC_IN_COMBAT = 1,
SNPCINT_AUTOMATIC_IN_COMBAT = 1,
};
};


// -----------------------------------------
// -----------------------------------------
// Scripted NPC interaction loop breaking trigger methods
// Scripted NPC interaction loop breaking trigger methods
// -----------------------------------------
// -----------------------------------------
#define SNPCINT_LOOPBREAK_ON_DAMAGE ( 1 << 1 )
#define SNPCINT_LOOPBREAK_ON_DAMAGE ( 1 << 1 )
#define SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ( 1 << 2 )
#define SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ( 1 << 2 )


// -----------------------------------------
// -----------------------------------------
// Scripted NPC interaction anim phases
// Scripted NPC interaction anim phases
// -----------------------------------------
// -----------------------------------------
enum
enum
{
{
SNPCINT_ENTRY = 0,
SNPCINT_ENTRY = 0,
SNPCINT_SEQUENCE,
SNPCINT_SEQUENCE,
SNPCINT_EXIT,
SNPCINT_EXIT,


SNPCINT_NUM_PHASES
SNPCINT_NUM_PHASES
};
};


struct ScriptedNPCInteraction_Phases_t
struct ScriptedNPCInteraction_Phases_t
{
{
string_t iszSequence;
string_t iszSequence;
int iActivity;
int iActivity;


DECLARE_SIMPLE_DATADESC();
DECLARE_SIMPLE_DATADESC();
};
};


// Allowable delta from the desired dynamic scripted sequence point
// Allowable delta from the desired dynamic scripted sequence point
#define DSS_MAX_DIST 6
#define DSS_MAX_DIST 6
#define DSS_MAX_ANGLE_DIFF 4
#define DSS_MAX_ANGLE_DIFF 4


// Interaction Logic States
// Interaction Logic States
enum
enum
{
{
NPCINT_NOT_RUNNING = 0,
NPCINT_NOT_RUNNING = 0,
NPCINT_RUNNING_ACTIVE, // I'm in an interaction that I initiated
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_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
NPCINT_MOVING_TO_MARK, // I'm moving to a position to do an interaction
};
};


#define NPCINT_NONE -1
#define NPCINT_NONE -1


#define MAXTACLAT_IGNORE -1
#define MAXTACLAT_IGNORE -1


// -----------------------------------------
// -----------------------------------------
// A scripted interaction between NPCs
// A scripted interaction between NPCs
// -----------------------------------------
// -----------------------------------------
struct ScriptedNPCInteraction_t
struct ScriptedNPCInteraction_t
{
{
ScriptedNPCInteraction_t()
ScriptedNPCInteraction_t()
{
{
iszInteractionName = NULL_STRING;
iszInteractionName = NULL_STRING;
iFlags = 0;
iFlags = 0;
iTriggerMethod = SNPCINT_CODE;
iTriggerMethod = SNPCINT_CODE;
iLoopBreakTriggerMethod = 0;
iLoopBreakTriggerMethod = 0;
vecRelativeOrigin = vec3_origin;
vecRelativeOrigin = vec3_origin;
bValidOnCurrentEnemy = false;
bValidOnCurrentEnemy = false;
flDelay = 5.0;
flDelay = 5.0;
flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST);
flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST);
flNextAttemptTime = 0;
flNextAttemptTime = 0;
iszMyWeapon = NULL_STRING;
iszMyWeapon = NULL_STRING;
iszTheirWeapon = NULL_STRING;
iszTheirWeapon = NULL_STRING;


for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
{
{
sPhases[i].iszSequence = NULL_STRING;
sPhases[i].iszSequence = NULL_STRING;
sPhases[i].iActivity = ACT_INVALID;
sPhases[i].iActivity = ACT_INVALID;
}
}
}
}


// Fill out these when passing to AddScriptedNPCInteraction
// Fill out these when passing to AddScriptedNPCInteraction
string_t iszInteractionName;
string_t iszInteractionName;
int iFlags;
int iFlags;
int iTriggerMethod;
int iTriggerMethod;
int iLoopBreakTriggerMethod;
int iLoopBreakTriggerMethod;
Vector vecRelativeOrigin; // (forward, right, up)
Vector vecRelativeOrigin; // (forward, right, up)
QAngle angRelativeAngles;
QAngle angRelativeAngles;
Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
float flDelay; // Delay before interaction can be used again
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
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 iszMyWeapon; // Classname of the weapon I'm holding, if any
string_t iszTheirWeapon; // Classname of the weapon my interaction partner is holding, if any
string_t iszTheirWeapon; // Classname of the weapon my interaction partner is holding, if any
ScriptedNPCInteraction_Phases_t sPhases[SNPCINT_NUM_PHASES];
ScriptedNPCInteraction_Phases_t sPhases[SNPCINT_NUM_PHASES];


// These will be filled out for you in AddScriptedNPCInteraction
// These will be filled out for you in AddScriptedNPCInteraction
VMatrix matDesiredLocalToWorld; // Desired relative position / angles of the other NPC
VMatrix matDesiredLocalToWorld; // Desired relative position / angles of the other NPC
bool bValidOnCurrentEnemy;
bool bValidOnCurrentEnemy;


float flNextAttemptTime;
float flNextAttemptTime;


DECLARE_SIMPLE_DATADESC();
DECLARE_SIMPLE_DATADESC();
};
};


//=============================================================================
//=============================================================================
//
//
// Utility functions
// 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 *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 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 );
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;
extern Vector g_vecAttackDir;


bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget );
bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget );
bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize = 0.0 );
bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize = 0.0 );


// FIXME: move to utils?
// FIXME: move to utils?
float DeltaV( float v0, float v1, float d );
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 );
float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVelocity, float flCurVelocity, float flIdealVelocity, float flAccelRate, float &flNewDistance, float &flNewVelocity );


//=============================================================================
//=============================================================================
//
//
// class CAI_Manager
// class CAI_Manager
//
//
// Central location for components of the AI to operate across all AIs without
// Central location for components of the AI to operate across all AIs without
// iterating over the global list of entities.
// iterating over the global list of entities.
//
//
//=============================================================================
//=============================================================================


class CAI_Manager
class CAI_Manager
{
{
public:
public:
CAI_Manager();
CAI_Manager();
CAI_BaseNPC ** AccessAIs();
CAI_BaseNPC ** AccessAIs();
int NumAIs();
int NumAIs();
void AddAI( CAI_BaseNPC *pAI );
void AddAI( CAI_BaseNPC *pAI );
void RemoveAI( CAI_BaseNPC *pAI );
void RemoveAI( CAI_BaseNPC *pAI );


bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); }
bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); }
private:
private:
enum
enum
{
{
MAX_AIS = 256
MAX_AIS = 256
};
};
typedef CUtlVector<CAI_BaseNPC *> CAIArray;
typedef CUtlVector<CAI_BaseNPC *> CAIArray;
CAIArray m_AIs;
CAIArray m_AIs;


};
};


//-------------------------------------
//-------------------------------------


extern CAI_Manager g_AI_Manager;
extern CAI_Manager g_AI_Manager;


//=============================================================================
//=============================================================================
//
//
// class CAI_BaseNPC
// class CAI_BaseNPC
//
//
//=============================================================================
//=============================================================================


class CAI_BaseNPC : public CBaseCombatCharacter,
class CAI_BaseNPC : public CBaseCombatCharacter,
public CAI_DefMovementSink
public CAI_DefMovementSink
{
{
DECLARE_CLASS( CAI_BaseNPC, CBaseCombatCharacter );
DECLARE_CLASS( CAI_BaseNPC, CBaseCombatCharacter );


public:
public:
//-----------------------------------------------------
//-----------------------------------------------------
//
//
// Initialization, cleanup, serialization, identity
// Initialization, cleanup, serialization, identity
//
//
CAI_BaseNPC();
CAI_BaseNPC();
~CAI_BaseNPC();
~CAI_BaseNPC();


//---------------------------------
//---------------------------------
DECLARE_DATADESC();
DECLARE_DATADESC();
DECLARE_SERVERCLASS();
DECLARE_SERVERCLASS();


virtual int Save( ISave &save );
virtual int Save( ISave &save );
virtual int Restore( IRestore &restore );
virtual int Restore( IRestore &restore );
virtual void OnRestore();
virtual void OnRestore();
void SaveConditions( ISave &save, const CAI_ScheduleBits &conditions );
void SaveConditions( ISave &save, const CAI_ScheduleBits &conditions );
void RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions );
void RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions );


bool ShouldSavePhysics() { return false; }
bool ShouldSavePhysics() { return false; }
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;


virtual bool KeyValue( const char *szKeyName, const char *szValue );
virtual bool KeyValue( const char *szKeyName, const char *szValue );


//---------------------------------
//---------------------------------
virtual void PostConstructor( const char *szClassname );
virtual void PostConstructor( const char *szClassname );
virtual void Activate( void );
virtual void Activate( void );
virtual void Precache( void ); // derived calls at start of Spawn()
virtual void Precache( void ); // derived calls at start of Spawn()
virtual bool CreateVPhysics();
virtual bool CreateVPhysics();
virtual void NPCInit( void ); // derived calls after Spawn()
virtual void NPCInit( void ); // derived calls after Spawn()
void NPCInitThink( void );
void NPCInitThink( void );
virtual void PostNPCInit() {};// called after NPC_InitThink
virtual void PostNPCInit() {};// called after NPC_InitThink
virtual void StartNPC( void );
virtual void StartNPC( void );
virtual bool IsTemplate( void );
virtual bool IsTemplate( void );


virtual void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
virtual void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true );
virtual void UpdateOnRemove( void );
virtual void UpdateOnRemove( void );


virtual int UpdateTransmitState();
virtual int UpdateTransmitState();


//---------------------------------
//---------------------------------
// Component creation factories
// Component creation factories
//
//
// The master call, override if you introduce new component types. Call base first
// The master call, override if you introduce new component types. Call base first
virtual bool CreateComponents();
virtual bool CreateComponents();
// Components defined by the base AI class
// Components defined by the base AI class
virtual CAI_Senses * CreateSenses();
virtual CAI_Senses * CreateSenses();
virtual CAI_MoveProbe * CreateMoveProbe();
virtual CAI_MoveProbe * CreateMoveProbe();
virtual CAI_Motor * CreateMotor();
virtual CAI_Motor * CreateMotor();
virtual CAI_LocalNavigator *CreateLocalNavigator();
virtual CAI_LocalNavigator *CreateLocalNavigator();
virtual CAI_Navigator * CreateNavigator();
virtual CAI_Navigator * CreateNavigator();
virtual CAI_Pathfinder *CreatePathfinder();
virtual CAI_Pathfinder *CreatePathfinder();
virtual CAI_TacticalServices *CreateTacticalServices();
virtual CAI_TacticalServices *CreateTacticalServices();


//---------------------------------
//---------------------------------


virtual bool IsNPC( void ) const { return true; }
virtual bool IsNPC( void ) const { return true; }


//---------------------------------
//---------------------------------


void TestPlayerPushing( CBaseEntity *pPlayer );
void TestPlayerPushing( CBaseEntity *pPlayer );
void CascadePlayerPush( const Vector &push, const Vector &pushOrigin );
void CascadePlayerPush( const Vector &push, const Vector &pushOrigin );
void NotifyPushMove();
void NotifyPushMove();


public:
public:
//-----------------------------------------------------
//-----------------------------------------------------
//
//
// AI processing - thinking, schedule selection and task running
// AI processing - thinking, schedule selection and task running
//
//
//-----------------------------------------------------
//-----------------------------------------------------
void CallNPCThink( void );
void CallNPCThink( void );
// Thinking, including core thinking, movement, animation
// Thinking, including core thinking, movement, animation
virtual void NPCThink( void );
virtual void NPCThink( void );


// Core thinking (schedules & tasks)
// Core thinking (schedules & tasks)
virtual void RunAI( void );// core ai function!
virtual void RunAI( void );// core ai function!


// Called to gather up all relevant conditons
// Called to gather up all relevant conditons
virtual void GatherConditions( void );
virtual void GatherConditions( void );


// Called immediately prior to schedule processing
// Called immediately prior to schedule processing
virtual void PrescheduleThink( void );
virtual void PrescheduleThink( void );


// Called immediately after schedule processing
// Called immediately after schedule processing
virtual void PostscheduleThink( void ) { return; };
virtual void PostscheduleThink( void ) { return; };


// Notification that the current schedule, if any, is ending and a new one is being selected
// Notification that the current schedule, if any, is ending and a new one is being selected
virtual void OnScheduleChange( void );
virtual void OnScheduleChange( void );


// Notification that a new schedule is about to run its first task
// Notification that a new schedule is about to run its first task
virtual void OnStartSchedule( int scheduleType ) {};
virtual void OnStartSchedule( int scheduleType ) {};


// This function implements a decision tree for the NPC. It is responsible for choosing the next behavior (schedule)
// 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.
// based on the current conditions and state.
virtual int SelectSchedule( void );
virtual int SelectSchedule( void );
virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
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
// 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
// remap base schedules into child-specific behaviors
virtual int TranslateSchedule( int scheduleType );
virtual int TranslateSchedule( int scheduleType );


virtual void StartTask( const Task_t *pTask );
virtual void StartTask( const Task_t *pTask );
virtual void RunTask( const Task_t *pTask );
virtual void RunTask( const Task_t *pTask );


void ClearTransientConditions();
void ClearTransientConditions();


virtual void HandleAnimEvent( animevent_t *pEvent );
virtual void HandleAnimEvent( animevent_t *pEvent );


virtual bool IsInterruptable();
virtual bool IsInterruptable();
virtual void OnStartScene( void ) {} // Called when an NPC begins a cine scene (useful for clean-up)
virtual void OnStartScene( void ) {} // Called when an NPC begins a cine scene (useful for clean-up)
virtual bool ShouldPlayerAvoid( void );
virtual bool ShouldPlayerAvoid( void );
virtual void SetPlayerAvoidState( void );
virtual void SetPlayerAvoidState( void );
virtual void PlayerPenetratingVPhysics( void );
virtual void PlayerPenetratingVPhysics( void );


virtual bool ShouldAlwaysThink();
virtual bool ShouldAlwaysThink();
void ForceGatherConditions() { m_bForceConditionsGather = true; SetEfficiency( AIE_NORMAL ); } // Force an NPC out of PVS to call GatherConditions on next think
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 float LineOfSightDist( const Vector &vecDir = vec3_invalid, float zEye = FLT_MAX );


virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
virtual const char *GetTracerType( void );
virtual const char *GetTracerType( void );
virtual void DoImpactEffect( trace_t &tr, int nDamageType );
virtual void DoImpactEffect( trace_t &tr, int nDamageType );
enum
enum
{
{
NEXT_SCHEDULE = LAST_SHARED_SCHEDULE,
NEXT_SCHEDULE = LAST_SHARED_SCHEDULE,
NEXT_TASK = LAST_SHARED_TASK,
NEXT_TASK = LAST_SHARED_TASK,
NEXT_CONDITION = LAST_SHARED_CONDITION,
NEXT_CONDITION = LAST_SHARED_CONDITION,
};
};


protected:
protected:
// Used by derived classes to chain a task to a task that might not be the
// Used by derived classes to chain a task to a task that might not be the
// one they are currently handling:
// one they are currently handling:
void ChainStartTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; StartTask( (const Task_t *)&tempTask ); }
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 ChainRunTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; RunTask( (const Task_t *) &tempTask ); }


void StartTaskOverlay();
void StartTaskOverlay();
void RunTaskOverlay();
void RunTaskOverlay();
void EndTaskOverlay();
void EndTaskOverlay();


virtual void PostRunStopMoving();
virtual void PostRunStopMoving();


bool CheckPVSCondition();
bool CheckPVSCondition();


private:
private:
bool CanThinkRebalance();
bool CanThinkRebalance();
void RebalanceThinks();
void RebalanceThinks();


bool PreNPCThink();
bool PreNPCThink();
void PostNPCThink();
void PostNPCThink();


bool PreThink( void );
bool PreThink( void );
void PerformSensing();
void PerformSensing();
void CheckOnGround( void );
void CheckOnGround( void );
void MaintainSchedule( void );
void MaintainSchedule( void );
void RunAnimation( void );
void RunAnimation( void );
void PostRun( void );
void PostRun( void );
void PerformMovement();
void PerformMovement();
void PostMovement();
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 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
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:
public:
//-----------------------------------------------------
//-----------------------------------------------------
//
//
// Schedules & tasks
// Schedules & tasks
//
//
//-----------------------------------------------------
//-----------------------------------------------------
void SetSchedule( CAI_Schedule *pNewSchedule );
void SetSchedule( CAI_Schedule *pNewSchedule );
bool SetSchedule( int localScheduleID );
bool SetSchedule( int localScheduleID );
void SetDefaultFailSchedule( int failSchedule ) { m_failSchedule = failSchedule; }
void SetDefaultFailSchedule( int failSchedule ) { m_failSchedule = failSchedule; }
void ClearSchedule( const char *szReason );
void ClearSchedule( const char *szReason );
CAI_Schedule * GetCurSchedule() { return m_pSchedule; }
CAI_Schedule * GetCurSchedule() { return m_pSchedule; }
bool IsCurSchedule( int schedId, bool fIdeal = true );
bool IsCurSchedule( int schedId, bool fIdeal = true );
virtual CAI_Schedule *GetSchedule(int localScheduleID);
virtual CAI_Schedule *GetSchedule(int localScheduleID);
virtual int GetLocalScheduleId( int globalScheduleID ) { return AI_IdIsLocal( globalScheduleID ) ? globalScheduleID : GetClassScheduleIdSpace()->ScheduleGlobalToLocal( globalScheduleID ); }
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 ); }
virtual int GetGlobalScheduleId( int localScheduleID ) { return AI_IdIsGlobal( localScheduleID ) ? localScheduleID : GetClassScheduleIdSpace()->ScheduleLocalToGlobal( localScheduleID ); }


float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; }
float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; }
//---------------------------------
//---------------------------------
const Task_t* GetTask( void );
const Task_t* GetTask( void );
int TaskIsRunning( void );
int TaskIsRunning( void );
virtual void TaskFail( AI_TaskFailureCode_t );
virtual void TaskFail( AI_TaskFailureCode_t );
void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); }
void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); }
void TaskComplete( bool fIgnoreSetFailedCondition = false );
void TaskComplete( bool fIgnoreSetFailedCondition = false );


void TaskInterrupt() { m_ScheduleState.iTaskInterrupt++; }
void TaskInterrupt() { m_ScheduleState.iTaskInterrupt++; }
void ClearTaskInterrupt() { m_ScheduleState.iTaskInterrupt = 0; }
void ClearTaskInterrupt() { m_ScheduleState.iTaskInterrupt = 0; }
int GetTaskInterrupt() const { return m_ScheduleState.iTaskInterrupt; }
int GetTaskInterrupt() const { return m_ScheduleState.iTaskInterrupt; }
void TaskMovementComplete( void );
void TaskMovementComplete( void );
inline int TaskIsComplete( void ) { return (GetTaskStatus() == TASKSTATUS_COMPLETE); }
inline int TaskIsComplete( void ) { return (GetTaskStatus() == TASKSTATUS_COMPLETE); }


virtual const char *TaskName(int taskID);
virtual const char *TaskName(int taskID);


float GetTimeTaskStarted() const { return m_ScheduleState.timeCurTaskStarted; }
float GetTimeTaskStarted() const { return m_ScheduleState.timeCurTaskStarted; }
virtual int GetLocalTaskId( int globalTaskId) { return GetClassScheduleIdSpace()->TaskGlobalToLocal( globalTaskId ); }
virtual int GetLocalTaskId( int globalTaskId) { return GetClassScheduleIdSpace()->TaskGlobalToLocal( globalTaskId ); }


virtual const char *GetSchedulingErrorName() { return "CAI_BaseNPC"; }
virtual const char *GetSchedulingErrorName() { return "CAI_BaseNPC"; }


protected:
protected:
static bool LoadSchedules(void);
static bool LoadSchedules(void);
virtual bool LoadedSchedules(void);
virtual bool LoadedSchedules(void);
virtual void BuildScheduleTestBits( void );
virtual void BuildScheduleTestBits( void );


//---------------------------------
//---------------------------------


// This is the main call to select/translate a schedule
// This is the main call to select/translate a schedule
virtual CAI_Schedule *GetNewSchedule( void );
virtual CAI_Schedule *GetNewSchedule( void );
virtual CAI_Schedule *GetFailSchedule( void );
virtual CAI_Schedule *GetFailSchedule( void );


//---------------------------------
//---------------------------------


virtual bool CanFlinch( void );
virtual bool CanFlinch( void );
virtual void CheckFlinches( void );
virtual void CheckFlinches( void );
virtual void PlayFlinchGesture( void );
virtual void PlayFlinchGesture( void );
int SelectFlinchSchedule( void );
int SelectFlinchSchedule( void );


virtual bool IsAllowedToDodge( void );
virtual bool IsAllowedToDodge( void );


bool IsInChoreo() const;
bool IsInChoreo() const;


private:
private:
// This function maps the type through TranslateSchedule() and then retrieves the pointer
// 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.
// to the actual CAI_Schedule from the database of schedules available to this class.
CAI_Schedule * GetScheduleOfType( int scheduleType );
CAI_Schedule * GetScheduleOfType( int scheduleType );
bool FHaveSchedule( void );
bool FHaveSchedule( void );
bool FScheduleDone ( void );
bool FScheduleDone ( void );
CAI_Schedule * ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount );
CAI_Schedule * ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount );


int GetScheduleCurTaskIndex() const { return m_ScheduleState.iCurTask; }
int GetScheduleCurTaskIndex() const { return m_ScheduleState.iCurTask; }
inline int IncScheduleCurTaskIndex();
inline int IncScheduleCurTaskIndex();
inline void ResetScheduleCurTaskIndex();
inline void ResetScheduleCurTaskIndex();
void NextScheduledTask ( void );
void NextScheduledTask ( void );
bool IsScheduleValid ( void );
bool IsScheduleValid ( void );
bool ShouldSelectIdealState( void );
bool ShouldSelectIdealState( void );
// Selecting the ideal state
// Selecting the ideal state
NPC_STATE SelectIdleIdealState();
NPC_STATE SelectIdleIdealState();
NPC_STATE SelectAlertIdealState();
NPC_STATE SelectAlertIdealState();
NPC_STATE SelectScriptIdealState();
NPC_STATE SelectScriptIdealState();


// Various schedule selections based on NPC_STATE
// Various schedule selections based on NPC_STATE
int SelectIdleSchedule();
int SelectIdleSchedule();
int SelectAlertSchedule();
int SelectAlertSchedule();
int SelectCombatSchedule();
int SelectCombatSchedule();
virtual int SelectDeadSchedule();
virtual int SelectDeadSchedule();
int SelectScriptSchedule();
int SelectScriptSchedule();
int SelectInteractionSchedule();
int SelectInteractionSchedule();


void OnStartTask( void ) { SetTaskStatus( TASKSTATUS_RUN_MOVE_AND_TASK ); }
void OnStartTask( void ) { SetTaskStatus( TASKSTATUS_RUN_MOVE_AND_TASK ); }
void SetTaskStatus( TaskStatus_e status ) { m_ScheduleState.fTaskStatus = status; }
void SetTaskStatus( TaskStatus_e status ) { m_ScheduleState.fTaskStatus = status; }
TaskStatus_e GetTaskStatus() const { return m_ScheduleState.fTaskStatus; }
TaskStatus_e GetTaskStatus() const { return m_ScheduleState.fTaskStatus; }


void DiscardScheduleState();
void DiscardScheduleState();


//---------------------------------
//---------------------------------


CAI_Schedule * m_pSchedule;
CAI_Schedule * m_pSchedule;
int m_IdealSchedule;
int m_IdealSchedule;
AIScheduleState_t m_ScheduleState;
AIScheduleState_t m_ScheduleState;
int m_failSchedule; // Schedule type to choose if current schedule fails
int m_failSchedule; // Schedule type to choose if current schedule fails
bo
bo