Factor out Bottom Frame
Factor out ArgParser Factor out working dirs for future Bind everything to the main window so that Custom tab doesn't complain
This commit is contained in:
339
CLI.py
Normal file
339
CLI.py
Normal file
@@ -0,0 +1,339 @@
|
||||
import argparse
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
import random
|
||||
import textwrap
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
from Main import main
|
||||
from Rom import get_sprite_from_name
|
||||
from Utils import is_bundled, close_console
|
||||
from Fill import FillError
|
||||
|
||||
|
||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||
|
||||
def _get_help_string(self, action):
|
||||
return textwrap.dedent(action.help)
|
||||
|
||||
def parse_arguments(argv, no_defaults=False):
|
||||
def defval(value):
|
||||
return value if not no_defaults else None
|
||||
|
||||
# we need to know how many players we have first
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument('--multi', default=defval(1), type=lambda value: min(max(int(value), 1), 255))
|
||||
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', 'nologic'],
|
||||
help='''\
|
||||
Select Enforcement of Item Requirements. (default: %(default)s)
|
||||
No Glitches:
|
||||
Minor Glitches: May require Fake Flippers, Bunny Revival
|
||||
and Dark Room Navigation.
|
||||
No Logic: Distribute items without regard for
|
||||
item requirements.
|
||||
''')
|
||||
parser.add_argument('--mode', default=defval('open'), const='open', nargs='?', choices=['standard', 'open', 'inverted'],
|
||||
help='''\
|
||||
Select game mode. (default: %(default)s)
|
||||
Open: World starts with Zelda rescued.
|
||||
Standard: Fixes Hyrule Castle Secret Entrance and Front Door
|
||||
but may lead to weird rain state issues if you exit
|
||||
through the Hyrule Castle side exits before rescuing
|
||||
Zelda in a full shuffle.
|
||||
Inverted: Starting locations are Dark Sanctuary in West Dark
|
||||
World or at Link's House, which is shuffled freely.
|
||||
Requires the moon pearl to be Link in the Light World
|
||||
instead of a bunny.
|
||||
''')
|
||||
parser.add_argument('--swords', default=defval('random'), const='random', nargs='?', choices= ['random', 'assured', 'swordless', 'vanilla'],
|
||||
help='''\
|
||||
Select sword placement. (default: %(default)s)
|
||||
Random: All swords placed randomly.
|
||||
Assured: Start game with a sword already.
|
||||
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.
|
||||
Vanilla: Swords are in vanilla locations.
|
||||
''')
|
||||
parser.add_argument('--goal', default=defval('ganon'), const='ganon', nargs='?', choices=['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'],
|
||||
help='''\
|
||||
Select completion goal. (default: %(default)s)
|
||||
Ganon: Collect all crystals, beat Agahnim 2 then
|
||||
defeat Ganon.
|
||||
Crystals: Collect all crystals then defeat Ganon.
|
||||
Pedestal: Places the Triforce at the Master Sword Pedestal.
|
||||
All Dungeons: Collect all crystals, pendants, beat both
|
||||
Agahnim fights and then defeat Ganon.
|
||||
Triforce Hunt: Places 30 Triforce Pieces in the world, collect
|
||||
20 of them to beat the game.
|
||||
''')
|
||||
parser.add_argument('--difficulty', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'],
|
||||
help='''\
|
||||
Select game difficulty. Affects available itempool. (default: %(default)s)
|
||||
Normal: Normal difficulty.
|
||||
Hard: A harder setting with less equipment and reduced health.
|
||||
Expert: A harder yet setting with minimum equipment and health.
|
||||
''')
|
||||
parser.add_argument('--item_functionality', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'hard', 'expert'],
|
||||
help='''\
|
||||
Select limits on item functionality to increase difficulty. (default: %(default)s)
|
||||
Normal: Normal functionality.
|
||||
Hard: Reduced functionality.
|
||||
Expert: Greatly reduced functionality.
|
||||
''')
|
||||
parser.add_argument('--timer', default=defval('none'), const='normal', nargs='?', choices=['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown'],
|
||||
help='''\
|
||||
Select game timer setting. Affects available itempool. (default: %(default)s)
|
||||
None: No timer.
|
||||
Display: Displays a timer but does not affect
|
||||
the itempool.
|
||||
Timed: Starts with clock at zero. Green Clocks
|
||||
subtract 4 minutes (Total: 20), Blue Clocks
|
||||
subtract 2 minutes (Total: 10), Red Clocks add
|
||||
2 minutes (Total: 10). Winner is player with
|
||||
lowest time at the end.
|
||||
Timed OHKO: Starts clock at 10 minutes. Green Clocks add
|
||||
5 minutes (Total: 25). As long as clock is at 0,
|
||||
Link will die in one hit.
|
||||
OHKO: Like Timed OHKO, but no clock items are present
|
||||
and the clock is permenantly at zero.
|
||||
Timed Countdown: Starts with clock at 40 minutes. Same clocks as
|
||||
Timed mode. If time runs out, you lose (but can
|
||||
still keep playing).
|
||||
''')
|
||||
parser.add_argument('--progressive', default=defval('on'), const='normal', nargs='?', choices=['on', 'off', 'random'],
|
||||
help='''\
|
||||
Select progressive equipment setting. Affects available itempool. (default: %(default)s)
|
||||
On: Swords, Shields, Armor, and Gloves will
|
||||
all be progressive equipment. Each subsequent
|
||||
item of the same type the player finds will
|
||||
upgrade that piece of equipment by one stage.
|
||||
Off: Swords, Shields, Armor, and Gloves will not
|
||||
be progressive equipment. Higher level items may
|
||||
be found at any time. Downgrades are not possible.
|
||||
Random: Swords, Shields, Armor, and Gloves will, per
|
||||
category, be randomly progressive or not.
|
||||
Link will die in one hit.
|
||||
''')
|
||||
parser.add_argument('--algorithm', default=defval('balanced'), const='balanced', nargs='?', choices=['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26', 'balanced'],
|
||||
help='''\
|
||||
Select item filling algorithm. (default: %(default)s
|
||||
balanced: vt26 derivative that aims to strike a balance between
|
||||
the overworld heavy vt25 and the dungeon heavy vt26
|
||||
algorithm.
|
||||
vt26: Shuffle items and place them in a random location
|
||||
that it is not impossible to be in. This includes
|
||||
dungeon keys and items.
|
||||
vt25: Shuffle items and place them in a random location
|
||||
that it is not impossible to be in.
|
||||
vt21: Unbiased in its selection, but has tendency to put
|
||||
Ice Rod in Turtle Rock.
|
||||
vt22: Drops off stale locations after 1/3 of progress
|
||||
items were placed to try to circumvent vt21\'s
|
||||
shortcomings.
|
||||
Freshness: Keep track of stale locations (ones that cannot be
|
||||
reached yet) and decrease likeliness of selecting
|
||||
them the more often they were found unreachable.
|
||||
Flood: Push out items starting from Link\'s House and
|
||||
slightly biased to placing progression items with
|
||||
less restrictions.
|
||||
''')
|
||||
parser.add_argument('--shuffle', default=defval('vanilla'), const='full', nargs='?', choices=['vanilla', 'simple', 'restricted', 'full', 'crossed', 'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy', 'dungeonsfull', 'dungeonssimple'],
|
||||
help='''\
|
||||
Select Entrance Shuffling Algorithm. (default: %(default)s)
|
||||
Full: Mix cave and dungeon entrances freely while limiting
|
||||
multi-entrance caves to one world.
|
||||
Simple: Shuffle Dungeon Entrances/Exits between each other
|
||||
and keep all 4-entrance dungeons confined to one
|
||||
location. All caves outside of death mountain are
|
||||
shuffled in pairs and matched by original type.
|
||||
Restricted: Use Dungeons shuffling from Simple but freely
|
||||
connect remaining entrances.
|
||||
Crossed: Mix cave and dungeon entrances freely while allowing
|
||||
caves to cross between worlds.
|
||||
Insanity: Decouple entrances and exits from each other and
|
||||
shuffle them freely. Caves that used to be single
|
||||
entrance will still exit to the same location from
|
||||
which they are entered.
|
||||
Vanilla: All entrances are in the same locations they were
|
||||
in the base game.
|
||||
Legacy shuffles preserve behavior from older versions of the
|
||||
entrance randomizer including significant technical limitations.
|
||||
The dungeon variants only mix up dungeons and keep the rest of
|
||||
the overworld vanilla.
|
||||
''')
|
||||
parser.add_argument('--door_shuffle', default=defval('basic'), const='vanilla', nargs='?', choices=['vanilla', 'basic', 'crossed', 'experimental'],
|
||||
help='''\
|
||||
Select Door Shuffling Algorithm. (default: %(default)s)
|
||||
Basic: Doors are mixed within a single dungeon.
|
||||
(Not yet implemented)
|
||||
Crossed: Doors are mixed between all dungeons.
|
||||
(Not yet implemented)
|
||||
Vanilla: All doors are connected the same way they were in the
|
||||
base game.
|
||||
Experimental: Experimental mixes live here. Use at your own risk.
|
||||
''')
|
||||
parser.add_argument('--crystals_ganon', default=defval('7'), const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'],
|
||||
help='''\
|
||||
How many crystals are needed to defeat ganon. Any other
|
||||
requirements for ganon for the selected goal still apply.
|
||||
This setting does not apply when the all dungeons goal is
|
||||
selected. (default: %(default)s)
|
||||
Random: Picks a random value between 0 and 7 (inclusive).
|
||||
0-7: Number of crystals needed
|
||||
''')
|
||||
parser.add_argument('--crystals_gt', default=defval('7'), const='7', nargs='?', choices=['random', '0', '1', '2', '3', '4', '5', '6', '7'],
|
||||
help='''\
|
||||
How many crystals are needed to open GT. For inverted mode
|
||||
this applies to the castle tower door instead. (default: %(default)s)
|
||||
Random: Picks a random value between 0 and 7 (inclusive).
|
||||
0-7: Number of crystals needed
|
||||
''')
|
||||
parser.add_argument('--openpyramid', default=defval(False), help='''\
|
||||
Pre-opens the pyramid hole, this removes the Agahnim 2 requirement for it
|
||||
''', action='store_true')
|
||||
parser.add_argument('--rom', default=defval('Zelda no Densetsu - Kamigami no Triforce (Japan).sfc'), help='Path to an ALttP JAP(1.0) rom to use as a base.')
|
||||
parser.add_argument('--loglevel', default=defval('info'), const='info', nargs='?', choices=['error', 'info', 'warning', 'debug'], help='Select level of logging for output.')
|
||||
parser.add_argument('--seed', help='Define seed number to generate.', type=int)
|
||||
parser.add_argument('--count', help='''\
|
||||
Use to batch generate multiple seeds with same settings.
|
||||
If --seed is provided, it will be used for the first seed, then
|
||||
used to derive the next seed (i.e. generating 10 seeds with
|
||||
--seed given will produce the same 10 (different) roms each
|
||||
time).
|
||||
''', type=int)
|
||||
parser.add_argument('--fastmenu', default=defval('normal'), const='normal', nargs='?', choices=['normal', 'instant', 'double', 'triple', 'quadruple', 'half'],
|
||||
help='''\
|
||||
Select the rate at which the menu opens and closes.
|
||||
(default: %(default)s)
|
||||
''')
|
||||
parser.add_argument('--quickswap', default=defval(False), help='Enable quick item swapping with L and R.', action='store_true')
|
||||
parser.add_argument('--disablemusic', default=defval(False), help='Disables game music.', action='store_true')
|
||||
parser.add_argument('--mapshuffle', default=defval(False), help='Maps are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||
parser.add_argument('--compassshuffle', default=defval(False), help='Compasses are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||
parser.add_argument('--keyshuffle', default=defval(False), help='Small Keys are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||
parser.add_argument('--bigkeyshuffle', default=defval(False), help='Big Keys are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||
parser.add_argument('--keysanity', default=defval(False), help=argparse.SUPPRESS, action='store_true')
|
||||
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('--startinventory', default=defval(''), help='Specifies a list of items that will be in your starting inventory (separated by commas)')
|
||||
parser.add_argument('--custom', default=defval(False), help='Not supported.')
|
||||
parser.add_argument('--customitemarray', default=defval(False), help='Not supported.')
|
||||
parser.add_argument('--accessibility', default=defval('items'), const='items', nargs='?', choices=['items', 'locations', 'none'], help='''\
|
||||
Select Item/Location Accessibility. (default: %(default)s)
|
||||
Items: You can reach all unique inventory items. No guarantees about
|
||||
reaching all locations or all keys.
|
||||
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='''\
|
||||
If set, the Pyramid Hole and Ganon's Tower are not
|
||||
included entrance shuffle pool.
|
||||
''', action='store_false', dest='shuffleganon')
|
||||
parser.add_argument('--heartbeep', default=defval('normal'), const='normal', nargs='?', choices=['double', 'normal', 'half', 'quarter', 'off'],
|
||||
help='''\
|
||||
Select the rate at which the heart beep sound is played at
|
||||
low health. (default: %(default)s)
|
||||
''')
|
||||
parser.add_argument('--heartcolor', default=defval('red'), const='red', nargs='?', choices=['red', 'blue', 'green', 'yellow', 'random'],
|
||||
help='Select the color of Link\'s heart meter. (default: %(default)s)')
|
||||
parser.add_argument('--ow_palettes', default=defval('default'), choices=['default', 'random', 'blackout'])
|
||||
parser.add_argument('--uw_palettes', default=defval('default'), choices=['default', 'random', 'blackout'])
|
||||
parser.add_argument('--sprite', help='''\
|
||||
Path to a sprite sheet to use for Link. Needs to be in
|
||||
binary format and have a length of 0x7000 (28672) bytes,
|
||||
or 0x7078 (28792) bytes including palette data.
|
||||
Alternatively, can be a ALttP Rom patched with a Link
|
||||
sprite that will be extracted.
|
||||
''')
|
||||
parser.add_argument('--suppress_rom', help='Do not create an output rom file.', action='store_true')
|
||||
parser.add_argument('--gui', help='Launch the GUI', action='store_true')
|
||||
parser.add_argument('--jsonout', action='store_true', help='''\
|
||||
Output .json patch to stdout instead of a patched rom. Used
|
||||
for VT site integration, do not use otherwise.
|
||||
''')
|
||||
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'])
|
||||
parser.add_argument('--shuffleenemies', default=defval('none'), choices=['none', 'shuffled', 'chaos'])
|
||||
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('--remote_items', 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('--teams', default=defval(1), type=lambda value: max(int(value), 1))
|
||||
parser.add_argument('--outputpath')
|
||||
parser.add_argument('--race', default=defval(False), action='store_true')
|
||||
parser.add_argument('--outputname')
|
||||
|
||||
if multiargs.multi:
|
||||
for player in range(1, multiargs.multi + 1):
|
||||
parser.add_argument(f'--p{player}', default=defval(''), help=argparse.SUPPRESS)
|
||||
|
||||
ret = parser.parse_args(argv)
|
||||
if ret.keysanity:
|
||||
ret.mapshuffle, ret.compassshuffle, ret.keyshuffle, ret.bigkeyshuffle = [True] * 4
|
||||
|
||||
if multiargs.multi:
|
||||
defaults = copy.deepcopy(ret)
|
||||
for player in range(1, multiargs.multi + 1):
|
||||
playerargs = parse_arguments(shlex.split(getattr(ret,f"p{player}")), True)
|
||||
|
||||
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
|
||||
'shuffle', 'door_shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid',
|
||||
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
|
||||
'retro', 'accessibility', 'hints', 'beemizer',
|
||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
|
||||
'remote_items']:
|
||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||
if player == 1:
|
||||
setattr(ret, name, {1: value})
|
||||
else:
|
||||
getattr(ret, name)[player] = value
|
||||
|
||||
return ret
|
||||
|
||||
def get_working_dirs():
|
||||
# set default working dirs to same dir as script
|
||||
working_dirs = {
|
||||
"adjust.rom": os.path.join("."),
|
||||
"enemizer.cli": os.path.join(".","EnemizerCLI","EnemizerCLI.Core"),
|
||||
"multi.worlds": 1,
|
||||
"multi.names": "",
|
||||
"rom.base": os.path.join(".","Zelda no Densetsu - Kamigami no Triforce (Japan).sfc"),
|
||||
"gen.seed": "",
|
||||
"gen.count": 1,
|
||||
"outputpath": os.path.join("."),
|
||||
}
|
||||
if sys.platform.lower().find("windows"):
|
||||
working_dirs["enemizer.cli"] += ".exe"
|
||||
|
||||
# read saved working dirs file if it exists and set these
|
||||
working_dirs_path = os.path.join(".","resources","user","working_dirs.json")
|
||||
if os.path.exists(working_dirs_path):
|
||||
with(open(working_dirs_path)) as json_file:
|
||||
data = json.load(json_file)
|
||||
for k,v in data.items():
|
||||
working_dirs[k] = v
|
||||
return working_dirs
|
||||
133
gui/bottom.py
Normal file
133
gui/bottom.py
Normal file
@@ -0,0 +1,133 @@
|
||||
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, Spinbox, E, W, LEFT, RIGHT, X
|
||||
from argparse import Namespace
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
from CLI import parse_arguments, get_working_dirs
|
||||
from Main import main
|
||||
from Utils import local_path, output_path, open_file
|
||||
|
||||
def bottom_frame(self,parent,args=None):
|
||||
# working_dirs = get_working_dirs()
|
||||
|
||||
self = ttk.Frame(parent)
|
||||
seedCountFrame = Frame(self)
|
||||
seedCountFrame.pack()
|
||||
## Seed #
|
||||
seedLabel = Label(self, text='Seed #')
|
||||
# self.seedVar = StringVar(value=parent.working_dirs["gen.seed"])
|
||||
self.seedVar = StringVar()
|
||||
def saveSeed(caller,_,mode):
|
||||
pass
|
||||
# parent.working_dirs["gen.seed"] = self.seedVar.get()
|
||||
self.seedVar.trace_add("write",saveSeed)
|
||||
seedEntry = Entry(self, width=15, textvariable=self.seedVar)
|
||||
seedLabel.pack(side=LEFT)
|
||||
seedEntry.pack(side=LEFT)
|
||||
## Number of Generation attempts
|
||||
countLabel = Label(self, text='Count')
|
||||
# self.countVar = StringVar(value=working_dirs["gen.count"])
|
||||
self.countVar = StringVar()
|
||||
countSpinbox = Spinbox(self, from_=1, to=100, width=5, textvariable=self.countVar)
|
||||
countLabel.pack(side=LEFT)
|
||||
countSpinbox.pack(side=LEFT)
|
||||
|
||||
def generateRom():
|
||||
guiargs = Namespace()
|
||||
guiargs.multi = int(parent.multiworldWindow.worldVar.get())
|
||||
guiargs.names = parent.multiworldWindow.namesVar.get()
|
||||
guiargs.seed = int(parent.farBottomFrame.seedVar.get()) if parent.farBottomFrame.seedVar.get() else None
|
||||
guiargs.count = int(parent.farBottomFrame.countVar.get()) if parent.farBottomFrame.countVar.get() != '1' else None
|
||||
guiargs.mode = parent.itemWindow.modeVar.get()
|
||||
guiargs.logic = parent.itemWindow.logicVar.get()
|
||||
|
||||
guiargs.goal = parent.itemWindow.goalVar.get()
|
||||
guiargs.crystals_gt = parent.itemWindow.crystalsGTVar.get()
|
||||
guiargs.crystals_ganon = parent.itemWindow.crystalsGanonVar.get()
|
||||
guiargs.swords = parent.itemWindow.swordVar.get()
|
||||
guiargs.difficulty = parent.itemWindow.difficultyVar.get()
|
||||
guiargs.item_functionality = parent.itemWindow.itemfunctionVar.get()
|
||||
guiargs.timer = parent.itemWindow.timerVar.get()
|
||||
guiargs.progressive = parent.itemWindow.progressiveVar.get()
|
||||
guiargs.accessibility = parent.itemWindow.accessibilityVar.get()
|
||||
guiargs.algorithm = parent.itemWindow.algorithmVar.get()
|
||||
guiargs.shuffle = parent.entrandoWindow.shuffleVar.get()
|
||||
guiargs.door_shuffle = parent.dungeonRandoWindow.doorShuffleVar.get()
|
||||
guiargs.heartbeep = parent.gameOptionsWindow.heartbeepVar.get()
|
||||
guiargs.heartcolor = parent.gameOptionsWindow.heartcolorVar.get()
|
||||
guiargs.fastmenu = parent.gameOptionsWindow.fastMenuVar.get()
|
||||
guiargs.create_spoiler = bool(parent.generationSetupWindow.createSpoilerVar.get())
|
||||
guiargs.skip_playthrough = not bool(parent.generationSetupWindow.createSpoilerVar.get())
|
||||
guiargs.suppress_rom = bool(parent.generationSetupWindow.suppressRomVar.get())
|
||||
guiargs.openpyramid = bool(parent.entrandoWindow.openpyramidVar.get())
|
||||
guiargs.mapshuffle = bool(parent.dungeonRandoWindow.mapshuffleVar.get())
|
||||
guiargs.compassshuffle = bool(parent.dungeonRandoWindow.compassshuffleVar.get())
|
||||
guiargs.keyshuffle = bool(parent.dungeonRandoWindow.keyshuffleVar.get())
|
||||
guiargs.bigkeyshuffle = bool(parent.dungeonRandoWindow.bigkeyshuffleVar.get())
|
||||
guiargs.retro = bool(parent.itemWindow.retroVar.get())
|
||||
guiargs.quickswap = bool(parent.gameOptionsWindow.quickSwapVar.get())
|
||||
guiargs.disablemusic = bool(parent.gameOptionsWindow.disableMusicVar.get())
|
||||
guiargs.ow_palettes = parent.gameOptionsWindow.owPalettesVar.get()
|
||||
guiargs.uw_palettes = parent.gameOptionsWindow.uwPalettesVar.get()
|
||||
guiargs.shuffleganon = bool(parent.entrandoWindow.shuffleGanonVar.get())
|
||||
guiargs.hints = bool(parent.gameOptionsWindow.hintsVar.get())
|
||||
guiargs.enemizercli = parent.enemizerWindow.enemizerCLIpathVar.get()
|
||||
guiargs.shufflebosses = parent.enemizerWindow.enemizerBossVar.get()
|
||||
guiargs.shuffleenemies = parent.enemizerWindow.enemyShuffleVar.get()
|
||||
guiargs.enemy_health = parent.enemizerWindow.enemizerHealthVar.get()
|
||||
guiargs.enemy_damage = parent.enemizerWindow.enemizerDamageVar.get()
|
||||
guiargs.shufflepots = bool(parent.enemizerWindow.potShuffleVar.get())
|
||||
guiargs.custom = bool(parent.generationSetupWindow.customVar.get())
|
||||
guiargs.customitemarray = [int(parent.customWindow.bowVar.get()), int(parent.customWindow.silverarrowVar.get()), int(parent.customWindow.boomerangVar.get()), int(parent.customWindow.magicboomerangVar.get()), int(parent.customWindow.hookshotVar.get()), int(parent.customWindow.mushroomVar.get()), int(parent.customWindow.magicpowderVar.get()), int(parent.customWindow.firerodVar.get()),
|
||||
int(parent.customWindow.icerodVar.get()), int(parent.customWindow.bombosVar.get()), int(parent.customWindow.etherVar.get()), int(parent.customWindow.quakeVar.get()), int(parent.customWindow.lampVar.get()), int(parent.customWindow.hammerVar.get()), int(parent.customWindow.shovelVar.get()), int(parent.customWindow.fluteVar.get()), int(parent.customWindow.bugnetVar.get()),
|
||||
int(parent.customWindow.bookVar.get()), int(parent.customWindow.bottleVar.get()), int(parent.customWindow.somariaVar.get()), int(parent.customWindow.byrnaVar.get()), int(parent.customWindow.capeVar.get()), int(parent.customWindow.mirrorVar.get()), int(parent.customWindow.bootsVar.get()), int(parent.customWindow.powergloveVar.get()), int(parent.customWindow.titansmittVar.get()),
|
||||
int(parent.customWindow.proggloveVar.get()), int(parent.customWindow.flippersVar.get()), int(parent.customWindow.pearlVar.get()), int(parent.customWindow.heartpieceVar.get()), int(parent.customWindow.fullheartVar.get()), int(parent.customWindow.sancheartVar.get()), int(parent.customWindow.sword1Var.get()), int(parent.customWindow.sword2Var.get()),
|
||||
int(parent.customWindow.sword3Var.get()), int(parent.customWindow.sword4Var.get()), int(parent.customWindow.progswordVar.get()), int(parent.customWindow.shield1Var.get()), int(parent.customWindow.shield2Var.get()), int(parent.customWindow.shield3Var.get()), int(parent.customWindow.progshieldVar.get()), int(parent.customWindow.bluemailVar.get()),
|
||||
int(parent.customWindow.redmailVar.get()), int(parent.customWindow.progmailVar.get()), int(parent.customWindow.halfmagicVar.get()), int(parent.customWindow.quartermagicVar.get()), int(parent.customWindow.bcap5Var.get()), int(parent.customWindow.bcap10Var.get()), int(parent.customWindow.acap5Var.get()), int(parent.customWindow.acap10Var.get()),
|
||||
int(parent.customWindow.arrow1Var.get()), int(parent.customWindow.arrow10Var.get()), int(parent.customWindow.bomb1Var.get()), int(parent.customWindow.bomb3Var.get()), int(parent.customWindow.rupee1Var.get()), int(parent.customWindow.rupee5Var.get()), int(parent.customWindow.rupee20Var.get()), int(parent.customWindow.rupee50Var.get()), int(parent.customWindow.rupee100Var.get()),
|
||||
int(parent.customWindow.rupee300Var.get()), int(parent.customWindow.rupoorVar.get()), int(parent.customWindow.blueclockVar.get()), int(parent.customWindow.greenclockVar.get()), int(parent.customWindow.redclockVar.get()), int(parent.customWindow.progbowVar.get()), int(parent.customWindow.bomb10Var.get()), int(parent.customWindow.triforcepieceVar.get()),
|
||||
int(parent.customWindow.triforcecountVar.get()), int(parent.customWindow.triforceVar.get()), int(parent.customWindow.rupoorcostVar.get()), int(parent.customWindow.universalkeyVar.get())]
|
||||
guiargs.rom = parent.generationSetupWindow.romVar.get()
|
||||
# guiargs.sprite = parent.gameOptionsWindow.sprite
|
||||
guiargs.outputpath = args.outputpath if args else None
|
||||
# get default values for missing parameters
|
||||
for k,v in vars(parse_arguments(['--multi', str(guiargs.multi)])).items():
|
||||
if k not in vars(guiargs):
|
||||
setattr(guiargs, k, v)
|
||||
elif type(v) is dict: # use same settings for every player
|
||||
setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, guiargs.multi + 1)})
|
||||
try:
|
||||
if guiargs.count is not None:
|
||||
seed = guiargs.seed
|
||||
for _ in range(guiargs.count):
|
||||
main(seed=seed, args=guiargs)
|
||||
seed = random.randint(0, 999999999)
|
||||
else:
|
||||
main(seed=guiargs.seed, args=guiargs)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
else:
|
||||
messagebox.showinfo(title="Success", message="Rom patched successfully")
|
||||
|
||||
## Generate Button
|
||||
generateButton = Button(self, text='Generate Patched Rom', command=generateRom)
|
||||
generateButton.pack(side=LEFT)
|
||||
|
||||
def open_output():
|
||||
if args and args.outputpath:
|
||||
open_file(output_path(args.outputpath))
|
||||
else:
|
||||
open_file(output_path("."))
|
||||
# open_file(output_path(working_dirs["outputpath"]))
|
||||
|
||||
openOutputButton = Button(self, text='Open Output Directory', command=open_output)
|
||||
openOutputButton.pack(side=RIGHT)
|
||||
|
||||
if os.path.exists(local_path('README.html')):
|
||||
def open_readme():
|
||||
open_file(local_path('README.html'))
|
||||
openReadmeButton = Button(self, text='Open Documentation', command=open_readme)
|
||||
openReadmeButton.pack()
|
||||
|
||||
return self
|
||||
Reference in New Issue
Block a user