import typing import random from Options import Option, DefaultOnToggle, Toggle, Range, OptionList, OptionSet, DeathLink from .LogicTricks import normalized_name_tricks from .ColorSFXOptions import * class TrackRandomRange(Range): """Overrides normal from_any behavior to track whether the option was randomized at generation time.""" supports_weighting = False randomized: bool = False @classmethod def from_any(cls, data: typing.Any) -> Range: if type(data) is list: val = random.choices(data)[0] ret = super().from_any(val) if not isinstance(val, int) or len(data) > 1: ret.randomized = True return ret if type(data) is not dict: return super().from_any(data) if any(data.values()): val = random.choices(list(data.keys()), weights=list(map(int, data.values())))[0] ret = super().from_any(val) if not isinstance(val, int) or len(list(filter(bool, map(int, data.values())))) > 1: ret.randomized = True return ret raise RuntimeError(f"All options specified in \"{cls.display_name}\" are weighted as zero.") class Logic(Choice): """Set the logic used for the generator.""" display_name = "Logic Rules" option_glitchless = 0 option_glitched = 1 option_no_logic = 2 class NightTokens(Toggle): """Nighttime skulltulas will logically require Sun's Song.""" display_name = "Nighttime Skulltulas Expect Sun's Song" class Forest(Choice): """Set the state of Kokiri Forest and the path to Deku Tree.""" display_name = "Forest" option_open = 0 option_closed_deku = 1 option_closed = 2 alias_open_forest = 0 alias_closed_forest = 2 class Gate(Choice): """Set the state of the Kakariko Village gate.""" display_name = "Kakariko Gate" option_open = 0 option_zelda = 1 option_closed = 2 class DoorOfTime(DefaultOnToggle): """Open the Door of Time by default, without the Song of Time.""" display_name = "Open Door of Time" class Fountain(Choice): """Set the state of King Zora, blocking the way to Zora's Fountain.""" display_name = "Zora's Fountain" option_open = 0 option_adult = 1 option_closed = 2 default = 2 class Fortress(Choice): """Set the requirements for access to Gerudo Fortress.""" display_name = "Gerudo Fortress" option_normal = 0 option_fast = 1 option_open = 2 default = 1 class Bridge(Choice): """Set the requirements for the Rainbow Bridge.""" display_name = "Rainbow Bridge Requirement" option_open = 0 option_vanilla = 1 option_stones = 2 option_medallions = 3 option_dungeons = 4 option_tokens = 5 option_hearts = 6 default = 3 class Trials(TrackRandomRange): """Set the number of required trials in Ganon's Castle.""" display_name = "Ganon's Trials Count" range_start = 0 range_end = 6 open_options: typing.Dict[str, type(Option)] = { "open_forest": Forest, "open_kakariko": Gate, "open_door_of_time": DoorOfTime, "zora_fountain": Fountain, "gerudo_fortress": Fortress, "bridge": Bridge, "trials": Trials, } class StartingAge(Choice): """Choose which age Link will start as.""" display_name = "Starting Age" option_child = 0 option_adult = 1 class InteriorEntrances(Choice): """Shuffles interior entrances. "Simple" shuffles houses and Great Fairies; "All" includes Windmill, Link's House, Temple of Time, and Kak potion shop.""" display_name = "Shuffle Interior Entrances" option_off = 0 option_simple = 1 option_all = 2 alias_true = 2 class GrottoEntrances(Toggle): """Shuffles grotto and grave entrances.""" display_name = "Shuffle Grotto/Grave Entrances" class DungeonEntrances(Choice): """Shuffles dungeon entrances. Opens Deku, Fire and BotW to both ages. "All" includes Ganon's Castle.""" display_name = "Shuffle Dungeon Entrances" option_off = 0 option_simple = 1 option_all = 2 alias_true = 1 class BossEntrances(Choice): """Shuffles boss entrances. "Limited" prevents age-mixing of bosses.""" display_name = "Shuffle Boss Entrances" option_off = 0 option_limited = 1 option_full = 2 class OverworldEntrances(Toggle): """Shuffles overworld loading zones.""" display_name = "Shuffle Overworld Entrances" class OwlDrops(Toggle): """Randomizes owl drops from Lake Hylia or Death Mountain Trail as child.""" display_name = "Randomize Owl Drops" class WarpSongs(Toggle): """Randomizes warp song destinations.""" display_name = "Randomize Warp Songs" class SpawnPositions(Choice): """Randomizes the starting position on loading a save. Consistent between savewarps.""" display_name = "Randomize Spawn Positions" option_off = 0 option_child = 1 option_adult = 2 option_both = 3 alias_true = 3 class MixEntrancePools(Choice): """Shuffles entrances into a mixed pool instead of separate ones. "indoor" keeps overworld entrances separate; "all" mixes them in.""" display_name = "Mix Entrance Pools" option_off = 0 option_indoor = 1 option_all = 2 class DecoupleEntrances(Toggle): """Decouple entrances when shuffling them. Also adds the one-way entrance from Gerudo Valley to Lake Hylia if overworld is shuffled.""" display_name = "Decouple Entrances" class TriforceHunt(Toggle): """Gather pieces of the Triforce scattered around the world to complete the game.""" display_name = "Triforce Hunt" class TriforceGoal(Range): """Number of Triforce pieces required to complete the game.""" display_name = "Required Triforce Pieces" range_start = 1 range_end = 80 default = 20 class ExtraTriforces(Range): """Percentage of additional Triforce pieces in the pool. With high numbers, you may need to randomize additional locations to have enough items.""" display_name = "Percentage of Extra Triforce Pieces" range_start = 0 range_end = 100 default = 50 class LogicalChus(Toggle): """Bombchus are properly considered in logic. The first found pack will have 20 chus; Kokiri Shop and Bazaar sell refills; bombchus open Bombchu Bowling.""" display_name = "Bombchus Considered in Logic" class DungeonShortcuts(Choice): """Shortcuts to dungeon bosses are available without any requirements.""" display_name = "Dungeon Boss Shortcuts Mode" option_off = 0 option_choice = 1 option_all = 2 option_random_dungeons = 3 class DungeonShortcutsList(OptionSet): """Chosen dungeons to have shortcuts.""" display_name = "Shortcut Dungeons" valid_keys = { "Deku Tree", "Dodongo's Cavern", "Jabu Jabu's Belly", "Forest Temple", "Fire Temple", "Water Temple", "Shadow Temple", "Spirit Temple", } class MQDungeons(Choice): """Choose between vanilla and Master Quest dungeon layouts.""" display_name = "MQ Dungeon Mode" option_vanilla = 0 option_mq = 1 option_specific = 2 option_count = 3 class MQDungeonList(OptionSet): """Chosen dungeons to be MQ layout.""" display_name = "MQ Dungeon List" valid_keys = { "Deku Tree", "Dodongo's Cavern", "Jabu Jabu's Belly", "Forest Temple", "Fire Temple", "Water Temple", "Shadow Temple", "Spirit Temple", "Bottom of the Well", "Ice Cavern", "Gerudo Training Ground", "Ganon's Castle", } class MQDungeonCount(TrackRandomRange): """Number of MQ dungeons, chosen randomly.""" display_name = "MQ Dungeon Count" range_start = 0 range_end = 12 default = 0 class EmptyDungeons(Choice): """Pre-completed dungeons are barren and rewards are given for free.""" display_name = "Pre-completed Dungeons Mode" option_none = 0 option_specific = 1 option_count = 2 class EmptyDungeonList(OptionSet): """Chosen dungeons to be pre-completed.""" display_name = "Pre-completed Dungeon List" valid_keys = { "Deku Tree", "Dodongo's Cavern", "Jabu Jabu's Belly", "Forest Temple", "Fire Temple", "Water Temple", "Shadow Temple", "Spirit Temple", } class EmptyDungeonCount(Range): display_name = "Pre-completed Dungeon Count" range_start = 1 range_end = 8 default = 2 world_options: typing.Dict[str, type(Option)] = { "starting_age": StartingAge, "shuffle_interior_entrances": InteriorEntrances, "shuffle_grotto_entrances": GrottoEntrances, "shuffle_dungeon_entrances": DungeonEntrances, "shuffle_overworld_entrances": OverworldEntrances, "owl_drops": OwlDrops, "warp_songs": WarpSongs, "spawn_positions": SpawnPositions, "shuffle_bosses": BossEntrances, # "mix_entrance_pools": MixEntrancePools, # "decouple_entrances": DecoupleEntrances, "triforce_hunt": TriforceHunt, "triforce_goal": TriforceGoal, "extra_triforce_percentage": ExtraTriforces, "bombchus_in_logic": LogicalChus, "dungeon_shortcuts": DungeonShortcuts, "dungeon_shortcuts_list": DungeonShortcutsList, "mq_dungeons_mode": MQDungeons, "mq_dungeons_list": MQDungeonList, "mq_dungeons_count": MQDungeonCount, # "empty_dungeons_mode": EmptyDungeons, # "empty_dungeons_list": EmptyDungeonList, # "empty_dungeon_count": EmptyDungeonCount, } # class LacsCondition(Choice): # """Set the requirements for the Light Arrow Cutscene in the Temple of Time.""" # display_name = "Light Arrow Cutscene Requirement" # option_vanilla = 0 # option_stones = 1 # option_medallions = 2 # option_dungeons = 3 # option_tokens = 4 # class LacsStones(Range): # """Set the number of Spiritual Stones required for LACS.""" # display_name = "Spiritual Stones Required for LACS" # range_start = 0 # range_end = 3 # default = 3 # class LacsMedallions(Range): # """Set the number of medallions required for LACS.""" # display_name = "Medallions Required for LACS" # range_start = 0 # range_end = 6 # default = 6 # class LacsRewards(Range): # """Set the number of dungeon rewards required for LACS.""" # display_name = "Dungeon Rewards Required for LACS" # range_start = 0 # range_end = 9 # default = 9 # class LacsTokens(Range): # """Set the number of Gold Skulltula Tokens required for LACS.""" # display_name = "Tokens Required for LACS" # range_start = 0 # range_end = 100 # default = 40 # lacs_options: typing.Dict[str, type(Option)] = { # "lacs_condition": LacsCondition, # "lacs_stones": LacsStones, # "lacs_medallions": LacsMedallions, # "lacs_rewards": LacsRewards, # "lacs_tokens": LacsTokens, # } class BridgeStones(Range): """Set the number of Spiritual Stones required for the rainbow bridge.""" display_name = "Spiritual Stones Required for Bridge" range_start = 0 range_end = 3 default = 3 class BridgeMedallions(Range): """Set the number of medallions required for the rainbow bridge.""" display_name = "Medallions Required for Bridge" range_start = 0 range_end = 6 default = 6 class BridgeRewards(Range): """Set the number of dungeon rewards required for the rainbow bridge.""" display_name = "Dungeon Rewards Required for Bridge" range_start = 0 range_end = 9 default = 9 class BridgeTokens(Range): """Set the number of Gold Skulltula Tokens required for the rainbow bridge.""" display_name = "Tokens Required for Bridge" range_start = 0 range_end = 100 default = 40 class BridgeHearts(Range): """Set the number of hearts required for the rainbow bridge.""" display_name = "Hearts Required for Bridge" range_start = 4 range_end = 20 default = 20 bridge_options: typing.Dict[str, type(Option)] = { "bridge_stones": BridgeStones, "bridge_medallions": BridgeMedallions, "bridge_rewards": BridgeRewards, "bridge_tokens": BridgeTokens, "bridge_hearts": BridgeHearts, } class SongShuffle(Choice): """Set where songs can appear.""" display_name = "Shuffle Songs" option_song = 0 option_dungeon = 1 option_any = 2 class ShopShuffle(Choice): """Randomizes shop contents. "fixed_number" randomizes a specific number of items per shop; "random_number" randomizes the value for each shop. """ display_name = "Shopsanity" option_off = 0 option_fixed_number = 1 option_random_number = 2 class ShopSlots(Range): """Number of items per shop to be randomized into the main itempool. Only active if Shopsanity is set to "fixed_number." """ display_name = "Shuffled Shop Slots" range_start = 0 range_end = 4 class ShopPrices(Choice): """Controls prices of shop items. "Normal" is a distribution from 0 to 300. "X Wallet" requires that wallet at max. "Affordable" is always 10 rupees.""" display_name = "Shopsanity Prices" option_normal = 0 option_affordable = 1 option_starting_wallet = 2 option_adults_wallet = 3 option_giants_wallet = 4 option_tycoons_wallet = 5 class TokenShuffle(Choice): """Token rewards from Gold Skulltulas are shuffled into the pool.""" display_name = "Tokensanity" option_off = 0 option_dungeons = 1 option_overworld = 2 option_all = 3 class ScrubShuffle(Choice): """Shuffle the items sold by Business Scrubs, and set the prices.""" display_name = "Scrub Shuffle" option_off = 0 option_low = 1 option_regular = 2 option_random_prices = 3 alias_affordable = 1 alias_expensive = 2 class ShuffleCows(Toggle): """Cows give items when Epona's Song is played.""" display_name = "Shuffle Cows" class ShuffleSword(Toggle): """Shuffle Kokiri Sword into the item pool.""" display_name = "Shuffle Kokiri Sword" class ShuffleOcarinas(Toggle): """Shuffle the Fairy Ocarina and Ocarina of Time into the item pool.""" display_name = "Shuffle Ocarinas" class ShuffleChildTrade(Choice): """Controls the behavior of the start of the child trade quest.""" display_name = "Shuffle Child Trade Item" option_vanilla = 0 option_shuffle = 1 option_skip_child_zelda = 2 alias_false = 0 alias_true = 1 class ShuffleCard(Toggle): """Shuffle the Gerudo Membership Card into the item pool.""" display_name = "Shuffle Gerudo Card" class ShuffleBeans(Toggle): """Adds a pack of 10 beans to the item pool and changes the bean salesman to sell one item for 60 rupees.""" display_name = "Shuffle Magic Beans" class ShuffleMedigoronCarpet(Toggle): """Shuffle the items sold by Medigoron and the Haunted Wasteland Carpet Salesman.""" display_name = "Shuffle Medigoron & Carpet Salesman" class ShuffleFreestanding(Choice): """Shuffles freestanding rupees, recovery hearts, Shadow Temple Spinning Pots, and Goron Pot.""" display_name = "Shuffle Rupees & Hearts" option_off = 0 option_all = 1 option_overworld = 2 option_dungeons = 3 class ShufflePots(Choice): """Shuffles pots and flying pots which normally contain an item.""" display_name = "Shuffle Pots" option_off = 0 option_all = 1 option_overworld = 2 option_dungeons = 3 class ShuffleCrates(Choice): """Shuffles large and small crates containing an item.""" display_name = "Shuffle Crates" option_off = 0 option_all = 1 option_overworld = 2 option_dungeons = 3 class ShuffleBeehives(Toggle): """Beehives drop an item when destroyed by an explosion, the Hookshot, or the Boomerang.""" display_name = "Shuffle Beehives" class ShuffleFrogRupees(Toggle): """Shuffles the purple rupees received from the Zora's River frogs.""" display_name = "Shuffle Frog Song Rupees" shuffle_options: typing.Dict[str, type(Option)] = { "shuffle_song_items": SongShuffle, "shopsanity": ShopShuffle, "shop_slots": ShopSlots, "shopsanity_prices": ShopPrices, "tokensanity": TokenShuffle, "shuffle_scrubs": ScrubShuffle, "shuffle_child_trade": ShuffleChildTrade, "shuffle_freestanding_items": ShuffleFreestanding, "shuffle_pots": ShufflePots, "shuffle_crates": ShuffleCrates, "shuffle_cows": ShuffleCows, "shuffle_beehives": ShuffleBeehives, "shuffle_kokiri_sword": ShuffleSword, "shuffle_ocarinas": ShuffleOcarinas, "shuffle_gerudo_card": ShuffleCard, "shuffle_beans": ShuffleBeans, "shuffle_medigoron_carpet_salesman": ShuffleMedigoronCarpet, "shuffle_frog_song_rupees": ShuffleFrogRupees, } class ShuffleMapCompass(Choice): """Control where to shuffle dungeon maps and compasses.""" display_name = "Maps & Compasses" option_remove = 0 option_startwith = 1 option_vanilla = 2 option_dungeon = 3 option_overworld = 4 option_any_dungeon = 5 option_keysanity = 6 option_regional = 7 default = 1 alias_anywhere = 6 class ShuffleKeys(Choice): """Control where to shuffle dungeon small keys.""" display_name = "Small Keys" option_remove = 0 option_vanilla = 2 option_dungeon = 3 option_overworld = 4 option_any_dungeon = 5 option_keysanity = 6 option_regional = 7 default = 3 alias_keysy = 0 alias_anywhere = 6 class ShuffleGerudoKeys(Choice): """Control where to shuffle the Thieves' Hideout small keys.""" display_name = "Thieves' Hideout Keys" option_vanilla = 0 option_overworld = 1 option_any_dungeon = 2 option_keysanity = 3 option_regional = 4 alias_anywhere = 3 class ShuffleBossKeys(Choice): """Control where to shuffle boss keys, except the Ganon's Castle Boss Key.""" display_name = "Boss Keys" option_remove = 0 option_vanilla = 2 option_dungeon = 3 option_overworld = 4 option_any_dungeon = 5 option_keysanity = 6 option_regional = 7 default = 3 alias_keysy = 0 alias_anywhere = 6 class ShuffleGanonBK(Choice): """Control how to shuffle the Ganon's Castle Boss Key.""" display_name = "Ganon's Boss Key" option_remove = 0 option_vanilla = 2 option_dungeon = 3 option_overworld = 4 option_any_dungeon = 5 option_keysanity = 6 option_on_lacs = 7 option_regional = 8 option_stones = 9 option_medallions = 10 option_dungeons = 11 option_tokens = 12 option_hearts = 13 default = 0 alias_keysy = 0 alias_anywhere = 6 class EnhanceMC(Toggle): """Map tells if a dungeon is vanilla or MQ. Compass tells what the dungeon reward is.""" display_name = "Maps and Compasses Give Information" class GanonBKMedallions(Range): """Set how many medallions are required to receive Ganon BK.""" display_name = "Medallions Required for Ganon's BK" range_start = 1 range_end = 6 default = 6 class GanonBKStones(Range): """Set how many Spiritual Stones are required to receive Ganon BK.""" display_name = "Spiritual Stones Required for Ganon's BK" range_start = 1 range_end = 3 default = 3 class GanonBKRewards(Range): """Set how many dungeon rewards are required to receive Ganon BK.""" display_name = "Dungeon Rewards Required for Ganon's BK" range_start = 1 range_end = 9 default = 9 class GanonBKTokens(Range): """Set how many Gold Skulltula Tokens are required to receive Ganon BK.""" display_name = "Tokens Required for Ganon's BK" range_start = 1 range_end = 100 default = 40 class GanonBKHearts(Range): """Set how many hearts are required to receive Ganon BK.""" display_name = "Hearts Required for Ganon's BK" range_start = 4 range_end = 20 default = 20 class KeyRings(Choice): """Dungeons have all small keys found at once, rather than individually.""" display_name = "Key Rings Mode" option_off = 0 option_choose = 1 option_all = 2 option_random_dungeons = 3 class KeyRingList(OptionSet): """Select areas with keyrings rather than individual small keys.""" display_name = "Key Ring Areas" valid_keys = { "Thieves' Hideout", "Forest Temple", "Fire Temple", "Water Temple", "Shadow Temple", "Spirit Temple", "Bottom of the Well", "Gerudo Training Ground", "Ganon's Castle" } dungeon_items_options: typing.Dict[str, type(Option)] = { "shuffle_mapcompass": ShuffleMapCompass, "shuffle_smallkeys": ShuffleKeys, "shuffle_hideoutkeys": ShuffleGerudoKeys, "shuffle_bosskeys": ShuffleBossKeys, "enhance_map_compass": EnhanceMC, "shuffle_ganon_bosskey": ShuffleGanonBK, "ganon_bosskey_medallions": GanonBKMedallions, "ganon_bosskey_stones": GanonBKStones, "ganon_bosskey_rewards": GanonBKRewards, "ganon_bosskey_tokens": GanonBKTokens, "ganon_bosskey_hearts": GanonBKHearts, "key_rings": KeyRings, "key_rings_list": KeyRingList, } class SkipEscape(DefaultOnToggle): """Skips the tower collapse sequence between the Ganondorf and Ganon fights.""" display_name = "Skip Tower Escape Sequence" class SkipStealth(DefaultOnToggle): """The crawlspace into Hyrule Castle skips straight to Zelda.""" display_name = "Skip Child Stealth" class SkipEponaRace(DefaultOnToggle): """Epona can always be summoned with Epona's Song.""" display_name = "Skip Epona Race" class SkipMinigamePhases(DefaultOnToggle): """Dampe Race and Horseback Archery give both rewards if the second condition is met on the first attempt.""" display_name = "Skip Some Minigame Phases" class CompleteMaskQuest(Toggle): """All masks are immediately available to borrow from the Happy Mask Shop.""" display_name = "Complete Mask Quest" class UsefulCutscenes(Toggle): """Reenables the Poe cutscene in Forest Temple, Darunia in Fire Temple, and Twinrova introduction. Mostly useful for glitched.""" display_name = "Enable Useful Cutscenes" class FastChests(DefaultOnToggle): """All chest animations are fast. If disabled, major items have a slow animation.""" display_name = "Fast Chest Cutscenes" class FreeScarecrow(Toggle): """Pulling out the ocarina near a scarecrow spot spawns Pierre without needing the song.""" display_name = "Free Scarecrow's Song" class FastBunny(Toggle): """Bunny Hood lets you move 1.5x faster like in Majora's Mask.""" display_name = "Fast Bunny Hood" class PlantBeans(Toggle): """Pre-plants all 10 magic beans in the soft soil spots.""" display_name = "Plant Magic Beans" class ChickenCount(Range): """Controls the number of Cuccos for Anju to give an item as child.""" display_name = "Cucco Count" range_start = 0 range_end = 7 default = 7 class BigPoeCount(Range): """Number of Big Poes required for the Poe Collector's item.""" display_name = "Big Poe Count" range_start = 1 range_end = 10 default = 1 class FAETorchCount(Range): """Number of lit torches required to open Shadow Temple.""" display_name = "Fire Arrow Entry Torch Count" range_start = 1 range_end = 24 default = 24 timesavers_options: typing.Dict[str, type(Option)] = { "no_escape_sequence": SkipEscape, "no_guard_stealth": SkipStealth, "no_epona_race": SkipEponaRace, "skip_some_minigame_phases": SkipMinigamePhases, "complete_mask_quest": CompleteMaskQuest, "useful_cutscenes": UsefulCutscenes, "fast_chests": FastChests, "free_scarecrow": FreeScarecrow, "fast_bunny_hood": FastBunny, "plant_beans": PlantBeans, "chicken_count": ChickenCount, "big_poe_count": BigPoeCount, "fae_torch_count": FAETorchCount, } class CorrectChestAppearance(Choice): """Changes chest textures and/or sizes to match their contents. "Classic" is the old behavior of CSMC.""" display_name = "Chest Appearance Matches Contents" option_off = 0 option_textures = 1 option_both = 2 option_classic = 3 class MinorInMajor(Toggle): """Hylian Shield, Deku Shield, and Bombchus appear in big/gold chests.""" display_name = "Minor Items in Big/Gold Chests" class InvisibleChests(Toggle): """Chests visible only with Lens of Truth. Logic is not changed.""" display_name = "Invisible Chests" class CorrectPotCrateAppearance(Choice): """Unchecked pots and crates have a different texture; unchecked beehives will wiggle. With textures_content, pots and crates have an appearance based on their contents; with textures_unchecked, all unchecked pots/crates have the same appearance.""" display_name = "Pot, Crate, and Beehive Appearance" option_off = 0 option_textures_content = 1 option_textures_unchecked = 2 class Hints(Choice): """Gossip Stones can give hints about item locations.""" display_name = "Gossip Stones" option_none = 0 option_mask = 1 option_agony = 2 option_always = 3 default = 3 class MiscHints(DefaultOnToggle): """The Temple of Time altar hints dungeon rewards, bridge info, and Ganon BK info; Ganondorf hints the Light Arrows; Dampe's diary hints a local Hookshot if one exists; Skulltula House locations hint their item.""" display_name = "Misc Hints" class HintDistribution(Choice): """Choose the hint distribution to use. Affects the frequency of strong hints, which items are always hinted, etc.""" display_name = "Hint Distribution" option_balanced = 0 option_ddr = 1 # option_league = 2 # option_mw3 = 3 option_scrubs = 4 option_strong = 5 # option_tournament = 6 option_useless = 7 option_very_strong = 8 option_async = 9 class TextShuffle(Choice): """Randomizes text in the game for comedic effect.""" display_name = "Text Shuffle" option_none = 0 option_except_hints = 1 option_complete = 2 alias_false = 0 class DamageMultiplier(Choice): """Controls the amount of damage Link takes.""" display_name = "Damage Multiplier" option_half = 0 option_normal = 1 option_double = 2 option_quadruple = 3 option_ohko = 4 default = 1 class DeadlyBonks(Choice): """Bonking on a wall or object will hurt Link. "Normal" is a half heart of damage.""" display_name = "Bonks Do Damage" option_none = 0 option_half = 1 option_normal = 2 option_double = 3 option_quadruple = 4 option_ohko = 5 class HeroMode(Toggle): """Hearts will not drop from enemies or objects.""" display_name = "Hero Mode" class StartingToD(Choice): """Change the starting time of day.""" display_name = "Starting Time of Day" option_default = 0 option_sunrise = 1 option_morning = 2 option_noon = 3 option_afternoon = 4 option_sunset = 5 option_evening = 6 option_midnight = 7 option_witching_hour = 8 class BlueFireArrows(Toggle): """Ice arrows can melt red ice and break the mud walls in Dodongo's Cavern.""" display_name = "Blue Fire Arrows" class FixBrokenDrops(Toggle): """Fixes two broken vanilla drops: deku shield in child Spirit Temple, and magic drop on GTG eye statue.""" display_name = "Fix Broken Drops" class ConsumableStart(Toggle): """Start the game with full Deku Sticks and Deku Nuts.""" display_name = "Start with Consumables" class RupeeStart(Toggle): """Start with a full wallet. Wallet upgrades will also fill your wallet.""" display_name = "Start with Rupees" misc_options: typing.Dict[str, type(Option)] = { "correct_chest_appearances": CorrectChestAppearance, "minor_items_as_major_chest": MinorInMajor, "invisible_chests": InvisibleChests, "correct_potcrate_appearances": CorrectPotCrateAppearance, "hints": Hints, "misc_hints": MiscHints, "hint_dist": HintDistribution, "text_shuffle": TextShuffle, "damage_multiplier": DamageMultiplier, "deadly_bonks": DeadlyBonks, "no_collectible_hearts": HeroMode, "starting_tod": StartingToD, "blue_fire_arrows": BlueFireArrows, "fix_broken_drops": FixBrokenDrops, "start_with_consumables": ConsumableStart, "start_with_rupees": RupeeStart, } class ItemPoolValue(Choice): """Changes the number of items available in the game.""" display_name = "Item Pool" option_plentiful = 0 option_balanced = 1 option_scarce = 2 option_minimal = 3 default = 1 class IceTraps(Choice): """Adds ice traps to the item pool.""" display_name = "Ice Traps" option_off = 0 option_normal = 1 option_on = 2 option_mayhem = 3 option_onslaught = 4 default = 1 alias_extra = 2 class IceTrapVisual(Choice): """Changes the appearance of ice traps as freestanding items.""" display_name = "Ice Trap Appearance" option_major_only = 0 option_junk_only = 1 option_anything = 2 class AdultTradeStart(OptionSet): """Choose the items that can appear to start the adult trade sequence. By default it is Claim Check only.""" display_name = "Adult Trade Sequence Items" default = {"Claim Check"} valid_keys = { "Pocket Egg", "Pocket Cucco", "Cojiro", "Odd Mushroom", "Poachers Saw", "Broken Sword", "Prescription", "Eyeball Frog", "Eyedrops", "Claim Check", } def __init__(self, value: typing.Iterable[str]): if not value: value = self.default super().__init__(value) itempool_options: typing.Dict[str, type(Option)] = { "item_pool_value": ItemPoolValue, "junk_ice_traps": IceTraps, "ice_trap_appearance": IceTrapVisual, "adult_trade_start": AdultTradeStart, } # Start of cosmetic options class Targeting(Choice): """Default targeting option.""" display_name = "Default Targeting Option" option_hold = 0 option_switch = 1 class DisplayDpad(DefaultOnToggle): """Show dpad icon on HUD for quick actions (ocarina, hover boots, iron boots).""" display_name = "Display D-Pad HUD" class DpadDungeonMenu(DefaultOnToggle): """Show separated menus on the pause screen for dungeon keys, rewards, and Vanilla/MQ info.""" display_name = "Display D-Pad Dungeon Info" class CorrectColors(DefaultOnToggle): """Makes in-game models match their HUD element colors.""" display_name = "Item Model Colors Match Cosmetics" class Music(Choice): option_normal = 0 option_off = 1 option_randomized = 2 class BackgroundMusic(Music): """Randomize or disable background music.""" display_name = "Background Music" class Fanfares(Music): """Randomize or disable item fanfares.""" display_name = "Fanfares" class OcarinaFanfares(Toggle): """Enable ocarina songs as fanfares. These are longer than usual fanfares. Does nothing without fanfares randomized.""" display_name = "Ocarina Songs as Fanfares" class SwordTrailDuration(Range): """Set the duration for sword trails.""" display_name = "Sword Trail Duration" range_start = 4 range_end = 20 default = 4 cosmetic_options: typing.Dict[str, type(Option)] = { "default_targeting": Targeting, "display_dpad": DisplayDpad, "dpad_dungeon_menu": DpadDungeonMenu, "correct_model_colors": CorrectColors, "background_music": BackgroundMusic, "fanfares": Fanfares, "ocarina_fanfares": OcarinaFanfares, "kokiri_color": kokiri_color, "goron_color": goron_color, "zora_color": zora_color, "silver_gauntlets_color": silver_gauntlets_color, "golden_gauntlets_color": golden_gauntlets_color, "mirror_shield_frame_color": mirror_shield_frame_color, "navi_color_default_inner": navi_color_default_inner, "navi_color_default_outer": navi_color_default_outer, "navi_color_enemy_inner": navi_color_enemy_inner, "navi_color_enemy_outer": navi_color_enemy_outer, "navi_color_npc_inner": navi_color_npc_inner, "navi_color_npc_outer": navi_color_npc_outer, "navi_color_prop_inner": navi_color_prop_inner, "navi_color_prop_outer": navi_color_prop_outer, "sword_trail_duration": SwordTrailDuration, "sword_trail_color_inner": sword_trail_color_inner, "sword_trail_color_outer": sword_trail_color_outer, "bombchu_trail_color_inner": bombchu_trail_color_inner, "bombchu_trail_color_outer": bombchu_trail_color_outer, "boomerang_trail_color_inner": boomerang_trail_color_inner, "boomerang_trail_color_outer": boomerang_trail_color_outer, "heart_color": heart_color, "magic_color": magic_color, "a_button_color": a_button_color, "b_button_color": b_button_color, "c_button_color": c_button_color, "start_button_color": start_button_color, } class SfxOcarina(Choice): """Change the sound of the ocarina.""" display_name = "Ocarina Instrument" option_ocarina = 1 option_malon = 2 option_whistle = 3 option_harp = 4 option_grind_organ = 5 option_flute = 6 default = 1 sfx_options: typing.Dict[str, type(Option)] = { "sfx_navi_overworld": sfx_navi_overworld, "sfx_navi_enemy": sfx_navi_enemy, "sfx_low_hp": sfx_low_hp, "sfx_menu_cursor": sfx_menu_cursor, "sfx_menu_select": sfx_menu_select, "sfx_nightfall": sfx_nightfall, "sfx_horse_neigh": sfx_horse_neigh, "sfx_hover_boots": sfx_hover_boots, "sfx_ocarina": SfxOcarina, } class LogicTricks(OptionList): """Set various tricks for logic in Ocarina of Time. Format as a comma-separated list of "nice" names: ["Fewer Tunic Requirements", "Hidden Grottos without Stone of Agony"]. A full list of supported tricks can be found at: https://github.com/ArchipelagoMW/Archipelago/blob/main/worlds/oot/LogicTricks.py """ display_name = "Logic Tricks" valid_keys = frozenset(normalized_name_tricks) valid_keys_casefold = True # All options assembled into a single dict oot_options: typing.Dict[str, type(Option)] = { "logic_rules": Logic, "logic_no_night_tokens_without_suns_song": NightTokens, **open_options, **world_options, **bridge_options, **dungeon_items_options, # **lacs_options, **shuffle_options, **timesavers_options, **misc_options, **itempool_options, **cosmetic_options, **sfx_options, "logic_tricks": LogicTricks, "death_link": DeathLink, }