Merge branch 'main' into breaking_changes
# Conflicts: # Adjuster.py # Gui.py # MultiClient.py # setup.py # worlds/alttp/AdjusterMain.py # worlds/alttp/Main.py
This commit is contained in:
commit
dcce53f8c8
137
Adjuster.py
137
Adjuster.py
|
@ -4,9 +4,11 @@ import os
|
||||||
import logging
|
import logging
|
||||||
import textwrap
|
import textwrap
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
from AdjusterMain import adjust
|
from AdjusterMain import adjust
|
||||||
from worlds.alttp.Rom import Sprite
|
from worlds.alttp.Rom import Sprite, LocalRom, apply_rom_settings
|
||||||
|
from Utils import output_path
|
||||||
|
|
||||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ def main():
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
||||||
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
||||||
|
parser.add_argument('--enableflashing', help='Reenable flashing animations (unfriendly to epilepsy, always disabled in race roms)', action='store_false', dest="reduceflashing")
|
||||||
parser.add_argument('--heartbeep', default='normal', const='normal', nargs='?', choices=['double', 'normal', 'half', 'quarter', 'off'],
|
parser.add_argument('--heartbeep', default='normal', const='normal', nargs='?', choices=['double', 'normal', 'half', 'quarter', 'off'],
|
||||||
help='''\
|
help='''\
|
||||||
Select the rate at which the heart beep sound is played at
|
Select the rate at which the heart beep sound is played at
|
||||||
|
@ -50,25 +53,127 @@ def main():
|
||||||
parser.add_argument('--names', default='', type=str)
|
parser.add_argument('--names', default='', type=str)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# ToDo: Validate files further than mere existance
|
|
||||||
if not os.path.isfile(args.rom):
|
|
||||||
input(
|
|
||||||
'Could not find valid rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.' % args.rom)
|
|
||||||
sys.exit(1)
|
|
||||||
if args.sprite is not None and not os.path.isfile(args.sprite) and not Sprite.get_sprite_from_name(args.sprite):
|
|
||||||
input('Could not find link sprite sheet at given location. \nPress Enter to exit.')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# set up logger
|
# set up logger
|
||||||
loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[
|
loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[
|
||||||
args.loglevel]
|
args.loglevel]
|
||||||
logging.basicConfig(format='%(message)s', level=loglevel)
|
logging.basicConfig(format='%(message)s', level=loglevel)
|
||||||
args, path = adjust(args=args)
|
|
||||||
from Utils import persistent_store
|
if not os.path.isfile(args.rom):
|
||||||
from Rom import Sprite
|
adjustGUI()
|
||||||
if isinstance(args.sprite, Sprite):
|
else:
|
||||||
args.sprite = args.sprite.name
|
if args.sprite is not None and not os.path.isfile(args.sprite) and not Sprite.get_sprite_from_name(args.sprite):
|
||||||
persistent_store("adjuster", "last_settings_3", args)
|
input('Could not find link sprite sheet at given location. \nPress Enter to exit.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
args, path = adjust(args=args)
|
||||||
|
from Utils import persistent_store
|
||||||
|
if isinstance(args.sprite, Sprite):
|
||||||
|
args.sprite = args.sprite.name
|
||||||
|
persistent_store("adjuster", "last_settings_3", args)
|
||||||
|
|
||||||
|
|
||||||
|
def adjust(args):
|
||||||
|
start = time.perf_counter()
|
||||||
|
logger = logging.getLogger('Adjuster')
|
||||||
|
logger.info('Patching ROM.')
|
||||||
|
vanillaRom = args.baserom
|
||||||
|
if os.path.splitext(args.rom)[-1].lower() == '.bmbp':
|
||||||
|
import Patch
|
||||||
|
meta, args.rom = Patch.create_rom_file(args.rom)
|
||||||
|
|
||||||
|
if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(args.rom)[-1].lower() == '.sfc':
|
||||||
|
rom = LocalRom(args.rom, patch=False, vanillaRom=vanillaRom)
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.')
|
||||||
|
palettes_options={}
|
||||||
|
palettes_options['dungeon']=args.uw_palettes
|
||||||
|
|
||||||
|
palettes_options['overworld']=args.ow_palettes
|
||||||
|
palettes_options['hud']=args.hud_palettes
|
||||||
|
palettes_options['sword']=args.sword_palettes
|
||||||
|
palettes_options['shield']=args.shield_palettes
|
||||||
|
# palettes_options['link']=args.link_palettesvera
|
||||||
|
racerom = rom.read_byte(0x180213) > 0
|
||||||
|
|
||||||
|
apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic,
|
||||||
|
args.sprite, palettes_options, reduceflashing=args.reduceflashing or racerom)
|
||||||
|
path = output_path(f'{os.path.basename(args.rom)[:-4]}_adjusted.sfc')
|
||||||
|
rom.write_to_file(path)
|
||||||
|
|
||||||
|
logger.info('Done. Enjoy.')
|
||||||
|
logger.debug('Total Time: %s', time.perf_counter() - start)
|
||||||
|
|
||||||
|
return args, path
|
||||||
|
|
||||||
|
def adjustGUI():
|
||||||
|
from tkinter import Checkbutton, OptionMenu, Toplevel, LabelFrame, PhotoImage, Tk, LEFT, RIGHT, BOTTOM, TOP, \
|
||||||
|
StringVar, IntVar, Frame, Label, W, E, X, BOTH, Entry, Spinbox, Button, filedialog, messagebox, ttk
|
||||||
|
from Gui import get_rom_options_frame, get_rom_frame
|
||||||
|
from GuiUtils import set_icon
|
||||||
|
from argparse import Namespace
|
||||||
|
from Main import __version__ as MWVersion
|
||||||
|
adjustWindow = Tk()
|
||||||
|
adjustWindow.wm_title("Berserker's Multiworld %s LttP Adjuster" % MWVersion)
|
||||||
|
set_icon(adjustWindow)
|
||||||
|
|
||||||
|
rom_options_frame, rom_vars, set_sprite = get_rom_options_frame(adjustWindow)
|
||||||
|
|
||||||
|
bottomFrame2 = Frame(adjustWindow)
|
||||||
|
|
||||||
|
romFrame, romVar = get_rom_frame(adjustWindow)
|
||||||
|
|
||||||
|
romDialogFrame = Frame(adjustWindow)
|
||||||
|
baseRomLabel2 = Label(romDialogFrame, text='Rom to adjust')
|
||||||
|
romVar2 = StringVar()
|
||||||
|
romEntry2 = Entry(romDialogFrame, textvariable=romVar2)
|
||||||
|
|
||||||
|
def RomSelect2():
|
||||||
|
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc", ".bmbp")), ("All Files", "*")])
|
||||||
|
romVar2.set(rom)
|
||||||
|
romSelectButton2 = Button(romDialogFrame, text='Select Rom', command=RomSelect2)
|
||||||
|
romDialogFrame.pack(side=TOP, expand=True, fill=X)
|
||||||
|
baseRomLabel2.pack(side=LEFT)
|
||||||
|
romEntry2.pack(side=LEFT, expand=True, fill=X)
|
||||||
|
romSelectButton2.pack(side=LEFT)
|
||||||
|
|
||||||
|
def adjustRom():
|
||||||
|
guiargs = Namespace()
|
||||||
|
guiargs.heartbeep = rom_vars.heartbeepVar.get()
|
||||||
|
guiargs.heartcolor = rom_vars.heartcolorVar.get()
|
||||||
|
guiargs.fastmenu = rom_vars.fastMenuVar.get()
|
||||||
|
guiargs.ow_palettes = rom_vars.owPalettesVar.get()
|
||||||
|
guiargs.uw_palettes = rom_vars.uwPalettesVar.get()
|
||||||
|
guiargs.hud_palettes = rom_vars.hudPalettesVar.get()
|
||||||
|
guiargs.sword_palettes = rom_vars.swordPalettesVar.get()
|
||||||
|
guiargs.shield_palettes = rom_vars.shieldPalettesVar.get()
|
||||||
|
guiargs.quickswap = bool(rom_vars.quickSwapVar.get())
|
||||||
|
guiargs.disablemusic = bool(rom_vars.disableMusicVar.get())
|
||||||
|
guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get())
|
||||||
|
guiargs.rom = romVar2.get()
|
||||||
|
guiargs.baserom = romVar.get()
|
||||||
|
guiargs.sprite = rom_vars.sprite
|
||||||
|
try:
|
||||||
|
guiargs, path = adjust(args=guiargs)
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(e)
|
||||||
|
messagebox.showerror(title="Error while adjusting Rom", message=str(e))
|
||||||
|
else:
|
||||||
|
messagebox.showinfo(title="Success", message=f"Rom patched successfully to {path}")
|
||||||
|
from Utils import persistent_store
|
||||||
|
from Rom import Sprite
|
||||||
|
if isinstance(guiargs.sprite, Sprite):
|
||||||
|
guiargs.sprite = guiargs.sprite.name
|
||||||
|
persistent_store("adjuster", "last_settings_3", guiargs)
|
||||||
|
|
||||||
|
adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
|
||||||
|
rom_options_frame.pack(side=TOP)
|
||||||
|
adjustButton.pack(side=BOTTOM, padx=(5, 5))
|
||||||
|
|
||||||
|
bottomFrame2.pack(side=BOTTOM, pady=(5, 5))
|
||||||
|
|
||||||
|
adjustWindow.mainloop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
|
@ -4,6 +4,7 @@ import copy
|
||||||
from enum import Enum, unique
|
from enum import Enum, unique
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
import functools
|
||||||
from collections import OrderedDict, Counter, deque
|
from collections import OrderedDict, Counter, deque
|
||||||
from typing import *
|
from typing import *
|
||||||
import secrets
|
import secrets
|
||||||
|
@ -25,6 +26,7 @@ class MultiWorld():
|
||||||
plando_texts: List[Dict[str, str]]
|
plando_texts: List[Dict[str, str]]
|
||||||
plando_items: List[PlandoItem]
|
plando_items: List[PlandoItem]
|
||||||
plando_connections: List[PlandoConnection]
|
plando_connections: List[PlandoConnection]
|
||||||
|
er_seeds: Dict[int, str]
|
||||||
|
|
||||||
def __init__(self, players: int, shuffle, logic, mode, swords, difficulty, item_functionality, timer,
|
def __init__(self, players: int, shuffle, logic, mode, swords, difficulty, item_functionality, timer,
|
||||||
progressive,
|
progressive,
|
||||||
|
@ -157,6 +159,10 @@ class MultiWorld():
|
||||||
region.world = self
|
region.world = self
|
||||||
self._region_cache[region.player][region.name] = region
|
self._region_cache[region.player][region.name] = region
|
||||||
|
|
||||||
|
@functools.cached_property
|
||||||
|
def world_name_lookup(self):
|
||||||
|
return {self.player_names[player_id][0]: player_id for player_id in self.player_ids}
|
||||||
|
|
||||||
def _recache(self):
|
def _recache(self):
|
||||||
"""Rebuild world cache"""
|
"""Rebuild world cache"""
|
||||||
for region in self.regions:
|
for region in self.regions:
|
||||||
|
@ -1285,7 +1291,8 @@ class Spoiler(object):
|
||||||
'shop_shuffle_slots': self.world.shop_shuffle_slots,
|
'shop_shuffle_slots': self.world.shop_shuffle_slots,
|
||||||
'shuffle_prizes': self.world.shuffle_prizes,
|
'shuffle_prizes': self.world.shuffle_prizes,
|
||||||
'sprite_pool': self.world.sprite_pool,
|
'sprite_pool': self.world.sprite_pool,
|
||||||
'restrict_dungeon_item_on_boss': self.world.restrict_dungeon_item_on_boss
|
'restrict_dungeon_item_on_boss': self.world.restrict_dungeon_item_on_boss,
|
||||||
|
'er_seeds': self.world.er_seeds
|
||||||
}
|
}
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
|
@ -1349,6 +1356,8 @@ class Spoiler(object):
|
||||||
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
outfile.write('Item Functionality: %s\n' % self.metadata['item_functionality'][player])
|
||||||
outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player])
|
outfile.write('Item Progression: %s\n' % self.metadata['progressive'][player])
|
||||||
outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player])
|
outfile.write('Entrance Shuffle: %s\n' % self.metadata['shuffle'][player])
|
||||||
|
if self.metadata['shuffle'][player] != "vanilla":
|
||||||
|
outfile.write('Entrance Shuffle Seed %s\n' % self.metadata['er_seeds'][player])
|
||||||
outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player])
|
outfile.write('Crystals required for GT: %s\n' % self.metadata['gt_crystals'][player])
|
||||||
outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player])
|
outfile.write('Crystals required for Ganon: %s\n' % self.metadata['ganon_crystals'][player])
|
||||||
outfile.write('Pyramid hole pre-opened: %s\n' % (
|
outfile.write('Pyramid hole pre-opened: %s\n' % (
|
||||||
|
|
2
Fill.py
2
Fill.py
|
@ -359,7 +359,7 @@ def swap_location_item(location_1: Location, location_2: Location, check_locked=
|
||||||
|
|
||||||
|
|
||||||
def distribute_planned(world):
|
def distribute_planned(world):
|
||||||
world_name_lookup = {world.player_names[player_id][0]: player_id for player_id in world.player_ids}
|
world_name_lookup = world.world_name_lookup
|
||||||
|
|
||||||
for player in world.player_ids:
|
for player in world.player_ids:
|
||||||
placement: PlandoItem
|
placement: PlandoItem
|
||||||
|
|
495
Gui.py
495
Gui.py
|
@ -19,7 +19,7 @@ from worlds.alttp.EntranceRandomizer import parse_arguments
|
||||||
from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress
|
from GuiUtils import ToolTips, set_icon, BackgroundTaskProgress
|
||||||
from worlds.alttp.Main import main, get_seed, __version__ as MWVersion
|
from worlds.alttp.Main import main, get_seed, __version__ as MWVersion
|
||||||
from worlds.alttp.Rom import Sprite
|
from worlds.alttp.Rom import Sprite
|
||||||
from Utils import is_bundled, local_path, output_path, open_file
|
from Utils import local_path, output_path, open_file
|
||||||
|
|
||||||
|
|
||||||
def guiMain(args=None):
|
def guiMain(args=None):
|
||||||
|
@ -30,10 +30,8 @@ def guiMain(args=None):
|
||||||
|
|
||||||
notebook = ttk.Notebook(mainWindow)
|
notebook = ttk.Notebook(mainWindow)
|
||||||
randomizerWindow = ttk.Frame(notebook)
|
randomizerWindow = ttk.Frame(notebook)
|
||||||
adjustWindow = ttk.Frame(notebook)
|
|
||||||
customWindow = ttk.Frame(notebook)
|
customWindow = ttk.Frame(notebook)
|
||||||
notebook.add(randomizerWindow, text='Randomize')
|
notebook.add(randomizerWindow, text='Randomize')
|
||||||
notebook.add(adjustWindow, text='Adjust')
|
|
||||||
notebook.add(customWindow, text='Custom Items')
|
notebook.add(customWindow, text='Custom Items')
|
||||||
notebook.pack()
|
notebook.pack()
|
||||||
|
|
||||||
|
@ -57,6 +55,8 @@ def guiMain(args=None):
|
||||||
# randomizer controls
|
# randomizer controls
|
||||||
|
|
||||||
topFrame = Frame(randomizerWindow)
|
topFrame = Frame(randomizerWindow)
|
||||||
|
romFrame, romVar = get_rom_frame(topFrame)
|
||||||
|
|
||||||
rightHalfFrame = Frame(topFrame)
|
rightHalfFrame = Frame(topFrame)
|
||||||
checkBoxFrame = Frame(rightHalfFrame)
|
checkBoxFrame = Frame(rightHalfFrame)
|
||||||
|
|
||||||
|
@ -119,154 +119,9 @@ def guiMain(args=None):
|
||||||
hintsCheckbutton.pack(expand=True, anchor=W)
|
hintsCheckbutton.pack(expand=True, anchor=W)
|
||||||
tileShuffleButton.pack(expand=True, anchor=W)
|
tileShuffleButton.pack(expand=True, anchor=W)
|
||||||
|
|
||||||
|
|
||||||
romOptionsFrame = LabelFrame(rightHalfFrame, text="Rom options")
|
|
||||||
romOptionsFrame.columnconfigure(0, weight=1)
|
|
||||||
romOptionsFrame.columnconfigure(1, weight=1)
|
|
||||||
for i in range(5):
|
|
||||||
romOptionsFrame.rowconfigure(i, weight=1)
|
|
||||||
|
|
||||||
disableMusicVar = IntVar()
|
|
||||||
disableMusicCheckbutton = Checkbutton(romOptionsFrame, text="Disable music", variable=disableMusicVar)
|
|
||||||
disableMusicCheckbutton.grid(row=0, column=0, sticky=E)
|
|
||||||
|
|
||||||
spriteDialogFrame = Frame(romOptionsFrame)
|
|
||||||
spriteDialogFrame.grid(row=0, column=1)
|
|
||||||
baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:')
|
|
||||||
|
|
||||||
spriteNameVar = StringVar()
|
|
||||||
sprite = None
|
|
||||||
def set_sprite(sprite_param):
|
|
||||||
nonlocal sprite
|
|
||||||
if isinstance(sprite_param, str):
|
|
||||||
sprite = sprite_param
|
|
||||||
spriteNameVar.set(sprite_param)
|
|
||||||
elif sprite_param is None or not sprite_param.valid:
|
|
||||||
sprite = None
|
|
||||||
spriteNameVar.set('(unchanged)')
|
|
||||||
else:
|
|
||||||
sprite = sprite_param
|
|
||||||
spriteNameVar.set(sprite.name)
|
|
||||||
|
|
||||||
set_sprite(None)
|
|
||||||
spriteNameVar.set('(unchanged)')
|
|
||||||
spriteEntry = Label(spriteDialogFrame, textvariable=spriteNameVar)
|
|
||||||
|
|
||||||
def SpriteSelect():
|
|
||||||
SpriteSelector(mainWindow, set_sprite)
|
|
||||||
|
|
||||||
spriteSelectButton = Button(spriteDialogFrame, text='...', command=SpriteSelect)
|
|
||||||
|
|
||||||
baseSpriteLabel.pack(side=LEFT)
|
|
||||||
spriteEntry.pack(side=LEFT)
|
|
||||||
spriteSelectButton.pack(side=LEFT)
|
|
||||||
|
|
||||||
quickSwapVar = IntVar(value=1)
|
|
||||||
quickSwapCheckbutton = Checkbutton(romOptionsFrame, text="L/R Quickswapping", variable=quickSwapVar)
|
|
||||||
quickSwapCheckbutton.grid(row=1, column=0, sticky=E)
|
|
||||||
|
|
||||||
fastMenuFrame = Frame(romOptionsFrame)
|
|
||||||
fastMenuFrame.grid(row=1, column=1, sticky=E)
|
|
||||||
fastMenuLabel = Label(fastMenuFrame, text='Menu speed')
|
|
||||||
fastMenuLabel.pack(side=LEFT)
|
|
||||||
fastMenuVar = StringVar()
|
|
||||||
fastMenuVar.set('normal')
|
|
||||||
fastMenuOptionMenu = OptionMenu(fastMenuFrame, fastMenuVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half')
|
|
||||||
fastMenuOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
heartcolorFrame = Frame(romOptionsFrame)
|
|
||||||
heartcolorFrame.grid(row=2, column=0, sticky=E)
|
|
||||||
heartcolorLabel = Label(heartcolorFrame, text='Heart color')
|
|
||||||
heartcolorLabel.pack(side=LEFT)
|
|
||||||
heartcolorVar = StringVar()
|
|
||||||
heartcolorVar.set('red')
|
|
||||||
heartcolorOptionMenu = OptionMenu(heartcolorFrame, heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random')
|
|
||||||
heartcolorOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
heartbeepFrame = Frame(romOptionsFrame)
|
|
||||||
heartbeepFrame.grid(row=2, column=1, sticky=E)
|
|
||||||
heartbeepLabel = Label(heartbeepFrame, text='Heartbeep')
|
|
||||||
heartbeepLabel.pack(side=LEFT)
|
|
||||||
heartbeepVar = StringVar()
|
|
||||||
heartbeepVar.set('normal')
|
|
||||||
heartbeepOptionMenu = OptionMenu(heartbeepFrame, heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off')
|
|
||||||
heartbeepOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
owPalettesFrame = Frame(romOptionsFrame)
|
|
||||||
owPalettesFrame.grid(row=3, column=0, sticky=E)
|
|
||||||
owPalettesLabel = Label(owPalettesFrame, text='Overworld palettes')
|
|
||||||
owPalettesLabel.pack(side=LEFT)
|
|
||||||
owPalettesVar = StringVar()
|
|
||||||
owPalettesVar.set('default')
|
|
||||||
owPalettesOptionMenu = OptionMenu(owPalettesFrame, owPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
owPalettesOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
uwPalettesFrame = Frame(romOptionsFrame)
|
|
||||||
uwPalettesFrame.grid(row=3, column=1, sticky=E)
|
|
||||||
uwPalettesLabel = Label(uwPalettesFrame, text='Dungeon palettes')
|
|
||||||
uwPalettesLabel.pack(side=LEFT)
|
|
||||||
uwPalettesVar = StringVar()
|
|
||||||
uwPalettesVar.set('default')
|
|
||||||
uwPalettesOptionMenu = OptionMenu(uwPalettesFrame, uwPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
uwPalettesOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
hudPalettesFrame = Frame(romOptionsFrame)
|
|
||||||
hudPalettesFrame.grid(row=4, column=0, sticky=E)
|
|
||||||
hudPalettesLabel = Label(hudPalettesFrame, text='HUD palettes')
|
|
||||||
hudPalettesLabel.pack(side=LEFT)
|
|
||||||
hudPalettesVar = StringVar()
|
|
||||||
hudPalettesVar.set('default')
|
|
||||||
hudPalettesOptionMenu = OptionMenu(hudPalettesFrame, hudPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
hudPalettesOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
swordPalettesFrame = Frame(romOptionsFrame)
|
|
||||||
swordPalettesFrame.grid(row=4, column=1, sticky=E)
|
|
||||||
swordPalettesLabel = Label(swordPalettesFrame, text='Sword palettes')
|
|
||||||
swordPalettesLabel.pack(side=LEFT)
|
|
||||||
swordPalettesVar = StringVar()
|
|
||||||
swordPalettesVar.set('default')
|
|
||||||
swordPalettesOptionMenu = OptionMenu(swordPalettesFrame, swordPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
swordPalettesOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
shieldPalettesFrame = Frame(romOptionsFrame)
|
|
||||||
shieldPalettesFrame.grid(row=5, column=0, sticky=E)
|
|
||||||
shieldPalettesLabel = Label(shieldPalettesFrame, text='Shield palettes')
|
|
||||||
shieldPalettesLabel.pack(side=LEFT)
|
|
||||||
shieldPalettesVar = StringVar()
|
|
||||||
shieldPalettesVar.set('default')
|
|
||||||
shieldPalettesOptionMenu = OptionMenu(shieldPalettesFrame, shieldPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
shieldPalettesOptionMenu.pack(side=LEFT)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
romDialogFrame = Frame(romOptionsFrame)
|
|
||||||
romDialogFrame.grid(row=6, column=0, columnspan=2, sticky=W+E)
|
|
||||||
|
|
||||||
baseRomLabel = Label(romDialogFrame, text='Base Rom: ')
|
|
||||||
romVar = StringVar(value="Zelda no Densetsu - Kamigami no Triforce (Japan).sfc")
|
|
||||||
romEntry = Entry(romDialogFrame, textvariable=romVar)
|
|
||||||
|
|
||||||
def RomSelect():
|
|
||||||
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc")), ("All Files", "*")])
|
|
||||||
import Patch
|
|
||||||
try:
|
|
||||||
Patch.get_base_rom_bytes(rom) # throws error on checksum fail
|
|
||||||
except Exception as e:
|
|
||||||
logging.exception(e)
|
|
||||||
messagebox.showerror(title="Error while reading ROM", message=str(e))
|
|
||||||
else:
|
|
||||||
romVar.set(rom)
|
|
||||||
romSelectButton['state'] = "disabled"
|
|
||||||
romSelectButton["text"] = "ROM verified"
|
|
||||||
romSelectButton = Button(romDialogFrame, text='Select Rom', command=RomSelect)
|
|
||||||
|
|
||||||
baseRomLabel.pack(side=LEFT)
|
|
||||||
romEntry.pack(side=LEFT, expand=True, fill=X)
|
|
||||||
romSelectButton.pack(side=LEFT)
|
|
||||||
|
|
||||||
checkBoxFrame.pack(side=TOP, anchor=W, padx=5, pady=10)
|
checkBoxFrame.pack(side=TOP, anchor=W, padx=5, pady=10)
|
||||||
|
|
||||||
|
romOptionsFrame, rom_vars, set_sprite = get_rom_options_frame(rightHalfFrame)
|
||||||
romOptionsFrame.pack(expand=True, fill=BOTH, padx=3)
|
romOptionsFrame.pack(expand=True, fill=BOTH, padx=3)
|
||||||
|
|
||||||
drowDownFrame = Frame(topFrame)
|
drowDownFrame = Frame(topFrame)
|
||||||
|
@ -382,7 +237,8 @@ def guiMain(args=None):
|
||||||
shuffleVar.set('vanilla')
|
shuffleVar.set('vanilla')
|
||||||
shuffleOptionMenu = OptionMenu(shuffleFrame, shuffleVar, 'vanilla', 'simple', 'restricted', 'full', 'crossed',
|
shuffleOptionMenu = OptionMenu(shuffleFrame, shuffleVar, 'vanilla', 'simple', 'restricted', 'full', 'crossed',
|
||||||
'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy',
|
'insanity', 'restricted_legacy', 'full_legacy', 'madness_legacy', 'insanity_legacy',
|
||||||
'dungeonsfull', 'dungeonssimple')
|
'dungeonsfull', 'dungeonssimple', "same simple", "same restricted", "same full",
|
||||||
|
"same crossed", "same insanity", "same dungeonsfull", "same dungeonssimple")
|
||||||
shuffleOptionMenu.pack(side=RIGHT)
|
shuffleOptionMenu.pack(side=RIGHT)
|
||||||
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle')
|
shuffleLabel = Label(shuffleFrame, text='Entrance shuffle')
|
||||||
shuffleLabel.pack(side=LEFT)
|
shuffleLabel.pack(side=LEFT)
|
||||||
|
@ -563,9 +419,12 @@ def guiMain(args=None):
|
||||||
guiargs.accessibility = accessibilityVar.get()
|
guiargs.accessibility = accessibilityVar.get()
|
||||||
guiargs.algorithm = algorithmVar.get()
|
guiargs.algorithm = algorithmVar.get()
|
||||||
guiargs.shuffle = shuffleVar.get()
|
guiargs.shuffle = shuffleVar.get()
|
||||||
guiargs.heartbeep = heartbeepVar.get()
|
if "same " in guiargs.shuffle:
|
||||||
guiargs.heartcolor = heartcolorVar.get()
|
guiargs.shuffle = guiargs.shuffle[5:] + "-" + str(seedVar.get() if seedVar.get() else
|
||||||
guiargs.fastmenu = fastMenuVar.get()
|
random.randint(0, 2**64))
|
||||||
|
guiargs.heartbeep = rom_vars.heartbeepVar.get()
|
||||||
|
guiargs.heartcolor = rom_vars.heartcolorVar.get()
|
||||||
|
guiargs.fastmenu = rom_vars.fastMenuVar.get()
|
||||||
guiargs.create_spoiler = bool(createSpoilerVar.get())
|
guiargs.create_spoiler = bool(createSpoilerVar.get())
|
||||||
guiargs.skip_playthrough = not bool(createSpoilerVar.get())
|
guiargs.skip_playthrough = not bool(createSpoilerVar.get())
|
||||||
guiargs.suppress_rom = bool(suppressRomVar.get())
|
guiargs.suppress_rom = bool(suppressRomVar.get())
|
||||||
|
@ -575,13 +434,14 @@ def guiMain(args=None):
|
||||||
guiargs.keyshuffle = {"on": True, "universal": "universal", "off": False}[keyshuffleVar.get()]
|
guiargs.keyshuffle = {"on": True, "universal": "universal", "off": False}[keyshuffleVar.get()]
|
||||||
guiargs.bigkeyshuffle = bool(bigkeyshuffleVar.get())
|
guiargs.bigkeyshuffle = bool(bigkeyshuffleVar.get())
|
||||||
guiargs.retro = bool(retroVar.get())
|
guiargs.retro = bool(retroVar.get())
|
||||||
guiargs.quickswap = bool(quickSwapVar.get())
|
guiargs.quickswap = bool(rom_vars.quickSwapVar.get())
|
||||||
guiargs.disablemusic = bool(disableMusicVar.get())
|
guiargs.disablemusic = bool(rom_vars.disableMusicVar.get())
|
||||||
guiargs.ow_palettes = owPalettesVar.get()
|
guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get())
|
||||||
guiargs.uw_palettes = uwPalettesVar.get()
|
guiargs.ow_palettes = rom_vars.owPalettesVar.get()
|
||||||
guiargs.hud_palettes = hudPalettesVar.get()
|
guiargs.uw_palettes = rom_vars.uwPalettesVar.get()
|
||||||
guiargs.sword_palettes = swordPalettesVar.get()
|
guiargs.hud_palettes = rom_vars.hudPalettesVar.get()
|
||||||
guiargs.shield_palettes = shieldPalettesVar.get()
|
guiargs.sword_palettes = rom_vars.swordPalettesVar.get()
|
||||||
|
guiargs.shield_palettes = rom_vars.shieldPalettesVar.get()
|
||||||
guiargs.shuffleganon = bool(shuffleGanonVar.get())
|
guiargs.shuffleganon = bool(shuffleGanonVar.get())
|
||||||
guiargs.hints = bool(hintsVar.get())
|
guiargs.hints = bool(hintsVar.get())
|
||||||
guiargs.enemizercli = enemizerCLIpathVar.get()
|
guiargs.enemizercli = enemizerCLIpathVar.get()
|
||||||
|
@ -641,7 +501,7 @@ def guiMain(args=None):
|
||||||
int(rupoorcostVar.get()), int(triforceVar.get())]
|
int(rupoorcostVar.get()), int(triforceVar.get())]
|
||||||
guiargs.rom = romVar.get()
|
guiargs.rom = romVar.get()
|
||||||
guiargs.create_diff = patchesVar.get()
|
guiargs.create_diff = patchesVar.get()
|
||||||
guiargs.sprite = sprite
|
guiargs.sprite = rom_vars.sprite
|
||||||
# get default values for missing parameters
|
# get default values for missing parameters
|
||||||
for k,v in vars(parse_arguments(['--multi', str(guiargs.multi)])).items():
|
for k,v in vars(parse_arguments(['--multi', str(guiargs.multi)])).items():
|
||||||
if k not in vars(guiargs):
|
if k not in vars(guiargs):
|
||||||
|
@ -689,150 +549,6 @@ def guiMain(args=None):
|
||||||
enemizerFrame.pack(side=BOTTOM, fill=BOTH)
|
enemizerFrame.pack(side=BOTTOM, fill=BOTH)
|
||||||
shopframe.pack(side=BOTTOM, expand=True, fill=X)
|
shopframe.pack(side=BOTTOM, expand=True, fill=X)
|
||||||
|
|
||||||
# Adjuster Controls
|
|
||||||
|
|
||||||
topFrame2 = Frame(adjustWindow)
|
|
||||||
rightHalfFrame2 = Frame(topFrame2)
|
|
||||||
checkBoxFrame2 = Frame(rightHalfFrame2)
|
|
||||||
|
|
||||||
quickSwapCheckbutton2 = Checkbutton(checkBoxFrame2, text="L/R Item quickswapping", variable=quickSwapVar)
|
|
||||||
disableMusicCheckbutton2 = Checkbutton(checkBoxFrame2, text="Disable game music", variable=disableMusicVar)
|
|
||||||
|
|
||||||
quickSwapCheckbutton2.pack(expand=True, anchor=W)
|
|
||||||
disableMusicCheckbutton2.pack(expand=True, anchor=W)
|
|
||||||
|
|
||||||
fileDialogFrame2 = Frame(rightHalfFrame2)
|
|
||||||
|
|
||||||
romDialogFrame2 = Frame(fileDialogFrame2)
|
|
||||||
baseRomLabel2 = Label(romDialogFrame2, text='Rom to adjust')
|
|
||||||
romVar2 = StringVar()
|
|
||||||
romEntry2 = Entry(romDialogFrame2, textvariable=romVar2)
|
|
||||||
|
|
||||||
def RomSelect2():
|
|
||||||
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc", ".apbp")), ("All Files", "*")])
|
|
||||||
romVar2.set(rom)
|
|
||||||
romSelectButton2 = Button(romDialogFrame2, text='Select Rom', command=RomSelect2)
|
|
||||||
|
|
||||||
baseRomLabel2.pack(side=LEFT)
|
|
||||||
romEntry2.pack(side=LEFT)
|
|
||||||
romSelectButton2.pack(side=LEFT)
|
|
||||||
|
|
||||||
spriteDialogFrame2 = Frame(fileDialogFrame2)
|
|
||||||
baseSpriteLabel2 = Label(spriteDialogFrame2, text='Link Sprite')
|
|
||||||
spriteEntry2 = Label(spriteDialogFrame2, textvariable=spriteNameVar)
|
|
||||||
|
|
||||||
def SpriteSelectAdjuster():
|
|
||||||
SpriteSelector(mainWindow, set_sprite, adjuster=True)
|
|
||||||
|
|
||||||
spriteSelectButton2 = Button(spriteDialogFrame2, text='Select Sprite', command=SpriteSelectAdjuster)
|
|
||||||
|
|
||||||
baseSpriteLabel2.pack(side=LEFT)
|
|
||||||
spriteEntry2.pack(side=LEFT)
|
|
||||||
spriteSelectButton2.pack(side=LEFT)
|
|
||||||
|
|
||||||
romDialogFrame2.pack()
|
|
||||||
spriteDialogFrame2.pack()
|
|
||||||
|
|
||||||
checkBoxFrame2.pack()
|
|
||||||
fileDialogFrame2.pack()
|
|
||||||
|
|
||||||
drowDownFrame2 = Frame(topFrame2)
|
|
||||||
heartbeepFrame2 = Frame(drowDownFrame2)
|
|
||||||
heartbeepOptionMenu2 = OptionMenu(heartbeepFrame2, heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off')
|
|
||||||
heartbeepOptionMenu2.pack(side=RIGHT)
|
|
||||||
heartbeepLabel2 = Label(heartbeepFrame2, text='Heartbeep sound rate')
|
|
||||||
heartbeepLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
heartcolorFrame2 = Frame(drowDownFrame2)
|
|
||||||
heartcolorOptionMenu2 = OptionMenu(heartcolorFrame2, heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random')
|
|
||||||
heartcolorOptionMenu2.pack(side=RIGHT)
|
|
||||||
heartcolorLabel2 = Label(heartcolorFrame2, text='Heart color')
|
|
||||||
heartcolorLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
fastMenuFrame2 = Frame(drowDownFrame2)
|
|
||||||
fastMenuOptionMenu2 = OptionMenu(fastMenuFrame2, fastMenuVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half')
|
|
||||||
fastMenuOptionMenu2.pack(side=RIGHT)
|
|
||||||
fastMenuLabel2 = Label(fastMenuFrame2, text='Menu speed')
|
|
||||||
fastMenuLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
owPalettesFrame2 = Frame(drowDownFrame2)
|
|
||||||
owPalettesOptionMenu2 = OptionMenu(owPalettesFrame2, owPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
owPalettesOptionMenu2.pack(side=RIGHT)
|
|
||||||
owPalettesLabel2 = Label(owPalettesFrame2, text='Overworld palettes')
|
|
||||||
owPalettesLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
uwPalettesFrame2 = Frame(drowDownFrame2)
|
|
||||||
uwPalettesOptionMenu2 = OptionMenu(uwPalettesFrame2, uwPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
uwPalettesOptionMenu2.pack(side=RIGHT)
|
|
||||||
uwPalettesLabel2 = Label(uwPalettesFrame2, text='Dungeon palettes')
|
|
||||||
uwPalettesLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
hudPalettesFrame2 = Frame(drowDownFrame2)
|
|
||||||
hudPalettesOptionMenu2 = OptionMenu(hudPalettesFrame2, hudPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
hudPalettesOptionMenu2.pack(side=RIGHT)
|
|
||||||
hudPalettesLabel2 = Label(hudPalettesFrame2, text='HUD palettes')
|
|
||||||
hudPalettesLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
swordPalettesFrame2 = Frame(drowDownFrame2)
|
|
||||||
swordPalettesOptionMenu2 = OptionMenu(swordPalettesFrame2, swordPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
swordPalettesOptionMenu2.pack(side=RIGHT)
|
|
||||||
swordPalettesLabel2 = Label(swordPalettesFrame2, text='Sword palettes')
|
|
||||||
swordPalettesLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
shieldPalettesFrame2 = Frame(drowDownFrame2)
|
|
||||||
shieldPalettesOptionMenu2 = OptionMenu(shieldPalettesFrame2, shieldPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
|
||||||
shieldPalettesOptionMenu2.pack(side=RIGHT)
|
|
||||||
shieldPalettesLabel2 = Label(shieldPalettesFrame2, text='Shield palettes')
|
|
||||||
shieldPalettesLabel2.pack(side=LEFT)
|
|
||||||
|
|
||||||
heartbeepFrame2.pack(expand=True, anchor=E)
|
|
||||||
heartcolorFrame2.pack(expand=True, anchor=E)
|
|
||||||
fastMenuFrame2.pack(expand=True, anchor=E)
|
|
||||||
owPalettesFrame2.pack(expand=True, anchor=E)
|
|
||||||
uwPalettesFrame2.pack(expand=True, anchor=E)
|
|
||||||
hudPalettesFrame2.pack(expand=True, anchor=E)
|
|
||||||
swordPalettesFrame2.pack(expand=True, anchor=E)
|
|
||||||
shieldPalettesFrame2.pack(expand=True, anchor=E)
|
|
||||||
|
|
||||||
bottomFrame2 = Frame(topFrame2)
|
|
||||||
|
|
||||||
def adjustRom():
|
|
||||||
guiargs = Namespace()
|
|
||||||
guiargs.heartbeep = heartbeepVar.get()
|
|
||||||
guiargs.heartcolor = heartcolorVar.get()
|
|
||||||
guiargs.fastmenu = fastMenuVar.get()
|
|
||||||
guiargs.ow_palettes = owPalettesVar.get()
|
|
||||||
guiargs.uw_palettes = uwPalettesVar.get()
|
|
||||||
guiargs.hud_palettes = hudPalettesVar.get()
|
|
||||||
guiargs.sword_palettes = swordPalettesVar.get()
|
|
||||||
guiargs.shield_palettes = shieldPalettesVar.get()
|
|
||||||
guiargs.quickswap = bool(quickSwapVar.get())
|
|
||||||
guiargs.disablemusic = bool(disableMusicVar.get())
|
|
||||||
guiargs.rom = romVar2.get()
|
|
||||||
guiargs.baserom = romVar.get()
|
|
||||||
guiargs.sprite = sprite
|
|
||||||
try:
|
|
||||||
guiargs, path = adjust(args=guiargs)
|
|
||||||
except Exception as e:
|
|
||||||
logging.exception(e)
|
|
||||||
messagebox.showerror(title="Error while adjusting Rom", message=str(e))
|
|
||||||
else:
|
|
||||||
messagebox.showinfo(title="Success", message="Rom patched successfully")
|
|
||||||
from Utils import persistent_store
|
|
||||||
from Rom import Sprite
|
|
||||||
if isinstance(guiargs.sprite, Sprite):
|
|
||||||
guiargs.sprite = guiargs.sprite.name
|
|
||||||
persistent_store("adjuster", "last_settings_3", guiargs)
|
|
||||||
|
|
||||||
adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
|
|
||||||
|
|
||||||
adjustButton.pack(side=LEFT, padx=(5, 0))
|
|
||||||
|
|
||||||
drowDownFrame2.pack(side=LEFT, pady=(0, 40))
|
|
||||||
rightHalfFrame2.pack(side=RIGHT)
|
|
||||||
topFrame2.pack(side=TOP, pady=70)
|
|
||||||
bottomFrame2.pack(side=BOTTOM, pady=(180, 0))
|
|
||||||
|
|
||||||
# Custom Controls
|
# Custom Controls
|
||||||
|
|
||||||
topFrame3 = Frame(customWindow)
|
topFrame3 = Frame(customWindow)
|
||||||
|
@ -1490,8 +1206,9 @@ def guiMain(args=None):
|
||||||
keyshuffleVar.set(args.keyshuffle)
|
keyshuffleVar.set(args.keyshuffle)
|
||||||
bigkeyshuffleVar.set(args.bigkeyshuffle)
|
bigkeyshuffleVar.set(args.bigkeyshuffle)
|
||||||
retroVar.set(args.retro)
|
retroVar.set(args.retro)
|
||||||
quickSwapVar.set(int(args.quickswap))
|
rom_vars.quickSwapVar.set(int(args.quickswap))
|
||||||
disableMusicVar.set(int(args.disablemusic))
|
rom_vars.disableMusicVar.set(int(args.disablemusic))
|
||||||
|
rom_vars.disableFlashingVar.set(int(args.reduceflashing))
|
||||||
if args.count:
|
if args.count:
|
||||||
countVar.set(str(args.count))
|
countVar.set(str(args.count))
|
||||||
if args.seed:
|
if args.seed:
|
||||||
|
@ -1512,10 +1229,10 @@ def guiMain(args=None):
|
||||||
crystalsGanonVar.set(args.crystals_ganon)
|
crystalsGanonVar.set(args.crystals_ganon)
|
||||||
algorithmVar.set(args.algorithm)
|
algorithmVar.set(args.algorithm)
|
||||||
shuffleVar.set(args.shuffle)
|
shuffleVar.set(args.shuffle)
|
||||||
heartbeepVar.set(args.heartbeep)
|
rom_vars.heartbeepVar.set(args.heartbeep)
|
||||||
fastMenuVar.set(args.fastmenu)
|
rom_vars.fastMenuVar.set(args.fastmenu)
|
||||||
logicVar.set(args.logic)
|
logicVar.set(args.logic)
|
||||||
romVar.set(args.rom)
|
rom_vars.romVar.set(args.rom)
|
||||||
shuffleGanonVar.set(args.shuffleganon)
|
shuffleGanonVar.set(args.shuffleganon)
|
||||||
hintsVar.set(args.hints)
|
hintsVar.set(args.hints)
|
||||||
if args.sprite is not None:
|
if args.sprite is not None:
|
||||||
|
@ -1523,11 +1240,165 @@ def guiMain(args=None):
|
||||||
|
|
||||||
mainWindow.mainloop()
|
mainWindow.mainloop()
|
||||||
|
|
||||||
|
def get_rom_frame(parent=None):
|
||||||
|
romFrame = Frame(parent)
|
||||||
|
baseRomLabel = Label(romFrame, text='LttP Base Rom: ')
|
||||||
|
romVar = StringVar(value="Zelda no Densetsu - Kamigami no Triforce (Japan).sfc")
|
||||||
|
romEntry = Entry(romFrame, textvariable=romVar)
|
||||||
|
|
||||||
|
def RomSelect():
|
||||||
|
rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc")), ("All Files", "*")])
|
||||||
|
import Patch
|
||||||
|
try:
|
||||||
|
Patch.get_base_rom_bytes(rom) # throws error on checksum fail
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(e)
|
||||||
|
messagebox.showerror(title="Error while reading ROM", message=str(e))
|
||||||
|
else:
|
||||||
|
romVar.set(rom)
|
||||||
|
romSelectButton['state'] = "disabled"
|
||||||
|
romSelectButton["text"] = "ROM verified"
|
||||||
|
romSelectButton = Button(romFrame, text='Select Rom', command=RomSelect)
|
||||||
|
|
||||||
|
baseRomLabel.pack(side=LEFT)
|
||||||
|
romEntry.pack(side=LEFT, expand=True, fill=X)
|
||||||
|
romSelectButton.pack(side=LEFT)
|
||||||
|
romFrame.pack(side=TOP, expand=True, fill=X)
|
||||||
|
|
||||||
|
return romFrame, romVar
|
||||||
|
|
||||||
|
|
||||||
|
def get_rom_options_frame(parent=None):
|
||||||
|
romOptionsFrame = LabelFrame(parent, text="Rom options")
|
||||||
|
romOptionsFrame.columnconfigure(0, weight=1)
|
||||||
|
romOptionsFrame.columnconfigure(1, weight=1)
|
||||||
|
for i in range(5):
|
||||||
|
romOptionsFrame.rowconfigure(i, weight=1)
|
||||||
|
vars = Namespace()
|
||||||
|
|
||||||
|
vars.disableMusicVar = IntVar()
|
||||||
|
disableMusicCheckbutton = Checkbutton(romOptionsFrame, text="Disable music", variable=vars.disableMusicVar)
|
||||||
|
disableMusicCheckbutton.grid(row=0, column=0, sticky=E)
|
||||||
|
|
||||||
|
vars.disableFlashingVar = IntVar(value=1)
|
||||||
|
disableFlashingCheckbutton = Checkbutton(romOptionsFrame, text="Disable flashing (anti-epilepsy)", variable=vars.disableFlashingVar)
|
||||||
|
disableFlashingCheckbutton.grid(row=6, column=0, sticky=E)
|
||||||
|
|
||||||
|
spriteDialogFrame = Frame(romOptionsFrame)
|
||||||
|
spriteDialogFrame.grid(row=0, column=1)
|
||||||
|
baseSpriteLabel = Label(spriteDialogFrame, text='Sprite:')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vars.spriteNameVar = StringVar()
|
||||||
|
vars.sprite = None
|
||||||
|
def set_sprite(sprite_param):
|
||||||
|
nonlocal vars
|
||||||
|
if isinstance(sprite_param, str):
|
||||||
|
vars.sprite = sprite_param
|
||||||
|
vars.spriteNameVar.set(sprite_param)
|
||||||
|
elif sprite_param is None or not sprite_param.valid:
|
||||||
|
vars.sprite = None
|
||||||
|
vars.spriteNameVar.set('(unchanged)')
|
||||||
|
else:
|
||||||
|
vars.sprite = sprite_param
|
||||||
|
vars.spriteNameVar.set(vars.sprite.name)
|
||||||
|
|
||||||
|
set_sprite(None)
|
||||||
|
vars.spriteNameVar.set('(unchanged)')
|
||||||
|
spriteEntry = Label(spriteDialogFrame, textvariable=vars.spriteNameVar)
|
||||||
|
|
||||||
|
def SpriteSelect():
|
||||||
|
SpriteSelector(parent, set_sprite)
|
||||||
|
|
||||||
|
spriteSelectButton = Button(spriteDialogFrame, text='...', command=SpriteSelect)
|
||||||
|
|
||||||
|
baseSpriteLabel.pack(side=LEFT)
|
||||||
|
spriteEntry.pack(side=LEFT)
|
||||||
|
spriteSelectButton.pack(side=LEFT)
|
||||||
|
|
||||||
|
vars.quickSwapVar = IntVar(value=1)
|
||||||
|
quickSwapCheckbutton = Checkbutton(romOptionsFrame, text="L/R Quickswapping", variable=vars.quickSwapVar)
|
||||||
|
quickSwapCheckbutton.grid(row=1, column=0, sticky=E)
|
||||||
|
|
||||||
|
fastMenuFrame = Frame(romOptionsFrame)
|
||||||
|
fastMenuFrame.grid(row=1, column=1, sticky=E)
|
||||||
|
fastMenuLabel = Label(fastMenuFrame, text='Menu speed')
|
||||||
|
fastMenuLabel.pack(side=LEFT)
|
||||||
|
vars.fastMenuVar = StringVar()
|
||||||
|
vars.fastMenuVar.set('normal')
|
||||||
|
fastMenuOptionMenu = OptionMenu(fastMenuFrame, vars.fastMenuVar, 'normal', 'instant', 'double', 'triple', 'quadruple', 'half')
|
||||||
|
fastMenuOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
heartcolorFrame = Frame(romOptionsFrame)
|
||||||
|
heartcolorFrame.grid(row=2, column=0, sticky=E)
|
||||||
|
heartcolorLabel = Label(heartcolorFrame, text='Heart color')
|
||||||
|
heartcolorLabel.pack(side=LEFT)
|
||||||
|
vars.heartcolorVar = StringVar()
|
||||||
|
vars.heartcolorVar.set('red')
|
||||||
|
heartcolorOptionMenu = OptionMenu(heartcolorFrame, vars.heartcolorVar, 'red', 'blue', 'green', 'yellow', 'random')
|
||||||
|
heartcolorOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
heartbeepFrame = Frame(romOptionsFrame)
|
||||||
|
heartbeepFrame.grid(row=2, column=1, sticky=E)
|
||||||
|
heartbeepLabel = Label(heartbeepFrame, text='Heartbeep')
|
||||||
|
heartbeepLabel.pack(side=LEFT)
|
||||||
|
vars.heartbeepVar = StringVar()
|
||||||
|
vars.heartbeepVar.set('normal')
|
||||||
|
heartbeepOptionMenu = OptionMenu(heartbeepFrame, vars.heartbeepVar, 'double', 'normal', 'half', 'quarter', 'off')
|
||||||
|
heartbeepOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
owPalettesFrame = Frame(romOptionsFrame)
|
||||||
|
owPalettesFrame.grid(row=3, column=0, sticky=E)
|
||||||
|
owPalettesLabel = Label(owPalettesFrame, text='Overworld palettes')
|
||||||
|
owPalettesLabel.pack(side=LEFT)
|
||||||
|
vars.owPalettesVar = StringVar()
|
||||||
|
vars.owPalettesVar.set('default')
|
||||||
|
owPalettesOptionMenu = OptionMenu(owPalettesFrame, vars.owPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||||
|
owPalettesOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
uwPalettesFrame = Frame(romOptionsFrame)
|
||||||
|
uwPalettesFrame.grid(row=3, column=1, sticky=E)
|
||||||
|
uwPalettesLabel = Label(uwPalettesFrame, text='Dungeon palettes')
|
||||||
|
uwPalettesLabel.pack(side=LEFT)
|
||||||
|
vars.uwPalettesVar = StringVar()
|
||||||
|
vars.uwPalettesVar.set('default')
|
||||||
|
uwPalettesOptionMenu = OptionMenu(uwPalettesFrame, vars.uwPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||||
|
uwPalettesOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
hudPalettesFrame = Frame(romOptionsFrame)
|
||||||
|
hudPalettesFrame.grid(row=4, column=0, sticky=E)
|
||||||
|
hudPalettesLabel = Label(hudPalettesFrame, text='HUD palettes')
|
||||||
|
hudPalettesLabel.pack(side=LEFT)
|
||||||
|
vars.hudPalettesVar = StringVar()
|
||||||
|
vars.hudPalettesVar.set('default')
|
||||||
|
hudPalettesOptionMenu = OptionMenu(hudPalettesFrame, vars.hudPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||||
|
hudPalettesOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
swordPalettesFrame = Frame(romOptionsFrame)
|
||||||
|
swordPalettesFrame.grid(row=4, column=1, sticky=E)
|
||||||
|
swordPalettesLabel = Label(swordPalettesFrame, text='Sword palettes')
|
||||||
|
swordPalettesLabel.pack(side=LEFT)
|
||||||
|
vars.swordPalettesVar = StringVar()
|
||||||
|
vars.swordPalettesVar.set('default')
|
||||||
|
swordPalettesOptionMenu = OptionMenu(swordPalettesFrame, vars.swordPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||||
|
swordPalettesOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
shieldPalettesFrame = Frame(romOptionsFrame)
|
||||||
|
shieldPalettesFrame.grid(row=5, column=0, sticky=E)
|
||||||
|
shieldPalettesLabel = Label(shieldPalettesFrame, text='Shield palettes')
|
||||||
|
shieldPalettesLabel.pack(side=LEFT)
|
||||||
|
vars.shieldPalettesVar = StringVar()
|
||||||
|
vars.shieldPalettesVar.set('default')
|
||||||
|
shieldPalettesOptionMenu = OptionMenu(shieldPalettesFrame, vars.shieldPalettesVar, 'default', 'random', 'blackout', 'grayscale', 'negative', 'classic', 'dizzy', 'sick', 'puke')
|
||||||
|
shieldPalettesOptionMenu.pack(side=LEFT)
|
||||||
|
|
||||||
|
return romOptionsFrame, vars, set_sprite
|
||||||
|
|
||||||
|
|
||||||
class SpriteSelector():
|
class SpriteSelector():
|
||||||
def __init__(self, parent, callback, adjuster=False):
|
def __init__(self, parent, callback, adjuster=False):
|
||||||
if is_bundled():
|
self.deploy_icons()
|
||||||
self.deploy_icons()
|
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.window = Toplevel(parent)
|
self.window = Toplevel(parent)
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
|
|
|
@ -25,7 +25,7 @@ class BackgroundTask(object):
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
#safe to call from worker
|
# safe to call from worker
|
||||||
def queue_event(self, event):
|
def queue_event(self, event):
|
||||||
self.queue.put(event)
|
self.queue.put(event)
|
||||||
|
|
||||||
|
|
|
@ -935,7 +935,7 @@ async def process_server_cmd(ctx: Context, cmd: str, args: typing.Optional[dict]
|
||||||
found = ReceivedItem(*args["item"])
|
found = ReceivedItem(*args["item"])
|
||||||
ctx.ui_node.notify_item_found(ctx.player_names[found.player], get_item_name_from_id(found.item),
|
ctx.ui_node.notify_item_found(ctx.player_names[found.player], get_item_name_from_id(found.item),
|
||||||
get_location_name_from_address(found.location), found.player == ctx.slot,
|
get_location_name_from_address(found.location), found.player == ctx.slot,
|
||||||
True if get_item_name_from_id(found.item) in Items.progression_items else False)
|
get_item_name_from_id(found.item) in Items.progression_items)
|
||||||
item = color_item(found.item, found.player == ctx.slot)
|
item = color_item(found.item, found.player == ctx.slot)
|
||||||
player_sent = color(ctx.player_names[found.player], 'yellow' if found.player != ctx.slot else 'magenta')
|
player_sent = color(ctx.player_names[found.player], 'yellow' if found.player != ctx.slot else 'magenta')
|
||||||
logging.info('%s found %s (%s)' % (player_sent, item, color(get_location_name_from_address(found.location),
|
logging.info('%s found %s (%s)' % (player_sent, item, color(get_location_name_from_address(found.location),
|
||||||
|
@ -1066,7 +1066,7 @@ class ClientCommandProcessor(CommandProcessor):
|
||||||
self.ctx.ui_node.notify_item_received(self.ctx.player_names[item.player], get_item_name_from_id(item.item),
|
self.ctx.ui_node.notify_item_received(self.ctx.player_names[item.player], get_item_name_from_id(item.item),
|
||||||
get_location_name_from_address(item.location), index,
|
get_location_name_from_address(item.location), index,
|
||||||
len(self.ctx.items_received),
|
len(self.ctx.items_received),
|
||||||
True if get_item_name_from_id(item.item) in Items.progression_items else False)
|
get_item_name_from_id(item.item) in Items.progression_items)
|
||||||
logging.info('%s from %s (%s) (%d/%d in list)' % (
|
logging.info('%s from %s (%s) (%d/%d in list)' % (
|
||||||
color(get_item_name_from_id(item.item), 'red', 'bold'),
|
color(get_item_name_from_id(item.item), 'red', 'bold'),
|
||||||
color(self.ctx.player_names[item.player], 'yellow'),
|
color(self.ctx.player_names[item.player], 'yellow'),
|
||||||
|
@ -1327,7 +1327,7 @@ async def game_watcher(ctx: Context):
|
||||||
ctx.ui_node.notify_item_received(ctx.player_names[item.player], get_item_name_from_id(item.item),
|
ctx.ui_node.notify_item_received(ctx.player_names[item.player], get_item_name_from_id(item.item),
|
||||||
get_location_name_from_address(item.location), recv_index + 1,
|
get_location_name_from_address(item.location), recv_index + 1,
|
||||||
len(ctx.items_received),
|
len(ctx.items_received),
|
||||||
True if get_item_name_from_id(item.item) in Items.progression_items else False)
|
get_item_name_from_id(item.item) in Items.progression_items)
|
||||||
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
logging.info('Received %s from %s (%s) (%d/%d in list)' % (
|
||||||
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
color(get_item_name_from_id(item.item), 'red', 'bold'), color(ctx.player_names[item.player], 'yellow'),
|
||||||
get_location_name_from_address(item.location), recv_index + 1, len(ctx.items_received)))
|
get_location_name_from_address(item.location), recv_index + 1, len(ctx.items_received)))
|
||||||
|
|
|
@ -325,6 +325,7 @@ def roll_linked_options(weights: dict) -> dict:
|
||||||
|
|
||||||
def roll_triggers(weights: dict) -> dict:
|
def roll_triggers(weights: dict) -> dict:
|
||||||
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
||||||
|
weights["_Generator_Version"] = "Main" # Some means for triggers to know if the seed is on main or doors.
|
||||||
for option_set in weights["triggers"]:
|
for option_set in weights["triggers"]:
|
||||||
try:
|
try:
|
||||||
key = get_choice("option_name", option_set)
|
key = get_choice("option_name", option_set)
|
||||||
|
@ -691,6 +692,7 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
|
||||||
ret.disablemusic = get_choice('disablemusic', romweights, False)
|
ret.disablemusic = get_choice('disablemusic', romweights, False)
|
||||||
ret.quickswap = get_choice('quickswap', romweights, True)
|
ret.quickswap = get_choice('quickswap', romweights, True)
|
||||||
ret.fastmenu = get_choice('menuspeed', romweights, "normal")
|
ret.fastmenu = get_choice('menuspeed', romweights, "normal")
|
||||||
|
ret.reduceflashing = get_choice('reduceflashing', romweights, False)
|
||||||
ret.heartcolor = get_choice('heartcolor', romweights, "red")
|
ret.heartcolor = get_choice('heartcolor', romweights, "red")
|
||||||
ret.heartbeep = convert_to_on_off(get_choice('heartbeep', romweights, "normal"))
|
ret.heartbeep = convert_to_on_off(get_choice('heartbeep', romweights, "normal"))
|
||||||
ret.ow_palettes = get_choice('ow_palettes', romweights, "default")
|
ret.ow_palettes = get_choice('ow_palettes', romweights, "default")
|
||||||
|
|
4
Utils.py
4
Utils.py
|
@ -341,8 +341,8 @@ def get_adjuster_settings(romfile: str) -> typing.Tuple[str, bool]:
|
||||||
f"Enter yes, no or never: ")
|
f"Enter yes, no or never: ")
|
||||||
if adjust_wanted and adjust_wanted.startswith("y"):
|
if adjust_wanted and adjust_wanted.startswith("y"):
|
||||||
adjusted = True
|
adjusted = True
|
||||||
import AdjusterMain
|
import Adjuster
|
||||||
_, romfile = AdjusterMain.adjust(adjuster_settings)
|
_, romfile = Adjuster.adjust(adjuster_settings)
|
||||||
elif adjust_wanted and "never" in adjust_wanted:
|
elif adjust_wanted and "never" in adjust_wanted:
|
||||||
persistent_store("adjuster", "never_adjust", True)
|
persistent_store("adjuster", "never_adjust", True)
|
||||||
return romfile, False
|
return romfile, False
|
||||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
||||||
import logging
|
import logging
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
|
import concurrent.futures
|
||||||
import sys
|
import sys
|
||||||
import typing
|
import typing
|
||||||
import time
|
import time
|
||||||
|
@ -135,6 +136,7 @@ def autohost(config: dict):
|
||||||
|
|
||||||
multiworlds = {}
|
multiworlds = {}
|
||||||
|
|
||||||
|
guardians = concurrent.futures.ThreadPoolExecutor(2, thread_name_prefix="Guardian")
|
||||||
|
|
||||||
class MultiworldInstance():
|
class MultiworldInstance():
|
||||||
def __init__(self, room: Room, config: dict):
|
def __init__(self, room: Room, config: dict):
|
||||||
|
@ -152,12 +154,18 @@ class MultiworldInstance():
|
||||||
args=(self.room_id, self.ponyconfig),
|
args=(self.room_id, self.ponyconfig),
|
||||||
name="MultiHost")
|
name="MultiHost")
|
||||||
self.process.start()
|
self.process.start()
|
||||||
|
self.guardian = guardians.submit(self._collect)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if self.process:
|
if self.process:
|
||||||
self.process.terminate()
|
self.process.terminate()
|
||||||
self.process = None
|
self.process = None
|
||||||
|
|
||||||
|
def _collect(self):
|
||||||
|
self.process.join() # wait for process to finish
|
||||||
|
self.process = None
|
||||||
|
self.guardian = None
|
||||||
|
|
||||||
|
|
||||||
from .models import Room, Generation, STATE_QUEUED, STATE_STARTED, STATE_ERROR, db, Seed
|
from .models import Room, Generation, STATE_QUEUED, STATE_STARTED, STATE_ERROR, db, Seed
|
||||||
from .customserver import run_server_process
|
from .customserver import run_server_process
|
||||||
|
|
|
@ -55,7 +55,7 @@ window.addEventListener('load', () => {
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
adjustTableHeight();
|
adjustTableHeight();
|
||||||
tables.draw()
|
tables.draw();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".table-wrapper").scrollsync({
|
$(".table-wrapper").scrollsync({
|
||||||
|
|
|
@ -1602,6 +1602,26 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"reduceflashing": {
|
||||||
|
"keyString": "rom.reduceflashing",
|
||||||
|
"friendlyName": "Full-Screen Flashing Effects",
|
||||||
|
"description": "Enable or disable full-screen flashing effects in game.",
|
||||||
|
"inputType": "range",
|
||||||
|
"subOptions": {
|
||||||
|
"on": {
|
||||||
|
"keyString": "rom.reduceflashing.on",
|
||||||
|
"friendlyName": "Disabled",
|
||||||
|
"description": "Disables flashing.",
|
||||||
|
"defaultValue": 50
|
||||||
|
},
|
||||||
|
"off": {
|
||||||
|
"keyString": "rom.reduceflashing.off",
|
||||||
|
"friendlyName": "Enabled",
|
||||||
|
"description": "Enables flashing.",
|
||||||
|
"defaultValue": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"quickswap": {
|
"quickswap": {
|
||||||
"keyString": "rom.quickswap",
|
"keyString": "rom.quickswap",
|
||||||
"friendlyName": "Item Quick-Swap",
|
"friendlyName": "Item Quick-Swap",
|
||||||
|
@ -1797,7 +1817,7 @@
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
},
|
},
|
||||||
"puke": {
|
"puke": {
|
||||||
"keyString": "rom.ow_palettes.Puke",
|
"keyString": "rom.ow_palettes.puke",
|
||||||
"friendlyName": "Puke",
|
"friendlyName": "Puke",
|
||||||
"description": "No logic at all.",
|
"description": "No logic at all.",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
|
@ -1859,7 +1879,7 @@
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
},
|
},
|
||||||
"puke": {
|
"puke": {
|
||||||
"keyString": "rom.uw_palettes.Puke",
|
"keyString": "rom.uw_palettes.puke",
|
||||||
"friendlyName": "Puke",
|
"friendlyName": "Puke",
|
||||||
"description": "No logic at all.",
|
"description": "No logic at all.",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
|
@ -1921,7 +1941,7 @@
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
},
|
},
|
||||||
"puke": {
|
"puke": {
|
||||||
"keyString": "rom.hud_palettes.Puke",
|
"keyString": "rom.hud_palettes.puke",
|
||||||
"friendlyName": "Puke",
|
"friendlyName": "Puke",
|
||||||
"description": "No logic at all.",
|
"description": "No logic at all.",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
|
@ -1983,7 +2003,7 @@
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
},
|
},
|
||||||
"puke": {
|
"puke": {
|
||||||
"keyString": "rom.shield_palettes.Puke",
|
"keyString": "rom.shield_palettes.puke",
|
||||||
"friendlyName": "Puke",
|
"friendlyName": "Puke",
|
||||||
"description": "No logic at all.",
|
"description": "No logic at all.",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
|
@ -2045,7 +2065,7 @@
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
},
|
},
|
||||||
"puke": {
|
"puke": {
|
||||||
"keyString": "rom.sword_palettes.Puke",
|
"keyString": "rom.sword_palettes.puke",
|
||||||
"friendlyName": "Puke",
|
"friendlyName": "Puke",
|
||||||
"description": "No logic at all.",
|
"description": "No logic at all.",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
# For use with the weighted-settings page on the website. Changing this value will cause all users to be prompted
|
# For use with the weighted-settings page on the website. Changing this value will cause all users to be prompted
|
||||||
# to update their settings. The version number should match the current released version number, and the revision
|
# to update their settings. The version number should match the current released version number, and the revision
|
||||||
# should be updated manually by whoever edits this file.
|
# should be updated manually by whoever edits this file.
|
||||||
ws_version: 4.0.1 rev0
|
ws_version: 4.0.1 rev1
|
||||||
|
|
||||||
description: Template Name # Used to describe your yaml. Useful if you have multiple files
|
description: Template Name # Used to describe your yaml. Useful if you have multiple files
|
||||||
name: YourName # Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
|
name: YourName # Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
|
||||||
|
@ -363,6 +363,9 @@ rom:
|
||||||
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
||||||
on: 50
|
on: 50
|
||||||
off: 0
|
off: 0
|
||||||
|
reduceflashing: # Reduces instances of flashing such as lightning attacks, weather, ether and more.
|
||||||
|
on: 50
|
||||||
|
off: 0
|
||||||
menuspeed: # Controls how fast the item menu opens and closes
|
menuspeed: # Controls how fast the item menu opens and closes
|
||||||
normal: 50
|
normal: 50
|
||||||
instant: 0
|
instant: 0
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends 'tablepage.html' %}
|
{% extends 'tablepage.html' %}
|
||||||
{% block head %}
|
{% block head %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<title>Multiworld Tracker for Room {{ room.id }}</title>
|
<title>Multiworld Tracker</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/tracker.css") }}"/>
|
<link rel="stylesheet" type="text/css" href="{{ static_autoversion("styles/tracker.css") }}"/>
|
||||||
<script type="application/ecmascript" src="{{ static_autoversion("assets/jquery.scrollsync.js") }}"></script>
|
<script type="application/ecmascript" src="{{ static_autoversion("assets/jquery.scrollsync.js") }}"></script>
|
||||||
<script type="application/ecmascript" src="{{ static_autoversion("assets/tracker.js") }}"></script>
|
<script type="application/ecmascript" src="{{ static_autoversion("assets/tracker.js") }}"></script>
|
||||||
|
@ -151,7 +151,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for team, hints in hints.items() %}
|
{% for team, hints in hints.items() %}
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
<table class="table non-unique-item-table">
|
<table class="table non-unique-item-table" data-order='[[5, "asc"], [0, "asc"]]'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Finder</th>
|
<th>Finder</th>
|
||||||
|
|
12
WebUI.py
12
WebUI.py
|
@ -61,9 +61,9 @@ class WebUiClient(Node, logging.Handler):
|
||||||
'recipient': recipient,
|
'recipient': recipient,
|
||||||
'item': item,
|
'item': item,
|
||||||
'location': location,
|
'location': location,
|
||||||
'iAmFinder': 1 if i_am_finder else 0,
|
'iAmFinder': int(i_am_finder),
|
||||||
'iAmRecipient': 1 if i_am_recipient else 0,
|
'iAmRecipient': int(i_am_recipient),
|
||||||
'itemIsUnique': 1 if item_is_unique else 0,
|
'itemIsUnique': int(item_is_unique),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def notify_item_found(self, finder: str, item: str, location: str, i_am_finder: bool, item_is_unique: bool = False):
|
def notify_item_found(self, finder: str, item: str, location: str, i_am_finder: bool, item_is_unique: bool = False):
|
||||||
|
@ -71,8 +71,8 @@ class WebUiClient(Node, logging.Handler):
|
||||||
'finder': finder,
|
'finder': finder,
|
||||||
'item': item,
|
'item': item,
|
||||||
'location': location,
|
'location': location,
|
||||||
'iAmFinder': 1 if i_am_finder else 0,
|
'iAmFinder': int(i_am_finder),
|
||||||
'itemIsUnique': 1 if item_is_unique else 0,
|
'itemIsUnique': int(item_is_unique),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def notify_item_received(self, finder: str, item: str, location: str, item_index: int, queue_length: int,
|
def notify_item_received(self, finder: str, item: str, location: str, item_index: int, queue_length: int,
|
||||||
|
@ -83,7 +83,7 @@ class WebUiClient(Node, logging.Handler):
|
||||||
'location': location,
|
'location': location,
|
||||||
'itemIndex': item_index,
|
'itemIndex': item_index,
|
||||||
'queueLength': queue_length,
|
'queueLength': queue_length,
|
||||||
'itemIsUnique': 1 if item_is_unique else 0,
|
'itemIsUnique': int(item_is_unique),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def send_hint(self, finder, recipient, item, location, found, i_am_finder: bool, i_am_recipient: bool,
|
def send_hint(self, finder, recipient, item, location, found, i_am_finder: bool, i_am_recipient: bool,
|
||||||
|
|
|
@ -87,6 +87,9 @@ entrance_shuffle: # Documentation: https://alttpr.com/en/options#entrance_shuffl
|
||||||
full: 0 # Less strict than restricted
|
full: 0 # Less strict than restricted
|
||||||
crossed: 0 # Less strict than full
|
crossed: 0 # Less strict than full
|
||||||
insanity: 0 # Very few grouping rules. Good luck
|
insanity: 0 # Very few grouping rules. Good luck
|
||||||
|
# you can also define entrance shuffle seed, like so:
|
||||||
|
crossed-1000: 0 # using this method, you can have the same layout as another player and share entrance information
|
||||||
|
# however, many other settings like logic, world state, retro etc. may affect the shuffle result as well.
|
||||||
goals:
|
goals:
|
||||||
ganon: 50 # Climb GT, defeat Agahnim 2, and then kill Ganon
|
ganon: 50 # Climb GT, defeat Agahnim 2, and then kill Ganon
|
||||||
fast_ganon: 0 # Only killing Ganon is required. However, items may still be placed in GT
|
fast_ganon: 0 # Only killing Ganon is required. However, items may still be placed in GT
|
||||||
|
@ -401,6 +404,9 @@ rom:
|
||||||
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
||||||
on: 50
|
on: 50
|
||||||
off: 0
|
off: 0
|
||||||
|
reduceflashing: # Reduces instances of flashing such as lightning attacks, weather, ether and more.
|
||||||
|
on: 50
|
||||||
|
off: 0
|
||||||
menuspeed: # Controls how fast the item menu opens and closes
|
menuspeed: # Controls how fast the item menu opens and closes
|
||||||
normal: 50
|
normal: 50
|
||||||
instant: 0
|
instant: 0
|
||||||
|
|
|
@ -3,7 +3,7 @@ websockets>=8.1
|
||||||
PyYAML>=5.4.1
|
PyYAML>=5.4.1
|
||||||
fuzzywuzzy>=0.18.0
|
fuzzywuzzy>=0.18.0
|
||||||
bsdiff4>=1.2.0
|
bsdiff4>=1.2.0
|
||||||
prompt_toolkit>=3.0.14
|
prompt_toolkit>=3.0.16
|
||||||
appdirs>=1.4.4
|
appdirs>=1.4.4
|
||||||
maseya-z3pr>=1.0.0rc1
|
maseya-z3pr>=1.0.0rc1
|
||||||
xxtea>=2.0.0.post0
|
xxtea>=2.0.0.post0
|
||||||
|
|
7
setup.py
7
setup.py
|
@ -48,8 +48,8 @@ def manifest_creation():
|
||||||
path = os.path.join(dirpath, filename)
|
path = os.path.join(dirpath, filename)
|
||||||
hashes[os.path.relpath(path, start=buildfolder)] = pool.submit(_threaded_hash, path)
|
hashes[os.path.relpath(path, start=buildfolder)] = pool.submit(_threaded_hash, path)
|
||||||
import json
|
import json
|
||||||
manifest = {"buildtime": buildtime.isoformat(sep=" ", timespec="seconds")}
|
manifest = {"buildtime": buildtime.isoformat(sep=" ", timespec="seconds"),
|
||||||
manifest["hashes"] = {path: hash.result() for path, hash in hashes.items()}
|
"hashes": {path: hash.result() for path, hash in hashes.items()}}
|
||||||
json.dump(manifest, open(manifestpath, "wt"), indent=4)
|
json.dump(manifest, open(manifestpath, "wt"), indent=4)
|
||||||
print("Created Manifest")
|
print("Created Manifest")
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ scripts = {"MultiClient.py": "ArchipelagoClient",
|
||||||
"MultiMystery.py": "ArchipelagoMultiMystery",
|
"MultiMystery.py": "ArchipelagoMultiMystery",
|
||||||
"MultiServer.py": "ArchipelagoServer",
|
"MultiServer.py": "ArchipelagoServer",
|
||||||
"gui.py": "ArchipelagoCreator",
|
"gui.py": "ArchipelagoCreator",
|
||||||
"Mystery.py": "ArchipelagoMystery"}
|
"Mystery.py": "ArchipelagoMystery",
|
||||||
|
"Adjuster.py": "ArchipelagoLttPAdjuster"}
|
||||||
|
|
||||||
exes = []
|
exes = []
|
||||||
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from Utils import output_path
|
|
||||||
from worlds.alttp.Rom import LocalRom, apply_rom_settings
|
|
||||||
|
|
||||||
|
|
||||||
def adjust(args):
|
|
||||||
start = time.perf_counter()
|
|
||||||
logger = logging.getLogger('Adjuster')
|
|
||||||
logger.info('Patching ROM.')
|
|
||||||
vanillaRom = args.baserom
|
|
||||||
if os.path.splitext(args.rom)[-1].lower() == '.apbp':
|
|
||||||
import Patch
|
|
||||||
meta, args.rom = Patch.create_rom_file(args.rom)
|
|
||||||
|
|
||||||
if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(args.rom)[-1].lower() == '.sfc':
|
|
||||||
rom = LocalRom(args.rom, patch=False, vanillaRom=vanillaRom)
|
|
||||||
else:
|
|
||||||
raise RuntimeError(
|
|
||||||
'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.')
|
|
||||||
palettes_options={}
|
|
||||||
palettes_options['dungeon']=args.uw_palettes
|
|
||||||
|
|
||||||
palettes_options['overworld']=args.ow_palettes
|
|
||||||
palettes_options['hud']=args.hud_palettes
|
|
||||||
palettes_options['sword']=args.sword_palettes
|
|
||||||
palettes_options['shield']=args.shield_palettes
|
|
||||||
# palettes_options['link']=args.link_palettesvera
|
|
||||||
|
|
||||||
apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic,
|
|
||||||
args.sprite, palettes_options)
|
|
||||||
path = output_path(f'{os.path.basename(args.rom)[:-4]}_adjusted.sfc')
|
|
||||||
rom.write_to_file(path)
|
|
||||||
|
|
||||||
logger.info('Done. Enjoy.')
|
|
||||||
logger.debug('Total Time: %s', time.perf_counter() - start)
|
|
||||||
|
|
||||||
return args, path
|
|
|
@ -251,6 +251,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
||||||
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
||||||
|
parser.add_argument('--enableflashing', help='Reenable flashing animations (unfriendly to epilepsy, always disabled in race roms)', action='store_false', dest="reduceflashing")
|
||||||
parser.add_argument('--mapshuffle', default=defval(False),
|
parser.add_argument('--mapshuffle', default=defval(False),
|
||||||
help='Maps are no longer restricted to their dungeons, but can be anywhere',
|
help='Maps are no longer restricted to their dungeons, but can be anywhere',
|
||||||
action='store_true')
|
action='store_true')
|
||||||
|
@ -377,6 +378,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
ret.plando_items = []
|
ret.plando_items = []
|
||||||
ret.plando_texts = {}
|
ret.plando_texts = {}
|
||||||
ret.plando_connections = []
|
ret.plando_connections = []
|
||||||
|
ret.er_seeds = {}
|
||||||
|
|
||||||
ret.glitch_boots = not ret.disable_glitch_boots
|
ret.glitch_boots = not ret.disable_glitch_boots
|
||||||
if ret.timer == "none":
|
if ret.timer == "none":
|
||||||
|
@ -407,10 +409,10 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
|
'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
|
||||||
"triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots",
|
"triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots",
|
||||||
"required_medallions",
|
"required_medallions",
|
||||||
"plando_items", "plando_texts", "plando_connections",
|
"plando_items", "plando_texts", "plando_connections", "er_seeds",
|
||||||
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
||||||
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
||||||
'restrict_dungeon_item_on_boss',
|
'restrict_dungeon_item_on_boss', 'reduceflashing',
|
||||||
'hud_palettes', 'sword_palettes', 'shield_palettes', 'link_palettes']:
|
'hud_palettes', 'sword_palettes', 'shield_palettes', 'link_palettes']:
|
||||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||||
if player == 1:
|
if player == 1:
|
||||||
|
|
|
@ -2054,10 +2054,11 @@ def connect_doors(world, doors, targets, player):
|
||||||
"""This works inplace"""
|
"""This works inplace"""
|
||||||
world.random.shuffle(doors)
|
world.random.shuffle(doors)
|
||||||
world.random.shuffle(targets)
|
world.random.shuffle(targets)
|
||||||
while doors:
|
placing = min(len(doors), len(targets))
|
||||||
door = doors.pop()
|
for door, target in zip(doors, targets):
|
||||||
target = targets.pop()
|
|
||||||
connect_entrance(world, door, target, player)
|
connect_entrance(world, door, target, player)
|
||||||
|
doors[:] = doors[placing:]
|
||||||
|
targets[:] = targets[placing:]
|
||||||
|
|
||||||
|
|
||||||
def skull_woods_shuffle(world, player):
|
def skull_woods_shuffle(world, player):
|
||||||
|
|
|
@ -93,11 +93,20 @@ def main(args, seed=None):
|
||||||
world.plando_items = args.plando_items.copy()
|
world.plando_items = args.plando_items.copy()
|
||||||
world.plando_texts = args.plando_texts.copy()
|
world.plando_texts = args.plando_texts.copy()
|
||||||
world.plando_connections = args.plando_connections.copy()
|
world.plando_connections = args.plando_connections.copy()
|
||||||
|
world.er_seeds = args.er_seeds.copy()
|
||||||
world.restrict_dungeon_item_on_boss = args.restrict_dungeon_item_on_boss.copy()
|
world.restrict_dungeon_item_on_boss = args.restrict_dungeon_item_on_boss.copy()
|
||||||
world.required_medallions = args.required_medallions.copy()
|
world.required_medallions = args.required_medallions.copy()
|
||||||
|
|
||||||
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
||||||
|
|
||||||
|
for player in range(1, world.players+1):
|
||||||
|
world.er_seeds[player] = str(world.random.randint(0, 2 ** 64))
|
||||||
|
|
||||||
|
if "-" in world.shuffle[player]:
|
||||||
|
shuffle, seed = world.shuffle[player].split("-")
|
||||||
|
world.shuffle[player] = shuffle
|
||||||
|
world.er_seeds[player] = seed
|
||||||
|
|
||||||
logger.info('Archipelago Version %s - Seed: %s\n', __version__, world.seed)
|
logger.info('Archipelago Version %s - Seed: %s\n', __version__, world.seed)
|
||||||
|
|
||||||
parsed_names = parse_player_names(args.names, world.players, args.teams)
|
parsed_names = parse_player_names(args.names, world.players, args.teams)
|
||||||
|
@ -171,12 +180,18 @@ def main(args, seed=None):
|
||||||
{"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}:
|
{"vanilla", "dungeonssimple", "dungeonsfull", "simple", "restricted", "full"}:
|
||||||
world.fix_fake_world[player] = False
|
world.fix_fake_world[player] = False
|
||||||
|
|
||||||
|
# seeded entrance shuffle
|
||||||
|
old_random = world.random
|
||||||
|
world.random = random.Random(world.er_seeds[player])
|
||||||
|
|
||||||
if world.mode[player] != 'inverted':
|
if world.mode[player] != 'inverted':
|
||||||
link_entrances(world, player)
|
link_entrances(world, player)
|
||||||
mark_light_world_regions(world, player)
|
mark_light_world_regions(world, player)
|
||||||
else:
|
else:
|
||||||
link_inverted_entrances(world, player)
|
link_inverted_entrances(world, player)
|
||||||
mark_dark_world_regions(world, player)
|
mark_dark_world_regions(world, player)
|
||||||
|
|
||||||
|
world.random = old_random
|
||||||
plando_connect(world, player)
|
plando_connect(world, player)
|
||||||
|
|
||||||
logger.info('Generating Item Pool.')
|
logger.info('Generating Item Pool.')
|
||||||
|
@ -260,7 +275,7 @@ def main(args, seed=None):
|
||||||
|
|
||||||
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player],
|
||||||
args.fastmenu[player], args.disablemusic[player], args.sprite[player],
|
args.fastmenu[player], args.disablemusic[player], args.sprite[player],
|
||||||
palettes_options, world, player, True)
|
palettes_options, world, player, True, reduceflashing=args.reduceflashing[player] if not args.race else True)
|
||||||
|
|
||||||
mcsb_name = ''
|
mcsb_name = ''
|
||||||
if all([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player],
|
if all([world.mapshuffle[player], world.compassshuffle[player], world.keyshuffle[player],
|
||||||
|
|
|
@ -1672,7 +1672,7 @@ def hud_format_text(text):
|
||||||
|
|
||||||
|
|
||||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite: str, palettes_options,
|
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite: str, palettes_options,
|
||||||
world=None, player=1, allow_random_on_event=False):
|
world=None, player=1, allow_random_on_event=False, reduceflashing=False):
|
||||||
local_random = random if not world else world.rom_seeds[player]
|
local_random = random if not world else world.rom_seeds[player]
|
||||||
|
|
||||||
# enable instant item menu
|
# enable instant item menu
|
||||||
|
@ -1697,6 +1697,23 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
||||||
else:
|
else:
|
||||||
rom.write_byte(0x180048, 0x08)
|
rom.write_byte(0x180048, 0x08)
|
||||||
|
|
||||||
|
|
||||||
|
# Reduce flashing by nopping out instructions
|
||||||
|
if reduceflashing:
|
||||||
|
rom.write_bytes(0x17E07, [0x06]) # reduce amount of colors changed, add this branch if we need to reduce more ""+ [0x80] + [(0x81-0x08)]""
|
||||||
|
rom.write_bytes(0x17EAB, [0xD0, 0x03, 0xA9, 0x40, 0x29, 0x60]) # nullifies aga lightning, cutscene, vitreous, bat, ether
|
||||||
|
# ONLY write to black values with this low pale blue to indicate flashing, that's IT. ""BNE + : LDA #$2940 : + : RTS""
|
||||||
|
rom.write_bytes(0x123FE, [0x72]) # set lightning flash in misery mire (and standard) to brightness 0x72
|
||||||
|
rom.write_bytes(0x3FA7B, [0x80, 0xac-0x7b]) # branch from palette writing lightning on death mountain
|
||||||
|
rom.write_byte(0x10817F, 0x01) # internal rom option
|
||||||
|
else:
|
||||||
|
rom.write_bytes(0x17E07, [0x00])
|
||||||
|
rom.write_bytes(0x17EAB, [0x85, 0x00, 0x29, 0x1F, 0x00, 0x18])
|
||||||
|
rom.write_bytes(0x123FE, [0x32]) # original weather flash value
|
||||||
|
rom.write_bytes(0x3FA7B, [0xc2, 0x20]) # rep #$20
|
||||||
|
rom.write_byte(0x10817F, 0x00) # internal rom option
|
||||||
|
|
||||||
|
|
||||||
rom.write_byte(0x18004B, 0x01 if quickswap else 0x00)
|
rom.write_byte(0x18004B, 0x01 if quickswap else 0x00)
|
||||||
|
|
||||||
rom.write_byte(0x0CFE18, 0x00 if disable_music else rom.orig_buffer[0x0CFE18] if rom.orig_buffer else 0x70)
|
rom.write_byte(0x0CFE18, 0x00 if disable_music else rom.orig_buffer[0x0CFE18] if rom.orig_buffer else 0x70)
|
||||||
|
|
|
@ -1884,7 +1884,7 @@ class TextTable(object):
|
||||||
text['item_get_whole_heart'] = CompressedTextMapper.convert("You got a whole ♥!!\nGo you!")
|
text['item_get_whole_heart'] = CompressedTextMapper.convert("You got a whole ♥!!\nGo you!")
|
||||||
text['item_get_sanc_heart'] = CompressedTextMapper.convert("You got a whole ♥!\nGo you!")
|
text['item_get_sanc_heart'] = CompressedTextMapper.convert("You got a whole ♥!\nGo you!")
|
||||||
text['fairy_fountain_refill'] = CompressedTextMapper.convert("Well done, lettuce have a cup of tea…")
|
text['fairy_fountain_refill'] = CompressedTextMapper.convert("Well done, lettuce have a cup of tea…")
|
||||||
text['death_mountain_bullied_no_pearl'] = CompressedTextMapper.convert("The following license applies to the base patch for the randomizer.\n\nCopyright (c) 2017 LLCoolDave\n\nCopyright (c) 2020 Berserker66\n\nCopyright (c) 2020 CaitSith2\n\nCopyright 2016, 2017 Equilateral IT\n\n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.")
|
text['death_mountain_bullied_no_pearl'] = CompressedTextMapper.convert("The following license applies to the base patch for the randomizer.\n\nCopyright (c) 2017 LLCoolDave\n\nCopyright (c) 2021 Berserker66\n\nCopyright (c) 2021 CaitSith2\n\nCopyright 2016, 2017 Equilateral IT\n\n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.")
|
||||||
text['death_mountain_bullied_with_pearl'] = CompressedTextMapper.convert("The software is provided \"as is\", without warranty of any kind, express or implied, including but not limited to the warranties of\nmerchantability,\nfitness for a particular purpose and\nnoninfringement.\nIn no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the software.")
|
text['death_mountain_bullied_with_pearl'] = CompressedTextMapper.convert("The software is provided \"as is\", without warranty of any kind, express or implied, including but not limited to the warranties of\nmerchantability,\nfitness for a particular purpose and\nnoninfringement.\nIn no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the software.")
|
||||||
text['death_mountain_bully_no_pearl'] = CompressedTextMapper.convert("Add garlic, ginger and apple and cook for 2 minutes. Add carrots, potatoes, garam masala and curry powder and stir well. Add tomato paste, stir well and slowly add red wine and bring to a boil. Add sugar, soy sauce and water, stir and bring to a boil again.")
|
text['death_mountain_bully_no_pearl'] = CompressedTextMapper.convert("Add garlic, ginger and apple and cook for 2 minutes. Add carrots, potatoes, garam masala and curry powder and stir well. Add tomato paste, stir well and slowly add red wine and bring to a boil. Add sugar, soy sauce and water, stir and bring to a boil again.")
|
||||||
text['death_mountain_bully_with_pearl'] = CompressedTextMapper.convert("I think I forgot how to smile…")
|
text['death_mountain_bully_with_pearl'] = CompressedTextMapper.convert("I think I forgot how to smile…")
|
||||||
|
|
Loading…
Reference in New Issue