2 Uniform pull towards a point
4 vector steerlib_pull(vector point)
6 return normalize(point - self.origin);
10 Uniform push from a point
12 #define steerlib_push(point) normalize(self.origin - point)
14 vector steerlib_push(vector point)
16 return normalize(self.origin - point);
20 Pull toward a point, The further away, the stronger the pull.
22 vector steerlib_arrive(vector point,float maximal_distance)
27 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
28 direction = normalize(point - self.origin);
29 return direction * (distance / maximal_distance);
33 Pull toward a point increasing the pull the closer we get
35 vector steerlib_attract(vector point, float maximal_distance)
40 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
41 direction = normalize(point - self.origin);
43 return direction * (1-(distance / maximal_distance));
46 vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
52 distance = bound(0.00001,vlen(self.origin - point),max_distance);
53 direction = normalize(point - self.origin);
55 influense = 1 - (distance / max_distance);
56 influense = min_influense + (influense * (max_influense - min_influense));
58 return direction * influense;
62 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
65 vector current_direction;
66 vector target_direction;
67 float i_target,i_current;
70 distance = vlen(self.origin - point);
72 distance = bound(0.001,distance,maximal_distance);
74 target_direction = normalize(point - self.origin);
75 current_direction = normalize(self.velocity);
77 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
78 i_current = 1 - i_target;
80 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
84 bprint("IT: ",s,"\n");
86 bprint("IC : ",s,"\n");
88 return normalize((target_direction * i_target) + (current_direction * i_current));
92 Move away from a point.
94 vector steerlib_repell(vector point,float maximal_distance)
99 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
100 direction = normalize(self.origin - point);
102 return direction * (1-(distance / maximal_distance));
106 Try to keep at ideal_distance away from point
108 vector steerlib_standoff(vector point,float ideal_distance)
113 distance = vlen(self.origin - point);
116 if(distance < ideal_distance)
118 direction = normalize(self.origin - point);
119 return direction * (distance / ideal_distance);
122 direction = normalize(point - self.origin);
123 return direction * (ideal_distance / distance);
128 A random heading in a forward halfcicrle
131 self.target = steerlib_wander(256,32,self.target)
133 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
135 vector steerlib_wander(float range,float tresh,vector oldpoint)
138 wander_point = v_forward - oldpoint;
140 if (vlen(wander_point) > tresh)
143 range = bound(0,range,1);
145 wander_point = self.origin + v_forward * 128;
146 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
148 return normalize(wander_point - self.origin);
152 Dodge a point. dont work to well.
154 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
158 distance = max(vlen(self.origin - point),min_distance);
159 if (min_distance < distance)
162 return dodge_dir * (min_distance/distance);
166 flocking by .flock_id
167 Group will move towards the unified direction while keeping close to eachother.
170 vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
173 vector push = '0 0 0', pull = '0 0 0';
176 flock_member = findradius(self.origin, _radius);
179 if(flock_member != self)
180 if(flock_member.flock_id == self.flock_id)
183 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
184 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
186 flock_member = flock_member.chain;
188 return push + (pull* (1 / ccount));
192 flocking by .flock_id
193 Group will move towards the unified direction while keeping close to eachother.
194 xy only version (for ground movers).
196 vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
199 vector push = '0 0 0', pull = '0 0 0';
202 flock_member = findradius(self.origin,_radius);
205 if(flock_member != self)
206 if(flock_member.flock_id == self.flock_id)
209 push = push + (steerlib_repell(flock_member.origin, standoff) * separation_force);
210 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
212 flock_member = flock_member.chain;
218 return push + (pull * (1 / ccount));
222 All members want to be in the center, and keep away from eachother.
223 The furtehr form the center the more they want to be there.
225 This results in a aligned movement (?!) much like flocking.
227 vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
230 vector force = '0 0 0', center = '0 0 0';
233 swarm_member = findradius(self.origin,_radius);
237 if(swarm_member.flock_id == self.flock_id)
240 center = center + swarm_member.origin;
241 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
243 swarm_member = swarm_member.chain;
246 center = center * (1 / ccount);
247 force = force + (steerlib_arrive(center,_radius) * swarm_force);
253 Steer towards the direction least obstructed.
254 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
255 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
257 vector steerlib_traceavoid(float pitch,float length)
259 vector vup_left,vup_right,vdown_left,vdown_right;
260 float fup_left,fup_right,fdown_left,fdown_right;
261 vector upwish,downwish,leftwish,rightwish;
262 vector v_left,v_down;
265 v_left = v_right * -1;
268 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
269 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
270 fup_left = trace_fraction;
272 //te_lightning1(world,self.origin, trace_endpos);
274 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
275 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
276 fup_right = trace_fraction;
278 //te_lightning1(world,self.origin, trace_endpos);
280 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
281 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
282 fdown_left = trace_fraction;
284 //te_lightning1(world,self.origin, trace_endpos);
286 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
287 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
288 fdown_right = trace_fraction;
290 //te_lightning1(world,self.origin, trace_endpos);
291 upwish = v_up * (fup_left + fup_right);
292 downwish = v_down * (fdown_left + fdown_right);
293 leftwish = v_left * (fup_left + fdown_left);
294 rightwish = v_right * (fup_right + fdown_right);
296 return (upwish+leftwish+downwish+rightwish) * 0.25;
301 Steer towards the direction least obstructed.
302 Run tracelines in a forward trident, bias each direction negative if something is found there.
304 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
306 vector vt_left, vt_right,vt_front;
307 float f_left, f_right,f_front;
308 vector leftwish, rightwish,frontwish, v_left;
310 v_left = v_right * -1;
313 vt_front = v_forward * length;
314 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
315 f_front = trace_fraction;
317 vt_left = (v_forward + (v_left * pitch)) * length;
318 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
319 f_left = trace_fraction;
321 //te_lightning1(world,self.origin, trace_endpos);
323 vt_right = (v_forward + (v_right * pitch)) * length;
324 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
325 f_right = trace_fraction;
327 //te_lightning1(world,self.origin, trace_endpos);
329 leftwish = v_left * f_left;
330 rightwish = v_right * f_right;
331 frontwish = v_forward * f_front;
333 return normalize(leftwish + rightwish + frontwish);
336 float beamsweep_badpoint(vector point,float waterok)
340 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
343 pc = pointcontents(point);
344 pc2 = pointcontents(point - '0 0 1');
348 case CONTENT_SOLID: break;
349 case CONTENT_SLIME: break;
350 case CONTENT_LAVA: break;
356 if (pc2 == CONTENT_SOLID)
359 if (pc2 == CONTENT_WATER)
375 //#define BEAMSTEER_VISUAL
376 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
381 u = '0 0 1' * step_up;
382 d = '0 0 1' * step_down;
384 traceline(from + u, from - d,MOVE_NORMAL,self);
385 if(trace_fraction == 1.0)
388 if(beamsweep_badpoint(trace_endpos,0))
392 for(i = 0; i < length; i += step)
396 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
397 if(trace_fraction != 1.0)
400 traceline(b + u, b - d,MOVE_NORMAL,self);
401 if(trace_fraction == 1.0)
404 if(beamsweep_badpoint(trace_endpos,0))
406 #ifdef BEAMSTEER_VISUAL
407 te_lightning1(world,a+u,b+u);
408 te_lightning1(world,b+u,b-d);
416 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
418 float bm_forward, bm_right, bm_left,p;
422 vr = vectoangles(dir);
425 tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self);
426 if(trace_fraction == 1.0)
428 //te_lightning1(self,self.origin,self.origin + (dir * length));
436 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
438 vr = normalize(v_forward + v_right * 0.125);
439 vl = normalize(v_forward - v_right * 0.125);
441 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
442 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
445 p = bm_left + bm_right;
448 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
449 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
456 vr = normalize(v_forward + v_right * p);
457 vl = normalize(v_forward - v_right * p);
458 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
459 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
462 if(bm_left + bm_right < 0.15)
464 vr = normalize((v_forward*-1) + v_right * 0.75);
465 vl = normalize((v_forward*-1) - v_right * 0.75);
467 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
468 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
471 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
472 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
474 bm_forward *= bm_forward;
475 bm_right *= bm_right;
481 return normalize(vr + vl);
486 //////////////////////////////////////////////
488 // Everything below this point is a mess :D //
489 //////////////////////////////////////////////
490 //#define TLIBS_TETSLIBS
491 #ifdef TLIBS_TETSLIBS
494 Send_Effect(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
499 self.nextthink = time;
500 self.think = SUB_Remove;
506 vector dodgemove,swarmmove;
507 vector reprellmove,wandermove,newmove;
509 self.angles_x = self.angles.x * -1;
510 makevectors(self.angles);
511 self.angles_x = self.angles.x * -1;
513 dodgemove = steerlib_traceavoid(0.35,1000);
514 swarmmove = steerlib_flock(500,75,700,500);
515 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
517 if(vlen(dodgemove) == 0)
519 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
520 wandermove = self.pos1 * 50;
523 self.pos1 = normalize(self.velocity);
525 dodgemove = dodgemove * vlen(self.velocity) * 5;
527 newmove = swarmmove + reprellmove + wandermove + dodgemove;
528 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
529 //self.velocity = movelib_inertmove(dodgemove,0.65);
531 self.velocity = movelib_dragvec(0.01,0.6);
533 self.angles = vectoangles(self.velocity);
538 self.nextthink = time + 0.1;
541 MODEL(FLOCKER, "models/turrets/rocket.md3");
549 setorigin(flocker, self.origin + '0 0 32');
550 setmodel (flocker, MDL_FLOCKER);
551 setsize (flocker, '-3 -3 -3', '3 3 3');
553 flocker.flock_id = self.flock_id;
554 flocker.classname = "flocker";
555 flocker.owner = self;
556 flocker.think = flocker_think;
557 flocker.nextthink = time + random() * 5;
558 PROJECTILE_MAKETRIGGER(flocker);
559 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
560 flocker.effects = EF_LOWPRECISION;
561 flocker.velocity = randomvec() * 300;
562 flocker.angles = vectoangles(flocker.velocity);
564 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
566 self.cnt = self.cnt -1;
570 void flockerspawn_think()
577 self.nextthink = time + self.delay;
581 void flocker_hunter_think()
583 vector dodgemove,attractmove,newmove;
587 self.angles_x = self.angles.x * -1;
588 makevectors(self.angles);
589 self.angles_x = self.angles.x * -1;
592 if(vlen(self.enemy.origin - self.origin) < 64)
602 e = findchainfloat(flock_id,self.flock_id);
605 d = vlen(self.origin - e.origin);
619 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
621 attractmove = normalize(self.velocity) * 200;
623 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
625 newmove = dodgemove + attractmove;
626 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
627 self.velocity = movelib_dragvec(0.01,0.5);
630 self.angles = vectoangles(self.velocity);
631 self.nextthink = time + 0.1;
636 spawnfunc(flockerspawn)
640 if(!self.cnt) self.cnt = 20;
641 if(!self.delay) self.delay = 0.25;
642 if(!self.flock_id) self.flock_id = globflockcnt;
644 self.think = flockerspawn_think;
645 self.nextthink = time + 0.25;
647 self.enemy = spawn();
649 setmodel(self.enemy, MDL_FLOCKER);
650 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
652 self.enemy.classname = "FLock Hunter";
653 self.enemy.scale = 3;
654 self.enemy.effects = EF_LOWPRECISION;
655 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
656 PROJECTILE_MAKETRIGGER(self.enemy);
657 self.enemy.think = flocker_hunter_think;
658 self.enemy.nextthink = time + 10;
659 self.enemy.flock_id = self.flock_id;
660 self.enemy.owner = self;