diff --git a/src/d_main.c b/src/d_main.c index aa79e6584..dfacb1606 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -464,22 +464,12 @@ static void D_Display(void) } break; - case GS_ENDING: - F_EndingDrawer(); - HU_Erase(); - HU_Drawer(); - break; - case GS_CUTSCENE: F_CutsceneDrawer(); HU_Erase(); HU_Drawer(); break; - case GS_GAMEEND: - F_GameEndDrawer(); - break; - case GS_EVALUATION: F_GameEvaluationDrawer(); HU_Erase(); @@ -980,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 bb1efe6f2..15daae677 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -6300,7 +6300,6 @@ void Command_ExitGame_f(void) SplitScreen_OnChange(); cht_debug = 0; - emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); if (dirmenu) diff --git a/src/deh_soc.c b/src/deh_soc.c index eb30c33ed..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"))) { @@ -3120,13 +3121,13 @@ 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")) { - 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 +3138,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")) @@ -3365,14 +3366,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; @@ -3438,6 +3431,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 +3541,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,9 +3554,16 @@ 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, "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) @@ -3558,6 +3571,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/deh_tables.c b/src/deh_tables.c index 6aa24dfad..26b0ae763 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6851,9 +6851,7 @@ 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}, {"GS_DEDICATEDSERVER",GS_DEDICATEDSERVER}, {"GS_WAITINGPLAYERS",GS_WAITINGPLAYERS}, diff --git a/src/doomstat.h b/src/doomstat.h index e6787116e..2fc4a3878 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 @@ -401,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 }; @@ -687,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) @@ -744,7 +746,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 a6f4fb900..98d0c15eb 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -129,18 +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 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; - // // PROMPT STATE // @@ -820,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) @@ -897,33 +890,73 @@ boolean F_CreditResponder(event_t *event) // EVALUATION // ============ -#define SPARKLLOOPTIME 7 // must be odd +typedef enum +{ + EVAL_NOTHING, + EVAL_CHAOS, + EVAL_SUPER, + EVAL_PERFECT, + 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 (cursaveslot == -1) + if ( + grandprixinfo.gp == false +#ifdef DEVELOP + && cv_soundtest.value == 0 +#endif + ) { - S_FadeOutStopMusic(2*MUSICRATE); F_StartGameEnd(); return; } - S_FadeOutStopMusic(5*MUSICRATE); - 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); + +#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)) + 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; } void F_GameEvaluationDrawer(void) @@ -931,113 +964,271 @@ 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 + { + endingtext = "COOL RUN!"; + } + else switch (evaluationtype) + { + case EVAL_PERFECT: + endingtext = "CONGRATULATIONS"; + rankharder = "You're too cool!"; + 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) + ; + else if (evaluationtype == EVAL_PERFECT) { - INT32 scale = FRACUNIT; - patch_t *rockpat; - UINT8 *colormap[2] = {NULL, NULL}; - patch_t *glow; - INT32 trans = 0; + // Symmetrical slow fade in and out. + if (finalecount > EVALLEN_PERFECT/2) + crossfade = EVALLEN_PERFECT - finalecount; + else + crossfade = finalecount; - x = (((BASEVIDWIDTH-82)/2)+11)< 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 1 - blank + sealpat = W_CachePatchName( + "K_FINB01", + PU_PATCH_LOWPRIORITY + ); + } + else if (sealtime < 0) + { + // 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) { - INT32 j = (sparklloop & 1) ? 2 : 3; - if (j > (finalecount/SPARKLLOOPTIME)) - j = (finalecount/SPARKLLOOPTIME); - while (j) + 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) { - if (j > 1 || sparklloop >= 2) + // Animation in progress! + + INT32 gainaxframe; + if (gainaxtime <= 0) { - // 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)); + // 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 + ); } - j--; } } + } + + 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, 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< 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) + { + // sitting on that distant _shore + S_ChangeMusicInternal("_SHORE", false); + } + } + else + { + if (finalecount == 1) + { + // _drift across open waters + S_ChangeMusicInternal("_DRIFT", false); + } + } + + if (++finalecount > evallen) { F_StartGameEnd(); return; } - if (!useBlackRock) - ; - else if (!goodending) - { - if (sparklloop) - sparklloop--; - - if (finalecount == (5*TICRATE)/2 - || finalecount == (7*TICRATE)/2 - || finalecount == ((7*TICRATE)/2)+5) - { - S_StartSound(NULL, sfx_s3k5c); - sparklloop = 10; - } - } - 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< 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< 0) - { - timetonext--; - } - else - { - nextmap = NEXTMAP_TITLE; - G_EndGame(); - } -} - - // ============== // TITLE SCREEN // ============== diff --git a/src/f_finale.h b/src/f_finale.h index 56691a847..af71edafe 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); @@ -54,9 +52,6 @@ void F_GameEvaluationDrawer(void); void F_StartGameEvaluation(void); void F_GameEvaluationTicker(void); -void F_EndingTicker(void); -void F_EndingDrawer(void); - void F_CreditTicker(void); void F_CreditDrawer(void); @@ -173,10 +168,8 @@ enum wipe_menu_toblack, wipe_credits_toblack, wipe_evaluation_toblack, - wipe_gameend_toblack, wipe_ceremony_toblack, wipe_intro_toblack, - wipe_ending_toblack, wipe_cutscene_toblack, // Specialized wipes @@ -192,10 +185,8 @@ enum wipe_menu_final, wipe_credits_final, wipe_evaluation_final, - wipe_gameend_final, wipe_ceremony_final, wipe_intro_final, - wipe_ending_final, wipe_cutscene_final, // custom intermissions diff --git a/src/f_wipe.c b/src/f_wipe.c index 105358407..5a1df0e96 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -63,10 +63,8 @@ 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) 99, // wipe_cutscene_toblack (hardcoded) 72, // wipe_encore_toinvert @@ -80,10 +78,8 @@ 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) 99 // wipe_cutscene_final (hardcoded) }; @@ -98,10 +94,8 @@ 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) true, // wipe_cutscene_toblack (hardcoded) false, // wipe_encore_toinvert @@ -115,10 +109,8 @@ 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) true // wipe_cutscene_final (hardcoded) }; @@ -133,10 +125,8 @@ 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) false, // wipe_cutscene_toblack (hardcoded) true, // wipe_encore_toinvert @@ -150,10 +140,8 @@ 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) false // wipe_cutscene_final (hardcoded) }; @@ -168,10 +156,8 @@ 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) false, // wipe_cutscene_toblack (hardcoded) false, // wipe_encore_toinvert @@ -185,10 +171,8 @@ 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) false // wipe_cutscene_final (hardcoded) }; @@ -203,10 +187,8 @@ 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) false, // wipe_cutscene_toblack (hardcoded) false, // wipe_encore_toinvert @@ -220,10 +202,8 @@ 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) true // wipe_cutscene_final (hardcoded) }; diff --git a/src/g_game.c b/src/g_game.c index 1b3dfa770..6f6e3bc79 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 @@ -264,7 +261,7 @@ UINT8 maxXtraLife = 2; // Max extra lives from rings UINT8 introtoplay; UINT8 creditscutscene; -UINT8 useBlackRock = 1; +UINT8 useSeal = 1; // Emerald locations mobj_t *hunt1; @@ -1785,7 +1782,7 @@ boolean G_Responder(event_t *ev) return true; } } - else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here? + else if (gamestate == GS_CREDITS) { if (HU_Responder(ev)) { @@ -1813,7 +1810,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; } @@ -1822,11 +1829,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)) @@ -2322,23 +2324,12 @@ void G_Ticker(boolean run) F_IntroTicker(); break; - case GS_ENDING: - if (run) - F_EndingTicker(); - HU_Ticker(); - break; - case GS_CUTSCENE: if (run) F_CutsceneTicker(); HU_Ticker(); break; - case GS_GAMEEND: - if (run) - F_GameEndTicker(); - break; - case GS_EVALUATION: if (run) F_GameEvaluationTicker(); @@ -3387,10 +3378,6 @@ void G_ExitLevel(void) // Don't save demos immediately here! Let standings write first } - else if (gamestate == GS_ENDING) - { - F_StartCredits(); - } else if (gamestate == GS_CREDITS) { F_StartGameEvaluation(); @@ -4664,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) @@ -4736,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) { @@ -4860,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 { @@ -5289,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); @@ -5426,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/g_state.h b/src/g_state.h index b78105639..52a77dcb5 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -35,12 +35,10 @@ 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 GS_INTRO, // introduction - GS_ENDING, // currently shared between bad and good endings GS_CUTSCENE, // custom cutscene // Not fadable diff --git a/src/info.c b/src/info.c index 3d1ec5bb8..0940b3ac1 100644 --- a/src/info.c +++ b/src/info.c @@ -8134,8 +8134,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 diff --git a/src/k_hud.c b/src/k_hud.c index 91fc27daa..ecfbc6e59 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -5440,7 +5440,7 @@ void K_drawKartHUD(void) { if (gametyperules & GTR_CIRCUIT) { - if (numlaps > 1) + if (numlaps != 1) { K_drawKartLaps(); gametypeinfoshown = true; diff --git a/src/k_menu.h b/src/k_menu.h index 921e0ecea..3e3294f2e 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1055,6 +1055,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/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: 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) { 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/m_cond.c b/src/m_cond.c index 1bbdef711..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; @@ -738,6 +739,43 @@ boolean M_NotFreePlay(player_t *player) return false; } +UINT16 M_CheckCupEmeralds(UINT8 difficulty) +{ + if (difficulty == 0) + return 0; + + if (difficulty >= KARTGP_MAX) + difficulty = KARTGP_MASTER; + + cupheader_t *cup; + UINT16 ret = 0, seen = 0; + + for (cup = kartcupheaders; cup; cup = cup->next) + { + // 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; + + // Wa hoo ! + ret |= emerald; + } + + return ret; +} + // See also M_GetConditionString boolean M_CheckCondition(condition_t *cn, player_t *player) { @@ -791,30 +829,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); @@ -835,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: @@ -1289,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 beb12d039..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; @@ -340,6 +342,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); 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 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/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/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; 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 d759da6af..8806af267 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5662,7 +5662,6 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITESINT8(save->p, g_pickedVote); - WRITEUINT16(save->p, emeralds); { UINT8 globools = 0; if (stagefailed) @@ -5836,7 +5835,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..e7c4e9fad 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; @@ -8362,7 +8358,7 @@ void P_PostLoadLevel(void) P_RunCachedActions(); - G_HandleSaveLevel(gamestate == GS_CEREMONY); + G_HandleSaveLevel(false); if (marathonmode & MA_INGAME) { 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; diff --git a/src/p_user.c b/src/p_user.c index c4535efb8..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) @@ -714,12 +713,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 +793,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 +831,8 @@ void P_EndingMusic(void) } } +skippingposition: + if (nointer == true) { // Do not set "racent" in G_Ticker