Disable continues outside of no-save/Ultimate by default, but allow SOC to re-enable them globally.

Please look at the merge request description for a full explanation, since I know the vanilla team has been hashing this out and I don't want to add fuel to the fire without at least presenting a solid case.
This commit is contained in:
toaster 2020-03-26 20:16:44 +00:00
parent e471134746
commit da86c17ee1
10 changed files with 90 additions and 31 deletions

View File

@ -4122,6 +4122,10 @@ static void readmaincfg(MYFILE *f)
{ {
maxXtraLife = (UINT8)get_number(word2); maxXtraLife = (UINT8)get_number(word2);
} }
else if (fastcmp(word, "USECONTINUES"))
{
useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "GAMEDATA")) else if (fastcmp(word, "GAMEDATA"))
{ {

View File

@ -575,6 +575,8 @@ extern UINT8 creditscutscene;
extern UINT8 use1upSound; extern UINT8 use1upSound;
extern UINT8 maxXtraLife; // Max extra lives from rings extern UINT8 maxXtraLife; // Max extra lives from rings
extern UINT8 useContinues;
#define continuesInSession (!multiplayer && (useContinues || ultimatemode || !(cursaveslot > 0)))
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations

View File

@ -3618,7 +3618,7 @@ void F_StartContinue(void)
{ {
I_Assert(!netgame && !multiplayer); I_Assert(!netgame && !multiplayer);
if (players[consoleplayer].continues <= 0) if (continuesInSession && players[consoleplayer].continues <= 0)
{ {
Command_ExitGame_f(); Command_ExitGame_f();
return; return;
@ -3725,7 +3725,9 @@ void F_ContinueDrawer(void)
} }
// Draw the continue markers! Show continues. // Draw the continue markers! Show continues.
if (ncontinues > 10) if (!continuesInSession)
;
else if (ncontinues > 10)
{ {
if (!(continuetime & 1) || continuetime > 17) if (!(continuetime & 1) || continuetime > 17)
V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);

View File

@ -219,6 +219,7 @@ UINT8 ammoremovaltics = 2*TICRATE;
UINT8 use1upSound = 0; UINT8 use1upSound = 0;
UINT8 maxXtraLife = 2; // Max extra lives from rings UINT8 maxXtraLife = 2; // Max extra lives from rings
UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes
UINT8 introtoplay; UINT8 introtoplay;
UINT8 creditscutscene; UINT8 creditscutscene;
@ -3859,7 +3860,8 @@ static void G_DoContinued(void)
I_Assert(!netgame && !multiplayer); I_Assert(!netgame && !multiplayer);
I_Assert(pl->continues > 0); I_Assert(pl->continues > 0);
pl->continues--; if (pl->continues)
pl->continues--;
// Reset score // Reset score
pl->score = 0; pl->score = 0;

View File

@ -934,6 +934,12 @@ void Command_Setcontinues_f(void)
REQUIRE_NOULTIMATE; REQUIRE_NOULTIMATE;
REQUIRE_PANDORA; REQUIRE_PANDORA;
if (!continuesInSession)
{
CONS_Printf(M_GetText("This session does not use continues.\n"));
return;
}
if (COM_Argc() > 1) if (COM_Argc() > 1)
{ {
INT32 numcontinues = atoi(COM_Argv(1)); INT32 numcontinues = atoi(COM_Argv(1));

View File

@ -6724,6 +6724,7 @@ static void M_PandorasBox(INT32 choice)
else else
CV_StealthSetValue(&cv_dummylives, max(players[consoleplayer].lives, 1)); CV_StealthSetValue(&cv_dummylives, max(players[consoleplayer].lives, 1));
CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues); CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues);
SR_PandorasBox[3].status = (continuesInSession) ? (IT_STRING | IT_CVAR) : (IT_GRAYEDOUT);
SR_PandorasBox[6].status = (players[consoleplayer].charflags & SF_SUPER) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL); SR_PandorasBox[6].status = (players[consoleplayer].charflags & SF_SUPER) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL);
SR_PandorasBox[7].status = (emeralds == ((EMERALD7)*2)-1) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL); SR_PandorasBox[7].status = (emeralds == ((EMERALD7)*2)-1) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL);
M_SetupNextMenu(&SR_PandoraDef); M_SetupNextMenu(&SR_PandoraDef);
@ -6740,7 +6741,7 @@ static boolean M_ExitPandorasBox(void)
} }
if (cv_dummylives.value != players[consoleplayer].lives) if (cv_dummylives.value != players[consoleplayer].lives)
COM_ImmedExecute(va("setlives %d", cv_dummylives.value)); COM_ImmedExecute(va("setlives %d", cv_dummylives.value));
if (cv_dummycontinues.value != players[consoleplayer].continues) if (continuesInSession && cv_dummycontinues.value != players[consoleplayer].continues)
COM_ImmedExecute(va("setcontinues %d", cv_dummycontinues.value)); COM_ImmedExecute(va("setcontinues %d", cv_dummycontinues.value));
return true; return true;
} }
@ -8251,9 +8252,19 @@ static void M_DrawLoadGameData(void)
V_DrawRightAlignedThinString(x + 79, y, V_YELLOWMAP, savegameinfo[savetodraw].levelname); V_DrawRightAlignedThinString(x + 79, y, V_YELLOWMAP, savegameinfo[savetodraw].levelname);
} }
if ((savegameinfo[savetodraw].lives == -42) if (savegameinfo[savetodraw].lives == -42)
|| (savegameinfo[savetodraw].lives == -666)) {
if (!useContinues)
V_DrawRightAlignedThinString(x + 80, y+1+60+16, V_GRAYMAP, "00000000");
continue; continue;
}
if (savegameinfo[savetodraw].lives == -666)
{
if (!useContinues)
V_DrawRightAlignedThinString(x + 80, y+1+60+16, V_REDMAP, "????????");
continue;
}
y += 64; y += 64;
@ -8270,7 +8281,7 @@ static void M_DrawLoadGameData(void)
y -= 4; y -= 4;
// character heads, lives, and continues // character heads, lives, and continues/score
{ {
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
@ -8321,10 +8332,14 @@ skipbot:
skipsign: skipsign:
y += 16; y += 16;
tempx = x + 10; tempx = x;
if (savegameinfo[savetodraw].lives != INFLIVES if (useContinues)
&& savegameinfo[savetodraw].lives > 9) {
tempx -= 4; tempx += 10;
if (savegameinfo[savetodraw].lives != INFLIVES
&& savegameinfo[savetodraw].lives > 9)
tempx -= 4;
}
if (!charskin) // shut up compiler if (!charskin) // shut up compiler
goto skiplife; goto skiplife;
@ -8354,22 +8369,45 @@ skiplife:
else else
V_DrawString(tempx, y, 0, va("%d", savegameinfo[savetodraw].lives)); V_DrawString(tempx, y, 0, va("%d", savegameinfo[savetodraw].lives));
tempx = x + 47; if (!useContinues)
if (savegameinfo[savetodraw].continues > 9)
tempx -= 4;
// continues
if (savegameinfo[savetodraw].continues > 0)
{ {
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH)); INT32 workingscorenum = savegameinfo[savetodraw].continuescore;
V_DrawScaledPatch(tempx + 9, y + 2, 0, patch); char workingscorestr[11] = " 000000000\0";
V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continues)); SINT8 j = 9;
// Change the above two lines if MAXSCORE ever changes from 8 digits long.
workingscorestr[0] = '\x86'; // done here instead of in initialiser 'cuz compiler complains
if (!workingscorenum)
j--; // just so ONE digit is not greyed out
else
{
while (workingscorenum)
{
workingscorestr[j--] = '0' + (workingscorenum % 10);
workingscorenum /= 10;
}
}
workingscorestr[j] = (savegameinfo[savetodraw].continuescore == MAXSCORE) ? '\x83' : '\x80';
V_DrawRightAlignedThinString(x + 80, y+1, 0, workingscorestr);
} }
else else
{ {
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH)); tempx = x + 47;
V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH)); if (savegameinfo[savetodraw].continuescore > 9)
V_DrawString(tempx + 16, y, V_GRAYMAP, "0"); tempx -= 4;
// continues
if (savegameinfo[savetodraw].continuescore > 0)
{
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH));
V_DrawScaledPatch(tempx + 9, y + 2, 0, patch);
V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continuescore));
}
else
{
V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH));
V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH));
V_DrawString(tempx + 16, y, V_GRAYMAP, "0");
}
} }
} }
} }
@ -8502,9 +8540,11 @@ static void M_ReadSavegameInfo(UINT32 slot)
CHECKPOS CHECKPOS
savegameinfo[slot].lives = READSINT8(save_p); // lives savegameinfo[slot].lives = READSINT8(save_p); // lives
CHECKPOS CHECKPOS
(void)READINT32(save_p); // Score savegameinfo[slot].continuescore = READINT32(save_p); // score
CHECKPOS CHECKPOS
savegameinfo[slot].continues = READINT32(save_p); // continues fake = READINT32(save_p); // continues
if (useContinues)
savegameinfo[slot].continuescore = fake;
// File end marker check // File end marker check
CHECKPOS CHECKPOS

