Doing GitHub's work for them and ACTUALLY merging in DR v0.4.0.7 changes

This commit is contained in:
codemann8
2021-07-04 11:23:08 -05:00
parent 6e49f38bce
commit 433a1dfc35
18 changed files with 153 additions and 37 deletions

View File

@@ -35,6 +35,7 @@ def main():
help='Select the color of Link\'s heart meter. (default: %(default)s)') help='Select the color of Link\'s heart meter. (default: %(default)s)')
parser.add_argument('--ow_palettes', default='default', choices=['default', 'random', 'blackout']) parser.add_argument('--ow_palettes', default='default', choices=['default', 'random', 'blackout'])
parser.add_argument('--uw_palettes', default='default', choices=['default', 'random', 'blackout']) parser.add_argument('--uw_palettes', default='default', choices=['default', 'random', 'blackout'])
parser.add_argument('--reduce_flashing', help='Reduce some in-game flashing.', action='store_true')
parser.add_argument('--sprite', help='''\ parser.add_argument('--sprite', help='''\
Path to a sprite sheet to use for Link. Needs to be in Path to a sprite sheet to use for Link. Needs to be in
binary format and have a length of 0x7000 (28672) bytes, binary format and have a length of 0x7000 (28672) bytes,

View File

@@ -24,8 +24,10 @@ def adjust(args):
if not hasattr(args,"sprite"): if not hasattr(args,"sprite"):
args.sprite = None args.sprite = 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.ow_palettes, args.uw_palettes, args.reduce_flashing)
output_path.cached_path = args.outputpath
rom.write_to_file(output_path('%s.sfc' % outfilebase)) rom.write_to_file(output_path('%s.sfc' % outfilebase))
logger.info('Done. Enjoy.') logger.info('Done. Enjoy.')

4
CLI.py
View File

@@ -102,7 +102,8 @@ def parse_cli(argv, no_defaults=False):
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
'remote_items', 'shopsanity', 'keydropshuffle', 'mixed_travel', 'standardize_palettes', 'code']: 'remote_items', 'shopsanity', 'keydropshuffle', 'mixed_travel', 'standardize_palettes', 'code',
'reduce_flashing']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name) value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1: if player == 1:
setattr(ret, name, {1: value}) setattr(ret, name, {1: value})
@@ -192,6 +193,7 @@ def parse_settings():
"fastmenu": "normal", "fastmenu": "normal",
"ow_palettes": "default", "ow_palettes": "default",
"uw_palettes": "default", "uw_palettes": "default",
"reduce_flashing": False,
# Spoiler defaults to TRUE # Spoiler defaults to TRUE
# Playthrough defaults to TRUE # Playthrough defaults to TRUE

View File

