From da226e75a53935e0e4ea81b1a1a20ccb42d12db2 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Tue, 20 May 2025 00:06:12 +0200 Subject: [PATCH] More robust(?) finish line handling --- src/k_waypoint.cpp | 4 +++ src/p_map.c | 20 ------------- src/p_spec.c | 72 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/k_waypoint.cpp b/src/k_waypoint.cpp index 83a0096f9..f3a1196da 100644 --- a/src/k_waypoint.cpp +++ b/src/k_waypoint.cpp @@ -409,6 +409,10 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj, waypoint_t *const hint) return; } + // do not path over the finish line. just don't. + if (checkwaypoint == finishline) + return; + checkdist = P_AproxDistance( (mobj->x / FRACUNIT) - (checkwaypoint->mobj->x / FRACUNIT), (mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT)); diff --git a/src/p_map.c b/src/p_map.c index 2d653d9af..270df41e8 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2837,26 +2837,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, Try { P_CrossSpecialLine(ld, oldside, thing); } - else if (ld->special == 2001 && thing->player) // Finish Line - { - // ~~ WAYPOINT BULLSHIT ~~ - // Right on the line, P_PointOnLineSide may - // disagree with P_TraceWaypointTraversal. - // If this happens, nextwaypoint may update - // ahead of the finish line before the player - // crosses it. - // This bloats the finish line distance and - // triggers lap cheat prevention, preventing - // the player from gaining a lap. - // Since this only seems like it can happen - // very near to the line, simply don't update - // waypoints if the player is touching the - // line but hasn't crossed it. - // This will cause distancetofinish to jump - // but only for a very short distance (the - // radius of the player). - thing->player->pflags |= PF_FREEZEWAYPOINTS; - } } } diff --git a/src/p_spec.c b/src/p_spec.c index dacb5b66f..e65425fe6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1971,6 +1971,73 @@ void P_SwitchWeather(preciptype_t newWeather) P_SpawnPrecipitation(); } +static boolean isfinish(waypoint_t *check) +{ + size_t i; + waypoint_t *finish = K_GetFinishLineWaypoint(); + + if (check == NULL) + return false; + if (check == finish) + return true; + + for (i = 0; i < check->numnextwaypoints; i++) + { + if (check->nextwaypoints[i] == finish) + return true; + } + for (i = 0; i < check->numprevwaypoints; i++) + { + if (check->prevwaypoints[i] == finish) + return true; + } + + return false; +} + +// fix the player's current waypoint after crossing the finish line +// get them off the finish line waypoint ASAP! +static void K_FixupFinishWaypoint(player_t *player, boolean reverse) +{ + size_t i; + fixed_t closest = INT32_MAX; + waypoint_t *finish = K_GetFinishLineWaypoint(), *snapto = NULL; + + // now did we actually cross the REAL finish line? + // this is important for sprint maps + if (!isfinish(player->currentwaypoint) && !isfinish(player->nextwaypoint)) + return; + + //CONS_Printf("fixed up %td\n", player - players); + + if (reverse) + { + for (i = 0; i < finish->numprevwaypoints; i++) + { + waypoint_t *check = finish->prevwaypoints[i]; + fixed_t dist = R_PointToDist2(player->mo->x, player->mo->y, check->mobj->x, check->mobj->y); + if (dist < closest) + closest = dist, snapto = check; + } + } + else + { + for (i = 0; i < finish->numnextwaypoints; i++) + { + waypoint_t *check = finish->nextwaypoints[i]; + fixed_t dist = R_PointToDist2(player->mo->x, player->mo->y, check->mobj->x, check->mobj->y); + if (dist < closest) + closest = dist, snapto = check; + } + } + + if (snapto) + { + player->currentwaypoint = snapto; + player->nextwaypoint = NULL; // don't forget to update position after this :^) + } +} + static boolean K_IgnoreFinishLine(player_t *player) { // If potential lap cheating has been detected, do not @@ -2027,9 +2094,11 @@ static void K_HandleLapIncrement(player_t *player) } if (!cv_kartdebuglap.value && player->laps == 1) - player->pflags |= PF_TRUSTWAYPOINTS; + player->pflags |= PF_TRUSTWAYPOINTS; + K_FixupFinishWaypoint(player, false); K_UpdateAllPlayerPositions(); + // Set up lap animation vars if (player->laps > 1) { @@ -2139,6 +2208,7 @@ static void K_HandleLapDecrement(player_t *player) return; if (player->laps > 0) { + K_FixupFinishWaypoint(player, true); player->starpostnum = numstarposts; player->laps--; K_UpdateAllPlayerPositions();