From f803b2a5acf74b2450b3a7dea63bfbe6bd6315d7 Mon Sep 17 00:00:00 2001 From: terencehill Date: Mon, 30 Jan 2017 16:38:45 +0100 Subject: [PATCH] Make so that bots chase players unless they go to dangerous places. If an enemy ends up in lava/slime/water bots try to reach the closest waypoint to him --- qcsrc/server/bot/default/havocbot/havocbot.qc | 21 +++++++--- qcsrc/server/bot/default/havocbot/roles.qc | 40 ++++++++++++++----- qcsrc/server/bot/default/navigation.qc | 7 +--- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc index 761300005..e2ff5e799 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@ -428,7 +428,6 @@ void havocbot_movetogoal(entity this) vector m2; vector evadeobstacle; vector evadelava; - float s; float maxspeed; vector gco; //float dist; @@ -727,6 +726,7 @@ void havocbot_movetogoal(entity this) } else { + float s; if(this.aistatus & AI_STATUS_OUT_WATER) this.aistatus &= ~AI_STATUS_OUT_WATER; @@ -786,6 +786,8 @@ void havocbot_movetogoal(entity this) // (only when the bot is on the ground or jumping intentionally) this.aistatus &= ~AI_STATUS_DANGER_AHEAD; + bool unreachable = false; + s = CONTENT_SOLID; if(trace_fraction == 1 && this.jumppadcount == 0 && !this.goalcurrent.wphardwired ) if((IS_ONGROUND(this)) || (this.aistatus & AI_STATUS_RUNNING) || (this.aistatus & AI_STATUS_ROAMING) || PHYS_INPUT_BUTTON_JUMP(this)) { @@ -809,11 +811,9 @@ void havocbot_movetogoal(entity this) if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos)) { if (gco.z > this.origin.z + jumpstepheightvec.z) - { + { // the goal is probably on an upper platform, assume bot can't get there - LOG_TRACE("bot ", this.netname, " avoided the goal ", this.goalcurrent.classname, " ", etos(this.goalcurrent), " because it led to a dangerous path; goal stack cleared"); - navigation_clearroute(this); - this.bot_strategytime = 0; + unreachable = true; } else evadelava = normalize(this.velocity) * -1; @@ -827,8 +827,17 @@ void havocbot_movetogoal(entity this) evadelava.z = 0; makevectors(this.v_angle.y * '0 1 0'); - if(evadeobstacle!='0 0 0'||evadelava!='0 0 0') + if(evadeobstacle || evadelava || (s == CONTENT_WATER)) + { this.aistatus |= AI_STATUS_DANGER_AHEAD; + if(IS_PLAYER(this.goalcurrent)) + unreachable = true; + } + if(unreachable) + { + navigation_clearroute(this); + this.bot_strategytime = 0; + } } dodge = havocbot_dodge(this); diff --git a/qcsrc/server/bot/default/havocbot/roles.qc b/qcsrc/server/bot/default/havocbot/roles.qc index 5c2580636..dfa2f4540 100644 --- a/qcsrc/server/bot/default/havocbot/roles.qc +++ b/qcsrc/server/bot/default/havocbot/roles.qc @@ -136,7 +136,6 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org ratingscale = ratingscale * 0.00005; // enemies are rated around 20000 already int 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)) @@ -149,8 +148,9 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org continue; */ + bool rate_wps = false; if((it.flags & FL_INWATER) || (it.flags & FL_PARTIALGROUND)) - continue; + rate_wps = true; // not falling if(!IS_ONGROUND(it)) @@ -158,16 +158,14 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org 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(t == CONTENT_WATER || t == CONTENT_SLIME || t == CONTENT_LAVA) + rate_wps = true; + else if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos)) + continue; + } } - // TODO: rate waypoints near the targeted player at that moment, instead of the player itself - // 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)) / 150; t = bound(0, 1 + t, 3); if (skill > 3) @@ -178,7 +176,27 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org 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); + { + if(rate_wps) + { + entity theEnemy = it; + entity best_wp = NULL; + float best_dist = 10000; + IL_EACH(g_waypoints, vdist(it.origin - theEnemy.origin, <, 500) && vdist(it.origin - this.origin, >, 100), + { + float dist = vlen(it.origin - theEnemy.origin); + if (dist < best_dist) + { + best_wp = it; + best_dist = dist; + } + }); + if (best_wp) + navigation_routerating(this, best_wp, ratingscale * BOT_RATING_ENEMY, 2000); + } + else + navigation_routerating(this, it, ratingscale * BOT_RATING_ENEMY, 2000); + } )); } diff --git a/qcsrc/server/bot/default/navigation.qc b/qcsrc/server/bot/default/navigation.qc index d6bb2195f..eb869601a 100644 --- a/qcsrc/server/bot/default/navigation.qc +++ b/qcsrc/server/bot/default/navigation.qc @@ -920,11 +920,6 @@ void navigation_poptouchedgoals(entity this) // personality property } - // HACK: remove players/bots as goals, they can lead a bot to unexpected places (cliffs, lava, etc) - // TODO: rate waypoints near the targetted player at that moment, instead of the player itself - if(IS_PLAYER(this.goalcurrent)) - navigation_poproute(this); - // Loose goal touching check when running if(this.aistatus & AI_STATUS_RUNNING) if(this.speed >= autocvar_sv_maxspeed) // if -really- running @@ -949,7 +944,7 @@ void navigation_poptouchedgoals(entity this) } } - while (this.goalcurrent && boxesoverlap(m1, m2, this.goalcurrent.absmin, this.goalcurrent.absmax)) + while (this.goalcurrent && !IS_PLAYER(this.goalcurrent) && boxesoverlap(m1, m2, this.goalcurrent.absmin, this.goalcurrent.absmax)) { if((this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)) break; -- 2.39.2