From: otta8634 Date: Sun, 9 Mar 2025 08:36:40 +0000 (+0800) Subject: Improve ka/tka/kh bot key/ball chasing logic X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=859d3e08fc22a06a07a5e846148cdeba9ae00dc9;p=xonotic%2Fxonotic-data.pk3dir.git Improve ka/tka/kh bot key/ball chasing logic Made them only chase a key/ball they can see. - First check if a waypoint exists and is visible. - If not, use checkpvs. Made the tka bots "chase" their own ball, so they can protect their team's ball carrier. - Uses a lower rating scale (half) than chasing a ball the other team has. --- diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/sv_keepaway.qc b/qcsrc/common/gamemodes/gamemode/keepaway/sv_keepaway.qc index 37054373d..648d05c3f 100644 --- a/qcsrc/common/gamemodes/gamemode/keepaway/sv_keepaway.qc +++ b/qcsrc/common/gamemodes/gamemode/keepaway/sv_keepaway.qc @@ -302,6 +302,18 @@ void ka_Handler_CheckBall(entity this) // Bot player logic // ================ +bool ka_waypointsprite_visible_for_bot(entity this, entity e, bool dropped) +{ + entity ball_wp = e.waypointsprite_attachedforcarrier; + if (!ball_wp) + if (dropped || !ball_wp.waypointsprite_visible_for_player(ball_wp, this, WaypointSprite_getviewentity(this))) + { // has no waypoint, or waypoint not visible + if (!checkpvs(this.origin + this.view_ofs, e)) // ball cannot be seen + return false; + } + return true; +} + void havocbot_goalrating_ball(entity this, float ratingscale, vector org) { entity ball = NULL, ball_carried = NULL; @@ -309,15 +321,23 @@ void havocbot_goalrating_ball(entity this, float ratingscale, vector org) // stops at last ball, prefers ball without carrier IL_EACH(g_kaballs, it.owner != this, { - if(it.owner) + if (it.owner) + { + if (!ka_waypointsprite_visible_for_bot(this, it.owner, false)) + continue; ball_carried = it.owner; + } else + { + if (!ka_waypointsprite_visible_for_bot(this, it, true)) + continue; ball = it; + } }); - if(ball) + if (ball) navigation_routerating(this, ball, ratingscale, 2000); - else if(ball_carried) + else if (ball_carried) navigation_routerating(this, ball_carried, ratingscale, 2000); } diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc b/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc index 04433c597..85814dfec 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc @@ -1025,30 +1025,37 @@ void(entity this) havocbot_role_kh_offense; void(entity this) havocbot_role_kh_freelancer; +bool kh_waypointsprite_visible_for_bot(entity this, entity e) +{ + entity key_wp = e.waypointsprite_attachedforcarrier; + if (!key_wp) + if (!key_wp.waypointsprite_visible_for_player(key_wp, this, WaypointSprite_getviewentity(this))) + { // has no waypoint, or waypoint not visible + if (!checkpvs(this.origin + this.view_ofs, e)) // key cannot be seen + return false; + } + return true; +} + void havocbot_goalrating_kh(entity this, float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy) { - entity head; - for (head = kh_worldkeylist; head; head = head.kh_worldkeynext) + for (entity head = kh_worldkeylist; head; head = head.kh_worldkeynext) { - if(head.owner == this) - continue; - if(!kh_tracking_enabled) + if (head.owner) { - // if it's carried by our team we know about it - // otherwise we have to see it to know about it - if(!head.owner || head.team != this.team) - { - traceline(this.origin + this.view_ofs, head.origin, MOVE_NOMONSTERS, this); - if (trace_fraction < 1 && trace_ent != head) - continue; // skip what I can't see - } + if (head.owner == this || !kh_waypointsprite_visible_for_bot(this, head.owner)) + continue; + if (SAME_TEAM(head, this)) + navigation_routerating(this, head.owner, ratingscale_team * 10000, 100000); + else + navigation_routerating(this, head.owner, ratingscale_enemy * 10000, 100000); } - if(!head.owner) - navigation_routerating(this, head, ratingscale_dropped * 10000, 100000); - else if(head.team == this.team) - navigation_routerating(this, head.owner, ratingscale_team * 10000, 100000); else - navigation_routerating(this, head.owner, ratingscale_enemy * 10000, 100000); + { + if (!kh_waypointsprite_visible_for_bot(this, head)) + continue; + navigation_routerating(this, head, ratingscale_dropped * 10000, 100000); + } } havocbot_goalrating_items(this, 80000, this.origin, 10000); diff --git a/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc b/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc index df807f430..f6835cee2 100644 --- a/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc +++ b/qcsrc/common/gamemodes/gamemode/tka/sv_tka.qc @@ -280,23 +280,48 @@ void tka_Handler_CheckBall(entity this) // Bot player logic // ================ -void havocbot_goalrating_tkaball(entity this, float ratingscale, vector org) +bool tka_waypointsprite_visible_for_bot(entity this, entity e, bool dropped) +{ + entity ball_wp = e.waypointsprite_attachedforcarrier; + if (!ball_wp) + if (dropped || !ball_wp.waypointsprite_visible_for_player(ball_wp, this, WaypointSprite_getviewentity(this))) + { // has no waypoint, or waypoint not visible + if (!checkpvs(this.origin + this.view_ofs, e)) // ball cannot be seen + return false; + } + return true; +} + +void havocbot_goalrating_tkaball(entity this, float ratingscale, float ratingscale_sameteam, vector org) { entity ball = NULL, ball_carried = NULL; // stops at last ball, prefers ball without carrier - IL_EACH(g_tkaballs, it.owner != this && DIFF_TEAM(ball.owner, this), + IL_EACH(g_tkaballs, it.owner != this, { - if(it.owner) + if (it.owner) + { + if (!tka_waypointsprite_visible_for_bot(this, it.owner, false)) + continue; ball_carried = it.owner; + } else + { + if (!tka_waypointsprite_visible_for_bot(this, it, true)) + continue; ball = it; + } }); if (ball) navigation_routerating(this, ball, ratingscale, 2000); - else if(ball_carried) - navigation_routerating(this, ball_carried, ratingscale, 2000); + else if (ball_carried) + { + if (DIFF_TEAM(ball_carried, this)) + navigation_routerating(this, ball_carried, ratingscale, 2000); + else + navigation_routerating(this, ball_carried, ratingscale_sameteam, 2000); + } } void havocbot_role_tka_carrier(entity this) @@ -332,7 +357,7 @@ void havocbot_role_tka_collector(entity this) navigation_goalrating_start(this); havocbot_goalrating_items(this, 10000, this.origin, 10000); havocbot_goalrating_enemyplayers(this, 500, this.origin, 10000); - havocbot_goalrating_tkaball(this, 8000, this.origin); + havocbot_goalrating_tkaball(this, 8000, 4000, this.origin); navigation_goalrating_end(this); navigation_goalrating_timeout_set(this);