From 08ab32537bd6fae1ae0b2c44c928b8acd850a6e2 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 27 Oct 2021 01:19:01 -0500 Subject: [PATCH] Implemented Whirlpool Shuffle --- BaseClasses.py | 6 + CLI.py | 3 +- Main.py | 2 + Mystery.py | 1 + OWEdges.py | 104 +++++++---- OverworldShuffle.py | 166 +++++++++++++----- Rom.py | 7 +- data/base2current.bps | Bin 141069 -> 141107 bytes mystery_example.yml | 3 + resources/app/cli/args.json | 4 + resources/app/cli/lang/en.json | 3 + resources/app/gui/lang/en.json | 5 + .../app/gui/randomize/overworld/widgets.json | 4 + source/classes/constants.py | 1 + source/gui/randomize/overworld.py | 2 +- 15 files changed, 225 insertions(+), 86 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 9f75f702..b6484e83 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -26,6 +26,7 @@ class World(object): self.owCrossed = owCrossed.copy() self.owKeepSimilar = {} self.owMixed = owMixed.copy() + self.owWhirlpoolShuffle = {} self.owFluteShuffle = {} self.shuffle = shuffle.copy() self.doorShuffle = doorShuffle.copy() @@ -76,6 +77,7 @@ class World(object): self.spoiler = Spoiler(self) self.lamps_needed_for_dark_rooms = 1 self.owswaps = {} + self.owwhirlpools = {} self.owedges = [] self._owedge_cache = {} self.owflutespots = {} @@ -105,6 +107,7 @@ class World(object): set_player_attr('_region_cache', {}) set_player_attr('player_names', []) set_player_attr('owswaps', [[],[],[]]) + set_player_attr('owwhirlpools', []) set_player_attr('remote_items', False) set_player_attr('required_medallions', ['Ether', 'Quake']) set_player_attr('swamp_patch_required', False) @@ -2693,6 +2696,7 @@ class Spoiler(object): 'ow_crossed': self.world.owCrossed, 'ow_keepsimilar': self.world.owKeepSimilar, 'ow_mixed': self.world.owMixed, + 'ow_whirlpool': self.world.owWhirlpoolShuffle, 'ow_fluteshuffle': self.world.owFluteShuffle, 'shuffle': self.world.shuffle, 'shuffleganon': self.world.shuffle_ganon, @@ -2784,6 +2788,7 @@ class Spoiler(object): outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_keepsimilar'][player] else 'No')) outfile.write('Crossed OW:'.ljust(line_width) + '%s\n' % self.metadata['ow_crossed'][player]) outfile.write('Swapped OW (Mixed):'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_mixed'][player] else 'No')) + outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['ow_whirlpool'][player] else 'No')) outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player]) outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player]) outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % ('Yes' if self.metadata['shuffleganon'][player] else 'No')) @@ -2807,6 +2812,7 @@ class Spoiler(object): if self.startinventory: outfile.write('Starting Inventory:'.ljust(line_width)) outfile.write('\n'.ljust(line_width+1).join(self.startinventory)) + outfile.write('\n\nRequirements:\n\n') for dungeon, medallion in self.medallions.items(): outfile.write(f'{dungeon}:'.ljust(line_width) + '%s Medallion\n' % medallion) diff --git a/CLI.py b/CLI.py index 41b812f8..198325b7 100644 --- a/CLI.py +++ b/CLI.py @@ -94,7 +94,7 @@ def parse_cli(argv, no_defaults=False): playerargs = parse_cli(shlex.split(getattr(ret, f"p{player}")), True) for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', - 'ow_shuffle', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_fluteshuffle', + 'ow_shuffle', 'ow_crossed', 'ow_keepsimilar', 'ow_mixed', 'ow_whirlpool', 'ow_fluteshuffle', 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid', 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory', 'bombbag', 'shuffleganon', @@ -149,6 +149,7 @@ def parse_settings(): "ow_crossed": "none", "ow_keepsimilar": False, "ow_mixed": False, + "ow_whirlpool": False, "ow_fluteshuffle": "vanilla", "shuffle": "vanilla", "shufflelinks": False, diff --git a/Main.py b/Main.py index 34bcc656..9827efb1 100644 --- a/Main.py +++ b/Main.py @@ -87,6 +87,7 @@ def main(args, seed=None, fish=None): world.crystals_ganon_orig = args.crystals_ganon.copy() world.crystals_gt_orig = args.crystals_gt.copy() world.owKeepSimilar = args.ow_keepsimilar.copy() + world.owWhirlpoolShuffle = args.ow_whirlpool.copy() world.owFluteShuffle = args.ow_fluteshuffle.copy() world.open_pyramid = args.openpyramid.copy() world.boss_shuffle = args.shufflebosses.copy() @@ -406,6 +407,7 @@ def copy_world(world): ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() ret.crystals_gt_orig = world.crystals_gt_orig.copy() ret.owKeepSimilar = world.owKeepSimilar.copy() + ret.owWhirlpoolShuffle = world.owWhirlpoolShuffle.copy() ret.owFluteShuffle = world.owFluteShuffle.copy() ret.open_pyramid = world.open_pyramid.copy() ret.boss_shuffle = world.boss_shuffle.copy() diff --git a/Mystery.py b/Mystery.py index 933a4fc1..8f1b5158 100644 --- a/Mystery.py +++ b/Mystery.py @@ -138,6 +138,7 @@ def roll_settings(weights): ret.ow_crossed = get_choice('overworld_crossed') ret.ow_keepsimilar = get_choice('overworld_keepsimilar') == 'on' ret.ow_mixed = get_choice('overworld_swap') == 'on' + ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on' overworld_flute = get_choice('flute_shuffle') ret.ow_fluteshuffle = overworld_flute if overworld_flute != 'none' else 'vanilla' entrance_shuffle = get_choice('entrance_shuffle') diff --git a/OWEdges.py b/OWEdges.py index cfaa9c2c..b9064281 100644 --- a/OWEdges.py +++ b/OWEdges.py @@ -969,7 +969,7 @@ OWTileRegions = bidict({ }) OWTileGroups = { - ("Woods", "Regular"): ( + ("Woods", "Regular", "None"): ( [ 0x00, 0x2d, 0x80 ], @@ -977,7 +977,7 @@ OWTileGroups = { 0x40, 0x6d ] ), - ("Lumberjack", "Regular"): ( + ("Lumberjack", "Regular", "None"): ( [ 0x02 ], @@ -985,7 +985,7 @@ OWTileGroups = { 0x42 ] ), - ("West Mountain", "Regular"): ( + ("West Mountain", "Regular", "None"): ( [ 0x03 ], @@ -993,7 +993,7 @@ OWTileGroups = { 0x43 ] ), - ("East Mountain", "Regular"): ( + ("East Mountain", "Regular", "None"): ( [ 0x05 ], @@ -1001,23 +1001,31 @@ OWTileGroups = { 0x45 ] ), - ("East Mountain", "Entrance"): ( + ("East Mountain", "Entrance", "None"): ( [ - 0x07, + 0x07 ], [ 0x47 ] ), - ("Lake", "Regular"): ( + ("Lake", "Regular", "Zora"): ( [ - 0x0f, 0x35, 0x81 + 0x0f, 0x81 ], [ - 0x4f, 0x75 + 0x4f ] ), - ("Mountain Entry", "Regular"): ( + ("Lake", "Regular", "Lake"): ( + [ + 0x35 + ], + [ + 0x75 + ] + ), + ("Mountain Entry", "Regular", "None"): ( [ 0x0a ], @@ -1025,7 +1033,7 @@ OWTileGroups = { 0x4a ] ), - ("Woods Pass", "Regular"): ( + ("Woods Pass", "Regular", "None"): ( [ 0x10 ], @@ -1033,7 +1041,7 @@ OWTileGroups = { 0x50 ] ), - ("Fortune", "Regular"): ( + ("Fortune", "Regular", "None"): ( [ 0x11 ], @@ -1041,15 +1049,39 @@ OWTileGroups = { 0x51 ] ), - ("Whirlpools", "Regular"): ( + ("Whirlpools", "Regular", "Pond"): ( [ - 0x12, 0x15, 0x33, 0x3f + 0x12 ], [ - 0x52, 0x55, 0x73, 0x7f + 0x52 ] ), - ("Castle", "Entrance"): ( + ("Whirlpools", "Regular", "Witch"): ( + [ + 0x15 + ], + [ + 0x55 + ] + ), + ("Whirlpools", "Regular", "CWhirlpool"): ( + [ + 0x33 + ], + [ + 0x73 + ] + ), + ("Whirlpools", "Regular", "Southeast"): ( + [ + 0x3f + ], + [ + 0x7f + ] + ), + ("Castle", "Entrance", "None"): ( [ 0x13, 0x14 ], @@ -1057,7 +1089,7 @@ OWTileGroups = { 0x53, 0x54 ] ), - ("Castle", "Regular"): ( + ("Castle", "Regular", "None"): ( [ 0x1a, 0x1b ], @@ -1065,7 +1097,7 @@ OWTileGroups = { 0x5a, 0x5b ] ), - ("Witch", "Regular"): ( + ("Witch", "Regular", "None"): ( [ 0x16 ], @@ -1073,7 +1105,7 @@ OWTileGroups = { 0x56 ] ), - ("Water Approach", "Regular"): ( + ("Water Approach", "Regular", "None"): ( [ 0x17 ], @@ -1081,7 +1113,7 @@ OWTileGroups = { 0x57 ] ), - ("Village", "Regular"): ( + ("Village", "Regular", "None"): ( [ 0x18 ], @@ -1089,7 +1121,7 @@ OWTileGroups = { 0x58 ] ), - ("Wooden Bridge", "Regular"): ( + ("Wooden Bridge", "Regular", "None"): ( [ 0x1d ], @@ -1097,7 +1129,7 @@ OWTileGroups = { 0x5d ] ), - ("Eastern", "Regular"): ( + ("Eastern", "Regular", "None"): ( [ 0x1e ], @@ -1105,7 +1137,7 @@ OWTileGroups = { 0x5e ] ), - ("Blacksmith", "Regular"): ( + ("Blacksmith", "Regular", "None"): ( [ 0x22 ], @@ -1113,7 +1145,7 @@ OWTileGroups = { 0x62 ] ), - ("Dunes", "Regular"): ( + ("Dunes", "Regular", "None"): ( [ 0x25 ], @@ -1121,7 +1153,7 @@ OWTileGroups = { 0x65 ] ), - ("Game", "Regular"): ( + ("Game", "Regular", "None"): ( [ 0x28, 0x29 ], @@ -1129,7 +1161,7 @@ OWTileGroups = { 0x68, 0x69 ] ), - ("Grove", "Regular"): ( + ("Grove", "Regular", "None"): ( [ 0x2a ], @@ -1137,7 +1169,7 @@ OWTileGroups = { 0x6a ] ), - ("Central Bonk Rocks", "Regular"): ( + ("Central Bonk Rocks", "Regular", "None"): ( [ 0x2b ], @@ -1145,7 +1177,7 @@ OWTileGroups = { 0x6b ] ), - # ("Links", "Regular"): ( + # ("Links", "Regular", "None"): ( # [ # 0x2c # ], @@ -1153,7 +1185,7 @@ OWTileGroups = { # 0x6c # ] # ), - ("Tree Line", "Regular"): ( + ("Tree Line", "Regular", "None"): ( [ 0x2e ], @@ -1161,7 +1193,7 @@ OWTileGroups = { 0x6e ] ), - ("Nook", "Regular"): ( + ("Nook", "Regular", "None"): ( [ 0x2f ], @@ -1169,7 +1201,7 @@ OWTileGroups = { 0x6f ] ), - ("Desert", "Regular"): ( + ("Desert", "Regular", "None"): ( [ 0x30, 0x3a ], @@ -1177,7 +1209,7 @@ OWTileGroups = { 0x70, 0x7a ] ), - ("Grove Approach", "Regular"): ( + ("Grove Approach", "Regular", "None"): ( [ 0x32 ], @@ -1185,7 +1217,7 @@ OWTileGroups = { 0x72 ] ), - ("Hype", "Regular"): ( + ("Hype", "Regular", "None"): ( [ 0x34 ], @@ -1193,7 +1225,7 @@ OWTileGroups = { 0x74 ] ), - ("Shopping Mall", "Regular"): ( + ("Shopping Mall", "Regular", "None"): ( [ 0x37 ], @@ -1201,7 +1233,7 @@ OWTileGroups = { 0x77 ] ), - ("Swamp", "Regular"): ( + ("Swamp", "Regular", "None"): ( [ 0x3b ], @@ -1209,7 +1241,7 @@ OWTileGroups = { 0x7b ] ), - ("South Pass", "Regular"): ( + ("South Pass", "Regular", "None"): ( [ 0x3c ], diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 89ada285..9ed24210 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -187,6 +187,44 @@ def link_overworld(world, player): trimmed_groups = performSwap(trimmed_groups, crossed_edges) assert len(crossed_edges) == 0, 'Not all edges were crossed successfully: ' + ', '.join(crossed_edges) + # whirlpool shuffle + logging.getLogger('').debug('Shuffling whirlpools') + + if not world.owWhirlpoolShuffle[player]: + for (_, from_whirlpool, from_region), (_, to_whirlpool, to_region) in default_whirlpool_connections: + connect_simple(world, from_whirlpool, to_region, player) + connect_simple(world, to_whirlpool, from_region, player) + else: + whirlpool_candidates = [[],[]] + for (from_owid, from_whirlpool, from_region), (to_owid, to_whirlpool, to_region) in default_whirlpool_connections: + if world.owCrossed[player] != 'none': + whirlpool_candidates[0].append(tuple((from_owid, from_whirlpool, from_region))) + whirlpool_candidates[0].append(tuple((to_owid, to_whirlpool, to_region))) + else: + if world.get_region(from_region, player).type == RegionType.LightWorld: + whirlpool_candidates[0].append(tuple((from_owid, from_whirlpool, from_region))) + else: + whirlpool_candidates[1].append(tuple((from_owid, from_whirlpool, from_region))) + + if world.get_region(to_region, player).type == RegionType.LightWorld: + whirlpool_candidates[0].append(tuple((to_owid, to_whirlpool, to_region))) + else: + whirlpool_candidates[1].append(tuple((to_owid, to_whirlpool, to_region))) + + # shuffle happens here + world.owwhirlpools[player] = [None] * 8 + whirlpool_map = [ 0x35, 0x0f, 0x15, 0x33, 0x12, 0x3f, 0x55, 0x7f ] + for whirlpools in whirlpool_candidates: + random.shuffle(whirlpools) + while len(whirlpools): + from_owid, from_whirlpool, from_region = whirlpools.pop() + to_owid, to_whirlpool, to_region = whirlpools.pop() + connect_simple(world, from_whirlpool, to_region, player) + connect_simple(world, to_whirlpool, from_region, player) + world.owwhirlpools[player][next(i for i, v in enumerate(whirlpool_map) if v == to_owid)] = from_owid + world.owwhirlpools[player][next(i for i, v in enumerate(whirlpool_map) if v == from_owid)] = to_owid + world.spoiler.set_overworld(from_whirlpool, to_whirlpool, 'both', player) + # layout shuffle logging.getLogger('').debug('Shuffling overworld layout') connected_edges = [] @@ -387,22 +425,33 @@ def connect_two_way(world, edgename1, edgename2, player, connected_edges=None): def shuffle_tiles(world, groups, result_list, player): swapped_edges = list() + valid_whirlpool_parity = False - # tile shuffle happens here - removed = list() - for group in groups.keys(): - if random.randint(0, 1): - removed.append(group) - - # save shuffled tiles to list - for group in groups.keys(): - if group not in removed: - (owids, lw_regions, dw_regions) = groups[group] - (exist_owids, exist_lw_regions, exist_dw_regions) = result_list - exist_owids.extend(owids) - exist_lw_regions.extend(lw_regions) - exist_dw_regions.extend(dw_regions) - result_list = [exist_owids, exist_lw_regions, exist_dw_regions] + while not valid_whirlpool_parity: + # tile shuffle happens here + removed = list() + for group in groups.keys(): + # if group[0] in ['Links', 'Central Bonk Rocks', 'Castle']: # TODO: Standard + Inverted + if random.randint(0, 1): + removed.append(group) + + # save shuffled tiles to list + new_results = [[],[],[]] + for group in groups.keys(): + if group not in removed: + (owids, lw_regions, dw_regions) = groups[group] + (exist_owids, exist_lw_regions, exist_dw_regions) = new_results + exist_owids.extend(owids) + exist_lw_regions.extend(lw_regions) + exist_dw_regions.extend(dw_regions) + + # check whirlpool parity + valid_whirlpool_parity = world.owCrossed[player] != 'none' or len(set(new_results[0]) & set({0x0f, 0x12, 0x15, 0x33, 0x35, 0x3f, 0x55, 0x7f})) % 2 == 0 + + (exist_owids, exist_lw_regions, exist_dw_regions) = result_list + exist_owids.extend(new_results[0]) + exist_lw_regions.extend(new_results[1]) + exist_dw_regions.extend(new_results[2]) # replace LW edges with DW ignore_list = list() #TODO: Remove ignore_list when special OW areas are included in pool @@ -426,36 +475,62 @@ def shuffle_tiles(world, groups, result_list, player): def reorganize_tile_groups(world, player): groups = {} - for (name, groupType) in OWTileGroups.keys(): + for (name, groupType, whirlpoolGroup) in OWTileGroups.keys(): if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks'] \ or (world.mode[player] == 'standard' and world.shuffle[player] in ['lite', 'lean', 'crossed', 'insanity'] and name == 'Castle' and groupType == 'Entrance'): if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'simple', 'restricted']: - groups[(name,)] = ([], [], []) + if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none': + groups[(name, whirlpoolGroup)] = ([], [], []) + else: + groups[(name,)] = ([], [], []) else: - groups[(name, groupType)] = ([], [], []) + if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none': + groups[(name, groupType, whirlpoolGroup)] = ([], [], []) + else: + groups[(name, groupType)] = ([], [], []) - for (name, groupType) in OWTileGroups.keys(): + for (name, groupType, whirlpoolGroup) in OWTileGroups.keys(): if world.mode[player] != 'standard' or name not in ['Castle', 'Links', 'Central Bonk Rocks'] \ or (world.mode[player] == 'standard' and world.shuffle[player] in ['lite', 'lean', 'crossed', 'insanity'] and name == 'Castle' and groupType == 'Entrance'): - (lw_owids, dw_owids) = OWTileGroups[(name, groupType,)] + (lw_owids, dw_owids) = OWTileGroups[(name, groupType, whirlpoolGroup)] if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull', 'simple', 'restricted']: - (exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name,)] - exist_owids.extend(lw_owids) - exist_owids.extend(dw_owids) - for owid in lw_owids: - exist_lw_regions.extend(OWTileRegions.inverse[owid]) - for owid in dw_owids: - exist_dw_regions.extend(OWTileRegions.inverse[owid]) - groups[(name,)] = (exist_owids, exist_lw_regions, exist_dw_regions) + if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none': + (exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, whirlpoolGroup)] + exist_owids.extend(lw_owids) + exist_owids.extend(dw_owids) + for owid in lw_owids: + exist_lw_regions.extend(OWTileRegions.inverse[owid]) + for owid in dw_owids: + exist_dw_regions.extend(OWTileRegions.inverse[owid]) + groups[(name, whirlpoolGroup)] = (exist_owids, exist_lw_regions, exist_dw_regions) + else: + (exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name,)] + exist_owids.extend(lw_owids) + exist_owids.extend(dw_owids) + for owid in lw_owids: + exist_lw_regions.extend(OWTileRegions.inverse[owid]) + for owid in dw_owids: + exist_dw_regions.extend(OWTileRegions.inverse[owid]) + groups[(name,)] = (exist_owids, exist_lw_regions, exist_dw_regions) else: - (exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, groupType)] - exist_owids.extend(lw_owids) - exist_owids.extend(dw_owids) - for owid in lw_owids: - exist_lw_regions.extend(OWTileRegions.inverse[owid]) - for owid in dw_owids: - exist_dw_regions.extend(OWTileRegions.inverse[owid]) - groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions) + if world.owWhirlpoolShuffle[player] or world.owCrossed[player] != 'none': + (exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, groupType, whirlpoolGroup)] + exist_owids.extend(lw_owids) + exist_owids.extend(dw_owids) + for owid in lw_owids: + exist_lw_regions.extend(OWTileRegions.inverse[owid]) + for owid in dw_owids: + exist_dw_regions.extend(OWTileRegions.inverse[owid]) + groups[(name, groupType, whirlpoolGroup)] = (exist_owids, exist_lw_regions, exist_dw_regions) + else: + (exist_owids, exist_lw_regions, exist_dw_regions) = groups[(name, groupType)] + exist_owids.extend(lw_owids) + exist_owids.extend(dw_owids) + for owid in lw_owids: + exist_lw_regions.extend(OWTileRegions.inverse[owid]) + for owid in dw_owids: + exist_dw_regions.extend(OWTileRegions.inverse[owid]) + groups[(name, groupType)] = (exist_owids, exist_lw_regions, exist_dw_regions) return groups def remove_reserved(world, groupedlist, connected_edges, player): @@ -733,17 +808,7 @@ temporary_mandatory_connections = [ ] # these are connections that cannot be shuffled and always exist. They link together separate parts of the world we need to divide into regions -mandatory_connections = [# Whirlpool Connections - ('C Whirlpool', 'River Bend Water'), - ('River Bend Whirlpool', 'C Whirlpool Water'), - ('Lake Hylia Whirlpool', 'Zora Waterfall Water'), - ('Zora Whirlpool', 'Lake Hylia Water'), - ('Kakariko Pond Whirlpool', 'Octoballoon Water'), - ('Octoballoon Whirlpool', 'Kakariko Pond Area'), - ('Qirn Jump Whirlpool', 'Bomber Corner Water'), - ('Bomber Corner Whirlpool', 'Qirn Jump Water'), - - # Intra-tile OW Connections +mandatory_connections = [# Intra-tile OW Connections ('Lost Woods Bush (West)', 'Lost Woods East Area'), #pearl ('Lost Woods Bush (East)', 'Lost Woods West Area'), #pearl ('West Death Mountain Drop', 'West Death Mountain (Bottom)'), @@ -967,6 +1032,13 @@ mandatory_connections = [# Whirlpool Connections ('Dark Tree Line WC Cliff Water Drop', 'Dark Tree Line Water') #fake flipper ] +default_whirlpool_connections = [ + ((0x33, 'C Whirlpool', 'C Whirlpool Water'), (0x15, 'River Bend Whirlpool', 'River Bend Water')), + ((0x35, 'Lake Hylia Whirlpool', 'Lake Hylia Water'), (0x0f, 'Zora Whirlpool', 'Zora Waterfall Water')), + ((0x12, 'Kakariko Pond Whirlpool', 'Kakariko Pond Area'), (0x3f, 'Octoballoon Whirlpool', 'Octoballoon Water')), + ((0x55, 'Qirn Jump Whirlpool', 'Qirn Jump Water'), (0x7f, 'Bomber Corner Whirlpool', 'Bomber Corner Water')) +] + default_flute_connections = [ 0x0b, 0x16, 0x18, 0x2c, 0x2f, 0x38, 0x3b, 0x3f ] diff --git a/Rom.py b/Rom.py index 58cd90bc..5be364ec 100644 --- a/Rom.py +++ b/Rom.py @@ -33,7 +33,7 @@ from source.classes.SFX import randomize_sfx JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'c6c2a2d5d89a3c84871f58806bbb3acf' +RANDOMIZERBASEHASH = 'e9dea70e0a0b15bfa0ff7ecd63228a0c' class JsonRom(object): @@ -644,6 +644,11 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): rom.write_byte(snes_to_pc(0x0AB793 + o), data[11] & 0xff) # Y low byte rom.write_byte(snes_to_pc(0x0AB79B + o), data[11] // 0x100) # Y high byte + # patch whirlpools + if world.owWhirlpoolShuffle[player]: + owFlags |= 0x01 + write_int16s(rom, snes_to_pc(0x02EA5C), world.owwhirlpools[player]) + # patch overworld edges inverted_buffer = [0] * 0x82 owMode = 0 diff --git a/data/base2current.bps b/data/base2current.bps index daf77e69ccf89d2044d3fcf39dae204306a0edd0..aa914956d578657a299b8406d23a1e7e69766b86 100644 GIT binary patch delta 293 zcmV+=0owkJ&Iq&42(U>31oI6H^0Q3=kpc)Pf{8_lsu+&5-~;gk0h_bZ2m1s8cazQx z7XeqZ<_xO!6-|HuYa(pw0E$$w1HssR5I! zuW3c5i5P1*SGkwn0s%q-1Xs5q0|A@@0eP3c1py!p1*QcchLfcQg^I#3V3*+q0VO9M z5T>n3K*>PR6Qy0r1n>l_UwEdSfDNTx$rsQ9p9_GaB}(*j-$b`H1_8VR2RIL44=4ak zm-q+)ISZ`>0B{eG4v delta 273 zcmV+s0q*{@&Ipap2(U>31V9b7%kpcoxk+bFl@dE*gv)Bjw1Q}(Bs_H<9og$u? zpdwbsq?R2=n(Gx-l8HsL>bj=oB{z+m(~RVAOlsV1(yQ`0VOXA5T>n3K*>PR6Qy0r1n>l_ zOL(T8fDNTx$rsQ9n+t%Mr3HnG!Z2W?BTDoG;5@fa1_8VR2XGIN4