#pragma once

#ifndef DEBUGPATHING
	#define DEBUGPATHING 0
#endif

.entity pathlib_list;
.entity path_next;
.entity path_prev;

#define inwater(point) (pointcontents(point) == CONTENT_WATER)

const vector PLIB_FORWARD = '0 1 0';
//#define PLIB_BACK    '0 -1 0'
const vector PLIB_RIGHT = '1 0 0';
//#define PLIB_LEFT    '-1 0 0'

entity openlist;
entity closedlist;

entity goal_node;
entity start_node;

.bool is_path_node;
.float pathlib_node_g;
.float pathlib_node_h;
.float pathlib_node_f;
.float pathlib_node_c;

const float pathlib_node_edgeflag_unknown 		= 0;
const float pathlib_node_edgeflag_left 			= BIT(1);
const float pathlib_node_edgeflag_right 		= BIT(2);
const float pathlib_node_edgeflag_forward 		= BIT(3);
const float pathlib_node_edgeflag_back 			= BIT(4);
const float pathlib_node_edgeflag_backleft 		= BIT(5);
const float pathlib_node_edgeflag_backright 	= BIT(6);
const float pathlib_node_edgeflag_forwardleft 	= BIT(7);
const float pathlib_node_edgeflag_forwardright 	= BIT(8);
const float pathlib_node_edgeflag_none 			= BIT(9);
.float pathlib_node_edgeflags;

float pathlib_open_cnt;
float pathlib_closed_cnt;
float pathlib_made_cnt;
float pathlib_merge_cnt;
float pathlib_searched_cnt;
float pathlib_bestopen_searched;
float pathlib_bestcash_hits;
float pathlib_bestcash_saved;
float pathlib_gridsize;
float pathlib_movecost;
float pathlib_movecost_diag;
float pathlib_movecost_waterfactor;
float pathlib_foundgoal;

float pathlib_starttime;
const float pathlib_maxtime = 60;

entity best_open_node;

vector tile_check_up;
vector tile_check_down;
float  tile_check_size;
bool     tile_check_cross(entity this, vector where);
bool     tile_check_plus(entity this, vector where);
bool     tile_check_star(entity this, vector where);
var bool tile_check(entity this, vector where);

float  movenode_stepsize;
vector movenode_stepup;
vector movenode_maxdrop;
vector movenode_boxup;
vector movenode_boxmax;
vector movenode_boxmin;
bool  pathlib_movenode_goodnode;

vector     pathlib_wateroutnode(entity this, vector start, vector end, float doedge);
vector     pathlib_swimnode(entity this, vector start, vector end, float doedge);
vector     pathlib_flynode(entity this, vector start, vector end, float doedge);
vector     pathlib_walknode(entity this, vector start, vector end, float doedge);
var vector pathlib_movenode(entity this, vector start, vector end, float doedge);

//float      pathlib_expandnode_starf(entity node, vector start, vector goal);
float      pathlib_expandnode_star(entity node, vector start, vector goal);
float      pathlib_expandnode_box(entity node, vector start, vector goal);
//float      pathlib_expandnode_octagon(entity node, vector start, vector goal);
var float  pathlib_expandnode(entity node, vector start, vector goal);

float      pathlib_g_static(entity parent, vector to, float static_cost);
float      pathlib_g_static_water(entity parent, vector to, float static_cost);
float      pathlib_g_euclidean(entity parent, vector to, float static_cost);
float      pathlib_g_euclidean_water(entity parent, vector to, float static_cost);
var float  pathlib_cost(entity parent, vector to, float static_cost);

float      pathlib_h_manhattan(vector a, vector b);
float      pathlib_h_diagonal(vector a, vector b);
float      pathlib_h_euclidean(vector a,vector b);
float      pathlib_h_diagonal2(vector a, vector b);
float      pathlib_h_diagonal3(vector a, vector b);
float      pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end);
float      pathlib_h_none(vector preprev, vector prev) { return 0; }
var float  pathlib_heuristic(vector from, vector to);

var bool  pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
var bool  buildpath_nodefilter(vector n,vector c,vector p);

var float  pathlib_wpp_waypointcallback(entity wp, entity wp_prev);

IntrusiveList g_pathlib_nodes;
STATIC_INIT(g_pathlib_nodes) { g_pathlib_nodes = IL_NEW(); }
