1 /* --- ClampPointToSpace ---
\r
2 This function lets the bot know where to go to reach the next navnode.
\r
4 This is a highly optimized version, it used to also be direction based, so it
\r
5 was far more accurate. However, this accuracy was so slow, that it was a
\r
6 show-stopper. Now it merely takes the shortest path to the navnode. Due to this,
\r
7 navigation gets more and more inaccurate as the navnodes get larger.
\r
8 A regular indoor map doesn't require navnodes of the kind of size that would
\r
9 suffer from this. I hope to reinstate direction based some time in the future,
\r
10 if I get it fast enough.*/
\r
12 vector(vector point, entity current_space, entity goal_space) ClampPointToSpace =
\r
14 local float North, South, West, East, Up, Down;
\r
16 local vector ret_point, tvec;
\r
20 goal_space = current_space;
\r
22 North = min(current_space.origin_y + current_space.maxs_y, goal_space.origin_y + goal_space.maxs_y);
\r
23 South = max(current_space.origin_y + current_space.mins_y, goal_space.origin_y + goal_space.mins_y);
\r
24 East = min(current_space.origin_x + current_space.maxs_x, goal_space.origin_x + goal_space.maxs_x);
\r
25 West = max(current_space.origin_x + current_space.mins_x, goal_space.origin_x + goal_space.mins_x);
\r
26 Up = min(current_space.origin_z + current_space.maxs_z, goal_space.origin_z + goal_space.maxs_z);
\r
27 Down = max(current_space.origin_z + current_space.mins_z, goal_space.origin_z + goal_space.mins_z);
\r
29 f = (East + West) * 0.5;
\r
30 f2 = East - self.maxs_x;
\r
32 f2 = West - self.mins_x;
\r
34 f = (North + South) * 0.5;
\r
35 f2 = North - self.maxs_y;
\r
37 f2 = South - self.mins_y;
\r
39 f = (Up + Down) * 0.5;
\r
40 f2 = Up - self.maxs_z;
\r
42 f2 = Down - self.mins_z;
\r
45 ret_point_x = bound(West, point_x, East);
\r
46 ret_point_y = bound(South, point_y, North);
\r
47 ret_point_z = bound(Down, point_z, Up);
\r
49 e = goal_space.plane_chain;
\r
54 tvec_x = self.mins_x;
\r
56 tvec_y = self.mins_y;
\r
58 tvec_z = self.mins_z;
\r
60 f = tvec*e.mangle - goal_space.origin*e.mangle-e.delay;
\r
62 ret_point = ret_point - f*e.mangle;
\r
69 entity (entity navn, entity from, entity to) MatchOptPoint =
\r
78 t = navn.optp_chain;
\r
82 if (t.link0 == from)
\r
86 if (t.link1 == from)
\r
90 if (t.link2 == from)
\r
94 if (t.link3 == from)
\r
98 if (t.link4 == from)
\r
102 if (t.link5 == from)
\r
106 if (t.link6 == from)
\r
110 if (t.link7 == from)
\r
114 if (t.link8 == from)
\r
118 if (t.link9 == from)
\r
129 if (t.link10 == from)
\r
133 if (t.link11 == from)
\r
137 if (t.link12 == from)
\r
141 if (t.link13 == from)
\r
145 if (t.link14 == from)
\r
149 if (t.link15 == from)
\r
153 if (t.link16 == from)
\r
157 if (t.link17 == from)
\r
161 if (t.link18 == from)
\r
165 if (t.link19 == from)
\r
183 /* --- PopRoute ---
\r
184 Traverses the bots goal-list to get a new goal to travel towards*/
\r
188 self.goallist = self.goalcurrent;
\r
189 self.goalcurrent = self.link0;
\r
190 self.link0 = self.link1;
\r
191 self.link1 = self.link2;
\r
192 self.link2 = self.link3;
\r
193 self.link3 = self.link4;
\r
194 self.link4 = self.link5;
\r
195 self.link5 = self.link6;
\r
196 self.link6 = self.link7;
\r
197 self.link7 = self.link8;
\r
198 self.link8 = self.link9;
\r
199 self.link9 = self.link10;
\r
200 self.link10 = self.link11;
\r
201 self.link11 = self.link12;
\r
202 self.link12 = self.link13;
\r
203 self.link13 = self.link14;
\r
204 self.link14 = self.link15;
\r
205 self.link15 = self.link16;
\r
206 self.link16 = self.link17;
\r
207 self.link17 = self.link18;
\r
208 self.link18 = self.link19;
\r
209 self.link19 = world;
\r
210 if (cvar("urrebots_debug"))
\r
212 bprint(self.goalcurrent.classname);
\r
217 /* --- PushRoute ---
\r
218 Adds navnodes to the bots goal-list*/
\r
220 void(entity e) PushRoute =
\r
222 self.link19 = self.link18;
\r
223 self.link18 = self.link17;
\r
224 self.link17 = self.link16;
\r
225 self.link16 = self.link15;
\r
226 self.link15 = self.link14;
\r
227 self.link14 = self.link13;
\r
228 self.link13 = self.link12;
\r
229 self.link12 = self.link11;
\r
230 self.link11 = self.link10;
\r
231 self.link10 = self.link9;
\r
232 self.link9 = self.link8;
\r
233 self.link8 = self.link7;
\r
234 self.link7 = self.link6;
\r
235 self.link6 = self.link5;
\r
236 self.link5 = self.link4;
\r
237 self.link4 = self.link3;
\r
238 self.link3 = self.link2;
\r
239 self.link2 = self.link1;
\r
240 self.link1 = self.link0;
\r
241 self.link0 = self.goalcurrent;
\r
242 self.goalcurrent = e;
\r
245 /* --- ClearRoute ---
\r
246 Removes all goals from the bots goal-list*/
\r
248 void() ClearRoute =
\r
250 self.movepoint = nullvector;
\r
251 self.goalcurrent = world;
\r
252 self.link0 = world;
\r
253 self.link1 = world;
\r
254 self.link2 = world;
\r
255 self.link3 = world;
\r
256 self.link4 = world;
\r
257 self.link5 = world;
\r
258 self.link6 = world;
\r
259 self.link7 = world;
\r
260 self.link8 = world;
\r
261 self.link9 = world;
\r
262 self.link10 = world;
\r
263 self.link11 = world;
\r
264 self.link12 = world;
\r
265 self.link13 = world;
\r
266 self.link14 = world;
\r
267 self.link15 = world;
\r
268 self.link16 = world;
\r
269 self.link17 = world;
\r
270 self.link18 = world;
\r
271 self.link19 = world;
\r
274 /* --- FindCurrentNavNode ---
\r
275 Returns the current navnode at an origin with a size*/
\r
276 // FIXME: you can do better
\r
277 entity(vector org, vector minss, vector maxss) FindCurrentNavNode =
\r
279 local float f, f2, bad;
\r
281 local entity e, plane, best;
\r
287 if (boxesoverlap(org, org, e.origin + e.mins, e.origin + e.maxs))
\r
289 plane = e.plane_chain;
\r
292 f = org*plane.mangle - e.origin*plane.mangle-plane.delay;
\r
295 plane = plane.list;
\r
306 if (boxesoverlap(org + minss, org + maxss, e.origin + e.mins, e.origin + e.maxs))
\r
308 plane = e.plane_chain;
\r
312 if (plane.mangle_x < 0)
\r
314 if (plane.mangle_y < 0)
\r
316 if (plane.mangle_z < 0)
\r
319 f = tvec*plane.mangle - e.origin*plane.mangle-plane.delay;
\r
322 plane = plane.list;
\r
333 traceline(org, e.origin, TRUE, world);
\r
334 if (trace_fraction == 1)
\r
336 f = vlen(org - e.origin);
\r
348 /* --- ToPointInSpace ---
\r
349 Returns a direction towards a point, inside a navnode
\r
350 It prefers staying inside a navnode over going towards the point
\r
351 This function exists to allow the bot to drop off a platform and run
\r
352 under it, and to avoid getting stuck in corners*/
\r
354 vector(entity space, vector point) ToPointInSpace =
\r
357 vector tvec, ret_dir, intonavn, towardspoint;
\r
360 if (self.origin_x + self.mins_x <= space.origin_x + space.mins_x)
\r
361 intonavn = '1 0 0';
\r
362 else if (self.origin_x + self.maxs_x >= space.origin_x + space.maxs_x)
\r
363 intonavn = '-1 0 0';
\r
364 if (self.origin_y + self.mins_y <= space.origin_y + space.mins_y)
\r
365 intonavn += '0 1 0';
\r
366 else if (self.origin_y + self.maxs_y >= space.origin_y + space.maxs_y)
\r
367 intonavn += '0 -1 0';
\r
368 if (self.origin_z + self.mins_z <= space.origin_z + space.mins_z)
\r
369 intonavn += '0 0 1';
\r
370 else if (self.origin_z + self.maxs_z >= space.origin_z + space.maxs_z)
\r
371 intonavn += '0 0 -1';
\r
373 e = space.plane_chain;
\r
377 if (e.mangle_x < 0)
\r
378 tvec_x = self.mins_x;
\r
379 if (e.mangle_y < 0)
\r
380 tvec_y = self.mins_y;
\r
381 if (e.mangle_z < 0)
\r
382 tvec_z = self.mins_z;
\r
383 tvec += self.origin;
\r
384 f = tvec*e.mangle - space.origin*e.mangle-e.delay;
\r
386 intonavn = intonavn - e.mangle;
\r
389 intonavn = normalize(intonavn);
\r
391 towardspoint = normalize(point - self.origin);
\r
393 ret_dir = towardspoint;
\r
396 if ((intonavn_x < 0 && towardspoint_x < 0) || (intonavn_x > 0 && towardspoint_x > 0))
\r
397 ret_dir_x = towardspoint_x;
\r
399 ret_dir_x = intonavn_x;
\r
400 if ((intonavn_y < 0 && towardspoint_y < 0) || (intonavn_y > 0 && towardspoint_y > 0))
\r
401 ret_dir_y = towardspoint_y;
\r
403 ret_dir_y = intonavn_y;
\r
404 if ((intonavn_z < 0 && towardspoint_z < 0) || (intonavn_z > 0 && towardspoint_z > 0))
\r
405 ret_dir_z = towardspoint_z;
\r
407 ret_dir_z = intonavn_z;
\r