2 .float havocbot_role_timeout;
3 .void() havocbot_previous_role;
4 .float bot_strategytime;
7 float(entity e) canreach =
9 return vlen(self.origin - e.origin) < 1500;
12 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items =
16 head = findchainfloat(bot_pickup, TRUE);
19 if (head.solid) // must be possible to pick up (respawning items don't count)
20 if (vlen(head.origin - org) < sradius)
23 //if (!head.bot_pickupevalfunc || head.model == "")
25 // get the value of the item
26 t = head.bot_pickupevalfunc(self, head) * 0.0001;
28 navigation_routerating(head, t * ratingscale);
34 void(float ratingscale, vector org, float sradius) havocbot_goalrating_controlpoints =
37 head = findchain(classname, "dom_controlpoint");
40 if (vlen(head.origin - org) < sradius)
42 if(head.cnt > -1) // this is just being fought for
43 navigation_routerating(head, ratingscale);
44 else if(head.goalentity.cnt == 0) // unclaimed point
45 navigation_routerating(head, ratingscale * 0.5);
46 else if(head.goalentity.team != self.team) // other team's point
47 navigation_routerating(head, ratingscale * 0.2);
53 void(float ratingscale, vector org, float sradius) havocbot_goalrating_waypoints =
56 head = findchain(classname, "waypoint");
59 if (vlen(head.origin - org) < sradius && vlen(head.origin - org) > 100)
60 navigation_routerating(head, ratingscale);
65 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers =
68 local float t, noteam;
69 ratingscale = ratingscale * 1200;
70 noteam = self.team == 0 || teamplay == 0;
71 head = findchain(classname, "player");
75 if (head.team != self.team || noteam)
76 if (vlen(head.origin - org) < sradius)
81 t = t / (head.health + head.armortype * head.armorvalue);
83 navigation_routerating(head, t * ratingscale);
90 void() havocbot_role_ctf_middle;
91 void() havocbot_role_ctf_defense;
92 void() havocbot_role_ctf_offense;
93 void() havocbot_role_ctf_interceptor;
95 void(float ratingscale, vector org, float sradius) havocbot_goalrating_ctf_carrieritems =
99 head = findchainfloat(bot_pickup, TRUE);
102 // look for health and armor only
103 if (head.solid) // must be possible to pick up (respawning items don't count)
104 if (head.health || head.armorvalue)
105 if (vlen(head.origin - org) < sradius)
108 //if (!head.bot_pickupevalfunc || head.model == "")
110 // get the value of the item
111 t = head.bot_pickupevalfunc(self, head) * 0.0001;
113 navigation_routerating(head, t * ratingscale);
119 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
122 if (self.team == 5) // red
123 head = find(world, classname, "item_flag_team1"); // red flag
125 head = find(world, classname, "item_flag_team2"); // blue flag
126 navigation_routerating(head, ratingscale);
129 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
132 if (self.team == 5) // red
133 head = find(world, classname, "item_flag_team2"); // blue flag
135 head = find(world, classname, "item_flag_team1"); // red flag
136 navigation_routerating(head, ratingscale);
139 void(float ratingscale) havocbot_goalrating_ctf_enemybase =
141 // div0: needs a change in the CTF code
144 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
147 if (self.team == 5) // red
148 head = find(world, classname, "item_flag_team1"); // red flag
150 head = find(world, classname, "item_flag_team2"); // blue flag
151 if (head.cnt != FLAG_BASE)
152 navigation_routerating(head, ratingscale);
155 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
157 local entity redflag, blueflag;
159 redflag = find(world, classname, "item_flag_team1");
160 blueflag = find(world, classname, "item_flag_team2");
162 if (redflag == world)
163 error("havocbot: item_flag_team1 missing\n");
164 if (blueflag == world)
165 error("havocbot: item_flag_team2 missing\n");
167 if (redflag.cnt != FLAG_BASE) // red flag is carried or out in the field
168 navigation_routerating(redflag, ratingscale);
169 if (blueflag.cnt != FLAG_BASE) // blue flag is carried or out in the field
170 navigation_routerating(blueflag, ratingscale);
173 // CTF: (always teamplay)
175 //role rogue: (is this used?)
176 //pick up items and dropped flags (with big rating boost to dropped flags)
177 void() havocbot_role_ctf_rogue =
179 if (self.bot_strategytime < time)
181 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
182 navigation_goalrating_start();
183 havocbot_goalrating_ctf_droppedflags(5000);
184 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
185 havocbot_goalrating_items(10000, self.origin, 10000);
186 navigation_goalrating_end();
191 //pick up armor and health
192 //go to our flag spot
193 void() havocbot_role_ctf_carrier =
195 if (self.flagcarried == world)
197 dprint("changing role to middle\n");
198 self.havocbot_role = havocbot_role_ctf_middle;
199 self.havocbot_role_timeout = 0;
202 if (self.bot_strategytime < time)
204 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
205 navigation_goalrating_start();
206 havocbot_goalrating_ctf_ourflag(5000);
207 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
208 navigation_goalrating_end();
213 //pick up armor and health
214 //if rockets < 25 || health < 100, change role to middle
215 //if carrying flag, change role to flag carrier
216 //if our flag taken, change role to interceptor
217 //(60-90 second timer) change role to middle
219 void() havocbot_role_ctf_offense =
222 if (self.flagcarried)
224 dprint("changing role to carrier\n");
225 self.havocbot_role = havocbot_role_ctf_carrier;
226 self.havocbot_role_timeout = 0;
230 if (self.team == 5) // red
231 f = find(world, classname, "item_flag_team1");
233 f = find(world, classname, "item_flag_team2");
234 if (f.cnt != FLAG_BASE && canreach(f))
236 dprint("changing role to interceptor\n");
237 self.havocbot_previous_role = self.havocbot_role;
238 self.havocbot_role = havocbot_role_ctf_interceptor;
239 self.havocbot_role_timeout = 0;
242 if (!self.havocbot_role_timeout)
243 self.havocbot_role_timeout = time + random() * 30 + 60;
244 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
246 dprint("changing role to middle\n");
247 self.havocbot_role = havocbot_role_ctf_middle;
248 self.havocbot_role_timeout = 0;
251 if (self.bot_strategytime < time)
253 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
254 navigation_goalrating_start();
255 havocbot_goalrating_ctf_ourstolenflag(5000);
256 havocbot_goalrating_ctf_enemyflag(3000);
257 havocbot_goalrating_ctf_enemybase(2000);
258 havocbot_goalrating_items(10000, self.origin, 10000);
259 navigation_goalrating_end();
263 //role interceptor (temporary role):
265 //if carrying flag, change role to flag carrier
266 //if our flag is back, change role to previous role
268 //go to least recently visited area
269 void() havocbot_role_ctf_interceptor =
272 if (self.flagcarried)
274 dprint("changing role to carrier\n");
275 self.havocbot_role = havocbot_role_ctf_carrier;
276 self.havocbot_role_timeout = 0;
280 if (self.team == 5) // red
281 f = find(world, classname, "item_flag_team1");
283 f = find(world, classname, "item_flag_team2");
284 if (f.cnt == FLAG_BASE)
286 dprint("changing role back\n");
287 self.havocbot_role = self.havocbot_previous_role;
288 self.havocbot_role_timeout = 0;
292 if (self.bot_strategytime < time)
294 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
295 navigation_goalrating_start();
296 havocbot_goalrating_ctf_ourstolenflag(5000);
297 havocbot_goalrating_ctf_droppedflags(5000);
298 havocbot_goalrating_items(10000, self.origin, 10000);
299 navigation_goalrating_end();
305 //if carrying flag, change role to flag carrier
306 //if our flag taken, change role to interceptor
307 //if see flag (of either team) follow it (this has many implications)
308 //(10-20 second timer) change role to defense or offense
309 //go to least recently visited area
310 void() havocbot_role_ctf_middle =
313 if (self.flagcarried)
315 dprint("changing role to carrier\n");
316 self.havocbot_role = havocbot_role_ctf_carrier;
317 self.havocbot_role_timeout = 0;
321 if (self.team == 5) // red
322 f = find(world, classname, "item_flag_team1");
324 f = find(world, classname, "item_flag_team2");
325 if (f.cnt != FLAG_BASE && canreach(f))
327 dprint("changing role to interceptor\n");
328 self.havocbot_previous_role = self.havocbot_role;
329 self.havocbot_role = havocbot_role_ctf_interceptor;
330 self.havocbot_role_timeout = 0;
333 if (!self.havocbot_role_timeout)
334 self.havocbot_role_timeout = time + random() * 10 + 10;
335 if (time > self.havocbot_role_timeout)
336 if (self.ammo_rockets >= 25)
340 dprint("changing role to offense\n");
341 self.havocbot_role = havocbot_role_ctf_offense;
345 dprint("changing role to defense\n");
346 self.havocbot_role = havocbot_role_ctf_defense;
348 self.havocbot_role_timeout = 0;
352 if (self.bot_strategytime < time)
354 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
355 navigation_goalrating_start();
356 havocbot_goalrating_ctf_ourstolenflag(5000);
357 havocbot_goalrating_ctf_droppedflags(3000);
358 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
359 havocbot_goalrating_items(10000, self.origin, 10000);
360 navigation_goalrating_end();
365 //if rockets < 25 || health < 100, change role to middle
366 //if carrying flag, change role to flag carrier
367 //if our flag taken, change role to interceptor
368 //(30-50 second timer) change role to middle
369 //move to nearest unclaimed defense spot
370 void() havocbot_role_ctf_defense =
373 if (self.flagcarried)
375 dprint("changing role to carrier\n");
376 self.havocbot_role = havocbot_role_ctf_carrier;
377 self.havocbot_role_timeout = 0;
381 if (self.team == 5) // red
382 f = find(world, classname, "item_flag_team1");
384 f = find(world, classname, "item_flag_team2");
385 if (f.cnt != FLAG_BASE && canreach(f))
387 dprint("changing role to interceptor\n");
388 self.havocbot_previous_role = self.havocbot_role;
389 self.havocbot_role = havocbot_role_ctf_interceptor;
390 self.havocbot_role_timeout = 0;
393 if (!self.havocbot_role_timeout)
394 self.havocbot_role_timeout = time + random() * 20 + 30;
395 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
397 dprint("changing role to middle\n");
398 self.havocbot_role = havocbot_role_ctf_middle;
399 self.havocbot_role_timeout = 0;
402 if (self.bot_strategytime < time)
404 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
405 navigation_goalrating_start();
406 havocbot_goalrating_ctf_ourstolenflag(20000);
407 havocbot_goalrating_ctf_droppedflags(500);
408 havocbot_goalrating_items(10000, f.origin, 10000);
409 navigation_goalrating_end();
412 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
413 // change position occasionally
414 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
416 self.bot_strategytime = time + random() * 45 + 15;
417 self.goalentity = world;
418 head = findchain(classname, "info_ctf_defensepoint");
421 if (time > head.count)
423 self.goalentity = head;
428 // if there are no defensepoints defined, switch to middle
429 if (self.goalentity == world)
431 dprint("changing role to middle\n");
432 self.havocbot_role = havocbot_role_ctf_middle;
433 self.havocbot_role_timeout = 0;
437 // keep anyone else from taking this spot
438 if (self.goalentity != world)
439 self.goalentity.count = time + 0.5;
444 // choose a role according to the situation
445 void() havocbot_chooserole_ctf =
448 dprint("choose CTF role...\n");
450 self.havocbot_role = havocbot_role_ctf_rogue;
455 self.havocbot_role = havocbot_role_ctf_offense;
457 self.havocbot_role = havocbot_role_ctf_middle;
459 self.havocbot_role = havocbot_role_ctf_defense;
464 //go to best items, or control points you don't own
465 void() havocbot_role_dom =
467 if (self.bot_strategytime < time)
469 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
470 navigation_goalrating_start();
471 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
472 havocbot_goalrating_items(8000, self.origin, 8000);
473 //havocbot_goalrating_enemyplayers(1, self.origin, 2000);
474 //havocbot_goalrating_waypoints(1, self.origin, 1000);
475 navigation_goalrating_end();
481 void() havocbot_role_dm =
483 if (self.bot_strategytime < time)
485 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
486 navigation_goalrating_start();
487 havocbot_goalrating_items(10000, self.origin, 10000);
488 havocbot_goalrating_enemyplayers(1, self.origin, 20000);
489 //havocbot_goalrating_waypoints(1, self.origin, 1000);
490 navigation_goalrating_end();
494 void() havocbot_chooserole_dm =
496 self.havocbot_role = havocbot_role_dm;
499 void() havocbot_chooserole_dom =
501 self.havocbot_role = havocbot_role_dom;
504 void() havocbot_chooserole =
506 dprint("choose a role...\n");
507 navigation_routetogoal(world);
508 self.bot_strategytime = -1;
510 havocbot_chooserole_ctf();
511 else if (cvar("g_domination"))
512 havocbot_chooserole_dom();
513 else // assume anything else is deathmatch
514 havocbot_chooserole_dm();