diff --git a/Fill.py b/Fill.py index 536d884b..5914b521 100644 --- a/Fill.py +++ b/Fill.py @@ -61,7 +61,7 @@ def fill_dungeons_restrictive(world, shuffled_locations): small_state_base = all_state_base.copy() for x in others: small_state_base.collect(x, True) - fill(small_state_base, smalls, smalls) + fill(small_state_base, smalls, list(smalls)) random.shuffle(shuffled_locations) fill(all_state_base, others, None) @@ -123,7 +123,6 @@ def fill_restrictive(world, base_state, locations, itempool, key_pool=None, sing raise FillError('No more spots to place %s' % item_to_place) world.push_item(spot_to_fill, item_to_place, False) - # todo: remove key item from key_pool if item_to_place.smallkey: with suppress(ValueError): key_pool.remove(item_to_place) diff --git a/Main.py b/Main.py index 240051d4..e63a5ec7 100644 --- a/Main.py +++ b/Main.py @@ -33,7 +33,7 @@ from source.overworld.EntranceShuffle2 import link_entrances_new from source.tools.BPS import create_bps_from_data from source.classes.CustomSettings import CustomSettings -__version__ = '1.0.1.1-x' +__version__ = '1.0.1.2-x' from source.classes.BabelFish import BabelFish @@ -587,11 +587,7 @@ def copy_dynamic_regions_and_locations(world, ret): for location in world.dynamic_locations: new_reg = ret.get_region(location.parent_region.name, location.parent_region.player) new_loc = Location(location.player, location.name, location.address, location.crystal, location.hint_text, new_reg) - # todo: this is potentially dangerous. later refactor so we - # can apply dynamic region rules on top of copied world like other rules - new_loc.access_rule = location.access_rule - new_loc.always_allow = location.always_allow - new_loc.item_rule = location.item_rule + new_loc.type = location.type new_reg.locations.append(new_loc) ret.clear_location_cache() diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0b792317..bde46641 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -201,12 +201,20 @@ Same as above but both small keys and bigs keys of the dungeon are not allowed o #### Customizer +* Fixed an issue where Interior Key Doors were missing from custom yaml output +* Updated lite/lean ER for pottery settings + * Fixed an issue with lite/lean ER not generating * Fixed up the GUI selection of the customizer file. * Fixed up the item_pool section to skip a lot of pool manipulations. Key items will be added (like the bow) if not detected. Extra dungeon items can be added to the pool and will be confined to the dungeon if possible (and not shuffled). If the pool isn't full, junk items are added to the pool to fill it out. #### Unstable +* 1.0.1.2 + * Fixed an issue with small key bias rework + * Fixed an issue where trinity goal would open pyramid unexpectedly. (No longer does so if ER mdoe is shuffling holes). Crystals goal updated to match that behavior. + * Fixed a playthrough issue that was not respecting pot rules + * Fixed an issue that was conflicting with downstream OWR project * 1.0.1.1 * Fixed the pots in Mire Storyteller/ Dark Desert Hint to be colorized when they should be * Certain pot items no longer reload when reloading the supertile (matches original pot behavior better) diff --git a/Rom.py b/Rom.py index 3bc64b82..ef640da5 100644 --- a/Rom.py +++ b/Rom.py @@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '7b330d5a813abb4bf036313ed42bccee' +RANDOMIZERBASEHASH = '7b877dcee4ece38713768b74acb333a6' class JsonRom(object): @@ -1269,7 +1269,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(0x50563, [0x3F, 0x14]) # disable below ganon chest rom.write_byte(0x50599, 0x00) # disable below ganon chest rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest - if world.open_pyramid[player] or world.goal[player] == 'trinity': + if world.open_pyramid[player] or (world.goal[player] in ['trinity', 'crystals'] and world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']): rom.initial_sram.pre_open_pyramid_hole() if world.crystals_needed_for_gt[player] == 0: rom.initial_sram.pre_open_ganons_tower() @@ -1540,9 +1540,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_bytes(room.address(), room.rom_data()) if world.pottery[player] not in ['none']: - rom.write_bytes(snes_to_pc(0x1F8375), int32_as_bytes(0x2A8000)) + rom.write_bytes(snes_to_pc(0x1F8375), int32_as_bytes(0x2B8000)) # make hammer pegs use different tiles - Room0127.write_to_rom(snes_to_pc(0x2A8000), rom) + Room0127.write_to_rom(snes_to_pc(0x2B8000), rom) if world.pot_contents[player]: colorize_pots = is_mystery or (world.pottery[player] not in ['vanilla', 'lottery'] diff --git a/data/base2current.bps b/data/base2current.bps index 7811e083..2137836d 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 39482fcd..64ef8b3d 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -310,7 +310,7 @@ class CustomSettings(object): for door in world.doors: if door.player == p and not door.entranceFlag and door.type in door_types and door not in skip: if door.type == DoorType.Interior: - if door.name in door_types: + if door.name in door_kinds: door_value = {'type': door_kinds[door.name]} door_map[door.name] = door_value # intra-tile note skip.add(door.dest) diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index cb176aba..da454795 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -770,6 +770,9 @@ def do_vanilla_connect(pool_def, avail): if pool_def['condition'] == 'shopsanity': if avail.world.shopsanity[avail.player]: return + elif pool_def['condition'] == 'pottery': # this condition involves whether caves with pots are shuffled or not + if avail.world.pottery[avail.player] not in ['none', 'keys', 'dungeon']: + return defaults = inverted_default_connections if avail.inverted else default_connections for entrance in pool_def['entrances']: if entrance in avail.entrances: @@ -1188,16 +1191,13 @@ modes = { 'fixed_non_items': { 'special': 'vanilla', 'condition': '', - 'entrances': ['Dark Death Mountain Fairy', 'Dark Desert Fairy', 'Dark Desert Hint', 'Archery Game', + 'entrances': ['Dark Death Mountain Fairy', 'Dark Desert Fairy', 'Archery Game', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint', 'Bonk Fairy (Dark)', - 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Spike Cave', - 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Fairy', 'Dark Lake Hylia Shop', - 'Palace of Darkness Hint', 'East Dark World Hint', 'Hookshot Fairy', '50 Rupee Cave', - 'Kakariko Gamble Game', '20 Rupee Cave', 'Good Bee Cave', 'Long Fairy Cave', - 'Light World Bomb Hut', 'Tavern (Front)', 'Bush Covered House', 'Snitch Lady (West)', - 'Snitch Lady (East)', 'Fortune Teller (Light)', 'Lost Woods Gamble', 'Desert Fairy', - 'Light Hype Fairy', 'Lake Hylia Fortune Teller', 'Lake Hylia Fairy', 'Bonk Fairy (Light)', - 'Lumberjack House', 'Inverted Dark Sanctuary'], + 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Fairy', + 'Dark Lake Hylia Shop', 'East Dark World Hint', 'Kakariko Gamble Game', 'Good Bee Cave', + 'Long Fairy Cave', 'Bush Covered House', 'Fortune Teller (Light)', 'Lost Woods Gamble', + 'Desert Fairy', 'Light Hype Fairy', 'Lake Hylia Fortune Teller', 'Lake Hylia Fairy', + 'Bonk Fairy (Light)', 'Inverted Dark Sanctuary'], }, 'fixed_shops': { 'special': 'vanilla', @@ -1206,7 +1206,16 @@ modes = { 'Dark World Shop', 'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Cave Shop (Lake Hylia)'], }, - 'item_caves': { # shuffles shops if they weren't fixed in the last one + 'fixed_pottery': { + 'special': 'vanilla', + 'condition': 'pottery', + 'entrances': ['Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)', + 'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy', + 'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave', + 'Dark Desert Hint'] + + }, + 'item_caves': { # shuffles shops/pottery if they weren't fixed in the last steps 'entrances': ['Mimic Cave', 'Spike Cave', 'Mire Shed', 'Dark World Hammer Peg Cave', 'Chest Game', 'C-Shaped House', 'Brewery', 'Hype Cave', 'Big Bomb Shop', 'Pyramid Fairy', 'Ice Rod Cave', 'Dam', 'Bonk Rock Cave', 'Library', 'Potion Shop', 'Mini Moldorm Cave', @@ -1215,6 +1224,10 @@ modes = { 'Waterfall of Wishing', 'Inverted Bomb Shop', 'Cave Shop (Dark Death Mountain)', 'Dark World Potion Shop', 'Dark World Lumberjack Shop', 'Dark World Shop', 'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Cave Shop (Lake Hylia)', + 'Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)', + 'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy', + 'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave', + 'Dark Desert Hint', 'Links House', 'Inverted Links House', 'Tavern North'] }, 'old_man_cave': { # have to do old man cave first so lw dungeon don't use up everything @@ -1254,16 +1267,13 @@ modes = { 'fixed_non_items': { 'special': 'vanilla', 'condition': '', - 'entrances': ['Dark Death Mountain Fairy', 'Dark Desert Fairy', 'Dark Desert Hint', 'Archery Game', + 'entrances': ['Dark Death Mountain Fairy', 'Dark Desert Fairy', 'Archery Game', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint', 'Bonk Fairy (Dark)', - 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Spike Cave', - 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Fairy', 'Dark Lake Hylia Shop', - 'Palace of Darkness Hint', 'East Dark World Hint', 'Hookshot Fairy', '50 Rupee Cave', - 'Kakariko Gamble Game', '20 Rupee Cave', 'Good Bee Cave', 'Long Fairy Cave', - 'Light World Bomb Hut', 'Tavern (Front)', 'Bush Covered House', 'Snitch Lady (West)', - 'Snitch Lady (East)', 'Fortune Teller (Light)', 'Lost Woods Gamble', 'Desert Fairy', - 'Light Hype Fairy', 'Lake Hylia Fortune Teller', 'Lake Hylia Fairy', 'Bonk Fairy (Light)', - 'Lumberjack House', 'Inverted Dark Sanctuary'], + 'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Fairy', + 'Dark Lake Hylia Shop', 'East Dark World Hint', 'Kakariko Gamble Game', 'Good Bee Cave', + 'Long Fairy Cave', 'Bush Covered House', 'Fortune Teller (Light)', 'Lost Woods Gamble', + 'Desert Fairy', 'Light Hype Fairy', 'Lake Hylia Fortune Teller', 'Lake Hylia Fairy', + 'Bonk Fairy (Light)', 'Inverted Dark Sanctuary'], }, 'fixed_shops': { 'special': 'vanilla', @@ -1272,7 +1282,16 @@ modes = { 'Dark World Shop', 'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Cave Shop (Lake Hylia)'], }, - 'item_caves': { # shuffles shops if they weren't fixed in the last one + 'fixed_pottery': { + 'special': 'vanilla', + 'condition': 'pottery', + 'entrances': ['Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)', + 'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy', + 'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave', + 'Dark Desert Hint'] + + }, + 'item_caves': { # shuffles shops/pottery if they weren't fixed in the last steps 'entrances': ['Mimic Cave', 'Spike Cave', 'Mire Shed', 'Dark World Hammer Peg Cave', 'Chest Game', 'C-Shaped House', 'Brewery', 'Hype Cave', 'Big Bomb Shop', 'Pyramid Fairy', 'Ice Rod Cave', 'Dam', 'Bonk Rock Cave', 'Library', 'Potion Shop', 'Mini Moldorm Cave', @@ -1281,6 +1300,10 @@ modes = { 'Waterfall of Wishing', 'Inverted Bomb Shop', 'Cave Shop (Dark Death Mountain)', 'Dark World Potion Shop', 'Dark World Lumberjack Shop', 'Dark World Shop', 'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Cave Shop (Lake Hylia)', + 'Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)', + 'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy', + 'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave', + 'Dark Desert Hint', 'Links House', 'Inverted Links House', 'Tavern North'] } } diff --git a/source/tools/MysteryUtils.py b/source/tools/MysteryUtils.py index d7e54098..5ca41b6d 100644 --- a/source/tools/MysteryUtils.py +++ b/source/tools/MysteryUtils.py @@ -115,12 +115,14 @@ def roll_settings(weights): ret.crystals_ganon = get_choice('ganon_open') - goal_min = get_choice_default('triforce_goal_min', default=20) - goal_max = get_choice_default('triforce_goal_max', default=20) - pool_min = get_choice_default('triforce_pool_min', default=30) - pool_max = get_choice_default('triforce_pool_max', default=30) + from ItemList import set_default_triforce + default_tf_goal, default_tf_pool = set_default_triforce(ret.goal, 0, 0) + goal_min = get_choice_default('triforce_goal_min', default=default_tf_goal) + goal_max = get_choice_default('triforce_goal_max', default=default_tf_goal) + pool_min = get_choice_default('triforce_pool_min', default=default_tf_pool) + pool_max = get_choice_default('triforce_pool_max', default=default_tf_pool) ret.triforce_goal = random.randint(int(goal_min), int(goal_max)) - min_diff = get_choice_default('triforce_min_difference', default=10) + min_diff = get_choice_default('triforce_min_difference', default=default_tf_pool-default_tf_goal) ret.triforce_pool = random.randint(max(int(pool_min), ret.triforce_goal + int(min_diff)), int(pool_max)) ret.mode = get_choice('world_state')