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
70 Traverses the bots goal-list to get a new goal to travel towards*/
\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
97 bprint(self.goalcurrent.classname);
\r
102 /* --- PushRoute ---
\r
103 Adds navnodes to the bots goal-list*/
\r
105 void(entity e) PushRoute =
\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
130 /* --- ClearRoute ---
\r
131 Removes all goals from the bots goal-list*/
\r
133 void() ClearRoute =
\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
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
164 local float f, f2, bad;
\r
166 local entity e, plane, best;
\r
172 if (boxesoverlap(org, org, e.origin + e.mins, e.origin + e.maxs))
\r
174 plane = e.plane_chain;
\r
177 f = org*plane.mangle - e.origin*plane.mangle-plane.delay;
\r
180 plane = plane.list;
\r
191 if (boxesoverlap(org + minss, org + maxss, e.origin + e.mins, e.origin + e.maxs))
\r
193 plane = e.plane_chain;
\r
197 if (plane.mangle_x < 0)
\r
199 if (plane.mangle_y < 0)
\r
201 if (plane.mangle_z < 0)
\r
204 f = tvec*plane.mangle - e.origin*plane.mangle-plane.delay;
\r
207 plane = plane.list;
\r
218 traceline(org, e.origin, TRUE, world);
\r
219 if (trace_fraction == 1)
\r
221 f = vlen(org - e.origin);
\r
233 /* --- ToPointInSpace ---
\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
239 vector(entity space, vector point) ToPointInSpace =
\r
242 vector tvec, ret_dir, intonavn, towardspoint;
\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
258 e = space.plane_chain;
\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
271 intonavn = intonavn - e.mangle;
\r
274 intonavn = normalize(intonavn);
\r
276 towardspoint = normalize(point - self.origin);
\r
278 ret_dir = towardspoint;
\r
281 if ((intonavn_x < 0 && towardspoint_x < 0) || (intonavn_x > 0 && towardspoint_x > 0))
\r
282 ret_dir_x = towardspoint_x;
\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
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
292 ret_dir_z = intonavn_z;
\r