More robust(?) finish line handling

This commit is contained in:
GenericHeroGuy 2025-05-20 00:06:12 +02:00
parent fbccc955c9
commit da226e75a5
3 changed files with 75 additions and 21 deletions

View file

@ -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));

View file

@ -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;
}
}
}

View file

@ -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();