@@ -99,6 +99,7 @@ def link_doors_main(world, player):
for portal in world.dungeon_portals[player]: for portal in world.dungeon_portals[player]:
connect_portal(portal, world, player) connect_portal(portal, world, player)
fix_big_key_doors_with_ugly_smalls(world, player)
if world.doorShuffle[player] == 'vanilla': if world.doorShuffle[player] == 'vanilla':
for entrance, ext in open_edges: for entrance, ext in open_edges:
connect_two_way(world, entrance, ext, player) connect_two_way(world, entrance, ext, player)
@@ -674,7 +675,6 @@ def find_entrance_region(portal):
# paired_door.pair = False # paired_door.pair = False
def within_dungeon(world, player): def within_dungeon(world, player):
fix_big_key_doors_with_ugly_smalls(world, player)
add_inaccessible_doors(world, player) add_inaccessible_doors(world, player)
entrances_map, potentials, connections = determine_entrance_list(world, player) entrances_map, potentials, connections = determine_entrance_list(world, player)
connections_tuple = (entrances_map, potentials, connections) connections_tuple = (entrances_map, potentials, connections)
@@ -930,7 +930,6 @@ def treat_split_as_whole_dungeon(split_dungeon, name, origin_list, world, player
def cross_dungeon(world, player): def cross_dungeon(world, player):
fix_big_key_doors_with_ugly_smalls(world, player)
add_inaccessible_doors(world, player) add_inaccessible_doors(world, player)
entrances_map, potentials, connections = determine_entrance_list(world, player) entrances_map, potentials, connections = determine_entrance_list(world, player)
connections_tuple = (entrances_map, potentials, connections) connections_tuple = (entrances_map, potentials, connections)
@@ -1617,13 +1616,15 @@ def reassign_key_doors(builder, world, player):
else: else:
room.delete(d.doorListPos) room.delete(d.doorListPos)
d.smallKey = False d.smallKey = False
elif d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal and not d.entranceFlag: elif d.type is DoorType.Interior and d not in flat_proposal and d.dest not in flat_proposal:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
d.smallKey = False d.smallKey = False
d.dest.smallKey = False d.dest.smallKey = False
queue.remove(d.dest) queue.remove(d.dest)
elif d.type is DoorType.Normal and d not in flat_proposal and not d.entranceFlag: elif d.type is DoorType.Normal and d not in flat_proposal:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal) if not d.entranceFlag:
world.get_room(d.roomIndex, player).change(d.doorListPos, DoorKind.Normal)
d.smallKey = False d.smallKey = False
for dp in world.paired_doors[player]: for dp in world.paired_doors[player]:
if dp.door_a == d.name or dp.door_b == d.name: if dp.door_a == d.name or dp.door_b == d.name:
@@ -2299,6 +2300,8 @@ logical_connections = [
('GT Double Switch Entry to Left Barrier - Orange', 'GT Double Switch Left'), ('GT Double Switch Entry to Left Barrier - Orange', 'GT Double Switch Left'),
('GT Double Switch Entry to Ranged Switches', 'GT Double Switch Entry - Ranged Switches'), ('GT Double Switch Entry to Ranged Switches', 'GT Double Switch Entry - Ranged Switches'),
('GT Double Switch Entry Ranged Switches Exit', 'GT Double Switch Entry'), ('GT Double Switch Entry Ranged Switches Exit', 'GT Double Switch Entry'),
('GT Double Switch Left to Crystal', 'GT Double Switch Left - Crystal'),
('GT Double Switch Left Crystal Exit', 'GT Double Switch Left'),
('GT Double Switch Left to Entry Barrier - Orange', 'GT Double Switch Entry'), ('GT Double Switch Left to Entry Barrier - Orange', 'GT Double Switch Entry'),
('GT Double Switch Left to Entry Bypass', 'GT Double Switch Entry'), ('GT Double Switch Left to Entry Bypass', 'GT Double Switch Entry'),
('GT Double Switch Left to Pot Corners Bypass', 'GT Double Switch Pot Corners'), ('GT Double Switch Left to Pot Corners Bypass', 'GT Double Switch Pot Corners'),

View File

@@ -397,10 +397,10 @@ def create_doors(world, player):
create_door(player, 'PoD Arena Landing to Right Barrier - Blue', Lgcl), create_door(player, 'PoD Arena Landing to Right Barrier - Blue', Lgcl),
create_door(player, 'PoD Arena Landing to North Barrier - Orange', Lgcl), create_door(player, 'PoD Arena Landing to North Barrier - Orange', Lgcl),
create_door(player, 'PoD Arena Right to Landing Barrier - Blue', Lgcl), create_door(player, 'PoD Arena Right to Landing Barrier - Blue', Lgcl),
create_door(player, 'PoD Arena Right to Ranged Crystal', Lgcl), create_door(player, 'PoD Arena Right to Ranged Crystal', Lgcl), # considered out of logic
create_door(player, 'PoD Arena Right Ranged Crystal Exit', Lgcl), create_door(player, 'PoD Arena Right Ranged Crystal Exit', Lgcl).no_exit(), # blocked here for pre-validate
create_door(player, 'PoD Arena Ledge to Ranged Crystal', Lgcl), create_door(player, 'PoD Arena Ledge to Ranged Crystal', Lgcl), # considered out of logic
create_door(player, 'PoD Arena Ledge Ranged Crystal Exit', Lgcl), create_door(player, 'PoD Arena Ledge Ranged Crystal Exit', Lgcl).no_exit(), # blocked here for pre-validate
create_door(player, 'PoD Arena Ledge ES', Nrml).dir(Ea, 0x2a, Bot, High).pos(2), create_door(player, 'PoD Arena Ledge ES', Nrml).dir(Ea, 0x2a, Bot, High).pos(2),
create_door(player, 'PoD Sexy Statue W', Nrml).dir(We, 0x2b, Mid, High).pos(3), create_door(player, 'PoD Sexy Statue W', Nrml).dir(We, 0x2b, Mid, High).pos(3),
create_door(player, 'PoD Sexy Statue NW', Nrml).dir(No, 0x2b, Left, High).trap(0x1).pos(2), create_door(player, 'PoD Sexy Statue NW', Nrml).dir(No, 0x2b, Left, High).trap(0x1).pos(2),
@@ -875,7 +875,7 @@ def create_doors(world, player):
create_door(player, 'Mire Left Bridge Down Stairs', Sprl).dir(Dn, 0xa2, 0, HTL).ss(A, 0x12, 0x00), create_door(player, 'Mire Left Bridge Down Stairs', Sprl).dir(Dn, 0xa2, 0, HTL).ss(A, 0x12, 0x00),
create_door(player, 'Mire Fishbone E', Nrml).dir(Ea, 0xa1, Mid, High).pos(1), create_door(player, 'Mire Fishbone E', Nrml).dir(Ea, 0xa1, Mid, High).pos(1),
create_door(player, 'Mire Fishbone Blue Barrier', Lgcl), create_door(player, 'Mire Fishbone Blue Barrier', Lgcl),
create_door(player, 'Mire Fishbone Blue Barrier Bypass', Lgcl), create_door(player, 'Mire Fishbone Blue Barrier Bypass', Lgcl).no_exit(), # considered out of logic
create_door(player, 'Mire South Fish Blue Barrier', Lgcl), create_door(player, 'Mire South Fish Blue Barrier', Lgcl),
create_door(player, 'Mire Fishbone SE', Nrml).dir(So, 0xa1, Right, High).small_key().pos(0), create_door(player, 'Mire Fishbone SE', Nrml).dir(So, 0xa1, Right, High).small_key().pos(0),
create_door(player, 'Mire Spike Barrier NE', Nrml).dir(No, 0xb1, Right, High).small_key().pos(1), create_door(player, 'Mire Spike Barrier NE', Nrml).dir(No, 0xb1, Right, High).small_key().pos(1),
@@ -1116,16 +1116,18 @@ def create_doors(world, player):
create_door(player, 'GT Double Switch NW', Nrml).dir(No, 0x9b, Left, High).pos(1).kill(), create_door(player, 'GT Double Switch NW', Nrml).dir(No, 0x9b, Left, High).pos(1).kill(),
create_door(player, 'GT Double Switch Entry to Pot Corners Barrier - Orange', Lgcl), create_door(player, 'GT Double Switch Entry to Pot Corners Barrier - Orange', Lgcl),
create_door(player, 'GT Double Switch Entry to Left Barrier - Orange', Lgcl), create_door(player, 'GT Double Switch Entry to Left Barrier - Orange', Lgcl),
create_door(player, 'GT Double Switch Entry to Ranged Switches', Lgcl), create_door(player, 'GT Double Switch Entry to Ranged Switches', Lgcl), # considered out of logic
create_door(player, 'GT Double Switch Entry Ranged Switches Exit', Lgcl), create_door(player, 'GT Double Switch Entry Ranged Switches Exit', Lgcl).no_exit(), # blocked here for reasons
create_door(player, 'GT Double Switch Left to Crystal', Lgcl),
create_door(player, 'GT Double Switch Left Crystal Exit', Lgcl),
create_door(player, 'GT Double Switch Left to Entry Barrier - Orange', Lgcl), create_door(player, 'GT Double Switch Left to Entry Barrier - Orange', Lgcl),
create_door(player, 'GT Double Switch Left to Pot Corners Bypass', Lgcl), create_door(player, 'GT Double Switch Left to Pot Corners Bypass', Lgcl),
create_door(player, 'GT Double Switch Left to Entry Bypass', Lgcl), create_door(player, 'GT Double Switch Left to Entry Bypass', Lgcl),
create_door(player, 'GT Double Switch Left to Exit Bypass', Lgcl), create_door(player, 'GT Double Switch Left to Exit Bypass', Lgcl).no_exit(), # considered out of logic
create_door(player, 'GT Double Switch Pot Corners to Entry Barrier - Orange', Lgcl), create_door(player, 'GT Double Switch Pot Corners to Entry Barrier - Orange', Lgcl),
create_door(player, 'GT Double Switch Pot Corners to Exit Barrier - Blue', Lgcl), create_door(player, 'GT Double Switch Pot Corners to Exit Barrier - Blue', Lgcl),
create_door(player, 'GT Double Switch Pot Corners to Ranged Switches', Lgcl), create_door(player, 'GT Double Switch Pot Corners to Ranged Switches', Lgcl), # considered out of logic
create_door(player, 'GT Double Switch Pot Corners Ranged Switches Exit', Lgcl), create_door(player, 'GT Double Switch Pot Corners Ranged Switches Exit', Lgcl).no_exit(), # blocked here
create_door(player, 'GT Double Switch Exit to Blue Barrier', Lgcl), create_door(player, 'GT Double Switch Exit to Blue Barrier', Lgcl),
create_door(player, 'GT Double Switch EN', Intr).dir(Ea, 0x9b, Top, High).small_key().pos(0), create_door(player, 'GT Double Switch EN', Intr).dir(Ea, 0x9b, Top, High).small_key().pos(0),
create_door(player, 'GT Spike Crystals WN', Intr).dir(We, 0x9b, Top, High).small_key().pos(0), create_door(player, 'GT Spike Crystals WN', Intr).dir(We, 0x9b, Top, High).small_key().pos(0),
@@ -1438,6 +1440,7 @@ def create_doors(world, player):
world.get_door('GT Double Switch Entry to Pot Corners Barrier - Orange', player).barrier(CrystalBarrier.Orange) world.get_door('GT Double Switch Entry to Pot Corners Barrier - Orange', player).barrier(CrystalBarrier.Orange)
world.get_door('GT Double Switch Entry to Left Barrier - Orange', player).barrier(CrystalBarrier.Orange) world.get_door('GT Double Switch Entry to Left Barrier - Orange', player).barrier(CrystalBarrier.Orange)
world.get_door('GT Double Switch Entry Ranged Switches Exit', player).c_switch() world.get_door('GT Double Switch Entry Ranged Switches Exit', player).c_switch()
world.get_door('GT Double Switch Left Crystal Exit', player).c_switch()
world.get_door('GT Double Switch Left to Entry Barrier - Orange', player).barrier(CrystalBarrier.Orange) world.get_door('GT Double Switch Left to Entry Barrier - Orange', player).barrier(CrystalBarrier.Orange)
world.get_door('GT Double Switch Left to Entry Bypass', player).barrier(CrystalBarrier.Blue) world.get_door('GT Double Switch Left to Entry Bypass', player).barrier(CrystalBarrier.Blue)
world.get_door('GT Double Switch Left to Pot Corners Bypass', player).barrier(CrystalBarrier.Blue) world.get_door('GT Double Switch Left to Pot Corners Bypass', player).barrier(CrystalBarrier.Blue)

View File

@@ -304,7 +304,8 @@ gt_regions = [
'GT Crystal Conveyor Corner - Ranged Crystal', 'GT Crystal Conveyor Corner - Ranged Crystal',
'GT Compass Room', 'GT Invisible Bridges', 'GT Invisible Catwalk', 'GT Conveyor Cross', 'GT Hookshot East Platform', 'GT Compass Room', 'GT Invisible Bridges', 'GT Invisible Catwalk', 'GT Conveyor Cross', 'GT Hookshot East Platform',
'GT Hookshot North Platform', 'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Hookshot South Entry - Ranged Crystal', 'GT Map Room', 'GT Hookshot North Platform', 'GT Hookshot South Platform', 'GT Hookshot South Entry', 'GT Hookshot South Entry - Ranged Crystal', 'GT Map Room',
'GT Double Switch Entry', 'GT Double Switch Pot Corners - Ranged Switches', 'GT Double Switch Pot Corners', 'GT Double Switch Left', 'GT Double Switch Entry', 'GT Double Switch Pot Corners - Ranged Switches', 'GT Double Switch Pot Corners',
'GT Double Switch Left', 'GT Double Switch Left - Crystal',
'GT Double Switch Entry - Ranged Switches', 'GT Double Switch Exit', 'GT Spike Crystal Left', 'GT Double Switch Entry - Ranged Switches', 'GT Double Switch Exit', 'GT Spike Crystal Left',
'GT Spike Crystal Right', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section', 'GT Spike Crystal Right', 'GT Warp Maze - Left Section', 'GT Warp Maze - Mid Section',
'GT Warp Maze - Right Section', 'GT Warp Maze - Pit Section', 'GT Warp Maze - Pit Exit Warp Spot', 'GT Warp Maze - Right Section', 'GT Warp Maze - Pit Section', 'GT Warp Maze - Pit Exit Warp Spot',

View File

@@ -290,7 +290,9 @@ def main(args, seed=None, fish=None):
rom_names.append((player, team, list(rom.name))) rom_names.append((player, team, list(rom.name)))
world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash) 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.ow_palettes[player], args.uw_palettes[player]) apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
args.fastmenu[player], args.disablemusic[player], args.sprite[player],
args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player])
if args.jsonout: if args.jsonout:
jsonout[f'patch_t{team}_p{player}'] = rom.patches jsonout[f'patch_t{team}_p{player}'] = rom.patches

