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 float havocbot_pickupevalfunc(entity item);
28 void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
31 local float t, i, c, needarmor, needweapons;
33 // Needs armor/health?
38 for(i = WEP_FIRST; i < WEP_LAST ; ++i)
41 if(power2of(i-1) & self.weapons)
49 if(!needweapons && !needarmor)
52 // dprint(self.netname, " needs weapons ", ftos(needweapons) , "\n");
53 // dprint(self.netname, " needs armor ", ftos(needarmor) , "\n");
56 head = findchainfloat(bot_pickup, TRUE);
59 // gather health and armor only
61 if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
62 if (vlen(head.origin - org) < sradius)
64 t = havocbot_pickupevalfunc(head);
66 navigation_routerating(head, t * ratingscale, 500);
72 void havocbot_role_ons_setrole(entity bot, float role)
74 dprint(strcat(bot.netname," switched to "));
77 case HAVOCBOT_ONS_ROLE_DEFENSE:
79 bot.havocbot_role = havocbot_role_ons_defense;
80 bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
81 bot.havocbot_role_timeout = 0;
83 case HAVOCBOT_ONS_ROLE_ASSISTANT:
85 bot.havocbot_role = havocbot_role_ons_assistant;
86 bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
87 bot.havocbot_role_timeout = 0;
89 case HAVOCBOT_ONS_ROLE_OFFENSE:
91 bot.havocbot_role = havocbot_role_ons_offense;
92 bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
93 bot.havocbot_role_timeout = 0;
99 float havocbot_ons_teamcount(entity bot, float role)
104 FOR_EACH_PLAYER(head)
105 if(head.team==self.team)
106 if(head.havocbot_role_flags & role)
112 float havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
114 local entity cp, wp, bestwp;
115 local float radius, found, bestcounter;
117 for (cp = findchain(classname, "onslaught_controlpoint"); cp; cp = cp.chain)
125 if(self.team == COLOR_TEAM1)
127 if( (cp.isgenneighbor_blue || cp.iscpneighbor_blue) && !(cp.isgenneighbor_red || cp.iscpneighbor_red) )
130 else if(self.team == COLOR_TEAM2)
132 if( (cp.isgenneighbor_red || cp.iscpneighbor_red) && !(cp.isgenneighbor_blue || cp.iscpneighbor_blue) )
138 // Should be attacked
139 // Rate waypoints near it
142 bestcounter = 99999999999;
143 for(radius=0; radius<1000 && !found; radius+=500)
145 for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
147 if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
148 if(wp.classname=="waypoint")
149 if(checkpvs(wp.origin,cp))
152 if(wp.cnt<bestcounter)
155 bestcounter = wp.cnt;
163 navigation_routerating(bestwp, ratingscale, 10000);
166 self.havocbot_attack_time = 0;
167 if(checkpvs(self.view_ofs,cp))
168 if(checkpvs(self.view_ofs,bestwp))
169 self.havocbot_attack_time = time + 2;
173 navigation_routerating(cp, ratingscale, 10000);
175 dprint(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n");
179 dprint(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n");
181 if not(bot_waypoints_for_items)
183 navigation_routerating(cp, ratingscale, 10000);
187 for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
189 if(wp.classname=="waypoint")
191 navigation_routerating(wp, ratingscale, 10000);
195 navigation_routerating(cp, ratingscale, 10000);
201 float havocbot_goalrating_ons_generator_attack(float ratingscale)
203 local entity g, wp, bestwp;
204 local float found, best;
206 for (g = findchain(classname, "onslaught_generator"); g; g = g.chain)
208 if(g.team == self.team || g.isshielded)
211 // Should be attacked
212 // Rate waypoints near it
217 for(wp=findradius(g.origin,400); wp; wp=wp.chain)
219 if(wp.classname=="waypoint")
220 if(checkpvs(wp.origin,g))
233 dprint("waypoints found around generator\n");
234 navigation_routerating(bestwp, ratingscale, 10000);
237 self.havocbot_attack_time = 0;
238 if(checkpvs(self.view_ofs,g))
239 if(checkpvs(self.view_ofs,bestwp))
240 self.havocbot_attack_time = time + 5;
246 dprint("generator found without waypoints around\n");
247 // if there aren't waypoints near the generator go straight to it
248 navigation_routerating(g, ratingscale, 10000);
249 self.havocbot_attack_time = 0;
256 void havocbot_role_ons_offense()
258 if(self.deadflag != DEAD_NO)
260 self.havocbot_attack_time = 0;
261 havocbot_ons_reset_role(self);
265 // Set the role timeout if necessary
266 if (!self.havocbot_role_timeout)
267 self.havocbot_role_timeout = time + 120;
269 if (time > self.havocbot_role_timeout)
271 havocbot_ons_reset_role(self);
275 if(self.havocbot_attack_time>time)
278 if (self.bot_strategytime < time)
280 navigation_goalrating_start();
281 havocbot_goalrating_enemyplayers(20000, self.origin, 650);
282 if(!havocbot_goalrating_ons_generator_attack(20000))
283 havocbot_goalrating_ons_controlpoints_attack(20000);
284 havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
285 navigation_goalrating_end();
287 self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
291 void havocbot_role_ons_assistant()
293 havocbot_ons_reset_role(self);
296 void havocbot_role_ons_defense()
298 havocbot_ons_reset_role(self);
301 void havocbot_ons_reset_role(entity bot)
306 if(self.deadflag != DEAD_NO)
309 // TODO: Defend control points or generator if necessary
311 // if there is only me on the team switch to offense
313 FOR_EACH_PLAYER(head)
314 if(head.team==self.team)
319 havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
323 havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
326 void havocbot_chooserole_ons()
328 havocbot_ons_reset_role(self);