* In-game timer option! Doesn't tick in intermission or in lag, only when a frame is actually run. Realtime option remains default.

* Tweak retry behaviour to restart timer and not subtract life if you're on the first level and haven't hit a checkpoint yet.
This commit is contained in:
toaster 2020-05-15 16:33:20 +01:00
parent 1e3e9c81ac
commit 9686ad2d70
6 changed files with 39 additions and 7 deletions

View File

@ -9933,9 +9933,10 @@ struct {
{"TC_DASHMODE",TC_DASHMODE}, {"TC_DASHMODE",TC_DASHMODE},
// marathonmode flags // marathonmode flags
//{"MA_INIT",MA_INIT}, -- should never see this {"MA_INIT",MA_INIT},
{"MA_RUNNING",MA_RUNNING}, {"MA_RUNNING",MA_RUNNING},
{"MA_NOCUTSCENES",MA_NOCUTSCENES}, {"MA_NOCUTSCENES",MA_NOCUTSCENES},
{"MA_INGAME",MA_INGAME},
{NULL,0} {NULL,0}
}; };

View File

@ -52,7 +52,8 @@ typedef enum
{ {
MA_RUNNING = 1, // In action MA_RUNNING = 1, // In action
MA_INIT = 1<<1, // Initialisation MA_INIT = 1<<1, // Initialisation
MA_NOCUTSCENES = 1<<2 // No cutscenes MA_NOCUTSCENES = 1<<2, // No cutscenes
MA_INGAME = 1<<3 // Timer ignores loads
} marathonmode_t; } marathonmode_t;
extern marathonmode_t marathonmode; extern marathonmode_t marathonmode;

View File

@ -2167,6 +2167,10 @@ void G_Ticker(boolean run)
UINT32 i; UINT32 i;
INT32 buf; INT32 buf;
// see also SCR_DisplayMarathonInfo
if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL)
marathontime++;
P_MapStart(); P_MapStart();
// do player reborns if needed // do player reborns if needed
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
@ -2183,8 +2187,13 @@ void G_Ticker(boolean run)
} }
else else
{ {
// Costs a life to retry ... unless the player in question is dead already. // Costs a life to retry ... unless the player in question is dead already, or you haven't even touched the first starpost in marathon run.
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) if (marathonmode && gamemap == spmarathon_start && !players[consoleplayer].starposttime)
{
marathonmode |= MA_INIT;
marathontime = 0;
}
else if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES)
players[consoleplayer].lives -= 1; players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer); G_DoReborn(consoleplayer);

View File

