#pragma once #include #include #include #include #include #include #include #include #include "category.hpp" #include "cosmetics.hpp" #include "debug.hpp" #include "menu.hpp" #include "pool_functions.hpp" typedef enum { OFF, ON, } BooleanSetting; typedef enum { DONT_SKIP, SKIP, } SkipSetting; typedef enum { LOGIC_GLITCHLESS, LOGIC_GLITCHED, LOGIC_NONE, LOGIC_VANILLA, } LogicSetting; typedef enum { OPENFOREST_CLOSED, OPENFOREST_CLOSED_DEKU, OPENFOREST_OPEN, } OpenForestSetting; typedef enum { OPENKAKARIKO_CLOSED, OPENKAKARIKO_OPEN, } OpenKakarikoSetting; typedef enum { OPENDOOROFTIME_CLOSED, OPENDOOROFTIME_SONGONLY, OPENDOOROFTIME_OPEN, } OpenDoorOfTimeSetting; typedef enum { ZORASFOUNTAIN_NORMAL, ZORASFOUNTAIN_ADULT, ZORASFOUNTAIN_OPEN, } ZorasFountainSetting; typedef enum { GERUDOFORTRESS_NORMAL, GERUDOFORTRESS_FAST, GERUDOFORTRESS_OPEN, } GerudoFortressSetting; typedef enum { RAINBOWBRIDGE_VANILLA, RAINBOWBRIDGE_OPEN, RAINBOWBRIDGE_STONES, RAINBOWBRIDGE_MEDALLIONS, RAINBOWBRIDGE_REWARDS, RAINBOWBRIDGE_DUNGEONS, RAINBOWBRIDGE_TOKENS, } RainbowBridgeSetting; typedef enum { LACSCONDITION_VANILLA, LACSCONDITION_STONES, LACSCONDITION_MEDALLIONS, LACSCONDITION_REWARDS, LACSCONDITION_DUNGEONS, LACSCONDITION_TOKENS, } LACSConditionSetting; typedef enum { AGE_CHILD, AGE_ADULT, AGE_RANDOM, } AgeSetting; typedef enum { SHUFFLEDUNGEONS_OFF, SHUFFLEDUNGEONS_ON, SHUFFLEDUNGEONS_GANON, } ShuffleDungeonEntrancesSetting; typedef enum { SHUFFLEINTERIORS_OFF, SHUFFLEINTERIORS_SIMPLE, SHUFFLEINTERIORS_ALL, } ShuffleInteriorEntrancesSetting; typedef enum { AMMODROPS_VANILLA, AMMODROPS_BOMBCHU, AMMODROPS_NONE, } AmmoDropsSetting; typedef enum { HEARTDROPREFILL_VANILLA, HEARTDROPREFILL_NODROP, HEARTDROPREFILL_NOREFILL, HEARTDROPREFILL_NODROPREFILL, } HeartDropRefillSetting; typedef enum { DUNGEONMODE_VANILLA, DUNGEONMODE_MQ, } DungeonMode; typedef enum { REWARDSHUFFLE_END_OF_DUNGEON, REWARDSHUFFLE_ANY_DUNGEON, REWARDSHUFFLE_OVERWORLD, REWARDSHUFFLE_ANYWHERE, } RewardShuffleSetting; typedef enum { LINKSPOCKETITEM_DUNGEON_REWARD, LINKSPOCKETITEM_ADVANCEMENT, LINKSPOCKETITEM_ANYTHING, LINKSPOCKETITEM_NOTHING, } LinksPocketSetting; typedef enum { SONGSHUFFLE_SONG_LOCATIONS, SONGSHUFFLE_DUNGEON_REWARDS, SONGSHUFFLE_ANYWHERE, } SongShuffleSetting; typedef enum { SHOPSANITY_OFF, SHOPSANITY_ZERO, SHOPSANITY_ONE, SHOPSANITY_TWO, SHOPSANITY_THREE, SHOPSANITY_FOUR, SHOPSANITY_RANDOM, } ShopsanitySetting; typedef enum { TOKENSANITY_OFF, TOKENSANITY_DUNGEONS, TOKENSANITY_OVERWORLD, TOKENSANITY_ALL_TOKENS, } TokensanitySetting; typedef enum { SCRUBSANITY_OFF, SCRUBSANITY_AFFORDABLE, SCRUBSANITY_EXPENSIVE, SCRUBSANITY_RANDOM_PRICES, } ScrubsanitySetting; typedef enum { SHUFFLEMERCHANTS_OFF, SHUFFLEMERCHANTS_NO_HINTS, SHUFFLEMERCHANTS_HINTS, } ShuffleMerchantsSetting; typedef enum { SHUFFLEADULTTRADEQUEST_OFF, SHUFFLEADULTTRADEQUEST_ON, } ShuffleAdultTradeQuestSetting; typedef enum { SHUFFLECHESTMINIGAME_OFF, SHUFFLECHESTMINIGAME_SINGLE_KEYS, SHUFFLECHESTMINIGAME_PACK, } ShuffleChestMinigameSetting; typedef enum { MAPSANDCOMPASSES_START_WITH, MAPSANDCOMPASSES_VANILLA, MAPSANDCOMPASSES_OWN_DUNGEON, MAPSANDCOMPASSES_ANY_DUNGEON, MAPSANDCOMPASSES_OVERWORLD, MAPSANDCOMPASSES_ANYWHERE, } MapsAndCompassesSetting; typedef enum { KEYSANITY_START_WITH, KEYSANITY_VANILLA, KEYSANITY_OWN_DUNGEON, KEYSANITY_ANY_DUNGEON, KEYSANITY_OVERWORLD, KEYSANITY_ANYWHERE, } KeysanitySetting; typedef enum { GERUDOKEYS_VANILLA, GERUDOKEYS_ANY_DUNGEON, GERUDOKEYS_OVERWORLD, GERUDOKEYS_ANYWHERE, } GerudoKeysSetting; typedef enum { KEYRINGS_OFF, KEYRINGS_RANDOM, KEYRINGS_RANDOM_COUNT, KEYRINGS_SELECTION, } KeyRingsSetting; typedef enum { BOSSKEYSANITY_START_WITH, BOSSKEYSANITY_VANILLA, BOSSKEYSANITY_OWN_DUNGEON, BOSSKEYSANITY_ANY_DUNGEON, BOSSKEYSANITY_OVERWORLD, BOSSKEYSANITY_ANYWHERE, } BossKeysanitySetting; typedef enum { GANONSBOSSKEY_VANILLA, GANONSBOSSKEY_OWN_DUNGEON, GANONSBOSSKEY_START_WITH, GANONSBOSSKEY_ANY_DUNGEON, GANONSBOSSKEY_OVERWORLD, GANONSBOSSKEY_ANYWHERE, GANONSBOSSKEY_LACS_VANILLA, GANONSBOSSKEY_LACS_MEDALLIONS, GANONSBOSSKEY_LACS_STONES, GANONSBOSSKEY_LACS_REWARDS, GANONSBOSSKEY_LACS_DUNGEONS, GANONSBOSSKEY_LACS_TOKENS, } GanonsBossKeySetting; typedef enum { QUICKTEXT_VANILLA, QUICKTEXT_SKIPPABLE, QUICKTEXT_INSTANT, QUICKTEXT_TURBO, } QuickTextSetting; typedef enum { SONGREPLAYS_DONT_SKIP, SONGREPLAYS_SKIP_NO_SFX, SONGREPLAYS_SKIP_KEEP_SFX, } SkipSongReplaysSetting; typedef enum { INCLUDE, EXCLUDE, } ExcludeLocationSetting; typedef enum { STARTINGINVENTORY_NONE, } StartingInventorySetting; typedef enum { TRICK_DISABLED, TRICK_ENABLED, } LogicTrickSetting; typedef enum { HINTMODE_OBSCURE, HINTMODE_AMBIGUOUS, HINTMODE_CLEAR, } HintModeSetting; typedef enum { DAMAGEMULTIPLIER_HALF, DAMAGEMULTIPLIER_DEFAULT, DAMAGEMULTIPLIER_DOUBLE, DAMAGEMULTIPLIER_QUADRUPLE, DAMAGEMULTIPLIER_OCTUPLE, DAMAGEMULTIPLIER_SEXDECUPLE, DAMAGEMULTIPLIER_OHKO, } DamageMultiplierSetting; typedef enum { STARTINGTIME_DAY, STARTINGTIME_NIGHT, } StartingTimeSetting; typedef enum { HINTS_NO_HINTS, HINTS_NEED_NOTHING, HINTS_MASK_OF_TRUTH, HINTS_STONE_OF_AGONY, } GossipStoneHintsSetting; typedef enum { ITEMPOOL_PLENTIFUL, ITEMPOOL_BALANCED, ITEMPOOL_SCARCE, ITEMPOOL_MINIMAL, } ItemPoolSetting; typedef enum { ICETRAPS_OFF, ICETRAPS_NORMAL, ICETRAPS_EXTRA, ICETRAPS_MAYHEM, ICETRAPS_ONSLAUGHT, } IceTrapSetting; typedef enum { GKDURABILITY_VANILLA, GKDURABILITY_RANDOMRISK, GKDURABILITY_RANDOMSAFE, } GkDurabilitySetting; typedef enum { STARTINGBOTTLE_NONE, STARTINGBOTTLE_EMPTY_BOTTLE, STARTINGBOTTLE_RED_POTION, STARTINGBOTTLE_GREEN_POTION, STARTINGBOTTLE_BLUE_POTION, STARTINGBOTTLE_FAIRY, STARTINGBOTTLE_FISH, STARTINGBOTTLE_MILK, STARTINGBOTTLE_BLUE_FIRE, STARTINGBOTTLE_BUGS, STARTINGBOTTLE_BIG_POE, STARTINGBOTTLE_HALF_MILK, STARTINGBOTTLE_POE, } StartingBottleSetting; typedef enum { STARTINGBGS_NONE, STARTINGBGS_GIANTS_KNIFE, STARTINGBGS_BIGGORON_SWORD, } StartingBiggoronSwordSetting; typedef enum { SHUFFLESFX_OFF, SHUFFLESFX_ALL, SHUFFLESFX_SCENESPECIFIC, SHUFFLESFX_CHAOS, } ShuffleSFXSetting; typedef enum { DUNGEON_NEITHER, DUNGEON_BARREN, DUNGEON_WOTH, } DungeonInfo; typedef enum { TRAILCOLOR_VANILLAMODE, TRAILCOLOR_FORCEDSIMPLEMODE, TRAILCOLOR_RAINBOW, TRAILCOLOR_RAINBOW_SIMPLEMODE, } TrailColorMode; typedef enum { TRAILDURATION_DISABLED, TRAILDURATION_VERYSHORT, TRAILDURATION_VANILLA, TRAILDURATION_LONG, TRAILDURATION_VERYLONG, TRAILDURATION_LIGHTSABER, } TrailDuration; typedef enum { PLAY_ON_CONSOLE, PLAY_ON_CITRA, } PlayOption; typedef struct { uint8_t hashIndexes[5]; uint8_t playOption; uint8_t logic; uint8_t openForest; uint8_t openKakariko; uint8_t openDoorOfTime; uint8_t zorasFountain; uint8_t gerudoFortress; uint8_t rainbowBridge; uint8_t bridgeStoneCount; uint8_t bridgeMedallionCount; uint8_t bridgeRewardCount; uint8_t bridgeDungeonCount; uint8_t bridgeTokenCount; uint8_t randomGanonsTrials; uint8_t ganonsTrialsCount; uint8_t startingAge; uint8_t resolvedStartingAge; uint8_t shuffleDungeonEntrances; uint8_t shuffleOverworldEntrances; uint8_t shuffleInteriorEntrances; uint8_t shuffleGrottoEntrances; uint8_t shuffleOwlDrops; uint8_t shuffleWarpSongs; uint8_t shuffleOverworldSpawns; uint8_t mixedEntrancePools; uint8_t mixDungeons; uint8_t mixOverworld; uint8_t mixInteriors; uint8_t mixGrottos; uint8_t decoupleEntrances; uint8_t bombchusInLogic; uint8_t ammoDrops; uint8_t heartDropRefill; uint8_t randomMQDungeons; uint8_t mqDungeonCount; uint8_t dungeonModesKnown[12]; // 12 dungeons which can be set Vanilla or MQ uint8_t shuffleRewards; uint8_t linksPocketItem; uint8_t shuffleSongs; uint8_t tokensanity; uint8_t scrubsanity; uint8_t shopsanity; uint8_t shuffleCows; uint8_t shuffleKokiriSword; uint8_t shuffleOcarinas; uint8_t shuffleWeirdEgg; uint8_t shuffleGerudoToken; uint8_t shuffleMagicBeans; uint8_t shuffleMerchants; uint8_t shuffleFrogSongRupees; uint8_t shuffleAdultTradeQuest; uint8_t shuffleChestMinigame; uint8_t mapsAndCompasses; uint8_t keysanity; uint8_t gerudoKeys; uint8_t bossKeysanity; uint8_t ganonsBossKey; uint8_t lacsCondition; uint8_t lacsMedallionCount; uint8_t lacsStoneCount; uint8_t lacsRewardCount; uint8_t lacsDungeonCount; uint8_t lacsTokenCount; uint8_t ringFortress; uint8_t ringForest; uint8_t ringFire; uint8_t ringWater; uint8_t ringSpirit; uint8_t ringShadow; uint8_t ringWell; uint8_t ringGtg; uint8_t ringCastle; uint8_t skipChildStealth; uint8_t skipTowerEscape; uint8_t skipEponaRace; uint8_t skipMinigamePhases; uint8_t freeScarecrow; uint8_t fourPoesCutscene; uint8_t lakeHyliaOwl; uint8_t bigPoeTargetCount; uint8_t numRequiredCuccos; uint8_t kingZoraSpeed; uint8_t completeMaskQuest; uint8_t enableGlitchCutscenes; uint8_t quickText; uint8_t skipSongReplays; uint8_t keepFWWarpPoint; uint8_t fastBunnyHood; uint8_t damageMultiplier; uint8_t startingTime; uint8_t gossipStoneHints; uint8_t compassesShowReward; uint8_t compassesShowWotH; uint8_t mapsShowDungeonMode; uint8_t chestAnimations; uint8_t chestSize; uint8_t generateSpoilerLog; uint8_t ingameSpoilers; uint8_t menuOpeningButton; uint8_t randomTrapDmg; uint8_t blueFireArrows; uint8_t sunLightArrows; uint8_t faroresWindAnywhere; uint8_t stickAsAdult; uint8_t boomerangAsAdult; uint8_t hammerAsChild; uint8_t slingshotAsAdult; uint8_t bowAsChild; uint8_t hookshotAsChild; uint8_t ironbootsAsChild; uint8_t hoverbootsAsChild; uint8_t masksAsAdult; uint8_t kokiriSwordAsAdult; uint8_t masterSwordAsChild; uint8_t biggoronSwordAsChild; uint8_t dekuShieldAsAdult; uint8_t mirrorShieldAsChild; uint8_t goronTunicAsChild; uint8_t zoraTunicAsChild; uint8_t gkDurability; uint8_t itemPoolValue; uint8_t iceTrapValue; uint8_t progressiveGoronSword; uint8_t mp_Enabled; uint8_t mp_SharedProgress; uint8_t mp_SyncId; uint8_t mp_SharedHealth; uint8_t mp_SharedRupees; uint8_t mp_SharedAmmo; uint8_t zTargeting; uint8_t cameraControl; uint8_t motionControl; uint8_t playMusic; uint8_t playSFX; uint8_t silenceNavi; uint8_t ignoreMaskReaction; uint8_t customTunicColors; uint8_t customNaviColors; uint8_t rainbowIdleNaviInnerColor; uint8_t rainbowNPCNaviInnerColor; uint8_t rainbowEnemyNaviInnerColor; uint8_t rainbowPropNaviInnerColor; uint8_t rainbowIdleNaviOuterColor; uint8_t rainbowNPCNaviOuterColor; uint8_t rainbowEnemyNaviOuterColor; uint8_t rainbowPropNaviOuterColor; uint8_t customTrailEffects; uint8_t rainbowSwordTrailInnerColor; uint8_t rainbowSwordTrailOuterColor; uint8_t boomerangTrailColorMode; uint8_t boomerangTrailDuration; uint8_t rainbowChuTrailInnerColor; uint8_t rainbowChuTrailOuterColor; uint8_t bombchuTrailDuration; uint8_t coloredKeys; uint8_t coloredBossKeys; uint8_t mirrorWorld; uint8_t shuffleSFX; uint8_t shuffleSFXCategorically; union { uint8_t dungeonModes[12]; struct { uint8_t dekuTreeDungeonMode; uint8_t dodongosCavernDungeonMode; uint8_t jabuJabusBellyDungeonMode; uint8_t forestTempleDungeonMode; uint8_t fireTempleDungeonMode; uint8_t waterTempleDungeonMode; uint8_t spiritTempleDungeonMode; uint8_t shadowTempleDungeonMode; uint8_t bottomOfTheWellDungeonMode; uint8_t iceCavernDungeonMode; uint8_t ganonsCastleDungeonMode; uint8_t gerudoTrainingGroundsDungeonMode; }; }; uint8_t forestTrialSkip; uint8_t fireTrialSkip; uint8_t waterTrialSkip; uint8_t spiritTrialSkip; uint8_t shadowTrialSkip; uint8_t lightTrialSkip; uint32_t linksPocketRewardBitMask; uint8_t startingConsumables; uint8_t startingMaxRupees; uint8_t startingStickCapacity; uint8_t startingNutCapacity; uint8_t startingBombBag; uint8_t startingBombchus; uint8_t startingBow; uint8_t startingFireArrows; uint8_t startingIceArrows; uint8_t startingLightArrows; uint8_t startingDinsFire; uint8_t startingFaroresWind; uint8_t startingNayrusLove; uint8_t startingSlingshot; uint8_t startingBoomerang; uint8_t startingLensOfTruth; uint8_t startingMagicBean; uint8_t startingMegatonHammer; uint8_t startingHookshot; uint8_t startingIronBoots; uint8_t startingHoverBoots; uint8_t startingBottle1; uint8_t startingBottle2; uint8_t startingBottle3; uint8_t startingBottle4; uint8_t startingRutoBottle; uint8_t startingOcarina; uint8_t startingKokiriSword; uint8_t startingBiggoronSword; uint8_t startingMagicMeter; uint8_t startingDoubleDefense; uint8_t startingHearts; uint32_t startingQuestItems; uint32_t startingDungeonReward; uint32_t startingEquipment; uint32_t startingUpgrades; uint8_t startingTokens; } SettingsContext; class Option { public: static Option Bool(std::string name_, std::vector options_, std::vector optionDescriptions_, OptionCategory category_ = OptionCategory::Setting, uint8_t defaultOption_ = 0, bool defaultHidden_ = false) { return Option{false, std::move(name_), std::move(options_), std::move(optionDescriptions_), category_, defaultOption_, defaultHidden_}; } static Option U8(std::string name_, std::vector options_, std::vector optionDescriptions_, OptionCategory category_ = OptionCategory::Setting, uint8_t defaultOption_ = 0, bool defaultHidden_ = false) { return Option{uint8_t{0}, std::move(name_), std::move(options_), std::move(optionDescriptions_), category_, defaultOption_, defaultHidden_}; } template T Value() const { return std::get(var); } template bool Is(T other) const { static_assert(std::is_integral_v || std::is_enum_v, "T must be an integral type or an enum."); if constexpr ((std::is_integral_v && !std::is_same_v) || std::is_enum_v) { return Value() == static_cast(other); } else { return Value() == static_cast(other); } } template bool IsNot(T other) const { return !Is(other); } explicit operator bool() const { if (std::holds_alternative(var)) { return Value(); } else { return Value() != 0; } } void SetOptions(std::vector o) { options = std::move(o); SetToDefault(); } size_t GetOptionCount() const { return options.size(); } const std::string& GetName() const { return name; } const std::string& GetSelectedOptionText() const { return options[selectedOption]; } void SetSelectedOptionText(std::string newText) { options[selectedOption] = std::move(newText); } bool IsDefaultSelected() { return selectedOption == defaultOption; } void SetToDefault() { SetSelectedIndex(defaultOption); hidden = defaultHidden; } std::string_view GetSelectedOptionDescription() const { //bounds checking if (selectedOption >= optionDescriptions.size()) { return optionDescriptions[optionDescriptions.size()-1]; } return optionDescriptions[selectedOption]; } uint8_t GetSelectedOptionIndex() const { return selectedOption; } void NextOptionIndex() { ++selectedOption; } void PrevOptionIndex() { --selectedOption; } void SanitizeSelectedOptionIndex() { if (selectedOption == options.size()) { selectedOption = 0; } else if (selectedOption == 0xFF) { selectedOption = static_cast(options.size() - 1); } } void SetVariable() { if (std::holds_alternative(var)) { var.emplace(selectedOption != 0); } else { var.emplace(selectedOption); } } void SetDelayedOption() { delayedOption = selectedOption; } void RestoreDelayedOption() { selectedOption = delayedOption; SetVariable(); } void SetSelectedIndex(size_t idx) { selectedOption = idx; if (selectedOption >= options.size()) { printf("\x1b[30;0HERROR: Incompatible selection for %s\n", name.c_str()); selectedOption = 0; } SetVariable(); } void SetSelectedIndexByString(std::string newSetting) { using namespace Cosmetics; //Special case for custom cosmetic settings if (options.size() > CUSTOM_COLOR) { if (newSetting.compare(0, 8, CUSTOM_COLOR_PREFIX) == 0 && options[CUSTOM_COLOR].compare(0, 8, CUSTOM_COLOR_PREFIX) == 0) { SetSelectedIndex(CUSTOM_COLOR); SetSelectedOptionText(newSetting); return; } } for (size_t i = 0; i < options.size(); i++) { std::string settingName = options[i]; if (settingName == newSetting) { SetSelectedIndex(i); return; } } } void Lock() { locked = true; } void Unlock() { locked = false; } bool IsLocked() const { return locked; } void Hide() { hidden = true; } void Unhide() { hidden = false; } bool IsHidden() const { return hidden; } bool IsCategory(OptionCategory category) const { return category == this->category; } private: Option(uint8_t var_, std::string name_, std::vector options_, std::vector optionDescriptions_, OptionCategory category_, uint8_t defaultOption_, bool defaultHidden_) : var(var_), name(std::move(name_)), options(std::move(options_)), optionDescriptions(std::move(optionDescriptions_)), category(category_), defaultOption(defaultOption_), defaultHidden(defaultHidden_) { selectedOption = defaultOption; hidden = defaultHidden; SetVariable(); } Option(bool var_, std::string name_, std::vector options_, std::vector optionDescriptions_, OptionCategory category_, uint8_t defaultOption_, bool defaultHidden_) : var(var_), name(std::move(name_)), options(std::move(options_)), optionDescriptions(std::move(optionDescriptions_)), category(category_), defaultOption(defaultOption_), defaultHidden(defaultHidden_) { selectedOption = defaultOption; hidden = defaultHidden; SetVariable(); } std::variant var; std::string name; std::vector options; std::vector optionDescriptions; uint8_t selectedOption = 0; uint8_t delayedOption = 0; bool locked = false; bool hidden = false; OptionCategory category; uint8_t defaultOption = 0; bool defaultHidden = false; }; enum class MenuType { MainMenu, SubMenu, Action, }; class Menu { public: static Menu SubMenu(std::string name_, std::vector