//===========================================================================
//
// Name:			ai_cast.h
// Function:		Wolfenstein AI Character Routines
// Programmer:		Ridah
// Tab Size:		4 (real tabs)
//===========================================================================

#include "../botai/ai_main.h"	// just so we can use the structures
#include "../botai/ai_dmq3.h"	// just so we can use the structures

#include "ai_cast_fight.h"

//
// constants/defines
//
#define MAX_AIFUNCS			15		// if we go over this per frame, likely to have an infinite loop
//
#define	SIGHT_PER_SEC		100		// do this many sight iterations per second
//
// Cast AI specific action flags (get translated into ucmd's
#define CASTACTION_WALK		1
//
#define	MAX_SCRIPT_ACCUM_BUFFERS	8
//
#define	AICAST_PRT_ALWAYS	0
#define	AICAST_PRT_DEBUG	1
//
#define	DEBUG_FOLLOW_DIST	96
//
#define	MAX_LEADER_DIST		256
//
#define	AASWORLD_STANDARD	0
#define	AASWORLD_LARGE		1
//
// use this for returning the length of an anim
#define	ANIMLENGTH(frames,fps)	((frames*1000)/fps)
//
#define AICAST_TFL_DEFAULT	TFL_DEFAULT & ~(TFL_JUMPPAD|TFL_ROCKETJUMP|TFL_BFGJUMP|TFL_GRAPPLEHOOK|TFL_DOUBLEJUMP|TFL_RAMPJUMP|TFL_STRAFEJUMP|TFL_LAVA)	//----(SA)	modified since slime is no longer deadly
//#define AICAST_TFL_DEFAULT	TFL_DEFAULT & ~(TFL_JUMPPAD|TFL_ROCKETJUMP|TFL_BFGJUMP|TFL_GRAPPLEHOOK|TFL_DOUBLEJUMP|TFL_RAMPJUMP|TFL_STRAFEJUMP|TFL_SLIME|TFL_LAVA)
//
// AI flags
#define	AIFL_CATCH_GRENADE		0x1
#define	AIFL_NO_FLAME_DAMAGE	0x2
#define	AIFL_FIRED				0x4
#define	AIFL_LAND_ANIM_PLAYED	0x8
#define	AIFL_ROLL_ANIM			0x10
#define	AIFL_FLIP_ANIM			0x20
#define	AIFL_STAND_IDLE2		0x40
#define	AIFL_NOAVOID			0x80	// if set, this AI will ignore requests for us to move out the way
#define	AIFL_NOPAIN				0x100	// don't stop for pain anims
#define	AIFL_WALKFORWARD		0x200	// only walk forward
#define	AIFL_DENYACTION			0x400	// used by scripting to prevent dynamic code from executing certain behaviour
#define	AIFL_VIEWLOCKED			0x800	// prevent anything outside movement routines from changing view
#define	AIFL_CORPSESIGHTING		0x1000	// share information through friendly corpses
#define	AIFL_WAITINGTOSPAWN		0x2000	// waiting until space is clear to spawn in to the game
#define	AIFL_JUST_SPAWNED		0x4000
#define	AIFL_NO_RELOAD			0x8000	// this character doesn't need to reload
#define	AIFL_TALKING			0x10000
#define	AIFL_NO_HEADLOOK		0x20000
#define	AIFL_ATTACK_CROUCH		0x40000
#define	AIFL_MISCFLAG1			0x80000		// used various bits of code, temporarily
#define	AIFL_MISCFLAG2			0x100000	// used various bits of code, temporarily
#define	AIFL_ZOOMING			0x200000
#define	AIFL_NO_HEADSHOT_DMG	0x400000
#define	AIFL_DIVE_ANIM			0x800000	// able to dive to cover
#define	AIFL_NO_TESLA_DAMAGE	0x1000000
//
// predict events
typedef enum
{
	PREDICTSTOP_NONE,
	PREDICTSTOP_HITENT,
	PREDICTSTOP_HITCLIENT
} predictStop_t;
//
typedef enum
{
	AITEAM_NAZI,
	AITEAM_ALLIES,
	AITEAM_MONSTER,
	AITEAM_SPARE1,
	AITEAM_SPARE2,
	AITEAM_SPARE3,
	AITEAM_SPARE4,
	AITEAM_NEUTRAL
} AITeam_t;
//
typedef enum
{
	BBOX_SMALL,
	BBOX_LARGE
} BBoxType_t;
//
// attributes
// !!! NOTE: any changes to this must be reflected in the attributeStrings in ai_cast.c
typedef enum
{
	RUNNING_SPEED,	// max = 300	(running speed)
	WALKING_SPEED,	// max = 300	(walking speed)
	CROUCHING_SPEED,// max = 300	(crouching speed)
	FOV,			// max = 360	(field of view)
	YAW_SPEED,		// max = 300	(yaw speed, so we can make zombie's turn slowly)
	LEADER,			// max = 1.0	(ability to lead an AI squadron)
	AIM_SKILL,		// max = 1.0	(skill while aiming)
	AIM_ACCURACY,	// max = 1.0	(accuracy of firing)
	ATTACK_SKILL,	// max = 1.0	(ability to attack and do other things, like retreat)
	REACTION_TIME,	// max = 1.0	(upon seeing enemy, wait this long before reaction)
	ATTACK_CROUCH,	// max = 1.0	(likely to crouch while firing)
	IDLE_CROUCH,	// max = 1.0	(likely to crouch while idling)
	AGGRESSION,		// max = 1.0	(willingness to fight till the death)
	TACTICAL,		// max = 1.0	(ability to use strategy to their advantage, also behaviour whilst hunting enemy, more likely to creep around)
	CAMPER,			// max = 1.0	(set this to make them stay in the spot they are spawned)
	ALERTNESS,		// max = 1.0	(ability to notice enemies at long range)
	STARTING_HEALTH,// MAX = 999	(starting health)
	HEARING_SCALE,	// max = 999	(multiply default hearing ranges by this)
	INNER_DETECTION_RADIUS,	// default = 512	(enemies within this range trigger immediate combat mode
	PAIN_THRESHOLD_SCALE,	// default = 1.0

	AICAST_MAX_ATTRIBUTES

} castAttributes_t;
//
typedef struct {
	char *name;
	float attributes[AICAST_MAX_ATTRIBUTES];
	char *sightSoundScript;
	char *attackSoundScript;
	char *ordersSoundScript;
	char *deathSoundScript;
	char *quietDeathSoundScript;	//----(SA)	added for silent deaths (sniper/knife)
	char *painSoundScript;

	char *staySoundScript;
	char *followSoundScript;
	char *ordersDenySoundScript;
	
	int aiTeam;
	char *skin;
	int	weapons[8];
	int bboxType;
	vec2_t	crouchstandZ;
	int	aiFlags;

	char	*(*aifuncAttack1)(struct cast_state_s *cs);		//use this battle aifunc for monster_attack1
	char	*(*aifuncAttack2)(struct cast_state_s *cs);		//use this battle aifunc for monster_attack2
	char	*(*aifuncAttack3)(struct cast_state_s *cs);		//use this battle aifunc for monster_attack2

	char *loopingSound;		// play this sound constantly while alive

	aistateEnum_t	aiState;
} AICharacterDefaults_t;

