[nexuiz-commits] r6245 - trunk/data/qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sun Mar 22 10:09:56 EDT 2009
Author: tzork
Date: 2009-03-22 10:09:56 -0400 (Sun, 22 Mar 2009)
New Revision: 6245
Added:
trunk/data/qcsrc/server/verbstack.qc
Modified:
trunk/data/qcsrc/server/movelib.qc
trunk/data/qcsrc/server/pathlib.qc
Log:
pathlib changed to use with AStar.
add verbstack for stack based ai.
Modified: trunk/data/qcsrc/server/movelib.qc
===================================================================
--- trunk/data/qcsrc/server/movelib.qc 2009-03-21 22:12:11 UTC (rev 6244)
+++ trunk/data/qcsrc/server/movelib.qc 2009-03-22 14:09:56 UTC (rev 6245)
@@ -31,7 +31,7 @@
/**
Do a inertia simulation based on velocity.
- Basicaly, this allows you to simulate objects loss steering with speed.
+ Basicaly, this allows you to simulate loss of steering with higher speed.
self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
**/
vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
@@ -55,14 +55,15 @@
{
float deltatime;
float acceleration;
- //float mspeed;
+ float mspeed;
+ vector breakvec;
deltatime = time - self.movelib_lastupdate;
if (deltatime > 0.15) deltatime = 0;
self.movelib_lastupdate = time;
if(!deltatime) return;
- //mspeed = vlen(self.velocity);
+ mspeed = vlen(self.velocity);
if(mass)
acceleration = vlen(force) / mass;
@@ -72,61 +73,144 @@
if(self.flags & FL_ONGROUND)
{
if(breakforce)
- {
- breakforce = 1 - ((breakforce / mass) * deltatime);
- self.velocity = self.velocity * breakforce;
- }
+ {
+ breakvec = (normalize(self.velocity) * (breakforce / mass) * deltatime);
+ self.velocity = self.velocity - breakvec;
+ }
self.velocity = self.velocity + force * (acceleration * deltatime);
- }
+ }
- self.velocity = self.velocity + '0 0 -1' * sv_gravity * deltatime;
+ if(drag)
+ self.velocity = movelib_dragvec(drag, 1);
+
+ if(self.waterlevel > 1)
+ {
+ self.velocity = self.velocity + force * (acceleration * deltatime);
+ self.velocity = self.velocity + '0 0 0.05' * sv_gravity * deltatime;
+ }
+ else
+ self.velocity = self.velocity + '0 0 -1' * sv_gravity * deltatime;
+
+ mspeed = vlen(self.velocity);
- if(drag)
- self.velocity = movelib_dragvec(drag, 1);
-
if(max_velocity)
- if(vlen(self.velocity) > max_velocity)
- self.velocity = normalize(self.velocity) * max_velocity;
-}
+ if(mspeed > max_velocity)
+ self.velocity = normalize(self.velocity) * (mspeed - 50);//* max_velocity;
+}
+
+/*
+.float mass;
+.float side_friction;
+.float ground_friction;
+.float air_friction;
+.float water_friction;
+.float buoyancy;
+float movelib_deltatime;
+
+void movelib_startupdate()
+{
+ movelib_deltatime = time - self.movelib_lastupdate;
+
+ if (movelib_deltatime > 0.5)
+ movelib_deltatime = 0;
+
+ self.movelib_lastupdate = time;
+}
-void movelib_move_simple(vector newdir,float velo,float turnrate)
-{
- vector olddir;
+void movelib_update(vector dir,float force)
+{
+ vector acceleration;
+ float old_speed;
+ float ffriction,v_z;
+
+ vector breakvec;
+ vector old_dir;
+ vector ggravity;
+ vector old;
+
+ if(!movelib_deltatime)
+ return;
+ v_z = self.velocity_z;
+ old_speed = vlen(self.velocity);
+ old_dir = normalize(self.velocity);
+
+ //ggravity = (sv_gravity / self.mass) * '0 0 100';
+ acceleration = (force / self.mass) * dir;
+ //acceleration -= old_dir * (old_speed / self.mass);
+ acceleration -= ggravity;
+
+ if(self.waterlevel > 1)
+ {
+ ffriction = self.water_friction;
+ acceleration += self.buoyancy * '0 0 1';
+ }
+ else
+ if(self.flags & FL_ONGROUND)
+ ffriction = self.ground_friction;
+ else
+ ffriction = self.air_friction;
+
+ acceleration *= ffriction;
+ //self.velocity = self.velocity * (ffriction * movelib_deltatime);
+ self.velocity += acceleration * movelib_deltatime;
+ self.velocity_z = v_z;
+
+}
+*/
- olddir = normalize(self.velocity);
-
- self.velocity = normalize(olddir + newdir * turnrate) * velo;
-}
-
-/*
-vector movelib_accelerate(float force)
+void movelib_move_simple(vector newdir,float velo,float blendrate)
{
- vector vel;
- vel = self.velocity;
- vel = normalize(vel) * (vlen(vel) + force);
- self.velocity = self.velocity + vel;
+ self.velocity = self.velocity * (1 - blendrate) + (newdir * blendrate) * velo;
}
-
-
-vector movelib_decelerate(float force,float mass)
-{
- vector vel;
- float decel;
-
- if(mass)
- decel = force / mass;
- else
- decel = force;
-
- vel = self.velocity;
- vel = normalize(vel) * max((vlen(vel) - decel),0);
- self.velocity = self.velocity - vel;
-
- if(vlen(self.velocity) < 5) self.velocity = '0 0 0';
-}
-*/
-vector movelib_velocity_transfer(entity source,entity destination)
-{
- return '0 0 0';
-}
+void movelib_beak_simple(float force)
+{
+ float mspeed;
+ vector mdir;
+
+ mspeed = max(0,vlen(self.velocity) - force);
+ mdir = normalize(self.velocity);
+ self.velocity = mdir * mspeed;
+}
+
+
+void movelib_groundalign4point(float spring_length,float spring_up)
+{
+ vector a,b,c,d,e,r,push_angle;
+ push_angle_y = 0;
+ r = (self.absmax + self.absmin) * 0.5 + (v_up * spring_up);
+ e = v_up * spring_length;
+
+ a = r + (v_forward * self.maxs_x) + (v_right * self.maxs_y);
+ b = r + (v_forward * self.maxs_x) - (v_right * self.maxs_y);
+ c = r - (v_forward * self.maxs_x) + (v_right * self.maxs_y);
+ d = r - (v_forward * self.maxs_x) - (v_right * self.maxs_y);
+
+ traceline(a, a - e,MOVE_NORMAL,self);
+ a_z = (1 - trace_fraction);
+ r = trace_endpos;
+ traceline(b, b - e,MOVE_NORMAL,self);
+ b_z = (1 - trace_fraction);
+ r += trace_endpos;
+ traceline(c, c - e,MOVE_NORMAL,self);
+ c_z = (1 - trace_fraction);
+ r += trace_endpos;
+ traceline(d, d - e,MOVE_NORMAL,self);
+ d_z = (1 - trace_fraction);
+ r += trace_endpos;
+ a_x = r_z;
+ r = self.origin;
+ r_z = r_z;
+
+ push_angle_x = (a_z - c_z) * 45;
+ push_angle_x += (b_z - d_z) * 45;
+
+ push_angle_z = (b_z - a_z) * 45;
+ push_angle_z += (d_z - c_z) * 45;
+
+ self.angles_x += push_angle_x * 0.95;
+ self.angles_z += push_angle_z * 0.95;
+
+ setorigin(self,r);
+}
+
Modified: trunk/data/qcsrc/server/pathlib.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib.qc 2009-03-21 22:12:11 UTC (rev 6244)
+++ trunk/data/qcsrc/server/pathlib.qc 2009-03-22 14:09:56 UTC (rev 6245)
@@ -1,480 +1,1001 @@
-#define PFL_GROUNDSNAP 1
-#define PFL_NOOPTIMIZE 2
-#define PFL_SUBPATH3D 4
-
-#define PT_QUICKSTAR 1
-#define PT_QUICKBOX 2
-#define PT_ASTAR 4 // FIXME NOT IMPLEMENTED
-
-//#define PATHLIB_RDFIELDS
-#ifdef PATHLIB_RDFIELDS
- #define path_flags lip
-
- #define path_subpathing_size autoswitch
- #define path_subpathing_bboxexpand welcomemessage_time
-
- #define path_next swampslug
- #define path_prev lasertarget
-#else
- .entity path_next;
- .entity path_prev;
-
- .float path_subpathing_size;
- .float path_subpathing_bboxexpand;
- .float path_flags;
-#endif
-
-#define pathlib_garbagetime 120
-#define pathib_maxdivide 512
-
-.float(vector start,vector end) path_validate;
-
-float pathlib_stdproc_path_validate(vector start,vector end)
-{
- tracebox(start, self.mins, self.maxs, end, MOVE_WORLDONLY, self);
-
- if(vlen(trace_endpos - end) < 32)
- return 1;
-
- return 0;
-}
-
-vector pathlib_groundsnap(vector where)
-{
- float lsize;
-
- lsize = vlen(self.mins - self.maxs) * 0.25;
-
- traceline(where + ('0 0 1' * lsize) ,where - '0 0 10240',MOVE_WORLDONLY,self);
-
- return trace_endpos + ('0 0 1' * lsize);
-
-}
-
-entity pathlib_createpoint(entity parent,entity next,entity first,vector where)
-{
- entity point;
-
- point = spawn();
- point.classname = "path_node";
-
- if(first)
- point.owner = first;
- else
- {
- point.classname = "path_master";
- point.owner = point;
- }
-
- if(parent)
- point.path_prev = parent;
-
- if(next)
- {
- point.path_next = next;
- }
- else
- point.classname = "path_end";
-
- if (point.owner.path_flags & PFL_GROUNDSNAP)
- where = pathlib_groundsnap(where);
-
- setorigin(point,where);
-
-
- return point;
-}
-
-/*
-float pathlib_scoresubpath(vector start,vector point,vector end,float minstep)
-{
- float dist_stp,dist_pte,dist_total;
-
- dist_stp = vlen(start - point);
- if(dist_stp < minstep)
- return 100000000;
-
- dist_pte = vlen(point - end);
- dist_total = dist_stp + dist_pte;
- return -1;
-}
-*/
-
-vector pathlib_subpath_quickbox(entity start,vector vcrash,entity end,float maxsize)
-{
-
- float step;
- float pathscore;
- float pathscore_best;
- float dist;
- vector bestpoint,point;
- float zmin,zmax;
- vector box;
-
- pathscore_best = 0;
-
- step = vlen(self.maxs - self.mins) * start.owner.path_subpathing_bboxexpand;
-
- if(start.owner.path_flags & PFL_SUBPATH3D)
- {
- zmin = maxsize * -1;
- zmax = maxsize;
- }
- else
- {
- zmin = 0;
- zmax = 1;
- }
-
- for(box_z = zmin; box_z < zmax; box_z += step)
- for(box_y = -maxsize; box_y < maxsize; box_y += step)
- for(box_x = -maxsize; box_x < maxsize; box_x += step)
- {
-
- point = vcrash + box;
-
- if(start.owner.path_flags & PFL_GROUNDSNAP)
- point = pathlib_groundsnap(point);
-
- if(self.path_validate(start.origin,point))
- {
- dist = vlen(start.origin - point);
- if(dist > step)
- {
- pathscore = 1 / (dist + vlen(point - end.origin));
- if(pathscore > pathscore_best)
- {
- bestpoint = point;
- pathscore_best = pathscore;
- }
- }
- }
-
- }
-
- if(pathscore_best != 0)
- return bestpoint;
-
- return start.origin;
-}
-
-vector pathlib_subpath_quickstar(entity start,entity end,float gridsize)
-{
- vector point, best_point;
- float score, best_score;
- vector dir_end;
-
- dir_end = normalize(end.origin - start.origin);
- dir_end_x = dir_end_x * -1;
-
- makevectors(dir_end);
-
- best_score = 0;
- score = 0;
-
- best_point = start.origin;
-
- // Forward
- point = start.origin + v_forward * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
- // Forward-right
- point = start.origin + (v_forward + v_right * 0.5) * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
-
- // Forward-left
- point = start.origin + (v_forward - v_right * 0.5) * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
-
- // Right
- point = start.origin + v_right * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
- // Left
- point = start.origin - v_right * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
- // Back
- point = start.origin - v_forward * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
- // Back-right
-
- point = start.origin - (v_forward + v_right * 0.5) * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
- // Back-left
- point = start.origin - (v_forward - v_right * 0.5) * gridsize;
- point = pathlib_groundsnap(point);
- if(self.path_validate(start.origin,point)) score = 1 / vlen(point - end.origin);
- if(score < best_score) { best_point = point; best_score = score; }
- //te_lightning1(world,start.origin,point);
-
- return(best_point);
-}
-
-float pathlib_path(entity start,entity end,float pathing_method)
-{
- vector vcrash;
- vector subpath_point;
- entity subpoint;
-
- // Fail.
- if(start.cnt > pathib_maxdivide)
- {
- bprint("To many segments!\n");
- return 0;
- }
-
- if(self.path_validate(start.origin,end.origin))
- return 1;
-
- vcrash = trace_endpos;
-
- switch(pathing_method)
- {
- case PT_QUICKSTAR:
- subpath_point = pathlib_subpath_quickstar(start,end,start.owner.path_subpathing_size);
- break;
- case PT_QUICKBOX:
- subpath_point = pathlib_subpath_quickbox(start,vcrash,end,start.owner.path_subpathing_size);
- break;
- case PT_ASTAR:
- dprint("Pathlib error: A* pathing not implemented!\n");
- return 0;
- default:
- subpath_point = pathlib_subpath_quickstar(start,end,start.owner.path_subpathing_size);
- dprint("Pathlib warning: unknown pathing method, using quickstar!\n");
- break;
- }
-
- if(subpath_point == start.origin)
- return 0; // Fail.
-
- subpoint = pathlib_createpoint(start,end,start.owner,subpath_point);
-
- subpoint.cnt = start.cnt +1;
- start.path_next = subpoint;
- end.path_prev = subpoint;
-
- if(self.path_validate(start.origin,end.origin))
- return 1;
-
- return pathlib_path(subpoint,end,pathing_method);
-}
-
-void pathlib_path_optimize(entity start,entity end)
-{
- entity point,point_tmp;
- float c;
-
- point = start.path_next;
-
- while(point != end)
- {
- ++c;
- if(c > 5000)
- {
- dprint("pathlib_path_optimize runaway!\n");
- return;
- }
-
- point_tmp = point;
- point = point.path_next;
- if(self.path_validate(point_tmp.path_prev.origin,point_tmp.path_next.origin))
- {
-
- point_tmp.path_next.path_prev = point_tmp.path_prev;
- point_tmp.path_prev.path_next = point_tmp.path_next;
- remove(point_tmp);
- }
- }
-}
-
-void pathlib_deletepath(entity start)
-{
- entity e;
-
- e = findchainentity(owner, start);
- while(e)
- {
- e.think = SUB_Remove;
- e.nextthink = time;
- e = e.chain;
- }
-}
-
-//#define DEBUGPATHING
-#ifdef DEBUGPATHING
-void pathlib_showpath(entity start)
-{
- entity e;
- e = start;
- while(e.path_next)
- {
- te_lightning1(e,e.origin,e.path_next.origin);
- e = e.path_next;
- }
-}
-
-void path_dbg_think()
-{
- pathlib_showpath(self);
- self.nextthink = time + 1;
-}
-#endif
-/**
- Pathing from 'from' to 'to'
-**/
-entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand,float pathing_method)
-{
- entity e_start,e_end;
-
- if(!self.path_validate)
- self.path_validate = pathlib_stdproc_path_validate;
-
-
- if(subpathing_size < 10)
- subpathing_size = 500;
-
- if(subpathing_bboxexpand < 1)
- subpathing_bboxexpand = 1;
-
- if(pathflags & PFL_GROUNDSNAP)
- {
- from = pathlib_groundsnap(from);
- to = pathlib_groundsnap(to);
- }
-
- e_start = pathlib_createpoint(world,world,world,from);
- e_start.path_flags = pathflags;
-
- e_start.path_subpathing_size = subpathing_size;
- e_start.path_subpathing_bboxexpand = subpathing_bboxexpand;
-
- e_start.owner = e_start;
-
- e_end = pathlib_createpoint(e_start,world,e_start,to);
- e_start.path_next = e_end;
- e_start.cnt = 0;
-
- if(!pathlib_path(e_start,e_end,pathing_method))
- {
- bprint("Fail, Fail, Fail!\n");
- pathlib_deletepath(e_start);
- remove(e_start);
-
- return world;
- }
-
- pathlib_path_optimize(e_start,e_end);
-
-#ifdef DEBUGPATHING
- e_start.think = path_dbg_think;
- e_start.nextthink = time + 1;
-#endif
-
- return e_start;
-
-}
-
-/*
-.entity goalcurrent, goalstack01, goalstack02, goalstack03;
-.entity goalstack04, goalstack05, goalstack06, goalstack07;
-.entity goalstack08, goalstack09, goalstack10, goalstack11;
-.entity goalstack12, goalstack13, goalstack14, goalstack15;
-.entity goalstack16, goalstack17, goalstack18, goalstack19;
-.entity goalstack20, goalstack21, goalstack22, goalstack23;
-.entity goalstack24, goalstack25, goalstack26, goalstack27;
-.entity goalstack28, goalstack29, goalstack30, goalstack31;
-*/
-
-#define node_left goalstack01
-#define node_right goalstack02
-#define node_front goalstack03
-#define node_back goalstack04
-
-#define node_open goalstack05
-#define node_closed goalstack06
-#define node_blocked goalstack07
-
-
-
-float pointinbox(vector point,vector box,float ssize)
-{
- return 0;
-}
-#ifdef DEBUGPATHING
-
-/* TESTING */
-void pathlib_test_think()
-{
- pathlib_showpath(self.enemy);
-
- self.nextthink = time + 0.5;
-}
-void pathlib_test_dinit()
-{
- entity path;
- entity end;
-
- if(self.target == "")
- {
- bprint("^1 ==== ERROR: pathlib_test with no target. ====\n");
- remove(self);
- return;
- }
-
- end = find(world,targetname,self.target);
- if(!end)
- {
- bprint("^1 ==== ERROR: pathlib_test with no valid target. ====\n");
- remove(self);
- return;
- }
-
- setsize(self,'-50 -50 0','50 50 50');
- path = pathlib_makepath(self.origin,end.origin, PFL_GROUNDSNAP,500,1.25,PT_QUICKSTAR);
-
- if(!path)
- {
- bprint("^1 ==== ERROR: pathlib_test pathing fail ====\n");
- remove(self);
- return;
- }
-
- self.enemy = path;
- self.think = pathlib_test_think;
- self.nextthink = time + 0.5;
-
-}
-void spawnfunc_pathlib_test()
-{
- self.think = pathlib_test_dinit;
- self.nextthink = time + 2;
-}
-
-#endif
+//#define PATHLIB_RDFIELDS
+#ifdef PATHLIB_RDFIELDS
+ #define path_next swampslug
+ #define path_prev lasertarget
+#else
+ .entity path_next;
+ .entity path_prev;
+#endif
+
+entity openlist;
+entity closedlist;
+entity scraplist;
+
+.float pathlib_node_g;
+.float pathlib_node_h;
+.float pathlib_node_f;
+
+float pathlib_open_cnt;
+float pathlib_closed_cnt;
+float pathlib_made_cnt;
+float pathlib_merge_cnt;
+float pathlib_recycle_cnt;
+float pathlib_searched_cnt;
+
+float pathlib_bestopen_seached;
+float pathlib_bestcash_hits;
+float pathlib_bestcash_saved;
+
+float pathlib_gridsize;
+
+float pathlib_movecost;
+float pathlib_movecost_diag;
+float pathlib_movecost_waterfactor;
+
+float pathlib_edge_check_size;
+
+float pathlib_foundgoal;
+entity goal_node;
+
+entity best_open_node;
+.float is_path_node;
+
+float edge_show(vector point,float fsize);
+
+//#define DEBUGPATHING
+#ifdef DEBUGPATHING
+void mark_error(vector where,float lifetime);
+void mark_info(vector where,float lifetime);
+entity mark_misc(vector where,float lifetime);
+
+
+
+void pathlib_showpath(entity start)
+{
+ entity e;
+ e = start;
+ while(e.path_next)
+ {
+ te_lightning1(e,e.origin,e.path_next.origin);
+ e = e.path_next;
+ }
+}
+
+void path_dbg_think()
+{
+ pathlib_showpath(self);
+ self.nextthink = time + 1;
+}
+
+void __showpath2_think()
+{
+ mark_info(self.origin,1);
+ if(self.path_next)
+ {
+ self.path_next.think = __showpath2_think;
+ self.path_next.nextthink = time + 0.15;
+ }
+ else
+ {
+ self.owner.think = __showpath2_think;
+ self.owner.nextthink = time + 0.15;
+ }
+}
+
+void pathlib_showpath2(entity path)
+{
+ path.think = __showpath2_think;
+ path.nextthink = time;
+}
+
+#endif
+
+/*
+float pathlib_stdproc_path_validate(vector start,vector end)
+{
+ tracebox(start, self.mins * 2, self.maxs * 2, end, MOVE_WORLDONLY, self);
+
+ if(vlen(trace_endpos - end) < 5)
+ return 1;
+
+ return 0;
+}
+*/
+
+
+void pathlib_deletepath(entity start)
+{
+ entity e;
+
+ e = findchainentity(owner, start);
+ while(e)
+ {
+ e.think = SUB_Remove;
+ e.nextthink = time;
+ e = e.chain;
+ }
+}
+
+float fsnap(float val,float fsize)
+{
+ return rint(val / fsize) * fsize;
+}
+
+vector vsnap(vector point,float fsize)
+{
+ vector vret;
+
+ vret_x = rint(point_x / fsize) * fsize;
+ vret_y = rint(point_y / fsize) * fsize;
+ vret_z = ceil(point_z / fsize) * fsize;
+
+ return vret;
+}
+
+
+#define floor_failmask (DPCONTENTS_SLIME | DPCONTENTS_LAVA)
+// | DPCONTENTS_MONSTERCLIP | DPCONTENTS_DONOTENTER
+float walknode_stepsize;
+vector walknode_stepup;
+vector walknode_maxdrop;
+vector walknode_boxup;
+vector walknode_boxmax;
+vector walknode_boxmin;
+float pathlib_movenode_goodnode;
+
+float floor_ok(vector point)
+{
+ float pc;
+
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ return 0;
+
+ pc = pointcontents(point);
+
+ switch(pc)
+ {
+ case CONTENT_SOLID:
+ case CONTENT_SLIME:
+ case CONTENT_LAVA:
+ case CONTENT_SKY:
+ return 0;
+ case CONTENT_EMPTY:
+ if not (pointcontents(point - '0 0 1') == CONTENT_SOLID)
+ return 0;
+ break;
+ case CONTENT_WATER:
+ return 1;
+ }
+ if(pointcontents(point - '0 0 1') == CONTENT_SOLID)
+ return 1;
+
+ return 0;
+}
+
+float inwater(vector point)
+{
+ if(pointcontents(point) == CONTENT_WATER)
+ return 1;
+
+ return 0;
+}
+
+//#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if(trace_fraction == 1.0) return 1
+#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if not(floor_ok(trace_endpos)) return 1
+float edge_check(vector point,float fsize)
+{
+ vector z_up,z_down;
+
+ z_up = '0 0 1' * fsize;
+ z_down = '0 0 1' * fsize;
+
+ _pcheck(point + ('1 1 0' * fsize));
+ _pcheck(point + ('1 -1 0' * fsize));
+ _pcheck(point + ('1 0 0' * fsize));
+
+ _pcheck(point + ('0 1 0' * fsize));
+ _pcheck(point + ('0 -1 0' * fsize));
+
+ _pcheck(point + ('-1 0 0' * fsize));
+ _pcheck(point + ('-1 1 0' * fsize));
+ _pcheck(point + ('-1 -1 0' * fsize));
+
+ return 0;
+}
+
+/*
+#define _pshow(p) mark_error(p,10)
+float edge_show(vector point,float fsize)
+{
+
+ _pshow(point + ('1 1 0' * fsize));
+ _pshow(point + ('1 -1 0' * fsize));
+ _pshow(point + ('1 0 0' * fsize));
+
+ _pshow(point + ('0 1 0' * fsize));
+ _pshow(point + ('0 -1 0' * fsize));
+
+ _pshow(point + ('-1 0 0' * fsize));
+ _pshow(point + ('-1 1 0' * fsize));
+ _pshow(point + ('-1 -1 0' * fsize));
+
+ return 0;
+}
+*/
+
+var vector pathlib_movenode(vector start,vector end,float doedge);
+vector pathlib_wateroutnode(vector start,vector end)
+{
+ vector surface;
+
+ pathlib_movenode_goodnode = 0;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
+ end = trace_endpos;
+
+ if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
+ return end;
+
+ for(surface = start ; surface_z < (end_z + 32); ++surface_z)
+ {
+ if(pointcontents(surface) == CONTENT_EMPTY)
+ break;
+ }
+ //mark_error(surface,10);
+
+ if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
+ return end;
+
+ tracebox(start + '0 0 64', walknode_boxmin,walknode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ {
+ pathlib_movenode_goodnode = 1;
+ //mark_error(end + '0 0 64',30);
+ }
+
+ if(fabs(surface_z - end_z) > 32)
+ pathlib_movenode_goodnode = 0;
+
+ return end;
+}
+
+vector pathlib_swimnode(vector start,vector end)
+{
+ pathlib_movenode_goodnode = 0;
+
+ if(pointcontents(start) != CONTENT_WATER)
+ return end;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ if(pointcontents(end) == CONTENT_EMPTY)
+ return pathlib_wateroutnode( start, end);
+
+ tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ return end;
+}
+
+vector pathlib_flynode(vector start,vector end)
+{
+ pathlib_movenode_goodnode = 0;
+
+ /*
+ if(pointcontents(start) == CONTENT_EMPTY)
+ return end;
+
+ if(pointcontents(end) == CONTENT_EMPTY)
+ return end;
+ */
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ return end;
+}
+
+vector pathlib_walknode(vector start,vector end,float doedge)
+{
+ vector direction,point,last_point,s,e;
+ float steps, distance, i,laststep;
+
+ pathlib_movenode_goodnode = 0;
+
+ s = start;
+ e = end;
+ e_z = 0;
+ s_z = 0;
+ direction = normalize(s - e);
+
+ distance = vlen(start - end);
+ laststep = distance / walknode_stepsize;
+ steps = floor(laststep);
+ laststep = laststep - steps;
+
+ point = start;
+ s = point + walknode_stepup;
+ e = point - walknode_maxdrop;
+
+ traceline(s, e,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ if (floor_ok(trace_endpos) == 0)
+ return trace_endpos;
+
+ last_point = trace_endpos;
+
+ for(i = 0; i < steps; ++i)
+ {
+ point = last_point + direction * walknode_stepsize;
+
+ s = point + walknode_stepup;
+ e = point - walknode_maxdrop;
+ traceline(s, e,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ point = trace_endpos;
+ if not(floor_ok(trace_endpos))
+ return trace_endpos;
+
+ tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
+ if(trace_fraction != 1.0)
+ return trace_endpos;
+
+ if(doedge)
+ if(edge_check(point,pathlib_edge_check_size))
+ return trace_endpos;
+
+ last_point = point;
+ }
+
+ point = last_point + direction * walknode_stepsize * laststep;
+
+ point_x = fsnap(point_x, pathlib_gridsize);
+ point_y = fsnap(point_y, pathlib_gridsize);
+
+ s = point + walknode_stepup;
+ e = point - walknode_maxdrop;
+ traceline(s, e,MOVE_WORLDONLY,self);
+
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ point = trace_endpos;
+
+ if not(floor_ok(trace_endpos))
+ return trace_endpos;
+
+ tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
+ if(trace_fraction != 1.0)
+ return trace_endpos;
+
+ pathlib_movenode_goodnode = 1;
+ return point;
+}
+
+var float pathlib_cost(entity parent,vector to, float static_cost);
+float pathlib_g_static(entity parent,vector to, float static_cost)
+{
+ if(inwater(to))
+ return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
+ else
+ return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_euclidean(entity parent,vector to, float static_cost)
+{
+ return vlen(parent.origin - to);
+}
+
+var float(vector from,vector to) pathlib_heuristic;
+float pathlib_h_manhattan(vector a,vector b)
+{
+ //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
+
+ float h;
+ h = fabs(a_x - b_x);
+ h = h + fabs(a_y - b_y);
+ h = pathlib_gridsize * h;
+
+ return h;
+}
+
+float pathlib_h_diagonal(vector a,vector b)
+{
+ //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
+ float h,x,y;
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+ h = pathlib_movecost * max(x,y);
+
+ return h;
+}
+
+float pathlib_h_euclidean(vector a,vector b)
+{
+ return vlen(a - b);
+}
+
+float pathlib_h_diagonal2(vector a,vector b)
+{
+ float h_diag,h_str,h,x,y;
+
+ /*
+ h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+ */
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+
+ h_diag = min(x,y);
+ h_str = x + y;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ return h;
+}
+
+float pathlib_h_diagonal2tbs(vector start,vector point,vector end)
+{
+ float h_diag,h_str,h,x,y;
+
+ /*
+ h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+ */
+
+ float dx1,dx2,dy1,dy2,fcross;
+ dx1 = point_x - end_x;
+ dy1 = point_y - end_y;
+ dx2 = start_x - end_x;
+ dy2 = start_y - end_y;
+ fcross = fabs(dx1*dy2 - dx2*dy1);
+
+ x = fabs(point_x - end_x);
+ y = fabs(point_y - end_y);
+
+ h_diag = min(x,y);
+ h_str = x + y;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ return h + (fcross * 0.001);
+}
+
+float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
+{
+ float h_diag,h_str,h,x,y,z;
+
+ //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+
+ x = fabs(point_x - end_x);
+ y = fabs(point_y - end_y);
+ z = fabs(point_z - end_z);
+
+ h_diag = min3(x,y,z);
+ h_str = x + y + z;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ float m;
+ vector d1,d2;
+
+ m = 0.999;
+ d1 = normalize(preprev - prev);
+ d2 = normalize(prev - point);
+ if(vlen(d1-d2) > 0.6)
+ m = 1;
+
+
+ return h * m;
+}
+
+
+float pathlib_h_diagonal3(vector a,vector b)
+{
+ float h_diag,h_str,h,x,y,z;
+
+ //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+ z = fabs(a_z - b_z);
+
+ h_diag = min3(x,y,z);
+ h_str = x + y + z;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ //if(inwater(a))
+ //h =
+
+ return h;
+}
+
+//#define PATHLIB_USE_NODESCRAP
+float pathlib_scraplist_cnt;
+entity newnode()
+{
+ entity n;
+#ifdef PATHLIB_USE_NODESCRAP
+ if(pathlib_scraplist_cnt)
+ {
+ n = findentity(world,owner,scraplist);
+ if(n)
+ {
+ --pathlib_scraplist_cnt;
+ ++pathlib_recycle_cnt;
+ return n;
+ }
+ else
+ pathlib_scraplist_cnt = 0;
+ }
+#endif
+ ++pathlib_made_cnt;
+ n = spawn();
+ return n;
+}
+
+void dumpnode(entity n)
+{
+#ifdef PATHLIB_USE_NODESCRAP
+ ++pathlib_scraplist_cnt;
+ n.owner = scraplist;
+#else
+ remove(n);
+#endif
+}
+
+entity pathlib_mknode(vector where,entity parent)
+{
+ entity node;
+
+ node = newnode();
+ node.is_path_node = TRUE;
+ node.owner = openlist;
+ node.path_prev = parent;
+
+ setorigin(node, where);
+
+ ++pathlib_open_cnt;
+
+ //if(inwater(where))
+ //{
+ //node.waterlevel = 1;
+ //mark_info(where,5);
+ //}
+ //mark_info(where,30);
+ return node;
+}
+var float pathlib_expandnode(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_makenode(entity parent,vector start, vector to, vector goal,float cost)
+{
+ entity node;
+ float h,g,f,doedge;
+ vector where;
+
+ ++pathlib_searched_cnt;
+
+ if(inwater(parent.origin))
+ {
+ if(inwater(to))
+ {
+ //bprint("Switch to water tracing\n");
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_swimnode;
+ }
+ else
+ {
+
+ //bprint("Switch to get out of water tracing\n");
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_swimnode;
+ }
+ }
+ else
+ {
+ if(inwater(to))
+ {
+ //bprint("Switch to get into water tracing\n");
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_swimnode;
+ }
+ else
+ {
+
+ //bprint("Switch to land tracing\n");
+ pathlib_expandnode = pathlib_expandnode_star;
+ pathlib_movenode = pathlib_walknode;
+ doedge = 1;
+ }
+ }
+
+ where = pathlib_movenode(parent.origin,to,0);
+ if not(pathlib_movenode_goodnode)
+ {
+ //mark_error(where,15);
+ return 0;
+ }
+
+ if(doedge)
+ if(edge_check(where,pathlib_edge_check_size))
+ return 0;
+
+ h = pathlib_heuristic(where,goal);
+
+ /*
+ if(parent.path_prev)
+ h = pathlib_h_diagonal2sdp(parent.path_prev.origin,parent.origin,where,goal);
+ else
+ h = pathlib_heuristic(where,goal);
+ */
+
+
+ //h = 0;
+ g = pathlib_cost(parent,where,cost);
+ f = g + h;
+
+ node = findradius(where,pathlib_gridsize * 0.75);
+ while(node)
+ {
+ if(node.is_path_node == TRUE)
+ {
+ ++pathlib_merge_cnt;
+ if(node.owner == openlist)
+ {
+ if(node.pathlib_node_g > g)
+ {
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+ node.path_prev = parent;
+ }
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+ }
+
+ return 1;
+ }
+ node = node.chain;
+ }
+
+ node = pathlib_mknode(where,parent);
+
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+
+ return 1;
+}
+
+entity pathlib_getbestopen()
+{
+ entity node;
+ entity bestnode;
+
+ if(best_open_node)
+ {
+ ++pathlib_bestcash_hits;
+ pathlib_bestcash_saved += pathlib_open_cnt;
+
+ return best_open_node;
+ }
+
+ node = findchainentity(owner,openlist);
+ if(!node)
+ return world;
+
+ bestnode = node;
+ while(node)
+ {
+ ++pathlib_bestopen_seached;
+ if(node.pathlib_node_f < bestnode.pathlib_node_f)
+ bestnode = node;
+
+ node = node.chain;
+ }
+
+ return bestnode;
+}
+
+void pathlib_close_node(entity node,vector goal)
+{
+
+ if(node.owner == closedlist)
+ {
+ dprint("Pathlib: Tried to close a closed node!\n");
+ return;
+ }
+
+ if(node == best_open_node)
+ best_open_node = world;
+
+ ++pathlib_closed_cnt;
+ --pathlib_open_cnt;
+
+ node.owner = closedlist;
+
+ if(vlen(node.origin - goal) <= pathlib_gridsize)
+ {
+ //if(vlen(node.origin - goal) < 128)
+ vector goalmove;
+ goalmove = pathlib_walknode(node.origin,goal,1);
+ if(pathlib_movenode_goodnode)
+ {
+ goal_node = node;
+ pathlib_foundgoal = TRUE;
+ }
+ }
+}
+
+float pathlib_expandnode_star(entity node, vector start, vector goal)
+{
+ vector point;
+ vector where;
+ float nodecnt;
+
+ where = node.origin;
+
+ v_forward = '1 0 0';
+ v_right = '0 1 0';
+
+ // Forward
+ point = where + v_forward * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Back
+ point = where - v_forward * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Right
+ point = where + v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Left
+ point = where - v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Forward-right
+ point = where + v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Forward-left
+ point = where + v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Back-right
+ point = where - v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Back-left
+ point = where - v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_box(entity node, vector start, vector goal)
+{
+ vector v;
+
+ for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
+ for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
+ for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
+ {
+ if(vlen(v - node.origin))
+ pathlib_makenode(node,start,v,goal,pathlib_movecost);
+ }
+
+ return pathlib_open_cnt;
+}
+
+void pathlib_cleanup()
+{
+ entity node;
+
+ if(best_open_node != world)
+ remove(best_open_node);
+
+ best_open_node = world;
+
+ node = findfloat(world,is_path_node, TRUE);
+ while(node)
+ {
+ node.path_next = world;
+ node.path_prev = world;
+ node.is_path_node = FALSE;
+ dumpnode(node);
+ //remove(node);
+ node = findfloat(world,is_path_node, TRUE);
+ }
+
+ if(openlist)
+ remove(openlist);
+
+ if(closedlist)
+ remove(closedlist);
+}
+
+entity pathlib_astar(vector from,vector to)
+{
+ entity path;
+ entity open,n;
+
+ pathlib_cleanup();
+
+ pathlib_heuristic = pathlib_h_diagonal3;
+ pathlib_cost = pathlib_g_static;
+ pathlib_expandnode = pathlib_expandnode_star;
+ pathlib_movenode = pathlib_walknode;
+
+ if not(openlist)
+ openlist = spawn();
+
+ if not(closedlist)
+ closedlist = spawn();
+
+ if not(scraplist)
+ scraplist = spawn();
+
+ pathlib_closed_cnt = 0;
+ pathlib_open_cnt = 0;
+ pathlib_made_cnt = 0;
+ pathlib_merge_cnt = 0;
+ pathlib_searched_cnt = 0;
+ pathlib_bestcash_hits = 0;
+ pathlib_bestcash_saved = 0;
+ pathlib_recycle_cnt = 0;
+
+ pathlib_gridsize = 192;
+ pathlib_movecost = pathlib_gridsize;
+ pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
+ pathlib_movecost_waterfactor = 1.1;
+ pathlib_foundgoal = 0;
+
+ walknode_boxmax = self.maxs * 1.5;
+ walknode_boxmin = self.mins * 1.5;
+
+ pathlib_edge_check_size = (vlen(walknode_boxmin - walknode_boxmax) * 0.25);
+
+ walknode_boxup = '0 0 2' * self.maxs_z;
+ walknode_stepsize = 32;
+ walknode_stepup = '0 0 1' * walknode_stepsize;
+ walknode_maxdrop = '0 0 3' * walknode_stepsize;
+
+ dprint("AStar init. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n");
+ path = pathlib_mknode(from,world);
+ pathlib_close_node(path,to);
+ if(pathlib_foundgoal)
+ {
+ dprint("A* Goal fond in first square!\n");
+
+ open = spawn();
+ open.owner = open;
+ open.classname = "path_end";
+ setorigin(open,path.origin);
+ pathlib_cleanup();
+
+ return open;
+ }
+
+ if(pathlib_expandnode(path,from,to) <= 0)
+ {
+ dprint("A* pathing fail\n");
+ pathlib_cleanup();
+ return world;
+ }
+
+ best_open_node = pathlib_getbestopen();
+ n = best_open_node;
+ pathlib_close_node(best_open_node,to);
+ if(inwater(n.origin))
+ pathlib_expandnode_box(n,from,to);
+ else
+ pathlib_expandnode_star(n,from,to);
+
+ //pathlib_expandnode(n,from,to);
+
+ while(pathlib_open_cnt)
+ {
+ best_open_node = pathlib_getbestopen();
+ n = best_open_node;
+ pathlib_close_node(best_open_node,to);
+
+ if(inwater(n.origin))
+ pathlib_expandnode_box(n,from,to);
+ else
+ pathlib_expandnode(n,from,to);
+
+ if(pathlib_foundgoal)
+ {
+ dprint("Path found, re-tracing...\n");
+
+ open = goal_node;
+ open.is_path_node = FALSE;
+ open.classname = "path_end";
+ open.owner = path;
+ open.path_next = world;
+
+
+ while(open.path_prev != path)
+ {
+ n = open;
+ open = open.path_prev;
+ open.owner = path;
+ open.path_next = n;
+
+ open.is_path_node = FALSE;
+ open.classname = "path_node";
+ }
+
+ open.path_prev = path;
+ path.path_next = open;
+ path.classname = "path_master";
+ path.is_path_node = FALSE;
+ path.owner = path;
+
+ pathlib_cleanup();
+
+#ifdef DEBUGPATHING
+ bprint("Chain done..\n");
+ pathlib_showpath2(path);
+
+
+ bprint(" Nodes reused: ", ftos(pathlib_recycle_cnt),"\n");
+ bprint(" Nodes created: ", ftos(pathlib_made_cnt),"\n");
+ bprint(" Nodes make/reuse: ", ftos(pathlib_made_cnt / pathlib_recycle_cnt),"\n");
+ bprint(" Nodes open: ", ftos(pathlib_open_cnt),"\n");
+ bprint(" Nodes merged: ", ftos(pathlib_merge_cnt),"\n");
+ bprint(" Nodes closed: ", ftos(pathlib_closed_cnt),"\n");
+ bprint(" Nodes searched: ", ftos(pathlib_searched_cnt),"\n");
+ bprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
+ bprint(" Nodes bestcash hits: ", ftos(pathlib_bestcash_hits),"\n");
+ bprint(" Nodes bestcash save: ", ftos(pathlib_bestcash_saved),"\n");
+ bprint("AStar done. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n\n");
+
+#endif
+ return path;
+ }
+ }
+
+ dprint("A* Faild to find a path! Try a smaller gridsize.\n");
+
+ pathlib_cleanup();
+
+ return world;
+}
+
Added: trunk/data/qcsrc/server/verbstack.qc
===================================================================
--- trunk/data/qcsrc/server/verbstack.qc (rev 0)
+++ trunk/data/qcsrc/server/verbstack.qc 2009-03-22 14:09:56 UTC (rev 6245)
@@ -0,0 +1,111 @@
+entity verb;
+.entity verbs_idle;
+.entity verbs_attack;
+.entity verbs_move;
+
+.float(float eval) verb_call;
+.entity verbstack;
+.float verb_static_value;
+
+#define VS_CALL_NO 0
+#define VS_CALL_YES_DOING -1
+#define VS_CALL_YES_DONE -2
+#define VS_CALL_REMOVE -3
+
+entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life)
+{
+ entity vrb;
+
+ vrb = spawn();
+ vrb.owner = self;
+ vrb.verbstack = stack;
+ vrb.verb_call = vrb_call;
+ vrb.verb_static_value = val_static;
+
+ if(vrb_life)
+ {
+ vrb.think = SUB_Remove;
+ vrb.nextthink = time + vrb_life;
+ }
+
+ return vrb;
+}
+
+float verbstack_pop(entity stack)
+{
+ entity vrb;
+ entity bestverb,oldself;
+ float value,bestvalue;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ verb = vrb;
+ self = vrb.owner;
+ value = vrb.verb_call(TRUE);
+ if(value < 0)
+ {
+ if(value == VS_CALL_REMOVE)
+ remove(vrb);
+ }
+ else
+ {
+ if(value > bestvalue)
+ {
+ bestverb = vrb;
+ bestvalue = value;
+ }
+ }
+ vrb = vrb.chain;
+ }
+
+ if(bestverb)
+ {
+ verb = bestverb;
+ self = verb.owner;
+ value = bestverb.verb_call(FALSE);
+ if(value == VS_CALL_REMOVE)
+ remove(bestverb);
+ }
+
+ self = oldself;
+
+ return value;
+}
+
+entity verbstack_pull(entity stack)
+{
+ entity vrb;
+ entity bestverb,oldself;
+ float value,bestvalue;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ self = vrb.owner;
+ verb = vrb;
+ value = vrb.verb_call(TRUE);
+ if(value > 0)
+ {
+ if(value == VS_CALL_REMOVE)
+ remove(vrb);
+ }
+ else
+ {
+ if(value > bestvalue)
+ {
+ bestverb = vrb;
+ bestvalue = value;
+ }
+ }
+ vrb =vrb.chain;
+ }
+
+ self = oldself;
+
+ return bestverb;
+}
More information about the nexuiz-commits
mailing list