View File

@@ -876,7 +876,8 @@ def create_dungeon_regions(world, player):
create_dungeon_region(player, 'GT Double Switch Entry', 'Ganon\'s Tower', None, ['GT Double Switch NW', 'GT Double Switch Entry to Left Barrier - Orange', 'GT Double Switch Entry to Pot Corners Barrier - Orange', 'GT Double Switch Entry to Ranged Switches']), create_dungeon_region(player, 'GT Double Switch Entry', 'Ganon\'s Tower', None, ['GT Double Switch NW', 'GT Double Switch Entry to Left Barrier - Orange', 'GT Double Switch Entry to Pot Corners Barrier - Orange', 'GT Double Switch Entry to Ranged Switches']),
create_dungeon_region(player, 'GT Double Switch Entry - Ranged Switches', 'Ganon\'s Tower', None, ['GT Double Switch Entry Ranged Switches Exit']), create_dungeon_region(player, 'GT Double Switch Entry - Ranged Switches', 'Ganon\'s Tower', None, ['GT Double Switch Entry Ranged Switches Exit']),
create_dungeon_region(player, 'GT Double Switch Left', 'Ganon\'s Tower', None, ['GT Double Switch Left to Entry Barrier - Orange', 'GT Double Switch Left to Entry Bypass', 'GT Double Switch Left to Pot Corners Bypass', 'GT Double Switch Left to Exit Bypass']), create_dungeon_region(player, 'GT Double Switch Left', 'Ganon\'s Tower', None, ['GT Double Switch Left to Crystal', 'GT Double Switch Left to Entry Barrier - Orange', 'GT Double Switch Left to Entry Bypass', 'GT Double Switch Left to Pot Corners Bypass', 'GT Double Switch Left to Exit Bypass']),
create_dungeon_region(player, 'GT Double Switch Left - Crystal', 'Ganon\'s Tower', None, ['GT Double Switch Left Crystal Exit']),
create_dungeon_region(player, 'GT Double Switch Pot Corners', 'Ganon\'s Tower', ['Ganons Tower - Double Switch Pot Key'], ['GT Double Switch Pot Corners to Entry Barrier - Orange', 'GT Double Switch Pot Corners to Exit Barrier - Blue', 'GT Double Switch Pot Corners to Ranged Switches']), create_dungeon_region(player, 'GT Double Switch Pot Corners', 'Ganon\'s Tower', ['Ganons Tower - Double Switch Pot Key'], ['GT Double Switch Pot Corners to Entry Barrier - Orange', 'GT Double Switch Pot Corners to Exit Barrier - Blue', 'GT Double Switch Pot Corners to Ranged Switches']),
create_dungeon_region(player, 'GT Double Switch Pot Corners - Ranged Switches', 'Ganon\'s Tower', None, ['GT Double Switch Pot Corners Ranged Switches Exit']), create_dungeon_region(player, 'GT Double Switch Pot Corners - Ranged Switches', 'Ganon\'s Tower', None, ['GT Double Switch Pot Corners Ranged Switches Exit']),
create_dungeon_region(player, 'GT Double Switch Exit', 'Ganon\'s Tower', None, ['GT Double Switch EN', 'GT Double Switch Exit to Blue Barrier']), create_dungeon_region(player, 'GT Double Switch Exit', 'Ganon\'s Tower', None, ['GT Double Switch EN', 'GT Double Switch Exit to Blue Barrier']),
@@ -997,7 +998,7 @@ def create_dungeon_regions(world, player):
world.get_region('GT Crystal Conveyor Corner - Ranged Crystal', player).crystal_switch = True world.get_region('GT Crystal Conveyor Corner - Ranged Crystal', player).crystal_switch = True
world.get_region('GT Hookshot South Platform', player).crystal_switch = True world.get_region('GT Hookshot South Platform', player).crystal_switch = True
world.get_region('GT Hookshot South Entry - Ranged Crystal', player).crystal_switch = True world.get_region('GT Hookshot South Entry - Ranged Crystal', player).crystal_switch = True
world.get_region('GT Double Switch Left', player).crystal_switch = True world.get_region('GT Double Switch Left - Crystal', player).crystal_switch = True
world.get_region('GT Double Switch Entry - Ranged Switches', player).crystal_switch = True world.get_region('GT Double Switch Entry - Ranged Switches', player).crystal_switch = True
world.get_region('GT Double Switch Pot Corners - Ranged Switches', player).crystal_switch = True world.get_region('GT Double Switch Pot Corners - Ranged Switches', player).crystal_switch = True
world.get_region('GT Spike Crystal Left', player).crystal_switch = True world.get_region('GT Spike Crystal Left', player).crystal_switch = True

