diff --git a/Adjuster.py b/Adjuster.py index 68ac73ad..ba502c8a 100755 --- a/Adjuster.py +++ b/Adjuster.py @@ -47,6 +47,7 @@ def main(): Alternatively, can be a ALttP Rom patched with a Link sprite that will be extracted. ''') + parser.add_argument('--triforce_gfx', help='Name of the triforce graphics to use.') parser.add_argument('--names', default='', type=str) args = parser.parse_args() diff --git a/AdjusterMain.py b/AdjusterMain.py index 803bed24..6b886a4b 100644 --- a/AdjusterMain.py +++ b/AdjusterMain.py @@ -30,9 +30,11 @@ def adjust(args): if not hasattr(args,"sprite"): args.sprite = None + if not hasattr(args,"triforce_gfx"): + args.triforce_gfx = None apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, - args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, + args.sprite, args.triforce_gfx, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume) output_path.cached_path = args.outputpath @@ -65,10 +67,12 @@ def patch(args): if not hasattr(args, "sprite"): args.sprite = None + if not hasattr(args, "triforce_gfx"): + args.triforce_gfx = None apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, - args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, - args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume) + args.sprite, args.triforce_gfx, args.ow_palettes, args.uw_palettes, args.reduce_flashing, + args.shuffle_sfx, args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume) output_path.cached_path = args.outputpath rom.write_to_file(output_path('%s.sfc' % outfile_base)) diff --git a/BaseClasses.py b/BaseClasses.py index 3abcbdd4..b95113bd 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -65,7 +65,7 @@ class World(object): self.lock_aga_door_in_escape = False self.save_and_quit_from_boss = True self.override_bomb_check = False - self.is_copied_world = False + self.is_premature_copied_world = False self.accessibility = accessibility.copy() self.fix_skullwoods_exit = {} self.fix_palaceofdarkness_exit = {} @@ -2701,8 +2701,8 @@ class Location(object): self.recursion_count = 0 self.staleness_count = 0 self.locked = False - self.real = True - self.always_allow = lambda item, state: False + self.real = not crystal + self.always_allow = None self.access_rule = lambda state: True self.verbose_rule = None self.item_rule = lambda item: True @@ -2716,7 +2716,7 @@ class Location(object): def can_fill(self, state, item, check_access=True): if not self.valid_multiworld(state, item): return False - return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) + return (self.always_allow and self.always_allow(state, item)) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) def valid_multiworld(self, state, item): if self.type == LocationType.Pot and self.player != item.player: diff --git a/CHANGELOG.md b/CHANGELOG.md index b7435482..dfa86a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.6.1.3 +- Added new post-gen option to change Triforce Piece GFX +- Added new GFX for 10/11 keys to replace the A/B GFX +- Fixed issue with Follower Sprite GFX after mirroring +- Fixed VRAM issue with Crystal Maiden cutscene +- Some performance updates +- \~Merged in DR v1.4.11~ + - Enemizer bans update + ## 0.6.1.2 - Various fixes for Custom Goal Framework - Added custom gfx for Pedestal and Murahdahla diff --git a/CLI.py b/CLI.py index c6ae7d9f..5eb4f3e2 100644 --- a/CLI.py +++ b/CLI.py @@ -141,7 +141,7 @@ def parse_cli(argv, no_defaults=False): 'skullwoods', 'linked_drops', 'pseudoboots', 'mirrorscroll', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', - 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', + 'ow_palettes', 'uw_palettes', 'sprite', 'triforce_gfx', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle', 'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_sfxinstruments', 'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode', @@ -264,6 +264,7 @@ def parse_settings(): "heartcolor": "red", "heartbeep": "normal", "sprite": None, + "triforce_gfx": None, "fastmenu": "normal", "ow_palettes": "default", "uw_palettes": "default", diff --git a/Fill.py b/Fill.py index b6b793db..0fa5868f 100644 --- a/Fill.py +++ b/Fill.py @@ -183,9 +183,13 @@ def fill_restrictive(world, base_state, locations, itempool, key_pool=None, sing spot_to_fill = None item_locations = filter_locations(item_to_place, locations, world, vanilla) + # for dungeon items, it is worth reducing this list further by excluding locations outside of the respective dungeon + reduced_locations = item_locations if not item_to_place.dungeon else \ + [location for location in item_locations if not location.always_allow and location.parent_region.can_fill(item_to_place)] + verify(item_to_place, item_locations, maximum_exploration_state, single_player_placement, perform_access_check, key_pool, world) - for location in item_locations: + for location in reduced_locations: spot_to_fill = verify_spot_to_fill(location, item_to_place, maximum_exploration_state, single_player_placement, perform_access_check, key_pool, world) if spot_to_fill: diff --git a/Main.py b/Main.py index a8d2265f..03d9e6fc 100644 --- a/Main.py +++ b/Main.py @@ -17,7 +17,7 @@ from OverworldGlitchRules import create_owg_connections from PotShuffle import shuffle_pots, shuffle_pot_switches from Regions import create_regions, create_shops, mark_light_dark_world_regions, create_dungeon_regions, adjust_locations from OWEdges import create_owedges -from OverworldShuffle import link_overworld, update_world_regions, create_dynamic_exits +from OverworldShuffle import link_overworld, update_world_regions, create_dynamic_flute_exits, create_dynamic_mirror_exits from Rom import patch_rom, patch_race_rom, apply_rom_settings, LocalRom, JsonRom, get_hash_string from Doors import create_doors from DoorShuffle import link_doors, connect_portal, link_doors_prep @@ -40,7 +40,7 @@ from source.enemizer.DamageTables import DamageTable from source.enemizer.Enemizer import randomize_enemies from source.rom.DataTables import init_data_tables -version_number = '1.4.10' +version_number = '1.4.11' version_branch = '-u' __version__ = f'{version_number}{version_branch}' @@ -170,9 +170,7 @@ def main(args, seed=None, fish=None): for player in range(1, world.players + 1): link_overworld(world, player) create_shops(world, player) - update_world_regions(world, player) mark_light_dark_world_regions(world, player) - create_dynamic_exits(world, player) init_districts(world) @@ -299,7 +297,7 @@ def main(args, seed=None, fish=None): world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash) apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player], - args.fastmenu[player], args.disablemusic[player], args.sprite[player], + args.fastmenu[player], args.disablemusic[player], args.sprite[player], args.triforce_gfx[player], args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player], args.shuffle_sfx[player], args.shuffle_sfxinstruments[player], args.shuffle_songinstruments[player], args.msu_resume[player]) @@ -809,13 +807,13 @@ def copy_world(world): update_world_regions(ret, player) if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'): create_owg_connections(ret, player) - create_dynamic_exits(ret, player) create_dungeon_regions(ret, player) create_owedges(ret, player) create_shops(ret, player) - #create_doors(ret, player) create_rooms(ret, player) create_dungeons(ret, player) + create_dynamic_mirror_exits(ret, player) + create_dynamic_flute_exits(ret, player) # there are region references here they must be migrated to preserve integrity # ret.exp_cache = world.exp_cache.copy() @@ -940,7 +938,7 @@ def copy_world(world): return ret -def copy_world_premature(world, player): +def copy_world_premature(world, player, create_flute_exits=True): # ToDo: Not good yet ret = World(world.players, world.owShuffle, world.owCrossed, world.owMixed, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, @@ -1026,19 +1024,21 @@ def copy_world_premature(world, player): ret.key_logic = world.key_logic.copy() ret.settings = world.settings - ret.is_copied_world = True + ret.is_premature_copied_world = True create_regions(ret, player) update_world_regions(ret, player) if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'): create_owg_connections(ret, player) - create_dynamic_exits(ret, player) create_dungeon_regions(ret, player) create_owedges(ret, player) create_shops(ret, player) create_doors(ret, player) create_rooms(ret, player) create_dungeons(ret, player) + create_dynamic_mirror_exits(ret, player) # assumes these have already been added to world + if create_flute_exits: + create_dynamic_flute_exits(ret, player) if world.mode[player] == 'standard': parent = ret.get_region('Menu', player) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 9588d020..07773366 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.2' +version_number = '0.6.1.3' # branch indicator is intentionally different across branches version_branch = '' @@ -200,6 +200,7 @@ def link_overworld(world, player): connect_simple(world, exitname, regionname, player) categorize_world_regions(world, player) + create_dynamic_mirror_exits(world, player) if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'): create_owg_connections(world, player) @@ -424,8 +425,6 @@ def link_overworld(world, player): assert len(forward_set) == len(back_set) for (forward_edge, back_edge) in zip(forward_set, back_set): connect_two_way(world, forward_edge, back_edge, player, connected_edges) - - world.owsectors[player] = build_sectors(world, player) else: if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel': for exitname, destname in parallelsimilar_connections: @@ -557,13 +556,14 @@ def link_overworld(world, player): connect_set(forward_edge_sets[0], back_edge_sets[0], connected_edges) remove_connected(forward_edge_sets, back_edge_sets) assert len(connected_edges) == len(default_connections) * 2, connected_edges - - world.owsectors[player] = build_sectors(world, player) + valid_layout = validate_layout(world, player) tries -= 1 assert valid_layout, 'Could not find a valid OW layout' + world.owsectors[player] = build_sectors(world, player) + # flute shuffle logging.getLogger('').debug('Shuffling flute spots') def connect_flutes(flute_destinations): @@ -725,6 +725,8 @@ def link_overworld(world, player): s[0x3a],s[0x3b],s[0x3c], s[0x3f]) world.spoiler.set_map('flute', text_output, new_spots, player) + create_dynamic_flute_exits(world, player) + def connect_custom(world, connected_edges, groups, forced, player): forced_crossed, forced_noncrossed = forced def remove_pair_from_pool(edgename1, edgename2, is_crossed): @@ -1292,7 +1294,7 @@ 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 create_flute_exits(world, player): +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: return @@ -1303,6 +1305,7 @@ def create_flute_exits(world, player): exit.spot_type = 'Flute' exit.connect(world.get_region('Flute Sky', player)) region.exits.append(exit) + world.initialize_regions() def get_mirror_exit_name(from_region, to_region): if from_region in mirror_connections and to_region in mirror_connections[from_region]: @@ -1329,7 +1332,7 @@ def get_mirror_edges(world, region, player): mirror_exits.append(tuple([get_mirror_exit_name(other_world_region_name, region.name), region.name])) return mirror_exits -def create_mirror_exits(world, player): +def create_dynamic_mirror_exits(world, player): mirror_exits = set() for region in (r for r in world.regions if r.player == player and r.name not in ['Zoras Domain', 'Master Sword Meadow', 'Hobo Bridge']): if region.type == (RegionType.DarkWorld if world.mode[player] != 'inverted' else RegionType.LightWorld): @@ -1350,12 +1353,6 @@ def create_mirror_exits(world, player): region.exits.append(exit) mirror_exits.add(exitname) - elif region.terrain == Terrain.Land: - pass - -def create_dynamic_exits(world, player): - create_flute_exits(world, player) - create_mirror_exits(world, player) world.initialize_regions() def categorize_world_regions(world, player): @@ -1433,7 +1430,7 @@ def build_sectors(world, player): # perform accessibility check on duplicate world for p in range(1, world.players + 1): world.key_logic[p] = {} - base_world = copy_world_premature(world, player) + base_world = copy_world_premature(world, player, create_flute_exits=False) # build lists of contiguous regions accessible with full inventory (excl portals/mirror/flute/entrances) regions = list(OWTileRegions.copy().keys()) @@ -1510,7 +1507,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F if build_copy_world: for p in range(1, world.players + 1): world.key_logic[p] = {} - base_world = copy_world_premature(world, player) + base_world = copy_world_premature(world, player, create_flute_exits=True) base_world.override_bomb_check = True else: base_world = world @@ -1554,11 +1551,9 @@ def validate_layout(world, player): 'Pyramid Area': ['Pyramid Exit Ledge'] } - from Main import copy_world_premature - from Utils import stack_size3a # TODO: Find a better source for the below lists, original sourced was deprecated from source.overworld.EntranceData import default_dungeon_connections, default_connector_connections, default_item_connections, default_shop_connections, default_drop_connections, default_dropexit_connections - + dungeon_entrances = list(zip(*default_dungeon_connections + [('Ganons Tower', '')]))[0] connector_entrances = list(zip(*default_connector_connections))[0] item_entrances = list(zip(*default_item_connections))[0] @@ -1567,12 +1562,11 @@ def validate_layout(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) def explore_region(region_name, region=None): - if stack_size3a() > 500: - raise GenerationException(f'Infinite loop detected for "{region_name}" located at \'validate_layout\'') - - explored_regions.append(region_name) + if region_name in explored_regions: + return + explored_regions.add(region_name) if not region: - region = base_world.get_region(region_name, player) + region = world.get_region(region_name, player) for exit in region.exits: if exit.connected_region is not None and exit.connected_region.name not in explored_regions \ and exit.connected_region.type in [RegionType.LightWorld, RegionType.DarkWorld]: @@ -1586,11 +1580,8 @@ def validate_layout(world, player): for dest_region in sane_connectors[region_name]: if dest_region not in explored_regions: explore_region(dest_region) - - for p in range(1, world.players + 1): - world.key_logic[p] = {} - base_world = copy_world_premature(world, player) - explored_regions = list() + + explored_regions = set() if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull'] or not world.shufflelinks[player]: if not world.is_bombshop_start(player): @@ -1616,14 +1607,14 @@ def validate_layout(world, player): start_region = 'Hyrule Castle Ledge' explore_region(start_region) - unreachable_regions = OrderedDict() + unreachable_regions = {} unreachable_count = -1 while unreachable_count != len(unreachable_regions): # find unreachable regions unreachable_regions = {} for region_name in list(OWTileRegions.copy().keys()): if region_name not in explored_regions and region_name not in isolated_regions: - region = base_world.get_region(region_name, player) + region = world.get_region(region_name, player) unreachable_regions[region_name] = region # loop thru unreachable regions to check if some can be excluded diff --git a/PastReleaseNotes.md b/PastReleaseNotes.md index 68b6b381..fa8d1286 100644 --- a/PastReleaseNotes.md +++ b/PastReleaseNotes.md @@ -5,7 +5,11 @@ # Patch Notes Changelog archive - +* 1.4.10 + * Logic: Changed the rule surrounding the Bumper Cave Ledge Drop (the murderdactyl) to only require Pearl AND (Cape OR Byrna OR a Sword) in OHKO mode for now. This is a temporary solution until a better way to prevent needing to use a framerule to get past the bird is invented. + * Helmacopter Fix. + * Fixed a bug in shopsanity that caused the generation to fail with certain prices. + * Enemizer: fairies were invalid on the overworld (unless a bonk occurred nearby), so they will no longer be randomized there. * 1.4.9 * Attempted fix for Moth conveyor room timing. Thanks for many people's input. Unsure if Helmacopter is still acceptable. * Mirror scroll will show up on file start screen if enabled (thanks Clearmouse!) diff --git a/Plando.py b/Plando.py index 2c948435..25003f24 100755 --- a/Plando.py +++ b/Plando.py @@ -76,7 +76,7 @@ def main(args): rom = LocalRom(args.rom) patch_rom(world, rom, 1, 1, False, str(args.rom_header) if args.rom_header else None) - apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.ow_palettes, args.uw_palettes) + apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.triforce_gfx, args.ow_palettes, args.uw_palettes) for textname, texttype, text in text_patches: if texttype == 'text': diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cd40aeaf..eb9a72d6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -141,8 +141,14 @@ These are now independent of retro mode and have three options: None, Random, an # Patch Notes -* 1.4.10 - * Logic: Changed the rule surrounding the Bumper Cave Ledge Drop (the murderdactyl) to only require Pearl AND (Cape OR Byrna OR a Sword) in OHKO mode for now. This is a temporary solution until a better way to prevent needing to use a framerule to get past the bird is invented. - * Helmacopter Fix. - * Fixed a bug in shopsanity that caused the generation to fail with certain prices. - * Enemizer: fairies were invalid on the overworld (unless a bonk occurred nearby), so they will no longer be randomized there. +* 1.4.11 + * Rom fixes (all thanks to Codemann, I believe) + * Pot bug when at sprite limit + * Kodongo AI vanilla in vanilla rooms + * Issue with music silencing across certain room transitions + * Glitched: Some HMG logic fixed. Thanks Muffins! (Sorry it took me forever to get this PR in) + * Glitched: Blind fight VRAM fix. Thanks Mufffins! + * Text: Updated tourney winners. Thanks clearmouse! + * Enemizer: Banned Swamola enemy everywhere as they may be causing crashes + * Enemizer: Enemy bans from Q2 and Q3. Thank you for all the reports. + diff --git a/Rom.py b/Rom.py index c0335ec8..67e4a122 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '2039c11b935d3b81f78810d9f4be19d6' +RANDOMIZERBASEHASH = '35f2b275114fcec150981e9cb28de373' class JsonRom(object): @@ -1875,7 +1875,7 @@ def hud_format_text(text): return output[:32] -def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, +def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, triforce_gfx, ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx, shuffle_sfxinstruments, shuffle_songinstruments, msu_resume): @@ -1933,6 +1933,20 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr # write link sprite if required if sprite is not None: write_sprite(rom, sprite) + + if triforce_gfx is not None: + from Tables import item_gfx_table + if triforce_gfx in item_gfx_table.keys(): + (is_custom, address, palette, pal_addr, size) = item_gfx_table[triforce_gfx] + address = address if is_custom else 0x8000 + address + write_int16(rom, snes_to_pc(0xA2C600+(0x6C*2)), address) + write_int16(rom, snes_to_pc(0xA2C800+(0x6C*2)), address) + rom.write_byte(snes_to_pc(0xA2B100+0x6C), 0 if size == 2 else 4) + rom.write_byte(snes_to_pc(0xA2BA00+0x6C), size) + rom.write_byte(snes_to_pc(0xA2BB00+0x6C), size) + rom.write_byte(snes_to_pc(0xA2BC00+0x6C), palette) + rom.write_byte(snes_to_pc(0xA2BD00+0x6C), palette) + write_int16(rom, snes_to_pc(0xA2BE00+(0x6C*2)), pal_addr) # sprite author credits padded_author = sprite.author_name if sprite is not None else "Nintendo" diff --git a/Rules.py b/Rules.py index ee69a481..cd3453d3 100644 --- a/Rules.py +++ b/Rules.py @@ -50,9 +50,11 @@ def set_rules(world, player): ow_bunny_rules(world, player) ow_terrain_rules(world, player) + if world.is_premature_copied_world: + return + if world.mode[player] == 'standard': - if not world.is_copied_world: - standard_rules(world, player) + standard_rules(world, player) else: misc_key_rules(world, player) @@ -91,23 +93,20 @@ def set_rules(world, player): if (world.flute_mode[player] != 'active' and not world.is_tile_swapped(0x18, player) and 'Ocarina (Activated)' not in list(map(str, [i for i in world.precollected_items if i.player == player]))): - if not world.is_copied_world: - # Commented out below, this would be needed for rando implementations where Inverted requires flute activation in bunny territory - # kak_region = self.world.get_region('Kakariko Village', player) - # add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player) and state.is_not_bunny(kak_region, player)) - add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player)) + # Commented out below, this would be needed for rando implementations where Inverted requires flute activation in bunny territory + # kak_region = self.world.get_region('Kakariko Village', player) + # add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player) and state.is_not_bunny(kak_region, player)) + add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player)) # if swamp and dam have not been moved we require mirror for swamp palace if not world.swamp_patch_required[player]: add_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has_Mirror(player)) - if not world.is_copied_world: - set_bunny_rules(world, player, world.mode[player] == 'inverted') + set_bunny_rules(world, player, world.mode[player] == 'inverted') # These rules go here because they overwrite/add to some of the above rules if world.logic[player] == 'hybridglitches': - if not world.is_copied_world: - underworld_glitches_rules(world, player) + underworld_glitches_rules(world, player) def mirrorless_path_to_location(world, startName, targetName, player): # If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch. @@ -399,7 +398,7 @@ def global_rules(world, player): # bonk items if world.shuffle_bonk_drops[player]: - if not world.is_copied_world: + if not world.is_premature_copied_world: from Regions import bonk_prize_table for location_name, (_, _, aga_required, _, _, _) in bonk_prize_table.items(): loc = world.get_location(location_name, player) @@ -983,7 +982,7 @@ def global_rules(world, player): add_key_logic_rules(world, player) - if world.logic[player] == 'hybridglitches' and not world.is_copied_world: + if world.logic[player] == 'hybridglitches' and not world.is_premature_copied_world: add_hmg_key_logic_rules(world, player) # End of door rando rules. @@ -1490,7 +1489,7 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override set_rule(world.get_entrance('Ice Lake Northeast Pier Hop', player), lambda state: False) forbid_bomb_jump_requirements(world, player) - if not world.is_copied_world: + if not world.is_premature_copied_world: add_conditional_lamps(world, player) @@ -1801,11 +1800,11 @@ def standard_rules(world, player): add_rule(world.get_entrance(entrance, player), lambda state: state.has('Zelda Delivered', player)) if world.shuffle_bonk_drops[player]: - if not world.is_copied_world: + if not world.is_premature_copied_world: add_rule(world.get_location('Hyrule Castle Tree', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_location('Central Bonk Rocks Tree', player), lambda state: state.has('Zelda Delivered', player)) - if not world.is_copied_world: + if not world.is_premature_copied_world: add_rule(world.get_location('Hyrule Castle Courtyard Tree Pull', player), lambda state: state.has('Zelda Delivered', player)) # don't allow bombs to get past here before zelda is rescued diff --git a/Tables.py b/Tables.py index 33e1e230..5272f586 100644 --- a/Tables.py +++ b/Tables.py @@ -147,101 +147,140 @@ bonk_prize_lookup = { 'Fairy': (0xe3, 15, None) } -# item name: (custom gfx, address offset, palette) +# item name: (custom gfx, address offset, palette, palette address, size) # decompressed gfx loaded at $7F8000 # custom gfx loaded at $228000 item_gfx_table = { - 'Green Rupees (20)': (False, 0x0000, 0x04), - 'Pegasus Boots': (False, 0x0040, 0x01), - 'Psuedoboots': (False, 0x0040, 0x02), - 'Blue Pendant': (False, 0x0080, 0x02), - 'Red Pendant': (False, 0x0080, 0x01), - 'Warp Tile': (False, 0x00C0, 0x04), - 'Open Chest': (False, 0x0100, 0x02), - 'Chicken': (False, 0x0140, 0x04), - 'Duck': (False, 0x0180, 0x01), - 'Chest': (False, 0x0400, 0x02), - 'Frog': (False, 0x0440, 0x04), - 'Kiki (Head)': (False, 0x0480, 0x04), - 'Purple Chest': (False, 0x0500, 0x04), - 'Super Bomb': (False, 0x0540, 0x04), - 'Blacksmith': (False, 0x0580, 0x04), - 'Bug Net': (False, 0x0860, 0x01), - 'Crystal': (False, 0x08A0, 0x06), - 'Silver Arrows': (False, 0x08E0, 0x01), - 'Bow': (False, 0x0920, 0x02), - 'Bottle (Fairy)': (False, 0x0960, 0x02), - 'Bottle (Bee)': (False, 0x09A0, 0x02), - 'Piece of Heart': (False, 0x0C00, 0x01), - 'Ocarina': (False, 0x0C40, 0x02), - 'Mirror Shield': (False, 0x0C80, 0x04), - 'Rupees (100)': (False, 0x0D20, 0x04), - 'Rupees (50)': (False, 0x0D60, 0x04), - 'Rupees (300)': (False, 0x0DA0, 0x04), - 'Flippers': (False, 0x1000, 0x02), - 'Mirror': (False, 0x1040, 0x02), - 'Bomb': (False, 0x1080, 0x02), - 'Lamp': (False, 0x10C0, 0x01), - 'Psuedolamp': (False, 0x10C0, 0x02), - 'Magic Cape': (False, 0x1100, 0x01), - 'Compass': (False, 0x1140, 0x02), - 'Moon Pearl': (False, 0x1180, 0x01), - 'Ether': (False, 0x1400, 0x04), - 'Bombos': (False, 0x1440, 0x04), - 'Quake': (False, 0x1480, 0x04), - 'Bottle': (False, 0x14C0, 0x01), - 'Bottle (Red Potion)': (False, 0x1500, 0x01), - 'Bottle (Green Potion)': (False, 0x1500, 0x04), - 'Bottle (Blue Potion)': (False, 0x1500, 0x02), - 'Mushroom': (False, 0x1540, 0x04), - 'Map': (False, 0x1580, 0x04), - 'Big Key': (False, 0x15C0, 0x04), - 'Bombs (3)': (False, 0x1840, 0x02), - 'Arrows (10)': (False, 0x1880, 0x02), - 'Heart Container': (False, 0x18C0, 0x01), - 'Green Mail': (False, 0x1900, 0x04), - 'Blue Mail': (False, 0x1900, 0x02), - 'Red Mail': (False, 0x1900, 0x01), - 'Fire Sheild': (False, 0x1980, 0x04), - 'Blue Shield': (False, 0x19C0, 0x02), - 'Magic Powder': (False, 0x1CC0, 0x02), - 'Bombs (10)': (False, 0x1D00, 0x02), - 'Power Glove': (False, 0x1D40, 0x01), - 'Titans Mitts': (False, 0x1D40, 0x04), - 'Book of Mudora': (False, 0x1D80, 0x04), - 'Maiden (Head)': (False, 0x2000, 0x04), - 'Zelda (Head)': (False, 0x2080, 0x04), - 'Old Man (Head)': (False, 0x2140, 0x04), - 'Locksmith (Head)': (False, 0x2180, 0x04), - 'Fire': (False, 0x25C0, 0x04), - 'Apples': (False, 0x30A0, 0x04), - 'Fairy': (False, 0x3140, 0x01), - 'Whirlpool': (False, 0x31C0, 0x01), + 'Green Rupees (20)': (False, 0x0000, 0x04, 0x0000, 2), + 'Pegasus Boots': (False, 0x0040, 0x01, 0x0000, 2), + 'Psuedoboots': (False, 0x0040, 0x02, 0x0000, 2), + 'Blue Pendant': (False, 0x0080, 0x02, 0x0000, 2), + 'Red Pendant': (False, 0x0080, 0x01, 0x0000, 2), + 'Warp Tile': (False, 0x00C0, 0x04, 0x0000, 2), + 'Open Chest': (False, 0x0100, 0x02, 0x0000, 2), + 'Chicken': (False, 0x0140, 0x04, 0x0000, 2), + 'Duck': (False, 0x0180, 0x01, 0x0000, 2), + 'Chest': (False, 0x0400, 0x02, 0x0000, 2), + 'Frog': (False, 0x0440, 0x04, 0x0000, 2), + 'Kiki (Head)': (False, 0x0480, 0x04, 0x0000, 2), + 'Purple Chest': (False, 0x0500, 0x04, 0x0000, 2), + 'Super Bomb': (False, 0x0540, 0x04, 0x0000, 2), + 'Blacksmith': (False, 0x0580, 0x04, 0x0000, 2), + 'Bug Net': (False, 0x0860, 0x01, 0x0000, 2), + 'Crystal': (False, 0x08A0, 0x86, 0xB240, 2), + 'Silver Arrows': (False, 0x08E0, 0x01, 0x0000, 2), + 'Progressive Bow': (False, 0x0920, 0x02, 0x0000, 2), + 'Bottle (Fairy)': (False, 0x0960, 0x02, 0x0000, 2), + 'Bottle (Bee)': (False, 0x09A0, 0x02, 0x0000, 2), + 'Piece of Heart': (False, 0x0C00, 0x01, 0x0000, 2), + 'Ocarina': (False, 0x0C40, 0x02, 0x0000, 2), + 'Mirror Shield': (False, 0x0C80, 0x80, 0xB230, 2), + 'Rupees (100)': (False, 0x0D20, 0x04, 0x0000, 2), + 'Rupees (50)': (False, 0x0D60, 0x04, 0x0000, 2), + 'Rupees (300)': (False, 0x0DA0, 0x04, 0x0000, 2), + 'Flippers': (False, 0x1000, 0x02, 0x0000, 2), + 'Magic Mirror': (False, 0x1040, 0x02, 0x0000, 2), + 'Bomb': (False, 0x1080, 0x02, 0x0000, 2), + 'Lamp': (False, 0x10C0, 0x01, 0x0000, 2), + 'Psuedolamp': (False, 0x10C0, 0x02, 0x0000, 2), + 'Magic Cape': (False, 0x1100, 0x01, 0x0000, 2), + 'Compass': (False, 0x1140, 0x02, 0x0000, 2), + 'Moon Pearl': (False, 0x1180, 0x01, 0x0000, 2), + 'Ether': (False, 0x1400, 0x04, 0x0000, 2), + 'Bombos': (False, 0x1440, 0x04, 0x0000, 2), + 'Quake': (False, 0x1480, 0x04, 0x0000, 2), + 'Bottle': (False, 0x14C0, 0x01, 0x0000, 2), + 'Bottle (Red Potion)': (False, 0x1500, 0x01, 0x0000, 2), + 'Bottle (Green Potion)': (False, 0x1500, 0x04, 0x0000, 2), + 'Bottle (Blue Potion)': (False, 0x1500, 0x02, 0x0000, 2), + 'Mushroom': (False, 0x1540, 0x04, 0x0000, 2), + 'Map': (False, 0x1580, 0x04, 0x0000, 2), + 'Big Key': (False, 0x15C0, 0x04, 0x0000, 2), + 'Green Potion': (False, 0x1800, 0x04, 0x0000, 2), + 'Blue Potion': (False, 0x1800, 0x02, 0x0000, 2), + 'Red Potion': (False, 0x1800, 0x01, 0x0000, 2), + 'Bombs (3)': (False, 0x1840, 0x02, 0x0000, 2), + 'Arrows (10)': (False, 0x1880, 0x02, 0x0000, 2), + 'Heart Container': (False, 0x18C0, 0x01, 0x0000, 2), + 'Heart Container (Green)': (False, 0x18C0, 0x04, 0x0000, 2), + 'Heart Container (Blue)': (False, 0x18C0, 0x02, 0x0000, 2), + 'Green Mail': (False, 0x1900, 0x04, 0x0000, 2), + 'Blue Mail': (False, 0x1900, 0x02, 0x0000, 2), + 'Red Mail': (False, 0x1900, 0x01, 0x0000, 2), + 'Fire Shield': (False, 0x1940, 0x80, 0xB220, 2), + 'Blue Shield': (False, 0x19C0, 0x02, 0x0000, 2), + 'Magic Powder': (False, 0x1CC0, 0x02, 0x0000, 2), + 'Bombs (10)': (False, 0x1D00, 0x02, 0x0000, 2), + 'Power Glove': (False, 0x1D40, 0x01, 0x0000, 2), + 'Titans Mitt': (False, 0x1D40, 0x04, 0x0000, 2), + 'Book of Mudora': (False, 0x1D80, 0x04, 0x0000, 2), + 'Maiden (Head)': (False, 0x2000, 0x04, 0x0000, 2), + 'Zelda (Head)': (False, 0x2080, 0x04, 0x0000, 2), + 'Old Man (Head)': (False, 0x2140, 0x04, 0x0000, 2), + 'Locksmith (Head)': (False, 0x2180, 0x04, 0x0000, 2), + 'Fire': (False, 0x25C0, 0x04, 0x0000, 2), + 'Apples': (False, 0x30A0, 0x04, 0x0000, 2), + 'Fairy': (False, 0x3140, 0x01, 0x0000, 2), + 'Whirlpool': (False, 0x31C0, 0x02, 0x0000, 2), - 'Triforce': (True, 0x0060, 0x04), - 'Fighter Sword': (True, 0x00A0, 0x02), - 'Master Sword': (True, 0x00E0, 0x02), - 'Tempered Sword': (True, 0x0120, 0x01), - 'Golden Sword': (True, 0x0160, 0x04), - 'Half Magic': (True, 0x01A0, 0x04), - 'Quarter Magic': (True, 0x01E0, 0x04), - 'Bomb Upgrade (+5)': (True, 0x0420, 0x04), - 'Bomb Upgrade (+10)': (True, 0x0460, 0x04), - 'Bomb Upgrade (50)': (True, 0x04A0, 0x04), - 'Bombbag': (True, 0x04E0, 0x02), - 'Arrow Upgrade (+5)': (True, 0x0520, 0x02), - 'Arrow Upgrade (+10)': (True, 0x0560, 0x02), - 'Arrows (70)': (True, 0x05A0, 0x02), - 'Silver Arrows (Ag)': (True, 0x05E0, 0x01), - 'Green Pendant': (True, 0x0820, 0x04), - 'Sword and Shield': (True, 0x0860, 0x02), - 'Green Potion': (True, 0x08A0, 0x04), - 'Blue Potion': (True, 0x08E0, 0x02), - 'Red Potion': (True, 0x0920, 0x01), - 'Bee Trap': (True, 0x0960, 0x02), - 'Red Crystal': (True, 0x0C60, 0x01), - 'Egg': (True, 0x1020, 0x02), - 'Master Key': (True, 0x1060, 0x02), - 'Lumberjack (Head)': (True, 0x11A0, 0x02), - 'Power Star': (True, 0x11E0, 0x04), + 'Nothing': (True, 0x0020, 0x01, 0x0000, 2), + 'Triforce': (True, 0x0060, 0x04, 0x0000, 2), + 'Fighter Sword': (True, 0x00A0, 0x02, 0x0000, 2), + 'Master Sword': (True, 0x00E0, 0x02, 0x0000, 2), + 'Tempered Sword': (True, 0x0120, 0x01, 0x0000, 2), + 'Golden Sword': (True, 0x0160, 0x04, 0x0000, 2), + 'Half Magic': (True, 0x01A0, 0x04, 0x0000, 2), + 'Quarter Magic': (True, 0x01E0, 0x04, 0x0000, 2), + 'Bomb Upgrade (+5)': (True, 0x0420, 0x04, 0x0000, 2), + 'Bomb Upgrade (+10)': (True, 0x0460, 0x04, 0x0000, 2), + 'Bomb Upgrade (50)': (True, 0x04A0, 0x04, 0x0000, 2), + 'Bombbag': (True, 0x04E0, 0x02, 0x0000, 2), + 'Arrow Upgrade (+5)': (True, 0x0520, 0x02, 0x0000, 2), + 'Arrow Upgrade (+10)': (True, 0x0560, 0x02, 0x0000, 2), + 'Arrow Upgrade (70)': (True, 0x05A0, 0x02, 0x0000, 2), + 'Silver Arrows (Ag)': (True, 0x05E0, 0x01, 0x0000, 2), + 'Green Pendant': (True, 0x0820, 0x04, 0x0000, 2), + 'Sword and Shield': (True, 0x0860, 0x02, 0xD244, 2), + 'Green Potion (G)': (True, 0x08A0, 0x04, 0x0000, 2), + 'Blue Potion (B)': (True, 0x08E0, 0x02, 0x0000, 2), + 'Red Potion (R)': (True, 0x0920, 0x01, 0x0000, 2), + 'Bee Trap': (True, 0x0960, 0x02, 0x0000, 2), + 'Red Crystal': (True, 0x0C60, 0x01, 0x0000, 2), + 'Green Clock': (True, 0x0DE0, 0x04, 0x0000, 2), + 'Blue Clock': (True, 0x0DE0, 0x02, 0x0000, 2), + 'Red Clock': (True, 0x0DE0, 0x01, 0x0000, 2), + 'Egg': (True, 0x1020, 0x02, 0x0000, 2), + 'Master Key': (True, 0x1060, 0x02, 0x0000, 2), + 'Lumberjack (Head)': (True, 0x11A0, 0x02, 0x0000, 2), + 'Power Star': (True, 0x11E0, 0x04, 0x0000, 2), + + # Thin GFX + 'Rupee (1)': (False, 0x0800, 0x04, 0x0000, 0), + 'Rupees (5)': (False, 0x0800, 0x02, 0x0000, 0), + 'Rupees (20)': (False, 0x0800, 0x01, 0x0000, 0), + 'Blue Shield (Thin)': (False, 0x09E0, 0x02, 0x0000, 0), + 'Heart': (False, 0x0CC0, 0x01, 0x0000, 0), + 'Heart (Green)': (False, 0x0CC0, 0x04, 0x0000, 0), + 'Heart (Blue)': (False, 0x0CC0, 0x02, 0x0000, 0), + 'Small Magic': (False, 0x0CE0, 0x04, 0x0000, 0), + 'Arrow': (False, 0x0D00, 0x02, 0x0000, 0), + 'Nothing (Thin)': (False, 0x0DE0, 0x01, 0x0000, 0), + 'Master Sword (Thin)': (False, 0x11C0, 0x05, 0x0000, 0), + 'Tempered Sword (Thin)': (False, 0x11C0, 0x01, 0x0000, 0), + 'Golden Sword (Thin)': (False, 0x11C0, 0x04, 0x0000, 0), + 'Shovel': (False, 0x11E0, 0x01, 0x0000, 0), + 'Bow': (False, 0x1C00, 0x01, 0x0000, 0), + 'Fighter Sword (Thin)': (False, 0x1C20, 0x02, 0x0000, 0), + 'Somaria': (False, 0x1C40, 0x01, 0x0000, 0), + 'Byrna': (False, 0x1C40, 0x02, 0x0000, 0), + 'Hookshot': (False, 0x1C60, 0x01, 0x0000, 0), + 'Fire Rod': (False, 0x1C80, 0x01, 0x0000, 0), + 'Ice Rod': (False, 0x1C80, 0x02, 0x0000, 0), + 'Hammer': (False, 0x1CA0, 0x01, 0x0000, 0), + 'Small Key': (False, 0x1DC0, 0x04, 0x0000, 0), + 'Boomerang': (False, 0x1DE0, 0x02, 0x0000, 0), + 'Red Boomerang': (False, 0x1DE0, 0x01, 0x0000, 0), + + 'Full Magic': (True, 0x01A0, 0x04, 0x0000, 0), } + \ No newline at end of file diff --git a/Text.py b/Text.py index 9eb6027f..b21eb57c 100644 --- a/Text.py +++ b/Text.py @@ -192,7 +192,7 @@ Blind_texts = [ "Gloves open\na handful\nof checks", "Red mail?\nReturn to\nsender.", "For sale:\nBaby boots,\nNever found", - "SRL or rtGG?\nI prefer the\nLadder", + "SRL or rtGG?\nI prefer the\nStepladder", "Ladders are\nalways up\nto something", "Zelda's\nfashion is\nvery chic", "Zombie geese\nare waterfoul.\n", diff --git a/data/base2current.bps b/data/base2current.bps index d052e425..d3e9c2e9 100644 Binary files a/data/base2current.bps and b/data/base2current.bps differ diff --git a/data/itemgfx/Apples.gif b/data/itemgfx/Apples.gif new file mode 100644 index 00000000..53cb2725 Binary files /dev/null and b/data/itemgfx/Apples.gif differ diff --git a/data/itemgfx/Arrow Upgrade (+10).gif b/data/itemgfx/Arrow Upgrade (+10).gif new file mode 100644 index 00000000..8b9c158b Binary files /dev/null and b/data/itemgfx/Arrow Upgrade (+10).gif differ diff --git a/data/itemgfx/Arrow Upgrade (+5).gif b/data/itemgfx/Arrow Upgrade (+5).gif new file mode 100644 index 00000000..25d2c7fd Binary files /dev/null and b/data/itemgfx/Arrow Upgrade (+5).gif differ diff --git a/data/itemgfx/Arrow Upgrade (70).gif b/data/itemgfx/Arrow Upgrade (70).gif new file mode 100644 index 00000000..db7cff10 Binary files /dev/null and b/data/itemgfx/Arrow Upgrade (70).gif differ diff --git a/data/itemgfx/Arrow.gif b/data/itemgfx/Arrow.gif new file mode 100644 index 00000000..fb3656a4 Binary files /dev/null and b/data/itemgfx/Arrow.gif differ diff --git a/data/itemgfx/Arrows (10).gif b/data/itemgfx/Arrows (10).gif new file mode 100644 index 00000000..54f0962c Binary files /dev/null and b/data/itemgfx/Arrows (10).gif differ diff --git a/data/itemgfx/Bee Trap.gif b/data/itemgfx/Bee Trap.gif new file mode 100644 index 00000000..b1706373 Binary files /dev/null and b/data/itemgfx/Bee Trap.gif differ diff --git a/data/itemgfx/Big Key.gif b/data/itemgfx/Big Key.gif new file mode 100644 index 00000000..026b6ae5 Binary files /dev/null and b/data/itemgfx/Big Key.gif differ diff --git a/data/itemgfx/Blacksmith.gif b/data/itemgfx/Blacksmith.gif new file mode 100644 index 00000000..30b372d8 Binary files /dev/null and b/data/itemgfx/Blacksmith.gif differ diff --git a/data/itemgfx/Blue Clock.gif b/data/itemgfx/Blue Clock.gif new file mode 100644 index 00000000..b60111ca Binary files /dev/null and b/data/itemgfx/Blue Clock.gif differ diff --git a/data/itemgfx/Blue Maiden (Body).gif b/data/itemgfx/Blue Maiden (Body).gif new file mode 100644 index 00000000..d6567942 Binary files /dev/null and b/data/itemgfx/Blue Maiden (Body).gif differ diff --git a/data/itemgfx/Blue Mail.gif b/data/itemgfx/Blue Mail.gif new file mode 100644 index 00000000..f82bcad3 Binary files /dev/null and b/data/itemgfx/Blue Mail.gif differ diff --git a/data/itemgfx/Blue Pendant.gif b/data/itemgfx/Blue Pendant.gif new file mode 100644 index 00000000..acbecc1a Binary files /dev/null and b/data/itemgfx/Blue Pendant.gif differ diff --git a/data/itemgfx/Blue Potion (B).gif b/data/itemgfx/Blue Potion (B).gif new file mode 100644 index 00000000..31364657 Binary files /dev/null and b/data/itemgfx/Blue Potion (B).gif differ diff --git a/data/itemgfx/Blue Potion.gif b/data/itemgfx/Blue Potion.gif new file mode 100644 index 00000000..8cc533e8 Binary files /dev/null and b/data/itemgfx/Blue Potion.gif differ diff --git a/data/itemgfx/Blue Shield (Thin).gif b/data/itemgfx/Blue Shield (Thin).gif new file mode 100644 index 00000000..2c9f7770 Binary files /dev/null and b/data/itemgfx/Blue Shield (Thin).gif differ diff --git a/data/itemgfx/Blue Shield.gif b/data/itemgfx/Blue Shield.gif new file mode 100644 index 00000000..196c216e Binary files /dev/null and b/data/itemgfx/Blue Shield.gif differ diff --git a/data/itemgfx/Bomb Upgrade (+10).gif b/data/itemgfx/Bomb Upgrade (+10).gif new file mode 100644 index 00000000..65e0675e Binary files /dev/null and b/data/itemgfx/Bomb Upgrade (+10).gif differ diff --git a/data/itemgfx/Bomb Upgrade (+5).gif b/data/itemgfx/Bomb Upgrade (+5).gif new file mode 100644 index 00000000..5c943927 Binary files /dev/null and b/data/itemgfx/Bomb Upgrade (+5).gif differ diff --git a/data/itemgfx/Bomb Upgrade (50).gif b/data/itemgfx/Bomb Upgrade (50).gif new file mode 100644 index 00000000..7a5b9a38 Binary files /dev/null and b/data/itemgfx/Bomb Upgrade (50).gif differ diff --git a/data/itemgfx/Bomb.gif b/data/itemgfx/Bomb.gif new file mode 100644 index 00000000..7f578fe6 Binary files /dev/null and b/data/itemgfx/Bomb.gif differ diff --git a/data/itemgfx/Bombbag.gif b/data/itemgfx/Bombbag.gif new file mode 100644 index 00000000..2f6f234e Binary files /dev/null and b/data/itemgfx/Bombbag.gif differ diff --git a/data/itemgfx/Bombos.gif b/data/itemgfx/Bombos.gif new file mode 100644 index 00000000..f5757b08 Binary files /dev/null and b/data/itemgfx/Bombos.gif differ diff --git a/data/itemgfx/Bombs (10).gif b/data/itemgfx/Bombs (10).gif new file mode 100644 index 00000000..2510e18b Binary files /dev/null and b/data/itemgfx/Bombs (10).gif differ diff --git a/data/itemgfx/Bombs (3).gif b/data/itemgfx/Bombs (3).gif new file mode 100644 index 00000000..4ccaa4d3 Binary files /dev/null and b/data/itemgfx/Bombs (3).gif differ diff --git a/data/itemgfx/Book of Mudora.gif b/data/itemgfx/Book of Mudora.gif new file mode 100644 index 00000000..b198d5a4 Binary files /dev/null and b/data/itemgfx/Book of Mudora.gif differ diff --git a/data/itemgfx/Boomerang.gif b/data/itemgfx/Boomerang.gif new file mode 100644 index 00000000..fed694ba Binary files /dev/null and b/data/itemgfx/Boomerang.gif differ diff --git a/data/itemgfx/Bottle (Bee).gif b/data/itemgfx/Bottle (Bee).gif new file mode 100644 index 00000000..d16add0f Binary files /dev/null and b/data/itemgfx/Bottle (Bee).gif differ diff --git a/data/itemgfx/Bottle (Blue Potion).gif b/data/itemgfx/Bottle (Blue Potion).gif new file mode 100644 index 00000000..f9c1560b Binary files /dev/null and b/data/itemgfx/Bottle (Blue Potion).gif differ diff --git a/data/itemgfx/Bottle (Fairy).gif b/data/itemgfx/Bottle (Fairy).gif new file mode 100644 index 00000000..d691e96a Binary files /dev/null and b/data/itemgfx/Bottle (Fairy).gif differ diff --git a/data/itemgfx/Bottle (Green Potion).gif b/data/itemgfx/Bottle (Green Potion).gif new file mode 100644 index 00000000..bb443f2c Binary files /dev/null and b/data/itemgfx/Bottle (Green Potion).gif differ diff --git a/data/itemgfx/Bottle (Red Potion).gif b/data/itemgfx/Bottle (Red Potion).gif new file mode 100644 index 00000000..3613a148 Binary files /dev/null and b/data/itemgfx/Bottle (Red Potion).gif differ diff --git a/data/itemgfx/Bottle.gif b/data/itemgfx/Bottle.gif new file mode 100644 index 00000000..477de6cf Binary files /dev/null and b/data/itemgfx/Bottle.gif differ diff --git a/data/itemgfx/Bow.gif b/data/itemgfx/Bow.gif new file mode 100644 index 00000000..18ee3d6c Binary files /dev/null and b/data/itemgfx/Bow.gif differ diff --git a/data/itemgfx/Bug Net.gif b/data/itemgfx/Bug Net.gif new file mode 100644 index 00000000..2795115f Binary files /dev/null and b/data/itemgfx/Bug Net.gif differ diff --git a/data/itemgfx/Byrna.gif b/data/itemgfx/Byrna.gif new file mode 100644 index 00000000..439ad828 Binary files /dev/null and b/data/itemgfx/Byrna.gif differ diff --git a/data/itemgfx/Chest.gif b/data/itemgfx/Chest.gif new file mode 100644 index 00000000..68e07985 Binary files /dev/null and b/data/itemgfx/Chest.gif differ diff --git a/data/itemgfx/Chicken.gif b/data/itemgfx/Chicken.gif new file mode 100644 index 00000000..f959f8bb Binary files /dev/null and b/data/itemgfx/Chicken.gif differ diff --git a/data/itemgfx/Compass.gif b/data/itemgfx/Compass.gif new file mode 100644 index 00000000..6a88b996 Binary files /dev/null and b/data/itemgfx/Compass.gif differ diff --git a/data/itemgfx/Crystal.gif b/data/itemgfx/Crystal.gif new file mode 100644 index 00000000..8492f4c7 Binary files /dev/null and b/data/itemgfx/Crystal.gif differ diff --git a/data/itemgfx/Duck.gif b/data/itemgfx/Duck.gif new file mode 100644 index 00000000..df8edbf3 Binary files /dev/null and b/data/itemgfx/Duck.gif differ diff --git a/data/itemgfx/Egg.gif b/data/itemgfx/Egg.gif new file mode 100644 index 00000000..b848c53c Binary files /dev/null and b/data/itemgfx/Egg.gif differ diff --git a/data/itemgfx/Ether.gif b/data/itemgfx/Ether.gif new file mode 100644 index 00000000..cd3e7294 Binary files /dev/null and b/data/itemgfx/Ether.gif differ diff --git a/data/itemgfx/Fairy.gif b/data/itemgfx/Fairy.gif new file mode 100644 index 00000000..3f461512 Binary files /dev/null and b/data/itemgfx/Fairy.gif differ diff --git a/data/itemgfx/Fighter Sword (Thin).gif b/data/itemgfx/Fighter Sword (Thin).gif new file mode 100644 index 00000000..a34335f2 Binary files /dev/null and b/data/itemgfx/Fighter Sword (Thin).gif differ diff --git a/data/itemgfx/Fighter Sword.gif b/data/itemgfx/Fighter Sword.gif new file mode 100644 index 00000000..4f5f2046 Binary files /dev/null and b/data/itemgfx/Fighter Sword.gif differ diff --git a/data/itemgfx/Fire Rod.gif b/data/itemgfx/Fire Rod.gif new file mode 100644 index 00000000..fdde5d16 Binary files /dev/null and b/data/itemgfx/Fire Rod.gif differ diff --git a/data/itemgfx/Fire Shield.gif b/data/itemgfx/Fire Shield.gif new file mode 100644 index 00000000..b4a151c7 Binary files /dev/null and b/data/itemgfx/Fire Shield.gif differ diff --git a/data/itemgfx/Fire.gif b/data/itemgfx/Fire.gif new file mode 100644 index 00000000..69f8250a Binary files /dev/null and b/data/itemgfx/Fire.gif differ diff --git a/data/itemgfx/Flippers.gif b/data/itemgfx/Flippers.gif new file mode 100644 index 00000000..c1cc5814 Binary files /dev/null and b/data/itemgfx/Flippers.gif differ diff --git a/data/itemgfx/Frog.gif b/data/itemgfx/Frog.gif new file mode 100644 index 00000000..e3c00a4e Binary files /dev/null and b/data/itemgfx/Frog.gif differ diff --git a/data/itemgfx/Full Magic.gif b/data/itemgfx/Full Magic.gif new file mode 100644 index 00000000..ed594f88 Binary files /dev/null and b/data/itemgfx/Full Magic.gif differ diff --git a/data/itemgfx/Golden Sword (Thin).gif b/data/itemgfx/Golden Sword (Thin).gif new file mode 100644 index 00000000..69a61930 Binary files /dev/null and b/data/itemgfx/Golden Sword (Thin).gif differ diff --git a/data/itemgfx/Golden Sword.gif b/data/itemgfx/Golden Sword.gif new file mode 100644 index 00000000..54cd4a13 Binary files /dev/null and b/data/itemgfx/Golden Sword.gif differ diff --git a/data/itemgfx/Green Clock.gif b/data/itemgfx/Green Clock.gif new file mode 100644 index 00000000..9e5a666e Binary files /dev/null and b/data/itemgfx/Green Clock.gif differ diff --git a/data/itemgfx/Green Maiden (Body).gif b/data/itemgfx/Green Maiden (Body).gif new file mode 100644 index 00000000..6c9fad99 Binary files /dev/null and b/data/itemgfx/Green Maiden (Body).gif differ diff --git a/data/itemgfx/Green Mail.gif b/data/itemgfx/Green Mail.gif new file mode 100644 index 00000000..793ec1ad Binary files /dev/null and b/data/itemgfx/Green Mail.gif differ diff --git a/data/itemgfx/Green Pendant.gif b/data/itemgfx/Green Pendant.gif new file mode 100644 index 00000000..9db766fe Binary files /dev/null and b/data/itemgfx/Green Pendant.gif differ diff --git a/data/itemgfx/Green Potion (G).gif b/data/itemgfx/Green Potion (G).gif new file mode 100644 index 00000000..f812ca71 Binary files /dev/null and b/data/itemgfx/Green Potion (G).gif differ diff --git a/data/itemgfx/Green Potion.gif b/data/itemgfx/Green Potion.gif new file mode 100644 index 00000000..591fee95 Binary files /dev/null and b/data/itemgfx/Green Potion.gif differ diff --git a/data/itemgfx/Green Rupees (20).gif b/data/itemgfx/Green Rupees (20).gif new file mode 100644 index 00000000..6dd23918 Binary files /dev/null and b/data/itemgfx/Green Rupees (20).gif differ diff --git a/data/itemgfx/Half Magic.gif b/data/itemgfx/Half Magic.gif new file mode 100644 index 00000000..ae039e5b Binary files /dev/null and b/data/itemgfx/Half Magic.gif differ diff --git a/data/itemgfx/Hammer.gif b/data/itemgfx/Hammer.gif new file mode 100644 index 00000000..2e5f68f3 Binary files /dev/null and b/data/itemgfx/Hammer.gif differ diff --git a/data/itemgfx/Heart (Blue).gif b/data/itemgfx/Heart (Blue).gif new file mode 100644 index 00000000..ead09923 Binary files /dev/null and b/data/itemgfx/Heart (Blue).gif differ diff --git a/data/itemgfx/Heart (Green).gif b/data/itemgfx/Heart (Green).gif new file mode 100644 index 00000000..b9cdc4b0 Binary files /dev/null and b/data/itemgfx/Heart (Green).gif differ diff --git a/data/itemgfx/Heart Container (Blue).gif b/data/itemgfx/Heart Container (Blue).gif new file mode 100644 index 00000000..3fb54bfc Binary files /dev/null and b/data/itemgfx/Heart Container (Blue).gif differ diff --git a/data/itemgfx/Heart Container (Green).gif b/data/itemgfx/Heart Container (Green).gif new file mode 100644 index 00000000..bfa4ace8 Binary files /dev/null and b/data/itemgfx/Heart Container (Green).gif differ diff --git a/data/itemgfx/Heart Container.gif b/data/itemgfx/Heart Container.gif new file mode 100644 index 00000000..97bde533 Binary files /dev/null and b/data/itemgfx/Heart Container.gif differ diff --git a/data/itemgfx/Heart.gif b/data/itemgfx/Heart.gif new file mode 100644 index 00000000..dbe31169 Binary files /dev/null and b/data/itemgfx/Heart.gif differ diff --git a/data/itemgfx/Hookshot.gif b/data/itemgfx/Hookshot.gif new file mode 100644 index 00000000..c97f65f2 Binary files /dev/null and b/data/itemgfx/Hookshot.gif differ diff --git a/data/itemgfx/Ice Rod.gif b/data/itemgfx/Ice Rod.gif new file mode 100644 index 00000000..59d5fa3e Binary files /dev/null and b/data/itemgfx/Ice Rod.gif differ diff --git a/data/itemgfx/Kiki (Body).gif b/data/itemgfx/Kiki (Body).gif new file mode 100644 index 00000000..39305489 Binary files /dev/null and b/data/itemgfx/Kiki (Body).gif differ diff --git a/data/itemgfx/Kiki (Head).gif b/data/itemgfx/Kiki (Head).gif new file mode 100644 index 00000000..232f6c86 Binary files /dev/null and b/data/itemgfx/Kiki (Head).gif differ diff --git a/data/itemgfx/Lamp.gif b/data/itemgfx/Lamp.gif new file mode 100644 index 00000000..a48c95be Binary files /dev/null and b/data/itemgfx/Lamp.gif differ diff --git a/data/itemgfx/Locksmith (Body).gif b/data/itemgfx/Locksmith (Body).gif new file mode 100644 index 00000000..9dec6d2f Binary files /dev/null and b/data/itemgfx/Locksmith (Body).gif differ diff --git a/data/itemgfx/Locksmith (Head).gif b/data/itemgfx/Locksmith (Head).gif new file mode 100644 index 00000000..f9c373b6 Binary files /dev/null and b/data/itemgfx/Locksmith (Head).gif differ diff --git a/data/itemgfx/Lumberjack (Head).gif b/data/itemgfx/Lumberjack (Head).gif new file mode 100644 index 00000000..d607b9d8 Binary files /dev/null and b/data/itemgfx/Lumberjack (Head).gif differ diff --git a/data/itemgfx/Magic Cape.gif b/data/itemgfx/Magic Cape.gif new file mode 100644 index 00000000..4e9442ed Binary files /dev/null and b/data/itemgfx/Magic Cape.gif differ diff --git a/data/itemgfx/Magic Mirror.gif b/data/itemgfx/Magic Mirror.gif new file mode 100644 index 00000000..e71a088a Binary files /dev/null and b/data/itemgfx/Magic Mirror.gif differ diff --git a/data/itemgfx/Magic Powder.gif b/data/itemgfx/Magic Powder.gif new file mode 100644 index 00000000..d805b264 Binary files /dev/null and b/data/itemgfx/Magic Powder.gif differ diff --git a/data/itemgfx/Maiden (Head).gif b/data/itemgfx/Maiden (Head).gif new file mode 100644 index 00000000..a67b7851 Binary files /dev/null and b/data/itemgfx/Maiden (Head).gif differ diff --git a/data/itemgfx/Map.gif b/data/itemgfx/Map.gif new file mode 100644 index 00000000..c8b90b47 Binary files /dev/null and b/data/itemgfx/Map.gif differ diff --git a/data/itemgfx/Master Key.gif b/data/itemgfx/Master Key.gif new file mode 100644 index 00000000..5c4d950a Binary files /dev/null and b/data/itemgfx/Master Key.gif differ diff --git a/data/itemgfx/Master Sword (Thin).gif b/data/itemgfx/Master Sword (Thin).gif new file mode 100644 index 00000000..f5766313 Binary files /dev/null and b/data/itemgfx/Master Sword (Thin).gif differ diff --git a/data/itemgfx/Master Sword.gif b/data/itemgfx/Master Sword.gif new file mode 100644 index 00000000..a730f087 Binary files /dev/null and b/data/itemgfx/Master Sword.gif differ diff --git a/data/itemgfx/Mirror Shield.gif b/data/itemgfx/Mirror Shield.gif new file mode 100644 index 00000000..790fcac4 Binary files /dev/null and b/data/itemgfx/Mirror Shield.gif differ diff --git a/data/itemgfx/Moon Pearl.gif b/data/itemgfx/Moon Pearl.gif new file mode 100644 index 00000000..4622e154 Binary files /dev/null and b/data/itemgfx/Moon Pearl.gif differ diff --git a/data/itemgfx/Mushroom.gif b/data/itemgfx/Mushroom.gif new file mode 100644 index 00000000..b533aeb7 Binary files /dev/null and b/data/itemgfx/Mushroom.gif differ diff --git a/data/itemgfx/Ocarina.gif b/data/itemgfx/Ocarina.gif new file mode 100644 index 00000000..ff68f924 Binary files /dev/null and b/data/itemgfx/Ocarina.gif differ diff --git a/data/itemgfx/Old Man (Body).gif b/data/itemgfx/Old Man (Body).gif new file mode 100644 index 00000000..7de45046 Binary files /dev/null and b/data/itemgfx/Old Man (Body).gif differ diff --git a/data/itemgfx/Old Man (Head).gif b/data/itemgfx/Old Man (Head).gif new file mode 100644 index 00000000..ca34f42a Binary files /dev/null and b/data/itemgfx/Old Man (Head).gif differ diff --git a/data/itemgfx/Open Chest.gif b/data/itemgfx/Open Chest.gif new file mode 100644 index 00000000..5ad6c64a Binary files /dev/null and b/data/itemgfx/Open Chest.gif differ diff --git a/data/itemgfx/Pegasus Boots.gif b/data/itemgfx/Pegasus Boots.gif new file mode 100644 index 00000000..5c2503a2 Binary files /dev/null and b/data/itemgfx/Pegasus Boots.gif differ diff --git a/data/itemgfx/Piece of Heart.gif b/data/itemgfx/Piece of Heart.gif new file mode 100644 index 00000000..be6d378b Binary files /dev/null and b/data/itemgfx/Piece of Heart.gif differ diff --git a/data/itemgfx/Power Glove.gif b/data/itemgfx/Power Glove.gif new file mode 100644 index 00000000..81752b3d Binary files /dev/null and b/data/itemgfx/Power Glove.gif differ diff --git a/data/itemgfx/Power Star.gif b/data/itemgfx/Power Star.gif new file mode 100644 index 00000000..89b7b948 Binary files /dev/null and b/data/itemgfx/Power Star.gif differ diff --git a/data/itemgfx/Progressive Bow.gif b/data/itemgfx/Progressive Bow.gif new file mode 100644 index 00000000..b61c67f8 Binary files /dev/null and b/data/itemgfx/Progressive Bow.gif differ diff --git a/data/itemgfx/Pseudoboots.gif b/data/itemgfx/Pseudoboots.gif new file mode 100644 index 00000000..3d08f85b Binary files /dev/null and b/data/itemgfx/Pseudoboots.gif differ diff --git a/data/itemgfx/Pseudolamp.gif b/data/itemgfx/Pseudolamp.gif new file mode 100644 index 00000000..2eb31420 Binary files /dev/null and b/data/itemgfx/Pseudolamp.gif differ diff --git a/data/itemgfx/Purple Chest.gif b/data/itemgfx/Purple Chest.gif new file mode 100644 index 00000000..745f6419 Binary files /dev/null and b/data/itemgfx/Purple Chest.gif differ diff --git a/data/itemgfx/Quake.gif b/data/itemgfx/Quake.gif new file mode 100644 index 00000000..e86194db Binary files /dev/null and b/data/itemgfx/Quake.gif differ diff --git a/data/itemgfx/Quarter Magic.gif b/data/itemgfx/Quarter Magic.gif new file mode 100644 index 00000000..97841b1e Binary files /dev/null and b/data/itemgfx/Quarter Magic.gif differ diff --git a/data/itemgfx/Red Boomerang.gif b/data/itemgfx/Red Boomerang.gif new file mode 100644 index 00000000..052dfa99 Binary files /dev/null and b/data/itemgfx/Red Boomerang.gif differ diff --git a/data/itemgfx/Red Clock.gif b/data/itemgfx/Red Clock.gif new file mode 100644 index 00000000..9629dccc Binary files /dev/null and b/data/itemgfx/Red Clock.gif differ diff --git a/data/itemgfx/Red Crystal.gif b/data/itemgfx/Red Crystal.gif new file mode 100644 index 00000000..6d17df29 Binary files /dev/null and b/data/itemgfx/Red Crystal.gif differ diff --git a/data/itemgfx/Red Maiden (Body).gif b/data/itemgfx/Red Maiden (Body).gif new file mode 100644 index 00000000..625947d3 Binary files /dev/null and b/data/itemgfx/Red Maiden (Body).gif differ diff --git a/data/itemgfx/Red Mail.gif b/data/itemgfx/Red Mail.gif new file mode 100644 index 00000000..0cc9885f Binary files /dev/null and b/data/itemgfx/Red Mail.gif differ diff --git a/data/itemgfx/Red Pendant.gif b/data/itemgfx/Red Pendant.gif new file mode 100644 index 00000000..dcf55738 Binary files /dev/null and b/data/itemgfx/Red Pendant.gif differ diff --git a/data/itemgfx/Red Potion (R).gif b/data/itemgfx/Red Potion (R).gif new file mode 100644 index 00000000..a39f20cd Binary files /dev/null and b/data/itemgfx/Red Potion (R).gif differ diff --git a/data/itemgfx/Red Potion.gif b/data/itemgfx/Red Potion.gif new file mode 100644 index 00000000..1bf1960e Binary files /dev/null and b/data/itemgfx/Red Potion.gif differ diff --git a/data/itemgfx/Rupee (1).gif b/data/itemgfx/Rupee (1).gif new file mode 100644 index 00000000..a2d025fe Binary files /dev/null and b/data/itemgfx/Rupee (1).gif differ diff --git a/data/itemgfx/Rupee (20).gif b/data/itemgfx/Rupee (20).gif new file mode 100644 index 00000000..88f807ff Binary files /dev/null and b/data/itemgfx/Rupee (20).gif differ diff --git a/data/itemgfx/Rupee (5).gif b/data/itemgfx/Rupee (5).gif new file mode 100644 index 00000000..c2744645 Binary files /dev/null and b/data/itemgfx/Rupee (5).gif differ diff --git a/data/itemgfx/Rupees (100).gif b/data/itemgfx/Rupees (100).gif new file mode 100644 index 00000000..1caa75f5 Binary files /dev/null and b/data/itemgfx/Rupees (100).gif differ diff --git a/data/itemgfx/Rupees (300).gif b/data/itemgfx/Rupees (300).gif new file mode 100644 index 00000000..6163dd17 Binary files /dev/null and b/data/itemgfx/Rupees (300).gif differ diff --git a/data/itemgfx/Rupees (50).gif b/data/itemgfx/Rupees (50).gif new file mode 100644 index 00000000..df4789c9 Binary files /dev/null and b/data/itemgfx/Rupees (50).gif differ diff --git a/data/itemgfx/Shovel.gif b/data/itemgfx/Shovel.gif new file mode 100644 index 00000000..fc211be3 Binary files /dev/null and b/data/itemgfx/Shovel.gif differ diff --git a/data/itemgfx/Silver Arrows (Ag).gif b/data/itemgfx/Silver Arrows (Ag).gif new file mode 100644 index 00000000..78e77cd4 Binary files /dev/null and b/data/itemgfx/Silver Arrows (Ag).gif differ diff --git a/data/itemgfx/Silver Arrows.gif b/data/itemgfx/Silver Arrows.gif new file mode 100644 index 00000000..454d5c28 Binary files /dev/null and b/data/itemgfx/Silver Arrows.gif differ diff --git a/data/itemgfx/Small Key.gif b/data/itemgfx/Small Key.gif new file mode 100644 index 00000000..b2632bfa Binary files /dev/null and b/data/itemgfx/Small Key.gif differ diff --git a/data/itemgfx/Small Magic.gif b/data/itemgfx/Small Magic.gif new file mode 100644 index 00000000..99b4b69d Binary files /dev/null and b/data/itemgfx/Small Magic.gif differ diff --git a/data/itemgfx/Somaria.gif b/data/itemgfx/Somaria.gif new file mode 100644 index 00000000..79327b8a Binary files /dev/null and b/data/itemgfx/Somaria.gif differ diff --git a/data/itemgfx/Super Bomb.gif b/data/itemgfx/Super Bomb.gif new file mode 100644 index 00000000..42ae2056 Binary files /dev/null and b/data/itemgfx/Super Bomb.gif differ diff --git a/data/itemgfx/Sword and Shield.gif b/data/itemgfx/Sword and Shield.gif new file mode 100644 index 00000000..de135c5d Binary files /dev/null and b/data/itemgfx/Sword and Shield.gif differ diff --git a/data/itemgfx/Tempered Sword (Thin).gif b/data/itemgfx/Tempered Sword (Thin).gif new file mode 100644 index 00000000..a1391b7d Binary files /dev/null and b/data/itemgfx/Tempered Sword (Thin).gif differ diff --git a/data/itemgfx/Tempered Sword.gif b/data/itemgfx/Tempered Sword.gif new file mode 100644 index 00000000..7a47e2cf Binary files /dev/null and b/data/itemgfx/Tempered Sword.gif differ diff --git a/data/itemgfx/Titans Mitt.gif b/data/itemgfx/Titans Mitt.gif new file mode 100644 index 00000000..bfd90ffa Binary files /dev/null and b/data/itemgfx/Titans Mitt.gif differ diff --git a/data/itemgfx/Triforce.gif b/data/itemgfx/Triforce.gif new file mode 100644 index 00000000..33f4e3d5 Binary files /dev/null and b/data/itemgfx/Triforce.gif differ diff --git a/data/itemgfx/Warp Tile.gif b/data/itemgfx/Warp Tile.gif new file mode 100644 index 00000000..6ba33bb1 Binary files /dev/null and b/data/itemgfx/Warp Tile.gif differ diff --git a/data/itemgfx/Whirlpool.gif b/data/itemgfx/Whirlpool.gif new file mode 100644 index 00000000..26edb127 Binary files /dev/null and b/data/itemgfx/Whirlpool.gif differ diff --git a/data/itemgfx/Zelda (Body).gif b/data/itemgfx/Zelda (Body).gif new file mode 100644 index 00000000..5db7ac8c Binary files /dev/null and b/data/itemgfx/Zelda (Body).gif differ diff --git a/data/itemgfx/Zelda (Head).gif b/data/itemgfx/Zelda (Head).gif new file mode 100644 index 00000000..a5f5d80f Binary files /dev/null and b/data/itemgfx/Zelda (Head).gif differ diff --git a/presets/world/owr_vanilla.yaml b/presets/world/owr_vanilla.yaml index d26bb8fa..9c86cc79 100644 --- a/presets/world/owr_vanilla.yaml +++ b/presets/world/owr_vanilla.yaml @@ -1,14 +1,36 @@ ow-edges: 1: two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Lost Woods EN*: Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + Skull Woods EN*: Dark Lumberjack WN* Lumberjack SW*: Mountain Pass NW* Dark Lumberjack SW*: Bumper Cave NW* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + East Dark Death Mountain EN*: Turtle Rock WN* Mountain Pass SE*: Kakariko Pond NE* Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall NE: Zoras Domain SW Zora Waterfall SE*: Zora Approach NE* Catfish SE*: Catfish Approach NE* + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Kakariko Fortune SC*: Kakariko NE* Kakariko Fortune EN*: Kakariko Pond WN* Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune SC*: Village of Outcasts NE* Dark Fortune EN*: Outcast Pond WN* Dark Fortune ES*: Outcast Pond WS* Kakariko Pond EN*: Sanctuary WN* @@ -39,8 +61,25 @@ ow-edges: Potion Shop EC*: Zora Approach WC* Dark Witch EN*: Catfish Approach WN* Dark Witch EC*: Catfish Approach WC* + Zora Approach NE*: Zora Waterfall SE* + Catfish Approach NE*: Catfish SE* + Kakariko SE*: Kakariko Suburb NE* + Kakariko ES*: Blacksmith WS* + Village of Outcasts SE*: Frog NE* + Village of Outcasts ES*: Hammer Pegs WS* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Hyrule Castle ES*: Sand Dunes WN* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Pyramid ES*: Dark Dunes WN* Wooden Bridge SW*: Sand Dunes NW* Broken Bridge SW*: Dark Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* Sand Dunes SC*: Stone Bridge NC* Dark Dunes SC*: Hammer Bridge NC* Maze Race ES*: Kakariko Suburb WS* @@ -65,10 +104,18 @@ ow-edges: Big Bomb Shop SC*: Hype Cave NC* Big Bomb Shop ES*: Hammer Bridge WS* Stone Bridge WC: Hobo EC + Stone Bridge SC*: Lake Hylia NW* Stone Bridge EN*: Tree Line WN* Stone Bridge EC*: Tree Line WC* + Hammer Bridge SC*: Ice Lake NW* Hammer Bridge EN*: Dark Tree Line WN* Hammer Bridge EC*: Dark Tree Line WC* + Tree Line SC*: Lake Hylia NC* + Tree Line SE*: Lake Hylia NE* + Dark Tree Line SC*: Ice Lake NC* + Dark Tree Line SE*: Ice Lake NE* + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS Flute Boy Approach EC*: C Whirlpool WC* Stumpy Approach EC*: Dark C Whirlpool WC* C Whirlpool EN*: Statues WN* @@ -81,6 +128,10 @@ ow-edges: Dark C Whirlpool SC*: Swamp NC* Statues SC*: South Pass NC* Hype Cave SC*: Dark South Pass NC* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* Ice Cave SW*: Octoballoon NW* Ice Cave SE*: Octoballoon NE* Shopping Mall SW*: Bomber Corner NW* @@ -91,96 +142,8 @@ ow-edges: Swamp Nook ES*: Swamp WS* Dam EC*: South Pass WC* Swamp EC*: Dark South Pass WC* - Lumberjack SW*: Mountain Pass NW* - Dark Lumberjack SW*: Bumper Cave NW* - Mountain Pass SE*: Kakariko Pond NE* - Bumper Cave SE*: Outcast Pond NE* - Zora Waterfall SE*: Zora Approach NE* - Catfish SE*: Catfish Approach NE* - Kakariko Fortune EN*: Kakariko Pond WN* - Kakariko Fortune ES*: Kakariko Pond WS* - Dark Fortune EN*: Outcast Pond WN* - Dark Fortune ES*: Outcast Pond WS* - Kakariko Pond EN*: Sanctuary WN* - Kakariko Pond ES*: Sanctuary WS* - Kakariko Pond SW*: Forgotten Forest NW* - Kakariko Pond SE*: Forgotten Forest NE* - Outcast Pond EN*: Dark Chapel WN* - Outcast Pond ES*: Dark Chapel WS* - Outcast Pond SW*: Shield Shop NW* - Outcast Pond SE*: Shield Shop NE* - Sanctuary EC*: Graveyard WC* - Dark Chapel EC*: Dark Graveyard WC* - Graveyard EC*: River Bend WC* - Dark Graveyard EC*: Qirn Jump WC* - River Bend EN*: Potion Shop WN* - River Bend EC*: Potion Shop WC* - River Bend ES*: Potion Shop WS* - River Bend SW*: Wooden Bridge NW* - River Bend SC*: Wooden Bridge NC* - River Bend SE*: Wooden Bridge NE* - Qirn Jump EN*: Dark Witch WN* - Qirn Jump EC*: Dark Witch WC* - Qirn Jump ES*: Dark Witch WS* - Qirn Jump SW*: Broken Bridge NW* - Qirn Jump SC*: Broken Bridge NC* - Qirn Jump SE*: Broken Bridge NE* - Potion Shop EN*: Zora Approach WN* - Potion Shop EC*: Zora Approach WC* - Dark Witch EN*: Catfish Approach WN* - Dark Witch EC*: Catfish Approach WC* - Wooden Bridge SW*: Sand Dunes NW* - Broken Bridge SW*: Dark Dunes NW* - Sand Dunes SC*: Stone Bridge NC* - Dark Dunes SC*: Hammer Bridge NC* - Maze Race ES*: Kakariko Suburb WS* - Dig Game EC: Frog WC - Dig Game ES*: Frog WS* - Kakariko Suburb ES*: Flute Boy WS* - Frog ES*: Stumpy WS* - Flute Boy SW*: Flute Boy Approach NW* - Flute Boy SC*: Flute Boy Approach NC* - Stumpy SW*: Stumpy Approach NW* - Stumpy SC*: Stumpy Approach NC* - Central Bonk Rocks EN*: Links House WN* - Central Bonk Rocks EC*: Links House WC* - Central Bonk Rocks ES*: Links House WS* - Central Bonk Rocks SW*: C Whirlpool NW* - Dark Bonk Rocks EN*: Big Bomb Shop WN* - Dark Bonk Rocks EC*: Big Bomb Shop WC* - Dark Bonk Rocks ES*: Big Bomb Shop WS* - Dark Bonk Rocks SW*: Dark C Whirlpool NW* - Links House SC*: Statues NC* - Links House ES*: Stone Bridge WS* - Big Bomb Shop SC*: Hype Cave NC* - Big Bomb Shop ES*: Hammer Bridge WS* - Stone Bridge WC: Hobo EC - Stone Bridge EN*: Tree Line WN* - Stone Bridge EC*: Tree Line WC* - Hammer Bridge EN*: Dark Tree Line WN* - Hammer Bridge EC*: Dark Tree Line WC* - Flute Boy Approach EC*: C Whirlpool WC* - Stumpy Approach EC*: Dark C Whirlpool WC* - C Whirlpool EN*: Statues WN* - C Whirlpool EC*: Statues WC* - C Whirlpool ES*: Statues WS* - C Whirlpool SC*: Dam NC* - Dark C Whirlpool EN*: Hype Cave WN* - Dark C Whirlpool EC*: Hype Cave WC* - Dark C Whirlpool ES*: Hype Cave WS* - Dark C Whirlpool SC*: Swamp NC* - Statues SC*: South Pass NC* - Hype Cave SC*: Dark South Pass NC* - Ice Cave SW*: Octoballoon NW* - Ice Cave SE*: Octoballoon NE* - Shopping Mall SW*: Bomber Corner NW* - Shopping Mall SE*: Bomber Corner NE* - Desert Pass EC*: Dam WC* - Desert Pass ES*: Dam WS* - Swamp Nook EC*: Swamp WC* - Swamp Nook ES*: Swamp WS* - Dam EC*: South Pass WC* - Swamp EC*: Dark South Pass WC* + South Pass ES*: Lake Hylia WS* + Dark South Pass ES*: Ice Lake WS* ow-whirlpools: 1: two-way: diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index b0dbf825..8141614a 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -501,6 +501,7 @@ ] }, "sprite": {}, + "triforce_gfx": {}, "create_rom": { "action": "store_false", "type": "bool" diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 8632601f..0ad57757 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -42,6 +42,8 @@ "adjust.sprite": "Sprite:", "adjust.sprite.unchanged": "(unchanged)", + "adjust.triforcegfx": "Triforce Piece:", + "adjust.triforcegfx.unchanged": "(unchanged)", "adjust.rom": "Rom to adjust: ", "adjust.rom.romfiles": "Rom Files", @@ -259,7 +261,8 @@ "randomizer.gameoptions.sprite": "Sprite:", "randomizer.gameoptions.sprite.unchanged": "(unchanged)", - + "randomizer.gameoptions.triforcegfx": "Triforce Piece:", + "randomizer.gameoptions.triforcegfx.unchanged": "(unchanged)", "randomizer.generation.bps": "Create BPS Patches", "randomizer.generation.spoiler": "Create Spoiler Log", diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index af34f007..ab3738e7 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -208,6 +208,7 @@ class CustomSettings(object): # rom adjust stuff args.sprite[p] = get_setting(settings['sprite'], args.sprite[p]) + args.triforce_gfx[p] = get_setting(settings['triforce_gfx'], args.triforce_gfx[p]) args.disablemusic[p] = get_setting(settings['disablemusic'], args.disablemusic[p]) args.quickswap[p] = get_setting(settings['quickswap'], args.quickswap[p]) args.reduce_flashing[p] = get_setting(settings['reduce_flashing'], args.reduce_flashing[p]) diff --git a/source/classes/ItemGfxSelector.py b/source/classes/ItemGfxSelector.py new file mode 100644 index 00000000..689ff626 --- /dev/null +++ b/source/classes/ItemGfxSelector.py @@ -0,0 +1,121 @@ +from tkinter import Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, LEFT, BOTTOM, X, RIGHT, TOP +import os +from GuiUtils import ToolTips, set_icon +from Utils import local_path + + +class ItemGfxSelector(object): + def __init__(self, parent, callback, valid_items=None): + self.parent = parent + self.window = Toplevel(parent) + self.window.geometry("800x650") + self.callback = callback + self.valid_items = valid_items if valid_items else [] + + self.window.wm_title("Select Triforce Piece Graphics") + self.window['padx'] = 5 + self.window['pady'] = 5 + + def open_itemgfx_dir(_evt): + from Utils import open_file + itemgfx_dir = local_path(os.path.join("data", "itemgfx")) + if not os.path.isdir(itemgfx_dir): + os.makedirs(itemgfx_dir) + open_file(itemgfx_dir) + + frametitle = Frame(self.window) + title_text = Label(frametitle, text="Item Graphics") + title_text.pack(side=LEFT) + local_title_link = Label(frametitle, text="(open folder)", fg="blue", cursor="hand2") + local_title_link.pack(side=LEFT) + local_title_link.bind("", open_itemgfx_dir) + + self.icon_section(frametitle) + + frame = Frame(self.window) + frame.pack(side=BOTTOM, fill=X, pady=5) + + button = Button(frame, text="Default (Triforce)", command=self.use_default) + button.pack(side=LEFT, padx=(0, 5)) + + set_icon(self.window) + self.window.focus() + + def icon_section(self, frame_label): + frame = LabelFrame(self.window, labelwidget=frame_label, padx=5, pady=5) + canvas = Canvas(frame, borderwidth=0, width=780) + y_scrollbar = Scrollbar(frame, orient="vertical", command=canvas.yview) + y_scrollbar.pack(side="right", fill="y") + content_frame = Frame(canvas) + canvas.pack(side="left", fill="both", expand=True) + canvas.create_window((4, 4), window=content_frame, anchor="nw") + canvas.configure(yscrollcommand=y_scrollbar.set) + + def onFrameConfigure(canvas): + """Reset the scroll region to encompass the inner frame""" + canvas.configure(scrollregion=canvas.bbox("all")) + + content_frame.bind("", lambda event, canvas=canvas: onFrameConfigure(canvas)) + frame.pack(side=TOP, fill="both", expand=True) + + itemgfx_dir = local_path(os.path.join("data", "itemgfx")) + + if not os.path.exists(itemgfx_dir): + label = Label(content_frame, text='No item graphics found in data/itemgfx folder.') + label.pack() + return + + # Get all GIF files (converted from PNG) + gif_files = [] + for file in os.listdir(itemgfx_dir): + if file.lower().endswith('.gif'): + item_name = os.path.splitext(file)[0] + # Only include if it's in the valid_items list + if item_name in self.valid_items: + gif_files.append((file, item_name)) + + # Sort by name + gif_files.sort(key=lambda x: str.lower(x[1])) + + if len(gif_files) == 0: + label = Label(content_frame, text='No valid item graphics found. Items must match names from Tables.py.') + label.pack() + return + + # Calculate how many columns can fit (assuming ~40px per icon with padding) + max_columns = 18 + + i = 0 + for filename, item_name in gif_files: + filepath = os.path.join(itemgfx_dir, filename) + image = self.get_image_for_item(filepath) + if image is None: + continue + + button = Button(content_frame, image=image, command=lambda name=item_name: self.select_item(name)) + ToolTips.register(button, item_name) + button.image = image + button.grid(row=i // max_columns, column=i % max_columns, padx=2, pady=2) + i += 1 + + if i == 0: + label = Label(content_frame, text='No valid item graphics could be loaded.') + label.pack() + + def get_image_for_item(self, filepath): + """Load and prepare an item graphic for display""" + try: + # Load GIF with native Tkinter PhotoImage (no PIL required) + photo = PhotoImage(file=filepath) + return photo + except Exception as e: + print(f"Error loading image {filepath}: {e}") + return None + + def use_default(self): + self.callback("Triforce") + self.window.destroy() + + def select_item(self, item_name): + self.callback(item_name) + self.window.destroy() diff --git a/source/enemizer/SpriteSheets.py b/source/enemizer/SpriteSheets.py index 0d1302fe..34f66e0f 100644 --- a/source/enemizer/SpriteSheets.py +++ b/source/enemizer/SpriteSheets.py @@ -363,7 +363,7 @@ def init_sprite_requirements(): SpriteRequirement(EnemySprite.TrinexxFireHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f), SpriteRequirement(EnemySprite.TrinexxIceHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f), SpriteRequirement(EnemySprite.Blind).exalt().sub_group(1, 0x2c).sub_group(2, 0x3b), - SpriteRequirement(EnemySprite.Swamola).no_drop().sub_group(3, 0x19), + SpriteRequirement(EnemySprite.Swamola).skip().no_drop().sub_group(3, 0x19), SpriteRequirement(EnemySprite.Lynel).sub_group(3, 0x14), SpriteRequirement(EnemySprite.BunnyBeam).no_drop().ow_skip(), SpriteRequirement(EnemySprite.FloppingFish).uw_skip().immune(), diff --git a/source/enemizer/enemy_deny.yaml b/source/enemizer/enemy_deny.yaml index 3bc8fc3b..56aca46d 100644 --- a/source/enemizer/enemy_deny.yaml +++ b/source/enemizer/enemy_deny.yaml @@ -84,7 +84,7 @@ UwGeneralDeny: - [ 0x0039, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 1" - [0x0039, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Bumper", "AntiFairyCircle"]] #"Skull Woods - Play Pen - Hardhat Beetle" - [ 0x0039, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 2" - - [0x003a, 1, ["RollerVerticalUp"]] + - [0x003a, 1, ["RollerVerticalUp", "RollerVerticalDown"]] - [ 0x003b, 1, [ "Bumper", "AntiFairyCircle" ]] - [ 0x003b, 4, ["RollerVerticalUp", "RollerVerticalDown"]] - [ 0x003c, 0, ["BigSpike"]] @@ -339,7 +339,11 @@ UwGeneralDeny: - [ 0x00c2, 5, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots - [ 0x00c5, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Turtle Rock - Catwalk - Mini Helmasaur" - [ 0x00c5, 7, [ "Statue" ] ] #"Turtle Rock - Catwalk - Laser Eye (Left) 4" + - [0x00c6, 2, ["Bumper", "AntiFairyCircle"]] + - [0x00c6, 3, ["Bumper", "AntiFairyCircle"]] + - [0x00c6, 4, ["Bumper", "AntiFairyCircle"]] - [0x00c6, 5, ["Bumper", "AntiFairyCircle"]] + - [0x00c6, 6, ["Bumper", "AntiFairyCircle"]] - [ 0x00cb, 0, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots - [ 0x00cb, 3, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 1" - [ 0x00cb, 5, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 2" @@ -397,6 +401,7 @@ UwGeneralDeny: - [ 0x00e4, 2, [ "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Old Man Home - Keese 3" - [ 0x00e5, 4, [ "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Old Man Home Circle - Keese 5" - [ 0x00e5, 5, [ "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Old Man Home Circle - Keese 6" + - [0x00e6, 0, ["Statue"]] # Death Mountain Descent Cave Left - Keese 1 - Statue blocking pot access - [ 0x00e7, 0, [ "RollerVerticalUp", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 1" - [ 0x00e7, 1, [ "RollerVerticalUp", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 2" - [ 0x00e7, 2, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 3" @@ -441,7 +446,7 @@ OwGeneralDeny: - [0x05, 10, ["Bumper", "AntiFairyCircle"]] # Blocks path - [0x05, 11, ["Bumper", "AntiFairyCircle"]] # Blocks path to portal - [0x07, 3, ["Bumper", "AntiFairyCircle", "RollerHorizontalRight", "RollerHorizontalLeft"]] # Blocks path to ladder - - [0x07, 4, ["RollerHorizontalLeft"]] # Blocks path to ladder + - [0x07, 4, ["Bumper", "AntiFairyCircle", "RollerHorizontalLeft"]] # Blocks path to ladder - [0x1e, 3, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle"]] # forbid a beamos here - [0x35, 8, ["RollerVerticalUp", "RollerVerticalDown"]] # blocks the dock - [0x37, 5, ["RollerVerticalUp"]] # combines with a roller above to make the way impassable @@ -450,7 +455,7 @@ OwGeneralDeny: - [0x40, 13, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]] - [0x40, 14, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]] - [0x40, 16, ["RollerVerticalUp", "RollerVerticalDown"]] # Ropa near back hole is really large as a roller - - [0x55, 6, ["BigSpike"]] + - [0x55, 6, ["BigSpike", "Bumper", "AntiFairyCircle"]] - [0x57, 5, ["RollerVerticalUp", "RollerVerticalDown"]] - [0x5b, 0, ["AntiFairyCircle", "Bumper"]] # ropa on pyramid - [0x5e, 0, ["Gibo"]] # kiki eating Gibo @@ -480,6 +485,7 @@ OwGeneralDeny: - [0x77, 1, ["Bumper", "AntiFairyCircle"]] # soft-lock potential near ladder - [0x7f, 1, ["Bumper", "AntiFairyCircle"]] # soft-lock potential near ladder UwEnemyDrop: + - [0x0015, 8, ["Zoro"]] # layer issues - [0x0085, 9, ["Babasu"]] # ran off the edge and didn't return - [0x00cb, 3, ["Zoro"]] # layer issues - [0x00cb, 5, ["Zoro"]] # layer issues diff --git a/source/gui/adjust/overview.py b/source/gui/adjust/overview.py index a26bd750..55ce0ffd 100644 --- a/source/gui/adjust/overview.py +++ b/source/gui/adjust/overview.py @@ -2,6 +2,7 @@ from tkinter import ttk, filedialog, messagebox, StringVar, Button, Entry, Frame from AdjusterMain import adjust, patch from argparse import Namespace from source.classes.SpriteSelector import SpriteSelector +from source.classes.ItemGfxSelector import ItemGfxSelector import source.gui.widgets as widgets import json import logging @@ -71,6 +72,30 @@ def adjust_page(top, parent, settings): spriteSelectButton2.pack(side=LEFT) spriteDialogFrame2.pack(anchor=E) + # Triforce Piece GFX Selection + self.triforceGfxNameVar = StringVar() + self.triforceGfxNameVar.set('(unchanged)') + triforceGfxDialogFrame = Frame(self.frames["leftAdjustFrame"]) + triforceGfxLabel = Label(triforceGfxDialogFrame, text='Triforce Piece:') + triforceGfxEntry = Label(triforceGfxDialogFrame, textvariable=self.triforceGfxNameVar) + self.triforce_gfx = None + + def set_triforce_gfx(item_name): + self.triforce_gfx = item_name + self.triforceGfxNameVar.set(item_name if item_name else '(unchanged)') + + def TriforceGfxSelectAdjuster(): + from Tables import item_gfx_table + valid_items = list(item_gfx_table.keys()) + ItemGfxSelector(parent, set_triforce_gfx, valid_items=valid_items) + + triforceGfxSelectButton = Button(triforceGfxDialogFrame, text='...', command=TriforceGfxSelectAdjuster) + + triforceGfxLabel.pack(side=LEFT) + triforceGfxEntry.pack(side=LEFT) + triforceGfxSelectButton.pack(side=LEFT) + triforceGfxDialogFrame.pack(anchor=E) + # Path to game file to Adjust # This one's more-complicated, build it and stuff it adjustRomFrame = Frame(self.frames["bottomAdjustFrame"]) @@ -117,6 +142,7 @@ def adjust_page(top, parent, settings): guiargs.rom = self.romVar2.get() guiargs.baserom = top.pages["randomizer"].pages["generation"].widgets["rom"].storageVar.get() guiargs.sprite = self.sprite + guiargs.triforce_gfx = self.triforce_gfx guiargs.outputpath = os.path.dirname(guiargs.rom) try: adjust(args=guiargs) @@ -171,6 +197,7 @@ def adjust_page(top, parent, settings): guiargs.patch = self.patchVar.get() guiargs.baserom = top.pages["randomizer"].pages["generation"].widgets["rom"].storageVar.get() guiargs.sprite = self.sprite + guiargs.triforce_gfx = self.triforce_gfx guiargs.outputpath = os.path.dirname(guiargs.patch) try: patch(args=guiargs) diff --git a/source/gui/bottom.py b/source/gui/bottom.py index e25c2b2f..35b6c516 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -345,6 +345,9 @@ def create_guiargs(parent): guiargs.sprite = parent.pages["randomizer"].pages["gameoptions"].widgets["sprite"]["spriteObject"] guiargs.randomSprite = parent.randomSprite.get() + # Get Triforce Piece GFX Selection + guiargs.triforce_gfx = parent.pages["randomizer"].pages["gameoptions"].widgets["triforce_gfx"]["selectedItem"] + # Get output path guiargs.outputpath = parent.settings["outputpath"] diff --git a/source/gui/loadcliargs.py b/source/gui/loadcliargs.py index 9230fe59..6ca7ad60 100644 --- a/source/gui/loadcliargs.py +++ b/source/gui/loadcliargs.py @@ -197,6 +197,13 @@ def loadcliargs(gui, args, settings=None): spriteNameVar=gui.pages["adjust"].content.spriteNameVar2, randomSpriteVar=gui.randomSprite) + # Figure out Triforce GFX Selection + if "triforce_gfx" in args and args["triforce_gfx"] is not None: + gui.pages["randomizer"].pages["gameoptions"].widgets["triforce_gfx"]["selectedItem"] = args["triforce_gfx"] + gui.pages["randomizer"].pages["gameoptions"].widgets["triforce_gfx"]["itemNameVar"].set(args["triforce_gfx"]) + gui.pages["adjust"].content.triforce_gfx = args["triforce_gfx"] + gui.pages["adjust"].content.triforceGfxNameVar.set(args["triforce_gfx"]) + # Load args/settings for Adjust tab def loadadjustargs(gui, settings): options = { diff --git a/source/gui/randomize/gameoptions.py b/source/gui/randomize/gameoptions.py index ac9bdc22..5f3dfddf 100644 --- a/source/gui/randomize/gameoptions.py +++ b/source/gui/randomize/gameoptions.py @@ -1,6 +1,7 @@ from tkinter import ttk, StringVar, Button, Entry, Frame, Label, NE, NW, E, W, LEFT, RIGHT from functools import partial import source.classes.SpriteSelector as spriteSelector +import source.classes.ItemGfxSelector as itemGfxSelector import source.gui.widgets as widgets import json import os @@ -66,6 +67,34 @@ def gameoptions_page(top, parent): spriteSelectButton.pack(side=LEFT) spriteDialogFrame.pack(anchor=E) + ## Triforce Piece graphics selection + triforcegfxDialogFrame = Frame(self.frames["leftRomOptionsFrame"]) + triforceGfxLabel = Label(triforcegfxDialogFrame, text='Triforce Piece:') + + self.widgets["triforce_gfx"] = {} + self.widgets["triforce_gfx"]["selectedItem"] = None + self.widgets["triforce_gfx"]["itemNameVar"] = StringVar() + self.widgets["triforce_gfx"]["itemNameVar"].set('Triforce') + + triforceGfxEntry = Label(triforcegfxDialogFrame, textvariable=self.widgets["triforce_gfx"]["itemNameVar"]) + + def triforce_gfx_setter(item_name): + self.widgets["triforce_gfx"]["selectedItem"] = item_name + self.widgets["triforce_gfx"]["itemNameVar"].set(item_name) + + def triforce_gfx_select(): + # Import Tables to get valid item names + from Tables import item_gfx_table + valid_items = list(item_gfx_table.keys()) + itemGfxSelector.ItemGfxSelector(parent, triforce_gfx_setter, valid_items=valid_items) + + triforceGfxSelectButton = Button(triforcegfxDialogFrame, text='...', command=triforce_gfx_select) + + triforceGfxLabel.pack(side=LEFT) + triforceGfxEntry.pack(side=LEFT) + triforceGfxSelectButton.pack(side=LEFT) + triforcegfxDialogFrame.pack(anchor=E) + return self diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index 777edaec..8ef10110 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -864,7 +864,7 @@ def get_accessible_entrances(start_region, avail, assumed_inventory=[], cross_wo for p in range(1, avail.world.players + 1): avail.world.key_logic[p] = {} - base_world = copy_world_premature(avail.world, avail.player) + base_world = copy_world_premature(avail.world, avail.player, create_flute_exits=True) base_world.override_bomb_check = True connect_simple(base_world, 'Links House S&Q', start_region, avail.player) diff --git a/source/tools/MysteryUtils.py b/source/tools/MysteryUtils.py index c7d811e3..ac130d8b 100644 --- a/source/tools/MysteryUtils.py +++ b/source/tools/MysteryUtils.py @@ -261,6 +261,7 @@ def roll_settings(weights): if 'rom' in weights: romweights = weights['rom'] ret.sprite = get_choice('sprite', romweights) + ret.triforce_gfx = get_choice('triforce_gfx', romweights) ret.disablemusic = get_choice_bool('disablemusic', romweights) ret.quickswap = get_choice_bool('quickswap', romweights) ret.reduce_flashing = get_choice_bool('reduce_flashing', romweights)