Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 82 additions & 6 deletions soh/soh/SohGui/SohMenuEnhancements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <soh/OTRGlobals.h>
#include <soh/Enhancements/cosmetics/authenticGfxPatches.h>
#include <soh/Enhancements/TimeDisplay/TimeDisplay.h>
#include <soh/ResourceManagerHelpers.h>

extern "C" {
#include "functions.h"
Expand Down Expand Up @@ -135,6 +136,28 @@ static const std::map<int32_t, const char*> mirroredWorldModes = {
{ MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" },
};

static uint8_t CountVisibleFileSelectQuests() {
uint8_t count = 0;

if (ResourceMgr_GameHasOriginal() && !CVarGetInteger(CVAR_ENHANCEMENT("HideNormalQuest"), 0)) {
count++;
}

if (ResourceMgr_GameHasMasterQuest() && !CVarGetInteger(CVAR_ENHANCEMENT("HideMasterQuest"), 0)) {
count++;
}

if (!CVarGetInteger(CVAR_ENHANCEMENT("HideRandomizerQuest"), 0)) {
count++;
}

if (!CVarGetInteger(CVAR_ENHANCEMENT("HideBossRushQuest"), 0)) {
count++;
}

return count;
}

void SohMenu::AddMenuEnhancements() {
// Add Enhancements Menu
AddMenuEntry("Enhancements", CVAR_SETTING("Menu.EnhancementsSidebarSection"));
Expand Down Expand Up @@ -674,22 +697,75 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"))
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip("Always shows dungeon entrance icons on the Minimap."));
AddWidget(path, "More Info in File Select", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FileSelectMoreInfo"))
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip(
"Shows what items you have collected in the File Select screen, like in N64 Randomizer."));
AddWidget(path, "Better Ammo Rendering in Pause Menu", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("BetterAmmoRendering"))
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip(
"Ammo counts in the pause menu will work correctly regardless of the position of items in the Inventory."));
AddWidget(path, "Enable Passage of Time on File Select", WIDGET_CVAR_CHECKBOX)

AddWidget(path, "File Select", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "More Info", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("FileSelectMoreInfo"))
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip(
"Shows what items you have collected in the File Select screen, like in N64 Randomizer."));
AddWidget(path, "Enable Passage of Time", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("TimeFlowFileSelect"))
.RaceDisable(false)
.Options(CheckboxOptions().Tooltip("The skybox in the background of the File Select screen will go through the "
"day and night cycle over time."));

AddWidget(path, "Hide Original", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("HideNormalQuest"))
.RaceDisable(false)
.PreFunc([](const WidgetInfo& info) {
if (!ResourceMgr_GameHasOriginal()) {
info.options->disabled = true;
info.options->disabledTooltip = "This option requires a loaded original O2R.";
} else if (CountVisibleFileSelectQuests() <= 1 && !CVarGetInteger(CVAR_ENHANCEMENT("HideNormalQuest"), 0)) {
info.options->disabled = true;
info.options->disabledTooltip = "At least one quest type must remain visible.";
}
})
.Options(CheckboxOptions().Tooltip(
"Hides the original game when selecting a quest type on the File Select screen."));
AddWidget(path, "Hide Master Quest", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("HideMasterQuest"))
.RaceDisable(false)
.PreFunc([](const WidgetInfo& info) {
if (!ResourceMgr_GameHasMasterQuest()) {
info.options->disabled = true;
info.options->disabledTooltip = "This option requires a loaded Master Quest O2R.";
} else if (CountVisibleFileSelectQuests() <= 1 && !CVarGetInteger(CVAR_ENHANCEMENT("HideMasterQuest"), 0)) {
info.options->disabled = true;
info.options->disabledTooltip = "At least one quest type must remain visible.";
}
})
.Options(CheckboxOptions().Tooltip(
"Hides the Master Quest option when selecting a quest type on the File Select screen."));
AddWidget(path, "Hide Randomizer", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("HideRandomizerQuest"))
.RaceDisable(false)
.PreFunc([](const WidgetInfo& info) {
if (CountVisibleFileSelectQuests() <= 1 && !CVarGetInteger(CVAR_ENHANCEMENT("HideRandomizerQuest"), 0)) {
info.options->disabled = true;
info.options->disabledTooltip = "At least one quest type must remain visible.";
}
})
.Options(CheckboxOptions().Tooltip(
"Hides the Randomizer option when selecting a quest type on the File Select screen."));
AddWidget(path, "Hide Boss Rush", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("HideBossRushQuest"))
.RaceDisable(false)
.PreFunc([](const WidgetInfo& info) {
if (CountVisibleFileSelectQuests() <= 1 && !CVarGetInteger(CVAR_ENHANCEMENT("HideBossRushQuest"), 0)) {
info.options->disabled = true;
info.options->disabledTooltip = "At least one quest type must remain visible.";
}
})
.Options(CheckboxOptions().Tooltip(
"Hides the Boss Rush option when selecting a quest type on the File Select screen."));