92
Rom.py
View File

@@ -496,8 +496,6 @@ class Sprite(object):
sprite_name = read_utf16le(stream) sprite_name = read_utf16le(stream)
author_name = read_utf16le(stream) author_name = read_utf16le(stream)
# Ignoring the Author Rom name for the time being.
real_csum = sum(filedata) % 0x10000 real_csum = sum(filedata) % 0x10000
if real_csum != csum or real_csum ^ 0xFFFF != icsum: if real_csum != csum or real_csum ^ 0xFFFF != icsum:
logger.warning('ZSPR file has incorrect checksum. It may be corrupted.') logger.warning('ZSPR file has incorrect checksum. It may be corrupted.')
@@ -1723,7 +1721,15 @@ def hud_format_text(text):
return output[:32] return output[:32]
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, ow_palettes, uw_palettes): def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite,
ow_palettes, uw_palettes, reduce_flashing):
if not os.path.exists("data/sprites/official/001.link.1.zspr"):
dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380],
rom.orig_buffer[0xdedf5:0xdedf9], "data/sprites/official/001.link.1.zspr", "Nintendo", "Link")
# todo: implement a flag for msu resume delay
rom.write_bytes(0x18021D, [0, 0]) # default to off for now
if sprite and not isinstance(sprite, Sprite): if sprite and not isinstance(sprite, Sprite):
sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite) sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite)
@@ -1780,6 +1786,32 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
if sprite is not None: if sprite is not None:
write_sprite(rom, sprite) write_sprite(rom, sprite)
# sprite author credits
padded_author = sprite.author_name if sprite is not None else "Nintendo"
padded_author = padded_author[:28] if len(padded_author) > 28 else padded_author
padded_author = padded_author.center(28).upper()
def convert_char_to_credits(char):
char_map = {
" ": (0x9F, 0x9F), "0": (0x53, 0x79), "1": (0x54, 0x7A), "2": (0x55, 0x7B), "3": (0x56, 0x7C),
"4": (0x57, 0x7D), "5": (0x58, 0x7E), "6": (0x59, 0x7F), "7": (0x5A, 0x80), "8": (0x5B, 0x81),
"9": (0x5C, 0x82), "A": (0x5D, 0x83), "B": (0x5E, 0x84), "C": (0x5F, 0x85), "D": (0x60, 0x86),
"E": (0x61, 0x87), "F": (0x62, 0x88), "G": (0x63, 0x89), "H": (0x64, 0x8A), "I": (0x65, 0x8B),
"J": (0x66, 0x8C), "K": (0x67, 0x8D), "L": (0x68, 0x8E), "M": (0x69, 0x8F), "N": (0x6A, 0x90),
"O": (0x6B, 0x91), "P": (0x6C, 0x92), "Q": (0x6D, 0x93), "R": (0x6E, 0x94), "S": (0x6F, 0x95),
"T": (0x70, 0x96), "U": (0x71, 0x97), "V": (0x72, 0x98), "W": (0x73, 0x99), "X": (0x74, 0x9A),
"Y": (0x75, 0x9B), "Z": (0x76, 0x9C), "'": (0x77, 0x9d), ".": (0xA0, 0xC0), "/": (0xA2, 0xC2),
":": (0xA3, 0xC3), "_": (0xA6, 0xC6)}
return char_map[char] if char in char_map else (0x9F, 0x9F)
character_bytes = map(convert_char_to_credits, padded_author)
for i, pair in enumerate(character_bytes):
rom.write_byte(0x118002 + i, pair[0])
rom.write_byte(0x118020 + i, pair[1])
if reduce_flashing:
rom.write_byte(0x18017f, 1)
default_ow_palettes(rom) default_ow_palettes(rom)
if ow_palettes == 'random': if ow_palettes == 'random':
randomize_ow_palettes(rom) randomize_ow_palettes(rom)
@@ -1795,6 +1827,60 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
if isinstance(rom, LocalRom): if isinstance(rom, LocalRom):
rom.write_crc() rom.write_crc()
# .zspr file dumping logic copied with permission from SpriteSomething:
# https://github.com/Artheau/SpriteSomething/blob/master/source/meta/classes/spritelib.py#L443 (thanks miketrethewey!)
def dump_zspr(basesprite, basepalette, baseglove, outfilename, author_name, sprite_name):
palettes = basepalette
# Add glove data
palettes.extend(baseglove)
HEADER_STRING = b"ZSPR"
VERSION = 0x01
SPRITE_TYPE = 0x01 # this format has "1" for the player sprite
RESERVED_BYTES = b'\x00\x00\x00\x00\x00\x00'
QUAD_BYTE_NULL_CHAR = b'\x00\x00\x00\x00'
DOUBLE_BYTE_NULL_CHAR = b'\x00\x00'
SINGLE_BYTE_NULL_CHAR = b'\x00'
write_buffer = bytearray()
write_buffer.extend(HEADER_STRING)
write_buffer.extend(struct.pack('B', VERSION)) # as_u8
checksum_start = len(write_buffer)
write_buffer.extend(QUAD_BYTE_NULL_CHAR) # checksum
sprite_sheet_pointer = len(write_buffer)
write_buffer.extend(QUAD_BYTE_NULL_CHAR)
write_buffer.extend(struct.pack('<H', len(basesprite))) # as_u16
palettes_pointer = len(write_buffer)
write_buffer.extend(QUAD_BYTE_NULL_CHAR)
write_buffer.extend(struct.pack('<H', len(palettes))) # as_u16
write_buffer.extend(struct.pack('<H', SPRITE_TYPE)) # as_u16
write_buffer.extend(RESERVED_BYTES)
# sprite.name
write_buffer.extend(sprite_name.encode('utf-16-le'))
write_buffer.extend(DOUBLE_BYTE_NULL_CHAR)
# author.name
write_buffer.extend(author_name.encode('utf-16-le'))
write_buffer.extend(DOUBLE_BYTE_NULL_CHAR)
# author.name-short
write_buffer.extend(author_name.encode('ascii'))
write_buffer.extend(SINGLE_BYTE_NULL_CHAR)
write_buffer[sprite_sheet_pointer:sprite_sheet_pointer +
4] = struct.pack('<L', len(write_buffer)) # as_u32
write_buffer.extend(basesprite)
write_buffer[palettes_pointer:palettes_pointer +
4] = struct.pack('<L', len(write_buffer)) # as_u32
write_buffer.extend(palettes)
checksum = (sum(write_buffer) + 0xFF + 0xFF) % 0x10000
checksum_complement = 0xFFFF - checksum
write_buffer[checksum_start:checksum_start +
2] = struct.pack('<H', checksum) # as_u16
write_buffer[checksum_start + 2:checksum_start +
4] = struct.pack('<H', checksum_complement) # as_u16
with open('%s' % outfilename, "wb") as zspr_file:
zspr_file.write(write_buffer)
def write_sprite(rom, sprite): def write_sprite(rom, sprite):
if not sprite.valid: if not sprite.valid:

View File

@@ -445,7 +445,7 @@ def global_rules(world, player):
set_rule(world.get_entrance('Hera Front to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('Hera Front to Crystal', player), lambda state: state.can_hit_crystal(player))
set_rule(world.get_entrance('Hera Down Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Hera Down Stairs Landing', player), player))) # or state.has_beam_sword(player) set_rule(world.get_entrance('Hera Down Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_blue(world.get_region('Hera Down Stairs Landing', player), player))) # or state.has_beam_sword(player)
set_rule(world.get_entrance('Hera Up Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('Hera Up Stairs Landing', player), player))) # or state.has_beam_sword(player) set_rule(world.get_entrance('Hera Up Stairs Landing to Ranged Crystal', player), lambda state: state.can_hit_crystal_through_barrier(player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('Hera Up Stairs Landing', player), player))) # or state.has_beam_sword(player)
set_rule(world.get_entrance('Hera Back to Ranged Crystal', player), lambda state: False) # state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.has('Red Boomerang', player)) set_rule(world.get_entrance('Hera Back to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) or (state.has('Hookshot', player) and state.has('Red Boomerang', player))
set_rule(world.get_entrance('Hera Front to Back Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Cane of Somaria', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player)) # or state.has_beam_sword(player) set_rule(world.get_entrance('Hera Front to Back Bypass', player), lambda state: state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Cane of Somaria', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player)) # or state.has_beam_sword(player)
set_rule(world.get_entrance('Hera Basement Cage to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('Hera Basement Cage to Crystal', player), lambda state: state.can_hit_crystal(player))
set_rule(world.get_entrance('Hera Tridorm to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('Hera Tridorm to Crystal', player), lambda state: state.can_hit_crystal(player))
@@ -473,7 +473,7 @@ def global_rules(world, player):
set_rule(world.get_entrance('PoD Map Balcony to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) # or state.has('Red Boomerang', player) set_rule(world.get_entrance('PoD Map Balcony to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) # or state.has('Red Boomerang', player)
set_rule(world.get_entrance('PoD Bow Statue Left to Crystal', player), lambda state: state.can_hit_crystal(player)) set_rule(world.get_entrance('PoD Bow Statue Left to Crystal', player), lambda state: state.can_hit_crystal(player))
set_rule(world.get_entrance('PoD Bow Statue Right to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) set_rule(world.get_entrance('PoD Bow Statue Right to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player))
set_rule(world.get_entrance('PoD Bow Statue Left to Right Bypass', player), lambda state: state.has('Cane of Somaria', player)) # or state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has_beam_sword(player) or state.has('Red Boomrang', player) or state.has('Ice Rod', player) or state.has('Fire Rod', player) set_rule(world.get_entrance('PoD Bow Statue Left to Right Bypass', player), lambda state: state.has('Cane of Somaria', player) or state.can_use_bombs(player) or state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Ice Rod', player) or state.has('Fire Rod', player)) # or state.has_beam_sword(player)
set_rule(world.get_entrance('PoD Dark Pegs Landing to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.can_use_bombs(player) or state.has('Blue boomerang', player) or state.has('Red boomerang', player) set_rule(world.get_entrance('PoD Dark Pegs Landing to Ranged Crystal', player), lambda state: state.has('Cane of Somaria', player)) # or state.can_use_bombs(player) or state.has('Blue boomerang', player) or state.has('Red boomerang', player)
set_rule(world.get_entrance('PoD Dark Pegs Middle to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.can_use_bombs(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('PoD Dark Pegs Middle', player), player))) # or state.has_beam_sword(player) set_rule(world.get_entrance('PoD Dark Pegs Middle to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.can_use_bombs(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player) or (state.has('Hookshot', player) and state.can_reach_orange(world.get_region('PoD Dark Pegs Middle', player), player))) # or state.has_beam_sword(player)
set_rule(world.get_entrance('PoD Dark Pegs Left to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player) set_rule(world.get_entrance('PoD Dark Pegs Left to Ranged Crystal', player), lambda state: state.can_shoot_arrows(player) or state.has('Red Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.has('Cane of Somaria', player)) # or state.has_beam_sword(player)
@@ -579,14 +579,15 @@ def global_rules(world, player):
set_rule(world.get_entrance('GT Crystal Conveyor Left to Corner Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Conveyor Left', player), player)) set_rule(world.get_entrance('GT Crystal Conveyor Left to Corner Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Conveyor Left', player), player))
set_rule(world.get_entrance('GT Crystal Circles Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Circles', player), player)) set_rule(world.get_entrance('GT Crystal Circles Barrier - Orange', player), lambda state: state.can_reach_orange(world.get_region('GT Crystal Circles', player), player))
set_rule(world.get_entrance('GT Hookshot Platform Barrier Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or state.has('Cane of Somaria', player)) # or state.has_Boots(player) /// There is a super precise trick where you can throw a pot and climp into the blue barrier, then sprint out of them. set_rule(world.get_entrance('GT Hookshot Platform Barrier Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or state.has('Cane of Somaria', player)) # or state.has_Boots(player) /// There is a super precise trick where you can throw a pot and climp into the blue barrier, then sprint out of them.
set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player))
set_rule(world.get_entrance('GT Double Switch Left to Crystal', player), lambda state: state.can_hit_crystal(player))
set_rule(world.get_entrance('GT Double Switch Entry to Ranged Switches', player), lambda state: False) # state.has('Cane of Somaria', player) set_rule(world.get_entrance('GT Double Switch Entry to Ranged Switches', player), lambda state: False) # state.has('Cane of Somaria', player)
set_rule(world.get_entrance('GT Double Switch Left to Entry Bypass', player), lambda state: True) # Can always use pots set_rule(world.get_entrance('GT Double Switch Left to Entry Bypass', player), lambda state: True) # Can always use pots
set_rule(world.get_entrance('GT Double Switch Left to Pot Corners Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player) or state.has('Red Boomerang', player)) # or (state.has('Blue Boomerang', player) and state.has('Hookshot', player)) or (state.has('Ice Rod', player) and state.has('Hookshot', player)) or state.has('Hookshot', player) /// You can do this with just a pot and a hookshot set_rule(world.get_entrance('GT Double Switch Left to Pot Corners Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player) or state.has('Red Boomerang', player)) # or (state.has('Blue Boomerang', player) and state.has('Hookshot', player)) or (state.has('Ice Rod', player) and state.has('Hookshot', player)) or state.has('Hookshot', player) /// You can do this with just a pot and a hookshot
set_rule(world.get_entrance('GT Double Switch Left to Exit Bypass', player), lambda state: False) # state.can_use_bombs(player) or (state.has('Cane of Somaria', player) and (state.has('Red Boomerang', player) or (state.has('Hookshot', player) and state.has('Blue Boomerang', player)) or (state.has('Hookshot', player) and state.has('Ice Rod', player)))) set_rule(world.get_entrance('GT Double Switch Left to Exit Bypass', player), lambda state: False) # state.can_use_bombs(player) or (state.has('Cane of Somaria', player) and (state.has('Red Boomerang', player) or (state.has('Hookshot', player) and state.has('Blue Boomerang', player)) or (state.has('Hookshot', player) and state.has('Ice Rod', player))))
set_rule(world.get_entrance('GT Double Switch Pot Corners to Ranged Switches', player), lambda state: False) # state.can_use_bombs(player) or state.has('Cane of Somaria', player) or (state.has('Cane of Somaria', player) and state.has_Boots(player)) /// There's two ways to interact with the switch. Somaria bounce at the top corner, or timed throws at the bottom corner. set_rule(world.get_entrance('GT Double Switch Pot Corners to Ranged Switches', player), lambda state: False) # state.can_use_bombs(player) or state.has('Cane of Somaria', player) or (state.has('Cane of Somaria', player) and state.has_Boots(player)) /// There's two ways to interact with the switch. Somaria bounce at the top corner, or timed throws at the bottom corner.
set_rule(world.get_entrance('GT Spike Crystal Left to Right Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player)) # or state.has('Fire Rod', player) or state.has('Ice Rod', player) or state.can_use_beam_sword(player) set_rule(world.get_entrance('GT Spike Crystal Left to Right Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player) or state.has('Red Boomerang', player) or state.has('Blue Boomerang', player) or state.has('Fire Rod', player) or state.has('Ice Rod', player)) # or state.can_use_beam_sword(player)
set_rule(world.get_entrance('GT Crystal Conveyor to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Crystal Conveyor to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player))
set_rule(world.get_entrance('GT Crystal Conveyor Corner to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Crystal Conveyor Corner to Ranged Crystal', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player))
set_rule(world.get_entrance('GT Crystal Conveyor Corner to Left Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player)) set_rule(world.get_entrance('GT Crystal Conveyor Corner to Left Bypass', player), lambda state: state.can_use_bombs(player) or state.has('Cane of Somaria', player))
@@ -1596,6 +1597,8 @@ def standard_rules(world, player):
add_rule(world.get_entrance('Hyrule Castle Main Gate (North)', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_entrance('Hyrule Castle Main Gate (North)', player), lambda state: state.has('Zelda Delivered', player))
add_rule(world.get_entrance('Hyrule Castle Ledge Drop', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_entrance('Hyrule Castle Ledge Drop', player), lambda state: state.has('Zelda Delivered', player))
# don't allow bombs to get past here before zelda is rescued
set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: (state.can_use_bombs(player) and state.has('Zelda Delivered', player)) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player))
def find_rules_for_zelda_delivery(world, player): def find_rules_for_zelda_delivery(world, player):
# path rules for backtracking # path rules for backtracking

View File

@@ -239,6 +239,10 @@
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"
}, },
"reduce_flashing": {
"action": "store_true",
"type": "bool"
},
"mapshuffle": { "mapshuffle": {
"action": "store_true", "action": "store_true",
"type": "bool" "type": "bool"

View File

@@ -306,7 +306,7 @@
"Include the Ganon's Tower and Pyramid Hole in the", "Include the Ganon's Tower and Pyramid Hole in the",
"entrance shuffle pool. (default: %(default)s)" "entrance shuffle pool. (default: %(default)s)"
], ],
"shufflelink": [ "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)"
], ],
"heartbeep": [ "heartbeep": [
@@ -321,6 +321,7 @@
"Alternatively, can be a ALttP Rom patched with a Link", "Alternatively, can be a ALttP Rom patched with a Link",
"sprite that will be extracted." "sprite that will be extracted."
], ],
"reduce_flashing": [ "Reduce some in-game flashing (default: %(default)s)" ],
"create_rom": [ "Create an output rom file. (default: %(default)s)" ], "create_rom": [ "Create an output rom file. (default: %(default)s)" ],
"gui": [ "Launch the GUI. (default: %(default)s)" ], "gui": [ "Launch the GUI. (default: %(default)s)" ],
"jsonout": [ "jsonout": [

View File

@@ -1,7 +1,8 @@
{ {
"checkboxes": { "checkboxes": {
"nobgm": { "type": "checkbox" }, "nobgm": { "type": "checkbox" },
"quickswap": { "type": "checkbox" } "quickswap": { "type": "checkbox" },
"reduce_flashing": {"type": "checkbox"}
}, },
"leftAdjustFrame": { "leftAdjustFrame": {
"heartcolor": { "heartcolor": {

View File

@@ -148,6 +148,7 @@
"randomizer.gameoptions.nobgm": "Disable Music & MSU-1", "randomizer.gameoptions.nobgm": "Disable Music & MSU-1",
"randomizer.gameoptions.quickswap": "L/R Quickswapping", "randomizer.gameoptions.quickswap": "L/R Quickswapping",
"randomizer.gameoptions.reduce_flashing": "Reduce Flashing",
"randomizer.gameoptions.heartcolor": "Heart Color", "randomizer.gameoptions.heartcolor": "Heart Color",
"randomizer.gameoptions.heartcolor.red": "Red", "randomizer.gameoptions.heartcolor.red": "Red",

View File

@@ -1,7 +1,8 @@
{ {
"checkboxes": { "checkboxes": {
"nobgm": { "type": "checkbox" }, "nobgm": { "type": "checkbox" },
"quickswap": { "type": "checkbox" } "quickswap": { "type": "checkbox" },
"reduce_flashing": { "type": "checkbox" }
}, },
"leftRomOptionsFrame": { "leftRomOptionsFrame": {
"heartcolor": { "heartcolor": {

View File

@@ -110,7 +110,7 @@ class SpriteSelector(object):
sprites = [] sprites = []
for file in glob(output_path(path)): for file in glob(path):
sprites.append(Sprite(file)) sprites.append(Sprite(file))
sprites.sort(key=lambda s: str.lower(s.name or "").strip()) sprites.sort(key=lambda s: str.lower(s.name or "").strip())
@@ -161,7 +161,8 @@ class SpriteSelector(object):
task.update_status("Determining needed sprites") task.update_status("Determining needed sprites")
current_sprites = [os.path.basename(file) for file in glob(os.path.join(self.official_sprite_dir,"*"))] current_sprites = [os.path.basename(file) for file in glob(os.path.join(self.official_sprite_dir,"*"))]
official_sprites = [(sprite['file'], os.path.basename(urlparse(sprite['file']).path)) for sprite in sprites_arr] official_sprites = [(sprite['file'], os.path.basename(urlparse(sprite['file']).path)) for sprite in sprites_arr]
needed_sprites = [(sprite_url, filename) for (sprite_url, filename) in official_sprites if filename not in current_sprites] needed_sprites = [(sprite_url, filename) for (sprite_url, filename) in official_sprites
if filename not in current_sprites and filename != "001.link.1.zspr"]
bundled_sprites = [os.path.basename(file) for file in glob(os.path.join(self.unofficial_sprite_dir,"*"))] bundled_sprites = [os.path.basename(file) for file in glob(os.path.join(self.unofficial_sprite_dir,"*"))]
# todo: eventually use the above list to avoid downloading any sprites that we already have cached in the bundle. # todo: eventually use the above list to avoid downloading any sprites that we already have cached in the bundle.

View File

@@ -111,7 +111,8 @@ SETTINGSTOPROCESS = {
"heartbeep": "heartbeep", "heartbeep": "heartbeep",
"menuspeed": "fastmenu", "menuspeed": "fastmenu",
"owpalettes": "ow_palettes", "owpalettes": "ow_palettes",
"uwpalettes": "uw_palettes" "uwpalettes": "uw_palettes",
"reduce_flashing": "reduce_flashing"
}, },
"generation": { "generation": {
"createspoiler": "create_spoiler", "createspoiler": "create_spoiler",

View File

@@ -101,7 +101,8 @@ def adjust_page(top, parent, settings):
"owpalettes": "ow_palettes", "owpalettes": "ow_palettes",
"uwpalettes": "uw_palettes", "uwpalettes": "uw_palettes",
"quickswap": "quickswap", "quickswap": "quickswap",
"nobgm": "disablemusic" "nobgm": "disablemusic",
"reduce_flashing": "reduce_flashing"
} }
guiargs = Namespace() guiargs = Namespace()
for option in options: for option in options:
@@ -110,6 +111,7 @@ def adjust_page(top, parent, settings):
guiargs.rom = self.romVar2.get() guiargs.rom = self.romVar2.get()
guiargs.baserom = top.pages["randomizer"].pages["generation"].widgets["rom"].storageVar.get() guiargs.baserom = top.pages["randomizer"].pages["generation"].widgets["rom"].storageVar.get()
guiargs.sprite = self.sprite guiargs.sprite = self.sprite
guiargs.outputpath = os.path.dirname(guiargs.rom)
try: try:
adjust(args=guiargs) adjust(args=guiargs)
except Exception as e: except Exception as e: