]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/gamec/urrebot_nn_use.c
i hope buttons can now be triggered by touch. i have no way to test that though...
[divverent/nexuiz.git] / data / qcsrc / server / gamec / urrebot_nn_use.c
1 /* --- ClampPointToSpace ---\r
2 This function lets the bot know where to go to reach the next navnode.\r
3 \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
11 \r
12 vector(vector point, entity current_space, entity goal_space) ClampPointToSpace =\r
13 {\r
14         local float North, South, West, East, Up, Down;\r
15         local float f, f2;\r
16         local vector ret_point, tvec;\r
17         local entity e;\r
18 \r
19         if (!goal_space)\r
20                 goal_space = current_space;\r
21 \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
28 \r
29         f = (East + West) * 0.5;\r
30         f2 = East - self.maxs_x;\r
31         East = max(f, f2);\r
32         f2 = West - self.mins_x;\r
33         West = min(f, f2);\r
34         f = (North + South) * 0.5;\r
35         f2 = North - self.maxs_y;\r
36         North = max(f, f2);\r
37         f2 = South - self.mins_y;\r
38         South = min(f, f2);\r
39         f = (Up + Down) * 0.5;\r
40         f2 = Up - self.maxs_z;\r
41         Up = max(f, f2);\r
42         f2 = Down - self.mins_z;\r
43         Down = min(f, f2);\r
44 \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
48 \r
49         e = goal_space.plane_chain;\r
50         while (e)\r
51         {\r
52                 tvec = self.maxs;\r
53                 if (e.mangle_x < 0)\r
54                         tvec_x = self.mins_x;\r
55                 if (e.mangle_y < 0)\r
56                         tvec_y = self.mins_y;\r
57                 if (e.mangle_z < 0)\r
58                         tvec_z = self.mins_z;\r
59                 tvec += ret_point;\r
60                 f = tvec*e.mangle - goal_space.origin*e.mangle-e.delay;\r
61                 if (f > 0)\r
62                         ret_point = ret_point - f*e.mangle;\r
63                 e = e.list;\r
64         }\r
65 \r
66         return ret_point;\r
67 };\r
68 \r
69 entity (entity navn, entity from, entity to) MatchOptPoint =\r
70 {\r
71         local float fr, go;\r
72         local entity t;\r
73 \r
74         if (!from)\r
75                 from = navn;\r
76         if (!to)\r
77                 to = navn;\r
78         t = navn.optp_chain;\r
79         while (t)\r
80         {\r
81                 fr = go = FALSE;\r
82                 if (t.link0 == from)\r
83                         fr = TRUE;\r
84                 if (t.link1)\r
85                 {\r
86                         if (t.link1 == from)\r
87                                 fr = TRUE;\r
88                         if (t.link2)\r
89                         {\r
90                                 if (t.link2 == from)\r
91                                         fr = TRUE;\r
92                                 if (t.link3)\r
93                                 {\r
94                                         if (t.link3 == from)\r
95                                                 fr = TRUE;\r
96                                         if (t.link4)\r
97                                         {\r
98                                                 if (t.link4 == from)\r
99                                                         fr = TRUE;\r
100                                                 if (t.link5)\r
101                                                 {\r
102                                                         if (t.link5 == from)\r
103                                                                 fr = TRUE;\r
104                                                         if (t.link6)\r
105                                                         {\r
106                                                                 if (t.link6 == from)\r
107                                                                         fr = TRUE;\r
108                                                                 if (t.link7)\r
109                                                                 {\r
110                                                                         if (t.link7 == from)\r
111                                                                                 fr = TRUE;\r
112                                                                         if (t.link8)\r
113                                                                         {\r
114                                                                                 if (t.link8 == from)\r
115                                                                                         fr = TRUE;\r
116                                                                                 if (t.link9)\r
117                                                                                 {\r
118                                                                                         if (t.link9 == from)\r
119                                                                                                 fr = TRUE;\r
120                                                                                 }\r
121                                                                         }\r
122                                                                 }\r
123                                                         }\r
124                                                 }\r
125                                         }\r
126                                 }\r
127                         }\r
128                 }\r
129                 if (t.link10 == from)\r
130                         fr = TRUE;\r
131                 if (t.link11)\r
132                 {\r
133                         if (t.link11 == from)\r
134                                 fr = TRUE;\r
135                         if (t.link12)\r
136                         {\r
137                                 if (t.link12 == from)\r
138                                         fr = TRUE;\r
139                                 if (t.link13)\r
140                                 {\r
141                                         if (t.link13 == from)\r
142                                                 fr = TRUE;\r
143                                         if (t.link14)\r
144                                         {\r
145                                                 if (t.link14 == from)\r
146                                                         fr = TRUE;\r
147                                                 if (t.link15)\r
148                                                 {\r
149                                                         if (t.link15 == from)\r
150                                                                 fr = TRUE;\r
151                                                         if (t.link16)\r
152                                                         {\r
153                                                                 if (t.link16 == from)\r
154                                                                         fr = TRUE;\r
155                                                                 if (t.link17)\r
156                                                                 {\r
157                                                                         if (t.link17 == from)\r
158                                                                                 fr = TRUE;\r
159                                                                         if (t.link18)\r
160                                                                         {\r
161                                                                                 if (t.link18 == from)\r
162                                                                                         fr = TRUE;\r
163                                                                                 if (t.link19)\r
164                                                                                 {\r
165                                                                                         if (t.link19 == from)\r
166                                                                                                 fr = TRUE;\r
167                                                                                 }\r
168                                                                         }\r
169                                                                 }\r
170                                                         }\r
171                                                 }\r
172                                         }\r
173                                 }\r
174                         }\r
175                 }\r
176                 if (fr && go)\r
177                         return t;\r
178                 t = t.list;\r
179         }\r
180         return world;\r
181 };\r
182 \r
183 /* --- PopRoute ---\r
184 Traverses the bots goal-list to get a new goal to travel towards*/\r
185 \r
186 void() PopRoute =\r
187 {\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
211         {\r
212                 bprint(self.goalcurrent.classname);\r
213                 bprint("\n");\r
214         }\r
215 };\r
216 \r
217 /* --- PushRoute ---\r
218 Adds navnodes to the bots goal-list*/\r
219 \r
220 void(entity e) PushRoute =\r
221 {\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
243 };\r
244 \r
245 /* --- ClearRoute ---\r
246 Removes all goals from the bots goal-list*/\r
247 \r
248 void() ClearRoute =\r
249 {\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
272 };\r
273 \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
278 {\r
279         local float f, f2, bad;\r
280         local vector tvec;\r
281         local entity e, plane, best;\r
282 \r
283         e = navnode_chain;\r
284         while (e)\r
285         {\r
286                 bad = FALSE;\r
287                 if (boxesoverlap(org, org, e.origin + e.mins, e.origin + e.maxs))\r
288                 {\r
289                         plane = e.plane_chain;\r
290                         while (plane)\r
291                         {\r
292                                 f = org*plane.mangle - e.origin*plane.mangle-plane.delay;\r
293                                 if (f > 0)\r
294                                         bad = TRUE;\r
295                                 plane = plane.list;\r
296                         }\r
297                         if (!bad)\r
298                                 return e;\r
299                 }\r
300                 e = e.list;\r
301         }\r
302         e = navnode_chain;\r
303         while (e)\r
304         {\r
305                 bad = FALSE;\r
306                 if (boxesoverlap(org + minss, org + maxss, e.origin + e.mins, e.origin + e.maxs))\r
307                 {\r
308                         plane = e.plane_chain;\r
309                         while (plane)\r
310                         {\r
311                                 tvec = maxss;\r
312                                 if (plane.mangle_x < 0)\r
313                                         tvec_x = minss_x;\r
314                                 if (plane.mangle_y < 0)\r
315                                         tvec_y = minss_y;\r
316                                 if (plane.mangle_z < 0)\r
317                                         tvec_z = minss_z;\r
318                                 tvec += org;\r
319                                 f = tvec*plane.mangle - e.origin*plane.mangle-plane.delay;\r
320                                 if (f > 0)\r
321                                         bad = TRUE;\r
322                                 plane = plane.list;\r
323                         }\r
324                         if (!bad)\r
325                                 return e;\r
326                 }\r
327                 e = e.list;\r
328         }\r
329         f2 = 10000000;\r
330         e = navnode_chain;\r
331         while (e)\r
332         {\r
333                 traceline(org, e.origin, TRUE, world);\r
334                 if (trace_fraction == 1)\r
335                 {\r
336                         f = vlen(org - e.origin);\r
337                         if (f < f2)\r
338                         {\r
339                                 best = e;\r
340                                 f2 = f;\r
341                         }\r
342                 }\r
343                 e = e.list;\r
344         }\r
345         return best;\r
346 };\r
347 \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
353 \r
354 vector(entity space, vector point) ToPointInSpace =\r
355 {\r
356         local float f;\r
357         vector tvec, ret_dir, intonavn, towardspoint;\r
358         local entity e;\r
359 \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
372 \r
373         e = space.plane_chain;\r
374         while (e)\r
375         {\r
376                 tvec = self.maxs;\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
385                 if (f > 0)\r
386                         intonavn = intonavn - e.mangle;\r
387                 e = e.list;\r
388         }\r
389         intonavn = normalize(intonavn);\r
390 \r
391         towardspoint = normalize(point - self.origin);\r
392         if (!intonavn)\r
393                 ret_dir = towardspoint;\r
394         else\r
395         {\r
396                 if ((intonavn_x < 0 && towardspoint_x < 0) || (intonavn_x > 0 && towardspoint_x > 0))\r
397                         ret_dir_x = towardspoint_x;\r
398                 else\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
402                 else\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
406                 else\r
407                         ret_dir_z = intonavn_z;\r
408         }\r
409         return ret_dir;\r
410 };