1 #define HAVOCBOT_ONS_ROLE_NONE 0
2 #define HAVOCBOT_ONS_ROLE_DEFENSE 2
3 #define HAVOCBOT_ONS_ROLE_ASSISTANT 4
4 #define HAVOCBOT_ONS_ROLE_OFFENSE 8
6 .float havocbot_role_flags;
7 .float havocbot_attack_time;
10 .void() havocbot_previous_role;
12 void() havocbot_role_ons_defense;
13 void() havocbot_role_ons_offense;
14 void() havocbot_role_ons_assistant;
16 void(entity bot) havocbot_ons_reset_role;
17 void(float ratingscale, vector org, float sradius) havocbot_goalrating_items;
18 void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
23 .float isgenneighbor_blue, iscpneighbor_blue;
24 .float isgenneighbor_red, iscpneighbor_red;
26 void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
29 local float t, i, c, needarmor, needweapons;
31 // Needs armor/health?
36 for(i = WEP_FIRST; i < WEP_LAST ; ++i)
39 if((get_weaponinfo(i)).weapons & self.weapons)
47 if(!needweapons && !needarmor)
50 // dprint(self.netname, " needs weapons ", ftos(needweapons) , "\n");
51 // dprint(self.netname, " needs armor ", ftos(needarmor) , "\n");
54 head = findchainfloat(bot_pickup, TRUE);
57 // gather health and armor only
59 if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
60 if (vlen(head.origin - org) < sradius)
62 t = head.bot_pickupevalfunc(self, head);
64 navigation_routerating(head, t * ratingscale, 500);
70 void havocbot_role_ons_setrole(entity bot, float role)
72 dprint(strcat(bot.netname," switched to "));
75 case HAVOCBOT_ONS_ROLE_DEFENSE:
77 bot.havocbot_role = havocbot_role_ons_defense;
78 bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
79 bot.havocbot_role_timeout = 0;
81 case HAVOCBOT_ONS_ROLE_ASSISTANT:
83 bot.havocbot_role = havocbot_role_ons_assistant;
84 bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
85 bot.havocbot_role_timeout = 0;
87 case HAVOCBOT_ONS_ROLE_OFFENSE:
89 bot.havocbot_role = havocbot_role_ons_offense;
90 bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
91 bot.havocbot_role_timeout = 0;
97 float havocbot_ons_teamcount(entity bot, float role)
102 FOR_EACH_PLAYER(head)
103 if(head.team==self.team)
104 if(head.havocbot_role_flags & role)
110 float havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
112 local entity cp, wp, bestwp;
113 local float radius, found, bestcounter;
115 for (cp = findchain(classname, "onslaught_controlpoint"); cp; cp = cp.chain)
123 if(self.team == COLOR_TEAM1)
125 if( (cp.isgenneighbor_blue || cp.iscpneighbor_blue) && !(cp.isgenneighbor_red || cp.iscpneighbor_red) )
128 else if(self.team == COLOR_TEAM2)
130 if( (cp.isgenneighbor_red || cp.iscpneighbor_red) && !(cp.isgenneighbor_blue || cp.iscpneighbor_blue) )
136 // Should be attacked
137 // Rate waypoints near it
140 bestcounter = 99999999999;
141 for(radius=0; radius<1000 && !found; radius+=500)
143 for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
145 if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
146 if(wp.classname=="waypoint")
147 if(checkpvs(wp.origin,cp))
150 if(wp.cnt<bestcounter)
153 bestcounter = wp.cnt;
161 navigation_routerating(bestwp, ratingscale, 10000);
164 self.havocbot_attack_time = 0;
165 if(checkpvs(self.view_ofs,cp))
166 if(checkpvs(self.view_ofs,bestwp))
167 self.havocbot_attack_time = time + 2;
171 navigation_routerating(cp, ratingscale, 10000);
173 dprint(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n");
177 dprint(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n");
179 if not(bot_waypoints_for_items)
181 navigation_routerating(cp, ratingscale, 10000);
185 for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
187 if(wp.classname=="waypoint")
189 navigation_routerating(wp, ratingscale, 10000);
193 navigation_routerating(cp, ratingscale, 10000);
199 float havocbot_goalrating_ons_generator_attack(float ratingscale)
201 local entity g, wp, bestwp;
202 local float found, best;
204 for (g = findchain(classname, "onslaught_generator"); g; g = g.chain)
206 if(g.team == self.team || g.isshielded)
209 // Should be attacked
210 // Rate waypoints near it
215 for(wp=findradius(g.origin,400); wp; wp=wp.chain)
217 if(wp.classname=="waypoint")
218 if(checkpvs(wp.origin,g))
231 dprint("waypoints found around generator\n");
232 navigation_routerating(bestwp, ratingscale, 10000);
235 self.havocbot_attack_time = 0;
236 if(checkpvs(self.view_ofs,g))
237 if(checkpvs(self.view_ofs,bestwp))
238 self.havocbot_attack_time = time + 5;
244 dprint("generator found without waypoints around\n");
245 // if there aren't waypoints near the generator go straight to it
246 navigation_routerating(g, ratingscale, 10000);
247 self.havocbot_attack_time = 0;
254 void havocbot_role_ons_offense()
256 if(self.deadflag != DEAD_NO)
258 self.havocbot_attack_time = 0;
259 havocbot_ons_reset_role(self);
263 // Set the role timeout if necessary
264 if (!self.havocbot_role_timeout)
265 self.havocbot_role_timeout = time + 120;
267 if (time > self.havocbot_role_timeout)
269 havocbot_ons_reset_role(self);
273 if(self.havocbot_attack_time>time)
276 if (self.bot_strategytime < time)
278 navigation_goalrating_start();
279 havocbot_goalrating_enemyplayers(20000, self.origin, 650);
280 if(!havocbot_goalrating_ons_generator_attack(20000))
281 havocbot_goalrating_ons_controlpoints_attack(20000);
282 havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
283 navigation_goalrating_end();
285 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
289 void havocbot_role_ons_assistant()
291 havocbot_ons_reset_role(self);
294 void havocbot_role_ons_defense()
296 havocbot_ons_reset_role(self);
299 void havocbot_ons_reset_role(entity bot)
304 if(self.deadflag != DEAD_NO)
307 // TODO: Defend control points or generator if necessary
309 // if there is only me on the team switch to offense
311 FOR_EACH_PLAYER(head)
312 if(head.team==self.team)
317 havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
321 havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
324 void havocbot_chooserole_ons()
326 havocbot_ons_reset_role(self);