Merge branch 'waypoint-distance-check' into 'master'

Prevent waypoints from updating much further ahead in the course

Closes #912

See merge request KartKrew/Kart!1966
This commit is contained in:
Oni 2024-02-29 10:24:36 +00:00
commit 54c58580e6
5 changed files with 114 additions and 57 deletions

View file

@ -671,6 +671,7 @@ struct player_t
mobj_t *ringShooter; // DEZ respawner object
tic_t airtime; // Used to track just air time, but has evolved over time into a general "karted" timer. Rename this variable?
tic_t lastairtime;
UINT8 bigwaypointgap; // timer counts down if finish line distance gap is too big to update waypoint
UINT8 startboost; // (0 to 125) - Boost you get from start of race
UINT8 dropdashboost; // Boost you get when holding A while respawning

View file

@ -5494,7 +5494,7 @@ static void K_DrawWaypointDebugger(void)
Draw::TextElement label;
label.font(Draw::Font::kThin);
label.flags(V_AQUAMAP);
Draw line = Draw(8, 136).font(Draw::Font::kMenu);
Draw line = Draw(8, 110).font(Draw::Font::kMenu);
auto put = [&](const char* label_str, auto&&... args)
{
constexpr int kTabWidth = 48;
@ -5527,6 +5527,11 @@ static void K_DrawWaypointDebugger(void)
put("Cheat Check:", "{} / {}", stplyr->cheatchecknum, numcheatchecks);
put("Last Safe Cheat Check:", "{}", stplyr->lastsafecheatcheck);
}
if (stplyr->bigwaypointgap)
{
put("Auto Respawn Timer:", "{}", stplyr->bigwaypointgap);
}
}
static void K_DrawBotDebugger(void)

View file

