Clean up enemizer cli argument and gui code
This commit is contained in:
4
CLI.py
4
CLI.py
@@ -199,7 +199,6 @@ def parse_settings():
|
||||
"shufflebosses": "none",
|
||||
"enemy_damage": "default",
|
||||
"enemy_health": "default",
|
||||
"enemizercli": os.path.join(".", "EnemizerCLI", "EnemizerCLI.Core"),
|
||||
|
||||
"shopsanity": False,
|
||||
'keydropshuffle': False,
|
||||
@@ -348,9 +347,6 @@ def parse_settings():
|
||||
"startinventoryarray": {}
|
||||
}
|
||||
|
||||
if sys.platform.lower().find("windows"):
|
||||
settings["enemizercli"] += ".exe"
|
||||
|
||||
# read saved settings file if it exists and set these
|
||||
settings_path = os.path.join(".", "resources", "user", "settings.json")
|
||||
settings = apply_settings_file(settings, settings_path)
|
||||
|
||||
2
Main.py
2
Main.py
@@ -17,7 +17,7 @@ from PotShuffle import shuffle_pots, shuffle_pot_switches
|
||||
from Regions import create_regions, create_shops, mark_light_dark_world_regions, create_dungeon_regions, adjust_locations
|
||||
from OverworldShuffle import create_dynamic_exits
|
||||
from EntranceShuffle import link_entrances
|
||||
from Rom import patch_rom, patch_race_rom, patch_enemizer, apply_rom_settings, LocalRom, JsonRom, get_hash_string
|
||||
from Rom import patch_rom, patch_race_rom, apply_rom_settings, LocalRom, JsonRom, get_hash_string
|
||||
from Doors import create_doors
|
||||
from DoorShuffle import link_doors, connect_portal, link_doors_prep
|
||||
from RoomData import create_rooms
|
||||
|
||||
@@ -33,7 +33,6 @@ def main():
|
||||
parser.add_argument('--suppress_meta', action='store_true')
|
||||
parser.add_argument('--bps', action='store_true')
|
||||
parser.add_argument('--rom')
|
||||
parser.add_argument('--enemizercli')
|
||||
parser.add_argument('--outputpath')
|
||||
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
||||
for player in range(1, multiargs.multi + 1):
|
||||
@@ -76,8 +75,6 @@ def main():
|
||||
|
||||
if args.rom:
|
||||
erargs.rom = args.rom
|
||||
if args.enemizercli:
|
||||
erargs.enemizercli = args.enemizercli
|
||||
|
||||
mw_settings = {'algorithm': False}
|
||||
|
||||
|
||||
163
Rom.py
163
Rom.py
@@ -217,169 +217,6 @@ def read_rom(stream):
|
||||
has_smc_header = True
|
||||
return buffer, has_smc_header
|
||||
|
||||
def patch_enemizer(world, player, rom, local_rom, enemizercli, random_sprite_on_hit):
|
||||
baserom_path = os.path.abspath(local_rom.file)
|
||||
unheadered_path = None
|
||||
if local_rom.has_smc_header:
|
||||
headered_path = baserom_path
|
||||
unheadered_path = baserom_path = os.path.abspath(output_path('unheadered_rom.sfc'))
|
||||
with open(headered_path, 'rb') as headered:
|
||||
with open(baserom_path, 'wb') as unheadered:
|
||||
unheadered.write(headered.read()[0x200:])
|
||||
basepatch_path = os.path.abspath(local_path(os.path.join("data","base2current.json")))
|
||||
enemizer_basepatch_path = os.path.join(os.path.dirname(enemizercli), "enemizerBasePatch.json")
|
||||
randopatch_path = os.path.abspath(output_path('enemizer_randopatch.json'))
|
||||
options_path = os.path.abspath(output_path('enemizer_options.json'))
|
||||
enemizer_output_path = os.path.abspath(output_path('enemizer_output.json'))
|
||||
|
||||
# write options file for enemizer
|
||||
options = {
|
||||
'RandomizeEnemies': world.enemy_shuffle[player] != 'none',
|
||||
'RandomizeEnemiesType': 3,
|
||||
'RandomizeBushEnemyChance': world.enemy_shuffle[player] in ['random', 'legacy'],
|
||||
'RandomizeEnemyHealthRange': world.enemy_health[player] != 'default',
|
||||
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[world.enemy_health[player]],
|
||||
'OHKO': False,
|
||||
'RandomizeEnemyDamage': world.enemy_damage[player] != 'default',
|
||||
'AllowEnemyZeroDamage': True,
|
||||
'ShuffleEnemyDamageGroups': world.enemy_damage[player] != 'default',
|
||||
'EnemyDamageChaosMode': world.enemy_damage[player] == 'random',
|
||||
'EasyModeEscape': False,
|
||||
'EnemiesAbsorbable': False,
|
||||
'AbsorbableSpawnRate': 10,
|
||||
'AbsorbableTypes': {
|
||||
'FullMagic': True, 'SmallMagic': True, 'Bomb_1': True, 'BlueRupee': True, 'Heart': True, 'BigKey': True, 'Key': True,
|
||||
'Fairy': True, 'Arrow_10': True, 'Arrow_5': True, 'Bomb_8': True, 'Bomb_4': True, 'GreenRupee': True, 'RedRupee': True
|
||||
},
|
||||
'BossMadness': False,
|
||||
'RandomizeBosses': True,
|
||||
'RandomizeBossesType': 0,
|
||||
'RandomizeBossHealth': False,
|
||||
'RandomizeBossHealthMinAmount': 0,
|
||||
'RandomizeBossHealthMaxAmount': 300,
|
||||
'RandomizeBossDamage': False,
|
||||
'RandomizeBossDamageMinAmount': 0,
|
||||
'RandomizeBossDamageMaxAmount': 200,
|
||||
'RandomizeBossBehavior': False,
|
||||
'RandomizeDungeonPalettes': False,
|
||||
'SetBlackoutMode': False,
|
||||
'RandomizeOverworldPalettes': False,
|
||||
'RandomizeSpritePalettes': False,
|
||||
'SetAdvancedSpritePalettes': False,
|
||||
'PukeMode': False,
|
||||
'NegativeMode': False,
|
||||
'GrayscaleMode': False,
|
||||
'GenerateSpoilers': False,
|
||||
'RandomizeLinkSpritePalette': False,
|
||||
'RandomizePots': False,
|
||||
'ShuffleMusic': False,
|
||||
'BootlegMagic': True,
|
||||
'CustomBosses': False,
|
||||
'AndyMode': False,
|
||||
'HeartBeepSpeed': 0,
|
||||
'AlternateGfx': False,
|
||||
'ShieldGraphics': "shield_gfx/normal.gfx",
|
||||
'SwordGraphics': "sword_gfx/normal.gfx",
|
||||
'BeeMizer': False,
|
||||
'BeesLevel': 0,
|
||||
'RandomizeTileTrapPattern': world.enemy_shuffle[player] in ['random', 'legacy'],
|
||||
'RandomizeTileTrapFloorTile': False,
|
||||
'AllowKillableThief': bool(random.randint(0, 1)) if world.enemy_shuffle[player] == 'legacy' else world.enemy_shuffle[player] != 'none',
|
||||
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
||||
'DebugMode': False,
|
||||
'DebugForceEnemy': False,
|
||||
'DebugForceEnemyId': 0,
|
||||
'DebugForceBoss': False,
|
||||
'DebugForceBossId': 0,
|
||||
'DebugOpenShutterDoors': False,
|
||||
'DebugForceEnemyDamageZero': False,
|
||||
'DebugShowRoomIdInRupeeCounter': False,
|
||||
'UseManualBosses': True,
|
||||
'ManualBosses': {
|
||||
'EasternPalace': world.get_dungeon("Eastern Palace", player).boss.enemizer_name,
|
||||
'DesertPalace': world.get_dungeon("Desert Palace", player).boss.enemizer_name,
|
||||
'TowerOfHera': world.get_dungeon("Tower of Hera", player).boss.enemizer_name,
|
||||
'AgahnimsTower': 'Agahnim',
|
||||
'PalaceOfDarkness': world.get_dungeon("Palace of Darkness", player).boss.enemizer_name,
|
||||
'SwampPalace': world.get_dungeon("Swamp Palace", player).boss.enemizer_name,
|
||||
'SkullWoods': world.get_dungeon("Skull Woods", player).boss.enemizer_name,
|
||||
'ThievesTown': world.get_dungeon("Thieves Town", player).boss.enemizer_name,
|
||||
'IcePalace': world.get_dungeon("Ice Palace", player).boss.enemizer_name,
|
||||
'MiseryMire': world.get_dungeon("Misery Mire", player).boss.enemizer_name,
|
||||
'TurtleRock': world.get_dungeon("Turtle Rock", player).boss.enemizer_name,
|
||||
'GanonsTower1': [x for x in world.dungeons if x.player == player and 'bottom' in x.bosses.keys()][0].bosses['bottom'].enemizer_name,
|
||||
'GanonsTower2': [x for x in world.dungeons if x.player == player and 'middle' in x.bosses.keys()][0].bosses['middle'].enemizer_name,
|
||||
'GanonsTower3': [x for x in world.dungeons if x.player == player and 'top' in x.bosses.keys()][0].bosses['top'].enemizer_name,
|
||||
'GanonsTower4': 'Agahnim2',
|
||||
'Ganon': 'Ganon',
|
||||
}
|
||||
}
|
||||
|
||||
rom.write_to_file(randopatch_path)
|
||||
|
||||
with open(options_path, 'w') as f:
|
||||
json.dump(options, f)
|
||||
|
||||
try:
|
||||
subprocess.run([os.path.abspath(enemizercli),
|
||||
'--rom', baserom_path,
|
||||
'--seed', str(world.rom_seeds[player]),
|
||||
'--base', basepatch_path,
|
||||
'--randomizer', randopatch_path,
|
||||
'--enemizer', options_path,
|
||||
'--output', enemizer_output_path],
|
||||
cwd=os.path.dirname(enemizercli),
|
||||
check=True,
|
||||
capture_output=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
from Main import EnemizerError
|
||||
enemizerMsg = world.fish.translate("cli","cli","Enemizer returned exit code: ") + str(e.returncode) + "\n"
|
||||
enemizerMsg += world.fish.translate("cli","cli","enemizer.nothing.applied")
|
||||
logging.error(f'Enemizer error output: {e.stderr.decode("utf-8")}\n')
|
||||
raise EnemizerError(enemizerMsg)
|
||||
|
||||
with open(enemizer_basepatch_path, 'r') as f:
|
||||
for patch in json.load(f):
|
||||
rom.write_bytes(patch["address"], patch["patchData"])
|
||||
|
||||
with open(enemizer_output_path, 'r') as f:
|
||||
for patch in json.load(f):
|
||||
rom.write_bytes(patch["address"], patch["patchData"])
|
||||
|
||||
if random_sprite_on_hit:
|
||||
_populate_sprite_table()
|
||||
sprites = list(_sprite_table.values())
|
||||
if sprites:
|
||||
while len(sprites) < 32:
|
||||
sprites.extend(sprites)
|
||||
random.shuffle(sprites)
|
||||
|
||||
for i, path in enumerate(sprites[:32]):
|
||||
sprite = Sprite(path)
|
||||
rom.write_bytes(0x300000 + (i * 0x8000), sprite.sprite)
|
||||
rom.write_bytes(0x307000 + (i * 0x8000), sprite.palette)
|
||||
rom.write_bytes(0x307078 + (i * 0x8000), sprite.glove_palette)
|
||||
|
||||
if local_rom.has_smc_header:
|
||||
try:
|
||||
os.remove(unheadered_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
os.remove(randopatch_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
os.remove(options_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
os.remove(enemizer_output_path)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
_sprite_table = {}
|
||||
def _populate_sprite_table():
|
||||
|
||||
@@ -461,9 +461,6 @@
|
||||
"bps": {
|
||||
"action": "store_true"
|
||||
},
|
||||
"enemizercli": {
|
||||
"setting": "enemizercli"
|
||||
},
|
||||
"shufflebosses": {
|
||||
"choices": [
|
||||
"none",
|
||||
|
||||
@@ -130,9 +130,6 @@
|
||||
"randomizer.enemizer.enemyhealth.hard": "Hard",
|
||||
"randomizer.enemizer.enemyhealth.expert": "Expert",
|
||||
|
||||
"randomizer.enemizer.enemizercli": "EnemizerCLI path: ",
|
||||
"randomizer.enemizer.enemizercli.online": "(get online)",
|
||||
|
||||
"randomizer.entrance.openpyramid": "Pre-open Pyramid Hole",
|
||||
"randomizer.entrance.openpyramid.auto": "Auto",
|
||||
"randomizer.entrance.openpyramid.yes": "Yes",
|
||||
|
||||
@@ -76,59 +76,58 @@ def bottom_frame(self, parent, args=None):
|
||||
elif type(v) is dict: # use same settings for every player
|
||||
setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, guiargs.multi + 1)})
|
||||
argsDump = vars(guiargs)
|
||||
hasEnemizer = "enemizercli" in argsDump and os.path.isfile(argsDump["enemizercli"])
|
||||
needEnemizer = False
|
||||
if hasEnemizer:
|
||||
falsey = ["none", "default", False, 0]
|
||||
for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]:
|
||||
if enemizerOption in argsDump:
|
||||
if isinstance(argsDump[enemizerOption], dict):
|
||||
for playerID,playerSetting in argsDump[enemizerOption].items():
|
||||
if not playerSetting in falsey:
|
||||
needEnemizer = True
|
||||
elif not argsDump[enemizerOption] in falsey:
|
||||
needEnemizer = True
|
||||
seeds = []
|
||||
if not needEnemizer or (needEnemizer and hasEnemizer):
|
||||
try:
|
||||
if guiargs.count is not None and guiargs.seed:
|
||||
seed = guiargs.seed
|
||||
for _ in range(guiargs.count):
|
||||
seeds.append(seed)
|
||||
main(seed=seed, args=guiargs, fish=parent.fish)
|
||||
seed = random.randint(0, 999999999)
|
||||
else:
|
||||
if guiargs.seed:
|
||||
seeds.append(guiargs.seed)
|
||||
else:
|
||||
random.seed(None)
|
||||
guiargs.seed = random.randint(0, 999999999)
|
||||
seeds.append(guiargs.seed)
|
||||
main(seed=guiargs.seed, args=guiargs, fish=parent.fish)
|
||||
except (FillError, EnemizerError, Exception, RuntimeError) as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
else:
|
||||
YES = parent.fish.translate("cli","cli","yes")
|
||||
NO = parent.fish.translate("cli","cli","no")
|
||||
successMsg = ""
|
||||
made = {}
|
||||
for k in [ "rom", "playthrough", "spoiler" ]:
|
||||
made[k] = parent.fish.translate("cli","cli","made." + k)
|
||||
made["enemizer"] = parent.fish.translate("cli","cli","used.enemizer")
|
||||
for k in made:
|
||||
v = made[k]
|
||||
pattern = "([\w]+)(:)([\s]+)(.*)"
|
||||
m = re.search(pattern,made[k])
|
||||
made[k] = m.group(1) + m.group(2) + ' ' + m.group(4)
|
||||
successMsg += (made["rom"] % (YES if (guiargs.create_rom) else NO)) + "\n"
|
||||
successMsg += (made["playthrough"] % (YES if (guiargs.calc_playthrough) else NO)) + "\n"
|
||||
successMsg += (made["spoiler"] % (YES if (not guiargs.jsonout and guiargs.create_spoiler) else NO)) + "\n"
|
||||
successMsg += (made["enemizer"] % (YES if needEnemizer else NO)) + "\n"
|
||||
# FIXME: English
|
||||
successMsg += ("Seed%s: %s" % ('s' if len(seeds) > 1 else "", ','.join(str(x) for x in seeds)))
|
||||
|
||||
messagebox.showinfo(title="Success", message=successMsg)
|
||||
needEnemizer = False
|
||||
falsey = ["none", "default", False, 0]
|
||||
for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]:
|
||||
if enemizerOption in argsDump:
|
||||
if isinstance(argsDump[enemizerOption], dict):
|
||||
for playerID,playerSetting in argsDump[enemizerOption].items():
|
||||
if not playerSetting in falsey:
|
||||
needEnemizer = True
|
||||
elif not argsDump[enemizerOption] in falsey:
|
||||
needEnemizer = True
|
||||
seeds = []
|
||||
|
||||
try:
|
||||
if guiargs.count is not None and guiargs.seed:
|
||||
seed = guiargs.seed
|
||||
for _ in range(guiargs.count):
|
||||
seeds.append(seed)
|
||||
main(seed=seed, args=guiargs, fish=parent.fish)
|
||||
seed = random.randint(0, 999999999)
|
||||
else:
|
||||
if guiargs.seed:
|
||||
seeds.append(guiargs.seed)
|
||||
else:
|
||||
random.seed(None)
|
||||
guiargs.seed = random.randint(0, 999999999)
|
||||
seeds.append(guiargs.seed)
|
||||
main(seed=guiargs.seed, args=guiargs, fish=parent.fish)
|
||||
except (FillError, EnemizerError, Exception, RuntimeError) as e:
|
||||
logging.exception(e)
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
else:
|
||||
YES = parent.fish.translate("cli","cli","yes")
|
||||
NO = parent.fish.translate("cli","cli","no")
|
||||
successMsg = ""
|
||||
made = {}
|
||||
for k in [ "rom", "playthrough", "spoiler" ]:
|
||||
made[k] = parent.fish.translate("cli","cli","made." + k)
|
||||
made["enemizer"] = parent.fish.translate("cli","cli","used.enemizer")
|
||||
for k in made:
|
||||
v = made[k]
|
||||
pattern = "([\w]+)(:)([\s]+)(.*)"
|
||||
m = re.search(pattern,made[k])
|
||||
made[k] = m.group(1) + m.group(2) + ' ' + m.group(4)
|
||||
successMsg += (made["rom"] % (YES if (guiargs.create_rom) else NO)) + "\n"
|
||||
successMsg += (made["playthrough"] % (YES if (guiargs.calc_playthrough) else NO)) + "\n"
|
||||
successMsg += (made["spoiler"] % (YES if (not guiargs.jsonout and guiargs.create_spoiler) else NO)) + "\n"
|
||||
successMsg += (made["enemizer"] % (YES if needEnemizer else NO)) + "\n"
|
||||
# FIXME: English
|
||||
successMsg += ("Seed%s: %s" % ('s' if len(seeds) > 1 else "", ','.join(str(x) for x in seeds)))
|
||||
|
||||
messagebox.showinfo(title="Success", message=successMsg)
|
||||
|
||||
## Generate Button
|
||||
# widget ID
|
||||
@@ -217,9 +216,6 @@ def create_guiargs(parent):
|
||||
pagewidgets = page.content.customWidgets if mainpage == "custom" else page.content.startingWidgets if mainpage == "startinventory" else page.widgets
|
||||
setattr(guiargs, arg, pagewidgets[widget].storageVar.get())
|
||||
|
||||
# Get EnemizerCLI setting
|
||||
guiargs.enemizercli = parent.pages["randomizer"].pages["enemizer"].widgets["enemizercli"].storageVar.get()
|
||||
|
||||
# Get Multiworld Worlds count
|
||||
guiargs.multi = int(parent.pages["bottom"].pages["content"].widgets["worlds"].storageVar.get())
|
||||
|
||||
|
||||
@@ -77,20 +77,6 @@ def loadcliargs(gui, args, settings=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
|
||||
mainpage = "randomizer"
|
||||
subpage = "enemizer"
|
||||
widget = "enemizercli"
|
||||
setting = "enemizercli"
|
||||
# set storagevar
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].storageVar.set(args[setting])
|
||||
# set textbox/frame label
|
||||
label = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget)
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].pieces["frame"].label.configure(text=label)
|
||||
# set get from web label
|
||||
label = fish.translate("gui","gui",mainpage + '.' + subpage + '.' + widget + ".online")
|
||||
gui.pages[mainpage].pages[subpage].widgets[widget].pieces["online"].label.configure(text=label)
|
||||
|
||||
# Get baserom path
|
||||
mainpage = "randomizer"
|
||||
subpage = "generation"
|
||||
|
||||
@@ -6,10 +6,7 @@ import webbrowser
|
||||
from source.classes.Empty import Empty
|
||||
|
||||
def enemizer_page(parent,settings):
|
||||
def open_enemizer_download(_evt):
|
||||
webbrowser.open("https://github.com/Bonta0/Enemizer/releases")
|
||||
|
||||
# Enemizer
|
||||
# Enemizer
|
||||
self = ttk.Frame(parent)
|
||||
|
||||
# Enemizer options
|
||||
@@ -45,45 +42,4 @@ def enemizer_page(parent,settings):
|
||||
packAttrs["anchor"] = W
|
||||
self.widgets[key].pack(packAttrs)
|
||||
|
||||
## Enemizer CLI Path
|
||||
# This one's more-complicated, build it and stuff it
|
||||
# widget ID
|
||||
widget = "enemizercli"
|
||||
|
||||
# Empty object
|
||||
self.widgets[widget] = Empty()
|
||||
# pieces
|
||||
self.widgets[widget].pieces = {}
|
||||
|
||||
# frame
|
||||
self.widgets[widget].pieces["frame"] = Frame(self.frames["bottomEnemizerFrame"])
|
||||
# frame: label
|
||||
self.widgets[widget].pieces["frame"].label = Label(self.widgets[widget].pieces["frame"], text="EnemizerCLI path: ")
|
||||
self.widgets[widget].pieces["frame"].label.pack(side=LEFT)
|
||||
|
||||
# get app online
|
||||
self.widgets[widget].pieces["online"] = Empty()
|
||||
# get app online: label
|
||||
self.widgets[widget].pieces["online"].label = Label(self.widgets[widget].pieces["frame"], text="(get online)", fg="blue", cursor="hand2")
|
||||
self.widgets[widget].pieces["online"].label.pack(side=LEFT)
|
||||
# get app online: open browser
|
||||
self.widgets[widget].pieces["online"].label.bind("<Button-1>", open_enemizer_download)
|
||||
# storage var
|
||||
self.widgets[widget].storageVar = StringVar(value=settings["enemizercli"])
|
||||
# textbox
|
||||
self.widgets[widget].pieces["textbox"] = Entry(self.widgets[widget].pieces["frame"], textvariable=self.widgets[widget].storageVar)
|
||||
self.widgets[widget].pieces["textbox"].pack(side=LEFT, fill=X, expand=True)
|
||||
|
||||
def EnemizerSelectPath():
|
||||
path = filedialog.askopenfilename(filetypes=[("EnemizerCLI executable", "*EnemizerCLI*")], initialdir=os.path.join("."))
|
||||
if path:
|
||||
self.widgets[widget].storageVar.set(path)
|
||||
settings["enemizercli"] = path
|
||||
# dialog button
|
||||
self.widgets[widget].pieces["opendialog"] = Button(self.widgets[widget].pieces["frame"], text='...', command=EnemizerSelectPath)
|
||||
self.widgets[widget].pieces["opendialog"].pack(side=LEFT)
|
||||
|
||||
# frame: pack
|
||||
self.widgets[widget].pieces["frame"].pack(fill=X)
|
||||
|
||||
return self,settings
|
||||
return self, settings
|
||||
|
||||
Reference in New Issue
Block a user