LttP: move some simple Toggle options over to new system
This commit is contained in:
parent
e57e92bfee
commit
033adceb6f
|
@ -77,7 +77,6 @@ class MultiWorld():
|
|||
set_player_attr('shuffle', "vanilla")
|
||||
set_player_attr('logic', "noglitches")
|
||||
set_player_attr('mode', 'open')
|
||||
set_player_attr('swordless', False)
|
||||
set_player_attr('difficulty', 'normal')
|
||||
set_player_attr('item_functionality', 'normal')
|
||||
set_player_attr('timer', False)
|
||||
|
@ -1127,7 +1126,7 @@ class Spoiler():
|
|||
'tile_shuffle': self.world.tile_shuffle,
|
||||
'bush_shuffle': self.world.bush_shuffle,
|
||||
'beemizer': self.world.beemizer,
|
||||
'shufflepots': self.world.shufflepots,
|
||||
'pot_shuffle': self.world.pot_shuffle,
|
||||
'players': self.world.players,
|
||||
'progression_balancing': self.world.progression_balancing,
|
||||
'triforce_pieces_available': self.world.triforce_pieces_available,
|
||||
|
@ -1193,13 +1192,7 @@ class Spoiler():
|
|||
|
||||
outfile.write('Logic: %s\n' % self.metadata['logic'][player])
|
||||
outfile.write('Dark Room Logic: %s\n' % self.metadata['dark_room_logic'][player])
|
||||
outfile.write('Restricted Boss Drops: %s\n' %
|
||||
bool_to_text(self.metadata['restrict_dungeon_item_on_boss'][player]))
|
||||
|
||||
outfile.write('Mode: %s\n' % self.metadata['mode'][player])
|
||||
outfile.write('Retro: %s\n' %
|
||||
('Yes' if self.metadata['retro'][player] else 'No'))
|
||||
outfile.write('Swordless: %s\n' % ('Yes' if self.metadata['swordless'][player] else 'No'))
|
||||
outfile.write('Goal: %s\n' % self.metadata['goal'][player])
|
||||
if "triforce" in self.metadata["goal"][player]: # triforce hunt
|
||||
outfile.write("Pieces available for Triforce: %s\n" %
|
||||
|
@ -1225,18 +1218,9 @@ class Spoiler():
|
|||
outfile.write('Custom Potion Shop: %s\n' %
|
||||
bool_to_text("w" in self.metadata["shop_shuffle"][player]))
|
||||
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
||||
outfile.write(
|
||||
'Enemy shuffle: %s\n' % bool_to_text(self.metadata['enemy_shuffle'][player]))
|
||||
outfile.write('Enemy health: %s\n' % self.metadata['enemy_health'][player])
|
||||
outfile.write('Enemy damage: %s\n' % self.metadata['enemy_damage'][player])
|
||||
outfile.write(f'Killable thieves: {bool_to_text(self.metadata["killable_thieves"][player])}\n')
|
||||
outfile.write(f'Shuffled tiles: {bool_to_text(self.metadata["tile_shuffle"][player])}\n')
|
||||
outfile.write(f'Shuffled bushes: {bool_to_text(self.metadata["bush_shuffle"][player])}\n')
|
||||
outfile.write(
|
||||
'Hints: %s\n' % ('Yes' if self.metadata['hints'][player] else 'No'))
|
||||
outfile.write('Beemizer: %s\n' % self.metadata['beemizer'][player])
|
||||
outfile.write('Pot shuffle %s\n'
|
||||
% ('Yes' if self.metadata['shufflepots'][player] else 'No'))
|
||||
outfile.write('Prize shuffle %s\n' %
|
||||
self.metadata['shuffle_prizes'][player])
|
||||
if self.entrances:
|
||||
|
|
18
Generate.py
18
Generate.py
|
@ -121,10 +121,9 @@ def main(args=None, callback=ERmain):
|
|||
f"A mix is also permitted.")
|
||||
erargs = parse_arguments(['--multi', str(args.multi)])
|
||||
erargs.seed = seed
|
||||
erargs.create_spoiler = args.spoiler > 0
|
||||
erargs.glitch_triforce = options["generator"]["glitch_triforce_room"]
|
||||
erargs.spoiler = args.spoiler
|
||||
erargs.race = args.race
|
||||
erargs.skip_playthrough = args.spoiler < 2
|
||||
erargs.outputname = seed_name
|
||||
erargs.outputpath = args.outputpath
|
||||
|
||||
|
@ -587,8 +586,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
if ret.dark_room_logic not in {"lamp", "torches", "none"}:
|
||||
raise ValueError(f"Unknown Dark Room Logic: \"{ret.dark_room_logic}\"")
|
||||
|
||||
ret.restrict_dungeon_item_on_boss = get_choice_legacy('restrict_dungeon_item_on_boss', weights, False)
|
||||
|
||||
entrance_shuffle = get_choice_legacy('entrance_shuffle', weights, 'vanilla')
|
||||
if entrance_shuffle.startswith('none-'):
|
||||
ret.shuffle = 'vanilla'
|
||||
|
@ -628,11 +625,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
ret.shop_shuffle = ''
|
||||
|
||||
ret.mode = get_choice_legacy("mode", weights)
|
||||
ret.retro = get_choice_legacy("retro", weights)
|
||||
|
||||
ret.hints = get_choice_legacy('hints', weights)
|
||||
|
||||
ret.swordless = get_choice_legacy('swordless', weights, False)
|
||||
|
||||
ret.difficulty = get_choice_legacy('item_pool', weights)
|
||||
|
||||
|
@ -641,12 +633,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
boss_shuffle = get_choice_legacy('boss_shuffle', weights)
|
||||
ret.shufflebosses = get_plando_bosses(boss_shuffle, plando_options)
|
||||
|
||||
ret.enemy_shuffle = bool(get_choice_legacy('enemy_shuffle', weights, False))
|
||||
|
||||
ret.killable_thieves = get_choice_legacy('killable_thieves', weights, False)
|
||||
ret.tile_shuffle = get_choice_legacy('tile_shuffle', weights, False)
|
||||
ret.bush_shuffle = get_choice_legacy('bush_shuffle', weights, False)
|
||||
|
||||
ret.enemy_damage = {None: 'default',
|
||||
'default': 'default',
|
||||
'shuffled': 'shuffled',
|
||||
|
@ -656,8 +642,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
|
||||
ret.enemy_health = get_choice_legacy('enemy_health', weights)
|
||||
|
||||
ret.shufflepots = get_choice_legacy('pot_shuffle', weights)
|
||||
|
||||
ret.beemizer = int(get_choice_legacy('beemizer', weights, 0))
|
||||
|
||||
ret.timer = {'none': False,
|
||||
|
|
12
Main.py
12
Main.py
|
@ -63,24 +63,17 @@ def main(args, seed=None):
|
|||
world.customitemarray = args.customitemarray
|
||||
|
||||
world.accessibility = args.accessibility.copy()
|
||||
world.retro = args.retro.copy()
|
||||
|
||||
world.hints = args.hints.copy()
|
||||
world.open_pyramid = args.open_pyramid.copy()
|
||||
world.boss_shuffle = args.shufflebosses.copy()
|
||||
world.enemy_shuffle = args.enemy_shuffle.copy()
|
||||
world.enemy_health = args.enemy_health.copy()
|
||||
world.enemy_damage = args.enemy_damage.copy()
|
||||
world.killable_thieves = args.killable_thieves.copy()
|
||||
world.bush_shuffle = args.bush_shuffle.copy()
|
||||
world.tile_shuffle = args.tile_shuffle.copy()
|
||||
world.beemizer = args.beemizer.copy()
|
||||
world.timer = args.timer.copy()
|
||||
world.countdown_start_time = args.countdown_start_time.copy()
|
||||
world.red_clock_time = args.red_clock_time.copy()
|
||||
world.blue_clock_time = args.blue_clock_time.copy()
|
||||
world.green_clock_time = args.green_clock_time.copy()
|
||||
world.shufflepots = args.shufflepots.copy()
|
||||
world.dungeon_counters = args.dungeon_counters.copy()
|
||||
world.triforce_pieces_available = args.triforce_pieces_available.copy()
|
||||
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
||||
|
@ -93,7 +86,6 @@ def main(args, seed=None):
|
|||
world.plando_texts = args.plando_texts.copy()
|
||||
world.plando_connections = args.plando_connections.copy()
|
||||
world.er_seeds = getattr(args, "er_seeds", {})
|
||||
world.restrict_dungeon_item_on_boss = args.restrict_dungeon_item_on_boss.copy()
|
||||
world.required_medallions = args.required_medallions.copy()
|
||||
world.game = args.game.copy()
|
||||
world.set_options(args)
|
||||
|
@ -346,11 +338,11 @@ def main(args, seed=None):
|
|||
logger.info(f'Generating output files ({i}/{len(output_file_futures)}).')
|
||||
future.result()
|
||||
|
||||
if not args.skip_playthrough:
|
||||
if args.spoiler > 1:
|
||||
logger.info('Calculating playthrough.')
|
||||
create_playthrough(world)
|
||||
|
||||
if args.create_spoiler:
|
||||
if args.spoiler:
|
||||
world.spoiler.to_file(os.path.join(temp_dir, '%s_Spoiler.txt' % outfilebase))
|
||||
|
||||
zipfilename = output_path(f"AP_{world.seed_name}.zip")
|
||||
|
|
|
@ -74,9 +74,8 @@ def gen_game(gen_options, race=False, owner=None, sid=None):
|
|||
erargs = parse_arguments(['--multi', str(playercount)])
|
||||
erargs.seed = seed
|
||||
erargs.name = {x: "" for x in range(1, playercount + 1)} # only so it can be overwrittin in mystery
|
||||
erargs.create_spoiler = not race
|
||||
erargs.spoiler = 0 if race else 2
|
||||
erargs.race = race
|
||||
erargs.skip_playthrough = race
|
||||
erargs.outputname = seedname
|
||||
erargs.outputpath = target.name
|
||||
erargs.teams = 1
|
||||
|
|
|
@ -20,7 +20,6 @@ def parse_arguments(argv, no_defaults=False):
|
|||
multiargs, _ = parser.parse_known_args(argv)
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('--create_spoiler', help='Output a Spoiler File', action='store_true')
|
||||
parser.add_argument('--logic', default=defval('noglitches'), const='noglitches', nargs='?', choices=['noglitches', 'minorglitches', 'owglitches', 'hybridglitches', 'nologic'],
|
||||
help='''\
|
||||
Select Enforcement of Item Requirements. (default: %(default)s)
|
||||
|
@ -46,17 +45,6 @@ def parse_arguments(argv, no_defaults=False):
|
|||
Requires the moon pearl to be Link in the Light World
|
||||
instead of a bunny.
|
||||
''')
|
||||
parser.add_argument('--swordless', action='store_true',
|
||||
help='''\
|
||||
Toggles Swordless Mode
|
||||
Swordless: No swords. Curtains in Skull Woods and Agahnim\'s
|
||||
Tower are removed, Agahnim\'s Tower barrier can be
|
||||
destroyed with hammer. Misery Mire and Turtle Rock
|
||||
can be opened without a sword. Hammer damages Ganon.
|
||||
Ether and Bombos Tablet can be activated with Hammer
|
||||
(and Book). Bombos pads have been added in Ice
|
||||
Palace, to allow for an alternative to firerod.
|
||||
''')
|
||||
parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?',
|
||||
choices=['ganon', 'pedestal', 'bosses', 'triforcehunt', 'localtriforcehunt', 'ganontriforcehunt', 'localganontriforcehunt', 'crystals', 'ganonpedestal'],
|
||||
help='''\
|
||||
|
@ -206,10 +194,6 @@ def parse_arguments(argv, no_defaults=False):
|
|||
time).
|
||||
''', type=int)
|
||||
|
||||
parser.add_argument('--retro', default=defval(False), help='''\
|
||||
Keys are universal, shooting arrows costs rupees,
|
||||
and a few other little things make this more like Zelda-1.
|
||||
''', action='store_true')
|
||||
parser.add_argument('--local_items', default=defval(''),
|
||||
help='Specifies a list of items that will not spread across the multiworld (separated by commas)')
|
||||
parser.add_argument('--non_local_items', default=defval(''),
|
||||
|
@ -223,9 +207,6 @@ def parse_arguments(argv, no_defaults=False):
|
|||
Locations: You will be able to reach every location in the game.
|
||||
None: You will be able to reach enough locations to beat the game.
|
||||
''')
|
||||
parser.add_argument('--hints', default=defval(False), help='''\
|
||||
Make telepathic tiles and storytellers give helpful hints.
|
||||
''', action='store_true')
|
||||
# included for backwards compatibility
|
||||
parser.add_argument('--shuffleganon', help=argparse.SUPPRESS, action='store_true', default=defval(True))
|
||||
parser.add_argument('--no-shuffleganon', help='''\
|
||||
|
@ -243,18 +224,13 @@ def parse_arguments(argv, no_defaults=False):
|
|||
parser.add_argument('--gui', help='Launch the GUI', action='store_true')
|
||||
parser.add_argument('--progression_balancing', action='store_true', default=defval(False),
|
||||
help="Enable Multiworld Progression balancing.")
|
||||
parser.add_argument('--skip_playthrough', action='store_true', default=defval(False))
|
||||
parser.add_argument('--enemizercli', default=defval('EnemizerCLI/EnemizerCLI.Core'))
|
||||
parser.add_argument('--shufflebosses', default=defval('none'), choices=['none', 'basic', 'normal', 'chaos',
|
||||
"singularity"])
|
||||
parser.add_argument('--enemy_shuffle', action='store_true')
|
||||
parser.add_argument('--killable_thieves', action='store_true')
|
||||
parser.add_argument('--tile_shuffle', action='store_true')
|
||||
parser.add_argument('--bush_shuffle', action='store_true')
|
||||
|
||||
parser.add_argument('--enemy_health', default=defval('default'),
|
||||
choices=['default', 'easy', 'normal', 'hard', 'expert'])
|
||||
parser.add_argument('--enemy_damage', default=defval('default'), choices=['default', 'shuffled', 'chaos'])
|
||||
parser.add_argument('--shufflepots', default=defval(False), action='store_true')
|
||||
parser.add_argument('--beemizer', default=defval(0), type=lambda value: min(max(int(value), 0), 4))
|
||||
parser.add_argument('--shop_shuffle', default='', help='''\
|
||||
combine letters for options:
|
||||
|
@ -272,7 +248,6 @@ def parse_arguments(argv, no_defaults=False):
|
|||
For unlit dark rooms, require the Lamp to be considered in logic by default.
|
||||
Torches means additionally easily accessible Torches that can be lit with Fire Rod are considered doable.
|
||||
None means full traversal through dark rooms without tools is considered doable.''')
|
||||
parser.add_argument('--restrict_dungeon_item_on_boss', default=defval(False), action="store_true")
|
||||
parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255))
|
||||
parser.add_argument('--names', default=defval(''))
|
||||
parser.add_argument('--outputpath')
|
||||
|
@ -307,19 +282,19 @@ def parse_arguments(argv, no_defaults=False):
|
|||
for player in range(1, multiargs.multi + 1):
|
||||
playerargs = parse_arguments(shlex.split(getattr(ret, f"p{player}")), True)
|
||||
|
||||
for name in ['logic', 'mode', 'swordless', 'goal', 'difficulty', 'item_functionality',
|
||||
for name in ['logic', 'mode', 'goal', 'difficulty', 'item_functionality',
|
||||
'shuffle', 'open_pyramid', 'timer',
|
||||
'countdown_start_time', 'red_clock_time', 'blue_clock_time', 'green_clock_time',
|
||||
'local_items', 'non_local_items', 'retro', 'accessibility', 'hints', 'beemizer',
|
||||
'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||
'local_items', 'non_local_items', 'accessibility', 'beemizer',
|
||||
'shufflebosses', 'enemy_health', 'enemy_damage',
|
||||
'sprite',
|
||||
"progression_balancing", "triforce_pieces_available",
|
||||
"triforce_pieces_required", "shop_shuffle",
|
||||
"required_medallions", "start_hints",
|
||||
"plando_items", "plando_texts", "plando_connections", "er_seeds",
|
||||
'dungeon_counters', 'killable_thieves',
|
||||
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
||||
'restrict_dungeon_item_on_boss', 'game']:
|
||||
'dungeon_counters',
|
||||
'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
||||
'game']:
|
||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||
if player == 1:
|
||||
setattr(ret, name, {1: value})
|
||||
|
|
|
@ -126,6 +126,59 @@ class Progressive(Choice):
|
|||
return random.choice([True, False]) if self.value == self.option_grouped_random else bool(self.value)
|
||||
|
||||
|
||||
class Swordless(Toggle):
|
||||
"""No swords. Curtains in Skull Woods and Agahnim\'s
|
||||
Tower are removed, Agahnim\'s Tower barrier can be
|
||||
destroyed with hammer. Misery Mire and Turtle Rock
|
||||
can be opened without a sword. Hammer damages Ganon.
|
||||
Ether and Bombos Tablet can be activated with Hammer
|
||||
(and Book)."""
|
||||
displayname = "Swordless"
|
||||
|
||||
|
||||
class Retro(Toggle):
|
||||
"""Zelda-1 like mode. You have to purchase a quiver to shoot arrows using rupees
|
||||
and there are randomly placed take-any caves that contain one Sword and choices of Heart Container/Blue Potion."""
|
||||
displayname = "Retro"
|
||||
|
||||
|
||||
class RestrictBossItem(Toggle):
|
||||
"""Don't place dungeon-native items on the dungeon's boss."""
|
||||
displayname = "Prevent Dungeon Item on Boss"
|
||||
|
||||
|
||||
class Hints(DefaultOnToggle):
|
||||
"""Put item and entrance placement hints on telepathic tiles and some NPCs.
|
||||
Additionally King Zora and Bottle Merchant say what they're selling."""
|
||||
displayname = "Hints"
|
||||
|
||||
|
||||
class EnemyShuffle(Toggle):
|
||||
"""Randomize every enemy spawn.
|
||||
If mode is Standard, Hyrule Castle is left out (may result in visually wrong enemy sprites in that area.)"""
|
||||
displayname = "Enemy Shuffle"
|
||||
|
||||
|
||||
class KillableThieves(Toggle):
|
||||
"""Makes Thieves killable."""
|
||||
displayname = "Killable Thieves"
|
||||
|
||||
|
||||
class BushShuffle(Toggle):
|
||||
"""Randomize chance that a bush contains an enemy as well as which enemy may spawn."""
|
||||
displayname = "Bush Shuffle"
|
||||
|
||||
|
||||
class TileShuffle(Toggle):
|
||||
"""Randomize flying tiles floor patterns."""
|
||||
displayname = "Tile Shuffle"
|
||||
|
||||
|
||||
class PotShuffle(Toggle):
|
||||
"""Shuffle contents of pots within "supertiles" (item will still be nearby original placement)."""
|
||||
displayname = "Pot Shuffle"
|
||||
|
||||
|
||||
class Palette(Choice):
|
||||
option_default = 0
|
||||
option_good = 1
|
||||
|
@ -226,6 +279,13 @@ alttp_options: typing.Dict[str, type(Option)] = {
|
|||
"compass_shuffle": compass_shuffle,
|
||||
"map_shuffle": map_shuffle,
|
||||
"progressive": Progressive,
|
||||
"swordless": Swordless,
|
||||
"hints": Hints,
|
||||
"restrict_dungeon_item_on_boss": RestrictBossItem,
|
||||
"pot_shuffle": PotShuffle,
|
||||
"enemy_shuffle": EnemyShuffle,
|
||||
"killable_thieves": KillableThieves,
|
||||
"bush_shuffle": BushShuffle,
|
||||
"shop_item_slots": ShopItemSlots,
|
||||
"ow_palettes": OWPalette,
|
||||
"uw_palettes": UWPalette,
|
||||
|
|
|
@ -323,7 +323,7 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, output_direct
|
|||
'GrayscaleMode': False,
|
||||
'GenerateSpoilers': False,
|
||||
'RandomizeLinkSpritePalette': False,
|
||||
'RandomizePots': world.shufflepots[player],
|
||||
'RandomizePots': world.pot_shuffle[player],
|
||||
'ShuffleMusic': False,
|
||||
'BootlegMagic': True,
|
||||
'CustomBosses': False,
|
||||
|
|
|
@ -258,7 +258,7 @@ class ALTTPWorld(World):
|
|||
try:
|
||||
use_enemizer = (world.boss_shuffle[player] != 'none' or world.enemy_shuffle[player]
|
||||
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
||||
or world.shufflepots[player] or world.bush_shuffle[player]
|
||||
or world.pot_shuffle[player] or world.bush_shuffle[player]
|
||||
or world.killable_thieves[player])
|
||||
|
||||
rom = LocalRom(world.alttp_rom)
|
||||
|
|
Loading…
Reference in New Issue