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)); // fteqcc sucks
72 //dprint("teamplay is "); dprint(ftos(teamplay)); dprint(", own team is ");
73 //dprint(ftos(self.team)); dprint(" -> noteam is "); dprint(ftos(noteam));
76 head = findchain(classname, "player");
81 if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
82 if (vlen(head.origin - org) < sradius)
87 t = t / (head.health + head.armortype * head.armorvalue);
90 //dprint("found: "); dprint(head.netname); dprint("\n");
91 navigation_routerating(head, t * ratingscale);
99 void() havocbot_role_ctf_middle;
100 void() havocbot_role_ctf_defense;
101 void() havocbot_role_ctf_offense;
102 void() havocbot_role_ctf_interceptor;
104 void(float ratingscale, vector org, float sradius) havocbot_goalrating_ctf_carrieritems =
108 head = findchainfloat(bot_pickup, TRUE);
111 // look for health and armor only
112 if (head.solid) // must be possible to pick up (respawning items don't count)
113 if (head.health || head.armorvalue)
114 if (vlen(head.origin - org) < sradius)
117 //if (!head.bot_pickupevalfunc || head.model == "")
119 // get the value of the item
120 t = head.bot_pickupevalfunc(self, head) * 0.0001;
122 navigation_routerating(head, t * ratingscale);
128 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
131 if (self.team == 5) // red
132 head = find(world, classname, "item_flag_team1"); // red flag
134 head = find(world, classname, "item_flag_team2"); // blue flag
135 navigation_routerating(head, ratingscale);
138 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
141 if (self.team == 5) // red
142 head = find(world, classname, "item_flag_team2"); // blue flag
144 head = find(world, classname, "item_flag_team1"); // red flag
145 navigation_routerating(head, ratingscale);
148 void(float ratingscale) havocbot_goalrating_ctf_enemybase =
150 // div0: needs a change in the CTF code
153 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
156 if (self.team == 5) // red
157 head = find(world, classname, "item_flag_team1"); // red flag
159 head = find(world, classname, "item_flag_team2"); // blue flag
160 if (head.cnt != FLAG_BASE)
161 navigation_routerating(head, ratingscale);
164 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
166 local entity redflag, blueflag;
168 redflag = find(world, classname, "item_flag_team1");
169 blueflag = find(world, classname, "item_flag_team2");
171 if (redflag == world)
172 error("havocbot: item_flag_team1 missing\n");
173 if (blueflag == world)
174 error("havocbot: item_flag_team2 missing\n");
176 if (redflag.cnt != FLAG_BASE) // red flag is carried or out in the field
177 navigation_routerating(redflag, ratingscale);
178 if (blueflag.cnt != FLAG_BASE) // blue flag is carried or out in the field
179 navigation_routerating(blueflag, ratingscale);
182 // CTF: (always teamplay)
184 //role rogue: (is this used?)
185 //pick up items and dropped flags (with big rating boost to dropped flags)
186 void() havocbot_role_ctf_rogue =
188 if (self.bot_strategytime < time)
190 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
191 navigation_goalrating_start();
192 havocbot_goalrating_ctf_droppedflags(5000);
193 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
194 havocbot_goalrating_items(10000, self.origin, 10000);
195 navigation_goalrating_end();
200 //pick up armor and health
201 //go to our flag spot
202 void() havocbot_role_ctf_carrier =
204 if (self.flagcarried == world)
206 dprint("changing role to middle\n");
207 self.havocbot_role = havocbot_role_ctf_middle;
208 self.havocbot_role_timeout = 0;
211 if (self.bot_strategytime < time)
213 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
214 navigation_goalrating_start();
215 havocbot_goalrating_ctf_ourflag(5000);
216 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
217 navigation_goalrating_end();
222 //pick up armor and health
223 //if rockets < 25 || health < 100, change role to middle
224 //if carrying flag, change role to flag carrier
225 //if our flag taken, change role to interceptor
226 //(60-90 second timer) change role to middle
228 void() havocbot_role_ctf_offense =
231 if (self.flagcarried)
233 dprint("changing role to carrier\n");
234 self.havocbot_role = havocbot_role_ctf_carrier;
235 self.havocbot_role_timeout = 0;
239 if (self.team == 5) // red
240 f = find(world, classname, "item_flag_team1");
242 f = find(world, classname, "item_flag_team2");
243 if (f.cnt != FLAG_BASE && canreach(f))
245 dprint("changing role to interceptor\n");
246 self.havocbot_previous_role = self.havocbot_role;
247 self.havocbot_role = havocbot_role_ctf_interceptor;
248 self.havocbot_role_timeout = 0;
251 if (!self.havocbot_role_timeout)
252 self.havocbot_role_timeout = time + random() * 30 + 60;
253 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
255 dprint("changing role to middle\n");
256 self.havocbot_role = havocbot_role_ctf_middle;
257 self.havocbot_role_timeout = 0;
260 if (self.bot_strategytime < time)
262 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
263 navigation_goalrating_start();
264 havocbot_goalrating_ctf_ourstolenflag(5000);
265 havocbot_goalrating_ctf_enemyflag(3000);
266 havocbot_goalrating_ctf_enemybase(2000);
267 havocbot_goalrating_items(10000, self.origin, 10000);
268 navigation_goalrating_end();
272 //role interceptor (temporary role):
274 //if carrying flag, change role to flag carrier
275 //if our flag is back, change role to previous role
277 //go to least recently visited area
278 void() havocbot_role_ctf_interceptor =
281 if (self.flagcarried)
283 dprint("changing role to carrier\n");
284 self.havocbot_role = havocbot_role_ctf_carrier;
285 self.havocbot_role_timeout = 0;
289 if (self.team == 5) // red
290 f = find(world, classname, "item_flag_team1");
292 f = find(world, classname, "item_flag_team2");
293 if (f.cnt == FLAG_BASE)
295 dprint("changing role back\n");
296 self.havocbot_role = self.havocbot_previous_role;
297 self.havocbot_role_timeout = 0;
301 if (self.bot_strategytime < time)
303 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
304 navigation_goalrating_start();
305 havocbot_goalrating_ctf_ourstolenflag(5000);
306 havocbot_goalrating_ctf_droppedflags(5000);
307 havocbot_goalrating_items(10000, self.origin, 10000);
308 navigation_goalrating_end();
314 //if carrying flag, change role to flag carrier
315 //if our flag taken, change role to interceptor
316 //if see flag (of either team) follow it (this has many implications)
317 //(10-20 second timer) change role to defense or offense
318 //go to least recently visited area
319 void() havocbot_role_ctf_middle =
322 if (self.flagcarried)
324 dprint("changing role to carrier\n");
325 self.havocbot_role = havocbot_role_ctf_carrier;
326 self.havocbot_role_timeout = 0;
330 if (self.team == 5) // red
331 f = find(world, classname, "item_flag_team1");
333 f = find(world, classname, "item_flag_team2");
334 if (f.cnt != FLAG_BASE && canreach(f))
336 dprint("changing role to interceptor\n");
337 self.havocbot_previous_role = self.havocbot_role;
338 self.havocbot_role = havocbot_role_ctf_interceptor;
339 self.havocbot_role_timeout = 0;
342 if (!self.havocbot_role_timeout)
343 self.havocbot_role_timeout = time + random() * 10 + 10;
344 if (time > self.havocbot_role_timeout)
345 if (self.ammo_rockets >= 25)
349 dprint("changing role to offense\n");
350 self.havocbot_role = havocbot_role_ctf_offense;
354 dprint("changing role to defense\n");
355 self.havocbot_role = havocbot_role_ctf_defense;
357 self.havocbot_role_timeout = 0;
361 if (self.bot_strategytime < time)
363 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
364 navigation_goalrating_start();
365 havocbot_goalrating_ctf_ourstolenflag(5000);
366 havocbot_goalrating_ctf_droppedflags(3000);
367 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
368 havocbot_goalrating_items(10000, self.origin, 10000);
369 navigation_goalrating_end();
374 //if rockets < 25 || health < 100, change role to middle
375 //if carrying flag, change role to flag carrier
376 //if our flag taken, change role to interceptor
377 //(30-50 second timer) change role to middle
378 //move to nearest unclaimed defense spot
379 void() havocbot_role_ctf_defense =
382 if (self.flagcarried)
384 dprint("changing role to carrier\n");
385 self.havocbot_role = havocbot_role_ctf_carrier;
386 self.havocbot_role_timeout = 0;
390 if (self.team == 5) // red
391 f = find(world, classname, "item_flag_team1");
393 f = find(world, classname, "item_flag_team2");
394 if (f.cnt != FLAG_BASE && canreach(f))
396 dprint("changing role to interceptor\n");
397 self.havocbot_previous_role = self.havocbot_role;
398 self.havocbot_role = havocbot_role_ctf_interceptor;
399 self.havocbot_role_timeout = 0;
402 if (!self.havocbot_role_timeout)
403 self.havocbot_role_timeout = time + random() * 20 + 30;
404 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
406 dprint("changing role to middle\n");
407 self.havocbot_role = havocbot_role_ctf_middle;
408 self.havocbot_role_timeout = 0;
411 if (self.bot_strategytime < time)
413 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
414 navigation_goalrating_start();
415 havocbot_goalrating_ctf_ourstolenflag(20000);
416 havocbot_goalrating_ctf_droppedflags(500);
417 havocbot_goalrating_items(10000, f.origin, 10000);
418 navigation_goalrating_end();
421 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
422 // change position occasionally
423 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
425 self.bot_strategytime = time + random() * 45 + 15;
426 self.goalentity = world;
427 head = findchain(classname, "info_ctf_defensepoint");
430 if (time > head.count)
432 self.goalentity = head;
437 // if there are no defensepoints defined, switch to middle
438 if (self.goalentity == world)
440 dprint("changing role to middle\n");
441 self.havocbot_role = havocbot_role_ctf_middle;
442 self.havocbot_role_timeout = 0;
446 // keep anyone else from taking this spot
447 if (self.goalentity != world)
448 self.goalentity.count = time + 0.5;
453 // choose a role according to the situation
454 void() havocbot_chooserole_ctf =
457 dprint("choose CTF role...\n");
459 self.havocbot_role = havocbot_role_ctf_rogue;
464 self.havocbot_role = havocbot_role_ctf_offense;
466 self.havocbot_role = havocbot_role_ctf_middle;
468 self.havocbot_role = havocbot_role_ctf_defense;
473 //go to best items, or control points you don't own
474 void() havocbot_role_dom =
476 if (self.bot_strategytime < time)
478 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
479 navigation_goalrating_start();
480 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
481 havocbot_goalrating_items(8000, self.origin, 8000);
482 //havocbot_goalrating_enemyplayers(1, self.origin, 2000);
483 //havocbot_goalrating_waypoints(1, self.origin, 1000);
484 navigation_goalrating_end();
490 void() havocbot_role_dm =
492 if (self.bot_strategytime < time)
494 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
495 navigation_goalrating_start();
496 havocbot_goalrating_items(10000, self.origin, 10000);
497 havocbot_goalrating_enemyplayers(1, self.origin, 20000);
498 //havocbot_goalrating_waypoints(1, self.origin, 1000);
499 navigation_goalrating_end();
503 void() havocbot_chooserole_dm =
505 self.havocbot_role = havocbot_role_dm;
508 void() havocbot_chooserole_dom =
510 self.havocbot_role = havocbot_role_dom;
513 void() havocbot_chooserole =
515 dprint("choose a role...\n");
516 navigation_routetogoal(world);
517 self.bot_strategytime = -1;
519 havocbot_chooserole_ctf();
520 else if (cvar("g_domination"))
521 havocbot_chooserole_dom();
522 else // assume anything else is deathmatch
523 havocbot_chooserole_dm();