View File

@ -397,7 +397,7 @@ typedef struct
UINT8 numemeralds; UINT8 numemeralds;
UINT8 numgameovers; UINT8 numgameovers;
INT32 lives; INT32 lives;
INT32 continues; INT32 continuescore;
INT32 gamemap; INT32 gamemap;
} saveinfo_t; } saveinfo_t;

View File

@ -633,7 +633,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (ALL7EMERALDS(emeralds)) // Got all 7 if (ALL7EMERALDS(emeralds)) // Got all 7
{ {
if (!(netgame || multiplayer)) if (continuesInSession)
{ {
player->continues += 1; player->continues += 1;
player->gotcontinue = true; player->gotcontinue = true;
@ -643,7 +643,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(toucher, sfx_chchng); S_StartSound(toucher, sfx_chchng);
} }
else else
{
P_GiveCoopLives(player, 1, true); // if continues are disabled, a life is a reasonable substitute
S_StartSound(toucher, sfx_chchng); S_StartSound(toucher, sfx_chchng);
}
} }
else else
{ {

View File

@ -1388,7 +1388,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
// Continues are worthless in netgames. // Continues are worthless in netgames.
// If that stops being the case uncomment this. // If that stops being the case uncomment this.
/* if (!ultimatemode && players[i].marescore > 50000 /* if (!ultimatemode && continuesInSession && players[i].marescore > 50000
&& oldscore < 50000) && oldscore < 50000)
{ {
players[i].continues += 1; players[i].continues += 1;
@ -1408,7 +1408,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
else else
player->marescore = MAXSCORE; player->marescore = MAXSCORE;
if (!ultimatemode && !(netgame || multiplayer) && G_IsSpecialStage(gamemap) if (!ultimatemode && continuesInSession && G_IsSpecialStage(gamemap)
&& player->marescore >= 50000 && oldscore < 50000) && player->marescore >= 50000 && oldscore < 50000)
{ {
player->continues += 1; player->continues += 1;
@ -9539,7 +9539,7 @@ static void P_DeathThink(player_t *player)
// continue logic // continue logic
if (!(netgame || multiplayer) && player->lives <= 0) if (!(netgame || multiplayer) && player->lives <= 0)
{ {
if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0) if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0))
G_UseContinue(); G_UseContinue();
else if (player->deadtimer >= gameovertics) else if (player->deadtimer >= gameovertics)
G_UseContinue(); // Even if we don't have one this handles ending the game G_UseContinue(); // Even if we don't have one this handles ending the game

View File

@ -564,7 +564,7 @@ dontdrawbg:
V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score); V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score);
// Draw continues! // Draw continues!
if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay if (continuesInSession /* && (data.spec.continues & 0x80) */) // Always draw when continues are a thing
{ {
UINT8 continues = data.spec.continues & 0x7F; UINT8 continues = data.spec.continues & 0x7F;