Merge branch 'challenge-consarnit' into 'master'

Challenge Consarn-it

See merge request KartKrew/Kart!1722
This commit is contained in:
toaster 2023-12-28 14:55:53 +00:00
commit 89b8aa0a55
11 changed files with 415 additions and 123 deletions

View file

@ -134,6 +134,7 @@ static void Command_LeaveParty_f(void);
static void Command_Addfile(void); static void Command_Addfile(void);
static void Command_ListWADS_f(void); static void Command_ListWADS_f(void);
static void Command_ListDoomednums_f(void); static void Command_ListDoomednums_f(void);
static void Command_cxdiag_f(void);
static void Command_RunSOC(void); static void Command_RunSOC(void);
static void Command_Pause(void); static void Command_Pause(void);
@ -396,6 +397,7 @@ void D_RegisterServerCommands(void)
COM_AddCommand("addfile", Command_Addfile); COM_AddCommand("addfile", Command_Addfile);
COM_AddDebugCommand("listwad", Command_ListWADS_f); COM_AddDebugCommand("listwad", Command_ListWADS_f);
COM_AddDebugCommand("listmapthings", Command_ListDoomednums_f); COM_AddDebugCommand("listmapthings", Command_ListDoomednums_f);
COM_AddDebugCommand("cxdiag", Command_cxdiag_f);
COM_AddCommand("runsoc", Command_RunSOC); COM_AddCommand("runsoc", Command_RunSOC);
COM_AddCommand("pause", Command_Pause); COM_AddCommand("pause", Command_Pause);
@ -4704,6 +4706,226 @@ static void Command_ListDoomednums_f(void)
#undef MAXDOOMEDNUM #undef MAXDOOMEDNUM
static void Command_cxdiag_f(void)
{
UINT16 i, j, errors = 0;
CONS_Printf("\x82""Welcome to the Challenge eXception Diagnostic.\n");
{
conditionset_t *c;
condition_t *cn;
CONS_Printf("\x82""Evaluating ConditionSets...\n");
for (i = 0; i < MAXCONDITIONSETS; i++)
{
c = &conditionSets[i];
if (!c->numconditions)
continue;
UINT32 lastID = 0;
boolean validSoFar = true;
boolean requiresPlaying = false;
boolean lastRequiresPlaying = false;
boolean lastrequiredplayingvalid = false;
boolean immediatelyprefix = false;
INT32 relevantlevelgt = -1;
UINT8 lastj = j = 0;
while (true) //for (j = 0; j < c->numconditions; ++j)
{
if (j >= c->numconditions)
{
if (j == lastj)
break;
UINT8 swap = j;
j = lastj;
lastj = swap;
lastrequiredplayingvalid = false;
validSoFar = true;
}
cn = &c->condition[j];
if (lastID)
{
//if (lastID != cn->id && validSoFar)
//CONS_Printf("\x87""Condition%d good\n", lastID);
if (lastID != cn->id)
{
lastrequiredplayingvalid = false;
validSoFar = true;
if (j != lastj)
{
UINT8 swap = j;
j = lastj;
lastj = swap;
continue;
}
relevantlevelgt = -1;
}
else if (!validSoFar)
{
j++;
continue;
}
}
const boolean firstpass = (lastj <= j);
if (cn->type == UC_DESCRIPTIONOVERRIDE)
{
if (firstpass)
;
else if (!cn->stringvar)
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) - Description override has no description!?\n", i+1, j+1, cn->id);
errors++;
}
else if (cn->stringvar[0] != tolower(cn->stringvar[0]))
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) - Description override begins with capital letter, which isn't necessary and can sometimes look weird in generated descriptions\n", i+1, j+1, cn->id);
errors++;
}
lastID = cn->id;
j++;
continue;
}
if (cn->type == UC_AND || cn->type == UC_COMMA)
{
if (firstpass)
;
else if (immediatelyprefix || lastID != cn->id)
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) - Conjunction immediately follows %s - this just looks plain weird!\n", i+1, j+1, cn->id, immediatelyprefix ? "Prefix type" : "start");
errors++;
}
lastID = cn->id;
j++;
continue;
}
lastID = cn->id;
lastRequiresPlaying = requiresPlaying;
requiresPlaying = (cn->type >= UCRP_REQUIRESPLAYING);
if (!firstpass && lastrequiredplayingvalid)
{
if (lastRequiresPlaying != requiresPlaying)
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) combines Playing condition and Statistics condition - will never be achieved\n", i+1, j+1, lastID);
validSoFar = false;
errors++;
}
}
lastrequiredplayingvalid = true;
immediatelyprefix = (cn->type >= UCRP_PREFIX_GRANDPRIX && cn->type <= UCRP_PREFIX_ISMAP);
if (cn->type == UCRP_PREFIX_ISMAP || cn->type == UCRP_ISMAP)
{
if (firstpass && relevantlevelgt != -1)
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) has multiple courses specified\n", i+1, j+1, lastID);
validSoFar = false;
errors++;
}
if (cn->requirement == 0)
relevantlevelgt = 0;
else if (cn->requirement > 0 && cn->requirement < basenummapheaders)
relevantlevelgt = G_GuessGametypeByTOL(mapheaderinfo[cn->requirement]->typeoflevel);
else
relevantlevelgt = -1;
}
else if (firstpass || relevantlevelgt == -1)
;
else if (cn->type >= UCRP_PODIUMCUP && cn->type <= UCRP_PODIUMNOCONTINUES)
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) is Podium state when specific course in Cup already requested\n", i+1, j+1, lastID);
validSoFar = false;
errors++;
}
else if (cn->type == UCRP_FINISHALLPRISONS || cn->type == UCRP_PREFIX_PRISONBREAK)
{
if (!(gametypes[relevantlevelgt]->rules & GTR_PRISONS))
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) is Prison Break-based, but with %s course\n", i+1, j+1, lastID, gametypes[relevantlevelgt]->name);
validSoFar = false;
errors++;
}
}
else if (cn->type == UCRP_SMASHUFO || cn->type == UCRP_PREFIX_SEALEDSTAR)
{
if (!(gametypes[relevantlevelgt]->rules & GTR_CATCHER))
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) is Sealed Star-based, but with %s course\n", i+1, j+1, lastID, gametypes[relevantlevelgt]->name);
validSoFar = false;
errors++;
}
}
else if (cn->type == UCRP_RINGS || cn->type == UCRP_RINGSEXACT || cn->type == UCRP_RINGDEBT)
{
if ((gametypes[relevantlevelgt]->rules & GTR_SPHERES))
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) is Rings-based, but with %s course\n", i+1, j+1, lastID, gametypes[relevantlevelgt]->name);
validSoFar = false;
errors++;
}
}
else if (cn->type == UCRP_GROWCONSECUTIVEBEAMS || cn->type == UCRP_FAULTED || cn->type == UCRP_FINISHPERFECT)
{
if (!(gametypes[relevantlevelgt]->rules & GTR_CIRCUIT))
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) is circuit-based, but with %s course\n", i+1, j+1, lastID, gametypes[relevantlevelgt]->name);
validSoFar = false;
errors++;
}
}
else if (cn->type == UCRP_FINISHTIMELEFT)
{
if (!(gametypes[relevantlevelgt]->rules & GTR_TIMELIMIT))
{
CONS_Printf("\x87"" ConditionSet %u entry %u (Condition%u) is timelimit-based, but with %s course\n", i+1, j+1, lastID, gametypes[relevantlevelgt]->name);
validSoFar = false;
errors++;
}
}
j++;
}
}
}
{
unlockable_t *un;
CONS_Printf("\x82""Evaluating Challenges...\n");
for (i = 0; i < MAXUNLOCKABLES; i++)
{
un = &unlockables[i];
j = un->conditionset;
if (!j)
continue;
if (!conditionSets[j-1].numconditions)
{
CONS_Printf("\x87"" Unlockable %u has ConditionSet %u, which has no Conditions successfully set - will never be unlocked?\n", i+1, j);
errors++;
}
}
}
if (errors)
CONS_Printf("\x85""%u errors detected.\n", errors);
else
CONS_Printf("\x83""No errors detected! Good job\n");
}
// ========================================================================= // =========================================================================
// MISC. COMMANDS // MISC. COMMANDS
// ========================================================================= // =========================================================================

