4 #include "../dpdefs/progsdefs.qh"
5 #include "../dpdefs/dpextensions.qh"
11 Uniform pull towards a point
13 vector steerlib_pull(vector point)
15 return normalize(point - self.origin);
19 Uniform push from a point
21 #define steerlib_push(point) normalize(self.origin - point)
23 vector steerlib_push(vector point)
25 return normalize(self.origin - point);
29 Pull toward a point, The further away, the stronger the pull.
31 vector steerlib_arrive(vector point,float maximal_distance)
36 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
37 direction = normalize(point - self.origin);
38 return direction * (distance / maximal_distance);
42 Pull toward a point increasing the pull the closer we get
44 vector steerlib_attract(vector point, float maximal_distance)
49 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
50 direction = normalize(point - self.origin);
52 return direction * (1-(distance / maximal_distance));
55 vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
61 distance = bound(0.00001,vlen(self.origin - point),max_distance);
62 direction = normalize(point - self.origin);
64 influense = 1 - (distance / max_distance);
65 influense = min_influense + (influense * (max_influense - min_influense));
67 return direction * influense;
71 vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
74 vector current_direction;
75 vector target_direction;
76 float i_target,i_current;
79 distance = vlen(self.origin - point);
81 distance = bound(0.001,distance,maximal_distance);
83 target_direction = normalize(point - self.origin);
84 current_direction = normalize(self.velocity);
86 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
87 i_current = 1 - i_target;
89 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
93 bprint("IT: ",s,"\n");
95 bprint("IC : ",s,"\n");
97 return normalize((target_direction * i_target) + (current_direction * i_current));
101 Move away from a point.
103 vector steerlib_repell(vector point,float maximal_distance)
108 distance = bound(0.001,vlen(self.origin - point),maximal_distance);
109 direction = normalize(self.origin - point);
111 return direction * (1-(distance / maximal_distance));
115 Try to keep at ideal_distance away from point
117 vector steerlib_standoff(vector point,float ideal_distance)
122 distance = vlen(self.origin - point);
125 if(distance < ideal_distance)
127 direction = normalize(self.origin - point);
128 return direction * (distance / ideal_distance);
131 direction = normalize(point - self.origin);
132 return direction * (ideal_distance / distance);
137 A random heading in a forward halfcicrle
140 self.target = steerlib_wander(256,32,self.target)
142 where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
144 vector steerlib_wander(float range,float tresh,vector oldpoint)
147 wander_point = v_forward - oldpoint;
149 if (vlen(wander_point) > tresh)
152 range = bound(0,range,1);
154 wander_point = self.origin + v_forward * 128;
155 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
157 return normalize(wander_point - self.origin);
161 Dodge a point. dont work to well.
163 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
167 distance = max(vlen(self.origin - point),min_distance);
168 if (min_distance < distance)
171 return dodge_dir * (min_distance/distance);
175 flocking by .flock_id
176 Group will move towards the unified direction while keeping close to eachother.
179 vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
182 vector push = '0 0 0', pull = '0 0 0';
185 flock_member = findradius(self.origin, _radius);
188 if(flock_member != self)
189 if(flock_member.flock_id == self.flock_id)
192 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
193 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
195 flock_member = flock_member.chain;
197 return push + (pull* (1 / ccount));
201 flocking by .flock_id
202 Group will move towards the unified direction while keeping close to eachother.
203 xy only version (for ground movers).
205 vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
208 vector push = '0 0 0', pull = '0 0 0';
211 flock_member = findradius(self.origin,_radius);
214 if(flock_member != self)
215 if(flock_member.flock_id == self.flock_id)
218 push = push + (steerlib_repell(flock_member.origin, standoff) * separation_force);
219 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity, _radius) * flock_force);
221 flock_member = flock_member.chain;
227 return push + (pull * (1 / ccount));
231 All members want to be in the center, and keep away from eachother.
232 The furtehr form the center the more they want to be there.
234 This results in a aligned movement (?!) much like flocking.
236 vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
239 vector force = '0 0 0', center = '0 0 0';
242 swarm_member = findradius(self.origin,_radius);
246 if(swarm_member.flock_id == self.flock_id)
249 center = center + swarm_member.origin;
250 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
252 swarm_member = swarm_member.chain;
255 center = center * (1 / ccount);
256 force = force + (steerlib_arrive(center,_radius) * swarm_force);
262 Steer towards the direction least obstructed.
263 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
264 You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
266 vector steerlib_traceavoid(float pitch,float length)
268 vector vup_left,vup_right,vdown_left,vdown_right;
269 float fup_left,fup_right,fdown_left,fdown_right;
270 vector upwish,downwish,leftwish,rightwish;
271 vector v_left,v_down;
274 v_left = v_right * -1;
277 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
278 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
279 fup_left = trace_fraction;
281 //te_lightning1(world,self.origin, trace_endpos);
283 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
284 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
285 fup_right = trace_fraction;
287 //te_lightning1(world,self.origin, trace_endpos);
289 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
290 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
291 fdown_left = trace_fraction;
293 //te_lightning1(world,self.origin, trace_endpos);
295 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
296 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
297 fdown_right = trace_fraction;
299 //te_lightning1(world,self.origin, trace_endpos);
300 upwish = v_up * (fup_left + fup_right);
301 downwish = v_down * (fdown_left + fdown_right);
302 leftwish = v_left * (fup_left + fdown_left);
303 rightwish = v_right * (fup_right + fdown_right);
305 return (upwish+leftwish+downwish+rightwish) * 0.25;
310 Steer towards the direction least obstructed.
311 Run tracelines in a forward trident, bias each direction negative if something is found there.
313 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
315 vector vt_left, vt_right,vt_front;
316 float f_left, f_right,f_front;
317 vector leftwish, rightwish,frontwish, v_left;
319 v_left = v_right * -1;
322 vt_front = v_forward * length;
323 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
324 f_front = trace_fraction;
326 vt_left = (v_forward + (v_left * pitch)) * length;
327 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
328 f_left = trace_fraction;
330 //te_lightning1(world,self.origin, trace_endpos);
332 vt_right = (v_forward + (v_right * pitch)) * length;
333 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
334 f_right = trace_fraction;
336 //te_lightning1(world,self.origin, trace_endpos);
338 leftwish = v_left * f_left;
339 rightwish = v_right * f_right;
340 frontwish = v_forward * f_front;
342 return normalize(leftwish + rightwish + frontwish);
345 float beamsweep_badpoint(vector point,float waterok)
349 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
352 pc = pointcontents(point);
353 pc2 = pointcontents(point - '0 0 1');
357 case CONTENT_SOLID: break;
358 case CONTENT_SLIME: break;
359 case CONTENT_LAVA: break;
365 if (pc2 == CONTENT_SOLID)
368 if (pc2 == CONTENT_WATER)
384 //#define BEAMSTEER_VISUAL
385 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
390 u = '0 0 1' * step_up;
391 d = '0 0 1' * step_down;
393 traceline(from + u, from - d,MOVE_NORMAL,self);
394 if(trace_fraction == 1.0)
397 if(beamsweep_badpoint(trace_endpos,0))
401 for(i = 0; i < length; i += step)
405 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
406 if(trace_fraction != 1.0)
409 traceline(b + u, b - d,MOVE_NORMAL,self);
410 if(trace_fraction == 1.0)
413 if(beamsweep_badpoint(trace_endpos,0))
415 #ifdef BEAMSTEER_VISUAL
416 te_lightning1(world,a+u,b+u);
417 te_lightning1(world,b+u,b-d);
425 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
427 float bm_forward, bm_right, bm_left,p;
431 vr = vectoangles(dir);
434 tracebox(self.origin + '0 0 1' * step_up, self.mins, self.maxs, ('0 0 1' * step_up) + self.origin + (dir * length), MOVE_NOMONSTERS, self);
435 if(trace_fraction == 1.0)
437 //te_lightning1(self,self.origin,self.origin + (dir * length));
445 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
447 vr = normalize(v_forward + v_right * 0.125);
448 vl = normalize(v_forward - v_right * 0.125);
450 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
451 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
454 p = bm_left + bm_right;
457 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
458 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
465 vr = normalize(v_forward + v_right * p);
466 vl = normalize(v_forward - v_right * p);
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 if(bm_left + bm_right < 0.15)
473 vr = normalize((v_forward*-1) + v_right * 0.75);
474 vl = normalize((v_forward*-1) - v_right * 0.75);
476 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
477 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
480 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
481 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
483 bm_forward *= bm_forward;
484 bm_right *= bm_right;
490 return normalize(vr + vl);
495 //////////////////////////////////////////////
497 // Everything below this point is a mess :D //
498 //////////////////////////////////////////////
499 //#define TLIBS_TETSLIBS
500 #ifdef TLIBS_TETSLIBS
503 pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
508 self.nextthink = time;
509 self.think = SUB_Remove;
515 vector dodgemove,swarmmove;
516 vector reprellmove,wandermove,newmove;
518 self.angles_x = self.angles.x * -1;
519 makevectors(self.angles);
520 self.angles_x = self.angles.x * -1;
522 dodgemove = steerlib_traceavoid(0.35,1000);
523 swarmmove = steerlib_flock(500,75,700,500);
524 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
526 if(vlen(dodgemove) == 0)
528 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
529 wandermove = self.pos1 * 50;
532 self.pos1 = normalize(self.velocity);
534 dodgemove = dodgemove * vlen(self.velocity) * 5;
536 newmove = swarmmove + reprellmove + wandermove + dodgemove;
537 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
538 //self.velocity = movelib_inertmove(dodgemove,0.65);
540 self.velocity = movelib_dragvec(0.01,0.6);
542 self.angles = vectoangles(self.velocity);
547 self.nextthink = time + 0.1;
557 setorigin(flocker, self.origin + '0 0 32');
558 setmodel (flocker, "models/turrets/rocket.md3");
559 setsize (flocker, '-3 -3 -3', '3 3 3');
561 flocker.flock_id = self.flock_id;
562 flocker.classname = "flocker";
563 flocker.owner = self;
564 flocker.think = flocker_think;
565 flocker.nextthink = time + random() * 5;
566 PROJECTILE_MAKETRIGGER(flocker);
567 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
568 flocker.effects = EF_LOWPRECISION;
569 flocker.velocity = randomvec() * 300;
570 flocker.angles = vectoangles(flocker.velocity);
572 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
574 self.cnt = self.cnt -1;
578 void flockerspawn_think()
585 self.nextthink = time + self.delay;
589 void flocker_hunter_think()
591 vector dodgemove,attractmove,newmove;
595 self.angles_x = self.angles.x * -1;
596 makevectors(self.angles);
597 self.angles_x = self.angles.x * -1;
600 if(vlen(self.enemy.origin - self.origin) < 64)
610 e = findchainfloat(flock_id,self.flock_id);
613 d = vlen(self.origin - e.origin);
627 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
629 attractmove = normalize(self.velocity) * 200;
631 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
633 newmove = dodgemove + attractmove;
634 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
635 self.velocity = movelib_dragvec(0.01,0.5);
638 self.angles = vectoangles(self.velocity);
639 self.nextthink = time + 0.1;
644 void spawnfunc_flockerspawn()
646 precache_model ( "models/turrets/rocket.md3");
647 precache_model("models/turrets/c512.md3");
650 if(!self.cnt) self.cnt = 20;
651 if(!self.delay) self.delay = 0.25;
652 if(!self.flock_id) self.flock_id = globflockcnt;
654 self.think = flockerspawn_think;
655 self.nextthink = time + 0.25;
657 self.enemy = spawn();
659 setmodel(self.enemy, "models/turrets/rocket.md3");
660 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
662 self.enemy.classname = "FLock Hunter";
663 self.enemy.scale = 3;
664 self.enemy.effects = EF_LOWPRECISION;
665 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
666 PROJECTILE_MAKETRIGGER(self.enemy);
667 self.enemy.think = flocker_hunter_think;
668 self.enemy.nextthink = time + 10;
669 self.enemy.flock_id = self.flock_id;
670 self.enemy.owner = self;