//
// script flags
#define	SFL_NOCHANGEWEAPON			0x1
#define	SFL_NOAIDAMAGE				0x2
#define	SFL_FRIENDLYSIGHTCORPSE_TRIGGERED	0x4
#define	SFL_WAITING_RESTORE			0x8
#define	SFL_FIRST_CALL				0x10
//
// attributes strings (used for per-entity attribute definitions)
// NOTE: these must match the attributes above)
extern char *castAttributeStrings[];
extern AICharacterDefaults_t aiDefaults[NUM_CHARACTERS];
//
// structure defines
//
#define	AIVIS_ENEMY			1
#define	AIVIS_INSPECTED		2		// we have inspected them once already
#define	AIVIS_INSPECT		4		// we should inspect them when we get a chance
#define	AIVIS_PROCESS_SIGHTING	8	// so we know if we have or haven't processed the sighting since they were last seen
//
// share range
#define	AIVIS_SHARE_RANGE	170		// if we are within this range of a friendly, share their vis info
//
#define	MAX_CHASE_MARKERS		3
#define	CHASE_MARKER_INTERVAL	1000
//
#define	COMBAT_TIMEOUT			8000
// sight info
typedef struct
{
	int		flags;
	int		lastcheck_timestamp;
	int		real_visible_timestamp;
	int		real_update_timestamp;
	int		real_notvisible_timestamp;
	int		visible_timestamp;		// time we last recorded a sighting
	vec3_t	visible_pos;			// position we last knew of them being at (could be hearing, etc)
	vec3_t	real_visible_pos;		// position we last physically saw them
	vec3_t	visible_vel;			// velocity during last sighting
	int		notvisible_timestamp;	// last time we didn't see the entity (used for reaction delay)
	vec3_t	chase_marker[MAX_CHASE_MARKERS];
	int		chase_marker_count;
	int		lastcheck_health;
} cast_visibility_t;
//
// starting weapons, ammo, etc
typedef struct
{
	int		startingWeapons[MAX_WEAPONS/(sizeof(int)*8)];
	int		startingAmmo[MAX_WEAPONS];		// starting ammo values for each weapon (set to 999 for unlimited)
} cast_weapon_info_t;
//
// scripting
typedef struct
{
	char	*actionString;
	qboolean (*actionFunc)(struct cast_state_s *cs, char *params);
} cast_script_stack_action_t;
//
typedef struct
{
	//
	// set during script parsing
	cast_script_stack_action_t		*action;			// points to an action to perform
	char							*params;
} cast_script_stack_item_t;
//
#define	AICAST_MAX_SCRIPT_STACK_ITEMS	64
//
typedef struct
{
	cast_script_stack_item_t	items[AICAST_MAX_SCRIPT_STACK_ITEMS];
	int							numItems;
} cast_script_stack_t;
//
typedef struct
{
	int					eventNum;			// index in scriptEvents[]
	char				*params;			// trigger targetname, etc
	cast_script_stack_t	stack;
} cast_script_event_t;
//
typedef struct
{
	char		*eventStr;
	qboolean	(*eventMatch)( cast_script_event_t *event, char *eventParm );
} cast_script_event_define_t;
//
typedef struct
{
	int		castScriptStackHead, castScriptStackChangeTime;
	int		castScriptEventIndex;	// current event containing stack of actions to perform
	// scripting system AI variables (set by scripting system, used directly by AI)
	int		scriptId;				// incremented each time the script changes
	int		scriptFlags;
	int		scriptNoAttackTime;
	int		scriptNoMoveTime;
	int		scriptGotoEnt;			// just goto them, then resume normal behaviour (don't follow)
	int		scriptGotoId;
	vec3_t	scriptWaitPos;
	int		scriptWaitMovetime;
	vec3_t	scriptWaitHidePos;
	int		scriptWaitHideTime;
	int		scriptNoSightTime;
	int		scriptAttackEnt;		// we should always attack this AI if they are alive
} cast_script_status_t;
//
typedef struct
{
	aistateEnum_t	currentState;
	aistateEnum_t	nextState;
	int				nextStateTimer;	// time left until "newState" is reached
} aistate_t;
//
typedef enum
{
	MS_DEFAULT,
	MS_WALK,
	MS_RUN,
	MS_CROUCH
} movestate_t;
//
typedef enum
{
	MSTYPE_NONE,
	MSTYPE_TEMPORARY,
	MSTYPE_PERMANENT
} movestateType_t;
//
//
typedef struct aicast_checkattack_cache_s
{
	int enemy;
	qboolean allowHitWorld;
	int time;
	int weapon;
	qboolean result;
} aicast_checkattack_cache_t;
//
// --------------------------------------------------------------------------------
// the main cast structure
typedef struct cast_state_s
{
	bot_state_t		*bs;
	int				entityNum;

	int		aasWorldIndex;			// set this according to our bounding box type

	// Cast specific information follows. Add to this as needed, this way the bot_state_t structure
	// remains untouched.	

	int		aiCharacter;
	int		aiFlags;
	int		lastThink;				// time they last thinked, so we can vary the think times
	int		actionFlags;			// cast AI specific movement flags
	int		lastPain, lastPainDamage;
	int		travelflags;
	int		thinkFuncChangeTime;

	aistateEnum_t		aiState;
	movestate_t			movestate;		// walk, run, crouch etc (can be specified in a script)
	movestateType_t		movestateType;	// temporary, permanent, etc

	float	attributes[AICAST_MAX_ATTRIBUTES];
									// these define the abilities of each cast AI

	// scripting system
	int						numCastScriptEvents;
	cast_script_event_t		*castScriptEvents;	// contains a list of actions to perform for each event type
	cast_script_status_t	castScriptStatus;	// current status of scripting
	cast_script_status_t	castScriptStatusCurrent;	// scripting status to use for backups
	cast_script_status_t	castScriptStatusBackup;	// perm backup of status of scripting, only used by backup and restore commands
	int						scriptCallIndex;	// inc'd each time a script is called
	int						scriptAnimTime, scriptAnimNum;		// last time an anim was played using scripting
	// the accumulation buffer
	int scriptAccumBuffer[MAX_SCRIPT_ACCUM_BUFFERS];

	//
	cast_weapon_info_t	*weaponInfo;	// FIXME: make this a list, so they can have multiple weapons?
	cast_visibility_t	vislist[MAX_CLIENTS];		// array of all other client entities, allocated at level start-up
	int		weaponFireTimes[MAX_WEAPONS];

	char	*(*aifunc)(struct cast_state_s *cs);			//current AI function
	char	*(*oldAifunc)(struct cast_state_s *cs);			// just so we can restore the last aiFunc if required

	char	*(*aifuncAttack1)(struct cast_state_s *cs);		//use this battle aifunc for monster_attack1
	char	*(*aifuncAttack2)(struct cast_state_s *cs);		//use this battle aifunc for monster_attack2
	char	*(*aifuncAttack3)(struct cast_state_s *cs);		//use this battle aifunc for monster_attack2

	void	(*painfunc)(gentity_t *ent, gentity_t *attacker, int damage, vec3_t point);
	void	(*deathfunc)(gentity_t *ent, gentity_t *attacker, int damage, int mod);	//----(SA)	added mod
	void	(*sightfunc)(gentity_t *ent, gentity_t *other, int lastSight);

	//int		(*getDeathAnim)(gentity_t *ent, gentity_t *attacker, int damage);
	void	(*sightEnemy)(gentity_t *ent, gentity_t *other);
	void	(*sightFriend)(gentity_t *ent, gentity_t *other);

	void	(*activate)(int entNum, int activatorNum);

	//
	// !!! NOTE: make sure any entityNum type variables get initialized
	//		to -1 in AICast_CreateCharacter(), or they'll be defaulting to
	//		the player (index 0)
	//

	// goal/AI stuff

	int		followEntity;
	float	followDist;
	qboolean followIsGoto;		// we are really just going to the entity, but should wait until scripting tells us we can stop
	int		followTime;			// if this runs out, the scripting has probably been interupted
	qboolean followSlowApproach;

	int		leaderNum;			// entnum of player we are following

	float	speedScale;			// so we can vary movement speed

	float	combatGoalTime;
	vec3_t	combatGoalOrigin;

	int		lastGetHidePos;
	int		startAttackCount;	// incremented each time we start a standing attack
								// used to make sure we only find a combat spot once per attack
	int		combatSpotAttackCount;
	int		combatSpotDelayTime;
	int		startBattleChaseTime;

	int		blockedTime;		// time they were last blocked by a solid entity
	int		obstructingTime;	// time that we should move so we are not obstructing someone else
	vec3_t	obstructingPos;

	int		blockedAvoidTime;
	float	blockedAvoidYaw;

	int		deathTime;
	int		rebirthTime, revivingTime;

	// battle values
	int		enemyHeight;
	int		enemyDist;

	vec3_t	takeCoverPos, takeCoverEnemyPos;
	int		takeCoverTime;

	int		attackSpotTime;

	int		triggerReleaseTime;

	int		lastWeaponFired;	// set each time a weapon is fired. used to detect when a weapon has been fired from within scripting
	vec3_t	lastWeaponFiredPos;
	int		lastWeaponFiredWeaponNum;

	// idle behaviour stuff
	int		lastEnemy, nextIdleAngleChange;
	float	idleYawChange, idleYaw;

	qboolean	crouchHideFlag;

	int		doorMarker, doorEntNum;

	// Rafael
	int		attackSNDtime;
	int		attacksnd;
	int		painSoundTime;
	int		firstSightTime;
	qboolean	secondDeadTime;
	// done

	int		startGrenadeFlushTime;
	int		lockViewAnglesTime;
	int		grenadeFlushEndTime;
	int		grenadeFlushFiring;

	int		dangerEntity;
	int		dangerEntityValidTime;	// dangerEntity is valid until this time expires
	vec3_t	dangerEntityPos;		// dangerEntity is predicted to end up here
	int		dangerEntityTimestamp;	// time this danger was recorded
	float	dangerDist;

	int		mountedEntity;			// mg42, etc that we have mounted
	int		inspectBodyTime;
	vec3_t	startOrigin;

	int		damageQuota;
	int		damageQuotaTime;

	int		dangerLastGetAvoid;
	int		lastAvoid;

	int		doorMarkerTime, doorMarkerNum, doorMarkerDoor;

	int		pauseTime;				// absolutely don't move move while this is > level.time

	aicast_checkattack_cache_t checkAttackCache;

	int		secretsFound;

	int		attempts;

	qboolean	grenadeGrabFlag;	// if this is set, we need to play the anim before we can grab it

	vec3_t	lastMoveToPosGoalOrg;	// if this changes, we should reset the Bot Avoid Reach

	int		noAttackTime;			// used by dynamic AI to stop attacking for set time

	int		lastRollMove;
	int		lastFlipMove;

	vec3_t	stimFlyAttackPos;

	int		lastDodgeRoll;			// last time we rolled to get out of our enemies direct aim
	int		battleRollTime;

	vec3_t	viewlock_viewangles;
	int		grenadeKickWeapon;

	int		animHitCount;			// for stepping through the frames on which to inflict damage

	int		totalPlayTime, lastLoadTime;

	int		queryStartTime, queryCountValidTime, queryCount, queryAlertSightTime;

	int		lastScriptSound;

	int		inspectNum;

	int		scriptPauseTime;

	int		bulletImpactTime;		// last time we heard/saw a bullet impact
	int		bulletImpactIgnoreTime;
	vec3_t	bulletImpactStart, bulletImpactEnd;

	int		audibleEventTime;
	vec3_t	audibleEventOrg;
	int		audibleEventEnt;

	int		battleChaseMarker, battleChaseMarkerDir;

	int		lastBattleHunted;		// last time an enemy decided to hunt us
	int		battleHuntPauseTime, battleHuntViewTime;

	int		lastAttackCrouch;

	int		lastMoveThink;		// last time we ran our ClientThink()

	int		numEnemies;			// last count of enemies that are currently pursuing us

	// -------------------------------------------------------------------------------------------
	// if working on a post release patch, new variables should ONLY be inserted after this point
	// -------------------------------------------------------------------------------------------
	
} cast_state_t;
//
#define	CSFOFS(x) ((int)&(((cast_state_t *)0)->x))
//
typedef struct aicast_predictmove_s
{
	vec3_t endpos;				//position at the end of movement prediction
	vec3_t velocity;			//velocity at the end of movement prediction
	int presencetype;			//presence type at end of movement prediction
	int stopevent;				//event that made the prediction stop
	float time;					//time predicted ahead
	int frames;					//number of frames predicted ahead
	int	numtouch;
	int	touchents[MAXTOUCH];
	int	groundEntityNum;
} aicast_predictmove_t;
//
// variables/globals
//
//cast states
extern cast_state_t	*caststates;
//number of characters
extern int numcast;
//
// minimum time between thinks (maximum is double this)
extern int	aicast_thinktime;
// maximum number of character thinks at once
extern int aicast_maxthink;
// maximum clients
extern int aicast_maxclients;
// skill scale
extern float aicast_skillscale;
//
// cvar to enable aicast debugging, set higher for more levels of debugging
extern vmCvar_t	aicast_debug;
extern vmCvar_t	aicast_debugname;
extern vmCvar_t	aicast_scripts;
//
extern int numSecrets;
//
// procedure defines
//
// ai_cast.c
void	AIChar_SetBBox( gentity_t *ent, cast_state_t *cs );
void	AICast_Printf( int type, const char *fmt, ... );
gentity_t *AICast_CreateCharacter( gentity_t *ent, float *attributes, cast_weapon_info_t *weaponInfo, char *castname, char *model, char *head, char *sex, char *color, char *handicap );
void	AICast_Init (void);
void	AICast_DelayedSpawnCast( gentity_t *ent, int castType );
qboolean AICast_SolidsInBBox( vec3_t pos, vec3_t mins, vec3_t maxs, int entnum, int mask );
void	AICast_CheckLevelAttributes( cast_state_t *cs, gentity_t *ent, char **ppStr );
//
// ai_cast_sight.c
void	AICast_SightUpdate (int numchecks);
qboolean AICast_VisibleFromPos(	vec3_t srcpos, int srcnum,
								vec3_t destpos, int destnum, qboolean updateVisPos );
