From bfa3c40033ee2636990297273dc83fcebef50198 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 03:51:35 -0400 Subject: [PATCH] Improve bot traversal for the prediction HatesSector was returning false positive for intangible FOFs, making them play really poorly in Desert Palace --- src/k_bot.c | 25 +++++++++++++++---------- src/k_botsearch.c | 22 +++++++++------------- src/p_sight.c | 43 +++++++++++++++++++++---------------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index a9124d91f..4c2bb1123 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -685,11 +685,23 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { wp = (waypoint_t *)pathtofinish.array[i].nodedata; - if (i > 0) + if (i == 0) + { + prevwpmobj = player->mo; + } + else { prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj; } + if (P_TraceBotTraversal(player->mo, wp->mobj) == false) + { + // If we can't get a direct path to this waypoint, stop predicting. + distanceleft = 0; + radreduce = FRACUNIT >> 1; + break; + } + angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y); disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT; @@ -698,13 +710,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) smallestradius = wp->mobj->radius; } - if (P_TraceBotTraversal(player->mo, wp->mobj) == false) - { - // If we can't get a direct path to this waypoint, predict less. - disttonext <<= 2; - radreduce = FRACUNIT >> 1; - } - distanceleft -= disttonext; if (distanceleft <= 0) @@ -733,8 +738,8 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) if (distanceleft > 0) { // Scaled with the leftover anglemul! - predict->x += P_ReturnThrustX(NULL, angletonext, distanceleft * FRACUNIT); - predict->y += P_ReturnThrustY(NULL, angletonext, distanceleft * FRACUNIT); + predict->x += P_ReturnThrustX(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); + predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); } return predict; diff --git a/src/k_botsearch.c b/src/k_botsearch.c index b62b55852..1192324e3 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -172,26 +172,24 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) { const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP); - INT32 specialflag = 0; fixed_t highestfloor = INT32_MAX; sector_t *bestsector = NULL; ffloor_t *rover; + // TODO: Properly support SF_FLIPSPECIAL_FLOOR / SF_FLIPSPECIAL_CEILING. + // An earlier attempt at it caused lots of false positives and other weird + // quirks with intangible FOFs. + if (flip == true) { - specialflag = SF_FLIPSPECIAL_CEILING; highestfloor = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight); } else { - specialflag = SF_FLIPSPECIAL_FLOOR; highestfloor = P_GetZAt(sec->f_slope, x, y, sec->floorheight); } - if (sec->flags & specialflag) - { - bestsector = sec; - } + bestsector = sec; for (rover = sec->ffloors; rover; rover = rover->next) { @@ -209,15 +207,13 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t if (!(rover->flags & FF_BLOCKPLAYER)) { if ((top >= player->mo->z) && (bottom <= player->mo->z + player->mo->height) - && K_BotHatesThisSectorsSpecial(player, rover->master->frontsector)) + && K_BotHatesThisSectorsSpecial(player, rover->master->frontsector)) { // Bad intangible sector at our height, so we DEFINITELY want to avoid return true; } - } - if ((rover->flags & FF_BLOCKPLAYER) && !(rover->master->frontsector->flags & specialflag)) - { + // Ignore them, we want the one below it. continue; } @@ -225,7 +221,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t if (flip == true) { if (bottom < highestfloor - && bottom >= player->mo->z + player->mo->height) + && bottom >= player->mo->z + player->mo->height) { bestsector = rover->master->frontsector; highestfloor = bottom; @@ -234,7 +230,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t else { if (top > highestfloor - && top <= player->mo->z) + && top <= player->mo->z) { bestsector = rover->master->frontsector; highestfloor = top; diff --git a/src/p_sight.c b/src/p_sight.c index 4faffcf32..10d670ede 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -516,6 +516,7 @@ typedef struct { divline_t strace; // from t1 to t2 fixed_t bbox[4]; mobj_t *compareThing; + boolean alreadyHates; } traceblocking_t; static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb) @@ -664,6 +665,7 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2) tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y; tb.compareThing = t1; + tb.alreadyHates = false; // the head node is the last node output return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb); @@ -760,31 +762,17 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t return false; } - if (tb->compareThing->player != NULL) + if (tb->compareThing->player != NULL && tb->alreadyHates == false) { - // Treat damage sectors like walls - boolean alreadyHates = K_BotHatesThisSector( - tb->compareThing->player, tb->compareThing->subsector->sector, - tb->compareThing->x, tb->compareThing->y - ); + // Treat damage sectors like walls, if you're not already in a bad sector. + vertex_t pos; + P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); - if (alreadyHates == false) + if (K_BotHatesThisSector(tb->compareThing->player, line->frontsector, pos.x, pos.y) + || K_BotHatesThisSector(tb->compareThing->player, line->backsector, pos.x, pos.y)) { - INT32 lineside = 0; - vertex_t pos; - - P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); - lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line); - - if (K_BotHatesThisSector( - tb->compareThing->player, - ((lineside == 1) ? line->frontsector : line->backsector), - pos.x, pos.y - )) - { - // This line does not block us, but we don't want to be in it. - return false; - } + // This line does not block us, but we don't want to be in it. + return false; } } } @@ -864,6 +852,17 @@ boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2) tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y; tb.compareThing = t1; + if (t1->player != NULL) + { + tb.alreadyHates = K_BotHatesThisSector( + t1->player, t1->subsector->sector, + t1->x, t1->y + ); + } + else + { + tb.alreadyHates = false; + } // the head node is the last node output return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb);