#ifndef	_AI_MOVE
#define	_AI_MOVE

///////////////////////////////////////////////////////////////////////////////////
//
// Basic movement routines for monsters/bots
//
///////////////////////////////////////////////////////////////////////////////////

#define	DEBUGINFO	1

#define	TER_CLEAR				0
#define TER_GRADEUP				1
#define TER_STEPSUP				2
#define TER_FAR_WALL			3

#define	TER_OBSTRUCTED			5
#define TER_WALL				6
#define TER_WALL_PARTIAL		7
#define TER_HIGH_OBS			8
#define	TER_WALL_RIGHT			10
#define	TER_WALL_LEFT			11
#define TER_LOW_OBS				12

// for movetogoal, swimtogoal
#define	MOVE_FORWARD		1
#define	MOVE_BACKWARD		2
#define	MOVE_UP				3
#define	MOVE_DOWN			4
#define	MOVE_STRAFE			5
#define	MOVE_STRAFEFORWARD	6
#define	MOVE_STRAFEBACKWARD	7

#define	MOVE_SPEED	380

#define	yaw_rate	22.5


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// typedefs
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef	struct
{
	int	num_ledges;
	int	ledge_height	[64];
} ledgeList_t;

typedef	struct
{
	float	ledge_z_dist;
	float	ledge_xy_dist;
} ledgeData_t;

//////////////////////////////////////////////////////////////////////////
/// terrain and navigation stuff
/////////////////////////////////////////////////////////////////////////

// terrain checking
typedef struct
{
	float	wall_dist;
	int  	wall_type;
	float	wall_yaw;
	float	wall_pitch;
	Vector	wall_normal;
	int		water_type;

	int		left_blocked;
	int		right_blocked;

	float	left_dist;
	float	right_dist;

	float	left_grade;
	float	right_grade;

	float	left_grade_bottom;
	float	right_grade_bottom;

	float	left_grade_top;
	float	right_grade_top;
} terInfo_t;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// globals
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

extern	ledgeList_t	ledge_list;  // stores status of ledge searches up to 1000 units wide
extern	ledgeData_t	ledge_data;
extern	terInfo_t	terrain;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// proto-toto-woto-typey-wipeys
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


userEntity_t *ai_spawn_goal		(userEntity_t *self);
void	ai_remove_goal			(userEntity_t *self);
void	ai_set_goal				(userEntity_t *self, void *ptr, vec3_t new_origin, int goal_type);
void	ai_restore_goal			(userEntity_t *self);
void	ai_set_task_goal		(userEntity_t *self);

int		ai_check_gap			(userEntity_t *self, terInfo_t ter, float dist);
int		ai_check_water			(userEntity_t *self, terInfo_t ter, float dist);
int		ai_find_ledge			(userEntity_t *self, float start_dist);
int		ai_terrain_type			(userEntity_t *self, Vector dir, float dist);
int		ai_jump_obstructed		(userEntity_t *self, float dist, float vz);
void	ai_rocket_jump			(userEntity_t *self);
float	ai_best_direction		(userEntity_t *self);
void	ai_water_best_direction (userEntity_t *self);
void	ai_check_water_jump		(userEntity_t *self);
int		ai_trace_up_down		(userEntity_t *self, int dir);
int		ai_path_clear			(userEntity_t *self, vec3_t end);
void	ai_swimtogoal			(userEntity_t *self, float speed, int move_dir);
float	ai_choose_turn			(userEntity_t *self, Vector dest, Vector normal);
void	ai_movetogoal			(userEntity_t *self, float speed, int move_dir);
int		ai_on_plat				(userEntity_t *self);
void	ai_water_level			(userEntity_t *self);
void	ai_water_damage			(userEntity_t *self);
void	ai_strafetogoal			(userEntity_t *self, int move_dir);
void	ai_attack_move			(userEntity_t *self);
void	ai_killed_enemy			(userEntity_t *self);
int		ai_go_to_enemy			(userEntity_t *self);

int		ai_find_target_client_bot	(userEntity_t *self);
int		ai_find_target_monster_bot	(userEntity_t *self);
int		ai_find_target_berserk		(userEntity_t *self);

void		ai_water_level		(userEntity_t *self);
void		ai_water_damage		(userEntity_t *self);

mapNode_t	*ai_choose_node		(userEntity_t *self);
int			ai_choose_roam_goal (userEntity_t *self);
int			ai_choose_wander_goal (userEntity_t *self);
void		ai_frame_sounds		(userEntity_t *self);
void		ai_seek_temporary_goal (userEntity_t *self, float	dist);
int			ai_should_follow	(userEntity_t *self);

void		ai_orient_to_normal (userEntity_t *self, Vector f_norm);
void		ai_orient_to_floor	(userEntity_t *self);
void		ai_orient_to_gravity (userEntity_t *self);
void		ai_adjust_angles	(userEntity_t *self);
void		ai_prethink			(userEntity_t *self);
void		ai_resume_think		(userEntity_t *self);

void		ai_path_wander		(userEntity_t *self);
void		ai_begin_path_wander (userEntity_t *self);

void		ai_wander			(userEntity_t *self);
void		ai_begin_wander		(userEntity_t *self);

void		ai_node_wander		(userEntity_t *self);
void		ai_begin_node_wander(userEntity_t *self);

int			ai_path_follow_check_goal (userEntity_t *self, float dist, int visible);
void		ai_path_follow		(userEntity_t *self);
void		ai_begin_path_follow(userEntity_t *self);

int			ai_time_follow_check_goal (userEntity_t *self, float dist, int visible);
void		ai_time_stamp_follow(userEntity_t *self);
void		ai_begin_time_stamp_follow(userEntity_t *self);

void		ai_follow			(userEntity_t *self);
void		ai_begin_follow		(userEntity_t *self);

void		ai_stand			(userEntity_t *self);
void		ai_begin_stand 		(userEntity_t *self);

void		ai_jump				(userEntity_t *self);
void		ai_begin_jump  		(userEntity_t *self);

void		ai_pain				(userEntity_t *self);
void		ai_begin_pain  		(userEntity_t *self);

void		ai_die				(userEntity_t *self);
void		ai_begin_die   		(userEntity_t *self);

void		ai_turn				(userEntity_t *self);
void		ai_begin_turn		(userEntity_t *self);

void		ai_jump_up			(userEntity_t *self);
void		ai_begin_jump_up	(userEntity_t *self);

void		ai_transition		(userEntity_t *self);
//void		ai_begin_transition	(userEntity_t *self, int startFrame, int endFrame, think_t think);
void		ai_begin_transition (userEntity_t *self, frameData_t *data, int seq_type, int seq_num, think_t think);

////////////////////////////////////////////////////////////////
// monster initialization functions
////////////////////////////////////////////////////////////////

void			ai_parse_epairs (userEntity_t *self);
playerHook_t	*ai_init_monster(userEntity_t *self, int type);

void	ai_get_spawn_node (userEntity_t *self);
void	ai_teleported (userEntity_t *self);

int		ai_find_ledge_list	(userEntity_t *self, float start_dist);
#endif