#ifndef _HOOKS_H
#define _HOOKS_H

//	interface to common.dll, Vector type and subroutines
#include	"common.h"	

////////////////////////////////////////////////////////////////////////////////////
///	defines
////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
///	task management
////////////////////////////////////////////////////////////////////////////////////

//	stack structure
typedef	struct	taskStack_s
{
	struct	taskStack_s	*next;

	int		task_type;
	void	*task_data;		//	saved data for this task, depending on the
						//	type of task being performed
} taskStack_t;

////////////////////////////////////////////////////////////////////////////////////
///	for frame updating
////////////////////////////////////////////////////////////////////////////////////

#define		FRAME_LOOP			1		// loop from startFrame to endFrame
#define		FRAME_ONCE			2		// go from startFrame to endFrame then stop
#define		FRAME_STATIC		4		// remain on one frame
#define		FRAME_REPEAT		8		// loop through a partial sequence for loopCount times
#define		FRAME_PLAYSOUND1	16		// this is set in the prethink each time hook->sound1Frame is reached
										// this allows the frames to run at 20/sec while the thinks happen at 5/sec
										// sounds can still be played from 5/sec thinks based on frame number
#define		FRAME_PLAYSOUND2	32		// this is set in the prethink each time hook->sound2Frame is reached
										// this allows the frames to run at 20/sec while the thinks happen at 5/sec
										// sounds can still be played from 5/sec thinks based on frame number
#define		FRAME_TRANS			64
#define		FRAME_NEEDTRANS		128		// this frame sequence needs a transition played at beginnig and end
#define		FRAME_LAST			256		// current frame is the last frame in the sequence
#define		FRAME_WEAPONSWITCH	512		// for switching weapons... when current sequence is done
										// select the weapon pointed to by weapon_next

////////////////////////////////////////////////////////////////////////////////////
///	for intQuota (how smart a creature is)
////////////////////////////////////////////////////////////////////////////////////

#define		INT_PSTEED		1
#define		INT_LOW			2
#define		INT_MEDIUM		3
#define		INT_HIGH		4
#define		INT_NELNO		5

////////////////////////////////////////////////////////////////////////////////////
///	for sequence_max, how many of each sequence type exist
////////////////////////////////////////////////////////////////////////////////////

enum	sequence_nums
{
	SEQUENCE_NONE = -1,
	SEQUENCE_STAND,
	SEQUENCE_RUN,
	SEQUENCE_WALK,
	SEQUENCE_ATAK,
	SEQUENCE_DEATH,
	SEQUENCE_SIGHT,
	SEQUENCE_PAIN,
	SEQUENCE_TURN,
	SEQUENCE_JUMP,
	SEQUENCE_FLY,
	SEQUENCE_SWIM,
	SEQUENCE_TRANS,
	SEQUENCE_SPECIAL,
	SEQUENCE_MAX
};
/*
#define		SEQUENCE_NONE		-1
#define		SEQUENCE_STAND		0
#define		SEQUENCE_RUN		1
#define		SEQUENCE_WALK		2
#define		SEQUENCE_ATAK		3
#define		SEQUENCE_DEATH		4
#define		SEQUENCE_SIGHT		5
#define		SEQUENCE_PAIN		6
#define		SEQUENCE_TURN		7
#define		SEQUENCE_JUMP		8
#define		SEQUENCE_FLY		9
#define		SEQUENCE_SWIM		10
#define		SEQUENCE_TRANS		11
#define		SEQUENCE_SPECIAL	12
*/
////////////////////////////////////////////////////////////////////////////////////
///	define for seq_flags, what exactly is happening in the current sequence
///	used to decide what transition, pain, etc. frames to use
////////////////////////////////////////////////////////////////////////////////////

#define		SF_STANDING			0x0001
#define		SF_WALKING			0x0002
#define		SF_SWIMMING			0x0004
#define		SF_FLYING			0x0008
#define		SF_ATTACKING		0x0010
#define		SF_TURNING			0x0020

////////////////////////////////////////////////////////////////////////////////////
///	flags for client entities
////////////////////////////////////////////////////////////////////////////////////

