7 Uniform pull towards a point
9 vector steerlib_pull(vector point)
11 return normalize(point - self.origin);
15 Uniform push from a point
17 #define steerlib_push(point) normalize(self.origin - point)
19 vector steerlib_push(vector point)
21 return normalize(self.origin - point);
25 Pull toward a point, The further away, the stronger the pull.
27 vector steerlib_arrive(vector point,float maximal_distance)
32 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
33 direction = normalize(point - self.origin);
34 return direction * (distance / maximal_distance);
38 Pull toward a point increasing the pull the closer we get
40 vector steerlib_attract(vector point, float maximal_distance)
45 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
46 direction = normalize(point - self.origin);
48 return direction * (1-(distance / maximal_distance));
51 vector steerlib_attract2(entity this, vector point, float min_influense,float max_distance,float max_influense)
57 distance = bound(0.00001,vlen(this.origin - point),max_distance);
58 direction = normalize(point - this.origin);
60 influense = 1 - (distance / max_distance);
61 influense = min_influense + (influense * (max_influense - min_influense));
63 return direction * influense;
67 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
70 vector current_direction;
71 vector target_direction;
72 float i_target,i_current;
75 distance = vlen(self.origin - point);
77 distance = bound(0.001,distance,maximal_distance);
79 target_direction = normalize(point - self.origin);
80 current_direction = normalize(self.velocity);
82 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
83 i_current = 1 - i_target;
85 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
89 bprint("IT: ",s,"\n");
91 bprint("IC : ",s,"\n");
93 return normalize((target_direction * i_target) + (current_direction * i_current));
97 Move away from a point.
99 vector steerlib_repell(vector point,float maximal_distance)
104 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
105 direction = normalize(self.origin - point);
107 return direction * (1-(distance / maximal_distance));
111 Try to keep at ideal_distance away from point
113 vector steerlib_standoff(vector point,float ideal_distance)
118 distance = vlen(self.origin - point);
121 if(distance < ideal_distance)
123 direction = normalize(self.origin - point);
124 return direction * (distance / ideal_distance);
127 direction = normalize(point - self.origin);
128 return direction * (ideal_distance / distance);
133 A random heading in a forward halfcicrle
136 self.target = steerlib_wander(256,32,self.target)
138 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
140 vector steerlib_wander(float range,float tresh,vector oldpoint)
143 wander_point = v_forward - oldpoint;
145 if (vlen(wander_point) > tresh)
148 range = bound(0,range,1);
150 wander_point = self.origin + v_forward * 128;
151 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
153 return normalize(wander_point - self.origin);
157 Dodge a point. dont work to well.
159 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
163 distance = max(vlen(self.origin - point),min_distance);
164 if (min_distance < distance)
167 return dodge_dir * (min_distance/distance);
171 flocking by .flock_id
172 Group will move towards the unified direction while keeping close to eachother.
175 vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
178 vector push = '0 0 0', pull = '0 0 0';
181 flock_member = findradius(self.origin, _radius);
184 if(flock_member != self)
185 if(flock_member.flock_id == self.flock_id)
188 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
189 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
191 flock_member = flock_member.chain;
193 return push + (pull* (1 / ccount));
197 flocking by .flock_id
198 Group will move towards the unified direction while keeping close to eachother.
199 xy only version (for ground movers).
201 vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
204 vector push = '0 0 0', pull = '0 0 0';
207 flock_member = findradius(self.origin,_radius);
210 if(flock_member != self)
211 if(flock_member.flock_id == self.flock_id)
214 push = push + (steerlib_repell(flock_member.origin, standoff) * separation_force);
215 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
217 flock_member = flock_member.chain;
223 return push + (pull * (1 / ccount));
227 All members want to be in the center, and keep away from eachother.
228 The furtehr form the center the more they want to be there.
230 This results in a aligned movement (?!) much like flocking.
232 vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
235 vector force = '0 0 0', center = '0 0 0';
238 swarm_member = findradius(self.origin,_radius);
242 if(swarm_member.flock_id == self.flock_id)
245 center = center + swarm_member.origin;
246 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
248 swarm_member = swarm_member.chain;
251 center = center * (1 / ccount);
252 force = force + (steerlib_arrive(center,_radius) * swarm_force);
258 Steer towards the direction least obstructed.
259 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
260 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
262 vector steerlib_traceavoid(float pitch,float length)
264 vector vup_left,vup_right,vdown_left,vdown_right;
265 float fup_left,fup_right,fdown_left,fdown_right;
266 vector upwish,downwish,leftwish,rightwish;
267 vector v_left,v_down;
270 v_left = v_right * -1;
273 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
274 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
275 fup_left = trace_fraction;
277 //te_lightning1(world,self.origin, trace_endpos);
279 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
280 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
281 fup_right = trace_fraction;
283 //te_lightning1(world,self.origin, trace_endpos);
285 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
286 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
287 fdown_left = trace_fraction;
289 //te_lightning1(world,self.origin, trace_endpos);
291 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
292 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
293 fdown_right = trace_fraction;
295 //te_lightning1(world,self.origin, trace_endpos);
296 upwish = v_up * (fup_left + fup_right);
297 downwish = v_down * (fdown_left + fdown_right);
298 leftwish = v_left * (fup_left + fdown_left);
299 rightwish = v_right * (fup_right + fdown_right);
301 return (upwish+leftwish+downwish+rightwish) * 0.25;
306 Steer towards the direction least obstructed.
307 Run tracelines in a forward trident, bias each direction negative if something is found there.
309 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
311 vector vt_left, vt_right,vt_front;
312 float f_left, f_right,f_front;
313 vector leftwish, rightwish,frontwish, v_left;
315 v_left = v_right * -1;
318 vt_front = v_forward * length;
319 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
320 f_front = trace_fraction;
322 vt_left = (v_forward + (v_left * pitch)) * length;
323 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
324 f_left = trace_fraction;
326 //te_lightning1(world,self.origin, trace_endpos);
328 vt_right = (v_forward + (v_right * pitch)) * length;
329 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
330 f_right = trace_fraction;
332 //te_lightning1(world,self.origin, trace_endpos);
334 leftwish = v_left * f_left;
335 rightwish = v_right * f_right;
336 frontwish = v_forward * f_front;
338 return normalize(leftwish + rightwish + frontwish);
341 float beamsweep_badpoint(vector point,float waterok)
345 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
348 pc = pointcontents(point);
349 pc2 = pointcontents(point - '0 0 1');
353 case CONTENT_SOLID: break;
354 case CONTENT_SLIME: break;
355 case CONTENT_LAVA: break;
361 if (pc2 == CONTENT_SOLID)
364 if (pc2 == CONTENT_WATER)
380 //#define BEAMSTEER_VISUAL
381 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
386 u = '0 0 1' * step_up;
387 d = '0 0 1' * step_down;
389 traceline(from + u, from - d,MOVE_NORMAL,self);
390 if(trace_fraction == 1.0)
393 if(beamsweep_badpoint(trace_endpos,0))
397 for(i = 0; i < length; i += step)
401 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
402 if(trace_fraction != 1.0)
405 traceline(b + u, b - d,MOVE_NORMAL,self);
406 if(trace_fraction == 1.0)
409 if(beamsweep_badpoint(trace_endpos,0))
411 #ifdef BEAMSTEER_VISUAL
412 te_lightning1(world,a+u,b+u);
413 te_lightning1(world,b+u,b-d);
421 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
423 float bm_forward, bm_right, bm_left,p;
427 vr = vectoangles(dir);
430 tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self);
431 if(trace_fraction == 1.0)
433 //te_lightning1(self,self.origin,self.origin + (dir * length));
441 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
443 vr = normalize(v_forward + v_right * 0.125);
444 vl = normalize(v_forward - v_right * 0.125);
446 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
447 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
450 p = bm_left + bm_right;
453 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
454 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
461 vr = normalize(v_forward + v_right * p);
462 vl = normalize(v_forward - v_right * p);
463 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
464 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
467 if(bm_left + bm_right < 0.15)
469 vr = normalize((v_forward*-1) + v_right * 0.75);
470 vl = normalize((v_forward*-1) - v_right * 0.75);
472 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
473 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
476 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
477 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
479 bm_forward *= bm_forward;
480 bm_right *= bm_right;
486 return normalize(vr + vl);
491 //////////////////////////////////////////////
493 // Everything below this point is a mess :D //
494 //////////////////////////////////////////////
495 //#define TLIBS_TETSLIBS
496 #ifdef TLIBS_TETSLIBS
499 Send_Effect(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
504 self.nextthink = time;
505 self.think = SUB_Remove;
511 vector dodgemove,swarmmove;
512 vector reprellmove,wandermove,newmove;
514 self.angles_x = self.angles.x * -1;
515 makevectors(self.angles);
516 self.angles_x = self.angles.x * -1;
518 dodgemove = steerlib_traceavoid(0.35,1000);
519 swarmmove = steerlib_flock(500,75,700,500);
520 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
522 if(vlen(dodgemove) == 0)
524 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
525 wandermove = self.pos1 * 50;
528 self.pos1 = normalize(self.velocity);
530 dodgemove = dodgemove * vlen(self.velocity) * 5;
532 newmove = swarmmove + reprellmove + wandermove + dodgemove;
533 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
534 //self.velocity = movelib_inertmove(dodgemove,0.65);
536 self.velocity = movelib_dragvec(0.01,0.6);
538 self.angles = vectoangles(self.velocity);
543 self.nextthink = time + 0.1;
546 MODEL(FLOCKER, "models/turrets/rocket.md3");
550 entity flocker = new(flocker);
552 setorigin(flocker, self.origin + '0 0 32');
553 setmodel (flocker, MDL_FLOCKER);
554 setsize (flocker, '-3 -3 -3', '3 3 3');
556 flocker.flock_id = self.flock_id;
557 flocker.owner = self;
558 flocker.think = flocker_think;
559 flocker.nextthink = time + random() * 5;
560 PROJECTILE_MAKETRIGGER(flocker);
561 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
562 flocker.effects = EF_LOWPRECISION;
563 flocker.velocity = randomvec() * 300;
564 flocker.angles = vectoangles(flocker.velocity);
566 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
568 self.cnt = self.cnt -1;
572 void flockerspawn_think()
579 self.nextthink = time + self.delay;
583 void flocker_hunter_think()
585 vector dodgemove,attractmove,newmove;
589 self.angles_x = self.angles.x * -1;
590 makevectors(self.angles);
591 self.angles_x = self.angles.x * -1;
594 if(vdist(self.enemy.origin - self.origin, <, 64))
604 e = findchainfloat(flock_id,self.flock_id);
607 d = vlen(self.origin - e.origin);
621 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
623 attractmove = normalize(self.velocity) * 200;
625 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
627 newmove = dodgemove + attractmove;
628 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
629 self.velocity = movelib_dragvec(0.01,0.5);
632 self.angles = vectoangles(self.velocity);
633 self.nextthink = time + 0.1;
638 spawnfunc(flockerspawn)
642 if(!self.cnt) self.cnt = 20;
643 if(!self.delay) self.delay = 0.25;
644 if(!self.flock_id) self.flock_id = globflockcnt;
646 self.think = flockerspawn_think;
647 self.nextthink = time + 0.25;
649 self.enemy = new(FLock Hunter);
651 setmodel(self.enemy, MDL_FLOCKER);
652 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
654 self.enemy.scale = 3;
655 self.enemy.effects = EF_LOWPRECISION;
656 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
657 PROJECTILE_MAKETRIGGER(self.enemy);
658 self.enemy.think = flocker_hunter_think;
659 self.enemy.nextthink = time + 10;
660 self.enemy.flock_id = self.flock_id;
661 self.enemy.owner = self;