4 Uniform pull towards a point
6 vector steerlib_pull(vector point)
8 return normalize(point - self.origin);
12 Uniform push from a 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);
160 return dodge_dir * (min_distance/distance);
164 flocking by .flock_id
165 Group will move towards the unified direction while keeping close to eachother.
168 vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
174 flock_member = findradius(self.origin,radius);
177 if(flock_member != self)
178 if(flock_member.flock_id == self.flock_id)
181 push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
182 pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity,radius) * flock_force);
184 flock_member = flock_member.chain;
186 return push + (pull* (1 / ccount));
190 All members want to be in the center, and keep away from eachother.
191 The furtehr form the center the more they want to be there.
193 This results in a aligned movement (?!) much like flocking.
195 vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
201 swarm_member = findradius(self.origin,radius);
205 if(swarm_member.flock_id == self.flock_id)
208 center = center + swarm_member.origin;
209 force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
211 swarm_member = swarm_member.chain;
214 center = center * (1 / ccount);
215 force = force + (steerlib_arrive(center,radius) * swarm_force);
221 Steer towards the direction least obstructed.
222 Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
224 vector steerlib_traceavoid(float pitch,float length)
226 vector vup_left,vup_right,vdown_left,vdown_right;
227 float fup_left,fup_right,fdown_left,fdown_right;
228 vector upwish,downwish,leftwish,rightwish;
229 vector v_left,v_down;
231 v_left = v_right * -1;
234 vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
235 traceline(self.origin, self.origin + vup_left,MOVE_NOMONSTERS,self);
236 fup_left = trace_fraction;
238 //te_lightning1(world,self.origin, trace_endpos);
240 vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
241 traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
242 fup_right = trace_fraction;
244 //te_lightning1(world,self.origin, trace_endpos);
246 vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
247 traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
248 fdown_left = trace_fraction;
250 //te_lightning1(world,self.origin, trace_endpos);
252 vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
253 traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
254 fdown_right = trace_fraction;
256 //te_lightning1(world,self.origin, trace_endpos);
258 upwish = v_up * (fup_left + fup_right);
259 downwish = v_down * (fdown_left + fdown_right);
260 leftwish = v_left * (fup_left + fdown_left);
261 rightwish = v_right * (fup_right + fdown_right);
263 return (upwish+leftwish+downwish+rightwish) * 0.25;
268 Steer towards the direction least obstructed.
269 Run two tracelines in a forward trident, bias each diretion negative if something is found there.
271 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
273 vector vt_left, vt_right,vt_front;
274 float f_left, f_right,f_front;
275 vector leftwish, rightwish,frontwish, v_left;
277 v_left = v_right * -1;
280 vt_front = v_forward * length;
281 traceline(self.origin + vofs, self.origin + vofs + vt_front,MOVE_NOMONSTERS,self);
282 f_front = trace_fraction;
284 vt_left = (v_forward + (v_left * pitch)) * length;
285 traceline(self.origin + vofs, self.origin + vofs + vt_left,MOVE_NOMONSTERS,self);
286 f_left = trace_fraction;
288 //te_lightning1(world,self.origin, trace_endpos);
290 vt_right = (v_forward + (v_right * pitch)) * length;
291 traceline(self.origin + vofs, self.origin + vofs + vt_right ,MOVE_NOMONSTERS,self);
292 f_right = trace_fraction;
294 //te_lightning1(world,self.origin, trace_endpos);
296 leftwish = v_left * f_left;
297 rightwish = v_right * f_right;
298 frontwish = v_forward * f_front;
300 return normalize(leftwish + rightwish + frontwish);
303 float beamsweep_badpoint(vector point,float waterok)
307 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
310 pc = pointcontents(point);
311 pc2 = pointcontents(point - '0 0 1');
315 case CONTENT_SOLID: break;
316 case CONTENT_SLIME: break;
317 case CONTENT_LAVA: break;
323 if (pc2 == CONTENT_SOLID)
326 if (pc2 == CONTENT_WATER)
342 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
347 u = '0 0 1' * step_up;
348 d = '0 0 1' * step_down;
350 traceline(from + u, from - d,MOVE_NORMAL,self);
351 if(trace_fraction == 1.0)
354 if(beamsweep_badpoint(trace_endpos,0))
358 for(i = 0; i < length; i += step)
362 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,self);
363 if(trace_fraction != 1.0)
366 traceline(b + u, b - d,MOVE_NORMAL,self);
367 if(trace_fraction == 1.0)
370 if(beamsweep_badpoint(trace_endpos,0))
373 //te_lightning1(world,a+u,b+u);
374 //te_lightning1(world,b+u,b-d);
382 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
384 float bm_forward, bm_right, bm_left,p;
388 vr = vectoangles(dir);
392 bm_forward = beamsweep(self.origin, v_forward, length, step, step_up, step_down);
394 vr = normalize(v_forward + v_right * 0.125);
395 vl = normalize(v_forward - v_right * 0.125);
397 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
398 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
401 p = bm_left + bm_right;
404 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
405 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
412 vr = normalize(v_forward + v_right * p);
413 vl = normalize(v_forward - v_right * p);
414 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
415 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
418 if(bm_left + bm_right < 0.15)
420 vr = normalize((v_forward*-1) + v_right * 0.75);
421 vl = normalize((v_forward*-1) - v_right * 0.75);
423 bm_right = beamsweep(self.origin, vr, length, step, step_up, step_down);
424 bm_left = beamsweep(self.origin, vl, length, step, step_up, step_down);
427 //te_lightning1(self,self.origin + '0 0 32',self.origin + '0 0 32' + vr * length);
428 //te_lightning1(self.tur_head,self.origin + '0 0 32',self.origin + '0 0 32' + vl * length);
430 bm_forward *= bm_forward;
431 bm_right *= bm_right;
437 return normalize(vr + vl);
442 //////////////////////////////////////////////
444 // Everything below this point is a mess :D //
445 //////////////////////////////////////////////
446 //#define TLIBS_TETSLIBS
447 #ifdef TLIBS_TETSLIBS
450 sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
452 pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
457 self.nextthink = time;
458 self.think = SUB_Remove;
464 vector dodgemove,swarmmove;
465 vector reprellmove,wandermove,newmove;
467 self.angles_x = self.angles_x * -1;
468 makevectors(self.angles);
469 self.angles_x = self.angles_x * -1;
471 dodgemove = steerlib_traceavoid(0.35,1000);
472 swarmmove = steerlib_flock(500,75,700,500);
473 reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,2000) * 700;
475 if(vlen(dodgemove) == 0)
477 self.pos1 = steerlib_wander(0.5,0.1,self.pos1);
478 wandermove = self.pos1 * 50;
481 self.pos1 = normalize(self.velocity);
483 dodgemove = dodgemove * vlen(self.velocity) * 5;
485 newmove = swarmmove + reprellmove + wandermove + dodgemove;
486 self.velocity = movelib_inertmove_byspeed(newmove,300,0.2,0.9);
487 //self.velocity = movelib_inertmove(dodgemove,0.65);
489 self.velocity = movelib_dragvec(0.01,0.6);
491 self.angles = vectoangles(self.velocity);
496 self.nextthink = time + 0.1;
506 setorigin(flocker, self.origin + '0 0 32');
507 setmodel (flocker, "models/turrets/rocket.md3");
508 setsize (flocker, '-3 -3 -3', '3 3 3');
510 flocker.flock_id = self.flock_id;
511 flocker.classname = "flocker";
512 flocker.owner = self;
513 flocker.think = flocker_think;
514 flocker.nextthink = time + random() * 5;
515 PROJECTILE_MAKETRIGGER(flocker);
516 flocker.movetype = MOVETYPE_BOUNCEMISSILE;
517 flocker.effects = EF_LOWPRECISION;
518 flocker.velocity = randomvec() * 300;
519 flocker.angles = vectoangles(flocker.velocity);
521 flocker.pos1 = normalize(flocker.velocity + randomvec() * 0.1);
523 self.cnt = self.cnt -1;
527 void flockerspawn_think()
534 self.nextthink = time + self.delay;
538 void flocker_hunter_think()
540 vector dodgemove,attractmove,newmove;
544 self.angles_x = self.angles_x * -1;
545 makevectors(self.angles);
546 self.angles_x = self.angles_x * -1;
549 if(vlen(self.enemy.origin - self.origin) < 64)
559 e = findchainfloat(flock_id,self.flock_id);
562 d = vlen(self.origin - e.origin);
576 attractmove = steerlib_attract(self.enemy.origin+self.enemy.velocity * 0.1,5000) * 1250;
578 attractmove = normalize(self.velocity) * 200;
580 dodgemove = steerlib_traceavoid(0.35,1500) * vlen(self.velocity);
582 newmove = dodgemove + attractmove;
583 self.velocity = movelib_inertmove_byspeed(newmove,1250,0.3,0.7);
584 self.velocity = movelib_dragvec(0.01,0.5);
587 self.angles = vectoangles(self.velocity);
588 self.nextthink = time + 0.1;
593 void spawnfunc_flockerspawn()
595 precache_model ( "models/turrets/rocket.md3");
596 precache_model("models/turrets/c512.md3");
599 if(!self.cnt) self.cnt = 20;
600 if(!self.delay) self.delay = 0.25;
601 if(!self.flock_id) self.flock_id = globflockcnt;
603 self.think = flockerspawn_think;
604 self.nextthink = time + 0.25;
606 self.enemy = spawn();
608 setmodel(self.enemy, "models/turrets/rocket.md3");
609 setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
611 self.enemy.classname = "FLock Hunter";
612 self.enemy.scale = 3;
613 self.enemy.effects = EF_LOWPRECISION;
614 self.enemy.movetype = MOVETYPE_BOUNCEMISSILE;
615 PROJECTILE_MAKETRIGGER(self.enemy);
616 self.enemy.think = flocker_hunter_think;
617 self.enemy.nextthink = time + 10;
618 self.enemy.flock_id = self.flock_id;
619 self.enemy.owner = self;