#define HAVOCBOT_ONS_ROLE_NONE 0 #define HAVOCBOT_ONS_ROLE_DEFENSE 2 #define HAVOCBOT_ONS_ROLE_ASSISTANT 4 #define HAVOCBOT_ONS_ROLE_OFFENSE 8 .float havocbot_role_flags; .float havocbot_attack_time; .void() havocbot_role; .void() havocbot_previous_role; void() havocbot_role_ons_defense; void() havocbot_role_ons_offense; void() havocbot_role_ons_assistant; void(entity bot) havocbot_ons_reset_role; void(float ratingscale, vector org, float sradius) havocbot_goalrating_items; void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers; .float isshielded; .float iscaptured; .float islinked; .float isgenneighbor_blue, iscpneighbor_blue; .float isgenneighbor_red, iscpneighbor_red; void havocbot_role_ons_setrole(entity bot, float role) { dprint(strcat(bot.netname," switched to ")); switch(role) { case HAVOCBOT_ONS_ROLE_DEFENSE: dprint("defense"); bot.havocbot_role = havocbot_role_ons_defense; bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE; bot.havocbot_role_timeout = 0; break; case HAVOCBOT_ONS_ROLE_ASSISTANT: dprint("assistant"); bot.havocbot_role = havocbot_role_ons_assistant; bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT; bot.havocbot_role_timeout = 0; break; case HAVOCBOT_ONS_ROLE_OFFENSE: dprint("offense"); bot.havocbot_role = havocbot_role_ons_offense; bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE; bot.havocbot_role_timeout = 0; break; } dprint("\n"); }; float havocbot_ons_teamcount(entity bot, float role) { local float c; local entity head; FOR_EACH_PLAYER(head) if(head.team==self.team) if(head.havocbot_role_flags & role) ++c; return c; }; float havocbot_goalrating_ons_controlpoints_attack(float ratingscale) { local entity cp, wp, bestwp; local float radius, found, bestcounter; for (cp = findchain(classname, "onslaught_controlpoint"); cp; cp = cp.chain) { if(cp==world) continue; if(cp.isshielded) continue; if(self.team == COLOR_TEAM1) { if( (cp.isgenneighbor_blue || cp.iscpneighbor_blue) && !(cp.isgenneighbor_red || cp.iscpneighbor_red) ) continue; } else if(self.team == COLOR_TEAM2) { if( (cp.isgenneighbor_red || cp.iscpneighbor_red) && !(cp.isgenneighbor_blue || cp.iscpneighbor_blue) ) continue; } if(cp.goalentity) { // Should be attacked // Rate waypoints near it found = FALSE; bestwp = world; bestcounter = 99999999999; for(radius=0; radius<1000 && !found; radius+=500) { for(wp=findradius(cp.origin,radius); wp; wp=wp.chain) { if(!(wp.wpflags & WAYPOINTFLAG_GENERATED)) if(wp.classname=="waypoint") if(checkpvs(wp.origin,cp)) { found = TRUE; if(wp.cnt self.havocbot_role_timeout) { havocbot_ons_reset_role(self); return; } if(self.havocbot_attack_time>time) return; if (self.bot_strategytime < time) { navigation_goalrating_start(); havocbot_goalrating_enemyplayers(20000, self.origin, 650); if(havocbot_goalrating_ons_generator_attack(20000)) havocbot_goalrating_items(10000, self.origin, 300); else { havocbot_goalrating_ons_controlpoints_attack(20000); havocbot_goalrating_items(10000, self.origin, 500); } havocbot_goalrating_items(500, self.origin, 10000); navigation_goalrating_end(); self.bot_strategytime = time + cvar("bot_ai_strategyinterval"); } }; void havocbot_role_ons_assistant() { havocbot_ons_reset_role(self); }; void havocbot_role_ons_defense() { havocbot_ons_reset_role(self); }; void havocbot_ons_reset_role(entity bot) { local entity head; local float c; if(self.deadflag != DEAD_NO) return; // TODO: Defend control points or generator if necessary // if there is only me on the team switch to offense c = 0; FOR_EACH_PLAYER(head) if(head.team==self.team) ++c; if(c==1) { havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE); return; } havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE); }; void havocbot_chooserole_ons() { havocbot_ons_reset_role(self); };