Start in BBS in Inverted, replacing LH/BBS entrance swap

This commit is contained in:
codemann8
2022-01-13 19:49:08 -06:00
parent f083a41045
commit af00bdec1e
5 changed files with 109 additions and 80 deletions

View File

@@ -1661,7 +1661,7 @@ class Entrance(object):
# this is checked first as this often the shortest path # this is checked first as this often the shortest path
follower_region = start_region follower_region = start_region
if follower_region.type not in [RegionType.LightWorld, RegionType.DarkWorld]: if follower_region.type not in [RegionType.LightWorld, RegionType.DarkWorld]:
follower_region = start_region.entrances[0].parent_region follower_region = [i for i in start_region.entrances if i.parent_region.name != 'Menu'][0].parent_region
if (follower_region.world.mode[self.player] != 'inverted') == (follower_region.type == RegionType.LightWorld): if (follower_region.world.mode[self.player] != 'inverted') == (follower_region.type == RegionType.LightWorld):
from OWEdges import OWTileRegions from OWEdges import OWTileRegions
from OverworldShuffle import ow_connections from OverworldShuffle import ow_connections

View File

@@ -1815,10 +1815,7 @@ def remove_pair_type_if_present(door, world, player):
def find_inaccessible_regions(world, player): def find_inaccessible_regions(world, player):
world.inaccessible_regions[player] = [] world.inaccessible_regions[player] = []
if world.mode[player] != 'inverted': start_regions = ['Links House' if not world.is_tile_swapped(0x2c, player) else 'Big Bomb Shop', 'Sanctuary' if world.mode[player] != 'inverted' else 'Dark Sanctuary Hint']
start_regions = ['Links House', 'Sanctuary']
else:
start_regions = ['Links House', 'Dark Sanctuary Hint']
regs = convert_regions(start_regions, world, player) regs = convert_regions(start_regions, world, player)
all_regions = [r for r in world.regions if r.player == player and r.type is not RegionType.Dungeon] all_regions = [r for r in world.regions if r.player == player and r.type is not RegionType.Dungeon]
visited_regions = set() visited_regions = set()

View File

