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 Send_Effect(EFFECT_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;
548 MODEL(FLOCKER, "models/turrets/rocket.md3");
556 setorigin(flocker, self.origin + '0 0 32');
557 setmodel (flocker, MDL_FLOCKER);
558 setsize (flocker, '-3 -3 -3', '3 3 3');
560 flocker.flock_id = self.flock_id;
561 flocker.classname = "flocker";
562 flocker.owner = self;
563 flocker.think = flocker_think;
564 flocker.nextthink = time + random() * 5;
565 PROJECTILE_MAKETRIGGER(flocker);
566 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
567 flocker.effects = EF_LOWPRECISION;
568 flocker.velocity = randomvec() * 300;
569 flocker.angles = vectoangles(flocker.velocity);
571 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
573 self.cnt = self.cnt -1;
577 void flockerspawn_think()
584 self.nextthink = time + self.delay;
588 void flocker_hunter_think()
590 vector dodgemove,attractmove,newmove;
594 self.angles_x = self.angles.x * -1;
595 makevectors(self.angles);
596 self.angles_x = self.angles.x * -1;
599 if(vlen(self.enemy.origin - self.origin) < 64)
609 e = findchainfloat(flock_id,self.flock_id);
612 d = vlen(self.origin - e.origin);
626 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
628 attractmove = normalize(self.velocity) * 200;
630 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
632 newmove = dodgemove + attractmove;
633 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
634 self.velocity = movelib_dragvec(0.01,0.5);
637 self.angles = vectoangles(self.velocity);
638 self.nextthink = time + 0.1;
643 spawnfunc(flockerspawn)
647 if(!self.cnt) self.cnt = 20;
648 if(!self.delay) self.delay = 0.25;
649 if(!self.flock_id) self.flock_id = globflockcnt;
651 self.think = flockerspawn_think;
652 self.nextthink = time + 0.25;
654 self.enemy = spawn();
656 setmodel(self.enemy, MDL_FLOCKER);
657 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
659 self.enemy.classname = "FLock Hunter";
660 self.enemy.scale = 3;
661 self.enemy.effects = EF_LOWPRECISION;
662 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
663 PROJECTILE_MAKETRIGGER(self.enemy);
664 self.enemy.think = flocker_hunter_think;
665 self.enemy.nextthink = time + 10;
666 self.enemy.flock_id = self.flock_id;
667 self.enemy.owner = self;