Skip to content
Merged
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
2 changes: 1 addition & 1 deletion source/include/item_location.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ class ItemLocation {
excludedOption = Option::Bool(settingText, { "Include", "Exclude" }, { desc });
}

Settings::excludeLocationsOptions.push_back(&excludedOption);
Settings::excludeLocationsOptionsVector[collectionCheckGroup].push_back(&excludedOption);
}

static auto Base(u8 scene, u8 flag, bool repeatable, std::string&& name, const HintKey hintKey, const ItemKey vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
Expand Down
1 change: 1 addition & 0 deletions source/include/menu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define POST_GENERATE 7
#define RESET_TO_DEFAULTS 8
#define MAX_MAINMENU_SETTINGS_ON_SCREEN 20
#define MAX_SUBMENUS_ON_SCREEN 27
#define MAX_SUBMENU_SETTINGS_ON_SCREEN 13
#define TOP_WIDTH 50
#define BOTTOM_WIDTH 40
Expand Down
21 changes: 19 additions & 2 deletions source/include/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,27 @@ class Menu {
Menu(std::string name_, MenuType type_, u8 mode_)
: name(std::move(name_)), type(type_), mode(mode_) {}

void ResetMenuIndex() {
if (mode == OPTION_SUB_MENU) {
for (size_t i = 0; i < settingsList->size(); i++) {
if (!settingsList->at(i)->IsLocked() && !settingsList->at(i)->IsHidden()) {
menuIdx = i;
settingBound = i;
return;
}
}
}
menuIdx = 0;
settingBound = 0;
}

std::string name;
MenuType type;
std::vector<Option *>* settingsList;
std::vector<Menu *>* itemsList;
u8 mode;
u16 menuIdx = 0;
u16 settingBound = 0;
int selectedSetting = 0;
bool printInSpoiler = true;
};
Expand All @@ -267,10 +282,11 @@ namespace Settings {
rnd::SettingsContext FillContext();
void InitSettings();
void SetDefaultSettings();
void ResolveExcludedLocationConflicts();
void RandomizeAllSettings(const bool selectOptions = false);
void ForceChange(u32 kDown, Option* currentSetting);
u8 StartingBottleConvert(u8 startingBottle);
const std::vector<Menu*> GetAllMenus();
const std::vector<Menu*> GetAllOptionMenus();
u32 CustomButtonConvert(u8 customButton);
bool CheckCustomButtons();

Expand Down Expand Up @@ -391,7 +407,8 @@ namespace Settings {
extern Option StartingFierceDeityMask;
extern Option StartingMaskOfTruth;
//Excluded Locations
extern std::vector<Option*> excludeLocationsOptions;
extern std::vector<std::vector<Option*>> excludeLocationsOptionsVector;
extern std::vector<Menu*> excludeLocationsMenu;

//Shuffle Settings
extern Option ShuffleMagicBeans;
Expand Down
45 changes: 26 additions & 19 deletions source/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ using namespace Settings;
namespace {
bool seedChanged;
u16 pastSeedLength;
u16 settingBound = 0;
PrintConsole topScreen, bottomScreen;
std::vector<std::string> presetEntries;
std::vector<Menu*> menuList;
Expand Down Expand Up @@ -49,8 +48,6 @@ void MenuInit() {
seedChanged = false;
pastSeedLength = Settings::seed.length();

settingBound = 0;

Menu* main = new Menu("Main", MenuType::MainMenu, &Settings::mainMenu, MAIN_MENU);
menuList.push_back(main);
currentMenu = main;
Expand Down Expand Up @@ -141,6 +138,12 @@ void MoveCursor(u32 kDown) {
} else if (currentMenu->menuIdx == 0xFFFF) {
currentMenu->menuIdx = max - 1;
}
//Scroll Check
if (currentMenu->menuIdx > currentMenu->settingBound + (MAX_SUBMENUS_ON_SCREEN - 1)) {
currentMenu->settingBound = currentMenu->menuIdx - (MAX_SUBMENUS_ON_SCREEN - 1);
} else if (currentMenu->menuIdx < currentMenu->settingBound) {
currentMenu->settingBound = currentMenu->menuIdx;
}
}
}

Expand Down Expand Up @@ -306,6 +309,10 @@ void UpdatePresetsMenu(u32 kDown) {
ClearDescription();
if (kDown & KEY_A && currentMenu->mode == LOAD_PRESET && !presetEntries.empty()) {
if (LoadPreset(presetEntries[currentMenu->menuIdx], OptionCategory::Setting)) {
Settings::ResolveExcludedLocationConflicts();
for (Menu* menu : Settings::GetAllOptionMenus()) {
menu->ResetMenuIndex();
}
printf("\x1b[24;5HPreset Loaded!");
} else {
printf("\x1b[24;5HFailed to load preset.");
Expand Down Expand Up @@ -344,7 +351,7 @@ void UpdateGenerateMenu(u32 kDown) {
void PrintMainMenu() {
printf("\x1b[0;%dHMain Settings", 1+(BOTTOM_WIDTH-13)/2);

for (u8 i = 0; i < MAX_MAINMENU_SETTINGS_ON_SCREEN; i++) {
for (u8 i = 0; i < MAX_SUBMENUS_ON_SCREEN; i++) {
if (i >= Settings::mainMenu.size()) break;

Menu* menu = Settings::mainMenu[i];
Expand All @@ -365,7 +372,7 @@ void PrintOptionSubMenu() {
//this is complicated to account for hidden settings and there's probably a better way to do it
u16 hiddenSettings = 0;
u16 visibleSettings = 0;
for (u16 i = settingBound; visibleSettings < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
for (u16 i = currentMenu->settingBound; visibleSettings < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
if (i >= currentMenu->settingsList->size()) {
break;
}
Expand All @@ -375,19 +382,19 @@ void PrintOptionSubMenu() {
visibleSettings++;
}
}
if (currentMenu->menuIdx >= settingBound + MAX_SUBMENU_SETTINGS_ON_SCREEN + hiddenSettings) {
settingBound = currentMenu->menuIdx;
if (currentMenu->menuIdx >= currentMenu->settingBound + MAX_SUBMENU_SETTINGS_ON_SCREEN + hiddenSettings) {
currentMenu->settingBound = currentMenu->menuIdx;
u8 offset = 0;
//skip over hidden settings
while (offset < MAX_SUBMENU_SETTINGS_ON_SCREEN - 1) {
settingBound--;
if (settingBound == 0) {
currentMenu->settingBound--;
if (currentMenu->settingBound == 0) {
break;
}
offset += currentMenu->settingsList->at(settingBound)->IsHidden() ? 0 : 1;
offset += currentMenu->settingsList->at(currentMenu->settingBound)->IsHidden() ? 0 : 1;
}
} else if (currentMenu->menuIdx < settingBound) {
settingBound = currentMenu->menuIdx;
} else if (currentMenu->menuIdx < currentMenu->settingBound) {
currentMenu->settingBound = currentMenu->menuIdx;
}

//print menu name
Expand All @@ -398,13 +405,13 @@ void PrintOptionSubMenu() {

for (u8 i = 0; i - hiddenSettings < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
//break if there are no more settings to print
if (i + settingBound >= currentMenu->settingsList->size()) break;
if (i + currentMenu->settingBound >= currentMenu->settingsList->size()) break;

Option* setting = currentMenu->settingsList->at(i + settingBound);
Option* setting = currentMenu->settingsList->at(i + currentMenu->settingBound);

u8 row = 3 + ((i - hiddenSettings) * 2);
//make the current setting green
if (currentMenu->menuIdx == i + settingBound) {
if (currentMenu->menuIdx == i + currentMenu->settingBound) {
printf("\x1b[%d;%dH%s>", row, 1, GREEN);
printf("\x1b[%d;%dH%s:", row, 2, setting->GetName().data());
printf("\x1b[%d;%dH%s%s", row, 26, setting->GetSelectedOptionText().data(), RESET);
Expand All @@ -428,16 +435,16 @@ void PrintOptionSubMenu() {
void PrintSubMenu() {
printf("\x1b[0;%dH%s", 1+(BOTTOM_WIDTH-currentMenu->name.length())/2, currentMenu->name.c_str());

for (u8 i = 0; i < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
for (u8 i = 0; i < MAX_SUBMENUS_ON_SCREEN; i++) {
if (i >= currentMenu->itemsList->size()) break;

u8 row = 3 + i;
//make the current menu green
if (currentMenu->menuIdx == i) {
if (currentMenu->menuIdx == currentMenu->settingBound + i) {
printf("\x1b[%d;%dH%s>", row, 2, GREEN);
printf("\x1b[%d;%dH%s%s", row, 3, currentMenu->itemsList->at(i)->name.c_str(), RESET);
printf("\x1b[%d;%dH%s%s", row, 3, currentMenu->itemsList->at(currentMenu->settingBound + i)->name.c_str(), RESET);
} else {
printf("\x1b[%d;%dH%s", row, 3, currentMenu->itemsList->at(i)->name.c_str());
printf("\x1b[%d;%dH%s", row, 3, currentMenu->itemsList->at(currentMenu->settingBound + i)->name.c_str());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion source/playthrough.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace Playthrough {
Settings::UpdateSettings();
//once the settings have been finalized turn them into a string for hashing
std::string settingsStr;
for (Menu* menu : Settings::GetAllMenus()) {
for (Menu* menu : Settings::GetAllOptionMenus()) {
//don't go through non-menus
if (menu->mode != OPTION_SUB_MENU) {
continue;
Expand Down
4 changes: 2 additions & 2 deletions source/preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ bool SavePreset(std::string_view presetName, OptionCategory category) {
XMLElement* rootNode = preset.NewElement("settings");
preset.InsertEndChild(rootNode);

for (Menu* menu : Settings::GetAllMenus()) {
for (Menu* menu : Settings::GetAllOptionMenus()) {
if (menu->mode != OPTION_SUB_MENU) {
continue;
}
Expand Down Expand Up @@ -155,7 +155,7 @@ bool LoadPreset(std::string_view presetName, OptionCategory category) {

XMLElement* curNode = rootNode->FirstChildElement();

for (Menu* menu : Settings::GetAllMenus()) {
for (Menu* menu : Settings::GetAllOptionMenus()) {
if (menu->mode != OPTION_SUB_MENU) {
continue;
}
Expand Down
95 changes: 83 additions & 12 deletions source/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,77 @@ namespace Settings {
};

//Excluded Locations (Individual definitions made in ItemLocation class)
std::vector<Option*> excludeLocationsOptions = {};
std::vector<std::vector<Option*>> excludeLocationsOptionsVector(SPOILER_COLLECTION_GROUP_COUNT);
Menu excludeClockTower = Menu::SubMenu("Clock Tower", &excludeLocationsOptionsVector[GROUP_INSIDE_CLOCKTOWER]);
Menu excludeSClockTown = Menu::SubMenu("South Clock Town", &excludeLocationsOptionsVector[GROUP_S_CLOCK_TOWN]);
Menu excludeLaundryPool = Menu::SubMenu("Laundry Pool", &excludeLocationsOptionsVector[GROUP_LAUNDRY_POOL]);
Menu excludeEClockTown = Menu::SubMenu("East Clock Town", &excludeLocationsOptionsVector[GROUP_E_CLOCK_TOWN]);
Menu excludeStockpotinn = Menu::SubMenu("Stockpotinn", &excludeLocationsOptionsVector[GROUP_STOCKPOTINN]);
Menu excludeWClockTown = Menu::SubMenu("West Clock Town", &excludeLocationsOptionsVector[GROUP_W_CLOCK_TOWN]);
Menu excludeNClockTown = Menu::SubMenu("North Clock Town", &excludeLocationsOptionsVector[GROUP_N_CLOCK_TOWN]);
Menu excludeTerminaField = Menu::SubMenu("Termina Field", &excludeLocationsOptionsVector[GROUP_TERMINA_FIELD]);
Menu excludeSouthernSwamp = Menu::SubMenu("Southern Swamp", &excludeLocationsOptionsVector[GROUP_SOUTHERN_SWAMP]);
Menu excludeDekuPalace = Menu::SubMenu("Deku Palace", &excludeLocationsOptionsVector[GROUP_DEKU_PALACE]);
Menu excludeWoodfall = Menu::SubMenu("Woodfall", &excludeLocationsOptionsVector [GROUP_WOODFALL]);
Menu excludeSnowhead = Menu::SubMenu("Snowhead", &excludeLocationsOptionsVector[GROUP_SNOWHEAD]);
Menu excludeMountainVillage = Menu::SubMenu("Mountain Village", &excludeLocationsOptionsVector[GROUP_MOUNTAIN_VILLAGE]);
Menu excludeTwinIslands = Menu::SubMenu("Twin Islands", &excludeLocationsOptionsVector[GROUP_TWIN_ISLANDS]);
Menu excludeGoronVillage = Menu::SubMenu("Goron Village", &excludeLocationsOptionsVector[GROUP_GORON_VILLAGE]);
Menu excludeMilkRoad = Menu::SubMenu("Milk Road", &excludeLocationsOptionsVector[GROUP_MILK_ROAD]);
Menu excludeRomaniRanch = Menu::SubMenu("Romani Ranch", &excludeLocationsOptionsVector[GROUP_ROMANI_RANCH]);
Menu excludeGreatBayCoast = Menu::SubMenu("Great Bay Coast", &excludeLocationsOptionsVector[GROUP_GREAT_BAY_COAST]);
Menu excludePinnacleRock = Menu::SubMenu("Pinnacle Rock", &excludeLocationsOptionsVector[GROUP_PINNACLE_ROCK]);
Menu excludeZoraCape = Menu::SubMenu("Zora Cape", &excludeLocationsOptionsVector[GROUP_ZORA_CAPE]);
Menu excludeZoraHall = Menu::SubMenu("Zora Hall", &excludeLocationsOptionsVector[GROUP_ZORA_HALL]);
Menu excludeIkanaCanyon = Menu::SubMenu("Ikana Canyon", &excludeLocationsOptionsVector[GROUP_IKANA_CANYON]);
Menu excludeIkanaGraveyard = Menu::SubMenu("Ikana Graveyard", &excludeLocationsOptionsVector[GROUP_IKANA_GRAVEYARD]);
Menu excludeStoneTower = Menu::SubMenu("Stone Tower", &excludeLocationsOptionsVector[GROUP_STONE_TOWER]);
Menu excludeDungeonWoodfallTemple = Menu::SubMenu("Woodfall Temple", &excludeLocationsOptionsVector[GROUP_DUNGEON_WOODFALL_TEMPLE]);
Menu excludeDungeonSnowheadTemple = Menu::SubMenu("Snowhead Temple", &excludeLocationsOptionsVector[GROUP_DUNGEON_SNOWHEAD_TEMPLE]);
Menu excludeDungeonGreatBay = Menu::SubMenu("Great Bay Temple", &excludeLocationsOptionsVector[GROUP_DUNGEON_GREAT_BAY]);
Menu excludeDungeonStoneTower = Menu::SubMenu("Stone Tower Temple", &excludeLocationsOptionsVector[GROUP_DUNGEON_STONE_TOWER]);
Menu excludeDungeonPirateFortress = Menu::SubMenu("Pirate Fortress", &excludeLocationsOptionsVector[GROUP_DUNGEON_PIRATE_FORTRESS]);
Menu excludeDungeonBeneathTheWell = Menu::SubMenu("Beneath the Well", &excludeLocationsOptionsVector[GROUP_DUNGEON_BENEATH_THE_WELL]);
Menu excludeDungeonIkanaCastle = Menu::SubMenu("Ikana Castle", &excludeLocationsOptionsVector[GROUP_DUNGEON_IKANA_CASTLE]);
Menu excludeDungeonSecretShrine = Menu::SubMenu("Secret Shrine", &excludeLocationsOptionsVector[GROUP_DUNGEON_SECRET_SHRINE]);
Menu excludeDungeonTheMoon = Menu::SubMenu("The Moon", &excludeLocationsOptionsVector[GROUP_DUNGEON_THE_MOON]);
Menu excludeSwampSkulltulaHouse = Menu::SubMenu("Swamp Skulltula House", &excludeLocationsOptionsVector[GROUP_SWAMP_SKULLTULA_HOUSE]);
Menu excludeOceanSkulltulaHouse = Menu::SubMenu("Ocean Skulltula House", &excludeLocationsOptionsVector[GROUP_OCEAN_SKULLTULA_HOUSE]);
std::vector<Menu*> excludeLocationsMenu = {
&excludeClockTower,
&excludeSClockTown,
&excludeLaundryPool,
&excludeEClockTown,
&excludeStockpotinn,
&excludeWClockTown,
&excludeNClockTown,
&excludeTerminaField,
&excludeSouthernSwamp,
&excludeDekuPalace,
&excludeWoodfall,
&excludeSnowhead,
&excludeMountainVillage,
&excludeTwinIslands,
&excludeGoronVillage,
&excludeMilkRoad,
&excludeRomaniRanch,
&excludeGreatBayCoast,
&excludePinnacleRock,
&excludeZoraCape,
&excludeZoraHall,
&excludeIkanaCanyon,
&excludeIkanaGraveyard,
&excludeStoneTower,
&excludeDungeonWoodfallTemple,
&excludeDungeonSnowheadTemple,
&excludeDungeonGreatBay,
&excludeDungeonStoneTower,
&excludeDungeonPirateFortress,
&excludeDungeonBeneathTheWell,
&excludeDungeonIkanaCastle,
&excludeDungeonSecretShrine,
&excludeDungeonTheMoon,
};

//Overworld Shuffle Settings
Option ShuffleMainInventory = Option::Bool("Shuffle Main Inventory",{"Off", "On"}, {shuffleMainInventoryDesc}, OptionCategory::Toggle, 1);
Expand Down Expand Up @@ -592,7 +662,7 @@ namespace Settings {
Menu logicSettings = Menu::SubMenu("Logic Options", &logicOptions);
Menu tricks = Menu::SubMenu("Logical Tricks", &trickOptions, false);
Menu startingInventory = Menu::SubMenu("Starting Inventory", &startingInventoryMenu, false);
Menu excludeLocations = Menu::SubMenu("Exclude Locations", &excludeLocationsOptions, false);
Menu excludeLocations = Menu::SubMenu("Exclude Locations", &excludeLocationsMenu, false);
Menu glitchSettings = Menu::SubMenu("Glitch Options", &glitchOptions, false);
Menu otherSettings = Menu::SubMenu("Other Settings", &otherSettingsOptions, false);
Menu gameSettings = Menu::SubMenu("Game Settings", &gameOptions);
Expand Down Expand Up @@ -1105,8 +1175,10 @@ namespace Settings {
for (auto op : cosmeticOptions) {
op->SetToDefault();
}
for (auto op : excludeLocationsOptions) {
op->SetToDefault();
for (auto menu : excludeLocationsMenu) {
for (auto op : *menu->settingsList) {
op->SetToDefault();
}
}
for (auto op : startingInventoryOptions) {
op->SetToDefault();
Expand Down Expand Up @@ -1162,14 +1234,13 @@ namespace Settings {
for (auto op : customButtons) {
op->SetToDefault();
}
//Don't let users exclude these locations
//TODO: Make sure the defaults are set appropriately for these?
//Also TODO: make sure some checks cant be skpped?
// Location(HC_ZELDAS_LETTER)->GetExcludedOption()->Hide();
// Location(MARKET_BOMBCHU_BOWLING_BOMBCHUS)->GetExcludedOption()->Hide();
//Location(GANON)->GetExcludedOption()->Hide();

SetDefaultCosmetics();

ResolveExcludedLocationConflicts();
for (Menu* menu : Settings::GetAllOptionMenus()) {
menu->ResetMenuIndex();
}
}

//Include and Lock the desired locations
Expand Down Expand Up @@ -1215,7 +1286,7 @@ namespace Settings {
//menu if the player's current settings would require non-junk to be placed
//at those locations. Excluded locations will have junk placed at them.

static void ResolveExcludedLocationConflicts() {
void ResolveExcludedLocationConflicts() {

//For now, just always hide shop locations, as not sure how to handle hiding them-
//1-4 should always be hidden, while the others should be settings dependent, but random shopsanity makes that more complicated...
Expand Down Expand Up @@ -1825,7 +1896,7 @@ namespace Settings {
}

//Recursively look through each menu from the main menu to get all settings
const std::vector<Menu*> GetAllMenus() {
const std::vector<Menu*> GetAllOptionMenus() {
std::vector<Menu*> allMenus;
for (Menu* menu : Settings::mainMenu) {
std::vector<Menu*> foundMenus = GetMenusRecursive(menu);
Expand Down
18 changes: 10 additions & 8 deletions source/spoiler_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ static tinyxml2::XMLElement* CreateCollapseCheckbox(tinyxml2::XMLDocument& spoil
static void WriteSettings(tinyxml2::XMLDocument& spoilerLog, const bool printAll = false) {
auto parentNode = spoilerLog.NewElement("settings");

std::vector<Menu*> allMenus = Settings::GetAllMenus();
std::vector<Menu*> allMenus = Settings::GetAllOptionMenus();

for (const Menu* menu : allMenus) {
//This is a menu of settings, write them
Expand All @@ -488,14 +488,16 @@ static void WriteSettings(tinyxml2::XMLDocument& spoilerLog, const bool printAll
static void WriteExcludedLocations(tinyxml2::XMLDocument& spoilerLog) {
auto parentNode = spoilerLog.NewElement("excluded-locations");

for (const auto& location : Settings::excludeLocationsOptions) {
if (location->GetSelectedOptionIndex() == (u8)ExcludeLocationSetting::INCLUDE) {
continue;
for (size_t i = 1; i < Settings::excludeLocationsOptionsVector.size(); i++) {
for (const auto& location : Settings::excludeLocationsOptionsVector[i]) {
if (location->GetSelectedOptionIndex() == (u8)ExcludeLocationSetting::INCLUDE) {
continue;
}

tinyxml2::XMLElement* node = spoilerLog.NewElement("location");
node->SetAttribute("name", SanitizedString(location->GetName()).c_str());
parentNode->InsertEndChild(node);
}

tinyxml2::XMLElement* node = spoilerLog.NewElement("location");
node->SetAttribute("name", SanitizedString(location->GetName()).c_str());
parentNode->InsertEndChild(node);
}

if (!parentNode->NoChildren()) {
Expand Down