@@ -54,32 +54,32 @@ def link_entrances(world, player):
for exitname, regionname in mandatory_connections: for exitname, regionname in mandatory_connections:
connect_simple(world, exitname, regionname, player) connect_simple(world, exitname, regionname, player)
if not invFlag: if not world.is_tile_swapped(0x2c, player):
for exitname, regionname in open_mandatory_connections: connect_simple(world, 'Links House S&Q', 'Links House', player)
connect_simple(world, exitname, regionname, player)
else: else:
for exitname, regionname in inverted_mandatory_connections: connect_simple(world, 'Links House S&Q', 'Big Bomb Shop', player)
connect_simple(world, exitname, regionname, player)
if not invFlag:
connect_simple(world, 'Sanctuary S&Q', 'Sanctuary', player)
else:
connect_simple(world, 'Sanctuary S&Q', 'Dark Sanctuary Hint', player)
connect_simple(world, 'Tavern North', 'Tavern', player) connect_simple(world, 'Tavern North', 'Tavern', player)
suppress_spoiler = False
connect_custom(world, player) connect_custom(world, player)
suppress_spoiler = True
# if we do not shuffle, set default connections # if we do not shuffle, set default connections
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']: 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 + drop_connections + default_item_connections + default_shop_connections:
connect_logical(world, entrancename, exitname, player, False) connect_logical(world, entrancename, exitname, player, exitname.endswith(' Exit'))
for entrancename, exitname in default_connector_connections + dropexit_connections: for entrancename, exitname in default_connector_connections + dropexit_connections:
connect_logical(world, entrancename, exitname, player, True) connect_logical(world, entrancename, exitname, player, True)
if invFlag: if invFlag:
world.get_entrance('Dark Sanctuary Hint Exit', player).connect(world.get_entrance('Dark Sanctuary Hint', player).parent_region) world.get_entrance('Dark Sanctuary Hint Exit', player).connect(world.get_entrance('Dark Sanctuary Hint', player).parent_region)
if world.is_tile_swapped(0x2c, player):
if not invFlag: world.get_entrance('Big Bomb Shop Exit', player).connect(world.get_entrance('Big Bomb Shop', player).parent_region)
for entrancename, exitname in open_default_connections:
connect_logical(world, entrancename, exitname, player, exitname.endswith(' Exit'))
else:
for entrancename, exitname in inverted_default_connections:
connect_logical(world, entrancename, exitname, player, exitname.endswith(' Exit'))
ignore_pool = False ignore_pool = False
@@ -215,6 +215,7 @@ def link_entrances(world, player):
junk_fill_inaccessible(world, player) junk_fill_inaccessible(world, player)
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
@@ -260,6 +261,7 @@ def link_entrances(world, player):
place_old_man(world, lw_entrances if not invFlag else dw_entrances, player) place_old_man(world, lw_entrances if not invFlag else dw_entrances, player)
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
@@ -317,6 +319,7 @@ def link_entrances(world, player):
place_old_man(world, lw_entrances if not invFlag else dw_entrances, player, list(zip(*drop_connections + dropexit_connections))[0]) place_old_man(world, lw_entrances if not invFlag else dw_entrances, player, list(zip(*drop_connections + dropexit_connections))[0])
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = [e for e in entrance_pool if e not in list(zip(*drop_connections + dropexit_connections))[0]] bomb_shop_doors = [e for e in entrance_pool if e not in list(zip(*drop_connections + dropexit_connections))[0]]
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in bomb_shop_doors if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in bomb_shop_doors if e not in ['Pyramid Fairy']]
@@ -419,6 +422,7 @@ def link_entrances(world, player):
connect_caves(world, lw_entrances, dw_entrances, caves, player) connect_caves(world, lw_entrances, dw_entrances, caves, player)
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
@@ -473,6 +477,7 @@ def link_entrances(world, player):
connect_caves(world, connector_entrances, [], caves, player) connect_caves(world, connector_entrances, [], caves, player)
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
@@ -522,6 +527,7 @@ def link_entrances(world, player):
place_old_man(world, pool, player) place_old_man(world, pool, player)
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
@@ -605,6 +611,7 @@ def link_entrances(world, player):
caves.append('Old Man Cave Exit (West)') caves.append('Old Man Cave Exit (West)')
# place bomb shop, has limited options # place bomb shop, has limited options
if not world.is_tile_swapped(0x2c, player):
bomb_shop_doors = list(entrance_pool) bomb_shop_doors = list(entrance_pool)
if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player): if world.logic[player] in ['noglitches', 'minorglitches'] or world.is_tile_swapped(0x1b, player):
bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']] bomb_shop_doors = [e for e in entrance_pool if e not in ['Pyramid Fairy']]
@@ -635,8 +642,8 @@ def link_entrances(world, player):
# ensure Houlihan exits where Links House does # ensure Houlihan exits where Links House does
# TODO: Plando should overrule this # TODO: Plando should overrule this
if not links_house: if not links_house:
for links_house in world.get_entrance('Links House Exit', player).connected_region.exits: for links_house in world.get_entrance('Links House Exit' if not world.is_tile_swapped(0x2c, player) else 'Big Bomb Shop Exit', player).connected_region.exits:
if links_house.connected_region and links_house.connected_region.name == 'Links House': if links_house.connected_region and links_house.connected_region.name == ('Links House' if not world.is_tile_swapped(0x2c, player) else 'Big Bomb Shop'):
links_house = links_house.name links_house = links_house.name
break break
connect_exit(world, 'Chris Houlihan Room Exit', links_house, player) connect_exit(world, 'Chris Houlihan Room Exit', links_house, player)
@@ -1335,7 +1342,7 @@ def full_shuffle_dungeons(world, Dungeon_Exits, player):
def place_links_house(world, player, ignore_list=[]): def place_links_house(world, player, ignore_list=[]):
invFlag = world.mode[player] == 'inverted' invFlag = world.mode[player] == 'inverted'
if world.mode[player] == 'standard' or not world.shufflelinks[player]: if world.mode[player] == 'standard' or not world.shufflelinks[player]:
links_house = 'Links House' if not invFlag else 'Big Bomb Shop' links_house = 'Links House' if not world.is_tile_swapped(0x2c, player) else 'Big Bomb Shop'
else: else:
if invFlag: if invFlag:
for dark_sanc in world.get_entrance('Dark Sanctuary Hint Exit', player).connected_region.exits: for dark_sanc in world.get_entrance('Dark Sanctuary Hint Exit', player).connected_region.exits:
@@ -1354,7 +1361,11 @@ def place_links_house(world, player, ignore_list=[]):
links_house_doors = [e for e in links_house_doors if e not in ignore_list] links_house_doors = [e for e in links_house_doors if e not in ignore_list]
assert len(links_house_doors), 'No valid candidates to place Links House' assert len(links_house_doors), 'No valid candidates to place Links House'
links_house = random.choice(links_house_doors) links_house = random.choice(links_house_doors)
if not world.is_tile_swapped(0x2c, player):
connect_two_way(world, links_house, 'Links House Exit', player) connect_two_way(world, links_house, 'Links House Exit', player)
else:
connect_entrance(world, links_house, 'Big Bomb Shop', player)
world.get_entrance('Big Bomb Shop Exit', player).connect(world.get_entrance(links_house, player).parent_region)
return links_house return links_house
@@ -2037,8 +2048,7 @@ Exit_Pool_Base = ['Links House Exit',
'Pyramid'] 'Pyramid']
# these are connections that cannot be shuffled and always exist. They link together separate parts of the world we need to divide into regions # 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 = [('Links House S&Q', 'Links House'), mandatory_connections = [('Old Man S&Q', 'Old Man House'),
('Old Man S&Q', 'Old Man House'),
# UW Connections # UW Connections
('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'), ('Lost Woods Hideout (top to bottom)', 'Lost Woods Hideout (bottom)'),
@@ -2069,10 +2079,6 @@ mandatory_connections = [('Links House S&Q', 'Links House'),
('Ganon Drop', 'Bottom of Pyramid') ('Ganon Drop', 'Bottom of Pyramid')
] ]
open_mandatory_connections = [('Sanctuary S&Q', 'Sanctuary')]
inverted_mandatory_connections = [('Sanctuary S&Q', 'Dark Sanctuary Hint')]
# non-shuffled entrance links # non-shuffled entrance links
default_connections = [('Lumberjack House', 'Lumberjack House'), default_connections = [('Lumberjack House', 'Lumberjack House'),
('Bonk Fairy (Light)', 'Bonk Fairy (Light)'), ('Bonk Fairy (Light)', 'Bonk Fairy (Light)'),
@@ -2137,7 +2143,8 @@ default_connector_connections = [('Old Man Cave (West)', 'Old Man Cave Exit (Wes
('Hookshot Cave Back Entrance', 'Hookshot Cave Back Exit') ('Hookshot Cave Back Entrance', 'Hookshot Cave Back Exit')
] ]
default_item_connections = [('Mimic Cave', 'Mimic Cave'), default_item_connections = [('Links House', 'Links House Exit'),
('Mimic Cave', 'Mimic Cave'),
('Waterfall of Wishing', 'Waterfall of Wishing'), ('Waterfall of Wishing', 'Waterfall of Wishing'),
('Bonk Rock Cave', 'Bonk Rock Cave'), ('Bonk Rock Cave', 'Bonk Rock Cave'),
('Graveyard Cave', 'Graveyard Cave'), ('Graveyard Cave', 'Graveyard Cave'),
@@ -2161,6 +2168,7 @@ default_item_connections = [('Mimic Cave', 'Mimic Cave'),
('Brewery', 'Brewery'), ('Brewery', 'Brewery'),
('Pyramid Fairy', 'Pyramid Fairy'), ('Pyramid Fairy', 'Pyramid Fairy'),
('Dark World Hammer Peg Cave', 'Dark World Hammer Peg Cave'), ('Dark World Hammer Peg Cave', 'Dark World Hammer Peg Cave'),
('Big Bomb Shop', 'Big Bomb Shop'),
('Mire Shed', 'Mire Shed'), ('Mire Shed', 'Mire Shed'),
('Hype Cave', 'Hype Cave') ('Hype Cave', 'Hype Cave')
] ]
@@ -2196,14 +2204,6 @@ default_dropexit_connections = [('Lost Woods Hideout Stump', 'Lost Woods Hideout
#('Pyramid Entrance', 'Pyramid Exit') # this is dynamically added because of Inverted/OW Mixed #('Pyramid Entrance', 'Pyramid Exit') # this is dynamically added because of Inverted/OW Mixed
] ]
open_default_connections = [('Links House', 'Links House Exit'),
('Big Bomb Shop', 'Big Bomb Shop')
]
inverted_default_connections = [('Big Bomb Shop', 'Links House Exit'),
('Links House', 'Big Bomb Shop')
]
# non shuffled dungeons # non shuffled dungeons
default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Palace Exit (South)'), default_dungeon_connections = [('Desert Palace Entrance (South)', 'Desert Palace Exit (South)'),
('Desert Palace Entrance (West)', 'Desert Palace Exit (West)'), ('Desert Palace Entrance (West)', 'Desert Palace Exit (West)'),

View File

@@ -326,7 +326,7 @@ def create_regions(world, player):
create_cave_region(player, 'Dark World Hammer Peg Cave', 'a cave with an item', ['Peg Cave']), create_cave_region(player, 'Dark World Hammer Peg Cave', 'a cave with an item', ['Peg Cave']),
create_cave_region(player, 'Archery Game', 'a game of skill'), create_cave_region(player, 'Archery Game', 'a game of skill'),
create_cave_region(player, 'Bonk Fairy (Dark)', 'a fairy fountain'), create_cave_region(player, 'Bonk Fairy (Dark)', 'a fairy fountain'),
create_cave_region(player, 'Big Bomb Shop', 'the bomb shop', ['Big Bomb']), create_cave_region(player, 'Big Bomb Shop', 'the bomb shop', ['Big Bomb'], ['Big Bomb Shop Exit']),
create_cave_region(player, 'Dark Lake Hylia Healer Fairy', 'a fairy fountain'), create_cave_region(player, 'Dark Lake Hylia Healer Fairy', 'a fairy fountain'),
create_cave_region(player, 'East Dark World Hint', 'a storyteller'), create_cave_region(player, 'East Dark World Hint', 'a storyteller'),
create_cave_region(player, 'Hype Cave', 'a bounty of five items', ['Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left', create_cave_region(player, 'Hype Cave', 'a bounty of five items', ['Hype Cave - Top', 'Hype Cave - Middle Right', 'Hype Cave - Middle Left',

40
Rom.py
View File

@@ -800,7 +800,10 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
if should_be_bunny(sanc_region, world.mode[player]): if should_be_bunny(sanc_region, world.mode[player]):
rom.write_bytes(0x13fff2, [0x12, 0x00]) rom.write_bytes(0x13fff2, [0x12, 0x00])
if not world.is_tile_swapped(0x2c, player):
lh_name = 'Links House' lh_name = 'Links House'
else:
lh_name = 'Big Bomb Shop'
links_house = world.get_region(lh_name, player) links_house = world.get_region(lh_name, player)
if should_be_bunny(links_house, world.mode[player]): if should_be_bunny(links_house, world.mode[player]):
rom.write_bytes(0x13fff0, [0x04, 0x01]) rom.write_bytes(0x13fff0, [0x04, 0x01])
@@ -2625,10 +2628,24 @@ def set_inverted_mode(world, player, rom, inverted_buffer):
if world.is_tile_swapped(0x29, player): if world.is_tile_swapped(0x29, player):
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05]) # frog pickup on contact rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05]) # frog pickup on contact
if world.is_tile_swapped(0x2c, player): if world.is_tile_swapped(0x2c, player):
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']: rom.write_bytes(snes_to_pc(0x03F484), [0xFD, 0x4B, 0x68]) # place bed in bomb shop
rom.write_byte(0x15B8C, 0x6C) # exit links at bomb shop area
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house # spawn in bomb shop
rom.write_byte(0xDBB73 + 0x52, 0x01) patch_shuffled_bomb_shop(world, rom, player)
rom.write_byte(snes_to_pc(0x02D8D2), 0x1C)
rom.write_bytes(snes_to_pc(0x02D8E0), [0x23, 0x22, 0x23, 0x23, 0x18, 0x18, 0x18, 0x19])
rom.write_byte(snes_to_pc(0x02D919), 0x18)
rom.write_byte(snes_to_pc(0x02D927), 0x23)
write_int16(rom, snes_to_pc(0x02D934), 0x2398)
rom.write_byte(snes_to_pc(0x02D943), 0x18)
write_int16(rom, snes_to_pc(0x02D950), 0x0087)
write_int16(rom, snes_to_pc(0x02D95E), 0x0081)
rom.write_byte(snes_to_pc(0x02D9A4), 0x53)
# disable custom exit on links house exit
rom.write_byte(snes_to_pc(0x02E225), 0x1C)
rom.write_byte(snes_to_pc(0x02DAEE), 0x1C)
rom.write_byte(snes_to_pc(0x02DB8C), 0x6C)
if world.is_tile_swapped(0x2f, player): if world.is_tile_swapped(0x2f, player):
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82]) # add warp under rock
rom.write_byte(snes_to_pc(0x1BC590), 0x00) # remove secret portal rom.write_byte(snes_to_pc(0x1BC590), 0x00) # remove secret portal
@@ -2661,6 +2678,21 @@ def patch_shuffled_dark_sanc(world, rom, player):
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00]) rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
def patch_shuffled_bomb_shop(world, rom, player):
bomb_shop = world.get_region('Big Bomb Shop', player)
bomb_shop_entrance = str([i for i in bomb_shop.entrances if i.parent_region.name != 'Menu'][0].name)
room_id, ow_area, vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x, unknown_1, unknown_2, door_1, door_2 = door_addresses[bomb_shop_entrance][1]
door_index = door_addresses[str(bomb_shop_entrance)][0]
rom.write_byte(0x180240, 0x02)
rom.write_byte(0x180247, door_index + 1)
write_int16(rom, 0x180264, room_id)
rom.write_byte(0x180266, ow_area)
write_int16s(rom, 0x180267, [vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x])
rom.write_bytes(0x180275, [unknown_1, unknown_2, 0x00])
write_int16(rom, snes_to_pc(0x02D996), door_1)
def update_compasses(rom, world, player): def update_compasses(rom, world, player):
layouts = world.dungeon_layouts[player] layouts = world.dungeon_layouts[player]
provided_dungeon = False provided_dungeon = False