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_ListWADS_f(void);
static void Command_ListDoomednums_f(void);
static void Command_cxdiag_f(void);
static void Command_RunSOC(void);
static void Command_Pause(void);
@ -396,6 +397,7 @@ void D_RegisterServerCommands(void)
COM_AddCommand("addfile", Command_Addfile);
COM_AddDebugCommand("listwad", Command_ListWADS_f);
COM_AddDebugCommand("listmapthings", Command_ListDoomednums_f);
COM_AddDebugCommand("cxdiag", Command_cxdiag_f);
COM_AddCommand("runsoc", Command_RunSOC);
COM_AddCommand("pause", Command_Pause);
@ -4704,6 +4706,226 @@ static void Command_ListDoomednums_f(void)
#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
// =========================================================================

View file

@ -1408,7 +1408,7 @@ void readlevelheader(MYFILE *f, char * name)
do {
if (j >= MAXDESTRUCTIBLES)
break;
mapheaderinfo[num]->destroyforchallenge[j] = get_mobjtype(word2);
mapheaderinfo[num]->destroyforchallenge[j] = get_mobjtype(tmp);
j++;
} while ((tmp = strtok(NULL,",")) != NULL);
@ -2773,9 +2773,9 @@ static void readcondition(UINT16 set, UINT32 id, char *word2)
if (fastcmp(params[1], "NORMAL"))
;
else if (fastcmp(params[1], "HARD"))
x1 = KARTSPEED_HARD;
re = KARTSPEED_HARD;
else if (fastcmp(params[1], "MASTER"))
x1 = KARTGP_MASTER;
re = KARTGP_MASTER;
else
{
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);
}
// 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);
if (versionMinor >= 4)

View file

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

View file

