]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/havocbot_roles.qc
make keys MUCH more important to bots, so they pick them up again
[divverent/nexuiz.git] / data / qcsrc / server / havocbot_roles.qc
1
2 .float havocbot_role_timeout;
3 .void() havocbot_previous_role;
4 .float bot_strategytime;
5 .void() havocbot_role;
6 float bot_ignore_bots;
7
8 float(entity e) canreach =
9 {
10         return vlen(self.origin - e.origin) < 1500;
11 }
12
13 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items =
14 {
15         local entity head;
16         local float t;
17         ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
18         head = findchainfloat(bot_pickup, TRUE);
19         while (head)
20         {
21                 if (head.solid) // must be possible to pick up (respawning items don't count)
22                 if (vlen(head.origin - org) < sradius)
23                 {
24                         // debugging
25                         //if (!head.bot_pickupevalfunc || head.model == "")
26                         //      eprint(head);
27                         // get the value of the item
28                         t = head.bot_pickupevalfunc(self, head);
29                         if (t > 0)
30                                 navigation_routerating(head, t * ratingscale, 2000);
31                 }
32                 head = head.chain;
33         }
34 };
35
36 void(float ratingscale, vector org, float sradius) havocbot_goalrating_controlpoints =
37 {
38         local entity head;
39         head = findchain(classname, "dom_controlpoint");
40         while (head)
41         {
42                 if (vlen(head.origin - org) < sradius)
43                 {
44                         if(head.cnt > -1) // this is just being fought for
45                                 navigation_routerating(head, ratingscale, 5000);
46                         else if(head.goalentity.cnt == 0) // unclaimed point
47                                 navigation_routerating(head, ratingscale * 0.5, 5000);
48                         else if(head.goalentity.team != self.team) // other team's point
49                                 navigation_routerating(head, ratingscale * 0.2, 5000);
50                 }
51                 head = head.chain;
52         }
53 };
54
55 /*
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 =
60 {
61         local entity head;
62         head = findchain(classname, "waypoint");
63         while (head)
64         {
65                 if (vlen(head.origin - org) < sradius && vlen(head.origin - org) > 100)
66                         navigation_routerating(head, ratingscale, 2000);
67                 head = head.chain;
68         }
69 };
70 */
71
72 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers =
73 {
74         local entity head;
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));
79         //dprint("\n");
80
81         FOR_EACH_PLAYER(head)
82         {
83                 if (self != head)
84                 if (head.health > 0)
85                 if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
86                 if (vlen(head.origin - org) < sradius)
87                 {
88                         t = 100 / (head.health + head.armorvalue);
89                         if (t > 0)
90                         {
91                                 //dprint("found: "); dprint(head.netname); dprint("\n");
92                                 navigation_routerating(head, t * ratingscale, 500);
93                         }
94                 }
95         }
96 };
97
98
99 void() havocbot_role_ctf_middle;
100 void() havocbot_role_ctf_defense;
101 void() havocbot_role_ctf_offense;
102 void() havocbot_role_ctf_interceptor;
103
104 void(float ratingscale, vector org, float sradius) havocbot_goalrating_ctf_carrieritems =
105 {
106         local entity head;
107         local float t;
108         head = findchainfloat(bot_pickup, TRUE);
109         while (head)
110         {
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)
115                 {
116                         // debugging
117                         //if (!head.bot_pickupevalfunc || head.model == "")
118                         //      eprint(head);
119                         // get the value of the item
120                         t = head.bot_pickupevalfunc(self, head) * 0.0001;
121                         if (t > 0)
122                                 navigation_routerating(head, t * ratingscale, 500);
123                 }
124                 head = head.chain;
125         }
126 };
127
128 entity ctf_worldflaglist;
129 .entity ctf_worldflagnext;
130 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
131 {
132         local entity head;
133         head = ctf_worldflaglist;
134         while (head)
135         {
136                 if (self.team == head.team)
137                         break;
138                 head = head.ctf_worldflagnext;
139         }
140         if (head)
141                 navigation_routerating(head, ratingscale, 10000);
142 };
143
144 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
145 {
146         local entity head;
147         head = ctf_worldflaglist;
148         while (head)
149         {
150                 if (self.team != head.team)
151                         break;
152                 head = head.ctf_worldflagnext;
153         }
154         if (head)
155                 navigation_routerating(head, ratingscale, 10000);
156 };
157
158 void(float ratingscale) havocbot_goalrating_ctf_enemybase =
159 {
160         // div0: needs a change in the CTF code
161 };
162
163 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
164 {
165         local entity head;
166         head = ctf_worldflaglist;
167         while (head)
168         {
169                 if (self.team == head.team)
170                         break;
171                 head = head.ctf_worldflagnext;
172         }
173         if (head)
174         if (head.cnt != FLAG_BASE)
175                 navigation_routerating(head, ratingscale, 10000);
176 };
177
178 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
179 {
180         local entity head;
181         head = ctf_worldflaglist;
182         while (head)
183         {
184                 if (head.cnt != FLAG_BASE) // flag is carried or out in the field
185                         navigation_routerating(head, ratingscale, 10000);
186                 head = head.ctf_worldflagnext;
187         }
188 };
189
190 // CTF: (always teamplay)
191
192 //role rogue: (is this used?)
193 //pick up items and dropped flags (with big rating boost to dropped flags)
194 void() havocbot_role_ctf_rogue =
195 {
196         if (self.bot_strategytime < time)
197         {
198                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
199                 navigation_goalrating_start();
200                 havocbot_goalrating_ctf_droppedflags(5000);
201                 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
202                 havocbot_goalrating_items(10000, self.origin, 10000);
203                 navigation_goalrating_end();
204         }
205 }
206
207 //role flag carrier:
208 //pick up armor and health
209 //go to our flag spot
210 .float bot_cantfindflag;
211 void() havocbot_role_ctf_carrier =
212 {
213         if (self.flagcarried == world)
214         {
215                 dprint("changing role to middle\n");
216                 self.havocbot_role = havocbot_role_ctf_middle;
217                 self.havocbot_role_timeout = 0;
218                 return;
219         }
220         if (self.bot_strategytime < time)
221         {
222                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
223                 navigation_goalrating_start();
224                 havocbot_goalrating_ctf_ourflag(50000);
225                 if (navigation_bestgoal)
226                         self.bot_cantfindflag = time + 10;
227                 else if (time > self.bot_cantfindflag)
228                 {
229                         // can't navigate to our own flag :(
230                         Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
231                 }
232                 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
233                 navigation_goalrating_end();
234         }
235 };
236
237 //role offense:
238 //pick up armor and health
239 //if rockets < 25 || health < 100, change role to middle
240 //if carrying flag, change role to flag carrier
241 //if our flag taken, change role to interceptor
242 //(60-90 second timer) change role to middle
243 //go to enemy flag
244 void() havocbot_role_ctf_offense =
245 {
246         local entity f;
247         if (self.flagcarried)
248         {
249                 dprint("changing role to carrier\n");
250                 self.havocbot_role = havocbot_role_ctf_carrier;
251                 self.havocbot_role_timeout = 0;
252                 self.bot_cantfindflag = time + 10;
253                 return;
254         }
255         // check our flag
256         f = ctf_worldflaglist;
257         while (f)
258         {
259                 if (self.team == f.team)
260                         break;
261                 f = f.ctf_worldflagnext;
262         }
263         if (f.cnt != FLAG_BASE && canreach(f))
264         {
265                 dprint("changing role to interceptor\n");
266                 self.havocbot_previous_role = self.havocbot_role;
267                 self.havocbot_role = havocbot_role_ctf_interceptor;
268                 self.havocbot_role_timeout = 0;
269                 return;
270         }
271         if (!self.havocbot_role_timeout)
272                 self.havocbot_role_timeout = time + random() * 30 + 60;
273         if (time > self.havocbot_role_timeout)
274         {
275                 dprint("changing role to middle\n");
276                 self.havocbot_role = havocbot_role_ctf_middle;
277                 self.havocbot_role_timeout = 0;
278                 return;
279         }
280         if (self.bot_strategytime < time)
281         {
282                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
283                 navigation_goalrating_start();
284                 havocbot_goalrating_ctf_ourstolenflag(50000);
285                 havocbot_goalrating_ctf_enemyflag(30000);
286                 havocbot_goalrating_ctf_enemybase(20000);
287                 havocbot_goalrating_items(10000, self.origin, 10000);
288                 navigation_goalrating_end();
289         }
290 };
291
292 //role interceptor (temporary role):
293 //pick up items
294 //if carrying flag, change role to flag carrier
295 //if our flag is back, change role to previous role
296 //follow our flag
297 //go to least recently visited area
298 void() havocbot_role_ctf_interceptor =
299 {
300         local entity f;
301         if (self.flagcarried)
302         {
303                 dprint("changing role to carrier\n");
304                 self.havocbot_role = havocbot_role_ctf_carrier;
305                 self.havocbot_role_timeout = 0;
306                 self.bot_cantfindflag = time + 10;
307                 return;
308         }
309         // check our flag
310         f = ctf_worldflaglist;
311         while (f)
312         {
313                 if (self.team == f.team)
314                         break;
315                 f = f.ctf_worldflagnext;
316         }
317         if (f.cnt == FLAG_BASE)
318         {
319                 dprint("changing role back\n");
320                 self.havocbot_role = self.havocbot_previous_role;
321                 self.havocbot_role_timeout = 0;
322                 return;
323         }
324
325         if (self.bot_strategytime < time)
326         {
327                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
328                 navigation_goalrating_start();
329                 havocbot_goalrating_ctf_ourstolenflag(50000);
330                 havocbot_goalrating_ctf_droppedflags(50000);
331                 havocbot_goalrating_items(10000, self.origin, 10000);
332                 navigation_goalrating_end();
333         }
334 };
335
336 //role middle:
337 //pick up items
338 //if carrying flag, change role to flag carrier
339 //if our flag taken, change role to interceptor
340 //if see flag (of either team) follow it (this has many implications)
341 //(10-20 second timer) change role to defense or offense
342 //go to least recently visited area
343 void() havocbot_role_ctf_middle =
344 {
345         local entity f;
346         if (self.flagcarried)
347         {
348                 dprint("changing role to carrier\n");
349                 self.havocbot_role = havocbot_role_ctf_carrier;
350                 self.havocbot_role_timeout = 0;
351                 self.bot_cantfindflag = time + 10;
352                 return;
353         }
354         // check our flag
355         f = ctf_worldflaglist;
356         while (f)
357         {
358                 if (self.team == f.team)
359                         break;
360                 f = f.ctf_worldflagnext;
361         }
362         if (f.cnt != FLAG_BASE && canreach(f))
363         {
364                 dprint("changing role to interceptor\n");
365                 self.havocbot_previous_role = self.havocbot_role;
366                 self.havocbot_role = havocbot_role_ctf_interceptor;
367                 self.havocbot_role_timeout = 0;
368                 return;
369         }
370         if (!self.havocbot_role_timeout)
371                 self.havocbot_role_timeout = time + random() * 10 + 10;
372         if (time > self.havocbot_role_timeout)
373         {
374                 if (random() < 0.5)
375                 {
376                         dprint("changing role to offense\n");
377                         self.havocbot_role = havocbot_role_ctf_offense;
378                 }
379                 else
380                 {
381                         dprint("changing role to defense\n");
382                         self.havocbot_role = havocbot_role_ctf_defense;
383                 }
384                 self.havocbot_role_timeout = 0;
385                 return;
386         }
387
388         if (self.bot_strategytime < time)
389         {
390                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
391                 navigation_goalrating_start();
392                 havocbot_goalrating_ctf_ourstolenflag(50000);
393                 havocbot_goalrating_ctf_droppedflags(30000);
394                 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
395                 havocbot_goalrating_items(10000, self.origin, 10000);
396                 navigation_goalrating_end();
397         }
398 };
399
400 //role defense:
401 //if rockets < 25 || health < 100, change role to middle
402 //if carrying flag, change role to flag carrier
403 //if our flag taken, change role to interceptor
404 //(30-50 second timer) change role to middle
405 //move to nearest unclaimed defense spot
406 void() havocbot_role_ctf_defense =
407 {
408         local entity f;
409         if (self.flagcarried)
410         {
411                 dprint("changing role to carrier\n");
412                 self.havocbot_role = havocbot_role_ctf_carrier;
413                 self.havocbot_role_timeout = 0;
414                 self.bot_cantfindflag = time + 10;
415                 return;
416         }
417         // check our flag
418         f = ctf_worldflaglist;
419         while (f)
420         {
421                 if (self.team == f.team)
422                         break;
423                 f = f.ctf_worldflagnext;
424         }
425         if (f.cnt != FLAG_BASE && canreach(f))
426         {
427                 dprint("changing role to interceptor\n");
428                 self.havocbot_previous_role = self.havocbot_role;
429                 self.havocbot_role = havocbot_role_ctf_interceptor;
430                 self.havocbot_role_timeout = 0;
431                 return;
432         }
433         if (!self.havocbot_role_timeout)
434                 self.havocbot_role_timeout = time + random() * 20 + 30;
435         if (time > self.havocbot_role_timeout)
436         {
437                 dprint("changing role to middle\n");
438                 self.havocbot_role = havocbot_role_ctf_middle;
439                 self.havocbot_role_timeout = 0;
440                 return;
441         }
442         if (self.bot_strategytime < time)
443         {
444                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
445                 navigation_goalrating_start();
446                 havocbot_goalrating_ctf_ourstolenflag(200000);
447                 havocbot_goalrating_ctf_droppedflags(50000);
448                 havocbot_goalrating_items(10000, f.origin, 10000);
449                 navigation_goalrating_end();
450         }
451         /*
452         // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
453         // change position occasionally
454         if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
455         {
456                 self.bot_strategytime = time + random() * 45 + 15;
457                 self.goalentity = world;
458                 head = findchain(classname, "info_ctf_defensepoint");
459                 while (head)
460                 {
461                         if (time > head.count)
462                         {
463                                 self.goalentity = head;
464                                 head.chain = world;
465                         }
466                         head = head.chain;
467                 }
468                 // if there are no defensepoints defined, switch to middle
469                 if (self.goalentity == world)
470                 {
471                         dprint("changing role to middle\n");
472                         self.havocbot_role = havocbot_role_ctf_middle;
473                         self.havocbot_role_timeout = 0;
474                         return;
475                 }
476         }
477         // keep anyone else from taking this spot
478         if (self.goalentity != world)
479                 self.goalentity.count = time + 0.5;
480         */
481 };
482
483 // CTF:
484 // choose a role according to the situation
485 void() havocbot_role_dm;
486 void() havocbot_chooserole_ctf =
487 {
488         local float r;
489         dprint("choose CTF role...\n");
490         if (self.team == COLOR_TEAM3 || self.team == COLOR_TEAM4)
491                 self.havocbot_role = havocbot_role_ctf_rogue;
492         else
493         {
494                 r = random() * 3;
495                 if (r < 1)
496                         self.havocbot_role = havocbot_role_ctf_offense;
497                 else if (r < 2)
498                         self.havocbot_role = havocbot_role_ctf_middle;
499                 else
500                         self.havocbot_role = havocbot_role_ctf_defense;
501         }
502 };
503
504 //DOM:
505 //go to best items, or control points you don't own
506 void() havocbot_role_dom =
507 {
508         if (self.bot_strategytime < time)
509         {
510                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
511                 navigation_goalrating_start();
512                 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
513                 havocbot_goalrating_items(8000, self.origin, 8000);
514                 //havocbot_goalrating_enemyplayers(3000, self.origin, 2000);
515                 //havocbot_goalrating_waypoints(1, self.origin, 1000);
516                 navigation_goalrating_end();
517         }
518 };
519
520 //DM:
521 //go to best items
522 void() havocbot_role_dm =
523 {
524         if (self.bot_strategytime < time)
525         {
526                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
527                 navigation_goalrating_start();
528                 havocbot_goalrating_items(10000, self.origin, 10000);
529                 havocbot_goalrating_enemyplayers(5000, self.origin, 20000);
530                 //havocbot_goalrating_waypoints(1, self.origin, 1000);
531                 navigation_goalrating_end();
532         }
533 };
534
535 void() havocbot_chooserole_dm =
536 {
537         self.havocbot_role = havocbot_role_dm;
538 };
539
540 void() havocbot_chooserole_dom =
541 {
542         self.havocbot_role = havocbot_role_dom;
543 };
544
545
546
547
548
549
550 entity kh_worldkeylist;
551 .entity kh_worldkeynext;
552 void(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy) havocbot_goalrating_kh =
553 {
554         local entity head;
555         for (head = kh_worldkeylist; head; head = head.kh_worldkeynext)
556         {
557                 if(head.owner == self)
558                         continue;
559                 if(!kh_tracking_enabled)
560                         if(!head.owner || head.team == self.team)
561                                 continue; // skip what I can't see
562                 if(!head.owner)
563                         navigation_routerating(head, ratingscale_dropped, 100000);
564                 else if(head.team == self.team)
565                         navigation_routerating(head, ratingscale_team, 100000);
566                 else
567                         navigation_routerating(head, ratingscale_enemy, 100000);
568         }
569 };
570
571 void() havocbot_role_kh_carrier;
572 void() havocbot_role_kh_defense;
573 void() havocbot_role_kh_offense;
574 void() havocbot_role_kh_freelancer;
575 void() havocbot_role_kh_carrier =
576 {
577         if (!(self.items & IT_KEY1))
578         {
579                 dprint("changing role to freelancer\n");
580                 self.havocbot_role = havocbot_role_kh_freelancer;
581                 self.havocbot_role_timeout = 0;
582                 return;
583         }
584
585         if (self.bot_strategytime < time)
586         {
587                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
588                 navigation_goalrating_start();
589
590                 if(kh_Key_AllOwnedByWhichTeam() == self.team)
591                         havocbot_goalrating_kh(100000, 1, 1); // bring home
592                 else
593                         havocbot_goalrating_kh(40000, 40000, 1000); // play defensively
594
595                 havocbot_goalrating_items(10000, self.origin, 10000);
596                 navigation_goalrating_end();
597         }
598 }
599
600 void() havocbot_role_kh_defense =
601 {
602         if (self.items & IT_KEY1)
603         {
604                 dprint("changing role to carrier\n");
605                 self.havocbot_role = havocbot_role_kh_carrier;
606                 self.havocbot_role_timeout = 0;
607                 return;
608         }
609
610         if (!self.havocbot_role_timeout)
611                 self.havocbot_role_timeout = time + random() * 10 + 20;
612         if (time > self.havocbot_role_timeout)
613         {
614                 dprint("changing role to freelancer\n");
615                 self.havocbot_role = havocbot_role_kh_freelancer;
616                 self.havocbot_role_timeout = 0;
617                 return;
618         }
619
620         if (self.bot_strategytime < time)
621         {
622                 float key_owner_team;
623                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
624                 navigation_goalrating_start();
625
626                 key_owner_team = kh_Key_AllOwnedByWhichTeam();
627                 if(key_owner_team == self.team)
628                         havocbot_goalrating_kh(100000, 1, 1); // defend key carriers
629                 else if(key_owner_team == -1)
630                         havocbot_goalrating_kh(40000, 10000, 1); // play defensively
631                 else
632                         havocbot_goalrating_kh(1, 1, 100000); // ATTACK ANYWAY
633
634                 havocbot_goalrating_items(10000, self.origin, 10000);
635                 navigation_goalrating_end();
636         }
637 };
638
639 void() havocbot_role_kh_offense =
640 {
641         if (self.items & IT_KEY1)
642         {
643                 dprint("changing role to carrier\n");
644                 self.havocbot_role = havocbot_role_kh_carrier;
645                 self.havocbot_role_timeout = 0;
646                 return;
647         }
648
649         if (!self.havocbot_role_timeout)
650                 self.havocbot_role_timeout = time + random() * 10 + 20;
651         if (time > self.havocbot_role_timeout)
652         {
653                 dprint("changing role to freelancer\n");
654                 self.havocbot_role = havocbot_role_kh_freelancer;
655                 self.havocbot_role_timeout = 0;
656                 return;
657         }
658
659         if (self.bot_strategytime < time)
660         {
661                 float key_owner_team;
662
663                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
664                 navigation_goalrating_start();
665
666                 key_owner_team = kh_Key_AllOwnedByWhichTeam();
667                 if(key_owner_team == self.team)
668                         havocbot_goalrating_kh(100000, 1, 1); // defend anyway
669                 else if(key_owner_team == -1)
670                         havocbot_goalrating_kh(1, 10000, 40000); // play offensively
671                 else
672                         havocbot_goalrating_kh(1, 1, 100000); // ATTACK! EMERGENCY!
673
674                 havocbot_goalrating_items(10000, self.origin, 10000);
675                 navigation_goalrating_end();
676         }
677 };
678
679 void() havocbot_role_kh_freelancer =
680 {
681         if (self.items & IT_KEY1)
682         {
683                 dprint("changing role to carrier\n");
684                 self.havocbot_role = havocbot_role_kh_carrier;
685                 self.havocbot_role_timeout = 0;
686                 return;
687         }
688
689         if (!self.havocbot_role_timeout)
690                 self.havocbot_role_timeout = time + random() * 10 + 10;
691         if (time > self.havocbot_role_timeout)
692         {
693                 if (random() < 0.5)
694                 {
695                         dprint("changing role to offense\n");
696                         self.havocbot_role = havocbot_role_kh_offense;
697                 }
698                 else
699                 {
700                         dprint("changing role to defense\n");
701                         self.havocbot_role = havocbot_role_kh_defense;
702                 }
703                 self.havocbot_role_timeout = 0;
704                 return;
705         }
706
707         if (self.bot_strategytime < time)
708         {
709                 float key_owner_team;
710
711                 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
712                 navigation_goalrating_start();
713
714                 key_owner_team = kh_Key_AllOwnedByWhichTeam();
715                 if(key_owner_team == self.team)
716                         havocbot_goalrating_kh(100000, 1, 1); // defend anyway
717                 else if(key_owner_team == -1)
718                         havocbot_goalrating_kh(10000, 40000, 10000); // prefer dropped keys
719                 else
720                         havocbot_goalrating_kh(1, 1, 100000); // ATTACK ANYWAY
721
722                 havocbot_goalrating_items(10000, self.origin, 10000);
723                 navigation_goalrating_end();
724         }
725 };
726
727
728
729
730
731 void() havocbot_chooserole_kh =
732 {
733         local float r;
734         r = random() * 3;
735         if (r < 1)
736                 self.havocbot_role = havocbot_role_kh_offense;
737         else if (r < 2)
738                 self.havocbot_role = havocbot_role_kh_defense;
739         else
740                 self.havocbot_role = havocbot_role_kh_freelancer;
741 };
742
743 void() havocbot_chooserole =
744 {
745         dprint("choose a role...\n");
746         navigation_routetogoal(world);
747         self.bot_strategytime = -1;
748         if (g_ctf)
749                 havocbot_chooserole_ctf();
750         else if (g_domination)
751                 havocbot_chooserole_dom();
752         else if (g_keyhunt)
753                 havocbot_chooserole_kh();
754         else // assume anything else is deathmatch
755                 havocbot_chooserole_dm();
756 };
757