X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Fhavocbot%2Froles.qc;h=5ddb0f74b576ab0bcd8107dad86e1af96a5f6a27;hp=771ab282ddd49039f36fcfbed52a8cb24ccb18c1;hb=b834eab77489d98d5d722d67c8a96cf6c3549436;hpb=3e21073f2bd7f282947bc1f214b3ec25d69ccae0 diff --git a/qcsrc/server/bot/default/havocbot/roles.qc b/qcsrc/server/bot/default/havocbot/roles.qc index 771ab282d..5ddb0f74b 100644 --- a/qcsrc/server/bot/default/havocbot/roles.qc +++ b/qcsrc/server/bot/default/havocbot/roles.qc @@ -13,19 +13,65 @@ .void(entity this) havocbot_previous_role; .void(entity this) havocbot_role; +void havocbot_goalrating_waypoints(entity this, float ratingscale, vector org, float sradius) +{ + // rate waypoints only if there's no alternative goal + if(navigation_bestgoal) + return; + + float f; + float range = 500; + sradius = max(range, (0.5 + random() * 0.5) * sradius); + while(sradius > 100) + { + IL_EACH(g_waypoints, vdist(it.origin - org, <, sradius) + && vdist(it.origin - org, >, max(100, sradius - range)) + && !(it.wpflags & WAYPOINTFLAG_TELEPORT), + { + if(vdist(it.origin - this.wp_goal_prev0.origin, <, range * 1.5)) + f = 0.1; + else if(vdist(it.origin - this.wp_goal_prev1.origin, <, range * 1.5)) + f = 0.1; + else + f = 0.5 + random() * 0.5; + navigation_routerating(this, it, ratingscale * f, 2000); + }); + if(navigation_bestgoal) + break; + sradius -= range; + } +}; + void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius) { float rating, d, discard, friend_distance, enemy_distance; vector o; ratingscale = ratingscale * 0.0001; // items are rated around 10000 already - FOREACH_ENTITY_FLOAT(bot_pickup, true, + IL_EACH(g_items, it.bot_pickup, { - o = (it.absmin + it.absmax) * 0.5; - friend_distance = 10000; enemy_distance = 10000; rating = 0; - if(!it.solid || vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) ) + if(!it.solid) + { + if(!it.scheduledrespawntime) + continue; + if(it.respawntime < 30 || (it.respawntimejitter && !it.itemdef.instanceOfPowerup)) + continue; + + float t = 0; + if(it.itemdef.instanceOfPowerup) + t = bound(0, skill / 10, 1) * 6; + else if(skill >= 9) + t = 4; + + if(time < it.scheduledrespawntime - t) + continue; + + it.bot_pickup_respawning = true; + } + o = (it.absmin + it.absmax) * 0.5; + if(vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) ) continue; // Check if the item can be picked up safely @@ -34,10 +80,13 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float traceline(o, o + '0 0 -1500', true, NULL); d = pointcontents(trace_endpos + '0 0 1'); - if(d & CONTENT_WATER || d & CONTENT_SLIME || d & CONTENT_LAVA) - continue; - if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos)) + if(d == CONTENT_WATER || d == CONTENT_SLIME || d == CONTENT_LAVA) continue; + // this tracebox_hits_trigger_hurt call isn't needed: + // dropped weapons are removed as soon as they fall on a trigger_hurt + // and can't be rated while they are in the air + //if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos)) + // continue; } else { @@ -49,6 +98,7 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float if(teamplay) { + friend_distance = 10000; enemy_distance = 10000; discard = false; entity picker = it; @@ -65,33 +115,18 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float continue; friend_distance = d; - discard = true; - if( picker.health && it.health > this.health ) - continue; + if (picker.health && it.health > this.health) continue; + if (picker.armorvalue && it.armorvalue > this.armorvalue) continue; - if( picker.armorvalue && it.armorvalue > this.armorvalue) - continue; + if (picker.weapons && (picker.weapons & ~it.weapons)) continue; - if( picker.weapons ) - if( picker.weapons & ~it.weapons ) - continue; - - if (picker.ammo_shells && it.ammo_shells > this.ammo_shells) - continue; - - if (picker.ammo_nails && it.ammo_nails > this.ammo_nails) - continue; - - if (picker.ammo_rockets && it.ammo_rockets > this.ammo_rockets) - continue; - - if (picker.ammo_cells && it.ammo_cells > this.ammo_cells) - continue; - - if (picker.ammo_plasma && it.ammo_plasma > this.ammo_plasma) - continue; + if (picker.ammo_shells && it.ammo_shells > this.ammo_shells) continue; + if (picker.ammo_nails && it.ammo_nails > this.ammo_nails) continue; + if (picker.ammo_rockets && it.ammo_rockets > this.ammo_rockets) continue; + if (picker.ammo_cells && it.ammo_cells > this.ammo_cells) continue; + if (picker.ammo_plasma && it.ammo_plasma > this.ammo_plasma) continue; discard = false; } @@ -108,7 +143,6 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float if ( (enemy_distance < friend_distance && vdist(o - org, <, enemy_distance)) || (friend_distance > autocvar_bot_ai_friends_aware_pickup_radius ) || !discard ) rating = it.bot_pickupevalfunc(this, it); - } else rating = it.bot_pickupevalfunc(this, it); @@ -118,19 +152,7 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float }); } -void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius) -{ - FOREACH_ENTITY_CLASS("dom_controlpoint", vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius), - { - if(it.cnt > -1) // this is just being fought - navigation_routerating(this, it, ratingscale, 5000); - else if(it.goalentity.cnt == 0) // unclaimed - navigation_routerating(this, it, ratingscale * 0.5, 5000); - else if(it.goalentity.team != this.team) // other team's point - navigation_routerating(this, it, ratingscale * 0.2, 5000); - }); -} - +#define BOT_RATING_ENEMY 2500 void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius) { if (autocvar_bot_nofire) @@ -140,8 +162,9 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org if(this.waterlevel>WATERLEVEL_WETFEET) return; - int t; + ratingscale = ratingscale * 0.00005; // enemies are rated around 20000 already + float t; FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), LAMBDA( // TODO: Merge this logic with the bot_shouldattack function if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius)) @@ -154,27 +177,17 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org continue; */ - if((it.flags & FL_INWATER) || (it.flags & FL_PARTIALGROUND)) - continue; - - // not falling - if((IS_ONGROUND(it)) == 0) + t = ((this.health + this.armorvalue) - (it.health + it.armorvalue)) / 150; + t = bound(0, 1 + t, 3); + if (skill > 3) { - traceline(it.origin, it.origin + '0 0 -1500', true, NULL); - t = pointcontents(trace_endpos + '0 0 1'); - if(t != CONTENT_SOLID ) - if(t & CONTENT_WATER || t & CONTENT_SLIME || t & CONTENT_LAVA) - continue; - if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos)) - continue; + if (time < this.strength_finished - 1) t += 0.5; + if (time < it.strength_finished - 1) t -= 0.5; } - - // TODO: rate waypoints near the targetted player at that moment, instead of the player itthis - // adding a player as a goal seems to be quite dangerous, especially on space maps - // remove hack in navigation_poptouchedgoals() after performing this change - - t = (this.health + this.armorvalue ) / (it.health + it.armorvalue ); - navigation_routerating(this, it, t * ratingscale, 2000); + t += max(0, 8 - skill) * 0.05; // less skilled bots attack more mindlessly + ratingscale *= t; + if (ratingscale > 0) + navigation_routerating(this, it, ratingscale * BOT_RATING_ENEMY, 2000); )); } @@ -191,8 +204,11 @@ void havocbot_role_generic(entity this) navigation_goalrating_start(this); havocbot_goalrating_items(this, 10000, this.origin, 10000); havocbot_goalrating_enemyplayers(this, 20000, this.origin, 10000); - //havocbot_goalrating_waypoints(1, this.origin, 1000); + havocbot_goalrating_waypoints(this, 1, this.origin, 3000); navigation_goalrating_end(this); + + if(IS_PLAYER(this.goalentity)) + this.bot_strategytime = time + min(2, autocvar_bot_ai_strategyinterval); } }