Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
steerlib.qc
Go to the documentation of this file.
1#include "steerlib.qh"
2
4
8#define steerlib_pull(ent,point) normalize(point - (ent).origin)
9/*vector steerlib_pull(entity this, vector point)
10{
11 return normalize(point - this.origin);
12}*/
13
17#define steerlib_push(ent,point) normalize((ent).origin - point)
18/*
19vector steerlib_push(entity this, vector point)
20{
21 return normalize(this.origin - point);
22}
23*/
27vector steerlib_arrive(entity this, vector point, float maximal_distance)
28{
29 float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
30 vector direction = normalize(point - this.origin);
31 return direction * (distance / maximal_distance);
32}
33
37vector steerlib_attract(entity this, vector point, float maximal_distance)
38{
39 float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
40 vector direction = normalize(point - this.origin);
41
42 return direction * (1 - (distance / maximal_distance));
43}
44
45vector steerlib_attract2(entity this, vector point, float min_influense, float max_distance, float max_influense)
46{
47 float distance = bound(0.00001, vlen(this.origin - point), max_distance);
48 vector direction = normalize(point - this.origin);
49
50 float influense = 1 - (distance / max_distance);
51 influense = min_influense + (influense * (max_influense - min_influense));
52
53 return direction * influense;
54}
55
56/*
57vector steerlib_attract2(vector point, float maximal_distance,float min_influense,float max_influense,float distance)
58{
59 //float distance;
60 vector current_direction;
61 vector target_direction;
62 float i_target,i_current;
63
64 if(!distance)
65 distance = vlen(this.origin - point);
66
67 distance = bound(0.001,distance,maximal_distance);
68
69 target_direction = normalize(point - this.origin);
70 current_direction = normalize(this.velocity);
71
72 i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
73 i_current = 1 - i_target;
74
75 // i_target = bound(min_influense,(1-(distance / maximal_distance)),max_influense);
76
77 string s;
78 s = ftos(i_target);
79 bprint("IT: ",s,"\n");
80 s = ftos(i_current);
81 bprint("IC : ",s,"\n");
82
83 return normalize((target_direction * i_target) + (current_direction * i_current));
84}
85*/
89vector steerlib_repel(entity this, vector point, float maximal_distance)
90{
91 float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
92 vector direction = normalize(this.origin - point);
93
94 return direction * (1 - (distance / maximal_distance));
95}
96
100vector steerlib_standoff(entity this, vector point, float ideal_distance)
101{
102 vector direction;
103 float distance = vlen(this.origin - point);
104
105 if(distance < ideal_distance)
106 {
107 direction = normalize(this.origin - point);
108 return direction * (distance / ideal_distance);
109 }
110
111 direction = normalize(point - this.origin);
112 return direction * (ideal_distance / distance);
113
114}
115
125vector steerlib_wander(entity this, float range, float threshold, vector oldpoint)
126{
127 vector wander_point = v_forward - oldpoint;
128
129 if (vdist(wander_point, >, threshold))
130 return oldpoint;
131
132 range = bound(0, range, 1);
133
134 wander_point = this.origin + v_forward * 128;
135 wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
136
137 return normalize(wander_point - this.origin);
138}
139
143vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
144{
145 float distance = max(vlen(this.origin - point), min_distance);
146 if (min_distance < distance)
147 return '0 0 0';
148
149 return dodge_dir * (min_distance / distance);
150}
151
156.float flock_id;
157vector steerlib_flock(entity this, float _radius, float standoff, float separation_force, float flock_force)
158{
159 vector push = '0 0 0', pull = '0 0 0';
160 int ccount = 0;
161
162 entity flock_member = findradius(this.origin, _radius);
163 while(flock_member)
164 {
165 if(flock_member != this)
166 if(flock_member.flock_id == this.flock_id)
167 {
168 ++ccount;
169 push = push + (steerlib_repel(this, flock_member.origin,standoff) * separation_force);
170 pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
171 }
172 flock_member = flock_member.chain;
173 }
174 return push + (pull* (1 / ccount));
175}
176
182vector steerlib_flock2d(entity this, float _radius, float standoff, float separation_force, float flock_force)
183{
184 vector push = '0 0 0', pull = '0 0 0';
185 int ccount = 0;
186
187 entity flock_member = findradius(this.origin,_radius);
188 while(flock_member)
189 {
190 if(flock_member != this)
191 if(flock_member.flock_id == this.flock_id)
192 {
193 ++ccount;
194 push = push + (steerlib_repel(this, flock_member.origin, standoff) * separation_force);
195 pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
196 }
197 flock_member = flock_member.chain;
198 }
199
200 push.z = 0;
201 pull.z = 0;
202
203 return push + (pull * (1 / ccount));
204}
205
212vector steerlib_swarm(entity this, float _radius, float standoff, float separation_force, float swarm_force)
213{
214 vector force = '0 0 0', center = '0 0 0';
215 int ccount = 0;
216
217 entity swarm_member = findradius(this.origin,_radius);
218 while(swarm_member)
219 {
220 if(swarm_member.flock_id == this.flock_id)
221 {
222 ++ccount;
223 center = center + swarm_member.origin;
224 force = force + (steerlib_repel(this, swarm_member.origin,standoff) * separation_force);
225 }
226 swarm_member = swarm_member.chain;
227 }
228
229 center = center * (1 / ccount);
230 force = force + (steerlib_arrive(this, center,_radius) * swarm_force);
231
232 return force;
233}
234
240vector steerlib_traceavoid(entity this, float pitch, float length)
241{
242 vector v_left = v_right * -1;
243 vector v_down = v_up * -1;
244
245 vector vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
246 traceline(this.origin, this.origin + vup_left, MOVE_NOMONSTERS, this);
247 float fup_left = trace_fraction;
248
249 //te_lightning1(NULL,this.origin, trace_endpos);
250
251 vector vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
252 traceline(this.origin, this.origin + vup_right, MOVE_NOMONSTERS, this);
253 float fup_right = trace_fraction;
254
255 //te_lightning1(NULL,this.origin, trace_endpos);
256
257 vector vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
258 traceline(this.origin, this.origin + vdown_left, MOVE_NOMONSTERS, this);
259 float fdown_left = trace_fraction;
260
261 //te_lightning1(NULL,this.origin, trace_endpos);
262
263 vector vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
264 traceline(this.origin, this.origin + vdown_right, MOVE_NOMONSTERS, this);
265 float fdown_right = trace_fraction;
266
267 //te_lightning1(NULL,this.origin, trace_endpos);
268 vector upwish = v_up * (fup_left + fup_right);
269 vector downwish = v_down * (fdown_left + fdown_right);
270 vector leftwish = v_left * (fup_left + fdown_left);
271 vector rightwish = v_right * (fup_right + fdown_right);
272
273 return (upwish + leftwish + downwish + rightwish) * 0.25;
274
275}
276
282vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
283{
284 vector v_left = v_right * -1;
285
286 vector vt_front = v_forward * length;
287 traceline(this.origin + vofs, this.origin + vofs + vt_front,MOVE_NOMONSTERS,this);
288 float f_front = trace_fraction;
289
290 vector vt_left = (v_forward + (v_left * pitch)) * length;
291 traceline(this.origin + vofs, this.origin + vofs + vt_left,MOVE_NOMONSTERS,this);
292 float f_left = trace_fraction;
293
294 //te_lightning1(NULL,this.origin, trace_endpos);
295
296 vector vt_right = (v_forward + (v_right * pitch)) * length;
297 traceline(this.origin + vofs, this.origin + vofs + vt_right ,MOVE_NOMONSTERS,this);
298 float f_right = trace_fraction;
299
300 //te_lightning1(NULL,this.origin, trace_endpos);
301
302 vector leftwish = v_left * f_left;
303 vector rightwish = v_right * f_right;
304 vector frontwish = v_forward * f_front;
305
306 return normalize(leftwish + rightwish + frontwish);
307}
308
309//#define BEAMSTEER_VISUAL
310float beamsweep(entity this, vector from, vector dir, float length, float step, float step_up, float step_down)
311{
312 vector u = '0 0 1' * step_up;
313 vector d = '0 0 1' * step_down;
314
315 traceline(from + u, from - d,MOVE_NORMAL,this);
316 if(trace_fraction == 1.0)
317 return 0;
318
319 if(!location_isok(trace_endpos, false, false))
320 return 0;
321
323 for(int i = 0; i < length; i += step)
324 {
325
326 vector b = a + dir * step;
327 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,this);
328 if(trace_fraction != 1.0)
329 return i / length;
330
331 traceline(b + u, b - d,MOVE_NORMAL,this);
332 if(trace_fraction == 1.0)
333 return i / length;
334
335 if(!location_isok(trace_endpos, false, false))
336 return i / length;
337#ifdef BEAMSTEER_VISUAL
338 te_lightning1(NULL,a+u,b+u);
339 te_lightning1(NULL,b+u,b-d);
340#endif
341 a = trace_endpos;
342 }
343
344 return 1;
345}
346
347vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
348{
349 dir.z *= 0.15;
350 vector vr = vectoangles(dir);
351 //vr.x *= -1;
352
353 tracebox(this.origin + '0 0 1' * step_up, this.mins, this.maxs, ('0 0 1' * step_up) + this.origin + (dir * length), MOVE_NOMONSTERS, this);
354 if(trace_fraction == 1.0)
355 {
356 //te_lightning1(this,this.origin,this.origin + (dir * length));
357 return dir;
358 }
359
360 makevectors(vr);
361 float bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
362
363 vr = normalize(v_forward + v_right * 0.125);
364 vector vl = normalize(v_forward - v_right * 0.125);
365
366 float bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
367 float bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
368
369 float p = bm_left + bm_right;
370 if(p == 2)
371 {
372 //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
373 //te_lightning1(this.tur_head,this.origin + '0 0 32',this.origin + '0 0 32' + vl * length);
374
375 return v_forward;
376 }
377
378 p = 2 - p;
379
380 vr = normalize(v_forward + v_right * p);
381 vl = normalize(v_forward - v_right * p);
382 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
383 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
384
385
386 if(bm_left + bm_right < 0.15)
387 {
388 vr = normalize((v_forward*-1) + v_right * 0.90);
389 vl = normalize((v_forward*-1) - v_right * 0.90);
390
391 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
392 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
393 }
394
395 //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
396 //te_lightning1(this.tur_head,this.origin + '0 0 32',this.origin + '0 0 32' + vl * length);
397
398 bm_forward *= bm_forward;
399 bm_right *= bm_right;
400 bm_left *= bm_left;
401
402 vr = vr * bm_right;
403 vl = vl * bm_left;
404
405 return normalize(vr + vl);
406}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
vector v_up
const float MOVE_NOMONSTERS
const float MOVE_NORMAL
vector mins
vector v_right
vector trace_endpos
vector maxs
vector v_forward
vector origin
float trace_fraction
float pitch
Definition halflife.qc:5
float bound(float min, float value, float max)
float vlen(vector v)
vector vectoangles(vector v)
vector randomvec(void)
vector normalize(vector v)
float max(float f,...)
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
vector
Definition self.qh:92
int dir
Definition impulse.qc:89
float flock_id
flocking by .flock_id Group will move towards the unified direction while keeping close to eachother.
Definition steerlib.qc:156
vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
Steer towards the direction least obstructed.
Definition steerlib.qc:282
vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
Dodge a point NOTE: doesn't work well.
Definition steerlib.qc:143
vector steerlib_swarm(entity this, float _radius, float standoff, float separation_force, float swarm_force)
All members want to be in the center, and keep away from eachother.
Definition steerlib.qc:212
float beamsweep(entity this, vector from, vector dir, float length, float step, float step_up, float step_down)
Definition steerlib.qc:310
vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
Definition steerlib.qc:347
vector steerlib_flock2d(entity this, float _radius, float standoff, float separation_force, float flock_force)
flocking by .flock_id Group will move towards the unified direction while keeping close to eachother.
Definition steerlib.qc:182
vector steerlib_arrive(entity this, vector point, float maximal_distance)
Pull toward a point, The further away, the stronger the pull.
Definition steerlib.qc:27
vector steerlib_standoff(entity this, vector point, float ideal_distance)
Try to keep at ideal_distance away from point.
Definition steerlib.qc:100
vector steerlib_attract2(entity this, vector point, float min_influense, float max_distance, float max_influense)
Definition steerlib.qc:45
vector steerlib_flock(entity this, float _radius, float standoff, float separation_force, float flock_force)
Definition steerlib.qc:157
vector steerlib_traceavoid(entity this, float pitch, float length)
Steer towards the direction least obstructed.
Definition steerlib.qc:240
vector steerlib_repel(entity this, vector point, float maximal_distance)
Move away from a point.
Definition steerlib.qc:89
vector steerlib_attract(entity this, vector point, float maximal_distance)
Pull toward a point increasing the pull the closer we get.
Definition steerlib.qc:37
vector steerlib_wander(entity this, float range, float threshold, vector oldpoint)
A random heading in a forward semicircle.
Definition steerlib.qc:125
bool location_isok(vector point, bool waterok, bool air_isok)
Definition utility.qc:7
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8