diff --git a/BaseClasses.py b/BaseClasses.py index 551d4957..e37b8d47 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3123,7 +3123,7 @@ class Spoiler(object): outfile.write('Pseudoboots:'.ljust(line_width) + '%s\n' % yn(self.metadata['pseudoboots'][player])) outfile.write('Overworld Layout Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_shuffle'][player]) outfile.write('Crossed OW:'.ljust(line_width) + '%s\n' % self.metadata['ow_crossed'][player]) - if self.metadata['ow_shuffle'][player] != 'vanilla' or self.metadata['ow_crossed'][player] not in ['none', 'allowed']: + if self.metadata['ow_shuffle'][player] != 'vanilla' or self.metadata['ow_crossed'][player] != 'none': outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_keepsimilar'][player])) outfile.write('Swapped OW (Mixed):'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_mixed'][player])) outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_whirlpool'][player])) diff --git a/Bosses.py b/Bosses.py index 53393d5f..a42b5176 100644 --- a/Bosses.py +++ b/Bosses.py @@ -202,12 +202,14 @@ def place_bosses(world, player): place_boss(boss, level, loc, loc_text, world, player) elif world.boss_shuffle[player] == 'unique': bosses = list(placeable_bosses) + gt_bosses = list() for [loc, level] in boss_locations: loc_text = loc + (' ('+level+')' if level else '') try: if level: - boss = random.choice([b for b in placeable_bosses if can_place_boss(world, player, b, loc, level)]) + boss = random.choice([b for b in placeable_bosses if can_place_boss(world, player, b, loc, level) and b not in gt_bosses]) + gt_bosses.append(boss) else: boss = random.choice([b for b in bosses if can_place_boss(world, player, b, loc, level)]) bosses.remove(boss) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe3f74df..1755913e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### 0.2.9.1 +- Lite/Lean ER now includes Cave Pot locations with various Pottery options +- Changed Unique Boss Shuffle so that GT Bosses are unique amongst themselves +- Changed MSU-1 in Inverted to trigger DW2 track with Aga1 kill and LW2 with 7 crystals +- Fixed disappearing mirror portal issue in Inverted (Hopefully for good) +- Fixed issue with TR Peg Puzzle not spawning portal in some Mixed OWR scenarios +- Removed ability to roll Myserty with phantom Crossed OWR options + ### 0.2.9.0 - Added Bonk Drop Shuffle - Fixed disappearing mirror portal issue in Inverted+Crossed OWR diff --git a/EntranceShuffle.py b/EntranceShuffle.py index dc48acdc..b15a7438 100644 --- a/EntranceShuffle.py +++ b/EntranceShuffle.py @@ -73,7 +73,7 @@ def link_entrances(world, player): # if we do not shuffle, set default connections if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']: - for entrancename, exitname in default_connections + drop_connections + default_item_connections + default_shop_connections: + for entrancename, exitname in default_connections + default_pot_connections + drop_connections + default_item_connections + default_shop_connections: connect_logical(world, entrancename, exitname, player, exitname.endswith(' Exit')) for entrancename, exitname in default_connector_connections + dropexit_connections: connect_logical(world, entrancename, exitname, player, True) @@ -341,7 +341,7 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, list(entrance_pool), list(exit_pool), player) elif world.shuffle[player] == 'lite': - for entrancename, exitname in default_connections + ([] if world.shopsanity[player] else default_shop_connections): + for entrancename, exitname in default_connections + ([] if world.shopsanity[player] else default_shop_connections) + ([] if world.pottery[player] not in ['none', 'keys', 'dungeon'] else default_pot_connections): connect_logical(world, entrancename, exitname, player, False) if invFlag: world.get_entrance('Dark Sanctuary Hint Exit', player).connect(world.get_entrance('Dark Sanctuary Hint', player).parent_region) @@ -433,7 +433,7 @@ def link_entrances(world, player): # place remaining doors connect_doors(world, list(entrance_pool), list(exit_pool), player) elif world.shuffle[player] == 'lean': - for entrancename, exitname in default_connections + ([] if world.shopsanity[player] else default_shop_connections): + for entrancename, exitname in default_connections + ([] if world.shopsanity[player] else default_shop_connections) + ([] if world.pottery[player] not in ['none', 'keys', 'dungeon'] else default_pot_connections): connect_logical(world, entrancename, exitname, player, False) if invFlag: world.get_entrance('Dark Sanctuary Hint Exit', player).connect(world.get_entrance('Dark Sanctuary Hint', player).parent_region) @@ -1356,7 +1356,7 @@ def place_links_house(world, player, ignore_list=[]): else: links_house_doors = [i for i in get_starting_entrances(world, player, world.shuffle[player] != 'insanity') if i in entrance_pool] if world.shuffle[player] in ['lite', 'lean']: - links_house_doors = [e for e in links_house_doors if e in list(zip(*(default_item_connections + (default_shop_connections if world.shopsanity[player] else []))))[0]] + links_house_doors = [e for e in links_house_doors if e in list(zip(*(default_item_connections + (default_shop_connections if world.shopsanity[player] else []) + (default_pot_connections if world.pottery[player] not in ['none', 'keys', 'dungeon'] else []))))[0]] #TODO: Need to improve Links House placement to choose a better sector or eliminate entrances that are after ledge drops links_house_doors = [e for e in links_house_doors if e not in ignore_list] @@ -1404,7 +1404,7 @@ def place_blacksmith(world, links_house, player): sanc_region = world.get_entrance('Sanctuary Exit', player).connected_region.name blacksmith_doors = list(OrderedDict.fromkeys(blacksmith_doors + list(build_accessible_entrance_list(world, sanc_region, player, assumed_inventory, False, True, True)))) if world.shuffle[player] in ['lite', 'lean']: - blacksmith_doors = [e for e in blacksmith_doors if e in list(zip(*(default_item_connections + (default_shop_connections if world.shopsanity[player] else []))))[0]] + blacksmith_doors = [e for e in blacksmith_doors if e in list(zip(*(default_item_connections + (default_shop_connections if world.shopsanity[player] else []) + (default_pot_connections if world.pottery[player] not in ['none', 'keys', 'dungeon'] else []))))[0]] assert len(blacksmith_doors), 'No valid candidates to place Blacksmiths Hut' blacksmith_hut = random.choice(blacksmith_doors) @@ -1472,7 +1472,7 @@ def junk_fill_inaccessible(world, player): if not exit.connected_region and exit.name in entrance_pool: inaccessible_entrances.append(exit.name) - junk_locations = [e for e in list(zip(*default_connections))[1] if e in exit_pool] + junk_locations = [e for e in list(zip(*(default_connections + ([] if world.pottery[player] not in ['none', 'keys', 'dungeon'] else default_pot_connections))))[1] if e in exit_pool] random.shuffle(junk_locations) for entrance in inaccessible_entrances: connect_entrance(world, entrance, junk_locations.pop(), player) @@ -2089,41 +2089,43 @@ mandatory_connections = [('Old Man S&Q', 'Old Man House'), ] # non-shuffled entrance links -default_connections = [('Lumberjack House', 'Lumberjack House'), - ('Bonk Fairy (Light)', 'Bonk Fairy (Light)'), +default_connections = [('Bonk Fairy (Light)', 'Bonk Fairy (Light)'), ('Lake Hylia Fairy', 'Lake Hylia Healer Fairy'), ('Lake Hylia Fortune Teller', 'Lake Hylia Fortune Teller'), ('Light Hype Fairy', 'Swamp Healer Fairy'), ('Desert Fairy', 'Desert Healer Fairy'), ('Lost Woods Gamble', 'Lost Woods Gamble'), ('Fortune Teller (Light)', 'Fortune Teller (Light)'), - ('Snitch Lady (East)', 'Snitch Lady (East)'), - ('Snitch Lady (West)', 'Snitch Lady (West)'), ('Bush Covered House', 'Bush Covered House'), - ('Tavern (Front)', 'Tavern (Front)'), - ('Light World Bomb Hut', 'Light World Bomb Hut'), ('Long Fairy Cave', 'Long Fairy Cave'), # near East Light World Teleporter ('Good Bee Cave', 'Good Bee Cave'), - ('20 Rupee Cave', '20 Rupee Cave'), - ('50 Rupee Cave', '50 Rupee Cave'), ('Kakariko Gamble Game', 'Kakariko Gamble Game'), - ('Hookshot Fairy', 'Hookshot Fairy'), ('East Dark World Hint', 'East Dark World Hint'), - ('Palace of Darkness Hint', 'Palace of Darkness Hint'), ('Dark Lake Hylia Fairy', 'Dark Lake Hylia Healer Fairy'), ('Dark Lake Hylia Ledge Fairy', 'Dark Lake Hylia Ledge Healer Fairy'), - ('Dark Lake Hylia Ledge Spike Cave', 'Dark Lake Hylia Ledge Spike Cave'), ('Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Ledge Hint'), ('Bonk Fairy (Dark)', 'Bonk Fairy (Dark)'), ('Dark Sanctuary Hint', 'Dark Sanctuary Hint'), ('Fortune Teller (Dark)', 'Fortune Teller (Dark)'), ('Archery Game', 'Archery Game'), - ('Dark Desert Hint', 'Dark Desert Hint'), ('Dark Desert Fairy', 'Dark Desert Healer Fairy'), ('Dark Death Mountain Fairy', 'Dark Death Mountain Healer Fairy'), ] +default_pot_connections = [('Lumberjack House', 'Lumberjack House'), + ('Snitch Lady (East)', 'Snitch Lady (East)'), + ('Snitch Lady (West)', 'Snitch Lady (West)'), + ('Tavern (Front)', 'Tavern (Front)'), + ('Light World Bomb Hut', 'Light World Bomb Hut'), + ('20 Rupee Cave', '20 Rupee Cave'), + ('50 Rupee Cave', '50 Rupee Cave'), + ('Hookshot Fairy', 'Hookshot Fairy'), + ('Palace of Darkness Hint', 'Palace of Darkness Hint'), + ('Dark Lake Hylia Ledge Spike Cave', 'Dark Lake Hylia Ledge Spike Cave'), + ('Dark Desert Hint', 'Dark Desert Hint') + ] + default_connector_connections = [('Old Man Cave (West)', 'Old Man Cave Exit (West)'), ('Old Man Cave (East)', 'Old Man Cave Exit (East)'), ('Old Man House (Bottom)', 'Old Man House Exit (Bottom)'), diff --git a/Mystery.py b/Mystery.py index 1a02d10d..e1be0eb7 100644 --- a/Mystery.py +++ b/Mystery.py @@ -168,7 +168,9 @@ def roll_settings(weights): overworld_shuffle = get_choice('overworld_shuffle') ret.ow_shuffle = overworld_shuffle if overworld_shuffle != 'none' else 'vanilla' + valid_options = {'none', 'polar', 'grouped', 'limited', 'chaos'} ret.ow_crossed = get_choice('overworld_crossed') + ret.ow_crossed = ret.ow_crossed if ret.ow_crossed in valid_options else 'none' ret.ow_keepsimilar = get_choice('overworld_keepsimilar') == 'on' ret.ow_mixed = get_choice('overworld_swap') == 'on' ret.ow_whirlpool = get_choice('whirlpool_shuffle') == 'on' diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 5ff3ab56..994fec9a 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -6,8 +6,10 @@ from Regions import mark_dark_world_regions, mark_light_world_regions from OWEdges import OWTileRegions, OWEdgeGroups, OWExitTypes, OpenStd, parallel_links, IsParallel from Utils import bidict -version_number = '0.2.9.0' +version_number = '0.2.9.1' +# branch indicator is intentionally different across branches version_branch = '' + __version__ = '%s%s' % (version_number, version_branch) def link_overworld(world, player): diff --git a/Rom.py b/Rom.py index 688c0274..63b5577c 100644 --- a/Rom.py +++ b/Rom.py @@ -38,7 +38,7 @@ from source.dungeon.RoomList import Room0127 JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '0574a782e225a87b90637db0847c5ae0' +RANDOMIZERBASEHASH = '92a390672efafb652774c1514ac66c4b' class JsonRom(object): diff --git a/asm/owrando.asm b/asm/owrando.asm index 07ab9f55..04ffd047 100644 --- a/asm/owrando.asm +++ b/asm/owrando.asm @@ -270,11 +270,11 @@ OWMirrorSpriteRestore: } OWLightWorldOrCrossed: { - lda.l OWMode+1 : and.b #!FLAG_OW_CROSSED : beq + + lda.l OWMode+1 : and.b #!FLAG_OW_CROSSED : beq ++ lda.l InvertedMode : beq + - lda #$40 : rtl - + lda #$00 : rtl - + jsl OWWorldCheck : rtl + lda #$40 + + rtl + ++ jsl OWWorldCheck : rtl } OWFluteCancel: diff --git a/data/base2current.bps b/data/base2current.bps index b48472f3..c6d73f65 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