path.column = SECTION_COLUMN_3;
AddWidget(path, "Misc.", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "N64 Mode", WIDGET_CVAR_CHECKBOX)
Expand Down
133 changes: 92 additions & 41 deletions soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,40 @@
#define MIN_QUEST (ResourceMgr_GameHasOriginal() ? QUEST_NORMAL : QUEST_MASTER)
#define MAX_QUEST QUEST_BOSSRUSH

// #region SOH [Enhancement] - Hide Quest Modes
static bool IsQuestSkipped(uint8_t quest) {
if (quest == QUEST_NORMAL && CVarGetInteger(CVAR_ENHANCEMENT("HideNormalQuest"), 0)) {
return true;
}

if (quest == QUEST_MASTER && (!ResourceMgr_GameHasMasterQuest() ||
CVarGetInteger(CVAR_ENHANCEMENT("HideMasterQuest"), 0))) {
return true;
}

if (quest == QUEST_RANDOMIZER && CVarGetInteger(CVAR_ENHANCEMENT("HideRandomizerQuest"), 0)) {
return true;
}

if (quest == QUEST_BOSSRUSH && CVarGetInteger(CVAR_ENHANCEMENT("HideBossRushQuest"), 0)) {
return true;
}

return false;
}

static uint8_t CountVisibleQuests(void) {
uint8_t count = 0;
for (int32_t quest = MIN_QUEST; quest <= MAX_QUEST; ++quest) {
if (!IsQuestSkipped(quest)) {
count++;
}
}

return count;
}
// #endregion

void Sram_InitDebugSave(void);
void Sram_InitBossRushSave();