View file

@ -1408,7 +1408,7 @@ void readlevelheader(MYFILE *f, char * name)
do { do {
if (j >= MAXDESTRUCTIBLES) if (j >= MAXDESTRUCTIBLES)
break; break;
mapheaderinfo[num]->destroyforchallenge[j] = get_mobjtype(word2); mapheaderinfo[num]->destroyforchallenge[j] = get_mobjtype(tmp);
j++; j++;
} while ((tmp = strtok(NULL,",")) != NULL); } while ((tmp = strtok(NULL,",")) != NULL);
@ -2773,9 +2773,9 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
if (fastcmp(params[1], "NORMAL")) if (fastcmp(params[1], "NORMAL"))
; ;
else if (fastcmp(params[1], "HARD")) else if (fastcmp(params[1], "HARD"))
x1 = KARTSPEED_HARD; re = KARTSPEED_HARD;
else if (fastcmp(params[1], "MASTER")) else if (fastcmp(params[1], "MASTER"))
x1 = KARTGP_MASTER; re = KARTGP_MASTER;
else else
{ {
deh_warning("gamespeed requirement \"%s\" invalid for condition ID %d", params[1], id+1); deh_warning("gamespeed requirement \"%s\" invalid for condition ID %d", params[1], id+1);

View file

@ -4691,6 +4691,16 @@ void G_LoadGameData(void)
gamedata->keyspending = READUINT16(save.p); gamedata->keyspending = READUINT16(save.p);
} }
// Sanity check.
if (gamedata->pendingkeyroundoffset >= GDCONVERT_ROUNDSTOKEY)
{
gamedata->pendingkeyrounds +=
(gamedata->pendingkeyroundoffset
- (GDCONVERT_ROUNDSTOKEY-1));
gamedata->pendingkeyroundoffset = (GDCONVERT_ROUNDSTOKEY-1);
gamedata->keyspending = 0; // safe to nuke - will be recalc'd if the offset still permits
}
gamedata->chaokeys = READUINT16(save.p); gamedata->chaokeys = READUINT16(save.p);
if (versionMinor >= 4) if (versionMinor >= 4)