void	AICast_UpdateVisibility( gentity_t *srcent, gentity_t *destent, qboolean shareVis, qboolean directview );
qboolean AICast_CheckVisibility( gentity_t *srcent, gentity_t *destent );
void	AICast_SightSoundEvent( cast_state_t *cs, float range );
//
// ai_cast_debug.c
void	AICast_DBG_InitAIFuncs (void);
void	AICast_DBG_AddAIFunc (cast_state_t *cs, char *funcname);
void	AICast_DBG_ListAIFuncs( cast_state_t *cs, int numprint );
void	AICast_DBG_RouteTable_f(vec3_t org, char *param);
int		Sys_MilliSeconds(void);
void	AICast_DebugFrame( cast_state_t *cs );
//
// ai_cast_funcs.c
bot_moveresult_t *AICast_MoveToPos( cast_state_t *cs, vec3_t pos, int entnum );
float	AICast_SpeedScaleForDistance( cast_state_t *cs, float startdist, float idealDist );
char	*AIFunc_DefaultStart( cast_state_t *cs );
char	*AIFunc_IdleStart( cast_state_t *cs );
char	*AIFunc_ChaseGoalIdleStart( cast_state_t *cs, int entitynum, float reachdist );
char	*AIFunc_ChaseGoalStart( cast_state_t *cs, int entitynum, float reachdist, qboolean slowApproach );
char	*AIFunc_BattleChaseStart( cast_state_t *cs );
char	*AIFunc_BattleStart( cast_state_t *cs );
char	*AIFunc_DoorMarkerStart( cast_state_t *cs, int doornum, int markernum );
char	*AIFunc_DoorMarker( cast_state_t *cs );
char	*AIFunc_BattleTakeCoverStart( cast_state_t *cs );
char	*AIFunc_GrenadeFlushStart( cast_state_t *cs );
char	*AIFunc_AvoidDangerStart( cast_state_t *cs );
char	*AIFunc_BattleMG42Start( cast_state_t *cs );
char	*AIFunc_InspectBodyStart( cast_state_t *cs );
char	*AIFunc_GrenadeKickStart( cast_state_t *cs );
char	*AIFunc_InspectFriendlyStart( cast_state_t *cs, int entnum );
char	*AIFunc_InspectBulletImpactStart( cast_state_t *cs );
char	*AIFunc_InspectAudibleEventStart( cast_state_t *cs, int entnum );
char	*AIFunc_BattleAmbushStart( cast_state_t *cs );
char	*AIFunc_BattleHuntStart( cast_state_t *cs );
//
// ai_cast_func_attack.c
char	*AIFunc_ZombieFlameAttackStart( cast_state_t *cs );
char	*AIFunc_ZombieAttack2Start( cast_state_t *cs );
char	*AIFunc_LoperAttack1Start( cast_state_t *cs );
char	*AIFunc_LoperAttack2Start( cast_state_t *cs );
char	*AIFunc_LoperAttack3Start( cast_state_t *cs );
char	*AIFunc_StimSoldierAttack1Start( cast_state_t *cs );
char	*AIFunc_StimSoldierAttack2Start( cast_state_t *cs );
char	*AIFunc_BlackGuardAttack1Start( cast_state_t *cs );
char	*AIFunc_RejectAttack1Start( cast_state_t *cs );	//----(SA)	
char	*AIFunc_WarriorZombieMeleeStart( cast_state_t *cs );
char	*AIFunc_WarriorZombieSightStart( cast_state_t *cs );
char	*AIFunc_WarriorZombieDefenseStart( cast_state_t *cs );
//
// ai_cast_func_boss1.c
char	*AIFunc_FZombie_IdleStart( cast_state_t *cs );
char	*AIFunc_FZombie_HandLightningAttackStart( cast_state_t *cs );
char	*AIFunc_FZombie_LightningAttackStart( cast_state_t *cs );
char	*AIFunc_Helga_IdleStart( cast_state_t *cs );
char	*AIFunc_FlameZombie_PortalStart( cast_state_t *cs );
//
// ai_cast_fight.c
qboolean AICast_StateChange( cast_state_t *cs, aistateEnum_t newaistate );
void	AICast_WeaponSway( cast_state_t *cs, vec3_t ofs );
int		AICast_ScanForEnemies( cast_state_t *cs, int *enemies );
void	AICast_UpdateBattleInventory(cast_state_t *cs, int enemy);
float	AICast_Aggression(cast_state_t *cs);
int		AICast_WantsToChase(cast_state_t *cs);
int		AICast_WantsToTakeCover(cast_state_t *cs, qboolean attacking);
qboolean AICast_EntityVisible( cast_state_t *cs, int enemynum, qboolean directview );
bot_moveresult_t AICast_CombatMove(cast_state_t *cs, int tfl);
qboolean AICast_AimAtEnemy(cast_state_t *cs);
qboolean AICast_CheckAttackAtPos(int entnum, int enemy, vec3_t pos, qboolean ducking, qboolean allowHitWorld);
qboolean AICast_CheckAttack(cast_state_t *cs, int enemy, qboolean allowHitWorld);
void	AICast_ProcessAttack(cast_state_t *cs);
void	AICast_ChooseWeapon( cast_state_t *cs, qboolean battleFunc );
qboolean AICast_GetTakeCoverPos( cast_state_t *cs, int enemyNum, vec3_t enemyPos, vec3_t returnPos );
qboolean AICast_CanMoveWhileFiringWeapon( int weaponnum );
float	AICast_GetWeaponSoundRange( int weapon );
qboolean AICast_StopAndAttack( cast_state_t *cs );
qboolean AICast_WantToRetreat( cast_state_t *cs );
int		AICast_SafeMissileFire( gentity_t *ent, int duration, int enemyNum, vec3_t enemyPos, int selfNum, vec3_t endPos );
void	AIChar_AttackSound (cast_state_t *cs);
qboolean AICast_GotEnoughAmmoForWeapon( cast_state_t *cs, int weapon );
qboolean AICast_HostileEnemy( cast_state_t *cs, int enemynum );
qboolean AICast_QueryEnemy( cast_state_t *cs, int enemynum );
void AICast_AudibleEvent( int srcnum, vec3_t pos, float range );

