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 = ftos(i_target);
78 bprint("IT: ",s,"\n");
79 s = ftos(i_current);
80 bprint("IC : ",s,"\n");
81
82 return normalize((target_direction * i_target) + (current_direction * i_current));
83}
84*/
88vector steerlib_repel(entity this, vector point, float maximal_distance)
89{
90 float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
91 vector direction = normalize(this.origin - point);
92
93 return direction * (1 - (distance / maximal_distance));
94}
95
99vector steerlib_standoff(entity this, vector point, float ideal_distance)
100{
101 vector direction;
102 float distance = vlen(this.origin - point);
103
104 if(distance < ideal_distance)
105 {
106 direction = normalize(this.origin - point);
107 return direction * (distance / ideal_distance);
108 }
109
110 direction = normalize(point - this.origin);
111 return direction * (ideal_distance / distance);
112
113}
114
124vector steerlib_wander(entity this, float range, float threshold, vector oldpoint)
125{
126 vector wander_point = v_forward - oldpoint;
127
128 if (vdist(wander_point, >, threshold))
129 return oldpoint;
130
131 range = bound(0, range, 1);
132
133 wander_point = this.origin + v_forward * 128;
134 wander_point += randomvec() * (range * 128) - randomvec() * (range * 128);
135
136 return normalize(wander_point - this.origin);
137}
138
142vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
143{
144 float distance = max(vlen(this.origin - point), min_distance);
145 if (min_distance < distance)
146 return '0 0 0';
147
148 return dodge_dir * (min_distance / distance);
149}
150
155.float flock_id;
156vector steerlib_flock(entity this, float _radius, float standoff, float separation_force, float flock_force)
157{
158 vector push = '0 0 0', pull = '0 0 0';
159 int ccount = 0;
160
161 entity flock_member = findradius(this.origin, _radius);
162 while(flock_member)
163 {
164 if(flock_member != this)
165 if(flock_member.flock_id == this.flock_id)
166 {
167 ++ccount;
168 push += steerlib_repel(this, flock_member.origin,standoff) * separation_force;
169 pull += steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force;
170 }
171 flock_member = flock_member.chain;
172 }
173 return push + (pull* (1 / ccount));
174}
175
181vector steerlib_flock2d(entity this, float _radius, float standoff, float separation_force, float flock_force)
182{
183 vector push = '0 0 0', pull = '0 0 0';
184 int ccount = 0;
185
186 entity flock_member = findradius(this.origin,_radius);
187 while(flock_member)
188 {
189 if(flock_member != this)
190 if(flock_member.flock_id == this.flock_id)
191 {
192 ++ccount;
193 push += steerlib_repel(this, flock_member.origin, standoff) * separation_force;
194 pull += steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force;
195 }
196 flock_member = flock_member.chain;
197 }
198
199 push.z = 0;
200 pull.z = 0;
201
202 return push + (pull * (1 / ccount));
203}
204
211vector steerlib_swarm(entity this, float _radius, float standoff, float separation_force, float swarm_force)
212{
213 vector force = '0 0 0', center = '0 0 0';
214 int ccount = 0;
215
216 entity swarm_member = findradius(this.origin,_radius);
217 while(swarm_member)
218 {
219 if(swarm_member.flock_id == this.flock_id)
220 {
221 ++ccount;
222 center += swarm_member.origin;
223 force += steerlib_repel(this, swarm_member.origin,standoff) * separation_force;
224 }
225 swarm_member = swarm_member.chain;
226 }
227
228 center *= 1 / ccount;
229 force += steerlib_arrive(this, center,_radius) * swarm_force;
230
231 return force;
232}
233
239vector steerlib_traceavoid(entity this, float pitch, float length)
240{
241 vector v_left = v_right * -1;
242 vector v_down = v_up * -1;
243
244 vector vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
245 traceline(this.origin, this.origin + vup_left, MOVE_NOMONSTERS, this);
246 float fup_left = trace_fraction;
247
248 //te_lightning1(NULL,this.origin, trace_endpos);
249
250 vector vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
251 traceline(this.origin, this.origin + vup_right, MOVE_NOMONSTERS, this);
252 float fup_right = trace_fraction;
253
254 //te_lightning1(NULL,this.origin, trace_endpos);
255
256 vector vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
257 traceline(this.origin, this.origin + vdown_left, MOVE_NOMONSTERS, this);
258 float fdown_left = trace_fraction;
259
260 //te_lightning1(NULL,this.origin, trace_endpos);
261
262 vector vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
263 traceline(this.origin, this.origin + vdown_right, MOVE_NOMONSTERS, this);
264 float fdown_right = trace_fraction;
265
266 //te_lightning1(NULL,this.origin, trace_endpos);
267 vector upwish = v_up * (fup_left + fup_right);
268 vector downwish = v_down * (fdown_left + fdown_right);
269 vector leftwish = v_left * (fup_left + fdown_left);
270 vector rightwish = v_right * (fup_right + fdown_right);
271
272 return (upwish + leftwish + downwish + rightwish) * 0.25;
273
274}
275
281vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
282{
283 vector v_left = v_right * -1;
284
285 vector vt_front = v_forward * length;
286 traceline(this.origin + vofs, this.origin + vofs + vt_front,MOVE_NOMONSTERS,this);
287 float f_front = trace_fraction;
288
289 vector vt_left = (v_forward + (v_left * pitch)) * length;
290 traceline(this.origin + vofs, this.origin + vofs + vt_left,MOVE_NOMONSTERS,this);
291 float f_left = trace_fraction;
292
293 //te_lightning1(NULL,this.origin, trace_endpos);
294
295 vector vt_right = (v_forward + (v_right * pitch)) * length;
296 traceline(this.origin + vofs, this.origin + vofs + vt_right ,MOVE_NOMONSTERS,this);
297 float f_right = trace_fraction;
298
299 //te_lightning1(NULL,this.origin, trace_endpos);
300
301 vector leftwish = v_left * f_left;
302 vector rightwish = v_right * f_right;
303 vector frontwish = v_forward * f_front;
304
305 return normalize(leftwish + rightwish + frontwish);
306}
307
308//#define BEAMSTEER_VISUAL
309float beamsweep(entity this, vector from, vector dir, float length, float step, float step_up, float step_down)
310{
311 vector u = '0 0 1' * step_up;
312 vector d = '0 0 1' * step_down;
313
314 traceline(from + u, from - d,MOVE_NORMAL,this);
315 if(trace_fraction == 1.0)
316 return 0;
317
318 if(!location_isok(trace_endpos, false, false))
319 return 0;
320
322 for(int i = 0; i < length; i += step)
323 {
324
325 vector b = a + dir * step;
326 tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,this);
327 if(trace_fraction != 1.0)
328 return i / length;
329
330 traceline(b + u, b - d,MOVE_NORMAL,this);
331 if(trace_fraction == 1.0)
332 return i / length;
333
334 if(!location_isok(trace_endpos, false, false))
335 return i / length;
336#ifdef BEAMSTEER_VISUAL
337 te_lightning1(NULL,a+u,b+u);
338 te_lightning1(NULL,b+u,b-d);
339#endif
340 a = trace_endpos;
341 }
342
343 return 1;
344}
345
346vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
347{
348 dir.z *= 0.15;
349 vector vr = vectoangles(dir);
350 //vr.x *= -1;
351
352 tracebox(this.origin + '0 0 1' * step_up, this.mins, this.maxs, ('0 0 1' * step_up) + this.origin + (dir * length), MOVE_NOMONSTERS, this);
353 if(trace_fraction == 1.0)
354 {
355 //te_lightning1(this,this.origin,this.origin + (dir * length));
356 return dir;
357 }
358
359 makevectors(vr);
360 float bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
361
362 vr = normalize(v_forward + v_right * 0.125);
363 vector vl = normalize(v_forward - v_right * 0.125);
364
365 float bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
366 float bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
367
368 float p = bm_left + bm_right;
369 if(p == 2)
370 {
371 //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
372 //te_lightning1(this.tur_head,this.origin + '0 0 32',this.origin + '0 0 32' + vl * length);
373
374 return v_forward;
375 }
376
377 p = 2 - p;
378
379 vr = normalize(v_forward + v_right * p);
380 vl = normalize(v_forward - v_right * p);
381 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
382 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
383
384
385 if(bm_left + bm_right < 0.15)
386 {
387 vr = normalize((v_forward*-1) + v_right * 0.90);
388 vl = normalize((v_forward*-1) - v_right * 0.90);
389
390 bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
391 bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
392 }
393
394 //te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
395 //te_lightning1(this.tur_head,this.origin + '0 0 32',this.origin + '0 0 32' + vl * length);
396
397 bm_forward *= bm_forward;
398 bm_right *= bm_right;
399 bm_left *= bm_left;
400
401 vr *= bm_right;
402 vl *= bm_left;
403
404 return normalize(vr + vl);
405}
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:155
vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
Steer towards the direction least obstructed.
Definition steerlib.qc:281
vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
Dodge a point NOTE: doesn't work well.
Definition steerlib.qc:142
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:211
float beamsweep(entity this, vector from, vector dir, float length, float step, float step_up, float step_down)
Definition steerlib.qc:309
vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
Definition steerlib.qc:346
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:181
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:99
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:156
vector steerlib_traceavoid(entity this, float pitch, float length)
Steer towards the direction least obstructed.
Definition steerlib.qc:239
vector steerlib_repel(entity this, vector point, float maximal_distance)
Move away from a point.
Definition steerlib.qc:88
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:124
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