diff --git a/src/k_menu.h b/src/k_menu.h index 588542002..5a314ab0a 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -398,12 +398,15 @@ extern menu_t EXTRAS_ReplayStartDef; extern menuitem_t PAUSE_Main[]; extern menu_t PAUSE_MainDef; +// EXTRAS +extern menuitem_t MISC_Manual[]; +extern menu_t MISC_ManualDef; + extern menuitem_t MISC_Addons[]; extern menu_t MISC_AddonsDef; -// MANUAL -extern menuitem_t MISC_Manual[]; -extern menu_t MISC_ManualDef; +extern menuitem_t MISC_Challenges[]; +extern menu_t MISC_ChallengesDef; // We'll need this since we're gonna have to dynamically enable and disable options depending on which state we're in. typedef enum @@ -1076,6 +1079,25 @@ void M_DrawReplayStartMenu(void); #define LOCATIONSTRING2 "Visit \x88SRB2.ORG/MODS\x80 to get & make addons!" void M_DrawAddons(void); +// Challenges menu: +#define UNLOCKTIME 35 + +// Keep track of some pause menu data for visual goodness. +extern struct challengesmenu_s { + + tic_t ticker; // How long the menu's been open for + INT16 offset; // To make the icons move smoothly when we transition! + + UINT8 currentunlock; + tic_t unlockanim; + + boolean pending; +} challengesmenu; + +void M_DrawChallenges(void); +void M_ChallengesTick(void); +boolean M_ChallengesInputs(INT32 ch); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(source, prev, x, y)\ {\ diff --git a/src/k_menudef.c b/src/k_menudef.c index f080ff4e5..9e10560a3 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -1744,3 +1744,24 @@ menu_t MISC_AddonsDef = { NULL, NULL }; + +// Challenges. +menuitem_t MISC_ChallengesMenu[] = +{ + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, +}; + +menu_t MISC_ChallengesDef = { + sizeof (MISC_ChallengesMenu)/sizeof (menuitem_t), + &MainDef, + 0, + MISC_ChallengesMenu, + 48, 80, + 0, 0, + 98, 0, + M_DrawChallenges, + M_ChallengesTick, + NULL, + NULL, + M_ChallengesInputs, +}; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 6c2c2029e..48652c6f9 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -4457,3 +4457,28 @@ void M_DrawAddons(void) } #undef addonsseperation + +void M_DrawChallenges(void) +{ + INT32 x, y; + + { + patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); + V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); + } + + if (challengesmenu.currentunlock < MAXUNLOCKABLES) + { + V_DrawThinString(currentMenu->x, currentMenu->y, V_ALLOWLOWERCASE, unlockables[challengesmenu.currentunlock].name); + + if (challengesmenu.unlockanim >= UNLOCKTIME) + V_DrawThinString(currentMenu->x, currentMenu->y + 10, V_ALLOWLOWERCASE, "Press (A)"); + } + else + { + V_DrawThinString(currentMenu->x, currentMenu->y, V_ALLOWLOWERCASE, va("pending = %c", challengesmenu.pending ? 'T' : 'F')); + + if (challengesmenu.unlockanim >= UNLOCKTIME) + V_DrawThinString(currentMenu->x, currentMenu->y + 10, V_ALLOWLOWERCASE, "Press (B)"); + } +} diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 39f94a1d9..a696a8eb8 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -775,6 +775,20 @@ static boolean M_PrevOpt(void) return true; } + static menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu) +{ + M_UpdateUnlockablesAndExtraEmblems(false); + + if (M_GetNextAchievedUnlock(false) < MAXUNLOCKABLES) + { + challengesmenu.pending = true; + challengesmenu.currentunlock = MAXUNLOCKABLES; + return &MISC_ChallengesDef; + } + + return desiredmenu; +} + // // M_Responder // @@ -981,7 +995,7 @@ void M_StartControlPanel(void) } else { - currentMenu = &MainDef; + currentMenu = M_InterruptMenuWithChallenges(&MainDef); } } else @@ -4811,7 +4825,7 @@ static void M_FirstPickProfile(INT32 c) optionsmenu.profile = NULL; // Make sure to get rid of that, too. PR_ApplyProfile(optionsmenu.profilen, 0); - M_SetupNextMenu(&MainDef, false); + M_SetupNextMenu(M_InterruptMenuWithChallenges(&MainDef), false); // Tell the game this is the last profile we picked. CV_StealthSetValue(&cv_ttlprofilen, optionsmenu.profilen); @@ -6807,3 +6821,53 @@ void M_Manual(INT32 choice) MISC_ManualDef.prevMenu = (choice == INT32_MAX ? NULL : currentMenu); M_SetupNextMenu(&MISC_ManualDef, true); } + +struct challengesmenu_s challengesmenu; + +void M_ChallengesTick(void) +{ + challengesmenu.ticker++; + + if (challengesmenu.pending && challengesmenu.currentunlock >= MAXUNLOCKABLES) + { + if ((challengesmenu.currentunlock = M_GetNextAchievedUnlock(true)) >= MAXUNLOCKABLES) + challengesmenu.pending = false; + } + else if (challengesmenu.unlockanim >= UNLOCKTIME) + { + ; + } + else + { + challengesmenu.unlockanim++; + } +} + +boolean M_ChallengesInputs(INT32 ch) +{ + const UINT8 pid = 0; + boolean start = M_MenuButtonPressed(pid, MBT_START); + (void) ch; + + if (challengesmenu.unlockanim < UNLOCKTIME) + { + ; + } + else if (challengesmenu.pending) + { + if ((M_MenuConfirmPressed(pid) || start)) + { + challengesmenu.currentunlock = MAXUNLOCKABLES; + challengesmenu.unlockanim = 0; + } + return true; + } + else if (M_MenuBackPressed(pid) || start) + { + M_GoBack(0); + M_SetMenuDelay(pid); + return true; + } + + return true; +} diff --git a/src/m_cond.c b/src/m_cond.c index 79dd92d2a..68ec3e206 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -261,12 +261,12 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud) continue; } - if ((gamedata->unlocked[i] = M_Achieved(unlockables[i].conditionset - 1)) == false) + if (gamedata->unlocked[i] == true) { continue; } - if (unlockables[i].nocecho) + if (M_Achieved(unlockables[i].conditionset - 1) == false) { continue; } @@ -281,6 +281,7 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud) // Announce if (cechoLines && loud) { + strcat(cechoText, "Return to main menu to see"); #ifdef DEVELOP // todo make debugmode CONS_Printf("%s\n", cechoText); @@ -290,6 +291,39 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud) return false; } +UINT8 M_GetNextAchievedUnlock(boolean set) +{ + UINT8 i; + + // Go through unlockables + for (i = 0; i < MAXUNLOCKABLES; ++i) + { + if (gamedata->unlocked[i] || !unlockables[i].conditionset) + { + continue; + } + + if (gamedata->unlocked[i] == true) + { + continue; + } + + if (M_Achieved(unlockables[i].conditionset - 1) == false) + { + continue; + } + + if (set) + { + gamedata->unlocked[i] = true; + } + + return i; + } + + return MAXUNLOCKABLES; +} + // Emblem unlocking shit UINT8 M_CheckLevelEmblems(void) { diff --git a/src/m_cond.h b/src/m_cond.h index 4df268277..e60ae6f31 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -182,6 +182,7 @@ void M_ClearSecrets(void); void M_CheckUnlockConditions(void); UINT8 M_CheckCondition(condition_t *cn); boolean M_UpdateUnlockablesAndExtraEmblems(boolean silent); +UINT8 M_GetNextAchievedUnlock(boolean set); UINT8 M_CheckLevelEmblems(void); UINT8 M_CompletionEmblems(void);