4 #include "../dpdefs/progsdefs.qh"
5 #include "../dpdefs/dpextensions.qh"
9 Uniform pull towards a point
11 vector steerlib_pull(vector point)
13 return normalize(point - self.origin);
17 Uniform push from a point
19 #define steerlib_push(point) normalize(self.origin - point)
21 vector steerlib_push(vector point)
23 return normalize(self.origin - point);
27 Pull toward a point, The further away, the stronger the pull.
29 vector steerlib_arrive(vector point,float maximal_distance)
34 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
35 direction = normalize(point - self.origin);
36 return direction * (distance / maximal_distance);
40 Pull toward a point increasing the pull the closer we get
42 vector steerlib_attract(vector point, float maximal_distance)
47 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
48 direction = normalize(point - self.origin);
50 return direction * (1-(distance / maximal_distance));
53 vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
59 distance = bound(0.00001,vlen(self.origin - point),max_distance);
60 direction = normalize(point - self.origin);
62 influense = 1 - (distance / max_distance);
63 influense = min_influense + (influense * (max_influense - min_influense));
65 return direction * influense;
69 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
72 vector current_direction;
73 vector target_direction;
74 float i_target,i_current;
77 distance = vlen(self.origin - point);
79 distance = bound(0.001,distance,maximal_distance);
81 target_direction = normalize(point - self.origin);
82 current_direction = normalize(self.velocity);
84 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
85 i_current = 1 - i_target;
87 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
91 bprint("IT: ",s,"\n");
93 bprint("IC : ",s,"\n");
95 return normalize((target_direction * i_target) + (current_direction * i_current));
99 Move away from a point.
101 vector steerlib_repell(vector point,float maximal_distance)
106 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
107 direction = normalize(self.origin - point);
109 return direction * (1-(distance / maximal_distance));
113 Try to keep at ideal_distance away from point
115 vector steerlib_standoff(vector point,float ideal_distance)
120 distance = vlen(self.origin - point);
123 if(distance < ideal_distance)
125 direction = normalize(self.origin - point);
126 return direction * (distance / ideal_distance);
129 direction = normalize(point - self.origin);
130 return direction * (ideal_distance / distance);
135 A random heading in a forward halfcicrle
138 self.target = steerlib_wander(256,32,self.target)
140 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
142 vector steerlib_wander(float range,float tresh,vector oldpoint)
145 wander_point = v_forward - oldpoint;
147 if (vlen(wander_point) > tresh)
150 range = bound(0,range,1);
152 wander_point = self.origin + v_forward * 128;
153 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
155 return normalize(wander_point - self.origin);
159 Dodge a point. dont work to well.
161 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
165 distance = max(vlen(self.origin - point),min_distance);
166 if (min_distance < distance)
169 return dodge_dir * (min_distance/distance);
173 flocking by .flock_id
174 Group will move towards the unified direction while keeping close to eachother.
177 vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
180 vector push = '0 0 0', pull = '0 0 0';
183 flock_member = findradius(self.origin, _radius);
186 if(flock_member != self)
187 if(flock_member.flock_id == self.flock_id)
190 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
191 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
193 flock_member = flock_member.chain;
195 return push + (pull* (1 / ccount));
199 flocking by .flock_id
200 Group will move towards the unified direction while keeping close to eachother.
201 xy only version (for ground movers).
203 vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
206 vector push = '0 0 0', pull = '0 0 0';
209 flock_member = findradius(self.origin,_radius);
212 if(flock_member != self)
213 if(flock_member.flock_id == self.flock_id)
216 push = push + (steerlib_repell(flock_member.origin, standoff) * separation_force);
217 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
219 flock_member = flock_member.chain;
225 return push + (pull * (1 / ccount));
229 All members want to be in the center, and keep away from eachother.
230 The furtehr form the center the more they want to be there.
232 This results in a aligned movement (?!) much like flocking.
234 vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
237 vector force = '0 0 0', center = '0 0 0';
240 swarm_member = findradius(self.origin,_radius);
244 if(swarm_member.flock_id == self.flock_id)
247 center = center + swarm_member.origin;
248 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
250 swarm_member = swarm_member.chain;
253 center = center * (1 / ccount);
254 force = force + (steerlib_arrive(center,_radius) * swarm_force);
260 Steer towards the direction least obstructed.
261 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
262 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
264 vector steerlib_traceavoid(float pitch,float length)
266 vector vup_left,vup_right,vdown_left,vdown_right;
267 float fup_left,fup_right,fdown_left,fdown_right;
268 vector upwish,downwish,leftwish,rightwish;
269 vector v_left,v_down;
272 v_left = v_right * -1;
275 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
276 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
277 fup_left = trace_fraction;
279 //te_lightning1(world,self.origin, trace_endpos);
281 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
282 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
283 fup_right = trace_fraction;
285 //te_lightning1(world,self.origin, trace_endpos);
287 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
288 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
289 fdown_left = trace_fraction;
291 //te_lightning1(world,self.origin, trace_endpos);
293 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
294 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
295 fdown_right = trace_fraction;
297 //te_lightning1(world,self.origin, trace_endpos);
298 upwish = v_up * (fup_left + fup_right);
299 downwish = v_down * (fdown_left + fdown_right);
300 leftwish = v_left * (fup_left + fdown_left);
301 rightwish = v_right * (fup_right + fdown_right);
303 return (upwish+leftwish+downwish+rightwish) * 0.25;
308 Steer towards the direction least obstructed.
309 Run tracelines in a forward trident, bias each direction negative if something is found there.
311 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
313 vector vt_left, vt_right,vt_front;
314 float f_left, f_right,f_front;
315 vector leftwish, rightwish,frontwish, v_left;
317 v_left = v_right * -1;
320 vt_front = v_forward * length;
321 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
322 f_front = trace_fraction;
324 vt_left = (v_forward + (v_left * pitch)) * length;
325 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
326 f_left = trace_fraction;
328 //te_lightning1(world,self.origin, trace_endpos);
330 vt_right = (v_forward + (v_right * pitch)) * length;
331 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
332 f_right = trace_fraction;
334 //te_lightning1(world,self.origin, trace_endpos);
336 leftwish = v_left * f_left;
337 rightwish = v_right * f_right;
338 frontwish = v_forward * f_front;
340 return normalize(leftwish + rightwish + frontwish);
343 float beamsweep_badpoint(vector point,float waterok)
347 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
350 pc = pointcontents(point);
351 pc2 = pointcontents(point - '0 0 1');
355 case CONTENT_SOLID: break;
356 case CONTENT_SLIME: break;
357 case CONTENT_LAVA: break;
363 if (pc2 == CONTENT_SOLID)
366 if (pc2 == CONTENT_WATER)
382 //#define BEAMSTEER_VISUAL
383 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
388 u = '0 0 1' * step_up;
389 d = '0 0 1' * step_down;
391 traceline(from + u, from - d,MOVE_NORMAL,self);
392 if(trace_fraction == 1.0)
395 if(beamsweep_badpoint(trace_endpos,0))
399 for(i = 0; i < length; i += step)
403 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
404 if(trace_fraction != 1.0)
407 traceline(b + u, b - d,MOVE_NORMAL,self);
408 if(trace_fraction == 1.0)
411 if(beamsweep_badpoint(trace_endpos,0))
413 #ifdef BEAMSTEER_VISUAL
414 te_lightning1(world,a+u,b+u);
415 te_lightning1(world,b+u,b-d);
423 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
425 float bm_forward, bm_right, bm_left,p;
429 vr = vectoangles(dir);
432 tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self);
433 if(trace_fraction == 1.0)
435 //te_lightning1(self,self.origin,self.origin + (dir * length));
443 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
445 vr = normalize(v_forward + v_right * 0.125);
446 vl = normalize(v_forward - v_right * 0.125);
448 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
449 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
452 p = bm_left + bm_right;
455 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
456 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
463 vr = normalize(v_forward + v_right * p);
464 vl = normalize(v_forward - v_right * p);
465 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
466 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
469 if(bm_left + bm_right < 0.15)
471 vr = normalize((v_forward*-1) + v_right * 0.75);
472 vl = normalize((v_forward*-1) - v_right * 0.75);
474 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
475 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
478 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
479 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
481 bm_forward *= bm_forward;
482 bm_right *= bm_right;
488 return normalize(vr + vl);
493 //////////////////////////////////////////////
495 // Everything below this point is a mess :D //
496 //////////////////////////////////////////////
497 //#define TLIBS_TETSLIBS
498 #ifdef TLIBS_TETSLIBS
501 pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
506 self.nextthink = time;
507 self.think = SUB_Remove;
513 vector dodgemove,swarmmove;
514 vector reprellmove,wandermove,newmove;
516 self.angles_x = self.angles.x * -1;
517 makevectors(self.angles);
518 self.angles_x = self.angles.x * -1;
520 dodgemove = steerlib_traceavoid(0.35,1000);
521 swarmmove = steerlib_flock(500,75,700,500);
522 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
524 if(vlen(dodgemove) == 0)
526 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
527 wandermove = self.pos1 * 50;
530 self.pos1 = normalize(self.velocity);
532 dodgemove = dodgemove * vlen(self.velocity) * 5;
534 newmove = swarmmove + reprellmove + wandermove + dodgemove;
535 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
536 //self.velocity = movelib_inertmove(dodgemove,0.65);
538 self.velocity = movelib_dragvec(0.01,0.6);
540 self.angles = vectoangles(self.velocity);
545 self.nextthink = time + 0.1;
555 setorigin(flocker, self.origin + '0 0 32');
556 setmodel (flocker, "models/turrets/rocket.md3");
557 setsize (flocker, '-3 -3 -3', '3 3 3');
559 flocker.flock_id = self.flock_id;
560 flocker.classname = "flocker";
561 flocker.owner = self;
562 flocker.think = flocker_think;
563 flocker.nextthink = time + random() * 5;
564 PROJECTILE_MAKETRIGGER(flocker);
565 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
566 flocker.effects = EF_LOWPRECISION;
567 flocker.velocity = randomvec() * 300;
568 flocker.angles = vectoangles(flocker.velocity);
570 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
572 self.cnt = self.cnt -1;
576 void flockerspawn_think()
583 self.nextthink = time + self.delay;
587 void flocker_hunter_think()
589 vector dodgemove,attractmove,newmove;
593 self.angles_x = self.angles.x * -1;
594 makevectors(self.angles);
595 self.angles_x = self.angles.x * -1;
598 if(vlen(self.enemy.origin - self.origin) < 64)
608 e = findchainfloat(flock_id,self.flock_id);
611 d = vlen(self.origin - e.origin);
625 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
627 attractmove = normalize(self.velocity) * 200;
629 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
631 newmove = dodgemove + attractmove;
632 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
633 self.velocity = movelib_dragvec(0.01,0.5);
636 self.angles = vectoangles(self.velocity);
637 self.nextthink = time + 0.1;
642 void spawnfunc_flockerspawn()
644 precache_model ( "models/turrets/rocket.md3");
645 precache_model("models/turrets/c512.md3");
648 if(!self.cnt) self.cnt = 20;
649 if(!self.delay) self.delay = 0.25;
650 if(!self.flock_id) self.flock_id = globflockcnt;
652 self.think = flockerspawn_think;
653 self.nextthink = time + 0.25;
655 self.enemy = spawn();
657 setmodel(self.enemy, "models/turrets/rocket.md3");
658 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
660 self.enemy.classname = "FLock Hunter";
661 self.enemy.scale = 3;
662 self.enemy.effects = EF_LOWPRECISION;
663 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
664 PROJECTILE_MAKETRIGGER(self.enemy);
665 self.enemy.think = flocker_hunter_think;
666 self.enemy.nextthink = time + 10;
667 self.enemy.flock_id = self.flock_id;
668 self.enemy.owner = self;