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 pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
501 self.nextthink = time;
502 self.think = SUB_Remove;
508 vector dodgemove,swarmmove;
509 vector reprellmove,wandermove,newmove;
511 self.angles_x = self.angles_x * -1;
512 makevectors(self.angles);
513 self.angles_x = self.angles_x * -1;
515 dodgemove = steerlib_traceavoid(0.35,1000);
516 swarmmove = steerlib_flock(500,75,700,500);
517 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
519 if(vlen(dodgemove) == 0)
521 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
522 wandermove = self.pos1 * 50;
525 self.pos1 = normalize(self.velocity);
527 dodgemove = dodgemove * vlen(self.velocity) * 5;
529 newmove = swarmmove + reprellmove + wandermove + dodgemove;
530 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
531 //self.velocity = movelib_inertmove(dodgemove,0.65);
533 self.velocity = movelib_dragvec(0.01,0.6);
535 self.angles = vectoangles(self.velocity);
540 self.nextthink = time + 0.1;
550 setorigin(flocker, self.origin + '0 0 32');
551 setmodel (flocker, "models/turrets/rocket.md3");
552 setsize (flocker, '-3 -3 -3', '3 3 3');
554 flocker.flock_id = self.flock_id;
555 flocker.classname = "flocker";
556 flocker.owner = self;
557 flocker.think = flocker_think;
558 flocker.nextthink = time + random() * 5;
559 PROJECTILE_MAKETRIGGER(flocker);
560 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
561 flocker.effects = EF_LOWPRECISION;
562 flocker.velocity = randomvec() * 300;
563 flocker.angles = vectoangles(flocker.velocity);
565 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
567 self.cnt = self.cnt -1;
571 void flockerspawn_think()
578 self.nextthink = time + self.delay;
582 void flocker_hunter_think()
584 vector dodgemove,attractmove,newmove;
588 self.angles_x = self.angles_x * -1;
589 makevectors(self.angles);
590 self.angles_x = self.angles_x * -1;
593 if(vlen(self.enemy.origin - self.origin) < 64)
603 e = findchainfloat(flock_id,self.flock_id);
606 d = vlen(self.origin - e.origin);
620 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
622 attractmove = normalize(self.velocity) * 200;
624 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
626 newmove = dodgemove + attractmove;
627 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
628 self.velocity = movelib_dragvec(0.01,0.5);
631 self.angles = vectoangles(self.velocity);
632 self.nextthink = time + 0.1;
637 void spawnfunc_flockerspawn()
639 precache_model ( "models/turrets/rocket.md3");
640 precache_model("models/turrets/c512.md3");
643 if(!self.cnt) self.cnt = 20;
644 if(!self.delay) self.delay = 0.25;
645 if(!self.flock_id) self.flock_id = globflockcnt;
647 self.think = flockerspawn_think;
648 self.nextthink = time + 0.25;
650 self.enemy = spawn();
652 setmodel(self.enemy, "models/turrets/rocket.md3");
653 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
655 self.enemy.classname = "FLock Hunter";
656 self.enemy.scale = 3;
657 self.enemy.effects = EF_LOWPRECISION;
658 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
659 PROJECTILE_MAKETRIGGER(self.enemy);
660 self.enemy.think = flocker_hunter_think;
661 self.enemy.nextthink = time + 10;
662 self.enemy.flock_id = self.flock_id;
663 self.enemy.owner = self;