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));
80 if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
81 if (vlen(head.origin - org) < sradius)
86 t = t / (head.health + head.armortype * head.armorvalue);
89 //dprint("found: "); dprint(head.netname); dprint("\n");
90 navigation_routerating(head, t * ratingscale);
97 void() havocbot_role_ctf_middle;
98 void() havocbot_role_ctf_defense;
99 void() havocbot_role_ctf_offense;
100 void() havocbot_role_ctf_interceptor;
102 void(float ratingscale, vector org, float sradius) havocbot_goalrating_ctf_carrieritems =
106 head = findchainfloat(bot_pickup, TRUE);
109 // look for health and armor only
110 if (head.solid) // must be possible to pick up (respawning items don't count)
111 if (head.health || head.armorvalue)
112 if (vlen(head.origin - org) < sradius)
115 //if (!head.bot_pickupevalfunc || head.model == "")
117 // get the value of the item
118 t = head.bot_pickupevalfunc(self, head) * 0.0001;
120 navigation_routerating(head, t * ratingscale);
126 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
129 if (self.team == 5) // red
130 head = find(world, classname, "item_flag_team1"); // red flag
132 head = find(world, classname, "item_flag_team2"); // blue flag
133 navigation_routerating(head, ratingscale);
136 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
139 if (self.team == 5) // red
140 head = find(world, classname, "item_flag_team2"); // blue flag
142 head = find(world, classname, "item_flag_team1"); // red flag
143 navigation_routerating(head, ratingscale);
146 void(float ratingscale) havocbot_goalrating_ctf_enemybase =
148 // div0: needs a change in the CTF code
151 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
154 if (self.team == 5) // red
155 head = find(world, classname, "item_flag_team1"); // red flag
157 head = find(world, classname, "item_flag_team2"); // blue flag
158 if (head.cnt != FLAG_BASE)
159 navigation_routerating(head, ratingscale);
162 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
164 local entity redflag, blueflag;
166 redflag = find(world, classname, "item_flag_team1");
167 blueflag = find(world, classname, "item_flag_team2");
169 if (redflag == world)
170 error("havocbot: item_flag_team1 missing\n");
171 if (blueflag == world)
172 error("havocbot: item_flag_team2 missing\n");
174 if (redflag.cnt != FLAG_BASE) // red flag is carried or out in the field
175 navigation_routerating(redflag, ratingscale);
176 if (blueflag.cnt != FLAG_BASE) // blue flag is carried or out in the field
177 navigation_routerating(blueflag, ratingscale);
180 // CTF: (always teamplay)
182 //role rogue: (is this used?)
183 //pick up items and dropped flags (with big rating boost to dropped flags)
184 void() havocbot_role_ctf_rogue =
186 if (self.bot_strategytime < time)
188 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
189 navigation_goalrating_start();
190 havocbot_goalrating_ctf_droppedflags(5000);
191 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
192 havocbot_goalrating_items(10000, self.origin, 10000);
193 navigation_goalrating_end();
198 //pick up armor and health
199 //go to our flag spot
200 void() havocbot_role_ctf_carrier =
202 if (self.flagcarried == world)
204 dprint("changing role to middle\n");
205 self.havocbot_role = havocbot_role_ctf_middle;
206 self.havocbot_role_timeout = 0;
209 if (self.bot_strategytime < time)
211 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
212 navigation_goalrating_start();
213 havocbot_goalrating_ctf_ourflag(5000);
214 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
215 navigation_goalrating_end();
220 //pick up armor and health
221 //if rockets < 25 || health < 100, change role to middle
222 //if carrying flag, change role to flag carrier
223 //if our flag taken, change role to interceptor
224 //(60-90 second timer) change role to middle
226 void() havocbot_role_ctf_offense =
229 if (self.flagcarried)
231 dprint("changing role to carrier\n");
232 self.havocbot_role = havocbot_role_ctf_carrier;
233 self.havocbot_role_timeout = 0;
237 if (self.team == 5) // red
238 f = find(world, classname, "item_flag_team1");
240 f = find(world, classname, "item_flag_team2");
241 if (f.cnt != FLAG_BASE && canreach(f))
243 dprint("changing role to interceptor\n");
244 self.havocbot_previous_role = self.havocbot_role;
245 self.havocbot_role = havocbot_role_ctf_interceptor;
246 self.havocbot_role_timeout = 0;
249 if (!self.havocbot_role_timeout)
250 self.havocbot_role_timeout = time + random() * 30 + 60;
251 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
253 dprint("changing role to middle\n");
254 self.havocbot_role = havocbot_role_ctf_middle;
255 self.havocbot_role_timeout = 0;
258 if (self.bot_strategytime < time)
260 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
261 navigation_goalrating_start();
262 havocbot_goalrating_ctf_ourstolenflag(5000);
263 havocbot_goalrating_ctf_enemyflag(3000);
264 havocbot_goalrating_ctf_enemybase(2000);
265 havocbot_goalrating_items(10000, self.origin, 10000);
266 navigation_goalrating_end();
270 //role interceptor (temporary role):
272 //if carrying flag, change role to flag carrier
273 //if our flag is back, change role to previous role
275 //go to least recently visited area
276 void() havocbot_role_ctf_interceptor =
279 if (self.flagcarried)
281 dprint("changing role to carrier\n");
282 self.havocbot_role = havocbot_role_ctf_carrier;
283 self.havocbot_role_timeout = 0;
287 if (self.team == 5) // red
288 f = find(world, classname, "item_flag_team1");
290 f = find(world, classname, "item_flag_team2");
291 if (f.cnt == FLAG_BASE)
293 dprint("changing role back\n");
294 self.havocbot_role = self.havocbot_previous_role;
295 self.havocbot_role_timeout = 0;
299 if (self.bot_strategytime < time)
301 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
302 navigation_goalrating_start();
303 havocbot_goalrating_ctf_ourstolenflag(5000);
304 havocbot_goalrating_ctf_droppedflags(5000);
305 havocbot_goalrating_items(10000, self.origin, 10000);
306 navigation_goalrating_end();
312 //if carrying flag, change role to flag carrier
313 //if our flag taken, change role to interceptor
314 //if see flag (of either team) follow it (this has many implications)
315 //(10-20 second timer) change role to defense or offense
316 //go to least recently visited area
317 void() havocbot_role_ctf_middle =
320 if (self.flagcarried)
322 dprint("changing role to carrier\n");
323 self.havocbot_role = havocbot_role_ctf_carrier;
324 self.havocbot_role_timeout = 0;
328 if (self.team == 5) // red
329 f = find(world, classname, "item_flag_team1");
331 f = find(world, classname, "item_flag_team2");
332 if (f.cnt != FLAG_BASE && canreach(f))
334 dprint("changing role to interceptor\n");
335 self.havocbot_previous_role = self.havocbot_role;
336 self.havocbot_role = havocbot_role_ctf_interceptor;
337 self.havocbot_role_timeout = 0;
340 if (!self.havocbot_role_timeout)
341 self.havocbot_role_timeout = time + random() * 10 + 10;
342 if (time > self.havocbot_role_timeout)
343 if (self.ammo_rockets >= 25)
347 dprint("changing role to offense\n");
348 self.havocbot_role = havocbot_role_ctf_offense;
352 dprint("changing role to defense\n");
353 self.havocbot_role = havocbot_role_ctf_defense;
355 self.havocbot_role_timeout = 0;
359 if (self.bot_strategytime < time)
361 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
362 navigation_goalrating_start();
363 havocbot_goalrating_ctf_ourstolenflag(5000);
364 havocbot_goalrating_ctf_droppedflags(3000);
365 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
366 havocbot_goalrating_items(10000, self.origin, 10000);
367 navigation_goalrating_end();
372 //if rockets < 25 || health < 100, change role to middle
373 //if carrying flag, change role to flag carrier
374 //if our flag taken, change role to interceptor
375 //(30-50 second timer) change role to middle
376 //move to nearest unclaimed defense spot
377 void() havocbot_role_ctf_defense =
380 if (self.flagcarried)
382 dprint("changing role to carrier\n");
383 self.havocbot_role = havocbot_role_ctf_carrier;
384 self.havocbot_role_timeout = 0;
388 if (self.team == 5) // red
389 f = find(world, classname, "item_flag_team1");
391 f = find(world, classname, "item_flag_team2");
392 if (f.cnt != FLAG_BASE && canreach(f))
394 dprint("changing role to interceptor\n");
395 self.havocbot_previous_role = self.havocbot_role;
396 self.havocbot_role = havocbot_role_ctf_interceptor;
397 self.havocbot_role_timeout = 0;
400 if (!self.havocbot_role_timeout)
401 self.havocbot_role_timeout = time + random() * 20 + 30;
402 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
404 dprint("changing role to middle\n");
405 self.havocbot_role = havocbot_role_ctf_middle;
406 self.havocbot_role_timeout = 0;
409 if (self.bot_strategytime < time)
411 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
412 navigation_goalrating_start();
413 havocbot_goalrating_ctf_ourstolenflag(20000);
414 havocbot_goalrating_ctf_droppedflags(500);
415 havocbot_goalrating_items(10000, f.origin, 10000);
416 navigation_goalrating_end();
419 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
420 // change position occasionally
421 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
423 self.bot_strategytime = time + random() * 45 + 15;
424 self.goalentity = world;
425 head = findchain(classname, "info_ctf_defensepoint");
428 if (time > head.count)
430 self.goalentity = head;
435 // if there are no defensepoints defined, switch to middle
436 if (self.goalentity == world)
438 dprint("changing role to middle\n");
439 self.havocbot_role = havocbot_role_ctf_middle;
440 self.havocbot_role_timeout = 0;
444 // keep anyone else from taking this spot
445 if (self.goalentity != world)
446 self.goalentity.count = time + 0.5;
451 // choose a role according to the situation
452 void() havocbot_chooserole_ctf =
455 dprint("choose CTF role...\n");
457 self.havocbot_role = havocbot_role_ctf_rogue;
462 self.havocbot_role = havocbot_role_ctf_offense;
464 self.havocbot_role = havocbot_role_ctf_middle;
466 self.havocbot_role = havocbot_role_ctf_defense;
471 //go to best items, or control points you don't own
472 void() havocbot_role_dom =
474 if (self.bot_strategytime < time)
476 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
477 navigation_goalrating_start();
478 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
479 havocbot_goalrating_items(8000, self.origin, 8000);
480 //havocbot_goalrating_enemyplayers(1, self.origin, 2000);
481 //havocbot_goalrating_waypoints(1, self.origin, 1000);
482 navigation_goalrating_end();
488 void() havocbot_role_dm =
490 if (self.bot_strategytime < time)
492 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
493 navigation_goalrating_start();
494 havocbot_goalrating_items(10000, self.origin, 10000);
495 havocbot_goalrating_enemyplayers(1, self.origin, 20000);
496 //havocbot_goalrating_waypoints(1, self.origin, 1000);
497 navigation_goalrating_end();
501 void() havocbot_chooserole_dm =
503 self.havocbot_role = havocbot_role_dm;
506 void() havocbot_chooserole_dom =
508 self.havocbot_role = havocbot_role_dom;
511 void() havocbot_chooserole =
513 dprint("choose a role...\n");
514 navigation_routetogoal(world);
515 self.bot_strategytime = -1;
517 havocbot_chooserole_ctf();
518 else if (cvar("g_domination"))
519 havocbot_chooserole_dom();
520 else // assume anything else is deathmatch
521 havocbot_chooserole_dm();