mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-04-23 08:14:31 +00:00
2963 lines
217 KiB
C++
2963 lines
217 KiB
C++
#include "settings.h"
|
|
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
|
#include "trial.h"
|
|
#include "dungeon.h"
|
|
#include "3drando/random.hpp"
|
|
|
|
#include "soh/OTRGlobals.h"
|
|
|
|
#include <spdlog/spdlog.h>
|
|
|
|
#include <libultraship/bridge/consolevariablebridge.h>
|
|
#include <libultraship/libultraship.h>
|
|
|
|
namespace Rando {
|
|
std::shared_ptr<Settings> Settings::mInstance;
|
|
|
|
std::vector<std::string> NumOpts(const int min, const int max, const int step = 1, const std::string& textBefore = {},
|
|
const std::string& textAfter = {}) {
|
|
std::vector<std::string> options;
|
|
options.reserve((max - min) / step + 1);
|
|
for (int i = min; i <= max; i += step) {
|
|
options.push_back(textBefore + std::to_string(i) += textAfter);
|
|
}
|
|
return options;
|
|
}
|
|
|
|
std::vector<std::string> MultiVecOpts(const std::vector<std::vector<std::string>>& optionsVector) {
|
|
size_t totalSize = 0;
|
|
for (const auto& vector : optionsVector) {
|
|
totalSize += vector.size();
|
|
}
|
|
std::vector<std::string> options;
|
|
options.reserve(totalSize);
|
|
for (const auto& vector : optionsVector) {
|
|
for (const auto& op : vector) {
|
|
options.push_back(op);
|
|
}
|
|
}
|
|
return options;
|
|
}
|
|
|
|
void Settings::HandleShopsanityPriceUI() {
|
|
bool isTycoon = CVarGetInteger(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), RO_GENERIC_OFF);
|
|
mOptions[RSK_SHOPSANITY].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_SHOPSANITY_PRICES].Unhide();
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_PRICE_VANILLA)) {
|
|
case RO_PRICE_FIXED:
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].Unhide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].GetOptionCount() == 501
|
|
: mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].GetOptionCount() == 1000) {
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].ChangeOptions(isTycoon ? NumOpts(0, 999) : NumOpts(0, 500));
|
|
}
|
|
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Hide();
|
|
break;
|
|
case RO_PRICE_RANGE:
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].Unhide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].Unhide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].GetOptionCount() == 101
|
|
: mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].GetOptionCount() == 200) {
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
}
|
|
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
case RO_PRICE_SET_BY_WALLET:
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT].Unhide();
|
|
if (isTycoon) {
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Unhide();
|
|
} else {
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
}
|
|
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
}
|
|
}
|
|
|
|
Settings::Settings() : mExcludeLocationsOptionsAreas(RCAREA_INVALID) {
|
|
}
|
|
|
|
#define OPT_U8(rsk, ...) mOptions[rsk] = Option::U8(rsk, __VA_ARGS__)
|
|
#define OPT_BOOL(rsk, ...) mOptions[rsk] = Option::Bool(rsk, __VA_ARGS__)
|
|
#define OPT_TRICK(rsk, ...) mTrickSettings[rsk] = TrickSetting::LogicTrick(rsk, __VA_ARGS__)
|
|
// All callbacks will be called once when the widget is Added (on boot, essentially) and
|
|
// once when the widget is interacted with such that the value was changed.
|
|
#define OPT_CALLBACK(rsk, body) mOptions[rsk].SetCallback([this](WidgetInfo & info) body)
|
|
#define OPT_CALLBACK_FN(rsk, fn) mOptions[rsk].SetCallback(fn)
|
|
|
|
void Settings::HandleMixedEntrancePoolsUI() {
|
|
bool dungeonShuffle =
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
|
|
bool bossShuffle =
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
|
|
bool overworldShuffle = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF);
|
|
bool interiorShuffle = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_GENERIC_OFF);
|
|
bool grottoShuffle = CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF);
|
|
bool thievesHideoutShuffle =
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleThievesHideoutEntrances"), RO_GENERIC_OFF);
|
|
|
|
// Hide Mixed Entrances option if 1 or no applicable entrance shuffles are visible
|
|
if (dungeonShuffle + bossShuffle + overworldShuffle + interiorShuffle + grottoShuffle + thievesHideoutShuffle <=
|
|
1) {
|
|
mOptions[RSK_MIXED_ENTRANCE_POOLS].Hide();
|
|
} else {
|
|
mOptions[RSK_MIXED_ENTRANCE_POOLS].Unhide();
|
|
}
|
|
}
|
|
|
|
void Settings::HandleStartingAgeUI() {
|
|
// Starting Age - Disabled under very specific conditions unless it's No Logic
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LogicRules"), RO_LOGIC_GLITCHLESS) != RO_LOGIC_NO_LOGIC &&
|
|
// If Closed DoT requires OoT then we can only start as child
|
|
((CVarGetInteger(CVAR_RANDOMIZER_SETTING("DoorOfTime"), RO_DOOROFTIME_CLOSED) == RO_DOOROFTIME_CLOSED &&
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), RO_GENERIC_OFF) == RO_GENERIC_OFF) ||
|
|
// If Forest is Closed, we cannot start as Adult unless there's a sphere 0 entrance shuffle in Kokiri forest,
|
|
// or there's random spawns, as the player may saveload as child and get stuck.
|
|
// Grottos only lead somewhere if decoupled
|
|
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_ON) == RO_CLOSED_FOREST_ON &&
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), RO_GENERIC_OFF) == RO_GENERIC_OFF &&
|
|
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) &&
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF &&
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF))) {
|
|
mOptions[RSK_STARTING_AGE].Disable("This option is disabled due to other options making the game unbeatable.");
|
|
} else {
|
|
mOptions[RSK_STARTING_AGE].Enable();
|
|
}
|
|
}
|
|
|
|
void Settings::CreateOptions() {
|
|
CreateOptionDescriptions();
|
|
// clang-format off
|
|
OPT_U8(RSK_FOREST, "Closed Forest", {"On", "Deku Only", "Off"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ClosedForest"), mOptionDescriptions[RSK_FOREST], WIDGET_CVAR_COMBOBOX, RO_CLOSED_FOREST_ON);
|
|
OPT_CALLBACK(RSK_FOREST, {
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_U8(RSK_KAK_GATE, "Kakariko Gate", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("KakarikoGate"), mOptionDescriptions[RSK_KAK_GATE]);
|
|
OPT_U8(RSK_DOOR_OF_TIME, "Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WIDGET_CVAR_COMBOBOX);
|
|
OPT_CALLBACK(RSK_DOOR_OF_TIME, {
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_U8(RSK_ZORAS_FOUNTAIN, "Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]);
|
|
OPT_U8(RSK_SLEEPING_WATERFALL, "Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]);
|
|
OPT_U8(RSK_JABU_OPEN, "Jabu-Jabu", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("JabuJabu"), mOptionDescriptions[RSK_JABU_OPEN]);
|
|
OPT_BOOL(RSK_LOCK_OVERWORLD_DOORS, "Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]);
|
|
OPT_U8(RSK_GERUDO_FORTRESS, "Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]);
|
|
OPT_CALLBACK(RSK_GERUDO_FORTRESS, {
|
|
const uint8_t maxKeyringCount =
|
|
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), RO_GF_CARPENTERS_NORMAL) ==
|
|
RO_GF_CARPENTERS_NORMAL &&
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)
|
|
? 9
|
|
: 8;
|
|
if (mOptions[RSK_KEYRINGS_RANDOM_COUNT].GetOptionCount() != maxKeyringCount + 1) {
|
|
mOptions[RSK_KEYRINGS_RANDOM_COUNT].ChangeOptions(NumOpts(0, maxKeyringCount));
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), RO_GF_CARPENTERS_NORMAL) !=
|
|
RO_GF_CARPENTERS_NORMAL ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA) {
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Disable(
|
|
"Disabled because the currently selected Gerudo Fortress Carpenters\n"
|
|
"setting and/or Gerudo Fortress Keys setting is incompatible with\n"
|
|
"having a Gerudo Fortress Keyring.");
|
|
} else {
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Enable();
|
|
}
|
|
});
|
|
OPT_U8(RSK_RAINBOW_BRIDGE, "Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WIDGET_CVAR_COMBOBOX, RO_BRIDGE_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_RAINBOW_BRIDGE, {
|
|
mOptions[RSK_BRIDGE_OPTIONS].Hide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Hide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Hide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Hide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Hide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Hide();
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_VANILLA)) {
|
|
case RO_BRIDGE_STONES:
|
|
// Show Bridge Options and Stone Count slider
|
|
mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_BRIDGE_OPTIONS].Unhide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].Unhide();
|
|
break;
|
|
case RO_BRIDGE_MEDALLIONS:
|
|
// Show Bridge Options and Medallion Count Slider
|
|
mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_BRIDGE_OPTIONS].Unhide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].Unhide();
|
|
break;
|
|
case RO_BRIDGE_DUNGEON_REWARDS:
|
|
// Show Bridge Options and Dungeon Reward Count Slider
|
|
mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_BRIDGE_OPTIONS].Unhide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].Unhide();
|
|
break;
|
|
case RO_BRIDGE_DUNGEONS:
|
|
// Show Bridge Options and Dungeon Count Slider
|
|
mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_BRIDGE_OPTIONS].Unhide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].Unhide();
|
|
break;
|
|
case RO_BRIDGE_TOKENS:
|
|
// Show token count slider (not bridge options)
|
|
mOptions[RSK_RAINBOW_BRIDGE].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_BRIDGE_OPTIONS].Hide();
|
|
mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT].Unhide();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_RAINBOW_BRIDGE_STONE_COUNT, "Bridge Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WIDGET_CVAR_SLIDER_INT, 3, true);
|
|
OPT_U8(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT, "Bridge Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MedallionCount"), "", WIDGET_CVAR_SLIDER_INT, 6, true);
|
|
OPT_U8(RSK_RAINBOW_BRIDGE_REWARD_COUNT, "Bridge Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RewardCount"), "", WIDGET_CVAR_SLIDER_INT, 9, true);
|
|
OPT_U8(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT, "Bridge Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DungeonCount"), "", WIDGET_CVAR_SLIDER_INT, 8, true);
|
|
OPT_U8(RSK_RAINBOW_BRIDGE_TOKEN_COUNT, "Bridge Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TokenCount"), "", WIDGET_CVAR_SLIDER_INT, 100, true);
|
|
OPT_U8(RSK_BRIDGE_OPTIONS, "Bridge Reward Options", {"Standard Rewards", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), mOptionDescriptions[RSK_BRIDGE_OPTIONS], WIDGET_CVAR_COMBOBOX, RO_BRIDGE_STANDARD_REWARD, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_BRIDGE_OPTIONS, {
|
|
const uint8_t bridgeOpt = CVarGetInteger(CVAR_RANDOMIZER_SETTING("BridgeRewardOptions"), RO_BRIDGE_STANDARD_REWARD);
|
|
if (bridgeOpt == RO_BRIDGE_GREG_REWARD) {
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].GetOptionCount() == 4) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].ChangeOptions(NumOpts(0, 4));
|
|
}
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].GetOptionCount() == 7) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 7));
|
|
}
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].GetOptionCount() == 10) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].ChangeOptions(NumOpts(0, 10));
|
|
}
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].GetOptionCount() == 9) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 9));
|
|
}
|
|
} else {
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].GetOptionCount() == 5) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT].ChangeOptions(NumOpts(0, 3));
|
|
}
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].GetOptionCount() == 8) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 6));
|
|
}
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].GetOptionCount() == 11) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT].ChangeOptions(NumOpts(0, 9));
|
|
}
|
|
if (mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].GetOptionCount() == 10) {
|
|
mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 8));
|
|
}
|
|
}
|
|
});
|
|
OPT_U8(RSK_GANONS_TRIALS, "Ganon's Trials", {"Skip", "Set Number", "Random Number"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrial"), mOptionDescriptions[RSK_GANONS_TRIALS], WIDGET_CVAR_COMBOBOX, RO_GANONS_TRIALS_SET_NUMBER);
|
|
OPT_CALLBACK(RSK_GANONS_TRIALS, {
|
|
// Only show the trial count slider if Trials is set to Set Number
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GanonTrial"), RO_GANONS_TRIALS_SET_NUMBER) ==
|
|
RO_GANONS_TRIALS_SET_NUMBER) {
|
|
mOptions[RSK_TRIAL_COUNT].Unhide();
|
|
} else {
|
|
mOptions[RSK_TRIAL_COUNT].Hide();
|
|
}
|
|
});
|
|
OPT_U8(RSK_TRIAL_COUNT, "Ganon's Trials Count", {NumOpts(0, 6)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanonTrialCount"), mOptionDescriptions[RSK_TRIAL_COUNT], WIDGET_CVAR_SLIDER_INT, 6, true);
|
|
OPT_BOOL(RSK_MEDALLION_LOCKED_TRIALS, "Medallion Locked Trials", CVAR_RANDOMIZER_SETTING("MedallionLockedTrials"), mOptionDescriptions[RSK_MEDALLION_LOCKED_TRIALS]);
|
|
OPT_U8(RSK_STARTING_AGE, "Starting Age", {"Child", "Adult", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WIDGET_CVAR_COMBOBOX, RO_AGE_CHILD);
|
|
OPT_U8(RSK_SELECTED_STARTING_AGE, "Selected Starting Age", {"Child", "Adult"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SelectedStartingAge"), mOptionDescriptions[RSK_STARTING_AGE], WIDGET_CVAR_COMBOBOX, RO_AGE_CHILD);
|
|
OPT_BOOL(RSK_SHUFFLE_ENTRANCES, "Shuffle Entrances");
|
|
OPT_U8(RSK_SHUFFLE_DUNGEON_ENTRANCES, "Dungeon Entrances", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_ENTRANCES], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_DUNGEON_ENTRANCES, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) ==
|
|
RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_DUNGEON_ENTRANCES].Hide();
|
|
} else {
|
|
mOptions[RSK_MIX_DUNGEON_ENTRANCES].Unhide();
|
|
}
|
|
});
|
|
OPT_U8(RSK_SHUFFLE_BOSS_ENTRANCES, "Boss Entrances", {"Off", "Age Restricted", "Full"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), mOptionDescriptions[RSK_SHUFFLE_BOSS_ENTRANCES], WIDGET_CVAR_COMBOBOX, RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_BOSS_ENTRANCES, {
|
|
HandleMixedEntrancePoolsUI();
|
|
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) == RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
|
|
mOptions[RSK_SHUFFLE_GANONS_TOWER_ENTRANCE].Hide();
|
|
} else {
|
|
mOptions[RSK_SHUFFLE_GANONS_TOWER_ENTRANCE].Unhide();
|
|
}
|
|
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) ==
|
|
RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_BOSS_ENTRANCES].Hide();
|
|
} else {
|
|
mOptions[RSK_MIX_BOSS_ENTRANCES].Unhide();
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE, "Ganon's Tower Entrance", CVAR_RANDOMIZER_SETTING("ShuffleGanonTowerEntrance"), mOptionDescriptions[RSK_SHUFFLE_GANONS_TOWER_ENTRANCE]);
|
|
OPT_BOOL(RSK_SHUFFLE_OVERWORLD_ENTRANCES, "Overworld Entrances", CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_OVERWORLD_ENTRANCES, {
|
|
HandleMixedEntrancePoolsUI();
|
|
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Hide();
|
|
} else {
|
|
mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Unhide();
|
|
}
|
|
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_U8(RSK_SHUFFLE_INTERIOR_ENTRANCES, "Interior Entrances", {"Off", "Simple", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), mOptionDescriptions[RSK_SHUFFLE_INTERIOR_ENTRANCES], WIDGET_CVAR_COMBOBOX, RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_INTERIOR_ENTRANCES, {
|
|
HandleMixedEntrancePoolsUI();
|
|
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_INTERIOR_ENTRANCES].Hide();
|
|
} else {
|
|
mOptions[RSK_MIX_INTERIOR_ENTRANCES].Unhide();
|
|
}
|
|
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES, "Thieves' Hideout Entrances", CVAR_RANDOMIZER_SETTING("ShuffleThievesHideoutEntrances"), mOptionDescriptions[RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES, {
|
|
HandleMixedEntrancePoolsUI();
|
|
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleThievesHideoutEntrances"), RO_GENERIC_OFF) ==
|
|
RO_GENERIC_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES].Hide();
|
|
} else {
|
|
mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES].Unhide();
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_GROTTO_ENTRANCES, "Grottos Entrances", CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), mOptionDescriptions[RSK_SHUFFLE_GROTTO_ENTRANCES]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_GROTTO_ENTRANCES, {
|
|
HandleMixedEntrancePoolsUI();
|
|
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_GROTTO_ENTRANCES].Hide();
|
|
} else {
|
|
mOptions[RSK_MIX_GROTTO_ENTRANCES].Unhide();
|
|
}
|
|
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_OWL_DROPS, "Owl Drops", CVAR_RANDOMIZER_SETTING("ShuffleOwlDrops"), mOptionDescriptions[RSK_SHUFFLE_OWL_DROPS]);
|
|
OPT_BOOL(RSK_SHUFFLE_WARP_SONGS, "Warp Songs", CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), mOptionDescriptions[RSK_SHUFFLE_WARP_SONGS]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_WARP_SONGS, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleWarpSongs"), RO_GENERIC_ON)) {
|
|
mOptions[RSK_WARP_SONG_HINTS].Enable();
|
|
} else {
|
|
mOptions[RSK_WARP_SONG_HINTS].Disable("This option is disabled since warp song locations are not shuffled.");
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_OVERWORLD_SPAWNS, "Overworld Spawns", CVAR_RANDOMIZER_SETTING("ShuffleOverworldSpawns"), mOptionDescriptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_OVERWORLD_SPAWNS, {
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_BOOL(RSK_MIXED_ENTRANCE_POOLS, "Mixed Entrance Pools", CVAR_RANDOMIZER_SETTING("MixedEntrances"), mOptionDescriptions[RSK_MIXED_ENTRANCE_POOLS]);
|
|
OPT_CALLBACK(RSK_MIXED_ENTRANCE_POOLS, {
|
|
// Show mixed entrance pool options if mixed entrance pools are enabled, but only the ones that aren't off
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MixedEntrances"), RO_GENERIC_OFF) == RO_GENERIC_OFF ||
|
|
mOptions[RSK_MIXED_ENTRANCE_POOLS].IsHidden()) {
|
|
mOptions[RSK_MIXED_ENTRANCE_POOLS].AddFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_MIX_DUNGEON_ENTRANCES].Hide();
|
|
mOptions[RSK_MIX_BOSS_ENTRANCES].Hide();
|
|
mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Hide();
|
|
mOptions[RSK_MIX_INTERIOR_ENTRANCES].Hide();
|
|
mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES].Hide();
|
|
mOptions[RSK_MIX_GROTTO_ENTRANCES].Hide();
|
|
} else {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonsEntrances"), RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) !=
|
|
RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) {
|
|
mOptions[RSK_MIX_DUNGEON_ENTRANCES].Unhide();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBossEntrances"), RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) !=
|
|
RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
|
|
mOptions[RSK_MIX_BOSS_ENTRANCES].Unhide();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleOverworldEntrances"), RO_GENERIC_OFF) != RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Unhide();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleInteriorsEntrances"), RO_GENERIC_OFF) != RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_INTERIOR_ENTRANCES].Unhide();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleThievesHideoutEntrances"), RO_GENERIC_OFF) != RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES].Unhide();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGrottosEntrances"), RO_GENERIC_OFF) != RO_GENERIC_OFF) {
|
|
mOptions[RSK_MIX_GROTTO_ENTRANCES].Unhide();
|
|
}
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_MIX_DUNGEON_ENTRANCES, "Mix Dungeons", CVAR_RANDOMIZER_SETTING("MixDungeons"), mOptionDescriptions[RSK_MIX_DUNGEON_ENTRANCES], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MIX_BOSS_ENTRANCES, "Mix Bosses", CVAR_RANDOMIZER_SETTING("MixBosses"), mOptionDescriptions[RSK_MIX_BOSS_ENTRANCES], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MIX_OVERWORLD_ENTRANCES, "Mix Overworld", CVAR_RANDOMIZER_SETTING("MixOverworld"), mOptionDescriptions[RSK_MIX_OVERWORLD_ENTRANCES], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MIX_INTERIOR_ENTRANCES, "Mix Interiors", CVAR_RANDOMIZER_SETTING("MixInteriors"), mOptionDescriptions[RSK_MIX_INTERIOR_ENTRANCES], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MIX_THIEVES_HIDEOUT_ENTRANCES, "Mix Thieves' Hideout", CVAR_RANDOMIZER_SETTING("MixThievesHideout"), mOptionDescriptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES]);
|
|
OPT_BOOL(RSK_MIX_GROTTO_ENTRANCES, "Mix Grottos", CVAR_RANDOMIZER_SETTING("MixGrottos"), mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]);
|
|
OPT_BOOL(RSK_DECOUPLED_ENTRANCES, "Decouple Entrances", CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), mOptionDescriptions[RSK_DECOUPLED_ENTRANCES]);
|
|
OPT_CALLBACK(RSK_DECOUPLED_ENTRANCES, {
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_U8(RSK_BOMBCHU_BAG, "Bombchu Bag", {"None", "Single Bag", "Progressive Bags"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BombchuBag"), mOptionDescriptions[RSK_BOMBCHU_BAG], WIDGET_CVAR_COMBOBOX, RO_BOMBCHU_BAG_NONE);
|
|
OPT_U8(RSK_ENABLE_BOMBCHU_DROPS, "Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WIDGET_CVAR_COMBOBOX, RO_AMMO_DROPS_ON);
|
|
// TODO: AmmoDrops and/or HeartDropRefill, combine with/separate Ammo Drops from Bombchu Drops?
|
|
OPT_U8(RSK_TRIFORCE_HUNT, "Triforce Hunt", {"Off", "Win", "Ganon's Boss Key"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT]);
|
|
OPT_CALLBACK(RSK_TRIFORCE_HUNT, {
|
|
// Remove the pieces required/total sliders and add a separator after Triforce Hunt if Triforce Hunt is off
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHunt"), RO_TRIFORCE_HUNT_OFF) == RO_TRIFORCE_HUNT_OFF) {
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Hide();
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Hide();
|
|
mOptions[RSK_GANONS_BOSS_KEY].Enable();
|
|
} else {
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].Unhide();
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL].Unhide();
|
|
mOptions[RSK_GANONS_BOSS_KEY].Disable(
|
|
"This option is disabled because Triforce Hunt is enabled."
|
|
"Ganon's Boss key\nwill instead be given to you after Triforce Hunt completion.");
|
|
}
|
|
});
|
|
OPT_U8(RSK_TRIFORCE_HUNT_PIECES_TOTAL, "Triforce Hunt Total Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL], WIDGET_CVAR_SLIDER_INT, 29, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_TRIFORCE_HUNT_PIECES_TOTAL, {
|
|
// Update triforce pieces required to be capped at the current value for pieces total.
|
|
const uint8_t triforceTotal = CVarGetInteger(CVAR_RANDOMIZER_SETTING("TriforceHuntTotalPieces"), 30);
|
|
if (mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].GetOptionCount() != triforceTotal + 1) {
|
|
mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED].ChangeOptions(NumOpts(1, triforceTotal + 1));
|
|
}
|
|
});
|
|
OPT_U8(RSK_TRIFORCE_HUNT_PIECES_REQUIRED, "Triforce Hunt Required Pieces", {NumOpts(1, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("TriforceHuntRequiredPieces"), mOptionDescriptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], WIDGET_CVAR_SLIDER_INT, 19);
|
|
OPT_U8(RSK_MQ_DUNGEON_RANDOM, "MQ Dungeon Setting", {"None", "Set Number", "Random", "Selection Only"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeons"), mOptionDescriptions[RSK_MQ_DUNGEON_RANDOM], WIDGET_CVAR_COMBOBOX, RO_MQ_DUNGEONS_NONE, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_MQ_DUNGEON_RANDOM, {
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE)) {
|
|
// If No MQ Dungeons, add a separator after the combobx and hide
|
|
// the count slider and the toggle for individual dungeon selections.
|
|
case RO_MQ_DUNGEONS_NONE:
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Hide();
|
|
mOptions[RSK_MQ_DUNGEON_SET].Hide();
|
|
break;
|
|
// If Set Number, remove the separator and show both the count slider and the
|
|
// individual dungeon selection toggle.
|
|
case RO_MQ_DUNGEONS_SET_NUMBER:
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Unhide();
|
|
mOptions[RSK_MQ_DUNGEON_SET].Unhide();
|
|
break;
|
|
// else if random number or selection only, remove the separator and only show
|
|
// the individual dungeon selection toggle.
|
|
case RO_MQ_DUNGEONS_RANDOM_NUMBER:
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Hide();
|
|
mOptions[RSK_MQ_DUNGEON_SET].Unhide();
|
|
break;
|
|
case RO_MQ_DUNGEONS_SELECTION:
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Hide();
|
|
mOptions[RSK_MQ_DUNGEON_SET].Hide();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
// Controls whether or not to show the selectors for individual dungeons.
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE &&
|
|
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), RO_GENERIC_OFF) == RO_GENERIC_ON ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION)) {
|
|
// if showing the dungeon selectors, remove the separator after the Set Dungeons checkbox.
|
|
mOptions[RSK_MQ_DEKU_TREE].Unhide();
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Unhide();
|
|
mOptions[RSK_MQ_JABU_JABU].Unhide();
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Unhide();
|
|
mOptions[RSK_MQ_ICE_CAVERN].Unhide();
|
|
mOptions[RSK_MQ_GTG].Unhide();
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Unhide();
|
|
} else {
|
|
// If those are not shown, add a separator after the Set Dungeons checkbox.
|
|
mOptions[RSK_MQ_DEKU_TREE].Hide();
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Hide();
|
|
mOptions[RSK_MQ_JABU_JABU].Hide();
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Hide();
|
|
mOptions[RSK_MQ_ICE_CAVERN].Hide();
|
|
mOptions[RSK_MQ_GTG].Hide();
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Hide();
|
|
}
|
|
});
|
|
OPT_U8(RSK_MQ_DUNGEON_COUNT, "MQ Dungeon Count", {NumOpts(0, MAX_MQ_DUNGEON_COUNT)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonCount"), "", WIDGET_CVAR_SLIDER_INT, MAX_MQ_DUNGEON_COUNT, true, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MQ_DUNGEON_SET, "Set Dungeon Quests", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), mOptionDescriptions[RSK_MQ_DUNGEON_SET], WIDGET_CVAR_CHECKBOX, false, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_MQ_DUNGEON_SET, {
|
|
// Controls whether or not to show the selectors for individual dungeons.
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_NONE &&
|
|
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonsSelection"), RO_GENERIC_OFF) == RO_GENERIC_ON ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) == RO_MQ_DUNGEONS_SELECTION)) {
|
|
// if showing the dungeon selectors, remove the separator after the Set Dungeons checkbox.
|
|
mOptions[RSK_MQ_DEKU_TREE].Unhide();
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Unhide();
|
|
mOptions[RSK_MQ_JABU_JABU].Unhide();
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Unhide();
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Unhide();
|
|
mOptions[RSK_MQ_ICE_CAVERN].Unhide();
|
|
mOptions[RSK_MQ_GTG].Unhide();
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Unhide();
|
|
} else {
|
|
// If those are not shown, add a separator after the Set Dungeons checkbox.
|
|
mOptions[RSK_MQ_DEKU_TREE].Hide();
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Hide();
|
|
mOptions[RSK_MQ_JABU_JABU].Hide();
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Hide();
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Hide();
|
|
mOptions[RSK_MQ_ICE_CAVERN].Hide();
|
|
mOptions[RSK_MQ_GTG].Hide();
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Hide();
|
|
}
|
|
});
|
|
OPT_U8(RSK_MQ_DEKU_TREE, "Deku Tree Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDekuTree"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_DODONGOS_CAVERN, "Dodongo's Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsDodongosCavern"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_JABU_JABU, "Jabu-Jabu's Belly Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsJabuJabu"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_FOREST_TEMPLE, "Forest Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsForestTemple"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_FIRE_TEMPLE, "Fire Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsFireTemple"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_WATER_TEMPLE, "Water Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsWaterTemple"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_SPIRIT_TEMPLE, "Spirit Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsSpiritTemple"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_SHADOW_TEMPLE, "Shadow Temple Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsShadowTemple"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_BOTTOM_OF_THE_WELL, "Bottom of the Well Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsBottomOfTheWell"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_ICE_CAVERN, "Ice Cavern Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsIceCavern"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_GTG, "Gerudo Training Ground Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGTG"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MQ_GANONS_CASTLE, "Ganon's Castle Quest", {"Vanilla", "Master Quest", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MQDungeonsGanonsCastle"), "", WIDGET_CVAR_COMBOBOX, RO_MQ_SET_VANILLA);
|
|
OPT_U8(RSK_SHUFFLE_DUNGEON_REWARDS, "Shuffle Dungeon Rewards", {"Vanilla", "End of Dungeons", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
|
|
OPT_CALLBACK(RSK_SHUFFLE_DUNGEON_REWARDS, {
|
|
// Link's Pocket - Disabled when Dungeon Rewards are shuffled to End of Dungeon
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
|
|
RO_DUNGEON_REWARDS_END_OF_DUNGEON) {
|
|
mOptions[RSK_LINKS_POCKET].Disable(
|
|
"This option is disabled because \"Dungeon Rewards\" are shuffled to \"End of Dungeons\".");
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Enable();
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Unhide();
|
|
} else {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
|
|
RO_DUNGEON_REWARDS_OWN_DUNGEON) {
|
|
mOptions[RSK_LINKS_POCKET].Enable();
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Disable(
|
|
"As \"Link's Pocket\" is set to \"Dungeon Reward\" while \"Dungeon Rewards\" is set to \"Own Dungeon\", Link's Pocket will always have the Light Medallion");
|
|
}else if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) ==
|
|
RO_DUNGEON_REWARDS_VANILLA) {
|
|
mOptions[RSK_LINKS_POCKET].Enable();
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Disable(
|
|
"As \"Link's Pocket\" is set to \"Dungeon Reward\" while \"Dungeon Rewards\" is set to \"Vanilla\", Link's Pocket will always have the Light Medallion");
|
|
} else {
|
|
mOptions[RSK_LINKS_POCKET].Enable();
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Enable();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) == RO_LINKS_POCKET_DUNGEON_REWARD) {
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Unhide();
|
|
} else {
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Hide();
|
|
}
|
|
}
|
|
});
|
|
OPT_U8(RSK_LINKS_POCKET, "Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), mOptionDescriptions[RSK_LINKS_POCKET], WIDGET_CVAR_COMBOBOX, RO_LINKS_POCKET_DUNGEON_REWARD);
|
|
OPT_CALLBACK(RSK_LINKS_POCKET, {
|
|
// Only show the dungeon reward type if Link's Pocket is set to Dungeon Reward and Dungeon Rewards are not Vanilla, OR Dungeon Rewards are end of dungeon
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD) == RO_LINKS_POCKET_DUNGEON_REWARD ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON) == RO_DUNGEON_REWARDS_END_OF_DUNGEON) {
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Unhide();
|
|
} else {
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Hide();
|
|
}
|
|
});
|
|
OPT_U8(RSK_LINKS_POCKET_REWARD, "Link's Pocket Reward Type", {"Any Reward", "Any Stone", "Any Medallion", "Light Medallion"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocketReward"), mOptionDescriptions[RSK_LINKS_POCKET_REWARD], WIDGET_CVAR_COMBOBOX, RO_LINKS_POCKET_ANY_REWARD);
|
|
OPT_U8(RSK_SHUFFLE_SONGS, "Shuffle Songs", {"Off", "Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WIDGET_CVAR_COMBOBOX, RO_SONG_SHUFFLE_SONG_LOCATIONS);
|
|
OPT_U8(RSK_SHOPSANITY, "Shop Shuffle", {"Off", "Specific Count", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WIDGET_CVAR_COMBOBOX, RO_SHOPSANITY_OFF);
|
|
OPT_CALLBACK(RSK_SHOPSANITY, {
|
|
// Hide shopsanity prices if shopsanity is off or zero
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF)) {
|
|
case RO_SHOPSANITY_OFF:
|
|
mOptions[RSK_SHOPSANITY].AddFlag(IMFLAG_SEPARATOR_BOTTOM);
|
|
mOptions[RSK_SHOPSANITY_COUNT].Hide();
|
|
mOptions[RSK_SHOPSANITY_COUNT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
break;
|
|
case RO_SHOPSANITY_SPECIFIC_COUNT:
|
|
mOptions[RSK_SHOPSANITY_COUNT].Unhide();
|
|
HandleShopsanityPriceUI();
|
|
break;
|
|
case RO_SHOPSANITY_RANDOM:
|
|
mOptions[RSK_SHOPSANITY_COUNT].Hide();
|
|
HandleShopsanityPriceUI();
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_SHOPSANITY_COUNT, "Shops Item Count", {NumOpts(0, 7/*8*/)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityCount"), mOptionDescriptions[RSK_SHOPSANITY_COUNT], WIDGET_CVAR_SLIDER_INT, 0, false, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES, "Shops Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), mOptionDescriptions[RSK_SHOPSANITY_PRICES], WIDGET_CVAR_COMBOBOX, RO_PRICE_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_SHOPSANITY_PRICES, {
|
|
HandleShopsanityPriceUI();
|
|
});
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_FIXED_PRICE, "Shops Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityFixedPrice"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE], WIDGET_CVAR_SLIDER_INT, 10, true);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_RANGE_1, "Shops Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPriceRange1"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_1], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_RANGE_2, "Shops Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPriceRange2"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_RANGE_2], WIDGET_CVAR_SLIDER_INT, 100, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT, "Shops No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityNoWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT, "Shops Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityChildWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT, "Shops Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityAdultWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT, "Shops Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityGiantWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT, "Shops Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityTycoonWalletWeight"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_SHOPSANITY_PRICES_AFFORDABLE, "Shops Affordable Prices", CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]);
|
|
OPT_U8(RSK_SHUFFLE_TOKENS, "Token Shuffle", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleTokens"), mOptionDescriptions[RSK_SHUFFLE_TOKENS], WIDGET_CVAR_COMBOBOX, RO_TOKENSANITY_OFF);
|
|
OPT_U8(RSK_SHUFFLE_SCRUBS, "Scrubs Shuffle", {"Off", "One-Time Only", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), mOptionDescriptions[RSK_SHUFFLE_SCRUBS], WIDGET_CVAR_COMBOBOX, RO_SCRUBS_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_SCRUBS, {
|
|
bool isTycoon = CVarGetInteger(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), RO_GENERIC_OFF);
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_OFF)) {
|
|
case RO_SCRUBS_OFF:
|
|
mOptions[RSK_SCRUBS_PRICES].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_SCRUBS_PRICES].Unhide();
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ScrubsPrices"), RO_PRICE_VANILLA)) {
|
|
case RO_PRICE_FIXED:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].GetOptionCount() == 501
|
|
: mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].GetOptionCount() == 1000) {
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].ChangeOptions(isTycoon ? NumOpts(0, 999)
|
|
: NumOpts(0, 500));
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Hide();
|
|
break;
|
|
case RO_PRICE_RANGE:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_SCRUBS_PRICES_RANGE_1].GetOptionCount() == 101
|
|
: mOptions[RSK_SCRUBS_PRICES_RANGE_1].GetOptionCount() == 200) {
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
case RO_PRICE_SET_BY_WALLET:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Unhide();
|
|
if (isTycoon) {
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Unhide();
|
|
} else {
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_SCRUBS_PRICES, "Scrubs Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPrices"), mOptionDescriptions[RSK_SCRUBS_PRICES], WIDGET_CVAR_COMBOBOX, RO_PRICE_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_SCRUBS_PRICES, {
|
|
bool isTycoon = CVarGetInteger(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), RO_GENERIC_OFF);
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ScrubsPrices"), RO_PRICE_VANILLA)) {
|
|
case RO_PRICE_FIXED:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].GetOptionCount() == 501
|
|
: mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].GetOptionCount() == 1000) {
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].ChangeOptions(isTycoon ? NumOpts(0, 999)
|
|
: NumOpts(0, 500));
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Hide();
|
|
break;
|
|
case RO_PRICE_RANGE:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_SCRUBS_PRICES_RANGE_1].GetOptionCount() == 101
|
|
: mOptions[RSK_SCRUBS_PRICES_RANGE_1].GetOptionCount() == 200) {
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
case RO_PRICE_SET_BY_WALLET:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Unhide();
|
|
if (isTycoon) {
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Unhide();
|
|
} else {
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
}
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_SCRUBS_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_SCRUBS_PRICES_FIXED_PRICE, "Scrubs Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsFixedPrice"), mOptionDescriptions[RSK_SCRUBS_PRICES_FIXED_PRICE], WIDGET_CVAR_SLIDER_INT, 10, true);
|
|
OPT_U8(RSK_SCRUBS_PRICES_RANGE_1, "Scrubs Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPriceRange1"), mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_1], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SCRUBS_PRICES_RANGE_2, "Scrubs Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsPriceRange2"), mOptionDescriptions[RSK_SCRUBS_PRICES_RANGE_2], WIDGET_CVAR_SLIDER_INT, 100, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT, "Scrubs No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsNoWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT, "Scrubs Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsChildWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT, "Scrubs Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsAdultWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT, "Scrubs Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsGiantWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT, "Scrubs Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ScrubsTycoonWalletWeight"), mOptionDescriptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_SCRUBS_PRICES_AFFORDABLE, "Scrubs Affordable Prices", CVAR_RANDOMIZER_SETTING("ScrubsPricesAffordable"), mOptionDescriptions[RSK_SCRUBS_PRICES_AFFORDABLE]);
|
|
OPT_BOOL(RSK_SHUFFLE_BEEHIVES, "Shuffle Beehives", CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), mOptionDescriptions[RSK_SHUFFLE_BEEHIVES]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_BEEHIVES, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), RO_GENERIC_OFF)) {
|
|
mOptions[RSK_SLINGBOW_BREAK_BEEHIVES].Enable();
|
|
} else {
|
|
mOptions[RSK_SLINGBOW_BREAK_BEEHIVES].Disable(
|
|
"This option is disabled because Shuffle Beehives is not enabled.");
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_COWS, "Shuffle Cows", CVAR_RANDOMIZER_SETTING("ShuffleCows"), mOptionDescriptions[RSK_SHUFFLE_COWS]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_COWS, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCows"), RO_GENERIC_OFF)) {
|
|
mOptions[RSK_MALON_HINT].Enable();
|
|
} else {
|
|
mOptions[RSK_MALON_HINT].Disable("Malon's hint points to a cow, so requires cows to be shuffled.");
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_KOKIRI_SWORD, "Shuffle Kokiri Sword", CVAR_RANDOMIZER_SETTING("ShuffleKokiriSword"), mOptionDescriptions[RSK_SHUFFLE_KOKIRI_SWORD]);
|
|
OPT_BOOL(RSK_SHUFFLE_MASTER_SWORD, "Shuffle Master Sword", CVAR_RANDOMIZER_SETTING("ShuffleMasterSword"), mOptionDescriptions[RSK_SHUFFLE_MASTER_SWORD]);
|
|
OPT_BOOL(RSK_SHUFFLE_CHILD_WALLET, "Shuffle Child's Wallet", CVAR_RANDOMIZER_SETTING("ShuffleChildWallet"), mOptionDescriptions[RSK_SHUFFLE_CHILD_WALLET], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_INCLUDE_TYCOON_WALLET, "Include Tycoon Wallet", CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), mOptionDescriptions[RSK_INCLUDE_TYCOON_WALLET]);
|
|
OPT_BOOL(RSK_SHUFFLE_OCARINA, "Shuffle Ocarinas", CVAR_RANDOMIZER_SETTING("ShuffleOcarinas"), mOptionDescriptions[RSK_SHUFFLE_OCARINA]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_OCARINA, {
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_OCARINA_BUTTONS, "Shuffle Ocarina Buttons", CVAR_RANDOMIZER_SETTING("ShuffleOcarinaButtons"), mOptionDescriptions[RSK_SHUFFLE_OCARINA_BUTTONS]);
|
|
OPT_BOOL(RSK_SHUFFLE_SWIM, "Shuffle Swim", CVAR_RANDOMIZER_SETTING("ShuffleSwim"), mOptionDescriptions[RSK_SHUFFLE_SWIM]);
|
|
OPT_BOOL(RSK_SHUFFLE_CLIMB, "Shuffle Climb", CVAR_RANDOMIZER_SETTING("ShuffleClimb"), mOptionDescriptions[RSK_SHUFFLE_CLIMB]);
|
|
OPT_BOOL(RSK_SHUFFLE_CRAWL, "Shuffle Crawl", CVAR_RANDOMIZER_SETTING("ShuffleCrawl"), mOptionDescriptions[RSK_SHUFFLE_CRAWL]);
|
|
OPT_BOOL(RSK_SHUFFLE_GRAB, "Shuffle Grab", CVAR_RANDOMIZER_SETTING("ShuffleGrab"), mOptionDescriptions[RSK_SHUFFLE_GRAB]);
|
|
OPT_BOOL(RSK_SHUFFLE_SPEAK, "Shuffle Jabber Nuts", CVAR_RANDOMIZER_SETTING("ShuffleSpeak"), mOptionDescriptions[RSK_SHUFFLE_SPEAK]);
|
|
OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]);
|
|
OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]);
|
|
OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
|
|
OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_POTS_OFF);
|
|
OPT_U8(RSK_SHUFFLE_GRASS, "Shuffle Grass", {"Off", "Dungeons", "Overworld", "All Grass"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGrass"), mOptionDescriptions[RSK_SHUFFLE_GRASS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_GRASS_OFF);
|
|
OPT_U8(RSK_SHUFFLE_CRATES, "Shuffle Crates", {"Off", "Dungeons", "Overworld", "All Crates"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleCrates"), mOptionDescriptions[RSK_SHUFFLE_CRATES], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_CRATES_OFF);
|
|
OPT_BOOL(RSK_SHUFFLE_TREES, "Shuffle Trees", CVAR_RANDOMIZER_SETTING("ShuffleTrees"), mOptionDescriptions[RSK_SHUFFLE_TREES]);
|
|
OPT_BOOL(RSK_SHUFFLE_BUSHES, "Shuffle Bushes", CVAR_RANDOMIZER_SETTING("ShuffleBushes"), mOptionDescriptions[RSK_SHUFFLE_BUSHES]);
|
|
OPT_BOOL(RSK_SHUFFLE_ICICLES, "Shuffle Icicles", CVAR_RANDOMIZER_SETTING("ShuffleIcicles"), mOptionDescriptions[RSK_SHUFFLE_ICICLES]);
|
|
OPT_BOOL(RSK_SHUFFLE_RED_ICE, "Shuffle Red Ice", CVAR_RANDOMIZER_SETTING("ShuffleRedIce"), mOptionDescriptions[RSK_SHUFFLE_RED_ICE]);
|
|
OPT_U8(RSK_SHUFFLE_SIGNS, "Shuffle Signs", {"Off", "Dungeons", "Overworld", "All Signs"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSigns"), mOptionDescriptions[RSK_SHUFFLE_SIGNS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_SIGNS_OFF);
|
|
OPT_BOOL(RSK_SHUFFLE_FISHING_POLE, "Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]);
|
|
OPT_CALLBACK(RSK_SHUFFLE_FISHING_POLE, {
|
|
// Disable fishing pole hint if the fishing pole is not shuffled
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), RO_GENERIC_OFF)) {
|
|
mOptions[RSK_FISHING_POLE_HINT].Enable();
|
|
} else {
|
|
mOptions[RSK_FISHING_POLE_HINT].Disable("This option is disabled since the fishing pole is not shuffled.");
|
|
}
|
|
});
|
|
OPT_U8(RSK_SHUFFLE_MERCHANTS, "Shuffle Merchants", {"Off", "Bean Merchant Only", "All But Beans", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_MERCHANTS_OFF, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_SHUFFLE_MERCHANTS, {
|
|
bool isTycoon = CVarGetInteger(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), RO_GENERIC_OFF);
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), RO_SHUFFLE_MERCHANTS_OFF)) {
|
|
case RO_SHUFFLE_MERCHANTS_OFF:
|
|
mOptions[RSK_MERCHANT_PRICES].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_MERCHANT_PRICES].Unhide();
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MerchantPrices"), RO_PRICE_VANILLA)) {
|
|
case RO_PRICE_FIXED:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].GetOptionCount() == 501
|
|
: mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].GetOptionCount() == 1000) {
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].ChangeOptions(isTycoon ? NumOpts(0, 999)
|
|
: NumOpts(0, 500));
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Hide();
|
|
break;
|
|
case RO_PRICE_RANGE:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_MERCHANT_PRICES_RANGE_1].GetOptionCount() == 101
|
|
: mOptions[RSK_MERCHANT_PRICES_RANGE_1].GetOptionCount() == 200) {
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
case RO_PRICE_SET_BY_WALLET:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Unhide();
|
|
if (isTycoon) {
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Unhide();
|
|
} else {
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_MERCHANT_PRICES, "Merchant Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPrices"), mOptionDescriptions[RSK_MERCHANT_PRICES], WIDGET_CVAR_COMBOBOX, RO_PRICE_VANILLA, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_MERCHANT_PRICES, {
|
|
bool isTycoon = CVarGetInteger(CVAR_RANDOMIZER_SETTING("IncludeTycoonWallet"), RO_GENERIC_OFF);
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MerchantPrices"), RO_PRICE_VANILLA)) {
|
|
case RO_PRICE_FIXED:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].GetOptionCount() == 501
|
|
: mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].GetOptionCount() == 1000) {
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].ChangeOptions(isTycoon ? NumOpts(0, 999)
|
|
: NumOpts(0, 500));
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Hide();
|
|
break;
|
|
case RO_PRICE_RANGE:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
if (isTycoon ? mOptions[RSK_MERCHANT_PRICES_RANGE_1].GetOptionCount() == 101
|
|
: mOptions[RSK_MERCHANT_PRICES_RANGE_1].GetOptionCount() == 200) {
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].ChangeOptions(isTycoon ? NumOpts(0, 995, 5)
|
|
: NumOpts(0, 500, 5));
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
case RO_PRICE_SET_BY_WALLET:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Unhide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Unhide();
|
|
if (isTycoon) {
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Unhide();
|
|
} else {
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
}
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_1].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_RANGE_2].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT].Hide();
|
|
mOptions[RSK_MERCHANT_PRICES_AFFORDABLE].Unhide();
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_MERCHANT_PRICES_FIXED_PRICE, "Merchant Fixed Price", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantFixedPrice"), mOptionDescriptions[RSK_MERCHANT_PRICES_FIXED_PRICE], WIDGET_CVAR_SLIDER_INT, 10, true);
|
|
OPT_U8(RSK_MERCHANT_PRICES_RANGE_1, "Merchant Lower Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPriceRange1"), mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_1], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MERCHANT_PRICES_RANGE_2, "Merchant Upper Bound", {NumOpts(0, 995, 5)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPriceRange2"), mOptionDescriptions[RSK_MERCHANT_PRICES_RANGE_2], WIDGET_CVAR_SLIDER_INT, 100, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT, "Merchant No Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantNoWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT, "Merchant Child Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantChildWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT, "Merchant Adult Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantAdultWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT, "Merchant Giant Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantGiantWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_U8(RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT, "Merchant Tycoon Wallet Weight", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantTycoonWalletWeight"), mOptionDescriptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT], WIDGET_CVAR_SLIDER_INT, 10, true, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MERCHANT_PRICES_AFFORDABLE, "Merchant Affordable Prices", CVAR_RANDOMIZER_SETTING("MerchantPricesAffordable"), mOptionDescriptions[RSK_MERCHANT_PRICES_AFFORDABLE]);
|
|
OPT_BOOL(RSK_SHUFFLE_BEGGAR, "Shuffle Beggar", CVAR_RANDOMIZER_SETTING("ShuffleBeggar"), mOptionDescriptions[RSK_SHUFFLE_BEGGAR]);
|
|
OPT_BOOL(RSK_SHUFFLE_FROG_SONG_RUPEES, "Shuffle Frog Song Rupees", CVAR_RANDOMIZER_SETTING("ShuffleFrogSongRupees"), mOptionDescriptions[RSK_SHUFFLE_FROG_SONG_RUPEES]);
|
|
OPT_BOOL(RSK_SHUFFLE_ADULT_TRADE, "Shuffle Adult Trade", CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), mOptionDescriptions[RSK_SHUFFLE_ADULT_TRADE]);
|
|
OPT_U8(RSK_SHUFFLE_CHEST_MINIGAME, "Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"});
|
|
OPT_BOOL(RSK_SHUFFLE_100_GS_REWARD, "Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_100_GS_REWARD, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), RO_GENERIC_OFF)) {
|
|
mOptions[RSK_KAK_100_SKULLS_HINT].Enable();
|
|
} else {
|
|
mOptions[RSK_KAK_100_SKULLS_HINT].Disable("There is no point to hinting 100 skulls if it is not shuffled.");
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_BEAN_SOULS, "Shuffle Bean Souls", CVAR_RANDOMIZER_SETTING("ShuffleBeanSouls"), mOptionDescriptions[RSK_SHUFFLE_BEAN_SOULS], IMFLAG_SEPARATOR_BOTTOM, WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_U8(RSK_SHUFFLE_BOSS_SOULS, "Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WIDGET_CVAR_COMBOBOX);
|
|
OPT_BOOL(RSK_SHUFFLE_DEKU_STICK_BAG, "Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_DEKU_STICK_BAG, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), 0)) {
|
|
mOptions[RSK_STARTING_STICKS].Disable("Disabled because Shuffle Deku Stick Bag is on.");
|
|
} else {
|
|
mOptions[RSK_STARTING_STICKS].Enable();
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SHUFFLE_DEKU_NUT_BAG, "Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_CALLBACK(RSK_SHUFFLE_DEKU_NUT_BAG, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), 0)) {
|
|
mOptions[RSK_STARTING_NUTS].Disable("Disabled because Shuffle Deku Nut Bag is on.");
|
|
} else {
|
|
mOptions[RSK_STARTING_NUTS].Enable();
|
|
}
|
|
});
|
|
OPT_U8(RSK_SHUFFLE_FREESTANDING, "Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_FREESTANDING_OFF);
|
|
OPT_U8(RSK_SHUFFLE_WONDER_ITEMS, "Shuffle Wonder Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleWonderItems"), mOptionDescriptions[RSK_SHUFFLE_WONDER_ITEMS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_WONDER_ITEMS_OFF);
|
|
OPT_U8(RSK_FISHSANITY, "Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WIDGET_CVAR_COMBOBOX, RO_FISHSANITY_OFF);
|
|
OPT_CALLBACK(RSK_FISHSANITY, {
|
|
// Hide fishing pond settings if we aren't shuffling the fishing pond
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_FISHSANITY_OFF)) {
|
|
case RO_FISHSANITY_POND:
|
|
case RO_FISHSANITY_BOTH:
|
|
mOptions[RSK_FISHSANITY_POND_COUNT].Unhide();
|
|
mOptions[RSK_FISHSANITY_AGE_SPLIT].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_FISHSANITY_POND_COUNT].Hide();
|
|
mOptions[RSK_FISHSANITY_AGE_SPLIT].Hide();
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Fishsanity"), RO_FISHSANITY_OFF) == RO_FISHSANITY_HYRULE_LOACH) {
|
|
mOptions[RSK_LOACH_HINT].Enable();
|
|
} else {
|
|
mOptions[RSK_LOACH_HINT].Disable(
|
|
"Loach hint is only avaliable with \"Fishsanity\" set to \"Shuffle only Hyrule Loach\"\nas that's the only "
|
|
"setting where you present the loach to the fishing pond owner.");
|
|
}
|
|
});
|
|
OPT_U8(RSK_FISHSANITY_POND_COUNT, "Pond Fish Count", {NumOpts(0,17,1)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FishsanityPondCount"), mOptionDescriptions[RSK_FISHSANITY_POND_COUNT], WIDGET_CVAR_SLIDER_INT, 0, true, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_FISHSANITY_AGE_SPLIT, "Pond Age Split", CVAR_RANDOMIZER_SETTING("FishsanityAgeSplit"), mOptionDescriptions[RSK_FISHSANITY_AGE_SPLIT]);
|
|
OPT_BOOL(RSK_SHUFFLE_FOUNTAIN_FAIRIES, "Shuffle Fairies in Fountains", CVAR_RANDOMIZER_SETTING("ShuffleFountainFairies"), mOptionDescriptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES]);
|
|
OPT_BOOL(RSK_SHUFFLE_STONE_FAIRIES, "Shuffle Gossip Stone Fairies", CVAR_RANDOMIZER_SETTING("ShuffleStoneFairies"), mOptionDescriptions[RSK_SHUFFLE_STONE_FAIRIES]);
|
|
OPT_BOOL(RSK_SHUFFLE_BEAN_FAIRIES, "Shuffle Bean Fairies", CVAR_RANDOMIZER_SETTING("ShuffleBeanFairies"), mOptionDescriptions[RSK_SHUFFLE_BEAN_FAIRIES]);
|
|
OPT_BOOL(RSK_SHUFFLE_SONG_FAIRIES, "Shuffle Fairy Spots", CVAR_RANDOMIZER_SETTING("ShuffleFairySpots"), mOptionDescriptions[RSK_SHUFFLE_SONG_FAIRIES]);
|
|
OPT_BOOL(RSK_SHUFFLE_BUTTERFLY_FAIRIES, "Shuffle Butterfly Fairies", CVAR_RANDOMIZER_SETTING("ShuffleButterflyFairies"), mOptionDescriptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES]);
|
|
OPT_U8(RSK_SHUFFLE_MAPANDCOMPASS, "Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
|
|
OPT_U8(RSK_KEYSANITY, "Small Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
|
|
OPT_U8(RSK_GERUDO_KEYS, "Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WIDGET_CVAR_COMBOBOX, RO_GERUDO_KEYS_VANILLA);
|
|
OPT_CALLBACK(RSK_GERUDO_KEYS, {
|
|
const uint8_t maxKeyringCount =
|
|
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), RO_GF_CARPENTERS_NORMAL) ==
|
|
RO_GF_CARPENTERS_NORMAL &&
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) != RO_GERUDO_KEYS_VANILLA)
|
|
? 9
|
|
: 8;
|
|
if (mOptions[RSK_KEYRINGS_RANDOM_COUNT].GetOptionCount() != maxKeyringCount + 1) {
|
|
mOptions[RSK_KEYRINGS_RANDOM_COUNT].ChangeOptions(NumOpts(0, maxKeyringCount));
|
|
}
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("FortressCarpenters"), RO_GF_CARPENTERS_NORMAL) !=
|
|
RO_GF_CARPENTERS_NORMAL ||
|
|
CVarGetInteger(CVAR_RANDOMIZER_SETTING("GerudoKeys"), RO_GERUDO_KEYS_VANILLA) == RO_GERUDO_KEYS_VANILLA) {
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Disable(
|
|
"Disabled because the currently selected Gerudo Fortress Carpenters\n"
|
|
"setting and/or Gerudo Fortress Keys setting is incompatible with\n"
|
|
"having a Gerudo Fortress Keyring.");
|
|
} else {
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Enable();
|
|
}
|
|
});
|
|
OPT_U8(RSK_BOSS_KEYSANITY, "Boss Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BossKeysanity"), mOptionDescriptions[RSK_BOSS_KEYSANITY], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON);
|
|
OPT_U8(RSK_GANONS_BOSS_KEY, "Ganon's Boss Key", {"Vanilla", "Own Dungeon", "Start With", "Any Dungeon", "Overworld", "Anywhere", "LACS-Vanilla", "LACS-Stones", "LACS-Medallions", "LACS-Rewards", "LACS-Dungeons", "LACS-Tokens", "100 GS Reward"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), mOptionDescriptions[RSK_GANONS_BOSS_KEY], WIDGET_CVAR_COMBOBOX, RO_GANON_BOSS_KEY_VANILLA);
|
|
OPT_CALLBACK(RSK_GANONS_BOSS_KEY, {
|
|
// Shuffle 100 GS Reward - Force-Enabled if Ganon's Boss Key is on the 100 GS Reward
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA) ==
|
|
RO_GANON_BOSS_KEY_KAK_TOKENS) {
|
|
mOptions[RSK_SHUFFLE_100_GS_REWARD].Disable(
|
|
"This option is force-enabled because \"Ganon's Boss Key\" is set to \"100 GS Reward\".");
|
|
} else {
|
|
mOptions[RSK_SHUFFLE_100_GS_REWARD].Enable();
|
|
}
|
|
mOptions[RSK_LACS_OPTIONS].Hide();
|
|
mOptions[RSK_LACS_STONE_COUNT].Hide();
|
|
mOptions[RSK_LACS_MEDALLION_COUNT].Hide();
|
|
mOptions[RSK_LACS_REWARD_COUNT].Hide();
|
|
mOptions[RSK_LACS_DUNGEON_COUNT].Hide();
|
|
mOptions[RSK_LACS_TOKEN_COUNT].Hide();
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleGanonBossKey"), RO_GANON_BOSS_KEY_VANILLA)) {
|
|
case RO_GANON_BOSS_KEY_LACS_STONES:
|
|
mOptions[RSK_LACS_OPTIONS].Unhide();
|
|
mOptions[RSK_LACS_STONE_COUNT].Unhide();
|
|
break;
|
|
case RO_GANON_BOSS_KEY_LACS_MEDALLIONS:
|
|
mOptions[RSK_LACS_OPTIONS].Unhide();
|
|
mOptions[RSK_LACS_MEDALLION_COUNT].Unhide();
|
|
break;
|
|
case RO_GANON_BOSS_KEY_LACS_REWARDS:
|
|
mOptions[RSK_LACS_OPTIONS].Unhide();
|
|
mOptions[RSK_LACS_REWARD_COUNT].Unhide();
|
|
break;
|
|
case RO_GANON_BOSS_KEY_LACS_DUNGEONS:
|
|
mOptions[RSK_LACS_OPTIONS].Unhide();
|
|
mOptions[RSK_LACS_DUNGEON_COUNT].Unhide();
|
|
break;
|
|
case RO_GANON_BOSS_KEY_LACS_TOKENS:
|
|
mOptions[RSK_LACS_TOKEN_COUNT].Unhide();
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_LACS_STONE_COUNT, "GCBK Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsStoneCount"), "", WIDGET_CVAR_SLIDER_INT, 3, true);
|
|
OPT_U8(RSK_LACS_MEDALLION_COUNT, "GCBK Medallion Count", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsMedallionCount"), "", WIDGET_CVAR_SLIDER_INT, 6, true);
|
|
OPT_U8(RSK_LACS_REWARD_COUNT, "GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WIDGET_CVAR_SLIDER_INT, 9, true);
|
|
OPT_U8(RSK_LACS_DUNGEON_COUNT, "GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WIDGET_CVAR_SLIDER_INT, 8, true);
|
|
OPT_U8(RSK_LACS_TOKEN_COUNT, "GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WIDGET_CVAR_SLIDER_INT, 100, true);
|
|
OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), mOptionDescriptions[RSK_LACS_OPTIONS], WIDGET_CVAR_COMBOBOX, RO_LACS_STANDARD_REWARD);
|
|
OPT_CALLBACK(RSK_LACS_OPTIONS, {
|
|
const uint8_t lacsOpts = CVarGetInteger(CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), RO_LACS_STANDARD_REWARD);
|
|
if (lacsOpts == RO_LACS_GREG_REWARD) {
|
|
if (mOptions[RSK_LACS_STONE_COUNT].GetOptionCount() == 4) {
|
|
mOptions[RSK_LACS_STONE_COUNT].ChangeOptions(NumOpts(0, 4));
|
|
}
|
|
if (mOptions[RSK_LACS_MEDALLION_COUNT].GetOptionCount() == 7) {
|
|
mOptions[RSK_LACS_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 7));
|
|
}
|
|
if (mOptions[RSK_LACS_REWARD_COUNT].GetOptionCount() == 10) {
|
|
mOptions[RSK_LACS_REWARD_COUNT].ChangeOptions(NumOpts(0, 10));
|
|
}
|
|
if (mOptions[RSK_LACS_DUNGEON_COUNT].GetOptionCount() == 9) {
|
|
mOptions[RSK_LACS_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 9));
|
|
}
|
|
} else {
|
|
if (mOptions[RSK_LACS_STONE_COUNT].GetOptionCount() == 5) {
|
|
mOptions[RSK_LACS_STONE_COUNT].ChangeOptions(NumOpts(0, 3));
|
|
}
|
|
if (mOptions[RSK_LACS_MEDALLION_COUNT].GetOptionCount() == 8) {
|
|
mOptions[RSK_LACS_MEDALLION_COUNT].ChangeOptions(NumOpts(0, 6));
|
|
}
|
|
if (mOptions[RSK_LACS_REWARD_COUNT].GetOptionCount() == 11) {
|
|
mOptions[RSK_LACS_REWARD_COUNT].ChangeOptions(NumOpts(0, 9));
|
|
}
|
|
if (mOptions[RSK_LACS_DUNGEON_COUNT].GetOptionCount() == 10) {
|
|
mOptions[RSK_LACS_DUNGEON_COUNT].ChangeOptions(NumOpts(0, 8));
|
|
}
|
|
}
|
|
});
|
|
OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WIDGET_CVAR_COMBOBOX, RO_KEYRINGS_OFF);
|
|
OPT_CALLBACK(RSK_KEYRINGS, {
|
|
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), RO_KEYRINGS_OFF)) {
|
|
case RO_KEYRINGS_COUNT:
|
|
// Show count slider.
|
|
mOptions[RSK_KEYRINGS_RANDOM_COUNT].Unhide();
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Hide();
|
|
mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_WATER_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Hide();
|
|
mOptions[RSK_KEYRINGS_GTG].Hide();
|
|
mOptions[RSK_KEYRINGS_GANONS_CASTLE].Hide();
|
|
break;
|
|
case RO_KEYRINGS_SELECTION:
|
|
// Show checkboxes for each dungeon with keys.
|
|
mOptions[RSK_KEYRINGS_RANDOM_COUNT].Hide();
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Unhide();
|
|
mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Unhide();
|
|
mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Unhide();
|
|
mOptions[RSK_KEYRINGS_WATER_TEMPLE].Unhide();
|
|
mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Unhide();
|
|
mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Unhide();
|
|
mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Unhide();
|
|
mOptions[RSK_KEYRINGS_GTG].Unhide();
|
|
mOptions[RSK_KEYRINGS_GANONS_CASTLE].Unhide();
|
|
break;
|
|
default:
|
|
mOptions[RSK_KEYRINGS_RANDOM_COUNT].Hide();
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Hide();
|
|
mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_WATER_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Hide();
|
|
mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Hide();
|
|
mOptions[RSK_KEYRINGS_GTG].Hide();
|
|
mOptions[RSK_KEYRINGS_GANONS_CASTLE].Hide();
|
|
break;
|
|
}
|
|
});
|
|
OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WIDGET_CVAR_SLIDER_INT, 8);
|
|
OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_FOREST_TEMPLE, "Forest Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsForestTemple"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_FIRE_TEMPLE, "Fire Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsFireTemple"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_WATER_TEMPLE, "Water Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsWaterTemple"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_SPIRIT_TEMPLE, "Spirit Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsSpiritTemple"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_SHADOW_TEMPLE, "Shadow Temple Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsShadowTemple"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_BOTTOM_OF_THE_WELL, "Bottom of the Well Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsBottomOfTheWell"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_GTG, "Gerudo Training Ground Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGTG"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_KEYRINGS_GANONS_CASTLE, "Ganon's Castle Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGanonsCastle"), "", WIDGET_CVAR_COMBOBOX, 0);
|
|
//Dummied out due to redundancy with TimeSavers.SkipChildStealth until such a time that logic needs to consider child stealth e.g. because it's freestanding checks are added to freestanding shuffle.
|
|
//To undo this dummying, readd this setting to an OptionGroup so it appears in the UI, then edit the timesaver check hooks to look at this, and the timesaver setting to lock itself as needed.
|
|
OPT_BOOL(RSK_SKIP_CHILD_STEALTH, "Skip Child Stealth", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildStealth"), mOptionDescriptions[RSK_SKIP_CHILD_STEALTH], WIDGET_CVAR_CHECKBOX, RO_GENERIC_DONT_SKIP);
|
|
OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WIDGET_CVAR_CHECKBOX, RO_GENERIC_DONT_SKIP);
|
|
OPT_CALLBACK(RSK_SKIP_CHILD_ZELDA, {
|
|
// Shuffle Weird Egg - Disabled when Skip Child Zelda is active
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), RO_GENERIC_DONT_SKIP)) {
|
|
mOptions[RSK_SHUFFLE_WEIRD_EGG].Disable("This option is disabled because \"Skip Child Zelda\" is enabled.");
|
|
mOptions[RSK_SKIP_CHILD_STEALTH].Disable("This option is disabled because \"Skip Child Zelda\" is enabled.");
|
|
} else {
|
|
mOptions[RSK_SHUFFLE_WEIRD_EGG].Enable();
|
|
mOptions[RSK_SKIP_CHILD_STEALTH].Enable();
|
|
}
|
|
});
|
|
OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WIDGET_CVAR_CHECKBOX, RO_GENERIC_DONT_SKIP);
|
|
OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]);
|
|
OPT_BOOL(RSK_SKIP_PLANTING_BEANS, "Skip Planting Beans", CVAR_RANDOMIZER_SETTING("SkipPlantingBeans"), mOptionDescriptions[RSK_SKIP_PLANTING_BEANS]);
|
|
OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WIDGET_CVAR_SLIDER_INT, 10);
|
|
OPT_CALLBACK(RSK_BIG_POE_COUNT, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 10) == 0) {
|
|
mOptions[RSK_BIG_POES_HINT].Disable("Poe Collector will just give you the item instead with 0 big poes.");
|
|
} else {
|
|
mOptions[RSK_BIG_POES_HINT].Enable();
|
|
}
|
|
});
|
|
OPT_U8(RSK_MASK_QUEST, "Mask Quest", {"Vanilla", "Completed", "Shuffle"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_MASK_QUEST], WIDGET_CVAR_COMBOBOX, 0);
|
|
OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WIDGET_CVAR_COMBOBOX, RO_GOSSIP_STONES_NEED_NOTHING, false, nullptr, IMFLAG_NONE);
|
|
OPT_CALLBACK(RSK_GOSSIP_STONE_HINTS, {
|
|
if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING) ==
|
|
RO_GOSSIP_STONES_NONE) {
|
|
mOptions[RSK_HINT_CLARITY].Hide();
|
|
mOptions[RSK_HINT_DISTRIBUTION].Hide();
|
|
} else {
|
|
mOptions[RSK_HINT_CLARITY].Unhide();
|
|
mOptions[RSK_HINT_DISTRIBUTION].Unhide();
|
|
}
|
|
});
|
|
OPT_U8(RSK_HINT_CLARITY, "Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintClarity"), mOptionDescriptions[RSK_HINT_CLARITY], WIDGET_CVAR_COMBOBOX, RO_HINT_CLARITY_CLEAR, true, nullptr, IMFLAG_INDENT);
|
|
OPT_U8(RSK_HINT_DISTRIBUTION, "Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintDistribution"), mOptionDescriptions[RSK_HINT_DISTRIBUTION], WIDGET_CVAR_COMBOBOX, RO_HINT_DIST_BALANCED, true, nullptr, IMFLAG_UNINDENT);
|
|
OPT_BOOL(RSK_TOT_ALTAR_HINT, "ToT Altar Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AltarHint"), mOptionDescriptions[RSK_TOT_ALTAR_HINT], WIDGET_CVAR_CHECKBOX, RO_GENERIC_ON, false, nullptr, IMFLAG_INDENT);
|
|
OPT_BOOL(RSK_GANONDORF_HINT, "Ganondorf Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GanondorfHint"), mOptionDescriptions[RSK_GANONDORF_HINT], WIDGET_CVAR_CHECKBOX, RO_GENERIC_ON, false, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_SHEIK_LA_HINT, "Sheik Light Arrow Hint", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SheikLAHint"), mOptionDescriptions[RSK_SHEIK_LA_HINT], WIDGET_CVAR_CHECKBOX, RO_GENERIC_ON, false, nullptr, IMFLAG_NONE);
|
|
OPT_BOOL(RSK_BOSS_KEY_HINT, "Boss Door Hints", CVAR_RANDOMIZER_SETTING("BossKeyHint"), mOptionDescriptions[RSK_BOSS_KEY_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_DAMPES_DIARY_HINT, "Dampe's Diary Hint", CVAR_RANDOMIZER_SETTING("DampeHint"), mOptionDescriptions[RSK_DAMPES_DIARY_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_GREG_HINT, "Greg the Green Rupee Hint", CVAR_RANDOMIZER_SETTING("GregHint"), mOptionDescriptions[RSK_GREG_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_LOACH_HINT, "Hyrule Loach Hint", CVAR_RANDOMIZER_SETTING("LoachHint"), mOptionDescriptions[RSK_LOACH_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_SARIA_HINT, "Saria's Hint", CVAR_RANDOMIZER_SETTING("SariaHint"), mOptionDescriptions[RSK_SARIA_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MIDO_HINT, "Mido's Hint", CVAR_RANDOMIZER_SETTING("MidoHint"), mOptionDescriptions[RSK_MIDO_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_FISHING_POLE_HINT, "Fishing Pole Hint", CVAR_RANDOMIZER_SETTING("FishingPoleHint"), mOptionDescriptions[RSK_FISHING_POLE_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_FROGS_HINT, "Frog Ocarina Game Hint", CVAR_RANDOMIZER_SETTING("FrogsHint"), mOptionDescriptions[RSK_FROGS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_OOT_HINT, "Ocarina of Time Hint", CVAR_RANDOMIZER_SETTING("OoTHint"), mOptionDescriptions[RSK_OOT_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_BIGGORON_HINT, "Biggoron's Hint", CVAR_RANDOMIZER_SETTING("BiggoronHint"), mOptionDescriptions[RSK_BIGGORON_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_BIG_POES_HINT, "Big Poes Hint", CVAR_RANDOMIZER_SETTING("BigPoesHint"), mOptionDescriptions[RSK_BIG_POES_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_CHICKENS_HINT, "Chickens Hint", CVAR_RANDOMIZER_SETTING("ChickensHint"), mOptionDescriptions[RSK_CHICKENS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MALON_HINT, "Malon Hint", CVAR_RANDOMIZER_SETTING("MalonHint"), mOptionDescriptions[RSK_MALON_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_HBA_HINT, "Horseback Archery Hint", CVAR_RANDOMIZER_SETTING("HBAHint"), mOptionDescriptions[RSK_HBA_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_WARP_SONG_HINTS, "Warp Song Hints", CVAR_RANDOMIZER_SETTING("WarpSongText"), mOptionDescriptions[RSK_WARP_SONG_HINTS], IMFLAG_NONE, WIDGET_CVAR_CHECKBOX, RO_GENERIC_ON);
|
|
OPT_BOOL(RSK_SCRUB_TEXT_HINT, "Scrub Hint Text", CVAR_RANDOMIZER_SETTING("ScrubText"), mOptionDescriptions[RSK_SCRUB_TEXT_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MERCHANT_TEXT_HINT, "Merchant Hint Text", CVAR_RANDOMIZER_SETTING("MerchantText"), mOptionDescriptions[RSK_MERCHANT_TEXT_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_KAK_10_SKULLS_HINT, "10 GS Hint", CVAR_RANDOMIZER_SETTING("10GSHint"), mOptionDescriptions[RSK_KAK_10_SKULLS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_KAK_20_SKULLS_HINT, "20 GS Hint", CVAR_RANDOMIZER_SETTING("20GSHint"), mOptionDescriptions[RSK_KAK_20_SKULLS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_KAK_30_SKULLS_HINT, "30 GS Hint", CVAR_RANDOMIZER_SETTING("30GSHint"), mOptionDescriptions[RSK_KAK_30_SKULLS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_KAK_40_SKULLS_HINT, "40 GS Hint", CVAR_RANDOMIZER_SETTING("40GSHint"), mOptionDescriptions[RSK_KAK_40_SKULLS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_KAK_50_SKULLS_HINT, "50 GS Hint", CVAR_RANDOMIZER_SETTING("50GSHint"), mOptionDescriptions[RSK_KAK_50_SKULLS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_KAK_100_SKULLS_HINT, "100 GS Hint", CVAR_RANDOMIZER_SETTING("100GSHint"), mOptionDescriptions[RSK_KAK_100_SKULLS_HINT], IMFLAG_NONE);
|
|
OPT_BOOL(RSK_MASK_SHOP_HINT, "Mask Shop Hint", CVAR_RANDOMIZER_SETTING("MaskShopHint"), mOptionDescriptions[RSK_MASK_SHOP_HINT]);
|
|
// TODO: Compasses show rewards/woth, maps show dungeon mode
|
|
OPT_BOOL(RSK_BLUE_FIRE_ARROWS, "Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]);
|
|
OPT_BOOL(RSK_SUNLIGHT_ARROWS, "Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]);
|
|
OPT_BOOL(RSK_ROCS_FEATHER, "Roc's Feather", CVAR_RANDOMIZER_SETTING("RocsFeather"), mOptionDescriptions[RSK_ROCS_FEATHER]);
|
|
OPT_U8(RSK_INFINITE_UPGRADES, "Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]);
|
|
OPT_BOOL(RSK_SKELETON_KEY, "Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]);
|
|
OPT_BOOL(RSK_SLINGBOW_BREAK_BEEHIVES, "Slingshot/Bow Can Break Beehives", CVAR_RANDOMIZER_SETTING("SlingBowBeehives"), mOptionDescriptions[RSK_SLINGBOW_BREAK_BEEHIVES]);
|
|
OPT_U8(RSK_ITEM_POOL, "Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WIDGET_CVAR_COMBOBOX, RO_ITEM_POOL_BALANCED);
|
|
OPT_BOOL(RSK_BASE_ICE_TRAPS, "Base Ice Traps", CVAR_RANDOMIZER_SETTING("BaseIceTraps"), mOptionDescriptions[RSK_BASE_ICE_TRAPS], IMFLAG_NONE, WIDGET_CVAR_COMBOBOX, RO_GENERIC_ON);
|
|
OPT_U8(RSK_ADDITIONAL_ICE_TRAPS, "Additional Ice Traps", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AdditionalIceTraps"), mOptionDescriptions[RSK_ADDITIONAL_ICE_TRAPS], WIDGET_CVAR_SLIDER_INT, 0);
|
|
OPT_U8(RSK_ICE_TRAP_PERCENT, "Ice Trap Percent", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTrapPercent"), mOptionDescriptions[RSK_ICE_TRAP_PERCENT], WIDGET_CVAR_SLIDER_INT, 0);
|
|
// TODO: Remove Double Defense, Progressive Goron Sword
|
|
OPT_U8(RSK_STARTING_OCARINA, "Start with Ocarina", {"Off", "Fairy Ocarina", "Ocarina of Time"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingOcarina"), "", WIDGET_CVAR_COMBOBOX, RO_STARTING_OCARINA_OFF);
|
|
OPT_BOOL(RSK_STARTING_DEKU_SHIELD, "Start with Deku Shield", CVAR_RANDOMIZER_SETTING("StartingDekuShield"));
|
|
OPT_BOOL(RSK_STARTING_KOKIRI_SWORD, "Start with Kokiri Sword", CVAR_RANDOMIZER_SETTING("StartingKokiriSword"));
|
|
OPT_BOOL(RSK_STARTING_MASTER_SWORD, "Start with Master Sword", CVAR_RANDOMIZER_SETTING("StartingMasterSword"));
|
|
OPT_BOOL(RSK_STARTING_STICKS, "Start with Stick Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSticks"), "", WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_BOOL(RSK_STARTING_NUTS, "Start with Nut Ammo", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingNuts"), "", WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_BOOL(RSK_STARTING_BEANS, "Start with Magic Beans", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingBeans"), "", WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_BOOL(RSK_FULL_WALLETS, "Full Wallets", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FullWallets"), mOptionDescriptions[RSK_FULL_WALLETS], WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF);
|
|
OPT_BOOL(RSK_STARTING_ZELDAS_LULLABY, "Start with Zelda's Lullaby", CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_EPONAS_SONG, "Start with Epona's Song", CVAR_RANDOMIZER_SETTING("StartingEponasSong"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_SARIAS_SONG, "Start with Saria's Song", CVAR_RANDOMIZER_SETTING("StartingSariasSong"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_SUNS_SONG, "Start with Sun's Song", CVAR_RANDOMIZER_SETTING("StartingSunsSong"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_SONG_OF_TIME, "Start with Song of Time", CVAR_RANDOMIZER_SETTING("StartingSongOfTime"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_SONG_OF_STORMS, "Start with Song of Storms", CVAR_RANDOMIZER_SETTING("StartingSongOfStorms"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_MINUET_OF_FOREST, "Start with Minuet of Forest", CVAR_RANDOMIZER_SETTING("StartingMinuetOfForest"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_BOLERO_OF_FIRE, "Start with Bolero of Fire", CVAR_RANDOMIZER_SETTING("StartingBoleroOfFire"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_SERENADE_OF_WATER, "Start with Serenade of Water", CVAR_RANDOMIZER_SETTING("StartingSerenadeOfWater"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_REQUIEM_OF_SPIRIT, "Start with Requiem of Spirit", CVAR_RANDOMIZER_SETTING("StartingRequiemOfSpirit"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_NOCTURNE_OF_SHADOW, "Start with Nocturne of Shadow", CVAR_RANDOMIZER_SETTING("StartingNocturneOfShadow"), "", IMFLAG_NONE);
|
|
OPT_BOOL(RSK_STARTING_PRELUDE_OF_LIGHT, "Start with Prelude of Light", CVAR_RANDOMIZER_SETTING("StartingPreludeOfLight"));
|
|
OPT_U8(RSK_STARTING_SKULLTULA_TOKEN, "Gold Skulltula Tokens", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingSkulltulaToken"), "", WIDGET_CVAR_SLIDER_INT);
|
|
OPT_U8(RSK_STARTING_HEARTS, "Starting Hearts", {NumOpts(1, 20)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingHearts"), "", WIDGET_CVAR_SLIDER_INT, 2);
|
|
// TODO: Remainder of Starting Items
|
|
OPT_U8(RSK_LOGIC_RULES, "Logic", {"Glitchless", "No Logic"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LogicRules"), mOptionDescriptions[RSK_LOGIC_RULES], WIDGET_CVAR_COMBOBOX, RO_LOGIC_GLITCHLESS, false, nullptr, IMFLAG_LABEL_INLINE);
|
|
OPT_CALLBACK(RSK_LOGIC_RULES, {
|
|
HandleStartingAgeUI();
|
|
});
|
|
OPT_BOOL(RSK_ALL_LOCATIONS_REACHABLE, "All Locations Reachable", {"Off", "On"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AllLocationsReachable"), mOptionDescriptions[RSK_ALL_LOCATIONS_REACHABLE], WIDGET_CVAR_CHECKBOX, RO_GENERIC_ON, false, nullptr, IMFLAG_SAME_LINE);
|
|
OPT_BOOL(RSK_SKULLS_SUNS_SONG, "Night Skulltula's Expect Sun's Song", CVAR_RANDOMIZER_SETTING("GsExpectSunsSong"), mOptionDescriptions[RSK_SKULLS_SUNS_SONG]);
|
|
OPT_U8(RSK_DAMAGE_MULTIPLIER, "Damage Multiplier", {"x1/2", "x1", "x2", "x4", "x8", "x16", "OHKO"}, OptionCategory::Setting, "", "", WIDGET_CVAR_SLIDER_INT, RO_DAMAGE_MULTIPLIER_DEFAULT);
|
|
// Don't show any MQ options if both quests aren't available
|
|
if (!(OTRGlobals::Instance->HasMasterQuest() && OTRGlobals::Instance->HasOriginal())) {
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_DUNGEON_SET].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_DEKU_TREE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_JABU_JABU].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_ICE_CAVERN].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_GTG].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Disable("This option has been disabled because only one type of O2R has been loaded");
|
|
} else {
|
|
// If any MQ Options are available, show the MQ Dungeon Randomization Combobox
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Enable();
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Enable();
|
|
mOptions[RSK_MQ_DUNGEON_SET].Enable();
|
|
mOptions[RSK_MQ_DEKU_TREE].Enable();
|
|
mOptions[RSK_MQ_DODONGOS_CAVERN].Enable();
|
|
mOptions[RSK_MQ_JABU_JABU].Enable();
|
|
mOptions[RSK_MQ_FOREST_TEMPLE].Enable();
|
|
mOptions[RSK_MQ_FIRE_TEMPLE].Enable();
|
|
mOptions[RSK_MQ_WATER_TEMPLE].Enable();
|
|
mOptions[RSK_MQ_SPIRIT_TEMPLE].Enable();
|
|
mOptions[RSK_MQ_SHADOW_TEMPLE].Enable();
|
|
mOptions[RSK_MQ_BOTTOM_OF_THE_WELL].Enable();
|
|
mOptions[RSK_MQ_ICE_CAVERN].Enable();
|
|
mOptions[RSK_MQ_GTG].Enable();
|
|
mOptions[RSK_MQ_GANONS_CASTLE].Enable();
|
|
}
|
|
// clang-format on
|
|
|
|
StaticData::optionNameToEnum = PopulateOptionNameToEnum();
|
|
|
|
mExcludeLocationsOptionsAreas.reserve(RCAREA_INVALID);
|
|
|
|
// RANDOTODO sweep trick descriptions and make sure they match a post-refactor, post shuffles reality
|
|
/* Common abbreviations in name tags
|
|
- A: Adult
|
|
- Blk: Block
|
|
- Blu: Blue (Switch)
|
|
- Bmb: Bombs
|
|
- Bou: Boulder
|
|
- C: Child
|
|
- Clp: Clip
|
|
- Col: Collision
|
|
- Cuc: Cucoo
|
|
- Crt: Crate
|
|
- Diff: Difficult (Weapons)
|
|
- Ent: Entrance
|
|
- HB: Hover Boots
|
|
- Jmp: Jump
|
|
- Ldg: Ledge
|
|
- LoT: Lens of Truth
|
|
- Prj: Projectile
|
|
- Rng: Boomerang
|
|
- Sli: Slingshot
|
|
- Skp: Skip
|
|
- Swt: Switch
|
|
- Tor: Torch
|
|
Try to keep Name Tags less than 8 chars.
|
|
*/
|
|
|
|
// the following are glitches and are currently disabled
|
|
|
|
// OPT_TRICK(RT_ACUTE_ANGLE_CLIP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_ADVANCED_CLIPS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_BLANK_A, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_DOOM_JUMP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_EPG, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH});
|
|
|
|
// OPT_TRICK(RT_EQUIP_SWAP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_EQUIP_SWAP_EXPECTS_DINS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_FLAME_STORAGE, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_GROUND_CLIP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_HESS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH});
|
|
|
|
// OPT_TRICK(RT_HOOKSHOT_CLIP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_HOOKSHOT_JUMP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH });
|
|
|
|
// OPT_TRICK(RT_ISG, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL,
|
|
// Tricks::Tag::GLITCH});
|
|
|
|
OPT_TRICK(RT_VISIBLE_COLLISION, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "VisCol");
|
|
OPT_TRICK(RT_GROTTOS_WITHOUT_AGONY, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "NoSoA");
|
|
OPT_TRICK(RT_FEWER_TUNIC_REQUIREMENTS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, "FTR");
|
|
OPT_TRICK(RT_UNINTUITIVE_JUMPS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "UnJmp");
|
|
OPT_TRICK(RT_FIRE_RINGS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, "FlaChst");
|
|
|
|
// disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely
|
|
// decoupled from rando
|
|
|
|
// OPT_TRICK(RT_BUNNY_HOOD_JUMPS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED });
|
|
|
|
OPT_TRICK(RT_DAMAGE_BOOST_SIMPLE, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::EXPERIMENTAL },
|
|
"SDmgBoo");
|
|
OPT_TRICK(RT_HOVER_BOOST_SIMPLE, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::ADVANCED, Tricks::Tag::GLITCH }, "SHovBoo");
|
|
OPT_TRICK(RT_BOMBCHU_BEEHIVES, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "ChuBee");
|
|
OPT_TRICK(RT_HOOKSHOT_LADDERS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "HSLad");
|
|
OPT_TRICK(RT_BLUE_FIRE_MUD_WALLS, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "BluFire");
|
|
OPT_TRICK(RT_OPEN_UNDERWATER_CHEST, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "OpenUC");
|
|
OPT_TRICK(RT_BOULDER_COLLISION, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "BolCol");
|
|
OPT_TRICK(RT_ITEM_EXTENSION, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE }, "HSExt");
|
|
OPT_TRICK(RT_BIG_SKULLTULA_PAUSE_LIFT, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH },
|
|
"SkulPaus");
|
|
OPT_TRICK(RT_GROUND_JUMP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "GrdJmp");
|
|
OPT_TRICK(RT_GROUND_JUMP_HARD, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::INTERMEDIATE, Tricks::Tag::GLITCH },
|
|
"HGrdJmp");
|
|
OPT_TRICK(RT_SLIDE_JUMP, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "SldJmp");
|
|
OPT_TRICK(RT_VOIDOUT_COLLECTION, RCQUEST_BOTH, RA_NONE, { Tricks::Tag::NOVICE }, "VdCl");
|
|
OPT_TRICK(RT_KF_ADULT_GS, RCQUEST_BOTH, RA_KOKIRI_FOREST, { Tricks::Tag::NOVICE }, "KFGSHB");
|
|
OPT_TRICK(RT_LW_BRIDGE, RCQUEST_BOTH, RA_THE_LOST_WOODS, { Tricks::Tag::EXPERT }, "LWBrgJmp");
|
|
OPT_TRICK(RT_LW_MIDO_BACKFLIP, RCQUEST_BOTH, RA_THE_LOST_WOODS, { Tricks::Tag::NOVICE }, "MidoSkip");
|
|
OPT_TRICK(RT_LOST_WOOD_NAVI_DIVE, RCQUEST_BOTH, RA_THE_LOST_WOODS, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH },
|
|
"LWNaviD");
|
|
OPT_TRICK(RT_LW_GS_BEAN, RCQUEST_BOTH, RA_THE_LOST_WOODS, { Tricks::Tag::INTERMEDIATE }, "LWGSHS");
|
|
OPT_TRICK(RT_HC_STORMS_GS, RCQUEST_BOTH, RA_HYRULE_CASTLE, { Tricks::Tag::INTERMEDIATE }, "HCGrGSRng");
|
|
OPT_TRICK(RT_HF_BIG_POE_WITHOUT_EPONA, RCQUEST_BOTH, RA_HYRULE_FIELD, { Tricks::Tag::NOVICE }, "PoeDiff");
|
|
OPT_TRICK(RT_KAK_TOWER_GS, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, { Tricks::Tag::INTERMEDIATE }, "KakGSJS");
|
|
OPT_TRICK(RT_KAK_CHILD_WINDMILL_POH, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, { Tricks::Tag::EXTREME }, "WndCJS");
|
|
OPT_TRICK(RT_KAK_ROOFTOP_GS, RCQUEST_BOTH, RA_KAKARIKO_VILLAGE, { Tricks::Tag::ADVANCED }, "KakGSHB");
|
|
OPT_TRICK(RT_GY_POH, RCQUEST_BOTH, RA_THE_GRAVEYARD, { Tricks::Tag::INTERMEDIATE }, "GYPoHRng");
|
|
OPT_TRICK(RT_GY_CHILD_DAMPE_RACE_POH, RCQUEST_BOTH, RA_THE_GRAVEYARD, { Tricks::Tag::NOVICE }, "CDmpRace");
|
|
OPT_TRICK(RT_GY_SHADOW_FIRE_ARROWS, RCQUEST_BOTH, RA_THE_GRAVEYARD, { Tricks::Tag::EXPERT }, "FAEntry");
|
|
OPT_TRICK(RT_DMT_SHIELDLESS_CLIMB, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::NOVICE }, "DMTCWoS");
|
|
OPT_TRICK(RT_DMT_SOIL_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::INTERMEDIATE }, "DMTSoil");
|
|
OPT_TRICK(RT_DMT_BOMBABLE, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::INTERMEDIATE }, "DMTSTR");
|
|
OPT_TRICK(RT_DMT_HOVERS_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::ADVANCED }, "DMTGSHB");
|
|
OPT_TRICK(RT_DMT_BEAN_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::EXPERT }, "DMTGSMB");
|
|
OPT_TRICK(RT_DMT_JS_LOWER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::INTERMEDIATE }, "DMTGSJS");
|
|
OPT_TRICK(RT_DMT_CLIMB_HOVERS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::ADVANCED }, "DMTBouHB");
|
|
OPT_TRICK(RT_DMT_UPPER_GS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::NOVICE }, "DMTGSBF");
|
|
|
|
// disabled for now, only applies when trade quest is not shuffled so there's a timer (currently not considered in
|
|
// logic)
|
|
|
|
// OPT_TRICK(RT_DMT_BOLERO_BIGGORON, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_TRAIL, { Tricks::Tag::INTERMEDIATE });
|
|
|
|
OPT_TRICK(RT_GC_POT, RCQUEST_BOTH, RA_GORON_CITY, { Tricks::Tag::ADVANCED }, "GorPotChu");
|
|
OPT_TRICK(RT_GC_POT_STRENGTH, RCQUEST_BOTH, RA_GORON_CITY, { Tricks::Tag::INTERMEDIATE }, "GorPotStr");
|
|
OPT_TRICK(RT_GC_ROLLING_STRENGTH, RCQUEST_BOTH, RA_GORON_CITY, { Tricks::Tag::INTERMEDIATE }, "GorStrC");
|
|
OPT_TRICK(RT_GC_LEFTMOST, RCQUEST_BOTH, RA_GORON_CITY, { Tricks::Tag::ADVANCED }, "GCMazHB");
|
|
OPT_TRICK(RT_GC_GROTTO, RCQUEST_BOTH, RA_GORON_CITY, { Tricks::Tag::ADVANCED }, "GorGroHS");
|
|
OPT_TRICK(RT_GC_LINK_GORON_DINS, RCQUEST_BOTH, RA_GORON_CITY, { Tricks::Tag::NOVICE }, "GorDinA");
|
|
OPT_TRICK(RT_DMC_HOVER_BEAN_POH, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, { Tricks::Tag::NOVICE }, "DMCHB");
|
|
OPT_TRICK(RT_DMC_BOLERO_JUMP, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, { Tricks::Tag::EXTREME }, "DMCBolJump");
|
|
OPT_TRICK(RT_DMC_BOULDER_JS, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, { Tricks::Tag::NOVICE }, "DMCHam");
|
|
OPT_TRICK(RT_DMC_BOULDER_SKIP, RCQUEST_BOTH, RA_DEATH_MOUNTAIN_CRATER, { Tricks::Tag::INTERMEDIATE }, "DMCULJmp");
|
|
OPT_TRICK(RT_ZR_LOWER, RCQUEST_BOTH, RA_ZORAS_RIVER, { Tricks::Tag::INTERMEDIATE }, "ZRLJmp");
|
|
OPT_TRICK(RT_ZR_UPPER, RCQUEST_BOTH, RA_ZORAS_RIVER, { Tricks::Tag::INTERMEDIATE }, "ZRUJmp");
|
|
OPT_TRICK(RT_ZR_HOVERS, RCQUEST_BOTH, RA_ZORAS_RIVER, { Tricks::Tag::NOVICE }, "ZRZDHB");
|
|
OPT_TRICK(RT_ZR_CUCCO, RCQUEST_BOTH, RA_ZORAS_RIVER, { Tricks::Tag::NOVICE }, "ZRZDCuc");
|
|
OPT_TRICK(RT_ZD_KING_ZORA_SKIP, RCQUEST_BOTH, RA_ZORAS_DOMAIN, { Tricks::Tag::INTERMEDIATE }, "Mweep");
|
|
OPT_TRICK(RT_ZD_GS, RCQUEST_BOTH, RA_ZORAS_DOMAIN, { Tricks::Tag::INTERMEDIATE }, "ZDGS");
|
|
OPT_TRICK(RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES, RCQUEST_BOTH, RA_ZORAS_FOUNTAIN, { Tricks::Tag::NOVICE },
|
|
"ZFGFStr2");
|
|
OPT_TRICK(RT_LH_LAB_WALL_GS, RCQUEST_BOTH, RA_LAKE_HYLIA, { Tricks::Tag::NOVICE }, "LHGSJS");
|
|
OPT_TRICK(RT_LH_LAB_DIVING, RCQUEST_BOTH, RA_LAKE_HYLIA, { Tricks::Tag::NOVICE }, "LabHS");
|
|
OPT_TRICK(RT_LH_WATER_HOOKSHOT, RCQUEST_BOTH, RA_LAKE_HYLIA, { Tricks::Tag::INTERMEDIATE }, "WTEntHS");
|
|
OPT_TRICK(RT_GV_CRATE_HOVERS, RCQUEST_BOTH, RA_GERUDO_VALLEY, { Tricks::Tag::INTERMEDIATE }, "GVPoHHB");
|
|
OPT_TRICK(RT_GV_CHILD_TENT, RCQUEST_BOTH, RA_GERUDO_VALLEY, { Tricks::Tag::NOVICE }, "GVTent");
|
|
OPT_TRICK(RT_GV_CHILD_CUCCO_JUMP, RCQUEST_BOTH, RA_GERUDO_VALLEY, { Tricks::Tag::INTERMEDIATE }, "GVCUC");
|
|
OPT_TRICK(RT_GV_HOOKSHOT_BRIDGE, RCQUEST_BOTH, RA_GERUDO_VALLEY, { Tricks::Tag::ADVANCED }, "GVHSBrg");
|
|
OPT_TRICK(RT_PASS_GUARDS_WITH_NOTHING, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, "Guards");
|
|
OPT_TRICK(RT_GF_WASTELAND_GATE_SIDEHOP_SKIP, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, "GFHWC");
|
|
OPT_TRICK(RT_GF_ADULT_SKIP_WASTELAND_GATE, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::INTERMEDIATE },
|
|
"GFHWA");
|
|
OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, "GWDiff");
|
|
OPT_TRICK(RT_GF_LEDGE_CLIP_INTO_GTG, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH },
|
|
"GTGLdgClp");
|
|
|
|
// disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely
|
|
// decoupled from rando
|
|
|
|
// OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::NOVICE });
|
|
|
|
OPT_TRICK(RT_HW_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::INTERMEDIATE }, "RvrSand");
|
|
OPT_TRICK(RT_LENS_HW, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::INTERMEDIATE }, "HWNoLoT");
|
|
OPT_TRICK(RT_HW_REVERSE, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, { Tricks::Tag::INTERMEDIATE }, "RevHW");
|
|
OPT_TRICK(RT_COLOSSUS_GS, RCQUEST_BOTH, RA_DESERT_COLOSSUS, { Tricks::Tag::NOVICE }, "ColGSHS");
|
|
OPT_TRICK(RT_DEKU_BASEMENT_GS, RCQUEST_VANILLA, RA_DEKU_TREE, { Tricks::Tag::NOVICE }, "DTGSJS");
|
|
OPT_TRICK(RT_DEKU_B1_SKIP, RCQUEST_BOTH, RA_DEKU_TREE, { Tricks::Tag::INTERMEDIATE }, "B1Skip");
|
|
OPT_TRICK(RT_DEKU_B1_BOW_WEBS, RCQUEST_VANILLA, RA_DEKU_TREE, { Tricks::Tag::NOVICE }, "DTWebBow");
|
|
OPT_TRICK(RT_DEKU_B1_BACKFLIP_OVER_SPIKED_LOG, RCQUEST_VANILLA, RA_DEKU_TREE, { Tricks::Tag::NOVICE }, "DTLogBF");
|
|
OPT_TRICK(RT_DEKU_MQ_COMPASS_GS, RCQUEST_MQ, RA_DEKU_TREE, { Tricks::Tag::NOVICE }, "DTGSHam");
|
|
OPT_TRICK(RT_DEKU_MQ_LOG, RCQUEST_MQ, RA_DEKU_TREE, { Tricks::Tag::NOVICE }, "DTLogRol");
|
|
OPT_TRICK(RT_DC_SCARECROW_GS, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "DCArmos");
|
|
OPT_TRICK(RT_DC_VINES_GS, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "DCGSLS");
|
|
OPT_TRICK(RT_DC_STAIRS_WITH_BOW, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "DCStaBow");
|
|
OPT_TRICK(RT_DC_SLINGSHOT_SKIP, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, { Tricks::Tag::EXPERT }, "DCSliSkp");
|
|
OPT_TRICK(RT_DC_SCRUB_ROOM, RCQUEST_VANILLA, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "DCSrbStr");
|
|
OPT_TRICK(RT_DC_HAMMER_FLOOR, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "KDHamFl");
|
|
OPT_TRICK(RT_DC_DODONGO_CHU, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "KDChu");
|
|
OPT_TRICK(RT_DC_MQ_STAIRS_WITH_ONLY_STRENGTH, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::NOVICE }, "DCStaStr");
|
|
OPT_TRICK(RT_DC_MQ_CHILD_BOMBS, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCLobyJS");
|
|
OPT_TRICK(RT_DC_MQ_CHILD_EYES, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::EXPERT }, "DCEyeStrC");
|
|
OPT_TRICK(RT_DC_MQ_ADULT_EYES, RCQUEST_MQ, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCEyeStrA");
|
|
OPT_TRICK(RT_DC_EYES_CHU, RCQUEST_BOTH, RA_DODONGOS_CAVERN, { Tricks::Tag::ADVANCED }, "DCEyeChu");
|
|
OPT_TRICK(RT_JABU_BOSS_HOVER, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, { Tricks::Tag::INTERMEDIATE }, "JbuBoxHB");
|
|
OPT_TRICK(RT_JABU_NEAR_BOSS_RANGED, RCQUEST_BOTH, RA_JABU_JABUS_BELLY, { Tricks::Tag::NOVICE }, "JbuBosPrj");
|
|
OPT_TRICK(RT_JABU_NEAR_BOSS_EXPLOSIVES, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, { Tricks::Tag::INTERMEDIATE },
|
|
"JbuBosExp");
|
|
OPT_TRICK(RT_JABU_B1_CUBE_HOVER, RCQUEST_VANILLA, RA_JABU_JABUS_BELLY, { Tricks::Tag::NOVICE }, "JbuJigHB");
|
|
OPT_TRICK(RT_LENS_JABU_MQ, RCQUEST_MQ, RA_JABU_JABUS_BELLY, { Tricks::Tag::NOVICE }, "JbuLoT");
|
|
OPT_TRICK(RT_JABU_MQ_RANG_JUMP, RCQUEST_MQ, RA_JABU_JABUS_BELLY, { Tricks::Tag::ADVANCED }, "JbuSwtRng");
|
|
OPT_TRICK(RT_JABU_MQ_SOT_GS, RCQUEST_MQ, RA_JABU_JABUS_BELLY, { Tricks::Tag::INTERMEDIATE }, "JbuSoTRng");
|
|
OPT_TRICK(RT_JABU_BARINADE_POTS, RCQUEST_BOTH, RA_JABU_JABUS_BELLY, { Tricks::Tag::ADVANCED }, "BariPot");
|
|
OPT_TRICK(RT_LENS_BOTW, RCQUEST_VANILLA, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, "BWLoT");
|
|
OPT_TRICK(RT_BOTTOM_OF_THE_WELL_NAVI_DIVE, RCQUEST_BOTH, RA_BOTTOM_OF_THE_WELL,
|
|
{ Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "KakNviD");
|
|
OPT_TRICK(RT_BOTW_CHILD_DEADHAND, RCQUEST_BOTH, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, "DHDiff");
|
|
OPT_TRICK(RT_BOTW_BASEMENT, RCQUEST_VANILLA, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, "BWBmbFl");
|
|
// RANDOTODO with doorsanity, this can be relevant in Vanilla
|
|
OPT_TRICK(RT_BOTW_PITS, RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, "BWPitJmp");
|
|
OPT_TRICK(RT_BOTW_MQ_DEADHAND_KEY, RCQUEST_MQ, RA_BOTTOM_OF_THE_WELL, { Tricks::Tag::NOVICE }, "BWKeyRng");
|
|
OPT_TRICK(RT_FOREST_FIRST_GS, RCQUEST_VANILLA, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FT1stGS");
|
|
OPT_TRICK(RT_FOREST_COURTYARD_EAST_GS, RCQUEST_VANILLA, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTGSRng");
|
|
OPT_TRICK(RT_FOREST_VINES, RCQUEST_BOTH, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTVineHS");
|
|
OPT_TRICK(RT_FOREST_COURTYARD_LEDGE, RCQUEST_BOTH, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTLdgHB");
|
|
OPT_TRICK(RT_FOREST_DOORFRAME, RCQUEST_BOTH, RA_FOREST_TEMPLE, { Tricks::Tag::ADVANCED }, "FTDoorHB");
|
|
OPT_TRICK(RT_FOREST_OUTSIDE_BACKDOOR, RCQUEST_BOTH, RA_FOREST_TEMPLE, { Tricks::Tag::ADVANCED }, "FTBlkJS");
|
|
OPT_TRICK(RT_FOREST_COURTYARD_HEARTS_BOOMERANG, RCQUEST_BOTH, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE },
|
|
"FTHrtRng");
|
|
OPT_TRICK(RT_FOREST_WELL_SWIM, RCQUEST_MQ, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTSwim");
|
|
OPT_TRICK(RT_FOREST_MQ_BLOCK_PUZZLE, RCQUEST_MQ, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTBlkChu");
|
|
// Child with hovers cannot do this from the lower floor, and must go to the upper floor which needs goron bracelet.
|
|
// Adult can do this with hammer and KSword, But child cannot.
|
|
OPT_TRICK(RT_FOREST_MQ_JS_HALLWAY_SWITCH, RCQUEST_MQ, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTTwstJS");
|
|
OPT_TRICK(RT_FOREST_MQ_HOOKSHOT_HALLWAY_SWITCH, RCQUEST_MQ, RA_FOREST_TEMPLE, { Tricks::Tag::INTERMEDIATE },
|
|
"FTTwstHS");
|
|
OPT_TRICK(RT_FOREST_MQ_RANG_HALLWAY_SWITCH, RCQUEST_MQ, RA_FOREST_TEMPLE, { Tricks::Tag::INTERMEDIATE },
|
|
"FTTwstRng");
|
|
OPT_TRICK(RT_FOREST_MQ_CHILD_DOORFRAME, RCQUEST_MQ, RA_FOREST_TEMPLE, { Tricks::Tag::NOVICE }, "FTDoorC");
|
|
// Is also used in MQ logic, but has no practical effect there as of now
|
|
OPT_TRICK(RT_FIRE_SOT, RCQUEST_VANILLA, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FISoTSkp");
|
|
OPT_TRICK(RT_FIRE_STRENGTH, RCQUEST_VANILLA, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FIStrSkp");
|
|
OPT_TRICK(RT_FIRE_SCARECROW, RCQUEST_VANILLA, RA_FIRE_TEMPLE, { Tricks::Tag::EXPERT }, "PixelShot");
|
|
OPT_TRICK(RT_FIRE_SKIP_FLAME_WALLS, RCQUEST_VANILLA, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FIRWAL");
|
|
OPT_TRICK(RT_FIRE_MQ_NEAR_BOSS, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::NOVICE }, "FICrtTor");
|
|
OPT_TRICK(RT_FIRE_MQ_BLOCKED_CHEST, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FIHSSkp");
|
|
OPT_TRICK(RT_FIRE_MQ_BK_CHEST, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FIBowSkp");
|
|
OPT_TRICK(RT_FIRE_MQ_CLIMB, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::NOVICE }, "FIFirSkp");
|
|
OPT_TRICK(RT_FIRE_MQ_MAZE_SIDE_ROOM, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::NOVICE }, "FIBoxSkp");
|
|
OPT_TRICK(RT_FIRE_MQ_MAZE_HOVERS, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::NOVICE }, "FIMazHB");
|
|
OPT_TRICK(RT_FIRE_MQ_MAZE_JUMP, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FIMazJmp");
|
|
OPT_TRICK(RT_FIRE_MQ_ABOVE_MAZE_GS, RCQUEST_MQ, RA_FIRE_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "FIGSLS");
|
|
OPT_TRICK(RT_WATER_LONGSHOT_TORCH, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTTorLS");
|
|
OPT_TRICK(RT_WATER_CRACKED_WALL_HOVERS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTCrkHB");
|
|
OPT_TRICK(RT_WATER_CRACKED_WALL, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "WTCrkJmp");
|
|
OPT_TRICK(RT_WATER_BK_REGION, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "WTBKHB");
|
|
OPT_TRICK(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP, RCQUEST_BOTH, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE },
|
|
"WTBolLdg");
|
|
// Also used in MQ logic, but won't be relevent unless a way to enter tower without irons exists (likely a clip +
|
|
// swim)
|
|
OPT_TRICK(RT_WATER_FW_CENTRAL_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTGSFW");
|
|
OPT_TRICK(RT_WATER_IRONS_CENTRAL_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTGSIB");
|
|
OPT_TRICK(RT_WATER_CENTRAL_BOW, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::ADVANCED }, "WTBowJmp");
|
|
OPT_TRICK(RT_WATER_HOOKSHOT_FALLING_PLATFORM_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE },
|
|
"WTWfalHS");
|
|
OPT_TRICK(RT_WATER_RANG_FALLING_PLATFORM_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE },
|
|
"WTWfalRng");
|
|
OPT_TRICK(RT_WATER_RIVER_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "WTRvrLS");
|
|
OPT_TRICK(RT_WATER_DRAGON_JUMP_DIVE, RCQUEST_BOTH, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTDrgJmp");
|
|
OPT_TRICK(RT_WATER_ADULT_DRAGON, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTDrgA");
|
|
OPT_TRICK(RT_WATER_CHILD_DRAGON, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::ADVANCED }, "WTDrgC");
|
|
OPT_TRICK(RT_WATER_MQ_CENTRAL_PILLAR, RCQUEST_MQ, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTCntFA");
|
|
OPT_TRICK(RT_WATER_IRON_BOOTS_LEDGE_GRAB, RCQUEST_BOTH, RA_WATER_TEMPLE,
|
|
{ Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, "IBSrfLG");
|
|
OPT_TRICK(RT_WATER_INVISIBLE_HOOKSHOT_TARGET, RCQUEST_BOTH, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTTarg");
|
|
OPT_TRICK(RT_WATER_MORPHA_WITHOUT_HOOKSHOT, RCQUEST_BOTH, RA_WATER_TEMPLE, { Tricks::Tag::EXTREME }, "MorphDiff");
|
|
OPT_TRICK(RT_LENS_SHADOW, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STStLoT");
|
|
OPT_TRICK(RT_LENS_SHADOW_PLATFORM, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STMvLot");
|
|
OPT_TRICK(RT_LENS_BONGO, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "BNGLoT");
|
|
OPT_TRICK(RT_SHADOW_UMBRELLA_HOVER, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::EXPERT }, "STUmbSkp");
|
|
OPT_TRICK(RT_SHADOW_UMBRELLA_CLIP, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH },
|
|
"STUmbClp");
|
|
OPT_TRICK(RT_SHADOW_UMBRELLA_GS, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::EXPERT }, "STUmbHB");
|
|
OPT_TRICK(RT_SHADOW_FREESTANDING_KEY, RCQUEST_VANILLA, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STPotChu");
|
|
OPT_TRICK(RT_SHADOW_STATUE, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "STStaChu");
|
|
OPT_TRICK(RT_SHADOW_BONGO, RCQUEST_BOTH, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "BngNoPrg");
|
|
OPT_TRICK(RT_LENS_SHADOW_MQ, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STMQStLoT");
|
|
OPT_TRICK(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STBldLoT");
|
|
OPT_TRICK(RT_LENS_SHADOW_MQ_PLATFORM, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STMQMvLot");
|
|
OPT_TRICK(RT_LENS_SHADOW_MQ_DEADHAND, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::NOVICE }, "STDHLoT");
|
|
OPT_TRICK(RT_SHADOW_MQ_GAP, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "STTSLS");
|
|
OPT_TRICK(RT_SHADOW_MQ_INVISIBLE_BLADES, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "STSoTSkp");
|
|
OPT_TRICK(RT_SHADOW_MQ_HUGE_PIT, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "STPitJmp");
|
|
OPT_TRICK(RT_SHADOW_MQ_WINDY_WALKWAY, RCQUEST_MQ, RA_SHADOW_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "STWindSkp");
|
|
OPT_TRICK(RT_LENS_SPIRIT, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::NOVICE }, "SPLoT");
|
|
OPT_TRICK(RT_SPIRIT_CHILD_CHU, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::NOVICE }, "SPBrgChu");
|
|
OPT_TRICK(RT_SPIRIT_WEST_LEDGE, RCQUEST_BOTH, RA_SPIRIT_TEMPLE, { Tricks::Tag::NOVICE }, "SPWeRng");
|
|
OPT_TRICK(RT_SPIRIT_LOWER_ADULT_SWITCH, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::ADVANCED }, "SPSwtBmb");
|
|
OPT_TRICK(RT_SPIRIT_STATUE_JUMP, RCQUEST_BOTH, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "SPHndJmp");
|
|
|
|
// disabled since "Spirit Temple boss shortcuts" (pre-lowers the platform where you break the statues face) isn't a
|
|
// setting in ship
|
|
|
|
// OPT_TRICK(RT_SPIRIT_PLATFORM_HOOKSHOT, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE });
|
|
|
|
OPT_TRICK(RT_SPIRIT_MAP_CHEST, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::NOVICE }, "SPMapBow");
|
|
OPT_TRICK(RT_SPIRIT_SUN_CHEST, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::ADVANCED }, "SPSUNBOW");
|
|
OPT_TRICK(RT_SPIRIT_WALL, RCQUEST_VANILLA, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "SPWall");
|
|
OPT_TRICK(RT_LENS_SPIRIT_MQ, RCQUEST_MQ, RA_SPIRIT_TEMPLE, { Tricks::Tag::NOVICE }, "SPMQLoT");
|
|
OPT_TRICK(RT_SPIRIT_MQ_SUN_BLOCK_SOT, RCQUEST_MQ, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "SPBluSkp");
|
|
OPT_TRICK(RT_SPIRIT_MQ_SUN_BLOCK_GS, RCQUEST_MQ, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "SPBlkGS");
|
|
OPT_TRICK(RT_SPIRIT_MQ_LOWER_ADULT, RCQUEST_MQ, RA_SPIRIT_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "SPTorDin");
|
|
OPT_TRICK(RT_SPIRIT_MQ_FROZEN_EYE, RCQUEST_MQ, RA_SPIRIT_TEMPLE, { Tricks::Tag::NOVICE }, "SPFEBow");
|
|
OPT_TRICK(RT_ICE_STALAGMITE_CLIP, RCQUEST_BOTH, RA_ICE_CAVERN, { Tricks::Tag::NOVICE }, "StalClp");
|
|
OPT_TRICK(RT_ICE_STALAGMITE_HOOKSHOT, RCQUEST_BOTH, RA_ICE_CAVERN, { Tricks::Tag::NOVICE }, "StalHS");
|
|
OPT_TRICK(RT_ICE_BLOCK_GS, RCQUEST_VANILLA, RA_ICE_CAVERN, { Tricks::Tag::INTERMEDIATE }, "ICBlkHB");
|
|
OPT_TRICK(RT_ICE_MQ_RED_ICE_GS, RCQUEST_MQ, RA_ICE_CAVERN, { Tricks::Tag::INTERMEDIATE }, "ICNoSoT");
|
|
OPT_TRICK(RT_LENS_GTG, RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::NOVICE }, "GTGLoT");
|
|
OPT_TRICK(RT_GTG_WITHOUT_HOOKSHOT, RCQUEST_VANILLA, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::INTERMEDIATE },
|
|
"GTGNoHS");
|
|
OPT_TRICK(RT_GTG_FAKE_WALL, RCQUEST_BOTH, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::NOVICE }, "GTGWallHB");
|
|
OPT_TRICK(RT_GTG_LAVA_JUMP, RCQUEST_BOTH, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::INTERMEDIATE }, "GTGLavaJmp");
|
|
OPT_TRICK(RT_GTG_STATUE_JUMP, RCQUEST_BOTH, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::INTERMEDIATE }, "GTGStJmp");
|
|
OPT_TRICK(RT_LENS_GTG_MQ, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::NOVICE }, "GTGMQLoT");
|
|
OPT_TRICK(RT_GTG_MQ_WITH_HOOKSHOT, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::NOVICE }, "GTGMQHS");
|
|
OPT_TRICK(RT_GTG_MQ_WITHOUT_HOOKSHOT, RCQUEST_MQ, RA_GERUDO_TRAINING_GROUND, { Tricks::Tag::INTERMEDIATE },
|
|
"GTGMQNoHS");
|
|
OPT_TRICK(RT_LENS_GANON, RCQUEST_VANILLA, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCLoT");
|
|
OPT_TRICK(RT_GANON_SPIRIT_TRIAL_HOOKSHOT, RCQUEST_VANILLA, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCNoHS");
|
|
OPT_TRICK(RT_LENS_GANON_MQ, RCQUEST_MQ, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCMQLoT");
|
|
OPT_TRICK(RT_GANON_MQ_FIRE_TRIAL, RCQUEST_MQ, RA_GANONS_CASTLE, { Tricks::Tag::ADVANCED }, "GCFTHS");
|
|
OPT_TRICK(RT_GANON_MQ_SHADOW_TRIAL, RCQUEST_MQ, RA_GANONS_CASTLE, { Tricks::Tag::NOVICE }, "GCSTBow");
|
|
OPT_TRICK(RT_GANON_MQ_LIGHT_TRIAL, RCQUEST_MQ, RA_GANONS_CASTLE, { Tricks::Tag::INTERMEDIATE }, "GCFirWal");
|
|
|
|
for (auto trick : mTrickSettings) {
|
|
if (trick.GetNameTag() != "") {
|
|
if (StaticData::trickToEnum.contains(trick.GetNameTag())) {
|
|
SPDLOG_ERROR("REPEATED TRICK NAME TAG " + trick.GetName());
|
|
assert(false);
|
|
} else {
|
|
StaticData::trickToEnum[trick.GetNameTag()] = trick.GetKey();
|
|
}
|
|
}
|
|
}
|
|
|
|
mOptionGroups[RSG_LOGIC] = OptionGroup::SubGroup("Logic Options", {
|
|
&mOptions[RSK_LOGIC_RULES],
|
|
&mOptions[RSK_ALL_LOCATIONS_REACHABLE],
|
|
&mOptions[RSK_SKULLS_SUNS_SONG],
|
|
&mOptions[RSK_BIG_POE_COUNT],
|
|
});
|
|
// TODO: Exclude Locations Menus
|
|
mTricksByArea.clear();
|
|
std::vector<Option*> tricksOption;
|
|
tricksOption.reserve(mTrickSettings.size());
|
|
for (int i = 0; i < RT_MAX; i++) {
|
|
auto trick = &mTrickSettings[i];
|
|
if (!trick->GetName().empty()) {
|
|
tricksOption.push_back(trick);
|
|
mTrickNameToEnum[std::string(trick->GetName())] = static_cast<RandomizerTrick>(i);
|
|
mTricksByArea[trick->GetArea()].push_back(static_cast<RandomizerTrick>(i));
|
|
}
|
|
}
|
|
mOptionGroups[RSG_TRICKS] = OptionGroup::SubGroup("Logical Tricks", tricksOption);
|
|
mOptionGroups[RSG_MENU_SECTION_LOGIC] = OptionGroup::SubGroup("Logic",
|
|
{
|
|
&mOptions[RSK_LOGIC_RULES],
|
|
&mOptions[RSK_ALL_LOCATIONS_REACHABLE],
|
|
&mOptions[RSK_STARTING_AGE],
|
|
&mOptions[RSK_SKULLS_SUNS_SONG],
|
|
&mOptions[RSK_BIG_POE_COUNT],
|
|
&mOptions[RSK_BLUE_FIRE_ARROWS],
|
|
&mOptions[RSK_SUNLIGHT_ARROWS],
|
|
&mOptions[RSK_FULL_WALLETS],
|
|
&mOptions[RSK_SLINGBOW_BREAK_BEEHIVES],
|
|
&mOptions[RSK_SKIP_CHILD_ZELDA],
|
|
&mOptions[RSK_MASK_QUEST],
|
|
&mOptions[RSK_SKIP_CHILD_STEALTH],
|
|
&mOptions[RSK_SKIP_PLANTING_BEANS],
|
|
&mOptions[RSK_SKIP_EPONA_RACE],
|
|
&mOptions[RSK_SKIP_SCARECROWS_SONG],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_SECTION_WINCON] = OptionGroup::SubGroup(
|
|
"Win Condition",
|
|
{ &mOptions[RSK_TRIFORCE_HUNT], &mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL],
|
|
&mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED], &mOptions[RSK_GANONS_BOSS_KEY], &mOptions[RSK_LACS_OPTIONS],
|
|
&mOptions[RSK_LACS_MEDALLION_COUNT], &mOptions[RSK_LACS_STONE_COUNT], &mOptions[RSK_LACS_DUNGEON_COUNT],
|
|
&mOptions[RSK_LACS_REWARD_COUNT], &mOptions[RSK_LACS_TOKEN_COUNT] },
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_LOGIC_WINCON] = OptionGroup::SubGroup("",
|
|
std::initializer_list<OptionGroup*>{
|
|
&mOptionGroups[RSG_ITEM_POOL],
|
|
&mOptionGroups[RSG_MENU_SECTION_LOGIC],
|
|
&mOptionGroups[RSG_MENU_SECTION_WINCON],
|
|
},
|
|
WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_AREA_ACCESS] =
|
|
OptionGroup::SubGroup("Area Access",
|
|
{
|
|
&mOptions[RSK_FOREST],
|
|
&mOptions[RSK_KAK_GATE],
|
|
&mOptions[RSK_DOOR_OF_TIME],
|
|
&mOptions[RSK_ZORAS_FOUNTAIN],
|
|
&mOptions[RSK_SLEEPING_WATERFALL],
|
|
&mOptions[RSK_JABU_OPEN],
|
|
&mOptions[RSK_LOCK_OVERWORLD_DOORS],
|
|
&mOptions[RSK_GERUDO_FORTRESS],
|
|
&mOptions[RSK_RAINBOW_BRIDGE],
|
|
&mOptions[RSK_BRIDGE_OPTIONS],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT],
|
|
&mOptions[RSK_GANONS_TRIALS],
|
|
&mOptions[RSK_TRIAL_COUNT],
|
|
&mOptions[RSK_MEDALLION_LOCKED_TRIALS],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_AREA_ACCESS] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_AREA_ACCESS] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_ENTRANCES] = OptionGroup::SubGroup(
|
|
"Entrances",
|
|
{ &mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES], &mOptions[RSK_SHUFFLE_BOSS_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_GANONS_TOWER_ENTRANCE], &mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES], &mOptions[RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES], &mOptions[RSK_SHUFFLE_OWL_DROPS], &mOptions[RSK_SHUFFLE_WARP_SONGS],
|
|
&mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS], &mOptions[RSK_DECOUPLED_ENTRANCES],
|
|
&mOptions[RSK_MIXED_ENTRANCE_POOLS], &mOptions[RSK_MIX_DUNGEON_ENTRANCES], &mOptions[RSK_MIX_BOSS_ENTRANCES],
|
|
&mOptions[RSK_MIX_OVERWORLD_ENTRANCES], &mOptions[RSK_MIX_INTERIOR_ENTRANCES],
|
|
&mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES], &mOptions[RSK_MIX_GROTTO_ENTRANCES] },
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_ENTRANCES] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_ENTRANCES] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SIDEBAR_LOGIC_ACCESS] =
|
|
OptionGroup::SubGroup("Logic/Access",
|
|
std::initializer_list<OptionGroup*>{ &mOptionGroups[RSG_MENU_COLUMN_LOGIC_WINCON],
|
|
&mOptionGroups[RSG_MENU_COLUMN_AREA_ACCESS],
|
|
&mOptionGroups[RSG_MENU_COLUMN_ENTRANCES] },
|
|
WidgetContainerType::TABLE);
|
|
mOptionGroups[RSG_MENU_SECTION_DUNGEON_ITEMS] = OptionGroup::SubGroup("Dungeon Items",
|
|
{
|
|
&mOptions[RSK_SHUFFLE_MAPANDCOMPASS],
|
|
&mOptions[RSK_KEYSANITY],
|
|
&mOptions[RSK_BOSS_KEYSANITY],
|
|
&mOptions[RSK_SHUFFLE_DUNGEON_REWARDS],
|
|
&mOptions[RSK_GERUDO_KEYS],
|
|
&mOptions[RSK_SHUFFLE_BOSS_SOULS],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_DUNGEON_ITEMS] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_DUNGEON_ITEMS] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_MQ] = OptionGroup::SubGroup("Master Quest",
|
|
{
|
|
&mOptions[RSK_MQ_DUNGEON_RANDOM],
|
|
&mOptions[RSK_MQ_DUNGEON_COUNT],
|
|
&mOptions[RSK_MQ_DUNGEON_SET],
|
|
&mOptions[RSK_MQ_DEKU_TREE],
|
|
&mOptions[RSK_MQ_DODONGOS_CAVERN],
|
|
&mOptions[RSK_MQ_JABU_JABU],
|
|
&mOptions[RSK_MQ_FOREST_TEMPLE],
|
|
&mOptions[RSK_MQ_FIRE_TEMPLE],
|
|
&mOptions[RSK_MQ_WATER_TEMPLE],
|
|
&mOptions[RSK_MQ_SPIRIT_TEMPLE],
|
|
&mOptions[RSK_MQ_SHADOW_TEMPLE],
|
|
&mOptions[RSK_MQ_BOTTOM_OF_THE_WELL],
|
|
&mOptions[RSK_MQ_ICE_CAVERN],
|
|
&mOptions[RSK_MQ_GTG],
|
|
&mOptions[RSK_MQ_GANONS_CASTLE],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_MQ] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_MQ] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_KEYRINGS] = OptionGroup::SubGroup(
|
|
"Keyrings",
|
|
{ &mOptions[RSK_KEYRINGS], &mOptions[RSK_KEYRINGS_RANDOM_COUNT], &mOptions[RSK_KEYRINGS_FOREST_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_FIRE_TEMPLE], &mOptions[RSK_KEYRINGS_WATER_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE], &mOptions[RSK_KEYRINGS_SHADOW_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL], &mOptions[RSK_KEYRINGS_GTG],
|
|
&mOptions[RSK_KEYRINGS_GANONS_CASTLE], &mOptions[RSK_KEYRINGS_GERUDO_FORTRESS] },
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_KEYRINGS] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_KEYRINGS] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SIDEBAR_DUNGEONS] = OptionGroup::SubGroup("Dungeons",
|
|
std::initializer_list<OptionGroup*>{
|
|
&mOptionGroups[RSG_MENU_COLUMN_DUNGEON_ITEMS],
|
|
&mOptionGroups[RSG_MENU_COLUMN_KEYRINGS],
|
|
&mOptionGroups[RSG_MENU_COLUMN_MQ],
|
|
},
|
|
WidgetContainerType::TABLE);
|
|
mOptionGroups[RSG_MENU_SECTION_BASIC_SHUFFLES] =
|
|
OptionGroup::SubGroup("Shuffle Items",
|
|
{
|
|
&mOptions[RSK_SHUFFLE_SONGS],
|
|
&mOptions[RSK_SHUFFLE_TOKENS],
|
|
&mOptions[RSK_SHUFFLE_KOKIRI_SWORD],
|
|
&mOptions[RSK_SHUFFLE_MASTER_SWORD],
|
|
&mOptions[RSK_SHUFFLE_OCARINA],
|
|
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
|
|
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
|
|
&mOptions[RSK_FISHSANITY],
|
|
&mOptions[RSK_FISHSANITY_POND_COUNT],
|
|
&mOptions[RSK_FISHSANITY_AGE_SPLIT],
|
|
&mOptions[RSK_SHUFFLE_FREESTANDING],
|
|
&mOptions[RSK_SHUFFLE_WONDER_ITEMS],
|
|
&mOptions[RSK_SHUFFLE_BEEHIVES],
|
|
&mOptions[RSK_SHUFFLE_COWS],
|
|
&mOptions[RSK_SHUFFLE_POTS],
|
|
&mOptions[RSK_SHUFFLE_GRASS],
|
|
&mOptions[RSK_SHUFFLE_CRATES],
|
|
&mOptions[RSK_SHUFFLE_TREES],
|
|
&mOptions[RSK_SHUFFLE_BUSHES],
|
|
&mOptions[RSK_SHUFFLE_ICICLES],
|
|
&mOptions[RSK_SHUFFLE_RED_ICE],
|
|
&mOptions[RSK_SHUFFLE_SIGNS],
|
|
&mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES],
|
|
&mOptions[RSK_SHUFFLE_ADULT_TRADE],
|
|
&mOptions[RSK_SHUFFLE_100_GS_REWARD],
|
|
&mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_STONE_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_BEAN_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_SONG_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_BASIC_SHUFFLES] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_BASIC_SHUFFLES] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_SHOP_SHUFFLES] =
|
|
OptionGroup::SubGroup("Shuffle Shops & Merchants",
|
|
{
|
|
&mOptions[RSK_SHOPSANITY],
|
|
&mOptions[RSK_SHOPSANITY_COUNT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_RANGE_1],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_RANGE_2],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_SHUFFLE_SCRUBS],
|
|
&mOptions[RSK_SCRUBS_PRICES],
|
|
&mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE],
|
|
&mOptions[RSK_SCRUBS_PRICES_RANGE_1],
|
|
&mOptions[RSK_SCRUBS_PRICES_RANGE_2],
|
|
&mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_SHUFFLE_MERCHANTS],
|
|
&mOptions[RSK_MERCHANT_PRICES],
|
|
&mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE],
|
|
&mOptions[RSK_MERCHANT_PRICES_RANGE_1],
|
|
&mOptions[RSK_MERCHANT_PRICES_RANGE_2],
|
|
&mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_SHUFFLE_BEGGAR],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_SHOP_SHUFFLES] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_SHOP_SHUFFLES] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_ADDITIONAL_ITEMS] = OptionGroup::SubGroup("Additional Items",
|
|
{
|
|
&mOptions[RSK_SHUFFLE_CHILD_WALLET],
|
|
&mOptions[RSK_INCLUDE_TYCOON_WALLET],
|
|
&mOptions[RSK_SHUFFLE_FISHING_POLE],
|
|
&mOptions[RSK_SHUFFLE_DEKU_STICK_BAG],
|
|
&mOptions[RSK_SHUFFLE_DEKU_NUT_BAG],
|
|
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
|
|
&mOptions[RSK_SHUFFLE_SWIM],
|
|
&mOptions[RSK_SHUFFLE_GRAB],
|
|
&mOptions[RSK_SHUFFLE_CLIMB],
|
|
&mOptions[RSK_SHUFFLE_CRAWL],
|
|
&mOptions[RSK_SHUFFLE_SPEAK],
|
|
&mOptions[RSK_SHUFFLE_OPEN_CHEST],
|
|
&mOptions[RSK_SHUFFLE_BEAN_SOULS],
|
|
&mOptions[RSK_ROCS_FEATHER],
|
|
&mOptions[RSK_BOMBCHU_BAG],
|
|
&mOptions[RSK_ENABLE_BOMBCHU_DROPS],
|
|
&mOptions[RSK_INFINITE_UPGRADES],
|
|
&mOptions[RSK_SKELETON_KEY],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_ADDITIONAL_ITEMS] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_ADDITIONAL_ITEMS] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SIDEBAR_SHUFFLES] =
|
|
OptionGroup::SubGroup("Shuffles",
|
|
{
|
|
&mOptionGroups[RSG_MENU_COLUMN_BASIC_SHUFFLES],
|
|
&mOptionGroups[RSG_MENU_COLUMN_SHOP_SHUFFLES],
|
|
&mOptionGroups[RSG_MENU_COLUMN_ADDITIONAL_ITEMS],
|
|
},
|
|
WidgetContainerType::TABLE);
|
|
mOptionGroups[RSG_MENU_SECTION_HINTS] = OptionGroup::SubGroup("Hints",
|
|
{
|
|
&mOptions[RSK_GOSSIP_STONE_HINTS],
|
|
&mOptions[RSK_HINT_CLARITY],
|
|
&mOptions[RSK_HINT_DISTRIBUTION],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_SECTION_TRAPS] = OptionGroup::SubGroup("Traps",
|
|
{
|
|
&mOptions[RSK_BASE_ICE_TRAPS],
|
|
&mOptions[RSK_ADDITIONAL_ICE_TRAPS],
|
|
&mOptions[RSK_ICE_TRAP_PERCENT],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_HINTS_TRAPS] =
|
|
OptionGroup::SubGroup("",
|
|
std::initializer_list<OptionGroup*>{ &mOptionGroups[RSG_MENU_SECTION_HINTS],
|
|
&mOptionGroups[RSG_MENU_SECTION_TRAPS] },
|
|
WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_STATIC_HINTS] = OptionGroup::SubGroup(
|
|
"Static Hints", { &mOptions[RSK_TOT_ALTAR_HINT], &mOptions[RSK_GANONDORF_HINT],
|
|
&mOptions[RSK_SHEIK_LA_HINT], &mOptions[RSK_BOSS_KEY_HINT],
|
|
&mOptions[RSK_DAMPES_DIARY_HINT], &mOptions[RSK_GREG_HINT],
|
|
&mOptions[RSK_LOACH_HINT], &mOptions[RSK_SARIA_HINT],
|
|
&mOptions[RSK_MIDO_HINT], &mOptions[RSK_FROGS_HINT],
|
|
&mOptions[RSK_OOT_HINT], &mOptions[RSK_BIGGORON_HINT],
|
|
&mOptions[RSK_BIG_POES_HINT], &mOptions[RSK_CHICKENS_HINT],
|
|
&mOptions[RSK_MALON_HINT], &mOptions[RSK_HBA_HINT],
|
|
&mOptions[RSK_FISHING_POLE_HINT], &mOptions[RSK_WARP_SONG_HINTS],
|
|
&mOptions[RSK_SCRUB_TEXT_HINT], &mOptions[RSK_MERCHANT_TEXT_HINT],
|
|
&mOptions[RSK_KAK_10_SKULLS_HINT], &mOptions[RSK_KAK_20_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_30_SKULLS_HINT], &mOptions[RSK_KAK_40_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_50_SKULLS_HINT], &mOptions[RSK_KAK_100_SKULLS_HINT],
|
|
&mOptions[RSK_MASK_SHOP_HINT] },
|
|
WidgetContainerType::SECTION, "This setting adds some hints at locations other than Gossip Stones.");
|
|
mOptionGroups[RSG_MENU_COLUMN_STATIC_HINTS] =
|
|
OptionGroup::SubGroup("", { &mOptionGroups[RSG_MENU_SECTION_STATIC_HINTS] }, WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SIDEBAR_HINTS_TRAPS] =
|
|
OptionGroup::SubGroup("Hints/Traps",
|
|
std::initializer_list<OptionGroup*>{
|
|
&mOptionGroups[RSG_MENU_COLUMN_HINTS_TRAPS],
|
|
&mOptionGroups[RSG_MENU_COLUMN_STATIC_HINTS],
|
|
},
|
|
WidgetContainerType::TABLE);
|
|
mOptionGroups[RSG_MENU_SECTION_STARTING_EQUIPS] = OptionGroup::SubGroup(
|
|
"Equips",
|
|
{ &mOptions[RSK_LINKS_POCKET], &mOptions[RSK_LINKS_POCKET_REWARD], &mOptions[RSK_STARTING_KOKIRI_SWORD],
|
|
&mOptions[RSK_STARTING_MASTER_SWORD], &mOptions[RSK_STARTING_DEKU_SHIELD] },
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_SECTION_STARTING_ITEMS] = OptionGroup::SubGroup("Items",
|
|
{
|
|
&mOptions[RSK_STARTING_OCARINA],
|
|
&mOptions[RSK_STARTING_STICKS],
|
|
&mOptions[RSK_STARTING_NUTS],
|
|
&mOptions[RSK_STARTING_BEANS],
|
|
&mOptions[RSK_STARTING_SKULLTULA_TOKEN],
|
|
&mOptions[RSK_STARTING_HEARTS],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_STARTING_EQUIPMENT] =
|
|
OptionGroup::SubGroup("",
|
|
std::initializer_list<OptionGroup*>{
|
|
&mOptionGroups[RSG_MENU_SECTION_STARTING_EQUIPS],
|
|
&mOptionGroups[RSG_MENU_SECTION_STARTING_ITEMS],
|
|
},
|
|
WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SECTION_NORMAL_SONGS] = OptionGroup::SubGroup("Normal Songs",
|
|
{
|
|
&mOptions[RSK_STARTING_ZELDAS_LULLABY],
|
|
&mOptions[RSK_STARTING_EPONAS_SONG],
|
|
&mOptions[RSK_STARTING_SARIAS_SONG],
|
|
&mOptions[RSK_STARTING_SUNS_SONG],
|
|
&mOptions[RSK_STARTING_SONG_OF_TIME],
|
|
&mOptions[RSK_STARTING_SONG_OF_STORMS],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_SECTION_WARP_SONGS] = OptionGroup::SubGroup("Warp Songs",
|
|
{
|
|
&mOptions[RSK_STARTING_MINUET_OF_FOREST],
|
|
&mOptions[RSK_STARTING_BOLERO_OF_FIRE],
|
|
&mOptions[RSK_STARTING_SERENADE_OF_WATER],
|
|
&mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT],
|
|
&mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW],
|
|
&mOptions[RSK_STARTING_PRELUDE_OF_LIGHT],
|
|
},
|
|
WidgetContainerType::SECTION);
|
|
mOptionGroups[RSG_MENU_COLUMN_STARTING_SONGS] =
|
|
OptionGroup::SubGroup("",
|
|
std::initializer_list<OptionGroup*>{
|
|
&mOptionGroups[RSG_MENU_SECTION_NORMAL_SONGS],
|
|
&mOptionGroups[RSG_MENU_SECTION_WARP_SONGS],
|
|
},
|
|
WidgetContainerType::COLUMN);
|
|
mOptionGroups[RSG_MENU_SIDEBAR_STARTING_ITEMS] =
|
|
OptionGroup::SubGroup("Starting Items",
|
|
std::initializer_list<OptionGroup*>{
|
|
&mOptionGroups[RSG_MENU_COLUMN_STARTING_EQUIPMENT],
|
|
&mOptionGroups[RSG_MENU_COLUMN_STARTING_SONGS],
|
|
},
|
|
WidgetContainerType::TABLE);
|
|
mOptionGroups[RSG_OPEN] = OptionGroup("Open Settings", {
|
|
&mOptions[RSK_FOREST],
|
|
&mOptions[RSK_KAK_GATE],
|
|
&mOptions[RSK_DOOR_OF_TIME],
|
|
&mOptions[RSK_ZORAS_FOUNTAIN],
|
|
&mOptions[RSK_SLEEPING_WATERFALL],
|
|
&mOptions[RSK_JABU_OPEN],
|
|
&mOptions[RSK_LOCK_OVERWORLD_DOORS],
|
|
&mOptions[RSK_GERUDO_FORTRESS],
|
|
&mOptions[RSK_RAINBOW_BRIDGE],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_MEDALLION_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_REWARD_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_DUNGEON_COUNT],
|
|
&mOptions[RSK_RAINBOW_BRIDGE_TOKEN_COUNT],
|
|
&mOptions[RSK_BRIDGE_OPTIONS],
|
|
&mOptions[RSK_GANONS_TRIALS],
|
|
&mOptions[RSK_TRIAL_COUNT],
|
|
&mOptions[RSK_MEDALLION_LOCKED_TRIALS],
|
|
});
|
|
mOptionGroups[RSG_WORLD] = OptionGroup("World Settings", {
|
|
&mOptions[RSK_STARTING_AGE],
|
|
&mOptions[RSK_SHUFFLE_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_BOSS_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_GANONS_TOWER_ENTRANCE],
|
|
&mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES],
|
|
&mOptions[RSK_SHUFFLE_OWL_DROPS],
|
|
&mOptions[RSK_SHUFFLE_WARP_SONGS],
|
|
&mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS],
|
|
&mOptions[RSK_MIXED_ENTRANCE_POOLS],
|
|
&mOptions[RSK_MIX_DUNGEON_ENTRANCES],
|
|
&mOptions[RSK_MIX_BOSS_ENTRANCES],
|
|
&mOptions[RSK_MIX_OVERWORLD_ENTRANCES],
|
|
&mOptions[RSK_MIX_INTERIOR_ENTRANCES],
|
|
&mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES],
|
|
&mOptions[RSK_MIX_GROTTO_ENTRANCES],
|
|
&mOptions[RSK_DECOUPLED_ENTRANCES],
|
|
&mOptions[RSK_BOMBCHU_BAG],
|
|
&mOptions[RSK_ENABLE_BOMBCHU_DROPS],
|
|
&mOptions[RSK_TRIFORCE_HUNT],
|
|
&mOptions[RSK_TRIFORCE_HUNT_PIECES_TOTAL],
|
|
&mOptions[RSK_TRIFORCE_HUNT_PIECES_REQUIRED],
|
|
&mOptions[RSK_MQ_DUNGEON_RANDOM],
|
|
&mOptions[RSK_MQ_DUNGEON_COUNT],
|
|
&mOptions[RSK_MQ_DUNGEON_SET],
|
|
});
|
|
mOptionGroups[RSG_SHUFFLE_DUNGEON_QUESTS] = OptionGroup::SubGroup(
|
|
"Shuffle Dungeon Quest",
|
|
{ &mOptions[RSK_MQ_DEKU_TREE], &mOptions[RSK_MQ_DODONGOS_CAVERN], &mOptions[RSK_MQ_JABU_JABU],
|
|
&mOptions[RSK_MQ_FOREST_TEMPLE], &mOptions[RSK_MQ_FIRE_TEMPLE], &mOptions[RSK_MQ_WATER_TEMPLE],
|
|
&mOptions[RSK_MQ_SPIRIT_TEMPLE], &mOptions[RSK_MQ_SHADOW_TEMPLE], &mOptions[RSK_MQ_BOTTOM_OF_THE_WELL],
|
|
&mOptions[RSK_MQ_ICE_CAVERN], &mOptions[RSK_MQ_GTG], &mOptions[RSK_MQ_GANONS_CASTLE] });
|
|
mOptionGroups[RSG_SHUFFLE] =
|
|
OptionGroup("Shuffle Settings", {
|
|
&mOptions[RSK_SHUFFLE_DUNGEON_REWARDS],
|
|
&mOptions[RSK_LINKS_POCKET],
|
|
&mOptions[RSK_SHUFFLE_SONGS],
|
|
&mOptions[RSK_SHOPSANITY],
|
|
&mOptions[RSK_SHOPSANITY_COUNT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_FIXED_PRICE],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_RANGE_1],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_RANGE_2],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_NO_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_CHILD_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_ADULT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_GIANT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_TYCOON_WALLET_WEIGHT],
|
|
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_FISHSANITY],
|
|
&mOptions[RSK_FISHSANITY_POND_COUNT],
|
|
&mOptions[RSK_FISHSANITY_AGE_SPLIT],
|
|
&mOptions[RSK_SHUFFLE_FISHING_POLE],
|
|
&mOptions[RSK_SHUFFLE_TOKENS],
|
|
&mOptions[RSK_SHUFFLE_SCRUBS],
|
|
&mOptions[RSK_SCRUBS_PRICES],
|
|
&mOptions[RSK_SCRUBS_PRICES_FIXED_PRICE],
|
|
&mOptions[RSK_SCRUBS_PRICES_RANGE_1],
|
|
&mOptions[RSK_SCRUBS_PRICES_RANGE_2],
|
|
&mOptions[RSK_SCRUBS_PRICES_NO_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_CHILD_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_ADULT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_GIANT_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_TYCOON_WALLET_WEIGHT],
|
|
&mOptions[RSK_SCRUBS_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_SHUFFLE_BEEHIVES],
|
|
&mOptions[RSK_SHUFFLE_COWS],
|
|
&mOptions[RSK_SHUFFLE_POTS],
|
|
&mOptions[RSK_SHUFFLE_GRASS],
|
|
&mOptions[RSK_SHUFFLE_CRATES],
|
|
&mOptions[RSK_SHUFFLE_TREES],
|
|
&mOptions[RSK_SHUFFLE_BUSHES],
|
|
&mOptions[RSK_SHUFFLE_ICICLES],
|
|
&mOptions[RSK_SHUFFLE_RED_ICE],
|
|
&mOptions[RSK_SHUFFLE_SIGNS],
|
|
&mOptions[RSK_SHUFFLE_KOKIRI_SWORD],
|
|
&mOptions[RSK_SHUFFLE_OCARINA],
|
|
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
|
|
&mOptions[RSK_SHUFFLE_SWIM],
|
|
&mOptions[RSK_SHUFFLE_GRAB],
|
|
&mOptions[RSK_SHUFFLE_CLIMB],
|
|
&mOptions[RSK_SHUFFLE_CRAWL],
|
|
&mOptions[RSK_SHUFFLE_SPEAK],
|
|
&mOptions[RSK_SHUFFLE_OPEN_CHEST],
|
|
&mOptions[RSK_SHUFFLE_WEIRD_EGG],
|
|
&mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD],
|
|
&mOptions[RSK_SHUFFLE_MERCHANTS],
|
|
&mOptions[RSK_MERCHANT_PRICES],
|
|
&mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE],
|
|
&mOptions[RSK_MERCHANT_PRICES_RANGE_1],
|
|
&mOptions[RSK_MERCHANT_PRICES_RANGE_2],
|
|
&mOptions[RSK_MERCHANT_PRICES_NO_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_CHILD_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_ADULT_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_GIANT_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_TYCOON_WALLET_WEIGHT],
|
|
&mOptions[RSK_MERCHANT_PRICES_AFFORDABLE],
|
|
&mOptions[RSK_SHUFFLE_BEGGAR],
|
|
&mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES],
|
|
&mOptions[RSK_SHUFFLE_ADULT_TRADE],
|
|
&mOptions[RSK_SHUFFLE_CHEST_MINIGAME],
|
|
&mOptions[RSK_SHUFFLE_100_GS_REWARD],
|
|
&mOptions[RSK_SHUFFLE_BEAN_SOULS],
|
|
&mOptions[RSK_ROCS_FEATHER],
|
|
&mOptions[RSK_SHUFFLE_BOSS_SOULS],
|
|
&mOptions[RSK_SHUFFLE_DEKU_STICK_BAG],
|
|
&mOptions[RSK_SHUFFLE_DEKU_NUT_BAG],
|
|
&mOptions[RSK_SHUFFLE_FREESTANDING],
|
|
&mOptions[RSK_SHUFFLE_WONDER_ITEMS],
|
|
&mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_STONE_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_BEAN_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_SONG_FAIRIES],
|
|
&mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES],
|
|
});
|
|
mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] =
|
|
OptionGroup("Shuffle Dungeon Items", {
|
|
&mOptions[RSK_SHUFFLE_MAPANDCOMPASS],
|
|
&mOptions[RSK_KEYSANITY],
|
|
&mOptions[RSK_GERUDO_KEYS],
|
|
&mOptions[RSK_BOSS_KEYSANITY],
|
|
&mOptions[RSK_GANONS_BOSS_KEY],
|
|
&mOptions[RSK_LACS_STONE_COUNT],
|
|
&mOptions[RSK_LACS_MEDALLION_COUNT],
|
|
&mOptions[RSK_LACS_DUNGEON_COUNT],
|
|
&mOptions[RSK_LACS_REWARD_COUNT],
|
|
&mOptions[RSK_LACS_TOKEN_COUNT],
|
|
&mOptions[RSK_LACS_OPTIONS],
|
|
&mOptions[RSK_KEYRINGS],
|
|
&mOptions[RSK_KEYRINGS_RANDOM_COUNT],
|
|
&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS],
|
|
&mOptions[RSK_KEYRINGS_FOREST_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_FIRE_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_WATER_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_SHADOW_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL],
|
|
&mOptions[RSK_KEYRINGS_GTG],
|
|
&mOptions[RSK_KEYRINGS_GANONS_CASTLE],
|
|
});
|
|
mOptionGroups[RSG_STARTING_ITEMS] =
|
|
OptionGroup::SubGroup("Items", { &mOptions[RSK_STARTING_OCARINA], &mOptions[RSK_STARTING_KOKIRI_SWORD],
|
|
&mOptions[RSK_STARTING_DEKU_SHIELD] });
|
|
mOptionGroups[RSG_STARTING_SONGS] =
|
|
OptionGroup::SubGroup("Ocarina Songs", {
|
|
&mOptions[RSK_STARTING_ZELDAS_LULLABY],
|
|
&mOptions[RSK_STARTING_EPONAS_SONG],
|
|
&mOptions[RSK_STARTING_SARIAS_SONG],
|
|
&mOptions[RSK_STARTING_SUNS_SONG],
|
|
&mOptions[RSK_STARTING_SONG_OF_TIME],
|
|
&mOptions[RSK_STARTING_SONG_OF_STORMS],
|
|
&mOptions[RSK_STARTING_SONG_OF_TIME],
|
|
&mOptions[RSK_STARTING_MINUET_OF_FOREST],
|
|
&mOptions[RSK_STARTING_BOLERO_OF_FIRE],
|
|
&mOptions[RSK_STARTING_SERENADE_OF_WATER],
|
|
&mOptions[RSK_STARTING_REQUIEM_OF_SPIRIT],
|
|
&mOptions[RSK_STARTING_NOCTURNE_OF_SHADOW],
|
|
&mOptions[RSK_STARTING_PRELUDE_OF_LIGHT],
|
|
});
|
|
mOptionGroups[RSG_STARTING_OTHER] = OptionGroup::SubGroup("Other", {
|
|
&mOptions[RSK_STARTING_STICKS],
|
|
&mOptions[RSK_STARTING_NUTS],
|
|
&mOptions[RSK_STARTING_BEANS],
|
|
&mOptions[RSK_FULL_WALLETS],
|
|
&mOptions[RSK_STARTING_SKULLTULA_TOKEN],
|
|
&mOptions[RSK_STARTING_HEARTS],
|
|
});
|
|
mOptionGroups[RSG_STARTING_INVENTORY] = OptionGroup("Starting Inventory",
|
|
{
|
|
&mOptionGroups[RSG_STARTING_ITEMS],
|
|
&mOptionGroups[RSG_STARTING_SONGS],
|
|
&mOptionGroups[RSG_STARTING_OTHER],
|
|
},
|
|
OptionGroupType::DEFAULT);
|
|
mOptionGroups[RSG_TIMESAVERS] = OptionGroup("Timesaver Settings", {
|
|
&mOptions[RSK_SKIP_CHILD_ZELDA],
|
|
&mOptions[RSK_SKIP_EPONA_RACE],
|
|
&mOptions[RSK_SKIP_SCARECROWS_SONG],
|
|
&mOptions[RSK_SKIP_PLANTING_BEANS],
|
|
&mOptions[RSK_BIG_POE_COUNT],
|
|
});
|
|
mOptionGroups[RSG_MISC] = OptionGroup("Miscellaneous Settings",
|
|
{
|
|
&mOptions[RSK_GOSSIP_STONE_HINTS],
|
|
&mOptions[RSK_HINT_CLARITY],
|
|
&mOptions[RSK_HINT_DISTRIBUTION],
|
|
&mOptions[RSK_TOT_ALTAR_HINT],
|
|
&mOptions[RSK_GANONDORF_HINT],
|
|
&mOptions[RSK_SHEIK_LA_HINT],
|
|
&mOptions[RSK_BOSS_KEY_HINT],
|
|
&mOptions[RSK_DAMPES_DIARY_HINT],
|
|
&mOptions[RSK_GREG_HINT],
|
|
&mOptions[RSK_LOACH_HINT],
|
|
&mOptions[RSK_SARIA_HINT],
|
|
&mOptions[RSK_MIDO_HINT],
|
|
&mOptions[RSK_FROGS_HINT],
|
|
&mOptions[RSK_OOT_HINT],
|
|
&mOptions[RSK_WARP_SONG_HINTS],
|
|
&mOptions[RSK_BIGGORON_HINT],
|
|
&mOptions[RSK_BIG_POES_HINT],
|
|
&mOptions[RSK_CHICKENS_HINT],
|
|
&mOptions[RSK_MALON_HINT],
|
|
&mOptions[RSK_HBA_HINT],
|
|
&mOptions[RSK_KAK_10_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_20_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_30_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_40_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_50_SKULLS_HINT],
|
|
&mOptions[RSK_KAK_100_SKULLS_HINT],
|
|
&mOptions[RSK_MASK_SHOP_HINT],
|
|
&mOptions[RSK_SCRUB_TEXT_HINT],
|
|
&mOptions[RSK_MERCHANT_TEXT_HINT],
|
|
&mOptions[RSK_FISHING_POLE_HINT],
|
|
// TODO: Compasses show Reward/WOTH, Maps show Dungeon Mode, Starting Time
|
|
&mOptions[RSK_DAMAGE_MULTIPLIER],
|
|
&mOptions[RSK_BLUE_FIRE_ARROWS],
|
|
&mOptions[RSK_SUNLIGHT_ARROWS],
|
|
&mOptions[RSK_INFINITE_UPGRADES],
|
|
&mOptions[RSK_SKELETON_KEY],
|
|
&mOptions[RSK_SLINGBOW_BREAK_BEEHIVES],
|
|
});
|
|
mOptionGroups[RSG_ITEM_POOL] =
|
|
OptionGroup("Item Pool Settings", std::initializer_list<Option*>({ &mOptions[RSK_ITEM_POOL] }));
|
|
// TODO: Progressive Goron Sword, Remove Double Defense
|
|
mOptionGroups[RSG_EXCLUDES_KOKIRI_FOREST] =
|
|
OptionGroup::SubGroup("Kokiri Forest", mExcludeLocationsOptionsAreas[RCAREA_KOKIRI_FOREST]);
|
|
mOptionGroups[RSG_EXCLUDES_LOST_WOODS] =
|
|
OptionGroup::SubGroup("Lost Woods", mExcludeLocationsOptionsAreas[RCAREA_LOST_WOODS]);
|
|
mOptionGroups[RSG_EXCLUDES_SACRED_FOREST_MEADOW] =
|
|
OptionGroup::SubGroup("Sacred Forest Meadow", mExcludeLocationsOptionsAreas[RCAREA_SACRED_FOREST_MEADOW]);
|
|
mOptionGroups[RSG_EXCLUDES_DEKU_TREE] =
|
|
OptionGroup::SubGroup("Deku Tree", mExcludeLocationsOptionsAreas[RCAREA_DEKU_TREE]);
|
|
mOptionGroups[RSG_EXCLUDES_FOREST_TEMPLE] =
|
|
OptionGroup::SubGroup("Forest Temple", mExcludeLocationsOptionsAreas[RCAREA_FOREST_TEMPLE]);
|
|
mOptionGroups[RSG_EXCLUDES_KAKARIKO_VILLAGE] =
|
|
OptionGroup::SubGroup("Kakariko Village", mExcludeLocationsOptionsAreas[RCAREA_KAKARIKO_VILLAGE]);
|
|
mOptionGroups[RSG_EXCLUDES_GRAVEYARD] =
|
|
OptionGroup::SubGroup("Graveyard", mExcludeLocationsOptionsAreas[RCAREA_GRAVEYARD]);
|
|
mOptionGroups[RSG_EXCLUDES_BOTTOM_OF_THE_WELL] =
|
|
OptionGroup::SubGroup("Bottom of the Well", mExcludeLocationsOptionsAreas[RCAREA_BOTTOM_OF_THE_WELL]);
|
|
mOptionGroups[RSG_EXCLUDES_SHADOW_TEMPLE] =
|
|
OptionGroup::SubGroup("Shadow Temple", mExcludeLocationsOptionsAreas[RCAREA_SHADOW_TEMPLE]);
|
|
mOptionGroups[RSG_EXCLUDES_DEATH_MOUNTAIN_TRAIL] =
|
|
OptionGroup::SubGroup("Death Mountain Trail", mExcludeLocationsOptionsAreas[RCAREA_DEATH_MOUNTAIN_TRAIL]);
|
|
mOptionGroups[RSG_EXCLUDES_DEATH_MOUNTAIN_CRATER] =
|
|
OptionGroup::SubGroup("Death Mountain Crater", mExcludeLocationsOptionsAreas[RCAREA_DEATH_MOUNTAIN_CRATER]);
|
|
mOptionGroups[RSG_EXCLUDES_GORON_CITY] =
|
|
OptionGroup::SubGroup("Goron City", mExcludeLocationsOptionsAreas[RCAREA_GORON_CITY]);
|
|
mOptionGroups[RSG_EXCLUDES_DODONGOS_CAVERN] =
|
|
OptionGroup::SubGroup("Dodongo's Cavern", mExcludeLocationsOptionsAreas[RCAREA_DODONGOS_CAVERN]);
|
|
mOptionGroups[RSG_EXCLUDES_FIRE_TEMPLE] =
|
|
OptionGroup::SubGroup("Fire Temple", mExcludeLocationsOptionsAreas[RCAREA_FIRE_TEMPLE]);
|
|
mOptionGroups[RSG_EXCLUDES_ZORAS_RIVER] =
|
|
OptionGroup::SubGroup("Zora's River", mExcludeLocationsOptionsAreas[RCAREA_ZORAS_RIVER]);
|
|
mOptionGroups[RSG_EXCLUDES_ZORAS_DOMAIN] =
|
|
OptionGroup::SubGroup("Zora's Domain", mExcludeLocationsOptionsAreas[RCAREA_ZORAS_DOMAIN]);
|
|
mOptionGroups[RSG_EXCLUDES_ZORAS_FOUNTAIN] =
|
|
OptionGroup::SubGroup("Zora's Fountain", mExcludeLocationsOptionsAreas[RCAREA_ZORAS_FOUNTAIN]);
|
|
mOptionGroups[RSG_EXCLUDES_JABU_JABU] =
|
|
OptionGroup::SubGroup("Jabu Jabu's Belly", mExcludeLocationsOptionsAreas[RCAREA_JABU_JABUS_BELLY]);
|
|
mOptionGroups[RSG_EXCLUDES_ICE_CAVERN] =
|
|
OptionGroup::SubGroup("Ice Cavern", mExcludeLocationsOptionsAreas[RCAREA_ICE_CAVERN]);
|
|
mOptionGroups[RSG_EXCLUDES_HYRULE_FIELD] =
|
|
OptionGroup::SubGroup("Hyrule Field", mExcludeLocationsOptionsAreas[RCAREA_HYRULE_FIELD]);
|
|
mOptionGroups[RSG_EXCLUDES_LON_LON_RANCH] =
|
|
OptionGroup::SubGroup("Lon Lon Ranch", mExcludeLocationsOptionsAreas[RCAREA_LON_LON_RANCH]);
|
|
mOptionGroups[RSG_EXCLUDES_LAKE_HYLIA] =
|
|
OptionGroup::SubGroup("Lake Hylia", mExcludeLocationsOptionsAreas[RCAREA_LAKE_HYLIA]);
|
|
mOptionGroups[RSG_EXCLUDES_WATER_TEMPLE] =
|
|
OptionGroup::SubGroup("Water Temple", mExcludeLocationsOptionsAreas[RCAREA_WATER_TEMPLE]);
|
|
mOptionGroups[RSG_EXCLUDES_GERUDO_VALLEY] =
|
|
OptionGroup::SubGroup("Gerudo Valley", mExcludeLocationsOptionsAreas[RCAREA_GERUDO_VALLEY]);
|
|
mOptionGroups[RSG_EXCLUDES_GERUDO_FORTRESS] =
|
|
OptionGroup::SubGroup("Gerudo Fortress", mExcludeLocationsOptionsAreas[RCAREA_GERUDO_FORTRESS]);
|
|
mOptionGroups[RSG_EXCLUDES_HAUNTED_WASTELAND] =
|
|
OptionGroup::SubGroup("Haunted Wasteland", mExcludeLocationsOptionsAreas[RCAREA_WASTELAND]);
|
|
mOptionGroups[RSG_EXCLUDES_DESERT_COLOSSUS] =
|
|
OptionGroup::SubGroup("Desert Colossus", mExcludeLocationsOptionsAreas[RCAREA_DESERT_COLOSSUS]);
|
|
mOptionGroups[RSG_EXCLUDES_GERUDO_TRAINING_GROUND] =
|
|
OptionGroup::SubGroup("Gerudo Training Ground", mExcludeLocationsOptionsAreas[RCAREA_GERUDO_TRAINING_GROUND]);
|
|
mOptionGroups[RSG_EXCLUDES_SPIRIT_TEMPLE] =
|
|
OptionGroup::SubGroup("Spirit Temple", mExcludeLocationsOptionsAreas[RCAREA_SPIRIT_TEMPLE]);
|
|
mOptionGroups[RSG_EXCLUDES_HYRULE_CASTLE] =
|
|
OptionGroup::SubGroup("Hyrule Castle", mExcludeLocationsOptionsAreas[RCAREA_HYRULE_CASTLE]);
|
|
mOptionGroups[RSG_EXCLUDES_MARKET] = OptionGroup::SubGroup("Market", mExcludeLocationsOptionsAreas[RCAREA_MARKET]);
|
|
mOptionGroups[RSG_EXCLUDES_GANONS_CASTLE] =
|
|
OptionGroup::SubGroup("Ganon's Castle", mExcludeLocationsOptionsAreas[RCAREA_GANONS_CASTLE]);
|
|
mOptionGroups[RSG_EXCLUDES] =
|
|
OptionGroup::SubGroup("Exclude Locations", {
|
|
&mOptionGroups[RSG_EXCLUDES_KOKIRI_FOREST],
|
|
&mOptionGroups[RSG_EXCLUDES_LOST_WOODS],
|
|
&mOptionGroups[RSG_EXCLUDES_SACRED_FOREST_MEADOW],
|
|
&mOptionGroups[RSG_EXCLUDES_DEKU_TREE],
|
|
&mOptionGroups[RSG_EXCLUDES_FOREST_TEMPLE],
|
|
&mOptionGroups[RSG_EXCLUDES_KAKARIKO_VILLAGE],
|
|
&mOptionGroups[RSG_EXCLUDES_GRAVEYARD],
|
|
&mOptionGroups[RSG_EXCLUDES_BOTTOM_OF_THE_WELL],
|
|
&mOptionGroups[RSG_EXCLUDES_SHADOW_TEMPLE],
|
|
&mOptionGroups[RSG_EXCLUDES_DEATH_MOUNTAIN_TRAIL],
|
|
&mOptionGroups[RSG_EXCLUDES_DEATH_MOUNTAIN_CRATER],
|
|
&mOptionGroups[RSG_EXCLUDES_GORON_CITY],
|
|
&mOptionGroups[RSG_EXCLUDES_DODONGOS_CAVERN],
|
|
&mOptionGroups[RSG_EXCLUDES_FIRE_TEMPLE],
|
|
&mOptionGroups[RSG_EXCLUDES_ZORAS_RIVER],
|
|
&mOptionGroups[RSG_EXCLUDES_ZORAS_DOMAIN],
|
|
&mOptionGroups[RSG_EXCLUDES_ZORAS_FOUNTAIN],
|
|
&mOptionGroups[RSG_EXCLUDES_JABU_JABU],
|
|
&mOptionGroups[RSG_EXCLUDES_ICE_CAVERN],
|
|
&mOptionGroups[RSG_EXCLUDES_HYRULE_FIELD],
|
|
&mOptionGroups[RSG_EXCLUDES_LON_LON_RANCH],
|
|
&mOptionGroups[RSG_EXCLUDES_LAKE_HYLIA],
|
|
&mOptionGroups[RSG_EXCLUDES_WATER_TEMPLE],
|
|
&mOptionGroups[RSG_EXCLUDES_GERUDO_VALLEY],
|
|
&mOptionGroups[RSG_EXCLUDES_GERUDO_FORTRESS],
|
|
&mOptionGroups[RSG_EXCLUDES_HAUNTED_WASTELAND],
|
|
&mOptionGroups[RSG_EXCLUDES_DESERT_COLOSSUS],
|
|
&mOptionGroups[RSG_EXCLUDES_GERUDO_TRAINING_GROUND],
|
|
&mOptionGroups[RSG_EXCLUDES_SPIRIT_TEMPLE],
|
|
&mOptionGroups[RSG_EXCLUDES_HYRULE_CASTLE],
|
|
&mOptionGroups[RSG_EXCLUDES_MARKET],
|
|
&mOptionGroups[RSG_EXCLUDES_GANONS_CASTLE],
|
|
});
|
|
mOptionGroups[RSG_DETAILED_LOGIC] =
|
|
OptionGroup("Detailed Logic Settings",
|
|
{ &mOptionGroups[RSG_LOGIC], &mOptionGroups[RSG_TRICKS], &mOptionGroups[RSG_EXCLUDES] });
|
|
}
|
|
|
|
std::unordered_map<std::string, RandomizerSettingKey> Settings::PopulateOptionNameToEnum() {
|
|
std::unordered_map<std::string, RandomizerSettingKey> output = {};
|
|
for (size_t count = 0; count < RSK_MAX; count++) {
|
|
output[mOptions[count].GetName()] = static_cast<RandomizerSettingKey>(count);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
Option& Settings::GetOption(const RandomizerSettingKey key) {
|
|
return mOptions[key];
|
|
}
|
|
|
|
TrickSetting& Settings::GetTrickSetting(const RandomizerTrick key) {
|
|
return mTrickSettings[key];
|
|
}
|
|
|
|
int Settings::GetRandomizerTrickByName(const std::string& name) {
|
|
const auto& it = mTrickNameToEnum.find(name);
|
|
if (it == mTrickNameToEnum.end()) {
|
|
return -1;
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
void Context::ResetTrickOptions() {
|
|
for (int count = 0; count < RT_MAX; count++) {
|
|
mTrickOptions[count].Set(0); // RANDOTODO this can probably be done better
|
|
};
|
|
}
|
|
|
|
const std::array<Option, RSK_MAX>& Settings::GetAllOptions() const {
|
|
return mOptions;
|
|
}
|
|
|
|
std::vector<Option*>& Settings::GetExcludeOptionsForArea(const RandomizerCheckArea area) {
|
|
return mExcludeLocationsOptionsAreas[area];
|
|
}
|
|
|
|
const std::vector<std::vector<Option*>>& Settings::GetExcludeLocationsOptions() const {
|
|
return mExcludeLocationsOptionsAreas;
|
|
}
|
|
|
|
const std::array<OptionGroup, RSG_MAX>& Settings::GetOptionGroups() {
|
|
return mOptionGroups;
|
|
}
|
|
|
|
const OptionGroup& Settings::GetOptionGroup(const RandomizerSettingGroupKey key) {
|
|
return mOptionGroups[key];
|
|
}
|
|
|
|
void Settings::UpdateAllOptions() {
|
|
for (auto& option : mOptions) {
|
|
option.RunCallback();
|
|
}
|
|
}
|
|
|
|
void Context::FinalizeSettings(const std::set<RandomizerCheck>& excludedLocations,
|
|
const std::set<RandomizerTrick>& enabledTricks) {
|
|
// if we skip child zelda, we start with zelda's letter, and malon starts
|
|
// at the ranch, so we should *not* shuffle the weird egg
|
|
if (mOptions[RSK_SKIP_CHILD_ZELDA]) {
|
|
mOptions[RSK_SHUFFLE_WEIRD_EGG].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
// With certain access settings, the seed is only beatable if Starting Age is set to Child.
|
|
if (mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC) &&
|
|
((mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA]) ||
|
|
(mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) && mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS].Is(RO_GENERIC_OFF) &&
|
|
mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES].Is(RO_GENERIC_OFF) &&
|
|
mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Is(RO_GENERIC_OFF) &&
|
|
(mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES].Is(RO_GENERIC_OFF) &&
|
|
mOptions[RSK_DECOUPLED_ENTRANCES].Is(RO_GENERIC_OFF))))) {
|
|
mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD);
|
|
}
|
|
|
|
// Force 100 GS Shuffle if that's where Ganon's Boss Key is
|
|
if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
|
|
mOptions[RSK_SHUFFLE_100_GS_REWARD].Set(1);
|
|
}
|
|
|
|
// If we only have MQ, set all dungeons to MQ
|
|
if (OTRGlobals::Instance->HasMasterQuest() && !OTRGlobals::Instance->HasOriginal()) {
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Set(RO_MQ_DUNGEONS_SET_NUMBER);
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Set(MAX_MQ_DUNGEON_COUNT);
|
|
mOptions[RSK_MQ_DUNGEON_SET].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
// If we don't have MQ, set all dungeons to Vanilla
|
|
if (OTRGlobals::Instance->HasOriginal() && !OTRGlobals::Instance->HasMasterQuest()) {
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Set(RO_MQ_DUNGEONS_NONE);
|
|
}
|
|
|
|
if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_NONE)) {
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Set(0);
|
|
mOptions[RSK_MQ_DUNGEON_SET].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
// If any of the individual shuffle settings are on, turn on the main Shuffle Entrances option
|
|
if (mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES].IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) ||
|
|
mOptions[RSK_SHUFFLE_BOSS_ENTRANCES].IsNot(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) ||
|
|
mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] ||
|
|
mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].IsNot(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) ||
|
|
mOptions[RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES] || mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES] ||
|
|
mOptions[RSK_SHUFFLE_OWL_DROPS] || mOptions[RSK_SHUFFLE_WARP_SONGS] || mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS]) {
|
|
mOptions[RSK_SHUFFLE_ENTRANCES].Set(RO_GENERIC_ON);
|
|
} else {
|
|
mOptions[RSK_SHUFFLE_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (mOptions[RSK_SHUFFLE_BOSS_ENTRANCES].Is(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF)) {
|
|
mOptions[RSK_SHUFFLE_GANONS_TOWER_ENTRANCE].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
|
mOptions[RSK_LINKS_POCKET].Set(RO_LINKS_POCKET_DUNGEON_REWARD);
|
|
} else if (mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_OWN_DUNGEON) ||
|
|
mOptions[RSK_SHUFFLE_DUNGEON_REWARDS].Is(RO_DUNGEON_REWARDS_VANILLA)) {
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Set(RO_LINKS_POCKET_LIGHT_MEDALLION);
|
|
}
|
|
|
|
if (mOptions[RSK_LINKS_POCKET].IsNot(RO_LINKS_POCKET_DUNGEON_REWARD)) {
|
|
mOptions[RSK_LINKS_POCKET_REWARD].Set(RO_LINKS_POCKET_ANY_REWARD);
|
|
}
|
|
|
|
for (const auto locationKey : this->everyPossibleLocation) {
|
|
if (const auto location = this->GetItemLocation(locationKey);
|
|
excludedLocations.contains(location->GetRandomizerCheck())) {
|
|
location->SetExcludedOption(1);
|
|
} else {
|
|
location->SetExcludedOption(0);
|
|
}
|
|
}
|
|
// Tricks
|
|
ResetTrickOptions();
|
|
for (const auto randomizerTrick : enabledTricks) {
|
|
mTrickOptions[randomizerTrick].Set(1);
|
|
}
|
|
if (!mOptions[RSK_SHUFFLE_KOKIRI_SWORD]) {
|
|
if (mOptions[RSK_STARTING_KOKIRI_SWORD]) {
|
|
this->GetItemLocation(RC_KF_KOKIRI_SWORD_CHEST)->SetExcludedOption(1);
|
|
}
|
|
}
|
|
if (!mOptions[RSK_SHUFFLE_MASTER_SWORD]) {
|
|
if (mOptions[RSK_STARTING_MASTER_SWORD]) {
|
|
this->GetItemLocation(RC_TOT_MASTER_SWORD)->SetExcludedOption(1);
|
|
}
|
|
}
|
|
if (!mOptions[RSK_SHUFFLE_OCARINA]) {
|
|
if (mOptions[RSK_STARTING_OCARINA].IsNot(RO_STARTING_OCARINA_OFF)) {
|
|
this->GetItemLocation(RC_LW_GIFT_FROM_SARIA)->SetExcludedOption(1);
|
|
if (mOptions[RSK_STARTING_OCARINA].Is(RO_STARTING_OCARINA_TIME)) {
|
|
this->GetItemLocation(RC_HF_OCARINA_OF_TIME_ITEM)->SetExcludedOption(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mOptions[RSK_SHUFFLE_DEKU_STICK_BAG]) {
|
|
mOptions[RSK_STARTING_STICKS].Set(false);
|
|
}
|
|
if (mOptions[RSK_SHUFFLE_DEKU_NUT_BAG]) {
|
|
mOptions[RSK_STARTING_NUTS].Set(false);
|
|
}
|
|
|
|
// RANDOTODO implement chest shuffle with keysanity
|
|
// ShuffleChestMinigame.Set(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]);
|
|
mOptions[RSK_SHUFFLE_CHEST_MINIGAME].Set(RO_CHEST_GAME_OFF);
|
|
|
|
// TODO: RandomizeAllSettings(true) when implementing the ability to randomize the options themselves.
|
|
std::array<DungeonInfo*, 12> dungeons = this->GetDungeons()->GetDungeonList();
|
|
|
|
// reset the MQ vars
|
|
for (auto dungeon : dungeons) {
|
|
dungeon->ClearMQ();
|
|
dungeon->SetDungeonKnown(true);
|
|
}
|
|
// if it's selection mode, process the selection directly
|
|
if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_SELECTION)) {
|
|
mOptions[RSK_MQ_DUNGEON_SET].Set(RO_GENERIC_ON);
|
|
// How many dungeons are set to MQ in selection
|
|
uint8_t mqSet = 0;
|
|
for (auto dungeon : dungeons) {
|
|
switch (mOptions[dungeon->GetMQSetting()].Get()) {
|
|
case RO_MQ_SET_MQ:
|
|
dungeon->SetMQ();
|
|
mqSet += 1;
|
|
break;
|
|
case RO_MQ_SET_RANDOM:
|
|
// 50% per dungeon, rolled separatly so people can either have a linear distribtuion
|
|
// or a bell curve for the number of MQ dungeons per seed.
|
|
if (Random(0, 2)) {
|
|
dungeon->SetMQ();
|
|
mqSet += 1;
|
|
}
|
|
dungeon->SetDungeonKnown(false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// override the dungeons set with the ones set by selection, so it's accurate for anything that wants to know MQ
|
|
// dungeon count
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Set(mqSet);
|
|
// handling set number and random number together
|
|
} else if (mOptions[RSK_MQ_DUNGEON_RANDOM].IsNot(RO_MQ_DUNGEONS_NONE)) {
|
|
// so we don't have to call this repeatedly
|
|
uint8_t mqCount = mOptions[RSK_MQ_DUNGEON_COUNT].Get();
|
|
// How many dungeons are set to MQ in selection
|
|
uint8_t mqSet = 0;
|
|
// the number of random
|
|
uint8_t mqToSet = 0;
|
|
// store the dungeons to randomly decide between. we use the id instead of a dungeon object to avoid a lot of
|
|
// casting.
|
|
std::vector<uint8_t> randMQOption = {};
|
|
// if dungeons have been preset, process them
|
|
if (mOptions[RSK_MQ_DUNGEON_SET]) {
|
|
for (size_t i = 0; i < dungeons.size(); i++) {
|
|
switch (mOptions[dungeons[i]->GetMQSetting()].Get()) {
|
|
case RO_MQ_SET_MQ:
|
|
dungeons[i]->SetMQ();
|
|
mqSet += 1;
|
|
break;
|
|
case RO_MQ_SET_RANDOM:
|
|
randMQOption.push_back(static_cast<uint8_t>(i));
|
|
dungeons[i]->SetDungeonKnown(false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// otherwise, every dungeon is possible
|
|
} else {
|
|
// if count is MAX_MQ_DUNGEON_COUNT, we know everything is MQ, so can skip some setps and not set Known
|
|
if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_SET_NUMBER) && mqCount == MAX_MQ_DUNGEON_COUNT) {
|
|
randMQOption.resize(MAX_MQ_DUNGEON_COUNT);
|
|
for (int i = 0; i < MAX_MQ_DUNGEON_COUNT; i++) {
|
|
randMQOption[i] = i;
|
|
}
|
|
for (auto dungeon : dungeons) {
|
|
mOptions[dungeon->GetMQSetting()].Set(RO_MQ_SET_MQ);
|
|
}
|
|
// if it's fixed to zero, set it to None instead. the rest is processed after
|
|
} else if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_SET_NUMBER) && mqCount == 0) {
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Set(RO_MQ_DUNGEONS_NONE);
|
|
// otherwise, make everything a possibility and unknown
|
|
} else {
|
|
for (size_t i = 0; i < dungeons.size(); i++) {
|
|
randMQOption.push_back(static_cast<uint8_t>(i));
|
|
dungeons[i]->SetDungeonKnown(false);
|
|
mOptions[dungeons[i]->GetMQSetting()].Set(RO_MQ_SET_RANDOM);
|
|
}
|
|
}
|
|
}
|
|
// if there's no random options, we can skip this
|
|
if (randMQOption.size() > 0) {
|
|
// Figure out how many dungeons to select, rolling the random number if needed
|
|
if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_RANDOM_NUMBER)) {
|
|
mqToSet = Random(0, static_cast<int>(randMQOption.size()) + 1);
|
|
} else if (mqCount > mqSet) {
|
|
mqToSet = std::min(mqCount - mqSet, static_cast<int>(randMQOption.size()));
|
|
}
|
|
// we only need to shuffle if we're not using them all
|
|
if (mqToSet <= static_cast<int8_t>(randMQOption.size()) && mqToSet > 0) {
|
|
Shuffle(randMQOption);
|
|
}
|
|
for (uint8_t i = 0; i < mqToSet; i++) {
|
|
dungeons[randMQOption[i]]->SetMQ();
|
|
}
|
|
} else {
|
|
// if there's no random options, check if we can collapse the setting into None or Selection
|
|
if (mqSet == 0) {
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Set(RO_MQ_DUNGEONS_NONE);
|
|
} else {
|
|
mOptions[RSK_MQ_DUNGEON_RANDOM].Set(RO_MQ_DUNGEONS_SELECTION);
|
|
}
|
|
}
|
|
// reset the value set based on what was actually set
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Set(mqToSet + mqSet);
|
|
}
|
|
// Not an if else as other settings can become None in processing
|
|
if (mOptions[RSK_MQ_DUNGEON_RANDOM].Is(RO_MQ_DUNGEONS_NONE)) {
|
|
mOptions[RSK_MQ_DUNGEON_SET].Set(RO_GENERIC_OFF);
|
|
mOptions[RSK_MQ_DUNGEON_COUNT].Set(0);
|
|
for (auto dungeon : dungeons) {
|
|
mOptions[dungeon->GetMQSetting()].Set(RO_MQ_SET_VANILLA);
|
|
}
|
|
}
|
|
|
|
// Set key ring for each dungeon
|
|
for (const auto dungeon : dungeons) {
|
|
dungeon->ClearKeyRing();
|
|
}
|
|
|
|
const std::vector<OptionValue*> keyRingOptions = {
|
|
&mOptions[RSK_KEYRINGS_FOREST_TEMPLE], &mOptions[RSK_KEYRINGS_FIRE_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_WATER_TEMPLE], &mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE],
|
|
&mOptions[RSK_KEYRINGS_SHADOW_TEMPLE], &mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL],
|
|
&mOptions[RSK_KEYRINGS_GTG], &mOptions[RSK_KEYRINGS_GANONS_CASTLE],
|
|
};
|
|
|
|
if (mOptions[RSK_KEYRINGS]) {
|
|
// Random Key Rings
|
|
auto keyrings = keyRingOptions;
|
|
if (mOptions[RSK_GERUDO_FORTRESS].Is(RO_GF_CARPENTERS_NORMAL) &&
|
|
mOptions[RSK_GERUDO_KEYS].IsNot(RO_GERUDO_KEYS_VANILLA)) {
|
|
keyrings.push_back(&mOptions[RSK_KEYRINGS_GERUDO_FORTRESS]);
|
|
} else {
|
|
mOptions[RSK_KEYRINGS_GERUDO_FORTRESS].Set(RO_KEYRING_FOR_DUNGEON_OFF);
|
|
}
|
|
if (mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_RANDOM) || mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT)) {
|
|
const uint32_t keyRingCount = mOptions[RSK_KEYRINGS].Is(RO_KEYRINGS_COUNT)
|
|
? mOptions[RSK_KEYRINGS_RANDOM_COUNT].Get()
|
|
: Random(0, static_cast<int>(keyrings.size()));
|
|
Shuffle(keyrings);
|
|
for (size_t i = 0; i < keyRingCount; i++) {
|
|
keyrings[i]->Set(RO_KEYRING_FOR_DUNGEON_ON);
|
|
}
|
|
for (size_t i = keyRingCount; i < keyrings.size(); i++) {
|
|
keyrings[i]->Set(RO_KEYRING_FOR_DUNGEON_OFF);
|
|
}
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_BOTTOM_OF_THE_WELL].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(BOTTOM_OF_THE_WELL)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_FOREST_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(FOREST_TEMPLE)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_FIRE_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(FIRE_TEMPLE)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_WATER_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_WATER_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(WATER_TEMPLE)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_SPIRIT_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(SPIRIT_TEMPLE)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_SHADOW_TEMPLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(SHADOW_TEMPLE)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_GTG].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_GTG].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(GERUDO_TRAINING_GROUND)->SetKeyRing();
|
|
}
|
|
if (mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_ON) ||
|
|
(mOptions[RSK_KEYRINGS_GANONS_CASTLE].Is(RO_KEYRING_FOR_DUNGEON_RANDOM) && Random(0, 2) == 1)) {
|
|
this->GetDungeon(GANONS_CASTLE)->SetKeyRing();
|
|
}
|
|
}
|
|
|
|
auto trials = this->GetTrials()->GetTrialList();
|
|
Shuffle(trials);
|
|
for (const auto trial : trials) {
|
|
trial->SetAsSkipped();
|
|
}
|
|
if (mOptions[RSK_GANONS_TRIALS].Is(RO_GANONS_TRIALS_SKIP)) {
|
|
mOptions[RSK_TRIAL_COUNT].Set(0);
|
|
} else if (mOptions[RSK_GANONS_TRIALS].Is(RO_GANONS_TRIALS_RANDOM_NUMBER)) {
|
|
mOptions[RSK_TRIAL_COUNT].Set(
|
|
Random(0, static_cast<int>(Rando::Settings::GetInstance()->GetOption(RSK_TRIAL_COUNT).GetOptionCount())));
|
|
}
|
|
for (uint8_t i = 0; i < mOptions[RSK_TRIAL_COUNT].Get(); i++) {
|
|
trials[i]->SetAsRequired();
|
|
}
|
|
|
|
bool dungeonShuffle = !mOptions[RSK_SHUFFLE_DUNGEON_ENTRANCES].Is(RO_GENERIC_OFF);
|
|
bool bossShuffle = !mOptions[RSK_SHUFFLE_BOSS_ENTRANCES].Is(RO_GENERIC_OFF);
|
|
bool overworldShuffle = !mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES].Is(RO_GENERIC_OFF);
|
|
bool interiorShuffle = !mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
|
|
bool gerudoFortressShuffle = !mOptions[RSK_SHUFFLE_THIEVES_HIDEOUT_ENTRANCES].Is(RO_GENERIC_OFF);
|
|
bool grottoShuffle = !mOptions[RSK_SHUFFLE_GROTTO_ENTRANCES].Is(RO_GENERIC_OFF);
|
|
|
|
if (dungeonShuffle + bossShuffle + overworldShuffle + interiorShuffle + grottoShuffle <= 1) {
|
|
mOptions[RSK_MIXED_ENTRANCE_POOLS].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_MIXED_ENTRANCE_POOLS] || !dungeonShuffle) {
|
|
mOptions[RSK_MIX_DUNGEON_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_MIXED_ENTRANCE_POOLS] || !bossShuffle) {
|
|
mOptions[RSK_MIX_BOSS_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_MIXED_ENTRANCE_POOLS] || !overworldShuffle) {
|
|
mOptions[RSK_MIX_OVERWORLD_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_MIXED_ENTRANCE_POOLS] || !interiorShuffle) {
|
|
mOptions[RSK_MIX_INTERIOR_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_MIXED_ENTRANCE_POOLS] || !gerudoFortressShuffle) {
|
|
mOptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_MIXED_ENTRANCE_POOLS] || !grottoShuffle) {
|
|
mOptions[RSK_MIX_GROTTO_ENTRANCES].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (mOptions[RSK_STARTING_AGE].Is(RO_AGE_RANDOM)) {
|
|
if (const uint32_t choice = Random(0, 2); choice == 0) {
|
|
mOptions[RSK_SELECTED_STARTING_AGE].Set(RO_AGE_CHILD);
|
|
} else {
|
|
mOptions[RSK_SELECTED_STARTING_AGE].Set(RO_AGE_ADULT);
|
|
}
|
|
} else {
|
|
mOptions[RSK_SELECTED_STARTING_AGE].Set(mOptions[RSK_STARTING_AGE].Get());
|
|
}
|
|
|
|
// TODO: Random Starting Time
|
|
|
|
if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
|
mLACSCondition = RO_LACS_STONES;
|
|
} else if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
|
|
mLACSCondition = RO_LACS_MEDALLIONS;
|
|
} else if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
|
|
mLACSCondition = RO_LACS_REWARDS;
|
|
} else if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
|
|
mLACSCondition = RO_LACS_DUNGEONS;
|
|
} else if (mOptions[RSK_GANONS_BOSS_KEY].Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
|
|
mLACSCondition = RO_LACS_TOKENS;
|
|
} else {
|
|
mLACSCondition = RO_LACS_VANILLA;
|
|
}
|
|
|
|
if (!mOptions[RSK_SHUFFLE_WARP_SONGS]) {
|
|
mOptions[RSK_WARP_SONG_HINTS].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_SHUFFLE_COWS]) {
|
|
mOptions[RSK_MALON_HINT].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_SHUFFLE_100_GS_REWARD]) {
|
|
mOptions[RSK_KAK_100_SKULLS_HINT].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (!mOptions[RSK_SHUFFLE_FISHING_POLE]) {
|
|
mOptions[RSK_FISHING_POLE_HINT].Set(RO_GENERIC_OFF);
|
|
}
|
|
|
|
if (mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_HYRULE_LOACH)) {
|
|
mOptions[RSK_LOACH_HINT].Set(RO_GENERIC_OFF);
|
|
}
|
|
}
|
|
|
|
void Settings::ParseJson(nlohmann::json spoilerFileJson) {
|
|
mContext->SetSeedString(spoilerFileJson["seed"].get<std::string>());
|
|
mContext->SetSeed(spoilerFileJson["finalSeed"].get<uint32_t>());
|
|
nlohmann::json settingsJson = spoilerFileJson["settings"];
|
|
for (auto it = settingsJson.begin(); it != settingsJson.end(); ++it) {
|
|
// todo load into cvars for UI
|
|
// RANDOTODO handle numeric value to options conversion better than brute force
|
|
if (StaticData::optionNameToEnum.contains(it.key())) {
|
|
const RandomizerSettingKey index = StaticData::optionNameToEnum[it.key()];
|
|
mContext->GetOption(index).Set(mOptions[index].GetValueFromText(it.value()));
|
|
}
|
|
}
|
|
|
|
nlohmann::json jsonExcludedLocations = spoilerFileJson["excludedLocations"];
|
|
const auto ctx = Context::GetInstance();
|
|
|
|
for (auto it = jsonExcludedLocations.begin(); it != jsonExcludedLocations.end(); ++it) {
|
|
const RandomizerCheck rc = Rando::StaticData::locationNameToEnum[it.value()];
|
|
ctx->GetItemLocation(rc)->SetExcludedOption(RO_GENERIC_ON);
|
|
}
|
|
|
|
nlohmann::json enabledTricksJson = spoilerFileJson["enabledTricks"];
|
|
for (auto it = enabledTricksJson.begin(); it != enabledTricksJson.end(); ++it) {
|
|
const RandomizerTrick rt = mTrickNameToEnum[it.value()];
|
|
GetTrickSetting(rt).SetContextIndex(RO_GENERIC_ON);
|
|
}
|
|
}
|
|
|
|
void Settings::AssignContext(std::shared_ptr<Context> ctx) {
|
|
mContext = ctx;
|
|
}
|
|
|
|
void Settings::ClearContext() {
|
|
mContext = nullptr;
|
|
}
|
|
|
|
void Settings::SetAllToContext() {
|
|
for (int i = 0; i < RSK_MAX; i++) {
|
|
mContext->GetOption(static_cast<RandomizerSettingKey>(i)).Set(mOptions[i].GetOptionIndex());
|
|
}
|
|
for (int i = 0; i < RT_MAX; i++) {
|
|
mContext->GetTrickOption(static_cast<RandomizerTrick>(i)).Set(mTrickSettings[i].GetOptionIndex());
|
|
}
|
|
for (int i = 0; i < RC_MAX; i++) {
|
|
mContext->GetItemLocation(i)->SetExcludedOption(
|
|
StaticData::GetLocation(static_cast<RandomizerCheck>(i))->GetExcludedOption()->GetOptionIndex());
|
|
}
|
|
}
|
|
|
|
void Settings::RandomizeAllSettings() {
|
|
// Randomize all settings except tricks
|
|
for (int i = 0; i < RSK_MAX; i++) {
|
|
switch (static_cast<RandomizerSettingKey>(i)) {
|
|
case RSK_STARTING_SKULLTULA_TOKEN:
|
|
case RSK_STARTING_HEARTS:
|
|
case RSK_STARTING_ZELDAS_LULLABY:
|
|
case RSK_STARTING_EPONAS_SONG:
|
|
case RSK_STARTING_SARIAS_SONG:
|
|
case RSK_STARTING_SUNS_SONG:
|
|
case RSK_STARTING_SONG_OF_TIME:
|
|
case RSK_STARTING_SONG_OF_STORMS:
|
|
case RSK_STARTING_MINUET_OF_FOREST:
|
|
case RSK_STARTING_BOLERO_OF_FIRE:
|
|
case RSK_STARTING_SERENADE_OF_WATER:
|
|
case RSK_STARTING_REQUIEM_OF_SPIRIT:
|
|
case RSK_STARTING_NOCTURNE_OF_SHADOW:
|
|
case RSK_STARTING_PRELUDE_OF_LIGHT:
|
|
continue;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
auto key = static_cast<RandomizerSettingKey>(i);
|
|
Option& option = mOptions[key];
|
|
|
|
if (option.GetOptionCount() == 0) {
|
|
continue;
|
|
}
|
|
|
|
uint8_t randomIndex = Random(0, static_cast<uint32_t>(option.GetOptionCount()));
|
|
|
|
option.SetContextIndex(randomIndex);
|
|
if (!option.GetCVarName().empty()) {
|
|
CVarSetInteger(option.GetCVarName().c_str(), randomIndex);
|
|
}
|
|
option.RunCallback();
|
|
}
|
|
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
|
|
std::shared_ptr<Settings> Settings::GetInstance() {
|
|
if (mInstance == nullptr) {
|
|
mInstance = std::make_shared<Settings>();
|
|
}
|
|
return mInstance;
|
|
}
|
|
} // namespace Rando
|