View file

@ -771,6 +771,7 @@ extern consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX];
void M_CharacterSelectInit(void); void M_CharacterSelectInit(void);
void M_CharacterSelect(INT32 choice); void M_CharacterSelect(INT32 choice);
void M_SetupReadyExplosions(boolean charsel, UINT16 basex, UINT16 basey, UINT16 color); void M_SetupReadyExplosions(boolean charsel, UINT16 basex, UINT16 basey, UINT16 color);
boolean M_CharacterSelectForceInAction(void);
boolean M_CharacterSelectHandler(INT32 choice); boolean M_CharacterSelectHandler(INT32 choice);
void M_CharacterSelectTick(void); void M_CharacterSelectTick(void);
boolean M_CharacterSelectQuit(void); boolean M_CharacterSelectQuit(void);

View file

@ -2272,7 +2272,7 @@ void M_DrawCharacterSelect(void)
INT16 quadx, quady; INT16 quadx, quady;
INT16 skin; INT16 skin;
INT32 basex = optionsmenu.profile ? (64 + (menutransition.tics*32)) : 0; INT32 basex = optionsmenu.profile ? (64 + (menutransition.tics*32)) : 0;
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); boolean forceskin = M_CharacterSelectForceInAction();
if (setup_numplayers > 0) if (setup_numplayers > 0)
{ {
@ -6622,7 +6622,7 @@ challengedesc:
) )
) )
{ {
V_DrawCenteredString(BASEVIDWIDTH/2, 120 + 32, 0, challengesmenu.unlockcondition); V_DrawCenteredThinString(BASEVIDWIDTH/2, 120 + 32, 0, challengesmenu.unlockcondition);
} }
} }

View file

