From 060c03f011ca0910e1bcb9d29e38bf32a5f8bd4f Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 23 Jun 2023 23:13:25 +0100 Subject: [PATCH] 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);