-
Notifications
You must be signed in to change notification settings - Fork 19
/
bot_navigate.cpp
300 lines (237 loc) · 10.1 KB
/
bot_navigate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/**
* RealBot : Artificial Intelligence
* Version : Work In Progress
* Author : Stefan Hendriks
* Url : http://realbot.bots-united.com
**
* DISCLAIMER
*
* History, Information & Credits:
* RealBot is based partially upon the HPB-Bot Template #3 by Botman
* Thanks to Ditlew (NNBot), Pierre Marie Baty (RACCBOT), Tub (RB AI PR1/2/3)
* Greg Slocum & Shivan (RB V1.0), Botman (HPB-Bot) and Aspirin (JOEBOT). And
* everybody else who helped me with this project.
* Storage of Visibility Table using BITS by Cheesemonster.
*
* Some portions of code are from other bots, special thanks (and credits) go
* to (in no specific order):
*
* Pierre Marie Baty
* Count-Floyd
*
* !! BOTS-UNITED FOREVER !!
*
* This project is open-source, it is protected under the GPL license;
* By using this source-code you agree that you will ALWAYS release the
* source-code with your project.
*
**/
#include <string.h>
#include <extdll.h>
#include <dllapi.h>
#include <meta_api.h>
#include <entity_state.h>
#include "bot.h"
#include "bot_weapons.h"
#include "bot_func.h"
#include "game.h"
#include "NodeMachine.h"
extern int mod_id;
extern edict_t *pHostEdict;
#define SCAN_RADIUS 45 // Radius to scan to prevent blocking with players
/**
* Given an angle, makes sure it wraps around properly
* @param angle
* @return
*/
float fixAngle(float angle) {
if (angle > 180) return (angle - 360);
if (angle < -180) return (angle + 360);
return angle;
}
void botFixIdealPitch(edict_t * pEdict) {
pEdict->v.idealpitch = fixAngle(pEdict->v.idealpitch);
}
void botFixIdealYaw(edict_t * pEdict) {
pEdict->v.ideal_yaw = fixAngle(pEdict->v.ideal_yaw);
}
bool BotCanJumpUp(cBot * pBot) {
// What I do here is trace 3 lines straight out, one unit higher than
// the highest normal jumping distance. I trace once at the center of
// the body, once at the right side, and once at the left side. If all
// three of these TraceLines don't hit an obstruction then I know the
// area to jump to is clear. I then need to trace from head level,
// above where the bot will jump to, downward to see if there is anything
// blocking the jump. There could be a narrow opening that the body
// will not fit into. These horizontal and vertical TraceLines seem
// to catch most of the problems with falsely trying to jump on something
// that the bot can not get onto.
TraceResult tr;
Vector v_jump, v_source, v_dest;
edict_t *pEdict = pBot->pEdict;
// convert current view angle to vectors for TraceLine math...
v_jump = pEdict->v.v_angle;
v_jump.x = 0; // reset pitch to 0 (level horizontally)
v_jump.z = 0; // reset roll to 0 (straight up and down)
UTIL_MakeVectors(v_jump);
// use center of the body first...
// maximum jump height is 45, so check one unit above that (46)
v_source = pEdict->v.origin + Vector(0, 0, -36 + MAX_JUMPHEIGHT);
v_dest = v_source + gpGlobals->v_forward * 24;
// trace a line forward at maximum jump height...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return FALSE;
// now check same height to one side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0,
-36 +
MAX_JUMPHEIGHT);
v_dest = v_source + gpGlobals->v_forward * 24;
// trace a line forward at maximum jump height...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return FALSE;
// now check same height on the other side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0,
-36 +
MAX_JUMPHEIGHT);
v_dest = v_source + gpGlobals->v_forward * 24;
// trace a line forward at maximum jump height...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return FALSE;
// now trace from head level downward to check for obstructions...
// start of trace is 24 units in front of bot, 72 units above head...
v_source = pEdict->v.origin + gpGlobals->v_forward * 24;
// offset 72 units from top of head (72 + 36)
v_source.z = v_source.z + 108;
// end point of trace is 99 units straight down from start...
// (99 is 108 minus the jump limit height which is 45 - 36 = 9)
// fix by stefan, max jump height is 63 , not 45! (using duck-jump)
// 108 - (63-36) = 81
v_dest = v_source + Vector(0, 0, -81);
// trace a line straight down toward the ground...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return FALSE;
// now check same height to one side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * 16 +
gpGlobals->v_forward * 24;
v_source.z = v_source.z + 108;
v_dest = v_source + Vector(0, 0, -81);
// trace a line straight down toward the ground...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return FALSE;
// now check same height on the other side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * -16 +
gpGlobals->v_forward * 24;
v_source.z = v_source.z + 108;
v_dest = v_source + Vector(0, 0, -81);
// trace a line straight down toward the ground...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return FALSE;
return TRUE;
}
bool BotCanDuckUnder(cBot * pBot) {
// What I do here is trace 3 lines straight out, one unit higher than
// the ducking height. I trace once at the center of the body, once
// at the right side, and once at the left side. If all three of these
// TraceLines don't hit an obstruction then I know the area to duck to
// is clear. I then need to trace from the ground up, 72 units, to make
// sure that there is something blocking the TraceLine. Then we know
// we can duck under it.
TraceResult tr;
Vector v_duck, v_source, v_dest;
edict_t *pEdict = pBot->pEdict;
// convert current view angle to vectors for TraceLine math...
v_duck = pEdict->v.v_angle;
v_duck.x = 0; // reset pitch to 0 (level horizontally)
v_duck.z = 0; // reset roll to 0 (straight up and down)
UTIL_MakeVectors(v_duck);
// use center of the body first...
// duck height is 36, so check one unit above that (37)
v_source = pEdict->v.origin + Vector(0, 0, -36 + 37);
v_dest = v_source + gpGlobals->v_forward * 24;
// trace a line forward at duck height...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return false;
// now check same height to one side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * 16 + Vector(0, 0, -36 + 37);
v_dest = v_source + gpGlobals->v_forward * 24;
// trace a line forward at duck height...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return false;
// now check same height on the other side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * -16 + Vector(0, 0,
-36 + 37);
v_dest = v_source + gpGlobals->v_forward * 24;
// trace a line forward at duck height...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace hit something, return FALSE
if (tr.flFraction < 1.0)
return false;
// now trace from the ground up to check for object to duck under...
// start of trace is 24 units in front of bot near ground...
v_source = pEdict->v.origin + gpGlobals->v_forward * 24;
v_source.z = v_source.z - 35; // offset to feet + 1 unit up
// end point of trace is 72 units straight up from start...
v_dest = v_source + Vector(0, 0, 72);
// trace a line straight up in the air...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace didn't hit something, return FALSE
if (tr.flFraction >= 1.0)
return false;
// now check same height to one side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * 16 +
gpGlobals->v_forward * 24;
v_source.z = v_source.z - 35; // offset to feet + 1 unit up
v_dest = v_source + Vector(0, 0, 72);
// trace a line straight up in the air...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace didn't hit something, return FALSE
if (tr.flFraction >= 1.0)
return false;
// now check same height on the other side of the bot...
v_source =
pEdict->v.origin + gpGlobals->v_right * -16 +
gpGlobals->v_forward * 24;
v_source.z = v_source.z - 35; // offset to feet + 1 unit up
v_dest = v_source + Vector(0, 0, 72);
// trace a line straight up in the air...
UTIL_TraceLine(v_source, v_dest, dont_ignore_monsters,
pEdict->v.pContainingEntity, &tr);
// if trace didn't hit something, return FALSE
if (tr.flFraction >= 1.0)
return false;
return true;
}