@ -864,7 +864,11 @@ void K_InitializePodiumWaypoint(player_t *const player)
{ {
if ((player != NULL) && (player->mo != NULL)) if ((player != NULL) && (player->mo != NULL))
{ {
player->position = K_GetPodiumPosition(player); if (player->position == 0)
{
// Just in case a netgame scenario with a late joiner ocurrs.
player->position = K_GetPodiumPosition(player);
}
if (player->position > 0 && player->position <= MAXPLAYERS) if (player->position > 0 && player->position <= MAXPLAYERS)
{ {
@ -989,12 +993,6 @@ void K_FinishCeremony(void)
} }
g_podiumData.ranking = true; g_podiumData.ranking = true;
// Play the noise now (via G_UpdateVisited's concluding challenge check)
prevmap = gamemap-1;
G_UpdateVisited();
if (gamedata->deferredsave)
G_SaveGameData();
} }
/*-------------------------------------------------- /*--------------------------------------------------
@ -1084,8 +1082,11 @@ void K_ResetCeremony(void)
} }
} }
// Save before playing the noise // Update visitation.
G_SaveGameData(); prevmap = gamemap-1;
G_UpdateVisited();
// will subsequently save in P_LoadLevel
} }
/*-------------------------------------------------- /*--------------------------------------------------

View file

@ -1034,7 +1034,7 @@ static void M_PrecacheLevelLocks(void)
&& mapheaderinfo[map]) && mapheaderinfo[map])
{ {
if (mapheaderinfo[map]->cache_maplock != MAXUNLOCKABLES) if (mapheaderinfo[map]->cache_maplock != MAXUNLOCKABLES)
CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_MAPs associated with Level %s\n", i, mapheaderinfo[map]->lumpname); CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_MAPs associated with Level %s\n", i+1, mapheaderinfo[map]->lumpname);
mapheaderinfo[map]->cache_maplock = i; mapheaderinfo[map]->cache_maplock = i;
} }
break; break;
@ -1115,11 +1115,17 @@ static void M_PrecacheLevelLocks(void)
break; break;
} }
if (j == mapheaderinfo[map]->musname_size) if (j == mapheaderinfo[map]->musname_size)
CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_ALTMUSICs associated with Level %s\n", i, mapheaderinfo[map]->lumpname); CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_ALTMUSICs associated with Level %s\n", i+1, mapheaderinfo[map]->lumpname);
}
else
{
CONS_Alert(CONS_ERROR, "Unlockable %u: Invalid levelname %s for SECRET_ALTMUSIC\n", i+1, unlockables[i].stringVar);
} }
if (tempstr == NULL) if (tempstr == NULL)
tempstr = va("INVALID MUSIC UNLOCK %u", i); {
tempstr = va("INVALID MUSIC UNLOCK %u", i+1);
}
strlcpy(unlockables[i].name, tempstr, sizeof (unlockables[i].name)); strlcpy(unlockables[i].name, tempstr, sizeof (unlockables[i].name));
@ -1132,7 +1138,7 @@ static void M_PrecacheLevelLocks(void)
if (cup) if (cup)
{ {
if (cup->cache_cuplock != MAXUNLOCKABLES) if (cup->cache_cuplock != MAXUNLOCKABLES)
CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_CUPs associated with Cup %s\n", i, cup->name); CONS_Alert(CONS_ERROR, "Unlockable %u: Too many SECRET_CUPs associated with Cup %s\n", i+1, cup->name);
cup->cache_cuplock = i; cup->cache_cuplock = i;
break; break;
} }
@ -1607,7 +1613,7 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
return (grandprixinfo.gamespeed >= cn->requirement); return (grandprixinfo.gamespeed >= cn->requirement);
case UCRP_PODIUMCUP: case UCRP_PODIUMCUP:
if (grandprixinfo.gp == false || K_PodiumRanking() == false) if (grandprixinfo.gp == false || K_PodiumSequence() == false)
return false; return false;
if (grandprixinfo.cup == NULL if (grandprixinfo.cup == NULL
|| ( || (
@ -1625,11 +1631,11 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
case UCRP_PODIUMEMERALD: case UCRP_PODIUMEMERALD:
case UCRP_PODIUMPRIZE: case UCRP_PODIUMPRIZE:
return (grandprixinfo.gp == true return (grandprixinfo.gp == true
&& K_PodiumRanking() == true && K_PodiumSequence() == true
&& grandprixinfo.rank.specialWon == true); && grandprixinfo.rank.specialWon == true);
case UCRP_PODIUMNOCONTINUES: case UCRP_PODIUMNOCONTINUES:
return (grandprixinfo.gp == true return (grandprixinfo.gp == true
&& K_PodiumRanking() == true && K_PodiumSequence() == true
&& grandprixinfo.rank.continuesUsed == 0); && grandprixinfo.rank.continuesUsed == 0);
case UCRP_FINISHCOOL: case UCRP_FINISHCOOL:
@ -1811,6 +1817,16 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
case UCRP_TRACKHAZARD: case UCRP_TRACKHAZARD:
{ {
if (!(gametyperules & GTR_CIRCUIT))
{
// Prison Break/Versus
if (!player->exiting && cn->requirement == 0)
return false;
return (((player->roundconditions.hittrackhazard[0] & 1) == 1) == (cn->requirement == 1));
}
INT16 requiredlap = cn->extrainfo1; INT16 requiredlap = cn->extrainfo1;
if (requiredlap < 0) if (requiredlap < 0)
@ -2514,7 +2530,7 @@ static const char *M_GetConditionString(condition_t *cn)
if (cn->extrainfo2) if (cn->extrainfo2)
{ {
switch (cn->requirement) switch (cn->extrainfo1)
{ {
case GRADE_E: { completetype = "get grade E"; break; } case GRADE_E: { completetype = "get grade E"; break; }
case GRADE_D: { completetype = "get grade D"; break; } case GRADE_D: { completetype = "get grade D"; break; }
@ -2700,7 +2716,7 @@ static const char *M_GetConditionString(condition_t *cn)
case UCRP_TRACKHAZARD: case UCRP_TRACKHAZARD:
{ {
work = (cn->requirement == 1) ? "touch a track hazard" : "don't touch any track hazards"; work = (cn->requirement == 1) ? "touch a course hazard" : "don't touch any course hazards";
if (cn->extrainfo1 == -1) if (cn->extrainfo1 == -1)
return va("%s%s", work, (cn->requirement == 1) ? " on every lap" : ""); return va("%s%s", work, (cn->requirement == 1) ? " on every lap" : "");
if (cn->extrainfo1 == -2) if (cn->extrainfo1 == -2)
@ -2880,7 +2896,7 @@ char *M_BuildConditionSetString(UINT16 unlockid)
DESCRIPTIONWIDTH << FRACBITS, DESCRIPTIONWIDTH << FRACBITS,
FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT,
0, 0,
HU_FONT, TINY_FONT,
message message
); );
} }
@ -2989,7 +3005,7 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud, boolean doall)
} }
} }
if (!demo.playback && Playing() && (gamestate == GS_LEVEL || K_PodiumRanking() == true)) if (!demo.playback && Playing() && (gamestate == GS_LEVEL || K_PodiumSequence() == true))
{ {
for (i = 0; i <= splitscreen; i++) for (i = 0; i <= splitscreen; i++)
{ {

View file

@ -630,9 +630,17 @@ static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num)
} }
static void M_HandlePlayerFinalise(setup_player_t *p)
{
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
}
static void M_HandleCharAskChange(setup_player_t *p, UINT8 num) static void M_HandleCharAskChange(setup_player_t *p, UINT8 num)
{ {
if (cv_splitdevice.value) if (cv_splitdevice.value)
num = 0; num = 0;
@ -658,11 +666,7 @@ static void M_HandleCharAskChange(setup_player_t *p, UINT8 num)
{ {
// no changes // no changes
M_GetFollowerState(p); M_GetFollowerState(p);
p->mdepth = CSSTEP_READY; M_HandlePlayerFinalise(p);
p->delay = TICRATE;
S_StartSound(NULL, sfx_s3k4e);
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
} }
else else
{ {
@ -675,11 +679,70 @@ static void M_HandleCharAskChange(setup_player_t *p, UINT8 num)
} }
} }
boolean M_CharacterSelectForceInAction(void)
{
if (!Playing())
return false;
if (K_CanChangeRules(true) == false)
return false;
return (cv_forceskin.value != -1);
}
static void M_HandleBackToChars(setup_player_t *p)
{
boolean forceskin = M_CharacterSelectForceInAction();
if (forceskin
|| setup_chargrid[p->gridx][p->gridy].numskins == 1)
{
p->mdepth = CSSTEP_CHARS; // Skip clones menu
}
else
{
p->mdepth = CSSTEP_ALTS;
}
}
static boolean M_HandleBeginningColors(setup_player_t *p)
{
p->mdepth = CSSTEP_COLORS;
M_NewPlayerColors(p);
if (p->colors.listLen != 1)
return true;
p->color = p->colors.list[0];
return false;
}
static void M_HandleBeginningFollowers(setup_player_t *p)
{
if (setup_numfollowercategories == 0)
{
p->followern = -1;
M_HandlePlayerFinalise(p);
}
else
{
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
S_StartSound(NULL, sfx_s3k63);
}
}
static void M_HandleBeginningColorsOrFollowers(setup_player_t *p)
{
if (M_HandleBeginningColors(p))
S_StartSound(NULL, sfx_s3k63);
else
M_HandleBeginningFollowers(p);
}
static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num) static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
{ {
UINT8 numclones; UINT8 numclones;
INT32 skin; INT32 skin;
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); boolean forceskin = M_CharacterSelectForceInAction();
if (cv_splitdevice.value) if (cv_splitdevice.value)
num = 0; num = 0;
@ -748,9 +811,7 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
} }
else else
{ {
p->mdepth = CSSTEP_COLORS; M_HandleBeginningColorsOrFollowers(p);
M_NewPlayerColors(p);
S_StartSound(NULL, sfx_s3k63);
} }
} }
else else
@ -764,15 +825,13 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
{ {
if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins) if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins)
{ {
p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page. M_HandleBeginningColorsOrFollowers(p);
M_NewPlayerColors(p);
} }
else else
{ {
p->mdepth = CSSTEP_ALTS; p->mdepth = CSSTEP_ALTS;
S_StartSound(NULL, sfx_s3k63);
} }
S_StartSound(NULL, sfx_s3k63);
} }
} }
@ -840,33 +899,10 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
S_StartSound(NULL, sfx_s3kc3s); S_StartSound(NULL, sfx_s3kc3s);
} }
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{ {
p->mdepth = CSSTEP_COLORS; M_HandleBeginningColorsOrFollowers(p);
M_NewPlayerColors(p); M_SetMenuDelay(num);
if (p->colors.listLen == 1)
{
p->color = p->colors.list[0];
if (setup_numfollowercategories == 0)
{
p->followern = -1;
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
}
else
{
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
S_StartSound(NULL, sfx_s3k63);
M_SetMenuDelay(num);
}
}
else
{
S_StartSound(NULL, sfx_s3k63);
M_SetMenuDelay(num);
}
} }
else if (M_MenuBackPressed(num)) else if (M_MenuBackPressed(num))
{ {
@ -886,8 +922,6 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
static void M_HandleColorRotate(setup_player_t *p, UINT8 num) static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
{ {
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1);
if (cv_splitdevice.value) if (cv_splitdevice.value)
num = 0; num = 0;
@ -908,32 +942,13 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{ {
if (setup_numfollowercategories == 0) M_HandleBeginningFollowers(p);
{ M_SetMenuDelay(num);
p->followern = -1;
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
}
else
{
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
S_StartSound(NULL, sfx_s3k63);
M_SetMenuDelay(num);
}
} }
else if (M_MenuBackPressed(num)) else if (M_MenuBackPressed(num))
{ {
if (forceskin M_HandleBackToChars(p);
|| setup_chargrid[p->gridx][p->gridy].numskins == 1)
{
p->mdepth = CSSTEP_CHARS; // Skip clones menu
}
else
{
p->mdepth = CSSTEP_ALTS;
}
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(num); M_SetMenuDelay(num);
} }
@ -1009,50 +1024,67 @@ static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num)
if (p->followercategory < 0) if (p->followercategory < 0)
{ {
p->followern = -1; p->followern = -1;
p->mdepth = CSSTEP_READY; M_HandlePlayerFinalise(p);
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
} }
else else
{ {
if (p->followern < 0 || followers[p->followern].category != p->followercategory) if (p->followern < 0
|| followers[p->followern].category != setup_followercategories[p->followercategory][1])
{ {
p->followern = 0; p->followern = 0;
while (p->followern < numfollowers while (p->followern < numfollowers)
&& (followers[p->followern].category != setup_followercategories[p->followercategory][1] {
|| !K_FollowerUsable(p->followern))) if (followers[p->followern].category == setup_followercategories[p->followercategory][1]
&& K_FollowerUsable(p->followern))
break;
p->followern++; p->followern++;
}
} }
if (p->followern >= numfollowers) if (p->followern < numfollowers)
{
p->followern = -1;
S_StartSound(NULL, sfx_s3kb2);
}
else
{ {
M_GetFollowerState(p); M_GetFollowerState(p);
p->mdepth = CSSTEP_FOLLOWER; p->mdepth = CSSTEP_FOLLOWER;
S_StartSound(NULL, sfx_s3k63); S_StartSound(NULL, sfx_s3k63);
} }
else
{
p->followern = -1;
S_StartSound(NULL, sfx_s3kb2);
}
} }
M_SetMenuDelay(num); M_SetMenuDelay(num);
} }
else if (M_MenuBackPressed(num)) else if (M_MenuBackPressed(num))
{ {
p->mdepth = CSSTEP_COLORS; if (!M_HandleBeginningColors(p))
M_NewPlayerColors(p); M_HandleBackToChars(p);
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(num); M_SetMenuDelay(num);
} }
else if (M_MenuExtraPressed(num)) else if (M_MenuExtraPressed(num))
{ {
if (p->followercategory >= 0 || p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories) INT16 i = -1;
p->followercategory = -1; if (p->followercategory < 0
else && p->followern >= 0
p->followercategory = followers[p->followern].category; && p->followern < numfollowers
&& followers[p->followern].category < numfollowercategories)
{
for (i = 0; i < setup_numfollowercategories; i++)
{
if (followers[p->followern].category != setup_followercategories[i][1])
continue;
break;
}
if (i >= setup_numfollowercategories)
i = -1;
}
p->followercategory = i;
p->rotate = CSROTATETICS; p->rotate = CSROTATETICS;
p->hitlag = true; p->hitlag = true;
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
@ -1114,10 +1146,7 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
} }
else else
{ {
p->mdepth = CSSTEP_READY; M_HandlePlayerFinalise(p);
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
} }
M_SetMenuDelay(num); M_SetMenuDelay(num);
@ -1163,10 +1192,7 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/) if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{ {
p->mdepth = CSSTEP_READY; M_HandlePlayerFinalise(p);
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
M_SetMenuDelay(num); M_SetMenuDelay(num);
} }
else if (M_MenuBackPressed(num)) else if (M_MenuBackPressed(num))
@ -1194,7 +1220,7 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
boolean M_CharacterSelectHandler(INT32 choice) boolean M_CharacterSelectHandler(INT32 choice)
{ {
INT32 i; INT32 i;
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1); boolean forceskin = M_CharacterSelectForceInAction();
(void)choice; (void)choice;
@ -1256,8 +1282,9 @@ boolean M_CharacterSelectHandler(INT32 choice)
default: // Unready default: // Unready
if (M_MenuBackPressed(i)) if (M_MenuBackPressed(i))
{ {
p->mdepth = CSSTEP_COLORS; if (!M_HandleBeginningColors(p))
M_NewPlayerColors(p); M_HandleBackToChars(p);
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(i); M_SetMenuDelay(i);
} }

View file

@ -2986,10 +2986,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
} }
} }
else if (!(inflictor && inflictor->player) else if (!(inflictor && inflictor->player)
&& player->laps <= numlaps && !(player->exiting || player->laps > numlaps)
&& damagetype != DMG_DEATHPIT) && damagetype != DMG_DEATHPIT)
{ {
// laps will never increment outside of GTR_CIRCUIT, so this is still fine
const UINT8 requiredbit = 1<<(player->laps & 7); const UINT8 requiredbit = 1<<(player->laps & 7);
if (!(player->roundconditions.hittrackhazard[player->laps/8] & requiredbit)) if (!(player->roundconditions.hittrackhazard[player->laps/8] & requiredbit))
{ {
player->roundconditions.hittrackhazard[player->laps/8] |= requiredbit; player->roundconditions.hittrackhazard[player->laps/8] |= requiredbit;

View file

@ -7600,7 +7600,13 @@ static void P_InitLevelSettings(void)
if (K_PodiumSequence() == true) if (K_PodiumSequence() == true)
{ {
; // NOP // Okay, now that everything preceding is handled, set the position.
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].position = K_GetPodiumPosition(&players[i]);
}
// We don't touch the gamespeed, though!
} }
else if (grandprixinfo.gp == true) else if (grandprixinfo.gp == true)
{ {

View file

@ -1926,6 +1926,13 @@ static void K_HandleLapIncrement(player_t *player)
ClearFakePlayerSkin(player); ClearFakePlayerSkin(player);
S_StartSound(player->mo, sfx_s3k8a); S_StartSound(player->mo, sfx_s3k8a);
P_MoveOrigin(player->mo, player->mo->old_x, player->mo->old_y, player->mo->z); P_MoveOrigin(player->mo, player->mo->old_x, player->mo->old_y, player->mo->z);
if (player->roundconditions.faulted == false)
{
player->roundconditions.faulted = true;
player->roundconditions.checkthisframe = true;
}
return; return;
} }