//
// ai_cast_events.c
void	AICast_Pain( gentity_t *targ, gentity_t *attacker, int damage, vec3_t point );
void	AICast_Die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath );
void	AICast_Sight( gentity_t *ent, gentity_t *other, int lastSight );
void	AICast_EndChase( cast_state_t *cs );
void	AICast_ProcessActivate( int entNum, int activatorNum );
//
// ai_cast_think.c
void AICast_Think( int client, float thinktime );
void AICast_UpdateInput(cast_state_t *cs, int time);
void AICast_InputToUserCommand(cast_state_t *cs, bot_input_t *bi, usercmd_t *ucmd, int delta_angles[3]);
void AICast_PredictMovement( cast_state_t *cs, int numframes, float frametime, aicast_predictmove_t *move, usercmd_t *ucmd, int checkHitEnt );
void AICast_Blocked(cast_state_t *cs, bot_moveresult_t *moveresult, int activate, bot_goal_t *goal);
qboolean AICast_RequestCrouchAttack( cast_state_t *cs, vec3_t org, float time );
qboolean AICast_GetAvoid( cast_state_t *cs, bot_goal_t *goal, vec3_t outpos, qboolean reverse, int blockEnt );
void AICast_QueryThink( cast_state_t *cs );
void AICast_DeadClipWalls( cast_state_t *cs );
//
// ai_cast_script.c
qboolean AICast_ScriptRun( cast_state_t *cs, qboolean force );
//
// ai_cast_soldier.c
void	AIChar_spawn( gentity_t *ent );
//
// other/external defines
void	BotCheckAir(bot_state_t *bs);
void	BotUpdateInput(bot_state_t *bs, int time);
float	AngleDifference(float ang1, float ang2);
float	BotChangeViewAngle(float angle, float ideal_angle, float speed);
void	BotInputToUserCommand(bot_input_t *bi, usercmd_t *ucmd, int delta_angles[3]);
void	GibEntity( gentity_t *self, int killer );
void	GibHead( gentity_t *self, int killer );
//
extern bot_state_t	*botstates[MAX_CLIENTS];
