diff --git a/BaseClasses.py b/BaseClasses.py index e2fd6804..f8f86bec 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -88,6 +88,8 @@ class World(object): self.owcrossededges = {} self.owwhirlpools = {} self.owgrid = {} + self.owlayoutmap_lw = {} + self.owlayoutmap_dw = {} self.owflutespots = {} self.owsectors = {} self.allow_flip_sanc = {} diff --git a/OverworldShuffle.py b/OverworldShuffle.py index a590e60b..1f79cc48 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -584,7 +584,10 @@ def link_overworld(world, player): connect_simple(world, 'Flute Spot ' + str(o + 1), regions[1], player) if world.owFluteShuffle[player] == 'vanilla': - connect_flutes(default_flute_connections) + flute_spots = default_flute_connections.copy() + sort_flute_spots(world, player, flute_spots) + world.owflutespots[player] = flute_spots + connect_flutes(flute_spots) else: flute_spots = 8 flute_pool = list(flute_data.keys()) @@ -709,9 +712,9 @@ def link_overworld(world, player): region_total -= sector[0] flute_spots -= spots_to_place - + # connect new flute spots - new_spots.sort() + sort_flute_spots(world, player, new_spots) world.owflutespots[player] = new_spots connect_flutes(new_spots) @@ -1309,6 +1312,15 @@ def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): groups[(mode, wrld, dir, terrain, parallel, count, group_name)][i].extend(matches) return groups +def sort_flute_spots(world, player, flute_spots): + if world.owLayout[player] != 'grid': + flute_spots.sort(key=lambda id: flute_data[id][1] if id != 0x03 or not world.is_tile_swapped(0x03, player) else 0x04) + else: + world_layout = world.owgrid[player][0] if world.mode[player] != 'inverted' else world.owgrid[player][1] + layout_list = sum(world_layout, []) + layout_map = {id & 0xBF: i for i, id in enumerate(layout_list)} + flute_spots.sort(key=lambda id: layout_map[flute_data[id][1] if id != 0x03 or not world.is_tile_swapped(0x03, player) else 0x04]) + def create_dynamic_flute_exits(world, player): flute_in_pool = True if player not in world.customitemarray else any(i for i, n in world.customitemarray[player].items() if i == 'flute' and n > 0) if not flute_in_pool: diff --git a/Rom.py b/Rom.py index 40e2e2c1..78be7463 100644 --- a/Rom.py +++ b/Rom.py @@ -513,14 +513,14 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): # patch flute spots owFlags = 0 owFog = 0 - if world.owFluteShuffle[player] == 'vanilla': + if world.owFluteShuffle[player] == 'vanilla' and world.owLayout[player] != 'grid': flute_spots = default_flute_connections else: flute_spots = world.owflutespots[player] owFlags |= 0x0100 write_int16(rom, snes_to_pc(0x0AB7F7), 0xEAEA) - flute_writes = sorted([(f, flute_data[f][1]) for f in flute_spots], key = lambda f: f[1]) + flute_writes = [(f, flute_data[f][1]) for f in flute_spots] for o in range(0, len(flute_writes)): owid = flute_writes[o][0] offset = 0 @@ -545,10 +545,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): write_int16(rom, snes_to_pc(0x02E937 + (o * 2)), data[base_index + 8]) # cam X write_int16(rom, snes_to_pc(0x02E959 + (o * 2)), data[base_index + 9]) # unknown 1 write_int16(rom, snes_to_pc(0x02E97B + (o * 2)), data[base_index + 10]) # unknown 2 - rom.write_byte(snes_to_pc(0x0AB783 + o), data[base_index + 12] & 0xff) # flute menu blip - X low byte - rom.write_byte(snes_to_pc(0x0AB78B + o), data[base_index + 12] // 0x100) # flute menu blip - X high byte - rom.write_byte(snes_to_pc(0x0AB793 + o), data[base_index + 11] & 0xff) # flute menu blip - Y low byte - rom.write_byte(snes_to_pc(0x0AB79B + o), data[base_index + 11] // 0x100) # flute menu blip - Y high byte + map_x, map_y = adjust_ow_coordinates_to_layout(world, player, data[base_index + 12], data[base_index + 11], world.mode[player] == 'inverted') + rom.write_byte(snes_to_pc(0x0AB783 + o), map_x & 0xff) # flute menu blip - X low byte + rom.write_byte(snes_to_pc(0x0AB78B + o), map_x // 0x100) # flute menu blip - X high byte + rom.write_byte(snes_to_pc(0x0AB793 + o), map_y & 0xff) # flute menu blip - Y low byte + rom.write_byte(snes_to_pc(0x0AB79B + o), map_y // 0x100) # flute menu blip - Y high byte # patch whirlpools if world.owWhirlpoolShuffle[player]: @@ -1447,10 +1448,14 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): y_map_position = [0x06E0, 0x0E50, 0xFF00, 0x0FD0, 0x06E0, 0x0D80, 0x0160, 0x0E80, 0x0130, 0x0840, 0x01B0] idx = ent owid = owid_map[idx] + map_x = x_map_position[idx] + map_y = y_map_position[idx] if owid != 0xFF: if (owid < 0x40) == (world.is_tile_swapped(owid, player)): coord_flags |= 0x8000 # world indicator flag - return (coord_flags | x_map_position[idx], y_map_position[idx]) + if coord_flags & 0x4000 == 0: + map_x, map_y = adjust_ow_coordinates_to_layout(world, player, map_x, map_y, coord_flags & 0x8000 != 0) + return (coord_flags | map_x, map_y) elif type(ent) is Location: from OverworldShuffle import OWTileRegions, ow_loc_prize_table if ent.name in ow_loc_prize_table: @@ -1471,8 +1476,10 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): coords = (door_addresses[ent.name][1][6], door_addresses[ent.name][1][5]) else: raise Exception(f"No overworld map coordinates for entrance {ent.name}") - coords = ((0x8000 if ent.parent_region.type == RegionType.DarkWorld else 0x0000) | coords[0], coords[1]) + map_x, map_y = adjust_ow_coordinates_to_layout(world, player, coords[0], coords[1], ent.parent_region.type == RegionType.DarkWorld) + coords = ((0x8000 if ent.parent_region.type == RegionType.DarkWorld else 0x0000) | map_x, map_y) return coords + if world.overworld_map[player] == 'default': # disable HC/AT/GT icons if not world.owMixed[player]: @@ -3023,6 +3030,13 @@ def update_compasses(rom, dungeon_locations, world, player): if not provided_dungeon: rom.write_byte(0x186FFF, 0xff) +def adjust_ow_coordinates_to_layout(world, player, x, y, dw_flag): + if world.owLayout[player] != 'grid': + return (x, y) + layout_map = world.owlayoutmap_dw[player] if dw_flag else world.owlayoutmap_lw[player] + original_slot_id = ((y // 0x0200) % 0x08) * 0x08 + ((x // 0x0200) % 0x08) + new_slot_id = layout_map[original_slot_id] + return ((new_slot_id % 0x08) * 0x0200 + x % 0x0200, ((new_slot_id // 0x08) % 0x08) * 0x0200 + y % 0x0200) InconvenientDungeonEntrances = {'Turtle Rock': 'Turtle Rock Main', diff --git a/source/overworld/LayoutGenerator.py b/source/overworld/LayoutGenerator.py index daa4c922..598212f9 100644 --- a/source/overworld/LayoutGenerator.py +++ b/source/overworld/LayoutGenerator.py @@ -1387,6 +1387,8 @@ def generate_random_grid_layout(world: World, player: int, connected_edges: List map_grid[w][(i + 1) % 8][j] = screen_id + 0x08 map_grid[w][(i + 1) % 8][(j + 1) % 8] = screen_id + 0x09 world.owgrid[player] = map_grid + world.owlayoutmap_lw[player] = {id & 0xBF: i for i, id in enumerate(sum(map_grid[0], []))} + world.owlayoutmap_dw[player] = {id & 0xBF: i for i, id in enumerate(sum(map_grid[1], []))} world.spoiler.set_map('layout_grid_lw', format_grid_for_spoiler(grid[0]), grid[0], player) if not world.owParallel[player]: