2 .float havocbot_role_timeout;
3 .float bot_strategytime;
6 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items =
10 head = findchainfloat(bot_pickup, TRUE);
13 if (head.solid) // must be possible to pick up (respawning items don't count)
14 if (vlen(head.origin - org) < sradius)
17 //if (!head.bot_pickupevalfunc || head.model == "")
19 // get the value of the item
20 t = head.bot_pickupevalfunc(self, head) * 0.0001;
22 navigation_routerating(head, t * ratingscale);
28 void(float ratingscale, vector org, float sradius) havocbot_goalrating_controlpoints =
31 head = findchain(classname, "dom_controlpoint");
34 if (vlen(head.origin - org) < sradius)
36 if(head.cnt > -1) // this is just being fought for
37 navigation_routerating(head, ratingscale);
38 else if(head.goalentity.cnt == 0) // unclaimed point
39 navigation_routerating(head, ratingscale * 0.5);
40 else if(head.goalentity.team != self.team) // other team's point
41 navigation_routerating(head, ratingscale * 0.2);
47 void(float ratingscale, vector org, float sradius) havocbot_goalrating_waypoints =
50 head = findchain(classname, "waypoint");
53 if (vlen(head.origin - org) < sradius && vlen(head.origin - org) > 100)
54 navigation_routerating(head, ratingscale);
59 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers =
62 local float t, noteam;
63 ratingscale = ratingscale * 1200;
64 noteam = self.team == 0 || teamplay == 0;
65 head = findchain(classname, "player");
69 if (head.team != self.team || noteam)
70 if (vlen(head.origin - org) < sradius)
75 t = t / (head.health + head.armortype * head.armorvalue);
77 navigation_routerating(head, t * ratingscale);
84 void() havocbot_role_ctf_middle;
85 void() havocbot_role_ctf_defense;
86 void() havocbot_role_ctf_offense;
88 void(float ratingscale, vector org, float sradius) havocbot_goalrating_ctf_carrieritems =
92 head = findchainfloat(bot_pickup, TRUE);
95 // look for health and armor only
96 if (head.solid) // must be possible to pick up (respawning items don't count)
97 if (head.health || head.armorvalue)
98 if (vlen(head.origin - org) < sradius)
101 //if (!head.bot_pickupevalfunc || head.model == "")
103 // get the value of the item
104 t = head.bot_pickupevalfunc(self, head) * 0.0001;
106 navigation_routerating(head, t * ratingscale);
112 void(float ratingscale) havocbot_goalrating_ctf_ourflag =
115 if (self.team == 5) // red
116 head = find(world, classname, "item_flag_team1"); // red flag
118 head = find(world, classname, "item_flag_team2"); // blue flag
119 navigation_routerating(head, ratingscale);
122 void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
125 if (self.team == 5) // red
126 head = find(world, classname, "item_flag_team2"); // blue flag
128 head = find(world, classname, "item_flag_team1"); // red flag
129 navigation_routerating(head, ratingscale);
132 void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
135 if (self.team == 5) // red
136 head = find(world, classname, "item_flag_team1"); // red flag
138 head = find(world, classname, "item_flag_team2"); // blue flag
139 if (head.cnt != FLAG_BASE)
140 navigation_routerating(head, ratingscale);
143 void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
145 local entity redflag, blueflag;
147 redflag = find(world, classname, "item_flag_team1");
148 blueflag = find(world, classname, "item_flag_team2");
150 if (redflag == world)
151 error("havocbot: item_flag_team1 missing\n");
152 if (blueflag == world)
153 error("havocbot: item_flag_team2 missing\n");
155 if (redflag.cnt != FLAG_BASE) // red flag is carried or out in the field
156 navigation_routerating(redflag, ratingscale);
157 if (blueflag.cnt != FLAG_BASE) // blue flag is carried or out in the field
158 navigation_routerating(blueflag, ratingscale);
161 // CTF: (always teamplay)
163 //role rogue: (is this used?)
164 //pick up items and dropped flags (with big rating boost to dropped flags)
165 void() havocbot_role_ctf_rogue =
167 if (self.bot_strategytime < time)
169 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
170 navigation_goalrating_start();
171 havocbot_goalrating_ctf_droppedflags(5000);
172 //havocbot_goalrating_enemyplayers(3000, self.origin, 3000);
173 havocbot_goalrating_items(10000, self.origin, 10000);
174 navigation_goalrating_end();
179 //pick up armor and health
180 //go to our flag spot
181 void() havocbot_role_ctf_carrier =
183 if (self.flagcarried == world)
185 dprint("changing role to middle\n");
186 self.havocbot_role = havocbot_role_ctf_middle;
187 self.havocbot_role_timeout = 0;
190 if (self.bot_strategytime < time)
192 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
193 navigation_goalrating_start();
194 havocbot_goalrating_ctf_ourflag(5000);
195 havocbot_goalrating_ctf_carrieritems(1000, self.origin, 1000);
196 navigation_goalrating_end();
201 //pick up armor and health
202 //if rockets < 25 || health < 100, change role to middle
203 //if carrying flag, change role to flag carrier
204 //if our flag taken, change role to interceptor
205 //(60-90 second timer) change role to middle
207 void() havocbot_role_ctf_offense =
210 if (self.flagcarried)
212 dprint("changing role to carrier\n");
213 self.havocbot_role = havocbot_role_ctf_carrier;
214 self.havocbot_role_timeout = 0;
219 if (self.team == 5) // red
220 f = find(world, classname, "item_flag_team1");
222 f = find(world, classname, "item_flag_team2");
223 if (f.cnt != FLAG_BASE && canreach(f))
225 dprint("changing role to interceptor\n");
226 self.havocbot_role = havocbot_role_ctf_interceptor;
227 self.havocbot_role_timeout = 0;
231 if (!self.havocbot_role_timeout)
232 self.havocbot_role_timeout = time + random() * 30 + 60;
233 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
235 dprint("changing role to middle\n");
236 self.havocbot_role = havocbot_role_ctf_middle;
237 self.havocbot_role_timeout = 0;
240 if (self.bot_strategytime < time)
242 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
243 navigation_goalrating_start();
244 havocbot_goalrating_ctf_ourstolenflag(5000);
245 havocbot_goalrating_ctf_enemyflag(3000);
246 havocbot_goalrating_items(10000, self.origin, 10000);
247 navigation_goalrating_end();
253 //if carrying flag, change role to flag carrier
254 //if our flag taken, change role to interceptor
255 //if see flag (of either team) follow it (this has many implications)
256 //(10-20 second timer) change role to defense or offense
257 //go to least recently visited area
258 void() havocbot_role_ctf_middle =
260 if (self.flagcarried)
262 dprint("changing role to carrier\n");
263 self.havocbot_role = havocbot_role_ctf_carrier;
264 self.havocbot_role_timeout = 0;
269 if (self.team == 5) // red
270 f = find(world, classname, "item_flag_team1");
272 f = find(world, classname, "item_flag_team2");
273 if (f.cnt != FLAG_BASE && canreach(f))
275 dprint("changing role to interceptor\n");
276 self.havocbot_role = havocbot_role_ctf_interceptor;
277 self.havocbot_role_timeout = 0;
281 if (!self.havocbot_role_timeout)
282 self.havocbot_role_timeout = time + random() * 10 + 10;
283 if (time > self.havocbot_role_timeout)
284 if (self.ammo_rockets >= 25)
288 dprint("changing role to offense\n");
289 self.havocbot_role = havocbot_role_ctf_offense;
293 dprint("changing role to defense\n");
294 self.havocbot_role = havocbot_role_ctf_defense;
296 self.havocbot_role_timeout = 0;
300 if (self.bot_strategytime < time)
302 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
303 navigation_goalrating_start();
304 havocbot_goalrating_ctf_ourstolenflag(5000);
305 havocbot_goalrating_ctf_droppedflags(3000);
306 //havocbot_goalrating_enemyplayers(1000, self.origin, 1000);
307 havocbot_goalrating_items(10000, self.origin, 10000);
308 navigation_goalrating_end();
313 //if rockets < 25 || health < 100, change role to middle
314 //if carrying flag, change role to flag carrier
315 //if our flag taken, change role to interceptor
316 //(30-50 second timer) change role to middle
317 //move to nearest unclaimed defense spot
318 void() havocbot_role_ctf_defense =
321 if (self.flagcarried)
323 dprint("changing role to carrier\n");
324 self.havocbot_role = havocbot_role_ctf_carrier;
325 self.havocbot_role_timeout = 0;
330 if (self.team == 5) // red
331 f = find(world, classname, "item_flag_team1");
333 f = find(world, classname, "item_flag_team2");
334 if (f.cnt != FLAG_BASE && canreach(f))
336 dprint("changing role to interceptor\n");
337 self.havocbot_role = havocbot_role_ctf_interceptor;
338 self.havocbot_role_timeout = 0;
342 if (!self.havocbot_role_timeout)
343 self.havocbot_role_timeout = time + random() * 20 + 30;
344 if (self.ammo_rockets < 15 || time > self.havocbot_role_timeout)
346 dprint("changing role to middle\n");
347 self.havocbot_role = havocbot_role_ctf_middle;
348 self.havocbot_role_timeout = 0;
351 if (self.bot_strategytime < time)
353 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
354 navigation_goalrating_start();
355 havocbot_goalrating_ctf_ourstolenflag(20000);
356 havocbot_goalrating_items(10000, f.origin, 10000);
357 navigation_goalrating_end();
360 // FIXME: place info_ctf_defensepoint entities in CTF maps and use them
361 // change position occasionally
362 if (time > self.bot_strategytime || self.goalentity.classname != "info_ctf_defensepoint")
364 self.bot_strategytime = time + random() * 45 + 15;
365 self.goalentity = world;
366 head = findchain(classname, "info_ctf_defensepoint");
369 if (time > head.count)
371 self.goalentity = head;
376 // if there are no defensepoints defined, switch to middle
377 if (self.goalentity == world)
379 dprint("changing role to middle\n");
380 self.havocbot_role = havocbot_role_ctf_middle;
381 self.havocbot_role_timeout = 0;
385 // keep anyone else from taking this spot
386 if (self.goalentity != world)
387 self.goalentity.count = time + 0.5;
392 // choose a role according to the situation
393 void() havocbot_chooserole_ctf =
396 dprint("choose CTF role...\n");
398 self.havocbot_role = havocbot_role_ctf_rogue;
403 self.havocbot_role = havocbot_role_ctf_offense;
405 self.havocbot_role = havocbot_role_ctf_middle;
407 self.havocbot_role = havocbot_role_ctf_defense;
412 //go to best items, or control points you don't own
413 void() havocbot_role_dom =
415 if (self.bot_strategytime < time)
417 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
418 navigation_goalrating_start();
419 havocbot_goalrating_controlpoints(10000, self.origin, 15000);
420 havocbot_goalrating_items(8000, self.origin, 8000);
421 //havocbot_goalrating_enemyplayers(1, self.origin, 2000);
422 //havocbot_goalrating_waypoints(1, self.origin, 1000);
423 navigation_goalrating_end();
429 void() havocbot_role_dm =
431 if (self.bot_strategytime < time)
433 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
434 navigation_goalrating_start();
435 havocbot_goalrating_items(10000, self.origin, 10000);
436 havocbot_goalrating_enemyplayers(1, self.origin, 2000);
437 //havocbot_goalrating_waypoints(1, self.origin, 1000);
438 navigation_goalrating_end();
442 void() havocbot_chooserole_dm =
444 self.havocbot_role = havocbot_role_dm;
447 void() havocbot_chooserole_dom =
449 self.havocbot_role = havocbot_role_dom;
452 void() havocbot_chooserole =
454 dprint("choose a role...\n");
455 navigation_routetogoal(world);
456 self.bot_strategytime = -1;
458 havocbot_chooserole_ctf();
459 else if (cvar("g_domination"))
460 havocbot_chooserole_dom();
461 else // assume anything else is deathmatch
462 havocbot_chooserole_dm();