1 /* --- UrreBotInfront ---
\r
2 I could've used id's infront, but as it wasn't in LordHavoc's multiplayer
\r
3 only mod, I had to add a new one, named something else to not mess with people's
\r
4 possible/eventual plugin-attempts*/
\r
6 float(entity targ) UrreBotInfront =
\r
11 makevectors (self.angles);
\r
12 vec = normalize (targ.origin - self.origin);
\r
13 dot = vec * v_forward;
\r
20 /* --- UrreBotEvalTargets ---
\r
21 Enemies are found and lost using this function
\r
22 If the bot can't see his enemy for 3 seconds, it is dropped*/
\r
24 void() UrreBotEvalTargets =
\r
26 local float old, new;
\r
27 local vector v1, v2;
\r
30 v1 = self.origin + self.view_ofs;
\r
34 if (self.enemy.health >= 1 && !self.enemy.deadflag)
\r
36 if (self.evaltime <= time)
\r
38 self.evaltime = time + 3;
\r
39 v2 = (self.enemy.absmin + self.enemy.absmax) * 0.5;
\r
40 traceline(v1, v2, TRUE, self);
\r
41 if (trace_fraction < 1)
\r
48 e = findradius(v1, 1500);
\r
51 if (!(e.flags & FL_NOTARGET) || e.killcount != -666) // -666 is spec/obs
\r
52 if (!(cvar("teamplay") && self.team == e.team)) // don't target teammates
\r
53 if (e.flags & FL_CLIENT)
\r
56 if (UrreBotInfront(e))
\r
59 v2 = (e.absmin + e.absmax) * 0.5;
\r
60 traceline(v1, v2, TRUE, self);
\r
61 if (trace_fraction == 1 || trace_ent == e)
\r
65 old = vlen(self.origin - (self.enemy.absmin + self.enemy.absmax)*0.5);
\r
66 new = vlen(self.origin - v2);
\r
78 if (self.goalcurrent.sflags & S_DOOR)
\r
79 e = self.goalcurrent.goalentity;
\r
80 else if (self.link0.sflags & S_DOOR)
\r
81 e = self.link0.goalentity;
\r
86 /* --- UrreBotAim ---
\r
87 Very crude and simple aiming, with some leading capability*/
\r
91 local float dist, skeel;
\r
92 local vector v, desiredang, testang, diffang;
\r
94 skeel = bound(1, skill, 10);
\r
96 // get the desired angles to aim at
\r
99 v = (self.enemy.absmin + self.enemy.absmax) * 0.5;
\r
100 if (self.enemy.classname == "door")
\r
102 else if (self.aimtime <= time)
\r
104 self.aimtime = time + 0.3;
\r
105 traceline(self.origin + self.view_ofs, (self.enemy.absmin + self.enemy.absmax) * 0.5, TRUE, self);
\r
106 if (trace_fraction == 1)
\r
108 self.aimpoint = v + self.enemy.velocity*vlen(self.origin - v)*self.lead;
\r
109 self.aimpoint = self.aimpoint + randomvec()*max(0, 120 - skeel*12);
\r
112 desiredang = vectoangles(self.aimpoint - (self.origin + self.view_ofs));
\r
115 desiredang = vectoangles(self.velocity);
\r
116 desiredang_x = 0-desiredang_x;
\r
118 if (desiredang_y <= -180)
\r
119 desiredang_y = desiredang_y + 360;
\r
120 else if (desiredang_y >= 180)
\r
121 desiredang_y = desiredang_y - 360;
\r
122 if (desiredang_x <= -180)
\r
123 desiredang_x = desiredang_x + 360;
\r
124 else if (desiredang_x >= 180)
\r
125 desiredang_x = desiredang_x - 360;
\r
127 // calculate turn angles
\r
128 testang = desiredang - self.v_angle;
\r
132 dist = vlen(testang * ((skeel + 1) * frametime));
\r
133 if (vlen(normalize(testang) * skeel) > dist)
\r
135 diffang = normalize(testang) * skeel;
\r
136 dist = vlen(normalize(testang) * skeel);
\r
139 diffang = testang * ((skeel + 1) * frametime);
\r
140 if (dist > vlen(testang))
\r
143 self.v_angle = self.v_angle + diffang;
\r
144 self.angles_y = self.v_angle_y;
\r
147 /* --- UrreBotMove ---
\r
148 Moves towards the closest point on the next goal in the bots list,
\r
149 which can be a navnode, item or domination point*/
\r
151 void() UrreBotMove =
\r
153 local float f, bad;
\r
154 local vector dir, tvec;
\r
155 local entity plane;
\r
159 if (boxesoverlap(self.origin + self.mins, self.origin + self.maxs, self.link0.origin + self.link0.mins, self.link0.origin + self.link0.maxs))
\r
161 plane = self.link0.plane_chain;
\r
165 if (plane.mangle_x < 0)
\r
166 tvec_x = self.mins_x;
\r
167 if (plane.mangle_y < 0)
\r
168 tvec_y = self.mins_y;
\r
169 if (plane.mangle_z < 0)
\r
170 tvec_z = self.mins_z;
\r
171 tvec += self.origin;
\r
172 f = tvec*plane.mangle - self.link0.origin*plane.mangle-plane.delay;
\r
175 plane = plane.list;
\r
180 if (self.goalcurrent.sflags & S_TELEPORT)
\r
181 self.movepoint = self.goalcurrent.origin;
\r
183 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.link0);
\r
186 else if (((self.goalcurrent.sflags & S_TOUCH) && boxesoverlap(self.origin + self.mins, self.origin + self.maxs, self.goalcurrent.origin + self.goalcurrent.mins, self.goalcurrent.origin + self.goalcurrent.maxs)) || boxenclosed(self.origin + self.mins, self.origin + self.maxs, self.goalcurrent.origin + self.goalcurrent.mins, self.goalcurrent.origin + self.goalcurrent.maxs))
\r
188 plane = self.goalcurrent.plane_chain;
\r
192 if (plane.mangle_x < 0)
\r
193 tvec_x = self.mins_x;
\r
194 if (plane.mangle_y < 0)
\r
195 tvec_y = self.mins_y;
\r
196 if (plane.mangle_z < 0)
\r
197 tvec_z = self.mins_z;
\r
198 tvec += self.origin;
\r
199 f = tvec*plane.mangle - self.goalcurrent.origin*plane.mangle-plane.delay;
\r
202 plane = plane.list;
\r
207 if (self.goalcurrent.sflags & S_TELEPORT)
\r
208 self.movepoint = self.goalcurrent.origin;
\r
210 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.goalcurrent);
\r
211 if (self.movepoint == '0 0 0')
\r
213 self.strat_me = TRUE;
\r
214 UrreBotPath(minisearch_distance);
\r
221 if (!self.goalcurrent || ((self.goalcurrent.flags & FL_ITEM) && !self.goalcurrent.solid) || (self.goalcurrent.classname == "dom_controlpoint" && self.goalcurrent.enemy.team == self.team))
\r
223 self.strat_me = TRUE;
\r
224 UrreBotPath(minisearch_distance);
\r
226 self.movepoint = ClampPointToSpace(self.origin, self.goalcurrent, self.goalcurrent);
\r
228 dir = normalize(ToPointInSpace(self.goalcurrent, self.movepoint));
\r
229 dir = dir * sv_maxspeed;
\r
230 makevectors(self.v_angle);
\r
231 self.movement_x = dir * v_forward;
\r
232 self.movement_y = dir * v_right;
\r
233 self.movement_z = dir * v_up;
\r
236 /* --- UrreBotImpulses ---
\r
237 Returns the impulse for the best weapon in the given situation*/
\r
239 float() UrreBotImpulses =
\r
242 local float cells, rockets, nails, shells;
\r
245 if (random() < 0.5)
\r
248 dist = 400; // we like nex and mortar
\r
251 v = (self.enemy.absmin + self.enemy.absmax) * 0.5;
\r
252 dist = vlen(v - self.origin);
\r
255 cells = self.ammo_cells;
\r
256 rockets = self.ammo_rockets;
\r
257 nails = self.ammo_nails;
\r
258 shells = self.ammo_shells;
\r
260 if (dist > 300 && cells && (self.items & IT_NEX))
\r
268 if (self.items & IT_GRENADE_LAUNCHER)
\r
270 self.lead = 1 / cvar("g_balance_grenadelauncher_speed");
\r
271 return WEP_GRENADE_LAUNCHER;
\r
273 if (self.items & IT_HAGAR)
\r
275 self.lead = 1 / cvar("g_balance_hagar_speed");
\r
278 else if (self.items & IT_ROCKET_LAUNCHER)
\r
280 self.lead = 1 / cvar("g_balance_rocketlauncher_speed");
\r
281 return WEP_ROCKET_LAUNCHER;
\r
286 if (self.items & IT_ELECTRO)
\r
288 self.lead = 1 / cvar("g_balance_electro_speed");
\r
289 return WEP_ELECTRO;
\r
291 else if (self.items & IT_CRYLINK)
\r
293 self.lead = 1 / cvar("g_balance_crylink_speed");
\r
294 return WEP_CRYLINK;
\r
299 if (self.items & IT_UZI)
\r
307 if (self.items & IT_SHOTGUN)
\r
310 return WEP_SHOTGUN;
\r
313 self.lead = 1 / cvar("g_balance_laser_speed");
\r
318 Used for some debugging, occasionally*/
\r
320 float BT_LIGHTNING = 0;
\r
322 void(float beamtype, vector bmins, vector bmaxs) BeamBox =
\r
324 local vector v1, v2;
\r
329 if (beamtype == BT_LIGHTNING)
\r
330 te_lightning1(world, v1, v2);
\r
332 te_beam(world, v1, v2);
\r
336 if (beamtype == BT_LIGHTNING)
\r
337 te_lightning1(world, v1, v2);
\r
339 te_beam(world, v1, v2);
\r
343 if (beamtype == BT_LIGHTNING)
\r
344 te_lightning1(world, v1, v2);
\r
346 te_beam(world, v1, v2);
\r
350 if (beamtype == BT_LIGHTNING)
\r
351 te_lightning1(world, v1, v2);
\r
353 te_beam(world, v1, v2);
\r
357 if (beamtype == BT_LIGHTNING)
\r
358 te_lightning1(world, v1, v2);
\r
360 te_beam(world, v1, v2);
\r
364 if (beamtype == BT_LIGHTNING)
\r
365 te_lightning1(world, v1, v2);
\r
367 te_beam(world, v1, v2);
\r
373 if (beamtype == BT_LIGHTNING)
\r
374 te_lightning1(world, v1, v2);
\r
376 te_beam(world, v1, v2);
\r
382 if (beamtype == BT_LIGHTNING)
\r
383 te_lightning1(world, v1, v2);
\r
385 te_beam(world, v1, v2);
\r
391 if (beamtype == BT_LIGHTNING)
\r
392 te_lightning1(world, v1, v2);
\r
394 te_beam(world, v1, v2);
\r
400 if (beamtype == BT_LIGHTNING)
\r
401 te_lightning1(world, v1, v2);
\r
403 te_beam(world, v1, v2);
\r
408 if (beamtype == BT_LIGHTNING)
\r
409 te_lightning1(world, v1, v2);
\r
411 te_beam(world, v1, v2);
\r
416 if (beamtype == BT_LIGHTNING)
\r
417 te_lightning1(world, v1, v2);
\r
419 te_beam(world, v1, v2);
\r
422 /* --- UrreBotPath ---
\r
423 Marks route and determines which goal is the most useful to head for*/
\r
425 void(float sdist) UrreBotPath =
\r
427 local float f, f2, f3;
\r
428 local entity e, best;
\r
434 e = findchainflags(flags, FL_ITEM);
\r
458 best = best.goallist;
\r
468 f = ceil(random() * navnodes);
\r
486 best = best.goallist;
\r
491 /* --- UrreBotThink ---
\r
492 In this version, UrreBot does a path search based on timer and turn
\r
493 Then it aims, moves, checks if it's stuck, finds/loses stuff to shoot at,
\r
494 picks best weapon, shoots, and optionally displays debug stuff, in that
\r
496 Aiming must happen before movement, because movement depends on angles
\r
497 He does not yet have any combat movement*/
\r
499 void() UrreBotThink =
\r
504 self.movement = '0 0 0';
\r
509 if (cvar("teamplay") && self.team == self.enemy.team) // don't return fire if hit by a teammate
\r
510 self.enemy = world;
\r
515 if (random() < 0.2)
\r
520 if (strategytime <= time)
\r
521 if (strategytoken == self)
\r
523 strategytime = time + urrebots_strategytime;
\r
524 strategytoken = self.list;
\r
525 if (!strategytoken)
\r
526 strategytoken = urrebot_chain;
\r
529 self.strat_me = FALSE;
\r
530 UrreBotPath(stratsearch_distance);
\r
537 if (self.camptime <= time)
\r
539 if (vlen(self.origin - self.campcheck) < 200) // stuckage avoidage
\r
541 self.camptime = time + urrebots;
\r
542 self.strat_me = TRUE;
\r
543 UrreBotPath(minisearch_distance);
\r
547 self.campcheck = self.origin;
\r
548 self.camptime = time + 2;
\r
552 if (self.combattime <= time)
\r
554 self.combattime = time + urrebots_combattime;
\r
555 UrreBotEvalTargets();
\r
556 self.impulse = UrreBotImpulses();
\r
561 makevectors (self.v_angle);
\r
562 v = self.origin + '0 0 16';
\r
563 f = vlen(v - self.aimpoint);
\r
564 traceline (v, v + v_forward*f, FALSE, self);
\r
565 if (vlen(trace_endpos - self.aimpoint) < 150)
\r
569 if (random() < 0.3)
\r
576 if (cvar("urrebots_debug"))
\r
578 te_lightning1(self, self.origin, self.movepoint);
\r
579 if (!self.goalcurrent)
\r
581 bprint(self.netname);
\r
582 bprint(" has no goalcurrent\n");
\r