1 /***********************************************
4 * "Because I ain't no Ghandi code" *
6 ***********************************************/
10 This program is in the Public Domain. My crack legal
11 team would like to add:
13 RYAN "FRIKAC" SMITH IS PROVIDING THIS SOFTWARE "AS IS"
14 AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE
15 ACCURACY, CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR
16 FUNCTIONING OF THIS SOFTWARE AND/OR DOCUMENTATION. IN
17 NO EVENT WILL RYAN "FRIKAC" SMITH BE LIABLE FOR ANY
18 GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL,
19 EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF RYAN "FRIKAC"
20 SMITH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
21 DAMAGES, IRRESPECTIVE OF THE CAUSE OF SUCH DAMAGES.
23 You accept this software on the condition that you
24 indemnify and hold harmless Ryan "FrikaC" Smith from
25 any and all liability or damages to third parties,
26 including attorney fees, court costs, and other
27 related costs and expenses, arising out of your use
28 of this software irrespective of the cause of said
31 The export from the United States or the subsequent
32 reexport of this software is subject to compliance
33 with United States export control and munitions
34 control restrictions. You agree that in the event you
35 seek to export this software, you assume full
36 responsibility for obtaining all necessary export
37 licenses and approvals and for assuring compliance
38 with applicable reexport restrictions.
40 Any reproduction of this software must contain
41 this notice in its entirety.
47 float(entity e) bot_size_player =
51 sz = e.health + e.armorvalue * e.armortype;
52 if (e.weapon == WEP_ROCKET_LAUNCHER)
54 else if (e.weapon == WEP_HAGAR)
56 else if (e.weapon == WEP_NEX)
58 else if (e.weapon == WEP_CRYLINK)
60 else if (e.weapon == WEP_ELECTRO)
62 else if (e.weapon == WEP_GRENADE_LAUNCHER)
64 else if (e.weapon == WEP_UZI)
66 else if (e.weapon == WEP_SHOTGUN)
68 else if (e.weapon == WEP_LASER)
70 if (e.items & 4194304) // Quad
72 if (e.items & 1048576) // Invul
74 if (e.items & 524288) // Invis
79 void() bot_dodge_stuff =
82 local float foedist, avdist, scandist, foesz, flen, tsz;
85 if (waypoint_mode > WM_LOADED)
93 v = self.origin - realorigin(self.enemy);
95 foesz = bot_size_player(self.enemy);
104 foe = find(world, classname, "grenade");
107 flen = vlen(foe.origin - self.origin);
113 foe = find(foe, classname, "grenade");
117 foe = find(world, classname, "missile");
120 if (foe.owner != self)
122 flen = vlen(foe.origin - self.origin);
129 foe = find(foe, classname, "missile");
133 foe = find(world, classname, "spike");
136 if (foe.owner != self)
138 flen = vlen(foe.origin - self.origin);
145 foe = find(foe, classname, "spike");
153 foe = findradius(self.origin, foedist);
156 if(foe.flags & FL_MONSTER)
160 flen = vlen(foe.origin - self.origin);
163 tsz = bot_size_player(foe);
187 if (foe.modelindex != 0)
191 if (!(teamplay && self.team == foe.team))
193 flen = vlen(foe.origin - self.origin);
196 tsz = bot_size_player(foe);
199 if (fov(foe) || foe.b_sound > time || self.b_skill == 3)
204 foedist = vlen(foe.origin - self.origin);
222 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
226 _x "sweet spot range" - try to maintain this range if possible
227 _y minimum range bot can be to be effective (rl/gl) (move away)
228 _z maximum range bot can be to be effective (lg/axe) (move in)
229 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
232 vector(float wep) weapon_range =
234 if (wep == WEP_LASER) // IT_AXE
236 else if (wep == WEP_SHOTGUN) // IT_SHOTGUN
237 return '128 0 99999';
238 else if (wep == WEP_CRYLINK) // IT_SUPER_SHOTGUN
239 return '128 0 99999';
240 else if (wep == WEP_UZI) // IT_NAILGUN
242 else if (wep == WEP_HAGAR) // IT_SUPER_NAILGUN
243 return '180 48 3000';
244 else if (wep == WEP_GRENADE_LAUNCHER) // IT_GRENADE_LAUNCHER
245 return '180 48 3000';
246 else if (wep == WEP_ELECTRO) // IT_ROCKET_LAUNCHER
247 return '180 48 3000';
248 else if (wep == WEP_ROCKET_LAUNCHER) // IT_ROCKET_LAUNCHER
249 return '180 48 3000';
250 else if (wep == WEP_NEX) // IT_LIGHTNING
251 return '350 0 99999';
254 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
258 Pick a weapon based on range / ammo
260 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
263 void(float brange) bot_weapon_switch =
265 local float it, flag, pulse;
268 it = self.items & 127;
272 if ((self.ammo_rockets >= 1) && (it & 32))
277 else if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & 64))
282 else if(self.ammo_nails >= 2 && (it & 8))
287 else if ((self.ammo_rockets >= 1) && (it & 16))
292 else if(self.ammo_shells >= 2 && (it & 2))
297 else if(self.ammo_nails >= 1 && (it & 4))
302 else if(self.ammo_shells >= 1 && (it & 1))
310 self.impulse = pulse;
317 self.impulse = pulse;
321 v = weapon_range(flag);
322 if (brange < v_y || brange > v_z)
327 self.impulse = pulse;
335 // quick little function to stop making him shoot the wrong way ! Argh
337 g = angcomp(self.v_angle_x, self.b_angle_x);
339 return; // argh, too far away
340 g = angcomp(self.v_angle_y, self.b_angle_y);
342 return; // not again!
347 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
351 This is the core of the bot's thinking when
354 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
357 void() bot_fight_style =
359 local vector v, v1, v2, org;
360 local float foedist, mysz, foesz;
363 if (self.enemy.health <= 0)
368 else if (!self.enemy.takedamage)
373 else if (!fisible(self.enemy))
379 org = realorigin(self.enemy);
380 makevectors(self.v_angle);
382 // decide if I should shoot
384 foedist = vlen(org - self.origin);
385 v = weapon_range(self.weapon);
386 if (foedist > v_y && foedist < v_z)
388 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * v_z, FALSE, self);
389 if (vlen(trace_endpos - (self.origin + self.view_ofs)) >= v_y)
391 // try to avoid shooting teammates
392 if (trace_ent.classname == "player")
393 if ((trace_ent.team == self.team && teamplay) || (coop))
399 bot_weapon_switch(foedist);
401 if (!(self.b_aiflags & (AI_PRECISION | AI_BLIND | AI_OBSTRUCTED)))
403 foesz = bot_size_player(self.enemy);
404 mysz = bot_size_player(self) + 5;
423 if (self.avoid.velocity)
424 v = self.avoid.velocity;
426 v = normalize(self.avoid.origin - self.origin);
431 foedist = vlen(self.avoid.origin - (self.origin + v1));
432 if (foedist < vlen(self.avoid.origin - (self.origin + v2)))
437 else if (!self.enemy.flags & FL_MONSTER)
439 if (foedist + 32 < v_x)
440 frik_walkmove(self.origin - org);
441 else if (foedist - 32 > v_x)
442 frik_walkmove(org - self.origin);
443 else if (self.wallhug)
444 frik_walkmove(v_right);
446 frik_walkmove(v_right * -1);
451 foesz = bot_size_player(self.enemy);
452 mysz = bot_size_player(self) + 5;
458 self.keys = self.keys & 960;