]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/gamec/urrebot_nn_use.qc
Forgot a couple of files
[divverent/nexuiz.git] / data / qcsrc / gamec / urrebot_nn_use.qc
1 /* --- ClampPointToNavNodes ---\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 /* --- PopRoute ---\r
70 Traverses the bots navnode-list to get a new navnode to travel towards*/\r
71 \r
72 void() PopRoute =\r
73 {\r
74         self.goalcurrent = self.link0;\r
75         self.link0 = self.link1;\r
76         self.link1 = self.link2;\r
77         self.link2 = self.link3;\r
78         self.link3 = self.link4;\r
79         self.link4 = self.link5;\r
80         self.link5 = self.link6;\r
81         self.link6 = self.link7;\r
82         self.link7 = self.link8;\r
83         self.link8 = self.link9;\r
84         self.link9 = self.link10;\r
85         self.link10 = self.link11;\r
86         self.link11 = self.link12;\r
87         self.link12 = self.link13;\r
88         self.link13 = self.link14;\r
89         self.link14 = self.link15;\r
90         self.link15 = self.link16;\r
91         self.link16 = self.link17;\r
92         self.link17 = self.link18;\r
93         self.link18 = self.link19;\r
94         self.link19 = world;\r
95         if (cvar("urrebots_debug"))\r
96         {\r
97                 bprint(self.goalcurrent.classname);\r
98                 bprint("\n");\r
99         }\r
100 };\r
101 \r
102 /* --- PushRoute ---\r
103 Adds navnodes to the bots navnode-list*/\r
104 \r
105 void(entity e) PushRoute =\r
106 {\r
107         self.link19 = self.link18;\r
108         self.link18 = self.link17;\r
109         self.link17 = self.link16;\r
110         self.link16 = self.link15;\r
111         self.link15 = self.link14;\r
112         self.link14 = self.link13;\r
113         self.link13 = self.link12;\r
114         self.link12 = self.link11;\r
115         self.link11 = self.link10;\r
116         self.link10 = self.link9;\r
117         self.link9 = self.link8;\r
118         self.link8 = self.link7;\r
119         self.link7 = self.link6;\r
120         self.link6 = self.link5;\r
121         self.link5 = self.link4;\r
122         self.link4 = self.link3;\r
123         self.link3 = self.link2;\r
124         self.link2 = self.link1;\r
125         self.link1 = self.link0;\r
126         self.link0 = self.goalcurrent;\r
127         self.goalcurrent = e;\r
128 };\r
129 \r
130 /* --- ClearRoute ---\r
131 Removes all navnodes from the bots navnode-list*/\r
132 \r
133 void() ClearRoute =\r
134 {\r
135         self.movepoint = nullvector;\r
136         self.goalcurrent = world;\r
137         self.link0 = world;\r
138         self.link1 = world;\r
139         self.link2 = world;\r
140         self.link3 = world;\r
141         self.link4 = world;\r
142         self.link5 = world;\r
143         self.link6 = world;\r
144         self.link7 = world;\r
145         self.link8 = world;\r
146         self.link9 = world;\r
147         self.link10 = world;\r
148         self.link11 = world;\r
149         self.link12 = world;\r
150         self.link13 = world;\r
151         self.link14 = world;\r
152         self.link15 = world;\r
153         self.link16 = world;\r
154         self.link17 = world;\r
155         self.link18 = world;\r
156         self.link19 = world;\r
157 };\r
158 \r
159 /* --- FindCurrentNavNode ---\r
160 Returns the current navnode at an origin with a size*/\r
161 // FIXME: you can do better\r
162 entity(vector org, vector minss, vector maxss) FindCurrentNavNode =\r
163 {\r
164         local float f, f2, bad;\r
165         local vector tvec;\r
166         local entity e, plane, best;\r
167 \r
168         e = navnode_chain;\r
169         while (e)\r
170         {\r
171                 bad = FALSE;\r
172                 if (boxesoverlap(org, org, e.origin + e.mins, e.origin + e.maxs))\r
173                 {\r
174                         plane = e.plane_chain;\r
175                         while (plane)\r
176                         {\r
177                                 f = org*plane.mangle - e.origin*plane.mangle-plane.delay;\r
178                                 if (f > 0)\r
179                                         bad = TRUE;\r
180                                 plane = plane.list;\r
181                         }\r
182                         if (!bad)\r
183                                 return e;\r
184                 }\r
185                 e = e.list;\r
186         }\r
187         e = navnode_chain;\r
188         while (e)\r
189         {\r
190                 bad = FALSE;\r
191                 if (boxesoverlap(org + minss, org + maxss, e.origin + e.mins, e.origin + e.maxs))\r
192                 {\r
193                         plane = e.plane_chain;\r
194                         while (plane)\r
195                         {\r
196                                 tvec = maxss;\r
197                                 if (plane.mangle_x < 0)\r
198                                         tvec_x = minss_x;\r
199                                 if (plane.mangle_y < 0)\r
200                                         tvec_y = minss_y;\r
201                                 if (plane.mangle_z < 0)\r
202                                         tvec_z = minss_z;\r
203                                 tvec += org;\r
204                                 f = tvec*plane.mangle - e.origin*plane.mangle-plane.delay;\r
205                                 if (f > 0)\r
206                                         bad = TRUE;\r
207                                 plane = plane.list;\r
208                         }\r
209                         if (!bad)\r
210                                 return e;\r
211                 }\r
212                 e = e.list;\r
213         }\r
214         f2 = 10000000;\r
215         e = navnode_chain;\r
216         while (e)\r
217         {\r
218                 traceline(org, e.origin, TRUE, world);\r
219                 if (trace_fraction == 1)\r
220                 {\r
221                         f = vlen(org - e.origin);\r
222                         if (f < f2)\r
223                         {\r
224                                 best = e;\r
225                                 f2 = f;\r
226                         }\r
227                 }\r
228                 e = e.list;\r
229         }\r
230         return best;\r
231 };\r
232 \r
233 /* --- ToPointInNavNode ---\r
234 Returns a direction towards a point, inside a navnode\r
235 It prefers staying inside a navnode over going towards the point\r
236 This function exists to allow the bot to drop off a platform and run\r
237 under it, and to avoid getting stuck in corners*/\r
238 \r
239 vector(entity space, vector point) ToPointInSpace =\r
240 {\r
241         local float f;\r
242         vector tvec, ret_dir, intonavn, towardspoint;\r
243         local entity e;\r
244 \r
245         if (self.origin_x + self.mins_x <= space.origin_x + space.mins_x)\r
246                 intonavn = '1 0 0';\r
247         else if (self.origin_x + self.maxs_x >= space.origin_x + space.maxs_x)\r
248                 intonavn = '-1 0 0';\r
249         if (self.origin_y + self.mins_y <= space.origin_y + space.mins_y)\r
250                 intonavn += '0 1 0';\r
251         else if (self.origin_y + self.maxs_y >= space.origin_y + space.maxs_y)\r
252                 intonavn += '0 -1 0';\r
253         if (self.origin_z + self.mins_z <= space.origin_z + space.mins_z)\r
254                 intonavn += '0 0 1';\r
255         else if (self.origin_z + self.maxs_z >= space.origin_z + space.maxs_z)\r
256                 intonavn += '0 0 -1';\r
257 \r
258         e = space.plane_chain;\r
259         while (e)\r
260         {\r
261                 tvec = self.maxs;\r
262                 if (e.mangle_x < 0)\r
263                         tvec_x = self.mins_x;\r
264                 if (e.mangle_y < 0)\r
265                         tvec_y = self.mins_y;\r
266                 if (e.mangle_z < 0)\r
267                         tvec_z = self.mins_z;\r
268                 tvec += self.origin;\r
269                 f = tvec*e.mangle - space.origin*e.mangle-e.delay;\r
270                 if (f > 0)\r
271                         intonavn = intonavn - e.mangle;\r
272                 e = e.list;\r
273         }\r
274         intonavn = normalize(intonavn);\r
275 \r
276         towardspoint = normalize(point - self.origin);\r
277         if (!intonavn)\r
278                 ret_dir = towardspoint;\r
279         else\r
280         {\r
281                 if ((intonavn_x < 0 && towardspoint_x < 0) || (intonavn_x > 0 && towardspoint_x > 0))\r
282                         ret_dir_x = towardspoint_x;\r
283                 else\r
284                         ret_dir_x = intonavn_x;\r
285                 if ((intonavn_y < 0 && towardspoint_y < 0) || (intonavn_y > 0 && towardspoint_y > 0))\r
286                         ret_dir_y = towardspoint_y;\r
287                 else\r
288                         ret_dir_y = intonavn_y;\r
289                 if ((intonavn_z < 0 && towardspoint_z < 0) || (intonavn_z > 0 && towardspoint_z > 0))\r
290                         ret_dir_z = towardspoint_z;\r
291                 else\r
292                         ret_dir_z = intonavn_z;\r
293         }\r
294         return ret_dir;\r
295 };