4 Uniform pull towards a point
6 vector steerlib_pull(vector point)
8 return normalize(point - self.origin);
12 Uniform push from a point
14 #define steerlib_push(point) normalize(self.origin - point)
16 vector steerlib_push(vector point)
18 return normalize(self.origin - point);
22 Pull toward a point, The further away, the stronger the pull.
24 vector steerlib_arrive(vector point,float maximal_distance)
29 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
30 direction = normalize(point - self.origin);
31 return direction * (distance / maximal_distance);
35 Pull toward a point increasing the pull the closer we get
37 vector steerlib_attract(vector point, float maximal_distance)
42 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
43 direction = normalize(point - self.origin);
45 return direction * (1-(distance / maximal_distance));
48 vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
54 distance = bound(0.00001,vlen(self.origin - point),max_distance);
55 direction = normalize(point - self.origin);
57 influense = 1 - (distance / max_distance);
58 influense = min_influense + (influense * (max_influense - min_influense));
60 return direction * influense;
64 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
67 vector current_direction;
68 vector target_direction;
69 float i_target,i_current;
72 distance = vlen(self.origin - point);
74 distance = bound(0.001,distance,maximal_distance);
76 target_direction = normalize(point - self.origin);
77 current_direction = normalize(self.velocity);
79 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
80 i_current = 1 - i_target;
82 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
86 bprint("IT: ",s,"\n");
88 bprint("IC : ",s,"\n");
90 return normalize((target_direction * i_target) + (current_direction * i_current));
94 Move away from a point.
96 vector steerlib_repell(vector point,float maximal_distance)
101 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
102 direction = normalize(self.origin - point);
104 return direction * (1-(distance / maximal_distance));
108 Try to keep at ideal_distance away from point
110 vector steerlib_standoff(vector point,float ideal_distance)
115 distance = vlen(self.origin - point);
118 if(distance < ideal_distance)
120 direction = normalize(self.origin - point);
121 return direction * (distance / ideal_distance);
124 direction = normalize(point - self.origin);
125 return direction * (ideal_distance / distance);
130 A random heading in a forward halfcicrle
133 self.target = steerlib_wander(256,32,self.target)
135 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
137 vector steerlib_wander(float range,float tresh,vector oldpoint)
140 wander_point = v_forward - oldpoint;
142 if (vlen(wander_point) > tresh)
145 range = bound(0,range,1);
147 wander_point = self.origin + v_forward * 128;
148 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
150 return normalize(wander_point - self.origin);
154 Dodge a point. dont work to well.
156 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
160 distance = max(vlen(self.origin - point),min_distance);
161 if (min_distance < distance)
164 return dodge_dir * (min_distance/distance);
168 flocking by .flock_id
169 Group will move towards the unified direction while keeping close to eachother.
172 vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
178 flock_member = findradius(self.origin,radius);
181 if(flock_member != self)
182 if(flock_member.flock_id == self.flock_id)
185 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
186 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity,radius) * flock_force);
188 flock_member = flock_member.chain;
190 return push + (pull* (1 / ccount));
194 flocking by .flock_id
195 Group will move towards the unified direction while keeping close to eachother.
196 xy only version (for ground movers).
198 vector steerlib_flock2d(float radius, float standoff,float separation_force,float flock_force)
204 flock_member = findradius(self.origin,radius);
207 if(flock_member != self)
208 if(flock_member.flock_id == self.flock_id)
211 push = push + (steerlib_repell(flock_member.origin, standoff) * separation_force);
212 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, radius) * flock_force);
214 flock_member = flock_member.chain;
220 return push + (pull * (1 / ccount));
224 All members want to be in the center, and keep away from eachother.
225 The furtehr form the center the more they want to be there.
227 This results in a aligned movement (?!) much like flocking.
229 vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
235 swarm_member = findradius(self.origin,radius);
239 if(swarm_member.flock_id == self.flock_id)
242 center = center + swarm_member.origin;
243 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
245 swarm_member = swarm_member.chain;
248 center = center * (1 / ccount);
249 force = force + (steerlib_arrive(center,radius) * swarm_force);
255 Steer towards the direction least obstructed.
256 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
257 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
259 vector steerlib_traceavoid(float pitch,float length)
261 vector vup_left,vup_right,vdown_left,vdown_right;
262 float fup_left,fup_right,fdown_left,fdown_right;
263 vector upwish,downwish,leftwish,rightwish;
264 vector v_left,v_down;
267 v_left = v_right * -1;
270 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
271 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
272 fup_left = trace_fraction;
274 //te_lightning1(world,self.origin, trace_endpos);
276 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
277 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
278 fup_right = trace_fraction;
280 //te_lightning1(world,self.origin, trace_endpos);
282 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
283 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
284 fdown_left = trace_fraction;
286 //te_lightning1(world,self.origin, trace_endpos);
288 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
289 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
290 fdown_right = trace_fraction;
292 //te_lightning1(world,self.origin, trace_endpos);
293 upwish = v_up * (fup_left + fup_right);
294 downwish = v_down * (fdown_left + fdown_right);
295 leftwish = v_left * (fup_left + fdown_left);
296 rightwish = v_right * (fup_right + fdown_right);
298 return (upwish+leftwish+downwish+rightwish) * 0.25;
303 Steer towards the direction least obstructed.
304 Run tracelines in a forward trident, bias each direction negative if something is found there.
306 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
308 vector vt_left, vt_right,vt_front;
309 float f_left, f_right,f_front;
310 vector leftwish, rightwish,frontwish, v_left;
312 v_left = v_right * -1;
315 vt_front = v_forward * length;
316 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
317 f_front = trace_fraction;
319 vt_left = (v_forward + (v_left * pitch)) * length;
320 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
321 f_left = trace_fraction;
323 //te_lightning1(world,self.origin, trace_endpos);
325 vt_right = (v_forward + (v_right * pitch)) * length;
326 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
327 f_right = trace_fraction;
329 //te_lightning1(world,self.origin, trace_endpos);
331 leftwish = v_left * f_left;
332 rightwish = v_right * f_right;
333 frontwish = v_forward * f_front;
335 return normalize(leftwish + rightwish + frontwish);
338 float beamsweep_badpoint(vector point,float waterok)
342 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
345 pc = pointcontents(point);
346 pc2 = pointcontents(point - '0 0 1');
350 case CONTENT_SOLID: break;
351 case CONTENT_SLIME: break;
352 case CONTENT_LAVA: break;
358 if (pc2 == CONTENT_SOLID)
361 if (pc2 == CONTENT_WATER)
377 //#define BEAMSTEER_VISUAL
378 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
383 u = '0 0 1' * step_up;
384 d = '0 0 1' * step_down;
386 traceline(from + u, from - d,MOVE_NORMAL,self);
387 if(trace_fraction == 1.0)
390 if(beamsweep_badpoint(trace_endpos,0))
394 for(i = 0; i < length; i += step)
398 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
399 if(trace_fraction != 1.0)
402 traceline(b + u, b - d,MOVE_NORMAL,self);
403 if(trace_fraction == 1.0)
406 if(beamsweep_badpoint(trace_endpos,0))
408 #ifdef BEAMSTEER_VISUAL
409 te_lightning1(world,a+u,b+u);
410 te_lightning1(world,b+u,b-d);
418 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
420 float bm_forward, bm_right, bm_left,p;
424 vr = vectoangles(dir);
427 tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self);
428 if(trace_fraction == 1.0)
430 //te_lightning1(self,self.origin,self.origin + (dir * length));
438 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
440 vr = normalize(v_forward + v_right * 0.125);
441 vl = normalize(v_forward - v_right * 0.125);
443 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
444 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
447 p = bm_left + bm_right;
450 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
451 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
458 vr = normalize(v_forward + v_right * p);
459 vl = normalize(v_forward - v_right * p);
460 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
461 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
464 if(bm_left + bm_right < 0.15)
466 vr = normalize((v_forward*-1) + v_right * 0.75);
467 vl = normalize((v_forward*-1) - v_right * 0.75);
469 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
470 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
473 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
474 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
476 bm_forward *= bm_forward;
477 bm_right *= bm_right;
483 return normalize(vr + vl);
488 //////////////////////////////////////////////
490 // Everything below this point is a mess :D //
491 //////////////////////////////////////////////
492 //#define TLIBS_TETSLIBS
493 #ifdef TLIBS_TETSLIBS
496 sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
498 pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
503 self.nextthink = time;
504 self.think = SUB_Remove;
510 vector dodgemove,swarmmove;
511 vector reprellmove,wandermove,newmove;
513 self.angles_x = self.angles_x * -1;
514 makevectors(self.angles);
515 self.angles_x = self.angles_x * -1;
517 dodgemove = steerlib_traceavoid(0.35,1000);
518 swarmmove = steerlib_flock(500,75,700,500);
519 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
521 if(vlen(dodgemove) == 0)
523 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
524 wandermove = self.pos1 * 50;
527 self.pos1 = normalize(self.velocity);
529 dodgemove = dodgemove * vlen(self.velocity) * 5;
531 newmove = swarmmove + reprellmove + wandermove + dodgemove;
532 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
533 //self.velocity = movelib_inertmove(dodgemove,0.65);
535 self.velocity = movelib_dragvec(0.01,0.6);
537 self.angles = vectoangles(self.velocity);
542 self.nextthink = time + 0.1;
552 setorigin(flocker, self.origin + '0 0 32');
553 setmodel (flocker, "models/turrets/rocket.md3");
554 setsize (flocker, '-3 -3 -3', '3 3 3');
556 flocker.flock_id = self.flock_id;
557 flocker.classname = "flocker";
558 flocker.owner = self;
559 flocker.think = flocker_think;
560 flocker.nextthink = time + random() * 5;
561 PROJECTILE_MAKETRIGGER(flocker);
562 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
563 flocker.effects = EF_LOWPRECISION;
564 flocker.velocity = randomvec() * 300;
565 flocker.angles = vectoangles(flocker.velocity);
567 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
569 self.cnt = self.cnt -1;
573 void flockerspawn_think()
580 self.nextthink = time + self.delay;
584 void flocker_hunter_think()
586 vector dodgemove,attractmove,newmove;
590 self.angles_x = self.angles_x * -1;
591 makevectors(self.angles);
592 self.angles_x = self.angles_x * -1;
595 if(vlen(self.enemy.origin - self.origin) < 64)
605 e = findchainfloat(flock_id,self.flock_id);
608 d = vlen(self.origin - e.origin);
622 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
624 attractmove = normalize(self.velocity) * 200;
626 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
628 newmove = dodgemove + attractmove;
629 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
630 self.velocity = movelib_dragvec(0.01,0.5);
633 self.angles = vectoangles(self.velocity);
634 self.nextthink = time + 0.1;
639 void spawnfunc_flockerspawn()
641 precache_model ( "models/turrets/rocket.md3");
642 precache_model("models/turrets/c512.md3");
645 if(!self.cnt) self.cnt = 20;
646 if(!self.delay) self.delay = 0.25;
647 if(!self.flock_id) self.flock_id = globflockcnt;
649 self.think = flockerspawn_think;
650 self.nextthink = time + 0.25;
652 self.enemy = spawn();
654 setmodel(self.enemy, "models/turrets/rocket.md3");
655 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
657 self.enemy.classname = "FLock Hunter";
658 self.enemy.scale = 3;
659 self.enemy.effects = EF_LOWPRECISION;
660 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
661 PROJECTILE_MAKETRIGGER(self.enemy);
662 self.enemy.think = flocker_hunter_think;
663 self.enemy.nextthink = time + 10;
664 self.enemy.flock_id = self.flock_id;
665 self.enemy.owner = self;