From be1aef14e03e2f042ce4e7ba1a14f41cf0a116ed Mon Sep 17 00:00:00 2001 From: tzork Date: Fri, 9 Jan 2009 16:45:52 +0000 Subject: [PATCH] Turret should now work in ONS. Updates to moving units. git-svn-id: svn://svn.icculus.org/nexuiz/trunk@5474 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/movelib.qc | 81 ++- data/qcsrc/server/pathlib.qc | 241 +++++++-- data/qcsrc/server/progs.src | 12 +- data/qcsrc/server/steerlib.qc | 115 ++-- .../server/tturrets/system/system_damage.qc | 19 +- .../server/tturrets/system/system_main.qc | 123 ++--- .../server/tturrets/system/system_misc.qc | 26 + .../tturrets/system/system_scoreprocs.qc | 8 +- .../server/tturrets/units/unit_checkpoint.qc | 37 +- .../server/tturrets/units/unit_ewheel.qc | 164 +++++- .../server/tturrets/units/unit_phaser.qc | 2 +- .../server/tturrets/units/unit_walker.qc | 489 +++++++++--------- 12 files changed, 843 insertions(+), 474 deletions(-) diff --git a/data/qcsrc/server/movelib.qc b/data/qcsrc/server/movelib.qc index 7684b7da2..04d1160b4 100644 --- a/data/qcsrc/server/movelib.qc +++ b/data/qcsrc/server/movelib.qc @@ -2,13 +2,13 @@ Simulate drag self.velocity = movelib_vdrag(self.velocity,0.02,0.5); **/ -vector movelib_drag(float drag, float exp) +vector movelib_dragvec(float drag, float exp) { float lspeed,ldrag; lspeed = vlen(self.velocity); ldrag = lspeed * drag; - ldrag = ldrag * drag * exp; + ldrag = ldrag * (drag * exp); ldrag = 1 - (ldrag / lspeed); return self.velocity * ldrag; @@ -50,19 +50,82 @@ vector movelib_inertmove(vector new_vel,float new_bias) return new_vel * new_bias + self.velocity * (1-new_bias); } +.float movelib_lastupdate; +void movelib_move(vector force,float max_velocity,float drag,float mass,float breakforce) +{ + float deltatime; + float acceleration; + //float mspeed; -/** - Applies absolute force to a velocity -**/ -vector movelib_accelerate(vector vel,float force) + deltatime = time - self.movelib_lastupdate; + if (deltatime > 0.15) deltatime = 0; + self.movelib_lastupdate = time; + if(!deltatime) return; + + //mspeed = vlen(self.velocity); + + if(mass) + acceleration = vlen(force) / mass; + else + acceleration = vlen(force); + + if(self.flags & FL_ONGROUND) + { + if(breakforce) + { + breakforce = 1 - ((breakforce / mass) * deltatime); + self.velocity = self.velocity * breakforce; + } + + 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(max_velocity) + if(vlen(self.velocity) > max_velocity) + self.velocity = normalize(self.velocity) * max_velocity; +} + +void movelib_move_simple(vector newdir,float velo,float turnrate) { - return normalize(vel) * (vlen(vel) + force); + vector olddir; + + olddir = normalize(self.velocity); + + self.velocity = normalize(olddir + newdir * turnrate) * velo; } -vector movelib_decelerate(vector vel,float force) + +/* +vector movelib_accelerate(float force) { - return normalize(vel) * (vlen(vel) - force); + vector vel; + vel = self.velocity; + vel = normalize(vel) * (vlen(vel) + force); + self.velocity = self.velocity + vel; } + +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'; diff --git a/data/qcsrc/server/pathlib.qc b/data/qcsrc/server/pathlib.qc index 98767f03a..e0e7601a9 100644 --- a/data/qcsrc/server/pathlib.qc +++ b/data/qcsrc/server/pathlib.qc @@ -2,6 +2,10 @@ #define PLF_NOOPTIMIZE 2 #define PLF_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 @@ -21,13 +25,13 @@ #endif #define pathlib_garbagetime 120 -#define pathib_maxdivide 256 +#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_NORMAL, self); + tracebox(start, self.mins, self.maxs, end, MOVE_WORLDONLY, self); if(vlen(trace_endpos - end) < 32) return 1; @@ -35,13 +39,13 @@ float pathlib_stdproc_path_validate(vector start,vector end) return 0; } -vector pathlib_groundsnap(vector where,entity path) +vector pathlib_groundsnap(vector where) { float lsize; lsize = vlen(self.mins - self.maxs) * 0.25; - traceline(where + ('0 0 1' * lsize) ,where - '0 0 10000',MOVE_NORMAL,self); + traceline(where + ('0 0 1' * lsize) ,where - '0 0 10240',MOVE_WORLDONLY,self); return trace_endpos + ('0 0 1' * lsize); @@ -68,14 +72,12 @@ entity pathlib_createpoint(entity parent,entity next,entity first,vector where) if(next) { point.path_next = next; - //point.path_nodelength = vlen(point.origin - next.origin) } else point.classname = "path_end"; - if(point.owner.path_flags & PLF_GROUNDSNAP) - where = pathlib_groundsnap(where,parent); - + if (point.owner.path_flags & PLF_GROUNDSNAP) + where = pathlib_groundsnap(where); setorigin(point,where); @@ -83,18 +85,33 @@ entity pathlib_createpoint(entity parent,entity next,entity first,vector where) return point; } -vector pathlib_findsubpath(entity start,vector vcrash,entity end,float maxsize) +/* +float pathlib_scoresubpath(vector start,vector point,vector end,float minstep) { - float x,y,z; + 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; - float pathlength; - float pathlength_best; - vector bestpoint; - vector point; + vector bestpoint,point; float zmin,zmax; + vector box; - pathlength_best = 1000000; + pathscore_best = 0; step = vlen(self.maxs - self.mins) * start.owner.path_subpathing_bboxexpand; @@ -109,42 +126,117 @@ vector pathlib_findsubpath(entity start,vector vcrash,entity end,float maxsize) zmax = 1; } - for(z = zmin; z < zmax; z += step) - for(y = -maxsize; y < maxsize; y += step) - for(x = -maxsize; x < maxsize; x += step) + 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_z = vcrash_z + z; - point_x = vcrash_x + x; - point_y = vcrash_y + y; - + point = vcrash + box; if(start.owner.path_flags & PLF_GROUNDSNAP) - point = pathlib_groundsnap(point,start); + point = pathlib_groundsnap(point); if(self.path_validate(start.origin,point)) { dist = vlen(start.origin - point); if(dist > step) { - pathlength = dist + vlen(point - end.origin); - if(pathlength < pathlength_best) + pathscore = 1 / (dist + vlen(point - end.origin)); + if(pathscore > pathscore_best) { bestpoint = point; - pathlength_best = pathlength; + pathscore_best = pathscore; } } } } - if(pathlength_best != 1000000) + if(pathscore_best != 0) return bestpoint; - return vcrash; + return start.origin; } -float pathlib_path(entity start,entity end) +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; @@ -152,16 +244,35 @@ float pathlib_path(entity start,entity end) // 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; - subpath_point = pathlib_findsubpath(start,vcrash,end,start.owner.path_subpathing_size); + 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; + break; + 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 == vcrash) + if(subpath_point == start.origin) return 0; // Fail. subpoint = pathlib_createpoint(start,end,start.owner,subpath_point); @@ -173,7 +284,7 @@ float pathlib_path(entity start,entity end) if(self.path_validate(start.origin,end.origin)) return 1; - return pathlib_path(subpoint,end); + return pathlib_path(subpoint,end,pathing_method); } void pathlib_path_optimize(entity start,entity end) @@ -208,14 +319,17 @@ void pathlib_deletepath(entity start) { entity e; - e = findentity(start, owner, start); + e = findchainentity(owner, start); while(e) { - remove(e); - e = findentity(start, owner, start); + e.think = SUB_Remove; + e.nextthink = time; + e = e.chain; } } +//#define DEBUGPATHING +#ifdef DEBUGPATHING void pathlib_showpath(entity start) { entity e; @@ -227,10 +341,16 @@ void pathlib_showpath(entity start) } } +void path_dbg_think() +{ + pathlib_showpath(self); + self.nextthink = time + 1; +} +#endif /** - Run a A*-like pathing from 'from' to 'to' + Pathing from 'from' to 'to' **/ -entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand) +entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand,float pathing_method) { entity e_start,e_end; @@ -244,6 +364,13 @@ entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_ if(subpathing_bboxexpand < 1) subpathing_bboxexpand = 1; + if(pathflags & PLF_GROUNDSNAP) + { + //bprint("SnapIT!\n"); + from = pathlib_groundsnap(from); + to = pathlib_groundsnap(to); + } + e_start = pathlib_createpoint(world,world,world,from); e_start.path_flags = pathflags; @@ -256,19 +383,53 @@ entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_ e_start.path_next = e_end; e_start.cnt = 0; - if(!pathlib_path(e_start,e_end)) + 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() @@ -298,7 +459,7 @@ void pathlib_test_dinit() } setsize(self,'-50 -50 0','50 50 50'); - path = pathlib_makepath(self.origin,end.origin, PLF_GROUNDSNAP,500,1.25); + path = pathlib_makepath(self.origin,end.origin, PLF_GROUNDSNAP,500,1.25,PT_QUICKSTAR); if(!path) { @@ -317,3 +478,5 @@ void spawnfunc_pathlib_test() self.think = pathlib_test_dinit; self.nextthink = time + 2; } + +#endif diff --git a/data/qcsrc/server/progs.src b/data/qcsrc/server/progs.src index f092aa075..094a6eaf5 100644 --- a/data/qcsrc/server/progs.src +++ b/data/qcsrc/server/progs.src @@ -52,12 +52,6 @@ havocbot.qc g_subs.qc -// tZork's libs -movelib.qc -steerlib.qc -pathlib.qc - - runematch.qc arena.qc @@ -68,6 +62,12 @@ teamplay.qc cl_physics.qc +// tZork's libs +movelib.qc +steerlib.qc +pathlib.qc +//animation.qc + g_world.qc g_decors.qc g_casings.qc diff --git a/data/qcsrc/server/steerlib.qc b/data/qcsrc/server/steerlib.qc index 2a6810624..56c8a3711 100644 --- a/data/qcsrc/server/steerlib.qc +++ b/data/qcsrc/server/steerlib.qc @@ -1,3 +1,19 @@ +/** + Uniform pull towards a point +**/ +vector steerlib_pull(vector point) +{ + return normalize(point - self.origin); +} + +/** + Uniform push from a point +**/ +vector steerlib_push(vector point) +{ + return normalize(self.origin - point); +} + /** Pull toward a point, The further away, the stronger the pull. **/ @@ -25,6 +41,51 @@ vector steerlib_attract(vector point, float maximal_distance) return direction * (1-(distance / maximal_distance)); } +vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense) +{ + float distance; + vector direction; + float influense; + + distance = bound(0.00001,vlen(self.origin - point),max_distance); + direction = normalize(point - self.origin); + + influense = 1 - (distance / max_distance); + influense = min_influense + (influense * (max_influense - min_influense)); + + return direction * influense; +} + +/* +vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance) +{ + //float distance; + vector current_direction; + vector target_direction; + float i_target,i_current; + + if(!distance) + distance = vlen(self.origin - point); + + distance = bound(0.001,distance,maximal_distance); + + target_direction = normalize(point - self.origin); + current_direction = normalize(self.velocity); + + i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense); + i_current = 1 - i_target; + + // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense); + + string s; + s = ftos(i_target); + bprint("IT: ",s,"\n"); + s = ftos(i_current); + bprint("IC : ",s,"\n"); + + return normalize((target_direction * i_target) + (current_direction * i_current)); +} +*/ /** Move away from a point. **/ @@ -40,7 +101,7 @@ vector steerlib_repell(vector point,float maximal_distance) } /** - Keep at ideal_distance away from point + Try to keep at ideal_distance away from point **/ vector steerlib_standoff(vector point,float ideal_distance) { @@ -63,6 +124,11 @@ vector steerlib_standoff(vector point,float ideal_distance) /** A random heading in a forward halfcicrle + + use like: + self.target = steerlib_waner(256,32,self.target) + + where range is the cicrle radius and tresh is how close we need to be to pick a new heading. **/ vector steerlib_waner(float range,float tresh,vector oldpoint) { @@ -81,7 +147,7 @@ vector steerlib_waner(float range,float tresh,vector oldpoint) } /** - Dodge a point- + Dodge a point. dont work to well. **/ vector steerlib_dodge(vector point,vector dodge_dir,float min_distance) { @@ -121,6 +187,8 @@ vector steerlib_flock(float radius, float standoff,float separation_force,float /** All members want to be in the center, and keep away from eachother. The furtehr form the center the more they want to be there. + + This results in a aligned movement (?!) much like flocking. **/ vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force) { @@ -155,52 +223,36 @@ vector steerlib_traceavoid(float pitch,float length) { vector vup_left,vup_right,vdown_left,vdown_right; float fup_left,fup_right,fdown_left,fdown_right; + vector upwish,downwish,leftwish,rightwish; vector v_left,v_down; - //vector point; - - /* - traceline(self.origin,self.origin + v_forward * length,MOVE_NOMONSTERS,self); - if(trace_fraction == 1) - return '0 0 0'; - */ v_left = v_right * -1; v_down = v_up * -1; vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length; traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self); - //vup_left = trace_endpos; fup_left = trace_fraction; //te_lightning1(world,self.origin, trace_endpos); vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length; traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self); - //vup_right = trace_endpos; fup_right = trace_fraction; //te_lightning1(world,self.origin, trace_endpos); vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length; traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self); - //vdown_left = trace_endpos; fdown_left = trace_fraction; //te_lightning1(world,self.origin, trace_endpos); vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length; traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self); - //vdown_right = trace_endpos; fdown_right = trace_fraction; //te_lightning1(world,self.origin, trace_endpos); - //(v_for * f_for) + - - //point = self.origin + (vup_left * fup_left) + (vup_right * fup_right) + - // (vdown_left * fdown_left) + (vdown_right * fdown_right); - - vector upwish,downwish,leftwish,rightwish; upwish = v_up * (fup_left + fup_right); downwish = v_down * (fdown_left + fdown_right); leftwish = v_left * (fup_left + fdown_left); @@ -208,9 +260,6 @@ vector steerlib_traceavoid(float pitch,float length) return (upwish+leftwish+downwish+rightwish) * 0.25; - //point = point * 0.2; // /5 - - // return normalize(point - self.origin) * (1- (fup_left+fup_right+fdown_left+fdown_right) * 0.25); } @@ -219,7 +268,7 @@ vector steerlib_traceavoid(float pitch,float length) // Testting // // Everything below this point is a mess :D // ////////////////////////////////////////////// -#define TLIBS_TETSLIBS +//#define TLIBS_TETSLIBS #ifdef TLIBS_TETSLIBS void flocker_die() { @@ -245,8 +294,8 @@ void flocker_think() self.angles_x = self.angles_x * -1; dodgemove = steerlib_traceavoid(0.35,1000); - swarmmove = steerlib_swarm(1000,100,150,400); - reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,1000) * 700; + swarmmove = steerlib_flock(500,75,700,500); + reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700; if(vlen(dodgemove) == 0) { @@ -256,13 +305,13 @@ void flocker_think() else self.pos1 = normalize(self.velocity); - dodgemove = dodgemove * 700; + dodgemove = dodgemove * vlen(self.velocity) * 5; newmove = swarmmove + reprellmove + wandermove + dodgemove; - self.velocity = movelib_inertmove_byspeed(newmove,900,0.4,0.8); + self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9); //self.velocity = movelib_inertmove(dodgemove,0.65); - self.velocity = movelib_drag(0.02,0.6); + self.velocity = movelib_dragvec(0.01,0.6); self.angles = vectoangles(self.velocity); @@ -349,15 +398,15 @@ void flocker_hunter_think() } if(self.enemy) - attractmove = steerlib_attract(self.enemy.origin,5000) * 1100; + attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250; else attractmove = normalize(self.velocity) * 200; - dodgemove = steerlib_traceavoid(0.35,1500) * 1700; + dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity); newmove = dodgemove + attractmove; - self.velocity = movelib_inertmove_byspeed(newmove,850,0.5,0.9); - self.velocity = movelib_drag(0.01,0.5); + self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7); + self.velocity = movelib_dragvec(0.01,0.5); self.angles = vectoangles(self.velocity); @@ -395,3 +444,5 @@ void spawnfunc_flockerspawn() self.enemy.owner = self; } #endif + + diff --git a/data/qcsrc/server/tturrets/system/system_damage.qc b/data/qcsrc/server/tturrets/system/system_damage.qc index 2008ebf57..6de6f8647 100644 --- a/data/qcsrc/server/tturrets/system/system_damage.qc +++ b/data/qcsrc/server/tturrets/system/system_damage.qc @@ -289,24 +289,25 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo self = baseent; if (teamplay != 0) + if (self.team == attacker.team) { - if (self.team == attacker.team) + // This does not happen anymore. Re-enable if you fix that. + //if(attacker.flags & FL_CLIENT) + //if not(attacker.isbot) + //sprint(attacker, "\{1}Turret tells you: I'm on your team!\n"); + + if(cvar("g_friendlyfire")) { - sprint(attacker, "\{1}Turret tells you: I'm on your team!\n"); + self = oldself; return; } else { - /* - // This will get enoying fast... - FOR_EACH_PLAYER(player) - if(player.team == self.team) - sprint(player, "The enemy is attacking your base!"); - */ + damage = damage * cvar("g_friendlyfire"); } } - baseent.health = baseent.health - damage; + self.health = self.health - damage; // thorw head slightly off aim when hit? if (oldself.classname == "turret_head") diff --git a/data/qcsrc/server/tturrets/system/system_main.qc b/data/qcsrc/server/tturrets/system/system_main.qc index d9b5835fe..6685c98a3 100644 --- a/data/qcsrc/server/tturrets/system/system_main.qc +++ b/data/qcsrc/server/tturrets/system/system_main.qc @@ -177,31 +177,30 @@ void turret_stdproc_track() real_angle = wish_angle - (self.angles + self.tur_head.angles); else { - //if(vlen(wish_angle - self.tur_head.angles) > vlen(self.tur_head.angles - wish_angle)) real_angle = wish_angle - self.tur_head.angles; - //else - // real_angle = self.tur_head.angles - wish_angle; - } - - /* - if(real_angle_y > 180) - bprint("^3"); - if(real_angle_y < -180) - bprint("^1"); - string s; - s = vtos(real_angle); - bprint("RA1: ",s); - */ - - - if (real_angle_x < 0) real_angle_x += 360; - if (real_angle_x > 180) real_angle_x -= 360; - if (real_angle_y < 0) real_angle_y += 360; - if (real_angle_y >= 180) real_angle_y -= 360; + } - //s = vtos(real_angle); - //bprint(" RA2: ",s,"\n"); + if(real_angle_x > self.tur_head.angles_x) + { + if(real_angle_x >= 180) + real_angle_x -= 360; + } + else + { + if(real_angle_x <= -180) + real_angle_x += 360; + } + if(real_angle_y > self.tur_head.angles_y) + { + if(real_angle_y >= 180) + real_angle_y -= 360; + } + else + { + if(real_angle_y <= -180) + real_angle_y += 360; + } // Limit pitch @@ -426,6 +425,7 @@ float turret_validate_target(entity e_turret,entity e_target,float validate_flag return -5.5; } + // Missile if (e_target.flags & FL_PROJECTILE) { @@ -459,13 +459,13 @@ float turret_validate_target(entity e_turret,entity e_target,float validate_flag { v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5); //v_tmp = e_target.origin; - traceline(e_turret.origin,v_tmp,0,e_turret); + traceline(e_turret.origin + e_turret.tur_aimorg,v_tmp,0,e_turret); if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos)) return -10; } - // Can we even aim this thing? (anglecheck) + // Can we even aim this thing? tvt_thadv = angleofs(e_turret.tur_head,e_target); tvt_tadv = angleofs(e_turret,e_target); tvt_thadf = vlen(tvt_thadv); @@ -501,44 +501,39 @@ float turret_validate_target(entity e_turret,entity e_target,float validate_flag entity turret_select_target() { entity e; // target looper entity - entity e_enemy; // currently best scoreing enemy - - float score; // current target (e) score - float m_score; // current best target (e_enemy) score + float score; // target looper entity score + entity e_enemy; // currently best scoreing target + float m_score; // currently best scoreing target's score float f; - // string s; + + m_score = 0; + if(self.enemy) + if(turret_validate_target(self,e,self.target_select_flags) > 0) + { + e_enemy = self.enemy; + m_score = self.turret_score_target(self,e_enemy) * self.target_select_samebias; + } + e = findradius(self.origin,self.target_range); - // Nothing to aim at. + // Nothing to aim at? if (!e) return world; - m_score = 0; - while (e) { f = turret_validate_target(self,e,self.target_select_flags); - //s = ftos(f); - //bprint(e.netname, " = ",s,"\n"); if (f > 0) { - score = self.turret_score_target(self,e); - if ((score > m_score) && (score > 0)) { e_enemy = e; m_score = score; } } - e = e.chain; } -// self.tur_lastscore = m_score; - - //if (self.enemy != e_enemy) - //self.volly_counter = 0; - return e_enemy; } @@ -731,9 +726,13 @@ void turret_stdproc_fire() dprint("^1Bang, ^3your dead^7 ",self.enemy.netname,"! ^1(turret with no real firefunc)\n"); } +/* + When .used a turret switched team to activator.team. + If activator is world, the turrets goes inactive. +*/ void turret_stdproc_use() { - // bprint("Used:",self.netname, " By ",other.netname,"\n"); + //bprint("Used:",self.netname, " By ",other.classname,"\n"); self.team = activator.team; @@ -742,38 +741,6 @@ void turret_stdproc_use() else self.tur_active = 1; - // ONS Uses _use to communicate. - //if (g_onslaught) - /* - if (1) // if anyone ever figures out why i needed a active toggle here, fix this - { - entity e; - - if (self.targetname) - { - e = find(world,target,self.targetname); - if (e != world) - self.team = e.team; - } - - if (self.team != self.tur_head.team) - turret_stdproc_respawn(); - - if(self.team == 0) - self.tur_active = 0; - else - self.tur_active = 1; - - } - else - { - if (self.tur_active) - self.tur_active = 0; - else - self.tur_active = 1; - } - */ - } /* @@ -1105,8 +1072,10 @@ float turret_stdproc_init (string cvar_base_name) self.tur_active = 1; - if (g_onslaught) - self.use(); + //if (g_onslaught) + // self.use(); + + //turret_stdproc_use(); return 1; } diff --git a/data/qcsrc/server/tturrets/system/system_misc.qc b/data/qcsrc/server/tturrets/system/system_misc.qc index fc81a6a86..0d41a47c9 100644 --- a/data/qcsrc/server/tturrets/system/system_misc.qc +++ b/data/qcsrc/server/tturrets/system/system_misc.qc @@ -1,5 +1,31 @@ //--// Some support routines //--// +float shortangle_f(float ang1,float ang2) +{ + if(ang1 > ang2) + { + if(ang1 >= 180) + return ang1 - 360; + } + else + { + if(ang1 <= -180) + return ang1 + 360; + } + + return ang1; +} +vector shortangle_v(vector ang1,vector ang2) +{ + vector vtmp; + vtmp_x = shortangle_f(ang1_x,ang2_x); + vtmp_y = shortangle_f(ang1_y,ang2_y); + vtmp_z = shortangle_f(ang1_z,ang2_z); + + return vtmp; +} + + // Get real origin vector real_origin(entity ent) { diff --git a/data/qcsrc/server/tturrets/system/system_scoreprocs.qc b/data/qcsrc/server/tturrets/system/system_scoreprocs.qc index a3e14b0f8..15c08fa33 100644 --- a/data/qcsrc/server/tturrets/system/system_scoreprocs.qc +++ b/data/qcsrc/server/tturrets/system/system_scoreprocs.qc @@ -39,7 +39,7 @@ float turret_stdproc_targetscore_generic(entity e_turret,entity e_target) float d_score; // Distance score //float da_score; // Distance from aimpoint score float a_score; // Angular score - float s_score; // samescore (same target as last time) + //float s_score; // samescore (same target as last time) float m_score; // missile score float p_score; // player score @@ -47,7 +47,7 @@ float turret_stdproc_targetscore_generic(entity e_turret,entity e_target) if(!e_target) return 0; - if (e_target == e_turret.enemy) s_score = 1; + //if (e_target == e_turret.enemy) s_score = 1; if (e_turret.tur_defend) { @@ -84,13 +84,13 @@ float turret_stdproc_targetscore_generic(entity e_turret,entity e_target) p_score = 1; d_score = max(d_score,0); - s_score = max(s_score,0); + //s_score = max(s_score,0); a_score = max(a_score,0); m_score = max(m_score,0); p_score = max(p_score,0); + // (s_score * e_turret.target_select_samebias) + score = (d_score * e_turret.target_select_rangebias) + - (s_score * e_turret.target_select_samebias) + (a_score * e_turret.target_select_anglebias) + (m_score * e_turret.target_select_missilebias) + (p_score * e_turret.target_select_playerbias); diff --git a/data/qcsrc/server/tturrets/units/unit_checkpoint.qc b/data/qcsrc/server/tturrets/units/unit_checkpoint.qc index 6125922cd..a13a45d80 100644 --- a/data/qcsrc/server/tturrets/units/unit_checkpoint.qc +++ b/data/qcsrc/server/tturrets/units/unit_checkpoint.qc @@ -1,14 +1,18 @@ /** turret_checkpoint - Semi smart pathing system for move capable turrets. **/ -#define checkpoint_path swampslug -#define checkpoint_target enemy -#define checkpoint_cache_who flagcarried +#define checkpoint_target goalstack03 + +/* +#define checkpoint_cache_who flagcarried #define checkpoint_cache_from lastrocket -#define checkpoint_cache_to selected_player +#define checkpoint_cache_to selected_player +*/ + +#define pathgoal goalstack01 +#define pathcurrent goalstack02 entity path_makeorcache(entity forwho,entity start, entity end) { @@ -17,21 +21,14 @@ entity path_makeorcache(entity forwho,entity start, entity end) oldself = self; self = forwho; - pth = pathlib_makepath(start.origin,end.origin,PLF_GROUNDSNAP,500,1.5); + pth = pathlib_makepath(start.origin,end.origin,PLF_GROUNDSNAP,500,1.5,PT_QUICKSTAR); + self = oldself; return pth; } void turret_checkpoint_use() { - if(other.checkpoint_path) - pathlib_deletepath(other.checkpoint_path); - - other.checkpoint_path = world; - - if(self.checkpoint_target) - other.checkpoint_path = path_makeorcache(other,self,self.checkpoint_target); - } /*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32) @@ -43,15 +40,21 @@ wait: Pause at this point # seconds. If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly. If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached. */ -void spawnfunc_turret_checkpoint() +void turret_checkpoint_init() { if(self.target != "") { - self.checkpoint_target = find(world,targetname,self.target); - if(!self.checkpoint_target) + self.enemy = find(world,targetname,self.target); + if(self.enemy == world) dprint("A turret_checkpoint faild to find its target!\n"); } +} +void spawnfunc_turret_checkpoint() +{ + setorigin(self,self.origin); + self.think = turret_checkpoint_init; + self.nextthink = time + 0.25; } // Compat. diff --git a/data/qcsrc/server/tturrets/units/unit_ewheel.qc b/data/qcsrc/server/tturrets/units/unit_ewheel.qc index 07ae3b0c0..b53d2e38c 100644 --- a/data/qcsrc/server/tturrets/units/unit_ewheel.qc +++ b/data/qcsrc/server/tturrets/units/unit_ewheel.qc @@ -26,7 +26,7 @@ void ewheel_attack() vector v; float f,i; - for(i=0;i<2;++i) + for (i=0;i<1;i++) { f = gettagindex(self.tur_head,"tag_fire"); v = gettaginfo(self.tur_head,f); @@ -56,61 +56,172 @@ void ewheel_attack() proj.enemy = self.enemy; proj.flags = FL_PROJECTILE | FL_NOTARGET; - self.tur_head.frame += 1; + self.tur_head.frame += 2; if (self.tur_head.frame > 3) - self.tur_head.frame = 0; - } + self.tur_head.frame = 0; + } } -void ewheel_postthink() +#define EWHEEL_MASS 50 +#define EWHEEL_MAXSPEED 1500 +#define EWHEEL_ACCEL_SLOW 50 +#define EWHEEL_ACCEL_FAST 150 +#define EWHEEL_BREAK_SLOW 100 +#define EWHEEL_BREAK_FAST 250 + +void ewheel_enemymove() { - vector wish_angle,real_angle; - float turn_limit; + vector wish_angle,real_angle,steer,avoid; + float turn_limit,angle_ofs; + + //steer = steerlib_attract2(point,0.5,2000,0.95); + steer = steerlib_pull(self.enemy.origin); + avoid = steerlib_traceavoid(0.3,350); + + wish_angle = normalize(avoid * 0.5 + steer); + wish_angle = vectoangles(wish_angle); + real_angle = wish_angle - self.angles; - if (!self.enemy) + if (real_angle_x > self.angles_x) { - self.velocity = '0 0 0'; - return; + if (real_angle_x >= 180) + real_angle_x -= 360; + } + else + { + if (real_angle_x <= -180) + real_angle_x += 360; + } + + if (real_angle_y > self.tur_head.angles_y) + { + if (real_angle_y >= 180) + real_angle_y -= 360; + } + else + { + if (real_angle_y <= -180) + real_angle_y += 360; } - wish_angle = normalize(self.enemy.origin - self.origin); + turn_limit = cvar("g_turrets_unit_ewheel_turnrate"); + // Convert from dgr / sec to dgr / tic + turn_limit = turn_limit / (1 / self.ticrate); + angle_ofs = fabs(real_angle_y); + real_angle_y = bound(turn_limit * -1,real_angle_y,turn_limit); + self.angles_y = (self.angles_y + real_angle_y); + + // Simulate banking + self.angles_z = bound(-45,real_angle_y * -1,45); + + + if (self.frame > 40) + self.frame = 1; + + makevectors(self.angles); + + if (self.tur_dist_enemy > self.target_range_optimal) + { + if ( angle_ofs < 10 ) + { + self.frame += 2; + movelib_move(v_forward * EWHEEL_ACCEL_FAST,EWHEEL_MAXSPEED,0,EWHEEL_MASS,0); + } + else if (angle_ofs < 16) + { + self.frame += 0.5; + movelib_move(v_forward,EWHEEL_MAXSPEED,0,EWHEEL_MASS,EWHEEL_BREAK_SLOW); + } + else + { + movelib_move('0 0 0',EWHEEL_MAXSPEED,0,EWHEEL_MASS,EWHEEL_BREAK_FAST); + } + } + else + movelib_move('0 0 0',EWHEEL_MAXSPEED,0,EWHEEL_MASS,EWHEEL_BREAK_FAST); +} + +void ewheel_roammove() +{ + movelib_move(v_forward,EWHEEL_MAXSPEED,0,EWHEEL_MASS,EWHEEL_BREAK_SLOW); + self.angles_z = 0; + + /* + vector wish_angle,real_angle,steer,avoid; + float turn_limit,angle_ofs; + float dist; + + return; + + dist = vlen(self.origin - self.pos1); + + //steer = steerlib_attract2(point,0.5,2000,0.95); + steer = steerlib_pull(self.pos1); + avoid = steerlib_traceavoid(0.3,350); + + wish_angle = normalize(avoid * 0.5 + steer); wish_angle = vectoangles(wish_angle); real_angle = wish_angle - self.angles; - if (real_angle_y < 0) real_angle_y += 360; - if (real_angle_y > 180) real_angle_y -= 360; + real_angle_y = shortangle_f(real_angle_y,self.angles_y); turn_limit = cvar("g_turrets_unit_ewheel_turnrate"); // Convert from dgr/sec to dgr/tic turn_limit = turn_limit / (1 / self.ticrate); + angle_ofs = fabs(real_angle_y); + real_angle_y = bound(turn_limit * -1,real_angle_y,turn_limit); - self.angles_y = self.angles_y + real_angle_y; - self.angles_z = bound(-10,real_angle_y * -1,10); + self.angles_y = (self.angles_y + real_angle_y); + + self.angles_z = bound(-12,real_angle_y * -1,12); if(self.frame > 40) self.frame = 1; - self.angles_z = 0; - if(self.tur_dist_enemy > self.target_range_optimal) + makevectors(self.angles); + float lspeed; + lspeed = vlen(self.velocity); + + if((dist < 64)||(self.phase < time)) { - self.angles_z = bound(-15,real_angle_y * -1,15); - makevectors(self.angles); - self.velocity = v_forward * 250; - self.frame += 2; - return; + movelib_move('0 0 0',150,0,50,200); + self.pos1 = self.origin + v_forward * 256 + randomvec() * 128; + self.pos1_z = self.origin_z; + self.phase = time + 5; } + else if(dist < 128) + { + self.frame += 1; + if(lspeed > 100) + movelib_move(v_forward * 50,150,0,50,50); + else + movelib_move(v_forward * 100,150,0,50,0); + } + else + { + self.frame += 1; + if(angle_ofs > 10) + movelib_move(v_forward * 50,150,0,50,50); + else + movelib_move(v_forward * 250,150,0,50,0); + } + */ +} - self.velocity = '0 0 0'; - +void ewheel_postthink() +{ + if (self.enemy) + ewheel_enemymove(); + else + ewheel_roammove(); } + void ewheel_respawnhook() { - - setorigin(self,self.pos1); //self.angles = self.wkr_spawn.angles; @@ -165,6 +276,7 @@ void turret_ewheel_dinit() //self.flags = FL_CLIENT; self.iscreature = TRUE; self.movetype = MOVETYPE_WALK; + self.gravity = 0.01; self.solid = SOLID_SLIDEBOX; self.takedamage = DAMAGE_AIM; diff --git a/data/qcsrc/server/tturrets/units/unit_phaser.qc b/data/qcsrc/server/tturrets/units/unit_phaser.qc index 96575df68..43c8e21c6 100644 --- a/data/qcsrc/server/tturrets/units/unit_phaser.qc +++ b/data/qcsrc/server/tturrets/units/unit_phaser.qc @@ -35,7 +35,7 @@ void turret_phaser_postthink() void beam_think() { - if ((time > self.cnt)||(self.owner.deadflag != DEAD_NO)) + if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO)) { self.owner.attack_finished_single = time + self.owner.shot_refire; self.owner.fireflag = 2; diff --git a/data/qcsrc/server/tturrets/units/unit_walker.qc b/data/qcsrc/server/tturrets/units/unit_walker.qc index afd5e40d9..64ff2b89e 100644 --- a/data/qcsrc/server/tturrets/units/unit_walker.qc +++ b/data/qcsrc/server/tturrets/units/unit_walker.qc @@ -1,3 +1,5 @@ +//#define rocket_rack tur_head.enemy + #define ANIM_NO 0 #define ANIM_WALK 1 #define ANIM_RUN 1.1 @@ -8,6 +10,7 @@ #define ANIM_LAND 5 #define ANIM_PAIN 6 #define ANIM_MEELE 7 + .float animflag; .entity wkr_props; @@ -27,33 +30,29 @@ .entity goalstack28, goalstack29, goalstack30, goalstack31; */ + float walker_firecheck() { - if (!turret_stdproc_firecheck()) return 0; - //if(self.tur_cannon.frame != 0) return 0; - - //if(self.walking == 1) self.walking = 2; - //if(self.walking != 0) - // return 0; - - return 1; + return turret_stdproc_firecheck(); } -void walker_meele_dmg() +void walker_meele_do_dmg() { vector where; entity e; - makevectors(self.angles); where = self.origin + v_forward * 128; - e = findradius(where,80); + e = findradius(where,128); while (e) { if (turret_validate_target(self,e,self.target_validate_flags)) if (e != self) - Damage(e,self,self,cvar("g_turrets_unit_walker_std_meele_dmg "),DEATH_TURRET,'0 0 0', v_forward * cvar("g_turrets_unit_walker_std_meele_force") ); + { + //bprint(self.netname, " is meele hitting ",e.netname,"\n"); + Damage(e,self,self,cvar("g_turrets_unit_walker_std_meele_dmg"),DEATH_TURRET,'0 0 0', v_forward * cvar("g_turrets_unit_walker_std_meele_force") ); + } e = e.chain; } } @@ -61,27 +60,22 @@ void walker_meele_dmg() void walker_animate() { - if (self.tur_head.frame != 0) - self.tur_head.frame = self.tur_head.frame +1; - - if (self.tur_head.frame > 12) - self.tur_head.frame = 0; - - switch (self.animflag) { case ANIM_NO: - //if(self.frame != 0) - // self.frame = 0; + if(self.frame != 0) + self.frame = 0; break; case ANIM_WALK: self.frame = self.frame + 1; if (self.frame > 25) self.frame = 5; + break; case ANIM_RUN: + self.frame = self.frame + 2; if (self.frame > 25) self.frame = 5; @@ -114,7 +108,7 @@ void walker_animate() break; case ANIM_PAIN: - if (self.frame < 90) self.frame = 90; + if (self.frame < 60) self.frame = 90; self.frame = self.frame + 1; if (self.frame > 95) self.animflag = ANIM_NO; @@ -125,7 +119,7 @@ void walker_animate() self.frame = self.frame + 1; if (self.frame == 133) - walker_meele_dmg(); + walker_meele_do_dmg(); if (self.frame > 140) self.animflag = ANIM_NO; @@ -133,6 +127,7 @@ void walker_animate() } } + void walker_rocket_explode() { vector org2; @@ -148,11 +143,7 @@ void walker_rocket_explode() sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", 1, ATTN_NORM); org2 = findbetterlocation (self.origin, 16); - WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte (MSG_BROADCAST, 78); - WriteCoord (MSG_BROADCAST, org2_x); - WriteCoord (MSG_BROADCAST, org2_y); - WriteCoord (MSG_BROADCAST, org2_z); + pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); RadiusDamage (self, self.owner, cvar("g_turrets_unit_walker_std_rocket_dmg"), 0, cvar("g_turrets_unit_walker_std_rocket_radius"), world, cvar("g_turrets_unit_walker_std_rocket_force"), DEATH_TURRET, world); @@ -166,17 +157,8 @@ void walker_rocket_damage (entity inflictor, entity attacker, float damage, floa if (self.health <= 0) walker_rocket_explode(); } - -/* -g_turrets_unit_walker_std_rocket_refire -g_turrets_unit_walker_std_rocket_dmg -g_turrets_unit_walker_std_rocket_radius -g_turrets_unit_walker_std_rocket_force -g_turrets_unit_walker_std_rocket_tunrate -g_turrets_unit_walker_std_rocket_speed -g_turrets_unit_walker_std_rocket_speed_add -*/ - +//#define WALKER_ROCKET_MOVE movelib_move(newdir * 275,900,0.1,10) +#define WALKER_ROCKET_MOVE movelib_move_simple(newdir,1000,cvar("g_turrets_unit_walker_std_rocket_tunrate")) void walker_rocket_loop(); void walker_rocket_think() { @@ -218,7 +200,6 @@ void walker_rocket_think() olddir = normalize(self.velocity); - // Accelerate m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add"); // Enemy dead? just keep on the current heading then. @@ -234,33 +215,36 @@ void walker_rocket_think() if (self.enemy) { - // Predict enemy position itime = max(edist / m_speed,1); - newdir = normalize((self.enemy.origin + self.tur_shotorg) - self.origin); + newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg); } else { - //pre_pos = self.origin + olddir; newdir = olddir; } - // Turn - newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate")); + WALKER_ROCKET_MOVE; - self.velocity = newdir * m_speed; // Turn model self.angles = vectoangles(self.velocity); - if (time+itime < time+0.1) + if (time + itime < time + 0.1) { - self.think = turret_hellion_missile_explode; + self.think = walker_rocket_explode; self.nextthink = time + itime; } } void walker_rocket_loop3() { + if (self.tur_health < time) + { + self.think = walker_rocket_explode; + self.nextthink = time; + return; + } + self.nextthink = time + 0.1; if (vlen(self.origin - self.tur_shotorg) < 128 ) @@ -270,21 +254,23 @@ void walker_rocket_loop3() } vector newdir; - vector olddir; - float m_speed; - m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add"); - olddir = normalize(self.velocity); - newdir = normalize(self.tur_shotorg - self.origin); - newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate")); + newdir = steerlib_pull(self.tur_shotorg); + WALKER_ROCKET_MOVE; - self.velocity = newdir * m_speed; self.angles = vectoangles(self.velocity); } void walker_rocket_loop2() { - self.nextthink = time + 0; + if (self.tur_health < time) + { + self.think = walker_rocket_explode; + self.nextthink = time; + return; + } + + self.nextthink = time; if (vlen(self.origin - self.tur_shotorg) < 128 ) { @@ -294,21 +280,16 @@ void walker_rocket_loop2() } vector newdir; - vector olddir; - float m_speed; - m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add"); - olddir = normalize(self.velocity); - newdir = normalize(self.tur_shotorg - self.origin); - newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate")); - self.velocity = newdir * m_speed; + newdir = steerlib_pull(self.tur_shotorg); + WALKER_ROCKET_MOVE; + self.angles = vectoangles(self.velocity); } void walker_rocket_loop() { - self.nextthink= time + 0; self.tur_shotorg = self.origin + '0 0 400'; self.think = walker_rocket_loop2; @@ -352,11 +333,11 @@ void walker_fire_rocket(vector org) rocket.event_damage = walker_rocket_damage; - rocket.nextthink = time + 0.2; + rocket.nextthink = time + 0.25; rocket.solid = SOLID_BBOX; rocket.movetype = MOVETYPE_FLYMISSILE; rocket.effects = EF_LOWPRECISION; - rocket.velocity = ((v_forward + v_up * 0.35) +(randomvec() * 0.15))* cvar("g_turrets_unit_walker_std_rocket_speed"); + rocket.velocity = ((v_forward + v_up * 0.25) +(randomvec() * 0.1))* cvar("g_turrets_unit_walker_std_rocket_speed"); rocket.angles = vectoangles(rocket.velocity); rocket.touch = walker_rocket_explode; rocket.flags = FL_PROJECTILE; @@ -367,17 +348,26 @@ void walker_fire_rocket(vector org) } +/* #define s_turn 10 #define s_walk 100 #define s_run 300 #define s_accel1 8 #define s_accel2 16 #define s_decel 8 +*/ void rv_think() { float f; vector org; + entity oldself; + + if(self.owner.deadflag != DEAD_NO) + { + remove(self); + return; + } self.cnt = self.cnt -1; @@ -395,231 +385,196 @@ void rv_think() org = self.owner.origin + gettaginfo(self.owner,f); + self.nextthink = time + 0.2; + oldself = self; self = self.owner; walker_fire_rocket(org); + self=oldself; } +/* +void acb_run() +{ + //bprint("run\n"); + animation_set(self,5,25,40,AF_ENDCALLBACK,5); +} +void acb_walk() +{ + bprint("walk\n"); + animation_set(self,5,25,20,AF_ENDCALLBACK,5); +} +void acb_meele() +{ + walker_do_meele(); +} + +void set_acb(void() acb_func) +{ + self.animator_callback = acb_func; + if(animation_query(self) != AS_RUNNING) + { + bprint("Not running\n"); + acb_func(); + } + else + { + if not(self.animator.anim_flags & AF_ENDCALLBACK) + self.animator.anim_flags = self.animator.anim_flags | AF_ENDCALLBACK; + } +} +*/ + void walker_postthink() { vector wish_angle; vector real_angle; - float turn_limit; + vector steer; + float vel; - if ((self.flags & FL_ONGROUND)&&(self.animflag != ANIM_MEELE)) - self.animflag = ANIM_NO; + //if (self.flags & FL_ONGROUND) + //if (self.animflag != ANIM_MEELE) + // self.animflag = ANIM_NO; + if (self.tur_head.attack_finished_single < time) if (self.enemy) - if (self.tur_head.attack_finished_single < time) - { - entity rv; - rv = spawn(); - rv.think = rv_think; - rv.nextthink = time; - rv.cnt = 4; - rv.owner = self; - - self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire"); - } + { + entity rv; + rv = spawn(); + rv.think = rv_think; + rv.nextthink = time; + rv.cnt = 4; + rv.owner = self; - if (self.checkpoint_path) + self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire"); + } + + // Do we have a path? + if (self.pathcurrent) { - if (vlen(self.origin - self.goalcurrent.origin) < 64) - if (self.goalcurrent.path_next == world) - { + //set_acb(acb_walk); + self.animflag = ANIM_WALK; - self.checkpoint_path = world; // Path endpoint reached, go roaming. + // Are we close enougth to a path node to switch to the next? + if (vlen(self.origin - self.pathcurrent.origin) < 64) + if (self.pathcurrent.path_next == world) + { + // Path endpoint reached + pathlib_deletepath(self.pathcurrent.owner); + self.pathcurrent = world; + + if(self.pathgoal) + { + if(self.pathgoal.use) + self.pathgoal.use(); + + if(self.pathgoal.enemy) + { + self.pathcurrent = pathlib_makepath(self.pathgoal.origin,self.pathgoal.enemy.origin,PLF_GROUNDSNAP,1500,2,PT_QUICKBOX); + self.pathgoal = self.pathgoal.enemy; + } + } + else + self.pathgoal = world; } else - self.goalcurrent = self.goalcurrent.path_next; + self.pathcurrent = self.pathcurrent.path_next; - self.animflag = ANIM_WALK; + steer = steerlib_attract2(self.pathcurrent.origin,0.5,2000,0.95); + vel = 150; } else // Roaming mode { - if (self.enemy) { - wish_angle = angleofs(self,self.enemy); //normalize(self.origin-self.enemy.origin); + wish_angle = angleofs(self,self.enemy); + steer = steerlib_pull(self.enemy.origin); if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range")) { - if (fabs(wish_angle_y) < 15) + { + vel = 0; + //set_acb(acb_meele); + //walker_do_meele(); self.animflag = ANIM_MEELE; + return; + } } else { if (fabs(wish_angle_y) < 15) + { + //set_acb(acb_run); self.animflag = ANIM_RUN; + vel = 300; + } else if (fabs(wish_angle_y) < 30) + { + //set_acb(acb_walk); self.animflag = ANIM_WALK; + vel = 150; + } else - self.animflag = ANIM_TURN; + { + //set_acb(acb_walk); + self.animflag = ANIM_WALK; + vel = 50; + } } - } else + { + vel = 0; + if(self.animflag != ANIM_MEELE) self.animflag = ANIM_NO; + } } + // Align the walker to the ground - float s_speed; - - s_speed = vlen(self.velocity); - - // Turn on the spot - if (self.animflag == ANIM_TURN) - { - if (self.enemy) - wish_angle = normalize(self.enemy.origin - self.origin); - else - wish_angle = normalize(self.goalcurrent.origin - self.origin); - - wish_angle = vectoangles(wish_angle); - - real_angle = wish_angle - self.angles; - - if (real_angle_x < 0) real_angle_x += 360; - if (real_angle_x > 180) real_angle_x -= 360; - - if (real_angle_y < 0) real_angle_y += 360; - if (real_angle_y > 180) real_angle_y -= 360; - - turn_limit = cvar("g_turrets_unit_walker_turn_turnrate"); - // Convert from dgr/sec to dgr/tic - turn_limit = turn_limit / (1 / self.ticrate); - - //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit); - real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit); + self.angles_x = self.angles_x * -1; + makevectors(self.angles); + self.angles_x = self.angles_x * -1; - self.angles_y = self.angles_y + real_angle_y; + traceline(self.origin + '0 0 15', self.origin - '0 0 150' ,MOVE_WORLDONLY,self); + wish_angle = (trace_endpos); + traceline(self.origin + v_forward * 10 + '0 0 15', self.origin + v_forward * 10 - '0 0 150' ,MOVE_WORLDONLY,self); + real_angle = vectoangles(normalize( trace_endpos - wish_angle)); - if (self.enemy) - v_forward = normalize(self.enemy.origin - self.origin); - else - v_forward = normalize(self.goalcurrent.origin - self.origin); + self.angles_x = real_angle_x; + self.angles_z = real_angle_z; - makevectors(self.angles); - - if (s_speed > s_turn) - self.velocity = (v_forward * max((s_speed - s_decel),s_turn)); - if (s_speed < s_turn) - self.velocity = (v_forward * min((s_speed + s_accel1),s_turn)); - } - else if (self.animflag == ANIM_WALK) // Gg walking + if(vel == 0) { - if (self.goalcurrent) - wish_angle = normalize(self.goalcurrent.origin - self.origin); - else - if (self.enemy) - wish_angle = normalize(self.enemy.origin - self.origin); - else - wish_angle = self.angles; - - - wish_angle = vectoangles(wish_angle); // And make a angle - real_angle = wish_angle - self.angles; - - if (real_angle_x < 0) real_angle_x += 360; - if (real_angle_x > 180) real_angle_x -= 360; - - if (real_angle_y < 0) real_angle_y += 360; - if (real_angle_y > 180) real_angle_y -= 360; - - turn_limit = cvar("g_turrets_unit_walker_walk_turnrate"); - // Convert from dgr/sec to dgr/tic - turn_limit = turn_limit / (1 / self.ticrate); - - //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit); - real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit); - - self.angles_y = self.angles_y + real_angle_y; - - if (self.goalcurrent) - v_forward = normalize(self.goalcurrent.origin - self.origin); - else - if (self.enemy) - v_forward = normalize(self.enemy.origin - self.origin); - - makevectors(self.angles); - self.velocity = v_forward * s_walk; - - //if(self.flags & FL_ONGROUND) - /* - { - float s_z; - s_z = self.velocity_z; - if(s_speed > s_walk) - self.velocity = (v_forward * max((s_speed - s_decel),s_walk)); - if(s_speed <= s_walk) - self.velocity = (v_forward * min((s_speed + s_accel1),s_walk)); - self.velocity_z = s_z;//s_walk; - } - */ - - + self.velocity = '0 0 0'; + //animator_remove(self); } - else if (self.animflag == ANIM_RUN) // Move fast, turn slow + else { - if (self.goalcurrent) - wish_angle = normalize(self.goalcurrent.origin - self.origin); - else - if (self.enemy) - wish_angle = normalize(self.enemy.origin - self.origin); - else - wish_angle = self.angles; - - wish_angle = vectoangles(wish_angle); // And make a angle - real_angle = wish_angle - self.angles; - - if (real_angle_x < 0) real_angle_x += 360; - if (real_angle_x > 180) real_angle_x -= 360; - - if (real_angle_y < 0) real_angle_y += 360; - if (real_angle_y > 180) real_angle_y -= 360; + steer = steer * 0.5 + steerlib_traceavoid(0.3,256); + float vz; + vz = self.velocity_z; + movelib_move_simple(steer * 200,vel,0.5); + self.velocity_z = vz; - turn_limit = cvar("g_turrets_unit_walker_run_turnrate"); - // Convert from dgr/sec to dgr/tic - turn_limit = turn_limit / (1 / self.ticrate); - - //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit); - real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit); - - self.angles_y = self.angles_y + real_angle_y; - - - if (self.enemy) - v_forward = normalize(self.enemy.origin - self.origin); - else - v_forward = normalize(self.goalcurrent.origin - self.origin); + wish_angle = vectoangles(self.velocity); - makevectors(self.angles); + real_angle = wish_angle - self.angles; - if (self.flags & FL_ONGROUND) - { - if (s_speed > s_run) - self.velocity = (v_forward * max((s_speed - s_decel),s_run)); - if (s_speed <= s_run) - self.velocity = (v_forward * min((s_speed + s_accel2),s_run)); - } - } - else - { + real_angle_y = shortangle_f(real_angle_y,self.angles_y); - if (self.flags & FL_ONGROUND) - { - makevectors(self.angles); - if (s_speed > 0) - self.velocity = min(s_speed - s_decel,0) * v_forward; - } + self.angles_y = self.angles_y + bound(-5,real_angle_y,5); } + walker_animate(); + if (self.tur_head.frame != 0) + self.tur_head.frame = self.tur_head.frame +1; - - walker_animate(); + if (self.tur_head.frame > 12) + self.tur_head.frame = 0; } @@ -659,11 +614,14 @@ void walker_attack() self.uzi_bulletcounter = self.uzi_bulletcounter + 1; } + void walker_respawnhook() { vector vtmp; entity e; + //load_unit_settings(self.rocket_rack,"walker_std_rocket",1); + self.origin = self.wkr_spawn.origin; self.wkr_props.solid = SOLID_BBOX; self.wkr_props.alpha = 1; @@ -680,45 +638,47 @@ void walker_respawnhook() { bprint("Warning! initital waypoint for Walker does NOT exsist!\n"); self.target = ""; - - //remove(self); - //return; } if (e.classname != "turret_checkpoint") dprint("Warning: not a turrret path\n"); else - self.goalcurrent = e; + { + self.pathcurrent = pathlib_makepath(self.origin,e.origin,PLF_GROUNDSNAP,500,2,PT_QUICKBOX); + self.pathgoal = e; + } } } void walker_diehook() { + //animator_remove(self); + + if(self.pathcurrent) + pathlib_deletepath(self.pathcurrent.owner); + + self.pathcurrent = world; self.wkr_props.solid = SOLID_NOT; self.wkr_props.alpha = -1; + + if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN) + { + + remove(self.wkr_props); + //remove(self.rocket_rack); + remove(self.wkr_spawn); + } + } //.string target_start; void turret_walker_dinit() { - if (self.netname == "") self.netname = "Walker Turret"; - /* - if (self.target != "") - { - e = find(world,targetname,self.target); - if (!e) - { - bprint("Warning! initital waypoint for Walker does NOT exsist!\n"); - self.target = ""; - } + entity e; + + if (self.netname == "") self.netname = "Walker Turret"; - if (e.classname != "turret_checkpoint") - dprint("Warning: not a turrret path\n"); - else - self.goalcurrent = e; - } - */ self.wkr_props = spawn(); self.wkr_spawn = spawn(); @@ -754,6 +714,7 @@ void turret_walker_dinit() self.wkr_spawn.angles = self.angles; self.wkr_spawn.solid = SOLID_NOT; + traceline(self.wkr_spawn.origin + '0 0 10', self.wkr_spawn.origin - '0 0 10000', MOVE_NOMONSTERS, self); setorigin(self.wkr_spawn,trace_endpos + '0 0 4'); @@ -773,7 +734,7 @@ void turret_walker_dinit() //setsize(self,'-70 -70 0','70 70 55'); self.tur_shotorg = v; - self.tur_aimorg = v; + self.tur_aimorg = v;// + '0 0 10'; self.idle_aim = '0 0 0'; @@ -786,6 +747,26 @@ void turret_walker_dinit() self.turret_postthink = walker_postthink; + if (self.target != "") + { + e = find(world,targetname,self.target); + if (!e) + { + bprint("Warning! initital waypoint for Walker does NOT exsist!\n"); + self.target = ""; + } + + if (e.classname != "turret_checkpoint") + dprint("Warning: not a turrret path\n"); + else + { + self.pathcurrent = pathlib_makepath(self.origin,e.origin,PLF_GROUNDSNAP,500,2,PT_QUICKBOX); + self.pathgoal = e; + } + } + + //self.solid = SOLID_NOT; + } -- 2.39.2