2 .float havocbot_role_timeout;
3 .void() havocbot_previous_role;
4 .float bot_strategytime;
8 float(entity e) canreach =
10 return vlen(self.origin - e.origin) < 1500;
13 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items =
17 head = findchainfloat(bot_pickup, TRUE);
20 if (head.solid) // must be possible to pick up (respawning items don't count)
21 if (vlen(head.origin - org) < sradius)
24 //if (!head.bot_pickupevalfunc || head.model == "")
26 // get the value of the item
27 t = head.bot_pickupevalfunc(self, head) * 0.0001;
29 navigation_routerating(head, t * ratingscale);
35 void(float ratingscale, vector org, float sradius) havocbot_goalrating_controlpoints =
38 head = findchain(classname, "dom_controlpoint");
41 if (vlen(head.origin - org) < sradius)
43 if(head.cnt > -1) // this is just being fought for
44 navigation_routerating(head, ratingscale);
45 else if(head.goalentity.cnt == 0) // unclaimed point
46 navigation_routerating(head, ratingscale * 0.5);
47 else if(head.goalentity.team != self.team) // other team's point
48 navigation_routerating(head, ratingscale * 0.2);
54 void(float ratingscale, vector org, float sradius) havocbot_goalrating_waypoints =
57 head = findchain(classname, "waypoint");
60 if (vlen(head.origin - org) < sradius && vlen(head.origin - org) > 100)
61 navigation_routerating(head, ratingscale);
66 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers =
69 local float t, noteam;
70 ratingscale = ratingscale * 1200;
71 noteam = self.team == 0 || teamplay == 0;
72 head = findchain(classname, "player");
76 if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
77 if (vlen(head.origin - org) < sradius)
82 t = t / (head.health + head.armortype * head.armorvalue);
84 navigation_routerating(head, t * ratingscale);
91 void() havocbot_role_ctf_middle;
92 void() havocbot_role_ctf_defense;
93 void() havocbot_role_ctf_offense;
94 void() havocbot_role_ctf_interceptor;
96 void(float ratingscale, vector org, float sradius) havocbot_goalrating_ctf_carrieritems =
100 head = findchainfloat(bot_pickup, TRUE);
103 // look for health and armor only
104 if (head.solid) // must be possible to pick up (respawning items don't count)
105 if (head.health || head.armorvalue)
106 if (vlen(head.origin - org) < sradius)
109 //if (!head.bot_pickupevalfunc || head.model == "")
111 // get the value of the item
112 t = head.bot_pickupevalfunc(self, head) * 0.0001;
114 navigation_routerating(head, t * ratingscale);
120 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
123 if (self.team == 5) // red
124 head = find(world, classname, "item_flag_team1"); // red flag
126 head = find(world, classname, "item_flag_team2"); // blue flag
127 navigation_routerating(head, ratingscale);
130 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
133 if (self.team == 5) // red
134 head = find(world, classname, "item_flag_team2"); // blue flag
136 head = find(world, classname, "item_flag_team1"); // red flag
137 navigation_routerating(head, ratingscale);
140 void(float ratingscale) havocbot_goalrating_ctf_enemybase =
142 // div0: needs a change in the CTF code
145 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
148 if (self.team == 5) // red
149 head = find(world, classname, "item_flag_team1"); // red flag
151 head = find(world, classname, "item_flag_team2"); // blue flag
152 if (head.cnt != FLAG_BASE)
153 navigation_routerating(head, ratingscale);
156 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
158 local entity redflag, blueflag;
160 redflag = find(world, classname, "item_flag_team1");
161 blueflag = find(world, classname, "item_flag_team2");
163 if (redflag == world)
164 error("havocbot: item_flag_team1 missing\n");
165 if (blueflag == world)
166 error("havocbot: item_flag_team2 missing\n");
168 if (redflag.cnt != FLAG_BASE) // red flag is carried or out in the field
169 navigation_routerating(redflag, ratingscale);
170 if (blueflag.cnt != FLAG_BASE) // blue flag is carried or out in the field
171 navigation_routerating(blueflag, ratingscale);
174 // CTF: (always teamplay)
176 //role rogue: (is this used?)
177 //pick up items and dropped flags (with big rating boost to dropped flags)
178 void() havocbot_role_ctf_rogue =
180 if (self.bot_strategytime < time)
182 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
183 navigation_goalrating_start();
184 havocbot_goalrating_ctf_droppedflags(5000);
185 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
186 havocbot_goalrating_items(10000, self.origin, 10000);
187 navigation_goalrating_end();
192 //pick up armor and health
193 //go to our flag spot
194 void() havocbot_role_ctf_carrier =
196 if (self.flagcarried == world)
198 dprint("changing role to middle\n");
199 self.havocbot_role = havocbot_role_ctf_middle;
200 self.havocbot_role_timeout = 0;
203 if (self.bot_strategytime < time)
205 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
206 navigation_goalrating_start();
207 havocbot_goalrating_ctf_ourflag(5000);
208 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
209 navigation_goalrating_end();
214 //pick up armor and health
215 //if rockets < 25 || health < 100, change role to middle
216 //if carrying flag, change role to flag carrier
217 //if our flag taken, change role to interceptor
218 //(60-90 second timer) change role to middle
220 void() havocbot_role_ctf_offense =
223 if (self.flagcarried)
225 dprint("changing role to carrier\n");
226 self.havocbot_role = havocbot_role_ctf_carrier;
227 self.havocbot_role_timeout = 0;
231 if (self.team == 5) // red
232 f = find(world, classname, "item_flag_team1");
234 f = find(world, classname, "item_flag_team2");
235 if (f.cnt != FLAG_BASE && canreach(f))
237 dprint("changing role to interceptor\n");
238 self.havocbot_previous_role = self.havocbot_role;
239 self.havocbot_role = havocbot_role_ctf_interceptor;
240 self.havocbot_role_timeout = 0;
243 if (!self.havocbot_role_timeout)
244 self.havocbot_role_timeout = time + random() * 30 + 60;
245 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
247 dprint("changing role to middle\n");
248 self.havocbot_role = havocbot_role_ctf_middle;
249 self.havocbot_role_timeout = 0;
252 if (self.bot_strategytime < time)
254 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
255 navigation_goalrating_start();
256 havocbot_goalrating_ctf_ourstolenflag(5000);
257 havocbot_goalrating_ctf_enemyflag(3000);
258 havocbot_goalrating_ctf_enemybase(2000);
259 havocbot_goalrating_items(10000, self.origin, 10000);
260 navigation_goalrating_end();
264 //role interceptor (temporary role):
266 //if carrying flag, change role to flag carrier
267 //if our flag is back, change role to previous role
269 //go to least recently visited area
270 void() havocbot_role_ctf_interceptor =
273 if (self.flagcarried)
275 dprint("changing role to carrier\n");
276 self.havocbot_role = havocbot_role_ctf_carrier;
277 self.havocbot_role_timeout = 0;
281 if (self.team == 5) // red
282 f = find(world, classname, "item_flag_team1");
284 f = find(world, classname, "item_flag_team2");
285 if (f.cnt == FLAG_BASE)
287 dprint("changing role back\n");
288 self.havocbot_role = self.havocbot_previous_role;
289 self.havocbot_role_timeout = 0;
293 if (self.bot_strategytime < time)
295 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
296 navigation_goalrating_start();
297 havocbot_goalrating_ctf_ourstolenflag(5000);
298 havocbot_goalrating_ctf_droppedflags(5000);
299 havocbot_goalrating_items(10000, self.origin, 10000);
300 navigation_goalrating_end();
306 //if carrying flag, change role to flag carrier
307 //if our flag taken, change role to interceptor
308 //if see flag (of either team) follow it (this has many implications)
309 //(10-20 second timer) change role to defense or offense
310 //go to least recently visited area
311 void() havocbot_role_ctf_middle =
314 if (self.flagcarried)
316 dprint("changing role to carrier\n");
317 self.havocbot_role = havocbot_role_ctf_carrier;
318 self.havocbot_role_timeout = 0;
322 if (self.team == 5) // red
323 f = find(world, classname, "item_flag_team1");
325 f = find(world, classname, "item_flag_team2");
326 if (f.cnt != FLAG_BASE && canreach(f))
328 dprint("changing role to interceptor\n");
329 self.havocbot_previous_role = self.havocbot_role;
330 self.havocbot_role = havocbot_role_ctf_interceptor;
331 self.havocbot_role_timeout = 0;
334 if (!self.havocbot_role_timeout)
335 self.havocbot_role_timeout = time + random() * 10 + 10;
336 if (time > self.havocbot_role_timeout)
337 if (self.ammo_rockets >= 25)
341 dprint("changing role to offense\n");
342 self.havocbot_role = havocbot_role_ctf_offense;
346 dprint("changing role to defense\n");
347 self.havocbot_role = havocbot_role_ctf_defense;
349 self.havocbot_role_timeout = 0;
353 if (self.bot_strategytime < time)
355 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
356 navigation_goalrating_start();
357 havocbot_goalrating_ctf_ourstolenflag(5000);
358 havocbot_goalrating_ctf_droppedflags(3000);
359 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
360 havocbot_goalrating_items(10000, self.origin, 10000);
361 navigation_goalrating_end();
366 //if rockets < 25 || health < 100, change role to middle
367 //if carrying flag, change role to flag carrier
368 //if our flag taken, change role to interceptor
369 //(30-50 second timer) change role to middle
370 //move to nearest unclaimed defense spot
371 void() havocbot_role_ctf_defense =
374 if (self.flagcarried)
376 dprint("changing role to carrier\n");
377 self.havocbot_role = havocbot_role_ctf_carrier;
378 self.havocbot_role_timeout = 0;
382 if (self.team == 5) // red
383 f = find(world, classname, "item_flag_team1");
385 f = find(world, classname, "item_flag_team2");
386 if (f.cnt != FLAG_BASE && canreach(f))
388 dprint("changing role to interceptor\n");
389 self.havocbot_previous_role = self.havocbot_role;
390 self.havocbot_role = havocbot_role_ctf_interceptor;
391 self.havocbot_role_timeout = 0;
394 if (!self.havocbot_role_timeout)
395 self.havocbot_role_timeout = time + random() * 20 + 30;
396 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
398 dprint("changing role to middle\n");
399 self.havocbot_role = havocbot_role_ctf_middle;
400 self.havocbot_role_timeout = 0;
403 if (self.bot_strategytime < time)
405 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
406 navigation_goalrating_start();
407 havocbot_goalrating_ctf_ourstolenflag(20000);
408 havocbot_goalrating_ctf_droppedflags(500);
409 havocbot_goalrating_items(10000, f.origin, 10000);
410 navigation_goalrating_end();
413 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
414 // change position occasionally
415 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
417 self.bot_strategytime = time + random() * 45 + 15;
418 self.goalentity = world;
419 head = findchain(classname, "info_ctf_defensepoint");
422 if (time > head.count)
424 self.goalentity = head;
429 // if there are no defensepoints defined, switch to middle
430 if (self.goalentity == world)
432 dprint("changing role to middle\n");
433 self.havocbot_role = havocbot_role_ctf_middle;
434 self.havocbot_role_timeout = 0;
438 // keep anyone else from taking this spot
439 if (self.goalentity != world)
440 self.goalentity.count = time + 0.5;
445 // choose a role according to the situation
446 void() havocbot_chooserole_ctf =
449 dprint("choose CTF role...\n");
451 self.havocbot_role = havocbot_role_ctf_rogue;
456 self.havocbot_role = havocbot_role_ctf_offense;
458 self.havocbot_role = havocbot_role_ctf_middle;
460 self.havocbot_role = havocbot_role_ctf_defense;
465 //go to best items, or control points you don't own
466 void() havocbot_role_dom =
468 if (self.bot_strategytime < time)
470 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
471 navigation_goalrating_start();
472 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
473 havocbot_goalrating_items(8000, self.origin, 8000);
474 //havocbot_goalrating_enemyplayers(1, self.origin, 2000);
475 //havocbot_goalrating_waypoints(1, self.origin, 1000);
476 navigation_goalrating_end();
482 void() havocbot_role_dm =
484 if (self.bot_strategytime < time)
486 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
487 navigation_goalrating_start();
488 havocbot_goalrating_items(10000, self.origin, 10000);
489 havocbot_goalrating_enemyplayers(1, self.origin, 20000);
490 //havocbot_goalrating_waypoints(1, self.origin, 1000);
491 navigation_goalrating_end();
495 void() havocbot_chooserole_dm =
497 self.havocbot_role = havocbot_role_dm;
500 void() havocbot_chooserole_dom =
502 self.havocbot_role = havocbot_role_dom;
505 void() havocbot_chooserole =
507 dprint("choose a role...\n");
508 navigation_routetogoal(world);
509 self.bot_strategytime = -1;
511 havocbot_chooserole_ctf();
512 else if (cvar("g_domination"))
513 havocbot_chooserole_dom();
514 else // assume anything else is deathmatch
515 havocbot_chooserole_dm();