From 11eebbbd328ac8b79d6d1c39bb43c06b8466d7f7 Mon Sep 17 00:00:00 2001 From: espeon65536 <81029175+espeon65536@users.noreply.github.com> Date: Thu, 12 Jan 2023 12:20:49 -0700 Subject: [PATCH] Ocarina of Time: 0.3.7 hotfixes round 2 (#1351) * oot: repair closed forest + dungeon ER * oot: finally skip triforce pieces in balancing * oot: fix mq_dungeons_mode set to mq or count * oot: force 0.3.7 client hopefully this makes people update * oot: temp fix for skip-child-zelda crash eventually I want to decide on a better fix for this though * oot: remove skip-child-zelda item inside if tree * oot: fix classification of some thieves hideout locations in tracker * oot: fix regional shuffle for hideout keys and ganon boss key * oot: properly attach hints to dungeon locations * Fix entrance shuffle flag not being set correctly due to new dungeon shuffle option format --- WebHostLib/tracker.py | 4 ++-- worlds/oot/Hints.py | 4 ++-- worlds/oot/Items.py | 2 +- worlds/oot/__init__.py | 42 ++++++++++++++++++++++++++++++++---------- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/WebHostLib/tracker.py b/WebHostLib/tracker.py index dfa17442..68a40a32 100644 --- a/WebHostLib/tracker.py +++ b/WebHostLib/tracker.py @@ -650,7 +650,7 @@ def __renderOoTTracker(multisave: Dict[str, Any], room: Room, locations: Dict[in # Gather dungeon locations area_id_ranges = { - "Overworld": ((67000, 67258), (67264, 67280), (67747, 68024), (68054, 68062)), + "Overworld": ((67000, 67263), (67269, 67280), (67747, 68024), (68054, 68062)), "Deku Tree": ((67281, 67303), (68063, 68077)), "Dodongo's Cavern": ((67304, 67334), (68078, 68160)), "Jabu Jabu's Belly": ((67335, 67359), (68161, 68188)), @@ -662,7 +662,7 @@ def __renderOoTTracker(multisave: Dict[str, Any], room: Room, locations: Dict[in "Spirit Temple": ((67533, 67582), (68566, 68625)), "Ice Cavern": ((67583, 67596), (68626, 68649)), "Gerudo Training Ground": ((67597, 67635), (68650, 68656)), - "Thieves' Hideout": ((67259, 67263), (68025, 68053)), + "Thieves' Hideout": ((67264, 67268), (68025, 68053)), "Ganon's Castle": ((67636, 67673), (68657, 68705)), } diff --git a/worlds/oot/Hints.py b/worlds/oot/Hints.py index d2011279..dfed0b4d 100644 --- a/worlds/oot/Hints.py +++ b/worlds/oot/Hints.py @@ -1136,14 +1136,14 @@ def buildMiscItemHints(world, messages): if world.multiworld.state.has(data['default_item'], world.player) > 0: text = data['default_item_text'].format(area='#your pocket#') elif item_locations: - location = item_locations[0] + location = world.hint_rng.choice(item_locations) player_text = '' if location.player != world.player: player_text = world.multiworld.get_player_name(location.player) + "'s " if location.game == 'Ocarina of Time': area = HintArea.at(location, use_alt_hint=data['use_alt_hint']).text(world.clearer_hints, world=None) else: - area = location.name + area = location.name text = data['default_item_text'].format(area=(player_text + area)) elif 'default_item_fallback' in data: text = data['default_item_fallback'] diff --git a/worlds/oot/Items.py b/worlds/oot/Items.py index 23256002..e3ce920d 100644 --- a/worlds/oot/Items.py +++ b/worlds/oot/Items.py @@ -41,7 +41,7 @@ class OOTItem(Item): classification = ItemClassification.useful elif name == "Ice Trap": classification = ItemClassification.trap - elif name == 'Gold Skulltula Token': + elif name in {'Gold Skulltula Token', 'Triforce Piece'}: classification = ItemClassification.progression_skip_balancing elif advancement: classification = ItemClassification.progression diff --git a/worlds/oot/__init__.py b/worlds/oot/__init__.py index 81518265..db9af7a5 100644 --- a/worlds/oot/__init__.py +++ b/worlds/oot/__init__.py @@ -109,7 +109,7 @@ class OOTWorld(World): data_version = 3 - required_client_version = (0, 3, 6) + required_client_version = (0, 3, 7) item_name_groups = { # internal groups @@ -171,12 +171,13 @@ class OOTWorld(World): # ER and glitched logic are not compatible; glitched takes priority if self.logic_rules == 'glitched': self.shuffle_interior_entrances = 'off' + self.shuffle_dungeon_entrances = 'off' + self.spawn_positions = 'off' + self.shuffle_bosses = 'off' self.shuffle_grotto_entrances = False - self.shuffle_dungeon_entrances = False self.shuffle_overworld_entrances = False self.owl_drops = False self.warp_songs = False - self.spawn_positions = 'off' # Fix spawn positions option new_sp = [] @@ -283,8 +284,17 @@ class OOTWorld(World): self.shuffle_special_dungeon_entrances = self.shuffle_dungeon_entrances == 'all' self.shuffle_dungeon_entrances = self.shuffle_dungeon_entrances != 'off' self.ensure_tod_access = (self.shuffle_interior_entrances != 'off') or self.shuffle_overworld_entrances or self.spawn_positions - self.entrance_shuffle = (self.shuffle_interior_entrances != 'off') or self.shuffle_grotto_entrances or self.shuffle_dungeon_entrances or \ - self.shuffle_overworld_entrances or self.owl_drops or self.warp_songs or self.spawn_positions + self.entrance_shuffle = ( + self.shuffle_interior_entrances != 'off' + or self.shuffle_bosses != 'off' + or self.shuffle_dungeon_entrances + or self.shuffle_special_dungeon_entrances + or self.spawn_positions + or self.shuffle_grotto_entrances + or self.shuffle_overworld_entrances + or self.owl_drops + or self.warp_songs + ) self.disable_trade_revert = (self.shuffle_interior_entrances != 'off') or self.shuffle_overworld_entrances self.shuffle_special_interior_entrances = self.shuffle_interior_entrances == 'all' @@ -317,13 +327,14 @@ class OOTWorld(World): # Determine which dungeons are MQ. Not compatible with glitched logic. mq_dungeons = set() + all_dungeons = [d['name'] for d in dungeon_table] if self.logic_rules != 'glitched': if self.mq_dungeons_mode == 'mq': - mq_dungeons = dungeon_table.keys() + mq_dungeons = all_dungeons elif self.mq_dungeons_mode == 'specific': mq_dungeons = self.mq_dungeons_specific elif self.mq_dungeons_mode == 'count': - mq_dungeons = self.multiworld.random.sample(dungeon_table, self.mq_dungeons_count) + mq_dungeons = self.multiworld.random.sample(all_dungeons, self.mq_dungeons_count) else: self.mq_dungeons_mode = 'count' self.mq_dungeons_count = 0 @@ -441,6 +452,7 @@ class OOTWorld(World): new_region.scene = region['scene'] if 'dungeon' in region: new_region.dungeon = region['dungeon'] + new_region.set_hint_data(region['dungeon']) if 'is_boss_room' in region: new_region.is_boss_room = region['is_boss_room'] if 'hint' in region: @@ -842,10 +854,13 @@ class OOTWorld(World): impa = self.multiworld.get_location("Song from Impa", self.player) if self.shuffle_child_trade == 'skip_child_zelda': if impa.item is None: - item_to_place = self.multiworld.random.choice( - list(item for item in self.multiworld.itempool if item.player == self.player)) + candidate_items = list(item for item in self.multiworld.itempool if item.player == self.player) + if candidate_items: + item_to_place = self.multiworld.random.choice(candidate_items) + self.multiworld.itempool.remove(item_to_place) + else: + item_to_place = self.create_item("Recovery Heart") impa.place_locked_item(item_to_place) - self.multiworld.itempool.remove(item_to_place) # Give items to startinventory self.multiworld.push_precollected(impa.item) self.multiworld.push_precollected(self.create_item("Zeldas Letter")) @@ -1269,6 +1284,13 @@ def gather_locations(multiworld: MultiWorld, 'HideoutSmallKey': 'shuffle_hideoutkeys', 'GanonBossKey': 'shuffle_ganon_bosskey', } + + # Special handling for atypical item types + if item_type == 'HideoutSmallKey': + dungeon = 'Thieves Hideout' + elif item_type == 'GanonBossKey': + dungeon = 'Ganons Castle' + if isinstance(players, int): players = {players} fill_opts = {p: getattr(multiworld.worlds[p], type_to_setting[item_type]) for p in players}