Rework exit timing nittygritty

- exitcountdown is now used for both No Contest and regular exits
    - Set in P_DoPlayerExit
    - Handles sending XD_EXITLEVEL in P_Ticker
- player->exiting is now 0 or 1 (we can make it a bool or a new timer later)
- Fixes a longstanding bug where failing a GP round could restart multiple times
Also:
- Fix a possible waiting-in-the-wings issue where mapchanges would occour client-side in K_CheckBumpers
- Add `gptest` cheat - sets numlaps to 1 lap on mapload for quick but legitimate(ish) progression
This commit is contained in:
toaster 2022-10-13 17:37:35 +01:00
parent 5103b804ba
commit c8471c7c27
8 changed files with 61 additions and 51 deletions

View file

@ -449,6 +449,7 @@ consvar_t cv_kartdebugnodes = CVAR_INIT ("debugnodes", "Off", CV_CHEAT, CV_OnOff
consvar_t cv_kartdebugcolorize = CVAR_INIT ("debugcolorize", "Off", CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_kartdebugdirector = CVAR_INIT ("debugdirector", "Off", CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_spbtest = CVAR_INIT ("spbtest", "Off", CV_CHEAT|CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_gptest = CVAR_INIT ("gptest", "Off", CV_CHEAT|CV_NETVAR, CV_OnOff, NULL);
static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_votetime = CVAR_INIT ("votetime", "20", CV_NETVAR, votetime_cons_t, NULL);

View file

@ -120,7 +120,8 @@ extern consvar_t cv_kartusepwrlv;
extern consvar_t cv_votetime;
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugdistribution, cv_kartdebughuddrop;
extern consvar_t cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector, cv_spbtest;
extern consvar_t cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector;
extern consvar_t cv_spbtest, cv_gptest;
extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict;
extern consvar_t cv_itemfinder;

View file

@ -133,6 +133,10 @@ void K_CheckBumpers(void)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].spectator)
continue;
players[i].pflags |= PF_NOCONTEST;
P_DoPlayerExit(&players[i]);
}
@ -144,7 +148,8 @@ void K_CheckBumpers(void)
if (!battlecapsules)
{
// Reset map to turn on battle capsules
D_MapChange(gamemap, gametype, encoremode, true, 0, false, false);
if (server)
D_MapChange(gamemap, gametype, encoremode, true, 0, false, false);
}
else
{
@ -152,6 +157,10 @@ void K_CheckBumpers(void)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (players[i].spectator)
continue;
players[i].pflags |= PF_NOCONTEST;
P_DoPlayerExit(&players[i]);
}

View file

@ -651,7 +651,7 @@ void K_FakeBotResults(player_t *bot)
}
// hey, you "won"
bot->exiting = 2;
bot->exiting = 1;
bot->realtime += (bot->distancetofinish / distfactor);
bot->distancetofinish = 0;
K_IncreaseBotDifficulty(bot);

View file

@ -848,7 +848,7 @@ boolean P_CheckRacers(void)
}
// Everyone should be done playing at this point now.
racecountdown = exitcountdown = 0;
racecountdown = 0;
return true;
}
@ -856,7 +856,7 @@ boolean P_CheckRacers(void)
{
// There might be bots that are still going,
// but all of the humans are done, so we can exit now.
racecountdown = exitcountdown = 0;
racecountdown = 0;
return true;
}

View file

