From e507a8b0ad5fb1271f28cc6b670213efe3139a57 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 22:07:28 +0100 Subject: [PATCH 01/23] P_EndingMusic: Play "EMRLD" in Emerald contexts - gametype has GTR_POWERSTONES and any one player has all 7 emeralds - gametyperules & GTR_SPECIALSTART and any one player isn't losing - GP after completing a GPEVENT_SPECIAL and any one player isn't losing - Catches custom gametypes in place of Sealed Star at the end of a GP --- src/p_user.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index c4535efb8..938bf96e1 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -714,12 +714,50 @@ void P_PlayVictorySound(mobj_t *source) void P_EndingMusic(void) { const char *jingle = NULL; - boolean nointer = false; UINT8 bestPos = UINT8_MAX; player_t *bestPlayer = NULL; SINT8 i; + // See G_DoCompleted and Y_DetermineIntermissionType + boolean nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST)) + || (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] + || players[i].spectator) + continue; + + // Battle powerstone win + if ((gametyperules & GTR_POWERSTONES) + && ALLCHAOSEMERALDS(players[i].emeralds)) + break; + + // Special round? + if (((gametyperules & GTR_SPECIALSTART) + || (grandprixinfo.gp == true + && grandprixinfo.eventmode == GPEVENT_SPECIAL) + ) == false) + continue; + + // Any player has completed well? + if (!players[i].exiting + || players[i].bot + || K_IsPlayerLosing(&players[i])) + continue; + + // Special win + break; + } + + // Event - Emerald Finish + if (i != MAXPLAYERS) + { + jingle = "EMRLD"; + goto skippingposition; + } + // Event - Level Finish // Check for if this is valid or not for (i = 0; i <= r_splitscreen; i++) @@ -756,10 +794,6 @@ void P_EndingMusic(void) } } - // See G_DoCompleted and Y_DetermineIntermissionType - nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST)) - || (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)); - if (bestPlayer == NULL) { // No jingle for you @@ -798,6 +832,8 @@ void P_EndingMusic(void) } } +skippingposition: + if (nointer == true) { // Do not set "racent" in G_Ticker From ed8158c00c94684567a4b31509ea68d4a8169e8a Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 22:09:49 +0100 Subject: [PATCH 02/23] P_SetupSignExit: Bail early if gametype has GTR_SPECIALSTART --- src/p_spec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 51a62332c..d43c6e07b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4647,11 +4647,12 @@ void P_SetupSignExit(player_t *player, boolean tie) thinker_t *think; INT32 numfound = 0; - angle_t bestAngle = K_MomentumAngle(player->mo) + ANGLE_180; - - if (player->position != 1) + if (player->position != 1 + || (gametyperules & GTR_SPECIALSTART)) return; + angle_t bestAngle = K_MomentumAngle(player->mo) + ANGLE_180; + for (; node; node = node->m_thinglist_next) { thing = node->m_thing; From 08b471c9b224126bfd8d9b806bc38fa827a5dba0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 22:10:22 +0100 Subject: [PATCH 03/23] Vaguely related request: Increase radius + height for MT_EMERALD by 8FU --- src/info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index 7d1c0023c..8733c8a4c 100644 --- a/src/info.c +++ b/src/info.c @@ -8117,8 +8117,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_s3k9c, // deathsound 0, // speed - 72*FRACUNIT, // radius - 72*FRACUNIT, // height + 80*FRACUNIT, // radius + 80*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage From 2c09f397960ac10802cf558fc2f5030664d0c10c Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 23:02:37 +0100 Subject: [PATCH 04/23] K_drawKartHUD: Draw laps if there's 0 laps, because that's more likely to be a testing environment --- src/k_hud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index c0098b016..8fa17c725 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -5280,7 +5280,7 @@ void K_drawKartHUD(void) { if (gametyperules & GTR_CIRCUIT) { - if (numlaps > 1) + if (numlaps != 1) { K_drawKartLaps(); gametypeinfoshown = true; From 8689e0735e3c7193fd6efd8fec1a8a7cb4baaa94 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 23:17:21 +0100 Subject: [PATCH 05/23] readcupheader: Permit emptying out BonusGame and SpecialStage for an existing cup Provide a single / and it'll be empty --- src/deh_soc.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index eb30c33ed..e9e184bae 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3438,6 +3438,15 @@ static void invalidateacrosscups(UINT16 map) mapheaderinfo[map]->cup = NULL; } +static char *MapNameOrRemoval(char *name) +{ + if (name[0] == '\0' + || (name[0] == '/' && name[1] == '\0')) + return NULL; + + return Z_StrDup(name); +} + void readcupheader(MYFILE *f, cupheader_t *cup) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -3539,8 +3548,12 @@ void readcupheader(MYFILE *f, cupheader_t *cup) break; } - cup->levellist[CUPCACHE_BONUS + cup->numbonus] = Z_StrDup(tmp); + cup->levellist[CUPCACHE_BONUS + cup->numbonus] = MapNameOrRemoval(tmp); cup->cachedlevels[CUPCACHE_BONUS + cup->numbonus] = NEXTMAP_INVALID; + + if (cup->levellist[CUPCACHE_BONUS + cup->numbonus] == NULL) + break; + cup->numbonus++; } while((tmp = strtok(NULL,",")) != NULL); } @@ -3548,7 +3561,7 @@ void readcupheader(MYFILE *f, cupheader_t *cup) { invalidateacrosscups(cup->cachedlevels[CUPCACHE_SPECIAL]); Z_Free(cup->levellist[CUPCACHE_SPECIAL]); - cup->levellist[CUPCACHE_SPECIAL] = Z_StrDup(word2); + cup->levellist[CUPCACHE_SPECIAL] = MapNameOrRemoval(word2); cup->cachedlevels[CUPCACHE_SPECIAL] = NEXTMAP_INVALID; } else if (fastcmp(word, "EMERALDNUM")) From 8d3e828663fdb0b9f57f8df6a725b701a42c670a Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 23:18:51 +0100 Subject: [PATCH 06/23] AltPodium for cups We're unlikely to utilise this, but permits creators of custom user-created cups to flex their own style without fighting to replace the default Podium. --- src/deh_soc.c | 7 +++++++ src/doomstat.h | 3 ++- src/k_podium.c | 19 ++++++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index e9e184bae..7037c7f36 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3564,6 +3564,13 @@ void readcupheader(MYFILE *f, cupheader_t *cup) cup->levellist[CUPCACHE_SPECIAL] = MapNameOrRemoval(word2); cup->cachedlevels[CUPCACHE_SPECIAL] = NEXTMAP_INVALID; } + else if (fastcmp(word, "ALTPODIUM")) + { + invalidateacrosscups(cup->cachedlevels[CUPCACHE_PODIUM]); + Z_Free(cup->levellist[CUPCACHE_PODIUM]); + cup->levellist[CUPCACHE_PODIUM] = MapNameOrRemoval(word2); + cup->cachedlevels[CUPCACHE_PODIUM] = NEXTMAP_INVALID; + } else if (fastcmp(word, "EMERALDNUM")) { if (i >= 0 && i <= 14) diff --git a/src/doomstat.h b/src/doomstat.h index e6787116e..d25ca720c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -383,7 +383,8 @@ struct customoption_t #define CUPCACHE_BONUS MAXLEVELLIST #define MAXBONUSLIST 2 #define CUPCACHE_SPECIAL (CUPCACHE_BONUS+MAXBONUSLIST) -#define CUPCACHE_MAX (CUPCACHE_SPECIAL+1) +#define CUPCACHE_PODIUM (CUPCACHE_SPECIAL+1) +#define CUPCACHE_MAX (CUPCACHE_PODIUM+1) #define MAXCUPNAME 16 // includes \0, for cleaner savedata diff --git a/src/k_podium.c b/src/k_podium.c index 630048e98..c5c70bdb9 100644 --- a/src/k_podium.c +++ b/src/k_podium.c @@ -235,16 +235,25 @@ void K_UpdatePodiumWaypoints(player_t *const player) --------------------------------------------------*/ boolean K_StartCeremony(void) { - INT32 podiumMapNum = nummapheaders; - INT32 i; - if (grandprixinfo.gp == false) { return false; } - if (podiummap - && ((podiumMapNum = G_MapNumber(podiummap)) < nummapheaders) + INT32 i; + INT32 podiumMapNum = NEXTMAP_INVALID; + + if (grandprixinfo.cup != NULL + && grandprixinfo.cup->cachedlevels[CUPCACHE_PODIUM] != NEXTMAP_INVALID) + { + podiumMapNum = grandprixinfo.cup->cachedlevels[CUPCACHE_PODIUM]; + } + else if (podiummap) + { + podiumMapNum = G_MapNumber(podiummap); + } + + if (podiumMapNum < nummapheaders && mapheaderinfo[podiumMapNum] && mapheaderinfo[podiumMapNum]->lumpnum != LUMPERROR) { From 43044ec032bcbdd88413467a3d494e1be6c51f81 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Jun 2023 23:21:04 +0100 Subject: [PATCH 07/23] PlayCredits for Cups Hilariously broken due to the evaulation gamestate, but the first piece of the puzzle: gets the player into the Credits gamestate after the conclusion of a Podium, if the GP context's cup has this boolean set. --- src/deh_soc.c | 8 ++++++-- src/doomstat.h | 3 +++ src/g_game.c | 12 +++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 7037c7f36..f6509eabd 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3126,7 +3126,7 @@ void readmaincfg(MYFILE *f, boolean mainfile) } else if (fastcmp(word, "LOOPTITLE")) { - looptitle = (value || word2[0] == 'T' || word2[0] == 'Y'); + looptitle = (value != 0 || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "TITLEMAP")) @@ -3137,7 +3137,7 @@ void readmaincfg(MYFILE *f, boolean mainfile) } else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "TITLEPICSHIDE")) { - hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); + hidetitlepics = (boolean)(value != 0 || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "TITLEPICSMODE")) @@ -3578,6 +3578,10 @@ void readcupheader(MYFILE *f, cupheader_t *cup) else deh_warning("%s Cup: invalid emerald number %d", cup->name, i); } + else if (fastcmp(word, "PLAYCREDITS")) + { + cup->playcredits = (i != 0 || word2[0] == 'T' || word2[0] == 'Y'); + } else deh_warning("%s Cup: unknown word '%s'", cup->name, word); } diff --git a/src/doomstat.h b/src/doomstat.h index d25ca720c..70d583f66 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -402,6 +402,9 @@ struct cupheader_t UINT8 numlevels; ///< Number of levels defined in levellist UINT8 numbonus; ///< Number of bonus stages defined UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald) + + boolean playcredits; ///< Play the credits? + cupwindata_t windata[4]; ///< Data for cup visitation cupheader_t *next; ///< Next cup in linked list }; diff --git a/src/g_game.c b/src/g_game.c index 1b3dfa770..252e09368 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1813,7 +1813,17 @@ boolean G_Responder(event_t *ev) if (K_CeremonyResponder(ev)) { - nextmap = NEXTMAP_TITLE; + if (grandprixinfo.gp == true + && grandprixinfo.cup != NULL + && grandprixinfo.cup->playcredits == true) + { + nextmap = NEXTMAP_CREDITS; + } + else + { + nextmap = NEXTMAP_TITLE; + } + G_EndGame(); return true; } From c89048def71e8f9623507b892e735e043fb5cf6d Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 20 Jun 2023 23:22:17 +0100 Subject: [PATCH 08/23] Game End cleanup - Remove specific gamestate, drawer, etc - Just add an extra fade straight into G_EndGame --- src/d_main.c | 4 ---- src/deh_soc.c | 8 -------- src/deh_tables.c | 1 - src/f_finale.c | 44 ++++++++------------------------------------ src/f_finale.h | 4 ---- src/f_wipe.c | 10 ---------- src/g_game.c | 10 ---------- src/g_state.h | 1 - src/k_menufunc.c | 1 - 9 files changed, 8 insertions(+), 75 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index aa79e6584..7439b612a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -476,10 +476,6 @@ static void D_Display(void) HU_Drawer(); break; - case GS_GAMEEND: - F_GameEndDrawer(); - break; - case GS_EVALUATION: F_GameEvaluationDrawer(); HU_Erase(); diff --git a/src/deh_soc.c b/src/deh_soc.c index f6509eabd..08995d083 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3365,14 +3365,6 @@ void readwipes(MYFILE *f) else if (fastcmp(pword, "FINAL")) wipeoffset = wipe_evaluation_final; } - else if (fastncmp(word, "GAMEEND_", 8)) - { - pword = word + 8; - if (fastcmp(pword, "TOBLACK")) - wipeoffset = wipe_gameend_toblack; - else if (fastcmp(pword, "FINAL")) - wipeoffset = wipe_gameend_final; - } else if (fastncmp(word, "CEREMONY_", 9)) { pword = word + 9; diff --git a/src/deh_tables.c b/src/deh_tables.c index ddbae5cbf..1435dc5d4 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6835,7 +6835,6 @@ struct int_const_s const INT_CONST[] = { {"GS_MENU",GS_MENU}, {"GS_CREDITS",GS_CREDITS}, {"GS_EVALUATION",GS_EVALUATION}, - {"GS_GAMEEND",GS_GAMEEND}, {"GS_INTRO",GS_INTRO}, {"GS_ENDING",GS_ENDING}, {"GS_CUTSCENE",GS_CUTSCENE}, diff --git a/src/f_finale.c b/src/f_finale.c index a6f4fb900..688009b68 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -904,7 +904,7 @@ void F_StartGameEvaluation(void) // Credits option in extras menu if (cursaveslot == -1) { - S_FadeOutStopMusic(2*MUSICRATE); + S_FadeOutStopMusic(MUSICRATE/2); F_StartGameEnd(); return; } @@ -1625,44 +1625,16 @@ void F_EndingDrawer(void) // ========== void F_StartGameEnd(void) { - G_SetGamestate(GS_GAMEEND); + // Early fadeout to let the sound finish playing + F_WipeStartScreen(); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeEndScreen(); + F_RunWipe(wipe_level_toblack, wipedefs[wipe_level_toblack], false, "FADEMAP0", false, false); - gameaction = ga_nothing; - paused = false; - CON_ToggleOff(); - S_StopSounds(); - - // In case menus are still up?!! - M_ClearMenus(true); - - timetonext = TICRATE; + nextmap = NEXTMAP_TITLE; + G_EndGame(); } -// -// F_GameEndDrawer -// -void F_GameEndDrawer(void) -{ - // this function does nothing -} - -// -// F_GameEndTicker -// -void F_GameEndTicker(void) -{ - if (timetonext > 0) - { - timetonext--; - } - else - { - nextmap = NEXTMAP_TITLE; - G_EndGame(); - } -} - - // ============== // TITLE SCREEN // ============== diff --git a/src/f_finale.h b/src/f_finale.h index 56691a847..6e79faab3 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -33,7 +33,6 @@ boolean F_CutsceneResponder(event_t *ev); boolean F_CreditResponder(event_t *ev); // Called by main loop. -void F_GameEndTicker(void); void F_IntroTicker(void); void F_TitleScreenTicker(boolean run); void F_CutsceneTicker(void); @@ -41,7 +40,6 @@ void F_TitleDemoTicker(void); void F_TextPromptTicker(void); // Called by main loop. -void F_GameEndDrawer(void); void F_IntroDrawer(void); void F_TitleScreenDrawer(void); void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname); @@ -173,7 +171,6 @@ enum wipe_menu_toblack, wipe_credits_toblack, wipe_evaluation_toblack, - wipe_gameend_toblack, wipe_ceremony_toblack, wipe_intro_toblack, wipe_ending_toblack, @@ -192,7 +189,6 @@ enum wipe_menu_final, wipe_credits_final, wipe_evaluation_final, - wipe_gameend_final, wipe_ceremony_final, wipe_intro_final, wipe_ending_final, diff --git a/src/f_wipe.c b/src/f_wipe.c index 105358407..50d2c7391 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -63,7 +63,6 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 1, // wipe_menu_toblack 99, // wipe_credits_toblack 0, // wipe_evaluation_toblack - 0, // wipe_gameend_toblack 0, // wipe_ceremony_toblack UINT8_MAX, // wipe_intro_toblack (hardcoded) 99, // wipe_ending_toblack (hardcoded) @@ -80,7 +79,6 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 1, // wipe_menu_final 99, // wipe_credits_final 0, // wipe_evaluation_final - 0, // wipe_gameend_final 0, // wipe_ceremony_final 99, // wipe_intro_final (hardcoded) 99, // wipe_ending_final (hardcoded) @@ -98,7 +96,6 @@ static boolean g_wipedef_toblack[NUMWIPEDEFS] = { true, // wipe_menu_toblack true, // wipe_credits_toblack true, // wipe_evaluation_toblack - true, // wipe_gameend_toblack true, // wipe_ceremony_toblack true, // wipe_intro_toblack (hardcoded) true, // wipe_ending_toblack (hardcoded) @@ -115,7 +112,6 @@ static boolean g_wipedef_toblack[NUMWIPEDEFS] = { true, // wipe_menu_final true, // wipe_credits_final true, // wipe_evaluation_final - true, // wipe_gameend_final true, // wipe_ceremony_final true, // wipe_intro_final (hardcoded) true, // wipe_ending_final (hardcoded) @@ -133,7 +129,6 @@ static boolean g_wipedef_toinvert[NUMWIPEDEFS] = { false, // wipe_menu_toblack false, // wipe_credits_toblack false, // wipe_evaluation_toblack - false, // wipe_gameend_toblack false, // wipe_ceremony_toblack false, // wipe_intro_toblack (hardcoded) false, // wipe_ending_toblack (hardcoded) @@ -150,7 +145,6 @@ static boolean g_wipedef_toinvert[NUMWIPEDEFS] = { false, // wipe_menu_final false, // wipe_credits_final false, // wipe_evaluation_final - false, // wipe_gameend_final false, // wipe_ceremony_final false, // wipe_intro_final (hardcoded) false, // wipe_ending_final (hardcoded) @@ -168,7 +162,6 @@ static boolean g_wipedef_towhite[NUMWIPEDEFS] = { false, // wipe_menu_toblack false, // wipe_credits_toblack false, // wipe_evaluation_toblack - false, // wipe_gameend_toblack false, // wipe_ceremony_toblack false, // wipe_intro_toblack (hardcoded) false, // wipe_ending_toblack (hardcoded) @@ -185,7 +178,6 @@ static boolean g_wipedef_towhite[NUMWIPEDEFS] = { false, // wipe_menu_final false, // wipe_credits_final false, // wipe_evaluation_final - false, // wipe_gameend_final false, // wipe_ceremony_final false, // wipe_intro_final (hardcoded) false, // wipe_ending_final (hardcoded) @@ -203,7 +195,6 @@ static boolean g_wipedef_crossfade[NUMWIPEDEFS] = { false, // wipe_menu_toblack false, // wipe_credits_toblack false, // wipe_evaluation_toblack - false, // wipe_gameend_toblack false, // wipe_ceremony_toblack false, // wipe_intro_toblack (hardcoded) false, // wipe_ending_toblack (hardcoded) @@ -220,7 +211,6 @@ static boolean g_wipedef_crossfade[NUMWIPEDEFS] = { true, // wipe_menu_final true, // wipe_credits_final true, // wipe_evaluation_final - true, // wipe_gameend_final true, // wipe_ceremony_final true, // wipe_intro_final (hardcoded) true, // wipe_ending_final (hardcoded) diff --git a/src/g_game.c b/src/g_game.c index 252e09368..a04707627 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1832,11 +1832,6 @@ boolean G_Responder(event_t *ev) { return true; } - // Demo End - else if (gamestate == GS_GAMEEND) - { - return true; - } else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_EVALUATION) { if (HU_Responder(ev)) @@ -2344,11 +2339,6 @@ void G_Ticker(boolean run) HU_Ticker(); break; - case GS_GAMEEND: - if (run) - F_GameEndTicker(); - break; - case GS_EVALUATION: if (run) F_GameEvaluationTicker(); diff --git a/src/g_state.h b/src/g_state.h index b78105639..97a828861 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -35,7 +35,6 @@ typedef enum GS_CREDITS, // credit sequence GS_EVALUATION, // Evaluation at the end of a game. - GS_GAMEEND, // game end sequence - "did you get all those chaos emeralds?" GS_CEREMONY, // RR: Podium sequence // Hardcoded fades or other fading methods diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 5acbb0e7d..1b4bddb01 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -209,7 +209,6 @@ static boolean M_GamestateCanOpenMenu(void) { case GS_INTRO: case GS_CUTSCENE: - case GS_GAMEEND: case GS_CREDITS: case GS_EVALUATION: case GS_CEREMONY: From 0ecc7ccd547b86f04df54c059b9b4fb9ed7a593a Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 21 Jun 2023 00:03:09 +0100 Subject: [PATCH 09/23] Make credits accessible from the menu again --- src/f_finale.c | 4 ++-- src/k_menu.h | 1 + src/menus/extras-1.c | 12 ++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 688009b68..f6bff28fb 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -902,9 +902,9 @@ boolean F_CreditResponder(event_t *event) void F_StartGameEvaluation(void) { // Credits option in extras menu - if (cursaveslot == -1) + if (grandprixinfo.gp == false) { - S_FadeOutStopMusic(MUSICRATE/2); + S_FadeMusic(0, MUSICRATE/4); F_StartGameEnd(); return; } diff --git a/src/k_menu.h b/src/k_menu.h index 7eefd06ea..832b4d7b2 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1048,6 +1048,7 @@ typedef enum extras_eggtv, extras_stereo, extras_password, + extras_credits, } extras_e; void M_InitExtras(INT32 choice); // init for the struct diff --git a/src/menus/extras-1.c b/src/menus/extras-1.c index 5e11a6121..f623b2d3b 100644 --- a/src/menus/extras-1.c +++ b/src/menus/extras-1.c @@ -5,6 +5,15 @@ #include "../m_cond.h" #include "../m_cheat.h" #include "../s_sound.h" +#include "../f_finale.h" + +static void M_Credits(INT32 choice) +{ + (void)choice; + restoreMenu = currentMenu; + M_ClearMenus(true); + F_StartCredits(); +} menuitem_t EXTRAS_Main[] = { @@ -32,6 +41,9 @@ menuitem_t EXTRAS_Main[] = {IT_STRING | IT_CVAR | IT_CV_STRING, "Password", "If you don't know any passwords, come back later!", NULL, {.cvar = &cv_dummyextraspassword}, 0, 0}, + + {IT_STRING | IT_CALL, "Credits", "It's important to know who makes the video games you play.", + NULL, {.routine = M_Credits}, 0, 0}, }; // the extras menu essentially reuses the options menu stuff From f15a7a946d7756137c3b8fba8d6ab873f0603299 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 23 Jun 2023 22:00:50 +0100 Subject: [PATCH 10/23] Remove GS_ENDING A whole bunch of extremely specific SRB2 material --- src/d_main.c | 6 - src/deh_tables.c | 1 - src/f_finale.c | 521 ----------------------------------------------- src/f_finale.h | 5 - src/f_wipe.c | 10 - src/g_game.c | 12 +- src/g_state.h | 1 - 7 files changed, 1 insertion(+), 555 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 7439b612a..3df9d455f 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -464,12 +464,6 @@ static void D_Display(void) } break; - case GS_ENDING: - F_EndingDrawer(); - HU_Erase(); - HU_Drawer(); - break; - case GS_CUTSCENE: F_CutsceneDrawer(); HU_Erase(); diff --git a/src/deh_tables.c b/src/deh_tables.c index 1435dc5d4..3c11a3aa2 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6836,7 +6836,6 @@ struct int_const_s const INT_CONST[] = { {"GS_CREDITS",GS_CREDITS}, {"GS_EVALUATION",GS_EVALUATION}, {"GS_INTRO",GS_INTRO}, - {"GS_ENDING",GS_ENDING}, {"GS_CUTSCENE",GS_CUTSCENE}, {"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER}, {"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS}, diff --git a/src/f_finale.c b/src/f_finale.c index f6bff28fb..277f8b5e6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -130,14 +130,6 @@ static patch_t *ttuser[TTMAX_USER]; static INT32 ttuser_count = 0; static boolean goodending; -static patch_t *endbrdr[2]; // border - blue, white, pink - where have i seen those colours before? -static patch_t *endbgsp[3]; // nebula, sun, planet -static patch_t *endegrk[2]; // eggrock - replaced midway through good ending -static patch_t *endfwrk[3]; // firework - replaced with skin when good ending -static patch_t *endspkl[3]; // sparkle -static patch_t *endglow[2]; // glow aura - replaced with black rock's midway through good ending -static patch_t *endxpld[4]; // mini explosion -static patch_t *endescp[5]; // escape pod + flame static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles static INT32 sparklloop; @@ -1107,519 +1099,6 @@ void F_GameEvaluationTicker(void) #undef SPARKLLOOPTIME -// ========== -// ENDING -// ========== - -#define INFLECTIONPOINT (6*TICRATE) -#define STOPPINGPOINT (14*TICRATE) -#define SPARKLLOOPTIME 15 // must be odd - -static void F_CacheEnding(void) -{ - endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_PATCH_LOWPRIORITY); - - endegrk[0] = W_CachePatchName("ENDEGRK0", PU_PATCH_LOWPRIORITY); - endegrk[1] = W_CachePatchName("ENDEGRK1", PU_PATCH_LOWPRIORITY); - - endglow[0] = W_CachePatchName("ENDGLOW0", PU_PATCH_LOWPRIORITY); - endglow[1] = W_CachePatchName("ENDGLOW1", PU_PATCH_LOWPRIORITY); - - endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_PATCH_LOWPRIORITY); - endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_PATCH_LOWPRIORITY); - endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_PATCH_LOWPRIORITY); - - endspkl[0] = W_CachePatchName("ENDSPKL0", PU_PATCH_LOWPRIORITY); - endspkl[1] = W_CachePatchName("ENDSPKL1", PU_PATCH_LOWPRIORITY); - endspkl[2] = W_CachePatchName("ENDSPKL2", PU_PATCH_LOWPRIORITY); - - endxpld[0] = W_CachePatchName("ENDXPLD0", PU_PATCH_LOWPRIORITY); - endxpld[1] = W_CachePatchName("ENDXPLD1", PU_PATCH_LOWPRIORITY); - endxpld[2] = W_CachePatchName("ENDXPLD2", PU_PATCH_LOWPRIORITY); - endxpld[3] = W_CachePatchName("ENDXPLD3", PU_PATCH_LOWPRIORITY); - - endescp[0] = W_CachePatchName("ENDESCP0", PU_PATCH_LOWPRIORITY); - endescp[1] = W_CachePatchName("ENDESCP1", PU_PATCH_LOWPRIORITY); - endescp[2] = W_CachePatchName("ENDESCP2", PU_PATCH_LOWPRIORITY); - endescp[3] = W_CachePatchName("ENDESCP3", PU_PATCH_LOWPRIORITY); - endescp[4] = W_CachePatchName("ENDESCP4", PU_PATCH_LOWPRIORITY); - - // so we only need to check once - if ((goodending = ALLCHAOSEMERALDS(emeralds))) - { - endfwrk[0] = W_CachePatchName("ENDFWRK3", PU_PATCH); - endfwrk[1] = W_CachePatchName("ENDFWRK4", PU_PATCH); - endfwrk[2] = W_CachePatchName("ENDFWRK5", PU_PATCH); - - endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_PATCH_LOWPRIORITY); - } - else - { - // eggman, skin nonspecific - endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_PATCH_LOWPRIORITY); - endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_PATCH_LOWPRIORITY); - endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_PATCH_LOWPRIORITY); - - endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_PATCH_LOWPRIORITY); - } -} - -static void F_CacheGoodEnding(void) -{ - endegrk[0] = W_CachePatchName("ENDEGRK2", PU_PATCH_LOWPRIORITY); - endegrk[1] = W_CachePatchName("ENDEGRK3", PU_PATCH_LOWPRIORITY); - - endglow[0] = W_CachePatchName("ENDGLOW2", PU_PATCH_LOWPRIORITY); - endglow[1] = W_CachePatchName("ENDGLOW3", PU_PATCH_LOWPRIORITY); - - endxpld[0] = W_CachePatchName("ENDEGRK4", PU_PATCH_LOWPRIORITY); -} - -void F_StartEnding(void) -{ - G_SetGamestate(GS_ENDING); - wipetypepost = INT16_MAX; - - // Just in case they're open ... somehow - M_ClearMenus(true); - - gameaction = ga_nothing; - paused = false; - CON_ToggleOff(); - S_StopMusic(); // todo: placeholder - S_StopSounds(); - - finalecount = -10; // what? this totally isn't a hack. why are you asking? - - memset(sparkloffs, 0, sizeof(INT32)*3*2); - sparklloop = 0; - - F_CacheEnding(); -} - -void F_EndingTicker(void) -{ - if (++finalecount > STOPPINGPOINT) - { - F_StartCredits(); - wipetypepre = INT16_MAX; - return; - } - - if (finalecount == -8) - S_ChangeMusicInternal((goodending ? "_endg" : "_endb"), false); - - if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets - F_CacheGoodEnding(); - - if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again - { - angle_t workingangle = FixedAngle((M_RandomRange(-170, 80))<>ANGLETOFINESHIFT; - fixed_t workingradius = M_RandomKey(26); - - sparkloffs[0][0] = (30< -19) - { - INT32 trans = (-parallaxticker)>>1; - if (trans < 0) - trans = 0; - V_DrawFixedPatch((200< 0) // gunchedrock - { - INT32 scale = FRACUNIT + ((parallaxticker-10)<<7); - INT32 trans = parallaxticker>>2; - UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); - - if (parallaxticker < 10) - { - tweakx = parallaxticker< 0) - { - i -= (3+(tweakx<<1)); - j += tweaky<<2; - } - - if (parallaxticker <= 70) // eggrock/blackrock - { - INT32 trans; - fixed_t scale = FRACUNIT; - UINT8 *colormap[2] = {NULL, NULL}; - - x += i; - y += j; - - if (parallaxticker > 66) - { - scale = ((70 - parallaxticker)<<(FRACBITS-2)); - x += (30*(FRACUNIT-scale)); - y += (30*(FRACUNIT-scale)); - } - else if ((parallaxticker > 60) || (goodending && parallaxticker > 0)) - ; - else - { - doexplosions = true; - if (!sparklloop) - { - x += ((sparkloffs[0][0] < 30< INFLECTIONPOINT) - parallaxticker -= 40; - - if ((-parallaxticker/4) < 5) - { - trans = (-parallaxticker/4) + 5; - if (trans < 0) - trans = 0; - V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT) - { - if (finalecount < INFLECTIONPOINT+10) - V_DrawFadeFill(24, 24, BASEVIDWIDTH-48, BASEVIDHEIGHT-48, 0, 0, INFLECTIONPOINT+10-finalecount); - parallaxticker -= 30; - } - - if ((parallaxticker/2) > -15) - colormap[0] = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); - V_DrawFixedPatch(x, y, scale, 0, rockpat, colormap[0]); - if ((parallaxticker/2) > -25) - { - trans = (parallaxticker/2) + 15; - if (trans < 0) - trans = -trans; - if (trans < 10) - V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT) - { - if (finalecount < INFLECTIONPOINT+10) - V_DrawFixedPatch(x, y, scale, (finalecount-INFLECTIONPOINT)<= 3 && doexplosions) - { - INT32 boomtime = parallaxticker - sparklloop; - - x = ((((BASEVIDWIDTH-82)/2)+11)< INFLECTIONPOINT && finalecount < INFLECTIONPOINT+10) - V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, (finalecount-INFLECTIONPOINT)<= TICRATE && finalecount < INFLECTIONPOINT) - { - INT32 workingtime = finalecount - TICRATE; - fixed_t radius = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); - angle_t fa; - INT32 eemeralds_cur[4]; - char patchname[7] = "CEMGx0"; - - radius <<= FRACBITS; - - for (i = 0; i < 4; ++i) - { - if (i == 1) - workingtime -= sparklloop; - else if (i) - workingtime -= SPARKLLOOPTIME; - eemeralds_cur[i] = (workingtime % 360)<>ANGLETOFINESHIFT) & FINEMASK; - x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); - y = (BASEVIDHEIGHT<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); - eemeralds_cur[j] += (360<>ANGLETOFINESHIFT) & FINEMASK; - x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); - y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); - eemeralds_cur[0] += (360< 20) - - // look, i make an ending for you last-minute, the least you could do is let me have this - if (cv_soundtest.value == 413) - { - INT32 trans = 0; - boolean donttouch = false; - const char *str; - if (goodending) - str = va("[S] %s: Engage.", skins[players[consoleplayer].skin].realname); - else - str = "[S] Eggman: Abscond."; - - if (finalecount < 10) - trans = (10-finalecount)/2; - else if (finalecount > STOPPINGPOINT - 20) - { - trans = 10 + (finalecount - STOPPINGPOINT)/2; - donttouch = true; - } - - if (trans < 10) - { - //colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret - V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<'|(trans<timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); - } - - if (finalecount > STOPPINGPOINT-(20+(2*TICRATE))) - { - INT32 trans2 = abs((5*FINECOSINE((FixedAngle((finalecount*5)<>ANGLETOFINESHIFT & FINEMASK)))>>FRACBITS)+2; - if (!donttouch) - { - trans = 10 + (STOPPINGPOINT-(20+(2*TICRATE))) - finalecount; - if (trans > trans2) - trans2 = trans; - } - else - trans2 += 2*trans; - if (trans2 < 10) - V_DrawCharacter(26, BASEVIDHEIGHT-33, '\x1C'|(trans2< Date: Fri, 23 Jun 2023 23:13:25 +0100 Subject: [PATCH 11/23] Ring Racers-specific Evaluation - Four evaluation modes. - Perfect - Currently no visual implementation - All others have a cool set of visuals - Multi-stage animation of a glowing threat and a Star that's Sealed - If they're relevant, show the gems you HAVEN'T grabbed - Three modes here - No gems - For Easy mode, asks you to brave a higher difficulty - Chaos Emeralds - Not all 7 chaos emeralds? Push your rank harder! - Super Emeralds - Not all 7 super emeralds? Further challenge awaits! - `useBlackRock` to make evaluation context less specific for custom material is replaced with `useSeal` option - M_CheckCupEmeralds(difficulty) - Returns the Emeralds you have for that difficulty - Obviously returns 0 for Easy - Makes the method of checking collected Emeralds for cup contexts significantly easier --- src/deh_soc.c | 4 +- src/doomstat.h | 2 +- src/f_finale.c | 333 +++++++++++++++++++++++++++++++++++++------------ src/g_game.c | 2 +- src/m_cond.c | 45 ++++--- src/m_cond.h | 1 + 6 files changed, 281 insertions(+), 106 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 08995d083..860d6ad0d 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3120,9 +3120,9 @@ void readmaincfg(MYFILE *f, boolean mainfile) if (creditscutscene > 128) creditscutscene = 128; } - else if (fastcmp(word, "USEBLACKROCK")) + else if (fastcmp(word, "USESEAL")) { - useBlackRock = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); + useSeal = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); } else if (fastcmp(word, "LOOPTITLE")) { diff --git a/src/doomstat.h b/src/doomstat.h index 70d583f66..00b8c9cf7 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -748,7 +748,7 @@ extern INT32 flameseg; extern UINT8 introtoplay; extern UINT8 creditscutscene; -extern UINT8 useBlackRock; +extern UINT8 useSeal; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings diff --git a/src/f_finale.c b/src/f_finale.c index 277f8b5e6..b4845cad6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -129,10 +129,6 @@ static UINT8 *waitcolormap; // colormap for the spinning character static patch_t *ttuser[TTMAX_USER]; static INT32 ttuser_count = 0; -static boolean goodending; -static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles -static INT32 sparklloop; - // // PROMPT STATE // @@ -889,8 +885,26 @@ boolean F_CreditResponder(event_t *event) // EVALUATION // ============ +#if 0 + +static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles +static INT32 sparklloop; + #define SPARKLLOOPTIME 7 // must be odd +#endif + +typedef enum +{ + EVAL_NOTHING, + EVAL_CHAOS, + EVAL_SUPER, + EVAL_PERFECT +} evaluationtype_t; + +static evaluationtype_t evaluationtype; +UINT16 finaleemeralds = 0; + void F_StartGameEvaluation(void) { // Credits option in extras menu @@ -902,20 +916,39 @@ void F_StartGameEvaluation(void) } S_FadeOutStopMusic(5*MUSICRATE); + S_StopMusicCredit(); G_SetGamestate(GS_EVALUATION); // Just in case they're open ... somehow M_ClearMenus(true); - goodending = (ALLCHAOSEMERALDS(emeralds)); + UINT8 difficulty = KARTSPEED_NORMAL; + if (grandprixinfo.gp == true) + { + if (grandprixinfo.masterbots == true) + difficulty = KARTGP_MASTER; + else + difficulty = grandprixinfo.gamespeed; + } + + finaleemeralds = M_CheckCupEmeralds(difficulty); + + if (difficulty == KARTSPEED_EASY) + evaluationtype = EVAL_NOTHING; + else if (!ALLCHAOSEMERALDS(finaleemeralds)) + evaluationtype = EVAL_CHAOS; + else if (!ALLSUPEREMERALDS(finaleemeralds)) + evaluationtype = EVAL_SUPER; + else + evaluationtype = EVAL_PERFECT; gameaction = ga_nothing; paused = false; CON_ToggleOff(); finalecount = -1; - sparklloop = 0; + //sparklloop = 0; } void F_GameEvaluationDrawer(void) @@ -923,68 +956,155 @@ void F_GameEvaluationDrawer(void) INT32 x, y, i; angle_t fa; INT32 eemeralds_cur; - char patchname[7] = "CEMGx0"; - const char* endingtext; + const char *endingtext = NULL, *rankharder = NULL; if (marathonmode) + { endingtext = "THANKS FOR THE RUN!"; - else if (goodending) - endingtext = "CONGRATULATIONS!"; - else + } + else switch (evaluationtype) + { + case EVAL_PERFECT: + endingtext = "CONGRATULATIONS!"; + break; + case EVAL_SUPER: + rankharder = "Further challenge awaits!"; + break; + default: + rankharder = "...push your rank harder"; + break; + case EVAL_NOTHING: + rankharder = "Brave a higher difficulty"; + break; + } + + if (endingtext == NULL) endingtext = "TRY AGAIN..."; + if (usedCheats) + rankharder = "Cheated games can't unlock extras!"; + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + const INT32 gainaxtime = ((3*TICRATE)/2) - finalecount; + const INT32 sealtime = finalecount - (4*TICRATE); + INT32 crossfade = 0; + // Draw all the good crap here. - if (finalecount > 0 && useBlackRock) + x = BASEVIDWIDTH<<(FRACBITS-1); + y = (BASEVIDHEIGHT + 16)<<(FRACBITS-1); + + if (useSeal && evaluationtype != EVAL_PERFECT) { - INT32 scale = FRACUNIT; - patch_t *rockpat; - UINT8 *colormap[2] = {NULL, NULL}; - patch_t *glow; - INT32 trans = 0; + patch_t *sealpat; - x = (((BASEVIDWIDTH-82)/2)+11)< 0) { - scale = (finalecount<<(FRACBITS-2)); - x += (30*(FRACUNIT-scale)); - y += (30*(FRACUNIT-scale)); + // Stage 1 - blank + sealpat = W_CachePatchName( + "K_FINB01", + PU_PATCH_LOWPRIORITY + ); } - - if (goodending) + else if (sealtime < 0) { - rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH_LOWPRIORITY); - glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH_LOWPRIORITY); - x -= FRACUNIT; + // Stage 2 - Catcher Glow + sealpat = W_CachePatchName( + va("K_FINB0%u", 2+(finalecount & 1)), + PU_PATCH_LOWPRIORITY + ); + + crossfade = 10 + sealtime/3; } else { - rockpat = W_CachePatchName("ROID0000", PU_PATCH_LOWPRIORITY); - glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH_LOWPRIORITY); + // Stage 3 - Star Within The Seal + sealpat = W_CachePatchName( + "K_FINB05", + PU_PATCH_LOWPRIORITY + ); + +#define SEAL_PULSELEN (TICRATE) + crossfade = (sealtime % (2*SEAL_PULSELEN)) - SEAL_PULSELEN; + if (crossfade < 0) + crossfade = -crossfade; + crossfade = (crossfade * 10)/SEAL_PULSELEN; +#undef SEAL_PULSELEN } - if (finalecount >= 5) - trans = (finalecount-5)>>1; - if (trans < 10) - V_DrawFixedPatch(x, y, scale, trans< 0) + { + sealpat = W_CachePatchName( + "K_FINB04", + PU_PATCH_LOWPRIORITY + ); + + V_DrawFixedPatch( + x, y, + FRACUNIT, + (10-crossfade)<numframes - 2); + + if (refframes < 0) + ; // Not enough sprites + else if (gainaxtime <= refframes) + { + // Animation in progress! + + INT32 gainaxframe; + if (gainaxtime <= 0) + { + // Flicker + gainaxframe = refframes + (finalecount & 1); + } + else + { + // Shwing in + gainaxframe = (sprdef->numframes - 2) - gainaxtime; + } + + spriteframe_t *sprframe = &sprdef->spriteframes[gainaxframe]; + + if (sprframe->lumppat[0] != LUMPERROR) + { + V_DrawFixedPatch( + x, (y - (20*FRACUNIT)), + FRACUNIT/2, + V_ADD + |(crossfade<flip & 1) ? V_FLIP : 0), + W_CachePatchNum(sprframe->lumppat[0], PU_CACHE), + NULL + ); + } + } + } + +#if 0 + if (evaluationtype == EVAL_PERFECT) { INT32 j = (sparklloop & 1) ? 2 : 3; if (j > (finalecount/SPARKLLOOPTIME)) @@ -1003,33 +1123,94 @@ void F_GameEvaluationDrawer(void) j--; } } +#endif + } + + if ((evaluationtype == EVAL_CHAOS || evaluationtype == EVAL_SUPER) + && finalecount > 0) + { + INT32 gemtrans; + + if (useSeal && sealtime > 0) + { + // Stage 3 - aggressive overexposure + gemtrans = 3 + ((10 - crossfade)/3); + } + else if (useSeal && crossfade > 0) + { + // Stage 2 - some overexposure + gemtrans = (crossfade/3); + } else { - patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH_LOWPRIORITY); - V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); - if (trans < 10) - V_DrawFixedPatch(x, y, scale, trans<>ANGLETOFINESHIFT) & FINEMASK; + + V_DrawFixedPatch( + x + (75*FINECOSINE(fa)), y + (75*FINESINE(fa)), + FRACUNIT, + gemtrans, + empat, + R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_CHAOSEMERALD1+(i-basegem), GTC_CACHE) + ); } } - eemeralds_cur = (finalecount % 360)<>ANGLETOFINESHIFT) & FINEMASK; - x = (BASEVIDWIDTH<<(FRACBITS-1)) + (60*FINECOSINE(fa)); - y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + (60*FINESINE(fa)); - eemeralds_cur += (360<= KARTGP_MAX) + difficulty = KARTGP_MASTER; + + cupheader_t *cup; + UINT16 ret = 0; + + for (cup = kartcupheaders; cup; cup = cup->next) + { + if (cup->emeraldnum == 0) + continue; + + if (cup->windata[difficulty].got_emerald == false) + continue; + + ret |= 1<<(cup->emeraldnum-1); + } + + return ret; +} + // See also M_GetConditionString boolean M_CheckCondition(condition_t *cn, player_t *player) { @@ -791,30 +816,12 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) case UC_ALLSUPER: case UC_ALLEMERALDS: { - cupheader_t *cup; UINT16 ret = 0; - UINT8 i; if (gamestate == GS_LEVEL) return false; // this one could be laggy with many cups available - for (cup = kartcupheaders; cup; cup = cup->next) - { - if (cup->emeraldnum == 0) - continue; - - i = cn->requirement; - for (i = cn->requirement; i < KARTGP_MAX; i++) - { - if (cup->windata[i].got_emerald == true) - break; - } - - if (i == KARTGP_MAX) - continue; - - ret |= 1<<(cup->emeraldnum-1); - } + ret = M_CheckCupEmeralds(cn->requirement); if (cn->type == UC_ALLCHAOS) return ALLCHAOSEMERALDS(ret); diff --git a/src/m_cond.h b/src/m_cond.h index beb12d039..83207aad0 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -340,6 +340,7 @@ void M_ClearSecrets(void); void M_ClearStats(void); boolean M_NotFreePlay(player_t *player); +UINT16 M_CheckCupEmeralds(UINT8 difficulty); // Updating conditions and unlockables boolean M_ConditionInterpret(const char *password); From 45f8f1c89fb3190d186bc7a817cd9218a6e03a58 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 23 Jun 2023 23:16:09 +0100 Subject: [PATCH 12/23] Remove a bunch of unused emerald stuff inherited from SRB2 All superseded by M_CheckCupEmeralds + GTR_POWERSTONES stuff --- src/d_main.c | 1 - src/d_netcmd.c | 1 - src/doomstat.h | 2 -- src/g_game.c | 3 --- src/lua_script.c | 2 -- src/m_cheat.c | 23 ----------------------- src/menus/play-local-race-time-attack.c | 1 - src/p_mobj.h | 2 -- src/p_saveg.c | 2 -- src/p_setup.c | 4 ---- src/p_user.c | 1 - 11 files changed, 42 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 3df9d455f..dfacb1606 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -970,7 +970,6 @@ void D_ClearState(void) SplitScreen_OnChange(); cht_debug = 0; - emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); // In case someone exits out at the same time they start a time attack run, diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f391e83c1..d67f09325 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -6254,7 +6254,6 @@ void Command_ExitGame_f(void) SplitScreen_OnChange(); cht_debug = 0; - emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); if (dirmenu) diff --git a/src/doomstat.h b/src/doomstat.h index 00b8c9cf7..2fc4a3878 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -691,8 +691,6 @@ typedef enum EMERALD_ALL = EMERALD_ALLCHAOS|EMERALD_ALLSUPER } emeraldflags_t; -extern UINT16 emeralds; - #define ALLCHAOSEMERALDS(v) ((v & EMERALD_ALLCHAOS) == EMERALD_ALLCHAOS) #define ALLSUPEREMERALDS(v) ((v & EMERALD_ALLSUPER) == EMERALD_ALLSUPER) #define ALLEMERALDS(v) ((v & EMERALD_ALL) == EMERALD_ALL) diff --git a/src/g_game.c b/src/g_game.c index 491a14f02..b2081eacd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -140,8 +140,6 @@ boolean usedCheats = false; // Set when a "cheats on" is ever used. UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; boolean imcontinuing = false; -boolean runemeraldmanager = false; -UINT16 emeraldspawndelay = 60*TICRATE; // menu demo things UINT8 numDemos = 0; @@ -205,7 +203,6 @@ static boolean retryingmodeattack = false; UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage. -UINT16 emeralds; INT32 luabanks[NUM_LUABANKS]; // Temporary holding place for nights data for the current map diff --git a/src/lua_script.c b/src/lua_script.c index 4da776e55..ee0a5f5ba 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -394,8 +394,6 @@ int LUA_WriteGlobals(lua_State *L, const char *word) skincolor_redring = (UINT16)luaL_checkinteger(L, 2); else if (fastcmp(word, "skincolor_bluering")) skincolor_bluering = (UINT16)luaL_checkinteger(L, 2); - else if (fastcmp(word, "emeralds")) - emeralds = (UINT16)luaL_checkinteger(L, 2); else if (fastcmp(word, "gravity")) gravity = (fixed_t)luaL_checkinteger(L, 2); else if (fastcmp(word, "stoppedclock")) diff --git a/src/m_cheat.c b/src/m_cheat.c index 1f81c370f..17e85e775 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -469,29 +469,6 @@ void Command_Savecheckpoint_f(void) } } -// Like M_GetAllEmeralds() but for console devmode junkies. -/* -void Command_Getallemeralds_f(void) -{ - REQUIRE_CHEATS; - REQUIRE_SINGLEPLAYER; - - emeralds = EMERALD_ALL; - - CONS_Printf(M_GetText("You now have all 7 emeralds.\n")); -} - -void Command_Resetemeralds_f(void) -{ - REQUIRE_CHEATS; - REQUIRE_SINGLEPLAYER; - - emeralds = 0; - - CONS_Printf(M_GetText("Emeralds reset to zero.\n")); -} -*/ - // // Devmode // diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index ed5990587..701ec94c4 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -485,7 +485,6 @@ void M_StartTimeAttack(INT32 choice) // Still need to reset devmode cht_debug = 0; - emeralds = 0; if (demo.playback) G_StopDemo(); diff --git a/src/p_mobj.h b/src/p_mobj.h index df453b0c2..a531c456d 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -566,8 +566,6 @@ extern INT32 modulothing; #define MAXHUNTEMERALDS 64 extern mapthing_t *huntemeralds[MAXHUNTEMERALDS]; extern INT32 numhuntemeralds; -extern boolean runemeraldmanager; -extern UINT16 emeraldspawndelay; extern INT32 numstarposts; extern UINT16 bossdisabled; extern boolean stoppedclock; diff --git a/src/p_saveg.c b/src/p_saveg.c index f80ffff7b..1e88332e4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5622,7 +5622,6 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITESINT8(save->p, g_pickedVote); - WRITEUINT16(save->p, emeralds); { UINT8 globools = 0; if (stagefailed) @@ -5796,7 +5795,6 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading) g_pickedVote = READSINT8(save->p); - emeralds = READUINT16(save->p); { UINT8 globools = READUINT8(save->p); stagefailed = !!(globools & 1); diff --git a/src/p_setup.c b/src/p_setup.c index ee07ccf14..2abe1fef7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7351,10 +7351,6 @@ static void P_InitLevelSettings(void) K_TimerReset(); - // special stage tokens, emeralds, and ring total - runemeraldmanager = false; - emeraldspawndelay = 60*TICRATE; - nummaprings = 0; nummapboxes = numgotboxes = 0; maptargets = numtargets = 0; diff --git a/src/p_user.c b/src/p_user.c index 938bf96e1..ed8c06116 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -342,7 +342,6 @@ void P_GiveEmerald(boolean spawnObj) UINT8 em = P_GetNextEmerald(); S_StartSound(NULL, sfx_cgot); // Got the emerald! - emeralds |= (1 << em); stagefailed = false; if (spawnObj) From 4e81f341f7865d16e67d9e96fa28b20b8f7fa55d Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 24 Jun 2023 14:58:54 +0100 Subject: [PATCH 13/23] Perfect evaluation --- src/f_finale.c | 93 +++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 58 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index b4845cad6..91a5d8958 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -885,15 +885,6 @@ boolean F_CreditResponder(event_t *event) // EVALUATION // ============ -#if 0 - -static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles -static INT32 sparklloop; - -#define SPARKLLOOPTIME 7 // must be odd - -#endif - typedef enum { EVAL_NOTHING, @@ -948,7 +939,6 @@ void F_StartGameEvaluation(void) CON_ToggleOff(); finalecount = -1; - //sparklloop = 0; } void F_GameEvaluationDrawer(void) @@ -960,12 +950,13 @@ void F_GameEvaluationDrawer(void) if (marathonmode) { - endingtext = "THANKS FOR THE RUN!"; + endingtext = "COOL RUN!"; } else switch (evaluationtype) { case EVAL_PERFECT: - endingtext = "CONGRATULATIONS!"; + endingtext = "CONGRATULATIONS"; + rankharder = "You're too cool!"; break; case EVAL_SUPER: rankharder = "Further challenge awaits!"; @@ -995,7 +986,38 @@ void F_GameEvaluationDrawer(void) x = BASEVIDWIDTH<<(FRACBITS-1); y = (BASEVIDHEIGHT + 16)<<(FRACBITS-1); - if (useSeal && evaluationtype != EVAL_PERFECT) + if (!useSeal) + ; + else if (evaluationtype == EVAL_PERFECT) + { + // Symmetrical slow fade in and out. + if (finalecount > 5*TICRATE) + crossfade = (10*TICRATE) - finalecount; + else + crossfade = finalecount; + + crossfade = 10 - (crossfade * 10)/TICRATE; + if (crossfade < 0) + crossfade = 0; + + // Imagery of a shattered pink palanquin resting in the flowers + // (abandoned cage for a gemstone far above Earth's station) + // ~toast 240623 + if (crossfade != 10) + { + V_DrawFixedPatch( + x, y, + FRACUNIT, + crossfade< (finalecount/SPARKLLOOPTIME)) - j = (finalecount/SPARKLLOOPTIME); - while (j) - { - if (j > 1 || sparklloop >= 2) - { - // if j == 0 - alternate between 0 and 1 - // 1 - 1 and 2 - // 2 - 2 and not rendered - V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, - W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), - R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUAMARINE, GTC_CACHE)); - } - j--; - } - } -#endif } if ((evaluationtype == EVAL_CHAOS || evaluationtype == EVAL_SUPER) @@ -1229,29 +1229,6 @@ void F_GameEvaluationTicker(void) return; } -#if 0 - if (!useSeal) - ; - else if (evaluationtype != EVAL_PERFECT) - { - ; - } - else if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again - { - angle_t workingangle = FixedAngle((M_RandomKey(360))<>ANGLETOFINESHIFT; - fixed_t workingradius = M_RandomKey(26); - - sparkloffs[2][0] = sparkloffs[1][0]; - sparkloffs[2][1] = sparkloffs[1][1]; - sparkloffs[1][0] = sparkloffs[0][0]; - sparkloffs[1][1] = sparkloffs[0][1]; - - sparkloffs[0][0] = (30< Date: Sat, 24 Jun 2023 15:03:17 +0100 Subject: [PATCH 14/23] In DEVELOP builds, you can force a particular evaluation by setting cv_soundtest to the numerical equivalent of the evaluationtype_t you're looking for Replaces the previously uncommited recompilation-based hacks the author of this commit was using to test the previous ones on this branch - 1 is Nothing - 2 is Chaos Emerald - 3 is Super Emerald - 4 is Perfect - 5, 6, 7, etc currently repeat --- src/f_finale.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 91a5d8958..f5436546e 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -890,7 +890,8 @@ typedef enum EVAL_NOTHING, EVAL_CHAOS, EVAL_SUPER, - EVAL_PERFECT + EVAL_PERFECT, + EVAL_MAX } evaluationtype_t; static evaluationtype_t evaluationtype; @@ -899,7 +900,12 @@ UINT16 finaleemeralds = 0; void F_StartGameEvaluation(void) { // Credits option in extras menu - if (grandprixinfo.gp == false) + if ( + grandprixinfo.gp == false +#ifdef DEVELOP + && cv_soundtest.value == 0 +#endif + ) { S_FadeMusic(0, MUSICRATE/4); F_StartGameEnd(); @@ -925,6 +931,11 @@ void F_StartGameEvaluation(void) finaleemeralds = M_CheckCupEmeralds(difficulty); +#ifdef DEVELOP + if (cv_soundtest.value != 0) + evaluationtype = (cv_soundtest.value-1) % EVAL_MAX; + else +#endif if (difficulty == KARTSPEED_EASY) evaluationtype = EVAL_NOTHING; else if (!ALLCHAOSEMERALDS(finaleemeralds)) From 1b03e7a75cbc8e209c7b6748baf1ee417b4003db Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 25 Jun 2023 15:05:03 +0100 Subject: [PATCH 15/23] Evaluation changes - Add music to Perfect evaluation - Thank you darling Tyron :sob: - Different evaluation durations - 18 seconds for Perfect evaluation - Extended because the music is too good - 14 seconds for all other evaluation types - Extended so it's not almost half the length of the perfect one - Timed so the Seal can glow 5 times (instead of 3) --- src/f_finale.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index f5436546e..9f36b6302 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -894,11 +894,17 @@ typedef enum EVAL_MAX } evaluationtype_t; +#define EVALLEN_PERFECT (18*TICRATE) +#define EVALLEN_NORMAL (14*TICRATE) + static evaluationtype_t evaluationtype; UINT16 finaleemeralds = 0; void F_StartGameEvaluation(void) { + S_FadeMusic(0, MUSICRATE/4); + S_StopMusicCredit(); + // Credits option in extras menu if ( grandprixinfo.gp == false @@ -907,14 +913,10 @@ void F_StartGameEvaluation(void) #endif ) { - S_FadeMusic(0, MUSICRATE/4); F_StartGameEnd(); return; } - S_FadeOutStopMusic(5*MUSICRATE); - S_StopMusicCredit(); - G_SetGamestate(GS_EVALUATION); // Just in case they're open ... somehow @@ -1002,8 +1004,8 @@ void F_GameEvaluationDrawer(void) else if (evaluationtype == EVAL_PERFECT) { // Symmetrical slow fade in and out. - if (finalecount > 5*TICRATE) - crossfade = (10*TICRATE) - finalecount; + if (finalecount > EVALLEN_PERFECT/2) + crossfade = EVALLEN_PERFECT - finalecount; else crossfade = finalecount; @@ -1234,13 +1236,29 @@ void F_GameEvaluationDrawer(void) void F_GameEvaluationTicker(void) { - if (++finalecount > 10*TICRATE) + INT32 evallen = EVALLEN_NORMAL; + + if (evaluationtype == EVAL_PERFECT) + { + // tyron made something perfect and i would sooner + // smite everyone in this room starting with myself + // over the idea of cutting it ~toast 250623 + evallen = EVALLEN_PERFECT; + + if (finalecount == 1) + { + // Now start the music + S_ChangeMusicInternal("_SHORE", false); + } + } + + if (++finalecount > evallen) { F_StartGameEnd(); return; } - if (finalecount == 5*TICRATE) + if (finalecount == evallen/2) { if (!usedCheats) { @@ -1252,7 +1270,8 @@ void F_GameEvaluationTicker(void) } } -#undef SPARKLLOOPTIME +#undef EVALLEN_PERFECT +#undef EVALLEN_NORMAL // ========== // GAME END From 8cd3305a34e9374e26e056d4012d97cbeea43b2a Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 12:56:01 +0100 Subject: [PATCH 16/23] Cleaner Super Emerald drawing --- src/f_finale.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 9f36b6302..9899033cd 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1174,9 +1174,9 @@ void F_GameEvaluationDrawer(void) UINT8 basegem = (evaluationtype == EVAL_SUPER) ? 7 : 0; - for (i = basegem; i < (basegem+7); ++i, eemeralds_cur += (360<>ANGLETOFINESHIFT) & FINEMASK; @@ -1186,7 +1186,7 @@ void F_GameEvaluationDrawer(void) FRACUNIT, gemtrans, empat, - R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_CHAOSEMERALD1+(i-basegem), GTC_CACHE) + R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_CHAOSEMERALD1+i, GTC_CACHE) ); } } From 15d744c4e345f6d6969f588dc32c8809699379d0 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 13:33:28 +0100 Subject: [PATCH 17/23] M_CheckCupEmeralds: Only count the first instance of each Emerald in the cups This prevents custom cups from being counted as completing primary Sealed Star progression unless you wipe existing ones. --- src/m_cond.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/m_cond.c b/src/m_cond.c index 7229007dc..a152204eb 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -747,17 +747,29 @@ UINT16 M_CheckCupEmeralds(UINT8 difficulty) difficulty = KARTGP_MASTER; cupheader_t *cup; - UINT16 ret = 0; + UINT16 ret = 0, seen = 0; for (cup = kartcupheaders; cup; cup = cup->next) { - if (cup->emeraldnum == 0) + // Does it not *have* an emerald? + if (cup->emeraldnum == 0 || cup->emeraldnum > 14) continue; + UINT16 emerald = 1<<(cup->emeraldnum-1); + + // Only count the first reference. + if (seen & emerald) + continue; + + // We've seen it, prevent future repetitions. + seen |= emerald; + + // Did you actually get it? if (cup->windata[difficulty].got_emerald == false) continue; - ret |= 1<<(cup->emeraldnum-1); + // Wa hoo ! + ret |= emerald; } return ret; From 32eead29e5587d5cfb4cf69a3ae4d8d9089c8cbe Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 14:23:38 +0100 Subject: [PATCH 18/23] Quicker, almost instantaneous Sealed Star conclusion after death Also gets rid of the "wuu wuu wuu" sound from Competition that plays in this instance --- src/p_user.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ed8c06116..890f087d8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1436,7 +1436,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) { if (specialout == true) { - exitcountdown = TICRATE; + exitcountdown = 2; } else { @@ -1498,7 +1498,8 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) { UINT8 i; boolean givenlife = false; - const boolean dofinishsound = (musiccountdown == 0); + boolean dofinishsound = (musiccountdown == 0); + boolean specialout = specialstageinfo.valid; for (i = 0; i < MAXPLAYERS; i++) { @@ -1513,6 +1514,11 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) P_DoPlayerExit(&players[i], flags); + if (specialout && K_IsPlayerLosing(&players[i]) == false) + { + specialout = false; + } + if (trygivelife == false) { continue; @@ -1522,7 +1528,7 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) givenlife = true; } - if (!dofinishsound) + if (!dofinishsound || specialout) { // You've already finished, don't play again ; From 35df66f2b1bc7af00df4bc7537d2e4b3931265a6 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 15:34:48 +0100 Subject: [PATCH 19/23] Play music for normal Evaluations too Lumpname _DRIFT, implement later --- src/f_finale.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/f_finale.c b/src/f_finale.c index 9899033cd..48b95ad43 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1247,10 +1247,18 @@ void F_GameEvaluationTicker(void) if (finalecount == 1) { - // Now start the music + // sitting on that distant _shore S_ChangeMusicInternal("_SHORE", false); } } + else + { + if (finalecount == 1) + { + // _drift across open waters + S_ChangeMusicInternal("_DRIFT", false); + } + } if (++finalecount > evallen) { From d17399bccec5848a5e852fecc589ec41a9768d89 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 20:23:29 +0100 Subject: [PATCH 20/23] Revert "Quicker, almost instantaneous Sealed Star conclusion after death" This reverts commit 32eead29e5587d5cfb4cf69a3ae4d8d9089c8cbe. --- src/p_user.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 890f087d8..ed8c06116 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1436,7 +1436,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) { if (specialout == true) { - exitcountdown = 2; + exitcountdown = TICRATE; } else { @@ -1498,8 +1498,7 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) { UINT8 i; boolean givenlife = false; - boolean dofinishsound = (musiccountdown == 0); - boolean specialout = specialstageinfo.valid; + const boolean dofinishsound = (musiccountdown == 0); for (i = 0; i < MAXPLAYERS; i++) { @@ -1514,11 +1513,6 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) P_DoPlayerExit(&players[i], flags); - if (specialout && K_IsPlayerLosing(&players[i]) == false) - { - specialout = false; - } - if (trygivelife == false) { continue; @@ -1528,7 +1522,7 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) givenlife = true; } - if (!dofinishsound || specialout) + if (!dofinishsound) { // You've already finished, don't play again ; From defd8850922c0d193e213a1827b8d6828ee81b95 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 20:54:43 +0100 Subject: [PATCH 21/23] GP Backup tidy (connected to ending gamestate) - Handle removing GP Backups when any game end sequence is started, not just the Podium (in case no Podium exists) - Guarantee removal in M_StartCup out-of-entries failure state --- src/g_game.c | 2 ++ src/menus/transient/cup-select.c | 3 ++- src/p_setup.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index b2081eacd..b1f036edd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4651,6 +4651,8 @@ void G_EndGame(void) // Only do evaluation and credits in singleplayer contexts if (!netgame && grandprixinfo.gp == true) { + G_HandleSaveLevel(true); + if (nextmap == NEXTMAP_CEREMONY) // end game with ceremony { if (K_StartCeremony() == true) diff --git a/src/menus/transient/cup-select.c b/src/menus/transient/cup-select.c index f146cd74f..69e155592 100644 --- a/src/menus/transient/cup-select.c +++ b/src/menus/transient/cup-select.c @@ -155,7 +155,8 @@ static void M_StartCup(UINT8 entry) NULL, MM_NOTHING, NULL, NULL ); - G_HandleSaveLevel(true); + if (FIL_FileExists(gpbackup)) + remove(gpbackup); return; } diff --git a/src/p_setup.c b/src/p_setup.c index 2abe1fef7..e7c4e9fad 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8358,7 +8358,7 @@ void P_PostLoadLevel(void) P_RunCachedActions(); - G_HandleSaveLevel(gamestate == GS_CEREMONY); + G_HandleSaveLevel(false); if (marathonmode & MA_INGAME) { From c9817b957a604c6b4a0d71dcf4faa9cdaaffbe5f Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 26 Jun 2023 22:32:47 +0100 Subject: [PATCH 22/23] New unlockable type for watching the Credits from start to finish Also makes gamedata save/load a little more forward compatible longterm by making a UINT32 bitfield for various once-event flags, with increased minor version --- src/deh_soc.c | 1 + src/f_finale.c | 5 +++++ src/g_game.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- src/m_cond.c | 5 +++++ src/m_cond.h | 2 ++ 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 860d6ad0d..6bda19b5c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2583,6 +2583,7 @@ static void readcondition(UINT8 set, UINT32 id, char *word2) } } else if ((offset=0) || fastcmp(params[0], "ADDON") + || (++offset && fastcmp(params[0], "CREDITS")) || (++offset && fastcmp(params[0], "REPLAY")) || (++offset && fastcmp(params[0], "CRASH"))) { diff --git a/src/f_finale.c b/src/f_finale.c index 48b95ad43..98d0c15eb 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -808,6 +808,11 @@ void F_CreditTicker(void) { timetonext = 5*TICRATE+1; finalecount = 5*TICRATE; + + // You watched all the credits? What a trooper! + gamedata->everfinishedcredits = true; + if (M_UpdateUnlockablesAndExtraEmblems(true, true)) + G_SaveGameData(); } if (timetonext) diff --git a/src/g_game.c b/src/g_game.c index b1f036edd..6f6e3bc79 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4725,7 +4725,15 @@ void G_LoadGameSettings(void) } #define GD_VERSIONCHECK 0xBA5ED123 // Change every major version, as usual -#define GD_VERSIONMINOR 3 // Change every format update +#define GD_VERSIONMINOR 4 // Change every format update + +typedef enum +{ + GDEVER_ADDON = 1, + GDEVER_CREDITS = 1<<1, + GDEVER_REPLAY = 1<<2, + GDEVER_SPECIAL = 1<<3, +} gdeverdone_t; static const char *G_GameDataFolder(void) { @@ -4849,9 +4857,21 @@ void G_LoadGameData(void) gamedata->chaokeys = READUINT16(save.p); - gamedata->everloadedaddon = (boolean)READUINT8(save.p); - gamedata->eversavedreplay = (boolean)READUINT8(save.p); - gamedata->everseenspecial = (boolean)READUINT8(save.p); + if (versionMinor >= 4) + { + UINT32 everflags = READUINT32(save.p); + + gamedata->everloadedaddon = !!(everflags & GDEVER_ADDON); + gamedata->everfinishedcredits = !!(everflags & GDEVER_CREDITS); + gamedata->eversavedreplay = !!(everflags & GDEVER_REPLAY); + gamedata->everseenspecial = !!(everflags & GDEVER_SPECIAL); + } + else + { + gamedata->everloadedaddon = (boolean)READUINT8(save.p); + gamedata->eversavedreplay = (boolean)READUINT8(save.p); + gamedata->everseenspecial = (boolean)READUINT8(save.p); + } } else { @@ -5278,7 +5298,7 @@ void G_SaveGameData(void) 4+4+ (4*GDGT_MAX)+ 4+1+2+2+ - 1+1+1+ + 4+ 4+ (MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+ 4+2); @@ -5415,11 +5435,22 @@ void G_SaveGameData(void) WRITEUINT16(save.p, gamedata->keyspending); // 2 WRITEUINT16(save.p, gamedata->chaokeys); // 2 - WRITEUINT8(save.p, gamedata->everloadedaddon); // 1 - WRITEUINT8(save.p, gamedata->eversavedreplay); // 1 - WRITEUINT8(save.p, gamedata->everseenspecial); // 1 + { + UINT32 everflags = 0; - WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64)); + if (gamedata->everloadedaddon) + everflags |= GDEVER_ADDON; + if (gamedata->everfinishedcredits) + everflags |= GDEVER_CREDITS; + if (gamedata->eversavedreplay) + everflags |= GDEVER_REPLAY; + if (gamedata->everseenspecial) + everflags |= GDEVER_SPECIAL; + + WRITEUINT32(save.p, everflags); // 4 + } + + WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64)); // 4 // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) // MAXEMBLEMS * 1; diff --git a/src/m_cond.c b/src/m_cond.c index a152204eb..2e69a211f 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -610,6 +610,7 @@ void M_ClearStats(void) gamedata->timesBeaten = 0; gamedata->everloadedaddon = false; + gamedata->everfinishedcredits = false; gamedata->eversavedreplay = false; gamedata->everseenspecial = false; gamedata->evercrashed = false; @@ -854,6 +855,8 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) case UC_ADDON: return ((gamedata->everloadedaddon == true) && M_SecretUnlocked(SECRET_ADDONS, true)); + case UC_CREDITS: + return (gamedata->everfinishedcredits == true); case UC_REPLAY: return (gamedata->eversavedreplay == true); case UC_CRASH: @@ -1308,6 +1311,8 @@ static const char *M_GetConditionString(condition_t *cn) if (!M_SecretUnlocked(SECRET_ADDONS, true)) return NULL; return "load a custom addon into \"Dr. Robotnik's Ring Racers\""; + case UC_CREDITS: + return "watch the developer credits all the way from start to finish"; case UC_REPLAY: return "save a replay after finishing a round"; case UC_CRASH: diff --git a/src/m_cond.h b/src/m_cond.h index 83207aad0..e3975a957 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -52,6 +52,7 @@ typedef enum UC_CONDITIONSET, // CONDITIONSET [condition set number] UC_ADDON, // Ever loaded a custom file? + UC_CREDITS, // Finish watching the credits UC_REPLAY, // Save a replay UC_CRASH, // Hee ho ! @@ -287,6 +288,7 @@ struct gamedata_t // SPECIFIC SPECIAL EVENTS boolean everloadedaddon; + boolean everfinishedcredits; boolean eversavedreplay; boolean everseenspecial; boolean evercrashed; From 5fedd38965198884c03c6107daaf861397143aed Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 27 Jun 2023 00:16:09 +0100 Subject: [PATCH 23/23] Fix condition for G_GetBackupCupData focus to not include Match Race --- src/menus/transient/level-select.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c index a759f7c0b..13eed9aef 100644 --- a/src/menus/transient/level-select.c +++ b/src/menus/transient/level-select.c @@ -266,7 +266,7 @@ boolean M_LevelListFromGametype(INT16 gt) G_GetBackupCupData( cupgrid.grandprix == true - || cv_splitplayers.value <= 1 + && cv_splitplayers.value <= 1 ); templevelsearch.cup = kartcupheaders;