@ -2272,7 +2272,7 @@ void M_DrawCharacterSelect(void)
INT16 quadx, quady;
INT16 skin;
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)
{
@ -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))
{
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)
{
@ -989,12 +993,6 @@ void K_FinishCeremony(void)
}
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
G_SaveGameData();
// Update visitation.
prevmap = gamemap-1;
G_UpdateVisited();
// will subsequently save in P_LoadLevel
}
/*--------------------------------------------------

View file

@ -1034,7 +1034,7 @@ static void M_PrecacheLevelLocks(void)
&& mapheaderinfo[map])
{
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;
}
break;
@ -1115,11 +1115,17 @@ static void M_PrecacheLevelLocks(void)
break;
}
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)
tempstr = va("INVALID MUSIC UNLOCK %u", i);
{
tempstr = va("INVALID MUSIC UNLOCK %u", i+1);
}
strlcpy(unlockables[i].name, tempstr, sizeof (unlockables[i].name));
@ -1132,7 +1138,7 @@ static void M_PrecacheLevelLocks(void)
if (cup)
{
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;
break;
}
@ -1607,7 +1613,7 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
return (grandprixinfo.gamespeed >= cn->requirement);
case UCRP_PODIUMCUP:
if (grandprixinfo.gp == false || K_PodiumRanking() == false)
if (grandprixinfo.gp == false || K_PodiumSequence() == false)
return false;
if (grandprixinfo.cup == NULL
|| (
@ -1625,11 +1631,11 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
case UCRP_PODIUMEMERALD:
case UCRP_PODIUMPRIZE:
return (grandprixinfo.gp == true
&& K_PodiumRanking() == true
&& K_PodiumSequence() == true
&& grandprixinfo.rank.specialWon == true);
case UCRP_PODIUMNOCONTINUES:
return (grandprixinfo.gp == true
&& K_PodiumRanking() == true
&& K_PodiumSequence() == true
&& grandprixinfo.rank.continuesUsed == 0);
case UCRP_FINISHCOOL:
@ -1811,6 +1817,16 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
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;
if (requiredlap < 0)
@ -2514,7 +2530,7 @@ static const char *M_GetConditionString(condition_t *cn)
if (cn->extrainfo2)
{
switch (cn->requirement)
switch (cn->extrainfo1)
{
case GRADE_E: { completetype = "get grade E"; break; }
case GRADE_D: { completetype = "get grade D"; break; }
@ -2700,7 +2716,7 @@ static const char *M_GetConditionString(condition_t *cn)
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)
return va("%s%s", work, (cn->requirement == 1) ? " on every lap" : "");
if (cn->extrainfo1 == -2)
@ -2880,7 +2896,7 @@ char *M_BuildConditionSetString(UINT16 unlockid)
DESCRIPTIONWIDTH << FRACBITS,
FRACUNIT, FRACUNIT, FRACUNIT,
0,
HU_FONT,
TINY_FONT,
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++)
{

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)
{
if (cv_splitdevice.value)
num = 0;
@ -658,11 +666,7 @@ static void M_HandleCharAskChange(setup_player_t *p, UINT8 num)
{
// no changes
M_GetFollowerState(p);
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
S_StartSound(NULL, sfx_s3k4e);
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
M_HandlePlayerFinalise(p);
}
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)
{
UINT8 numclones;
INT32 skin;
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1);
boolean forceskin = M_CharacterSelectForceInAction();
if (cv_splitdevice.value)
num = 0;
@ -748,9 +811,7 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
}
else
{
p->mdepth = CSSTEP_COLORS;
M_NewPlayerColors(p);
S_StartSound(NULL, sfx_s3k63);
M_HandleBeginningColorsOrFollowers(p);
}
}
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)
{
p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page.
M_NewPlayerColors(p);
M_HandleBeginningColorsOrFollowers(p);
}
else
{
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);
}
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{
p->mdepth = CSSTEP_COLORS;
M_NewPlayerColors(p);
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);
}
M_HandleBeginningColorsOrFollowers(p);
M_SetMenuDelay(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)
{
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1);
if (cv_splitdevice.value)
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 (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);
}
M_HandleBeginningFollowers(p);
M_SetMenuDelay(num);
}
else if (M_MenuBackPressed(num))
{
if (forceskin
|| setup_chargrid[p->gridx][p->gridy].numskins == 1)
{
p->mdepth = CSSTEP_CHARS; // Skip clones menu
}
else
{
p->mdepth = CSSTEP_ALTS;
}
M_HandleBackToChars(p);
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(num);
}
@ -1009,50 +1024,67 @@ static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num)
if (p->followercategory < 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);
M_HandlePlayerFinalise(p);
}
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;
while (p->followern < numfollowers
&& (followers[p->followern].category != setup_followercategories[p->followercategory][1]
|| !K_FollowerUsable(p->followern)))
while (p->followern < numfollowers)
{
if (followers[p->followern].category == setup_followercategories[p->followercategory][1]
&& K_FollowerUsable(p->followern))
break;
p->followern++;
}
}
if (p->followern >= numfollowers)
{
p->followern = -1;
S_StartSound(NULL, sfx_s3kb2);
}
else
if (p->followern < numfollowers)
{
M_GetFollowerState(p);
p->mdepth = CSSTEP_FOLLOWER;
S_StartSound(NULL, sfx_s3k63);
}
else
{
p->followern = -1;
S_StartSound(NULL, sfx_s3kb2);
}
}
M_SetMenuDelay(num);
}
else if (M_MenuBackPressed(num))
{
p->mdepth = CSSTEP_COLORS;
M_NewPlayerColors(p);
if (!M_HandleBeginningColors(p))
M_HandleBackToChars(p);
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(num);
}
else if (M_MenuExtraPressed(num))
{
if (p->followercategory >= 0 || p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories)
p->followercategory = -1;
else
p->followercategory = followers[p->followern].category;
INT16 i = -1;
if (p->followercategory < 0
&& p->followern >= 0
&& 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->hitlag = true;
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
@ -1114,10 +1146,7 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
}
else
{
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
M_HandlePlayerFinalise(p);
}
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)*/)
{
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
S_StartSound(NULL, sfx_s3k4e);
M_HandlePlayerFinalise(p);
M_SetMenuDelay(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)
{
INT32 i;
boolean forceskin = (Playing() && K_CanChangeRules(true) == true) && (cv_forceskin.value != -1);
boolean forceskin = M_CharacterSelectForceInAction();
(void)choice;
@ -1256,8 +1282,9 @@ boolean M_CharacterSelectHandler(INT32 choice)
default: // Unready
if (M_MenuBackPressed(i))
{
p->mdepth = CSSTEP_COLORS;
M_NewPlayerColors(p);
if (!M_HandleBeginningColors(p))
M_HandleBackToChars(p);
S_StartSound(NULL, sfx_s3k5b);
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)
&& player->laps <= numlaps
&& !(player->exiting || player->laps > numlaps)
&& damagetype != DMG_DEATHPIT)
{
// laps will never increment outside of GTR_CIRCUIT, so this is still fine
const UINT8 requiredbit = 1<<(player->laps & 7);
if (!(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)
{
; // 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)
{

View file

@ -1926,6 +1926,13 @@ static void K_HandleLapIncrement(player_t *player)
ClearFakePlayerSkin(player);
S_StartSound(player->mo, sfx_s3k8a);
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;
}