Expand Down Expand Up @@ -640,27 +674,38 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {

FileChoose_UpdateRandomizer();

if (ABS(this->stickRelX) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DRIGHT))) {
// #region SOH [Enhancement] - Hide Quest Modes
// If the current quest type was hidden after being selected (i.e., CVar changed while on the quest menu), advance
// to the next visible one.
while (IsQuestSkipped(this->questType[this->buttonIndex])) {
this->questType[this->buttonIndex] += 1;
if (this->questType[this->buttonIndex] > MAX_QUEST) {
this->questType[this->buttonIndex] = MIN_QUEST;
}
}
// #endregion

// #region SOH [Enhancement] - Hide Quest Modes
if (CountVisibleQuests() > 1 && ABS(this->stickRelX) > 30 || (dpad && CHECK_BTN_ANY(input->press.button,
BTN_DLEFT | BTN_DRIGHT))) {
// Cycle through quest types, skipping any that are hidden (i.e., Master Quest without O2R,
// Randomizer/Boss Rush when their CVars are set). Wraps around if past min/max.
if (this->stickRelX > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT))) {
this->questType[this->buttonIndex] += 1;
while (this->questType[this->buttonIndex] == QUEST_MASTER && !ResourceMgr_GameHasMasterQuest()) {
// If Master Quest is selected without a Master Quest OTR present, skip past it.
do {
this->questType[this->buttonIndex] += 1;
}
if (this->questType[this->buttonIndex] > MAX_QUEST) {
this->questType[this->buttonIndex] = MIN_QUEST;
}
} while (IsQuestSkipped(this->questType[this->buttonIndex]));
} else if (this->stickRelX < -30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT))) {
this->questType[this->buttonIndex] -= 1;
while (this->questType[this->buttonIndex] == QUEST_MASTER && !ResourceMgr_GameHasMasterQuest()) {
// If Master Quest is selected without a Master Quest OTR present, skip past it.
do {
this->questType[this->buttonIndex] -= 1;
}
}

// If current buttonIndex is higher or lower than the min/max value, wrap around.
if (this->questType[this->buttonIndex] > MAX_QUEST) {
this->questType[this->buttonIndex] = MIN_QUEST;
} else if (this->questType[this->buttonIndex] < MIN_QUEST) {
this->questType[this->buttonIndex] = MAX_QUEST;
if (this->questType[this->buttonIndex] < MIN_QUEST) {
this->questType[this->buttonIndex] = MAX_QUEST;
}
} while (IsQuestSkipped(this->questType[this->buttonIndex]));
}
// #endregion

Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CURSOR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
Expand Down Expand Up @@ -1718,31 +1763,37 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
if ((this->configMode == CM_QUEST_MENU) || (this->configMode == CM_START_QUEST_MENU) ||
this->configMode == CM_NAME_ENTRY_TO_QUEST_MENU ||
this->configMode == CM_NAME_ENTRY_TO_RANDOMIZER_SETTINGS_MENU) {
// draw control stick prompts.
Gfx_SetupDL_39Opa(this->state.gfxCtx);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 24, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.arrowColorR, this->stickLeftPrompt.arrowColorG,
this->stickLeftPrompt.arrowColorB, this->stickLeftPrompt.arrowColorA,
this->stickLeftPrompt.arrowTexX, this->stickLeftPrompt.arrowTexY,
this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.arrowColorR,
this->stickRightPrompt.arrowColorG, this->stickRightPrompt.arrowColorB,
this->stickRightPrompt.arrowColorA, this->stickRightPrompt.arrowTexX,
this->stickRightPrompt.arrowTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
gDPLoadTextureBlock(POLY_OPA_DISP++, gControlStickTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.stickColorR, this->stickLeftPrompt.stickColorG,
this->stickLeftPrompt.stickColorB, this->stickLeftPrompt.stickColorA,
this->stickLeftPrompt.stickTexX, this->stickLeftPrompt.stickTexY,
this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.stickColorR,
this->stickRightPrompt.stickColorG, this->stickRightPrompt.stickColorB,
this->stickRightPrompt.stickColorA, this->stickRightPrompt.stickTexX,
this->stickRightPrompt.stickTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
// #region SOH [Enhancement] - Hide Quest Modes
// Only draw the control stick prompts and arrows when there's more than one quest to cycle through.
if (CountVisibleQuests() > 1) {
// #endregion
// draw control stick prompts.
Gfx_SetupDL_39Opa(this->state.gfxCtx);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPLoadTextureBlock(POLY_OPA_DISP++, gArrowCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 24, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.arrowColorR, this->stickLeftPrompt.arrowColorG,
this->stickLeftPrompt.arrowColorB, this->stickLeftPrompt.arrowColorA,
this->stickLeftPrompt.arrowTexX, this->stickLeftPrompt.arrowTexY,
this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.arrowColorR,
this->stickRightPrompt.arrowColorG, this->stickRightPrompt.arrowColorB,
this->stickRightPrompt.arrowColorA, this->stickRightPrompt.arrowTexX,
this->stickRightPrompt.arrowTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
gDPLoadTextureBlock(POLY_OPA_DISP++, gControlStickTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickLeftPrompt.stickColorR, this->stickLeftPrompt.stickColorG,
this->stickLeftPrompt.stickColorB, this->stickLeftPrompt.stickColorA,
this->stickLeftPrompt.stickTexX, this->stickLeftPrompt.stickTexY,
this->stickLeftPrompt.z, 0, 0, -1.0f, 1.0f);
FileChoose_DrawTextRec(this->state.gfxCtx, this->stickRightPrompt.stickColorR,
this->stickRightPrompt.stickColorG, this->stickRightPrompt.stickColorB,
this->stickRightPrompt.stickColorA, this->stickRightPrompt.stickTexX,
this->stickRightPrompt.stickTexY, this->stickRightPrompt.z, 0, 0, 1.0f, 1.0f);
}

switch (this->questType[this->buttonIndex]) {
case QUEST_NORMAL:
default:
Expand Down