8 Uniform pull towards a point
10 vector steerlib_pull(vector point)
12 return normalize(point - self.origin);
16 Uniform push from a point
18 #define steerlib_push(point) normalize(self.origin - point)
20 vector steerlib_push(vector point)
22 return normalize(self.origin - point);
26 Pull toward a point, The further away, the stronger the pull.
28 vector steerlib_arrive(vector point,float maximal_distance)
33 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
34 direction = normalize(point - self.origin);
35 return direction * (distance / maximal_distance);
39 Pull toward a point increasing the pull the closer we get
41 vector steerlib_attract(vector point, float maximal_distance)
46 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
47 direction = normalize(point - self.origin);
49 return direction * (1-(distance / maximal_distance));
52 vector steerlib_attract2(entity this, vector point, float min_influense,float max_distance,float max_influense)
58 distance = bound(0.00001,vlen(this.origin - point),max_distance);
59 direction = normalize(point - this.origin);
61 influense = 1 - (distance / max_distance);
62 influense = min_influense + (influense * (max_influense - min_influense));
64 return direction * influense;
68 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
71 vector current_direction;
72 vector target_direction;
73 float i_target,i_current;
76 distance = vlen(self.origin - point);
78 distance = bound(0.001,distance,maximal_distance);
80 target_direction = normalize(point - self.origin);
81 current_direction = normalize(self.velocity);
83 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
84 i_current = 1 - i_target;
86 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
90 bprint("IT: ",s,"\n");
92 bprint("IC : ",s,"\n");
94 return normalize((target_direction * i_target) + (current_direction * i_current));
98 Move away from a point.
100 vector steerlib_repell(vector point,float maximal_distance)
105 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
106 direction = normalize(self.origin - point);
108 return direction * (1-(distance / maximal_distance));
112 Try to keep at ideal_distance away from point
114 vector steerlib_standoff(vector point,float ideal_distance)
119 distance = vlen(self.origin - point);
122 if(distance < ideal_distance)
124 direction = normalize(self.origin - point);
125 return direction * (distance / ideal_distance);
128 direction = normalize(point - self.origin);
129 return direction * (ideal_distance / distance);
134 A random heading in a forward halfcicrle
137 self.target = steerlib_wander(256,32,self.target)
139 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
141 vector steerlib_wander(float range,float tresh,vector oldpoint)
144 wander_point = v_forward - oldpoint;
146 if (vlen(wander_point) > tresh)
149 range = bound(0,range,1);
151 wander_point = self.origin + v_forward * 128;
152 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
154 return normalize(wander_point - self.origin);
158 Dodge a point. dont work to well.
160 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
164 distance = max(vlen(self.origin - point),min_distance);
165 if (min_distance < distance)
168 return dodge_dir * (min_distance/distance);
172 flocking by .flock_id
173 Group will move towards the unified direction while keeping close to eachother.
176 vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
179 vector push = '0 0 0', pull = '0 0 0';
182 flock_member = findradius(self.origin, _radius);
185 if(flock_member != self)
186 if(flock_member.flock_id == self.flock_id)
189 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
190 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
192 flock_member = flock_member.chain;
194 return push + (pull* (1 / ccount));
198 flocking by .flock_id
199 Group will move towards the unified direction while keeping close to eachother.
200 xy only version (for ground movers).
202 vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
205 vector push = '0 0 0', pull = '0 0 0';
208 flock_member = findradius(self.origin,_radius);
211 if(flock_member != self)
212 if(flock_member.flock_id == self.flock_id)
215 push = push + (steerlib_repell(flock_member.origin, standoff) * separation_force);
216 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
218 flock_member = flock_member.chain;
224 return push + (pull * (1 / ccount));
228 All members want to be in the center, and keep away from eachother.
229 The furtehr form the center the more they want to be there.
231 This results in a aligned movement (?!) much like flocking.
233 vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
236 vector force = '0 0 0', center = '0 0 0';
239 swarm_member = findradius(self.origin,_radius);
243 if(swarm_member.flock_id == self.flock_id)
246 center = center + swarm_member.origin;
247 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
249 swarm_member = swarm_member.chain;
252 center = center * (1 / ccount);
253 force = force + (steerlib_arrive(center,_radius) * swarm_force);
259 Steer towards the direction least obstructed.
260 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
261 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
263 vector steerlib_traceavoid(float pitch,float length)
265 vector vup_left,vup_right,vdown_left,vdown_right;
266 float fup_left,fup_right,fdown_left,fdown_right;
267 vector upwish,downwish,leftwish,rightwish;
268 vector v_left,v_down;
271 v_left = v_right * -1;
274 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
275 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
276 fup_left = trace_fraction;
278 //te_lightning1(world,self.origin, trace_endpos);
280 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
281 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
282 fup_right = trace_fraction;
284 //te_lightning1(world,self.origin, trace_endpos);
286 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
287 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
288 fdown_left = trace_fraction;
290 //te_lightning1(world,self.origin, trace_endpos);
292 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
293 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
294 fdown_right = trace_fraction;
296 //te_lightning1(world,self.origin, trace_endpos);
297 upwish = v_up * (fup_left + fup_right);
298 downwish = v_down * (fdown_left + fdown_right);
299 leftwish = v_left * (fup_left + fdown_left);
300 rightwish = v_right * (fup_right + fdown_right);
302 return (upwish+leftwish+downwish+rightwish) * 0.25;
307 Steer towards the direction least obstructed.
308 Run tracelines in a forward trident, bias each direction negative if something is found there.
310 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
312 vector vt_left, vt_right,vt_front;
313 float f_left, f_right,f_front;
314 vector leftwish, rightwish,frontwish, v_left;
316 v_left = v_right * -1;
319 vt_front = v_forward * length;
320 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
321 f_front = trace_fraction;
323 vt_left = (v_forward + (v_left * pitch)) * length;
324 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
325 f_left = trace_fraction;
327 //te_lightning1(world,self.origin, trace_endpos);
329 vt_right = (v_forward + (v_right * pitch)) * length;
330 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
331 f_right = trace_fraction;
333 //te_lightning1(world,self.origin, trace_endpos);
335 leftwish = v_left * f_left;
336 rightwish = v_right * f_right;
337 frontwish = v_forward * f_front;
339 return normalize(leftwish + rightwish + frontwish);
342 float beamsweep_badpoint(vector point,float waterok)
346 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
349 pc = pointcontents(point);
350 pc2 = pointcontents(point - '0 0 1');
354 case CONTENT_SOLID: break;
355 case CONTENT_SLIME: break;
356 case CONTENT_LAVA: break;
362 if (pc2 == CONTENT_SOLID)
365 if (pc2 == CONTENT_WATER)
381 //#define BEAMSTEER_VISUAL
382 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
387 u = '0 0 1' * step_up;
388 d = '0 0 1' * step_down;
390 traceline(from + u, from - d,MOVE_NORMAL,self);
391 if(trace_fraction == 1.0)
394 if(beamsweep_badpoint(trace_endpos,0))
398 for(i = 0; i < length; i += step)
402 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
403 if(trace_fraction != 1.0)
406 traceline(b + u, b - d,MOVE_NORMAL,self);
407 if(trace_fraction == 1.0)
410 if(beamsweep_badpoint(trace_endpos,0))
412 #ifdef BEAMSTEER_VISUAL
413 te_lightning1(world,a+u,b+u);
414 te_lightning1(world,b+u,b-d);
422 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
424 float bm_forward, bm_right, bm_left,p;
428 vr = vectoangles(dir);
431 tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self);
432 if(trace_fraction == 1.0)
434 //te_lightning1(self,self.origin,self.origin + (dir * length));
442 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
444 vr = normalize(v_forward + v_right * 0.125);
445 vl = normalize(v_forward - v_right * 0.125);
447 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
448 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
451 p = bm_left + bm_right;
454 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
455 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
462 vr = normalize(v_forward + v_right * p);
463 vl = normalize(v_forward - v_right * p);
464 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
465 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
468 if(bm_left + bm_right < 0.15)
470 vr = normalize((v_forward*-1) + v_right * 0.75);
471 vl = normalize((v_forward*-1) - v_right * 0.75);
473 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
474 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
477 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
478 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
480 bm_forward *= bm_forward;
481 bm_right *= bm_right;
487 return normalize(vr + vl);
492 //////////////////////////////////////////////
494 // Everything below this point is a mess :D //
495 //////////////////////////////////////////////
496 //#define TLIBS_TETSLIBS
497 #ifdef TLIBS_TETSLIBS
500 Send_Effect(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
505 self.nextthink = time;
506 self.think = SUB_Remove;
512 vector dodgemove,swarmmove;
513 vector reprellmove,wandermove,newmove;
515 self.angles_x = self.angles.x * -1;
516 makevectors(self.angles);
517 self.angles_x = self.angles.x * -1;
519 dodgemove = steerlib_traceavoid(0.35,1000);
520 swarmmove = steerlib_flock(500,75,700,500);
521 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
523 if(vlen(dodgemove) == 0)
525 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
526 wandermove = self.pos1 * 50;
529 self.pos1 = normalize(self.velocity);
531 dodgemove = dodgemove * vlen(self.velocity) * 5;
533 newmove = swarmmove + reprellmove + wandermove + dodgemove;
534 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
535 //self.velocity = movelib_inertmove(dodgemove,0.65);
537 self.velocity = movelib_dragvec(0.01,0.6);
539 self.angles = vectoangles(self.velocity);
544 self.nextthink = time + 0.1;
547 MODEL(FLOCKER, "models/turrets/rocket.md3");
551 entity flocker = new(flocker);
553 setorigin(flocker, self.origin + '0 0 32');
554 setmodel (flocker, MDL_FLOCKER);
555 setsize (flocker, '-3 -3 -3', '3 3 3');
557 flocker.flock_id = self.flock_id;
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(vdist(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 spawnfunc(flockerspawn)
643 if(!this.cnt) this.cnt = 20;
644 if(!this.delay) this.delay = 0.25;
645 if(!this.flock_id) this.flock_id = globflockcnt;
647 this.think = flockerspawn_think;
648 this.nextthink = time + 0.25;
650 this.enemy = new(FLock Hunter);
652 setmodel(this.enemy, MDL_FLOCKER);
653 setorigin(this.enemy,this.origin + '0 0 768' + (randomvec() * 128));
655 this.enemy.scale = 3;
656 this.enemy.effects = EF_LOWPRECISION;
657 this.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
658 PROJECTILE_MAKETRIGGER(this.enemy);
659 this.enemy.think = flocker_hunter_think;
660 this.enemy.nextthink = time + 10;
661 this.enemy.flock_id = this.flock_id;
662 this.enemy.owner = this;