#define	DFL_LLAMA			0x00000001	//	invulnerability cheat
#define DFL_RAMPAGE			0x00000002	//	super damage cheat
#define	DFL_SHOWSTATS		0x00000004
#define	DFL_RESPAWN			0x00000008	//	set when no respawn points are free
#define	DFL_RANGEDATTACK	0x00000010	//	entity can attack from a distance
#define	DFL_CANSTRAFE		0x00000020	
#define	DFL_TURNED			0x00000040	//	entity just came out of ai_turn
#define	DFL_JUMPATTACK		0x00000080	//	entity can try to jump at enemy from a distance
#define	DFL_BERSERK			0x00000100	//	attacks anything that moves, even same type
#define	DFL_EVIL			0x00000200	//	always attacks DFL_GOOD
#define	DFL_NEUTRAL			0x00000400	//	attacks anything, but only when attacked
#define	DFL_GOOD			0x00000800	//	always attacks DFL_EVIL
#define	DFL_TIMEFOLLOW		0x00001000	//	entity will try to follow using time stamps
#define	DFL_FOLLOWATTACK	0x00002000	//	entity is following while attacking
#define	DFL_HIERARCHICAL	0x00004000	//	entity is made of multiple models
#define	DFL_FLYSWOOP		0x00008000	//	entity will fly by adjusting height to match goal
#define	DFL_FACEENEMY		0x00010000	//	entity will turn to face self->enemy, default is to face self->goalentity
#define	DFL_FACENONE 		0x00020000	//	entity will turn not turn to face anything
#define	DFL_FACEPITCH		0x00040000	//	entity will adjust pitch to face goal
#define	DFL_FACEOWNER		0x00080000	//	entity will turn to face hook->owner
#define	DFL_ORIENTTOFLOOR	0x00100000	//	entity's pitch/roll will be adjusted to match ground normal
#define	DFL_MECHANICAL		0x00200000	//	entity is a freaking robot

////////////////////////////////////////////////////////////////////////////////////
///	Monster spawn flags
////////////////////////////////////////////////////////////////////////////////////

#define		SPAWN_WANDER			1
#define		SPAWN_PATH_WANDER		2
#define		SPAWN_NODE_WANDER		4


////////////////////////////////////////////////////////////////////////////////////
/// skat list
////////////////////////////////////////////////////////////////////////////////////

// individual treasure list for each bot/player

typedef	struct	skatNode_s
{
	userEntity_t			*item;
	struct	mapNode_s		*map_node;
	struct	skatNode_s		*next_node;
} skatNode_t;

///////////////////////////////////////////////////////////////////////////////
/// dynamic mapping stuff
///////////////////////////////////////////////////////////////////////////////

#define	MAX_NODE_LINKS	6
#define	MAX_TIME_STAMPS	4

typedef	struct	nodeTime_s
{
	int		ID_stamp [MAX_TIME_STAMPS];				//	who left the corresponding time stamp on this node
													//	only bots and players can leave time stamps, everything
													//	else must be pathed to
	float	time_stamp [MAX_TIME_STAMPS];			//	time that entity with ID_stamp visited this node

	char	num_stamps;
} nodeTime_t;

typedef	struct	mapNode_s
{
	struct	mapNode_s	*next_node;					// used to maintain a linear list of all nodes
	
	vec3_t				origin;						// location of this node in the world

	struct	mapNode_s	*link [MAX_NODE_LINKS];		// links to other nodes reachable from current node

	userEntity_t		*marker;					// links to other nodes reachable from current node
	int					number;

	char				*target;
	char				*targetname;

	//	node types
	int					node_type;
	void				*node_data;

	nodeTime_t			*node_time;
} mapNode_t;

//	list header (each list has ONE of these only)

typedef struct	mapHeader_s
{
	struct	mapNode_s	*head;

	int		node_count;
} mapHeader_t;

//	list structure (each entity using a list has one of these)

typedef	struct	mapList_s
{
	struct	mapHeader_s	*header;
	struct	mapNode_s	*last_node;
	struct	mapNode_s	*cur_node;	
} mapList_t;

////////////////////////////////////////////////////////////////////////////////////
/// pathNodes
////////////////////////////////////////////////////////////////////////////////////

// list of nodes in a shortest path

typedef	struct	pathNode_s
{
	struct	mapNode_s		*map_node;
	struct	pathNode_s		*next_node;
} pathNode_t;

////////////////////////////////////////////////////////////////////////////////////
///	frame tables -- what sounds to perform during a specific sequence and what
///					frames to play them on
////////////////////////////////////////////////////////////////////////////////////