@ -3843,6 +3843,7 @@ static void P_InitPlayers(void)
static void P_InitGametype(void)
{
size_t i;
boolean canchangerules = K_CanChangeRules();
spectateGriefed = 0;
K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped
@ -3852,24 +3853,31 @@ static void P_InitGametype(void)
if (modeattacking && !demo.playback)
P_LoadRecordGhosts();
numlaps = 0;
if (gametyperules & GTR_CIRCUIT)
{
if ((netgame || multiplayer) && cv_numlaps.value
if (canchangerules && cv_numlaps.value
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_numlaps.value)))
{
numlaps = cv_numlaps.value;
}
else if (cv_gptest.value)
{
numlaps = 1;
}
else
{
numlaps = mapheaderinfo[gamemap - 1]->numlaps;
}
}
else
{
numlaps = 0;
}
if ((gametyperules & GTR_TIMELIMIT) && !bossinfo.boss)
{
if (K_CanChangeRules() == false)
if (!canchangerules)
{
timelimitintics = timelimits[gametype] * (60*TICRATE);
}

View file

@ -594,20 +594,31 @@ void P_Ticker(boolean run)
ps_playerthink_time = I_GetPreciseTime();
#define PLAYERCONDITION(i) (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
// 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))
K_UpdateDistanceFromFinishLine(&players[i]);
{
if (!PLAYERCONDITION(i))
continue;
K_UpdateDistanceFromFinishLine(&players[i]);
}
// Second loop: Ensure all player positions reflect everyone's distances
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
K_KartUpdatePosition(&players[i]);
{
if (!PLAYERCONDITION(i))
continue;
K_KartUpdatePosition(&players[i]);
}
// OK! Now that we got all of that sorted, players can think!
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]);
{
if (!PLAYERCONDITION(i))
continue;
P_PlayerThink(&players[i]);
}
#undef PLAYERCONDITION
ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time;
}
@ -690,7 +701,13 @@ void P_Ticker(boolean run)
racecountdown--;
if (exitcountdown > 1)
{
exitcountdown--;
if (server && exitcountdown == 1)
{
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
}
K_RunItemCooldowns();

View file

@ -1261,9 +1261,10 @@ void P_DoPlayerExit(player_t *player)
K_PlayerLoseLife(player);
}
player->exiting = 1;
if ((gametyperules & GTR_CIRCUIT)) // If in Race Mode, allow
{
player->exiting = raceexittime+2;
K_KartUpdatePosition(player);
if (cv_kartvoices.value)
@ -1289,16 +1290,20 @@ void P_DoPlayerExit(player_t *player)
if (!K_CanChangeRules() || cv_inttime.value > 0)
P_EndingMusic(player);
if (P_CheckRacers())
player->exiting = raceexittime+1;
if (P_CheckRacers() && !exitcountdown)
exitcountdown = raceexittime+1;
}
else if ((gametyperules & GTR_BUMPERS)) // Battle Mode exiting
{
player->exiting = battleexittime+1;
if (!exitcountdown)
exitcountdown = battleexittime+1;
P_EndingMusic(player);
}
else
player->exiting = raceexittime+2; // Accidental death safeguard???
else // Accidental death safeguard???
{
if (!exitcountdown)
exitcountdown = raceexittime+2;
}
if (grandprixinfo.gp == true)
{
@ -3946,21 +3951,6 @@ void P_PlayerThink(player_t *player)
{
if (gametyperules & GTR_CIRCUIT)
{
INT32 i;
// Check if all the players in the race have finished. If so, end the level.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
if (!players[i].exiting && !(players[i].pflags & PF_NOCONTEST) && players[i].lives > 0)
break;
}
}
if (i == MAXPLAYERS && player->exiting == raceexittime+2) // finished
player->exiting = raceexittime+1;
#if 0
// If 10 seconds are left on the timer,
// begin the drown music for countdown!
@ -3985,22 +3975,6 @@ void P_PlayerThink(player_t *player)
}
}
}
// If it is set, start subtracting
// Don't allow it to go back to 0
if (player->exiting > 1 && (player->exiting < raceexittime+2 || !(gametyperules & GTR_CIRCUIT))) // SRB2kart - "&& player->exiting > 1"
player->exiting--;
if (player->exiting && exitcountdown)
player->exiting = 99; // SRB2kart
if (player->exiting == 2 || exitcountdown == 2)
{
if (server)
{
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
}
}
// check water content, set stuff in mobj