]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/bot_fight.c
Added new GameC with class selection and random class selection working
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / bot_fight.c
1 /***********************************************\r
2 *                                              *\r
3 *             FrikBot Fight Code               *\r
4 *      "Because I ain't no Ghandi code"        *\r
5 *                                              *\r
6 ***********************************************/\r
7 \r
8 /*\r
9 \r
10 This program is in the Public Domain. My crack legal\r
11 team would like to add:\r
12 \r
13 RYAN "FRIKAC" SMITH IS PROVIDING THIS SOFTWARE "AS IS"\r
14 AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE\r
15 ACCURACY, CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR\r
16 FUNCTIONING OF THIS SOFTWARE AND/OR DOCUMENTATION. IN\r
17 NO EVENT WILL RYAN "FRIKAC" SMITH BE LIABLE FOR ANY\r
18 GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL,\r
19 EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF RYAN "FRIKAC"\r
20 SMITH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\r
21 DAMAGES, IRRESPECTIVE OF THE CAUSE OF SUCH DAMAGES.\r
22 \r
23 You accept this software on the condition that you\r
24 indemnify and hold harmless Ryan "FrikaC" Smith from\r
25 any and all liability or damages to third parties,\r
26 including attorney fees, court costs, and other\r
27 related costs and expenses, arising out of your use\r
28 of this software irrespective of the cause of said\r
29 liability.\r
30 \r
31 The export from the United States or the subsequent\r
32 reexport of this software is subject to compliance\r
33 with United States export control and munitions\r
34 control restrictions. You agree that in the event you\r
35 seek to export this software, you assume full\r
36 responsibility for obtaining all necessary export\r
37 licenses and approvals and for assuring compliance\r
38 with applicable reexport restrictions.\r
39 \r
40 Any reproduction of this software must contain\r
41 this notice in its entirety.\r
42 \r
43 */\r
44 \r
45 .entity avoid;\r
46 \r
47 float(entity e) bot_size_player =\r
48 {\r
49         local float sz;\r
50 \r
51         sz = e.health + e.armorvalue * e.armortype;\r
52         if (e.weapon == WEP_ROCKET_LAUNCHER)\r
53                 sz = sz + 60;\r
54         else if (e.weapon == WEP_HAGAR)\r
55                 sz = sz + 60;\r
56         else if (e.weapon == WEP_NEX)\r
57                 sz = sz + 60;\r
58         else if (e.weapon == WEP_CRYLINK)\r
59                 sz = sz + 50;\r
60         else if (e.weapon == WEP_ELECTRO)\r
61                 sz = sz + 50;\r
62         else if (e.weapon == WEP_GRENADE_LAUNCHER)\r
63                 sz = sz + 40;\r
64         else if (e.weapon == WEP_UZI)\r
65                 sz = sz + 40;\r
66         else if (e.weapon == WEP_SHOTGUN)\r
67                 sz = sz + 10;\r
68         else if (e.weapon == WEP_LASER)\r
69                 sz = sz - 50;\r
70         if (e.items & 4194304) // Quad\r
71                 sz = sz + 200;\r
72         if (e.items & 1048576) // Invul\r
73                 sz = sz + 300;\r
74         if (e.items & 524288) // Invis\r
75                 sz = sz + 250;\r
76         return sz;\r
77 };\r
78 \r
79 void() bot_dodge_stuff =\r
80 {\r
81         local entity foe;\r
82         local float foedist, avdist, foesz, flen, tsz;\r
83         local vector v;\r
84 \r
85         if (waypoint_mode > WM_LOADED)\r
86                 return;\r
87 \r
88         self.avoid = world;\r
89 \r
90 \r
91         if (self.enemy)\r
92         {\r
93                 v = self.origin - realorigin(self.enemy);\r
94                 foedist = vlen(v);\r
95                 foesz = bot_size_player(self.enemy);\r
96         }\r
97         else\r
98         {\r
99                 foedist = 3000;\r
100                 foesz = 9999999;\r
101         }\r
102         avdist = 256;\r
103 \r
104         foe = find(world, classname, "grenade");\r
105         while(foe)\r
106         {\r
107                 flen = vlen(foe.origin - self.origin);\r
108                 if (flen < avdist)\r
109                 {\r
110                         avdist = flen;\r
111                         self.avoid = foe;\r
112                 }\r
113                 foe = find(foe, classname, "grenade");\r
114         }\r
115         if (!self.avoid)\r
116         {\r
117                 foe = find(world, classname, "missile");\r
118                 while(foe)\r
119                 {\r
120                         if (foe.owner != self)\r
121                         {\r
122                                 flen = vlen(foe.origin - self.origin);\r
123                                 if (flen < avdist)\r
124                                 {\r
125                                         avdist = flen;\r
126                                         self.avoid = foe;\r
127                                 }\r
128                         }\r
129                         foe = find(foe, classname, "missile");\r
130                 }\r
131                 if (!self.avoid)\r
132                 {\r
133                         foe = find(world, classname, "spike");\r
134                         while(foe)\r
135                         {\r
136                                 if (foe.owner != self)\r
137                                 {\r
138                                         flen = vlen(foe.origin - self.origin);\r
139                                         if (flen < avdist)\r
140                                         {\r
141                                                 avdist = flen;\r
142                                                 self.avoid = foe;\r
143                                         }\r
144                                 }\r
145                                 foe = find(foe, classname, "spike");\r
146                         }\r
147                 }\r
148         }\r
149         if (coop)\r
150         {\r
151                 if (!self.enemy)\r
152                 {\r
153                         foe = findradius(self.origin, foedist);\r
154                         while(foe)\r
155                         {\r
156                                 if(foe.flags & FL_MONSTER)\r
157                                 {\r
158                                         if(foe.health > 0)\r
159                                         {\r
160                                                 flen = vlen(foe.origin - self.origin);\r
161                                                 if (flen < foedist)\r
162                                                 {\r
163                                                         tsz = bot_size_player(foe);\r
164                                                         if (tsz < foesz)\r
165                                                         {\r
166                                                                 if (fisible(foe))\r
167                                                                 {\r
168                                                                         self.enemy = foe;\r
169                                                                         foedist = flen;\r
170                                                                         foesz = tsz;\r
171                                                                 }\r
172                                                         }\r
173                                                 }\r
174                                         }\r
175                                 }\r
176                                 foe = foe.chain;\r
177                         }\r
178                 }\r
179         }\r
180         else\r
181         {\r
182                 foe = player_head;\r
183                 while(foe)\r
184                 {\r
185                         if(foe != self)\r
186                         {\r
187                                 if (foe.modelindex != 0)\r
188                                 {\r
189                                         if (foe.health > 0)\r
190                                         {\r
191                                                 if (!(teamplay && self.team == foe.team))\r
192                                                 {\r
193                                                         flen = vlen(foe.origin - self.origin);\r
194                                                         if (flen < foedist)\r
195                                                         {\r
196                                                                 tsz = bot_size_player(foe);\r
197                                                                 if (tsz < foesz)\r
198                                                                 {\r
199                                                                         if (fov(foe) || foe.b_sound > time || self.b_skill == 3)\r
200                                                                         {\r
201                                                                                 if (fisible(foe))\r
202                                                                                 {\r
203                                                                                         self.enemy = foe;\r
204                                                                                         foedist = vlen(foe.origin - self.origin);\r
205                                                                                 }\r
206                                                                         }\r
207                                                                 }\r
208                                                         }\r
209                                                 }\r
210                                         }\r
211                                 }\r
212                         }\r
213                         foe = foe._next;\r
214                 }\r
215         }\r
216 };\r
217 \r
218 \r
219 \r
220 \r
221 /*\r
222 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
223 \r
224 weapon_range\r
225 \r
226 _x "sweet spot range" - try to maintain this range if possible\r
227 _y minimum range bot can be to be effective (rl/gl) (move away)\r
228 _z maximum range bot can be to be effective (lg/axe) (move in)\r
229 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
230 */\r
231 \r
232 vector(float wep) weapon_range =\r
233 {\r
234         if (wep == IT_LASER) // IT_AXE\r
235                 return '48 0 300';\r
236         else if (wep == IT_SHOTGUN) // IT_SHOTGUN\r
237                 return '128 0 99999';\r
238         else if (wep == IT_CRYLINK) // IT_SUPER_SHOTGUN\r
239                 return '128 0 99999';\r
240         else if (wep == IT_UZI) // IT_NAILGUN\r
241                 return '180 0 3000';\r
242         else if (wep == IT_HAGAR) // IT_SUPER_NAILGUN\r
243                 return '180 48 3000';\r
244         else if (wep == IT_GRENADE_LAUNCHER) // IT_GRENADE_LAUNCHER\r
245                 return '180 48 3000';\r
246         else if (wep == IT_ELECTRO) // IT_ROCKET_LAUNCHER\r
247                 return '180 48 3000';\r
248         else if (wep == IT_ROCKET_LAUNCHER) // IT_ROCKET_LAUNCHER\r
249                 return '180 48 3000';\r
250         else if (wep == IT_NEX) // IT_LIGHTNING\r
251                 return '350 0 99999';\r
252         return '48 0 300';\r
253 };\r
254 \r
255 /*\r
256 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
257 \r
258 bot_weapon_switch\r
259 \r
260 Pick a weapon based on range / ammo\r
261 \r
262 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
263 */\r
264 \r
265 void(float brange) bot_weapon_switch =\r
266 {\r
267         local   float   it, flag, pulse;\r
268         local vector v;\r
269 \r
270         it = self.items & 127;\r
271         pulse = 0;\r
272 \r
273         while(it)\r
274         {\r
275                 if ((self.ammo_rockets >= 3) && (it & IT_ROCKET_LAUNCHER)){flag = IT_ROCKET_LAUNCHER;pulse = 9;}\r
276                 else if ((self.ammo_rockets >= 1) && (it & IT_HAGAR)){flag = IT_HAGAR;pulse = 8;}\r
277                 else if ((self.ammo_cells >= 5) && (it & IT_NEX)){flag = IT_NEX;pulse = 7;}\r
278                 else if ((self.ammo_cells >= 1) && (it & IT_CRYLINK)){flag = IT_CRYLINK;pulse = 6;}\r
279                 else if ((self.ammo_cells >= 2) && (it & IT_ELECTRO)){flag = IT_ELECTRO;pulse = 5;}\r
280                 else if ((self.ammo_rockets >= 3) && (it & IT_GRENADE_LAUNCHER)){flag = IT_GRENADE_LAUNCHER;pulse = 4;}\r
281                 else if ((self.ammo_nails >= 1) && (it & IT_UZI)){flag = IT_UZI;pulse = 3;}\r
282                 else if ((self.ammo_shells >= 1) && (it & IT_SHOTGUN)){flag = IT_SHOTGUN;pulse = 2;}\r
283                 else\r
284                 {\r
285                         if (pulse)\r
286                                 self.impulse = pulse;\r
287                         return;\r
288                 }\r
289 \r
290                 if (brange == -1)\r
291                 {\r
292                         if (pulse)\r
293                                 self.impulse = pulse;\r
294                         return;\r
295                 }\r
296 \r
297                 v = weapon_range(flag);\r
298                 if (brange < v_y || brange > v_z)\r
299                         it = it - flag;\r
300                 else\r
301                 {\r
302                         if (pulse)\r
303                                 self.impulse = pulse;\r
304                         return;\r
305                 }\r
306         }\r
307 };\r
308 \r
309 void() bot_shoot =\r
310 {\r
311         // quick little function to stop making him shoot the wrong way ! Argh\r
312         local float g;\r
313         g = angcomp(self.v_angle_x, self.b_angle_x);\r
314         if (fabs(g) > 30)\r
315                 return; // argh, too far away\r
316         g = angcomp(self.v_angle_y, self.b_angle_y);\r
317         if (fabs(g) > 30)\r
318                 return; // not again!\r
319         self.button0 = TRUE;\r
320 };\r
321 \r
322 /*\r
323 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
324 \r
325 Bot_fight_style\r
326 \r
327 This is the core of the bot's thinking when\r
328 attacking an enemy.\r
329 \r
330 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
331 */\r
332 \r
333 void() bot_fight_style =\r
334 {\r
335         local vector v, v1, v2, org;\r
336         local float foedist, mysz, foesz;\r
337 \r
338 \r
339         if (self.enemy.health <= 0)\r
340         {\r
341                 self.enemy = world;\r
342                 return;\r
343         }\r
344         else if (!self.enemy.takedamage)\r
345         {\r
346                 self.enemy = world;\r
347                 return;\r
348         }\r
349         else if (!fisible(self.enemy))\r
350         {\r
351                 self.enemy = world;\r
352                 return;\r
353         }\r
354 \r
355         org = realorigin(self.enemy);\r
356         makevectors(self.v_angle);\r
357 \r
358         // decide if I should shoot\r
359 \r
360         foedist = vlen(org - self.origin);\r
361         v = weapon_range(self.weapon);\r
362         if (foedist > v_y && foedist < v_z)\r
363         {\r
364                 traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * v_z, FALSE, self);\r
365                 if (vlen(trace_endpos - (self.origin + self.view_ofs)) >= v_y)\r
366                 {\r
367                         // try to avoid shooting teammates\r
368                         if (trace_ent.classname == "player")\r
369                                 if ((trace_ent.team == self.team && teamplay) || (coop))\r
370                                         return;\r
371                         bot_shoot();\r
372                 }\r
373         }\r
374         else\r
375                 bot_weapon_switch(foedist);\r
376 \r
377         if (!(self.b_aiflags & (AI_PRECISION | AI_BLIND | AI_OBSTRUCTED)))\r
378         {\r
379                 foesz = bot_size_player(self.enemy);\r
380                 mysz = bot_size_player(self) + 5;\r
381 \r
382                 if (foesz > mysz)\r
383                 {\r
384                         if (teamplay)\r
385                         {\r
386                                 if (random() < 0.02)\r
387                                 {\r
388                                         bot_start_topic(5);\r
389                                         self.b_chattime = 1;\r
390                                 }\r
391                         }\r
392 \r
393                         return;\r
394                 }\r
395                 else if (mysz < 140)\r
396                         return;\r
397                 else if (self.avoid)\r
398                 {\r
399                         if (self.avoid.velocity)\r
400                                 v = self.avoid.velocity;\r
401                         else\r
402                                 v = normalize(self.avoid.origin - self.origin);\r
403                         v1_x = v_y;\r
404                         v1_y = v_y * -1;\r
405                         v2_x = v_y;\r
406                         v2_y = v_y * -1;\r
407                         foedist = vlen(self.avoid.origin - (self.origin + v1));\r
408                         if (foedist < vlen(self.avoid.origin - (self.origin + v2)))\r
409                                 frik_walkmove(v2);\r
410                         else\r
411                                 frik_walkmove(v1);\r
412                 }\r
413                 else if (!self.enemy.flags & FL_MONSTER)\r
414                 {\r
415                         if (foedist + 32 <  v_x)\r
416                                 frik_walkmove(self.origin - org);\r
417                         else if (foedist - 32 >  v_x)\r
418                                 frik_walkmove(org - self.origin);\r
419                         else if (self.wallhug)\r
420                                 frik_walkmove(v_right);\r
421                         else\r
422                                 frik_walkmove(v_right * -1);\r
423                 }\r
424         }\r
425         else\r
426         {\r
427                 foesz = bot_size_player(self.enemy);\r
428                 mysz = bot_size_player(self) + 5;\r
429 \r
430                 if (foesz > mysz)\r
431                         return;\r
432                 else if (mysz < 140)\r
433                         return;\r
434                 self.keys = self.keys & 960;\r
435         }\r
436 };\r
437 \r
438 \r