From 0053cda35c9f1b79d3352e5d2e4b02603a9e677c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 26 Nov 2022 02:31:11 -0500 Subject: [PATCH] Don't allow nextwaypoint to be past finish linedef --- src/k_kart.c | 121 +++++++---------------------------------------- src/k_waypoint.c | 4 +- src/p_local.h | 1 + src/p_sight.c | 79 +++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 107 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 8ca23b483..3fd42d6bf 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8848,6 +8848,7 @@ void K_KartPlayerAfterThink(player_t *player) --------------------------------------------------*/ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) { + waypoint_t *finishline = K_GetFinishLineWaypoint(); waypoint_t *bestwaypoint = NULL; if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) @@ -8864,13 +8865,15 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) // Otherwise it breaks the distance calculations. if (waypoint != NULL) { - boolean finishlinehack = false; angle_t playerangle = player->mo->angle; angle_t momangle = K_MomentumAngle(player->mo); angle_t angletowaypoint = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y); - angle_t angledelta = ANGLE_MAX; - angle_t momdelta = ANGLE_MAX; + angle_t angledelta = ANGLE_180; + angle_t momdelta = ANGLE_180; + + // Remove WRONG WAY flag. + player->pflags &= ~PF_WRONGWAY; angledelta = playerangle - angletowaypoint; if (angledelta > ANGLE_180) @@ -8884,31 +8887,15 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) momdelta = InvAngle(momdelta); } - if (bestwaypoint == K_GetFinishLineWaypoint()) - { - waypoint_t *nextwaypoint = waypoint->nextwaypoints[0]; - angle_t angletonextwaypoint = - R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, nextwaypoint->mobj->x, nextwaypoint->mobj->y); - - // facing towards the finishline - if (AngleDelta(angletonextwaypoint, angletowaypoint) <= ANGLE_90) - { - finishlinehack = true; - } - } - // We're using a lot of angle calculations here, because only using facing angle or only using momentum angle both have downsides. // nextwaypoints will be picked if you're facing OR moving forward. // prevwaypoints will be picked if you're facing AND moving backward. - if ( #if 0 - (angledelta > ANGLE_45 || momdelta > ANGLE_45) && + if (angledelta > ANGLE_45 || momdelta > ANGLE_45) #endif - (finishlinehack == false) - ) { - angle_t nextbestdelta = ANGLE_MAX; - angle_t nextbestmomdelta = ANGLE_MAX; + angle_t nextbestdelta = ANGLE_90; + angle_t nextbestmomdelta = ANGLE_90; size_t i = 0U; if ((waypoint->nextwaypoints != NULL) && (waypoint->numnextwaypoints > 0U)) @@ -8952,10 +8939,13 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) if (angledelta < nextbestdelta || momdelta < nextbestmomdelta) { - if (P_TraceBlockingLines(player->mo, waypoint->nextwaypoints[i]->mobj) == false) + if (waypoint->nextwaypoints[i] != finishline) // Allow finish line. { - // Save sight checks when all of the other checks pass, so we only do it if we have to - continue; + if (P_TraceWaypointTraversal(player->mo, waypoint->nextwaypoints[i]->mobj) == false) + { + // Save sight checks when all of the other checks pass, so we only do it if we have to + continue; + } } bestwaypoint = waypoint->nextwaypoints[i]; @@ -8969,8 +8959,6 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) nextbestmomdelta = momdelta; } - // Remove wrong way flag if we're using nextwaypoints - player->pflags &= ~PF_WRONGWAY; updaterespawn = true; } } @@ -9004,7 +8992,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) if (angledelta < nextbestdelta && momdelta < nextbestmomdelta) { - if (P_TraceBlockingLines(player->mo, waypoint->prevwaypoints[i]->mobj) == false) + if (P_TraceWaypointTraversal(player->mo, waypoint->prevwaypoints[i]->mobj) == false) { // Save sight checks when all of the other checks pass, so we only do it if we have to continue; @@ -9044,69 +9032,6 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) return bestwaypoint; } -#if 0 -static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_t *const player) -{ - boolean nextiscloser = true; - - if ((waypoint != NULL) && (player != NULL) && (player->mo != NULL)) - { - size_t i = 0U; - waypoint_t *currentwpcheck = NULL; - angle_t angletoplayer = ANGLE_MAX; - angle_t currentanglecheck = ANGLE_MAX; - angle_t bestangle = ANGLE_MAX; - - angletoplayer = R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, - player->mo->x, player->mo->y); - - for (i = 0U; i < waypoint->numnextwaypoints; i++) - { - currentwpcheck = waypoint->nextwaypoints[i]; - currentanglecheck = R_PointToAngle2( - waypoint->mobj->x, waypoint->mobj->y, currentwpcheck->mobj->x, currentwpcheck->mobj->y); - - // Get delta angle - currentanglecheck = currentanglecheck - angletoplayer; - - if (currentanglecheck > ANGLE_180) - { - currentanglecheck = InvAngle(currentanglecheck); - } - - if (currentanglecheck < bestangle) - { - bestangle = currentanglecheck; - } - } - - for (i = 0U; i < waypoint->numprevwaypoints; i++) - { - currentwpcheck = waypoint->prevwaypoints[i]; - currentanglecheck = R_PointToAngle2( - waypoint->mobj->x, waypoint->mobj->y, currentwpcheck->mobj->x, currentwpcheck->mobj->y); - - // Get delta angle - currentanglecheck = currentanglecheck - angletoplayer; - - if (currentanglecheck > ANGLE_180) - { - currentanglecheck = InvAngle(currentanglecheck); - } - - if (currentanglecheck < bestangle) - { - bestangle = currentanglecheck; - nextiscloser = false; - break; - } - } - } - - return nextiscloser; -} -#endif - /*-------------------------------------------------- void K_UpdateDistanceFromFinishLine(player_t *const player) @@ -9302,21 +9227,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == 0U) { const UINT8 numfulllapsleft = ((UINT8)numlaps - player->laps); - player->distancetofinish += numfulllapsleft * K_GetCircuitLength(); - -#if 0 - // An additional HACK, to fix looking backwards towards the finish line - // If the player's next waypoint is the finishline and the angle distance from player to - // connectin waypoints implies they're closer to a next waypoint, add a full track distance - if (player->nextwaypoint == finishline) - { - if (K_PlayerCloserToNextWaypoints(player->nextwaypoint, player) == true) - { - player->distancetofinish += K_GetCircuitLength(); - } - } -#endif } } } diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 28ff00d04..837f77102 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -361,7 +361,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) // remember: huge radius if (closestdist <= rad && checkdist <= rad && finishline != NULL) { - if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj)) + if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj)) // Intentionally not P_TraceWaypointTraversal { // Save sight checks when all of the other checks pass, so we only do it if we have to continue; @@ -379,7 +379,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) } else if (checkdist < closestdist && bestfindist == INT32_MAX) { - if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj)) + if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj)) // Intentionally not P_TraceWaypointTraversal { // Save sight checks when all of the other checks pass, so we only do it if we have to continue; diff --git a/src/p_local.h b/src/p_local.h index 1042f1193..9bc92cb64 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -456,6 +456,7 @@ void P_BounceMove(mobj_t *mo, TryMoveResult_t *result); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2); boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2); +boolean P_TraceWaypointTraversal(mobj_t *t1, mobj_t *t2); void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius); boolean P_CheckSector(sector_t *sector, boolean crunch); diff --git a/src/p_sight.c b/src/p_sight.c index 50b22243d..b582931f6 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -392,6 +392,26 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los return true; } +static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t *los) +{ + line_t *line = seg->linedef; + + if (P_CanTraceBlockingLine(seg, divl, los) == false) + { + // Blocked, so obviously can't traverse either. + return false; + } + + if (line->special == 2001) + { + // Don't allow through the finish linedef. + // Causes some janky behavior. + return false; + } + + return true; +} + // // P_CrossSubsector // @@ -780,3 +800,62 @@ boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2) return P_CrossBSPNode((INT32)numnodes - 1, &los, &funcs); } +boolean P_TraceWaypointTraversal(mobj_t *t1, mobj_t *t2) +{ + const sector_t *s1, *s2; + size_t pnum; + los_t los; + los_funcs_t funcs; + + // First check for trivial rejection. + if (!t1 || !t2) + return false; + + I_Assert(!P_MobjWasRemoved(t1)); + I_Assert(!P_MobjWasRemoved(t2)); + + if (!t1->subsector || !t2->subsector + || !t1->subsector->sector || !t2->subsector->sector) + return false; + + s1 = t1->subsector->sector; + s2 = t2->subsector->sector; + pnum = (s1-sectors)*numsectors + (s2-sectors); + + if (rejectmatrix != NULL) + { + // Check in REJECT table. + if (rejectmatrix[pnum>>3] & (1 << (pnum&7))) // can't possibly be connected + return false; + } + + // killough 11/98: shortcut for melee situations + // same subsector? obviously visible + // haleyjd 02/23/06: can't do this if there are polyobjects in the subsec + if (!t1->subsector->polyList && + t1->subsector == t2->subsector) + return true; + + validcount++; + + los.strace.dx = (los.t2x = t2->x) - (los.strace.x = t1->x); + los.strace.dy = (los.t2y = t2->y) - (los.strace.y = t1->y); + + if (t1->x > t2->x) + los.bbox[BOXRIGHT] = t1->x, los.bbox[BOXLEFT] = t2->x; + else + los.bbox[BOXRIGHT] = t2->x, los.bbox[BOXLEFT] = t1->x; + + if (t1->y > t2->y) + los.bbox[BOXTOP] = t1->y, los.bbox[BOXBOTTOM] = t2->y; + else + los.bbox[BOXTOP] = t2->y, los.bbox[BOXBOTTOM] = t1->y; + + los.compareThing = t1; + los.alreadyHates = false; + + funcs.validate = &P_CanWaypointTraverse; + + // the head node is the last node output + return P_CrossBSPNode((INT32)numnodes - 1, &los, &funcs); +}