typedef	struct	frameData_s
{
	int		first;			// first frame in this sequence
	int		last;			// last frame in this sequence

	char	*sound1;		// sound to play during sequence
	int		soundframe1;	// frame to play sound on

	char	*sound2;		// second sound to play during sequence
	int		soundframe2;	// frame to play second sound on

	int		trans_pre;		// transition sequence to play to get to this sequence
	int		trans_pre_type;	// type of sequence, i.e. SEQUENCE_ATAK, SEQUENCE_RUN, etc.
	int		trans_post;		// transition sequence to play when leaving this sequence
	int		trans_post_type;// type of sequence, i.e. SEQUENCE_ATAK, SEQUENCE_RUN, etc.

	unsigned	long	int	flags;	// flags this sequence starts with (FRAME_LOOP, FRAME_ONCE, etc.)

	char 	move_scale [50];	//	movement scale for each frame (move_scale [i] + 128) / 128
} frameData_t;

typedef	struct	sequenceTable_s
{
	frameData_t	*stand	[9];
	frameData_t	*run	[9];
	frameData_t	*walk	[9];
	frameData_t	*atak	[9];
	frameData_t	*death	[9];
	frameData_t	*pain	[9];
	frameData_t	*turn	[9];
	frameData_t	*jump	[9];
	frameData_t	*fly	[9];
	frameData_t	*swim	[9];
	frameData_t	*trans	[9];
	frameData_t	*special[9];
} sequenceTable_t;

typedef	struct	vm_sequenceTable_s
{
	frameData_t	*shoot	[9];
	frameData_t	*ready	[9];
	frameData_t	*goaway	[9];
	frameData_t	*reload	[9];
	frameData_t	*ambient[9];
	frameData_t	*running[9];
} vm_sequenceTable_t;

////////////////////////////////////////////////////////////////////////////////////
/// player hook
////////////////////////////////////////////////////////////////////////////////////

typedef struct
{
	// bot's have this alternate owner field because Quake doesn't clip
	// objects against their owner
	userEntity_t		*owner;

	//////////////////////////////////////////////
	//	stats
	//////////////////////////////////////////////

	float		max_health;
	char		pain_chance;
	int			intQuota;			// how smart this monster/bot is 

	int			active_distance;	// distance from a client before
									// becoming inactive;
	short		back_away_dist;		// distance from goal when entity will back away
	char		type;				// what monster is this?  For avoiding stricmps

	float		upward_vel;			// used for jumping, set in FindLedge
	float		forward_vel;		// FIXME: obsolete?

	float		run_speed;
	float		walk_speed;
	float		attack_dist;		// distance away before bot will attack
	float		fov;				// field of view
	int			max_jump_dist;
	char		jump_chance;		//	percentage chance that this entity will use a jump attack (0-100)
	float		attack_speed;
	float		fly_speed;
	float		fly_goal_offset;		//	how far above/below its goal a flying creature desires to be
	int			ID;						//	this entity's ID number (only for bots and players, used for time stamp node following)


	//////////////////////////////////////////////
	// timer fields
	//////////////////////////////////////////////

	float		pain_finished;
	float		drown_time;
	float		attack_finished;
	float		jump_time;
	// time left to search for current goal before aborting
	float		goal_search_time;
	float		tempgoal_search_time;
	// time remaining until entity can make a sound
	float		sound_time;
	float		path_time;
	float		think_time;
	float		shake_time;
	float		ambient_time;              // delay before next ambient

	/////////////////////////////////////////////
	// powerup flags and timers
	/////////////////////////////////////////////

	float		megashield_time;
	float		envirosuit_time;
	float		wraithorb_time;
	float		oxylung_time;
	
	/////////////////////////////////////////////
	//	poisoning
	/////////////////////////////////////////////

	float		poison_time;					//	time when poison expires
	float		poison_next_damage_time;		//	next time when poison will damage
	float		poison_damage;					//	amount of damage poison will do
	float		poison_interval;				//	how often poison does damage

	// stat boosts
	int			power_boost;
	int			attack_boost;
	int			speed_boost;
	int			acro_boost;
	int			vita_boost;

	// expiration times for temporary attribute powerups
	float		power_boost_time;
	float		attack_boost_time;
	float		speed_boost_time;
	float		acro_boost_time;
	float		vita_boost_time;

	/////////////////////////////////////////////
	// flags
	/////////////////////////////////////////////

	unsigned	long	dflags;		//	DLL specific flags (ie. not needed by the engine)
	unsigned	long	items;
	unsigned	long	exp_flags;	//	expiration flags for items
	unsigned	long	ai_flags;	//	the current ai action a bot is performing
	unsigned	short	seq_flags;	//	describes what actions are happening in the current frame sequence
	char				th_state;	//	think states

	// for toggling fog in water
	int			fog_on;
	int			fog_value;

	// for track velocity changes
	float		last_zvel;
	float		last_xyvel;

	/////////////////////////////////////////////
	// node system stuff
	/////////////////////////////////////////////

	struct		mapList_s	*node_list;			// pointer to the node list this bot is using
	struct		pathNode_s	*path;				// the current path that the bot is following, NULL when no path
	struct		pathNode_s	*path_end;			// the last node in the current path

	// length of current path
	int				path_length;
	int				max_path_length;

	struct		skatNode_s	*skat_list;			// list of items found on the map and pointers to their nodes

	// location of entity during its think, not necessarily
	// it's last location before the Quake engine moved it
	Vector		last_origin;
	
	int			off_ground;						// flag to tell if bot/player left ground between nodes
	int			jumped;							// flag to tell if player jumped between nodes
	
	//////////////////////////////////////////////
	// wall following stuff
	//////////////////////////////////////////////

	// used by wall following code so that entities keep
	// turning the same way to go around an obstruction
	float		turn_yaw;
	int			stuck;							// TRUE if entity was stuck/blocked during last move attempt

	//////////////////////////////////////////////
	// animation and frame stuff
	//////////////////////////////////////////////

	// next_frame_time and frame_time allow the bot's frames to
	// be updated slower than its think functions (but not faster)
	// game time when the bot's frame should next be changed
	float		next_frameTime;

	// the desired time between frame changes
	float		frameTime;
	
	int			endFrame;						// last frame to play in a sequence
	int			startFrame;						// first frame to play in a sequence
	int			frameInc;						// number of frames to each update
	unsigned	long	frame_flags;			

	// for looping certain frames within a sequence (ie. uzi gangmember's standing fire)
	int			startLoop;						// first frame to loop frome
	int			endLoop;						// last frame to loop to
	int			loopCount;						// number of times to loop before resuming sequence

	// in order for client to possess any entity the frame data
	// needs to be available through the playerHook
	sequenceTable_t		*frames;
	
	unsigned	char	sequence_max [11];		// max number of sequences for each sequence type (jump, die, etc.)

	//	these need to be removed with latest AI

	// for flagging sounds in frame updates to be played in ai thinks
	int			sound1Frame;					// set this to the frame you want a sound to play on
												// when that frame is reached ai_prethink will set FRAME_PLAYSOUND1 in frame_flags
												// check the FRAME_PLAYSOUND1 bit in the ai thinks, if set, play the sound and
												// clear the bit
	int			sound2Frame;					// set this to the frame you want a sound to play on
												// when that frame is reached ai_prethink will set FRAME_PLAYSOUND2 in frame_flags
												// check the FRAME_PLAYSOUND2 bit in the ai thinks, if set, play the sound and
												// clear the bit
	char		*sound1;
	char		*sound2;

	frameData_t		*cur_sequence;

	int				start_seq_num;
	int				start_seq_type;

	int				main_seq_type;			// sequence to go to after playing transition
	int				main_seq_num;			// sequence to go to after playing transition

	int				end_seq_num;
	int				end_seq_type;

	int				cur_seq_type;			//	type of sequence currently playing
	int				cur_seq_num;			//	number of sequence currently playing

	/////////////////////////////////////////////////////
	//	vars for animating client viewmodel (weapon)
	/////////////////////////////////////////////////////

	float	vm_frameTime;
	float	vm_next_frameTime;

	int		vm_endFrame;
	int		vm_startFrame;
	int		vm_frameInc;
	unsigned	long	vm_frameFlags;

	int		vm_startLoop;
	int		vm_endLoop;
	int		vm_loopCount;

	vm_sequenceTable_t		*vm_frames;		// not using yet, but should be used

	short	fxFrameNum;
	void	(*fxFrameFunc)(userEntity_t *self);


	/////////////////////////////////////////////////////
	//	hooks
	/////////////////////////////////////////////////////

	void			*fHook;
	void			*floatHook;
	void			*trackHook;				//	pointer to structure for track attacks, track daddies, etc.

	/////////////////////////////////////////////////////
	// goal tracking
	/////////////////////////////////////////////////////

	int				goal_type;
	int				last_goal_type;

	userEntity_t	*goalpath;
	userEntity_t	*goalitem;
	userEntity_t	*goalobject;	//	goal objects are usually bmodels, such as switches
	vec3_t			goalorigin;	//	because goalobjects origin = 0,0,0 we need to save the derived origin
	mapNode_t		*goalnode;

	////////////////////////////////////////////////////
	// weapons and armor
	////////////////////////////////////////////////////
	
	int				last_button0; // for weapons that are fired when button0 is released

	int				viewmodel_start_frame;			// first frame to play in weapon firing sequence
	int				viewmodel_end_frame;			// last frame to play in weapon firing sequence
	float			viewmodel_frame_time;			// time between weapon fire frames

	userInventory_t	*weapon_fired;
	think_t			weapon_next;					// routine to call after current weapon is put away

	/////////////////////////////////////////////////
	// for keeping track of deathmatch stats
	/////////////////////////////////////////////////
	int				killed;
	int				died;
	int				fired;
	int				hit;

	/////////////////////////////////////////////////
	// function pointers
	/////////////////////////////////////////////////

	think_t		begin_jump;
	think_t		begin_stand;
	think_t		begin_follow;
	think_t		begin_path_follow;
	think_t		begin_wander;
	think_t		begin_attack;
	think_t		begin_seek;
	think_t		begin_pain;
	think_t		wander_sound;
	think_t		sight_sound;
	think_t		begin_turn;
	think_t		begin_path_wander;
	think_t		begin_action;
	think_t		continue_think;
	think_t		special_think;
	think_t		temp_think;
	think_t		begin_node_wander;
	think_t		begin_node_retreat;
	think_t		sight;					//	if not NULL, called when an entity sights an enemy
	think_t		begin_time_stamp_follow;
	think_t		follow_attack;			//	attack to perform while moving towards a specific goal
	think_t		begin_follow_attack;	//	sets up frames for starting a following attack
	
	int			(*find_target)(userEntity_t *self);

	void	(*begin_transition)(userEntity_t *self, frameData_t *data, int seq_type, int seq_num, think_t think);

	// for breathing effect after running
	int				fatigue;

	////////////////////////////////////////////////
	// warping 
	////////////////////////////////////////////////

	Vector			force_angles;
	Vector			force_rate;
	float			ideal_pitch;
	int				angles_last_change;

	////////////////////////////////////////////////
	//	camera and possession stuff
	////////////////////////////////////////////////

	userEntity_t	*camera;	// pointer to the camera this ent is
								// viewing from, usually NULL
	userEntity_t	*demon;    	// pointer to the entity possessing this ent

	////////////////////////////////////////////////
	//	combat strafing
	////////////////////////////////////////////////

	char			strafe_dir;
	float			strafe_time;

	/////////////////////////////////////////////////
	//	hierarchical model pieces
	/////////////////////////////////////////////////

	userEntity_t	*head;
	userEntity_t	*torso;
	userEntity_t	*legs;
	userEntity_t	*weapon;

	taskStack_t		*task_stack;

	///	FIXME: reorder when recompiling all DLLs
	char			turn_dir;

	Vector			ground_org;

	char			*caller [10];			//	who made the last 10 calls to ai_set_think

	//	ambient motion stuff for Mikiko and Superfly
	float			follow_dist;			//	distance away that Superfly, Mikiko will run after player
	char			wander_chance;
	char			look_up_down_chance;
	char			look_right_left_chance;
	char			ambient_chance;
	float			walk_follow_dist;		//	distance away that Superfly, Mikiko will walk after player

	//////////////////////////////////////////////////
	//	field of view ramping
	//////////////////////////////////////////////////
	float			fov_rate;				//	rate of change/second
	float			fov_desired;			//	desired fov
	unsigned long	fov_last_change;		//	last time of change
} playerHook_t;

//////////////////////////////////////////////////////////////////////////
// hardcoded monster paths
//////////////////////////////////////////////////////////////////////////

typedef	struct
{
	char	*target [4];
	char	*action	[4];
} mpathHook_t;

#endif
