Port basic lap anticheat for new waypoints from RR

This commit is contained in:
NepDisk 2025-03-09 20:03:10 -04:00
parent 58e243a20c
commit bda7d26a0f
15 changed files with 145 additions and 13 deletions

View file

@ -469,6 +469,7 @@ consvar_t cv_kartdebugdistribution = CVAR_INIT ("kartdebugdistribution", "Off",
consvar_t cv_kartdebughuddrop = CVAR_INIT ("kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL);
static CV_PossibleValue_t kartdebugwaypoint_cons_t[] = {{0, "Off"}, {1, "Forwards"}, {2, "Backwards"}, {0, NULL}};
consvar_t cv_kartdebugwaypoints = CVAR_INIT ("kartdebugwaypoints", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugwaypoint_cons_t, NULL);
consvar_t cv_kartdebuglap = CVAR_INIT ("kartdebuglap", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugwaypoint_cons_t, NULL);
consvar_t cv_kartdebugbotpredict = CVAR_INIT ("kartdebugbotpredict", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL);
consvar_t cv_kartdebugcheckpoint = CVAR_INIT ("kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL);

View file

@ -106,7 +106,7 @@ extern consvar_t cv_votetime;
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartallowgiveitem, cv_kartdebugdistribution, cv_kartdebughuddrop;
extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector;
extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict;
extern consvar_t cv_kartdebugwaypoints, cv_kartdebuglap,cv_kartdebugbotpredict;
extern consvar_t cv_itemfinder;

View file

@ -102,7 +102,7 @@ typedef enum
PF_UPDATEMYRESPAWN = 1<<19,
PF_FLIPCAM = 1<<20,
//free = 1<<21,
PF_TRUSTWAYPOINTS = 1<<21, // Do not activate lap cheat prevention next time finish line distance is updated
PF_HITFINISHLINE = 1<<22, // Already hit the finish line this tic
PF_WRONGWAY = 1<<23, // Moving the wrong way with respect to waypoints?
@ -548,6 +548,7 @@ struct player_t
UINT32 distancetofinishprev;
waypoint_t *currentwaypoint;
waypoint_t *nextwaypoint;
UINT16 bigwaypointgap;
tic_t airtime; // Keep track of how long you've been in the air
UINT8 startboost; // (0 to 125) - Boost you get from start of race or respawn drop dash
@ -657,6 +658,9 @@ struct player_t
UINT16 breathTimer; // Holding your breath underwater
UINT8 lastsafelap;
UINT8 lastsafestarpost;
//
SINT8 lives;

View file

@ -1408,6 +1408,8 @@ void readlevelheader(MYFILE *f, char * name)
mapheaderinfo[num]->encorepal = (UINT16)i;
else if (fastcmp(word, "NUMLAPS"))
mapheaderinfo[num]->numlaps = (UINT8)i;
else if (fastcmp(word, "LAPSPERSECTION"))
mapheaderinfo[num]->lapspersection = max((UINT8)i, 1u);
else if (fastcmp(word, "UNLOCKABLE"))
{
if (i >= 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something

View file

@ -267,7 +267,7 @@ const char *const PLAYERFLAG_LIST[] = {
"UPDATEMYRESPAWN",
"FLIPCAM",
"\x01",
"TRUSTWAYPOINTS",
"HITFINISHLINE", // Already hit the finish line this tic
"WRONGWAY", // Moving the wrong way with respect to waypoints?

View file

@ -413,6 +413,7 @@ struct mapheader_t
UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below
UINT32 typeoflevel; ///< Combination of typeoflevel flags.
UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden.
UINT8 lapspersection; ///< Number of laps per section in hybrid section-circuit maps.
fixed_t gravity; ///< Map-wide gravity.
// Music information

View file

@ -2359,6 +2359,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
UINT16 nocontrol;
INT32 kickstartaccel;
boolean enteredGame;
UINT8 lastsafelap;
UINT8 lastsafestarpost;
UINT16 bigwaypointgap;
score = players[player].score;
lives = players[player].lives;
@ -2412,6 +2415,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
wanted = 0;
rings = 10;
kickstartaccel = 0;
lastsafelap = 0;
lastsafestarpost = 0;
bigwaypointgap = 0;
nocontrol = 0;
laps = 0;
latestlap = 0;
@ -2479,6 +2485,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
prevcheck = players[player].nextcheck;
pflags |= (players[player].pflags & (PF_STASIS|PF_ELIMINATED|PF_NOCONTEST|PF_LOSTLIFE|PF_FLIPCAM));
lastsafelap = players[player].lastsafelap;
lastsafestarpost = players[player].lastsafestarpost;
bigwaypointgap = players[player].bigwaypointgap;
}
if (!betweenmaps)
@ -2513,6 +2523,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->splitscreenindex = splitscreenindex;
p->spectator = spectator;
p->angleturn = playerangleturn;
p->lastsafelap = lastsafelap;
p->lastsafestarpost = lastsafestarpost;
p->bigwaypointgap = bigwaypointgap;
// save player config truth reborn
p->skincolor = skincolor;

View file

@ -4299,6 +4299,11 @@ static void K_DrawWaypointDebugger(void)
if (stplyr != &players[displayplayers[0]]) // only for p1
return;
if (stplyr->bigwaypointgap)
{
V_DrawString(8, 146, 0, va("Auto Respawn Timer: %d", stplyr->bigwaypointgap));
}
V_DrawString(8, 156, 0, va("Current Waypoint ID: %d", K_GetWaypointID(stplyr->currentwaypoint)));
V_DrawString(8, 166, 0, va("Next Waypoint ID: %d", K_GetWaypointID(stplyr->nextwaypoint)));
V_DrawString(8, 176, 0, va("Finishline Distance: %d", stplyr->distancetofinish));

View file

@ -238,6 +238,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartdebugdistribution);
CV_RegisterVar(&cv_kartdebughuddrop);
CV_RegisterVar(&cv_kartdebugwaypoints);
CV_RegisterVar(&cv_kartdebuglap);
CV_RegisterVar(&cv_kartdebugbotpredict);
CV_RegisterVar(&cv_kartdebugcheckpoint);
@ -7025,6 +7026,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->checkskip)
player->checkskip--;
if (player->bigwaypointgap && (player->bigwaypointgap > AUTORESPAWN_THRESHOLD || !P_PlayerInPain(player)))
{
player->bigwaypointgap--;
if (!player->bigwaypointgap)
P_KillMobj(player->mo, NULL, NULL, DMG_INSTAKILL);
else if (player->bigwaypointgap == AUTORESPAWN_THRESHOLD)
{
S_StartSound(player->mo, sfx_s26d);
CONS_Printf("You are going the wrong way! You will automatically respawn in 7 seconds.\n");
}
}
if (player->growshrinktimer != 0)
{
if (player->growshrinktimer > 0)
@ -8134,7 +8147,7 @@ static void K_UpdateDistanceFromFinishLine(player_t *player)
const mapheader_t *mapheader = mapheaderinfo[gamemap - 1];
if ((mapheader->levelflags & LF_SECTIONRACE) == 0U)
{
const UINT8 numfulllapsleft = ((UINT8)numlaps - player->laps);
const UINT8 numfulllapsleft = ((UINT8)numlaps - player->laps) / mapheader->lapspersection;
player->distancetofinish += numfulllapsleft * K_GetCircuitLength();
}
}
@ -8183,24 +8196,59 @@ static void K_UpdatePlayerWaypoints(player_t *const player)
boolean updaterespawn = K_SetPlayerNextWaypoint(player);
// Update prev value (used for grief prevention code)
K_UpdateDistanceFromFinishLine(player);
player->distancetofinishprev = player->distancetofinish;
K_UpdateDistanceFromFinishLine(player);
// Respawning should be a full reset.
UINT32 delta = u32_delta(player->distancetofinish, player->distancetofinishprev);
if (!player->respawn && delta > distance_threshold)
if (delta > distance_threshold &&
!player->respawn && // Respawning should be a full reset.
old_currentwaypoint != NULL && // So should touching the first waypoint ever.
player->laps != 0 && // POSITION rooms may have unorthodox waypoints to guide bots.
!(player->pflags & PF_TRUSTWAYPOINTS)) // Special exception.
{
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);
#define debug_args "Player %s: waypoint ID %d too far away (%u > %u)\n", \
sizeu1(player - players), K_GetWaypointID(player->nextwaypoint), delta, distance_threshold
if (cv_kartdebuglap.value)
CONS_Printf(debug_args);
else
CONS_Debug(DBG_GAMELOGIC, debug_args);
#undef debug_args
// Distance jump is too great, keep the old waypoints and recalculate distance.
player->currentwaypoint = old_currentwaypoint;
player->nextwaypoint = old_nextwaypoint;
player->distancetofinish = player->distancetofinishprev;
if (!cv_kartdebuglap.value)
{
// Distance jump is too great, keep the old waypoints and old distance.
player->currentwaypoint = old_currentwaypoint;
player->nextwaypoint = old_nextwaypoint;
player->distancetofinish = player->distancetofinishprev;
// Start the auto respawn timer when the distance jumps.
if (!player->bigwaypointgap)
{
player->bigwaypointgap = AUTORESPAWN_TIME;
}
}
}
else
{
// Reset the auto respawn timer if distance changes are back to normal.
if (player->bigwaypointgap && player->bigwaypointgap <= AUTORESPAWN_THRESHOLD + 1)
{
player->bigwaypointgap = 0;
// While the player was in the "bigwaypointgap" state, laps did not change from crossing finish lines.
// So reset the lap back to normal, in case they were able to get behind the line.
player->laps = player->lastsafelap;
if (numbosswaypoints == 0)
{
player->starpostnum = player->lastsafestarpost;
}
}
}
// Respawn point should only be updated when we're going to a nextwaypoint
if ((updaterespawn) &&
(player->bigwaypointgap == 0) &&
(!player->respawn) &&
(player->nextwaypoint != old_nextwaypoint) &&
(K_GetWaypointIsSpawnpoint(player->nextwaypoint)) &&
@ -8209,6 +8257,9 @@ static void K_UpdatePlayerWaypoints(player_t *const player)
if (!(player->pflags & PF_WRONGWAY))
player->grieftime = 0;
player->lastsafelap = player->laps;
player->lastsafestarpost = player->starpostnum;
// Check if respawn is safe. If not then goto next spawnpoint and respawn there.
if (K_SafeRespawnPosition(player->mo))
{
@ -8244,6 +8295,8 @@ static void K_UpdatePlayerWaypoints(player_t *const player)
K_FudgeRespawn(player, player->nextwaypoint);
}
}
player->pflags &= ~PF_TRUSTWAYPOINTS; // clear special exception
}
INT32 K_GetKartRingPower(player_t *player, boolean boosted)
@ -8819,6 +8872,16 @@ void K_UpdateAllPlayerPositions(void)
continue;
}
if (player->respawn > 0 && player->lastsafelap != player->laps)
{
player->laps = player->lastsafelap;
if (numbosswaypoints == 0)
{
player->starpostnum = player->lastsafestarpost;
}
}
K_UpdatePlayerWaypoints(player);
}

