diff --git a/src/dehacked.c b/src/dehacked.c index c92fc3412..031ba39d8 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9933,9 +9933,10 @@ struct { {"TC_DASHMODE",TC_DASHMODE}, // marathonmode flags - //{"MA_INIT",MA_INIT}, -- should never see this + {"MA_INIT",MA_INIT}, {"MA_RUNNING",MA_RUNNING}, {"MA_NOCUTSCENES",MA_NOCUTSCENES}, + {"MA_INGAME",MA_INGAME}, {NULL,0} }; diff --git a/src/doomstat.h b/src/doomstat.h index f407d7add..05512df9b 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -52,7 +52,8 @@ typedef enum { MA_RUNNING = 1, // In action 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; extern marathonmode_t marathonmode; diff --git a/src/g_game.c b/src/g_game.c index e6a6d851c..b46e9cfc0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2167,6 +2167,10 @@ void G_Ticker(boolean run) UINT32 i; INT32 buf; + // see also SCR_DisplayMarathonInfo + if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL) + marathontime++; + P_MapStart(); // do player reborns if needed if (gamestate == GS_LEVEL) @@ -2183,8 +2187,13 @@ void G_Ticker(boolean run) } else { - // Costs a life to retry ... unless the player in question is dead already. - if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE && players[consoleplayer].lives != INFLIVES) + // 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 (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; G_DoReborn(consoleplayer); diff --git a/src/m_menu.c b/src/m_menu.c index f07bbf703..8e9bb87fd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -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}; 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_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. @@ -919,8 +921,9 @@ enum // Marathon static menuitem_t SP_MarathonMenu[] = { - {IT_STRING|IT_KEYHANDLER, NULL, "Character", M_HandleMarathonChoosePlayer, 100}, - {IT_STRING|IT_CVAR, NULL, "Category", &cv_dummymarathon, 110}, + {IT_STRING|IT_KEYHANDLER, NULL, "Character", M_HandleMarathonChoosePlayer, 90}, + {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_WHITESTRING|IT_CALL, NULL, "Start", M_StartMarathon, 130}, }; @@ -929,6 +932,7 @@ enum { marathonplayer, marathonultimate, + marathonloadless, marathoncutscenes, marathonstart }; @@ -3909,6 +3913,7 @@ void M_Init(void) CV_RegisterVar(&cv_dummycontinues); CV_RegisterVar(&cv_dummymares); CV_RegisterVar(&cv_dummymarathon); + CV_RegisterVar(&cv_dummyloadless); 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)"); @@ -6910,6 +6915,11 @@ static void M_RetryResponse(INT32 ch) static void M_Retry(INT32 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); } @@ -10430,7 +10440,7 @@ static void M_Marathon(INT32 choice) 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); @@ -10490,6 +10500,8 @@ static void M_StartMarathon(INT32 choice) cursaveslot = MARATHONSLOT; if (!cv_dummycutscenes.value) marathonmode |= MA_NOCUTSCENES; + if (cv_dummyloadless.value) + marathonmode |= MA_INGAME; M_ChoosePlayer(char_on); } diff --git a/src/p_tick.c b/src/p_tick.c index 7ea6edb2d..0f8440960 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -755,6 +755,9 @@ void P_PreTicker(INT32 frames) postimgtype = postimgtype2 = postimg_none; + if (marathonmode & MA_INGAME) + marathonmode |= MA_INIT; + for (framecnt = 0; framecnt < frames; ++framecnt) { P_MapStart(); @@ -797,4 +800,7 @@ void P_PreTicker(INT32 frames) P_MapEnd(); } + + if (marathonmode & MA_INGAME) + marathonmode &= ~MA_INIT; } diff --git a/src/screen.c b/src/screen.c index 04dd73c46..e7ff9e735 100644 --- a/src/screen.c +++ b/src/screen.c @@ -640,10 +640,13 @@ void SCR_DisplayMarathonInfo(void) entertic = I_GetTime(); if (gamecomplete) flags |= V_YELLOWMAP; + else if (marathonmode & MA_INGAME) + ; // see also G_Ticker else if (marathonmode & MA_INIT) marathonmode &= ~MA_INIT; else marathontime += entertic - oldentertics; + // Create a sequence of primes such that their LCM is nice and big. #define PRIMEV1 13 #define PRIMEV2 17 // I can't believe it! I'm on TV!