Merged in DR v1.4.1.11
This commit is contained in:
298
BaseClasses.py
298
BaseClasses.py
@@ -20,7 +20,7 @@ from source.dungeon.RoomObject import RoomObject
|
|||||||
class World(object):
|
class World(object):
|
||||||
|
|
||||||
def __init__(self, players, owShuffle, owCrossed, owMixed, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments,
|
def __init__(self, players, owShuffle, owCrossed, owMixed, shuffle, doorShuffle, logic, mode, swords, difficulty, difficulty_adjustments,
|
||||||
timer, progressive, goal, algorithm, accessibility, shuffle_ganon, custom, customitemarray, hints):
|
timer, progressive, goal, algorithm, accessibility, shuffle_ganon, custom, customitemarray, hints, spoiler_mode):
|
||||||
self.players = players
|
self.players = players
|
||||||
self.teams = 1
|
self.teams = 1
|
||||||
self.owShuffle = owShuffle.copy()
|
self.owShuffle = owShuffle.copy()
|
||||||
@@ -78,6 +78,7 @@ class World(object):
|
|||||||
self.prizes = {}
|
self.prizes = {}
|
||||||
self.dynamic_regions = []
|
self.dynamic_regions = []
|
||||||
self.dynamic_locations = []
|
self.dynamic_locations = []
|
||||||
|
self.spoiler_mode = spoiler_mode
|
||||||
self.spoiler = Spoiler(self)
|
self.spoiler = Spoiler(self)
|
||||||
self.lamps_needed_for_dark_rooms = 1
|
self.lamps_needed_for_dark_rooms = 1
|
||||||
self.owedges = []
|
self.owedges = []
|
||||||
@@ -106,6 +107,7 @@ class World(object):
|
|||||||
self.data_tables = {}
|
self.data_tables = {}
|
||||||
self.damage_table = {}
|
self.damage_table = {}
|
||||||
|
|
||||||
|
|
||||||
for player in range(1, players + 1):
|
for player in range(1, players + 1):
|
||||||
def set_player_attr(attr, val):
|
def set_player_attr(attr, val):
|
||||||
self.__dict__.setdefault(attr, {})[player] = val
|
self.__dict__.setdefault(attr, {})[player] = val
|
||||||
@@ -2869,6 +2871,17 @@ class Spoiler(object):
|
|||||||
self.metadata = {}
|
self.metadata = {}
|
||||||
self.shops = []
|
self.shops = []
|
||||||
self.bosses = OrderedDict()
|
self.bosses = OrderedDict()
|
||||||
|
if world.spoiler_mode == 'settings':
|
||||||
|
self.settings = {'settings'}
|
||||||
|
elif world.spoiler_mode == 'semi':
|
||||||
|
self.settings = {'settings', 'entrances', 'requirements', 'prizes'}
|
||||||
|
elif world.spoiler_mode == 'full':
|
||||||
|
self.settings = {'all'}
|
||||||
|
elif world.spoiler_mode == 'debug':
|
||||||
|
self.settings = {'all', 'debug'}
|
||||||
|
else:
|
||||||
|
self.settings = {}
|
||||||
|
|
||||||
|
|
||||||
self.suppress_spoiler_locations = ['Big Bomb', 'Frog', 'Dark Blacksmith Ruins', 'Middle Aged Man', 'Lost Old Man', 'Old Man Drop Off']
|
self.suppress_spoiler_locations = ['Big Bomb', 'Frog', 'Dark Blacksmith Ruins', 'Middle Aged Man', 'Lost Old Man', 'Old Man Drop Off']
|
||||||
|
|
||||||
@@ -3012,27 +3025,29 @@ class Spoiler(object):
|
|||||||
self.bottles[f'Waterfall Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][0]
|
self.bottles[f'Waterfall Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][0]
|
||||||
self.bottles[f'Pyramid Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][1]
|
self.bottles[f'Pyramid Bottle ({self.world.get_player_names(player)})'] = self.world.bottle_refills[player][1]
|
||||||
|
|
||||||
|
def include_item(item):
|
||||||
|
return 'all' in self.settings or ('items' in self.settings and not item.crystal) or ('prizes' in self.settings and item.crystal)
|
||||||
self.locations = OrderedDict()
|
self.locations = OrderedDict()
|
||||||
listed_locations = set()
|
listed_locations = set()
|
||||||
|
|
||||||
lw_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.LightWorld and not loc.skip]
|
lw_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.LightWorld and not loc.skip and include_item(loc.item)]
|
||||||
self.locations['Light World'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in lw_locations])
|
self.locations['Light World'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in lw_locations])
|
||||||
listed_locations.update(lw_locations)
|
listed_locations.update(lw_locations)
|
||||||
|
|
||||||
dw_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.DarkWorld and not loc.skip]
|
dw_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.DarkWorld and not loc.skip and include_item(loc.item)]
|
||||||
self.locations['Dark World'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dw_locations])
|
self.locations['Dark World'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dw_locations])
|
||||||
listed_locations.update(dw_locations)
|
listed_locations.update(dw_locations)
|
||||||
|
|
||||||
cave_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.Cave and not loc.skip]
|
cave_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.type == RegionType.Cave and not loc.skip and include_item(loc.item)]
|
||||||
self.locations['Caves'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in cave_locations])
|
self.locations['Caves'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in cave_locations])
|
||||||
listed_locations.update(cave_locations)
|
listed_locations.update(cave_locations)
|
||||||
|
|
||||||
for dungeon in self.world.dungeons:
|
for dungeon in self.world.dungeons:
|
||||||
dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item and not loc.skip]
|
dungeon_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and loc.parent_region and loc.parent_region.dungeon == dungeon and not loc.forced_item and not loc.skip and include_item(loc.item)]
|
||||||
self.locations[str(dungeon)] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations])
|
self.locations[str(dungeon)] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in dungeon_locations])
|
||||||
listed_locations.update(dungeon_locations)
|
listed_locations.update(dungeon_locations)
|
||||||
|
|
||||||
other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and not loc.skip]
|
other_locations = [loc for loc in self.world.get_locations() if loc not in listed_locations and not loc.skip and include_item(loc.item)]
|
||||||
if other_locations:
|
if other_locations:
|
||||||
self.locations['Other Locations'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in other_locations])
|
self.locations['Other Locations'] = OrderedDict([(location.gen_name(), str(location.item) if location.item is not None else 'Nothing') for location in other_locations])
|
||||||
listed_locations.update(other_locations)
|
listed_locations.update(other_locations)
|
||||||
@@ -3132,85 +3147,88 @@ class Spoiler(object):
|
|||||||
outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v)
|
outfile.write((k + ' Version:').ljust(line_width) + '%s\n' % v)
|
||||||
if self.metadata['user_notes']:
|
if self.metadata['user_notes']:
|
||||||
outfile.write('User Notes:'.ljust(line_width) + '%s\n' % self.metadata['user_notes'])
|
outfile.write('User Notes:'.ljust(line_width) + '%s\n' % self.metadata['user_notes'])
|
||||||
outfile.write('Filling Algorithm:'.ljust(line_width) + '%s\n' % self.world.algorithm)
|
if 'all' in self.settings or 'settings' in self.settings:
|
||||||
|
outfile.write('Filling Algorithm:'.ljust(line_width) + '%s\n' % self.world.algorithm)
|
||||||
outfile.write('Players:'.ljust(line_width) + '%d\n' % self.world.players)
|
outfile.write('Players:'.ljust(line_width) + '%d\n' % self.world.players)
|
||||||
outfile.write('Teams:'.ljust(line_width) + '%d\n' % self.world.teams)
|
outfile.write('Teams:'.ljust(line_width) + '%d\n' % self.world.teams)
|
||||||
for player in range(1, self.world.players + 1):
|
for player in range(1, self.world.players + 1):
|
||||||
if self.world.players > 1:
|
if self.world.players > 1:
|
||||||
outfile.write('\nPlayer %d: %s\n' % (player, self.world.get_player_names(player)))
|
outfile.write('\nPlayer %d: %s\n' % (player, self.world.get_player_names(player)))
|
||||||
outfile.write('Settings Code:'.ljust(line_width) + '%s\n' % self.metadata["code"][player])
|
if 'all' in self.settings or 'settings' in self.settings:
|
||||||
|
outfile.write('Settings Code:'.ljust(line_width) + '%s\n' % self.metadata["code"][player])
|
||||||
outfile.write('\n')
|
outfile.write('\n')
|
||||||
outfile.write('Mode:'.ljust(line_width) + '%s\n' % self.metadata['mode'][player])
|
if 'all' in self.settings or 'settings' in self.settings:
|
||||||
outfile.write('Logic:'.ljust(line_width) + '%s\n' % self.metadata['logic'][player])
|
outfile.write('Mode:'.ljust(line_width) + '%s\n' % self.metadata['mode'][player])
|
||||||
outfile.write('Goal:'.ljust(line_width) + '%s\n' % self.metadata['goal'][player])
|
outfile.write('Logic:'.ljust(line_width) + '%s\n' % self.metadata['logic'][player])
|
||||||
if self.metadata['goal'][player] in ['triforcehunt', 'trinity', 'ganonhunt']:
|
outfile.write('Goal:'.ljust(line_width) + '%s\n' % self.metadata['goal'][player])
|
||||||
outfile.write('Triforce Pieces Required:'.ljust(line_width) + '%s\n' % self.metadata['triforcegoal'][player])
|
if self.metadata['goal'][player] in ['triforcehunt', 'trinity', 'ganonhunt']:
|
||||||
outfile.write('Triforce Pieces Total:'.ljust(line_width) + '%s\n' % self.metadata['triforcepool'][player])
|
outfile.write('Triforce Pieces Required:'.ljust(line_width) + '%s\n' % self.metadata['triforcegoal'][player])
|
||||||
outfile.write('Crystals Required for GT:'.ljust(line_width) + '%s\n' % str(self.world.crystals_gt_orig[player]))
|
outfile.write('Triforce Pieces Total:'.ljust(line_width) + '%s\n' % self.metadata['triforcepool'][player])
|
||||||
outfile.write('Crystals Required for Ganon:'.ljust(line_width) + '%s\n' % str(self.world.crystals_ganon_orig[player]))
|
outfile.write('Crystals Required for GT:'.ljust(line_width) + '%s\n' % str(self.world.crystals_gt_orig[player]))
|
||||||
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
|
outfile.write('Crystals Required for Ganon:'.ljust(line_width) + '%s\n' % str(self.world.crystals_ganon_orig[player]))
|
||||||
outfile.write('\n')
|
outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player])
|
||||||
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
|
outfile.write('\n')
|
||||||
outfile.write('Restricted Boss Items:'.ljust(line_width) + '%s\n' % self.metadata['restricted_boss_items'][player])
|
outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player])
|
||||||
outfile.write('Item Functionality:'.ljust(line_width) + '%s\n' % self.metadata['item_functionality'][player])
|
outfile.write('Restricted Boss Items:'.ljust(line_width) + '%s\n' % self.metadata['restricted_boss_items'][player])
|
||||||
outfile.write('Difficulty:'.ljust(line_width) + '%s\n' % self.metadata['item_pool'][player])
|
outfile.write('Item Functionality:'.ljust(line_width) + '%s\n' % self.metadata['item_functionality'][player])
|
||||||
outfile.write('Flute Mode:'.ljust(line_width) + '%s\n' % self.metadata['flute_mode'][player])
|
outfile.write('Difficulty:'.ljust(line_width) + '%s\n' % self.metadata['item_pool'][player])
|
||||||
outfile.write('Bow Mode:'.ljust(line_width) + '%s\n' % self.metadata['bow_mode'][player])
|
outfile.write('Flute Mode:'.ljust(line_width) + '%s\n' % self.metadata['flute_mode'][player])
|
||||||
outfile.write('Beemizer:'.ljust(line_width) + '%s\n' % self.metadata['beemizer'][player])
|
outfile.write('Bow Mode:'.ljust(line_width) + '%s\n' % self.metadata['bow_mode'][player])
|
||||||
outfile.write('Bombbag:'.ljust(line_width) + '%s\n' % yn(self.metadata['bombbag'][player]))
|
outfile.write('Beemizer:'.ljust(line_width) + '%s\n' % self.metadata['beemizer'][player])
|
||||||
outfile.write('\n')
|
outfile.write('Bombbag:'.ljust(line_width) + '%s\n' % yn(self.metadata['bombbag'][player]))
|
||||||
outfile.write('Shopsanity:'.ljust(line_width) + '%s\n' % yn(self.metadata['shopsanity'][player]))
|
outfile.write('\n')
|
||||||
outfile.write('Bonk Drops:'.ljust(line_width) + '%s\n' % yn(self.metadata['bonk_drops'][player]))
|
outfile.write('Shopsanity:'.ljust(line_width) + '%s\n' % yn(self.metadata['shopsanity'][player]))
|
||||||
outfile.write('Pottery Mode:'.ljust(line_width) + '%s\n' % self.metadata['pottery'][player])
|
outfile.write('Bonk Drops:'.ljust(line_width) + '%s\n' % yn(self.metadata['bonk_drops'][player]))
|
||||||
outfile.write('Pot Shuffle (Legacy):'.ljust(line_width) + '%s\n' % yn(self.metadata['potshuffle'][player]))
|
outfile.write('Pottery Mode:'.ljust(line_width) + '%s\n' % self.metadata['pottery'][player])
|
||||||
outfile.write('Enemy Drop Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['dropshuffle'][player])
|
outfile.write('Pot Shuffle (Legacy):'.ljust(line_width) + '%s\n' % yn(self.metadata['potshuffle'][player]))
|
||||||
outfile.write('Take Any Caves:'.ljust(line_width) + '%s\n' % self.metadata['take_any'][player])
|
outfile.write('Enemy Drop Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['dropshuffle'][player])
|
||||||
outfile.write('\n')
|
outfile.write('Take Any Caves:'.ljust(line_width) + '%s\n' % self.metadata['take_any'][player])
|
||||||
outfile.write('Overworld Layout Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_shuffle'][player])
|
outfile.write('\n')
|
||||||
if self.metadata['ow_shuffle'][player] != 'vanilla':
|
outfile.write('Overworld Layout Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_shuffle'][player])
|
||||||
outfile.write('Free Terrain:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_terrain'][player]))
|
if self.metadata['ow_shuffle'][player] != 'vanilla':
|
||||||
outfile.write('Crossed OW:'.ljust(line_width) + '%s\n' % self.metadata['ow_crossed'][player])
|
outfile.write('Free Terrain:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_terrain'][player]))
|
||||||
if self.metadata['ow_shuffle'][player] != 'vanilla' or self.metadata['ow_crossed'][player] != 'none':
|
outfile.write('Crossed OW:'.ljust(line_width) + '%s\n' % self.metadata['ow_crossed'][player])
|
||||||
outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_keepsimilar'][player]))
|
if self.metadata['ow_shuffle'][player] != 'vanilla' or self.metadata['ow_crossed'][player] != 'none':
|
||||||
outfile.write('OW Tile Flip (Mixed):'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_mixed'][player]))
|
outfile.write('Keep Similar OW Edges Together:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_keepsimilar'][player]))
|
||||||
outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_whirlpool'][player]))
|
outfile.write('OW Tile Flip (Mixed):'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_mixed'][player]))
|
||||||
outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player])
|
outfile.write('Whirlpool Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['ow_whirlpool'][player]))
|
||||||
outfile.write('\n')
|
outfile.write('Flute Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['ow_fluteshuffle'][player])
|
||||||
outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player])
|
outfile.write('\n')
|
||||||
if self.metadata['shuffle'][player] != 'vanilla':
|
outfile.write('Entrance Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['shuffle'][player])
|
||||||
outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player]))
|
if self.metadata['shuffle'][player] != 'vanilla':
|
||||||
outfile.write('Shuffle Link\'s House:'.ljust(line_width) + '%s\n' % yn(self.metadata['shufflelinks'][player]))
|
outfile.write('Shuffle GT/Ganon:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffleganon'][player]))
|
||||||
outfile.write('Shuffle Tavern:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffletavern'][player]))
|
outfile.write('Shuffle Link\'s House:'.ljust(line_width) + '%s\n' % yn(self.metadata['shufflelinks'][player]))
|
||||||
outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % self.metadata['open_pyramid'][player])
|
outfile.write('Shuffle Tavern:'.ljust(line_width) + '%s\n' % yn(self.metadata['shuffletavern'][player]))
|
||||||
if self.metadata['shuffle'][player] != 'vanilla' or self.metadata['ow_mixed'][player]:
|
outfile.write('Pyramid Hole Pre-opened:'.ljust(line_width) + '%s\n' % self.metadata['open_pyramid'][player])
|
||||||
outfile.write('Overworld Map:'.ljust(line_width) + '%s\n' % self.metadata['overworld_map'][player])
|
if self.metadata['shuffle'][player] != 'vanilla' or self.metadata['ow_mixed'][player]:
|
||||||
outfile.write('\n')
|
outfile.write('Overworld Map:'.ljust(line_width) + '%s\n' % self.metadata['overworld_map'][player])
|
||||||
outfile.write('Map Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['mapshuffle'][player]))
|
outfile.write('\n')
|
||||||
outfile.write('Compass Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['compassshuffle'][player]))
|
outfile.write('Map Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['mapshuffle'][player]))
|
||||||
outfile.write('Small Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['keyshuffle'][player])
|
outfile.write('Compass Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['compassshuffle'][player]))
|
||||||
outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['bigkeyshuffle'][player]))
|
outfile.write('Small Key Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['keyshuffle'][player])
|
||||||
outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player])
|
outfile.write('Big Key Shuffle:'.ljust(line_width) + '%s\n' % yn(self.metadata['bigkeyshuffle'][player]))
|
||||||
outfile.write('\n')
|
outfile.write('Key Logic Algorithm:'.ljust(line_width) + '%s\n' % self.metadata['key_logic'][player])
|
||||||
outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player])
|
outfile.write('\n')
|
||||||
if self.metadata['door_shuffle'][player] != 'vanilla':
|
outfile.write('Door Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['door_shuffle'][player])
|
||||||
outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player])
|
if self.metadata['door_shuffle'][player] != 'vanilla':
|
||||||
outfile.write('Door Type Mode:'.ljust(line_width) + '%s\n' % self.metadata['door_type_mode'][player])
|
outfile.write('Intensity:'.ljust(line_width) + '%s\n' % self.metadata['intensity'][player])
|
||||||
outfile.write('Trap Door Mode:'.ljust(line_width) + '%s\n' % self.metadata['trap_door_mode'][player])
|
outfile.write('Door Type Mode:'.ljust(line_width) + '%s\n' % self.metadata['door_type_mode'][player])
|
||||||
outfile.write('Decouple Doors:'.ljust(line_width) + '%s\n' % yn(self.metadata['decoupledoors'][player]))
|
outfile.write('Trap Door Mode:'.ljust(line_width) + '%s\n' % self.metadata['trap_door_mode'][player])
|
||||||
outfile.write('Spiral Stairs Self-Loop:'.ljust(line_width) + '%s\n' % yn(self.metadata['door_self_loops'][player]))
|
outfile.write('Decouple Doors:'.ljust(line_width) + '%s\n' % yn(self.metadata['decoupledoors'][player]))
|
||||||
outfile.write('Experimental:'.ljust(line_width) + '%s\n' % yn(self.metadata['experimental'][player]))
|
outfile.write('Spiral Stairs Self-Loop:'.ljust(line_width) + '%s\n' % yn(self.metadata['door_self_loops'][player]))
|
||||||
outfile.write('Dungeon Counters:'.ljust(line_width) + '%s\n' % self.metadata['dungeon_counters'][player])
|
outfile.write('Experimental:'.ljust(line_width) + '%s\n' % yn(self.metadata['experimental'][player]))
|
||||||
outfile.write('\n')
|
outfile.write('Dungeon Counters:'.ljust(line_width) + '%s\n' % self.metadata['dungeon_counters'][player])
|
||||||
outfile.write('Boss Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['boss_shuffle'][player])
|
outfile.write('\n')
|
||||||
outfile.write('Enemy Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['enemy_shuffle'][player])
|
outfile.write('Boss Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['boss_shuffle'][player])
|
||||||
if self.metadata['enemy_shuffle'][player] != 'none':
|
outfile.write('Enemy Shuffle:'.ljust(line_width) + '%s\n' % self.metadata['enemy_shuffle'][player])
|
||||||
outfile.write('Enemy Logic:'.ljust(line_width) + '%s\n' % self.metadata['any_enemy_logic'][player])
|
if self.metadata['enemy_shuffle'][player] != 'none':
|
||||||
outfile.write('Enemy Health:'.ljust(line_width) + '%s\n' % self.metadata['enemy_health'][player])
|
outfile.write('Enemy Logic:'.ljust(line_width) + '%s\n' % self.metadata['any_enemy_logic'][player])
|
||||||
outfile.write('Enemy Damage:'.ljust(line_width) + '%s\n' % self.metadata['enemy_damage'][player])
|
outfile.write('Enemy Health:'.ljust(line_width) + '%s\n' % self.metadata['enemy_health'][player])
|
||||||
outfile.write('\n')
|
outfile.write('Enemy Damage:'.ljust(line_width) + '%s\n' % self.metadata['enemy_damage'][player])
|
||||||
outfile.write('Pseudoboots:'.ljust(line_width) + '%s\n' % yn(self.metadata['pseudoboots'][player]))
|
outfile.write('\n')
|
||||||
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
|
outfile.write('Pseudoboots:'.ljust(line_width) + '%s\n' % yn(self.metadata['pseudoboots'][player]))
|
||||||
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))
|
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
|
||||||
|
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))
|
||||||
|
|
||||||
if self.startinventory:
|
if self.startinventory:
|
||||||
outfile.write('Starting Inventory:'.ljust(line_width))
|
outfile.write('Starting Inventory:'.ljust(line_width))
|
||||||
@@ -3247,70 +3265,74 @@ class Spoiler(object):
|
|||||||
self.parse_data()
|
self.parse_data()
|
||||||
with open(filename, 'a') as outfile:
|
with open(filename, 'a') as outfile:
|
||||||
line_width = 35
|
line_width = 35
|
||||||
outfile.write('\n\nRequirements:\n\n')
|
if 'all' in self.settings or 'requirements' in self.settings:
|
||||||
for dungeon, medallion in self.medallions.items():
|
outfile.write('\n\nRequirements:\n\n')
|
||||||
outfile.write(f'{dungeon}:'.ljust(line_width) + '%s Medallion\n' % medallion)
|
for dungeon, medallion in self.medallions.items():
|
||||||
for player in range(1, self.world.players + 1):
|
outfile.write(f'{dungeon}:'.ljust(line_width) + '%s Medallion\n' % medallion)
|
||||||
player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')')
|
for player in range(1, self.world.players + 1):
|
||||||
if self.world.crystals_gt_orig[player] == 'random':
|
player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')')
|
||||||
outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player])))
|
if self.world.crystals_gt_orig[player] == 'random':
|
||||||
if self.world.crystals_ganon_orig[player] == 'random':
|
outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player])))
|
||||||
outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player])))
|
if self.world.crystals_ganon_orig[player] == 'random':
|
||||||
|
outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player])))
|
||||||
|
|
||||||
outfile.write('\n\nBottle Refills:\n\n')
|
if 'all' in self.settings or 'misc' in self.settings:
|
||||||
for fairy, bottle in self.bottles.items():
|
outfile.write('\n\nBottle Refills:\n\n')
|
||||||
outfile.write(f'{fairy}: {bottle}\n')
|
for fairy, bottle in self.bottles.items():
|
||||||
|
outfile.write(f'{fairy}: {bottle}\n')
|
||||||
|
|
||||||
if self.maps:
|
if self.maps:
|
||||||
# flute shuffle
|
if 'all' in self.settings or 'flute' in self.settings:
|
||||||
for player in range(1, self.world.players + 1):
|
# flute shuffle
|
||||||
if ('flute', player) in self.maps:
|
for player in range(1, self.world.players + 1):
|
||||||
outfile.write('\n\nFlute Spots:\n\n')
|
if ('flute', player) in self.maps:
|
||||||
break
|
outfile.write('\n\nFlute Spots:\n\n')
|
||||||
for player in range(1, self.world.players + 1):
|
break
|
||||||
if ('flute', player) in self.maps:
|
for player in range(1, self.world.players + 1):
|
||||||
if self.world.players > 1:
|
if ('flute', player) in self.maps:
|
||||||
outfile.write(str('(Player ' + str(player) + ')\n')) # player name
|
if self.world.players > 1:
|
||||||
outfile.write(self.maps[('flute', player)]['text'])
|
outfile.write(str('(Player ' + str(player) + ')\n')) # player name
|
||||||
|
outfile.write(self.maps[('flute', player)]['text'])
|
||||||
|
|
||||||
# overworld tile flips
|
if 'all' in self.settings or 'overworld' in self.settings:
|
||||||
for player in range(1, self.world.players + 1):
|
# overworld tile flips
|
||||||
if ('swaps', player) in self.maps:
|
for player in range(1, self.world.players + 1):
|
||||||
outfile.write('\n\nOW Tile Flips:\n\n')
|
if ('swaps', player) in self.maps:
|
||||||
break
|
outfile.write('\n\nOW Tile Flips:\n\n')
|
||||||
for player in range(1, self.world.players + 1):
|
break
|
||||||
if ('swaps', player) in self.maps:
|
for player in range(1, self.world.players + 1):
|
||||||
if self.world.players > 1:
|
if ('swaps', player) in self.maps:
|
||||||
outfile.write(str('(Player ' + str(player) + ')\n')) # player name
|
if self.world.players > 1:
|
||||||
outfile.write(self.maps[('swaps', player)]['text'])
|
outfile.write(str('(Player ' + str(player) + ')\n')) # player name
|
||||||
|
outfile.write(self.maps[('swaps', player)]['text'])
|
||||||
# crossed groups
|
|
||||||
for player in range(1, self.world.players + 1):
|
# crossed groups
|
||||||
if ('groups', player) in self.maps:
|
for player in range(1, self.world.players + 1):
|
||||||
outfile.write('\n\nOW Crossed Groups:\n\n')
|
if ('groups', player) in self.maps:
|
||||||
break
|
outfile.write('\n\nOW Crossed Groups:\n\n')
|
||||||
for player in range(1, self.world.players + 1):
|
break
|
||||||
if ('groups', player) in self.maps:
|
for player in range(1, self.world.players + 1):
|
||||||
if self.world.players > 1:
|
if ('groups', player) in self.maps:
|
||||||
outfile.write(str('(Player ' + str(player) + ')\n')) # player name
|
if self.world.players > 1:
|
||||||
outfile.write(self.maps[('groups', player)]['text'])
|
outfile.write(str('(Player ' + str(player) + ')\n')) # player name
|
||||||
|
outfile.write(self.maps[('groups', player)]['text'])
|
||||||
|
|
||||||
if self.overworlds:
|
if self.overworlds and ('all' in self.settings or 'overworld' in self.settings):
|
||||||
outfile.write('\n\nOverworld Edges:\n\n')
|
outfile.write('\n\nOverworld Edges:\n\n')
|
||||||
# overworld transitions
|
# overworld transitions
|
||||||
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","overworlds",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","overworlds",entry['exit'])) for entry in self.overworlds.values()]))
|
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","overworlds",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","overworlds",entry['exit'])) for entry in self.overworlds.values()]))
|
||||||
|
|
||||||
if self.whirlpools:
|
if self.whirlpools and ('all' in self.settings or 'overworld' in self.settings):
|
||||||
outfile.write('\n\nWhirlpools:\n\n')
|
outfile.write('\n\nWhirlpools:\n\n')
|
||||||
# whirlpools
|
# whirlpools
|
||||||
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","whirlpools",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","whirlpools",entry['exit'])) for entry in self.whirlpools.values()]))
|
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta","whirlpools",entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta","whirlpools",entry['exit'])) for entry in self.whirlpools.values()]))
|
||||||
|
|
||||||
if self.entrances:
|
if self.entrances and ('all' in self.settings or 'entrances' in self.settings):
|
||||||
# entrances: To/From overworld; Checking w/ & w/out "Exit" and translating accordingly
|
# entrances: To/From overworld; Checking w/ & w/out "Exit" and translating accordingly
|
||||||
outfile.write('\n\nEntrances:\n\n')
|
outfile.write('\n\nEntrances:\n\n')
|
||||||
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta", "entrances", entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta", "entrances", entry['exit'])) for entry in self.entrances.values()]))
|
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', self.world.fish.translate("meta", "entrances", entry['entrance']), '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', self.world.fish.translate("meta", "entrances", entry['exit'])) for entry in self.entrances.values()]))
|
||||||
|
|
||||||
if self.doors:
|
if self.doors and ('all' in self.settings or 'doors' in self.settings):
|
||||||
outfile.write('\n\nDoors:\n\n')
|
outfile.write('\n\nDoors:\n\n')
|
||||||
outfile.write('\n'.join(
|
outfile.write('\n'.join(
|
||||||
['%s%s %s %s %s' % ('Player {0}: '.format(entry['player']) if self.world.players > 1 else '',
|
['%s%s %s %s %s' % ('Player {0}: '.format(entry['player']) if self.world.players > 1 else '',
|
||||||
@@ -3319,33 +3341,37 @@ class Spoiler(object):
|
|||||||
self.world.fish.translate("meta", "doors", entry['exit']),
|
self.world.fish.translate("meta", "doors", entry['exit']),
|
||||||
'({0})'.format(entry['dname']) if self.world.doorShuffle[entry['player']] != 'basic' else '') for
|
'({0})'.format(entry['dname']) if self.world.doorShuffle[entry['player']] != 'basic' else '') for
|
||||||
entry in self.doors.values()]))
|
entry in self.doors.values()]))
|
||||||
if self.lobbies:
|
if self.lobbies and ('all' in self.settings or 'doors' in self.settings):
|
||||||
outfile.write('\n\nDungeon Lobbies:\n\n')
|
outfile.write('\n\nDungeon Lobbies:\n\n')
|
||||||
outfile.write('\n'.join(
|
outfile.write('\n'.join(
|
||||||
[f"{'Player {0}: '.format(entry['player']) if self.world.players > 1 else ''}{entry['lobby_name']}: {entry['door_name']}"
|
[f"{'Player {0}: '.format(entry['player']) if self.world.players > 1 else ''}{entry['lobby_name']}: {entry['door_name']}"
|
||||||
for
|
for
|
||||||
entry in self.lobbies.values()]))
|
entry in self.lobbies.values()]))
|
||||||
if self.doorTypes:
|
if self.doorTypes and ('all' in self.settings or 'doors' in self.settings):
|
||||||
# doorNames: For some reason these come in combined, somehow need to split on the thing to translate
|
# doorNames: For some reason these come in combined, somehow need to split on the thing to translate
|
||||||
# doorTypes: Small Key, Bombable, Bonkable
|
# doorTypes: Small Key, Bombable, Bonkable
|
||||||
outfile.write('\n\nDoor Types:\n\n')
|
outfile.write('\n\nDoor Types:\n\n')
|
||||||
outfile.write('\n'.join(['%s%s %s' % ('Player {0}: '.format(entry['player']) if self.world.players > 1 else '', self.world.fish.translate("meta", "doors", entry['doorNames']), self.world.fish.translate("meta", "doorTypes", entry['type'])) for entry in self.doorTypes.values()]))
|
outfile.write('\n'.join(['%s%s %s' % ('Player {0}: '.format(entry['player']) if self.world.players > 1 else '', self.world.fish.translate("meta", "doors", entry['doorNames']), self.world.fish.translate("meta", "doorTypes", entry['type'])) for entry in self.doorTypes.values()]))
|
||||||
|
|
||||||
|
|
||||||
# locations: Change up location names; in the instance of a location with multiple sections, it'll try to translate the room name
|
# locations: Change up location names; in the instance of a location with multiple sections, it'll try to translate the room name
|
||||||
# items: Item names
|
# items: Item names
|
||||||
outfile.write('\n\nLocations:\n\n')
|
outfile.write('\n\nLocations:\n\n')
|
||||||
outfile.write('\n'.join(['%s: %s' % (self.world.fish.translate("meta", "locations", location), self.world.fish.translate("meta", "items", item)) for grouping in self.locations.values() for (location, item) in grouping.items()]))
|
outfile.write('\n'.join(['%s: %s' % (self.world.fish.translate("meta", "locations", location), self.world.fish.translate("meta", "items", item))
|
||||||
|
for grouping in self.locations.values() for (location, item) in grouping.items()]))
|
||||||
|
|
||||||
# locations: Change up location names; in the instance of a location with multiple sections, it'll try to translate the room name
|
# locations: Change up location names; in the instance of a location with multiple sections, it'll try to translate the room name
|
||||||
# items: Item names
|
# items: Item names
|
||||||
outfile.write('\n\nShops:\n\n')
|
if 'all' in self.settings or 'shops' in self.settings:
|
||||||
outfile.write('\n'.join("{} [{}]\n {}".format(self.world.fish.translate("meta", "locations", shop['location']), shop['type'], "\n ".join(self.world.fish.translate("meta", "items", item) for item in [shop.get('item_0', None), shop.get('item_1', None), shop.get('item_2', None)] if item)) for shop in self.shops))
|
outfile.write('\n\nShops:\n\n')
|
||||||
|
outfile.write('\n'.join("{} [{}]\n {}".format(self.world.fish.translate("meta", "locations", shop['location']), shop['type'], "\n ".join(self.world.fish.translate("meta", "items", item) for item in [shop.get('item_0', None), shop.get('item_1', None), shop.get('item_2', None)] if item)) for shop in self.shops))
|
||||||
|
|
||||||
for player in range(1, self.world.players + 1):
|
if 'all' in self.settings or 'bosses' in self.settings:
|
||||||
if self.world.boss_shuffle[player] != 'none':
|
for player in range(1, self.world.players + 1):
|
||||||
bossmap = self.bosses[str(player)] if self.world.players > 1 else self.bosses
|
if self.world.boss_shuffle[player] != 'none':
|
||||||
outfile.write(f'\n\nBosses ({self.world.get_player_names(player)}):\n\n')
|
bossmap = self.bosses[str(player)] if self.world.players > 1 else self.bosses
|
||||||
outfile.write('\n'.join([f'{x}: {y}' for x, y in bossmap.items() if y not in ['Agahnim', 'Agahnim 2', 'Ganon']]))
|
outfile.write(f'\n\nBosses ({self.world.get_player_names(player)}):\n\n')
|
||||||
|
outfile.write('\n'.join([f'{x}: {y}' for x, y in bossmap.items() if y not in ['Agahnim', 'Agahnim 2', 'Ganon']]))
|
||||||
|
|
||||||
def extras(self, filename):
|
def extras(self, filename):
|
||||||
# todo: conditional on enemy shuffle mode
|
# todo: conditional on enemy shuffle mode
|
||||||
|
|||||||
5
CLI.py
5
CLI.py
@@ -236,7 +236,7 @@ def parse_settings():
|
|||||||
"mixed_travel": "prevent",
|
"mixed_travel": "prevent",
|
||||||
"standardize_palettes": "standardize",
|
"standardize_palettes": "standardize",
|
||||||
'aga_randomness': True,
|
'aga_randomness': True,
|
||||||
|
|
||||||
"triforce_pool": 0,
|
"triforce_pool": 0,
|
||||||
"triforce_goal": 0,
|
"triforce_goal": 0,
|
||||||
"triforce_pool_min": 0,
|
"triforce_pool_min": 0,
|
||||||
@@ -267,10 +267,9 @@ def parse_settings():
|
|||||||
"msu_resume": False,
|
"msu_resume": False,
|
||||||
"collection_rate": False,
|
"collection_rate": False,
|
||||||
|
|
||||||
# Spoiler defaults to TRUE
|
'spoiler': 'full',
|
||||||
# Playthrough defaults to TRUE
|
# Playthrough defaults to TRUE
|
||||||
# ROM defaults to TRUE
|
# ROM defaults to TRUE
|
||||||
"create_spoiler": True,
|
|
||||||
"calc_playthrough": True,
|
"calc_playthrough": True,
|
||||||
"create_rom": True,
|
"create_rom": True,
|
||||||
"bps": False,
|
"bps": False,
|
||||||
|
|||||||
2
Fill.py
2
Fill.py
@@ -1115,7 +1115,7 @@ def set_prize_drops(world, player):
|
|||||||
for player, drop_config in drops.items():
|
for player, drop_config in drops.items():
|
||||||
for pack_num in range(1, 8):
|
for pack_num in range(1, 8):
|
||||||
if f'Pack {pack_num}' in drop_config:
|
if f'Pack {pack_num}' in drop_config:
|
||||||
for prize, idx in enumerate(drop_config[f'Pack {pack_num}']):
|
for idx, prize in enumerate(drop_config[f'Pack {pack_num}']):
|
||||||
chosen = random.choice(uniform_prizes) if prize == 'Random' else possible_prizes[prize]
|
chosen = random.choice(uniform_prizes) if prize == 'Random' else possible_prizes[prize]
|
||||||
prizes[(pack_num-1)*8 + idx] = chosen
|
prizes[(pack_num-1)*8 + idx] = chosen
|
||||||
for tree_pull_tier in range(1, 4):
|
for tree_pull_tier in range(1, 4):
|
||||||
|
|||||||
2
Gui.py
2
Gui.py
@@ -44,7 +44,7 @@ def save_settings(gui, args, filename):
|
|||||||
if not os.path.exists(settings_path):
|
if not os.path.exists(settings_path):
|
||||||
os.makedirs(settings_path)
|
os.makedirs(settings_path)
|
||||||
output_args = {}
|
output_args = {}
|
||||||
settings = ["create_rom", "suppress_rom", "bps", "create_spoiler", "suppress_spoiler",
|
settings = ["create_rom", "suppress_rom", "bps", "spoiler",
|
||||||
"calc_playthrough", "skip_playthrough", "print_custom_yaml",
|
"calc_playthrough", "skip_playthrough", "print_custom_yaml",
|
||||||
"settingsonload", "rom", "outputpath"]
|
"settingsonload", "rom", "outputpath"]
|
||||||
if filename == "settings.json":
|
if filename == "settings.json":
|
||||||
|
|||||||
21
Main.py
21
Main.py
@@ -41,7 +41,7 @@ from source.enemizer.DamageTables import DamageTable
|
|||||||
from source.enemizer.Enemizer import randomize_enemies
|
from source.enemizer.Enemizer import randomize_enemies
|
||||||
from source.rom.DataTables import init_data_tables
|
from source.rom.DataTables import init_data_tables
|
||||||
|
|
||||||
version_number = '1.4.1.10'
|
version_number = '1.4.1.11'
|
||||||
version_branch = '-u'
|
version_branch = '-u'
|
||||||
__version__ = f'{version_number}{version_branch}'
|
__version__ = f'{version_number}{version_branch}'
|
||||||
|
|
||||||
@@ -87,7 +87,6 @@ def main(args, seed=None, fish=None):
|
|||||||
for i in zip(args.logic.values(), args.door_shuffle.values()):
|
for i in zip(args.logic.values(), args.door_shuffle.values()):
|
||||||
if i[0] == 'hybridglitches' and i[1] != 'vanilla':
|
if i[0] == 'hybridglitches' and i[1] != 'vanilla':
|
||||||
raise RuntimeError(BabelFish().translate("cli","cli","hybridglitches.door.shuffle"))
|
raise RuntimeError(BabelFish().translate("cli","cli","hybridglitches.door.shuffle"))
|
||||||
|
|
||||||
if seed is None:
|
if seed is None:
|
||||||
random.seed(None)
|
random.seed(None)
|
||||||
world.seed = random.randint(0, 999999999)
|
world.seed = random.randint(0, 999999999)
|
||||||
@@ -160,7 +159,7 @@ def main(args, seed=None, fish=None):
|
|||||||
world.settings = CustomSettings()
|
world.settings = CustomSettings()
|
||||||
world.settings.create_from_world(world, args)
|
world.settings.create_from_world(world, args)
|
||||||
|
|
||||||
if args.create_spoiler and not args.jsonout:
|
if world.spoiler_mode != 'none' and not args.jsonout:
|
||||||
logger.info(world.fish.translate("cli", "cli", "create.meta"))
|
logger.info(world.fish.translate("cli", "cli", "create.meta"))
|
||||||
world.spoiler.meta_to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
world.spoiler.meta_to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||||
if args.mystery and not (args.suppress_meta or args.create_spoiler):
|
if args.mystery and not (args.suppress_meta or args.create_spoiler):
|
||||||
@@ -365,12 +364,12 @@ def main(args, seed=None, fish=None):
|
|||||||
|
|
||||||
if args.mystery and not (args.suppress_meta or args.create_spoiler):
|
if args.mystery and not (args.suppress_meta or args.create_spoiler):
|
||||||
world.spoiler.hashes_to_file(output_path(f'{outfilebase}_meta.txt'))
|
world.spoiler.hashes_to_file(output_path(f'{outfilebase}_meta.txt'))
|
||||||
elif args.create_spoiler and not args.jsonout:
|
elif world.spoiler_mode != 'none' and not args.jsonout:
|
||||||
world.spoiler.hashes_to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
world.spoiler.hashes_to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||||
if args.create_spoiler and not args.jsonout:
|
if world.spoiler_mode != 'none' and not args.jsonout:
|
||||||
logger.info(world.fish.translate("cli", "cli", "patching.spoiler"))
|
logger.info(world.fish.translate("cli", "cli", "patching.spoiler"))
|
||||||
world.spoiler.to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
world.spoiler.to_file(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||||
if args.loglevel == 'debug':
|
if 'debug' in world.spoiler.settings:
|
||||||
world.spoiler.extras(output_path(f'{outfilebase}_Spoiler.txt'))
|
world.spoiler.extras(output_path(f'{outfilebase}_Spoiler.txt'))
|
||||||
|
|
||||||
if not args.skip_playthrough:
|
if not args.skip_playthrough:
|
||||||
@@ -379,7 +378,7 @@ def main(args, seed=None, fish=None):
|
|||||||
|
|
||||||
if args.jsonout:
|
if args.jsonout:
|
||||||
print(json.dumps({**jsonout, 'spoiler': world.spoiler.to_json()}))
|
print(json.dumps({**jsonout, 'spoiler': world.spoiler.to_json()}))
|
||||||
elif args.create_spoiler:
|
elif world.spoiler_mode != 'none':
|
||||||
logger.info(world.fish.translate("cli","cli","patching.spoiler"))
|
logger.info(world.fish.translate("cli","cli","patching.spoiler"))
|
||||||
if args.jsonout:
|
if args.jsonout:
|
||||||
with open(output_path('%s_Spoiler.json' % outfilebase), 'w') as outfile:
|
with open(output_path('%s_Spoiler.json' % outfilebase), 'w') as outfile:
|
||||||
@@ -394,7 +393,7 @@ def main(args, seed=None, fish=None):
|
|||||||
logger.info("")
|
logger.info("")
|
||||||
logger.info(world.fish.translate("cli","cli","made.rom") % (YES if (args.create_rom) else NO))
|
logger.info(world.fish.translate("cli","cli","made.rom") % (YES if (args.create_rom) else NO))
|
||||||
logger.info(world.fish.translate("cli","cli","made.playthrough") % (YES if (args.calc_playthrough) else NO))
|
logger.info(world.fish.translate("cli","cli","made.playthrough") % (YES if (args.calc_playthrough) else NO))
|
||||||
logger.info(world.fish.translate("cli","cli","made.spoiler") % (YES if (not args.jsonout and args.create_spoiler) else NO))
|
logger.info(world.fish.translate("cli","cli","made.spoiler") % (YES if (not args.jsonout and world.spoiler_mode != 'none') else NO))
|
||||||
logger.info(world.fish.translate("cli","cli","seed") + ": %s", world.seed)
|
logger.info(world.fish.translate("cli","cli","seed") + ": %s", world.seed)
|
||||||
logger.info(world.fish.translate("cli","cli","total.time"), time.perf_counter() - start)
|
logger.info(world.fish.translate("cli","cli","total.time"), time.perf_counter() - start)
|
||||||
|
|
||||||
@@ -452,7 +451,7 @@ def init_world(args, fish):
|
|||||||
|
|
||||||
world = World(args.multi, args.ow_shuffle, args.ow_crossed, args.ow_mixed, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
|
world = World(args.multi, args.ow_shuffle, args.ow_crossed, args.ow_mixed, args.shuffle, args.door_shuffle, args.logic, args.mode, args.swords,
|
||||||
args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
|
args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm,
|
||||||
args.accessibility, args.shuffleganon, args.custom, args.customitemarray, args.hints)
|
args.accessibility, args.shuffleganon, args.custom, args.customitemarray, args.hints, args.spoiler)
|
||||||
|
|
||||||
world.customizer = customized
|
world.customizer = customized
|
||||||
world.boots_hint = args.boots_hint.copy()
|
world.boots_hint = args.boots_hint.copy()
|
||||||
@@ -530,7 +529,7 @@ def copy_world(world):
|
|||||||
# ToDo: Not good yet
|
# ToDo: Not good yet
|
||||||
ret = World(world.players, world.owShuffle, world.owCrossed, world.owMixed, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords,
|
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,
|
world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm,
|
||||||
world.accessibility, world.shuffle_ganon, world.custom, world.customitemarray, world.hints)
|
world.accessibility, world.shuffle_ganon, world.custom, world.customitemarray, world.hints, world.spoiler_mode)
|
||||||
ret.teams = world.teams
|
ret.teams = world.teams
|
||||||
ret.player_names = copy.deepcopy(world.player_names)
|
ret.player_names = copy.deepcopy(world.player_names)
|
||||||
ret.remote_items = world.remote_items.copy()
|
ret.remote_items = world.remote_items.copy()
|
||||||
@@ -725,7 +724,7 @@ def copy_world_premature(world, player):
|
|||||||
# ToDo: Not good yet
|
# ToDo: Not good yet
|
||||||
ret = World(world.players, world.owShuffle, world.owCrossed, world.owMixed, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords,
|
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,
|
world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm,
|
||||||
world.accessibility, world.shuffle_ganon, world.custom, world.customitemarray, world.hints)
|
world.accessibility, world.shuffle_ganon, world.custom, world.customitemarray, world.hints, world.spoiler_mode)
|
||||||
ret.teams = world.teams
|
ret.teams = world.teams
|
||||||
ret.player_names = copy.deepcopy(world.player_names)
|
ret.player_names = copy.deepcopy(world.player_names)
|
||||||
ret.remote_items = world.remote_items.copy()
|
ret.remote_items = world.remote_items.copy()
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ def main():
|
|||||||
parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255))
|
parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255))
|
||||||
parser.add_argument('--names', default='')
|
parser.add_argument('--names', default='')
|
||||||
parser.add_argument('--teams', default=1, type=lambda value: max(int(value), 1))
|
parser.add_argument('--teams', default=1, type=lambda value: max(int(value), 1))
|
||||||
parser.add_argument('--create_spoiler', action='store_true')
|
parser.add_argument('--spoiler', default='none', choices=['none', 'settings', 'semi', 'full', 'debug'])
|
||||||
parser.add_argument('--no_race', action='store_true')
|
parser.add_argument('--no_race', action='store_true')
|
||||||
parser.add_argument('--suppress_rom', action='store_true')
|
parser.add_argument('--suppress_rom', action='store_true')
|
||||||
parser.add_argument('--suppress_meta', action='store_true')
|
parser.add_argument('--suppress_meta', action='store_true')
|
||||||
@@ -64,7 +64,7 @@ def main():
|
|||||||
erargs = parse_cli(['--multi', str(args.multi)])
|
erargs = parse_cli(['--multi', str(args.multi)])
|
||||||
erargs.seed = seed
|
erargs.seed = seed
|
||||||
erargs.names = args.names
|
erargs.names = args.names
|
||||||
erargs.create_spoiler = args.create_spoiler
|
erargs.spoiler = args.spoiler
|
||||||
erargs.suppress_rom = args.suppress_rom
|
erargs.suppress_rom = args.suppress_rom
|
||||||
erargs.suppress_meta = args.suppress_meta
|
erargs.suppress_meta = args.suppress_meta
|
||||||
erargs.bps = args.bps
|
erargs.bps = args.bps
|
||||||
|
|||||||
@@ -141,6 +141,16 @@ These are now independent of retro mode and have three options: None, Random, an
|
|||||||
|
|
||||||
# Patch Notes
|
# Patch Notes
|
||||||
|
|
||||||
|
* 1.4.1.11u
|
||||||
|
* New Feature: Several spoiler levels added: None, Settings-only, Semi, Full, Debug
|
||||||
|
* Semi includes only entrances, prizes, and medallions (potential new spoiler mode being worked on, definition may change)
|
||||||
|
* Entrance: Lite/Lean support enemy drop shuffle
|
||||||
|
* Standard: Re-added tutorial guard near large rock
|
||||||
|
* Enemizer
|
||||||
|
* Fixed the overwriting of bonk fairies
|
||||||
|
* Fixed broken graphics on hyrule castle
|
||||||
|
* Enemy bans
|
||||||
|
* Customizer: Fixed bug with customizing prize packs
|
||||||
* 1.4.1.10u
|
* 1.4.1.10u
|
||||||
* Vanilla key logic: Fix for vanilla layout Misery Mire which allows more complex key logic. Locations blocked by crystal switch access are only locked by 2 keys thanks to that being the minimum in Mire to reach one of two crystal switches.
|
* Vanilla key logic: Fix for vanilla layout Misery Mire which allows more complex key logic. Locations blocked by crystal switch access are only locked by 2 keys thanks to that being the minimum in Mire to reach one of two crystal switches.
|
||||||
* Autotracking: Fix for chest turn counter with chest containing multiworld items (Thanks Hiimcody)
|
* Autotracking: Fix for chest turn counter with chest containing multiworld items (Thanks Hiimcody)
|
||||||
|
|||||||
4
Utils.py
4
Utils.py
@@ -347,11 +347,11 @@ def update_deprecated_args(args):
|
|||||||
# Don't do: Yes
|
# Don't do: Yes
|
||||||
# Do: No
|
# Do: No
|
||||||
if "suppress_spoiler" in argVars:
|
if "suppress_spoiler" in argVars:
|
||||||
args.create_spoiler = not args.suppress_spoiler in truthy
|
args.spoiler = 'none'
|
||||||
# Don't do: No
|
# Don't do: No
|
||||||
# Do: Yes
|
# Do: Yes
|
||||||
if "create_spoiler" in argVars:
|
if "create_spoiler" in argVars:
|
||||||
args.suppress_spoiler = not args.create_spoiler in truthy
|
args.spoiler = 'full'
|
||||||
|
|
||||||
# ROM defaults to TRUE
|
# ROM defaults to TRUE
|
||||||
# Don't do: Yes
|
# Don't do: Yes
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
"create_spoiler": {
|
"spoiler": {
|
||||||
"action": "store_false",
|
"choices": [
|
||||||
"dest": "suppress_spoiler",
|
"none",
|
||||||
"type": "bool",
|
"settings",
|
||||||
"help": "suppress"
|
"semi",
|
||||||
},
|
"full",
|
||||||
"suppress_spoiler": {
|
"debug"
|
||||||
"action": "store_true"
|
]
|
||||||
},
|
},
|
||||||
"mystery": {
|
"mystery": {
|
||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
|
|||||||
@@ -61,7 +61,15 @@
|
|||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"lang": [ "App Language, if available, defaults to English" ],
|
"lang": [ "App Language, if available, defaults to English" ],
|
||||||
"create_spoiler": [ "Output a Spoiler File" ],
|
"spoiler": [
|
||||||
|
"Spoiler File Options. (default: %(default)s)",
|
||||||
|
"None: No Spoiler",
|
||||||
|
"Meta: Meta information only about game. Intended for mystery settings",
|
||||||
|
"Settings: Only settings information",
|
||||||
|
"Semi: ",
|
||||||
|
"Full: Full spoiler generated",
|
||||||
|
"Debug: Includes debug information"
|
||||||
|
],
|
||||||
"bps": [ "Output BPS patches instead of ROMs"],
|
"bps": [ "Output BPS patches instead of ROMs"],
|
||||||
"logic": [
|
"logic": [
|
||||||
"Select Enforcement of Item Requirements. (default: %(default)s)",
|
"Select Enforcement of Item Requirements. (default: %(default)s)",
|
||||||
|
|||||||
@@ -236,7 +236,12 @@
|
|||||||
|
|
||||||
|
|
||||||
"randomizer.generation.bps": "Create BPS Patches",
|
"randomizer.generation.bps": "Create BPS Patches",
|
||||||
"randomizer.generation.createspoiler": "Create Spoiler Log",
|
"randomizer.generation.spoiler": "Create Spoiler Log",
|
||||||
|
"randomizer.generation.spoiler.none": "None",
|
||||||
|
"randomizer.generation.spoiler.settings": "Settings Only",
|
||||||
|
"randomizer.generation.spoiler.semi": "Semi (Entrances and Prizes)",
|
||||||
|
"randomizer.generation.spoiler.full": "Full",
|
||||||
|
"randomizer.generation.spoiler.debug": "Debug",
|
||||||
"randomizer.generation.createrom": "Create Patched ROM",
|
"randomizer.generation.createrom": "Create Patched ROM",
|
||||||
"randomizer.generation.calcplaythrough": "Calculate Playthrough",
|
"randomizer.generation.calcplaythrough": "Calculate Playthrough",
|
||||||
"randomizer.generation.print_custom_yaml": "Print Customizer File",
|
"randomizer.generation.print_custom_yaml": "Print Customizer File",
|
||||||
|
|||||||
@@ -2,7 +2,16 @@
|
|||||||
"checkboxes": {
|
"checkboxes": {
|
||||||
"createrom": { "type": "checkbox" },
|
"createrom": { "type": "checkbox" },
|
||||||
"bps": { "type": "checkbox" },
|
"bps": { "type": "checkbox" },
|
||||||
"createspoiler": { "type": "checkbox" },
|
"spoiler": {
|
||||||
|
"type": "selectbox",
|
||||||
|
"options": [
|
||||||
|
"none",
|
||||||
|
"settings",
|
||||||
|
"semi",
|
||||||
|
"full",
|
||||||
|
"debug"
|
||||||
|
]
|
||||||
|
},
|
||||||
"calcplaythrough": { "type": "checkbox" },
|
"calcplaythrough": { "type": "checkbox" },
|
||||||
"print_custom_yaml": { "type": "checkbox" }
|
"print_custom_yaml": { "type": "checkbox" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ SETTINGSTOPROCESS = {
|
|||||||
},
|
},
|
||||||
"generation": {
|
"generation": {
|
||||||
"bps": "bps",
|
"bps": "bps",
|
||||||
"createspoiler": "create_spoiler",
|
"spoiler": "spoiler",
|
||||||
"createrom": "create_rom",
|
"createrom": "create_rom",
|
||||||
"calcplaythrough": "calc_playthrough",
|
"calcplaythrough": "calc_playthrough",
|
||||||
"print_custom_yaml": "print_custom_yaml",
|
"print_custom_yaml": "print_custom_yaml",
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ def get_randomize_able_sprites_ow(area_id, data_tables):
|
|||||||
req = data_tables.sprite_requirements[key]
|
req = data_tables.sprite_requirements[key]
|
||||||
if isinstance(req, dict):
|
if isinstance(req, dict):
|
||||||
continue
|
continue
|
||||||
if not req.static and req.can_randomize:
|
if not req.static and req.can_randomize and not sprite.static:
|
||||||
sprite_table[idx] = sprite
|
sprite_table[idx] = sprite
|
||||||
return sprite_table
|
return sprite_table
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ def init_vanilla_sprites_ow():
|
|||||||
create_sprite(0x21b, EnemySprite.GreenKnifeGuard, 0x20, 0x1A, '', 0x09CB51)
|
create_sprite(0x21b, EnemySprite.GreenKnifeGuard, 0x20, 0x1A, '', 0x09CB51)
|
||||||
create_sprite(0x21b, EnemySprite.TutorialGuard, 0x2D, 0x25, '', 0x09CB54)
|
create_sprite(0x21b, EnemySprite.TutorialGuard, 0x2D, 0x25, '', 0x09CB54)
|
||||||
create_sprite(0x21b, EnemySprite.TutorialGuard, 0x20, 0x29, '', 0x09CB57)
|
create_sprite(0x21b, EnemySprite.TutorialGuard, 0x20, 0x29, '', 0x09CB57)
|
||||||
|
create_sprite(0x21b, EnemySprite.TutorialGuard, 0x3C, 0x2A, '', 0x09CB5B)
|
||||||
create_sprite(0x21d, EnemySprite.Apple, 0x0B, 0x06, '', 0x09CB5B, bonk=True)
|
create_sprite(0x21d, EnemySprite.Apple, 0x0B, 0x06, '', 0x09CB5B, bonk=True)
|
||||||
create_sprite(0x22b, EnemySprite.TutorialGuard, 0x09, 0x1E, '', 0x09CB5F)
|
create_sprite(0x22b, EnemySprite.TutorialGuard, 0x09, 0x1E, '', 0x09CB5F)
|
||||||
create_sprite(0x22b, EnemySprite.TutorialGuard, 0x0B, 0x1E, '', 0x09CB62)
|
create_sprite(0x22b, EnemySprite.TutorialGuard, 0x0B, 0x1E, '', 0x09CB62)
|
||||||
|
|||||||
@@ -687,7 +687,11 @@ def setup_required_overworld_groups(sheets):
|
|||||||
sheets[4].add_sprite_to_sheet([None, None, None, None], {0xF, 0x9F}) # Waterfall of wishing (pre/post-Aga)
|
sheets[4].add_sprite_to_sheet([None, None, None, None], {0xF, 0x9F}) # Waterfall of wishing (pre/post-Aga)
|
||||||
sheets[3].add_sprite_to_sheet([None, None, None, 14], {0x14, 0xA4}) # Graveyard (pre/post-Aga)
|
sheets[3].add_sprite_to_sheet([None, None, None, 14], {0x14, 0xA4}) # Graveyard (pre/post-Aga)
|
||||||
sheets[1].add_sprite_to_sheet([None, None, 76, 0x3F], {0x1B, 0xAB}) # Hyrule Castle (pre/post-Aga)
|
sheets[1].add_sprite_to_sheet([None, None, 76, 0x3F], {0x1B, 0xAB}) # Hyrule Castle (pre/post-Aga)
|
||||||
sheets[2].add_sprite_to_sheet([None, None, None, 0x3F], {}) # Hyrule Castle - rain state
|
## group 0 set to 0x48 for tutortial guards
|
||||||
|
## group 1 & 2 set for green knife guards (and probably normal green guard)
|
||||||
|
## group 3 set for lightning gate
|
||||||
|
sheets[2].add_sprite_to_sheet([0x48, 0x49, 0x13, 0x3F], {}) # Hyrule Castle - rain state
|
||||||
|
|
||||||
# Smithy/Race/Kak (pre/post-Aga)
|
# Smithy/Race/Kak (pre/post-Aga)
|
||||||
sheets[6].add_sprite_to_sheet([0x4F, 0x49, 0x4A, 0x50], {0x18, 0x22, 0x28, 0xA8, 0xB2, 0xB8})
|
sheets[6].add_sprite_to_sheet([0x4F, 0x49, 0x4A, 0x50], {0x18, 0x22, 0x28, 0xA8, 0xB2, 0xB8})
|
||||||
sheets[8].add_sprite_to_sheet([None, None, 18, None], {0x30, 0xC0}) # Desert (pre/post-Aga)
|
sheets[8].add_sprite_to_sheet([None, None, 18, None], {0x30, 0xC0}) # Desert (pre/post-Aga)
|
||||||
|
|||||||
@@ -325,6 +325,7 @@ UwGeneralDeny:
|
|||||||
- [ 0x00c2, 5, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
- [ 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, 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"
|
- [ 0x00c5, 7, [ "Statue" ] ] #"Turtle Rock - Catwalk - Laser Eye (Left) 4"
|
||||||
|
- [0x00c6, 5, ["Bumper"]]
|
||||||
- [ 0x00cb, 0, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots
|
- [ 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, 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"
|
- [ 0x00cb, 5, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 2"
|
||||||
@@ -419,10 +420,12 @@ OwGeneralDeny:
|
|||||||
- [0x03, 10, ["Gibo"]] # OldMan eating Gibo
|
- [0x03, 10, ["Gibo"]] # OldMan eating Gibo
|
||||||
- [0x05, 11, ["Bumper", "AntiFairyCircle"]] # Blocks path to portal
|
- [0x05, 11, ["Bumper", "AntiFairyCircle"]] # Blocks path to portal
|
||||||
- [0x1e, 3, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle"]] # forbid a beamos here
|
- [0x1e, 3, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle"]] # forbid a beamos here
|
||||||
|
- [0x35, 8, ["RollerVerticalUp", "RollerVerticalDown"]] # blocks the dock
|
||||||
- [0x40, 0, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
- [0x40, 0, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
||||||
- [0x40, 7, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
- [0x40, 7, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
||||||
- [0x40, 13, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
- [0x40, 13, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]]
|
||||||
- [0x40, 14, ["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"]]
|
||||||
- [0x57, 5, ["RollerVerticalUp", "RollerVerticalDown"]]
|
- [0x57, 5, ["RollerVerticalUp", "RollerVerticalDown"]]
|
||||||
- [0x5e, 0, ["Gibo"]] # kiki eating Gibo
|
- [0x5e, 0, ["Gibo"]] # kiki eating Gibo
|
||||||
|
|||||||
@@ -133,7 +133,6 @@ def bottom_frame(self, parent, args=None):
|
|||||||
made[k] = m.group(1) + m.group(2) + ' ' + m.group(4)
|
made[k] = m.group(1) + m.group(2) + ' ' + m.group(4)
|
||||||
successMsg += (made["rom"] % (YES if (guiargs.create_rom) else NO)) + "\n"
|
successMsg += (made["rom"] % (YES if (guiargs.create_rom) else NO)) + "\n"
|
||||||
successMsg += (made["playthrough"] % (YES if (guiargs.calc_playthrough) else NO)) + "\n"
|
successMsg += (made["playthrough"] % (YES if (guiargs.calc_playthrough) else NO)) + "\n"
|
||||||
successMsg += (made["spoiler"] % (YES if (not guiargs.jsonout and guiargs.create_spoiler) else NO)) + "\n"
|
|
||||||
successMsg += (made["enemizer"] % (YES if needEnemizer else NO)) + "\n"
|
successMsg += (made["enemizer"] % (YES if needEnemizer else NO)) + "\n"
|
||||||
# FIXME: English
|
# FIXME: English
|
||||||
successMsg += ("Seed%s: %s" % ('s' if len(seeds) > 1 else "", ','.join(str(x) for x in seeds)))
|
successMsg += ("Seed%s: %s" % ('s' if len(seeds) > 1 else "", ','.join(str(x) for x in seeds)))
|
||||||
|
|||||||
@@ -1340,18 +1340,24 @@ def do_limited_shuffle_exclude_drops(pool_def, avail, lw=True):
|
|||||||
|
|
||||||
|
|
||||||
def do_vanilla_connect(pool_def, avail):
|
def do_vanilla_connect(pool_def, avail):
|
||||||
if pool_def['condition'] == 'shopsanity':
|
if 'shopsanity' in pool_def['condition']:
|
||||||
if avail.world.shopsanity[avail.player]:
|
if avail.world.shopsanity[avail.player]:
|
||||||
return
|
return
|
||||||
elif pool_def['condition'] == 'pottery': # this condition involves whether caves with pots are shuffled or not
|
if 'pottery' in pool_def['condition']: # this condition involves whether caves with pots are shuffled or not
|
||||||
if avail.world.pottery[avail.player] not in ['none', 'keys', 'dungeon']:
|
if avail.world.pottery[avail.player] not in ['none', 'keys', 'dungeon']:
|
||||||
return
|
return
|
||||||
elif pool_def['condition'] == 'takeany':
|
if 'takeany' in pool_def['condition']:
|
||||||
if avail.world.take_any[avail.player] == 'fixed':
|
if avail.world.take_any[avail.player] == 'fixed':
|
||||||
return
|
return
|
||||||
elif pool_def['condition'] == 'bonk':
|
if 'bonk' in pool_def['condition']:
|
||||||
if avail.world.shuffle_bonk_drops[avail.player]:
|
if avail.world.shuffle_bonk_drops[avail.player]:
|
||||||
return
|
return
|
||||||
|
if 'dropshuffle' in pool_def['condition']:
|
||||||
|
if avail.world.dropshuffle[avail.player] not in ['none', 'keys']:
|
||||||
|
return
|
||||||
|
if 'enemy_drop' in pool_def['condition']:
|
||||||
|
if avail.world.dropshuffle[avail.player] not in ['none', 'keys'] or avail.world.enemy_shuffle[avail.player] != 'none':
|
||||||
|
return
|
||||||
defaults = {**default_connections, **(inverted_default_connections if avail.inverted != avail.world.is_tile_swapped(0x1b, avail.player) else open_default_connections)}
|
defaults = {**default_connections, **(inverted_default_connections if avail.inverted != avail.world.is_tile_swapped(0x1b, avail.player) else open_default_connections)}
|
||||||
for entrance in pool_def['entrances']:
|
for entrance in pool_def['entrances']:
|
||||||
if entrance in avail.entrances:
|
if entrance in avail.entrances:
|
||||||
@@ -1871,35 +1877,56 @@ modes = {
|
|||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': '',
|
'condition': '',
|
||||||
'entrances': ['Mire Fairy', 'Archery Game', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint',
|
'entrances': ['Mire Fairy', 'Archery Game', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint',
|
||||||
'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Fairy', 'Dark Lake Hylia Shop',
|
'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Fairy', 'East Dark World Hint',
|
||||||
'East Dark World Hint', 'Kakariko Gamble Game', 'Long Fairy Cave',
|
'Kakariko Gamble Game', 'Bush Covered House', 'Fortune Teller (Light)',
|
||||||
'Bush Covered House', 'Fortune Teller (Light)', 'Lost Woods Gamble',
|
'Lost Woods Gamble', 'Lake Hylia Fortune Teller', 'Lake Hylia Fairy'],
|
||||||
'Lake Hylia Fortune Teller', 'Lake Hylia Fairy', 'Bonk Fairy (Light)'],
|
|
||||||
},
|
},
|
||||||
'fixed_shops': {
|
'fixed_shops': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'shopsanity',
|
'condition': 'shopsanity',
|
||||||
'entrances': ['Dark Death Mountain Shop', 'Dark Potion Shop', 'Dark Lumberjack Shop',
|
'entrances': ['Dark Death Mountain Shop', 'Dark Potion Shop', 'Dark Lumberjack Shop', 'Dark World Shop',
|
||||||
'Dark World Shop', 'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade',
|
'Red Shield Shop', 'Kakariko Shop', 'Lake Hylia Shop', 'Dark Lake Hylia Shop'],
|
||||||
'Lake Hylia Shop'],
|
|
||||||
},
|
},
|
||||||
'fixed_takeanys': {
|
'fixed_takeanys': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'takeany',
|
'condition': 'takeany',
|
||||||
'entrances': ['Desert Fairy', 'Light Hype Fairy', 'Dark Death Mountain Fairy',
|
'entrances': ['Desert Fairy', 'Light Hype Fairy', 'Dark Death Mountain Fairy', 'Dark Lake Hylia Ledge Fairy'],
|
||||||
'Dark Lake Hylia Ledge Fairy', 'Bonk Fairy (Dark)'],
|
},
|
||||||
|
'fixed_takeanys_enemy_drops_fairies': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['takeany', 'enemy_drop'],
|
||||||
|
'entrances': ['Bonk Fairy (Dark)'],
|
||||||
},
|
},
|
||||||
'fixed_pottery': {
|
'fixed_pottery': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'pottery',
|
'condition': 'pottery',
|
||||||
'entrances': ['Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
'entrances': ['Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
||||||
'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy',
|
'20 Rupee Cave', '50 Rupee Cave', 'Palace of Darkness Hint',
|
||||||
'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave',
|
'Dark Lake Hylia Ledge Spike Cave', 'Mire Hint']
|
||||||
'Mire Hint']
|
},
|
||||||
|
'fixed_enemy_drops_fairies': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': 'enemy_drop',
|
||||||
|
'entrances': ['Long Fairy Cave', 'Bonk Fairy (Light)']
|
||||||
|
},
|
||||||
|
'fixed_pots_n_bones_fairies': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['pottery', 'enemy_drop'],
|
||||||
|
'entrances': ['Hookshot Fairy']
|
||||||
|
},
|
||||||
|
'fixed_pots_n_bones': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['pottery', 'dropshuffle'],
|
||||||
|
'entrances': ['Light World Bomb Hut']
|
||||||
|
},
|
||||||
|
'fixed_shop_n_bones': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['shopsanity', 'enemy_drop'],
|
||||||
|
'entrances': ['Capacity Upgrade']
|
||||||
},
|
},
|
||||||
'fixed_bonk': {
|
'fixed_bonk': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'bonk',
|
'condition': ['enemy_drop', 'bonk'],
|
||||||
'entrances': ['Good Bee Cave']
|
'entrances': ['Good Bee Cave']
|
||||||
},
|
},
|
||||||
'item_caves': { # shuffles shops/pottery if they weren't fixed in the last steps
|
'item_caves': { # shuffles shops/pottery if they weren't fixed in the last steps
|
||||||
@@ -1908,15 +1935,15 @@ modes = {
|
|||||||
'Ice Rod Cave', 'Dam', 'Bonk Rock Cave', 'Library', 'Potion Shop', 'Mini Moldorm Cave',
|
'Ice Rod Cave', 'Dam', 'Bonk Rock Cave', 'Library', 'Potion Shop', 'Mini Moldorm Cave',
|
||||||
'Checkerboard Cave', 'Graveyard Cave', 'Cave 45', 'Sick Kids House', 'Blacksmiths Hut',
|
'Checkerboard Cave', 'Graveyard Cave', 'Cave 45', 'Sick Kids House', 'Blacksmiths Hut',
|
||||||
'Sahasrahlas Hut', 'Aginahs Cave', 'Chicken House', 'Kings Grave', 'Blinds Hideout',
|
'Sahasrahlas Hut', 'Aginahs Cave', 'Chicken House', 'Kings Grave', 'Blinds Hideout',
|
||||||
'Waterfall of Wishing', 'Dark Death Mountain Shop', 'Good Bee Cave',
|
'Waterfall of Wishing', 'Dark Death Mountain Shop', 'Dark Lake Hylia Shop',
|
||||||
'Dark Potion Shop', 'Dark Lumberjack Shop', 'Dark World Shop',
|
'Dark Potion Shop', 'Dark Lumberjack Shop', 'Dark World Shop',
|
||||||
'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Lake Hylia Shop',
|
'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Lake Hylia Shop',
|
||||||
'Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
'Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
||||||
'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy',
|
'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy',
|
||||||
'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave',
|
'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave', 'Desert Fairy',
|
||||||
'Mire Hint', 'Desert Fairy', 'Light Hype Fairy', 'Dark Death Mountain Fairy',
|
'Light Hype Fairy', 'Dark Death Mountain Fairy', 'Dark Lake Hylia Ledge Fairy',
|
||||||
'Dark Lake Hylia Ledge Fairy', 'Bonk Fairy (Dark)',
|
'Bonk Fairy (Dark)', 'Good Bee Cave', 'Long Fairy Cave', 'Bonk Fairy (Light)',
|
||||||
'Links House', 'Tavern North']
|
'Mire Hint', 'Links House', 'Tavern North']
|
||||||
},
|
},
|
||||||
'old_man_cave': { # have to do old man cave first so lw dungeon don't use up everything
|
'old_man_cave': { # have to do old man cave first so lw dungeon don't use up everything
|
||||||
'special': 'old_man_cave_east',
|
'special': 'old_man_cave_east',
|
||||||
@@ -1962,35 +1989,56 @@ modes = {
|
|||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': '',
|
'condition': '',
|
||||||
'entrances': ['Mire Fairy', 'Archery Game', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint',
|
'entrances': ['Mire Fairy', 'Archery Game', 'Fortune Teller (Dark)', 'Dark Sanctuary Hint',
|
||||||
'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Fairy', 'Dark Lake Hylia Shop',
|
'Dark Lake Hylia Ledge Hint', 'Dark Lake Hylia Fairy', 'East Dark World Hint',
|
||||||
'East Dark World Hint', 'Kakariko Gamble Game', 'Long Fairy Cave',
|
'Kakariko Gamble Game', 'Bush Covered House', 'Fortune Teller (Light)',
|
||||||
'Bush Covered House', 'Fortune Teller (Light)', 'Lost Woods Gamble',
|
'Lost Woods Gamble', 'Lake Hylia Fortune Teller', 'Lake Hylia Fairy'],
|
||||||
'Lake Hylia Fortune Teller', 'Lake Hylia Fairy', 'Bonk Fairy (Light)'],
|
|
||||||
},
|
},
|
||||||
'fixed_shops': {
|
'fixed_shops': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'shopsanity',
|
'condition': 'shopsanity',
|
||||||
'entrances': ['Dark Death Mountain Shop', 'Dark Potion Shop', 'Dark Lumberjack Shop',
|
'entrances': ['Dark Death Mountain Shop', 'Dark Potion Shop', 'Dark Lumberjack Shop', 'Dark World Shop',
|
||||||
'Dark World Shop', 'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade',
|
'Red Shield Shop', 'Kakariko Shop', 'Lake Hylia Shop', 'Dark Lake Hylia Shop'],
|
||||||
'Lake Hylia Shop'],
|
|
||||||
},
|
},
|
||||||
'fixed_takeanys': {
|
'fixed_takeanys': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'takeany',
|
'condition': 'takeany',
|
||||||
'entrances': ['Desert Fairy', 'Light Hype Fairy', 'Dark Death Mountain Fairy',
|
'entrances': ['Desert Fairy', 'Light Hype Fairy', 'Dark Death Mountain Fairy', 'Dark Lake Hylia Ledge Fairy'],
|
||||||
'Dark Lake Hylia Ledge Fairy', 'Bonk Fairy (Dark)'],
|
},
|
||||||
|
'fixed_takeanys_enemy_drops_fairies': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['takeany', 'enemy_drop'],
|
||||||
|
'entrances': ['Bonk Fairy (Dark)'],
|
||||||
},
|
},
|
||||||
'fixed_pottery': {
|
'fixed_pottery': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'pottery',
|
'condition': 'pottery',
|
||||||
'entrances': ['Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
'entrances': ['Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
||||||
'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy',
|
'20 Rupee Cave', '50 Rupee Cave', 'Palace of Darkness Hint',
|
||||||
'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave',
|
'Dark Lake Hylia Ledge Spike Cave', 'Mire Hint']
|
||||||
'Mire Hint']
|
},
|
||||||
|
'fixed_enemy_drops_fairies': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': 'enemy_drop',
|
||||||
|
'entrances': ['Long Fairy Cave', 'Bonk Fairy (Light)']
|
||||||
|
},
|
||||||
|
'fixed_pots_n_bones_fairies': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['pottery', 'enemy_drop'],
|
||||||
|
'entrances': ['Hookshot Fairy']
|
||||||
|
},
|
||||||
|
'fixed_pots_n_bones': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['pottery', 'dropshuffle'],
|
||||||
|
'entrances': ['Light World Bomb Hut']
|
||||||
|
},
|
||||||
|
'fixed_shop_n_bones': {
|
||||||
|
'special': 'vanilla',
|
||||||
|
'condition': ['shopsanity', 'enemy_drop'],
|
||||||
|
'entrances': ['Capacity Upgrade']
|
||||||
},
|
},
|
||||||
'fixed_bonk': {
|
'fixed_bonk': {
|
||||||
'special': 'vanilla',
|
'special': 'vanilla',
|
||||||
'condition': 'bonk',
|
'condition': ['enemy_drop', 'bonk'],
|
||||||
'entrances': ['Good Bee Cave']
|
'entrances': ['Good Bee Cave']
|
||||||
},
|
},
|
||||||
'item_caves': { # shuffles shops/pottery if they weren't fixed in the last steps
|
'item_caves': { # shuffles shops/pottery if they weren't fixed in the last steps
|
||||||
@@ -1999,15 +2047,15 @@ modes = {
|
|||||||
'Ice Rod Cave', 'Dam', 'Bonk Rock Cave', 'Library', 'Potion Shop', 'Mini Moldorm Cave',
|
'Ice Rod Cave', 'Dam', 'Bonk Rock Cave', 'Library', 'Potion Shop', 'Mini Moldorm Cave',
|
||||||
'Checkerboard Cave', 'Graveyard Cave', 'Cave 45', 'Sick Kids House', 'Blacksmiths Hut',
|
'Checkerboard Cave', 'Graveyard Cave', 'Cave 45', 'Sick Kids House', 'Blacksmiths Hut',
|
||||||
'Sahasrahlas Hut', 'Aginahs Cave', 'Chicken House', 'Kings Grave', 'Blinds Hideout',
|
'Sahasrahlas Hut', 'Aginahs Cave', 'Chicken House', 'Kings Grave', 'Blinds Hideout',
|
||||||
'Waterfall of Wishing', 'Dark Death Mountain Shop', 'Good Bee Cave',
|
'Waterfall of Wishing', 'Dark Death Mountain Shop', 'Dark Lake Hylia Shop',
|
||||||
'Dark Potion Shop', 'Dark Lumberjack Shop', 'Dark World Shop',
|
'Dark Potion Shop', 'Dark Lumberjack Shop', 'Dark World Shop',
|
||||||
'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Lake Hylia Shop',
|
'Red Shield Shop', 'Kakariko Shop', 'Capacity Upgrade', 'Lake Hylia Shop',
|
||||||
'Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
'Lumberjack House', 'Snitch Lady (West)', 'Snitch Lady (East)', 'Tavern (Front)',
|
||||||
'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy',
|
'Light World Bomb Hut', '20 Rupee Cave', '50 Rupee Cave', 'Hookshot Fairy',
|
||||||
'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave',
|
'Palace of Darkness Hint', 'Dark Lake Hylia Ledge Spike Cave', 'Desert Fairy',
|
||||||
'Mire Hint', 'Desert Fairy', 'Light Hype Fairy', 'Dark Death Mountain Fairy',
|
'Light Hype Fairy', 'Dark Death Mountain Fairy', 'Dark Lake Hylia Ledge Fairy',
|
||||||
'Dark Lake Hylia Ledge Fairy', 'Bonk Fairy (Dark)',
|
'Bonk Fairy (Dark)', 'Good Bee Cave', 'Long Fairy Cave', 'Bonk Fairy (Light)',
|
||||||
'Links House', 'Tavern North'] # inverted links house gets substituted
|
'Mire Hint', 'Links House', 'Tavern North']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class DataTables:
|
|||||||
# _00FA81 is LW normal
|
# _00FA81 is LW normal
|
||||||
# _00FAC1 is LW post-aga
|
# _00FAC1 is LW post-aga
|
||||||
# _00FB01 is DW
|
# _00FB01 is DW
|
||||||
|
# _00FA41 is rain state
|
||||||
self.write_ow_sprite_data_to_rom(rom)
|
self.write_ow_sprite_data_to_rom(rom)
|
||||||
for sprite, stats in self.enemy_stats.items():
|
for sprite, stats in self.enemy_stats.items():
|
||||||
# write health to rom
|
# write health to rom
|
||||||
@@ -134,9 +135,11 @@ class DataTables:
|
|||||||
# calculate how big this table is going to be?
|
# calculate how big this table is going to be?
|
||||||
# bytes = sum(1+len(x)*3 for x in self.ow_enemy_table.values() if len(x) > 0)+1
|
# bytes = sum(1+len(x)*3 for x in self.ow_enemy_table.values() if len(x) > 0)+1
|
||||||
# ending_byte = 0x09CB3B + bytes
|
# ending_byte = 0x09CB3B + bytes
|
||||||
max_per_state = {0: 0x40, 1: 0x90, 2: 0x8D} # dropped max on state 2 to steal space for a couple extra sprites (Murahdahla)
|
max_per_state = {0: 0x40, 1: 0x90, 2: 0x8B} # dropped max on state 2 to steal space for a couple extra sprites (Murahdahla, extra tutorial guard)
|
||||||
|
|
||||||
pointer_address = snes_to_pc(0x09C881)
|
pointer_address = snes_to_pc(0x09C881)
|
||||||
data_pointer = snes_to_pc(0x09CB3B) # was originally 0x09CB41 - stealing space for a couple extra sprites (Murahdahla)
|
# currently borrowed 10 bytes, used 9 (2xMurah + TutorialGuard)
|
||||||
|
data_pointer = snes_to_pc(0x09CB38) # was originally 0x09CB41 - stealing space for a couple extra sprites (Murahdahla, extra tutorial guard)
|
||||||
empty_pointer = pc_to_snes(data_pointer) & 0xFFFF
|
empty_pointer = pc_to_snes(data_pointer) & 0xFFFF
|
||||||
rom.write_byte(data_pointer, 0xff)
|
rom.write_byte(data_pointer, 0xff)
|
||||||
cached_dark_world = {}
|
cached_dark_world = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user