Overworld map code

This commit is contained in:
aerinon
2021-10-21 16:29:09 -06:00
parent 12846df681
commit dc7d4940d9
17 changed files with 250 additions and 41 deletions

View File

@@ -1957,6 +1957,12 @@ class Portal(object):
self.dependent = None self.dependent = None
self.deadEnd = False self.deadEnd = False
self.light_world = False self.light_world = False
self.chosen = False
def find_portal_entrance(self):
p_region = self.door.entrance.connected_region
return next((x for x in p_region.entrances
if x.parent_region.type in [RegionType.LightWorld, RegionType.DarkWorld]), None)
def change_boss_exit(self, exit_idx): def change_boss_exit(self, exit_idx):
self.default = False self.default = False

3
CLI.py
View File

@@ -96,7 +96,7 @@ def parse_cli(argv, no_defaults=False):
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality', for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid', 'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory', 'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
'bombbag', 'bombbag', 'overworld_map',
'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots', 'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'pseudoboots',
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
@@ -146,6 +146,7 @@ def parse_settings():
"shuffleganon": True, "shuffleganon": True,
"shuffle": "vanilla", "shuffle": "vanilla",
"shufflelinks": False, "shufflelinks": False,
"overworld_map": "default",
"pseudoboots": False, "pseudoboots": False,
"shufflepots": False, "shufflepots": False,

View File

@@ -1278,6 +1278,7 @@ def refine_boss_exits(world, player):
if 0 < len(filtered) < len(reachable_portals): if 0 < len(filtered) < len(reachable_portals):
reachable_portals = filtered reachable_portals = filtered
chosen_one = random.choice(reachable_portals) if len(reachable_portals) > 1 else reachable_portals[0] chosen_one = random.choice(reachable_portals) if len(reachable_portals) > 1 else reachable_portals[0]
chosen_one.chosen = True
if chosen_one != current_boss: if chosen_one != current_boss:
chosen_one.change_boss_exit(current_boss.boss_exit_idx) chosen_one.change_boss_exit(current_boss.boss_exit_idx)
current_boss.change_boss_exit(-1) current_boss.change_boss_exit(-1)

View File

@@ -378,8 +378,8 @@ flexible_starts = {
class DungeonInfo: class DungeonInfo:
def __init__(self, free, keys, bk, map, compass, bk_drop, drops, prize=None): def __init__(self, free, keys, bk, map, compass, bk_drop, drops, prize, midx):
# todo reduce static maps ideas: prize, bk_name, sm_name, cmp_name, map_name): # todo reduce static maps ideas: prize, bk_name, sm_name, cmp_name, map_name):
self.free_items = free self.free_items = free
self.key_num = keys self.key_num = keys
self.bk_present = bk self.bk_present = bk
@@ -389,21 +389,23 @@ class DungeonInfo:
self.key_drops = drops self.key_drops = drops
self.prize = prize self.prize = prize
self.map_index = midx
dungeon_table = { dungeon_table = {
'Hyrule Castle': DungeonInfo(6, 1, False, True, False, True, 3, None), 'Hyrule Castle': DungeonInfo(6, 1, False, True, False, True, 3, None, 0xc),
'Eastern Palace': DungeonInfo(3, 0, True, True, True, False, 2, 'Eastern Palace - Prize'), 'Eastern Palace': DungeonInfo(3, 0, True, True, True, False, 2, 'Eastern Palace - Prize', 0x0),
'Desert Palace': DungeonInfo(2, 1, True, True, True, False, 3, 'Desert Palace - Prize'), 'Desert Palace': DungeonInfo(2, 1, True, True, True, False, 3, 'Desert Palace - Prize', 0x2),
'Tower of Hera': DungeonInfo(2, 1, True, True, True, False, 0, 'Tower of Hera - Prize'), 'Tower of Hera': DungeonInfo(2, 1, True, True, True, False, 0, 'Tower of Hera - Prize', 0x1),
'Agahnims Tower': DungeonInfo(0, 2, False, False, False, False, 2, None), 'Agahnims Tower': DungeonInfo(0, 2, False, False, False, False, 2, None, 0xb),
'Palace of Darkness': DungeonInfo(5, 6, True, True, True, False, 0, 'Palace of Darkness - Prize'), 'Palace of Darkness': DungeonInfo(5, 6, True, True, True, False, 0, 'Palace of Darkness - Prize', 0x3),
'Swamp Palace': DungeonInfo(6, 1, True, True, True, False, 5, 'Swamp Palace - Prize'), 'Swamp Palace': DungeonInfo(6, 1, True, True, True, False, 5, 'Swamp Palace - Prize', 0x9),
'Skull Woods': DungeonInfo(2, 3, True, True, True, False, 2, 'Skull Woods - Prize'), 'Skull Woods': DungeonInfo(2, 3, True, True, True, False, 2, 'Skull Woods - Prize', 0x4),
'Thieves Town': DungeonInfo(4, 1, True, True, True, False, 2, "Thieves' Town - Prize"), 'Thieves Town': DungeonInfo(4, 1, True, True, True, False, 2, "Thieves' Town - Prize", 0x6),
'Ice Palace': DungeonInfo(3, 2, True, True, True, False, 4, 'Ice Palace - Prize'), 'Ice Palace': DungeonInfo(3, 2, True, True, True, False, 4, 'Ice Palace - Prize', 0x8),
'Misery Mire': DungeonInfo(2, 3, True, True, True, False, 3, 'Misery Mire - Prize'), 'Misery Mire': DungeonInfo(2, 3, True, True, True, False, 3, 'Misery Mire - Prize', 0x7),
'Turtle Rock': DungeonInfo(5, 4, True, True, True, False, 2, 'Turtle Rock - Prize'), 'Turtle Rock': DungeonInfo(5, 4, True, True, True, False, 2, 'Turtle Rock - Prize', 0x5),
'Ganons Tower': DungeonInfo(20, 4, True, True, True, False, 4, None), 'Ganons Tower': DungeonInfo(20, 4, True, True, True, False, 4, None, 0xa),
} }

View File

@@ -3733,8 +3733,6 @@ indirect_connections = {
# | ([addr], None) # holes # | ([addr], None) # holes
# exitdata = (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) # exitdata = (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)
# ToDo somehow merge this with creation of the locations
# ToDo somehow merge this with creation of the locations # ToDo somehow merge this with creation of the locations
door_addresses = {'Links House': (0x00, (0x0104, 0x2c, 0x0506, 0x0a9a, 0x0832, 0x0ae8, 0x08b8, 0x0b07, 0x08bf, 0x06, 0xfe, 0x0816, 0x0000)), door_addresses = {'Links House': (0x00, (0x0104, 0x2c, 0x0506, 0x0a9a, 0x0832, 0x0ae8, 0x08b8, 0x0b07, 0x08bf, 0x06, 0xfe, 0x0816, 0x0000)),
'Inverted Big Bomb Shop': (0x00, (0x0104, 0x2c, 0x0506, 0x0a9a, 0x0832, 0x0ae8, 0x08b8, 0x0b07, 0x08bf, 0x06, 0xfe, 0x0816, 0x0000)), 'Inverted Big Bomb Shop': (0x00, (0x0104, 0x2c, 0x0506, 0x0a9a, 0x0832, 0x0ae8, 0x08b8, 0x0b07, 0x08bf, 0x06, 0xfe, 0x0816, 0x0000)),
@@ -4034,3 +4032,137 @@ exit_ids = {'Links House Exit': (0x01, 0x00),
'Skull Pinball': 0x78, 'Skull Pinball': 0x78,
'Skull Pot Circle': 0x76, 'Skull Pot Circle': 0x76,
'Pyramid': 0x7B} 'Pyramid': 0x7B}
ow_prize_table = {'Links House': (0x8b1, 0xb2d), 'Inverted Big Bomb Shop': (0x8b1, 0xb2d),
'Desert Palace Entrance (South)': (0x108, 0xd70), 'Desert Palace Entrance (West)': (0x031, 0xca0),
'Desert Palace Entrance (North)': (0x0e1, 0xba0), 'Desert Palace Entrance (East)': (0x191, 0xca0),
'Eastern Palace': (0xf31, 0x620), 'Tower of Hera': (0x8D0, 0x080),
'Hyrule Castle Entrance (South)': (0x7b0, 0x730), 'Hyrule Castle Entrance (West)': (0x700, 0x640),
'Hyrule Castle Entrance (East)': (0x8a0, 0x640), 'Inverted Pyramid Entrance': (0x720, 0x700),
'Agahnims Tower': (0x7e0, 0x640), 'Inverted Ganons Tower': (0x7e0, 0x640),
'Thieves Town': (0x1d0, 0x780), 'Skull Woods First Section Door': (0x240, 0x280),
'Skull Woods Second Section Door (East)': (0x1a0, 0x240),
'Skull Woods Second Section Door (West)': (0x0c0, 0x1c0), 'Skull Woods Final Section': (0x082, 0x0b0),
'Ice Palace': (0xca0, 0xda0),
'Misery Mire': (0x100, 0xca0),
'Palace of Darkness': (0xf40, 0x620), 'Swamp Palace': (0x759, 0xED0),
'Turtle Rock': (0xf11, 0x103),
'Dark Death Mountain Ledge (West)': (0xb80, 0x180),
'Dark Death Mountain Ledge (East)': (0xc80, 0x180),
'Turtle Rock Isolated Ledge Entrance': (0xc00, 0x240),
'Hyrule Castle Secret Entrance Stairs': (0x850, 0x700),
'Kakariko Well Cave': (0x060, 0x680),
'Bat Cave Cave': (0x540, 0x8f0),
'Elder House (East)': (0x2b0, 0x6a0),
'Elder House (West)': (0x230, 0x6a0),
'North Fairy Cave': (0xa80, 0x440),
'Lost Woods Hideout Stump': (0x240, 0x280),
'Lumberjack Tree Cave': (0x4e0, 0x004),
'Two Brothers House (East)': (0x200, 0x0b60),
'Two Brothers House (West)': (0x180, 0x0b60),
'Sanctuary': (0x720, 0x4a0),
'Old Man Cave (West)': (0x580, 0x2c0),
'Old Man Cave (East)': (0x620, 0x2c0),
'Old Man House (Bottom)': (0x720, 0x320),
'Old Man House (Top)': (0x820, 0x220),
'Death Mountain Return Cave (East)': (0x600, 0x220),
'Death Mountain Return Cave (West)': (0x500, 0x1c0),
'Spectacle Rock Cave Peak': (0x720, 0x0a0),
'Spectacle Rock Cave': (0x790, 0x1a0),
'Spectacle Rock Cave (Bottom)': (0x710, 0x0a0),
'Paradox Cave (Bottom)': (0xd80, 0x180),
'Paradox Cave (Middle)': (0xd80, 0x380),
'Paradox Cave (Top)': (0xd80, 0x020),
'Fairy Ascension Cave (Bottom)': (0xcc8, 0x2a0),
'Fairy Ascension Cave (Top)': (0xc00, 0x240),
'Spiral Cave': (0xb80, 0x180),
'Spiral Cave (Bottom)': (0xb80, 0x2c0),
'Bumper Cave (Bottom)': (0x580, 0x2c0),
'Bumper Cave (Top)': (0x500, 0x1c0),
'Superbunny Cave (Top)': (0xd80, 0x020),
'Superbunny Cave (Bottom)': (0xd00, 0x180),
'Hookshot Cave': (0xc80, 0x0c0),
'Hookshot Cave Back Entrance': (0xcf0, 0x004),
'Ganons Tower': (0x8D0, 0x080),
'Inverted Agahnims Tower': (0x8D0, 0x080),
'Pyramid Entrance': (0x640, 0x7c0),
'Skull Woods First Section Hole (West)': None,
'Skull Woods First Section Hole (East)': None,
'Skull Woods First Section Hole (North)': None,
'Skull Woods Second Section Hole': None,
'Pyramid Hole': None,
'Inverted Pyramid Hole': None,
'Waterfall of Wishing': (0xe80, 0x280),
'Dam': (0x759, 0xED0),
'Blinds Hideout': (0x190, 0x6c0),
'Hyrule Castle Secret Entrance Drop': None,
'Bonk Fairy (Light)': (0x740, 0xa80),
'Lake Hylia Fairy': (0xd40, 0x9f0),
'Light Hype Fairy': (0x940, 0xc80),
'Desert Fairy': (0x420, 0xe00),
'Kings Grave': (0x920, 0x520),
'Tavern North': None, # can't mark this one technically
'Chicken House': (0x120, 0x880),
'Aginahs Cave': (0x2e0, 0xd00),
'Sahasrahlas Hut': (0xcf0, 0x6c0),
'Cave Shop (Lake Hylia)': (0xbc0, 0xc00),
'Capacity Upgrade': (0xca0, 0xda0),
'Kakariko Well Drop': None,
'Blacksmiths Hut': (0x4a0, 0x880),
'Bat Cave Drop': None,
'Sick Kids House': (0x220, 0x880),
'North Fairy Cave Drop': None,
'Lost Woods Gamble': (0x240, 0x080),
'Fortune Teller (Light)': (0x2c0, 0x4c0),
'Snitch Lady (East)': (0x310, 0x7a0),
'Snitch Lady (West)': (0x800, 0x7a0),
'Bush Covered House': (0x2e0, 0x880),
'Tavern (Front)': (0x270, 0x980),
'Light World Bomb Hut': (0x070, 0x980),
'Kakariko Shop': (0x170, 0x980),
'Lost Woods Hideout Drop': None,
'Lumberjack Tree Tree': None,
'Cave 45': (0x440, 0xca0), 'Graveyard Cave': (0x8f0, 0x430),
'Checkerboard Cave': (0x260, 0xc00),
'Mini Moldorm Cave': (0xa40, 0xe80),
'Long Fairy Cave': (0xf60, 0xb00),
'Good Bee Cave': (0xec0, 0xc00),
'20 Rupee Cave': (0xe80, 0xca0),
'50 Rupee Cave': (0x4d0, 0xed0),
'Ice Rod Cave': (0xe00, 0xc00),
'Bonk Rock Cave': (0x5f0, 0x460),
'Library': (0x270, 0xaa0),
'Potion Shop': (0xc80, 0x4c0),
'Sanctuary Grave': None,
'Hookshot Fairy': (0xd00, 0x180),
'Pyramid Fairy': (0x740, 0x740),
'East Dark World Hint': (0xf60, 0xb00),
'Palace of Darkness Hint': (0xd60, 0x7c0),
'Dark Lake Hylia Fairy': (0xd40, 0x9f0),
'Dark Lake Hylia Ledge Fairy': (0xe00, 0xc00),
'Dark Lake Hylia Ledge Spike Cave': (0xe80, 0xca0),
'Dark Lake Hylia Ledge Hint': (0xec0, 0xc00),
'Hype Cave': (0x940, 0xc80),
'Bonk Fairy (Dark)': (0x740, 0xa80),
'Brewery': (0x170, 0x980), 'C-Shaped House': (0x310, 0x7a0), 'Chest Game': (0x800, 0x7a0),
'Dark World Hammer Peg Cave': (0x4c0, 0x940),
'Red Shield Shop': (0x500, 0x680),
'Dark Sanctuary Hint': (0x720, 0x4a0),
'Inverted Dark Sanctuary': (0x720, 0x4a0),
'Fortune Teller (Dark)': (0x2c0, 0x4c0),
'Dark World Shop': (0x2e0, 0x880),
'Dark World Lumberjack Shop': (0x4e0, 0x0d0),
'Dark World Potion Shop': (0xc80, 0x4c0),
'Archery Game': (0x2f0, 0xaf0),
'Mire Shed': (0x060, 0xc90),
'Dark Desert Hint': (0x2e0, 0xd00),
'Dark Desert Fairy': (0x1c0, 0xc90),
'Spike Cave': (0x860, 0x180),
'Cave Shop (Dark Death Mountain)': (0xd80, 0x180),
'Dark Death Mountain Fairy': (0x620, 0x2c0),
'Mimic Cave': (0xc80, 0x180),
'Big Bomb Shop': (0x8b1, 0xb2d), 'Inverted Links House': (0x8b1, 0xb2d),
'Dark Lake Hylia Shop': (0xa40, 0xc40),
'Lumberjack House': (0x4e0, 0x0d0),
'Lake Hylia Fortune Teller': (0xa40, 0xc40),
'Kakariko Gamble Game': (0x2f0, 0xaf0)}

View File

@@ -22,7 +22,7 @@ def ItemFactory(items, player):
return ret return ret
# Format: Name: (Advancement, Priority, Type, ItemCode, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text) # Format: Name: (Advancement, Priority, Type, ItemCode, BasePrice, Pedestal Hint Text, Pedestal Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text, Hint Text)
item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'), item_table = {'Bow': (True, False, None, 0x0B, 200, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'the Bow'),
'Progressive Bow': (True, False, None, 0x64, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), 'Progressive Bow': (True, False, None, 0x64, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),
'Progressive Bow (Alt)': (True, False, None, 0x65, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'), 'Progressive Bow (Alt)': (True, False, None, 0x65, 150, 'You have\nchosen the\narcher class.', 'the stick and twine', 'arrow-slinging kid', 'arrow sling for sale', 'witch and robin hood', 'archer boy shoots again', 'a Bow'),

View File

@@ -104,6 +104,7 @@ def main(args, seed=None, fish=None):
world.treasure_hunt_total = args.triforce_pool.copy() world.treasure_hunt_total = args.triforce_pool.copy()
world.shufflelinks = args.shufflelinks.copy() world.shufflelinks = args.shufflelinks.copy()
world.pseudoboots = args.pseudoboots.copy() world.pseudoboots = args.pseudoboots.copy()
world.overworld_map = args.overworld_map.copy()
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}

View File

@@ -135,6 +135,8 @@ def roll_settings(weights):
entrance_shuffle = get_choice('entrance_shuffle') entrance_shuffle = get_choice('entrance_shuffle')
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla' ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
overworld_map = get_choice('overworld_map')
ret.overworld_map = overworld_map if overworld_map != 'default' else 'default'
door_shuffle = get_choice('door_shuffle') door_shuffle = get_choice('door_shuffle')
ret.door_shuffle = door_shuffle if door_shuffle != 'none' else 'vanilla' ret.door_shuffle = door_shuffle if door_shuffle != 'none' else 'vanilla'
ret.intensity = get_choice('intensity') ret.intensity = get_choice('intensity')

View File

@@ -1335,16 +1335,16 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'),
'Ice Block Drop': (None, None, False, None), 'Ice Block Drop': (None, None, False, None),
'Zelda Pickup': (None, None, False, None), 'Zelda Pickup': (None, None, False, None),
'Zelda Drop Off': (None, None, False, None), 'Zelda Drop Off': (None, None, False, None),
'Eastern Palace - Prize': ([0x1209D, 0x53EF8, 0x53EF9, 0x180052, 0x18007C, 0xC6FE], None, True, 'Eastern Palace'), 'Eastern Palace - Prize': ([0x1209D, 0x53E76, 0x53E77, 0x180052, 0x180070, 0xC6FE], None, True, 'Eastern Palace'),
'Desert Palace - Prize': ([0x1209E, 0x53F1C, 0x53F1D, 0x180053, 0x180078, 0xC6FF], None, True, 'Desert Palace'), 'Desert Palace - Prize': ([0x1209E, 0x53E7A, 0x53E7B, 0x180053, 0x180072, 0xC6FF], None, True, 'Desert Palace'),
'Tower of Hera - Prize': ([0x120A5, 0x53F0A, 0x53F0B, 0x18005A, 0x18007A, 0xC706], None, True, 'Tower of Hera'), 'Tower of Hera - Prize': ([0x120A5, 0x53E78, 0x53E79, 0x18005A, 0x180071, 0xC706], None, True, 'Tower of Hera'),
'Palace of Darkness - Prize': ([0x120A1, 0x53F00, 0x53F01, 0x180056, 0x18007D, 0xC702], None, True, 'Palace of Darkness'), 'Palace of Darkness - Prize': ([0x120A1, 0x53E7C, 0x53E7D, 0x180056, 0x180073, 0xC702], None, True, 'Palace of Darkness'),
'Swamp Palace - Prize': ([0x120A0, 0x53F6C, 0x53F6D, 0x180055, 0x180071, 0xC701], None, True, 'Swamp Palace'), 'Swamp Palace - Prize': ([0x120A0, 0x53E88, 0x53E89, 0x180055, 0x180079, 0xC701], None, True, 'Swamp Palace'),
'Thieves\' Town - Prize': ([0x120A6, 0x53F36, 0x53F37, 0x18005B, 0x180077, 0xC707], None, True, 'Thieves\' Town'), 'Thieves\' Town - Prize': ([0x120A6, 0x53E82, 0x53E83, 0x18005B, 0x180076, 0xC707], None, True, 'Thieves\' Town'),
'Skull Woods - Prize': ([0x120A3, 0x53F12, 0x53F13, 0x180058, 0x18007B, 0xC704], None, True, 'Skull Woods'), 'Skull Woods - Prize': ([0x120A3, 0x53E7E, 0x53E7F, 0x180058, 0x180074, 0xC704], None, True, 'Skull Woods'),
'Ice Palace - Prize': ([0x120A4, 0x53F5A, 0x53F5B, 0x180059, 0x180073, 0xC705], None, True, 'Ice Palace'), 'Ice Palace - Prize': ([0x120A4, 0x53E86, 0x53E87, 0x180059, 0x180078, 0xC705], None, True, 'Ice Palace'),
'Misery Mire - Prize': ([0x120A2, 0x53F48, 0x53F49, 0x180057, 0x180075, 0xC703], None, True, 'Misery Mire'), 'Misery Mire - Prize': ([0x120A2, 0x53E84, 0x53E85, 0x180057, 0x180077, 0xC703], None, True, 'Misery Mire'),
'Turtle Rock - Prize': ([0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock'), 'Turtle Rock - Prize': ([0x120A7, 0x53E80, 0x53E81, 0x18005C, 0x180075, 0xC708], None, True, 'Turtle Rock'),
'Kakariko Shop - Left': (None, None, False, 'for sale in Kakariko'), 'Kakariko Shop - Left': (None, None, False, 'for sale in Kakariko'),
'Kakariko Shop - Middle': (None, None, False, 'for sale in Kakariko'), 'Kakariko Shop - Middle': (None, None, False, 'for sale in Kakariko'),
'Kakariko Shop - Right': (None, None, False, 'for sale in Kakariko'), 'Kakariko Shop - Right': (None, None, False, 'for sale in Kakariko'),

54
Rom.py
View File

@@ -16,8 +16,8 @@ except ImportError:
raise Exception('Could not load BPS module') raise Exception('Could not load BPS module')
from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem
from DoorShuffle import compass_data, DROptions, boss_indicator from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals
from Dungeons import dungeon_music_addresses from Dungeons import dungeon_music_addresses, dungeon_table
from Regions import location_table, shop_to_location_table, retro_shops from Regions import location_table, shop_to_location_table, retro_shops
from RoomData import DoorKind from RoomData import DoorKind
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
@@ -26,13 +26,13 @@ from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
from Items import ItemFactory from Items import ItemFactory
from EntranceShuffle import door_addresses, exit_ids from EntranceShuffle import door_addresses, exit_ids, ow_prize_table
from source.classes.SFX import randomize_sfx from source.classes.SFX import randomize_sfx
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '1c59cec98ba4555db8eed1d2dea76497' RANDOMIZERBASEHASH = '7ec52e136e8c73a9e093a4baa43fc2d2'
class JsonRom(object): class JsonRom(object):
@@ -1401,14 +1401,48 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] else 0x00) # maps showing crystals on overworld
# compasses showing dungeon count # compasses showing dungeon count
compass_mode = 0x00
if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off': if world.clock_mode != 'none' or world.dungeon_counters[player] == 'off':
rom.write_byte(0x18003C, 0x00) # Currently must be off if timer is on, because they use same HUD location compass_mode = 0x00 # Currently must be off if timer is on, because they use same HUD location
elif world.dungeon_counters[player] == 'on':
rom.write_byte(0x18003C, 0x02) # always on
elif world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla' or world.dungeon_counters[player] == 'pickup':
rom.write_byte(0x18003C, 0x01) # show on pickup
else:
rom.write_byte(0x18003C, 0x00) rom.write_byte(0x18003C, 0x00)
elif world.dungeon_counters[player] == 'on':
compass_mode = 0x02 # always on
elif world.compassshuffle[player] or world.doorShuffle[player] != 'vanilla' or world.dungeon_counters[player] == 'pickup':
compass_mode = 0x01 # show on pickup
if world.shuffle[player] != 'vanilla' and world.overworld_map[player] != 'default':
compass_mode |= 0x80 # turn on locating dungeons
x_map_position_generic = [0x3c0, 0xbc0, 0x7c0, 0x1c0, 0x5c0, 0xdc0, 0x7c0, 0xbc0, 0x9c0, 0x3c0]
for idx, x_map in enumerate(x_map_position_generic):
rom.write_bytes(0x53df6+idx*2, int16_as_bytes(x_map))
rom.write_bytes(0x53e16+idx*2, int16_as_bytes(0xFC0))
if world.compassshuffle[player] and world.overworld_map[player] == 'compass':
compass_mode |= 0x40 # compasses are wild
for dungeon, portal_list in dungeon_portals.items():
ow_map_index = dungeon_table[dungeon].map_index
if len(portal_list) == 1:
portal_idx = 0
else:
if world.doorShuffle[player] == 'crossed':
# the random choice excludes sanctuary
portal_idx = next((i for i, elem in enumerate(portal_list)
if world.get_portal(elem, player).chosen), random.choice([1, 2, 3]))
else:
portal_idx = {'Hyrule Castle': 0, 'Desert Palace': 0, 'Skull Woods': 3, 'Turtle Rock': 3}[dungeon]
portal = world.get_portal(portal_list[portal_idx], player)
entrance = portal.find_portal_entrance()
world_indicator = 0x01 if entrance.parent_region.type == RegionType.DarkWorld else 0x00
coords = ow_prize_table[entrance.name]
# figure out compass entrances and what world (light/dark)
rom.write_bytes(0x53E36+ow_map_index*2, int16_as_bytes(coords[0]))
rom.write_bytes(0x53E56+ow_map_index*2, int16_as_bytes(coords[1]))
rom.write_byte(0x53EA6+ow_map_index, world_indicator)
# in crossed doors - flip the compass exists flags
if world.doorShuffle[player] == 'crossed':
exists_flag = any(x for x in world.get_dungeon(dungeon, player).dungeon_items if x.type == 'Compass')
rom.write_byte(0x53E96+ow_map_index, 0x1 if exists_flag else 0x0)
rom.write_byte(0x18003C, compass_mode)
# Bitfield - enable free items to show up in menu # Bitfield - enable free items to show up in menu
# #

Binary file not shown.

View File

@@ -28,6 +28,10 @@
full: 2 full: 2
crossed: 3 crossed: 3
insanity: 1 insanity: 1
overworld_map: # control how the overworld map operates when entrance shuffle is on
default: 1
compass: 10
map: 5
world_state: world_state:
standard: 1 standard: 1
open: 1 open: 1

View File

@@ -318,6 +318,13 @@
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"
}, },
"overworld_map": {
"choices": [
"default",
"compass",
"map"
]
},
"pseudoboots": { "pseudoboots": {
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"

View File

@@ -284,6 +284,9 @@
"shufflelinks": [ "shufflelinks": [
"Include Link's House in the entrance shuffle pool. (default: %(default)s)" "Include Link's House in the entrance shuffle pool. (default: %(default)s)"
], ],
"overworld_map": [
"Control if and how the overworld map indicators show the locations of dungeons (default: %(default)s)"
],
"heartbeep": [ "heartbeep": [
"Select the rate at which the heart beep sound is played at", "Select the rate at which the heart beep sound is played at",
"low health. (default: %(default)s)" "low health. (default: %(default)s)"

View File

@@ -115,6 +115,10 @@
"randomizer.entrance.openpyramid": "Pre-open Pyramid Hole", "randomizer.entrance.openpyramid": "Pre-open Pyramid Hole",
"randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool", "randomizer.entrance.shuffleganon": "Include Ganon's Tower and Pyramid Hole in shuffle pool",
"randomizer.entrance.shufflelinks": "Include Link's House in the shuffle pool", "randomizer.entrance.shufflelinks": "Include Link's House in the shuffle pool",
"randomizer.entrance.overworld_map": "Overworld Map",
"randomizer.entrance.overworld_map.default": "Default (no location display)",
"randomizer.entrance.overworld_map.compass": "Compass indicates location",
"randomizer.entrance.overworld_map.map": "Map indicates location",
"randomizer.entrance.entranceshuffle": "Entrance Shuffle", "randomizer.entrance.entranceshuffle": "Entrance Shuffle",
"randomizer.entrance.entranceshuffle.vanilla": "Vanilla", "randomizer.entrance.entranceshuffle.vanilla": "Vanilla",

View File

@@ -19,6 +19,17 @@
"dungeonssimple" "dungeonssimple"
] ]
}, },
"shufflelinks": { "type": "checkbox" } "shufflelinks": { "type": "checkbox" },
"overworld_map": {
"type": "selectbox",
"options": [
"default",
"compass",
"map"
],
"config": {
"width": 45
}
}
} }
} }

View File

@@ -78,7 +78,8 @@ SETTINGSTOPROCESS = {
"openpyramid": "openpyramid", "openpyramid": "openpyramid",
"shuffleganon": "shuffleganon", "shuffleganon": "shuffleganon",
"shufflelinks": "shufflelinks", "shufflelinks": "shufflelinks",
"entranceshuffle": "shuffle" "entranceshuffle": "shuffle",
"overworld_map": "overworld_map",
}, },
"enemizer": { "enemizer": {
"enemyshuffle": "shuffleenemies", "enemyshuffle": "shuffleenemies",