View file

@ -26,6 +26,9 @@ Make sure this matches the actual number of states
#define GROW_SCALE ((3*FRACUNIT)/2)
#define SHRINK_SCALE ((6*FRACUNIT)/8)
#define AUTORESPAWN_TIME (10 * TICRATE)
#define AUTORESPAWN_THRESHOLD (7 * TICRATE)
// Used for respawning checks.
typedef struct respawnresult_s

View file

@ -2609,6 +2609,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->palette);
else if (fastcmp(field,"numlaps"))
lua_pushinteger(L, header->numlaps);
else if (fastcmp(field,"lapspersection"))
lua_pushinteger(L, header->lapspersection);
else if (fastcmp(field,"unlockrequired"))
lua_pushinteger(L, header->unlockrequired);
else if (fastcmp(field,"levelselect"))

View file

@ -388,6 +388,12 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->confirmVictimDelay);
else if (fastcmp(field,"glanceDir"))
lua_pushinteger(L, plr->glanceDir);
else if (fastcmp(field,"breathTimer"))
lua_pushinteger(L, plr->breathTimer);
else if (fastcmp(field,"lastsafelap"))
lua_pushinteger(L, plr->lastsafelap);
else if (fastcmp(field,"laststarpost"))
lua_pushinteger(L, plr->lastsafestarpost);
else if (fastcmp(field,"roundscore"))
plr->roundscore = luaL_checkinteger(L, 3);
else if (fastcmp(field,"marescore"))
@ -799,6 +805,12 @@ static int player_set(lua_State *L)
plr->confirmVictimDelay = luaL_checkinteger(L, 3);
else if (fastcmp(field,"glanceDir"))
plr->glanceDir = luaL_checkinteger(L, 3);
else if (fastcmp(field,"breathTimer"))
plr->breathTimer = luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastsafelap"))
plr->lastsafelap = luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastsafestarpost"))
plr->lastsafestarpost = luaL_checkinteger(L, 3);
else if (fastcmp(field,"roundscore"))
lua_pushinteger(L, plr->roundscore);
else if (fastcmp(field,"marescore"))

View file

@ -246,6 +246,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT32(save->p, players[i].distancetofinishprev);
WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint));
WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
WRITEUINT16(save->p, players[i].bigwaypointgap);
WRITEUINT32(save->p, players[i].airtime);
WRITEUINT8(save->p, players[i].startboost);
@ -348,6 +349,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT16(save->p, players[i].breathTimer);
WRITEUINT8(save->p, players[i].lastsafelap);
WRITEUINT8(save->p, players[i].lastsafestarpost);
WRITEUINT8(save->p, players[i].typing_timer);
WRITEUINT8(save->p, players[i].typing_duration);
@ -552,7 +556,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].distancetofinish = READUINT32(save->p);
players[i].distancetofinishprev = READUINT32(save->p);
players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p);
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p);
players[i].bigwaypointgap = READUINT16(save->p);
players[i].airtime = READUINT32(save->p);
players[i].startboost = READUINT8(save->p);
@ -655,6 +661,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].breathTimer = READUINT16(save->p);
players[i].lastsafelap = READUINT8(save->p);
players[i].lastsafestarpost = READUINT8(save->p);
players[i].typing_timer = READUINT8(save->p);
players[i].typing_duration = READUINT8(save->p);

View file

@ -427,6 +427,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->palette = UINT16_MAX;
mapheaderinfo[num]->encorepal = UINT16_MAX;
mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT;
mapheaderinfo[num]->lapspersection = 1;
mapheaderinfo[num]->unlockrequired = -1;
mapheaderinfo[num]->levelselect = 0;
mapheaderinfo[num]->levelflags = 0;

