2 .float havocbot_role_timeout;
3 .void() havocbot_previous_role;
4 .float bot_strategytime;
8 float canreach(entity e)
10 return vlen(self.origin - e.origin) < 1500;
13 .float max_armorvalue;
14 float havocbot_pickupevalfunc(entity item)
16 float i, j, rating, base, position, need_shells, need_nails, need_rockets, need_cells;
19 base = item.bot_pickupbasevalue;
21 need_shells = self.weapons & WEPBIT_SHOTGUN;
22 need_nails = self.weapons & WEPBIT_UZI;
23 need_cells = self.weapons & ( WEPBIT_HOOK | WEPBIT_HLAC | WEPBIT_MINSTANEX | WEPBIT_NEX | WEPBIT_ELECTRO | WEPBIT_CRYLINK );
24 need_rockets = self.weapons & ( WEPBIT_ROCKET_LAUNCHER | WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_SEEKER );
28 if( self.weapons & item.weapons == item.weapons )
29 rating = 0.5 + bound(0, skill / 20, 0.5);
33 if( bot_custom_weapon )
35 for(i = WEP_FIRST; i < WEP_LAST ; ++i){
36 if( power2of(i-1) & item.weapons != item.weapons )
40 for(j = 0; j < WEP_LAST ; ++j){
42 bot_weapons_far[j] == i ||
43 bot_weapons_mid[j] == i ||
44 bot_weapons_close[j] == i
54 position = WEP_LAST - position;
55 // item.bot_pickupbasevalue is overwritten here
56 base = BOT_PICKUP_RATING_LOW + ( (BOT_PICKUP_RATING_HIGH - BOT_PICKUP_RATING_LOW) * (position / WEP_LAST ));
64 if (self.ammo_shells < g_pickup_shells_max && need_cells )
65 rating = rating + max(0, 1 - self.ammo_shells / g_pickup_shells_max);
68 if (self.ammo_nails < g_pickup_nails_max && need_nails )
69 rating = rating + max(0, 1 - self.ammo_nails / g_pickup_nails_max);
71 if (item.ammo_rockets)
72 if (self.ammo_rockets < g_pickup_rockets_max && need_rockets)
73 rating = rating + max(0, 1 - self.ammo_rockets / g_pickup_rockets_max);
76 if (self.ammo_cells < g_pickup_cells_max && need_cells)
77 rating = rating + max(0, 1 - self.ammo_cells / g_pickup_cells_max);
80 if (self.armorvalue < item.max_armorvalue)
81 rating = rating + max(0, 1 - self.armorvalue / item.max_armorvalue);
84 if (self.health < item.max_health)
85 rating = rating + max(0, 1 - self.health / item.max_health);
87 // TODO: if the item is not recognized then default to item.bot_pickupevalfunc(self, item);
92 void havocbot_goalrating_items(float ratingscale, vector org, float sradius)
96 local float rating, d, discard, distance, friend_distance, enemy_distance;
97 ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
98 head = findchainfloat(bot_pickup, TRUE);
102 distance = vlen(head.origin - org);
103 friend_distance = 10000; enemy_distance = 10000;
106 if(!head.solid || distance > sradius ){
115 FOR_EACH_PLAYER(player)
118 if ( self == player || player.deadflag != DEAD_NO)
121 d = vlen(player.origin - head.origin); // distance between player and item
123 if ( player.team == self.team )
125 if ( clienttype(player) != CLIENTTYPE_REAL || discard )
128 if( d > friend_distance)
135 if( head.health && player.health > self.health )
138 if( head.armorvalue && player.armorvalue > self.armorvalue)
142 if( (player.weapons & head.weapons) != head.weapons)
145 if (head.ammo_shells && player.ammo_shells > self.ammo_shells)
148 if (head.ammo_nails && player.ammo_nails > self.ammo_nails)
151 if (head.ammo_rockets && player.ammo_rockets > self.ammo_rockets)
154 if (head.ammo_cells && player.ammo_cells > self.ammo_cells )
161 // If enemy only track distances
162 // TODO: track only if visible ?
163 if( d < enemy_distance )
168 // Rate the item only if no one needs it, or if an enemy is closer to it
169 if ( (enemy_distance < friend_distance && distance < enemy_distance) ||
170 (friend_distance > cvar("bot_ai_friends_aware_pickup_radius") ) || !discard )
172 // rating = head.bot_pickupevalfunc(self, head);
173 rating = havocbot_pickupevalfunc(head);
178 // rating = head.bot_pickupevalfunc(self, head);
179 rating = havocbot_pickupevalfunc(head);
183 navigation_routerating(head, rating * ratingscale, 2000);
189 void havocbot_goalrating_controlpoints(float ratingscale, vector org, float sradius)
192 head = findchain(classname, "dom_controlpoint");
195 if (vlen(head.origin - org) < sradius)
197 if(head.cnt > -1) // this is just being fought for
198 navigation_routerating(head, ratingscale, 5000);
199 else if(head.goalentity.cnt == 0) // unclaimed point
200 navigation_routerating(head, ratingscale * 0.5, 5000);
201 else if(head.goalentity.team != self.team) // other team's point
202 navigation_routerating(head, ratingscale * 0.2, 5000);
209 // LordHavoc: this function was already unused, but for waypoints to be a
210 // useful goal the bots would have to seek out the least-recently-visited
211 // ones, not the closest
212 void havocbot_goalrating_waypoints(float ratingscale, vector org, float sradius)
215 head = findchain(classname, "waypoint");
218 if (vlen(head.origin - org) < sradius && vlen(head.origin - org) > 100)
219 navigation_routerating(head, ratingscale, 2000);
225 void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius)
228 local float t, noteam;
229 noteam = ((self.team == 0) || (teamplay == 0)); // fteqcc sucks
230 //dprint("teamplay is "); dprint(ftos(teamplay)); dprint(", own team is ");
231 //dprint(ftos(self.team)); dprint(" -> noteam is "); dprint(ftos(noteam));
234 FOR_EACH_PLAYER(head)
238 if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
239 if (vlen(head.origin - org) < sradius)
241 t = (self.health + self.armorvalue ) / (head.health + head.armorvalue );
242 // clientcommand(self, strcat("say rating ", ftos(t*ratingscale)));
243 navigation_routerating(head, t * ratingscale, 2000);
249 void() havocbot_role_ctf_middle;
250 void() havocbot_role_ctf_defense;
251 void() havocbot_role_ctf_offense;
252 void() havocbot_role_ctf_interceptor;
254 void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
258 head = findchainfloat(bot_pickup, TRUE);
261 // look for health and armor only
262 if (head.solid) // must be possible to pick up (respawning items don't count)
263 if (head.health || head.armorvalue)
264 if (vlen(head.origin - org) < sradius)
267 //if (!head.bot_pickupevalfunc || head.model == "")
269 // get the value of the item
270 t = head.bot_pickupevalfunc(self, head) * 0.0001;
272 navigation_routerating(head, t * ratingscale, 500);
278 entity ctf_worldflaglist;
279 .entity ctf_worldflagnext;
280 void havocbot_goalrating_ctf_ourflag(float ratingscale)
283 head = ctf_worldflaglist;
286 if (self.team == head.team)
288 head = head.ctf_worldflagnext;
291 navigation_routerating(head, ratingscale, 10000);
294 void havocbot_goalrating_ctf_enemyflag(float ratingscale)
297 head = ctf_worldflaglist;
300 if (self.team != head.team)
302 head = head.ctf_worldflagnext;
305 navigation_routerating(head, ratingscale, 10000);
308 void havocbot_goalrating_ctf_enemybase(float ratingscale)
310 // div0: needs a change in the CTF code
313 void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
316 head = ctf_worldflaglist;
319 if (self.team == head.team)
321 head = head.ctf_worldflagnext;
324 if (head.cnt != FLAG_BASE)
325 navigation_routerating(head, ratingscale, 10000);
328 void havocbot_goalrating_ctf_droppedflags(float ratingscale)
331 head = ctf_worldflaglist;
334 if (head.cnt != FLAG_BASE) // flag is carried or out in the field
335 navigation_routerating(head, ratingscale, 10000);
336 head = head.ctf_worldflagnext;
340 // CTF: (always teamplay)
342 //role rogue: (is this used?)
343 //pick up items and dropped flags (with big rating boost to dropped flags)
344 void havocbot_role_ctf_rogue()
346 if (self.bot_strategytime < time)
348 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
349 navigation_goalrating_start();
350 havocbot_goalrating_ctf_droppedflags(5000);
351 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
352 havocbot_goalrating_items(10000, self.origin, 10000);
353 navigation_goalrating_end();
358 //pick up armor and health
359 //go to our flag spot
360 .float bot_cantfindflag;
361 void havocbot_role_ctf_carrier()
363 if (self.flagcarried == world)
365 dprint("changing role to middle\n");
366 self.havocbot_role = havocbot_role_ctf_middle;
367 self.havocbot_role_timeout = 0;
370 if (self.bot_strategytime < time)
372 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
373 navigation_goalrating_start();
374 havocbot_goalrating_ctf_ourflag(50000);
375 if (navigation_bestgoal)
376 self.bot_cantfindflag = time + 10;
377 else if (time > self.bot_cantfindflag)
379 // can't navigate to our own flag :(
380 Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
382 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
383 navigation_goalrating_end();
388 //pick up armor and health
389 //if rockets < 25 || health < 100, change role to middle
390 //if carrying flag, change role to flag carrier
391 //if our flag taken, change role to interceptor
392 //(60-90 second timer) change role to middle
394 void havocbot_role_ctf_offense()
397 if (self.flagcarried)
399 dprint("changing role to carrier\n");
400 self.havocbot_role = havocbot_role_ctf_carrier;
401 self.havocbot_role_timeout = 0;
402 self.bot_cantfindflag = time + 10;
406 f = ctf_worldflaglist;
409 if (self.team == f.team)
411 f = f.ctf_worldflagnext;
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() * 30 + 60;
423 if (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(50000);
435 havocbot_goalrating_ctf_enemyflag(30000);
436 havocbot_goalrating_ctf_enemybase(20000);
437 havocbot_goalrating_items(10000, self.origin, 10000);
438 navigation_goalrating_end();
442 //role interceptor (temporary role):
444 //if carrying flag, change role to flag carrier
445 //if our flag is back, change role to previous role
447 //go to least recently visited area
448 void havocbot_role_ctf_interceptor()
451 if (self.flagcarried)
453 dprint("changing role to carrier\n");
454 self.havocbot_role = havocbot_role_ctf_carrier;
455 self.havocbot_role_timeout = 0;
456 self.bot_cantfindflag = time + 10;
460 f = ctf_worldflaglist;
463 if (self.team == f.team)
465 f = f.ctf_worldflagnext;
467 if (f.cnt == FLAG_BASE)
469 dprint("changing role back\n");
470 self.havocbot_role = self.havocbot_previous_role;
471 self.havocbot_role_timeout = 0;
475 if (self.bot_strategytime < time)
477 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
478 navigation_goalrating_start();
479 havocbot_goalrating_ctf_ourstolenflag(50000);
480 havocbot_goalrating_ctf_droppedflags(50000);
481 havocbot_goalrating_items(10000, self.origin, 10000);
482 navigation_goalrating_end();
488 //if carrying flag, change role to flag carrier
489 //if our flag taken, change role to interceptor
490 //if see flag (of either team) follow it (this has many implications)
491 //(10-20 second timer) change role to defense or offense
492 //go to least recently visited area
493 void havocbot_role_ctf_middle()
496 if (self.flagcarried)
498 dprint("changing role to carrier\n");
499 self.havocbot_role = havocbot_role_ctf_carrier;
500 self.havocbot_role_timeout = 0;
501 self.bot_cantfindflag = time + 10;
505 f = ctf_worldflaglist;
508 if (self.team == f.team)
510 f = f.ctf_worldflagnext;
512 if (f.cnt != FLAG_BASE && canreach(f))
514 dprint("changing role to interceptor\n");
515 self.havocbot_previous_role = self.havocbot_role;
516 self.havocbot_role = havocbot_role_ctf_interceptor;
517 self.havocbot_role_timeout = 0;
520 if (!self.havocbot_role_timeout)
521 self.havocbot_role_timeout = time + random() * 10 + 10;
522 if (time > self.havocbot_role_timeout)
526 dprint("changing role to offense\n");
527 self.havocbot_role = havocbot_role_ctf_offense;
531 dprint("changing role to defense\n");
532 self.havocbot_role = havocbot_role_ctf_defense;
534 self.havocbot_role_timeout = 0;
538 if (self.bot_strategytime < time)
540 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
541 navigation_goalrating_start();
542 havocbot_goalrating_ctf_ourstolenflag(50000);
543 havocbot_goalrating_ctf_droppedflags(30000);
544 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
545 havocbot_goalrating_items(10000, self.origin, 10000);
546 navigation_goalrating_end();
551 //if rockets < 25 || health < 100, change role to middle
552 //if carrying flag, change role to flag carrier
553 //if our flag taken, change role to interceptor
554 //(30-50 second timer) change role to middle
555 //move to nearest unclaimed defense spot
556 void havocbot_role_ctf_defense()
559 if (self.flagcarried)
561 dprint("changing role to carrier\n");
562 self.havocbot_role = havocbot_role_ctf_carrier;
563 self.havocbot_role_timeout = 0;
564 self.bot_cantfindflag = time + 10;
568 f = ctf_worldflaglist;
571 if (self.team == f.team)
573 f = f.ctf_worldflagnext;
575 if (f.cnt != FLAG_BASE && canreach(f))
577 dprint("changing role to interceptor\n");
578 self.havocbot_previous_role = self.havocbot_role;
579 self.havocbot_role = havocbot_role_ctf_interceptor;
580 self.havocbot_role_timeout = 0;
583 if (!self.havocbot_role_timeout)
584 self.havocbot_role_timeout = time + random() * 20 + 30;
585 if (time > self.havocbot_role_timeout)
587 dprint("changing role to middle\n");
588 self.havocbot_role = havocbot_role_ctf_middle;
589 self.havocbot_role_timeout = 0;
592 if (self.bot_strategytime < time)
594 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
595 navigation_goalrating_start();
596 havocbot_goalrating_ctf_ourstolenflag(200000);
597 havocbot_goalrating_ctf_droppedflags(50000);
598 havocbot_goalrating_items(10000, f.origin, 10000);
599 navigation_goalrating_end();
602 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
603 // change position occasionally
604 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
606 self.bot_strategytime = time + random() * 45 + 15;
607 self.goalentity = world;
608 head = findchain(classname, "info_ctf_defensepoint");
611 if (time > head.count)
613 self.goalentity = head;
618 // if there are no defensepoints defined, switch to middle
619 if (self.goalentity == world)
621 dprint("changing role to middle\n");
622 self.havocbot_role = havocbot_role_ctf_middle;
623 self.havocbot_role_timeout = 0;
627 // keep anyone else from taking this spot
628 if (self.goalentity != world)
629 self.goalentity.count = time + 0.5;
634 // choose a role according to the situation
635 void() havocbot_role_dm;
636 void havocbot_chooserole_ctf()
639 dprint("choose CTF role...\n");
640 if (self.team == COLOR_TEAM3 || self.team == COLOR_TEAM4)
641 self.havocbot_role = havocbot_role_ctf_rogue;
646 self.havocbot_role = havocbot_role_ctf_offense;
648 self.havocbot_role = havocbot_role_ctf_middle;
650 self.havocbot_role = havocbot_role_ctf_defense;
655 //go to best items, or control points you don't own
656 void havocbot_role_dom()
658 if (self.bot_strategytime < time)
660 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
661 navigation_goalrating_start();
662 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
663 havocbot_goalrating_items(8000, self.origin, 8000);
664 //havocbot_goalrating_enemyplayers(3000, self.origin, 2000);
665 //havocbot_goalrating_waypoints(1, self.origin, 1000);
666 navigation_goalrating_end();
672 void havocbot_role_dm()
674 if (self.bot_strategytime < time)
676 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
677 navigation_goalrating_start();
678 havocbot_goalrating_items(10000, self.origin, 10000);
679 havocbot_goalrating_enemyplayers(10000, self.origin, 20000);
680 //havocbot_goalrating_waypoints(1, self.origin, 1000);
681 navigation_goalrating_end();
686 //go to next checkpoint, and annoy enemies
687 .float race_checkpoint;
688 void havocbot_role_race()
691 if (self.bot_strategytime < time)
693 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
694 navigation_goalrating_start();
696 havocbot_goalrating_items(100, self.origin, 10000);
697 havocbot_goalrating_enemyplayers(500, self.origin, 20000);
700 for(e = world; (e = find(e, classname, "trigger_race_checkpoint")) != world; )
702 if(e.cnt == self.race_checkpoint)
704 navigation_routerating(e, 1000000, 5000);
706 else if(self.race_checkpoint == -1)
708 navigation_routerating(e, 1000000, 5000);
712 navigation_goalrating_end();
716 void havocbot_chooserole_dm()
718 self.havocbot_role = havocbot_role_dm;
721 void havocbot_chooserole_race()
723 self.havocbot_role = havocbot_role_race;
726 void havocbot_chooserole_dom()
728 self.havocbot_role = havocbot_role_dom;
736 entity kh_worldkeylist;
737 .entity kh_worldkeynext;
738 void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy)
741 for (head = kh_worldkeylist; head; head = head.kh_worldkeynext)
743 if(head.owner == self)
745 if(!kh_tracking_enabled)
747 // if it's carried by our team we know about it
748 // otherwise we have to see it to know about it
749 if(!head.owner || head.team != self.team)
751 traceline(self.origin + self.view_ofs, head.origin, MOVE_NOMONSTERS, self);
752 if (trace_fraction < 1 && trace_ent != head)
753 continue; // skip what I can't see
757 navigation_routerating(head, ratingscale_dropped, 100000);
758 else if(head.team == self.team)
759 navigation_routerating(head, ratingscale_team, 100000);
761 navigation_routerating(head, ratingscale_enemy, 100000);
765 void() havocbot_role_kh_carrier;
766 void() havocbot_role_kh_defense;
767 void() havocbot_role_kh_offense;
768 void() havocbot_role_kh_freelancer;
769 void havocbot_role_kh_carrier()
771 if (!(self.items & IT_KEY1))
773 dprint("changing role to freelancer\n");
774 self.havocbot_role = havocbot_role_kh_freelancer;
775 self.havocbot_role_timeout = 0;
779 if (self.bot_strategytime < time)
781 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
782 navigation_goalrating_start();
784 if(kh_Key_AllOwnedByWhichTeam() == self.team)
785 havocbot_goalrating_kh(100000, 1, 1); // bring home
787 havocbot_goalrating_kh(40000, 40000, 1000); // play defensively
789 havocbot_goalrating_items(10000, self.origin, 10000);
790 navigation_goalrating_end();
794 void havocbot_role_kh_defense()
796 if (self.items & IT_KEY1)
798 dprint("changing role to carrier\n");
799 self.havocbot_role = havocbot_role_kh_carrier;
800 self.havocbot_role_timeout = 0;
804 if (!self.havocbot_role_timeout)
805 self.havocbot_role_timeout = time + random() * 10 + 20;
806 if (time > self.havocbot_role_timeout)
808 dprint("changing role to freelancer\n");
809 self.havocbot_role = havocbot_role_kh_freelancer;
810 self.havocbot_role_timeout = 0;
814 if (self.bot_strategytime < time)
816 float key_owner_team;
817 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
818 navigation_goalrating_start();
820 key_owner_team = kh_Key_AllOwnedByWhichTeam();
821 if(key_owner_team == self.team)
822 havocbot_goalrating_kh(100000, 1, 1); // defend key carriers
823 else if(key_owner_team == -1)
824 havocbot_goalrating_kh(40000, 10000, 1); // play defensively
826 havocbot_goalrating_kh(1, 1, 100000); // ATTACK ANYWAY
828 havocbot_goalrating_items(10000, self.origin, 10000);
829 navigation_goalrating_end();
833 void havocbot_role_kh_offense()
835 if (self.items & IT_KEY1)
837 dprint("changing role to carrier\n");
838 self.havocbot_role = havocbot_role_kh_carrier;
839 self.havocbot_role_timeout = 0;
843 if (!self.havocbot_role_timeout)
844 self.havocbot_role_timeout = time + random() * 10 + 20;
845 if (time > self.havocbot_role_timeout)
847 dprint("changing role to freelancer\n");
848 self.havocbot_role = havocbot_role_kh_freelancer;
849 self.havocbot_role_timeout = 0;
853 if (self.bot_strategytime < time)
855 float key_owner_team;
857 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
858 navigation_goalrating_start();
860 key_owner_team = kh_Key_AllOwnedByWhichTeam();
861 if(key_owner_team == self.team)
862 havocbot_goalrating_kh(100000, 1, 1); // defend anyway
863 else if(key_owner_team == -1)
864 havocbot_goalrating_kh(1, 10000, 40000); // play offensively
866 havocbot_goalrating_kh(1, 1, 100000); // ATTACK! EMERGENCY!
868 havocbot_goalrating_items(10000, self.origin, 10000);
869 navigation_goalrating_end();
873 void havocbot_role_kh_freelancer()
875 if (self.items & IT_KEY1)
877 dprint("changing role to carrier\n");
878 self.havocbot_role = havocbot_role_kh_carrier;
879 self.havocbot_role_timeout = 0;
883 if (!self.havocbot_role_timeout)
884 self.havocbot_role_timeout = time + random() * 10 + 10;
885 if (time > self.havocbot_role_timeout)
889 dprint("changing role to offense\n");
890 self.havocbot_role = havocbot_role_kh_offense;
894 dprint("changing role to defense\n");
895 self.havocbot_role = havocbot_role_kh_defense;
897 self.havocbot_role_timeout = 0;
901 if (self.bot_strategytime < time)
903 float key_owner_team;
905 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
906 navigation_goalrating_start();
908 key_owner_team = kh_Key_AllOwnedByWhichTeam();
909 if(key_owner_team == self.team)
910 havocbot_goalrating_kh(100000, 1, 1); // defend anyway
911 else if(key_owner_team == -1)
912 havocbot_goalrating_kh(10000, 40000, 10000); // prefer dropped keys
914 havocbot_goalrating_kh(1, 1, 100000); // ATTACK ANYWAY
916 havocbot_goalrating_items(10000, self.origin, 10000);
917 navigation_goalrating_end();
925 void havocbot_chooserole_kh()
930 self.havocbot_role = havocbot_role_kh_offense;
932 self.havocbot_role = havocbot_role_kh_defense;
934 self.havocbot_role = havocbot_role_kh_freelancer;
937 void havocbot_chooserole()
939 dprint("choose a role...\n");
940 navigation_routetogoal(world);
941 self.bot_strategytime = -1;
943 havocbot_chooserole_ctf();
944 else if (g_domination)
945 havocbot_chooserole_dom();
947 havocbot_chooserole_kh();
949 havocbot_chooserole_race();
950 else // assume anything else is deathmatch
951 havocbot_chooserole_dm();