@ -485,9 +485,11 @@ static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, contlimit
static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL}; static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL};
CV_PossibleValue_t marathon_cons_t[] = {{0, "Standard"}, {1, "Live Event Backup"}, {2, "Ultimate"}, {0, NULL}}; CV_PossibleValue_t marathon_cons_t[] = {{0, "Standard"}, {1, "Live Event Backup"}, {2, "Ultimate"}, {0, NULL}};
CV_PossibleValue_t loadless_cons_t[] = {{0, "Realtime"}, {1, "In-game"}, {0, NULL}};
consvar_t cv_dummymarathon = {"dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_dummymarathon = {"dummymarathon", "Standard", CV_HIDEN, marathon_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummycutscenes = {"dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_dummycutscenes = {"dummycutscenes", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummyloadless = {"dummyloadless", "Realtime", CV_HIDEN, loadless_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// ========================================================================== // ==========================================================================
// ORGANIZATION START. // ORGANIZATION START.
@ -919,8 +921,9 @@ enum
// Marathon // Marathon
static menuitem_t SP_MarathonMenu[] = static menuitem_t SP_MarathonMenu[] =
{ {
{IT_STRING|IT_KEYHANDLER, NULL, "Character", M_HandleMarathonChoosePlayer, 100}, {IT_STRING|IT_KEYHANDLER, NULL, "Character", M_HandleMarathonChoosePlayer, 90},
{IT_STRING|IT_CVAR, NULL, "Category", &cv_dummymarathon, 110}, {IT_STRING|IT_CVAR, NULL, "Category", &cv_dummymarathon, 100},
{IT_STRING|IT_CVAR, NULL, "Timer", &cv_dummyloadless, 110},
{IT_STRING|IT_CVAR, NULL, "Cutscenes", &cv_dummycutscenes, 120}, {IT_STRING|IT_CVAR, NULL, "Cutscenes", &cv_dummycutscenes, 120},
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartMarathon, 130}, {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartMarathon, 130},
}; };
@ -929,6 +932,7 @@ enum
{ {
marathonplayer, marathonplayer,
marathonultimate, marathonultimate,
marathonloadless,
marathoncutscenes, marathoncutscenes,
marathonstart marathonstart
}; };
@ -3909,6 +3913,7 @@ void M_Init(void)
CV_RegisterVar(&cv_dummycontinues); CV_RegisterVar(&cv_dummycontinues);
CV_RegisterVar(&cv_dummymares); CV_RegisterVar(&cv_dummymares);
CV_RegisterVar(&cv_dummymarathon); CV_RegisterVar(&cv_dummymarathon);
CV_RegisterVar(&cv_dummyloadless);
CV_RegisterVar(&cv_dummycutscenes); CV_RegisterVar(&cv_dummycutscenes);
quitmsg[QUITMSG] = M_GetText("Eggman's tied explosives\nto your girlfriend, and\nwill activate them if\nyou press the 'Y' key!\nPress 'N' to save her!\n\n(Press 'Y' to quit)"); quitmsg[QUITMSG] = M_GetText("Eggman's tied explosives\nto your girlfriend, and\nwill activate them if\nyou press the 'Y' key!\nPress 'N' to save her!\n\n(Press 'Y' to quit)");
@ -6910,6 +6915,11 @@ static void M_RetryResponse(INT32 ch)
static void M_Retry(INT32 choice) static void M_Retry(INT32 choice)
{ {
(void)choice; (void)choice;
if (marathonmode)
{
M_RetryResponse(KEY_ENTER);
return;
}
M_StartMessage(M_GetText("Retry this act from the last starpost?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO); M_StartMessage(M_GetText("Retry this act from the last starpost?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO);
} }
@ -10430,7 +10440,7 @@ static void M_Marathon(INT32 choice)
mapnum++; mapnum++;
} }
SP_MarathonMenu[marathoncutscenes].status = (mapnum < NUMMAPS) ? IT_CVAR |IT_STRING : IT_NOTHING|IT_DISABLED; SP_MarathonMenu[marathoncutscenes].status = (mapnum < NUMMAPS) ? IT_CVAR|IT_STRING : IT_NOTHING|IT_DISABLED;
M_ChangeMenuMusic("spec8", true); M_ChangeMenuMusic("spec8", true);
@ -10490,6 +10500,8 @@ static void M_StartMarathon(INT32 choice)
cursaveslot = MARATHONSLOT; cursaveslot = MARATHONSLOT;
if (!cv_dummycutscenes.value) if (!cv_dummycutscenes.value)
marathonmode |= MA_NOCUTSCENES; marathonmode |= MA_NOCUTSCENES;
if (cv_dummyloadless.value)
marathonmode |= MA_INGAME;
M_ChoosePlayer(char_on); M_ChoosePlayer(char_on);
} }

View File

@ -755,6 +755,9 @@ void P_PreTicker(INT32 frames)
postimgtype = postimgtype2 = postimg_none; postimgtype = postimgtype2 = postimg_none;
if (marathonmode & MA_INGAME)
marathonmode |= MA_INIT;
for (framecnt = 0; framecnt < frames; ++framecnt) for (framecnt = 0; framecnt < frames; ++framecnt)
{ {
P_MapStart(); P_MapStart();
@ -797,4 +800,7 @@ void P_PreTicker(INT32 frames)
P_MapEnd(); P_MapEnd();
} }
if (marathonmode & MA_INGAME)
marathonmode &= ~MA_INIT;
} }

View File

@ -640,10 +640,13 @@ void SCR_DisplayMarathonInfo(void)
entertic = I_GetTime(); entertic = I_GetTime();
if (gamecomplete) if (gamecomplete)
flags |= V_YELLOWMAP; flags |= V_YELLOWMAP;
else if (marathonmode & MA_INGAME)
; // see also G_Ticker
else if (marathonmode & MA_INIT) else if (marathonmode & MA_INIT)
marathonmode &= ~MA_INIT; marathonmode &= ~MA_INIT;
else else
marathontime += entertic - oldentertics; marathontime += entertic - oldentertics;
// Create a sequence of primes such that their LCM is nice and big. // Create a sequence of primes such that their LCM is nice and big.
#define PRIMEV1 13 #define PRIMEV1 13
#define PRIMEV2 17 // I can't believe it! I'm on TV! #define PRIMEV2 17 // I can't believe it! I'm on TV!