View file

@ -1970,11 +1970,23 @@ void P_SwitchWeather(preciptype_t newWeather)
P_SpawnPrecipitation();
}
static boolean K_IgnoreFinishLine(player_t *player)
{
// If potential lap cheating has been detected, do not
// interact with the finish line at all.
if (player->bigwaypointgap)
return true;
return false;
}
// Passed over the finish line forwards
static void K_HandleLapIncrement(player_t *player)
{
if (player)
{
if (K_IgnoreFinishLine(player))
return;
if (((numbosswaypoints > 0) ? (player->starpostnum >= (numstarposts - (numstarposts/2))) : (player->starpostnum == numstarposts)) || (player->laps == 0))
{
size_t i = 0;
@ -1992,6 +2004,9 @@ static void K_HandleLapIncrement(player_t *player)
player->starposttime = player->realtime;
player->starpostnum = 0;
player->lastsafestarpost = 0;
player->laps++;
if (mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
{
@ -2010,7 +2025,8 @@ static void K_HandleLapIncrement(player_t *player)
player->starpostangle = player->starpostx = player->starposty = player->starpostz = player->starpostflip = 0;
}
player->laps++;
if (!cv_kartdebuglap.value && player->laps == 1)
player->pflags |= PF_TRUSTWAYPOINTS;
K_UpdateAllPlayerPositions();
// Set up lap animation vars