5 #include "pathlib/utility.qh"
9 Uniform pull towards a point
11 #define steerlib_pull(ent,point) normalize(point - (ent).origin)
12 /*vector steerlib_pull(entity this, vector point)
14 return normalize(point - this.origin);
18 Uniform push from a point
20 #define steerlib_push(ent,point) normalize(ent.origin - point)
22 vector steerlib_push(entity this, vector point)
24 return normalize(this.origin - point);
28 Pull toward a point, The further away, the stronger the pull.
30 vector steerlib_arrive(entity this, vector point, float maximal_distance)
32 float distance = bound(0.001,vlen(this.origin - point),maximal_distance);
33 vector direction = normalize(point - this.origin);
34 return direction * (distance / maximal_distance);
38 Pull toward a point increasing the pull the closer we get
40 vector steerlib_attract(entity this, vector point, float maximal_distance)
42 float distance = bound(0.001,vlen(this.origin - point),maximal_distance);
43 vector direction = normalize(point - this.origin);
45 return direction * (1-(distance / maximal_distance));
48 vector steerlib_attract2(entity this, vector point, float min_influense,float max_distance,float max_influense)
50 float distance = bound(0.00001,vlen(this.origin - point),max_distance);
51 vector direction = normalize(point - this.origin);
53 float influense = 1 - (distance / max_distance);
54 influense = min_influense + (influense * (max_influense - min_influense));
56 return direction * influense;
60 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
63 vector current_direction;
64 vector target_direction;
65 float i_target,i_current;
68 distance = vlen(this.origin - point);
70 distance = bound(0.001,distance,maximal_distance);
72 target_direction = normalize(point - this.origin);
73 current_direction = normalize(this.velocity);
75 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
76 i_current = 1 - i_target;
78 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
82 bprint("IT: ",s,"\n");
84 bprint("IC : ",s,"\n");
86 return normalize((target_direction * i_target) + (current_direction * i_current));
90 Move away from a point.
92 vector steerlib_repell(entity this, vector point,float maximal_distance)
97 distance = bound(0.001,vlen(this.origin - point),maximal_distance);
98 direction = normalize(this.origin - point);
100 return direction * (1-(distance / maximal_distance));
104 Try to keep at ideal_distance away from point
106 vector steerlib_standoff(entity this, vector point,float ideal_distance)
111 distance = vlen(this.origin - point);
114 if(distance < ideal_distance)
116 direction = normalize(this.origin - point);
117 return direction * (distance / ideal_distance);
120 direction = normalize(point - this.origin);
121 return direction * (ideal_distance / distance);
126 A random heading in a forward halfcicrle
129 this.target = steerlib_wander(256,32,this.target)
131 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
133 vector steerlib_wander(entity this, float range, float tresh, vector oldpoint)
136 wander_point = v_forward - oldpoint;
138 if (vdist(wander_point, >, tresh))
141 range = bound(0,range,1);
143 wander_point = this.origin + v_forward * 128;
144 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
146 return normalize(wander_point - this.origin);
150 Dodge a point. dont work to well.
152 vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
156 distance = max(vlen(this.origin - point),min_distance);
157 if (min_distance < distance)
160 return dodge_dir * (min_distance/distance);
164 flocking by .flock_id
165 Group will move towards the unified direction while keeping close to eachother.
168 vector steerlib_flock(entity this, float _radius, float standoff,float separation_force,float flock_force)
171 vector push = '0 0 0', pull = '0 0 0';
174 flock_member = findradius(this.origin, _radius);
177 if(flock_member != this)
178 if(flock_member.flock_id == this.flock_id)
181 push = push + (steerlib_repell(this, flock_member.origin,standoff) * separation_force);
182 pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
184 flock_member = flock_member.chain;
186 return push + (pull* (1 / ccount));
190 flocking by .flock_id
191 Group will move towards the unified direction while keeping close to eachother.
192 xy only version (for ground movers).
194 vector steerlib_flock2d(entity this, float _radius, float standoff,float separation_force,float flock_force)
197 vector push = '0 0 0', pull = '0 0 0';
200 flock_member = findradius(this.origin,_radius);
203 if(flock_member != this)
204 if(flock_member.flock_id == this.flock_id)
207 push = push + (steerlib_repell(this, flock_member.origin, standoff) * separation_force);
208 pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
210 flock_member = flock_member.chain;
216 return push + (pull * (1 / ccount));
220 All members want to be in the center, and keep away from eachother.
221 The furtehr form the center the more they want to be there.
223 This results in a aligned movement (?!) much like flocking.
225 vector steerlib_swarm(entity this, float _radius, float standoff,float separation_force,float swarm_force)
228 vector force = '0 0 0', center = '0 0 0';
231 swarm_member = findradius(this.origin,_radius);
235 if(swarm_member.flock_id == this.flock_id)
238 center = center + swarm_member.origin;
239 force = force + (steerlib_repell(this, swarm_member.origin,standoff) * separation_force);
241 swarm_member = swarm_member.chain;
244 center = center * (1 / ccount);
245 force = force + (steerlib_arrive(this, center,_radius) * swarm_force);
251 Steer towards the direction least obstructed.
252 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
253 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
255 vector steerlib_traceavoid(entity this, float pitch,float length)
257 vector vup_left,vup_right,vdown_left,vdown_right;
258 float fup_left,fup_right,fdown_left,fdown_right;
259 vector upwish,downwish,leftwish,rightwish;
260 vector v_left,v_down;
263 v_left = v_right * -1;
266 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
267 traceline(this.origin, this.origin + vup_left,MOVE_NOMONSTERS,this);
268 fup_left = trace_fraction;
270 //te_lightning1(NULL,this.origin, trace_endpos);
272 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
273 traceline(this.origin,this.origin + vup_right ,MOVE_NOMONSTERS,this);
274 fup_right = trace_fraction;
276 //te_lightning1(NULL,this.origin, trace_endpos);
278 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
279 traceline(this.origin,this.origin + vdown_left,MOVE_NOMONSTERS,this);
280 fdown_left = trace_fraction;
282 //te_lightning1(NULL,this.origin, trace_endpos);
284 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
285 traceline(this.origin,this.origin + vdown_right,MOVE_NOMONSTERS,this);
286 fdown_right = trace_fraction;
288 //te_lightning1(NULL,this.origin, trace_endpos);
289 upwish = v_up * (fup_left + fup_right);
290 downwish = v_down * (fdown_left + fdown_right);
291 leftwish = v_left * (fup_left + fdown_left);
292 rightwish = v_right * (fup_right + fdown_right);
294 return (upwish+leftwish+downwish+rightwish) * 0.25;
299 Steer towards the direction least obstructed.
300 Run tracelines in a forward trident, bias each direction negative if something is found there.
302 vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
304 vector vt_left, vt_right,vt_front;
305 float f_left, f_right,f_front;
306 vector leftwish, rightwish,frontwish, v_left;
308 v_left = v_right * -1;
311 vt_front = v_forward * length;
312 traceline(this.origin + vofs, this.origin + vofs + vt_front,MOVE_NOMONSTERS,this);
313 f_front = trace_fraction;
315 vt_left = (v_forward + (v_left * pitch)) * length;
316 traceline(this.origin + vofs, this.origin + vofs + vt_left,MOVE_NOMONSTERS,this);
317 f_left = trace_fraction;
319 //te_lightning1(NULL,this.origin, trace_endpos);
321 vt_right = (v_forward + (v_right * pitch)) * length;
322 traceline(this.origin + vofs, this.origin + vofs + vt_right ,MOVE_NOMONSTERS,this);
323 f_right = trace_fraction;
325 //te_lightning1(NULL,this.origin, trace_endpos);
327 leftwish = v_left * f_left;
328 rightwish = v_right * f_right;
329 frontwish = v_forward * f_front;
331 return normalize(leftwish + rightwish + frontwish);
334 //#define BEAMSTEER_VISUAL
335 float beamsweep(entity this, vector from, vector dir,float length, float step,float step_up, float step_down)
340 u = '0 0 1' * step_up;
341 d = '0 0 1' * step_down;
343 traceline(from + u, from - d,MOVE_NORMAL,this);
344 if(trace_fraction == 1.0)
347 if(!location_isok(trace_endpos, false, false))
351 for(i = 0; i < length; i += step)
355 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,this);
356 if(trace_fraction != 1.0)
359 traceline(b + u, b - d,MOVE_NORMAL,this);
360 if(trace_fraction == 1.0)
363 if(!location_isok(trace_endpos, false, false))
365 #ifdef BEAMSTEER_VISUAL
366 te_lightning1(NULL,a+u,b+u);
367 te_lightning1(NULL,b+u,b-d);
375 vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
377 float bm_forward, bm_right, bm_left,p;
381 vr = vectoangles(dir);
384 tracebox(this.origin + '0 0 1' * step_up, this.mins, this.maxs, ('0 0 1' * step_up) + this.origin + (dir * length), MOVE_NOMONSTERS, this);
385 if(trace_fraction == 1.0)
387 //te_lightning1(this,this.origin,this.origin + (dir * length));
392 bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
394 vr = normalize(v_forward + v_right * 0.125);
395 vl = normalize(v_forward - v_right * 0.125);
397 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
398 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
401 p = bm_left + bm_right;
404 //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
405 //te_lightning1(this.tur_head,this.origin + '0 0 32',this.origin + '0 0 32' + vl * length);
412 vr = normalize(v_forward + v_right * p);
413 vl = normalize(v_forward - v_right * p);
414 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
415 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
418 if(bm_left + bm_right < 0.15)
420 vr = normalize((v_forward*-1) + v_right * 0.90);
421 vl = normalize((v_forward*-1) - v_right * 0.90);
423 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
424 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
427 //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
428 //te_lightning1(this.tur_head,this.origin + '0 0 32',this.origin + '0 0 32' + vl * length);
430 bm_forward *= bm_forward;
431 bm_right *= bm_right;
437 return normalize(vr + vl);