constexprautoMAX_AI_PATH_SIZE=512;// Maximum number of points allowed in a path (this should be enough for any sized map)
staticconstintMAX_NAV_MESHES=8;// Max number of nav meshes allowed. Currently 3 are used (one for building placement, one for the onos, and a regular one for everyone else)
// NS weapon types. Each number refers to the GoldSrc weapon index
typedefenum
{
WEAPON_INVALID=0,
WEAPON_LERK_SPIKE=4,// I think this is an early NS weapon, replaced by primal scream
// Marine Weapons
WEAPON_MARINE_KNIFE=13,
WEAPON_MARINE_PISTOL=14,
WEAPON_MARINE_MG=15,
WEAPON_MARINE_SHOTGUN=16,
WEAPON_MARINE_HMG=17,
WEAPON_MARINE_WELDER=18,
WEAPON_MARINE_MINES=19,
WEAPON_MARINE_GL=20,
WEAPON_MARINE_GRENADE=28,
// Alien Abilities
WEAPON_SKULK_BITE=5,
WEAPON_SKULK_PARASITE=10,
WEAPON_SKULK_LEAP=21,
WEAPON_SKULK_XENOCIDE=12,
WEAPON_GORGE_SPIT=2,
WEAPON_GORGE_HEALINGSPRAY=27,
WEAPON_GORGE_BILEBOMB=25,
WEAPON_GORGE_WEB=8,
WEAPON_LERK_BITE=6,
WEAPON_LERK_SPORES=3,
WEAPON_LERK_UMBRA=23,
WEAPON_LERK_PRIMALSCREAM=24,
WEAPON_FADE_SWIPE=7,
WEAPON_FADE_BLINK=11,
WEAPON_FADE_METABOLIZE=9,
WEAPON_FADE_ACIDROCKET=26,
WEAPON_ONOS_GORE=1,
WEAPON_ONOS_DEVOUR=30,
WEAPON_ONOS_STOMP=29,
WEAPON_ONOS_CHARGE=22,
WEAPON_MAX=31
}
AvHAIWeapon;
// Hives can either be unbuilt ("ghost" hive), in progress or fully built (active)
typedefenum
{
HIVE_STATUS_UNBUILT=0,
HIVE_STATUS_BUILDING=1,
HIVE_STATUS_BUILT=2
}HiveStatusType;
// All tech statuses that can be assigned to a hive
typedefenum
{
HIVE_TECH_NONE=0,// Hive doesn't have any tech assigned to it yet (no chambers built for it)
HIVE_TECH_DEFENCE=1,
HIVE_TECH_SENSORY=2,
HIVE_TECH_MOVEMENT=3
}HiveTechStatus;
typedefenum_AI_REACHABILITY_STATUS
{
AI_REACHABILITY_NONE=0,
AI_REACHABILITY_MARINE=1u<<0,
AI_REACHABILITY_SKULK=1u<<1,
AI_REACHABILITY_GORGE=1u<<2,
AI_REACHABILITY_ONOS=1u<<3,
AI_REACHABILITY_WELDER=1u<<4,
AI_REACHABILITY_UNREACHABLE=1u<<5,
AI_REACHABILITY_ALL=-1
}AvHAIReachabilityStatus;
typedefenum
{
STRUCTURE_STATUS_NONE=0,// No filters, all buildings will be returned
STRUCTURE_STATUS_COMPLETED=1,// Structure is fully built
STRUCTURE_STATUS_ELECTRIFIED=1<<1,
STRUCTURE_STATUS_RECYCLING=1<<2,
STRUCTURE_STATUS_PARASITED=1<<3,
STRUCTURE_STATUS_UNDERATTACK=1<<4,
STRUCTURE_STATUS_RESEARCHING=1<<5,
STRUCTURE_STATUS_DAMAGED=1<<6,
STRUCTURE_STATUS_DISABLED=1<<7,// For marine turrets when there's no TF
boolbReachabilityMarkedDirty=false;// Reachability needs to be recalculated
intLastSeen=0;// Which refresh cycle was this last seen on? Used to determine if the item has been removed from play
}AvHAIDroppedItem;
// How far a bot can be from a useable object when trying to interact with it. Used also for melee attacks. We make it slightly less than actual to avoid edge cases
staticconstfloatmax_ai_use_reach=55.0f;
// Minimum time a bot can wait between attempts to use something in seconds (when not holding the use key down)
staticconstfloatmin_ai_use_interval=0.5f;
// Minimum time a bot can wait between attempts to use something in seconds (when not holding the use key down)
staticconstfloatmax_ai_jump_height=62.0f;
// Affects the bot's pathfinding choices
enumBotMoveStyle
{
MOVESTYLE_NORMAL,// Most direct route to target
MOVESTYLE_AMBUSH,// Prefer wall climbing and vents
MOVESTYLE_HIDE// Prefer crouched areas like vents
};
// The list of potential task types for the bot_task structure
typedefenum
{
TASK_NONE,
TASK_GET_HEALTH,
TASK_GET_AMMO,
TASK_GET_WEAPON,
TASK_GET_EQUIPMENT,
TASK_BUILD,
TASK_ATTACK,
TASK_MOVE,
TASK_CAP_RESNODE,
TASK_DEFEND,
TASK_GUARD,
TASK_HEAL,
TASK_WELD,
TASK_RESUPPLY,
TASK_EVOLVE,
TASK_COMMAND,
TASK_USE,
TASK_TOUCH,
TASK_REINFORCE_STRUCTURE,
TASK_SECURE_HIVE,
TASK_PLACE_MINE
}
BotTaskType;
//
typedefenum
{
ATTACK_SUCCESS,
ATTACK_BLOCKED,
ATTACK_OUTOFRANGE,
ATTACK_INVALIDTARGET,
ATTACK_NOWEAPON
}
BotAttackResult;
typedefenum
{
BUILD_ATTEMPT_NONE=0,
BUILD_ATTEMPT_PENDING,
BUILD_ATTEMPT_SUCCESS,
BUILD_ATTEMPT_FAILED
}BotBuildAttemptStatus;
typedefenum
{
MOVE_TASK_NONE=0,
MOVE_TASK_MOVE,
MOVE_TASK_USE,
MOVE_TASK_BREAK,
MOVE_TASK_TOUCH,
MOVE_TASK_PICKUP,
MOVE_TASK_WELD
}BotMovementTaskType;
// Door type. Not currently used, future feature so bots know how to open a door
enumDoorActivationType
{
DOOR_NONE,// No type, cannot be activated (permanently open/shut)
DOOR_USE,// Door activated by using it directly
DOOR_TRIGGER,// Door activated by touching a trigger_once or trigger_multiple
DOOR_BUTTON,// Door activated by pressing a button
DOOR_WELD,// Door activated by welding something
DOOR_SHOOT,// Door activated by being shot
DOOR_BREAK// Door activated by breaking something
};
// Door type. Not currently used, future feature so bots know how to open a door
enumNavDoorType
{
DOORTYPE_DOOR,// No type, cannot be activated (permanently open/shut)
DOORTYPE_PLAT,// Door activated by using it directly
DOORTYPE_TRAIN// Door activated by touching a trigger_once or trigger_multiple
};
// Bot path node. A path will be several of these strung together to lead the bot to its destination
typedefstruct_BOT_PATH_NODE
{
VectorFromLocation=g_vecZero;// Location to move from
VectorLocation=g_vecZero;// Location to move to
floatrequiredZ=0.0f;// If climbing a up ladder or wall, how high should they aim to get before dismounting.
unsignedintflag=0;// Is this a ladder movement, wall climb, walk etc
unsignedchararea=0;// Is this a crouch area, normal walking area etc
unsignedintpoly=0;// The nav mesh poly this point resides on
}bot_path_node;
// Represents a bot's current understanding of an enemy player's status
typedefstruct_ENEMY_STATUS
{
AvHPlayer*EnemyPlayer=nullptr;
edict_t*EnemyEdict=nullptr;// Reference to the enemy player edict
VectorLastVisibleLocation=g_vecZero;// The last point the bot saw the target
VectorLastSeenLocation=g_vecZero;// The last visibly-confirmed location of the player or tracked location (if parasited / motion tracked)
VectorLastFloorPosition=g_vecZero;// Nearest point on the floor where the enemy was (for moving towards it)
VectorLastSeenVelocity=g_vecZero;// Last visibly-confirmed movement direction of the player
VectorPendingSeenLocation=g_vecZero;// The last visibly-confirmed location of the player
VectorPendingSeenVelocity=g_vecZero;// Last visibly-confirmed movement direction of the player
VectorLastLOSPosition=g_vecZero;// The last position where the bot has LOS to the enemy
VectorLastHiddenPosition=g_vecZero;// The last position where the bot did NOT have LOS to the enemy
floatLastSeenTime=0.0f;// Last time the bot saw the player (not tracked)
floatLastTrackedTime=0.0f;// Last time the bot saw the player (tracked position)
//bool bInFOV = false; // Is the player in the bot's FOV
boolbHasLOS=false;// Does the bot have LOS to the target
boolbIsVisible=false;// Enemy is in FOV and has LOS
boolbIsAwareOfPlayer=false;// Is the bot aware of this player's presence?
floatNextUpdateTime=0.0f;// When the bot can next react to a change in target's state
floatNextVelocityUpdateTime=0.0f;// When the bot can next react to a change in target's state
floatEndTrackingTime=0.0f;// When to stop "sensing" enemy movement after losing LOS
VectorActualMoveDestination=g_vecZero;// Actual destination on nav mesh
VectorPathDestination=g_vecZero;// Where the path is currently headed to
VectorLastNavMeshCheckPosition=g_vecZero;
VectorLastNavMeshPosition=g_vecZero;// Tracks the last place the bot was on the nav mesh. Useful if accidentally straying off it
VectorLastOpenLocation=g_vecZero;// Tracks the last place the bot had enough room to move around people. Useful if in a vent and need to back up somewhere to let another player past.
intCurrentMoveType=MOVETYPE_NONE;// Tracks the edict's current movement type
unsignedintCurrentPoly=0;// Which nav mesh poly the bot is currently on
floatLastStuckCheckTime=0.0f;// Last time the bot checked if it had successfully moved
floatTotalStuckTime=0.0f;// Total time the bot has spent stuck
floatLastDistanceFromDestination=0.0f;// How far from its destination was it last stuck check
VectorStuckCheckMoveLocation=g_vecZero;// Where is the bot trying to go that we're checking if they're stuck?
VectorUnstuckMoveLocation=g_vecZero;// If the bot is unable to find a path, blindly move here to try and fix the problem
floatLandedTime=0.0f;// When the bot last landed after a fall/jump.
floatLeapAttemptedTime=0.0f;// When the bot last attempted to leap/blink. Avoid spam that sends it flying around too fast
boolbIsJumping=false;// Is the bot in the air from a jump? Will duck so it can duck-jump
boolIsOnGround=true;// Is the bot currently on the ground, or on a ladder?
boolbHasAttemptedJump=false;// Last frame, the bot tried a jump. If the bot is still on the ground, it probably tried to jump in a vent or something
floatLastFlapTime=0.0f;// When the bot last flapped its wings (if Lerk). Prevents per-frame spam draining adrenaline
boolbShouldWalk=false;// Should the bot walk at this point?
BotMoveStylePreviousMoveStyle=MOVESTYLE_NORMAL;// Previous desired move style (e.g. normal, ambush, hide). Will trigger new path calculations if this changes
BotMoveStyleMoveStyle=MOVESTYLE_NORMAL;// Current desired move style (e.g. normal, ambush, hide). Will trigger new path calculations if this changes
floatLastPathCalcTime=0.0f;// When the bot last calculated a path, to limit how frequently it can recalculate
floatNextForceRecalc=0.0f;// If set, then the bot will force-recalc its current path
boolbZig;// Is the bot zigging, or zagging?
floatNextZigTime;// Controls how frequently they zig or zag
nav_profileNavProfile;
boolbNavProfileChanged=false;
AvHAIPlayerStuckTrackerStuckInfo;
unsignedintSpecialMovementFlags=0;// Any special movement flags required for this path (e.g. needs a welder, needs a jetpack etc.)
AvHAIPlayerMoveTaskMovementTask;
}nav_status;
// Type of goal the commander wants to achieve
typedefenum_COMMANDERACTIONTYPE
{
ACTION_NONE=0,
ACTION_UPGRADE,
ACTION_RESEARCH,
ACTION_RECYCLE,
ACTION_GIVEORDER,
ACTION_DEPLOY// Deploy a structure or item into the map
}CommanderActionType;
// Some commander actions are multi-step (e.g. click to select building, release to complete selection, input recycle command etc). Tracks where the commander is in the process
typedefenum_COMMANDERACTIONSTEP
{
ACTION_STEP_NONE=0,
ACTION_STEP_BEGIN_SELECT,// Click mouse button down to start select
ACTION_STEP_END_SELECT,// Release mouse button to complete select
}CommanderActionStep;
// Used by the AI commander instead of bot_task. Has data specifically to handle commander-specific stuff
typedefstruct_COMMANDER_ACTION
{
boolbIsActive=false;
CommanderActionTypeActionType=ACTION_NONE;// What action to perform (e.g. build, recycle, drop item etc)
CommanderActionStepActionStep=ACTION_STEP_NONE;// Used for multi-stage processes such as selecting a building, issuing recycle command etc.
AvHAIDeployableStructureTypeStructureToBuild=STRUCTURE_NONE;// What structure to build if build action
VectorBuildLocation=g_vecZero;// Where to build the structure
VectorDesiredCommanderLocation=g_vecZero;// To perform this action, where does the commander's view need to be? For building, usually directly above location, but could be off to side if obstructed by geometry
VectorLastAttemptedCommanderLocation=g_vecZero;// The position of the commander's view at the last action attempt
VectorLastAttemptedCommanderAngle=g_vecZero;// The click angle of the last action attempt
intAssignedPlayer=0;// Which player index is assigned to perform the action (e.g. build structure)? Will send orders to that player (move here, build this structure etc.)
edict_t*StructureOrItem=nullptr;// Reference the structure edict. If a structure has been successfully placed but not yet fully built, it will be referenced here
edict_t*ActionTarget=nullptr;// Mostly used for dropping health packs and ammo for players where the drop location might be moving around
boolbHasAttemptedAction=false;// Has the commander tried placing a structure or item at the build location? If so, and it didn't appear, will try to adjust view around until it works
floatStructureBuildAttemptTime=0.0f;// When the commander tried placing a structure. Commander will wait a short while to confirm if the building appeared or if it should try again
intNumActionAttempts=0;// Commander will give up after a certain number of attempts to place structure/item
AvHMessageIDResearchId=MESSAGE_NULL;// What research to perform if research action
boolbIsAwaitingBuildLink=false;// The AI has tried placing a structure or item and is waiting to confirm it worked or not
boolbIsActionUrgent=false;
}commander_action;
typedefenum
{
ORDERPURPOSE_NONE,
ORDERPURPOSE_SECURE_HIVE,
ORDERPURPOSE_SIEGE_HIVE,
ORDERPURPOSE_SECURE_RESNODE
}AvHAIOrderPurpose;
typedefstruct_AI_COMMANDER_ORDER
{
edict_t*Assignee=nullptr;
AvHAIOrderPurposeOrderPurpose=ORDERPURPOSE_NONE;
edict_t*OrderTarget=nullptr;
VectorOrderLocation=g_vecZero;
floatLastReminderTime=0.0f;
floatLastPlayerDistance=0.0f;
}ai_commander_order;
typedefstruct_AI_COMMANDER_REQUEST
{
boolbNewRequest=false;// Is this a new request just come in?
edict_t*Requestor=nullptr;// Who sent the request?
AvHMessageIDRequestType=MESSAGE_NULL;// What did they request?
boolbAcknowledged=false;// If we can't satisfy the request right now, have we at least acknowledged it?
boolbResponded=false;// Have we already responded to this request?
floatRequestTime=0.0f;// When the request came in
intResponseAttempts=0;// How many times have we tried to respond to this request?
VectorRequestLocation=g_vecZero;// Where was the request raised? Ideal drop location for stuff
charPathStatus[128];// Debug used to help figure out what's going on with a bot's path finding
charMoveStatus[128];// Debug used to help figure out what's going on with a bot's steering
nav_statusBotNavInfo;// Bot's movement information, their current path, where in the path they are etc.
vector<ai_commander_request>ActiveRequests;
vector<ai_commander_order>ActiveOrders;
floatnext_commander_action_time=0.0f;
bot_msgChatMessages[5];// Bot can have up to 5 chat messages pending
floatLastCombatTime=0.0f;
AvHAIGuardInfoGuardInfo;
floatLastRequestTime=0.0f;// When bot last used a voice line to request something. Prevents spam
VectorDesiredLookDirection=g_vecZero;// What view angle is the bot currently turning towards
VectorInterpolatedLookDirection=g_vecZero;// Used to smoothly interpolate the bot's view rather than snap instantly like an aimbot
edict_t*LookTarget=nullptr;// Used to work out what view angle is needed to look at the desired entity
VectorLookTargetLocation=g_vecZero;// This is the bot's current desired look target. Could be an enemy (see LookTarget), or point of interest
VectorMoveLookLocation=g_vecZero;// If the bot has to look somewhere specific for movement (e.g. up for a ladder or wall-climb), this will override LookTargetLocation so the bot doesn't get distracted and mess the move up
floatLastTargetTrackUpdate=0.0f;// Add a delay to how frequently a bot can track a target's movements
floatViewInterpolationSpeed=0.0f;// How fast should the bot turn its view? Depends on distance to turn
floatViewInterpStartedTime=0.0f;// Used for interpolation
floatViewUpdateRate=0.2f;// How frequently the bot can react to new sightings of enemies etc.
floatLastViewUpdateTime=0.0f;// Used to throttle view updates based on ViewUpdateRate
VectorViewForwardVector=g_vecZero;// Bot's current forward unit vector
VectorLastSafeLocation=g_vecZero;
AvHAIBotRoleBotRole=BOT_ROLE_NONE;
intExperiencePointsAvailable=0;// How much experience the bot has to spend
AvHMessageIDNextCombatModeUpgrade=MESSAGE_NULL;
floatThinkDelta=0.0f;// How long since this bot last ran AIPlayerThink
floatLastThinkTime=0.0f;// When the bot last ran AIPlayerThink
floatServerUpdateDelta=0.0f;// How long since we last called RunPlayerMove
floatLastServerUpdateTime=0.0f;// When we last called RunPlayerMove
floatHearingThreshold=0.0f;// How loud does a sound need to be before the bot detects it? This is set when hearing a sound so that louder sounds drown out quieter ones, and decrements quickly