Document stuff, add a couple things
Add Retro World State (Open & Retro on) Add SpriteSomething plug to sprite selector Fix Custom Item Pool loading to use disct instead of list
This commit is contained in:
@@ -73,6 +73,10 @@ class World(object):
|
||||
self.key_layout = defaultdict(dict)
|
||||
|
||||
for player in range(1, players + 1):
|
||||
# If World State is Retro, set to Open and set Retro flag
|
||||
if self.mode[player] == "retro":
|
||||
self.mode[player] = "open"
|
||||
self.retro[player] = True
|
||||
def set_player_attr(attr, val):
|
||||
self.__dict__.setdefault(attr, {})[player] = val
|
||||
set_player_attr('_region_cache', {})
|
||||
|
||||
9
CLI.py
9
CLI.py
@@ -9,8 +9,6 @@ import shlex
|
||||
import sys
|
||||
|
||||
from Main import main
|
||||
from Utils import is_bundled, close_console
|
||||
from Fill import FillError
|
||||
|
||||
import classes.constants as CONST
|
||||
|
||||
@@ -185,7 +183,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||
Crossed: Doors are mixed between all dungeons.
|
||||
(Not yet implemented)
|
||||
Vanilla: All doors are connected the same way they were in the
|
||||
base game.
|
||||
base game.
|
||||
''')
|
||||
parser.add_argument('--experimental', default=defval(settings["experimental"] != 0), help='Enable experimental features', action='store_true')
|
||||
parser.add_argument('--dungeon_counters', default=defval(settings["dungeon_counters"]), help='Enable dungeon chest counters', const='off', nargs='?', choices=['off', 'on', 'pickup'])
|
||||
@@ -477,7 +475,10 @@ def get_settings():
|
||||
settings[k] = v
|
||||
return settings
|
||||
|
||||
|
||||
# Priority fallback is:
|
||||
# 1: CLI
|
||||
# 2: Settings file
|
||||
# 3: Canned defaults
|
||||
def get_args_priority(settings_args, gui_args, cli_args):
|
||||
args = {}
|
||||
args["settings"] = get_settings() if settings_args is None else settings_args
|
||||
|
||||
7
Gui.py
7
Gui.py
@@ -4,8 +4,7 @@ import os
|
||||
import sys
|
||||
from tkinter import Tk, Button, BOTTOM, TOP, StringVar, BooleanVar, X, BOTH, RIGHT, ttk, messagebox
|
||||
|
||||
from argparse import Namespace
|
||||
from CLI import get_settings, get_args_priority
|
||||
from CLI import get_args_priority
|
||||
from DungeonRandomizer import parse_arguments
|
||||
from gui.adjust.overview import adjust_page
|
||||
from gui.startinventory.overview import startinventory_page
|
||||
@@ -24,6 +23,7 @@ from Main import __version__ as ESVersion
|
||||
|
||||
|
||||
def guiMain(args=None):
|
||||
# Save settings to file
|
||||
def save_settings(args):
|
||||
user_resources_path = os.path.join(".", "resources", "user")
|
||||
settings_path = os.path.join(user_resources_path)
|
||||
@@ -35,6 +35,7 @@ def guiMain(args=None):
|
||||
f.write(json.dumps(args, indent=2))
|
||||
os.chmod(os.path.join(settings_path, "settings.json"),0o755)
|
||||
|
||||
# Save settings from GUI
|
||||
def save_settings_from_gui(confirm):
|
||||
gui_args = vars(create_guiargs(self))
|
||||
if self.randomSprite.get():
|
||||
@@ -83,6 +84,7 @@ def guiMain(args=None):
|
||||
# make array for frames
|
||||
self.frames = {}
|
||||
|
||||
# make pages for each section
|
||||
self.notebook = ttk.Notebook(self)
|
||||
self.pages["randomizer"] = ttk.Frame(self.notebook)
|
||||
self.pages["adjust"] = ttk.Frame(self.notebook)
|
||||
@@ -178,6 +180,7 @@ def guiMain(args=None):
|
||||
# load adjust settings into options
|
||||
loadadjustargs(self, self.settings)
|
||||
|
||||
# run main window
|
||||
mainWindow.mainloop()
|
||||
|
||||
|
||||
|
||||
32
ItemList.py
32
ItemList.py
@@ -126,6 +126,7 @@ difficulties = {
|
||||
),
|
||||
}
|
||||
|
||||
# Translate between Mike's label array and YAML/JSON keys
|
||||
def get_custom_array_key(item):
|
||||
label_switcher = {
|
||||
"silverarrow": "silversupgrade",
|
||||
@@ -264,10 +265,10 @@ def generate_itempool(world, player):
|
||||
if player in world.pool_adjustment.keys():
|
||||
amt = world.pool_adjustment[player]
|
||||
if amt < 0:
|
||||
for i in range(0, amt):
|
||||
for _ in range(0, amt):
|
||||
pool.remove('Rupees (20)')
|
||||
elif amt > 0:
|
||||
for i in range(0, amt):
|
||||
for _ in range(0, amt):
|
||||
pool.append('Rupees (20)')
|
||||
|
||||
for item in precollected_items:
|
||||
@@ -707,24 +708,25 @@ def test():
|
||||
for difficulty in ['normal', 'hard', 'expert']:
|
||||
for goal in ['ganon', 'triforcehunt', 'pedestal']:
|
||||
for timer in ['none', 'display', 'timed', 'timed-ohko', 'ohko', 'timed-countdown']:
|
||||
for mode in ['open', 'standard', 'inverted']:
|
||||
for mode in ['open', 'standard', 'inverted', 'retro']:
|
||||
for swords in ['random', 'assured', 'swordless', 'vanilla']:
|
||||
for progressive in ['on', 'off']:
|
||||
for shuffle in ['full', 'insanity_legacy']:
|
||||
for retro in [True, False]:
|
||||
out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro)
|
||||
count = len(out[0]) + len(out[1])
|
||||
for door_shuffle in ['basic', 'crossed', 'vanilla']:
|
||||
out = get_pool_core(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, door_shuffle)
|
||||
count = len(out[0]) + len(out[1])
|
||||
|
||||
correct_count = total_items_to_place
|
||||
if goal == 'pedestal' and swords != 'vanilla':
|
||||
# pedestal goals generate one extra item
|
||||
correct_count += 1
|
||||
if retro:
|
||||
correct_count += 28
|
||||
try:
|
||||
assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro))
|
||||
except AssertionError as e:
|
||||
print(e)
|
||||
correct_count = total_items_to_place
|
||||
if goal == 'pedestal' and swords != 'vanilla':
|
||||
# pedestal goals generate one extra item
|
||||
correct_count += 1
|
||||
if retro:
|
||||
correct_count += 28
|
||||
try:
|
||||
assert count == correct_count, "expected {0} items but found {1} items for {2}".format(correct_count, count, (progressive, shuffle, difficulty, timer, goal, mode, swords, retro))
|
||||
except AssertionError as e:
|
||||
print(e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
|
||||
5
Main.py
5
Main.py
@@ -77,7 +77,8 @@ def main(args, seed=None):
|
||||
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
|
||||
|
||||
if world.mode[player] == 'standard' and world.enemy_shuffle[player] != 'none':
|
||||
world.escape_assist[player].append('bombs') # enemized escape assumes infinite bombs available and will likely be unbeatable without it
|
||||
if hasattr(world,"escape_assist") and player in world.escape_assist:
|
||||
world.escape_assist[player].append('bombs') # enemized escape assumes infinite bombs available and will likely be unbeatable without it
|
||||
|
||||
for tok in filter(None, args.startinventory[player].split(',')):
|
||||
item = ItemFactory(tok.strip(), player)
|
||||
@@ -383,7 +384,7 @@ def copy_dynamic_regions_and_locations(world, ret):
|
||||
new_loc.always_allow = location.always_allow
|
||||
new_loc.item_rule = location.item_rule
|
||||
new_reg.locations.append(new_loc)
|
||||
|
||||
|
||||
ret.clear_location_cache()
|
||||
|
||||
|
||||
|
||||
@@ -2,16 +2,20 @@ import subprocess
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Destination is current dir
|
||||
DEST_DIRECTORY = '.'
|
||||
|
||||
# Check for UPX
|
||||
if os.path.isdir("upx"):
|
||||
upx_string = "--upx-dir=upx"
|
||||
else:
|
||||
upx_string = ""
|
||||
|
||||
# Nuke Build dir
|
||||
if os.path.isdir("build"):
|
||||
shutil.rmtree("build")
|
||||
|
||||
# Run pyinstaller for DungeonRandomizer
|
||||
subprocess.run(" ".join(["pyinstaller DungeonRandomizer.spec ",
|
||||
upx_string,
|
||||
"-y ",
|
||||
|
||||
@@ -2,16 +2,20 @@ import subprocess
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Destination is current dir
|
||||
DEST_DIRECTORY = '.'
|
||||
|
||||
# Check for UPX
|
||||
if os.path.isdir("upx"):
|
||||
upx_string = "--upx-dir=upx"
|
||||
else:
|
||||
upx_string = ""
|
||||
|
||||
# Nuke Build dir
|
||||
if os.path.isdir("build"):
|
||||
shutil.rmtree("build")
|
||||
|
||||
# Run pyinstaller for Gui
|
||||
subprocess.run(" ".join(["pyinstaller Gui.spec ",
|
||||
upx_string,
|
||||
"-y ",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import filedialog, messagebox, Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, ALL, NSEW, LEFT, BOTTOM, X, RIGHT, TOP, HORIZONTAL, EW, NS
|
||||
from tkinter import filedialog, messagebox, Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, ALL, LEFT, BOTTOM, X, RIGHT, TOP, EW, NS
|
||||
from glob import glob
|
||||
import json
|
||||
import os
|
||||
@@ -34,6 +34,7 @@ class SpriteSelector(object):
|
||||
def open_unofficial_sprite_dir(_evt):
|
||||
open_file(self.unofficial_sprite_dir)
|
||||
|
||||
# Open SpriteSomething directory for Link sprites
|
||||
def open_spritesomething_listing(_evt):
|
||||
webbrowser.open("https://artheau.github.io/SpriteSomething/?mode=zelda3/link")
|
||||
|
||||
@@ -50,6 +51,7 @@ class SpriteSelector(object):
|
||||
unofficial_title_text.pack(side=LEFT)
|
||||
unofficial_title_link.pack(side=LEFT)
|
||||
unofficial_title_link.bind("<Button-1>", open_unofficial_sprite_dir)
|
||||
# Include hyperlink to SpriteSomething directory for Link sprites
|
||||
spritesomething_title_link = Label(unofficial_frametitle, text="(SpriteSomething)", fg="blue", cursor="hand2")
|
||||
spritesomething_title_link.pack(side=LEFT)
|
||||
spritesomething_title_link.bind("<Button-1>", open_spritesomething_listing)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Ordered list of items in Custom Item Pool page and Starting Inventory page
|
||||
CUSTOMITEMS = [
|
||||
"bow", "progressivebow", "boomerang", "redmerang", "hookshot",
|
||||
"mushroom", "powder", "firerod", "icerod", "bombos",
|
||||
@@ -20,11 +21,13 @@ CUSTOMITEMS = [
|
||||
"rupoorcost"
|
||||
]
|
||||
|
||||
# These can't be in the Starting Inventory page
|
||||
CANTSTARTWITH = [
|
||||
"triforcepiecesgoal", "triforce", "rupoor",
|
||||
"rupoorcost"
|
||||
]
|
||||
|
||||
# In the same order as CUSTOMITEMS, these are Pretty Labels for each option
|
||||
CUSTOMITEMLABELS = [
|
||||
"Bow", "Progressive Bow", "Blue Boomerang", "Red Boomerang", "Hookshot",
|
||||
"Mushroom", "Magic Powder", "Fire Rod", "Ice Rod", "Bombos",
|
||||
@@ -33,7 +36,7 @@ CUSTOMITEMLABELS = [
|
||||
"Ocarina", "Bug Catching Net", "Book of Mudora", "Bottle", "Cane of Somaria",
|
||||
"Cane of Byrna", "Magic Cape", "Magic Mirror", "Pegasus Boots", "Power Glove",
|
||||
"Titans Mitts", "Progressive Glove", "Flippers", "Moon Pearl", "Piece of Heart",
|
||||
|
||||
|
||||
"Boss Heart Container", "Sanctuary Heart Container", "Fighter Sword", "Master Sword", "Tempered Sword",
|
||||
"Golden Sword", "Progressive Sword", "Blue Shield", "Red Shield", "Mirror Shield",
|
||||
"Progressive Shield", "Blue Mail", "Red Mail", "Progressive Armor", "Magic Upgrade (1/2)",
|
||||
@@ -47,6 +50,8 @@ CUSTOMITEMLABELS = [
|
||||
"Rupoor Cost"
|
||||
]
|
||||
|
||||
# Stuff on each page to save, according to internal names as defined by the widgets definitions
|
||||
# and how it eventually translates to YAML/JSON weight files
|
||||
SETTINGSTOPROCESS = {
|
||||
"randomizer": {
|
||||
"item": {
|
||||
@@ -104,6 +109,6 @@ SETTINGSTOPROCESS = {
|
||||
"usestartinventory": "usestartinventory",
|
||||
"usecustompool": "custom",
|
||||
"saveonexit": "saveonexit"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, filedialog, messagebox, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, OptionMenu, E, W, LEFT, RIGHT, X, BOTTOM
|
||||
from tkinter import ttk, filedialog, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X, BOTTOM
|
||||
from AdjusterMain import adjust
|
||||
from argparse import Namespace
|
||||
from classes.SpriteSelector import SpriteSelector
|
||||
@@ -19,6 +19,7 @@ def adjust_page(top, parent, settings):
|
||||
self.frames["checkboxes"] = Frame(self)
|
||||
self.frames["checkboxes"].pack(anchor=W)
|
||||
|
||||
# Adjust option frames
|
||||
self.frames["selectOptionsFrame"] = Frame(self)
|
||||
self.frames["leftAdjustFrame"] = Frame(self.frames["selectOptionsFrame"])
|
||||
self.frames["rightAdjustFrame"] = Frame(self.frames["selectOptionsFrame"])
|
||||
@@ -28,6 +29,8 @@ def adjust_page(top, parent, settings):
|
||||
self.frames["rightAdjustFrame"].pack(side=RIGHT)
|
||||
self.frames["bottomAdjustFrame"].pack(fill=X)
|
||||
|
||||
# Load Adjust option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
with open(os.path.join("resources","app","gui","adjust","overview","widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
@@ -40,6 +43,7 @@ def adjust_page(top, parent, settings):
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
# Sprite Selection
|
||||
# This one's more-complicated, build it and stuff it
|
||||
self.spriteNameVar2 = StringVar()
|
||||
spriteDialogFrame2 = Frame(self.frames["leftAdjustFrame"])
|
||||
baseSpriteLabel2 = Label(spriteDialogFrame2, text='Sprite:')
|
||||
@@ -65,6 +69,8 @@ def adjust_page(top, parent, settings):
|
||||
spriteSelectButton2.pack(side=LEFT)
|
||||
spriteDialogFrame2.pack(anchor=E)
|
||||
|
||||
# Path to game file to Adjust
|
||||
# This one's more-complicated, build it and stuff it
|
||||
adjustRomFrame = Frame(self.frames["bottomAdjustFrame"])
|
||||
adjustRomLabel = Label(adjustRomFrame, text='Rom to adjust: ')
|
||||
self.romVar2 = StringVar(value=settings["rom"])
|
||||
@@ -82,6 +88,7 @@ def adjust_page(top, parent, settings):
|
||||
romSelectButton2.pack(side=LEFT)
|
||||
adjustRomFrame.pack(fill=X)
|
||||
|
||||
# These are the options to Adjust
|
||||
def adjustRom():
|
||||
options = {
|
||||
"heartbeep": "heartbeep",
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, Spinbox, E, W, LEFT, RIGHT, X
|
||||
from tkinter import ttk, messagebox, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT, X
|
||||
from argparse import Namespace
|
||||
from functools import partial
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
from CLI import parse_arguments, get_settings
|
||||
from CLI import parse_arguments
|
||||
from Main import main
|
||||
from Utils import local_path, output_path, open_file
|
||||
import classes.constants as CONST
|
||||
@@ -97,22 +96,35 @@ def create_guiargs(parent):
|
||||
# Page::Subpage::GUI-id::param-id
|
||||
options = CONST.SETTINGSTOPROCESS
|
||||
|
||||
# Cycle through each page
|
||||
for mainpage in options:
|
||||
# Cycle through each subpage (in case of Item Randomizer)
|
||||
for subpage in options[mainpage]:
|
||||
# Cycle through each widget
|
||||
for widget in options[mainpage][subpage]:
|
||||
# Get the value and set it
|
||||
arg = options[mainpage][subpage][widget]
|
||||
setattr(guiargs, arg, parent.pages[mainpage].pages[subpage].widgets[widget].storageVar.get())
|
||||
|
||||
# Get EnemizerCLI setting
|
||||
guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].enemizerCLIpathVar.get()
|
||||
|
||||
# Get Multiworld Worlds count
|
||||
guiargs.multi = int(parent.pages["randomizer"].pages["multiworld"].widgets["worlds"].storageVar.get())
|
||||
|
||||
# Get baserom path
|
||||
guiargs.rom = parent.pages["randomizer"].pages["generation"].romVar.get()
|
||||
|
||||
# Get if we're using the Custom Item Pool
|
||||
guiargs.custom = bool(parent.pages["randomizer"].pages["generation"].widgets["usecustompool"].storageVar.get())
|
||||
|
||||
# Get Seed ID
|
||||
guiargs.seed = int(parent.frames["bottom"].seedVar.get()) if parent.frames["bottom"].seedVar.get() else None
|
||||
|
||||
# Get number of generations to run
|
||||
guiargs.count = int(parent.frames["bottom"].widgets["generationcount"].storageVar.get()) if parent.frames["bottom"].widgets["generationcount"].storageVar.get() != '1' else None
|
||||
|
||||
# Get Adjust settings
|
||||
adjustargs = {
|
||||
"nobgm": "disablemusic",
|
||||
"quickswap": "quickswap",
|
||||
@@ -126,22 +138,29 @@ def create_guiargs(parent):
|
||||
internal = adjustargs[adjustarg]
|
||||
setattr(guiargs,"adjust." + internal, parent.pages["adjust"].content.widgets[adjustarg].storageVar.get())
|
||||
|
||||
# Get Custom Items and Starting Inventory Items
|
||||
customitems = CONST.CUSTOMITEMS
|
||||
guiargs.startinventory = []
|
||||
guiargs.customitemarray = {}
|
||||
guiargs.startinventoryarray = {}
|
||||
for customitem in customitems:
|
||||
if customitem not in ["triforcepiecesgoal", "triforce", "rupoor", "rupoorcost"]:
|
||||
if customitem not in CONST.CANTSTARTWITH:
|
||||
# Starting Inventory is a CSV
|
||||
amount = int(parent.pages["startinventory"].content.startingWidgets[customitem].storageVar.get())
|
||||
guiargs.startinventoryarray[customitem] = amount
|
||||
for i in range(0, amount):
|
||||
for _ in range(0, amount):
|
||||
label = CONST.CUSTOMITEMLABELS[customitems.index(customitem)]
|
||||
guiargs.startinventory.append(label)
|
||||
# Custom Item Pool is a dict of ints
|
||||
guiargs.customitemarray[customitem] = int(parent.pages["custom"].content.customWidgets[customitem].storageVar.get())
|
||||
|
||||
# Starting Inventory is a CSV
|
||||
guiargs.startinventory = ','.join(guiargs.startinventory)
|
||||
|
||||
# Get Sprite Selection (set or random)
|
||||
guiargs.sprite = parent.pages["randomizer"].pages["gameoptions"].widgets["sprite"]["spriteObject"]
|
||||
guiargs.randomSprite = parent.randomSprite.get()
|
||||
|
||||
# Get output path
|
||||
guiargs.outputpath = parent.outputPath.get()
|
||||
return guiargs
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
from tkinter import ttk, Frame, N, LEFT, VERTICAL, Y
|
||||
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
|
||||
import classes.constants as CONST
|
||||
|
||||
|
||||
def custom_page(top, parent):
|
||||
def custom_page(top,parent):
|
||||
# Custom Item Pool
|
||||
self = ttk.Frame(parent)
|
||||
|
||||
# Create uniform list columns
|
||||
def create_list_frame(parent, framename):
|
||||
parent.frames[framename] = Frame(parent)
|
||||
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
|
||||
parent.frames[framename].thisRow = 0
|
||||
parent.frames[framename].thisCol = 0
|
||||
|
||||
# Create a vertical rule to help with splitting columns visually
|
||||
def create_vertical_rule(num=1):
|
||||
for i in range(0,num):
|
||||
for _ in range(0,num):
|
||||
ttk.Separator(self, orient=VERTICAL).pack(side=LEFT, anchor=N, fill=Y)
|
||||
|
||||
# This was in here, I have no idea what it was but I left it just in case: MikeT
|
||||
def validation(P):
|
||||
if str.isdigit(P) or P == "":
|
||||
return True
|
||||
@@ -32,6 +34,7 @@ def custom_page(top, parent):
|
||||
|
||||
# Custom Item Pool option sections
|
||||
self.frames = {}
|
||||
# Create 5 columns with 2 vertical rules in between each
|
||||
create_list_frame(self, "itemList1")
|
||||
create_vertical_rule(2)
|
||||
create_list_frame(self, "itemList2")
|
||||
@@ -42,6 +45,8 @@ def custom_page(top, parent):
|
||||
create_vertical_rule(2)
|
||||
create_list_frame(self, "itemList5")
|
||||
|
||||
# Load Custom option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
with open(os.path.join("resources", "app", "gui", "custom", "overview", "widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
@@ -49,7 +54,8 @@ def custom_page(top, parent):
|
||||
for key in dictWidgets:
|
||||
self.customWidgets[key] = dictWidgets[key]
|
||||
|
||||
for i, key in enumerate(CONST.CUSTOMITEMS):
|
||||
self.customWidgets[key].storageVar.set(top.settings["customitemarray"][i])
|
||||
# Load Custom Item Pool settings from settings file
|
||||
for key in CONST.CUSTOMITEMS:
|
||||
self.customWidgets[key].storageVar.set(top.settings["customitemarray"][key])
|
||||
|
||||
return self
|
||||
|
||||
@@ -3,6 +3,7 @@ from gui.randomize.gameoptions import set_sprite
|
||||
from Rom import Sprite, get_sprite_from_name
|
||||
import classes.constants as CONST
|
||||
|
||||
# Load args/settings for most tabs
|
||||
def loadcliargs(gui, args, settings=None):
|
||||
if args is not None:
|
||||
# for k, v in vars(args).items():
|
||||
@@ -14,28 +15,47 @@ def loadcliargs(gui, args, settings=None):
|
||||
# Page::Subpage::GUI-id::param-id
|
||||
options = CONST.SETTINGSTOPROCESS
|
||||
|
||||
# Cycle through each page
|
||||
for mainpage in options:
|
||||
# Cycle through each subpage (in case of Item Randomizer)
|
||||
for subpage in options[mainpage]:
|
||||
# Cycle through each widget
|
||||
for widget in options[mainpage][subpage]:
|
||||
# Get the value and set it
|
||||
arg = options[mainpage][subpage][widget]
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].storageVar.set(args[arg])
|
||||
# If we're on the Game Options page and it's not about Hints
|
||||
if subpage == "gameoptions" and not widget == "hints":
|
||||
# Check if we've got settings
|
||||
# Check if we've got the widget in Adjust settings
|
||||
hasSettings = settings is not None
|
||||
hasWidget = ("adjust." + widget) in settings if hasSettings else None
|
||||
if hasWidget is None:
|
||||
# If we've got a Game Options val and we don't have an Adjust val, use the Game Options val
|
||||
gui.pages["adjust"].content.widgets[widget].storageVar.set(args[arg])
|
||||
|
||||
# Get EnemizerCLI setting
|
||||
gui.pages["randomizer"].pages["enemizer"].enemizerCLIpathVar.set(args["enemizercli"])
|
||||
|
||||
# Get baserom path
|
||||
gui.pages["randomizer"].pages["generation"].romVar.set(args["rom"])
|
||||
|
||||
# Get Multiworld Worlds count
|
||||
if args["multi"]:
|
||||
gui.pages["randomizer"].pages["multiworld"].widgets["worlds"].storageVar.set(str(args["multi"]))
|
||||
|
||||
# Get Seed ID
|
||||
if args["seed"]:
|
||||
gui.frames["bottom"].seedVar.set(str(args["seed"]))
|
||||
|
||||
# Get number of generations to run
|
||||
if args["count"]:
|
||||
gui.frames["bottom"].widgets["generationcount"].storageVar.set(str(args["count"]))
|
||||
|
||||
# Get output path
|
||||
gui.outputPath.set(args["outputpath"])
|
||||
|
||||
# Figure out Sprite Selection
|
||||
def sprite_setter(spriteObject):
|
||||
gui.pages["randomizer"].pages["gameoptions"].widgets["sprite"]["spriteObject"] = spriteObject
|
||||
if args["sprite"] is not None:
|
||||
@@ -52,6 +72,7 @@ def loadcliargs(gui, args, settings=None):
|
||||
spriteNameVar=gui.pages["adjust"].content.spriteNameVar2,
|
||||
randomSpriteVar=gui.randomSprite)
|
||||
|
||||
# Load args/settings for Adjust tab
|
||||
def loadadjustargs(gui, settings):
|
||||
options = {
|
||||
"adjust": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
|
||||
from tkinter import ttk, Frame, Label, E, W, LEFT, RIGHT
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -19,6 +19,9 @@ def dungeon_page(parent):
|
||||
mscbLabel = Label(self.frames["keysanity"], text="Shuffle: ")
|
||||
mscbLabel.pack(side=LEFT)
|
||||
|
||||
# Load Dungeon Shuffle option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
# This first set goes in the Keysanity frame
|
||||
with open(os.path.join("resources","app","gui","randomize","dungeon","keysanity.json")) as keysanityItems:
|
||||
myDict = json.load(keysanityItems)
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["keysanity"])
|
||||
@@ -26,6 +29,7 @@ def dungeon_page(parent):
|
||||
self.widgets[key] = dictWidgets[key]
|
||||
self.widgets[key].pack(side=LEFT)
|
||||
|
||||
# These get split left & right
|
||||
self.frames["widgets"] = Frame(self)
|
||||
self.frames["widgets"].pack(anchor=W)
|
||||
with open(os.path.join("resources","app","gui","randomize","dungeon","widgets.json")) as dungeonWidgets:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
from tkinter import ttk, filedialog, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, LabelFrame, OptionMenu, N, E, W, LEFT, RIGHT, BOTTOM, X
|
||||
from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, N, E, W, LEFT, RIGHT, BOTTOM, X
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -18,6 +18,7 @@ def enemizer_page(parent,settings):
|
||||
# Enemizer option sections
|
||||
self.frames = {}
|
||||
|
||||
# Enemizer option frames
|
||||
self.frames["checkboxes"] = Frame(self)
|
||||
self.frames["checkboxes"].pack(anchor=W)
|
||||
|
||||
@@ -30,6 +31,9 @@ def enemizer_page(parent,settings):
|
||||
self.frames["rightEnemizerFrame"].pack(side=RIGHT)
|
||||
self.frames["bottomEnemizerFrame"].pack(fill=X)
|
||||
|
||||
# Load Enemizer option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
# These get split left & right
|
||||
with open(os.path.join("resources","app","gui","randomize","enemizer","widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
@@ -42,6 +46,7 @@ def enemizer_page(parent,settings):
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
## Enemizer CLI Path
|
||||
# This one's more-complicated, build it and stuff it
|
||||
enemizerPathFrame = Frame(self.frames["bottomEnemizerFrame"])
|
||||
enemizerCLIlabel = Label(enemizerPathFrame, text="EnemizerCLI path: ")
|
||||
enemizerCLIlabel.pack(side=LEFT)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
|
||||
from tkinter import ttk, Frame, E, W, LEFT, RIGHT
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -15,6 +15,11 @@ def entrando_page(parent):
|
||||
self.frames["widgets"] = Frame(self)
|
||||
self.frames["widgets"].pack(anchor=W)
|
||||
|
||||
# Load Entrance Randomizer option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
# Checkboxes go West
|
||||
# Everything else goes East
|
||||
# They also get split left & right
|
||||
with open(os.path.join("resources","app","gui","randomize","entrando","widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
|
||||
from tkinter import ttk, StringVar, Button, Entry, Frame, Label, E, W, LEFT, RIGHT
|
||||
from functools import partial
|
||||
import classes.SpriteSelector as spriteSelector
|
||||
import gui.widgets as widgets
|
||||
@@ -17,11 +17,17 @@ def gameoptions_page(top, parent):
|
||||
self.frames["checkboxes"] = Frame(self)
|
||||
self.frames["checkboxes"].pack(anchor=W)
|
||||
|
||||
# Game Options frames
|
||||
self.frames["leftRomOptionsFrame"] = Frame(self)
|
||||
self.frames["rightRomOptionsFrame"] = Frame(self)
|
||||
self.frames["leftRomOptionsFrame"].pack(side=LEFT)
|
||||
self.frames["rightRomOptionsFrame"].pack(side=RIGHT)
|
||||
|
||||
# Load Game Options widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
# Checkboxes go West
|
||||
# Everything else goes East
|
||||
# They also get split left & right
|
||||
with open(os.path.join("resources","app","gui","randomize","gameoptions","widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
@@ -34,6 +40,7 @@ def gameoptions_page(top, parent):
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
## Sprite selection
|
||||
# This one's more-complicated, build it and stuff it
|
||||
spriteDialogFrame = Frame(self.frames["leftRomOptionsFrame"])
|
||||
baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:')
|
||||
|
||||
@@ -75,4 +82,3 @@ def set_sprite(sprite_param, random_sprite=False, spriteSetter=None, spriteNameV
|
||||
spriteNameVar.set(sprite_param.name)
|
||||
if randomSpriteVar:
|
||||
randomSpriteVar.set(random_sprite)
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
from tkinter import ttk, filedialog, IntVar, StringVar, Button, Checkbutton, Entry, Frame, Label, E, W, LEFT, RIGHT, X
|
||||
from tkinter import ttk, filedialog, StringVar, Button, Entry, Frame, Label, E, W, LEFT, X
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -16,6 +15,8 @@ def generation_page(parent,settings):
|
||||
self.frames["checkboxes"] = Frame(self)
|
||||
self.frames["checkboxes"].pack(anchor=W)
|
||||
|
||||
# Load Generation Setup option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
with open(os.path.join("resources","app","gui","randomize","generation","checkboxes.json")) as checkboxes:
|
||||
myDict = json.load(checkboxes)
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["checkboxes"])
|
||||
@@ -26,6 +27,7 @@ def generation_page(parent,settings):
|
||||
self.frames["baserom"] = Frame(self)
|
||||
self.frames["baserom"].pack(anchor=W, fill=X)
|
||||
## Locate base ROM
|
||||
# This one's more-complicated, build it and stuff it
|
||||
baseRomFrame = Frame(self.frames["baserom"])
|
||||
baseRomLabel = Label(baseRomFrame, text='Base Rom: ')
|
||||
self.romVar = StringVar()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from tkinter import ttk, IntVar, StringVar, Checkbutton, Frame, Label, OptionMenu, E, W, LEFT, RIGHT
|
||||
from tkinter import ttk, Frame, E, W, LEFT, RIGHT
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def item_page(parent):
|
||||
# Item Randomizer
|
||||
self = ttk.Frame(parent)
|
||||
@@ -13,6 +13,7 @@ def item_page(parent):
|
||||
# Item Randomizer option sections
|
||||
self.frames = {}
|
||||
|
||||
# Item Randomizer option frames
|
||||
self.frames["checkboxes"] = Frame(self)
|
||||
self.frames["checkboxes"].pack(anchor=W)
|
||||
|
||||
@@ -21,6 +22,10 @@ def item_page(parent):
|
||||
self.frames["leftItemFrame"].pack(side=LEFT)
|
||||
self.frames["rightItemFrame"].pack(side=RIGHT)
|
||||
|
||||
# Load Item Randomizer option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
# Checkboxes go West
|
||||
# Everything else goes East
|
||||
with open(os.path.join("resources","app","gui","randomize","item","widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for framename,theseWidgets in myDict.items():
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, StringVar, Entry, Frame, Label, Spinbox, N, E, W, X, LEFT, RIGHT
|
||||
from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, X, LEFT
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -15,6 +15,8 @@ def multiworld_page(parent,settings):
|
||||
self.frames["widgets"] = Frame(self)
|
||||
self.frames["widgets"].pack(anchor=W, fill=X)
|
||||
|
||||
# Load Multiworld option widgets as defined by JSON file
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
with open(os.path.join("resources","app","gui","randomize","multiworld","widgets.json")) as multiworldItems:
|
||||
myDict = json.load(multiworldItems)
|
||||
dictWidgets = widgets.make_widgets_from_dict(self, myDict, self.frames["widgets"])
|
||||
@@ -23,6 +25,7 @@ def multiworld_page(parent,settings):
|
||||
self.widgets[key].pack(side=LEFT, anchor=N)
|
||||
|
||||
## List of Player Names
|
||||
# This one's more-complicated, build it and stuff it
|
||||
key = "names"
|
||||
self.widgets[key] = Frame(self.frames["widgets"])
|
||||
self.widgets[key].label = Label(self.widgets[key], text='Player names')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from tkinter import ttk, StringVar, Entry, Frame, Label, N, E, W, LEFT, RIGHT, X, VERTICAL, Y
|
||||
from tkinter import ttk, Frame, N, E, W, LEFT, X, VERTICAL, Y
|
||||
import gui.widgets as widgets
|
||||
import json
|
||||
import os
|
||||
@@ -9,16 +9,19 @@ def startinventory_page(top,parent):
|
||||
# Starting Inventory
|
||||
self = ttk.Frame(parent)
|
||||
|
||||
# Create uniform list columns
|
||||
def create_list_frame(parent, framename):
|
||||
parent.frames[framename] = Frame(parent)
|
||||
parent.frames[framename].pack(side=LEFT, padx=(0,0), anchor=N)
|
||||
parent.frames[framename].thisRow = 0
|
||||
parent.frames[framename].thisCol = 0
|
||||
|
||||
# Create a vertical rule to help with splitting columns visually
|
||||
def create_vertical_rule(num=1):
|
||||
for i in range(0,num):
|
||||
for _ in range(0,num):
|
||||
ttk.Separator(self, orient=VERTICAL).pack(side=LEFT, anchor=N, fill=Y)
|
||||
|
||||
# This was in Custom Item Pool, I have no idea what it was but I left it just in case: MikeT
|
||||
def validation(P):
|
||||
if str.isdigit(P) or P == "":
|
||||
return True
|
||||
@@ -31,6 +34,7 @@ def startinventory_page(top,parent):
|
||||
|
||||
# Starting Inventory option sections
|
||||
self.frames = {}
|
||||
# Create 5 columns with 2 vertical rules in between each
|
||||
create_list_frame(self,"itemList1")
|
||||
create_vertical_rule(2)
|
||||
create_list_frame(self,"itemList2")
|
||||
@@ -41,6 +45,8 @@ def startinventory_page(top,parent):
|
||||
create_vertical_rule(2)
|
||||
create_list_frame(self,"itemList5")
|
||||
|
||||
# Load Starting Inventory option widgets as defined by JSON file, ignoring the ones to be excluded
|
||||
# Defns include frame name, widget type, widget options, widget placement attributes
|
||||
with open(os.path.join("resources","app","gui","custom","overview","widgets.json")) as widgetDefns:
|
||||
myDict = json.load(widgetDefns)
|
||||
for key in CONST.CANTSTARTWITH:
|
||||
@@ -53,6 +59,7 @@ def startinventory_page(top,parent):
|
||||
for key in dictWidgets:
|
||||
self.startingWidgets[key] = dictWidgets[key]
|
||||
|
||||
# Load Custom Starting Inventory settings from settings file, ignoring ones to be excluded
|
||||
for key in CONST.CUSTOMITEMS:
|
||||
if key not in CONST.CANTSTARTWITH:
|
||||
val = 0
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from tkinter import Checkbutton, Entry, Frame, IntVar, Label, OptionMenu, Spinbox, StringVar, RIGHT, X
|
||||
|
||||
# Need a dummy class
|
||||
class Empty():
|
||||
pass
|
||||
|
||||
# Override Spinbox to include mousewheel support for changing value
|
||||
class mySpinbox(Spinbox):
|
||||
def __init__(self, *args, **kwargs):
|
||||
Spinbox.__init__(self, *args, **kwargs)
|
||||
@@ -16,6 +18,7 @@ class mySpinbox(Spinbox):
|
||||
elif event.num == 4 or event.delta == 120:
|
||||
self.invoke('buttonup')
|
||||
|
||||
# Make a Checkbutton with a label
|
||||
def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
self = Frame(parent, name="checkframe-" + label.lower())
|
||||
self.storageVar = storageVar
|
||||
@@ -26,6 +29,7 @@ def make_checkbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
self.checkbox.pack()
|
||||
return self
|
||||
|
||||
# Make an OptionMenu with a label and pretty option labels
|
||||
def make_selectbox(self, parent, label, options, storageVar, manager, managerAttrs):
|
||||
def change_storage(*args):
|
||||
self.storageVar.set(options[self.labelVar.get()])
|
||||
@@ -54,6 +58,7 @@ def make_selectbox(self, parent, label, options, storageVar, manager, managerAtt
|
||||
self.selectbox.pack()
|
||||
return self
|
||||
|
||||
# Make a Spinbox with a label, limit 1-100
|
||||
def make_spinbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
self = Frame(parent, name="spinframe-" + label.lower())
|
||||
self.storageVar = storageVar
|
||||
@@ -76,6 +81,8 @@ def make_spinbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
self.spinbox.pack()
|
||||
return self
|
||||
|
||||
# Make an Entry box with a label
|
||||
# Support for Grid or Pack so that the Custom Item Pool & Starting Inventory pages don't look ugly
|
||||
def make_textbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
widget = Empty()
|
||||
widget.storageVar = storageVar
|
||||
@@ -98,7 +105,7 @@ def make_textbox(self, parent, label, storageVar, manager, managerAttrs):
|
||||
widget.textbox.pack(managerAttrs["textbox"] if managerAttrs is not None and "textbox" in managerAttrs else None)
|
||||
return widget
|
||||
|
||||
|
||||
# Make a generic widget
|
||||
def make_widget(self, type, parent, label, storageVar=None, manager=None, managerAttrs=dict(), options=None):
|
||||
widget = None
|
||||
if manager is None:
|
||||
@@ -129,6 +136,7 @@ def make_widget(self, type, parent, label, storageVar=None, manager=None, manage
|
||||
widget.type = type
|
||||
return widget
|
||||
|
||||
# Make a generic widget from a dict
|
||||
def make_widget_from_dict(self, defn, parent):
|
||||
type = defn["type"] if "type" in defn else None
|
||||
label = defn["label"]["text"] if "label" in defn and "text" in defn["label"] else ""
|
||||
@@ -138,8 +146,9 @@ def make_widget_from_dict(self, defn, parent):
|
||||
widget = make_widget(self, type, parent, label, None, manager, managerAttrs, options)
|
||||
return widget
|
||||
|
||||
# Make a set of generic widgets from a dict
|
||||
def make_widgets_from_dict(self, defns, parent):
|
||||
widgets = {}
|
||||
for key,defn in defns.items():
|
||||
widgets[key] = make_widget_from_dict(self, defn, parent)
|
||||
return widgets
|
||||
return widgets
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"options": {
|
||||
"Standard": "standard",
|
||||
"Open": "open",
|
||||
"Inverted": "inverted"
|
||||
"Inverted": "inverted",
|
||||
"Retro": "retro"
|
||||
}
|
||||
},
|
||||
"logiclevel": {
|
||||
|
||||
Reference in New Issue
Block a user