diff --git a/worlds/oot_soh/Enums.py b/worlds/oot_soh/Enums.py index cc927ee11b11..3deee99ecd8c 100644 --- a/worlds/oot_soh/Enums.py +++ b/worlds/oot_soh/Enums.py @@ -239,21 +239,21 @@ class Regions(StrEnum): DEKU_TREE_BASEMENT_BACK_ROOM = "Deku Tree Basement Back Room" DEKU_TREE_BASEMENT_UPPER = "Deku Tree Basement Upper" DEKU_TREE_OUTSIDE_BOSS_ROOM = "Deku Tree Outside Boss Room" - # DEKU_TREE_MQ_1F = "Deku Tree MQ 1F" - # DEKU_TREE_MQ_2F = "Deku Tree MQ 2F" - # DEKU_TREE_MQ_3F = "Deku Tree MQ 3F" - # DEKU_TREE_MQ_EYE_TARGET_ROOM = "Deku Tree MQ Eye Target Room" - # DEKU_TREE_MQ_COMPASS_ROOM = "Deku Tree MQ Compass Room" - # DEKU_TREE_MQ_PAST_BOULDER_VINES = "Deku Tree MQ Past Boulder Vines" - # DEKU_TREE_MQ_BASEMENT = "Deku Tree MQ Basement" - # DEKU_TREE_MQ_SOUTHEAST_ROOM = "Deku Tree MQ Southeast Room" - # DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT = "Deku Tree MQ Basement Water Room Front" - # DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK = "Deku Tree MQ Basement Water Room Back" - # DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM = "Deku Tree MQ Basement Southwest Room" - # DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM = "Deku Tree MQ Basement Grave Room" - # DEKU_TREE_MQ_BASEMENT_BACK_ROOM = "Deku Tree MQ Basement Back Room" - # DEKU_TREE_MQ_BASEMENT_LEDGE = "Deku Tree MQ Basement Ledge" - # DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM = "Deku Tree MQ Outside Boss Room" + DEKU_TREE_MQ_1F = "Deku Tree MQ 1F" + DEKU_TREE_MQ_2F = "Deku Tree MQ 2F" + DEKU_TREE_MQ_3F = "Deku Tree MQ 3F" + DEKU_TREE_MQ_EYE_TARGET_ROOM = "Deku Tree MQ Eye Target Room" + DEKU_TREE_MQ_COMPASS_ROOM = "Deku Tree MQ Compass Room" + DEKU_TREE_MQ_PAST_BOULDER_VINES = "Deku Tree MQ Past Boulder Vines" + DEKU_TREE_MQ_BASEMENT = "Deku Tree MQ Basement" + DEKU_TREE_MQ_SOUTHEAST_ROOM = "Deku Tree MQ Southeast Room" + DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT = "Deku Tree MQ Basement Water Room Front" + DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK = "Deku Tree MQ Basement Water Room Back" + DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM = "Deku Tree MQ Basement Southwest Room" + DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM = "Deku Tree MQ Basement Grave Room" + DEKU_TREE_MQ_BASEMENT_BACK_ROOM = "Deku Tree MQ Basement Back Room" + DEKU_TREE_MQ_BASEMENT_LEDGE = "Deku Tree MQ Basement Ledge" + DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM = "Deku Tree MQ Outside Boss Room" DEKU_TREE_BOSS_ENTRYWAY = "Deku Tree Boss Entryway" DEKU_TREE_BOSS_EXIT = "Deku Tree Boss Exit" DEKU_TREE_BOSS_ROOM = "Deku Tree Boss Room" @@ -3846,6 +3846,56 @@ class Tricks(StrEnum): GANONS_CASTLE_BARRIER_SKIP_HOVER = "Ganons Castle Barrier Skip Hover" GANONS_CASTLE_GOLD_GAUNTLET_SKIP = "Ganons Castle Gold Gauntlet Skip" + +class DungeonQuest(StrEnum): + VANILLA = "Vanilla" + MASTER_QUEST = "Master Quest" + + +class Dungeons(StrEnum): + DEKU_TREE = "Deku Tree" + DODONGOS_CAVERN = "Dodongo's Cavern" + JABU_JABUS_BELLY = "Jabu Jabu's Belly" + FOREST_TEMPLE = "Forest Temple" + FIRE_TEMPLE = "Fire Temple" + WATER_TEMPLE = "Water Temple" + SPIRIT_TEMPLE = "Spirit Temple" + SHADOW_TEMPLE = "Shadow Temple" + BOTTOM_OF_THE_WELL = "Bottom of the Well" + ICE_CAVERN = "Ice Cavern" + GERUDO_TRAINING_GROUND = "Gerudo Training Ground" + GANONS_CASTLE = "Ganon's Castle" + + @classmethod + def from_str(cls, s: str): + match s: + case "Deku Tree": + return cls.DEKU_TREE + case "Dodongo's Cavern": + return cls.DODONGOS_CAVERN + case "Jabu Jabu's Belly": + return cls.JABU_JABUS_BELLY + case "Forest Temple": + return cls.FOREST_TEMPLE + case "Fire Temple": + return cls.FIRE_TEMPLE + case "Water Temple": + return cls.WATER_TEMPLE + case "Spirit Temple": + return cls.SPIRIT_TEMPLE + case "Shadow Temple": + return cls.SHADOW_TEMPLE + case "Bottom of the Well": + return cls.BOTTOM_OF_THE_WELL + case "Ice Cavern": + return cls.ICE_CAVERN + case "Gerudo Training Ground": + return cls.GERUDO_TRAINING_GROUND + case "Ganon's Castle": + return cls.GANONS_CASTLE + case _: + return None + class TokenCounts(IntEnum): DUNGEON = 44 OVERWORLD = 56 diff --git a/worlds/oot_soh/Options.py b/worlds/oot_soh/Options.py index 4226be638dbd..a77941ac638c 100644 --- a/worlds/oot_soh/Options.py +++ b/worlds/oot_soh/Options.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from Options import Choice, Toggle, DefaultOnToggle, Range, PerGameCommonOptions, StartInventoryPool, Visibility, OptionGroup, OptionSet -from .Enums import Tricks +from .Enums import Tricks, Dungeons class ClosedForest(Choice): @@ -100,6 +100,38 @@ class FortressCarpenters(Choice): default = 1 +class MasterQuestDungeonSettings(Choice): + """ + Sets the number of Master Quest Dungeons that are shuffled into the pool. + None - All Dungeons will be their Vanilla versions. + Count - Select a number of Master Quest Dungeons that are shuffled into the pool using the MQ Dungeon Count setting. + Select - Select which Master Quest Dungeons that are shuffled into the pool using the MQ Dungeon Selection setting. + """ + display_name = "Master Quest Dungeon Settings" + option_none = 0 + option_count = 1 + option_select = 2 + default = 0 + + +class MasterQuestDungeonCount(Range): + """ + When MQ Dungeon Settings is set to count, this is how many dungeons will be the Master Quest variant. + """ + display_name = "Master Quest Dungeon Count" + range_start = 0 + range_end = 9 + default = 0 + + +class MasterQuestDungeonSelection(OptionSet): + """ + When MQ Dungeon Settings is set to select, this determines which dungeons are selected to be Master Quest Dungeons. + """ + display_name = "MQ Dungeon Selection" + valid_keys = [str(dungeon) for dungeon in Dungeons] + + class RainbowBridge(Choice): """ Alters the requirements to open the bridge to Ganon's Castle. @@ -898,6 +930,9 @@ class SohOptions(PerGameCommonOptions): jabu_jabu: JabuJabu lock_overworld_doors: LockOverworldDoors fortress_carpenters: FortressCarpenters + master_quest_dungeon_settings: MasterQuestDungeonSettings + master_quest_dungeon_count: MasterQuestDungeonCount + master_quest_dungeon_selection: MasterQuestDungeonSelection rainbow_bridge: RainbowBridge rainbow_bridge_stones_required: RainbowBridgeStonesRequired rainbow_bridge_medallions_required: RainbowBridgeMedallionsRequired @@ -993,6 +1028,9 @@ class SohOptions(PerGameCommonOptions): OptionGroup("World Settings", [ StartingAge, FortressCarpenters, + MasterQuestDungeonSettings, + MasterQuestDungeonCount, + MasterQuestDungeonSelection, RainbowBridge, RainbowBridgeStonesRequired, RainbowBridgeMedallionsRequired, diff --git a/worlds/oot_soh/Regions.py b/worlds/oot_soh/Regions.py index 71fdf61589cc..3ac5d48432f6 100644 --- a/worlds/oot_soh/Regions.py +++ b/worlds/oot_soh/Regions.py @@ -99,162 +99,174 @@ def can_reach(self, state) -> bool: return self in state._soh_child_reachable_regions[self.player] or self in state._soh_adult_reachable_regions[self.player] +overworld_regions = [root, castle_grounds, death_mountain_crater, death_mountain_trail, desert_colossus, gerudo_fortress, + gerudo_valley, goron_city, graveyard, haunted_wasteland, hyrule_field, kakariko, kokiri_forest, + lake_hylia, lon_lon_ranch, lost_woods, market, sacred_forest_meadow, temple_of_time, thieves_hideout, + zoras_domain, zoras_fountain, zoras_river] + + +dungeoon_regions = [(bottom_of_the_well, Dungeons.BOTTOM_OF_THE_WELL), (deku_tree, Dungeons.DEKU_TREE), + (dodongos_cavern, Dungeons.DODONGOS_CAVERN), (fire_temple, Dungeons.FIRE_TEMPLE), + (forest_temple, Dungeons.FOREST_TEMPLE), (ganons_castle, Dungeons.GANONS_CASTLE), + (gerudo_training_ground, Dungeons.GERUDO_TRAINING_GROUND),(ice_cavern, Dungeons.ICE_CAVERN), + (jabujabus_belly, Dungeons.JABU_JABUS_BELLY), (shadow_temple, Dungeons.SHADOW_TEMPLE), + (spirit_temple, Dungeons.SPIRIT_TEMPLE), (water_temple, Dungeons.WATER_TEMPLE)] + + def create_regions_and_locations(world: "SohWorld") -> None: - # Fill region data table based on the regions enum list - region_data_table: dict[str, SohRegionData] = {} - for entry in Regions: - region_data_table[entry] = SohRegionData([]) + if world.options.master_quest_dungeon_settings.value != 0: + # Select which dungeons are master quest + set_master_quest_dungeons(world) + + for region in overworld_regions: + region.init_regions(world) + + for region in dungeoon_regions: + region_file = region[0] + region_type = region[1] + dungeon_quest = world.dungeon_quests[region_type] + + region.init_regions(world, dungeon_quest) + + # Create locations + + # Base locations + world.included_locations.update(base_location_table) + + # Gold Skulltulas (Overworld) + world.included_locations.update( + gold_skulltula_overworld_location_table) + + # Gold Skulltulas (Dungeon) + world.included_locations.update(gold_skulltula_dungeon_location_table) + + # Shops, Add all shop locations vanilla items will get prefilled and locked + # Todo: maybe we have to add the vanilla locations as events (id = None) + # check if vanilla items show up in the list of checks + world.included_locations.update(shops_location_table) + + # Scrubs + if world.options.shuffle_scrubs == "all": + world.included_locations.update(scrubs_location_table) + + if world.options.shuffle_scrubs == "one_time_only": + for location_name in scrubs_one_time_only: + world.included_locations[location_name] = scrubs_location_table[location_name] + + # Adult Trade Items + if world.options.shuffle_adult_trade_items: + world.included_locations.update(trade_items_location_table) + + # Merchants + if world.options.shuffle_merchants == "bean_merchant_only" or world.options.shuffle_merchants == "all": + world.included_locations[Locations.ZR_MAGIC_BEAN_SALESMAN] \ + = merchants_items_location_table[Locations.ZR_MAGIC_BEAN_SALESMAN] + + if world.options.shuffle_merchants == "all_but_beans" or world.options.shuffle_merchants == "all": + for location_name in (Locations.KAK_GRANNYS_SHOP, Locations.GC_MEDIGORON, + Locations.WASTELAND_CARPET_SALESMAN): + world.included_locations[location_name] = merchants_items_location_table[location_name] - # exclusions - # We don't need HC Garden if child zelda is skipped - if world.options.skip_child_zelda: - region_data_table.pop(Regions.HC_GARDEN) + # Cows + if world.options.shuffle_cows: + world.included_locations.update(cows_location_table) - # Create regions. - for region_name in region_data_table.keys(): - region = SohRegion(region_name, world.player, world.multiworld) - world.multiworld.regions.append(region) - region.add_exits(region_data_table[region_name].connecting_regions) + # Frogs + if world.options.shuffle_frog_song_rupees: + world.included_locations.update(frogs_location_table) - # Create locations + # Beehives + if world.options.shuffle_beehives: + world.included_locations.update(beehives_location_table) - # Base locations - world.included_locations.update(base_location_table) + # Pots (Overworld) + if world.options.shuffle_pots == "overworld" or world.options.shuffle_pots == "all": + world.included_locations.update(pots_overworld_location_table) - # Gold Skulltulas (Overworld) + # Pots (Dungeon) + if world.options.shuffle_pots == "dungeon" or world.options.shuffle_pots == "all": + world.included_locations.update(pots_dungeon_location_table) + + # Crates (Overworld) + if world.options.shuffle_crates == "overworld" or world.options.shuffle_crates == "all": + world.included_locations.update(crates_overworld_location_table) + + # Crates (Dungeon) + if world.options.shuffle_crates == "dungeon" or world.options.shuffle_crates == "all": + world.included_locations.update(crates_dungeon_location_table) + + # Trees + if world.options.shuffle_trees: + world.included_locations.update(tree_location_table) + + # Freestanding (Overworld) + if world.options.shuffle_freestanding_items == "overworld" or world.options.shuffle_freestanding_items == "all": world.included_locations.update( - gold_skulltula_overworld_location_table) - - # Gold Skulltulas (Dungeon) - world.included_locations.update(gold_skulltula_dungeon_location_table) - - # Shops, Add all shop locations vanilla items will get prefilled and locked - # Todo: maybe we have to add the vanilla locations as events (id = None) - # check if vanilla items show up in the list of checks - world.included_locations.update(shops_location_table) - - # Scrubs - if world.options.shuffle_scrubs == "all": - world.included_locations.update(scrubs_location_table) - - if world.options.shuffle_scrubs == "one_time_only": - for location_name in scrubs_one_time_only: - world.included_locations[location_name] = scrubs_location_table[location_name] - - # Adult Trade Items - if world.options.shuffle_adult_trade_items: - world.included_locations.update(trade_items_location_table) - - # Merchants - if world.options.shuffle_merchants == "bean_merchant_only" or world.options.shuffle_merchants == "all": - world.included_locations[Locations.ZR_MAGIC_BEAN_SALESMAN] \ - = merchants_items_location_table[Locations.ZR_MAGIC_BEAN_SALESMAN] - - if world.options.shuffle_merchants == "all_but_beans" or world.options.shuffle_merchants == "all": - for location_name in (Locations.KAK_GRANNYS_SHOP, Locations.GC_MEDIGORON, - Locations.WASTELAND_CARPET_SALESMAN): - world.included_locations[location_name] = merchants_items_location_table[location_name] - - # Cows - if world.options.shuffle_cows: - world.included_locations.update(cows_location_table) - - # Frogs - if world.options.shuffle_frog_song_rupees: - world.included_locations.update(frogs_location_table) - - # Beehives - if world.options.shuffle_beehives: - world.included_locations.update(beehives_location_table) - - # Pots (Overworld) - if world.options.shuffle_pots == "overworld" or world.options.shuffle_pots == "all": - world.included_locations.update(pots_overworld_location_table) - - # Pots (Dungeon) - if world.options.shuffle_pots == "dungeon" or world.options.shuffle_pots == "all": - world.included_locations.update(pots_dungeon_location_table) - - # Crates (Overworld) - if world.options.shuffle_crates == "overworld" or world.options.shuffle_crates == "all": - world.included_locations.update(crates_overworld_location_table) + freestanding_overworld_location_table) + + # Freestanding (Dungeon) + if world.options.shuffle_freestanding_items == "dungeon" or world.options.shuffle_freestanding_items == "all": + world.included_locations.update( + freestanding_dungeon_location_table) + + # Fairies + if world.options.shuffle_fountain_fairies: + world.included_locations.update(fairies_fountain_location_table) + if world.options.shuffle_stone_fairies: + world.included_locations.update(fairies_stone_location_table) + if world.options.shuffle_bean_fairies: + world.included_locations.update(fairies_bean_location_table) + if world.options.shuffle_song_fairies: + world.included_locations.update(fairies_song_location_table) + + # Grass (Overworld) + if world.options.shuffle_grass == "overworld" or world.options.shuffle_grass == "all": + world.included_locations.update(grass_overworld_location_table) + + # Grass (Dungeon) + if world.options.shuffle_grass == "dungeon" or world.options.shuffle_grass == "all": + world.included_locations.update(grass_dungeon_location_table) + + # Fish (Pond) + if world.options.shuffle_fish == "pond" or world.options.shuffle_fish == "all": + world.included_locations.update(fish_pond_location_table) + + # Fish (Overworld) + if world.options.shuffle_fish == "overworld" or world.options.shuffle_fish == "all": + world.included_locations.update(fish_overworld_location_table) + + # Child Zelda + if not world.options.skip_child_zelda: + world.included_locations.update(child_zelda_location_table) + + # Carpenters + if world.options.fortress_carpenters == "normal": + world.included_locations.update(carpenters_location_table) + + if world.options.fortress_carpenters == "fast": + for location_name in (Locations.GF_GERUDO_MEMBERSHIP_CARD, Locations.TH_1_TORCH_CARPENTER): + world.included_locations[location_name] = carpenters_location_table[location_name] - # Crates (Dungeon) - if world.options.shuffle_crates == "dungeon" or world.options.shuffle_crates == "all": - world.included_locations.update(crates_dungeon_location_table) + if world.options.shuffle_100_gs_reward: + world.included_locations.update(hundred_skulls_location_table) - # Trees + if world.options.true_no_logic: + if world.options.shuffle_crates == "overworld" or world.options.shuffle_crates == "all": + world.included_locations.update(no_logic_crates_location_table) if world.options.shuffle_trees: - world.included_locations.update(tree_location_table) - - # Freestanding (Overworld) - if world.options.shuffle_freestanding_items == "overworld" or world.options.shuffle_freestanding_items == "all": - world.included_locations.update( - freestanding_overworld_location_table) - - # Freestanding (Dungeon) - if world.options.shuffle_freestanding_items == "dungeon" or world.options.shuffle_freestanding_items == "all": - world.included_locations.update( - freestanding_dungeon_location_table) - - # Fairies - if world.options.shuffle_fountain_fairies: - world.included_locations.update(fairies_fountain_location_table) - if world.options.shuffle_stone_fairies: - world.included_locations.update(fairies_stone_location_table) - if world.options.shuffle_bean_fairies: - world.included_locations.update(fairies_bean_location_table) - if world.options.shuffle_song_fairies: - world.included_locations.update(fairies_song_location_table) - - # Grass (Overworld) - if world.options.shuffle_grass == "overworld" or world.options.shuffle_grass == "all": - world.included_locations.update(grass_overworld_location_table) - - # Grass (Dungeon) - if world.options.shuffle_grass == "dungeon" or world.options.shuffle_grass == "all": - world.included_locations.update(grass_dungeon_location_table) - - # Fish (Pond) - if world.options.shuffle_fish == "pond" or world.options.shuffle_fish == "all": - world.included_locations.update(fish_pond_location_table) - - # Fish (Overworld) - if world.options.shuffle_fish == "overworld" or world.options.shuffle_fish == "all": - world.included_locations.update(fish_overworld_location_table) - - # Child Zelda - if not world.options.skip_child_zelda: - world.included_locations.update(child_zelda_location_table) - - # Carpenters - if world.options.fortress_carpenters == "normal": - world.included_locations.update(carpenters_location_table) - - if world.options.fortress_carpenters == "fast": - for location_name in (Locations.GF_GERUDO_MEMBERSHIP_CARD, Locations.TH_1_TORCH_CARPENTER): - world.included_locations[location_name] = carpenters_location_table[location_name] - - if world.options.shuffle_100_gs_reward: - world.included_locations.update(hundred_skulls_location_table) - - if world.options.true_no_logic: - if world.options.shuffle_crates == "overworld" or world.options.shuffle_crates == "all": - world.included_locations.update(no_logic_crates_location_table) - if world.options.shuffle_trees: - world.included_locations.update(no_logic_trees_location_table) - - # Set region rules and location rules after all locations are created - all_regions = [root, castle_grounds, death_mountain_crater, death_mountain_trail, desert_colossus, gerudo_fortress, - gerudo_valley, goron_city, graveyard, haunted_wasteland, hyrule_field, kakariko, kokiri_forest, - lake_hylia, lon_lon_ranch, lost_woods, market, sacred_forest_meadow, temple_of_time, thieves_hideout, - zoras_domain, zoras_fountain, zoras_river, bottom_of_the_well, deku_tree, dodongos_cavern, - fire_temple, forest_temple, ganons_castle, gerudo_training_ground, ice_cavern, jabujabus_belly, - shadow_temple, spirit_temple, water_temple] - for region in all_regions: + world.included_locations.update(no_logic_trees_location_table) + + for region in overworld_regions: region.set_region_rules(world) + for region in dungeoon_regions: + region_file = region[0] + region_type = region[1] + dungeon_quest = world.dungeon_quests[region_type] + + region_file.set_region_rule(world, dungeon_quest) + # Create a dictionary mapping blue warp rewards to their vanilla items dungeon_reward_item_mapping = { @@ -306,7 +318,7 @@ def place_locked_items(world: "SohWorld") -> None: token_item_progressive = world.create_item(Items.GOLD_SKULLTULA_TOKEN, True, ItemClassification.progression_deprioritized_skip_balancing) token_item = world.create_item(Items.GOLD_SKULLTULA_TOKEN, True) - # Preplace tokens based on settings. + # Preplace tokens based on settings. if world.options.shuffle_skull_tokens == "off" or world.options.shuffle_skull_tokens == "dungeon": for location_name, address in gold_skulltula_overworld_location_table.items(): if world.vanilla_progressive_skulltula_count > 0: @@ -314,7 +326,7 @@ def place_locked_items(world: "SohWorld") -> None: world.vanilla_progressive_skulltula_count -= 1 else: world.get_location(location_name).place_locked_item(token_item) - world.get_location(location_name).address = None + world.get_location(location_name).address = None world.get_location(location_name).item.code = None if world.options.shuffle_skull_tokens == "off" or world.options.shuffle_skull_tokens == "overworld": @@ -324,5 +336,22 @@ def place_locked_items(world: "SohWorld") -> None: world.vanilla_progressive_skulltula_count -= 1 else: world.get_location(location_name).place_locked_item(token_item) - world.get_location(location_name).address = None + world.get_location(location_name).address = None world.get_location(location_name).item.code = None + + +def set_master_quest_dungeons(world: "SohWorld") -> None: + if world.options.master_quest_dungeon_settings == 1: + # Choose a random selection of a given value + target_number = world.options.master_quest_dungeon_count + dungeons = [dungeon for dungeon in Dungeons] + while target_number > 0: + dungeon = random.choice(dungeons) + world.dungeon_quest[dungeon] = DungeonQuest.MASTER_QUEST + dungeons.remove(dungeon) + target_number -= 1 + elif world.options.master_quest_dungeon_settings == 2: + # Set the dungeons to the selected quest + for dungeon in world.options.master_quest_dungeon_selection.value: + world.dungeon_quest[Dungeons.from_str(dungeon)] = DungeonQuest.MASTER_QUEST + diff --git a/worlds/oot_soh/__init__.py b/worlds/oot_soh/__init__.py index 2a07c63a863d..a2f8b3328259 100644 --- a/worlds/oot_soh/__init__.py +++ b/worlds/oot_soh/__init__.py @@ -83,6 +83,7 @@ def __init__(self, multiworld, player): self.triforce_pieces_required: int = 0 self.vanilla_progressive_skulltula_count: int = 0 self.randomized_progressive_skulltula_count: int = 0 + self.dungeon_quest: dict[Dungeons, DungeonQuest] = {dungeon: DungeonQuest.VANILLA for dungeon in Dungeons} apworld_manifest = orjson.loads(pkgutil.get_data( __name__, "archipelago.json").decode("utf-8")) @@ -123,9 +124,9 @@ def generate_early(self) -> None: # Figure out how many Skulltula tokens need to be progressive # Max amount from KAK turn ins turn_in_amount: int = 0 - + if self.options.shuffle_100_gs_reward: - turn_in_amount = 100 + turn_in_amount = 100 else: for location, amount in token_amounts.items(): if location not in self.options.exclude_locations: @@ -137,10 +138,10 @@ def generate_early(self) -> None: if self.options.shuffle_skull_tokens: self.randomized_progressive_skulltula_count = progressive_skulltula_count - + if self.options.shuffle_skull_tokens == "dungeon": self.vanilla_progressive_skulltula_count = max(self.randomized_progressive_skulltula_count - TokenCounts.OVERWORLD.value, 0) - + if self.options.shuffle_skull_tokens == "overworld": self.vanilla_progressive_skulltula_count = max(self.randomized_progressive_skulltula_count - TokenCounts.DUNGEON.value, 0) else: @@ -365,5 +366,9 @@ def fill_slot_data(self) -> dict[str, Any]: "no_logic": self.options.true_no_logic.value, "apworld_version": self.apworld_version, "enable_all_tricks": self.options.enable_all_tricks.value, - "tricks_in_logic": self.options.tricks_in_logic.value + "tricks_in_logic": self.options.tricks_in_logic.value, + "master_quest_dungeon_settings": self.options.master_quest_dungeon_settings.value, + "master_quest_dungeon_count": self.options.master_quest_dungeon_count.value, + "master_quest_dungeon_selection": self.options.master_quest_dungeon_selection.value, + "dungeon_quest": {str(dungeon): str(quest) for dungeon, quest in self.dungeon_quest.items()}, } diff --git a/worlds/oot_soh/location_access/dungeons/bottom_of_the_well.py b/worlds/oot_soh/location_access/dungeons/bottom_of_the_well.py index b322bff9246f..24660d769395 100644 --- a/worlds/oot_soh/location_access/dungeons/bottom_of_the_well.py +++ b/worlds/oot_soh/location_access/dungeons/bottom_of_the_well.py @@ -1,9 +1,26 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.BOTTOM_OF_THE_WELL_ENTRYWAY, + Regions.BOTTOM_OF_THE_WELL_PERIMETER, + Regions.BOTTOM_OF_THE_WELL_BEHIND_FAKE_WALLS, + Regions.BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, + Regions.BOTTOM_OF_THE_WELL_KEESE_BEAMOS_ROOM, + Regions.BOTTOM_OF_THE_WELL_LIKE_LIKE_CAGE, + Regions.BOTTOM_OF_THE_WELL_INNER_ROOMS, + Regions.BOTTOM_OF_THE_WELL_COFFIN_ROOM, + Regions.BOTTOM_OF_THE_WELL_DEAD_HAND_ROOM, + Regions.BOTTOM_OF_THE_WELL_BASEMENT, + Regions.BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, + Regions.BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM, +] + + class EventLocations(StrEnum): BOTTOM_OF_THE_WELL_LOWERED_WATER = "Bottom of the Well Lowered Water" BOTTOM_OF_THE_WELL_NUT_POT = "Bottom of the Well Nut Pot" @@ -282,3 +299,10 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.BOTTOM_OF_THE_WELL_BASEMENT_PLATFORM, world, [ (Regions.BOTTOM_OF_THE_WELL_BASEMENT, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/deku_tree.py b/worlds/oot_soh/location_access/dungeons/deku_tree.py index 27d533cd8606..1bbd9a8cdae5 100644 --- a/worlds/oot_soh/location_access/dungeons/deku_tree.py +++ b/worlds/oot_soh/location_access/dungeons/deku_tree.py @@ -1,9 +1,53 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions: list[Regions] = [ + Regions.DEKU_TREE_ENTRYWAY, + Regions.DEKU_TREE_LOBBY, + Regions.DEKU_TREE_2F_MIDDLE_ROOM, + Regions.DEKU_TREE_SLINGSHOT_ROOM, + Regions.DEKU_TREE_COMPASS_ROOM, + Regions.DEKU_TREE_BASEMENT_LOWER, + Regions.DEKU_TREE_BASEMENT_SCRUB_ROOM, + Regions.DEKU_TREE_BASEMENT_WATER_ROOM_FRONT, + Regions.DEKU_TREE_BASEMENT_WATER_ROOM_BACK, + Regions.DEKU_TREE_BASEMENT_TORCH_ROOM, + Regions.DEKU_TREE_BASEMENT_BACK_LOBBY, + Regions.DEKU_TREE_BASEMENT_TORCH_ROOM, + Regions.DEKU_TREE_BASEMENT_UPPER, + Regions.DEKU_TREE_OUTSIDE_BOSS_ROOM, + Regions.DEKU_TREE_BOSS_ENTRYWAY, + Regions.DEKU_TREE_BOSS_EXIT, + Regions.DEKU_TREE_BOSS_ROOM, +] + +master_quest_regions: list[Regions] = [ + Regions.DEKU_TREE_ENTRYWAY, + Regions.DEKU_TREE_MQ_1F, + Regions.DEKU_TREE_MQ_2F, + Regions.DEKU_TREE_MQ_3F, + Regions.DEKU_TREE_MQ_EYE_TARGET_ROOM, + Regions.DEKU_TREE_MQ_COMPASS_ROOM, + Regions.DEKU_TREE_MQ_PAST_BOULDER_VINES, + Regions.DEKU_TREE_MQ_BASEMENT, + Regions.DEKU_TREE_MQ_SOUTHEAST_ROOM, + Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, + Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, + Regions.DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, + Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, + Regions.DEKU_TREE_MQ_BASEMENT_BACK_ROOM, + Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, + Regions.DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, + Regions.DEKU_TREE_BOSS_ENTRYWAY, + Regions.DEKU_TREE_BOSS_EXIT, + Regions.DEKU_TREE_BOSS_ROOM, +] + + class EventLocations(StrEnum): DEKU_TREE_LOBBY_BABA_STICKS = "Deku Tree Lobby Baba Sticks", DEKU_TREE_LOBBY_BABA_NUTS = "Deku Tree Lobby Baba Nuts", @@ -18,19 +62,81 @@ class EventLocations(StrEnum): DEKU_TREE_BASEMENT_UPPER_BABA_STICKS = "Deku Tree Basement Upper Baba Sticks", DEKU_TREE_BASEMENT_UPPER_BABA_NUTS = "Deku Tree Basement Upper Baba Nuts", DEKU_TREE_BASEMENT_UPPER_BLOCK = "Deku Tree Basement Upper Push Block", + DEKU_TREE_MQ_1F_WEB = "Deku Tree MQ 1F Web", + DEKU_TREE_MQ_1F_DEKU_BABA = "Deku Tree MQ 1F Deku Baba", + DEKU_TREE_MQ_3F_DEKU_STICKS = "Deku Tree MQ 3F Deku Sticks", + DEKU_TREE_MQ_3F_DEKU_NUTS = "Deku Tree MQ 3F Deku Nuts", + DEKU_TREE_MQ_3F_WEB = "Deku Tree MQ 3F Web", + DEKU_TREE_MQ_BASEMENT_DEKU_BABA_STICKS = "Deku Tree MQ Basement Baba Sticks", + DEKU_TREE_MQ_BASEMENT_DEKU_BABA_NUTS = "Deku Tree MQ Basement Baba Nuts", + DEKU_TREE_MQ_BASEMENT_SE_ROOM = "Deku Tree MQ Basement SE Room", + DEKU_TREE_MQ_WATER_ROOM_TORCHES_FROM_FRONT = "Deku Tree MQ Water Room Torches From Front", + DEKU_TREE_MQ_WATER_ROOM_TORCHES_FROM_BACK = "Deku Tree MQ Water Room Torches From Back", + DEKU_TREE_MQ_WATER_ROOM_DEKU_BABA = "Deku Tree MQ Water Room Deku Baba", + DEKU_TREE_MQ_GRAVE_ROOM_DEKU_BABA_STICKS = "Deku Tree MQ Grave Room Baba Sticks", + DEKU_TREE_MQ_GRAVE_ROOM_DEKU_BABA_NUTS = "Deku Tree MQ Grave Room Baba Nuts", DEKU_TREE_QUEEN_GOHMA = "Deku Tree Queen Gohma" class LocalEvents(StrEnum): DEKU_TREE_BASEMENT_UPPER_BLOCK_PUSHED = "Deku Tree Basement Upper Block Pushed" + DEKU_TREE_MQ_1F_BROKE_WEB = "Deku Tree MQ 1F Broke Web" + DEKU_TREE_MQ_CLEARED_SE_ROOM = "Deku Tree MQ Cleared SE Room" + DEKU_TREE_MQ_WATER_ROOM_TORCHES = "Deku Tree MQ Water Room Torches", + + +def set_region_rules(world: "SohWorld", dungeon_quest: DungeonQuest) -> None: + connect_regions(Regions.DEKU_TREE_ENTRYWAY, world, [ + (Regions.KF_OUTSIDE_DEKU_TREE, lambda bundle: True), + ]) + + # Deku Tree boss room + # Events + add_events(Regions.DEKU_TREE_BOSS_ROOM, world, [ + (EventLocations.DEKU_TREE_QUEEN_GOHMA, Events.DEKU_TREE_COMPLETED, + lambda bundle: can_kill_enemy(bundle, Enemies.GOHMA)) + ]) + # Locations + add_locations(Regions.DEKU_TREE_BOSS_ROOM, world, [ + (Locations.QUEEN_GOHMA, lambda bundle: has_item( + Events.DEKU_TREE_COMPLETED, bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_HEART_CONTAINER, + lambda bundle: has_item(Events.DEKU_TREE_COMPLETED, bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS1, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS2, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS3, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS4, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS5, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS6, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS7, + lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS8, + lambda bundle: can_cut_shrubs(bundle)) + ]) + # Connections + connect_regions(Regions.DEKU_TREE_BOSS_ROOM, world, [ + (Regions.DEKU_TREE_BOSS_EXIT, lambda bundle: True), + (Regions.KF_OUTSIDE_DEKU_TREE, lambda bundle: has_item( + Events.DEKU_TREE_COMPLETED, bundle)) + ]) + + if dungeon_quest == DungeonQuest.VANILLA: + set_vanilla_rules(world) + else: + set_master_quest_rules(world) -def set_region_rules(world: "SohWorld") -> None: +def set_vanilla_rules(world: "SohWorld") -> None: # Deku Tree Entryway # Connections connect_regions(Regions.DEKU_TREE_ENTRYWAY, world, [ (Regions.DEKU_TREE_LOBBY, lambda bundle: True), - (Regions.KF_OUTSIDE_DEKU_TREE, lambda bundle: True) ]) # Deku Lobby @@ -280,14 +386,6 @@ def set_region_rules(world: "SohWorld") -> None: and can_reflect_nuts(bundle)) ]) - # Skipping master quest for now - - # Deku Boss room entryway - # Connections - connect_regions(Regions.DEKU_TREE_BOSS_ENTRYWAY, world, [ - (Regions.DEKU_TREE_BOSS_ROOM, lambda bundle: True) - ]) - # Deku boss exit # Connections connect_regions(Regions.DEKU_TREE_BOSS_EXIT, world, [ @@ -295,38 +393,291 @@ def set_region_rules(world: "SohWorld") -> None: # skipping mq connection ]) - # Deku Tree boss room + +def set_master_quest_rules(world: "SohWorld") -> None: + # Deku Tree Entryway + # Connections + connect_regions(Regions.DEKU_TREE_ENTRYWAY, world, [ + (Regions.DEKU_TREE_MQ_1F, lambda bundle: True), + ]) + + # Deku Tree MQ 1F # Events - add_events(Regions.DEKU_TREE_BOSS_ROOM, world, [ - (EventLocations.DEKU_TREE_QUEEN_GOHMA, Events.DEKU_TREE_COMPLETED, - lambda bundle: can_kill_enemy(bundle, Enemies.GOHMA)) + add_events(Regions.DEKU_TREE_MQ_1F, world, [ + (EventLocations.DEKU_TREE_MQ_1F_DEKU_BABA, Events.CAN_FARM_STICKS, lambda bundle: can_kill_enemy(bundle, Enemies.WITHERED_DEKU_BABA)), + (EventLocations.DEKU_TREE_MQ_1F_WEB, LocalEvents.DEKU_TREE_MQ_1F_BROKE_WEB, lambda bundle: has_fire_source(bundle)), ]) # Locations - add_locations(Regions.DEKU_TREE_BOSS_ROOM, world, [ - (Locations.QUEEN_GOHMA, lambda bundle: has_item( - Events.DEKU_TREE_COMPLETED, bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_HEART_CONTAINER, - lambda bundle: has_item(Events.DEKU_TREE_COMPLETED, bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS1, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS2, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS3, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS4, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS5, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS6, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS7, - lambda bundle: can_cut_shrubs(bundle)), - (Locations.DEKU_TREE_QUEEN_GOHMA_GRASS8, - lambda bundle: can_cut_shrubs(bundle)) + add_locations(Regions.DEKU_TREE_MQ_1F, world, [ + (Locations.DEKU_TREE_MQ_LOBBY_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LOBBY_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LOBBY_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LOBBY_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LOBBY_GRASS5, lambda bundle: can_cut_shrubs(bundle)), ]) # Connections - connect_regions(Regions.DEKU_TREE_BOSS_ROOM, world, [ - (Regions.DEKU_TREE_BOSS_EXIT, lambda bundle: True), - (Regions.KF_OUTSIDE_DEKU_TREE, lambda bundle: has_item( - Events.DEKU_TREE_COMPLETED, bundle)) + connect_regions(Regions.DEKU_TREE_MQ_1F, world, [ + (Regions.DEKU_TREE_ENTRYWAY, lambda bundle: True), + (Regions.DEKU_TREE_MQ_2F, lambda bundle: True), + (Regions.DEKU_TREE_MQ_BASEMENT, lambda bundle: has_item(LocalEvents.DEKU_TREE_MQ_1F_BROKE_WEB, bundle)), ]) + + # Deku Tree MQ 2F + # Locations + add_locations(Regions.DEKU_TREE_MQ_2F, world, [ + (Locations.DEKU_TREE_MQ_MAP_CHEST, lambda bundle: True), + (Locations.DEKU_TREE_MQ_GS_LOBBY, lambda bundle: can_get_enemy_drop(bundle, Enemies.GOLD_SKULLTULA)), + (Locations.DEKU_TREE_MQ_LOBBY_HEART, lambda bundle: True), + (Locations.DEKU_TREE_MQ_LOBBY_GRASS6, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LOBBY_GRASS7, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LOBBY_HEART, lambda bundle: can_break_crates(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_2F, world, [ + (Regions.DEKU_TREE_MQ_1F, lambda bundle: True), + (Regions.DEKU_TREE_MQ_3F, lambda bundle: True), + (Regions.DEKU_TREE_MQ_EYE_TARGET_ROOM, lambda bundle: has_fire_source(bundle)), + ]) + + # Deku Tree MQ 3F + # Events + add_events(Regions.DEKU_TREE_MQ_3F, world, [ + (EventLocations.DEKU_TREE_MQ_3F_DEKU_STICKS, Events.CAN_FARM_STICKS, lambda bundle: can_get_deku_baba_sticks(bundle)), + (EventLocations.DEKU_TREE_MQ_3F_DEKU_NUTS, Events.CAN_FARM_NUTS, lambda bundle: can_get_deku_baba_nuts(bundle)), + (EventLocations.DEKU_TREE_MQ_3F_WEB, LocalEvents.DEKU_TREE_MQ_1F_BROKE_WEB, lambda bundle: True), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_3F, world, [ + (Locations.DEKU_TREE_MQ_SLINGSHOT_CHEST, lambda bundle: can_kill_enemy(bundle, Enemies.DEKU_BABA)), + (Locations.DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, lambda bundle: has_fire_source_with_torch(bundle) or (is_adult(bundle) and can_use(Items.FAIRY_BOW, bundle))), + (Locations.DEKU_TREE_MQ_SLINGSHOT_ROOM_HEART, lambda bundle: True), + (Locations.DEKU_TREE_MQ_SLINGSHOT_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SLINGSHOT_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SLINGSHOT_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SLINGSHOT_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SLINGSHOT_ROOM_CRATE1, lambda bundle: can_break_crates(bundle)), + (Locations.DEKU_TREE_MQ_SLINGSHOT_ROOM_CRATE2, lambda bundle: can_break_crates(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_3F, world, [ + (Regions.DEKU_TREE_MQ_2F, lambda bundle: True), + (Regions.DEKU_TREE_MQ_EYE_TARGET_ROOM, lambda bundle: can_use(Items.STICKS, bundle) or can_use(Items.FAIRY_BOW, bundle)), + (Regions.DEKU_TREE_MQ_BASEMENT, lambda bundle: True), + ]) + + # Deku Tree MQ Eye Target Room + # Locations + add_locations(Regions.DEKU_TREE_MQ_EYE_TARGET_ROOM, world, [ + (Locations.DEKU_TREE_MQ_DEKU_BABA_HEART, lambda bundle: True), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS5, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS6, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_COMPASS_GRASS7, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_EYE_TARGET_ROOM, world, [ + (Regions.DEKU_TREE_MQ_COMPASS_ROOM, lambda bundle: can_hit_eye_targets(bundle)), + (Regions.DEKU_TREE_MQ_2F, lambda bundle: True), + ]) + + # Deku Tree MQ Compass Room + # Locations + add_locations(Regions.DEKU_TREE_MQ_COMPASS_ROOM, world, [ + (Locations.DEKU_TREE_MQ_COMPASS_CHEST, lambda bundle: True), + (Locations.DEKU_TREE_MQ_COMPASS_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_COMPASS_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_COMPASS_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_COMPASS_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_COMPASS_ROOM, world, [ + (Regions.DEKU_TREE_MQ_EYE_TARGET_ROOM, lambda bundle: can_use(Items.FAIRY_SLINGSHOT, bundle) or can_use(Items.HOVER_BOOTS, bundle)), + (Regions.DEKU_TREE_MQ_PAST_BOULDER_VINES, lambda bundle: can_use(Items.BOMBCHUS_5, bundle) or (can_use(Items.BOMB_BAG, bundle) and (can_use(Items.SONG_OF_TIME, bundle) or is_adult(bundle) or can_use(Items.HOVER_BOOTS, bundle))) or (can_use(Items.MEGATON_HAMMER, bundle) and (can_use(Items.SONG_OF_TIME, bundle) or can_do_trick(Tricks.DEKU_MQ_COMPASS_GS, bundle)))), + ]) + + # Deku Tree MQ Past Boulder Vines + # Locations + add_locations(Regions.DEKU_TREE_MQ_PAST_BOULDER_VINES, world, [ + (Locations.DEKU_TREE_MQ_GS_PAST_BOULDER_VINES, lambda bundle: can_get_enemy_drop(bundle, Enemies.GOLD_SKULLTULA, EnemyDistance.BOOMERANG)), + (Locations.DEKU_TREE_MQ_COMPASS_ROOM_HEART, lambda bundle: True), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_PAST_BOULDER_VINES, world, [ + (Regions.DEKU_TREE_MQ_COMPASS_ROOM, lambda bundle: blast_or_smash(bundle)), + ]) + + # Deku Tree MQ Basement + # Events + add_events(Regions.DEKU_TREE_MQ_BASEMENT, world, [ + (EventLocations.DEKU_TREE_MQ_BASEMENT_DEKU_BABA_STICKS, Events.CAN_FARM_STICKS, lambda bundle: can_get_deku_baba_sticks(bundle)), + (EventLocations.DEKU_TREE_MQ_BASEMENT_DEKU_BABA_NUTS, Events.CAN_FARM_NUTS, lambda bundle: can_get_deku_baba_nuts(bundle)), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT, world, [ + (Locations.DEKU_TREE_MQ_BASEMENT_CHEST, lambda bundle: has_fire_source_with_torch(bundle) or can_use(Items.FAIRY_BOW, bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_LOWER_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_LOWER_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_LOWER_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_LOWER_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT, world, [ + (Regions.DEKU_TREE_MQ_1F, lambda bundle: True), + (Regions.DEKU_TREE_MQ_SOUTHEAST_ROOM, lambda bundle: can_hit_eye_targets(bundle)), + (Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, lambda bundle: can_hit_eye_targets(bundle) and has_item(LocalEvents.DEKU_TREE_MQ_CLEARED_SE_ROOM, bundle) and can_use(Items.STICKS, bundle)), + (Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, lambda bundle: is_adult(bundle) or can_do_trick(Tricks.DEKU_B1_SKIP, bundle) or can_ground_jump(bundle) or has_item(LocalEvents.DEKU_TREE_BASEMENT_UPPER_BLOCK_PUSHED, bundle) or can_use(Items.HOVER_BOOTS, bundle)), + ]) + + # Deku Tree MQ Southeast Room + # Events + add_events(Regions.DEKU_TREE_MQ_SOUTHEAST_ROOM, world, [ + (EventLocations.DEKU_TREE_MQ_BASEMENT_SE_ROOM, LocalEvents.DEKU_TREE_MQ_CLEARED_SE_ROOM, lambda bundle: can_kill_enemy(bundle, Enemies.MAD_SCRUB)), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT, world, [ + (Locations.DEKU_TREE_MQ_TORCHES_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_TORCHES_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_TORCHES_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_TORCHES_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_SOUTHEAST_ROOM, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, lambda bundle: has_fire_source(bundle)), + (Regions.DEKU_TREE_MQ_BASEMENT, lambda bundle: has_item(LocalEvents.DEKU_TREE_MQ_CLEARED_SE_ROOM, bundle)), + ]) + + # Deku Tree MQ Basement Water Room Front + # Events + add_events(Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, world, [ + (EventLocations.DEKU_TREE_MQ_WATER_ROOM_TORCHES_FROM_FRONT, LocalEvents.DEKU_TREE_MQ_WATER_ROOM_TORCHES, lambda bundle: can_use(Items.FIRE_ARROW, bundle) or (can_use(Items.STICKS, bundle) and (can_do_trick(Tricks.DEKU_MQ_LOG, bundle) or (is_child(bundle) and can_shield(bundle))))), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, world, [ + (Locations.DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, lambda bundle: True), + (Locations.DEKU_TREE_MQ_SPIKE_ROLLER_FRONT_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SPIKE_ROLLER_FRONT_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SPIKE_ROLLER_FRONT_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, lambda bundle: can_do_trick(Tricks.DEKU_MQ_LOG, bundle) or (is_child(bundle) and can_shield(bundle)) or can_use(Items.LONGSHOT, bundle) or (can_use(Items.HOOKSHOT, bundle) and can_use(Items.IRON_BOOTS, bundle))), + (Regions.DEKU_TREE_MQ_SOUTHEAST_ROOM, lambda bundle: True), + ]) + + # Deku Tree MQ Basement Water Room Back + # Events + add_events(Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, world, [ + (EventLocations.DEKU_TREE_MQ_WATER_ROOM_DEKU_BABA, Events.CAN_FARM_STICKS, lambda bundle: can_kill_enemy(bundle, Enemies.WITHERED_DEKU_BABA)), + (EventLocations.DEKU_TREE_MQ_WATER_ROOM_TORCHES_FROM_BACK, LocalEvents.DEKU_TREE_MQ_WATER_ROOM_TORCHES, lambda bundle: has_fire_source(bundle)), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, world, [ + (Locations.DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, lambda bundle: can_use(Items.SONG_OF_STORMS, bundle) and can_pass_enemy(bundle, Enemies.BIG_SKULLTULA)), + (Locations.DEKU_TREE_MQ_SPIKE_ROLLER_BACK_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_SPIKE_ROLLER_BACK_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, lambda bundle: has_item(LocalEvents.DEKU_TREE_MQ_WATER_ROOM_TORCHES, bundle) and can_pass_enemy(bundle, Enemies.BIG_SKULLTULA, EnemyDistance.CLOSE if can_use(Items.SONG_OF_TIME, bundle) else EnemyDistance.SHORT_JUMPSLASH)), + (Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, lambda bundle: can_do_trick(Tricks.DEKU_MQ_LOG, bundle) or (is_child(bundle) and can_shield(bundle)) or can_use(Items.LONGSHOT, bundle) or has_item(Items.BRONZE_SCALE, bundle) or (can_use(Items.IRON_BOOTS, bundle) and (is_adult(bundle) or can_use(Items.HOOKSHOT, bundle)))), + ]) + + # Deku Tree MQ Basement Southwest Room + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, world, [ + (Locations.DEKU_TREE_MQ_LARVAE_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_LARVAE_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, lambda bundle: can_kill_enemy(bundle, Enemies.MAD_SCRUB) and can_kill_enemy(bundle, Enemies.KEESE)), + (Regions.DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, lambda bundle: can_kill_enemy(bundle, Enemies.MAD_SCRUB) and can_kill_enemy(bundle, Enemies.KEESE)), + ]) + + # Deku Tree MQ Basement Grave Room + # Events + add_events(Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, world, [ + (EventLocations.DEKU_TREE_MQ_GRAVE_ROOM_DEKU_BABA_STICKS, Events.CAN_FARM_STICKS, lambda bundle: can_get_deku_baba_sticks(bundle)), + (EventLocations.DEKU_TREE_MQ_GRAVE_ROOM_DEKU_BABA_NUTS, Events.CAN_FARM_NUTS, lambda bundle: can_get_deku_baba_nuts(bundle)), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, world, [ + (Locations.DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, lambda bundle: can_use(Items.LONGSHOT, bundle) or (can_use(Items.SONG_OF_TIME, bundle) and can_get_enemy_drop(bundle, Enemies.GOLD_SKULLTULA, EnemyDistance.BOOMERANG))), + (Locations.DEKU_TREE_MQ_GRAVES_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_GRAVES_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_GRAVES_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_GRAVES_GRASS4, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_GRAVES_GRASS5, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, lambda bundle: is_child(bundle) and (has_fire_source_with_torch(bundle) or can_use(Items.FAIRY_BOW, bundle))), + (Regions.DEKU_TREE_MQ_BASEMENT_SOUTHWEST_ROOM, lambda bundle: True), + (Regions.DEKU_TREE_MQ_BASEMENT_BACK_ROOM, lambda bundle: has_fire_source_with_torch(bundle) or can_use(Items.FAIRY_BOW, bundle)), + ]) + + # Deku Tree MQ Basement Back Room + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT_BACK_ROOM, world, [ + (Locations.DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, lambda bundle: can_get_enemy_drop(bundle, Enemies.GOLD_SKULLTULA, EnemyDistance.BOOMERANG)), + (Locations.DEKU_TREE_MQ_BACK_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BACK_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BACK_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT_BACK_ROOM, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, lambda bundle: True), + ]) + + # Deku Tree Basement Ledge + # Events + add_events(Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, world, [ + (EventLocations.DEKU_TREE_BASEMENT_UPPER_BLOCK, LocalEvents.DEKU_TREE_BASEMENT_UPPER_BLOCK_PUSHED, lambda bundle: True), + ]) + # Locations + add_locations(Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, world, [ + (Locations.DEKU_TREE_MQ_DEKU_SCRUB, lambda bundle: can_stun_deku(bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_UPPER_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_UPPER_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BASEMENT_UPPER_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + ]) + connect_regions(Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_GRAVE_ROOM, lambda bundle: is_child(bundle)), + (Regions.DEKU_TREE_MQ_BASEMENT, lambda bundle: True), + (Regions.DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, lambda bundle: (has_fire_source(bundle) or can_use(Items.STICKS, bundle)) and (has_item(Items.BRONZE_SCALE, bundle) or can_use(Items.IRON_BOOTS, bundle))), + ]) + + # Deku Tree MQ Outside Boss Room + # Locations + add_locations(Regions.DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, world, [ + (Locations.DEKU_TREE_MQ_FINAL_ROOM_LEFT_FRONT_HEART, lambda bundle: has_item(Items.BRONZE_SCALE, bundle) or can_use(Items.IRON_BOOTS, bundle) or can_use(Items.BOOMERANG, bundle)), + (Locations.DEKU_TREE_MQ_FINAL_ROOM_LEFT_BACK_HEART, + lambda bundle: has_item(Items.BRONZE_SCALE, bundle) or can_use(Items.IRON_BOOTS, bundle) or can_use( + Items.BOOMERANG, bundle)), + (Locations.DEKU_TREE_MQ_FINAL_ROOM_RIGHT_HEART, lambda bundle: has_item(Items.BRONZE_SCALE, bundle) or can_use(Items.IRON_BOOTS, bundle) or can_use(Items.BOOMERANG, bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_BOSS_GRASS1, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_BOSS_GRASS2, lambda bundle: can_cut_shrubs(bundle)), + (Locations.DEKU_TREE_MQ_BEFORE_BOSS_GRASS3, lambda bundle: can_cut_shrubs(bundle)), + ]) + # Connections + connect_regions(Regions.DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, world, [ + (Regions.DEKU_TREE_MQ_BASEMENT_LEDGE, lambda bundle: has_item(Items.BRONZE_SCALE, bundle) or can_use(Items.HOOKSHOT, bundle)), + (Regions.DEKU_TREE_BOSS_ENTRYWAY, lambda bundle: can_reflect_nuts(bundle)), + ]) + + # Deku boss exit + # Connections + connect_regions(Regions.DEKU_TREE_BOSS_EXIT, world, [ + (Regions.DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, lambda bundle: True), + # skipping mq connection + ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + regions = vanilla_regions if dungeon_quest == DungeonQuest.VANILLA else master_quest_regions + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/dodongos_cavern.py b/worlds/oot_soh/location_access/dungeons/dodongos_cavern.py index bf93b67b0714..6e2312cf6ec2 100644 --- a/worlds/oot_soh/location_access/dungeons/dodongos_cavern.py +++ b/worlds/oot_soh/location_access/dungeons/dodongos_cavern.py @@ -1,9 +1,42 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.DODONGOS_CAVERN_ENTRYWAY, + Regions.DODONGOS_CAVERN_BEGINNING, + Regions.DODONGOS_CAVERN_LOBBY, + Regions.DODONGOS_CAVERN_LOBBY_SWITCH, + Regions.DODONGOS_CAVERN_SE_CORRIDOR, + Regions.DODONGOS_CAVERN_SE_ROOM, + Regions.DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, + Regions.DODONGOS_CAVERN_LOWER_LIZALFOS, + Regions.DODONGOS_CAVERN_LOWER_LIZALFOS_LOCATIONS, + Regions.DODONGOS_CAVERN_DODONGO_ROOM, + Regions.DODONGOS_CAVERN_NEAR_DODONGO_ROOM, + Regions.DODONGOS_CAVERN_STAIRS_LOWER, + Regions.DODONGOS_CAVERN_STAIRS_UPPER, + Regions.DODONGOS_CAVERN_VINES_ABOVE_STAIRS_GS, + Regions.DODONGOS_CAVERN_COMPASS_ROOM, + Regions.DODONGOS_CAVERN_ARMOS_ROOM, + Regions.DODONGOS_CAVERN_BOMB_ROOM_LOWER, + Regions.DODONGOS_CAVERN_2F_SIDE_ROOM, + Regions.DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, + Regions.DODONGOS_CAVERN_UPPER_LIZALFOS, + Regions.DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, + Regions.DODONGOS_CAVERN_BOMB_ROOM_UPPER, + Regions.DODONGOS_CAVERN_FAR_BRIDGE, + Regions.DODONGOS_CAVERN_BOSS_REGION, + Regions.DODONGOS_CAVERN_BACK_ROOM, + Regions.DODONGOS_CAVERN_BOSS_ENTRYWAY, + Regions.DODONGOS_CAVERN_BOSS_EXIT, + Regions.DODONGOS_CAVERN_BOSS_ROOM, +] + + class EventLocations(StrEnum): DODONGOS_CAVERN_GOSSIP_STONE_SONG_FAIRY = "Dodongos Cavern Gossip Stone Song Fairy" DODONGOS_CAVERN_LOBBY_SWITCH = "Dodongos Cavern Lobby Switch", @@ -455,3 +488,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.DEATH_MOUNTAIN_TRAIL, lambda bundle: has_item( Events.DODONGOS_CAVERN_COMPLETED, bundle)), ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/fire_temple.py b/worlds/oot_soh/location_access/dungeons/fire_temple.py index bc3a5f927416..a3187bd30438 100644 --- a/worlds/oot_soh/location_access/dungeons/fire_temple.py +++ b/worlds/oot_soh/location_access/dungeons/fire_temple.py @@ -1,9 +1,52 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.FIRE_TEMPLE_ENTRYWAY, + Regions.FIRE_TEMPLE_FIRST_ROOM, + Regions.FIRE_TEMPLE_NEAR_BOSS_ROOM, + Regions.FIRE_TEMPLE_LOOP_ENEMIES, + Regions.FIRE_TEMPLE_LOOP_TILES, + Regions.FIRE_TEMPLE_LOOP_FLARE_DANCER, + Regions.FIRE_TEMPLE_LOOP_HAMMER_SWITCH, + Regions.FIRE_TEMPLE_LOOP_GORON_ROOM, + Regions.FIRE_TEMPLE_LOOP_EXIT, + Regions.FIRE_TEMPLE_BIG_LAVA_ROOM, + Regions.FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, + Regions.FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, + Regions.FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, + Regions.FIRE_TEMPLE_FIRE_PILLAR_ROOM, + Regions.FIRE_TEMPLE_SHORTCUT_ROOM, + Regions.FIRE_TEMPLE_SHORTCUT_CLIMB, + Regions.FIRE_TEMPLE_BOULDER_MAZE_LOWER, + Regions.FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM, + Regions.FIRE_TEMPLE_EAST_CENTRAL_ROOM, + Regions.FIRE_TEMPLE_FIRE_WALL_CHASE, + Regions.FIRE_TEMPLE_MAP_REGION, + Regions.FIRE_TEMPLE_BOULDER_MAZE_UPPER, + Regions.FIRE_TEMPLE_SCARECROW_ROOM, + Regions.FIRE_TEMPLE_EAST_PEAK, + Regions.FIRE_TEMPLE_CORRIDOR, + Regions.FIRE_TEMPLE_FIRE_MAZE_ROOM, + Regions.FIRE_TEMPLE_FIRE_MAZE_UPPER, + Regions.FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, + Regions.FIRE_TEMPLE_WEST_CENTRAL_LOWER, + Regions.FIRE_TEMPLE_WEST_CENTRAL_UPPER, + Regions.FIRE_TEMPLE_LATE_FIRE_MAZE, + Regions.FIRE_TEMPLE_UPPER_FLARE_DANCER, + Regions.FIRE_TEMPLE_WEST_CLIMB, + Regions.FIRE_TEMPLE_WEST_PEAK, + Regions.FIRE_TEMPLE_HAMMER_RETURN_PATH, + Regions.FIRE_TEMPLE_ABOVE_FIRE_MAZE, + Regions.FIRE_TEMPLE_BOSS_ENTRYWAY, + Regions.FIRE_TEMPLE_BOSS_ROOM, +] + + class EventLocations(StrEnum): FIRE_TEMPLE_NEAR_BOSS_ROOM_FAIRY_POT = "Fire Temple Near Boss Room Fairy Pot" FIRE_TEMPLE_LOOP_HAMMER_SWITCH_ROOM_SWITCH = "Fire Temple Loop Hammer Switch Room Switch" @@ -556,3 +599,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.DMC_CENTRAL_LOCAL, lambda bundle: has_item( Events.FIRE_TEMPLE_COMPLETED, bundle)) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/forest_temple.py b/worlds/oot_soh/location_access/dungeons/forest_temple.py index 86a8548042c1..3be827d42290 100644 --- a/worlds/oot_soh/location_access/dungeons/forest_temple.py +++ b/worlds/oot_soh/location_access/dungeons/forest_temple.py @@ -1,9 +1,48 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.FOREST_TEMPLE_ENTRYWAY, + Regions.FOREST_TEMPLE_FIRST_ROOM, + Regions.FOREST_TEMPLE_SOUTH_CORRIDOR, + Regions.FOREST_TEMPLE_LOBBY, + Regions.FOREST_TEMPLE_NORTH_CORRIDOR, + Regions.FOREST_TEMPLE_LOWER_STALFOS, + Regions.FOREST_TEMPLE_NW_OUTDOORS_LOWER, + Regions.FOREST_TEMPLE_NW_OUTDOORS_UPPER, + Regions.FOREST_TEMPLE_NW_COURTYARD_HEARTS, + Regions.FOREST_TEMPLE_NW_COURTYARD_SKULLTULA_ISLAND, + Regions.FOREST_TEMPLE_NE_OUTDOORS_LOWER, + Regions.FOREST_TEMPLE_NE_OUTDOORS_UPPER, + Regions.FOREST_TEMPLE_NE_COURTYARD_SKULLTULA_ISLAND, + Regions.FOREST_TEMPLE_NE_COURTYARD_SKULLTULA_ISLAND_GS, + Regions.FOREST_TEMPLE_MAP_ROOM, + Regions.FOREST_TEMPLE_WELL, + Regions.FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, + Regions.FOREST_TEMPLE_FLOORMASTER_ROOM, + Regions.FOREST_TEMPLE_WEST_CORRIDOR, + Regions.FOREST_TEMPLE_BLOCK_PUSH_ROOM, + Regions.FOREST_TEMPLE_NW_CORRIDOR_TWISTED, + Regions.FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, + Regions.FOREST_TEMPLE_RED_POE_ROOM, + Regions.FOREST_TEMPLE_UPPER_STALFOS, + Regions.FOREST_TEMPLE_BLUE_POE_ROOM, + Regions.FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, + Regions.FOREST_TEMPLE_NE_CORRIDOR_TWISTED, + Regions.FOREST_TEMPLE_FROZEN_EYE_ROOM, + Regions.FOREST_TEMPLE_FALLING_ROOM, + Regions.FOREST_TEMPLE_GREEN_POE_ROOM, + Regions.FOREST_TEMPLE_EAST_CORRIDOR, + Regions.FOREST_TEMPLE_BOSS_REGION, + Regions.FOREST_TEMPLE_BOSS_ENTRYWAY, + Regions.FOREST_TEMPLE_BOSS_ROOM +] + + class EventLocations(StrEnum): FOREST_TEMPLE_MEG = "Forest Temple Meg" FOREST_TEMPLE_JOELLE = "Forest Temple Joelle" @@ -541,3 +580,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.SACRED_FOREST_MEADOW, lambda bundle: has_item( Events.FOREST_TEMPLE_COMPLETED, bundle)) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/ganons_castle.py b/worlds/oot_soh/location_access/dungeons/ganons_castle.py index c96d9905a74c..a505c5433ad0 100644 --- a/worlds/oot_soh/location_access/dungeons/ganons_castle.py +++ b/worlds/oot_soh/location_access/dungeons/ganons_castle.py @@ -1,9 +1,31 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.GANONS_CASTLE_ENTRYWAY, + Regions.GANONS_CASTLE_LOBBY, + Regions.GANONS_CASTLE_DEKU_SCRUBS, + Regions.GANONS_CASTLE_FOREST_TRIAL, + Regions.GANONS_CASTLE_FIRE_TRIAL, + Regions.GANONS_CASTLE_WATER_TRIAL, + Regions.GANONS_CASTLE_SHADOW_TRIAL, + Regions.GANONS_CASTLE_SPIRIT_TRIAL, + Regions.GANONS_CASTLE_LIGHT_TRIAL, + Regions.GANONS_TOWER_ENTRYWAY, + Regions.GANONS_TOWER_FLOOR_1, + Regions.GANONS_TOWER_FLOOR_2, + Regions.GANONS_TOWER_FLOOR_3, + Regions.GANONS_TOWER_BEFORE_GANONDORFS_LAIR, + Regions.GANONDORFS_LAIR, + Regions.GANONS_CASTLE_ESCAPE, + Regions.GANONS_ARENA, +] + + class EventLocations(StrEnum): GANONS_CASTLE_FREE_FAIRIES = "Ganon's Castle Free Fairies" GANONS_CASTLE_FOREST_TRIAL_AREA = "Ganon's Castle Forest Trial Area" @@ -389,3 +411,10 @@ def set_region_rules(world: "SohWorld") -> None: (EventLocations.GANON_DEFEATED, Events.GAME_COMPLETED, lambda bundle: (can_kill_enemy(bundle, Enemies.GANON))) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/gerudo_training_ground.py b/worlds/oot_soh/location_access/dungeons/gerudo_training_ground.py index 400913076c01..4bb6dd7eb327 100644 --- a/worlds/oot_soh/location_access/dungeons/gerudo_training_ground.py +++ b/worlds/oot_soh/location_access/dungeons/gerudo_training_ground.py @@ -1,9 +1,24 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.GERUDO_TRAINING_GROUND_ENTRYWAY, + Regions.GERUDO_TRAINING_GROUND_LOBBY, + Regions.GERUDO_TRAINING_GROUND_CENTRAL_MAZE, + Regions.GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, + Regions.GERUDO_TRAINING_GROUND_LAVA_ROOM, + Regions.GERUDO_TRAINING_GROUND_HAMMER_ROOM, + Regions.GERUDO_TRAINING_GROUND_EYE_STATUE_LOWER, + Regions.GERUDO_TRAINING_GROUND_EYE_STATUE_UPPER, + Regions.GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM, + Regions.GERUDO_TRAINING_GROUND_LIKE_LIKE_ROOM, +] + + def set_region_rules(world: "SohWorld") -> None: # Gerudo Training Ground Entryway # Connections @@ -161,3 +176,10 @@ def set_region_rules(world: "SohWorld") -> None: (Locations.GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, lambda bundle: can_jump_slash_except_hammer(bundle)), ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/ice_cavern.py b/worlds/oot_soh/location_access/dungeons/ice_cavern.py index 9c85c02ccf4a..8c99d682e28f 100644 --- a/worlds/oot_soh/location_access/dungeons/ice_cavern.py +++ b/worlds/oot_soh/location_access/dungeons/ice_cavern.py @@ -1,9 +1,24 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.ICE_CAVERN_ENTRYWAY, + Regions.ICE_CAVERN_BEGINNING, + Regions.ICE_CAVERN_HUB, + Regions.ICE_CAVERN_MAP_ROOM, + Regions.ICE_CAVERN_COMPASS_ROOM, + Regions.ICE_CAVERN_BLOCK_ROOM, + Regions.ICE_CAVERN_BEFORE_FINAL_ROOM, + Regions.ICE_CAVERN_FINAL_ROOM, + Regions.ICE_CAVERN_FINAL_ROOM_UNDERWATER, + Regions.ICE_CAVERN_ABOVE_BEGINNING, +] + + class EventLocations(StrEnum): ICE_CAVERN_MAP_ROOM_BLUE_FIRE_ACCESS = "Ice Cavern Map Room Blue Fire Access" ICE_CAVERN_COMPASS_ROOM_BLUE_FIRE_ACCESS = "Ice Cavern Compass Room Blue Fire Access" @@ -169,3 +184,10 @@ def set_region_rules(world: "SohWorld") -> None: lambda bundle: can_use(Items.IRON_BOOTS, bundle)), (Regions.ICE_CAVERN_BEGINNING, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/jabujabus_belly.py b/worlds/oot_soh/location_access/dungeons/jabujabus_belly.py index fcc01392fe5d..dd8367dc6328 100644 --- a/worlds/oot_soh/location_access/dungeons/jabujabus_belly.py +++ b/worlds/oot_soh/location_access/dungeons/jabujabus_belly.py @@ -1,9 +1,30 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.JABU_JABUS_BELLY_ENTRYWAY, + Regions.JABU_JABUS_BELLY_BEGINNING, + Regions.JABU_JABUS_BELLY_MAIN, + Regions.JABU_JABUS_BELLY_B1_NORTH, + Regions.JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, + Regions.JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, + Regions.JABU_JABUS_BELLY_COMPASS_ROOM, + Regions.JABU_JABUS_BELLY_BLUE_TENTACLE, + Regions.JABU_JABUS_BELLY_GREEN_TENTACLE, + Regions.JABU_JABUS_BELLY_LOBBY_BASEMENT_UPPER_GS, + Regions.JABU_JABUS_BELLY_BIGOCTO_LEDGE, + Regions.JABU_JABUS_BELLY_ABOVE_BIGOCTO, + Regions.JABU_JABUS_BELLY_LIFT_UPPER, + Regions.JABU_JABUS_BELLY_NEAR_BOSS_ROOM, + Regions.JABU_JABUS_BELLY_BOSS_ENTRYWAY, + Regions.JABU_JABUS_BELLY_BOSS_ROOM, +] + + class EventLocations(StrEnum): JABU_JABUS_BELLY_WEST_TENTACLE = "Jabu Jabus Belly West Tentacle" JABU_JABUS_BELLY_EAST_TENTACLE = "Jabu Jabus Belly East Tentacle" @@ -294,3 +315,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.ZORAS_FOUNTAIN, lambda bundle: has_item( Events.JABU_JABUS_BELLY_COMPLETED, bundle)) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/shadow_temple.py b/worlds/oot_soh/location_access/dungeons/shadow_temple.py index f31a86e78ab8..efa68210deb5 100644 --- a/worlds/oot_soh/location_access/dungeons/shadow_temple.py +++ b/worlds/oot_soh/location_access/dungeons/shadow_temple.py @@ -1,9 +1,22 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.SHADOW_TEMPLE_ENTRYWAY, + Regions.SHADOW_TEMPLE_BEGINNING, + Regions.SHADOW_TEMPLE_FIRST_BEAMOS, + Regions.SHADOW_TEMPLE_HUGE_PIT, + Regions.SHADOW_TEMPLE_WIND_TUNNEL, + Regions.SHADOW_TEMPLE_BEYOND_BOAT, + Regions.SHADOW_TEMPLE_BOSS_ENTRYWAY, + Regions.SHADOW_TEMPLE_BOSS_ROOM, +] + + class EventLocations(StrEnum): SHADOW_TEMPLE_BEGINNING_NUT_POT = "Shadow Temple Beginning Nut Pot" SHADOW_TEMPLE_FAIRY_POT = "Shadow Temple Fairy Pot" @@ -208,3 +221,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.GRAVEYARD_WARP_PAD_REGION, lambda bundle: has_item( Events.SHADOW_TEMPLE_COMPLETED, bundle)) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/spirit_temple.py b/worlds/oot_soh/location_access/dungeons/spirit_temple.py index c03e244ee36d..9d664dc08dce 100644 --- a/worlds/oot_soh/location_access/dungeons/spirit_temple.py +++ b/worlds/oot_soh/location_access/dungeons/spirit_temple.py @@ -1,9 +1,26 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_regions = [ + Regions.SPIRIT_TEMPLE_ENTRYWAY, + Regions.SPIRIT_TEMPLE_LOBBY, + Regions.SPIRIT_TEMPLE_CHILD, + Regions.SPIRIT_TEMPLE_CHILD_CLIMB, + Regions.SPIRIT_TEMPLE_EARLY_ADULT, + Regions.SPIRIT_TEMPLE_CENTRAL_CHAMBER, + Regions.SPIRIT_TEMPLE_OUTDOOR_HANDS, + Regions.SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, + Regions.SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, + Regions.SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, + Regions.SPIRIT_TEMPLE_BOSS_ENTRYWAY, + Regions.SPIRIT_TEMPLE_BOSS_ROOM, +] + + class EventLocations(StrEnum): SPIRIT_TEMPLE_BEGINNING_NUT_CRATE = "Spirit Temple Nut Crate" SPIRIT_TEMPLE_TWINROVA = "Spirit Temple Twinrova" @@ -233,3 +250,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.DESERT_COLOSSUS, lambda bundle: has_item( Events.SPIRIT_TEMPLE_COMPLETED, bundle)) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/dungeons/water_temple.py b/worlds/oot_soh/location_access/dungeons/water_temple.py index aba8ea48f3d8..c7c9038ee03d 100644 --- a/worlds/oot_soh/location_access/dungeons/water_temple.py +++ b/worlds/oot_soh/location_access/dungeons/water_temple.py @@ -1,9 +1,46 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +vanilla_dungeons = [ + Regions.WATER_TEMPLE_ENTRYWAY, + Regions.WATER_TEMPLE_LOBBY, + Regions.WATER_TEMPLE_EAST_LOWER, + Regions.WATER_TEMPLE_MAP_ROOM, + Regions.WATER_TEMPLE_CRACKED_WALL, + Regions.WATER_TEMPLE_TORCH_ROOM, + Regions.WATER_TEMPLE_NORTH_LOWER, + Regions.WATER_TEMPLE_BOULDERS_LOWER, + Regions.WATER_TEMPLE_BLOCK_ROOM, + Regions.WATER_TEMPLE_JETS_ROOM, + Regions.WATER_TEMPLE_BOULDERS_UPPER, + Regions.WATER_TEMPLE_BOSS_KEY_ROOM, + Regions.WATER_TEMPLE_NEAR_BOSS_KEY_CHEST_GS, + Regions.WATER_TEMPLE_SOUTH_LOWER, + Regions.WATER_TEMPLE_WEST_LOWER, + Regions.WATER_TEMPLE_DRAGON_ROOM, + Regions.WATER_TEMPLE_DRAGON_ROOM_CHEST, + Regions.WATER_TEMPLE_CENTRAL_PILLAR_LOWER, + Regions.WATER_TEMPLE_CENTRAL_PILLAR_UPPER, + Regions.WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, + Regions.WATER_TEMPLE_EAST_MIDDLE, + Regions.WATER_TEMPLE_WEST_MIDDLE, + Regions.WATER_TEMPLE_HIGH_WATER, + Regions.WATER_TEMPLE_BLOCK_CORRIDOR, + Regions.WATER_TEMPLE_FALLING_PLATFORM_ROOM, + Regions.WATER_TEMPLE_DRAGON_PILLARS_ROOM, + Regions.WATER_TEMPLE_DARK_LINK_ROOM, + Regions.WATER_TEMPLE_LONGSHOT_ROOM, + Regions.WATER_TEMPLE_RIVER, + Regions.WATER_TEMPLE_PRE_BOSS_ROOM, + Regions.WATER_TEMPLE_BOSS_ENTRYWAY, + Regions.WATER_TEMPLE_BOSS_ROOM, +] + + class EventLocations(StrEnum): WATER_TEMPLE_EAST_LOWER_WATER_LOW_FROM_HIGH = "Water Temple East Lower Water Low From High" WATER_TEMPLE_CENTRAL_PILLAR_UPPER_WATER_MIDDLE = "Water Temple Central Pillar Upper Water Middle" @@ -589,3 +626,10 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.LAKE_HYLIA, lambda bundle: has_item( Events.WATER_TEMPLE_COMPLETED, bundle)) ]) + + +def init_regions(world: "SohWorld", dungeon_quest: DungeonQuest = DungeonQuest.VANILLA) -> None: + if dungeon_quest == DungeonQuest.VANILLA: + for region_name in vanilla_regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/castle_grounds.py b/worlds/oot_soh/location_access/overworld/castle_grounds.py index ac8a82ab8a97..ffb62469977a 100644 --- a/worlds/oot_soh/location_access/overworld/castle_grounds.py +++ b/worlds/oot_soh/location_access/overworld/castle_grounds.py @@ -1,9 +1,26 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.CASTLE_GROUNDS, + Regions.CASTLE_GROUNDS_FROM_GANONS_CASTLE, + Regions.HYRULE_CASTLE_GROUNDS, + Regions.HC_GARDEN_SONG_FROM_IMPA, + Regions.HC_GARDEN, + Regions.HC_GREAT_FAIRY_FOUNTAIN, + Regions.HC_STORMS_GROTTO, + Regions.HC_STORMS_GROTTO_BEHIND_WALLS, + Regions.HC_STORMS_SKULLTULA, + Regions.GANONS_CASTLE_GROUNDS, + Regions.OGC_GREAT_FAIRY_FOUNTAIN, + Regions.GANONS_CASTLE_LEDGE, +] + + class EventLocations(StrEnum): HC_GOSSIP_STONE_SONG_FAIRY = "HC Gossip Stone Song Fairy" HC_BUTTERFLY_FAIRY = "HC Butterfly Fairy" @@ -198,3 +215,13 @@ def set_region_rules(world: "SohWorld") -> None: LocalEvents.HC_OGC_RAINBOW_BRIDGE_BUILT, bundle)), (Regions.GANONS_CASTLE_ENTRYWAY, lambda bundle: is_adult(bundle)) ]) + + +def init_regions(world: "SohWorld") -> None: + # We don't need HC Garden if child zelda is skipped + if world.options.skip_child_zelda: + regions.remove(Regions.HC_GARDEN) + + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/death_mountain_crater.py b/worlds/oot_soh/location_access/overworld/death_mountain_crater.py index 40831fca872f..f8b37ffb8078 100644 --- a/worlds/oot_soh/location_access/overworld/death_mountain_crater.py +++ b/worlds/oot_soh/location_access/overworld/death_mountain_crater.py @@ -1,9 +1,25 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.DMC_UPPER_LOCAL, + Regions.DMC_CENTRAL_LOCAL, + Regions.DMC_LOWER_LOCAL, + Regions.DMC_LOWER_NEARBY, + Regions.DMC_UPPER_NEARBY, + Regions.DMC_CENTRAL_NEARBY, + Regions.DMC_LADDER_REGION_NEARBY, + Regions.DMC_UPPER_GROTTO, + Regions.DMC_HAMMER_GROTTO, + Regions.DMC_GREAT_FAIRY_FOUNTAIN, + Regions.DMC_DISTANT_PLATFORM, +] + + class EventLocations(StrEnum): DMC_GOSSIP_STONE_SONG_FAIRY = "DMC Gossip Stone Song Fairy" DMC_BEAN_PLANT_FAIRY = "DMC Bean Plant Fairy" @@ -247,3 +263,9 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.DMC_CENTRAL_LOCAL, lambda bundle: fire_timer( bundle) >= 48 and can_use(Items.DISTANT_SCARECROW, bundle)) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/death_mountain_trail.py b/worlds/oot_soh/location_access/overworld/death_mountain_trail.py index 2ad25937625f..7b8c26a4fc7e 100644 --- a/worlds/oot_soh/location_access/overworld/death_mountain_trail.py +++ b/worlds/oot_soh/location_access/overworld/death_mountain_trail.py @@ -1,9 +1,21 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.DEATH_MOUNTAIN, + Regions.DEATH_MOUNTAIN_SUMMIT, + Regions.DEATH_MOUNTAIN_TRAIL, + Regions.DMT_OWL_FLIGHT, + Regions.DMT_GREAT_FAIRY_FOUNTAIN, + Regions.DMT_COW_GROTTO, + Regions.DMT_STORMS_GROTTO, +] + + class EventLocations(StrEnum): DMT_BEAN_PLANT_FAIRY = "DMT Bean Plant Fairy" DMT_GOSSIP_STONE_SONG_FAIRY = "DMT Gossip Stone Song Fairy" @@ -180,3 +192,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.DMT_GREAT_FAIRY_FOUNTAIN, world, [ (Regions.DEATH_MOUNTAIN_SUMMIT, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/desert_colossus.py b/worlds/oot_soh/location_access/overworld/desert_colossus.py index b09d2159f65f..7e92728cb583 100644 --- a/worlds/oot_soh/location_access/overworld/desert_colossus.py +++ b/worlds/oot_soh/location_access/overworld/desert_colossus.py @@ -1,9 +1,19 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.DESERT_COLOSSUS, + Regions.DESERT_COLOSSUS_OASIS, + Regions.DESERT_COLOSSUS_OUTSIDE_TEMPLE, + Regions.COLOSSUS_GREAT_FAIRY_FOUNTAIN, + Regions.COLOSSUS_GROTTO, +] + + class EventLocations(StrEnum): DESERT_COLOSSUS_FAIRY_POND_COLOSSUS = "Desert Colossus Fairy Pond Colossus" DESERT_COLOSSUS_FAIRY_POND_OASIS = "Desert Colossus Fairy Pond Oasis" @@ -124,3 +134,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.COLOSSUS_GROTTO, world, [ (Regions.DESERT_COLOSSUS, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/gerudo_fortress.py b/worlds/oot_soh/location_access/overworld/gerudo_fortress.py index 3fd44aa5ccf9..e5b08d7d5686 100644 --- a/worlds/oot_soh/location_access/overworld/gerudo_fortress.py +++ b/worlds/oot_soh/location_access/overworld/gerudo_fortress.py @@ -1,9 +1,35 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.GERUDO_FORTRESS_OUTSKIRTS, + Regions.GF_NEAR_GROTTO, + Regions.GF_TO_GTG, + Regions.GF_EXITING_GTG, + Regions.GF_ABOVE_GTG, + Regions.GF_BOTTOM_OF_LOWER_VINES, + Regions.GF_TOP_OF_LOWER_VINES, + Regions.GF_NEAR_GS, + Regions.GF_SLOPED_ROOF, + Regions.GF_BOTTOM_OF_UPPER_VINES, + Regions.GF_TOP_OF_UPPER_VINES, + Regions.GF_NEAR_CHEST, + Regions.GF_LONG_ROOF, + Regions.GF_BELOW_GS, + Regions.GF_GS_KILL_ZONE, + Regions.GF_BELOW_CHEST, + Regions.GF_HBA_RANGE, + Regions.GF_ABOVE_JAIL, + Regions.GF_JAIL_WINDOW, + Regions.GF_OUTSIDE_GATE, + Regions.GF_STORMS_GROTTO, +] + + class EventLocations(StrEnum): GF_GATE = "GF Gate" GF_GATE_OUTSIDE = "GF Gate Outside" @@ -354,3 +380,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.GF_STORMS_GROTTO, world, [ (Regions.GF_NEAR_GROTTO, lambda bundle: True), ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/gerudo_valley.py b/worlds/oot_soh/location_access/overworld/gerudo_valley.py index c0339b28c7aa..7596a3c2ad0b 100644 --- a/worlds/oot_soh/location_access/overworld/gerudo_valley.py +++ b/worlds/oot_soh/location_access/overworld/gerudo_valley.py @@ -1,9 +1,23 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.GERUDO_VALLEY, + Regions.GV_UPPER_STREAM, + Regions.GV_LOWER_STREAM, + Regions.GV_GROTTO_LEDGE, + Regions.GV_CRATE_LEDGE, + Regions.GV_OCTOROK_GROTTO, + Regions.GV_FORTRESS_SIDE, + Regions.GV_CARPENTER_TENT, + Regions.GV_STORMS_GROTTO, +] + + class EventLocations(StrEnum): GV_BUG_ROCK = "GV Bug Rock" GV_GOSSIP_STONE_SONG_FAIRY = "GV Gossip Stone Song Fairy" @@ -210,3 +224,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.GV_STORMS_GROTTO, world, [ (Regions.GV_FORTRESS_SIDE, lambda bundle: True), ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/goron_city.py b/worlds/oot_soh/location_access/overworld/goron_city.py index 2f2f947b17fe..4c99ba27edc1 100644 --- a/worlds/oot_soh/location_access/overworld/goron_city.py +++ b/worlds/oot_soh/location_access/overworld/goron_city.py @@ -1,9 +1,21 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.GORON_CITY, + Regions.GC_MEDIGORON, + Regions.GC_WOODS_WARP, + Regions.GC_DARUNIAS_CHAMBER, + Regions.GC_GROTTO_PLATFORM, + Regions.GC_SHOP, + Regions.GC_GROTTO +] + + class EventLocations(StrEnum): GC_GOSSIP_STONE_SONG_FAIRY = "GC Gossip Stone Song Fairy" GC_STICK_POT = "GC Stick Pot" @@ -176,3 +188,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.GC_GROTTO, world, [ (Regions.GC_GROTTO_PLATFORM, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/graveyard.py b/worlds/oot_soh/location_access/overworld/graveyard.py index 450c212c429f..e52676d26afc 100644 --- a/worlds/oot_soh/location_access/overworld/graveyard.py +++ b/worlds/oot_soh/location_access/overworld/graveyard.py @@ -1,9 +1,22 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.THE_GRAVEYARD, + Regions.GRAVEYARD_DAMPES_GRAVE, + Regions.GRAVEYARD_DAMPES_HOUSE, + Regions.GRAVEYARD_SHIELD_GRAVE, + Regions.GRAVEYARD_SHIELD_GRAVE_BACK, + Regions.GRAVEYARD_COMPOSERS_GRAVE, + Regions.GRAVEYARD_HEART_PIECE_GRAVE, + Regions.GRAVEYARD_WARP_PAD_REGION, +] + + class EventLocations(StrEnum): GRAVEYARD_BUTTERFLY_FAIRY = "Graveyard Butterfly Fairy" GRAVEYARD_BEAN_PLANT_FAIRY = "Graveyard Bean Plant Fairy" @@ -203,3 +216,9 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.SHADOW_TEMPLE_ENTRYWAY, lambda bundle: can_use(Items.DINS_FIRE, bundle) or (can_do_trick( Tricks.GY_SHADOW_FIRE_ARROWS, bundle) and is_adult(bundle) and can_use(Items.FIRE_ARROW, bundle))) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/haunted_wasteland.py b/worlds/oot_soh/location_access/overworld/haunted_wasteland.py index a5e43c823dc9..0058802c89fb 100644 --- a/worlds/oot_soh/location_access/overworld/haunted_wasteland.py +++ b/worlds/oot_soh/location_access/overworld/haunted_wasteland.py @@ -1,9 +1,17 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.WASTELAND_NEAR_FORTRESS, + Regions.HAUNTED_WASTELAND, + Regions.WASTELAND_NEAR_COLOSSUS, +] + + class EventLocations(StrEnum): WASTELAND_FAIRY_POT = "Wasteland Fairy Pot" WASTELAND_NUT_POT = "Wasteland Nut Pot" @@ -74,3 +82,9 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.HAUNTED_WASTELAND, lambda bundle: can_do_trick( Tricks.HW_REVERSE, bundle)) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/hyrule_field.py b/worlds/oot_soh/location_access/overworld/hyrule_field.py index 155e10ce9b8a..cdef8e96c1ba 100644 --- a/worlds/oot_soh/location_access/overworld/hyrule_field.py +++ b/worlds/oot_soh/location_access/overworld/hyrule_field.py @@ -1,9 +1,25 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.HYRULE_FIELD, + Regions.HF_SOUTHEAST_GROTTO, + Regions.HF_OPEN_GROTTO, + Regions.HF_OPEN_GROTTO, + Regions.HF_INSIDE_FENCE_GROTTO, + Regions.HF_COW_GROTTO, + Regions.HF_COW_GROTTO_BEHIND_WEBS, + Regions.HF_NEAR_MARKET_GROTTO, + Regions.HF_FAIRY_GROTTO, + Regions.HF_NEAR_KAK_GROTTO, + Regions.HF_TEKTITE_GROTTO, +] + + class EventLocations(StrEnum): HF_BIG_POE = "HF Big Poe" HF_RUNNING_MAN = "HF Running Man" @@ -396,3 +412,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.HF_TEKTITE_GROTTO, world, [ (Regions.HYRULE_FIELD, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/kakariko.py b/worlds/oot_soh/location_access/overworld/kakariko.py index f087438fa503..e12b39d26e16 100644 --- a/worlds/oot_soh/location_access/overworld/kakariko.py +++ b/worlds/oot_soh/location_access/overworld/kakariko.py @@ -1,9 +1,35 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.KAKARIKO_VILLAGE, + Regions.KAK_CARPENTER_BOSS_HOUSE, + Regions.KAK_HOUSE_OF_SKULLTULA, + Regions.KAK_IMPAS_HOUSE, + Regions.KAK_COW_CAGE, + Regions.KAK_IMPAS_LEDGE, + Regions.KAK_IMPAS_HOUSE_BACK, + Regions.KAK_WINDMILL, + Regions.KAK_BAZAAR, + Regions.KAK_SHOOTING_GALLERY, + Regions.KAK_POTION_SHOP_FRONT, + Regions.KAK_POTION_SHOP_BACK, + Regions.KAK_WATCHTOWER, + Regions.KAK_ROOFTOP, + Regions.KAK_IMPAS_ROOFTOP, + Regions.KAK_BEHIND_GATE, + Regions.KAK_BACKYARD, + Regions.KAK_WELL, + Regions.KAK_GRANNYS_POTION_SHOP, + Regions.KAK_REDEAD_GROTTO, + Regions.KAK_OPEN_GROTTO, +] + + class EventLocations(StrEnum): KAK_GATE = "Kak Gate" KAK_GATE_GUARD = "Kak Gate Guard" @@ -436,3 +462,9 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.BOTTOM_OF_THE_WELL_ENTRYWAY, lambda bundle: is_child( bundle) or has_item(Events.DRAIN_WELL, bundle)), ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/kokiri_forest.py b/worlds/oot_soh/location_access/overworld/kokiri_forest.py index f697f40ef08e..a8e12ec31884 100644 --- a/worlds/oot_soh/location_access/overworld/kokiri_forest.py +++ b/worlds/oot_soh/location_access/overworld/kokiri_forest.py @@ -1,9 +1,23 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.KOKIRI_FOREST, + Regions.KF_LINKS_HOUSE, + Regions.KF_MIDOS_HOUSE, + Regions.KF_SARIAS_HOUSE, + Regions.KF_HOUSE_OF_TWINS, + Regions.KF_KNOW_IT_ALL_HOUSE, + Regions.KF_KOKIRI_SHOP, + Regions.KF_OUTSIDE_DEKU_TREE, + Regions.KF_STORMS_GROTTO, +] + + class EventLocations(StrEnum): MIDO = "Mido" MIDO_FROM_OUTSIDE_DEKU_TREE = "Mido From Outside Deku Tree" @@ -335,3 +349,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.KF_STORMS_GROTTO, world, [ (Regions.KOKIRI_FOREST, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/lake_hylia.py b/worlds/oot_soh/location_access/overworld/lake_hylia.py index 6f8f1bcfd6f0..34b8f271cb3f 100644 --- a/worlds/oot_soh/location_access/overworld/lake_hylia.py +++ b/worlds/oot_soh/location_access/overworld/lake_hylia.py @@ -1,9 +1,22 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.LAKE_HYLIA, + Regions.LH_FROM_SHORTCUT, + Regions.LH_FROM_WATER_TEMPLE, + Regions.LH_FISHING_ISLAND, + Regions.LH_OWL_FLIGHT, + Regions.LH_LAB, + Regions.LH_FISHING_HOLE, + Regions.LH_GROTTO, +] + + class EventLocations(StrEnum): LH_BUG_SHRUB = "LH Bug Shrub" LH_BEAN_FAIRY = "LH Bean Fairy" @@ -335,3 +348,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.LH_GROTTO, world, [ (Regions.LAKE_HYLIA, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/lon_lon_ranch.py b/worlds/oot_soh/location_access/overworld/lon_lon_ranch.py index 9906fd9522e2..73708eca72d1 100644 --- a/worlds/oot_soh/location_access/overworld/lon_lon_ranch.py +++ b/worlds/oot_soh/location_access/overworld/lon_lon_ranch.py @@ -1,9 +1,19 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.LON_LON_RANCH, + Regions.LLR_TALONS_HOUSE, + Regions.LLR_STABLES, + Regions.LLR_TOWER, + Regions.LLR_GROTTO, +] + + class EventLocations(StrEnum): LLR_TALON_RACE = "LLR Talon Race" LLR_TIME_TRIAL = "LLR Time Trial" @@ -118,3 +128,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.LLR_GROTTO, world, [ (Regions.LON_LON_RANCH, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/lost_woods.py b/worlds/oot_soh/location_access/overworld/lost_woods.py index 42fb3e5ca92e..9c5d3f1446bf 100644 --- a/worlds/oot_soh/location_access/overworld/lost_woods.py +++ b/worlds/oot_soh/location_access/overworld/lost_woods.py @@ -1,9 +1,22 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.LOST_WOODS, + Regions.LW_BRIDGE_FROM_FOREST, + Regions.LW_BRIDGE, + Regions.LW_FOREST_EXIT, + Regions.LW_BEYOND_MIDO, + Regions.LW_NEAR_SHORTCUTS_GROTTO, + Regions.DEKU_THEATER, + Regions.LW_SCRUBS_GROTTO, +] + + class EventLocations(StrEnum): LW_GOSSIP_STONE_SONG_FAIRY = "LW Gossip Stone Song Fairy" LW_BEAN_PLANT_FAIRY = "LW Bean Plant Fairy" @@ -250,3 +263,9 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.HYRULE_FIELD, lambda bundle: True), (Regions.LOST_WOODS, lambda bundle: can_use(Items.LONGSHOT, bundle)) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/market.py b/worlds/oot_soh/location_access/overworld/market.py index 50dc336489a9..cf34c85735c5 100644 --- a/worlds/oot_soh/location_access/overworld/market.py +++ b/worlds/oot_soh/location_access/overworld/market.py @@ -1,9 +1,27 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.MARKET_ENTRANCE, + Regions.MARKET, + Regions.MARKET_GUARD_HOUSE, + Regions.MARKET_BAZAAR, + Regions.MARKET_MASK_SHOP, + Regions.MARKET_SHOOTING_GALLERY, + Regions.MARKET_BOMBCHU_BOWLING, + Regions.MARKET_TREASURE_CHEST_GAME, + Regions.MARKET_POTION_SHOP, + Regions.MARKET_BACK_ALLEY, + Regions.MARKET_BOMBCHU_SHOP, + Regions.MARKET_DOG_LADY_HOUSE, + Regions.MARKET_MAN_IN_GREEN_HOUSE, +] + + class EventLocations(StrEnum): MARKET_GUARD_HOUSE = "Market Guard House" MARKET_MASK_SHOP_MASKS = "Market Mask Shop Masks" @@ -361,3 +379,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.MARKET_MAN_IN_GREEN_HOUSE, world, [ (Regions.MARKET_BACK_ALLEY, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/sacred_forest_meadow.py b/worlds/oot_soh/location_access/overworld/sacred_forest_meadow.py index 24323b25390c..939315777ef1 100644 --- a/worlds/oot_soh/location_access/overworld/sacred_forest_meadow.py +++ b/worlds/oot_soh/location_access/overworld/sacred_forest_meadow.py @@ -1,9 +1,19 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.SFM_ENTRYWAY, + Regions.SACRED_FOREST_MEADOW, + Regions.SFM_WOLFOS_GROTTO, + Regions.SFM_FAIRY_GROTTO, + Regions.SFM_STORMS_GROTTO, +] + + class EventLocations(StrEnum): SFM_GOSSIP_STONE_SONG_FAIRY = "SFM Gossip Stone Song Fairy" SFM_FAIRY_FOUNTAIN_FAIRY = "SFM Fairy Fountain Fairy" @@ -101,3 +111,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.SFM_STORMS_GROTTO, world, [ (Regions.SACRED_FOREST_MEADOW, lambda bundle: True), ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/temple_of_time.py b/worlds/oot_soh/location_access/overworld/temple_of_time.py index c3eee32e28da..a6d2d5b305bd 100644 --- a/worlds/oot_soh/location_access/overworld/temple_of_time.py +++ b/worlds/oot_soh/location_access/overworld/temple_of_time.py @@ -1,9 +1,18 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.TOT_ENTRANCE, + Regions.TEMPLE_OF_TIME, + Regions.BEYOND_DOOR_OF_TIME, + Regions.MASTER_SWORD_PEDESTAL, +] + + class EventLocations(StrEnum): TOT_ENTRANCE_GOSSIP_STONE_SONG_FAIRY = "ToT Entrance Gossip Stone Fairy" CHAMBER_OF_SAGES = "Chamber of Sages" @@ -80,3 +89,9 @@ def set_region_rules(world: "SohWorld") -> None: add_locations(Regions.MASTER_SWORD_PEDESTAL, world, [ (Locations.MARKET_TOT_MASTER_SWORD, lambda bundle: True), ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/thieves_hideout.py b/worlds/oot_soh/location_access/overworld/thieves_hideout.py index b4ce44e58ce7..21313830bedd 100644 --- a/worlds/oot_soh/location_access/overworld/thieves_hideout.py +++ b/worlds/oot_soh/location_access/overworld/thieves_hideout.py @@ -1,9 +1,25 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.THIEVES_HIDEOUT_1_TORCH_CELL, + Regions.THIEVES_HIDEOUT_DOUBLE_CELL, + Regions.THIEVES_HIDEOUT_DEAD_END_CELL, + Regions.THIEVES_HIDEOUT_STEEP_SLOPE_CELL, + Regions.THIEVES_HIDEOUT_KITCHEN_CORRIDOR, + Regions.THIEVES_HIDEOUT_KITCHEN_BOTTOM, + Regions.THIEVES_HIDEOUT_KITCHEN_TOP, + Regions.THIEVES_HIDEOUT_BREAK_ROOM, + Regions.THIEVES_HIDEOUT_BREAK_ROOM_CORRIDOR, + Regions.THIEVES_HIDEOUT_RESCUE_CARPENTERS, + Regions.THIEVES_HIDEOUT_KITCHEN_POTS, +] + + class EventsLocations(StrEnum): TH_1_TORCH_CARPENTER_CELL = "TH 1 Torch Carpenter Cell" TH_DOUBLE_CELL_CARPENTER_CELL = "TH Double Cell Carpenter Cell" @@ -239,3 +255,9 @@ def set_region_rules(world: "SohWorld") -> None: lambda bundle: can_use(Items.HOOKSHOT, bundle)), (Regions.GF_ABOVE_JAIL, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/zoras_domain.py b/worlds/oot_soh/location_access/overworld/zoras_domain.py index 71b8f6675080..11fd0a6613c3 100644 --- a/worlds/oot_soh/location_access/overworld/zoras_domain.py +++ b/worlds/oot_soh/location_access/overworld/zoras_domain.py @@ -1,9 +1,19 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.ZORAS_DOMAIN, + Regions.ZORAS_DOMAIN_ISLAND, + Regions.ZD_BEHIND_KING_ZORA, + Regions.ZD_SHOP, + Regions.ZD_STORMS_GROTTO, +] + + class EventLocations(StrEnum): ZD_GOSSIP_STONE_SONG_FAIRY = "ZD Gossip Stone Song Fairy" ZD_NUT_POT = "ZD Nut Pot" @@ -158,3 +168,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.ZD_STORMS_GROTTO, world, [ (Regions.ZORAS_DOMAIN_ISLAND, lambda bundle: True), ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/zoras_fountain.py b/worlds/oot_soh/location_access/overworld/zoras_fountain.py index 37834e7e44b4..9bc95accd183 100644 --- a/worlds/oot_soh/location_access/overworld/zoras_fountain.py +++ b/worlds/oot_soh/location_access/overworld/zoras_fountain.py @@ -1,9 +1,22 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.ZORAS_FOUNTAIN, + Regions.ZF_ICEBERGS, + Regions.ZF_LAKEBED, + Regions.ZF_LEDGE, + Regions.ZF_HIDDEN_CAVE, + Regions.ZF_HIDDEN_LEDGE, + Regions.ZF_ROCK, + Regions.ZF_GREAT_FAIRY_FOUNTAIN, +] + + class EventLocations(StrEnum): ZF_GOSSIP_STONE_SONG_FAIRY = "ZF Gossip Stone Song Fairy" ZF_BUTTERFLY_FAIRY = "ZF Butterfly Fairy" @@ -171,3 +184,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.ZF_GREAT_FAIRY_FOUNTAIN, world, [ (Regions.ZORAS_FOUNTAIN, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/overworld/zoras_river.py b/worlds/oot_soh/location_access/overworld/zoras_river.py index 57bf47c3435d..9c92eb03af83 100644 --- a/worlds/oot_soh/location_access/overworld/zoras_river.py +++ b/worlds/oot_soh/location_access/overworld/zoras_river.py @@ -1,9 +1,21 @@ from ...LogicHelpers import * +from ...Regions import SohRegion if TYPE_CHECKING: from ... import SohWorld +regions = [ + Regions.ZR_FRONT, + Regions.ZORA_RIVER, + Regions.ZR_FROM_SHORTCUT, + Regions.ZR_BEHIND_WATERFALL, + Regions.ZR_OPEN_GROTTO, + Regions.ZR_FAIRY_GROTTO, + Regions.ZR_STORMS_GROTTO, +] + + class EventLocations(StrEnum): ZR_BUG_GRASS = "ZR Bug Grass" MAGIC_BEAN_SALESMAN_SHOP = "Magic Bean Salesman Shop" @@ -255,3 +267,9 @@ def set_region_rules(world: "SohWorld") -> None: connect_regions(Regions.ZR_STORMS_GROTTO, world, [ (Regions.ZORA_RIVER, lambda bundle: True) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region) diff --git a/worlds/oot_soh/location_access/root.py b/worlds/oot_soh/location_access/root.py index 67ef8069b80a..f11d18efb8fb 100644 --- a/worlds/oot_soh/location_access/root.py +++ b/worlds/oot_soh/location_access/root.py @@ -1,9 +1,24 @@ from ..LogicHelpers import * +from ..Regions import SohRegion if TYPE_CHECKING: from .. import SohWorld +regions = [ + Regions.ROOT, + Regions.ROOT_EXITS, + Regions.CHILD_SPAWN, + Regions.ADULT_SPAWN, + Regions.MINUET_OF_FOREST_WARP, + Regions.BOLERO_OF_FIRE_WARP, + Regions.SERENADE_OF_WATER_WARP, + Regions.REQUIEM_OF_SPIRIT_WARP, + Regions.NOCTURNE_OF_SHADOW_WARP, + Regions.PRELUDE_OF_LIGHT_WARP, +] + + class EventLocations(StrEnum): ROOT_AMMO_DROP = "Root Ammo Drop" ROOT_DEKU_SHIELD = "Root Deku Shield" @@ -115,3 +130,9 @@ def set_region_rules(world: "SohWorld") -> None: (Regions.TEMPLE_OF_TIME, lambda bundle: can_use( Items.PRELUDE_OF_LIGHT, bundle)) ]) + + +def init_regions(world: "SohWorld") -> None: + for region_name in regions: + region = SohRegion(str(region_name), world.player, world.multiworld) + world.multiworld.regions.append(region)