@ -8709,6 +8709,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
K_DoIngameRespawn(player);
}
if (player->bigwaypointgap)
{
player->bigwaypointgap--;
if (!player->bigwaypointgap)
K_DoIngameRespawn(player);
}
if (player->tripwireUnstuck && !player->mo->hitlag)
player->tripwireUnstuck--;
@ -9422,26 +9429,27 @@ void K_KartPlayerAfterThink(player_t *player)
}
/*--------------------------------------------------
static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
static boolean K_SetPlayerNextWaypoint(player_t *player)
Gets the next waypoint of a player, by finding their closest waypoint, then checking which of itself and next or
Sets the next waypoint of a player, by finding their closest waypoint, then checking which of itself and next or
previous waypoints are infront of the player.
Also sets the current waypoint.
Input Arguments:-
player - The player the next waypoint is being found for
Return:-
The waypoint that is the player's next waypoint
Whether it is safe to update the respawn waypoint
--------------------------------------------------*/
static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
static boolean K_SetPlayerNextWaypoint(player_t *player)
{
waypoint_t *finishline = K_GetFinishLineWaypoint();
waypoint_t *bestwaypoint = NULL;
boolean updaterespawn = false;
if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false))
{
waypoint_t *waypoint = K_GetBestWaypointForMobj(player->mo, player->currentwaypoint);
boolean updaterespawn = false;
// Our current waypoint.
bestwaypoint = waypoint;
@ -9630,25 +9638,19 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
player->pflags &= ~PF_UPDATEMYRESPAWN;
}
// Respawn point should only be updated when we're going to a nextwaypoint
if ((updaterespawn) &&
(player->respawn.state == RESPAWNST_NONE) &&
(bestwaypoint != NULL) &&
(bestwaypoint != player->nextwaypoint) &&
(K_GetWaypointIsSpawnpoint(bestwaypoint)) &&
(K_GetWaypointIsEnabled(bestwaypoint) == true))
// If nextwaypoint is NULL, it means we don't want to update the waypoint until we touch another one.
// player->nextwaypoint will keep its previous value in this case.
if (bestwaypoint != NULL)
{
player->respawn.wp = bestwaypoint;
player->lastsafelap = player->laps;
player->lastsafecheatcheck = player->cheatchecknum;
player->nextwaypoint = bestwaypoint;
}
}
return bestwaypoint;
return updaterespawn;
}
/*--------------------------------------------------
void K_UpdateDistanceFromFinishLine(player_t *const player)
static void K_UpdateDistanceFromFinishLine(player_t *const player)
Updates the distance a player has to the finish line.
@ -9658,46 +9660,11 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
Return:-
None
--------------------------------------------------*/
void K_UpdateDistanceFromFinishLine(player_t *const player)
static void K_UpdateDistanceFromFinishLine(player_t *const player)
{
if (K_PodiumSequence() == true)
{
K_UpdatePodiumWaypoints(player);
return;
}
if ((player != NULL) && (player->mo != NULL))
{
waypoint_t *finishline = K_GetFinishLineWaypoint();
waypoint_t *nextwaypoint = NULL;
if (player->respawn.state == RESPAWNST_MOVE &&
player->respawn.init == true &&
player->lastsafelap < player->laps)
{
player->laps = player->lastsafelap;
player->cheatchecknum = player->lastsafecheatcheck;
}
if (player->spectator)
{
// Don't update waypoints while spectating
nextwaypoint = finishline;
}
else
{
nextwaypoint = K_GetPlayerNextWaypoint(player);
}
if (nextwaypoint != NULL)
{
// If nextwaypoint is NULL, it means we don't want to update the waypoint until we touch another one.
// player->nextwaypoint will keep its previous value in this case.
player->nextwaypoint = nextwaypoint;
}
// Update prev value (used for grief prevention code)
player->distancetofinishprev = player->distancetofinish;
// nextwaypoint is now the waypoint that is in front of us
if ((player->exiting && !(player->pflags & PF_NOCONTEST)) || player->spectator)
@ -9874,6 +9841,72 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
}
}
static UINT32 u32_delta(UINT32 x, UINT32 y)
{
return x > y ? x - y : y - x;
}
/*--------------------------------------------------
static void K_UpdatePlayerWaypoints(player_t *const player)
Updates the player's waypoints and finish line distance.
Input Arguments:-
player - The player to update
Return:-
None
--------------------------------------------------*/
static void K_UpdatePlayerWaypoints(player_t *const player)
{
const UINT32 distance_threshold = FixedMul(32768, mapobjectscale);
waypoint_t *const old_currentwaypoint = player->currentwaypoint;
waypoint_t *const old_nextwaypoint = player->nextwaypoint;
boolean updaterespawn = K_SetPlayerNextWaypoint(player);
// Update prev value (used for grief prevention code)
player->distancetofinishprev = player->distancetofinish;
K_UpdateDistanceFromFinishLine(player);
// Respawning should be a full reset.
UINT32 delta = u32_delta(player->distancetofinish, player->distancetofinishprev);
if (player->respawn.state == RESPAWNST_NONE && delta > distance_threshold)
{
CONS_Debug(DBG_GAMELOGIC, "Player %s: waypoint ID %d too far away (%u > %u)\n",
sizeu1(player - players), K_GetWaypointID(player->nextwaypoint), delta, distance_threshold);
// Distance jump is too great, keep the old waypoints and recalculate distance.
player->currentwaypoint = old_currentwaypoint;
player->nextwaypoint = old_nextwaypoint;
K_UpdateDistanceFromFinishLine(player);
// Start the auto respawn timer when the distance jumps.
if (!player->bigwaypointgap)
{
player->bigwaypointgap = 35;
}
}
else
{
// Reset the auto respawn timer if distance changes are back to normal.
player->bigwaypointgap = 0;
}
// Respawn point should only be updated when we're going to a nextwaypoint
if ((updaterespawn) &&
(player->respawn.state == RESPAWNST_NONE) &&
(player->nextwaypoint != old_nextwaypoint) &&
(K_GetWaypointIsSpawnpoint(player->nextwaypoint)) &&
(K_GetWaypointIsEnabled(player->nextwaypoint) == true))
{
player->respawn.wp = player->nextwaypoint;
player->lastsafelap = player->laps;
player->lastsafecheatcheck = player->cheatchecknum;
}
}
INT32 K_GetKartRingPower(const player_t *player, boolean boosted)
{
fixed_t ringPower = ((9 - player->kartspeed) + (9 - player->kartweight)) * (FRACUNIT/2);
@ -10798,10 +10831,27 @@ void K_UpdateAllPlayerPositions(void)
// First loop: Ensure all players' distance to the finish line are all accurate
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
player_t *player = &players[i];
if (!playeringame[i] || player->spectator || !player->mo || P_MobjWasRemoved(player->mo))
{
K_UpdateDistanceFromFinishLine(&players[i]);
continue;
}
if (K_PodiumSequence() == true)
{
K_UpdatePodiumWaypoints(player);
continue;
}
if (player->respawn.state == RESPAWNST_MOVE &&
player->respawn.init == true &&
player->lastsafelap < player->laps)
{
player->laps = player->lastsafelap;
player->cheatchecknum = player->lastsafecheatcheck;
}
K_UpdatePlayerWaypoints(player);
}
// Second loop: Ensure all player positions reflect everyone's distances

View file

@ -165,7 +165,6 @@ void K_RepairOrbitChain(mobj_t *orbit);
void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player);
mobj_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range);
INT32 K_GetKartRingPower(const player_t *player, boolean boosted);
void K_UpdateDistanceFromFinishLine(player_t *const player);
boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y);
INT16 K_UpdateSteeringValue(INT16 inputSteering, INT16 destSteering);
INT16 K_GetKartTurnValue(const player_t *player, INT16 turnvalue);

View file

@ -417,6 +417,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
WRITEUINT32(save->p, players[i].airtime);
WRITEUINT32(save->p, players[i].lastairtime);
WRITEUINT8(save->p, players[i].bigwaypointgap);
WRITEUINT8(save->p, players[i].startboost);
WRITEUINT8(save->p, players[i].dropdashboost);
@ -996,6 +997,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p);
players[i].airtime = READUINT32(save->p);
players[i].lastairtime = READUINT32(save->p);
players[i].bigwaypointgap = READUINT8(save->p);
players[i].startboost = READUINT8(save->p);
players[i].dropdashboost = READUINT8(save->p);