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 ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
18 head = findchainfloat(bot_pickup, TRUE);
21 if (head.solid) // must be possible to pick up (respawning items don't count)
22 if (vlen(head.origin - org) < sradius)
25 //if (!head.bot_pickupevalfunc || head.model == "")
27 // get the value of the item
28 t = head.bot_pickupevalfunc(self, head);
30 navigation_routerating(head, t * ratingscale);
36 void(float ratingscale, vector org, float sradius) havocbot_goalrating_controlpoints =
39 head = findchain(classname, "dom_controlpoint");
42 if (vlen(head.origin - org) < sradius)
44 if(head.cnt > -1) // this is just being fought for
45 navigation_routerating(head, ratingscale);
46 else if(head.goalentity.cnt == 0) // unclaimed point
47 navigation_routerating(head, ratingscale * 0.5);
48 else if(head.goalentity.team != self.team) // other team's point
49 navigation_routerating(head, ratingscale * 0.2);
56 // LordHavoc: this function was already unused, but for waypoints to be a
57 // useful goal the bots would have to seek out the least-recently-visited
58 // ones, not the closest
59 void(float ratingscale, vector org, float sradius) havocbot_goalrating_waypoints =
62 head = findchain(classname, "waypoint");
65 if (vlen(head.origin - org) < sradius && vlen(head.origin - org) > 100)
66 navigation_routerating(head, ratingscale);
72 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers =
75 local float t, noteam;
76 noteam = ((self.team == 0) || (teamplay == 0)); // fteqcc sucks
77 //dprint("teamplay is "); dprint(ftos(teamplay)); dprint(", own team is ");
78 //dprint(ftos(self.team)); dprint(" -> noteam is "); dprint(ftos(noteam));
85 if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
86 if (vlen(head.origin - org) < sradius)
88 t = 100 / (head.health + head.armorvalue);
91 //dprint("found: "); dprint(head.netname); dprint("\n");
92 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);
129 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
135 if (self.team == head.team)
140 navigation_routerating(head, ratingscale);
143 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
149 if (self.team != head.team)
154 navigation_routerating(head, ratingscale);
157 void(float ratingscale) havocbot_goalrating_ctf_enemybase =
159 // div0: needs a change in the CTF code
162 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
168 if (self.team == head.team)
173 if (head.cnt != FLAG_BASE)
174 navigation_routerating(head, ratingscale);
177 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
183 if (head.cnt != FLAG_BASE) // flag is carried or out in the field
184 navigation_routerating(head, ratingscale);
189 // CTF: (always teamplay)
191 //role rogue: (is this used?)
192 //pick up items and dropped flags (with big rating boost to dropped flags)
193 void() havocbot_role_ctf_rogue =
195 if (self.bot_strategytime < time)
197 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
198 navigation_goalrating_start();
199 havocbot_goalrating_ctf_droppedflags(5000);
200 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
201 havocbot_goalrating_items(10000, self.origin, 10000);
202 navigation_goalrating_end();
207 //pick up armor and health
208 //go to our flag spot
209 void() havocbot_role_ctf_carrier =
211 if (self.flagcarried == world)
213 dprint("changing role to middle\n");
214 self.havocbot_role = havocbot_role_ctf_middle;
215 self.havocbot_role_timeout = 0;
218 if (self.bot_strategytime < time)
220 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
221 navigation_goalrating_start();
222 havocbot_goalrating_ctf_ourflag(5000);
223 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
224 navigation_goalrating_end();
229 //pick up armor and health
230 //if rockets < 25 || health < 100, change role to middle
231 //if carrying flag, change role to flag carrier
232 //if our flag taken, change role to interceptor
233 //(60-90 second timer) change role to middle
235 void() havocbot_role_ctf_offense =
238 if (self.flagcarried)
240 dprint("changing role to carrier\n");
241 self.havocbot_role = havocbot_role_ctf_carrier;
242 self.havocbot_role_timeout = 0;
249 if (self.team == f.team)
253 if (f.cnt != FLAG_BASE && canreach(f))
255 dprint("changing role to interceptor\n");
256 self.havocbot_previous_role = self.havocbot_role;
257 self.havocbot_role = havocbot_role_ctf_interceptor;
258 self.havocbot_role_timeout = 0;
261 if (!self.havocbot_role_timeout)
262 self.havocbot_role_timeout = time + random() * 30 + 60;
263 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
265 dprint("changing role to middle\n");
266 self.havocbot_role = havocbot_role_ctf_middle;
267 self.havocbot_role_timeout = 0;
270 if (self.bot_strategytime < time)
272 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
273 navigation_goalrating_start();
274 havocbot_goalrating_ctf_ourstolenflag(5000);
275 havocbot_goalrating_ctf_enemyflag(3000);
276 havocbot_goalrating_ctf_enemybase(2000);
277 havocbot_goalrating_items(10000, self.origin, 10000);
278 navigation_goalrating_end();
282 //role interceptor (temporary role):
284 //if carrying flag, change role to flag carrier
285 //if our flag is back, change role to previous role
287 //go to least recently visited area
288 void() havocbot_role_ctf_interceptor =
291 if (self.flagcarried)
293 dprint("changing role to carrier\n");
294 self.havocbot_role = havocbot_role_ctf_carrier;
295 self.havocbot_role_timeout = 0;
302 if (self.team == f.team)
306 if (f.cnt == FLAG_BASE)
308 dprint("changing role back\n");
309 self.havocbot_role = self.havocbot_previous_role;
310 self.havocbot_role_timeout = 0;
314 if (self.bot_strategytime < time)
316 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
317 navigation_goalrating_start();
318 havocbot_goalrating_ctf_ourstolenflag(5000);
319 havocbot_goalrating_ctf_droppedflags(5000);
320 havocbot_goalrating_items(10000, self.origin, 10000);
321 navigation_goalrating_end();
327 //if carrying flag, change role to flag carrier
328 //if our flag taken, change role to interceptor
329 //if see flag (of either team) follow it (this has many implications)
330 //(10-20 second timer) change role to defense or offense
331 //go to least recently visited area
332 void() havocbot_role_ctf_middle =
335 if (self.flagcarried)
337 dprint("changing role to carrier\n");
338 self.havocbot_role = havocbot_role_ctf_carrier;
339 self.havocbot_role_timeout = 0;
346 if (self.team == f.team)
350 if (f.cnt != FLAG_BASE && canreach(f))
352 dprint("changing role to interceptor\n");
353 self.havocbot_previous_role = self.havocbot_role;
354 self.havocbot_role = havocbot_role_ctf_interceptor;
355 self.havocbot_role_timeout = 0;
358 if (!self.havocbot_role_timeout)
359 self.havocbot_role_timeout = time + random() * 10 + 10;
360 if (time > self.havocbot_role_timeout)
361 if (self.ammo_rockets >= 25)
365 dprint("changing role to offense\n");
366 self.havocbot_role = havocbot_role_ctf_offense;
370 dprint("changing role to defense\n");
371 self.havocbot_role = havocbot_role_ctf_defense;
373 self.havocbot_role_timeout = 0;
377 if (self.bot_strategytime < time)
379 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
380 navigation_goalrating_start();
381 havocbot_goalrating_ctf_ourstolenflag(5000);
382 havocbot_goalrating_ctf_droppedflags(3000);
383 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
384 havocbot_goalrating_items(10000, self.origin, 10000);
385 navigation_goalrating_end();
390 //if rockets < 25 || health < 100, change role to middle
391 //if carrying flag, change role to flag carrier
392 //if our flag taken, change role to interceptor
393 //(30-50 second timer) change role to middle
394 //move to nearest unclaimed defense spot
395 void() havocbot_role_ctf_defense =
398 if (self.flagcarried)
400 dprint("changing role to carrier\n");
401 self.havocbot_role = havocbot_role_ctf_carrier;
402 self.havocbot_role_timeout = 0;
409 if (self.team == f.team)
413 if (f.cnt != FLAG_BASE && canreach(f))
415 dprint("changing role to interceptor\n");
416 self.havocbot_previous_role = self.havocbot_role;
417 self.havocbot_role = havocbot_role_ctf_interceptor;
418 self.havocbot_role_timeout = 0;
421 if (!self.havocbot_role_timeout)
422 self.havocbot_role_timeout = time + random() * 20 + 30;
423 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
425 dprint("changing role to middle\n");
426 self.havocbot_role = havocbot_role_ctf_middle;
427 self.havocbot_role_timeout = 0;
430 if (self.bot_strategytime < time)
432 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
433 navigation_goalrating_start();
434 havocbot_goalrating_ctf_ourstolenflag(20000);
435 havocbot_goalrating_ctf_droppedflags(500);
436 havocbot_goalrating_items(10000, f.origin, 10000);
437 navigation_goalrating_end();
440 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
441 // change position occasionally
442 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
444 self.bot_strategytime = time + random() * 45 + 15;
445 self.goalentity = world;
446 head = findchain(classname, "info_ctf_defensepoint");
449 if (time > head.count)
451 self.goalentity = head;
456 // if there are no defensepoints defined, switch to middle
457 if (self.goalentity == world)
459 dprint("changing role to middle\n");
460 self.havocbot_role = havocbot_role_ctf_middle;
461 self.havocbot_role_timeout = 0;
465 // keep anyone else from taking this spot
466 if (self.goalentity != world)
467 self.goalentity.count = time + 0.5;
472 // choose a role according to the situation
473 void() havocbot_role_dm;
474 void() havocbot_chooserole_ctf =
477 dprint("choose CTF role...\n");
478 if (self.team == COLOR_TEAM3 || self.team == COLOR_TEAM4)
479 self.havocbot_role = havocbot_role_ctf_rogue;
484 self.havocbot_role = havocbot_role_ctf_offense;
486 self.havocbot_role = havocbot_role_ctf_middle;
488 self.havocbot_role = havocbot_role_ctf_defense;
493 //go to best items, or control points you don't own
494 void() havocbot_role_dom =
496 if (self.bot_strategytime < time)
498 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
499 navigation_goalrating_start();
500 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
501 havocbot_goalrating_items(8000, self.origin, 8000);
502 //havocbot_goalrating_enemyplayers(3000, self.origin, 2000);
503 //havocbot_goalrating_waypoints(1, self.origin, 1000);
504 navigation_goalrating_end();
510 void() havocbot_role_dm =
512 if (self.bot_strategytime < time)
514 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
515 navigation_goalrating_start();
516 havocbot_goalrating_items(10000, self.origin, 10000);
517 havocbot_goalrating_enemyplayers(5000, self.origin, 20000);
518 //havocbot_goalrating_waypoints(1, self.origin, 1000);
519 navigation_goalrating_end();
523 void() havocbot_chooserole_dm =
525 self.havocbot_role = havocbot_role_dm;
528 void() havocbot_chooserole_dom =
530 self.havocbot_role = havocbot_role_dom;
539 void(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy) havocbot_goalrating_kh =
545 if(head.owner == self)
547 if(!kh_tracking_enabled)
548 if(!head.owner || head.team == self.team)
549 continue; // skip what I can't see
551 navigation_routerating(head, ratingscale_dropped);
552 else if(head.team == self.team)
553 navigation_routerating(head, ratingscale_team);
555 navigation_routerating(head, ratingscale_enemy);
560 void() havocbot_role_kh_carrier;
561 void() havocbot_role_kh_defense;
562 void() havocbot_role_kh_offense;
563 void() havocbot_role_kh_freelancer;
564 void() havocbot_role_kh_carrier =
566 if (!(self.items & IT_KEY1))
568 dprint("changing role to freelancer\n");
569 self.havocbot_role = havocbot_role_kh_freelancer;
570 self.havocbot_role_timeout = 0;
574 if (self.bot_strategytime < time)
576 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
577 navigation_goalrating_start();
579 if(kh_Key_AllOwnedByWhichTeam() == self.team)
580 havocbot_goalrating_kh(10000, 1, 1); // bring home
582 havocbot_goalrating_kh(4000, 4000, 100); // play defensively
584 havocbot_goalrating_items(10000, self.origin, 10000);
585 navigation_goalrating_end();
589 void() havocbot_role_kh_defense =
591 if (self.items & IT_KEY1)
593 dprint("changing role to carrier\n");
594 self.havocbot_role = havocbot_role_kh_carrier;
595 self.havocbot_role_timeout = 0;
599 if (!self.havocbot_role_timeout)
600 self.havocbot_role_timeout = time + random() * 10 + 20;
601 if (time > self.havocbot_role_timeout)
603 dprint("changing role to freelancer\n");
604 self.havocbot_role = havocbot_role_kh_freelancer;
605 self.havocbot_role_timeout = 0;
609 if (self.bot_strategytime < time)
611 float key_owner_team;
612 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
613 navigation_goalrating_start();
615 key_owner_team = kh_Key_AllOwnedByWhichTeam();
616 if(key_owner_team == self.team)
617 havocbot_goalrating_kh(10000, 1, 1); // defend key carriers
618 else if(key_owner_team == -1)
619 havocbot_goalrating_kh(4000, 1000, 1); // play defensively
621 havocbot_goalrating_kh(1, 1, 10000); // ATTACK ANYWAY
623 havocbot_goalrating_items(10000, self.origin, 10000);
624 navigation_goalrating_end();
628 void() havocbot_role_kh_offense =
630 if (self.items & IT_KEY1)
632 dprint("changing role to carrier\n");
633 self.havocbot_role = havocbot_role_kh_carrier;
634 self.havocbot_role_timeout = 0;
638 if (!self.havocbot_role_timeout)
639 self.havocbot_role_timeout = time + random() * 10 + 20;
640 if (time > self.havocbot_role_timeout)
642 dprint("changing role to freelancer\n");
643 self.havocbot_role = havocbot_role_kh_freelancer;
644 self.havocbot_role_timeout = 0;
648 if (self.bot_strategytime < time)
650 float key_owner_team;
652 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
653 navigation_goalrating_start();
655 key_owner_team = kh_Key_AllOwnedByWhichTeam();
656 if(key_owner_team == self.team)
657 havocbot_goalrating_kh(10000, 1, 1); // defend anyway
658 else if(key_owner_team == -1)
659 havocbot_goalrating_kh(1, 1000, 4000); // play offensively
661 havocbot_goalrating_kh(1, 1, 10000); // ATTACK! EMERGENCY!
663 havocbot_goalrating_items(10000, self.origin, 10000);
664 navigation_goalrating_end();
668 void() havocbot_role_kh_freelancer =
670 if (self.items & IT_KEY1)
672 dprint("changing role to carrier\n");
673 self.havocbot_role = havocbot_role_kh_carrier;
674 self.havocbot_role_timeout = 0;
678 if (!self.havocbot_role_timeout)
679 self.havocbot_role_timeout = time + random() * 10 + 10;
680 if (time > self.havocbot_role_timeout)
684 dprint("changing role to offense\n");
685 self.havocbot_role = havocbot_role_kh_offense;
689 dprint("changing role to defense\n");
690 self.havocbot_role = havocbot_role_kh_defense;
692 self.havocbot_role_timeout = 0;
696 if (self.bot_strategytime < time)
698 float key_owner_team;
700 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
701 navigation_goalrating_start();
703 key_owner_team = kh_Key_AllOwnedByWhichTeam();
704 if(key_owner_team == self.team)
705 havocbot_goalrating_kh(10000, 1, 1); // defend anyway
706 else if(key_owner_team == -1)
707 havocbot_goalrating_kh(1000, 4000, 1000); // prefer dropped keys
709 havocbot_goalrating_kh(1, 1, 10000); // ATTACK ANYWAY
711 havocbot_goalrating_items(10000, self.origin, 10000);
712 navigation_goalrating_end();
720 void() havocbot_chooserole_kh =
725 self.havocbot_role = havocbot_role_kh_offense;
727 self.havocbot_role = havocbot_role_kh_defense;
729 self.havocbot_role = havocbot_role_kh_freelancer;
732 void() havocbot_chooserole =
734 dprint("choose a role...\n");
735 navigation_routetogoal(world);
736 self.bot_strategytime = -1;
738 havocbot_chooserole_ctf();
739 else if (g_domination)
740 havocbot_chooserole_dom();
742 havocbot_chooserole_kh();
743 else // assume anything else is deathmatch
744 havocbot_chooserole_dm();